log("Upgrading formfield rules and custom settings"); // List of rules that have been created in all stages $fields = Versioned::get_including_deleted('EditableFormField'); foreach ($fields as $field) { $this->upgradeField($field); } } /** * Migrate a versioned field in all stages * * @param EditableFormField $field */ protected function upgradeField(EditableFormField $field) { $this->log("Upgrading formfield ID = ".$field->ID); // Check versions this field exists on $filter = sprintf('"EditableFormField"."ID" = \'%d\' AND "Migrated" = 0', $field->ID); $stageField = Versioned::get_one_by_stage('EditableFormField', 'Stage', $filter); $liveField = Versioned::get_one_by_stage('EditableFormField', 'Live', $filter); if ($stageField) { $this->upgradeFieldInStage($stageField, 'Stage'); } if ($liveField) { $this->upgradeFieldInStage($liveField, 'Live'); } } /** * Migrate a versioned field in a single stage * * @param EditableFormField $field * @param stage $stage */ protected function upgradeFieldInStage(EditableFormField $field, $stage) { Versioned::reading_stage($stage); // Migrate field rules $this->migrateRules($field, $stage); // Migrate custom settings $this->migrateCustomSettings($field, $stage); // Flag as migrated $field->Migrated = true; $field->write(); } /** * Migrate custom rules for the given field * * @param EditableFormField $field * @param string $stage */ protected function migrateRules(EditableFormField $field, $stage) { $rulesData = $field->CustomRules ? unserialize($field->CustomRules) : array(); // Skip blank rules or fields with custom rules already if (empty($rulesData) || $field->DisplayRules()->count()) { return; } // Check value of this condition foreach ($rulesData as $ruleDataItem) { if (empty($ruleDataItem['ConditionOption']) || empty($ruleDataItem['Display'])) { continue; } // Get data for this rule $conditionOption = $ruleDataItem['ConditionOption']; $display = $ruleDataItem['Display']; $conditionFieldName = empty($ruleDataItem['ConditionField']) ? null : $ruleDataItem['ConditionField']; $value = isset($ruleDataItem['Value']) ? $ruleDataItem['Value'] : null; // Create rule $rule = $this->findOrCreateRule($field, $stage, $conditionOption, $display, $conditionFieldName, $value); $this->log("Upgrading rule ID = " . $rule->ID); } } /** * Migrate custom settings for the given field * * @param EditableFormField $field * @param string $stage */ protected function migrateCustomSettings(EditableFormField $field, $stage) { // Custom settings include: // - ExtraClass // - RightTitle // - ShowOnLoad (show or '' are treated as true) // // - CheckedDefault (new field on EditableCheckbox - should be read from old "default" value) // - Default (EditableCheckbox) // - DefaultToToday (EditableDateField) // - Folder (EditableFileField) // - Level (EditableFormHeading) // - HideFromReports (EditableFormHeading / EditableLiteralField) // - Content (EditableLiteralField) // - GroupID (EditableMemberListField) // - MinValue (EditableNumericField) // - MaxValue (EditableNumericField) // - MinLength (EditableTextField) // - MaxLength (EditableTextField) // - Rows (EditableTextField) // - Placeholder (EditableTextField / EditableEmailField / EditableNumericField) $customSettings = $field->CustomSettings ? unserialize($field->CustomSettings) : array(); // Skip blank rules or fields with custom rules already if (empty($customSettings)) { return; } $field->migrateSettings($customSettings); if ($field->config()->has_placeholder) { $this->migratePlaceholder($field, $field->ClassName); } $field->write(); } /** * Create or find an existing field with the matched specification * * @param EditableFormField $field * @param string $stage * @param string $conditionOption * @param string $display * @param string $conditionFieldName * @param string $value * @return EditableCustomRule */ protected function findOrCreateRule(EditableFormField $field, $stage, $conditionOption, $display, $conditionFieldName, $value) { // Get id of field $conditionField = $conditionFieldName ? EditableFormField::get()->filter('Name', $conditionFieldName)->first() : null; // If live, search stage record for matching one if ($stage === 'Live') { $list = Versioned::get_by_stage('EditableCustomRule', 'Stage') ->filter(array( 'ParentID' => $field->ID, 'ConditionFieldID' => $conditionField ? $conditionField->ID : 0, 'Display' => $display, 'ConditionOption' => $conditionOption )); if ($value) { $list = $list->filter('FieldValue', $value); } else { $list = $list->where('"FieldValue" IS NULL OR "FieldValue" = \'\''); } $rule = $list->first(); if ($rule) { $rule->write(); $rule->publish("Stage", "Live"); return $rule; } } // If none found, or in stage, create new record $rule = new EditableCustomRule(); $rule->ParentID = $field->ID; $rule->ConditionFieldID = $conditionField ? $conditionField->ID : 0; $rule->Display = $display; $rule->ConditionOption = $conditionOption; $rule->FieldValue = $value; $rule->write(); return $rule; } public function log($message) { if ($this->getQuiet()) { return; } if (Director::is_cli()) { echo "{$message}\n"; } else { echo "{$message}
"; } } /** * Set if this service should be quiet * * @param bool $quiet * @return $ths */ public function setQuiet($quiet) { $this->quiet = $quiet; return $this; } public function getQuiet() { return $this->quiet; } /** * Migrate Placeholder data from field specific table to the EditableFormField table * * @param EditableFormField $field * @param string $tableName */ private function migratePlaceholder($field, $tableName) { // Migrate Placeholder setting from $tableName table to EditableFormField table if ($field->Placeholder) { return; } // Check if draft table exists if (!DB::get_schema()->hasTable($tableName)) { // Check if _obsolete_ draft table exists $tableName = '_obsolete_' . $tableName; if (!DB::get_schema()->hasTable($tableName)) { return; } } // Check if old Placeholder column exists if (!DB::get_schema()->hasField($tableName, 'Placeholder')) { return; } // Fetch existing draft Placeholder value $query = "SELECT \"Placeholder\" FROM \"$tableName\" WHERE \"ID\" = '$field->ID'"; $draftPlaceholder = DB::query($query)->value(); if (!$draftPlaceholder) { return; } // Update draft Placeholder value DB::prepared_query( "UPDATE \"EditableFormField\" SET \"Placeholder\" = ? WHERE \"ID\" = ?", array($draftPlaceholder, $field->ID) ); $livePlaceholder = $draftPlaceholder; // Check if live table exists $tableName = $tableName . '_Live'; if (DB::get_schema()->hasTable($tableName)) { // Fetch existing live Placeholder value $query = "SELECT \"Placeholder\" FROM \"$tableName\" WHERE \"ID\" = '" . $field->ID . "'"; $livePlaceholder = DB::query($query)->value(); if (!$livePlaceholder) { $livePlaceholder = $draftPlaceholder; } } // Update live Placeholder value DB::prepared_query( "UPDATE \"EditableFormField_Live\" SET \"Placeholder\" = ? WHERE \"ID\" = ?", array($draftPlaceholder, $field->ID) ); } }