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) |
|
|
|
|
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); |
|
|
|
|
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); |
|
|
|
|
174
|
|
|
} |
175
|
|
|
else |
176
|
|
|
{ |
177
|
|
|
check_namespace_recursive($arg,$replace_file); |
|
|
|
|
178
|
|
|
} |
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.