PluginProbe
YayMail – WooCommerce Email Customizer / 4.4.2
YayMail – WooCommerce Email Customizer v4.4.2
4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 trunk 1.9.6 2.1.4 2.1.5 3.2.2 3.2.6 3.2.7.1 3.2.8.1 3.2.9 3.3 3.3.1 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4 3.4.1 All 57 releases
yaymail / vendor-prefixed / src / Menu / SubmenuPositioner.php

SubmenuPositioner.php in YayMail – WooCommerce Email Customizer 4.4.2, at vendor-prefixed/src/Menu/SubmenuPositioner.php

75 lines 3.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace YayMailScoped\YayCommerce\AdminShell\Menu;
4
5 use YayMailScoped\YayCommerce\AdminShell\Support\AdminContext;
6 /**
7 * Applies the intended ordering to the YayCommerce submenu.
8 *
9 * WordPress treats add_submenu_page()'s $position as an array INSERTION INDEX,
10 * not an ordering rank, and silently appends any value >= the current submenu
11 * count. Sparse positions (e.g. 10, 20, 21, 40) therefore collapse to plugin
12 * load order. Rather than fight that at registration time (which can't be
13 * coordinated across already-shipped scoped copies), we let every plugin
14 * register however it likes, then reorder the FINAL assembled array once.
15 *
16 * Ownership: run only by the version-elected winner (via do_shell_registration),
17 * so a single authority orders ALL submenus — including those registered by
18 * older co-installed copies. Positions are read from a shared cross-scope map
19 * populated by AdminShell::register_plugin().
20 * @internal
21 */
22 class SubmenuPositioner
23 {
24 const PARENT = 'yaycommerce';
25 const POSITION_KEY = 'yaycommerce_admin_shell_submenu_positions';
26 public function init() : void
27 {
28 // Priority 9999: run after every plugin (<=10) and TopLevelMenu's parent
29 // submenu cleanup (999) have finished, so the array is complete.
30 // Bound to both hooks so reordering also applies in Network Admin.
31 AdminContext::bind_menu([$this, 'reorder'], 9999);
32 }
33 /**
34 * Reorder $submenu['yaycommerce'] by declared position.
35 * Lower position first; ties and unknown/null positions keep their existing
36 * order and sort after positioned items.
37 */
38 public function reorder() : void
39 {
40 global $submenu;
41 if (empty($submenu[self::PARENT]) || !\is_array($submenu[self::PARENT])) {
42 return;
43 }
44 $positions = $GLOBALS[self::POSITION_KEY] ?? [];
45 // Decorate with original index for a stable sort (usort is not stable
46 // before PHP 8.0). Item shape: [ menu_title, capability, menu_slug, ... ].
47 $decorated = [];
48 foreach ($submenu[self::PARENT] as $index => $item) {
49 $slug = $item[2] ?? '';
50 $decorated[] = ['item' => $item, 'index' => $index, 'position' => $positions[$slug] ?? null];
51 }
52 \usort($decorated, function ($a, $b) {
53 $pa = $a['position'];
54 $pb = $b['position'];
55 if (null === $pa && null === $pb) {
56 return $a['index'] <=> $b['index'];
57 }
58 if (null === $pa) {
59 return 1;
60 // unknown/null positions last
61 }
62 if (null === $pb) {
63 return -1;
64 }
65 if ($pa === $pb) {
66 return $a['index'] <=> $b['index'];
67 // stable tiebreak
68 }
69 return $pa <=> $pb;
70 });
71 // Re-index to sequential keys; WP renders the submenu in array order.
72 $submenu[self::PARENT] = \array_values(\array_column($decorated, 'item'));
73 }
74 }
75