PluginProbe
YayMail – WooCommerce Email Customizer / trunk
YayMail – WooCommerce Email Customizer vtrunk
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 3.4.2 3.4.3 All 55 releases
yaymail / vendor-prefixed / src / Menu / SubmenuPositioner.php

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

74 lines 2.9 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 */
21 class SubmenuPositioner
22 {
23 const PARENT = 'yaycommerce';
24 const POSITION_KEY = 'yaycommerce_admin_shell_submenu_positions';
25 public function init(): void
26 {
27 // Priority 9999: run after every plugin (<=10) and TopLevelMenu's parent
28 // submenu cleanup (999) have finished, so the array is complete.
29 // Bound to both hooks so reordering also applies in Network Admin.
30 AdminContext::bind_menu([$this, 'reorder'], 9999);
31 }
32 /**
33 * Reorder $submenu['yaycommerce'] by declared position.
34 * Lower position first; ties and unknown/null positions keep their existing
35 * order and sort after positioned items.
36 */
37 public function reorder(): void
38 {
39 global $submenu;
40 if (empty($submenu[self::PARENT]) || !is_array($submenu[self::PARENT])) {
41 return;
42 }
43 $positions = $GLOBALS[self::POSITION_KEY] ?? [];
44 // Decorate with original index for a stable sort (usort is not stable
45 // before PHP 8.0). Item shape: [ menu_title, capability, menu_slug, ... ].
46 $decorated = [];
47 foreach ($submenu[self::PARENT] as $index => $item) {
48 $slug = $item[2] ?? '';
49 $decorated[] = ['item' => $item, 'index' => $index, 'position' => $positions[$slug] ?? null];
50 }
51 usort($decorated, function ($a, $b) {
52 $pa = $a['position'];
53 $pb = $b['position'];
54 if (null === $pa && null === $pb) {
55 return $a['index'] <=> $b['index'];
56 }
57 if (null === $pa) {
58 return 1;
59 // unknown/null positions last
60 }
61 if (null === $pb) {
62 return -1;
63 }
64 if ($pa === $pb) {
65 return $a['index'] <=> $b['index'];
66 // stable tiebreak
67 }
68 return $pa <=> $pb;
69 });
70 // Re-index to sequential keys; WP renders the submenu in array order.
71 $submenu[self::PARENT] = array_values(array_column($decorated, 'item'));
72 }
73 }
74