check_namespace()   F
last analyzed

Complexity

Conditions 19
Paths 395

Size

Total Lines 78
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
eloc 44
nc 395
nop 1
dl 0
loc 78
rs 1.2458
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
#!/usr/bin/env php
2
<?php
3
/**
4
 * EGroupware - check namespace usage in converted code
5
 *
6
 * @link http://www.egroupware.org
7
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
8
 * @author Ralf Becker <[email protected]>
9
 * @copyright 2015 by Ralf Becker <[email protected]>
10
 * @version $Id$
11
 */
12
13
if (php_sapi_name() !== 'cli')	// security precaution: forbit calling as web-page
14
{
15
	die('<h1>check_namespace.php must NOT be called as web-page --> exiting !!!</h1>');
16
}
17
18
/**
19
 * Check namespace usage in converted code
20
 *
21
 * @param string $file filename
22
 * @return boolean false on error
23
 */
24
function check_namespace($file)
25
{
26
	global $prog;
27
	if (basename($file) == $prog) return true;	// dont fix ourself ;-)
28
29
	if (($content = file_get_contents($file)) === false) return false;
30
31
	// replace commented lines with empty ones
32
	$lines = preg_replace_callback('#(//.*$|/\\*.*\\*/)#msU', function($matches)
33
	{
34
		return str_repeat("\n", substr_count($matches[0], "\n"));
35
	}, $content);
36
37
	// find classes declared in file itself, in case they are used
38
	$declared = array();
39
	foreach(explode("\n", $lines) as $num => $line)
40
	{
41
		$matches = null;
42
		if (preg_match('/class\s+([^ ]+)/', $line, $matches))
43
		{
44
			$declared[] = $matches[1];
45
		}
46
	}
47
	$namespace = '';
48
	$use = array();
49
	$allways = array('self', 'parent', 'static');
50
	foreach(explode("\n", $lines) as $num => $line)
51
	{
52
		$matches = null;
53
		if (preg_match('/namespace\s+([A-Za-z0-9_\\\\]+);/', $line, $matches))
54
		{
55
			$namespace = $matches[1];
56
			$use = array();
57
		}
58
		if ($namespace === '') continue;
59
60
		if (preg_match('/use\s+([^;]+);/', $line, $matches))
61
		{
62
			foreach(preg_split('/,\s*/', $matches[1]) as $alias)
63
			{
64
				$parts = explode('\\', $alias);
65
				$use[$alias] = array_pop($parts);
66
			}
67
		}
68
		$all_matches_raw = array();
69
		if (preg_match_all('/[=\s]new\s+([a-z0-9_\\\\]+)\s*\(/i', $line, $matches))
70
		{
71
			$all_matches_raw = $matches[1];
72
		}
73
		if (preg_match_all('/[\s,\(]([a-z0-9_\\\\]+)::/i', $line, $matches))
74
		{
75
			$all_matches_raw = array_merge($all_matches_raw, $matches[1]);
76
		}
77
		$all_matches = array_unique($all_matches_raw);
78
		foreach($all_matches as $c => $class)
79
		{
80
			$parts = explode('\\', $class);
81
			$first_part = array_shift($parts);
82
			if (in_array($class, $allways) || in_array($class, $declared) || $class[0] == '\\' || in_array($first_part, $use))
83
			{
84
				unset($all_matches[$c]);
85
				continue;
86
			}
87
			if (file_exists(dirname($file).'/'.str_replace('\\', '/', $class).'.php'))
88
			{
89
				$use[$namespace.'\\'.$class] = $class;
90
				unset($all_matches[$c]);
91
				continue;
92
			}
93
		}
94
		if ($all_matches)
0 ignored issues
show
Bug Best Practice introduced by
The expression $all_matches of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
95
		{
96
			echo (1+$num).":\t".$line."\n";
97
			echo "--> ".implode(', ', $all_matches)."\n\n";
98
		}
99
	}
100
	//print_r($use);
101
	return true;
102
}
103
104
/**
105
 * Loop recursive through directory and call check_namespace for each php file
106
 *
107
 * @param string $dir
108
 * @return boolean false on error
109
 */
110
function check_namespace_recursive($dir)
111
{
112
	if (!is_dir($dir)) return false;
113
114
	foreach(scandir($dir) as $file)
115
	{
116
		if ($file == '.' || $file == '..') continue;
117
118
		if (is_dir($dir.'/'.$file))
119
		{
120
			check_namespace_recursive($dir.'/'.$file);
121
		}
122
		elseif(substr($file,-4) == '.php')
123
		{
124
			echo "\r".str_repeat(' ',100)."\r".$dir.'/'.$file.': ';
125
			check_namespace($dir.'/'.$file);
126
		}
127
	}
128
	echo "\r".str_repeat(' ',100)."\r";
129
	return true;
130
}
131
132
/**
133
 * Give usage
134
 *
135
 * @param string $error =null
136
 */
137
function usage($error=null)
138
{
139
	global $prog;
140
	echo "Usage: $prog [-h|--help] file or dir\n\n";
141
	if ($error) echo $error."\n\n";
142
	exit($error ? 1 : 0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
143
}
144
145
$args = $_SERVER['argv'];
146
$prog = basename(array_shift($args));
147
148
if (!$args) usage();
149
150
$replace_file = false;
151
while(($arg = array_shift($args)))
152
{
153
	switch($arg)
154
	{
155
		case '-h':
156
		case '--help':
157
			usage();
158
			break;
159
160
		default:
161
			if ($args)	// not last argument
162
			{
163
				usage("Unknown argument '$arg'!");
164
			}
165
			break 2;
166
	}
167
}
168
169
if (!file_exists($arg)) usage("Error: $arg not found!");
170
171
if (!is_dir($arg))
172
{
173
	check_namespace($arg,$replace_file);
0 ignored issues
show
Unused Code introduced by
The call to check_namespace() has too many arguments starting with $replace_file. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

173
	/** @scrutinizer ignore-call */ 
174
 check_namespace($arg,$replace_file);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
174
}
175
else
176
{
177
	check_namespace_recursive($arg,$replace_file);
0 ignored issues
show
Unused Code introduced by
The call to check_namespace_recursive() has too many arguments starting with $replace_file. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

177
	/** @scrutinizer ignore-call */ 
178
 check_namespace_recursive($arg,$replace_file);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
178
}