/** * 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'])) { unset($fields[$key]); 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 $mmTable = isset($relConf[2]) ? $relConf[2] : static::getMMTableName($rel['table'], $relConf[1], $table, $key, $rel['fieldConf'][$relConf[1]]['has-many']); if (!in_array($mmTable, $schema->getTables())) { $mmt = $schema->createTable($mmTable); $mmt->addColumn($relConf[1])->type($relConf['relFieldType']); $mmt->addColumn($key)->type($field['type']); $index = array($relConf[1], $key); sort($index); $mmt->addIndex($index); $mmt->build(); } } } // 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; } unset($field); } } 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); } if (isset($df) && $df['primary'] != 'id') { $table->addColumn($df['primary'])->type_int(); $table->primary($df['primary']); } $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; }