PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 2.0.25
Advanced Ads – Ad Manager & AdSense v2.0.25
2.0.25 2.0.24 2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.42.1 1.42.2 1.43.0 1.44.0 1.44.1 1.45.0 1.45.1 1.46.0 1.47.0 1.47.1 1.47.2 1.47.3 1.47.4 1.47.5 1.48.0 1.48.1 1.49.0 1.5.0 1.5.0.1 1.5.1 1.5.2 1.5.2.1 1.5.4 1.5.4.1 1.5.5 1.50.0 1.51.0 1.51.1 1.51.2 1.51.3 1.52.0 1.52.1 1.52.2 1.52.3 1.52.4 1.53.0 1.53.1 1.53.2 1.54.0 1.54.1 1.55.0 1.56.0 1.56.1 1.56.2 1.56.3 1.56.4 1.6 1.6.1 1.6.10 1.6.10.1 1.6.10.2 1.6.11 1.6.11.1 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.17.1 1.6.17.2 1.6.2 1.6.2.1 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.6.1 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.6.8.3 1.6.9 1.6.9.1 1.6.9.2 1.6.9.3 1.6.9.4 1.7 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.1.1 1.7.1.2 1.7.1.3 1.7.1.4 1.7.1.5 1.7.10 trunk 1.7.11 1.0.1 1.7.12 1.0.2 1.7.13 1.0.3 1.7.14 1.1.0 1.7.15 1.1.1 1.7.16 1.1.2 1.7.17 1.1.3 1.7.18 1.10 1.7.19 1.10.1 1.7.2 1.10.10 1.7.2.1 1.10.11 1.7.20 1.10.12 1.7.21 1.10.2 1.7.22 1.10.3 1.7.23 1.10.4 1.7.24 1.10.5 1.7.25 1.10.6 1.7.3 1.10.7 1.7.4 1.10.8 1.7.4.1 1.10.9 1.7.4.2 1.11 1.7.4.3 1.11.1 1.7.4.4 1.11.2 1.7.4.5 1.12 1.7.5 1.13 1.7.5.1 1.13.1 1.7.6 1.13.2 1.7.7 1.13.3 1.7.8 1.13.4 1.7.9 1.13.5 1.7.9.1 1.13.6 1.7.9.2 1.13.7 1.7.9.3 1.13.8 1.8 1.14 1.8.1 1.14.1 1.8.10 1.14.10 1.8.11 1.14.11 1.8.12 1.14.2 1.8.13 1.14.3 1.8.14 1.14.4 1.8.15 1.14.5 1.8.16 1.14.6 1.8.17 1.14.7 1.8.18 1.14.8 1.8.19 1.14.9 1.8.2 1.15 1.8.20 1.16 1.8.21 1.16.1 1.8.22 1.17 1.8.23 1.17.1 1.8.24 1.17.10 1.8.25 1.17.10-rc.1 1.8.26 1.17.11 1.8.27 1.17.12 1.8.28 1.17.12-rc.1 1.8.29 1.17.2 1.8.3 1.17.3 1.8.30 1.17.4 1.8.4 1.17.5 1.8.5 1.17.6 1.8.6 1.17.7 1.8.7 1.17.8 1.8.8 1.17.9 1.8.9 1.17.9-beta.1 1.9 1.18.0 2.0.0 1.19.0 2.0.1 1.19.1 2.0.10 1.2 2.0.11 1.2.1 2.0.12 1.2.2 2.0.13 1.2.3 2.0.14 1.2.4 2.0.15 1.2.5 2.0.16 1.2.6 2.0.17 1.2.7 2.0.18 1.20.0 2.0.19 1.20.0-rc.1 2.0.2 1.20.0-rc.2 2.0.20 1.20.1 2.0.3 1.20.2 2.0.4 1.20.3 2.0.5 1.21.0 2.0.6 1.21.1 2.0.7 1.22.0 2.0.8 1.22.1 2.0.9 1.22.2 1.23.0 1.23.1 1.23.2 1.24.0 1.24.1 1.24.2 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.29.0 1.29.1 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.30.0 1.30.1 1.30.2 1.30.2-rc.1 1.30.3 1.30.4 1.30.4-rc.1 1.30.5 1.31.0 1.31.1 1.32.0 1.32.0-rc.1 1.33.0 1.33.1 1.33.2 1.34.0 1.35.0 1.35.1 1.36.0 1.36.1 1.36.2 1.36.3 1.37.0 1.37.1 1.37.2
advanced-ads / includes / utilities / class-addons.php
advanced-ads / includes / utilities Last commit date
class-ad-list-stats.php 1 week ago class-addons.php 1 day ago class-cache.php 1 week ago class-conditional.php 1 day ago class-content-injection.php 1 year ago class-data.php 1 day ago class-sanitize.php 1 year ago class-testing.php 1 year ago class-validation.php 1 day ago class-wordpress.php 1 day ago index.php 2 years ago
class-addons.php
240 lines
1 <?php
2 /**
3 * Paid add-on registry and installed-plugin discovery.
4 *
5 * @package AdvancedAds
6 * @author Advanced Ads <info@wpadvancedads.com>
7 * @since 2.0.24
8 */
9
10 namespace AdvancedAds\Utilities;
11
12 defined( 'ABSPATH' ) || exit;
13
14 /**
15 * Canonical add-on paths and shared get_plugins() lookups.
16 */
17 final class Addons {
18
19 /**
20 * Plugin bootstrap paths keyed by short add-on id.
21 *
22 * @var array<string, string>
23 */
24 private const PLUGIN_FILES = [
25 'pro' => 'advanced-ads-pro/advanced-ads-pro.php',
26 'responsive' => 'advanced-ads-responsive/responsive-ads.php',
27 'gam' => 'advanced-ads-gam/advanced-ads-gam.php',
28 'layer' => 'advanced-ads-layer/layer-ads.php',
29 'selling' => 'advanced-ads-selling/advanced-ads-selling.php',
30 'sticky' => 'advanced-ads-sticky-ads/sticky-ads.php',
31 'tracking' => 'advanced-ads-tracking/tracking.php',
32 'slider-ads' => 'advanced-ads-slider/slider.php',
33 ];
34
35 /**
36 * Cached get_plugins() result for the current request.
37 *
38 * @var array<string, array>|null
39 */
40 private static $plugins = null;
41
42 /**
43 * Canonical plugin bootstrap paths for paid add-ons.
44 *
45 * @return array<string, string> Short add-on id => plugins-relative bootstrap path.
46 */
47 public static function plugin_files(): array {
48 return self::PLUGIN_FILES;
49 }
50
51 /**
52 * All known paid add-on short ids.
53 *
54 * @return string[]
55 */
56 public static function known_addon_ids(): array {
57 return array_keys( self::PLUGIN_FILES );
58 }
59
60 /**
61 * Whether the short id belongs to a paid add-on in the catalog.
62 *
63 * @param string $addon_id Short add-on id.
64 *
65 * @return bool
66 */
67 public static function is_known_addon( string $addon_id ): bool {
68 return isset( self::PLUGIN_FILES[ sanitize_key( $addon_id ) ] );
69 }
70
71 /**
72 * Canonical bootstrap path for a catalog add-on.
73 *
74 * @param string $addon_id Short add-on id.
75 *
76 * @return string|null Plugins-relative bootstrap path, or null when unknown.
77 */
78 public static function plugin_file( string $addon_id ): ?string {
79 $addon_id = sanitize_key( $addon_id );
80
81 return self::PLUGIN_FILES[ $addon_id ] ?? null;
82 }
83
84 /**
85 * Installed plugins from WordPress.
86 *
87 * @param bool $refresh When true, bust the plugins object cache first.
88 *
89 * @return array<string, array> Plugin bootstrap path => plugin header data.
90 */
91 public static function get_plugins( bool $refresh = false ): array {
92 if ( $refresh ) {
93 self::$plugins = null;
94 wp_cache_delete( 'plugins', 'plugins' );
95 }
96
97 if ( null !== self::$plugins ) {
98 return self::$plugins;
99 }
100
101 if ( ! function_exists( 'get_plugins' ) ) {
102 require_once ABSPATH . 'wp-admin/includes/plugin.php';
103 }
104
105 self::$plugins = get_plugins();
106
107 return self::$plugins;
108 }
109
110 /**
111 * Installed plugins indexed by TextDomain.
112 *
113 * @param bool $refresh When true, bust the plugins object cache first.
114 *
115 * @return array<string, array{file: string, version: string}>
116 */
117 public static function get_plugins_by_text_domain( bool $refresh = false ): array {
118 $normalized = [];
119
120 foreach ( self::get_plugins( $refresh ) as $plugin_file => $plugin_data ) {
121 $text_domain = $plugin_data['TextDomain'] ?? '';
122 if ( '' === $text_domain ) {
123 continue;
124 }
125
126 $normalized[ $text_domain ] = [
127 'file' => $plugin_file,
128 'version' => $plugin_data['Version'] ?? '0.0.1',
129 ];
130 }
131
132 return $normalized;
133 }
134
135 /**
136 * Resolve the installed bootstrap path for a catalog add-on.
137 *
138 * Falls back to TextDomain and plugin folder matching when the canonical path differs.
139 *
140 * @param string $addon_id Short add-on id.
141 *
142 * @return string|null Plugins-relative bootstrap path when installed, otherwise null.
143 */
144 public static function resolve_installed_plugin_file( string $addon_id ): ?string {
145 $addon_id = sanitize_key( $addon_id );
146 $file = self::plugin_file( $addon_id );
147 if ( null === $file ) {
148 return null;
149 }
150
151 $plugins = self::get_plugins();
152 if ( isset( $plugins[ $file ] ) ) {
153 return $file;
154 }
155
156 $text_domain = self::text_domain( $addon_id );
157 foreach ( $plugins as $plugin_file => $plugin_data ) {
158 if ( ( $plugin_data['TextDomain'] ?? '' ) === $text_domain ) {
159 return $plugin_file;
160 }
161 }
162
163 $folder = dirname( $file );
164 foreach ( array_keys( $plugins ) as $plugin_file ) {
165 if ( dirname( $plugin_file ) === $folder ) {
166 return $plugin_file;
167 }
168 }
169
170 return file_exists( WP_PLUGIN_DIR . '/' . $file ) ? $file : null;
171 }
172
173 /**
174 * Whether a catalog add-on is present on disk.
175 *
176 * @param string $addon_id Short add-on id.
177 *
178 * @return bool
179 */
180 public static function is_addon_on_disk( string $addon_id ): bool {
181 return null !== self::resolve_installed_plugin_file( $addon_id );
182 }
183
184 /**
185 * Installed paid add-ons with metadata for admin and license UIs.
186 *
187 * @return array<string, array{id: string, name: string, version: string, path: string, options_slug: string, uri: string}> TextDomain => add-on data.
188 */
189 public static function get_installed_addons(): array {
190 $installed = [];
191
192 foreach ( self::get_plugins() as $plugin_file => $plugin_data ) {
193 $text_domain = $plugin_data['TextDomain'] ?? '';
194 $addon_id = self::addon_id_for_text_domain( $text_domain );
195 if ( null === $addon_id ) {
196 continue;
197 }
198
199 $installed[ $text_domain ] = [
200 'id' => $addon_id,
201 'name' => str_replace( [ '', 'Advanced Ads ' ], '', $plugin_data['Name'] ),
202 'version' => $plugin_data['Version'] ?? '0.0.1',
203 'path' => $plugin_file,
204 'options_slug' => $text_domain,
205 'uri' => $plugin_data['PluginURI'] ?? 'https://wpadvancedads.com',
206 ];
207 }
208
209 return $installed;
210 }
211
212 /**
213 * Expected TextDomain for a catalog add-on id.
214 *
215 * @param string $addon_id Short add-on id.
216 *
217 * @return string
218 */
219 private static function text_domain( string $addon_id ): string {
220 return 'slider-ads' === $addon_id ? 'slider-ads' : 'advanced-ads-' . $addon_id;
221 }
222
223 /**
224 * Map an installed plugin TextDomain back to a catalog add-on id.
225 *
226 * @param string $text_domain Plugin TextDomain.
227 *
228 * @return string|null Short add-on id when recognized, otherwise null.
229 */
230 private static function addon_id_for_text_domain( string $text_domain ): ?string {
231 foreach ( self::PLUGIN_FILES as $addon_id => $file ) {
232 if ( self::text_domain( $addon_id ) === $text_domain ) {
233 return $addon_id;
234 }
235 }
236
237 return null;
238 }
239 }
240