Example #1
0
 public function getTables($scope = ENTITY_SCOPE_ALL)
 {
     if (!is_array($this->TABLES)) {
         $this->TABLES[ENTITY_SCOPE_ALL] = array();
         $this->TABLES[ENTITY_SCOPE_SDK] = array();
         $this->TABLES[ENTITY_SCOPE_PROJ] = array();
         $tables = PsTable::all();
         $tablesNotConfigured = array();
         //Таблицы, описанные в ini, но не сконфигурированные
         foreach (DbIni::getTables() as $tableName) {
             if (!array_key_exists($tableName, $tables)) {
                 continue;
                 //---
             }
             /* @var $table PsTable */
             $table = $tables[$tableName];
             if ($table->isConfigured()) {
                 $this->TABLES[ENTITY_SCOPE_ALL][$tableName] = $table;
                 $this->TABLES[$table->getScope()][$tableName] = $table;
                 unset($tables[$tableName]);
             } else {
                 $tablesNotConfigured[ENTITY_SCOPE_ALL][$tableName] = $table;
                 $tablesNotConfigured[$table->getScope()][$tableName] = $table;
             }
         }
         foreach ($tablesNotConfigured as $_scope => $_tables) {
             $this->TABLES[$_scope] = array_merge($this->TABLES[$_scope], $_tables);
         }
         foreach ($tables as $tableName => $table) {
             $this->TABLES[ENTITY_SCOPE_ALL][$tableName] = $table;
             $this->TABLES[$table->getScope()][$tableName] = $table;
         }
     }
     return $this->TABLES[PsCheck::scope($scope)];
 }
Example #2
0
 public function buildContent()
 {
     $navigation = AdminPageNavigation::inst();
     $PARAMS['mode'] = self::MODE_TABLES_LIST;
     /*
      * Просмотр содержимого таблицы
      */
     $table = RequestArrayAdapter::inst()->str('table');
     if ($table) {
         $PARAMS['mode'] = self::MODE_TABLE_VIEW;
         $table = PsTable::inst($table);
         $PARAMS['table'] = $table;
         $PARAMS['rows'] = $table->getRows();
         $navigation->addPath(self::urlTables(), 'Настройки');
         $navigation->setCurrent('Просмотр ' . $table->getName());
     }
     /*
      * Просмотр и настройка всех таблиц
      */
     if ($PARAMS['mode'] == self::MODE_TABLES_LIST) {
         $PARAMS['errors'] = PsDbIniHelper::validateAll();
         foreach (ConfigIni::getAllowedScopes() as $scope) {
             $PARAMS['data'][$scope] = TableExporter::inst()->getTables($scope);
             $PARAMS['data']["{$scope}.ini"] = DbIni::getIniContent($scope);
         }
         $navigation->setCurrent('Настройки');
     }
     echo $this->getFoldedEntity()->fetchTpl($PARAMS);
 }
Example #3
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');
}
Example #4
0
 /**
  * Метод валидирует настройки таблицы, заданные в b.ini
  */
 public static function validateTableProperties(PsTable $table)
 {
     return self::validateTablePropertiesCustom($table, DbIni::getGroupOrNull($table->getName()));
 }
Example #5
0
 /**
  * Проверка, относится ли таблица к SDK
  */
 public function isSdk()
 {
     return DbIni::isSdkTable($this->getName());
 }
Example #6
0
 /**
  * Метод формирует сщвуржимое db.ini файла для развёрнутой схемы.
  * 
  * За основу берутся текущие натсройки db.ini, которые могут быть расширены 
  * или сокращены (если таблица удалена из схемы).
  * 
  * @param string $scope - тип развёрнутой схемы.
  *                      Она может быть развёрнута, как SDK или как проектная.
  *                      Считаем, что в схему могли как добавиться новые таблицы,
  *                      так и кол-во таблиц в схеме могло быть сокращено.
  * @return array - настройки таблиц для db.ini
  */
 public static function makeDbIniForSchema($scope, array $dbTables)
 {
     /*
      * Список таблиц SDK можно получить из db.ini, так как если мы работаем по SDK,
      * то нужно взять старые настройки и порядок таблиц.
      * Если же мы работаем по проектному скоупу, то db.ini для SDK уже актуален.
      */
     $sdkTableNames = DbIni::getSdkTables();
     $settings = array();
     switch ($scope) {
         case ENTITY_SCOPE_SDK:
             foreach ($sdkTableNames as $tableName) {
                 if (!array_key_exists($tableName, $dbTables)) {
                     //Таблица была исключена из схемы
                     continue;
                     //---
                 }
                 $table = array_get_value_unset($tableName, $dbTables);
                 $settings[$tableName] = array();
                 /* @var $property PsTableColumnProps */
                 foreach (PsTableColumnProps::getAllowedTableProperties($table) as $propName => $property) {
                     $settings[$tableName][$propName] = $table->isProperty($property);
                 }
                 /* @var $property PsTableColumnProps */
                 foreach (PsTableColumnProps::getAllowedColumnProperties($table) as $propName => $property) {
                     /* @var $col PsTableColumn */
                     foreach ($table->getColumns() as $colName => $col) {
                         if ($col->isProperty($property)) {
                             $settings[$tableName][$propName][] = $colName;
                         }
                     }
                 }
             }
             /*
              * Добавляем несконфигурированные таблицы
              */
             foreach ($dbTables as $tableName => $table) {
                 $settings[$tableName] = array();
                 /* @var $property PsTableColumnProps */
                 foreach (PsTableColumnProps::getAllowedTableProperties($dbTables[$tableName]) as $propName => $property) {
                     $settings[$tableName][$propName] = false;
                 }
             }
             break;
         case ENTITY_SCOPE_PROJ:
             //Сразу удаляем из списка все таблицы SDK
             array_remove_keys($dbTables, $sdkTableNames);
             foreach (DbIni::getProjectTables() as $tableName) {
                 if (!array_key_exists($tableName, $dbTables)) {
                     //Таблица была исключена из схемы или перенесена в SDK
                     continue;
                     //---
                 }
                 $table = array_get_value_unset($tableName, $dbTables);
                 $settings[$tableName] = array();
                 /* @var $property PsTableColumnProps */
                 foreach (PsTableColumnProps::getAllowedTableProperties($table) as $propName => $property) {
                     $settings[$tableName][$propName] = $table->isProperty($property);
                 }
                 /* @var $property PsTableColumnProps */
                 foreach (PsTableColumnProps::getAllowedColumnProperties($table) as $propName => $property) {
                     /* @var $col PsTableColumn */
                     foreach ($table->getColumns() as $colName => $col) {
                         if ($col->isProperty($property)) {
                             $settings[$tableName][$propName][] = $colName;
                         }
                     }
                 }
             }
             /*
              * Не добавляем несконфигурированные таблицы, так как для проектных 
              * таблиц мы не требуем полного перечисления в db.ini
              */
             break;
         default:
             raise_error("Unknown scope [{$scope}]");
     }
     return $settings;
 }