PluginProbe
YayMail – WooCommerce Email Customizer / 4.4.1
YayMail – WooCommerce Email Customizer v4.4.1
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 / Registry / AddonBridge.php

AddonBridge.php in YayMail – WooCommerce Email Customizer 4.4.1, at vendor-prefixed/src/Registry/AddonBridge.php

166 lines 6.6 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\Registry;
4
5 use YayMailScoped\YayCommerce\AdminShell\License\License;
6 use YayMailScoped\YayCommerce\AdminShell\License\RestAPI;
7 use YayMailScoped\YayCommerce\AdminShell\Support\Slug;
8 /**
9 * Reads a plugin-specific addon licensing filter and bridges entries
10 * into the LicenseRegistry. Renders license cards for addon entries.
11 *
12 * Similar to LegacyBridge but for plugin-specific addon filters
13 * (e.g., yaymail_available_licensing_plugins) rather than the global
14 * yaycommerce_licensing_plugins filter.
15 *
16 * Pattern mirrors LegacyBridge — derive_status() logic intentionally
17 * duplicated (only two consumers; extract if a third appears).
18 */
19 class AddonBridge
20 {
21 private string $filter_name;
22 private LicenseRegistry $registry;
23 /** @var string[] Slugs this bridge registered (for rendering). */
24 private array $addon_slugs = [];
25 /** @var array<string, array> Raw addon data keyed by slug (for rendering). */
26 private array $addon_data = [];
27 public function __construct(string $filter_name, LicenseRegistry $registry)
28 {
29 $this->filter_name = $filter_name;
30 $this->registry = $registry;
31 }
32 /**
33 * Hook into plugins_loaded at priority 9999 (same as LegacyBridge)
34 * and yaycommerce_licenses_page at priority 100 for card rendering.
35 */
36 public function init() : void
37 {
38 \add_action('plugins_loaded', [$this, 'load_addon_plugins'], 9999);
39 if (\is_admin()) {
40 \add_action('yaycommerce_licenses_page', [$this, 'render_addon_cards'], 100);
41 \add_action('admin_enqueue_scripts', [$this, 'enqueue_addon_scripts']);
42 }
43 }
44 /**
45 * Read addon filter and convert entries to PluginLicenseInfo stubs.
46 * Addon format matches yaycommerce_licensing_plugins:
47 * [ 'slug', 'name', 'basename', 'file', 'url', 'item_id' ]
48 */
49 public function load_addon_plugins() : void
50 {
51 $addons = \apply_filters($this->filter_name, []);
52 foreach ($addons as $plugin) {
53 $slug = $plugin['slug'] ?? '';
54 if (empty($slug) || $this->registry->has($slug)) {
55 continue;
56 }
57 $info = $this->build_addon_info($plugin);
58 $this->registry->register($info);
59 $this->addon_slugs[] = $slug;
60 $this->addon_data[$slug] = $plugin;
61 // Register REST routes so license card buttons (activate/update/deactivate) work.
62 new RestAPI($this->build_addon_adapter($plugin));
63 }
64 }
65 /**
66 * Build a PluginLicenseInfo from an addon filter entry.
67 * Reads {slug}_license_info from wp_options for current status.
68 * Pattern mirrors LegacyBridge::build_legacy_info().
69 */
70 private function build_addon_info(array $plugin) : PluginLicenseInfo
71 {
72 $slug = $plugin['slug'] ?? '';
73 $raw_info = \get_option($slug . '_license_info', []);
74 if (\is_string($raw_info)) {
75 $raw_info = \json_decode($raw_info, \true) ?: [];
76 }
77 $license_key = (string) \get_option($slug . '_license_key', '');
78 $expires_raw = $raw_info['expires'] ?? null;
79 $status = $this->derive_status($license_key, $raw_info);
80 $info = new PluginLicenseInfo();
81 $info->slug = $slug;
82 $info->name = $plugin['name'] ?? $slug;
83 $info->version = '';
84 $info->basename = $plugin['basename'] ?? '';
85 $info->item_id = (int) ($plugin['item_id'] ?? 0);
86 $info->store_link = $plugin['url'] ?? '';
87 $info->license_key = $license_key;
88 $info->status = $status;
89 $info->expires_at = $expires_raw && 'Not updated' !== $expires_raw ? $expires_raw : null;
90 $info->activations_used = (int) ($raw_info['site_count'] ?? 0);
91 $info->activations_limit = (int) ($raw_info['license_limit'] ?? 0);
92 $info->is_legacy = \true;
93 $info->raw_info = $raw_info;
94 return $info;
95 }
96 /**
97 * Derive normalized status from wp_options data.
98 * Mirrors LegacyBridge::derive_status().
99 */
100 private function derive_status(string $license_key, array $raw_info) : string
101 {
102 if (empty($license_key)) {
103 return 'inactive';
104 }
105 $expires = $raw_info['expires'] ?? null;
106 if ($expires && 'lifetime' !== $expires && 'Not updated' !== $expires) {
107 if (\strtotime($expires) < \time()) {
108 return 'expired';
109 }
110 }
111 return 'valid';
112 }
113 /**
114 * Render license cards for addon entries this bridge registered.
115 * Builds a minimal LicenseConfigAdapter per addon so the License
116 * class and card templates work without modification.
117 */
118 public function render_addon_cards() : void
119 {
120 foreach ($this->addon_slugs as $slug) {
121 $plugin_data = $this->addon_data[$slug] ?? [];
122 if (empty($plugin_data)) {
123 continue;
124 }
125 $adapter = $this->build_addon_adapter($plugin_data);
126 $license = new License($adapter);
127 $_plugin = ['slug' => $slug, 'name' => $plugin_data['name'] ?? $slug];
128 if ($license->is_active()) {
129 include __DIR__ . '/../../views/license-card.php';
130 } else {
131 include __DIR__ . '/../../views/license-activate-card.php';
132 }
133 }
134 }
135 /**
136 * Enqueue license.js and localize data for each addon slug.
137 * Mirrors LicenseHandler::enqueue_license_scripts().
138 *
139 * NOTE: Addon must register REST routes at {slug}/v1/license/*
140 * for the activate/update/deactivate buttons to work.
141 */
142 public function enqueue_addon_scripts() : void
143 {
144 if (!isset($_GET['page']) || 'yaycommerce-licenses' !== $_GET['page']) {
145 // phpcs:ignore WordPress.Security.NonceVerification
146 return;
147 }
148 if (empty($this->addon_slugs)) {
149 return;
150 }
151 $assets_url = \plugin_dir_url(__FILE__) . '../../assets/';
152 \wp_enqueue_script('yaycommerce-license', $assets_url . 'js/license.js', ['jquery'], '1.0', \true);
153 foreach ($this->addon_slugs as $slug) {
154 \wp_localize_script('yaycommerce-license', Slug::to_var_name($slug) . 'LicenseData', ['slug' => $slug, 'apiSettings' => ['restNonce' => \wp_create_nonce('wp_rest'), 'restUrl' => \esc_url_raw(\rest_url(Slug::to_var_name($slug) . '/v1')), 'adminUrl' => \admin_url()]]);
155 }
156 }
157 /**
158 * Build a minimal LicenseConfigAdapter from addon filter data.
159 * Used by License constructor + card templates.
160 */
161 private function build_addon_adapter(array $plugin_data) : AddonLicenseAdapter
162 {
163 return new AddonLicenseAdapter($plugin_data);
164 }
165 }
166