Beispiel #1
0
 public static function valueOf($name)
 {
     if (in_array($name, self::names())) {
         return static::$name();
     }
     PsUtil::raise('Enum {} not contains value {}', get_called_class(), $name);
 }
 /**
  * Метод возвращает экземпляр класса-хранилища маппингов.
  * Может быть переопределён в config.ini
  */
 private static final function inst()
 {
     if (isset(self::$inst)) {
         return self::$inst;
         //----
     }
     /*
      * Получим название класса
      */
     $class = ConfigIni::mappingStorage();
     /*
      * Класс совпадает с базовым?
      */
     if (__CLASS__ == $class) {
         return self::$inst = new MappingStorage();
     }
     /*
      * Нам передан класс, который отличается от SDK
      */
     $classPath = Autoload::inst()->getClassPath($class);
     if (!PsCheck::isNotEmptyString($classPath)) {
         return PsUtil::raise('Не удалось найти класс хранилища маппингов [{}]', $class);
     }
     /*
      * Указанный класс должен быть наследником данного
      */
     if (!PsUtil::isInstanceOf($class, __CLASS__)) {
         return PsUtil::raise('Указанное хранилище маппингов [{}] не является наследником класса [{}]', $class, __CLASS__);
     }
     return self::$inst = new $class();
 }
Beispiel #3
0
 /**
  * Метод вызывается для инициализации окружения:
  * 1. Директория ресурсов окружения будет подключена в Autoload
  * 2. Файл, включающий окружение, будет выполнен
  */
 public static function init()
 {
     if (self::$inited) {
         return;
         //---
     }
     self::$inited = true;
     //---
     /*
      * Проверим, нужно ли подключать окружение
      */
     if (self::isSkipInclude()) {
         return;
         //---
     }
     $env = self::env();
     if (!$env) {
         return;
         //---
     }
     $envDir = array_get_value($env, ConfigIni::environments());
     if (!$envDir) {
         return PsUtil::raise('Environment [{}] not found', $env);
     }
     if (!is_dir($envDir)) {
         return PsUtil::raise('Environment dir for [{}] not found', $env);
     }
     $envSrcDir = next_level_dir($envDir, DirManager::DIR_SRC);
     $envIncFile = file_path($envDir, $env, PsConst::EXT_PHP);
     if (!is_file($envIncFile)) {
         return PsUtil::raise('Environment include file for [{}] not found', $env);
     }
     $LOGGER = PsLogger::inst(__CLASS__);
     if ($LOGGER->isEnabled()) {
         $LOGGER->info('Including \'{}\' environment for context \'{}\'', $env, PsContext::describe());
         $LOGGER->info('Env dir:  {}', $envDir);
         $LOGGER->info('Src dir:  {}', $envSrcDir);
         $LOGGER->info('Inc file: {}', $envIncFile);
     }
     //Проинициализировано окружение
     self::$included = true;
     //Регистрируем директорию с классами, специфичными только для данного окружения
     Autoload::inst()->registerBaseDir($envSrcDir, false);
     //Выполним необходимое действие
     $PROFILER = PsProfiler::inst(__CLASS__);
     try {
         $LOGGER->info('{');
         $PROFILER->start($env);
         self::initImpl($LOGGER, $envIncFile);
         $secundomer = $PROFILER->stop();
         $LOGGER->info('}');
         $LOGGER->info('Inc file included for {} sec', $secundomer->getTime());
     } catch (Exception $ex) {
         $PROFILER->stop(false);
         $LOGGER->info('Inc file execution error: [{}]', $ex->getMessage());
         throw $ex;
         //---
     }
 }
Beispiel #4
0
 public function __construct(array $data)
 {
     /*
      * Инициализируем поля
      */
     parent::__construct($data);
     /*
      * Определим тип поля ($coltype)
      */
     switch ($this->getDataType()) {
         //ЧИСЛОВЫЕ
         case 'tinyint':
             if (starts_with($this->getName(), 'b_')) {
                 $this->coltype = self::TYPE_BIT;
                 break;
             }
         case 'int':
             if (starts_with($this->getName(), 'dt_')) {
                 $this->coltype = self::TYPE_INT_DATE;
                 break;
             }
             $this->coltype = self::TYPE_INT;
             break;
             //ТЕКСТОВЫЕ
         //ТЕКСТОВЫЕ
         case 'char':
             if ($this->getCharMaxlen() == 1) {
                 $this->coltype = self::TYPE_CHAR;
                 break;
             }
         case 'varchar':
             if ($this->getCharMaxlen() <= 255) {
                 if (starts_with($this->getName(), 'dt_')) {
                     $this->coltype = self::TYPE_STRING_DATE;
                 } else {
                     $this->coltype = self::TYPE_STRING;
                 }
                 break;
             }
         case 'text':
             $this->coltype = self::TYPE_TEXT;
             break;
         default:
             PsUtil::raise('Неизвестный тип данных для столбца {}.{}: {}.', $this->getTableName(), $this->getName(), $this->getDataType());
             break;
     }
 }
Beispiel #5
0
 public static function format($__CLASS__, $__FUNCTION__, array $arguments)
 {
     if (!array_key_exists($__CLASS__, self::$MESSAGES)) {
         /*
          * Защита от зацикливания
          */
         self::$MESSAGES[$__CLASS__] = null;
         /*
          * Определим, где расположен класс с сообщениями
          */
         $classPath = Autoload::inst()->getClassPath($__CLASS__);
         if (!$classPath) {
             return PsUtil::raise('Группа сообщений {} не зарегистрирована', $__CLASS__);
         }
         /*
          * Получим DirItem сообщений для этого класса
          */
         $messagesDi = DirItem::inst(dirname($classPath), $__CLASS__, PsConst::EXT_MSGS);
         if (!$messagesDi->isFile()) {
             return PsUtil::raise('Файл с сообщениями {} не существует', $messagesDi->getName());
         }
         /*
          * Распарсим сообщения из файла
          */
         self::$MESSAGES[$__CLASS__] = $messagesDi->getFileAsProps();
     }
     /*
      * Проверим на зацикливание
      */
     if (self::$MESSAGES[$__CLASS__] === null) {
         PsUtil::raise('Зацикливание при попытке получить сообещние {}::{}', $__CLASS__, $__FUNCTION__);
     }
     /*
      * Проверим на существование самого сообщения
      */
     if (!array_key_exists($__FUNCTION__, self::$MESSAGES[$__CLASS__])) {
         return PsUtil::raise('Сообщение {}::{} не существует', $__CLASS__, $__FUNCTION__);
     }
     /*
      * Заменим макросы {} и вернём сообщение
      */
     return PsStrings::replaceMapBracedKeys(self::$MESSAGES[$__CLASS__][$__FUNCTION__], $arguments);
 }
Beispiel #6
0
 /**
  * Метод предназначен для загрузки единичной записи. Если извлекается более одной записи -
  * выбразывается исключение.
  *
  * $ensureHasOne:
  * true - если не найдена единственная запись, выкидывает ошибку
  * false - если не найдена единственная запись, метод возвращает null
  */
 public static function getRec($query, $inputarr = false, $ensureHasOne = false)
 {
     $rs = self::executeQuery($query, $inputarr, $queryFinal, $paramsFinal);
     $rs->Close();
     switch ($rs->RecordCount()) {
         case 0:
             if ($ensureHasOne) {
                 throw new DBException('No data found', DBException::ERROR_NO_DATA_FOUND, $queryFinal, $paramsFinal);
             }
             return null;
             //---
         //---
         case 1:
             return $rs->fields;
             //---
         //---
         default:
             throw new DBException('Too many rows', DBException::ERROR_TOO_MANY_ROWS, $queryFinal, $paramsFinal);
     }
     PsUtil::raise('Unexpected recs count requrned: {}', $rs->RecordCount());
 }
 /**
  * Метод возвращает экземпляр класса-хранилища экземпляров фолдинов.
  * Для переопределения этого класса, на уровне проектного config.ini
  * должен быть задан другой класс.
  * 
  * @return FoldedStorageInsts
  */
 protected static final function inst()
 {
     if (isset(self::$inst)) {
         return self::$inst;
         //----
     }
     /*
      * Получим название класса
      */
     $class = FoldingsIni::foldingsStore();
     /*
      * Класс совпадает с базовым
      */
     if (__CLASS__ == $class) {
         return self::$inst = new FoldedStorageInsts();
     }
     /*
      * Нам передан класс, который отличается от SDK
      */
     $classPath = Autoload::inst()->getClassPath($class);
     if (!PsCheck::isNotEmptyString($classPath)) {
         return PsUtil::raise('Не удалось найти класс регистрации экземпляров фолдингов [{}]', $class);
     }
     /*
      * Указанный класс должен быть наследником данного
      */
     if (!PsUtil::isInstanceOf($class, __CLASS__)) {
         return PsUtil::raise('Указанный класс регистрации экземпляров фолдингов [{}] не является наследником класса [{}]', $class, __CLASS__);
     }
     return self::$inst = new $class();
 }
 /**
  * Метод возвращает экземпляр класса-плагина Smarty.
  * Для переопределения этого класса, на уровне проектного config.ini
  * должен быть задан другой класс.
  * 
  * Это позволит использовать стандартизованный метод подключения плагинов
  */
 public static final function inst()
 {
     if (isset(self::$inst)) {
         return self::$inst;
         //----
     }
     /*
      * Получим название класса
      */
     $class = ConfigIni::smartyPlugin();
     /*
      * Класс подключения библиотек совпадает с базовым
      */
     if (__CLASS__ == $class) {
         return self::$inst = new PSSmartyPlugin();
     }
     /*
      * Нам передан класс, который отличается от SDK
      */
     $classPath = Autoload::inst()->getClassPath($class);
     if (!PsCheck::isNotEmptyString($classPath)) {
         return PsUtil::raise('Не удалось найти класс плагинов Smarty [{}]', $class);
     }
     /*
      * Указанный класс должен быть наследником данного
      */
     if (!PsUtil::isInstanceOf($class, __CLASS__)) {
         return PsUtil::raise('Указанный плагин Smarty [{}] не является наследником класса [{}]', $class, __CLASS__);
     }
     return self::$inst = new $class();
 }
Beispiel #9
0
<?php

/*
 * wordpress - Классы окружения, когда ps-sdk работает, как wordpress plugin.
 * Нужно учитывать, что ps-sdk может быть вызван после подключения классов 
 * wordpress (например при построении страницы, когда подключаются плагины) или до этого
 */
if (PsUtil::isWordPress()) {
    /*
     * Мы уже работаем как часть WordPress, ничего делать не нужно.
     * Классы src подключатся автоматически.
     */
    $LOGGER->info('WordPress is already loaded, skip including...');
    //Нужно подключить данный класс, так как он подключается после пагинов
    //Код подключения находится в файле /wp-settings.php
    require_once ABSPATH . WPINC . '/pluggable.php';
} else {
    /*
     * Нас вызвали раньше wordpress. Это может быть процесс, или ajax, или ещё что-либо.
     * Необходимо проанализировать контекст выполнения, нужно ли подключить ядро.
     */
    $wpInc = PATH_BASE_DIR . 'wp-load.php';
    $LOGGER->info('WordPress is not loaded yet, include wp core \'{}\'', $wpInc);
    if (is_file($wpInc)) {
        require_once $wpInc;
    } else {
        PsUtil::raise('WordPress core file not found, environment cannot be loaded.');
    }
}
//Установим специальный провайдер безопасности
PsSecurity::set(new PsSecurityProviderWp());
Beispiel #10
0
 /**
  * Загрузка конкретной настройки
  */
 public static function getProp($group, $prop, $mandatory = true, $scope = ENTITY_SCOPE_ALL)
 {
     if (self::hasProp($group, $prop, $scope)) {
         return self::getGroup($group, true, $scope)[$prop];
     }
     if ($mandatory) {
         PsUtil::raise('Required config property [{}/{}] not found in {} [{}]', $group, $prop, static::getConfigName(), $scope);
     }
     return null;
     //--
 }
 public function registerContents($contents)
 {
     $this->getEntitys();
     $contents = to_array($contents);
     foreach ($contents as $entity) {
         if (is_array($entity)) {
             $this->registerContents($entity);
             continue;
         }
         if (!is_object($entity)) {
             continue;
         }
         if (!method_exists($entity, 'getId') || !method_exists($entity, 'getIdent')) {
             return PsUtil::raise('Контент сущности {} не имеет методов getId и getIdent', $this->entityTitle());
         }
         $id = $entity->getId();
         $this->assertExistsWithId($id);
         $this->ENTITYS[$id] = $entity;
         $this->CONTENTS[$id] = true;
     }
 }
Beispiel #12
0
 /**
  * Проверка состояния
  * 
  * @param int $state - одно из состояний
  */
 private function checkState($state)
 {
     if ($state !== $this->STATE) {
         PsUtil::raise('Invalid state of {}. Current state: {}. Expected: {}.', __CLASS__, PsUtil::getClassConstByValue(__CLASS__, 'STATE_', $this->STATE), PsUtil::getClassConstByValue(__CLASS__, 'STATE_', $state));
     }
 }
Beispiel #13
0
 /**
  * Извлекает тип и подтип фолдинга из его идентификатора:
  * [lib-p] => [lib, p]
  */
 public static function extractFoldedTypeAndSubtype($foldedUnique, &$type, &$subtype)
 {
     $tokens = explode('-', PsCheck::notEmptyString($foldedUnique), 3);
     $tokensCnt = count($tokens);
     switch ($tokensCnt) {
         case 1:
             $type = PsCheck::notEmptyString($tokens[0]);
             $subtype = '';
             break;
         case 2:
             $type = PsCheck::notEmptyString($tokens[0]);
             $subtype = PsCheck::notEmptyString($tokens[1]);
             break;
         default:
             PsUtil::raise('Invalid folded resource ident: [{}]', $foldedUnique);
     }
 }
Beispiel #14
0
 public function assertExtension($ext)
 {
     if (PsCheck::notEmptyString($ext) !== $this->getExtension()) {
         PsUtil::raise('File with extention [.{}] is expected', $ext);
     }
 }
 /**
  * Метод получения коннекта к БД
  * 
  * @return ADOConnection
  */
 protected final function getConnection()
 {
     if ($this->CONNECTION != null) {
         return $this->CONNECTION;
         //---
     }
     if (!$this->isConfigured()) {
         PsUtil::raise('Cannot get DB connection, {} is not configured.', get_called_class());
     }
     $this->LOGGER->info();
     $this->LOGGER->info('?  Connection for [{}] is requested', $this->CONNECTION_PARAMS);
     $URL = $this->CONNECTION_PARAMS->url();
     //Посмотрим, есть ли у нас нужный коннект
     if (array_key_exists($URL, $this->CONNECTIONS)) {
         $this->LOGGER->info('<  Fast returned from cache');
         return $this->CONNECTION = $this->CONNECTIONS[$URL];
     }
     //Отлогируем
     $this->LOGGER->info('+  Establishing connection {}', $this->CONNECTION_PARAMS);
     //Подключаем adodb
     PsLibs::inst()->AdoDb();
     //Подключаемся
     $this->CONNECTION = ADONewConnection($URL);
     if (!is_object($this->CONNECTION)) {
         PsUtil::raise("Unable to connect to [{}]", $this->CONNECTION_PARAMS);
     }
     //Зададим некоторые настройки
     $this->CONNECTION->debug = ADODB_DEBUG;
     $this->CONNECTION->SetFetchMode(ADODB_FETCH_ASSOC);
     $this->CONNECTION->query("SET NAMES 'utf8'");
     $this->CONNECTION->query("SET CHARACTER SET 'utf8'");
     //Положим соединение в пул
     if (array_key_exists($URL, $this->CONNECTIONS)) {
         raise_error('Double trying to register db connection');
     }
     $this->LOGGER->info('<  Established connection returned');
     return $this->CONNECTIONS[$URL] = $this->CONNECTION;
 }
Beispiel #16
0
function executeProcess(array $argv)
{
    PsConnectionPool::assertDisconnectied();
    /*
     * СОЗДАЁМ SQL
     * 
     * Нам нужны настройки таблиц, которые неоткуда взять, кроме как из базы, поэтому для экспорта данных нужна БД.
     * Все данные из "редактируемых" таблиц также загружаются из этой БД.
     */
    $DB = DirManager::inst(__DIR__ . '/temp');
    $SDK = DirManager::inst(__DIR__ . '/temp/sdk');
    //Почистим файлы для удаления
    dolog('Clearing not .sql/.txt from temp dir');
    /* @var $item DirItem */
    foreach ($DB->getDirContentFull(null, DirItemFilter::FILES) as $item) {
        if (!$item->checkExtension(array(PsConst::EXT_TXT, PsConst::EXT_SQL))) {
            dolog('[-] {}', $item->remove()->getRelPath());
        }
    }
    dolog();
    /*
     * SDK
     */
    //dolog('Processing objects.sql');
    /* @var $DIR DirManager */
    foreach (array(ENTITY_SCOPE_SDK => $SDK, ENTITY_SCOPE_PROJ => $DB) as $scope => $DM) {
        dolog();
        dolog('***************************************************************');
        dolog('>>> Processing scope [{}], dir: [{}]', $scope, $DM->absDirPath());
        $SCHEMA = $DM->getDirItem(null, 'schema.sql');
        if (!$SCHEMA->isFile()) {
            dolog('schema.sql is not exists, skipping');
            continue;
            //---
        }
        $DM_SYSOBJECTS = DirManager::inst($DM->absDirPath(), 'sysobjects');
        /*
         * Очищаем папку, в которой будет содержимое для автосгенерированных файлов
         */
        $DM_AUTO = DirManager::inst($DM_SYSOBJECTS->absDirPath(), 'auto')->clearDir();
        /*
         * Создадим ссылку на файл с данными, выгруженными из таблиц
         */
        $DI_AUTO_DATA = $DM_AUTO->getDirItem(null, 'data.sql');
        /*
         * Сначала сделаем триггеры на таблицы, от которых зависит кеш и к которым привязаны фолдинги.
         */
        LOGBOX_INIT();
        LOGBOX('Making cache and folding table triggers');
        $DM_AUTO_TRIGGERS = $DM_AUTO->getDirItem('triggers')->makePath();
        $DI_AUTO_TRIGGERS_SQL = $DM_AUTO->getDirItem(null, 'triggers', 'sql')->getSqlFileBuilder();
        $triggerPattern = $SDK->getDirItem('sysobjects/patterns', 'ta_iud_pattern.sql')->getFileContents();
        //BUILDIAN AND ADDING TRIGGERS
        foreach (PsTriggersAware::getTriggeredTables($scope) as $table) {
            foreach (PsTriggersAware::getActions() as $action) {
                $actions = PsTriggersAware::getTriggerActions($table, $scope, $action);
                if (empty($actions)) {
                    continue;
                    //---
                }
                $name = 'ta' . strtolower(first_char($action)) . '_' . $table;
                $trigger = str_replace('<%NAME%>', $name, $triggerPattern);
                $trigger = str_replace('<%TABLE%>', $table, $trigger);
                $trigger = str_replace('<%ACTION%>', $action, $trigger);
                $trigger = str_replace('<%CALL%>', implode("\n", $actions), $trigger);
                dolog("+ {$name}");
                foreach ($actions as $_action) {
                    dolog($_action);
                }
                $DI_AUTO_TRIGGERS_SQL->appendFile($DM_AUTO_TRIGGERS->getDirItem(null, $name, 'sql')->putToFile($trigger));
            }
        }
        //Все автоматически сгенерированные триггеры положим в отдельный файл
        $DI_AUTO_TRIGGERS_SQL->save();
        $autoTriggers = DirManager::inst($DM_AUTO_TRIGGERS->getAbsPath())->getDirContent(null, PsConst::EXT_SQL);
        dolog('Triggers made: {}', count($autoTriggers));
        /*
         * objects.sql
         */
        $OBJECTS_SQL = $DM_AUTO->getDirItem(null, 'objects.sql')->getSqlFileBuilder();
        /*
         * Добавляем автосгенерированные триггеры
         */
        LOGBOX('Processing objects.sql');
        if (empty($autoTriggers)) {
            dolog('No auto triggers');
        } else {
            dolog('Adding {} auto triggers', count($autoTriggers));
            $OBJECTS_SQL->appendMlComment('AUTO TRIGGERS SECTION');
            /* @var $triggerDi DirItem */
            foreach ($autoTriggers as $triggerDi) {
                dolog('+ {}', $triggerDi->getName());
                $OBJECTS_SQL->appendFile($triggerDi);
            }
        }
        /*
         * Получаем строки с включениями
         */
        $ALL = $DM_SYSOBJECTS->getDirItem(null, 'all.txt')->getFileLines(false);
        if (empty($ALL)) {
            dolog('No includes');
        } else {
            dolog('Adding {} includes from all.txt', count($ALL));
            $OBJECTS_SQL->appendMlComment('INCLUDES SECTION');
            foreach ($ALL as $include) {
                dolog('+ {}', $include);
                $OBJECTS_SQL->appendFile($DM_SYSOBJECTS->getDirItem($include));
            }
        }
        $OBJECTS_SQL->save();
        /*
         * Создаём скрипты инициализации для схем
         */
        foreach (PsConnectionParams::getDefaultConnectionNames() as $connection) {
            if (PsConnectionParams::has($connection, $scope)) {
                $props = PsConnectionParams::get($connection, $scope);
                $database = $props->database();
                if (empty($database)) {
                    continue;
                    //Не задана БД - пропускаем (для root)
                }
                LOGBOX('Making schema script for {}', $props);
                $SCHEMA_SQL = $DM_AUTO->getDirItem('schemas', $database, 'sql')->makePath()->getSqlFileBuilder();
                //DROP+USE
                $SCHEMA_SQL->clean();
                $SCHEMA_SQL->appendLine("DROP DATABASE IF EXISTS {$database};");
                $SCHEMA_SQL->appendLine("CREATE DATABASE {$database} CHARACTER SET utf8 COLLATE utf8_general_ci;");
                $SCHEMA_SQL->appendLine("USE {$database};");
                if ($scope == ENTITY_SCOPE_PROJ) {
                    dolog('+ SDK PART');
                    //Добавим секцию в лог
                    $SCHEMA_SQL->appendMlComment('>>> SDK');
                    //CREATE CHEMA SCRIPT
                    $SCHEMA_SQL->appendFile($SDK->getDirItem(null, 'schema.sql'));
                    //OBJECTS SCRIPT
                    $SCHEMA_SQL->appendFile($SDK->getDirItem('sysobjects/auto', 'objects.sql'));
                    //Добавим секцию в лог
                    $SCHEMA_SQL->appendMlComment('<<< SDK');
                }
                //CREATE CHEMA SCRIPT
                $SCHEMA_SQL->appendFile($SCHEMA);
                //OBJECTS SCRIPT
                $SCHEMA_SQL->appendFile($OBJECTS_SQL->getDi());
                //CREATE USER
                $grant = "grant all on {}.* to '{}'@'{}' identified by '{}';";
                $SCHEMA_SQL->appendMlComment('Grants');
                $SCHEMA_SQL->appendLine(PsStrings::replaceWithBraced($grant, $database, $props->user(), $props->host(), $props->password()));
                /*
                 * Мы должны создать тестовую схему, чтобы убедиться, что всё хорошо и сконфигурировать db.ini
                 */
                if ($connection == PsConnectionParams::CONN_TEST) {
                    dolog('Making physical schema {}', $props);
                    $rootProps = PsConnectionParams::get(PsConnectionParams::CONN_ROOT);
                    dolog('Root connection props: {}', $rootProps);
                    $rootProps->execureShell($SCHEMA_SQL->getDi());
                    dolog('Connecting to [{}]', $props);
                    PsConnectionPool::configure($props);
                    $tables = PsTable::all();
                    /*
                     * Нам нужно определить новый список таблиц SDK, чтобы по ним 
                     * провести валидацию новых db.ini.
                     * 
                     * Если мы обрабатываем проект, то SDK-шный db.ini уже готов и 
                     * можем положиться на него. Если мы подготавливаем SDK-шный db.ini,
                     * но новый список таблиц возмём из развёрнутой тестовой БД.
                     */
                    $sdkTableNames = $scope == ENTITY_SCOPE_SDK ? array_keys($tables) : DbIni::getSdkTables();
                    if ($scope == ENTITY_SCOPE_PROJ) {
                        //Уберём из всех таблиц - SDK`шные
                        array_remove_keys($tables, $sdkTableNames);
                    }
                    $scopeTableNames = array_keys($tables);
                    sort($scopeTableNames);
                    /*
                     * Составим список таблиц.
                     * Он нам особенно не нужен, но всёже будем его формировать для наглядности - какие таблицы добавились.
                     */
                    $tablesDi = $DM_AUTO->getDirItem(null, 'tables.txt')->putToFile(implode("\n", $scopeTableNames));
                    dolog('Tables: {} saved to {}', print_r($scopeTableNames, true), $tablesDi->getAbsPath());
                    /*
                     * Загружаем полный список таблиц схемы и на основе имеющихся db.ini файлов строим новые, добавляя/удаляя 
                     * таблицы, добавленные/удалённые из схемы.
                     */
                    $dbIniProps = PsDbIniHelper::makeDbIniForSchema($scope, $tables);
                    dolog('db.ini props: {}', print_r($dbIniProps, true));
                    $dbIniErrors = PsDbIniHelper::validateAndSaveDbIniTableProps($scope, $dbIniProps, $sdkTableNames);
                    if ($dbIniErrors) {
                        PsUtil::raise('db.ini errors for {}: {}', $scope, print_r($dbIniErrors, true));
                    }
                    /*
                     * Для проекта выгружаем данные, хранящиеся в файлах
                     */
                    if ($scope == ENTITY_SCOPE_PROJ) {
                        dolog('Exporting tables data from files');
                        $DM_AUTO->getDirItem('data')->makePath();
                        $AUTO_DATA_SQL = $DI_AUTO_DATA->touch()->getSqlFileBuilder();
                        //Пробегаемся по таблицам
                        foreach (DbIni::getTables() as $tableName) {
                            $table = PsTable::inst($tableName);
                            if ($table->isFilesync()) {
                                $fileData = $table->exportFileAsInsertsSql();
                                if ($fileData) {
                                    dolog(' + {}', $tableName);
                                    $AUTO_DATA_SQL->appendFile($DM_AUTO->getDirItem('data', $tableName, 'sql')->putToFile($fileData));
                                } else {
                                    dolog(' - {}', $tableName);
                                }
                            }
                        }
                        $AUTO_DATA_SQL->save();
                        /*
                         * Вставим данные в тестовую схему
                         */
                        dolog('Inserting data to test schema.');
                        $props->execureShell($DI_AUTO_DATA);
                    }
                    /*
                     * Теперь ещё создадим тестовые объекты.
                     * Мы уверены, что для SDK тестовая часть есть всегда.
                     */
                    $TEST_SCHEMA_SQL = $DM_AUTO->getDirItem('test', 'schema', 'sql')->makePath()->getSqlFileBuilder();
                    if ($scope == ENTITY_SCOPE_PROJ) {
                        dolog('+ SDK TEST PART');
                        //Добавим секцию в лог
                        $TEST_SCHEMA_SQL->appendMlComment('>>> SDK');
                        //CREATE CHEMA SCRIPT
                        $TEST_SCHEMA_SQL->appendFile($SDK->getDirItem('sysobjects/auto/test', 'schema.sql'));
                        //Добавим секцию в лог
                        $TEST_SCHEMA_SQL->appendMlComment('<<< SDK');
                    }
                    $TEST_SCHEMA_SQL->appendFile($DM_SYSOBJECTS->getDirItem('test', 'schema.sql'), false);
                    $TEST_SCHEMA_SQL->appendFile($DM_SYSOBJECTS->getDirItem('test', 'data.sql'), false);
                    $TEST_SCHEMA_SQL->save();
                    /*
                     * На тестовой схеме прогоняем скрипты с тестовыми данными
                     */
                    dolog('Making test schema objects.');
                    $props->execureShell($TEST_SCHEMA_SQL->getDi());
                }
                #end conn== TEST
                /*
                 * Если были сгенерированы данные из файлов - добавляем их
                 */
                if ($DI_AUTO_DATA->isFile() && $DI_AUTO_DATA->getSize() > 0) {
                    dolog('Append data inserts to {}', $SCHEMA_SQL->getDi()->getName());
                    $SCHEMA_SQL->appendFile($DI_AUTO_DATA);
                }
                //SAVE .sql
                $SCHEMA_SQL->save();
            }
        }
    }
    dolog('Database schemas successfully exported');
}
Beispiel #17
0
 /**
  * Метод возвращает экземпляр класса, подключающего библиотеки.
  * Для переопределения этого класса, на уровне проектного config.ini
  * должен быть задан другой класс, отвечающий за подключение библиотек.
  * 
  * Это позволит:
  * 1. Использовать стандартизованный метод подключения внешних библиотек
  * 2. Переопределить подключение библиотек из SDK
  */
 public static final function inst()
 {
     if (isset(self::$inst)) {
         return self::$inst;
         //----
     }
     /*
      * Получим название класса, отвечающего за подключение библиотек
      */
     $class = ConfigIni::libsIncluder();
     /*
      * Подготовим директории
      */
     $SDK_LIB_DIR = DirManager::inst(PS_DIR_INCLUDES, DirManager::DIR_LIB)->absDirPath();
     $PROJ_LIB_DIR = DirManager::inst(PS_DIR_ADDON, DirManager::DIR_LIB)->absDirPath();
     /*
      * Класс подключения библиотек совпадает с базовым
      */
     if (__CLASS__ == $class) {
         self::$inst = new PsLibs();
         self::$inst->SDK_LIB_DIR = $SDK_LIB_DIR;
         self::$inst->LOGGER = PsLogger::inst($class);
         self::$inst->LOGGER->info('Libs includer  SDK: [{}]', __FILE__);
         self::$inst->LOGGER->info('Libs directory SDK: [{}]', $SDK_LIB_DIR);
         return self::$inst;
         //---
     }
     /*
      * Нам передан класс, который отличается от SDK
      */
     $classPath = Autoload::inst()->getClassPath($class);
     if (!PsCheck::isNotEmptyString($classPath)) {
         return PsUtil::raise('Не удалось найти класс загрузчика библиотек [{}]', $class);
     }
     /*
      * Указанный класс должен быть наследником данного
      */
     if (!PsUtil::isInstanceOf($class, __CLASS__)) {
         return PsUtil::raise('Указанный загрузчик библиотек [{}] не является наследником класса [{}]', $class, __CLASS__);
     }
     self::$inst = new $class();
     self::$inst->SDK_LIB_DIR = $SDK_LIB_DIR;
     self::$inst->PROJ_LIB_DIR = $PROJ_LIB_DIR;
     self::$inst->LOGGER = PsLogger::inst($class);
     self::$inst->LOGGER->info('Libs includer  CUSTOM: [{}]', $classPath);
     self::$inst->LOGGER->info('Libs directory    SDK: [{}]', $SDK_LIB_DIR);
     self::$inst->LOGGER->info('Libs directory CUSTOM: [{}]', $PROJ_LIB_DIR);
     return self::$inst;
     //---
 }
Beispiel #18
0
 public function fetchResult(array $ROWS)
 {
     switch ($this->fetchType) {
         /*
          * Фетчим в массив
          */
         case self::FETCH_TYPE_ARRAY:
             $idxCol = $this->idxCol;
             $result = array();
             foreach ($ROWS as $row) {
                 if ($idxCol) {
                     $idx = $row[$idxCol];
                     if ($this->filterKey($idx)) {
                         $inst = $this->getInst($row);
                         if ($inst) {
                             if ($this->useFetcher) {
                                 //http://stackoverflow.com/questions/3637164/why-does-the-error-expected-to-be-a-reference-value-given-appear
                                 $params = array();
                                 $params[] = $inst;
                                 $params[] =& $result;
                                 $params[] = $row;
                                 call_user_func_array($this->fetcher, $params);
                             } else {
                                 $result[$idx] = $inst;
                             }
                         }
                     }
                 } else {
                     $inst = $this->getInst($row);
                     if ($inst) {
                         if ($this->useFetcher) {
                             $params = array();
                             $params[] = $inst;
                             $params[] =& $result;
                             $params[] = $row;
                             call_user_func_array($this->fetcher, $params);
                         } else {
                             $result[] = $inst;
                         }
                     }
                 }
             }
             return $result;
             /*
              * Фетчим одну запись
              */
         /*
          * Фетчим одну запись
          */
         case self::FETCH_TYPE_RECORD:
         case self::FETCH_TYPE_RECORD_OR_NULL:
             $rowsCnt = count($ROWS);
             switch ($rowsCnt) {
                 case 0:
                     if ($this->fetchType == self::FETCH_TYPE_RECORD_OR_NULL) {
                         return null;
                         //--
                     }
                     return PsUtil::raise('Данные для объекта [{}] не найдены', $this->RC->getName());
                 case 1:
                     $inst = $this->getInst($ROWS[0]);
                     if ($inst) {
                         return $inst;
                     }
                     return PsUtil::raise('Объект [{}] загружен, но не прошёл фильтрацию', $this->RC->getName());
             }
             return PsUtil::raise('Найдено {} записей при извлечении объекта [{}]', $rowsCnt, $this->RC->getName());
     }
     PsUtil::raise('Неизвестный тип фетчинга {} для {}', $this->fetchType, __CLASS__);
 }
 /**
  * Метод возвращает путь к классу для сущности фолдинга
  * Если сущности не существует или мы не поддерживаем работу с классами - выдаём ошибку.
  */
 public function getClassPath($ident)
 {
     if (self::PATTERN_NAME === $ident) {
         return PsUtil::raise('Нельзя загрузить путь к классу для сущности {}', self::PATTERN_NAME);
     }
     $this->assertAllowedResourceType(self::RTYPE_PHP);
     return check_condition(FoldedStorage::tryGetEntityClassPath($this->CLASS_PREFIX . $ident), 'Не найден класс реализации для сущности ' . $this->getTextDescr($ident));
 }
Beispiel #20
0
 /**
  * Конструктор класса для работы с кешем.
  * Кеширование идёт в два этапа:
  * 1. Кеширование на уровне класса для максимально быстрого доступа
  * 2. Кеширование в долгосрочном хранилище, которое реализуется отдельным классом - "движком" кеширования
  * 
  * Движок кеширования должен быть задан на уровне config.ini
  * 
  * @return PSCache
  */
 protected function __construct()
 {
     $this->LOGGER = PsLogger::inst(__CLASS__);
     /*
      * Получим название класса "движка" кеширования
      */
     $class = ConfigIni::cacheEngine();
     /*
      * Проверим наличие класса
      */
     $classPath = Autoload::inst()->getClassPath($class);
     if (!PsCheck::isNotEmptyString($classPath)) {
         return PsUtil::raise('Не удалось найти класс для кеширования [{}]', $class);
     }
     /*
      * Правильный ли класс указан?
      */
     if (!PsUtil::isInstanceOf($class, 'PSCacheEngine')) {
         return PsUtil::raise('Указанный класс кеширования [{}] не является наследником класса [{}]', $class, 'PSCacheEngine');
     }
     $this->LOGGER->info('Используем движок кеширования: {}', $class);
     $this->CACHE_ENGINE = new $class();
 }
Beispiel #21
0
 /**
  * Метод вызывается для выполнения периодических задач cron
  * 
  * @return type
  */
 public function execute()
 {
     if ($this->called) {
         return $this->executed;
         //---
     }
     $this->called = true;
     $LOGGER = PsLogger::inst(__CLASS__);
     $LOGGER->info('Executing {}', __CLASS__);
     /*
      * Получим список классов, которые нужно выполнить
      */
     $processes = ConfigIni::cronProcesses();
     if (empty($processes)) {
         $LOGGER->info('No cron processes configured, fast return...');
         return $this->executed;
         //---
     }
     $processes = array_unique($processes);
     $LOGGER->info('Configured processes: {}', array_to_string($processes));
     foreach ($processes as $class) {
         if (!PsUtil::isInstanceOf($class, 'PsCronProcess')) {
             PsUtil::raise("Class {$class} cannot be executed as cron process, it should be instance of PsCronProcess");
         }
     }
     $locked = PsLock::lock(__CLASS__, false);
     $LOGGER->info('Lock accured ? {}', var_export($locked, true));
     if (!$locked) {
         return $this->executed;
         //---
     }
     $LOCKFILE = DirManager::autoNoDel(DirManager::DIR_SERVICE)->getDirItem(null, __CLASS__, PsConst::EXT_LOCK);
     $LOCKFILE_LIFETIME = $LOCKFILE->getFileLifetime();
     $MAX_LIFETIME = 5 * 60;
     $NED_PROCESS = $LOCKFILE_LIFETIME === null || $LOCKFILE_LIFETIME > $MAX_LIFETIME;
     $LOGGER->info("Lock file {}: {}", $LOCKFILE_LIFETIME === null ? 'NOT EXISTS' : 'EXISTS', $LOCKFILE->getRelPath());
     if ($LOCKFILE_LIFETIME !== null) {
         $LOGGER->info('Last modified: {} seconds ago. Max process delay: {} seconds.', $LOCKFILE_LIFETIME, $MAX_LIFETIME);
         //
     }
     if (!$NED_PROCESS) {
         $LOGGER->info('Skip execution.');
         //Отпустим лок
         PsLock::unlock();
         //Выходим
         return $this->executed;
         //---
     }
     //Обновим время последнего выполнения
     $LOCKFILE->touch();
     //Отпустим лок, так как внутри он может потребоваться для выполнения других действий, например для перестройки спрайтов
     PsLock::unlock();
     $LOGGER->info();
     $LOGGER->info('External process execution started...');
     //Запускаем режим неограниченного выполнения
     PsUtil::startUnlimitedMode();
     //Начинаем выполнение
     $this->executed = true;
     //Создаём профайлер
     $PROFILER = PsProfiler::inst(__CLASS__);
     //Создадим конфиг выполнения процесса
     $config = new PsCronProcessConfig();
     //Пробегаемся по процессам и выполняем. При первой ошибке - выходим.
     foreach ($processes as $class) {
         $LOGGER->info('Executing cron process {}', $class);
         $PROFILER->start($class);
         try {
             $inst = new $class();
             $inst->onCron($config);
             $secundomer = $PROFILER->stop();
             $LOGGER->info(" > Cron process '{}' executed in {} seconds", $class, $secundomer->getTotalTime());
         } catch (Exception $ex) {
             $PROFILER->stop();
             $LOGGER->info(" > Cron process '{}' execution error: '{}'", $class, $ex->getMessage());
         }
     }
     $LOGGER->info('Removing cron lock file.');
     $LOCKFILE->remove();
     return $this->executed;
 }
 private function raiseNotRealised($__CLASS__, $__FUNCTION__, $tagName)
 {
     PsUtil::raise("Не реализована функиця {$__CLASS__}->{$__FUNCTION__}, при этом она вызвана для тега {$tagName}");
 }