Exemplo n.º 1
0
 /**
  * setup / update table schema
  * @static
  * @param $db
  * @param $table
  * @param $fields
  * @return bool
  */
 public static function setup($db = null, $table = null, $fields = null)
 {
     /** @var Cortex $self */
     $self = get_called_class();
     if (is_null($db) || is_null($table) || is_null($fields)) {
         $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 = $table ?: $df['table']) == 0) {
         trigger_error(self::E_NO_TABLE);
     }
     if (is_null($fields)) {
         if (!empty($df['fieldConf'])) {
             $fields = $df['fieldConf'];
         } elseif (!$df['fluid']) {
             trigger_error(self::E_FIELD_SETUP);
             return false;
         } else {
             $fields = array();
         }
     }
     if ($db instanceof SQL) {
         $schema = new Schema($db);
         // prepare field configuration
         if (!empty($fields)) {
             foreach ($fields as $key => &$field) {
                 // fetch relation field types
                 $field = static::resolveRelationConf($field);
                 // check m:m relation
                 if (array_key_exists('has-many', $field)) {
                     // m:m relation conf [class,to-key,from-key]
                     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($rel['fieldConf'][$relConf[1]]) && $relConf['hasRel'] == 'has-many') {
                         // compute mm table name
                         $fConf = $rel['fieldConf'][$relConf[1]]['has-many'];
                         $mmTable = static::getMMTableName($rel['table'], $relConf[1], $table, $key, $fConf);
                         // create dummy to invoke table
                         $mmRel = new Cortex($db, $mmTable, true);
                         $rand = rand(0, 1000000);
                         $mmRel->{$relConf[1]} = $rand;
                         $mmRel->{$key} = $rand;
                         $mmRel->save();
                         $mmRel->reset();
                         $mmRel->erase(array($relConf[1] . ' = :rand AND ' . $key . ' = :rand', ':rand' => $rand));
                     }
                 }
                 // skip virtual fields with no type
                 if (!array_key_exists('type', $field)) {
                     unset($fields[$key]);
                     continue;
                 }
                 // transform array fields
                 if (in_array($field['type'], array(self::DT_JSON, self::DT_SERIALIZED))) {
                     $field['type'] = $schema::DT_TEXT;
                 }
                 // defaults values
                 if (!array_key_exists('nullable', $field)) {
                     $field['nullable'] = true;
                 }
             }
         }
         if (!in_array($table, $schema->getTables())) {
             // create table
             $table = $schema->createTable($table);
             foreach ($fields as $field_key => $field_conf) {
                 $table->addColumn($field_key, $field_conf);
             }
             $table->build();
         } else {
             // add missing fields
             $table = $schema->alterTable($table);
             $existingCols = $table->getCols();
             foreach ($fields as $field_key => $field_conf) {
                 if (!in_array($field_key, $existingCols)) {
                     $table->addColumn($field_key, $field_conf);
                 }
             }
             // remove unused fields
             // foreach ($existingCols as $col)
             //     if (!in_array($col, array_keys($fields)) && $col!='id')
             //     $table->dropColumn($col);
             $table->build();
         }
     }
     return true;
 }