silverstripe-userforms/code/Task/UserFormsUpgradeService.php

292 lines
9.0 KiB
PHP

<?php
/**
* Service to support upgrade of userforms module
*/
class UserFormsUpgradeService
{
/**
* @var bool
*/
protected $quiet;
public function run()
{
$this->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}<br />";
}
}
/**
* 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)
);
}
}