/** * 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(); } }