Skip to content

Commit 3afd33f

Browse files
authored
Merge pull request #16783 from craftcms/feature/maintain-field-settings
Maintain field settings when switching field types
2 parents b5bbf39 + c0d5074 commit 3afd33f

File tree

5 files changed

+38
-5
lines changed

5 files changed

+38
-5
lines changed

CHANGELOG-WIP.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### Administration
44
- Added the `--batch-size` option for `resave/*` commands. ([#16586](https://github.com/craftcms/cms/issues/16586))
55
- Dragging headings within the Customize Sources modal now also drags any subsequent sources. ([#16737](https://github.com/craftcms/cms/issues/16737))
6+
- When switching field types, any field settings which are defined by the same base class are now preserved. ([#16783](https://github.com/craftcms/cms/pull/16783))
67

78
### Extensibility
89
- Global nav items and breadcrumbs can now have `aria-label` attributes via an `ariaLabel` property.

src/controllers/FieldsController.php

+26
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@
1313
use craft\fields\MissingField;
1414
use craft\fields\PlainText;
1515
use craft\helpers\ArrayHelper;
16+
use craft\helpers\Component;
1617
use craft\helpers\UrlHelper;
1718
use craft\models\FieldGroup;
1819
use craft\models\FieldLayoutTab;
1920
use craft\web\assets\fieldsettings\FieldSettingsAsset;
2021
use craft\web\Controller;
22+
use ReflectionException;
23+
use ReflectionProperty;
2124
use yii\web\BadRequestHttpException;
2225
use yii\web\NotFoundHttpException;
2326
use yii\web\Response;
@@ -292,9 +295,32 @@ public function actionRenderSettings(): Response
292295
$this->requirePostRequest();
293296
$this->requireAcceptsJson();
294297

298+
/** @var class-string<FieldInterface> $type */
295299
$type = $this->request->getRequiredBodyParam('type');
296300
$field = Craft::$app->getFields()->createField($type);
297301

302+
/** @var class-string<FieldInterface>|null $oldType */
303+
$oldType = $this->request->getBodyParam('oldType');
304+
if ($oldType && Component::validateComponentClass($oldType, FieldInterface::class)) {
305+
$settingsStr = $this->request->getBodyParam('settings');
306+
parse_str($settingsStr, $postedOldSettings);
307+
$oldNamespace = $this->request->getBodyParam('oldNamespace');
308+
$settings = ArrayHelper::getValue($postedOldSettings, $oldNamespace, []);
309+
310+
// Remove any settings that aren't defined by the same class between both types
311+
$settings = array_filter($settings, function($attribute) use ($type, $oldType) {
312+
try {
313+
$r1 = new ReflectionProperty($type, $attribute);
314+
$r2 = new ReflectionProperty($oldType, $attribute);
315+
return $r1->getDeclaringClass()->name === $r2->getDeclaringClass()->name;
316+
} catch (ReflectionException) {
317+
return false;
318+
}
319+
}, ARRAY_FILTER_USE_KEY);
320+
321+
Craft::configure($field, $settings);
322+
}
323+
298324
$view = Craft::$app->getView();
299325
$html = $view->renderTemplate('settings/fields/_type-settings.twig', [
300326
'field' => $field,

src/web/assets/fieldsettings/dist/fieldsettings.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/web/assets/fieldsettings/dist/fieldsettings.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/web/assets/fieldsettings/src/fieldsettings.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,13 @@
3232
});
3333
}
3434

35+
const oldType = this.currentType;
36+
const settings = $('<form/>')
37+
.append(this.$container.clone())
38+
.serialize();
39+
3540
// Save & detach the current settings
36-
this.typeSettings[this.currentType] = this.$container
37-
.children()
38-
.detach();
41+
this.typeSettings[oldType] = this.$container.children().detach();
3942

4043
this.currentType = this.$toggle.val();
4144

@@ -54,12 +57,15 @@
5457

5558
let data = {
5659
type: this.currentType,
60+
oldType,
61+
settings,
5762
};
5863
if (this.namespace) {
5964
data.namespace = this.namespace.replace(
6065
/__TYPE__/g,
6166
this.currentType
6267
);
68+
data.oldNamespace = this.namespace.replace(/__TYPE__/g, oldType);
6369
}
6470

6571
Craft.sendActionRequest('POST', 'fields/render-settings', {

0 commit comments

Comments
 (0)