Skip to content

Commit

Permalink
Add Formie 3 migration prep for field layout changes
Browse files Browse the repository at this point in the history
  • Loading branch information
engram-design committed Dec 31, 2023
1 parent 7584999 commit 9925889
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/Formie.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class Formie extends Plugin

public bool $hasCpSection = true;
public bool $hasCpSettings = true;
public string $schemaVersion = '2.0.12';
public string $schemaVersion = '2.0.13';
public string $minVersionRequired = '1.5.15';


Expand Down
84 changes: 84 additions & 0 deletions src/helpers/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@
namespace verbb\formie\helpers;

use verbb\formie\Formie;
use verbb\formie\base\NestedFieldInterface;
use verbb\formie\elements\Form;
use verbb\formie\web\assets\forms\FormsAsset;

use Craft;
use craft\db\Query;
use craft\helpers\Db;
use craft\helpers\Json;

class Plugin
{
// Static Methods
Expand Down Expand Up @@ -34,4 +41,81 @@ public static function registerAsset(string $path): void
}
}

public static function saveFormie3Layout(Form $form): void
{
$fieldLayout = $form->getFormFieldLayout();

if (!$fieldLayout) {
return;
}

$newLayoutConfig = [];
$nestedFields = [];

foreach ($fieldLayout->getPages() as $pageKey => $page) {
$newLayoutConfig['pages'][$pageKey]['label'] = $page->name;
$newLayoutConfig['pages'][$pageKey]['settings'] = $page->settings->toArray();

foreach ($page->getRows() as $rowKey => $row) {
foreach ($row['fields'] as $fieldKey => $field) {
$newLayoutConfig['pages'][$pageKey]['rows'][$rowKey]['fields'][] = [
'fieldUid' => $field->uid,
'required' => $field->required,
];

if ($field instanceof NestedFieldInterface) {
$nestedFields[] = $field;
}
}
}
}

$existingLayout = (new Query())->from('{{%formie_newlayout}}')->where(['formId' => $form->id])->one();

if ($existingLayout) {
Db::update('{{%formie_newlayout}}', [
'formId' => $form->id,
'layoutConfig' => Json::encode($newLayoutConfig),
], ['id' => $existingLayout['id']]);
} else {
Db::insert('{{%formie_newlayout}}', [
'formId' => $form->id,
'layoutConfig' => Json::encode($newLayoutConfig),
]);
}

// Do a similar thing for Group/Repeater fields, which have field layouts, but won't in Formie 3.
foreach ($nestedFields as $nestedField) {
$newNestedConfig = [];

if ($fieldLayout = $nestedField->getFieldLayout()) {
foreach ($fieldLayout->getPages() as $pageKey => $page) {
foreach ($page->getRows() as $rowKey => $row) {
foreach ($row['fields'] as $fieldKey => $field) {
$newNestedConfig['rowsConfig'][$rowKey]['fields'][] = [
'fieldUid' => $field->uid,
'required' => $field->required,
];
}
}
}
}

if ($newNestedConfig) {
$existingLayout = (new Query())->from('{{%formie_newnestedlayout}}')->where(['fieldId' => $nestedField->id])->one();

if ($existingLayout) {
Db::update('{{%formie_newnestedlayout}}', [
'fieldId' => $nestedField->id,
'layoutConfig' => Json::encode($newNestedConfig),
], ['id' => $existingLayout['id']]);
} else {
Db::insert('{{%formie_newnestedlayout}}', [
'fieldId' => $nestedField->id,
'layoutConfig' => Json::encode($newNestedConfig),
]);
}
}
}
}
}
20 changes: 20 additions & 0 deletions src/migrations/Install.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,26 @@ public function createTables(): void
'uid' => $this->uid(),
]);

$this->archiveTableIfExists('{{%formie_newlayout}}');
$this->createTable('{{%formie_newlayout}}', [
'id' => $this->primaryKey(),
'formId' => $this->integer()->notNull(),
'layoutConfig' => $this->text(),
'dateCreated' => $this->dateTime()->notNull(),
'dateUpdated' => $this->dateTime()->notNull(),
'uid' => $this->uid(),
]);

$this->archiveTableIfExists('{{%formie_newnestedlayout}}');
$this->createTable('{{%formie_newnestedlayout}}', [
'id' => $this->primaryKey(),
'fieldId' => $this->integer()->notNull(),
'layoutConfig' => $this->text(),
'dateCreated' => $this->dateTime()->notNull(),
'dateUpdated' => $this->dateTime()->notNull(),
'uid' => $this->uid(),
]);

$this->archiveTableIfExists('{{%formie_notifications}}');
$this->createTable('{{%formie_notifications}}', [
'id' => $this->primaryKey(),
Expand Down
49 changes: 49 additions & 0 deletions src/migrations/m231231_000000_formie3_prep.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
namespace verbb\formie\migrations;

use verbb\formie\elements\Form;
use verbb\formie\helpers\Plugin;

use craft\db\Migration;
use craft\db\Query;
use craft\helpers\StringHelper;

class m231231_000000_formie3_prep extends Migration
{
public function safeUp(): bool
{
if (!$this->db->tableExists('{{%formie_newlayout}}')) {
$this->createTable('{{%formie_newlayout}}', [
'id' => $this->primaryKey(),
'formId' => $this->integer()->notNull(),
'layoutConfig' => $this->text(),
'dateCreated' => $this->dateTime()->notNull(),
'dateUpdated' => $this->dateTime()->notNull(),
'uid' => $this->uid(),
]);
}

if (!$this->db->tableExists('{{%formie_newnestedlayout}}')) {
$this->createTable('{{%formie_newnestedlayout}}', [
'id' => $this->primaryKey(),
'fieldId' => $this->integer()->notNull(),
'layoutConfig' => $this->text(),
'dateCreated' => $this->dateTime()->notNull(),
'dateUpdated' => $this->dateTime()->notNull(),
'uid' => $this->uid(),
]);
}

foreach (Form::find()->status(null)->all() as $form) {
Plugin::saveFormie3Layout($form);
}

return true;
}

public function safeDown(): bool
{
echo "m231231_000000_formie3_prep cannot be reverted.\n";
return false;
}
}
5 changes: 5 additions & 0 deletions src/services/Forms.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use verbb\formie\base\FormField;
use verbb\formie\elements\Form;
use verbb\formie\helpers\HandleHelper;
use verbb\formie\helpers\Plugin;
use verbb\formie\migrations\CreateFormContentTable;
use verbb\formie\models\FieldLayout;
use verbb\formie\models\FieldLayoutPage;
Expand Down Expand Up @@ -273,6 +274,10 @@ public function saveForm(Form $form, bool $runValidation = true): bool
return false;
}

// To prepare for Formie 3, where field layouts have been revampled, it's important to maintain a copy
// for the upgrade, because Craft's migrations will blow the table away, and we need it before that.
Plugin::saveFormie3Layout($form);

return true;
}

Expand Down

0 comments on commit 9925889

Please sign in to comment.