Example #1
0
 /**
  * get database connection information
  * @param $f3
  * @param bool|false $exec
  * @return array
  */
 protected function checkDatabase($f3, $exec = false)
 {
     foreach ($this->databases as $dbKey => $dbData) {
         $dbLabel = '';
         $dbName = '';
         $dbUser = '';
         $dbConfig = [];
         // DB connection status
         $dbConnected = false;
         // DB type (e.g. MySql,..)
         $dbDriver = 'unknown';
         // enable database ::setup() function in UI
         $dbSetupEnable = false;
         // check  of everything is OK (connection, tables, columns, indexes,..)
         $dbStatusCheckCount = 0;
         // db queries for column fixes (types, indexes, unique)
         $dbColumnQueries = [];
         // tables that should exist in this DB
         $requiredTables = [];
         // check DB for valid connection
         $db = DB\Database::instance()->getDB($dbKey);
         switch ($dbKey) {
             case 'PF':
                 $dbLabel = 'Pathfinder';
                 $dbName = Controller::getEnvironmentData('DB_NAME');
                 $dbUser = Controller::getEnvironmentData('DB_USER');
                 // enable (table) setup for this DB
                 $dbSetupEnable = true;
                 // get table data from model
                 foreach ($dbData['models'] as $model) {
                     $tableConfig = call_user_func($model . '::resolveConfiguration');
                     $requiredTables[$tableConfig['table']] = ['model' => $model, 'name' => $tableConfig['table'], 'fieldConf' => $tableConfig['fieldConf'], 'exists' => false, 'empty' => true, 'foreignKeys' => []];
                 }
                 break;
             case 'CCP':
                 $dbLabel = 'EVE-Online [SDE]';
                 $dbName = Controller::getEnvironmentData('DB_CCP_NAME');
                 $dbUser = Controller::getEnvironmentData('DB_CCP_USER');
                 // get table model from static table array
                 foreach ($dbData['tables'] as $tableName) {
                     $requiredTables[$tableName] = ['exists' => false, 'empty' => true];
                 }
                 break;
         }
         if ($db) {
             // db connect was successful
             $dbConnected = true;
             $dbDriver = $db->driver();
             $dbConfig = $this->checkDBConfig($f3, $db);
             // get tables
             $schema = new SQL\Schema($db);
             $currentTables = $schema->getTables();
             // check each table for changes
             foreach ($requiredTables as $requiredTableName => $data) {
                 $tableExists = false;
                 $tableEmpty = true;
                 // Check if table status is OK (no errors/warnings,..)
                 $tableStatusCheckCount = 0;
                 $currentColumns = [];
                 if (in_array($requiredTableName, $currentTables)) {
                     // Table exists
                     $tableExists = true;
                     // get existing table columns and column related constraints (if exists)
                     $tableModifierTemp = new MySQL\TableModifier($requiredTableName, $schema);
                     $currentColumns = $tableModifierTemp->getCols(true);
                     // get row count
                     $countRes = $db->exec("SELECT COUNT(*) `num` FROM " . $db->quotekey($requiredTableName));
                     $tableEmpty = $countRes[0]['num'] > 0 ? false : true;
                 } else {
                     // table missing
                     $dbStatusCheckCount++;
                     $tableStatusCheckCount++;
                 }
                 foreach ((array) $data['fieldConf'] as $columnName => $fieldConf) {
                     $columnStatusCheck = true;
                     $foreignKeyStatusCheck = true;
                     $requiredTables[$requiredTableName]['fieldConf'][$columnName]['requiredType'] = $fieldConf['type'];
                     $requiredTables[$requiredTableName]['fieldConf'][$columnName]['requiredIndex'] = $fieldConf['index'] ? '1' : '0';
                     $requiredTables[$requiredTableName]['fieldConf'][$columnName]['requiredUnique'] = $fieldConf['unique'] ? '1' : '0';
                     if (array_key_exists($columnName, $currentColumns)) {
                         // column exists
                         // get tableModifier -> possible column update
                         $tableModifier = new MySQL\TableModifier($requiredTableName, $schema);
                         // get new column and copy Schema from existing column
                         $col = new MySQL\Column($columnName, $tableModifier);
                         $col->copyfrom($currentColumns[$columnName]);
                         $currentColType = $currentColumns[$columnName]['type'];
                         $currentColIndexData = call_user_func($data['model'] . '::indexExists', [$columnName]);
                         $currentColIndex = is_array($currentColIndexData);
                         $hasIndex = $currentColIndex ? '1' : '0';
                         $hasUnique = $currentColIndexData['unique'] ? '1' : '0';
                         $changedType = false;
                         $changedUnique = false;
                         $changedIndex = false;
                         // set (new) column information -------------------------------------------------------
                         $requiredTables[$requiredTableName]['fieldConf'][$columnName]['exists'] = true;
                         $requiredTables[$requiredTableName]['fieldConf'][$columnName]['currentType'] = $currentColType;
                         $requiredTables[$requiredTableName]['fieldConf'][$columnName]['currentIndex'] = $hasIndex;
                         $requiredTables[$requiredTableName]['fieldConf'][$columnName]['currentUnique'] = $hasUnique;
                         // check constraint -------------------------------------------------------------------
                         if (isset($fieldConf['constraint'])) {
                             // add or update constraints
                             foreach ((array) $fieldConf['constraint'] as $constraintData) {
                                 $constraint = $col->newConstraint($constraintData);
                                 $foreignKeyExists = $col->constraintExists($constraint);
                                 $requiredTables[$requiredTableName]['foreignKeys'][] = ['exists' => $foreignKeyExists, 'keyName' => $constraint->getConstraintName()];
                                 $col->addConstraint($constraint);
                                 if (!$foreignKeyExists) {
                                     $tableStatusCheckCount++;
                                     $foreignKeyStatusCheck = false;
                                 }
                             }
                         }
                         // check type changed -----------------------------------------------------------------
                         if ($fieldConf['type'] !== 'JSON' && !$schema->isCompatible($fieldConf['type'], $currentColType)) {
                             // column type has changed
                             $changedType = true;
                             $columnStatusCheck = false;
                             $tableStatusCheckCount++;
                         }
                         // check if column unique changed -----------------------------------------------------
                         $indexUpdate = false;
                         $indexKey = (bool) $hasIndex;
                         $indexUnique = (bool) $hasUnique;
                         if ($currentColIndexData['unique'] != $fieldConf['unique']) {
                             $changedUnique = true;
                             $columnStatusCheck = false;
                             $tableStatusCheckCount++;
                             $indexUpdate = true;
                             $indexUnique = (bool) $fieldConf['unique'];
                         }
                         // check if column index changed ------------------------------------------------------
                         if ($currentColIndex != $fieldConf['index']) {
                             $changedIndex = true;
                             $columnStatusCheck = false;
                             $tableStatusCheckCount++;
                             $indexUpdate = true;
                             $indexKey = (bool) $fieldConf['index'];
                         }
                         // build table with changed columns ---------------------------------------------------
                         if (!$columnStatusCheck || !$foreignKeyStatusCheck) {
                             if (!$columnStatusCheck) {
                                 // IMPORTANT: setType is always required! Even if type has not changed
                                 $col->type($fieldConf['type']);
                                 // update/change/delete index/unique keys
                                 if ($indexUpdate) {
                                     if ($hasIndex) {
                                         $tableModifier->dropIndex($columnName);
                                     }
                                     if ($indexKey) {
                                         $tableModifier->addIndex($columnName, $indexUnique);
                                     }
                                 }
                                 $tableModifier->updateColumn($columnName, $col);
                             }
                             $buildStatus = $tableModifier->build($exec);
                             if (is_array($buildStatus) || is_string($buildStatus)) {
                                 // query strings for change available
                                 $dbColumnQueries = array_merge($dbColumnQueries, (array) $buildStatus);
                             }
                         }
                         // set (new) column information -------------------------------------------------------
                         $requiredTables[$requiredTableName]['fieldConf'][$columnName]['changedType'] = $changedType;
                         $requiredTables[$requiredTableName]['fieldConf'][$columnName]['changedUnique'] = $changedUnique;
                         $requiredTables[$requiredTableName]['fieldConf'][$columnName]['changedIndex'] = $changedIndex;
                     } elseif (!isset($fieldConf['has-manny']) && isset($fieldConf['type'])) {
                         // column not exists but it is required!
                         // columns that do not match this criteria ("mas-manny") are "virtual" fields
                         // and can be ignored
                         $requiredTables[$requiredTableName]['fieldConf'][$columnName]['currentType'] = '';
                         $columnStatusCheck = false;
                         $tableStatusCheckCount++;
                     }
                     $requiredTables[$requiredTableName]['fieldConf'][$columnName]['statusCheck'] = $columnStatusCheck;
                 }
                 $dbStatusCheckCount += $tableStatusCheckCount;
                 $requiredTables[$requiredTableName]['empty'] = $tableEmpty;
                 $requiredTables[$requiredTableName]['exists'] = $tableExists;
                 $requiredTables[$requiredTableName]['statusCheckCount'] = $tableStatusCheckCount;
             }
         } else {
             // DB connection failed
             $dbStatusCheckCount++;
         }
         if ($exec) {
             $f3->reroute('@setup');
         }
         $this->databases[$dbKey]['info'] = ['db' => $db, 'label' => $dbLabel, 'driver' => $dbDriver, 'name' => $dbName, 'user' => $dbUser, 'dbConfig' => $dbConfig, 'setupEnable' => $dbSetupEnable, 'connected' => $dbConnected, 'statusCheckCount' => $dbStatusCheckCount, 'columnQueries' => $dbColumnQueries, 'tableData' => $requiredTables];
     }
     return $this->databases;
 }
Example #2
0
 /**
  * erase all model data, handle with care
  * @param null $db
  * @param null $table
  */
 public static function setdown($db = null, $table = null)
 {
     $self = get_called_class();
     if (is_null($db) || is_null($table)) {
         $df = $self::resolveConfiguration();
     }
     if (!is_object($db = is_string($db = $db ?: $df['db']) ? \Base::instance()->get($db) : $db)) {
         trigger_error(self::E_CONNECTION);
     }
     if (strlen($table = strtolower($table ?: $df['table'])) == 0) {
         trigger_error(self::E_NO_TABLE);
     }
     if (isset($df) && !empty($df['fieldConf'])) {
         $fields = $df['fieldConf'];
     } else {
         $fields = array();
     }
     $deletable = array();
     $deletable[] = $table;
     foreach ($fields as $key => $field) {
         $field = static::resolveRelationConf($field);
         if (array_key_exists('has-many', $field)) {
             if (!is_array($relConf = $field['has-many'])) {
                 continue;
             }
             $rel = $relConf[0]::resolveConfiguration();
             // check if foreign conf matches m:m
             if (array_key_exists($relConf[1], $rel['fieldConf']) && !is_null($relConf[1]) && key($rel['fieldConf'][$relConf[1]]) == 'has-many') {
                 // compute mm table name
                 $deletable[] = isset($relConf[2]) ? $relConf[2] : static::getMMTableName($rel['table'], $relConf[1], $table, $key, $rel['fieldConf'][$relConf[1]]['has-many']);
             }
         }
     }
     if ($db instanceof Jig) {
         /** @var Jig $db */
         $dir = $db->dir();
         foreach ($deletable as $item) {
             if (file_exists($dir . $item)) {
                 unlink($dir . $item);
             }
         }
     } elseif ($db instanceof SQL) {
         /** @var SQL $db */
         $schema = new Schema($db);
         $tables = $schema->getTables();
         foreach ($deletable as $item) {
             if (in_array($item, $tables)) {
                 $schema->dropTable($item);
             }
         }
     } elseif ($db instanceof Mongo) {
         /** @var Mongo $db */
         foreach ($deletable as $item) {
             $db->selectCollection($item)->drop();
         }
     }
 }
Example #3
0
 /**
  * get all table names from a DB
  * @param string $database
  * @return array|bool
  */
 public function getTables($database = 'PF')
 {
     $schema = new SQL\Schema($this->getDB($database));
     return $schema->getTables();
 }