. */ /* */ /*************************************************************************************/ namespace Thelia\Tools; class DIGenerator { /** * Find all models in a directory * * @param string $directory Directory where models have to be find. * @param array $exclude Model to be exclude in the return * * @return array key is the service name and value the full Class name (including namespace if needed) * * @throws \RuntimeException id $directory is not a valid directory * */ public static function genDiModel($directory, array $exclude = array()) { if(!is_string($directory)) return array(); if (!is_dir($directory)) { throw new \RuntimeException($directory." is not a valid directory"); } $results = array(); $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory)); foreach ($files as $file) { //$file is instance of SplFileInfo if(!$file->isFile()) continue; $filePath = $file->getRealPath(); $classes = self::findClasses($filePath); foreach ($classes as $class) { $classInfo = new \ReflectionClass($class); $shortName = $classInfo->getShortName(); if (!in_array($shortName, $exclude)) { $results[$shortName] = $class; } } } return $results; } /** * Extract the classes in the given file * * copied from Composer\Autoload\GenerateClassMap::findClasses() * * @param string $path The file to check * * @return array The found classes */ private static function findClasses($path) { $traits = version_compare(PHP_VERSION, '5.4', '<') ? '' : '|trait'; try { $contents = php_strip_whitespace($path); } catch (\Exception $e) { throw new \RuntimeException('Could not scan for classes inside '.$path.": \n".$e->getMessage(), 0, $e); } // return early if there is no chance of matching anything in this file if (!preg_match('{\b(?:class|interface'.$traits.')\b}i', $contents)) { return array(); } // strip heredocs/nowdocs $contents = preg_replace('{<<<\'?(\w+)\'?(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\1(?=\r\n|\n|\r|;)}s', 'null', $contents); // strip strings $contents = preg_replace('{"[^"\\\\]*(\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(\\\\.[^\'\\\\]*)*\'}', 'null', $contents); // strip leading non-php code if needed if (substr($contents, 0, 2) !== '.+<\?}s', '?>'); if (false !== $pos && false === strpos(substr($contents, $pos), '])(?Pclass|interface'.$traits.') \s+ (?P[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*) | \b(?])(?Pnamespace) (?P\s+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\s*\\\\\s*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*)? \s*[\{;] ) }ix', $contents, $matches); $classes = array(); $namespace = ''; for ($i = 0, $len = count($matches['type']); $i < $len; $i++) { if (!empty($matches['ns'][$i])) { $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\'; } else { $classes[] = ltrim($namespace . $matches['name'][$i], '\\'); } } return $classes; } }