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 / VersionedLoader.php

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

94 lines 3.2 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;
4
5 /**
6 * Highest-version-wins runtime election for the admin-shell package.
7 *
8 * When multiple plugins include different versions of this package
9 * (before PHP-Scoper prefixing is applied), each plugin registers its
10 * version during 'plugins_loaded'. After 'plugins_loaded', the highest
11 * registered version wins — only that version's boot() runs.
12 *
13 * Usage (in each consuming plugin's main file):
14 * add_action('plugins_loaded', function() {
15 * \YayCommerce\AdminShell\VersionedLoader::register('1.2.0', function() {
16 * \YayCommerce\AdminShell\AdminShell::boot();
17 * });
18 * }, 0);
19 */
20 class VersionedLoader
21 {
22 /** @var array<string, callable> version => boot callback */
23 private static array $candidates = [];
24 /** @var bool Whether election has already run */
25 private static bool $elected = \false;
26 /**
27 * Register this package version as a candidate to run the boot callback.
28 *
29 * If two plugins register the same version string, the FIRST registration
30 * wins (deterministic first-wins, not last-wins). This prevents silent
31 * callback replacement when two plugins ship identical admin-shell versions.
32 *
33 * @param string $version Semver string, e.g. '1.2.0'
34 * @param callable $callback Boot callback — called only if this version wins.
35 */
36 public static function register(string $version, callable $callback): void
37 {
38 // First-wins: do not overwrite an already-registered version.
39 if (isset(self::$candidates[$version])) {
40 return;
41 }
42 self::$candidates[$version] = $callback;
43 // Schedule election to run after all plugins_loaded callbacks.
44 // We use priority 999 so all candidates at default priority register first.
45 if (!self::$elected) {
46 add_action('plugins_loaded', [self::class, 'elect'], 999);
47 }
48 }
49 /**
50 * Run after all plugins_loaded hooks. Pick highest version and invoke its callback.
51 * Idempotent — second call is a no-op.
52 */
53 public static function elect(): void
54 {
55 if (self::$elected || empty(self::$candidates)) {
56 return;
57 }
58 self::$elected = \true;
59 $winner = null;
60 foreach (array_keys(self::$candidates) as $version) {
61 if ($winner === null || version_compare($version, $winner, '>')) {
62 $winner = $version;
63 }
64 }
65 if ($winner !== null && isset(self::$candidates[$winner])) {
66 self::$candidates[$winner]();
67 }
68 }
69 /**
70 * Return the winning version string, or null if election hasn't run.
71 */
72 public static function get_elected_version(): ?string
73 {
74 if (!self::$elected || empty(self::$candidates)) {
75 return null;
76 }
77 $winner = null;
78 foreach (array_keys(self::$candidates) as $version) {
79 if ($winner === null || version_compare($version, $winner, '>')) {
80 $winner = $version;
81 }
82 }
83 return $winner;
84 }
85 /**
86 * Reset state — only for unit tests.
87 */
88 public static function reset(): void
89 {
90 self::$candidates = [];
91 self::$elected = \false;
92 }
93 }
94