Example #1
0
 /**
  * Copy file from source location to destination location with
  * analyzing last file modification time, and copying only changed files
  *
  * @param string $src source file
  * @param string $dst destination file
  * @param null   $handler
  *
  * @return bool
  */
 public function copy_resource($src, $dst, $handler = null)
 {
     if (!file_exists($src)) {
         return e('Cannot copy file - Source file(##) does not exists', E_SAMSON_SNAPSHOT_ERROR, $src);
     }
     // Action to do
     $action = null;
     // Get source file timestamp
     $source_ts = filemtime($src);
     // If destination file does not exists
     if (!file_exists($dst)) {
         $action = 'Creating';
     } else {
         if (abs($source_ts - filemtime($dst)) > 125) {
             $action = 'Updating';
         }
     }
     // If we know what to do
     if (isset($action)) {
         // Create folder structure if necessary
         $dir_path = pathname($dst);
         if (!file_exists($dir_path)) {
             elapsed('  -- Creating folder structure ' . $dir_path . ' from ' . $src);
             \samson\core\File::mkdir($dir_path);
         }
         // If file handler specified
         if (is_callable($handler)) {
             call_user_func($handler, $src, $dst, $action);
         } else {
             copy($src, $dst);
         }
         elapsed('  -- ' . $action . ' file ' . $dst . ' from ' . $src . '(Difference ' . date('H:i:s', abs($source_ts - filemtime($dst))) . ')');
         // Touch source file with copied file
         touch($src);
     }
 }
Example #2
0
 /**
  * Выполнить рекурсивное "собирание" файла
  *
  * @param string $path Абсолютный путь к файлу сайта
  *
  * @param null $module
  * @param array $code
  * @param string $namespace
  *
  * @return string
  */
 public function compress_php($path, $module = NULL, &$code = array(), $namespace = self::NS_GLOBAL)
 {
     // TODO: Довести до ума разпознование require - убрать точку с зяпятоц которая остается
     // TODO: Убрать пустые линии
     // TODO: Анализатор использования функция и переменных??
     //trace(' + Вошли в функцию:'.$path.'('.$namespace.')');
     $_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('   -- Compressing file [##]', $path);
     // Load file
     require_once $path;
     //trace('Чтение файла: '.$path );
     // Сохраним файл
     $this->files[$path] = $path;
     // Относительный путь к файлу
     if (isset($rel_path)) {
         $this->files[$rel_path] = $path;
     }
     // Прочитаем php файл
     $fileStr = file_get_contents($path);
     // Если в файле нет namespace - считаем его глобальным
     if (strpos($fileStr, 'namespace') === false) {
         //$file_dir = '';
         // Вырежим путь к файлу
         //$file_dir = (pathinfo( $path, PATHINFO_DIRNAME ) == '.' ? '' : pathinfo( $path, PATHINFO_DIRNAME ).'/');
         // Сюда соберем код программы
         $main_code = '';
     }
     $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);
     $className = '';
     $classConstList = array();
     //TODO: Fix to normal external dependency with ResourceRouter
     $fileStr = preg_replace_callback('/(\\\\samson\\\\resourcer\\\\)?ResourceRouter::url\\((\'|\\")(?<path>[^,)]+)(\'|\\")(,(?<module>[^)]+))?\\);/i', array($this, 'rewriteResourceRouter'), $fileStr);
     /** @var bool $classStared Flag for matching trait uses */
     $classStared = false;
     // Разберем код программы
     $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 !== '(') {
                         // If this tait use
                         if ($classStared) {
                             // Consider rewriting trait usage fully qualified name
                             //TODO: Not fully qualified trait name adds slash before
                             $_use = strpos($_use, '\\') === false ? '\\' . $namespace . '\\' . $_use : $_use;
                             // TODO: Import trait code
                             if (!trait_exists($_use)) {
                                 throw new \Exception('Trait "' . $_use . '" does not exists in "' . $path . '"');
                             } else {
                                 $main_code .= ' use ' . $_use . ';';
                             }
                         } else {
                             // Преведем все 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;
                 case T_INTERFACE:
                 case T_CLASS:
                     $classStared = true;
                     $main_code .= $text;
                     for ($j = $i + 1; $j < sizeof($tokens); $j++) {
                         // Get id and text of token
                         $id = isset($tokens[$j][0]) ? $tokens[$j][0] : '';
                         $text = isset($tokens[$j][1]) ? $tokens[$j][1] : '';
                         // Ignore all whitespace
                         if ($id == T_WHITESPACE) {
                             continue;
                         }
                         if (isset($text)) {
                             $className = $text;
                             break;
                         }
                     }
                     break;
                 case T_CONST:
                     $main_code .= $text;
                     $classConst = array();
                     $nameFlag = 'name';
                     for ($j = $i + 1; $j < sizeof($tokens); $j++) {
                         // Get id and text of token
                         $id = isset($tokens[$j][0]) ? $tokens[$j][0] : '';
                         $text = isset($tokens[$j][1]) ? $tokens[$j][1] : '';
                         if ($id == ';') {
                             break;
                         }
                         // Ignore all whitespace
                         if ($id == T_WHITESPACE) {
                             continue;
                         }
                         if ($id == '=') {
                             $nameFlag = 'value';
                             continue;
                         }
                         if (isset($text)) {
                             // Is it defined constant
                             if (isset($consts[$text])) {
                                 $classConst[$nameFlag] = $consts[$text];
                             } else {
                                 $classConst[$nameFlag] = $text;
                             }
                         }
                     }
                     $classConstList[$classConst['name']] = $classConst['value'];
                     break;
                     // Собираем основной код программы
                 // Собираем основной код программы
                 default:
                     $main_code .= $text;
                     break;
             }
         }
     }
     // Replace all class shortcut usage with full name
     if (count($file_uses)) {
         $main_code = $this->removeUSEStatement($main_code, $file_uses);
     }
     $matches = array();
     if ($className == 'Module') {
         $temp = '';
     }
     if (preg_match_all('/(?<start>[(=+-\\/*%., \\n\\t])(?<class>[\\\\a-zA-Z_]+)::(?<name>[a-zA-Z_]+)(?<end>[):;=+-\\/*%., \\n\\t])/i', $main_code, $matches)) {
         for ($i = 0; $i < sizeof($matches['name']); $i++) {
             $matchClass = $matches['class'][$i];
             // If this is self - use current file class
             if ($matches['class'][$i] === 'self') {
                 $constantName = $namespace . '\\' . $className;
             } elseif ($matches['class'][$i] == $className) {
                 // If this is current class add namespace
                 $constantName = $namespace . '\\' . $className;
             } elseif ($matches['class'][$i] === 'parent') {
                 continue;
             } elseif ($matches['class'][$i] === 'static') {
                 continue;
             } else {
                 $constantName = $matches['class'][$i];
             }
             // If constant has no namespace - use current
             if (strpos($constantName, '\\') === false) {
                 $constantName = $namespace . '\\' . $constantName;
             }
             // Add constant name
             $constantName .= '::' . $matches['name'][$i];
             $replaceName = $matches['start'][$i] . $matchClass . '::' . $matches['name'][$i] . $matches['end'][$i];
             // Check if we have this constant defined
             if (defined($constantName)) {
                 // Get constant value
                 $value = constant($constantName);
                 // Fix slashes, add quotes for string
                 $value = is_string($value) ? str_replace('\\', '\\\\\\\\', "'" . $value . "'") : $value;
                 $replacer = str_replace('\\', '\\\\', $replaceName);
                 $replacer = str_replace(array(')', '('), array('\\)', '\\('), $replacer);
                 // Replace constant call in the code
                 $main_code = preg_replace('/' . $replacer . '/i', $matches['start'][$i] . $value . $matches['end'][$i], $main_code);
             }
         }
     }
     // Запишем в коллекцию кода полученный код
     $code[$namespace][$path] = $main_code;
     return $main_code;
 }
Example #3
0
 /**
  * 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;
 }
 /**
  * Generate ORM classes
  * @param string $force Force class generation
  */
 public function generate($force = false, $cachePath = '')
 {
     // Processed permanent table relations
     $db_relations = array();
     // Get all virtual tables structure data
     $db_mapper = array();
     // Получим информацию о всех таблицах из БД
     $rows = $this->fetch('SELECT
           `TABLES`.`TABLE_NAME` as `TABLE_NAME`,
           `COLUMNS`.`COLUMN_NAME` as `Field`,
           `COLUMNS`.`DATA_TYPE` as `Type`,
           `COLUMNS`.`IS_NULLABLE` as `Null`,
           `COLUMNS`.`COLUMN_KEY` as `Key`,
           `COLUMNS`.`COLUMN_DEFAULT` as `Default`,
           `COLUMNS`.`EXTRA` as `Extra`
           FROM `information_schema`.`TABLES` as `TABLES`
           LEFT JOIN `information_schema`.`COLUMNS` as `COLUMNS`
           ON `TABLES`.`TABLE_NAME`=`COLUMNS`.`TABLE_NAME`
           WHERE `TABLES`.`TABLE_SCHEMA`="' . $this->database . '" AND `COLUMNS`.`TABLE_SCHEMA`="' . $this->database . '"');
     foreach ($rows as $row) {
         // Получим имя таблицы
         $table_name = $row['TABLE_NAME'];
         // Создадим коллекцию для описания структуры таблицы
         if (!isset(self::$tables[$table_name])) {
             self::$tables[$table_name] = array();
         }
         // Удалим имя таблицы из масива
         unset($row['TABLE_NAME']);
         // Запишем описание каждой колонки таблиц в специальный массив
         self::$tables[$table_name][] = $row;
     }
     $bstr = md5(serialize(self::$tables));
     //TODO: check if virtual table has not changed and add it to hash
     // Создадим имя файла содержащего пути к модулям
     $md5_file = $cachePath . 'metadata/classes_' . $bstr . '.php';
     $md5_file_func = $cachePath . 'metadata/func_' . $bstr . '.php';
     // Если еще не создан отпечаток базы данных - создадим его
     if (!file_exists($md5_file) || $force) {
         // Get directory path
         $dir = pathname($md5_file);
         // Create folder
         if (!file_exists($dir)) {
             mkdir($dir, 0777, true);
         } else {
             File::clear($dir);
         }
         // Удалим все файлы с расширением map
         //foreach ( \samson\core\File::dir( getcwd(), 'dbs' ) as $file ) unlink( $file );
         // Если еще не создан отпечаток базы данных - создадим его
         // Сохраним классы БД
         $db_classes = 'namespace samson\\activerecord;';
         $db_func = '';
         // Создадим классы
         foreach ($db_mapper as $table_name => $table_data) {
             $file_full = $this->classes($table_data, $table_name, $virtualTable->table, $db_relations);
             $db_classes .= $file_full[0];
             $db_func .= $file_full[1];
         }
         // Создадим классы
         foreach (self::$tables as $table_name => $table_data) {
             $file_full = $this->classes(self::$tables[$table_name], $table_name, $table_name, $db_relations);
             $db_classes .= $file_full[0];
             $db_func .= $file_full[1];
         }
         // Запишем файл для IDE в корень проекта
         file_put_contents($md5_file, '<?php ' . $db_classes . '?>');
         file_put_contents($md5_file_func, '<?php ' . $db_func . '?>');
         // Подключим наш ХУК для АктивРекорда!!!!!
         eval($db_classes);
         eval($db_func);
     } else {
         include $md5_file;
         include $md5_file_func;
     }
     //elapsed('end');
 }