/** * Получить список файлов каталога * * @param string $path Путь к каталогу * @param string $type Фильтр для типа собираемых файлов * @param array $result Результат работі рекурсивной функции * @param string $modifier Модификатор пути к файлам для изменения их пути * @param string $max_level Максимальная глубина работы метода * @param integer $level Текщий уровень рекурсии * @param array $restrict Коллекция папок которые необходимо пропускать * * @return array Коллекция файлов в каталоге */ public static function dir($path, $type = null, $modifier = '', &$result = array(), $max_level = NULL, $level = 0, $restrict = array('.git', '.svn', '.hg', '.settings')) { // Если установлено ограничение на глубину - выйдем if (isset($max_level) && $level > $max_level) { return $result; } // If type filter is passed make it array anyway if (isset($type) && !is_array($type)) { $type = array($type); } // Откроем папку if (file_exists($path) && ($handle = opendir($path))) { /* Именно этот способ чтения элементов каталога является правильным. */ while (false !== ($entry = readdir($handle))) { // Ignore root paths if ($entry == '..' || $entry == '.') { continue; } // Build full REAL path to entry $full_path = realpath($path . '/' . $entry); if (is_file($full_path)) { // Check file type if ty filter is passed if (!isset($type) || in_array(pathinfo($full_path, PATHINFO_EXTENSION), $type)) { $result[] = normalizepath($modifier . $full_path); } } else { if (is_dir($full_path)) { // Define if current path is not restricted $ignored = false; // Iterate all restrictions foreach ($restrict as $ignore) { // Try to find ignored path pattern in full path and store it to ignored flag if (($ignored = $ignore == $full_path) !== false) { // This is ignored path - break, ignored now is false(0) break; } } // If this path is not restricted if ($ignored === false) { // Go deeper in recursion self::dir($full_path, $type, $modifier, $result, $max_level, ++$level, $restrict); } } } } // Закроем чтение папки closedir($handle); } //else return e( 'Ошибка открытия папки(##)', E_SAMSON_CORE_ERROR, array( $path ) ); // Сортируем if (sizeof($result)) { sort($result); } // Соберем массив в строку return $result; }
/** * Преобразовать коллекцию имен классов в коллекцию * [Namespace][ ClassFileName ] * * @param array $collection Коллекция имен классов * @param array $classes Коллекция для возврата результатов */ private function classes_to_ns_files($collection, &$classes = array()) { // Соберем коллекцию загруженных интерфейсов их файлов по пространствам имен foreach ($collection as $class) { $ac = new \ReflectionClass($class); $ns = $ac->getNamespaceName(); if ($ns != '') { $ns = strtolower($ns); if (!isset($classes[$ns])) { $classes[$ns] = array(); } $classes[$ns][normalizepath($ac->getFileName())] = ''; } } }
/** * Reccurent PHP code parser * * @param string $path Abcolute path to php file * @param Module $module Pointer to file owning module object * @param array $code Collection where we need to gather parsed PHP code * @param string $namespace Module namespace * * @return array */ protected function parse($path, $module = NULL, &$code = array(), $namespace = self::NS_GLOBAL) { $_path = $path; $path = normalizepath(realpath($path)); // Если мы уже подключили данный файл или он не существует if (isset($this->files[$path])) { return $this->log(' ! Файл: [##], already compressed', $path); } else { if (!is_file($path)) { return $this->log(' ! Файл: [##], не существует', $_path); } else { if (strpos($path, 'vendor/autoload.php') !== false) { return $this->log(' Ignoring composer autoloader [##]', $path); } else { if (in_array(basename($path), $this->ignoredFiles)) { return $this->log(' Ignoring file[##] by configuration', $path); } } } } $this->log(' - Parsing file [##]', $path); // Load file once, if it's not have been loaded before require_once $path; // Сохраним файл $this->files[$path] = $path; // Прочитаем php файл $fileStr = file_get_contents($path); $main_code = "\n" . '// Модуль: ' . m($module)->id() . ', файл: ' . $path . "\n"; // Создадим уникальную коллекцию алиасов для NS if (!isset($code[$namespace]['uses'])) { $code[$namespace]['uses'] = array(); } // Установим ссылку на коллекцию алиасов $uses =& $code[$namespace]['uses']; // Local file uses collection $file_uses = array(); // Получим константы документа $consts = get_defined_constants(); // Маркеры для отрезания специальных блоков которые не нужны в PRODUCTION $rmarker_st = '\\/\\/\\[PHPCOMPRESSOR\\(remove\\,start\\)\\]'; $rmarker_en = '\\/\\/\\[PHPCOMPRESSOR\\(remove\\,end\\)\\]'; // Найдем все "ненужные" блоки кода и уберем их $fileStr = preg_replace('/' . $rmarker_st . '.*?' . $rmarker_en . '/uis', '', $fileStr); // Разберем код программы $tokens = token_get_all($fileStr); for ($i = 0; $i < sizeof($tokens); $i++) { // Получим следующий жетон из кода программы $token = $tokens[$i]; // Если просто строка if (is_string($token)) { $main_code .= $token; } else { // token array list($id, $text) = $token; // Перебирем тип комманды switch ($id) { case T_COMMENT: // Пропускаем все комментарии // Пропускаем все комментарии case T_DOC_COMMENT: case T_CLOSE_TAG: // Начало,конец файла // Начало,конец файла case T_OPEN_TAG: break; case T_WHITESPACE: $main_code .= $text; /*$main_code .= ' ';*/ break; // Обработаем алиасы // Обработаем алиасы case T_USE: $_use = ''; // Переберем все что иде после комманды алиаса for ($j = $i + 1; $j < sizeof($tokens); $j++) { // Получим идентификатор метки и текстовое представление $id = isset($tokens[$j][0]) ? $tokens[$j][0] : ''; $text = isset($tokens[$j][1]) ? $tokens[$j][1] : ''; //trace('"'.$id.'" - "'.$text.'"'); // Если use используется в функции if ($id == '(') { $j--; break; } // Если это закрывающая скобка - прекратим собирание пути к файлу if ($id == ';') { break; } // Все пробелы игнорирую if ($id == T_WHITESPACE) { continue; } // Если у метки есть текстовое представление if (isset($text)) { // Если єто константа if (isset($consts[$text])) { $_use .= $consts[$text]; } else { $_use .= $text; } } } // Если это не use в inline функции - добавим алиас в коллекцию // для данного ns с проверкой на уникальность if ($id !== '(') { // Нижний регистр //$_use = strtolower($_use); // Преведем все use к одному виду if ($_use[0] !== '\\') { $_use = '\\' . $_use; } // Add local file uses $file_uses[] = $_use; // TODO: Вывести замечание что бы код везде был одинаковый if (!in_array($_use, $uses)) { $uses[] = $_use; } } else { $main_code .= ' use '; } // Сместим указатель чтения файла $i = $j; break; case T_NAMESPACE: // Определим временное пространство имен $_namespace = ''; // Переберем все что иде после комманды подключения файла for ($j = $i + 1; $j < sizeof($tokens); $j++) { // Получим идентификатор метки и текстовое представление $id = isset($tokens[$j][0]) ? $tokens[$j][0] : ''; $text = isset($tokens[$j][1]) ? $tokens[$j][1] : ''; //trace('"'.$id.'" - "'.$text.'"'); // Если это закрывающая скобка - прекратим собирание пути к файлу if ($id == ')' || $id == ';' || $id == '{') { break; } // Все пробелы игнорирую if ($id == T_WHITESPACE) { continue; } // Если у метки есть текстовое представление if (isset($text)) { // Если єто константа if (isset($consts[$text])) { $_namespace .= $consts[$text]; } else { $_namespace .= $text; } } } // Если найденный NS отличается от текущего - установим переход к новому NS if ($namespace !== $_namespace) { // Сохраним новый как текущий $namespace = strtolower($_namespace); //trace(' #'.$i.' -> Изменили NS с '.$namespace.' на '.$_namespace); // Если мы еще не создали данный NS if (!isset($code[$namespace])) { $code[$namespace] = array(); } // Создадим уникальную коллекцию алиасов для NS if (!isset($code[$namespace]['uses'])) { $code[$namespace]['uses'] = array(); } // Установим ссылку на коллекцию алиасов $uses =& $code[$namespace]['uses']; } // Сместим указатель чтения файла $i = $j; break; // Выделяем код подключаемых файлов // Выделяем код подключаемых файлов case T_REQUIRE: case T_REQUIRE_ONCE: //case T_INCLUDE : //case T_INCLUDE : case T_INCLUDE_ONCE: // Получим путь к подключаемому файлу $file_path = ''; // Переберем все что иде после комманды подключения файла for ($j = $i + 1; $j < sizeof($tokens); $j++) { // Получим идентификатор метки и текстовое представление $id = isset($tokens[$j][0]) ? $tokens[$j][0] : ''; $text = isset($tokens[$j][1]) ? $tokens[$j][1] : ''; //trace('"'.$id.'" - "'.$text.'"'); // Если это закрывающая скобка - прекратим собирание пути к файлу if ($id == ';') { break; } // Все пробелы игнорирую if ($id == T_WHITESPACE) { continue; } // Если у метки есть текстовое представление if (isset($text)) { // Если єто константа if (isset($consts[$text])) { $file_path .= $consts[$text]; } else { $file_path .= $text; } } } // Если указан путь к файлу if (isset($file_path[1])) { // Уберем ковычки $file_path = str_replace(array("'", '"'), array('', ''), $file_path); // Если это не абсолютный путь - попробуем относительный if (!file_exists($file_path)) { $file_path = pathname($path) . $file_path; } // Если файл найден - получим его содержимое if (file_exists($file_path)) { //trace('Углубляемся в файл:'.$file_path.'('.$namespace.')'); // Углубимся в рекурсию $this->compress_php($file_path, $module, $code, $namespace); // Измением позицию маркера чтения файла $i = $j + 1; } } else { $main_code .= $text; } break; // Собираем основной код программы // Собираем основной код программы default: $main_code .= $text; break; } } } //trace(' - Вышли из функции:'.$path.'('.$namespace.')'); //trace(''); // Replace all class shortcut usage with full name if (sizeof($file_uses)) { $main_code = $this->removeUSEStatement($main_code, $file_uses); } // Запишем в коллекцию кода полученный код $code[$namespace][$path] = $main_code; return $main_code; }
/** @see iModule::path() */ public function path($value = null) { // Если передан параметр - установим его if (func_num_args()) { $this->path = isset($value[0]) ? rtrim(normalizepath($value), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : ''; return $this; } else { return $this->path; } }
/** * Perform resource gathering starting from $path entry point * @param string $path Entry point to start scanning resources * @return bool True if we had no errors on building path resource map */ public function build($path = null) { // If no other path is passed use current entry point and convert it to *nix path format $path = isset($path) ? realpath(normalizepath($path)) . '/' : $this->entryPoint; // Store new entry point $this->entryPoint = $path; // Check for correct path and then try to get files if (file_exists($path)) { // Collect all resources from entry point $files = array(); foreach (File::dir($this->entryPoint, null, '', $files, null, 0, $this->ignoreFolders) as $file) { // Get real path to file $file = realpath($file); // Check if this file does not has to be ignored if (!in_array(basename($file), $this->ignoreFiles)) { // Class name $class = ''; // Parent class $extends = ''; // We can determine SamsonPHP view files by 100% if ($this->isView($file)) { $this->views[] = $file; } elseif ($this->isGlobal($file)) { $this->globals[] = $file; } elseif ($this->isModel($file)) { $this->models[] = $file; } elseif ($this->isController($file)) { $this->controllers[] = $file; } elseif ($this->isModule($file, $class, $extends)) { $this->module = array($class, $file, $extends); $this->modules[] = array($class, $file, $extends); } elseif ($this->isPHP($file)) { $this->php[] = $file; } else { // Save resource by file extension // Get extension as resource type $rt = pathinfo($file, PATHINFO_EXTENSION); // Check if resource type array cell created if (!isset($this->resources[$rt])) { $this->resources[$rt] = array(); } // Add resource to collection $this->resources[$rt][] = $file; } } } // Iterate all defined object variables foreach (array_keys(get_object_vars($this)) as $var) { // If we have matched resources with that type if (isset($this->resources[$var])) { // Bind object variable to resources collection $this->{$var} =& $this->resources[$var]; } } return true; } else { // Signal error return e('Cannot build ResourceMap from ## - path does not exists', E_SAMSON_CORE_ERROR, $path); } }