PluginProbe ʕ •ᴥ•ʔ
WP Chat App / trunk
WP Chat App vtrunk
3.8.1 3.8.2 trunk 2.6 3.4 3.4.1 3.4.2 3.4.4 3.4.5 3.4.6 3.5 3.6 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0
wp-whatsapp / vendor-prefixed / src / VersionedLoader.php
wp-whatsapp / vendor-prefixed / src Last commit date
Contracts 4 months ago License 3 months ago Menu 3 months ago Pages 3 months ago Registry 3 months ago Support 4 months ago AdminShell.php 3 months ago VersionedLoader.php 4 months ago
VersionedLoader.php
95 lines
1 <?php
2
3 namespace WhatsappScoped\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 * @internal
20 */
21 class VersionedLoader
22 {
23 /** @var array<string, callable> version => boot callback */
24 private static array $candidates = [];
25 /** @var bool Whether election has already run */
26 private static bool $elected = \false;
27 /**
28 * Register this package version as a candidate to run the boot callback.
29 *
30 * If two plugins register the same version string, the FIRST registration
31 * wins (deterministic first-wins, not last-wins). This prevents silent
32 * callback replacement when two plugins ship identical admin-shell versions.
33 *
34 * @param string $version Semver string, e.g. '1.2.0'
35 * @param callable $callback Boot callback — called only if this version wins.
36 */
37 public static function register(string $version, callable $callback) : void
38 {
39 // First-wins: do not overwrite an already-registered version.
40 if (isset(self::$candidates[$version])) {
41 return;
42 }
43 self::$candidates[$version] = $callback;
44 // Schedule election to run after all plugins_loaded callbacks.
45 // We use priority 999 so all candidates at default priority register first.
46 if (!self::$elected) {
47 add_action('plugins_loaded', [self::class, 'elect'], 999);
48 }
49 }
50 /**
51 * Run after all plugins_loaded hooks. Pick highest version and invoke its callback.
52 * Idempotent — second call is a no-op.
53 */
54 public static function elect() : void
55 {
56 if (self::$elected || empty(self::$candidates)) {
57 return;
58 }
59 self::$elected = \true;
60 $winner = null;
61 foreach (\array_keys(self::$candidates) as $version) {
62 if ($winner === null || \version_compare($version, $winner, '>')) {
63 $winner = $version;
64 }
65 }
66 if ($winner !== null && isset(self::$candidates[$winner])) {
67 self::$candidates[$winner]();
68 }
69 }
70 /**
71 * Return the winning version string, or null if election hasn't run.
72 */
73 public static function get_elected_version() : ?string
74 {
75 if (!self::$elected || empty(self::$candidates)) {
76 return null;
77 }
78 $winner = null;
79 foreach (\array_keys(self::$candidates) as $version) {
80 if ($winner === null || \version_compare($version, $winner, '>')) {
81 $winner = $version;
82 }
83 }
84 return $winner;
85 }
86 /**
87 * Reset state — only for unit tests.
88 */
89 public static function reset() : void
90 {
91 self::$candidates = [];
92 self::$elected = \false;
93 }
94 }
95