示例#1
0
 /**
  * Take the module creator form input and apply changes
  *
  * @param array $input
  * @param array $changeGroups
  *
  * @todo Break this up into smaller parts
  */
 public function applyModuleChanges(array $input = array(), array $changeGroups = array())
 {
     // Initialize needed variables
     $tableName = $input['table_name'];
     // Module table name
     $moduleId = $input['id'];
     // Module ID
     $moduleChangeset = ArrayLib::getKey(array_shift($changeGroups), 0);
     // Get the module changeset
     // Initialize the generator map array
     $generatorMap = array('created_fields' => array(), 'deleted_fields' => array(), 'updated_fields' => array());
     // Define artisan generator methods to be used with generator map keys
     $generatorMethods = array('created_fields' => 'add', 'deleted_fields' => 'remove');
     // If there's no module id, spawn a migration for creation of a new module
     if (!$moduleId) {
         MigrationGenerator::create($tableName);
         sleep(1);
         // Pause a second so succeeding migrations are named (ordered) properly
     }
     // Gather fields
     foreach ($changeGroups as $groupType => $changesets) {
         // Skip if we're dealing with updates
         if ($groupType === 'updated_fields') {
             continue;
         }
         foreach ($changesets as $changeset) {
             // Skip if changeset is empty
             if (!is_array($changeset['changes']) || empty($changeset['changes'])) {
                 continue;
             }
             // Retrieve the column type of a current changeset
             $columnType = ArrayLib::getKey(ArrayLib::findByKeyValue($changeset['changes'], 'name', 'column_type') ?: array(), 'new');
             // Retrieve the column name of a current changeset
             $columnName = ArrayLib::getKey(ArrayLib::findByKeyValue($changeset['changes'], 'name', 'column_name') ?: array(), 'new');
             $generatorMap[$groupType][$columnName] = $columnType;
         }
     }
     // Generate migrations for new fields
     foreach ($generatorMap as $key => $fields) {
         // Check if a migration should be generated
         if (array_key_exists($key, $generatorMethods) && !empty($fields)) {
             // Bam!
             MigrationGenerator::$generatorMethods[$key]($tableName, array_filter($fields, function ($value) {
                 return !empty($value);
             }));
         }
     }
     // Update model
     if (!empty($moduleChangeset['changes'])) {
         // Map of field => value entries
         $changemap = [];
         // Fill the changemap
         foreach ($moduleChangeset['changes'] as $change) {
             $changemap[$change['name']] = $change['new'];
         }
         // If module already exists, update it with new entries
         if ($moduleChangeset['item_id']) {
             \DB::table(\Orangehill\Photon\Module::getTableName())->where('table_name', $tableName)->update($changemap);
         } else {
             // Module doesn't exist yet, it should be created
             // Create a new module based on an form input entry
             $newModule = new Module($changemap);
             // Generate a model file
             $modelName = ucfirst(camel_case(str_singular($tableName)));
             \Artisan::call('generate:model', array('modelName' => $modelName));
             // Store the path to the model file
             $pathToModel = app_path('models') . '/' . $modelName . '.php';
             // Open the newly created file and make the model extend Baum's Node instead of Eloquent
             $fileContent = file_get_contents($pathToModel);
             $replaced = str_replace('extends \\Eloquent', 'extends Baum\\Node', $fileContent);
             // Try to find a name of first added column, fallback to the id
             $toStringField = 'id';
             if (is_array($changeGroups['created_fields'])) {
                 $head = head($changeGroups['created_fields']);
                 if (is_array($head['changes'])) {
                     foreach ($head['changes'] as $fieldSegment) {
                         if ($fieldSegment['name'] == 'column_name') {
                             $toStringField = $fieldSegment['new'];
                         }
                     }
                 }
             }
             // Create a __toString method stub
             $toStringStub = StubFactory::make('ModelToStringMethod', array('field' => $toStringField))->append("\n}")->get();
             // Add the method to the model files
             $replaced = substr_replace($replaced, $toStringStub, strrpos($replaced, '}'));
             file_put_contents($pathToModel, $replaced);
             // Save a model and update the module id
             $newModule->save();
             $moduleId = $newModule->id;
         }
     }
     // Add newborn fields
     foreach ($changeGroups['created_fields'] as $field) {
         $fieldData = array('module_id' => $moduleId);
         foreach ($field['changes'] as $element) {
             $fieldData[$element['name']] = $element['new'];
         }
         $field = FieldCreator::make($fieldData);
         $field->save();
     }
     // Update fields
     foreach ($changeGroups['updated_fields'] as $field) {
         $fieldData = array();
         foreach ($field['changes'] as $element) {
             $fieldData[$element['name']] = $element['new'];
         }
         \DB::table(Field::getTableName())->where('id', $field['item_id'])->update($fieldData);
     }
     // Delete fields
     $deletedFieldIds = array_fetch($changeGroups['deleted_fields'], 'item_id') + array(0);
     $moduleFields = Field::whereIn('id', $deletedFieldIds)->get();
     foreach ($moduleFields as $moduleField) {
         FieldFactory::make($moduleField)->uninstall();
     }
     foreach ($changeGroups['deleted_fields'] as $field) {
         \DB::table(Field::getTableName())->where('id', $field['item_id'])->delete();
     }
 }
 /**
  * @expectedException Orangehill\Photon\MigrationException
  */
 public function testArgumentPreparationWithInvalidCommandName()
 {
     MigrationGenerator::prepareArguments('create', array());
 }
示例#3
0
 /**
  * Saves submitted and validated data
  *
  * @param  $verbose boolean $verbose If set to true function will only specify pending changes without making any
  *
  * @return array
  */
 protected function save($fieldIds, $verbose = false)
 {
     $report = '';
     // Instantiate Migration Generator Class (Laravel 4 Generator Module Wrapper)
     $generator = new MigrationGenerator();
     // Check if module_name is new or existing one
     if (is_numeric(\Input::get('module_id'))) {
         // Get module data
         $module = Module::find(\Input::get('module_id'));
         // Handle Folder module type
         if (\Input::get('is_folder') == '1') {
             return $this->updateFolderModuleType($module, $verbose);
         }
         // Get id's of fields that are stored in the database
         $existingFieldIds = array_fetch($module->fields()->get()->toArray(), 'id');
         // Check if remove module request is received
         if (\Input::get('remove_request') == 1) {
             $report .= $this->reportSectionTitleGenerator('remove', 'module', \Input::get('name'));
             // If in verbose mode return report array
             if ($verbose) {
                 return array('report' => $report);
             }
             // Populate migrationFieldsDropped array (needed for php artisan migrate:rollback)
             $migrationFieldsDropped = array();
             $existingFieldIds = $module->fields()->get();
             foreach ($existingFieldIds as $field) {
                 $migrationFieldsDropped[$field->column_name] = $field->column_type;
             }
             // Generate migration file
             $generator->destroy($module->table_name, $migrationFieldsDropped);
             // Run the migrations
             if (\Input::get('run-migrations') == 1) {
                 \Artisan::call('migrate');
             }
             // Remove the module (also removes orphans from fields table)
             $module->delete();
             // Notify about successful data removal
             \Session::flash('success', 'Data has been removed.');
             // Redirect to settings page
             return \Redirect::to('/admin/settings/');
         }
         // Create an array of deleted fields, if any
         $deletedFieldIds = array_diff($existingFieldIds, $fieldIds);
         // Create an array of new fields, if any
         $newFieldIds = array_diff($fieldIds, $existingFieldIds);
         // Create an array of edited fields
         $editedFieldIds = array_diff($fieldIds, $deletedFieldIds, $newFieldIds);
         if (!$module->get()->isEmpty()) {
             $moduleHasChanged = false;
             // Updating existing module
             $report .= $this->reportSectionTitleGenerator('change', 'module', \Input::get('name'));
             if ($module->name != \Input::get('module_name')) {
                 $report .= $this->reportGenerator('set', 'name', \Input::get('name'), $module->name);
                 $module->name = \Input::get('name');
                 $moduleHasChanged = true;
             }
             if ($module->parent_module != \Input::get('parent_module')) {
                 $report .= $this->reportGenerator('set', 'parent module', \Input::get('parent_module'), $module->parent_module);
                 $module->parent_module = \Input::get('parent_module');
                 $moduleHasChanged = true;
             }
             if ($module->nestable != \Input::get('nestable')) {
                 $report .= $this->reportGenerator('set', 'nestable', \Input::get('nestable'), $module->nestable);
                 $module->nestable = \Input::get('nestable');
                 $moduleHasChanged = true;
             }
             $report .= $moduleHasChanged ? '' : '<br/>';
             // Save changes to module table
             if (!$verbose) {
                 $module->save();
             }
             // Process new fields for an existing module
             if (count($newFieldIds) > 0) {
                 $migrationFields = array();
                 foreach ($newFieldIds as $newFieldId) {
                     // Generate a report line
                     $report .= $this->insertFieldReport($newFieldId);
                     // Insert a new record in fields table
                     if (!$verbose) {
                         $tmp = array();
                         $tmp['module_id'] = \Input::get('module_id');
                         $tmp['field_name'] = \Input::get('field_name' . $newFieldId);
                         $tmp['field_type'] = \Input::get('field_type' . $newFieldId);
                         $tmp['relation_table'] = \Input::get('relation_table' . $newFieldId);
                         $tmp['column_name'] = \Input::get('column_name' . $newFieldId);
                         $tmp['column_type'] = \Input::get('column_type' . $newFieldId);
                         $tmp['tooltip_text'] = \Input::get('tooltip_text' . $newFieldId);
                         $newField = Field::create($tmp);
                         // Populate migrationFields array
                         $migrationFields[\Input::get('column_name' . $newFieldId)] = \Input::get('column_type' . $newFieldId);
                     }
                     $moduleHasChanged = true;
                 }
                 // Generate migration files
                 if (!$verbose) {
                     $generator->add($module->table_name, $migrationFields);
                 }
             }
             // Process edited fields for an existing module
             if (count($editedFieldIds) > 0) {
                 $migrationFields = array();
                 $migrationFieldsDropped = array();
                 foreach ($editedFieldIds as $fieldId) {
                     $fieldHasChanged = false;
                     $fieldReport = '';
                     $field = $module->fields()->find($fieldId);
                     // Populate migrationFields and migrationFieldsDropped arrays
                     if ($field->column_name != \Input::get('column_name' . $fieldId) or $field->column_type != \Input::get('column_type' . $fieldId)) {
                         $migrationFields[\Input::get('column_name' . $fieldId)] = \Input::get('column_type' . $fieldId);
                         $migrationFieldsDropped[$field->column_name] = $field->column_type;
                     }
                     if ($field->field_name != \Input::get('field_name' . $fieldId)) {
                         $fieldReport .= $this->reportGenerator('set', 'field name', \Input::get('field_name' . $fieldId), $field->field_name);
                         $field->field_name = \Input::get('field_name' . $fieldId);
                         $fieldHasChanged = true;
                     }
                     if ($field->field_type != \Input::get('field_type' . $fieldId)) {
                         $fieldReport .= $this->reportGenerator('set', 'field type', \Input::get('field_type' . $fieldId), $field->field_type);
                         $field->field_type = \Input::get('field_type' . $fieldId);
                         $fieldHasChanged = true;
                     }
                     if ($field->relation_table != \Input::get('relation_table' . $fieldId)) {
                         $fieldReport .= $this->reportGenerator('set', 'relation table', \Input::get('relation_table' . $fieldId), $field->relation_table);
                         $field->relation_table = \Input::get('relation_table' . $fieldId);
                         $fieldHasChanged = true;
                     }
                     if ($field->column_name != \Input::get('column_name' . $fieldId)) {
                         $fieldReport .= $this->reportGenerator('set', 'column name', \Input::get('column_name' . $fieldId), $field->column_name);
                         $field->column_name = \Input::get('column_name' . $fieldId);
                         $fieldHasChanged = true;
                     }
                     if ($field->column_type != \Input::get('column_type' . $fieldId)) {
                         $fieldReport .= $this->reportGenerator('set', 'column type', \Input::get('column_type' . $fieldId), $field->column_type);
                         $field->column_type = \Input::get('column_type' . $fieldId);
                         $fieldHasChanged = true;
                     }
                     if ($field->tooltip_text != \Input::get('tooltip_text' . $fieldId)) {
                         $fieldReport .= $this->reportGenerator('set', 'tooltip text', \Input::get('tooltip_text' . $fieldId), $field->tooltip_text);
                         $field->tooltip_text = \Input::get('tooltip_text' . $fieldId);
                         $fieldHasChanged = true;
                     }
                     if ($fieldHasChanged) {
                         $fieldReport = $this->reportSectionTitleGenerator('change', 'field', $field->field_name) . $fieldReport;
                         $fieldReport .= '<br/>';
                         $report .= $fieldReport;
                         $moduleHasChanged = true;
                     }
                     if (!$verbose and $fieldHasChanged) {
                         $field->save();
                     }
                 }
                 // Generate migration files
                 if (!$verbose and $fieldHasChanged) {
                     // First drop fields with old column_type
                     $generator->remove($module->table_name, $migrationFieldsDropped);
                     // Wait 1 second so that remove migration is executed before add (filenaming issue)
                     sleep(1);
                     // Than add fields with changed column_type
                     $generator->add($module->table_name, $migrationFields);
                 }
             }
             // Process deleted fields
             if (count($deletedFieldIds) > 0) {
                 $migrationFieldsDropped = array();
                 foreach ($deletedFieldIds as $deletedFieldId) {
                     $field = $module->fields()->find($deletedFieldId);
                     $report .= $this->reportSectionTitleGenerator('remove', 'field', $field->field_name);
                     // Populate migrationFieldsDropped array
                     $migrationFieldsDropped[$field->column_name] = $field->column_type;
                     if (!$verbose) {
                         $field->delete();
                     }
                     $moduleHasChanged = true;
                 }
                 // Generate migration files
                 if (!$verbose) {
                     $generator->remove($module->table_name, $migrationFieldsDropped);
                 }
             }
             // This will yield 'no changes detected' message
             if (!$moduleHasChanged) {
                 return false;
             }
             // If in verbose mode return report array
             if ($verbose) {
                 return array('report' => $report);
             }
             // Run the migrations
             if (\Input::get('run-migrations') == 1) {
                 \Artisan::call('migrate');
             }
             // Notify about successful data entry
             \Session::flash('success', 'Data has been saved.');
             // Redirect to module settings page
             return \Redirect::to('/admin/settings/' . \Input::get('module_id'));
         }
     }
     // Inserting a new model
     $report .= $this->reportSectionTitleGenerator('create', 'module');
     $report .= $this->reportGenerator('set', 'module name', \Input::get('name'));
     $report .= $this->reportGenerator('set', 'table name', \Input::get('table_name'));
     $report .= $this->reportGenerator('set', 'parent module', \Input::get('parent_module'));
     $report .= $this->reportGenerator('set', 'nestable', \Input::get('nestable'));
     $report .= '<br/>';
     // Insert a new record in modules table, and get it's ID
     if (!$verbose) {
         $newModule = Module::create(\Input::all());
     }
     $migrationFields = array();
     // Inserting new fields
     foreach ($fieldIds as $fieldId) {
         // Generate a report line
         $report .= $this->insertFieldReport($fieldId);
         // Insert a new record in fields table
         if (!$verbose) {
             $tmp = array();
             $tmp['module_id'] = $newModule->id;
             $tmp['field_name'] = \Input::get('field_name' . $fieldId);
             $tmp['field_type'] = \Input::get('field_type' . $fieldId);
             $tmp['relation_table'] = \Input::get('relation_table' . $fieldId);
             $tmp['column_name'] = \Input::get('column_name' . $fieldId);
             $tmp['column_type'] = \Input::get('column_type' . $fieldId);
             $tmp['tooltip_text'] = \Input::get('tooltip_text' . $fieldId);
             $newField = Field::create($tmp);
             // Populate migrationFields array
             $migrationFields[\Input::get('column_name' . $fieldId)] = \Input::get('column_type' . $fieldId);
         }
     }
     // If in verbose mode return report array
     if ($verbose) {
         return array('report' => $report);
     }
     // Generate migration files (Only if module type is not folder)
     if (\Input::get('is_folder') !== '1') {
         $generator->create(\Input::get('table_name'), $migrationFields);
     }
     // Run the migrations (Only if module type is not folder)
     if (\Input::get('run-migrations') == 1 && \Input::get('is_folder') !== '1') {
         \Artisan::call('migrate');
     }
     // Notify about successful data entry
     \Session::flash('success', 'Data has been saved.');
     // Redirect to new module settings page
     return \Redirect::to('/admin/settings/' . $newModule->id);
 }