From eee7a84a480b028a3d925bc7483cae9c45e9d252 Mon Sep 17 00:00:00 2001 From: Guy Sartorelli <36352093+GuySartorelli@users.noreply.github.com> Date: Mon, 12 Aug 2024 09:33:55 +1200 Subject: [PATCH] NEW Add new method TabSet::changeTabOrder(). (#11329) --- src/Forms/TabSet.php | 33 ++++++++++++++++++++++++++++++ tests/php/Forms/TabSetTest.php | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 tests/php/Forms/TabSetTest.php diff --git a/src/Forms/TabSet.php b/src/Forms/TabSet.php index c397b62a2..47037193e 100644 --- a/src/Forms/TabSet.php +++ b/src/Forms/TabSet.php @@ -249,6 +249,39 @@ class TabSet extends CompositeField return parent::insertAfter($insertAfter, $field, $appendIfMissing); } + /** + * Change the order of tabs which are direct children of this TabSet by specifying an ordered list of + * tab names. + * + * This works well in conjunction with SilverStripe's scaffolding functions: take the scaffold, and + * shuffle the tabs around to the order that you want. + * + * Tab names should exclude prefixes. For example if this TabSet is "Root", include "Main" not "Root.Main" + */ + public function changeTabOrder(array $tabNames): static + { + // Build a map of tabs indexed by their name. This will make the 2nd step much easier. + $existingTabs = []; + foreach ($this->children as $tab) { + $existingTabs[$tab->getName()] = $tab; + } + + // Iterate through the ordered list of names, building a new array. + // While we're doing this, empty out $existingTabs so that we can keep track of leftovers. + // Unrecognised field names are okay; just ignore them. + $orderedTabs = []; + foreach ($tabNames as $tabName) { + if (isset($existingTabs[$tabName])) { + $orderedTabs[] = $existingTabs[$tabName]; + unset($existingTabs[$tabName]); + } + } + + // Add the leftover fields to the end of the ordered list. + $this->setTabs(FieldList::create([...$orderedTabs, ...$existingTabs])); + return $this; + } + /** * Sets an additional default for $schemaData. * The existing keys are immutable. HideNav is added in this overriding method to ensure it is not ignored by diff --git a/tests/php/Forms/TabSetTest.php b/tests/php/Forms/TabSetTest.php new file mode 100644 index 000000000..35e9cb1a9 --- /dev/null +++ b/tests/php/Forms/TabSetTest.php @@ -0,0 +1,37 @@ +findOrMakeTab('Root.Main'); + $fieldList->findOrMakeTab('Root.Next'); + $fieldList->findOrMakeTab('Root.More'); + $fieldList->findOrMakeTab('Root.Extra'); + $fieldList->addFieldToTab('Root', new TabSet('SubTabSet')); + $fieldList->findOrMakeTab('Root.SubTabSet.Another'); + + // Reorder tabs - intentionally leaving some alone, which will be added to the end. + $tabSet->changeTabOrder([ + 'SubTabSet', + 'More', + 'Main', + 'Non-Existent', // will be ignored + 'Another', // will be ignored + ]); + // Order is correct + $this->assertSame(['SubTabSet', 'More', 'Main', 'Next', 'Extra'], $tabSet->getChildren()->column('Name')); + // Sub-tab is still there + $this->assertNotNull($fieldList->findTab('Root.SubTabSet.Another')); + } +}