egroupware/doc/check_namespace.php

178 lines
4.0 KiB
PHP
Executable File

#!/usr/bin/env php
<?php
/**
* EGroupware - check namespace usage in converted code
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @author Ralf Becker <rb@stylite.de>
* @copyright 2015 by Ralf Becker <rb@stylite.de>
* @version $Id$
*/
if (php_sapi_name() !== 'cli') // security precaution: forbit calling as web-page
{
die('<h1>check_namespace.php must NOT be called as web-page --> exiting !!!</h1>');
}
/**
* Check namespace usage in converted code
*
* @param string $file filename
* @return boolean false on error
*/
function check_namespace($file)
{
global $prog;
if (basename($file) == $prog) return true; // dont fix ourself ;-)
if (($content = file_get_contents($file)) === false) return false;
// replace commented lines with empty ones
$lines = preg_replace_callback('#(//.*$|/\\*.*\\*/)#msU', function($matches)
{
return str_repeat("\n", substr_count($matches[0], "\n"));
}, $content);
// find classes declared in file itself, in case they are used
$declared = array();
foreach(explode("\n", $lines) as $num => $line)
{
$matches = null;
if (preg_match('/class\s+([^ ]+)/', $line, $matches))
{
$declared[] = $matches[1];
}
}
$namespace = '';
$use = array();
$allways = array('self', 'parent', 'static');
foreach(explode("\n", $lines) as $num => $line)
{
$matches = null;
if (preg_match('/namespace\s+([A-Za-z0-9_\\\\]+);/', $line, $matches))
{
$namespace = $matches[1];
$use = array();
}
if ($namespace === '') continue;
if (preg_match('/use\s+([^;]+);/', $line, $matches))
{
foreach(preg_split('/,\s*/', $matches[1]) as $alias)
{
$parts = explode('\\', $alias);
$use[$alias] = array_pop($parts);
}
}
$all_matches_raw = array();
if (preg_match_all('/[=\s]new\s+([a-z0-9_\\\\]+)\s*\(/i', $line, $matches))
{
$all_matches_raw = $matches[1];
}
if (preg_match_all('/[\s,\(]([a-z0-9_\\\\]+)::/i', $line, $matches))
{
$all_matches_raw = array_merge($all_matches_raw, $matches[1]);
}
$all_matches = array_unique($all_matches_raw);
foreach($all_matches as $c => $class)
{
$parts = explode('\\', $class);
$first_part = array_shift($parts);
if (in_array($class, $allways) || in_array($class, $declared) || $class[0] == '\\' || in_array($first_part, $use))
{
unset($all_matches[$c]);
continue;
}
if (file_exists(dirname($file).'/'.str_replace('\\', '/', $class).'.php'))
{
$use[$namespace.'\\'.$class] = $class;
unset($all_matches[$c]);
continue;
}
}
if ($all_matches)
{
echo (1+$num).":\t".$line."\n";
echo "--> ".implode(', ', $all_matches)."\n\n";
}
}
//print_r($use);
return true;
}
/**
* Loop recursive through directory and call check_namespace for each php file
*
* @param string $dir
* @return boolean false on error
*/
function check_namespace_recursive($dir)
{
if (!is_dir($dir)) return false;
foreach(scandir($dir) as $file)
{
if ($file == '.' || $file == '..') continue;
if (is_dir($dir.'/'.$file))
{
check_namespace_recursive($dir.'/'.$file);
}
elseif(substr($file,-4) == '.php')
{
echo "\r".str_repeat(' ',100)."\r".$dir.'/'.$file.': ';
check_namespace($dir.'/'.$file);
}
}
echo "\r".str_repeat(' ',100)."\r";
return true;
}
/**
* Give usage
*
* @param string $error =null
*/
function usage($error=null)
{
global $prog;
echo "Usage: $prog [-h|--help] file or dir\n\n";
if ($error) echo $error."\n\n";
exit($error ? 1 : 0);
}
$args = $_SERVER['argv'];
$prog = basename(array_shift($args));
if (!$args) usage();
$replace_file = false;
while(($arg = array_shift($args)))
{
switch($arg)
{
case '-h':
case '--help':
usage();
break;
default:
if ($args) // not last argument
{
usage("Unknown argument '$arg'!");
}
break 2;
}
}
if (!file_exists($arg)) usage("Error: $arg not found!");
if (!is_dir($arg))
{
check_namespace($arg,$replace_file);
}
else
{
check_namespace_recursive($arg,$replace_file);
}