@@ -117,6 +117,7 @@ public function addTab($tabId, $tab)
117117 if (empty ($ tabId )) {
118118 throw new \Exception (__ ('Please correct the tab configuration and try again. Tab Id should be not empty ' ));
119119 }
120+
120121 if (is_array ($ tab )) {
121122 $ this ->_tabs [$ tabId ] = new \Magento \Framework \DataObject ($ tab );
122123 } elseif ($ tab instanceof \Magento \Framework \DataObject) {
@@ -126,13 +127,15 @@ public function addTab($tabId, $tab)
126127 }
127128 } elseif (is_string ($ tab )) {
128129 $ this ->_addTabByName ($ tab , $ tabId );
130+
129131 if (!$ this ->_tabs [$ tabId ] instanceof TabInterface) {
130132 unset($ this ->_tabs [$ tabId ]);
131133 return $ this ;
132134 }
133135 } else {
134136 throw new \Exception (__ ('Please correct the tab configuration and try again. ' ));
135137 }
138+
136139 if ($ this ->_tabs [$ tabId ]->getUrl () === null ) {
137140 $ this ->_tabs [$ tabId ]->setUrl ('# ' );
138141 }
@@ -143,10 +146,7 @@ public function addTab($tabId, $tab)
143146
144147 $ this ->_tabs [$ tabId ]->setId ($ tabId );
145148 $ this ->_tabs [$ tabId ]->setTabId ($ tabId );
146-
147- if ($ this ->_activeTab === null ) {
148- $ this ->_activeTab = $ tabId ;
149- }
149+
150150 if (true === $ this ->_tabs [$ tabId ]->getActive ()) {
151151 $ this ->setActiveTab ($ tabId );
152152 }
@@ -235,33 +235,108 @@ protected function _setActiveTab($tabId)
235235 */
236236 protected function _beforeToHtml ()
237237 {
238+ $ this ->_tabs = $ this ->reorderTabs ();
239+
238240 if ($ activeTab = $ this ->getRequest ()->getParam ('active_tab ' )) {
239241 $ this ->setActiveTab ($ activeTab );
240242 } elseif ($ activeTabId = $ this ->_authSession ->getActiveTabId ()) {
241243 $ this ->_setActiveTab ($ activeTabId );
242244 }
243245
244- $ _new = [];
246+ if ($ this ->_activeTab === null && !empty ($ this ->_tabs )) {
247+ /** @var TabInterface $tab */
248+ $ this ->_activeTab = (reset ($ this ->_tabs ))->getId ();
249+ }
250+
251+ $ this ->assign ('tabs ' , $ this ->_tabs );
252+ return parent ::_beforeToHtml ();
253+ }
254+
255+ /**
256+ * Reorder the tabs.
257+ *
258+ * @return array
259+ */
260+ private function reorderTabs ()
261+ {
262+ $ orderByIdentity = [];
263+ $ orderByPosition = [];
264+ $ position = 100 ;
265+
266+ /**
267+ * Set the initial positions for each tab.
268+ *
269+ * @var string $key
270+ * @var TabInterface $tab
271+ */
245272 foreach ($ this ->_tabs as $ key => $ tab ) {
246- foreach ($ this ->_tabs as $ k => $ t ) {
247- if ($ t ->getAfter () == $ key ) {
248- $ _new [$ key ] = $ tab ;
249- $ _new [$ k ] = $ t ;
250- } else {
251- if (!$ tab ->getAfter () || !in_array ($ tab ->getAfter (), array_keys ($ this ->_tabs ))) {
252- $ _new [$ key ] = $ tab ;
253- }
254- }
255- }
273+ $ tab ->setPosition ($ position );
274+
275+ $ orderByIdentity [$ key ] = $ tab ;
276+ $ orderByPosition [$ position ] = $ tab ;
277+
278+ $ position += 100 ;
256279 }
257280
258- $ this ->_tabs = $ _new ;
259- unset( $ _new );
281+ return $ this ->applyTabsCorrectOrder ( $ orderByPosition , $ orderByIdentity ) ;
282+ }
260283
261- $ this ->assign ('tabs ' , $ this ->_tabs );
262- return parent ::_beforeToHtml ();
284+ /**
285+ * @param array $orderByPosition
286+ * @param array $orderByIdentity
287+ *
288+ * @return array
289+ */
290+ private function applyTabsCorrectOrder (array $ orderByPosition , array $ orderByIdentity )
291+ {
292+ $ positionFactor = 1 ;
293+
294+ /**
295+ * Rearrange the positions by using the after tag for each tab.
296+ *
297+ * @var integer $position
298+ * @var TabInterface $tab
299+ */
300+ foreach ($ orderByPosition as $ position => $ tab ) {
301+ if (!$ tab ->getAfter () || !in_array ($ tab ->getAfter (), array_keys ($ orderByIdentity ))) {
302+ $ positionFactor = 1 ;
303+ continue ;
304+ }
305+
306+ $ grandPosition = $ orderByIdentity [$ tab ->getAfter ()]->getPosition ();
307+ $ newPosition = $ grandPosition + $ positionFactor ;
308+
309+ unset($ orderByPosition [$ position ]);
310+ $ orderByPosition [$ newPosition ] = $ tab ;
311+ $ tab ->setPosition ($ newPosition );
312+
313+ $ positionFactor ++;
314+ }
315+
316+ return $ this ->finalTabsSortOrder ($ orderByPosition );
263317 }
264318
319+ /**
320+ * Apply the last sort order to tabs.
321+ *
322+ * @param array $orderByPosition
323+ *
324+ * @return array
325+ */
326+ private function finalTabsSortOrder (array $ orderByPosition )
327+ {
328+ ksort ($ orderByPosition );
329+
330+ $ ordered = [];
331+
332+ /** @var TabInterface $tab */
333+ foreach ($ orderByPosition as $ tab ) {
334+ $ ordered [$ tab ->getId ()] = $ tab ;
335+ }
336+
337+ return $ ordered ;
338+ }
339+
265340 /**
266341 * @return string
267342 */
0 commit comments