PluginProbe
YayMail – WooCommerce Email Customizer / 4.4.6
YayMail – WooCommerce Email Customizer v4.4.6
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
← All changes | vendor-prefixed/src/AdminShell.php +38 -39 4.4.2 → 4.4.6 View file →
@@ -18,9 +18,9 @@
18 18 use YayMailScoped\YayCommerce\AdminShell\Registry\LegacyBridge;
19 19 use YayMailScoped\YayCommerce\AdminShell\Registry\LicenseRegistry;
20 20 use YayMailScoped\YayCommerce\AdminShell\Support\AdminContext;
21 21 use YayMailScoped\YayCommerce\AdminShell\Support\Constants;
22 -\defined('ABSPATH') || exit;
22 +defined('ABSPATH') || exit;
23 23 /**
24 24 * Public facade — entry point for consuming plugins.
25 25 *
26 26 * Version election: when multiple scoped copies coexist, the highest
@@ -25,14 +25,13 @@
25 25 *
26 26 * Version election: when multiple scoped copies coexist, the highest
27 27 * VERSION wins and registers menus/pages. All copies' register_plugin()
28 28 * and enable_license() still run — they hook global WP actions.
29 - * @internal
30 29 */
31 30 class AdminShell
32 31 {
33 32 /** Package version — used for cross-scope version election. */
34 - const VERSION = '2.7.1';
33 + const VERSION = '2.8.5';
35 34 private static ?self $instance = null;
36 35 private static bool $booted = \false;
37 36 private static array $enabled_slugs = [];
38 37 /** The scoped prefix for THIS copy (derived from namespace). */
@@ -48,9 +47,9 @@
48 47 * Each scoped copy calls boot(). All register their version in a shared
49 48 * global. Actual menu/page registration is deferred to admin_menu where
50 49 * only the highest version runs.
51 50 */
52 - public static function boot() : void
51 + public static function boot(): void
53 52 {
54 53 if (self::$booted) {
55 54 return;
56 55 }
@@ -59,10 +58,10 @@
59 58 $instance = self::get_instance();
60 59 // Derive our scoped prefix from the namespace (e.g. "YayMailScoped\YayCommerce\AdminShell" → "YayMailScoped")
61 60 $ns = __NAMESPACE__;
62 61 // YayCommerce\AdminShell or ScopedPrefix\YayCommerce\AdminShell
63 - $parts = \explode('\\', $ns);
64 - self::$prefix = \count($parts) > 2 ? $parts[0] : 'default';
62 + $parts = explode('\\', $ns);
63 + self::$prefix = count($parts) > 2 ? $parts[0] : 'default';
65 64 // Register this version in the shared global for cross-scope election
66 65 if (!isset($GLOBALS['yaycommerce_admin_shell_versions'])) {
67 66 $GLOBALS['yaycommerce_admin_shell_versions'] = [];
68 67 }
@@ -69,9 +68,9 @@
69 68 $GLOBALS['yaycommerce_admin_shell_versions'][self::$prefix] = ['version' => self::VERSION, 'registry' => $instance->registry, 'boot_cb' => [static::class, 'do_shell_registration']];
70 69 // Register the version election — only once (first copy to call boot sets it up).
71 70 // Bound to both admin_menu and network_admin_menu so election runs in the
72 71 // Multisite Network Admin too; only the firing hook's election actually runs.
73 - if (1 === \count($GLOBALS['yaycommerce_admin_shell_versions'])) {
72 + if (1 === count($GLOBALS['yaycommerce_admin_shell_versions'])) {
74 73 AdminContext::bind_menu([static::class, 'elect_version'], 8);
75 74 // bind_menu() already wired BOTH hooks here, so mark the network election
76 75 // as done. This is load-bearing: it stops the safety net below from adding
77 76 // a SECOND network binding (elect_version is NOT idempotent — a double
@@ -104,15 +103,15 @@
104 103 $GLOBALS['yaycommerce_ajax_handlers_registered'] = self::VERSION;
105 104 RecommendedPluginsPage::get_instance();
106 105 }
107 106 }
108 - \do_action('yaycommerce_admin_shell_booted', $instance);
107 + do_action('yaycommerce_admin_shell_booted', $instance);
109 108 }
110 109 /**
111 110 * Version election — picks the highest version and runs its shell registration.
112 111 * Called once at admin_menu priority 8 (before TopLevelMenu at 9).
113 112 */
114 - public static function elect_version() : void
113 + public static function elect_version(): void
115 114 {
116 115 $versions = $GLOBALS['yaycommerce_admin_shell_versions'] ?? [];
117 116 if (empty($versions)) {
118 117 return;
@@ -120,9 +119,9 @@
120 119 // Find highest version
121 120 $winner_prefix = '';
122 121 $winner_ver = '0.0.0';
123 122 foreach ($versions as $prefix => $data) {
124 - if (\version_compare($data['version'], $winner_ver, '>')) {
123 + if (version_compare($data['version'], $winner_ver, '>')) {
125 124 $winner_ver = $data['version'];
126 125 $winner_prefix = $prefix;
127 126 }
128 127 }
@@ -127,16 +126,16 @@
127 126 }
128 127 }
129 128 // Call the winner's registration — may be a different scoped class
130 129 $winner = $versions[$winner_prefix];
131 - if (isset($winner['boot_cb']) && \is_callable($winner['boot_cb'])) {
132 - \call_user_func($winner['boot_cb']);
130 + if (isset($winner['boot_cb']) && is_callable($winner['boot_cb'])) {
131 + call_user_func($winner['boot_cb']);
133 132 }
134 133 }
135 134 /**
136 135 * Register menus/pages — only called by the winning version.
137 136 */
138 - public static function do_shell_registration() : void
137 + public static function do_shell_registration(): void
139 138 {
140 139 $instance = self::get_instance();
141 140 // Merge all registries into the winner's registry
142 141 foreach ($GLOBALS['yaycommerce_admin_shell_versions'] ?? [] as $prefix => $data) {
@@ -164,9 +163,9 @@
164 163 * Register a plugin with the admin shell.
165 164 * Auto-detects pro vs lite via instanceof.
166 165 * Runs for ALL versions (not version-gated).
167 166 */
168 - public static function register_plugin(PluginMenuAdapter $adapter) : void
167 + public static function register_plugin(PluginMenuAdapter $adapter): void
169 168 {
170 169 self::validate_adapter($adapter);
171 170 // Publish this plugin's intended submenu position into a shared,
172 171 // cross-scope map (keyed by menu slug). The version-elected winner reads
@@ -183,9 +182,9 @@
183 182 // Submenu registration — per-plugin, all versions
184 183 $submenu = new PluginSubmenu($adapter);
185 184 $submenu->init();
186 185 // Action links + row meta — per-plugin, all versions
187 - if (\is_admin()) {
186 + if (is_admin()) {
188 187 self::register_plugin_links($adapter);
189 188 }
190 189 // License subsystem — per-plugin, all versions
191 190 if ($adapter instanceof LicenseConfigAdapter) {
@@ -206,9 +205,9 @@
206 205 * not appear under the shared YayCommerce menu.
207 206 *
208 207 * @param array{parent_menu: string, menu_title: string, menu_capability: string, menu_slug: string} $config
209 208 */
210 - public static function register_external_plugin_menu(array $config) : void
209 + public static function register_external_plugin_menu(array $config): void
211 210 {
212 211 $adapter = new ExternalPluginMenuAdapter($config);
213 212 $adapter->init();
214 213 }
@@ -214,38 +213,38 @@
214 213 }
215 214 /**
216 215 * Validate adapter values upfront.
217 216 */
218 - private static function validate_adapter(PluginMenuAdapter $adapter) : void
217 + private static function validate_adapter(PluginMenuAdapter $adapter): void
219 218 {
220 219 $menu_title = $adapter->get_menu_title();
221 220 if (empty($menu_title)) {
222 - \trigger_error('[YayCommerce AdminShell] get_menu_title() must return a non-empty string.', \E_USER_WARNING);
221 + trigger_error('[YayCommerce AdminShell] get_menu_title() must return a non-empty string.', \E_USER_WARNING);
223 222 }
224 223 $basename = $adapter->get_plugin_basename();
225 224 if (empty($basename)) {
226 - \trigger_error('[YayCommerce AdminShell] get_plugin_basename() must return a non-empty string.', \E_USER_WARNING);
225 + trigger_error('[YayCommerce AdminShell] get_plugin_basename() must return a non-empty string.', \E_USER_WARNING);
227 226 }
228 227 $callback = $adapter->get_settings_page_callback();
229 - if (null !== $callback && !\is_callable($callback)) {
230 - \trigger_error('[YayCommerce AdminShell] get_settings_page_callback() returned a non-callable value.', \E_USER_WARNING);
228 + if (null !== $callback && !is_callable($callback)) {
229 + trigger_error('[YayCommerce AdminShell] get_settings_page_callback() returned a non-callable value.', \E_USER_WARNING);
231 230 }
232 231 if ($adapter instanceof LicenseConfigAdapter) {
233 232 $slug = $adapter->get_plugin_slug();
234 233 if (empty($slug)) {
235 - \trigger_error('[YayCommerce AdminShell] get_plugin_slug() must return a non-empty string.', \E_USER_WARNING);
234 + trigger_error('[YayCommerce AdminShell] get_plugin_slug() must return a non-empty string.', \E_USER_WARNING);
236 235 }
237 236 $item_id = $adapter->get_item_id();
238 237 if ($item_id <= 0) {
239 - \trigger_error('[YayCommerce AdminShell] get_item_id() must return a positive integer.', \E_USER_WARNING);
238 + trigger_error('[YayCommerce AdminShell] get_item_id() must return a positive integer.', \E_USER_WARNING);
240 239 }
241 240 $store_url = $adapter->get_store_url();
242 241 if (empty($store_url)) {
243 - \trigger_error('[YayCommerce AdminShell] get_store_url() must return a non-empty URL.', \E_USER_WARNING);
242 + trigger_error('[YayCommerce AdminShell] get_store_url() must return a non-empty URL.', \E_USER_WARNING);
244 243 }
245 244 $plugin_file = $adapter->get_plugin_file();
246 245 if (empty($plugin_file)) {
247 - \trigger_error('[YayCommerce AdminShell] get_plugin_file() must return a non-empty path.', \E_USER_WARNING);
246 + trigger_error('[YayCommerce AdminShell] get_plugin_file() must return a non-empty path.', \E_USER_WARNING);
248 247 }
249 248 }
250 249 }
251 250 /**
@@ -251,9 +250,9 @@
251 250 /**
252 251 * Enable the license subsystem for a plugin.
253 252 * Runs for ALL versions (not version-gated).
254 253 */
255 - public static function enable_license(LicenseConfigAdapter $adapter) : void
254 + public static function enable_license(LicenseConfigAdapter $adapter): void
256 255 {
257 256 $slug = $adapter->get_plugin_slug();
258 257 if (isset(self::$enabled_slugs[$slug])) {
259 258 return;
@@ -262,38 +261,38 @@
262 261 $instance = self::get_instance();
263 262 new LicenseHandler($adapter);
264 263 $info = PluginInfoFactory::from_adapter($adapter);
265 264 $instance->registry->register($info);
266 - \do_action('yaycommerce_admin_shell_license_enabled', $adapter);
265 + do_action('yaycommerce_admin_shell_license_enabled', $adapter);
267 266 }
268 267 /**
269 268 * Register plugin action links + row meta.
270 269 */
271 - private static function register_plugin_links(PluginMenuAdapter $adapter) : void
270 + private static function register_plugin_links(PluginMenuAdapter $adapter): void
272 271 {
273 272 $basename = $adapter->get_plugin_basename();
274 - add_filter('plugin_action_links_' . $basename, function (array $links) use($adapter) {
273 + add_filter('plugin_action_links_' . $basename, function (array $links) use ($adapter) {
275 274 $new = [];
276 275 $menu_slug = $adapter->get_menu_slug();
277 276 if (!empty($menu_slug)) {
278 - $url = \admin_url('admin.php?page=' . $menu_slug);
279 - $new['settings'] = '<a href="' . \esc_url($url) . '">' . \esc_html($adapter->get_settings_label()) . '</a>';
277 + $url = admin_url('admin.php?page=' . $menu_slug);
278 + $new['settings'] = '<a href="' . esc_url($url) . '">' . esc_html($adapter->get_settings_label()) . '</a>';
280 279 }
281 280 $pro_url = $adapter->get_pro_url();
282 281 if (!empty($pro_url)) {
283 - $new['go-pro'] = '<a href="' . \esc_url($pro_url) . '" target="_blank" style="color:#00a32a;font-weight:700;">' . \esc_html__('Go Pro', 'yaycommerce') . '</a>';
282 + $new['go-pro'] = '<a href="' . esc_url($pro_url) . '" target="_blank" style="color:#00a32a;font-weight:700;">' . esc_html__('Go Pro', 'yaycommerce') . '</a>';
284 283 }
285 - return \array_merge($new, $links);
284 + return array_merge($new, $links);
286 285 });
287 - add_filter('plugin_row_meta', function (array $meta, string $file) use($adapter, $basename) {
286 + add_filter('plugin_row_meta', function (array $meta, string $file) use ($adapter, $basename) {
288 287 if ($file !== $basename) {
289 288 return $meta;
290 289 }
291 290 $docs_url = $adapter->get_docs_url();
292 291 if (!empty($docs_url)) {
293 - $meta[] = '<a href="' . \esc_url($docs_url) . '" target="_blank">' . \esc_html__('Docs', 'yaycommerce') . '</a>';
292 + $meta[] = '<a href="' . esc_url($docs_url) . '" target="_blank">' . esc_html__('Docs', 'yaycommerce') . '</a>';
294 293 }
295 - $meta[] = '<a href="https://yaycommerce.com/support" target="_blank">' . \esc_html__('Support', 'yaycommerce') . '</a>';
294 + $meta[] = '<a href="https://yaycommerce.com/support" target="_blank">' . esc_html__('Support', 'yaycommerce') . '</a>';
296 295 return $meta;
297 296 }, 10, 2);
298 297 }
299 298 /**
@@ -298,13 +297,13 @@
298 297 }
299 298 /**
300 299 * Return the shared registry.
301 300 */
302 - public static function registry() : LicenseRegistry
301 + public static function registry(): LicenseRegistry
303 302 {
304 303 return self::get_instance()->registry;
305 304 }
306 - private static function get_instance() : self
305 + private static function get_instance(): self
307 306 {
308 307 if (null === self::$instance) {
309 308 self::$instance = new self();
310 309 }
@@ -312,9 +311,9 @@
312 311 }
313 312 /**
314 313 * Reset state — for unit tests only.
315 314 */
316 - public static function reset() : void
315 + public static function reset(): void
317 316 {
318 317 self::$instance = null;
319 318 self::$booted = \false;
320 319 self::$enabled_slugs = [];