Example #1
0
 /**
  * migrate
  *
  * @param Hook\Model\Collection $model
  * @param array $collection_config
  *
  * @return bool
  */
 public function migrate($model, $collection_config, $is_dynamic = false)
 {
     $that = $this;
     $result = false;
     $connection = $model->getConnectionResolver()->connection();
     // Ignore NoSQL databases.
     if (!$connection->getPdo()) {
         return;
     }
     // Get modified Schema\Grammar for hook features.
     $connection->setSchemaGrammar($this->getSchemaGrammar($connection));
     // Set custom blueprint resolver
     $builder = $connection->getSchemaBuilder();
     $builder->blueprintResolver(function ($table, $callback) {
         return new \Hook\Database\Schema\Blueprint($table, $callback);
     });
     $table = $model->getTable();
     $table_schema = Cache::get($table);
     $table_prefix = Context::getPrefix();
     $collection_config = $this->sanitizeConfigs($table, $collection_config, $is_dynamic);
     $is_creating = !$builder->hasTable($table);
     if (!empty($collection_config['attributes']) || !empty($collection_config['relationships'])) {
         $migrate = function ($t) use($that, &$table, &$table_prefix, &$builder, &$is_creating, &$table_schema, $collection_config, &$result) {
             $table_columns = array('created_at', 'updated_at', 'deleted_at');
             if ($is_creating) {
                 $that->createCollection($t);
             } else {
                 $table_columns = array_merge($table_columns, $builder->getColumnListing($table));
             }
             foreach ($collection_config['attributes'] as $attribute) {
                 if (!isset($attribute['name'])) {
                     throw new MethodFailureException('invalid_schema');
                 }
                 $field_name = strtolower(array_remove($attribute, 'name'));
                 $type = camel_case(array_remove($attribute, 'type') ?: 'string');
                 $default = array_remove($attribute, 'default');
                 $index = array_remove($attribute, 'index');
                 $unique = array_remove($attribute, 'unique') || $index == 'unique';
                 $required = array_remove($attribute, 'required');
                 // Skip if column already exists
                 // TODO: deprecate strtolower
                 if (in_array($field_name, array_map('strtolower', $table_columns))) {
                     continue;
                 }
                 // include field_name to list of collection columns
                 array_push($table_columns, $field_name);
                 if (count($attribute) > 0) {
                     // the remaining attributes on field definition are
                     // the data-type related collection_config, such as 'length',
                     // 'allowed', 'total', 'places', etc.
                     $column = $t->newColumn($type, $field_name, $attribute);
                 } else {
                     $column = $t->{$type}($field_name);
                 }
                 // apply default value
                 if ($default !== NULL) {
                     $required = true;
                     $column->default($default);
                 }
                 // spatial indexes are NOT NULL by default
                 $nullable = !$required && $type !== 'point';
                 // columns are nullable unless specified as 'required'
                 if ($nullable) {
                     $column->nullable();
                 }
                 if ($index == 'spatial') {
                     // apply geospatial index, only MyISAM
                     $t->spatialIndex($field_name);
                 } else {
                     if ($index && !$unique) {
                         // apply index if specified
                         $column->index();
                     }
                 }
                 if ($unique) {
                     // apply unique index if specified
                     $unique_fields = !is_array($unique) ? $field_name : array_unique(array_merge(array($field_name), $unique));
                     $t->unique($unique_fields);
                 }
             }
             // onDelete / onUpdate actions
             $actions = array('restrict' => "RESTRICT", 'cascade' => "CASCADE", 'none' => "NO ACTION", 'null' => "SET NULL", 'default' => "SET DEFAULT");
             if (!isset($collection_config['relationships'])) {
                 $collection_config['relationships'] = array();
             }
             foreach ($collection_config['relationships'] as $relation => $fields) {
                 // only create field on belongs_to relationships
                 if ($relation == "belongs_to") {
                     foreach ($fields as $field => $config) {
                         // create 'foreign_key' column on collection.
                         if (!in_array($config['foreign_key'], array_map('strtolower', $table_columns))) {
                             $column = $t->unsignedInteger($config['foreign_key']);
                             $column->nullable();
                         }
                         // create collection if it doesn't exists
                         if (!$builder->hasTable($config['collection'])) {
                             $builder->create($table_prefix . $config['collection'], function ($t) use($that) {
                                 $that->createCollection($t);
                             });
                         }
                         // //
                         // // create foreign key on database
                         // //
                         // // TODO: list foreign keys already defined before
                         // // trying to create it.
                         // //
                         // $t->foreign($config['foreign_key'])
                         //     ->references($config['primary_key'])
                         //     ->on($table_prefix . $config['collection'])
                         //     ->onDelete($actions[$config['on_delete']])
                         //     ->onUpdate($actions[$config['on_update']]);
                     }
                 }
             }
             // return true when any modification is present
             if (count($t->getColumns()) > 0 || count($t->getCommands()) > 0) {
                 $result = true;
             }
         };
         if ($is_creating) {
             // CREATE TABLE statement
             $builder->create($table_prefix . $table, $migrate);
         } else {
             // ALTER TABLE statement.
             $builder->table($table_prefix . $table, $migrate);
         }
     }
     // merge previous schema with new one.
     $table_schema = $this->mergeSchema($table_schema, $collection_config, $is_dynamic);
     // Cache table schema for further reference
     Cache::forever($table, $table_schema);
     $app_collections = Cache::get('app_collections');
     Cache::forever('app_collections', array_unique(array_merge($app_collections, array($table))));
     return $result;
 }