fix_depricated_recursive()   B
last analyzed

Complexity

Conditions 7
Paths 6

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 10
nc 6
nop 2
dl 0
loc 20
rs 8.8333
c 0
b 0
f 0
1
#!/usr/bin/php -qC
2
<?php
3
/**
4
 * EGroupware - fix deprecated PHP functions and constructs
5
 *
6
 * The depricated warnings fill up the log files, as they can not be swichted off in the logs.
7
 *
8
 * @link http://www.egroupware.org
9
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
10
 * @author [email protected]
11
 * @copyright 2009-19 by [email protected]
12
 */
13
14
if (php_sapi_name() !== 'cli')	// security precaution: forbit calling as web-page
15
{
16
	die('<h1>fix_depricated.php must NOT be called as web-page --> exiting !!!</h1>');
17
}
18
19
/**
20
 * Fix depricated stuff in a given file
21
 *
22
 * @param string $file filename
23
 * @param boolean $replace_file =false replace existing file if modifications are necessary, otherwise .php53 file is created
24
 * @return boolean false on error
25
 */
26
function fix_depricated($file,$replace_file=false)
27
{
28
	$orig = $lines = file_get_contents($file);
29
	if ($lines === false) return false;
30
	global $prog;
31
	if (basename($file) == $prog) return true;	// dont fix ourself ;-)
32
33
	// match "variables" like: $var, $obj->attr, $arr['key']
34
	$variable = '\$[a-z_0-9\[\]\'>-]+';
35
36
	// list($key) = each($array); --> $key = key($array);
37
	if (preg_match("/each\(($variable)\);/i", $lines))
38
	{
39
		$lines = preg_replace("/list\(($variable)\)\s+=\s+@?each\(($variable)\);/i", '$1 = key($2);', $lines);
40
41
		// list($key, $val) = each($array); --> $key = key($array); $val = current($array);
42
		if (preg_match("/[^=]+=\s+@?each\(($variable)\);/i", $lines))
43
		{
44
			$lines = preg_replace("/^(\s)*list\(($variable),\s*($variable)\)\s+=\s+@?each\(($variable)\);/mi",
45
				'$1$2 = key($4);$1$3 = current($4);', $lines);
46
47
			$matches = null;
48
			if (preg_match_all("/^[^=]+=\s+@?each\(($variable)\);/i", $lines, $matches, PREG_PATTERN_ORDER))
49
			{
50
				error_log("Unfixed each(...) constructs: ", implode(' ', $matches[0]));
51
			}
52
		}
53
	}
54
55
	// count($non_array) --> is_array($non_array) && count($non_array)
56
	/* commented as (in most cases) unnecessary, if argument is garantied to be an array
57
	if (preg_match('/count\((\$[a-z_0-9]+)\)/i', $lines))
58
	{
59
		$lines = preg_replace('/count\((\$[a-z_0-9]+)\)/i', 'is_array($1) && $0', $lines);
60
	}*/
61
62
	// PHP Deprecated:  Assigning the return value of new by reference is deprecated
63
	if (preg_match('/= *& *new /m',$lines))
64
	{
65
		$lines = preg_replace('/= *& *new /','= new ',$lines);
66
	}
67
	// PHP Deprecated:  Function split() is deprecated
68
	$matches = null;
69
	if (preg_match_all('/[= \t(]+spliti? *\\(("[^"]*"|\'[^\']*\'),/m',$lines,$matches))
70
	{
71
		$replace = array();
72
		//print_r($matches);
73
		foreach($matches[1] as $key => $pattern)
74
		{
75
			$full_pattern = $matches[0][$key];
76
			// single char --> just explode
77
			if (strlen($pattern) == 3 || strlen($pattern) == 4 && substr($pattern,0,2) == '"\\')
78
			{
79
				$replace[$full_pattern] = str_replace('split','explode',$full_pattern);
80
			}
81
			else
82
			{
83
				$preg_pattern = $pattern[0].'/'.str_replace('/','\\\\/',substr($pattern,1,-1)).'/'.$pattern[0];
84
				if (strpos($full_pattern,'spliti')) $preg_pattern = substr($preg_pattern,0,-1).'i'.$pattern[0];
85
				$replace[$full_pattern] = str_replace(array('spliti','split',$pattern),array('preg_split','preg_split',$preg_pattern),$full_pattern);
86
			}
87
		}
88
		//print_r($replace);
89
		$lines = strtr($lines,$replace);
90
	}
91
	// PHP Deprecated:  Function ereg() is deprecated
92
	if (preg_match_all('/!?eregi? *\\(("[^"]+"[^,]*|\'[^\']+\'[^,]*), *(\$[A-Za-z0-9_\[\]\$\'\"]+)(, *\$[A-Za-z0-9_\[\]\$\'\"]+)?\)([ )&|]+)/m',$lines,$matches))
93
	{
94
		$replace = array();
95
		//print_r($matches);
96
		foreach($matches[1] as $key => $pattern)
97
		{
98
			$full_pattern = $matches[0][$key];
99
			$what = $matches[2][$key];
100
101
			// simple existence check --> use strpos()
102
			if (preg_quote($pattern) == $pattern)
103
			{
104
105
				$replace[$full_pattern] = (strpos($full_pattern,'eregi')!==false?'strposi':'strpos').'('.$what.','.$pattern.
106
					') '.($full_pattern[0]=='!'?'===':'!==').' false'.$matches[4][$key];
107
			}
108
			else
109
			{
110
				// full ereg regular expression --> preg_match
111
				$preg_pattern = "'/'.".str_replace('/','\\\\/',$pattern).(strpos($full_pattern,'eregi') !== false ? ".'/i'" : ".'/'");
112
				$replace[$full_pattern] = str_replace(array('eregi','ereg',$pattern),array('preg_match','preg_match',$preg_pattern),$full_pattern);
113
			}
114
		}
115
		//print_r($replace);
116
		$lines = strtr($lines,$replace);
117
	}
118
	// PHP Deprecated:  Function ereg_replace() is deprecated
119
	if (preg_match_all('/eregi?_replace *\\((".+"|\'.+\'|[^,]+), *(.+), *[\'s$].+\)[,; =]/m',$lines,$matches))
120
	{
121
		$replace = array();
122
		//print_r($matches);
123
		foreach($matches[1] as $key => $pattern)
124
		{
125
			$full_pattern = $matches[0][$key];
126
127
			// simple replace --> use str_replace()
128
			if (preg_quote($pattern) == $pattern)
129
			{
130
				$replace[$full_pattern] = str_replace(array('eregi_replace','ereg_replace'),array('stri_replace','str_replace'),$full_pattern);
131
			}
132
			else
133
			{
134
				// full ereg regular expression --> preg_replace
135
				$preg_pattern = "'/'.".str_replace('/','\\\\/',$pattern).(strpos($full_pattern,'eregi') !== false ? ".'/i'" : ".'/'");
136
				$replace[$full_pattern] = str_replace(array('eregi_replace','ereg_replace',$pattern),
137
					array('preg_replace','preg_replace',$preg_pattern),$full_pattern);
138
			}
139
		}
140
		//print_r($replace);
141
		$lines = strtr($lines,$replace);
142
	}
143
	// remove extra '/' from regular expressions
144
	$lines = str_replace(array("'/'.'","'.'/'","'.'/i'"),array("'/","/'","/i'"),$lines);
145
146
	// fix call to not longer existing PDO method $result->fetchSingle()
147
	$lines = str_replace('->fetchSingle(','->fetchColumn(',$lines);
148
149
	// fix calls to deprecated call_user_method(_array)?(method,object[,args])
150
	if (preg_match('/call_user_method(_array)?\(/',$lines,$matches))
151
	{
152
		$lines = preg_replace('/call_user_method\(([^,]+),([^,\)]+)([,)])/','call_user_func(array(\\2,\\1)\\3',$lines);
153
		$lines = preg_replace('/call_user_method_array\(([^,]+),([^,\)]+)([,)])/','call_user_func_array(array(\\2,\\1)\\3',$lines);
154
	}
155
156
	if ($lines != $orig)
157
	{
158
		file_put_contents($file.'.new',$lines);
159
		$ret = null;
160
		system('/usr/bin/php -l '.$file.'.new',$ret);
161
		system('/usr/bin/diff -u '.$file.' '.$file.'.new');
162
		if (!$ret && $replace_file)
163
		{
164
			unlink($file);
165
			rename($file.'.new',$file);
166
		}
167
		return !$ret;
168
	}
169
	return true;
170
}
171
172
/**
173
 * Loop recursive through directory and call fix_depricated for each php file
174
 *
175
 * @param string $dir
176
 * @param boolean $replace_file =false replace existing file if modifications are necessary, otherwise .php53 file is created
177
 * @return boolean false on error
178
 */
179
function fix_depricated_recursive($dir,$replace_file=false)
180
{
181
	if (!is_dir($dir)) return false;
182
183
	foreach(scandir($dir) as $file)
184
	{
185
		if ($file == '.' || $file == '..') continue;
186
187
		if (is_dir($dir.'/'.$file))
188
		{
189
			fix_depricated_recursive($dir.'/'.$file,$replace_file);
190
		}
191
		elseif(substr($file,-4) == '.php')
192
		{
193
			echo "\r".str_repeat(' ',100)."\r".$dir.'/'.$file.': ';
194
			fix_depricated($dir.'/'.$file,$replace_file);
195
		}
196
	}
197
	echo "\r".str_repeat(' ',100)."\r";
198
	return true;
199
}
200
201
/**
202
 * Give usage
203
 *
204
 * @param string $error =null
205
 */
206
function usage($error=null)
207
{
208
	global $prog;
209
	echo "Usage: $prog [--replace] [-h|--help] file or dir\n\n";
210
	if ($error) echo $error."\n\n";
211
	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...
212
}
213
214
$args = $_SERVER['argv'];
215
$prog = basename(array_shift($args));
216
217
if (!$args) usage();
218
219
$replace_file = false;
220
while(($arg = array_shift($args)))
221
{
222
	switch($arg)
223
	{
224
		case '-h':
225
		case '--help':
226
			usage();
227
			break;
228
229
		case '--replace':
230
			$replace_file = true;
231
			break;
232
233
		default:
234
			if ($args)	// not last argument
235
			{
236
				usage("Unknown argument '$arg'!");
237
			}
238
			break 2;
239
	}
240
}
241
242
if (!file_exists($arg)) usage("Error: $arg not found!");
243
244
if (!is_dir($arg))
245
{
246
	fix_depricated($arg,$replace_file);
247
}
248
else
249
{
250
	fix_depricated_recursive($arg,$replace_file);
251
}