#!/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); }