diff --git a/app/code/core/Mage/Adminhtml/Block/Widget/Tabs.php b/app/code/core/Mage/Adminhtml/Block/Widget/Tabs.php index f78bbde04dc..99b2a0d6fc1 100644 --- a/app/code/core/Mage/Adminhtml/Block/Widget/Tabs.php +++ b/app/code/core/Mage/Adminhtml/Block/Widget/Tabs.php @@ -38,7 +38,28 @@ class Mage_Adminhtml_Block_Widget_Tabs extends Mage_Adminhtml_Block_Widget * * @var array */ - protected $_tabs = array(); + protected $_tabs = []; + + /** + * For sorting tabs. + * + * @var array + */ + protected $_afterTabIds = []; + + /** + * For sorting tabs. + * + * @var array + */ + protected $_tabPositions = []; + + /** + * For sorting tabs. + * + * @var int + */ + protected $_tabPosition = 100; /** * Active tab key @@ -79,21 +100,21 @@ public function setDestElementId($elementId) * Add new tab after another * * @param string $tabId new tab Id - * @param array|Varien_Object $tab + * @param string|array|Varien_Object $tab * @param string $afterTabId * @return Mage_Adminhtml_Block_Widget_Tabs */ public function addTabAfter($tabId, $tab, $afterTabId) { $this->addTab($tabId, $tab); - $this->_tabs[$tabId]->setAfter($afterTabId); + $this->_afterTabIds[$tabId] = $afterTabId; } /** * Add new tab * * @param string $tabId - * @param array|Varien_Object $tab + * @param string|array|Varien_Object $tab * @return Mage_Adminhtml_Block_Widget_Tabs */ public function addTab($tabId, $tab) @@ -137,8 +158,16 @@ public function addTab($tabId, $tab) $this->_tabs[$tabId]->setId($tabId); $this->_tabs[$tabId]->setTabId($tabId); - if (is_null($this->_activeTab)) $this->_activeTab = $tabId; - if (true === $this->_tabs[$tabId]->getActive()) $this->setActiveTab($tabId); + if (true === $this->_tabs[$tabId]->getActive()) { + $this->setActiveTab($tabId); + } + + // For sorting tabs. + $this->_tabPositions[$tabId] = $this->_tabPosition; + $this->_tabPosition += 100; + if ($this->_tabs[$tabId]->getAfter()) { + $this->_afterTabIds[$tabId] = $this->_tabs[$tabId]->getAfter(); + } return $this; } @@ -160,11 +189,6 @@ public function setActiveTab($tabId) if (isset($this->_tabs[$tabId]) && $this->canShowTab($this->_tabs[$tabId]) && !$this->getTabIsHidden($this->_tabs[$tabId])) { $this->_activeTab = $tabId; - if (!(is_null($this->_activeTab)) && ($tabId !== $this->_activeTab)) { - foreach ($this->_tabs as $id => $tab) { - $tab->setActive($id === $tabId); - } - } } return $this; } @@ -195,27 +219,60 @@ protected function _beforeToHtml() $this->_setActiveTab($activeTabId); } - $_new = array(); - foreach( $this->_tabs as $key => $tab ) { - foreach( $this->_tabs as $k => $t ) { - if( $t->getAfter() == $key ) { - $_new[$key] = $tab; - $_new[$k] = $t; - } else { - if( !$tab->getAfter() || !in_array($tab->getAfter(), array_keys($this->_tabs)) ) { - $_new[$key] = $tab; - } - } - } + if ($this->_activeTab === null && !empty($this->_tabs)) { + $this->_activeTab = (reset($this->_tabs))->getId(); } - $this->_tabs = $_new; - unset($_new); + if (!empty($this->_afterTabIds)) { + $this->_tabs = $this->_reorderTabs(); + } $this->assign('tabs', $this->_tabs); return parent::_beforeToHtml(); } + /** + * Find the root parent Tab ID recursively. + * + * @param string $currentAfterTabId + * @param int $degree Degrees of separation between child and root parent. + * @return string The parent tab ID. + */ + protected function _getRootParentTabId($currentAfterTabId, &$degree) + { + if (array_key_exists($currentAfterTabId, $this->_afterTabIds)) { + $degree++; + return $this->_getRootParentTabId($this->_afterTabIds[$currentAfterTabId], $degree); + } else { + return $currentAfterTabId; + } + } + + protected function _reorderTabs() + { + // Set new position based on $afterTabId. + foreach ($this->_afterTabIds as $tabId => $afterTabId) { + if (array_key_exists($afterTabId, $this->_tabs)) { + $degree = 1; // Initialize to 1 degree of separation. + $parentAfterTabId = $this->_getRootParentTabId($afterTabId, $degree); + $this->_tabPositions[$tabId] = $this->_tabPositions[$parentAfterTabId] + $degree; + $degree++; + } + } + + asort($this->_tabPositions); + + $ordered = []; + foreach ($this->_tabPositions as $tabId => $position) { + if (isset($this->_tabs[$tabId])) { + $tab = $this->_tabs[$tabId]; + $ordered[$tabId] = $tab; + } + } + + return $ordered; + } + public function getJsObjectName() { return $this->getId() . 'JsTabs';