PluginProbe ʕ •ᴥ•ʔ
WPML Multilingual & Multicurrency for WooCommerce / 5.5.7
WPML Multilingual & Multicurrency for WooCommerce v5.5.7
5.5.7 5.3.8 5.3.9 5.4.3 5.4.4 5.4.5 5.5.1 5.5.1.1 5.5.2.2 5.5.2.3 5.5.3 5.5.3.1 5.5.4 5.5.5 5.5.6 trunk 0.9 1.0 1.1 1.2 1.3 1.4 1.5 2.0 2.2 2.3 2.3.1 2.3.2 3.0 3.0.1 3.1 3.2 3.2.1 3.2.2 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.4 3.4.1 3.4.2 3.4.3 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.6 3.6.1 3.6.10 3.6.11 3.6.2 3.6.3 3.6.4 3.6.5 3.6.5.1 3.6.6 3.6.7 3.6.8 3.6.9 3.7 3.7.1 3.7.10 3.7.11 3.7.12 3.7.13 3.7.14 3.7.15 3.7.16 3.7.2 3.7.3 3.7.4 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.9.0 3.9.1 3.9.1.1 3.9.2 3.9.3 3.9.4 3.9.5 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10.0 4.10.1 4.10.2 4.10.3 4.10.4 4.11.2 4.11.3.2 4.11.5 4.11.6 4.12.1 4.12.4 4.12.5 4.12.6 4.2.0 4.2.0.1 4.2.1 4.2.1.1 4.2.10 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.7.1 4.2.8 4.2.8.1 4.2.9 4.3.0 4.3.1 4.3.2 4.3.2.1 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.4.0 4.4.1 4.4.2 4.4.2.1 4.5.0 4.6.0 4.6.1 4.6.2 4.6.2.1 4.6.3 4.6.5 4.6.6 4.6.7 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.7.6 4.7.7 4.7.8 4.7.9 4.8.0 4.9.0 4.9.1 5.0.1 5.0.2 5.1.1 5.1.2 5.1.3 5.2.0 5.2.1 5.3.2 5.3.3.1 5.3.4 5.3.5 5.3.6 5.3.7
woocommerce-multilingual / vendor / otgs / installer / src / Recommendations / RecommendationsManager.php
woocommerce-multilingual / vendor / otgs / installer / src / Recommendations Last commit date
GluePluginData.php 1 month ago RecommendationsForInstallerPlugins.php 1 month ago RecommendationsManager.php 1 month ago Storage.php 1 month ago
RecommendationsManager.php
439 lines
1 <?php
2
3 namespace OTGS\Installer\Recommendations;
4
5 use OTGS_Installer_Subscription;
6 use WP_Installer;
7
8 class RecommendationsManager {
9 private $repositories;
10
11 private $settings;
12
13 private $repositoriesForRecommendation = [ 'wpml' ];
14
15 private $noticesStorage;
16
17 public function __construct( \OTGS_Installer_Repositories $repositories, Storage $noticesStorage ) {
18 $this->repositories = $repositories;
19 $this->noticesStorage = $noticesStorage;
20 }
21
22 private function settings() {
23 if ( $this->settings === null ) {
24 $this->settings = WP_Installer::instance()->get_settings()['repositories'];
25 }
26 return $this->settings;
27 }
28
29 public function addHooks() {
30 add_action( 'deactivated_plugin', [ $this, 'deactivatedPluginRecommendation' ] );
31 add_action( 'wp_ajax_installer_recommendation_success', [ $this, 'recommendationSuccess' ] );
32 add_action( 'current_screen', [ $this, 'checkAllInstalledPluginsForRecommendations' ] );
33
34 add_filter( 'wpml_installer_get_stored_recommendation_notices', [ $this, 'getRecommendationNotices' ] );
35 }
36
37
38
39 public function checkAllInstalledPluginsForRecommendations( $screen = null ) {
40 if ( ! $screen || $screen->id !== 'plugins' ) {
41 return;
42 }
43
44 $installedPlugins = $this->getInstalledPlugins();
45
46 foreach ( $installedPlugins as $pluginSlug => $pluginData ) {
47 if ( ! $pluginData['is_active'] ) {
48 continue;
49 }
50
51 $pluginInfo = $this->getPluginData( $pluginSlug . '/plugin.php' );
52 $gluePluginData = $pluginInfo->getGluePluginData();
53
54 if ( $gluePluginData
55 && ! $this->isGluePluginActive( $gluePluginData['glue_plugin_slug'] )
56 && $this->noticesStorage->missing( $pluginSlug, $gluePluginData['repository_id'] )
57 ) {
58 $this->noticesStorage->save($pluginSlug, $gluePluginData );
59 }
60 }
61 }
62
63 private function isGluePluginActive( $gluePluginSlug ) {
64 $pluginData = isset( $this->getInstalledPlugins()[ $gluePluginSlug ] ) ? $this->getInstalledPlugins()[ $gluePluginSlug ] : null;
65
66 return $pluginData && $pluginData['is_active'];
67 }
68
69 public function deactivatedPluginRecommendation( $plugin ) {
70 $deactivatedPlugin = $this->getPluginData( $plugin );
71 $gluePluginData = $deactivatedPlugin->getGluePluginData();
72 if ( $gluePluginData ) {
73 $this->noticesStorage->delete( $deactivatedPlugin->getPluginSlug(), $gluePluginData['repository_id'] );
74 }
75 }
76
77 public function recommendationSuccess() {
78 if ( array_key_exists( 'nonce', $_POST )
79 && array_key_exists( 'pluginData', $_POST )
80 && wp_verify_nonce( $_POST['nonce'], 'recommendation_success_nonce' ) ) {
81 $data = json_decode( base64_decode( sanitize_text_field( $_POST['pluginData'] ) ), true );
82 $this->noticesStorage->delete( $data['slug'], $data['repository_id'] );
83 }
84
85 }
86
87 private function getActivatedPluginGlue( $activatedPluginSlug ) {
88 $language = $this->getCurrentLanguage();
89
90 foreach ( $this->repositoriesForRecommendation as $repositoryId ) {
91 $downloads = isset( $this->settings()[ $repositoryId ]['data']['downloads']['plugins'] )
92 ? $this->settings()[ $repositoryId ]['data']['downloads']['plugins'] : [];
93 foreach ( $downloads as $pluginData ) {
94 $gluePluginSlug = isset( $pluginData['glue_check_slug'] ) ? $pluginData['glue_check_slug'] : false;
95 if ( $gluePluginSlug && $activatedPluginSlug === $pluginData['glue_check_slug'] ) {
96
97 return $this->prepareRecommendedPluginData( $repositoryId, $pluginData, $language );
98
99 }
100 }
101 }
102
103 return null;
104 }
105
106 private function getGluePluginData( $gluePluginSlug, $mappingData ) {
107
108 $language = $this->getCurrentLanguage();
109
110 foreach ( $this->repositoriesForRecommendation as $repositoryId ) {
111 $downloads = isset( $this->settings()[ $repositoryId ]['data']['downloads']['plugins'] )
112 ? $this->settings()[ $repositoryId ]['data']['downloads']['plugins'] : [];
113 if ( isset( $downloads[ $gluePluginSlug ] ) ) {
114 $pluginData = $downloads[ $gluePluginSlug ];
115
116 return $this->prepareRecommendedPluginData( $repositoryId, $pluginData, $language, $mappingData );
117 }
118 }
119
120 return null;
121 }
122
123 private function getNotificationForLanguage( $pluginData, $language ) {
124 $default = isset( $pluginData['recommendation_notification']['en'] ) ? $pluginData['recommendation_notification']['en'] : '';
125
126 return isset( $pluginData['recommendation_notification'][ $language ] )
127 ? $pluginData['recommendation_notification'][ $language ]
128 : $default;
129 }
130
131 public function getRepositoryPluginsRecommendations() {
132 $pluginsRecommendations = [];
133 $pluginsData = [];
134 $language = $this->getCurrentLanguage();
135
136 foreach ( $this->repositoriesForRecommendation as $repositoryId ) {
137 $repository = $this->repositories->get( $repositoryId );
138
139 if ( $this->settings()[ $repositoryId ]['data']['downloads']['plugins']
140 && $this->settings()[ $repositoryId ]['data']['recommendation_sections'] ) {
141 $downloads = $this->settings()[ $repositoryId ]['data']['downloads']['plugins'];
142 $sections = $this->settings()[ $repositoryId ]['data']['recommendation_sections'];
143 } else {
144 continue;
145 }
146
147 $subscription = $repository->get_subscription();
148 if ( ! $subscription ) {
149 continue;
150 }
151
152 $available_plugins_list = $this->getAvailablePluginsForSubscription( $repository );
153 $installedPlugins = $this->getInstalledPlugins();
154
155 foreach ( $downloads as $pluginData ) {
156 if ( $pluginData['recommended']
157 && in_array( $pluginData['slug'], $available_plugins_list, true )
158 && $this->shouldBeDisplayed( $pluginData )
159 ) {
160 $isInstalled = isset( $installedPlugins[ $pluginData['slug'] ] );
161 $isActive = $isInstalled && $installedPlugins[ $pluginData['slug'] ]['is_active'];
162
163 if ( ! $isInstalled || ! $isActive ) {
164 $recommendation = $this->preparePluginData(
165 $language,
166 $pluginData,
167 $subscription->get_site_key(),
168 $repositoryId,
169 $subscription->get_site_url(),
170 $isInstalled,
171 $isActive
172 );
173
174 $sectionPlugin = $this->prepareSectionPlugin(
175 $language,
176 $pluginData,
177 $isInstalled,
178 $isActive
179 );
180
181 if (
182 array_key_exists( 'download_recommendation_section', $pluginData ) &&
183 is_string( $pluginData['download_recommendation_section']) && !empty( $pluginData['download_recommendation_section'] )
184 ) {
185 $pluginsRecommendations[ $pluginData['download_recommendation_section'] ]['plugins'][ $pluginData['slug'] ] = $sectionPlugin;
186 $pluginsData[ $pluginData['slug'] ] = $recommendation;
187 }
188 }
189 }
190 }
191
192 $recommendationsForInstallerPlugins = $this->prepareRecommendationsForInstalledPlugins( $repositoryId, $subscription, $downloads, $installedPlugins, $pluginsRecommendations, $pluginsData );
193 $pluginsData = $recommendationsForInstallerPlugins->getPluginsData();
194
195 $pluginsRecommendations = $recommendationsForInstallerPlugins->getRecommendations();
196
197 foreach ( $recommendationsForInstallerPlugins->getRecommendations() as $section => $plugins_recommendation ) {
198 $pluginsRecommendations[ $section ]['title'] = $sections[ $section ][ $language ]['name'] ?? $sections[ $section ]['en']['name'] ?? '';
199 $pluginsRecommendations[ $section ]['order'] = $sections[ $section ][ $language ]['order'] ?? $sections[ $section ]['en']['order'] ?? '';
200
201 }
202 }
203
204 uasort( $pluginsRecommendations, function ( $a, $b ) {
205 return (int) $a['order'] - (int) $b['order'];
206 } );
207
208 return [ 'sections' => $pluginsRecommendations, 'plugins' => $pluginsData ];
209 }
210
211 private function prepareRecommendationsForInstalledPlugins( $repositoryId, OTGS_Installer_Subscription $subscription, $downloads, $installedPlugins, $pluginsRecommendations, $pluginsData ) {
212 $language = $this->getCurrentLanguage();
213
214 if ( isset($this->settings()[ $repositoryId ]['data']['glue_plugins_mapping']) ) {
215 $gluePluginsMapping = $this->settings()[ $repositoryId ]['data']['glue_plugins_mapping'];
216 } else {
217 return new RecommendationsForInstallerPlugins( $pluginsRecommendations, $pluginsData );
218 }
219
220 foreach ( $installedPlugins as $pluginSlug => $pluginData ) {
221 if(isset($pluginData['is_active']) && !$pluginData['is_active']) {
222 continue;
223 }
224
225 if ( isset( $gluePluginsMapping[ $pluginSlug ] ) ) {
226 $gluePluginSlug = $gluePluginsMapping[ $pluginSlug ]['glue_plugin'];
227 $gluePluginData = $this->getGluePluginData( $gluePluginSlug, $gluePluginsMapping[ $pluginSlug ] );
228
229 if ( $gluePluginData ) {
230 $isGlueInstalled = isset( $installedPlugins[ $gluePluginSlug ] );
231 $isGlueActive = $isGlueInstalled && $installedPlugins[ $gluePluginSlug ]['is_active'];
232
233 if ( ! $isGlueInstalled || ! $isGlueActive ) {
234 $recommendation = $this->preparePluginData(
235 $language,
236 $downloads[ $gluePluginSlug ],
237 $subscription->get_site_key(),
238 $repositoryId,
239 $subscription->get_site_url(),
240 $isGlueInstalled,
241 $isGlueActive
242 );
243
244 $sectionPlugin = $this->prepareSectionPlugin(
245 $language,
246 $downloads[ $gluePluginSlug ],
247 $isGlueInstalled,
248 $isGlueActive
249 );
250
251 if ( $downloads[ $gluePluginSlug ] ) {
252 $pluginsRecommendations[ $downloads[ $gluePluginSlug ]['download_recommendation_section'] ]['plugins'][ $gluePluginSlug ] = $sectionPlugin;
253 $pluginsData[ $gluePluginSlug ] = $recommendation;
254 }
255 }
256 }
257 }
258 }
259
260 return new RecommendationsForInstallerPlugins( $pluginsRecommendations, $pluginsData );
261 }
262
263 private function getCurrentLanguage() {
264 global $sitepress;
265
266 return $sitepress ? $sitepress->get_admin_language() : 'en';
267 }
268
269 private function getAvailablePluginsForSubscription( \OTGS_Installer_Repository $repository ) {
270 $product = $repository->get_product_by_subscription_type();
271 if ( ! $product ) {
272 $product = $repository->get_product_by_subscription_type_equivalent();
273 }
274
275 return $product->get_plugins();
276 }
277
278 private function getInstalledPlugins() {
279 $installed_plugins = [];
280
281 foreach ( get_plugins() as $plugin_id => $plugin_data ) {
282 $installed_plugins[ dirname( $plugin_id ) ] = [
283 'is_active' => is_plugin_active( $plugin_id ),
284 ];
285 }
286
287 return $installed_plugins;
288 }
289
290 private function preparePluginData( $language, $pluginData, $siteKey, $repositoryId, $siteUrl, $isInstalled, $isActive ) {
291 $url = $this->appendSiteKeyToDownloadUrl( $pluginData['url'], $siteKey, $siteUrl );
292
293 $downloadData = [
294 'url' => $url,
295 'slug' => $pluginData['slug'],
296 'nonce' => wp_create_nonce( 'install_plugin_' . $url ),
297 'repository_id' => $repositoryId,
298 ];
299
300 return [
301 'name' => $pluginData['name'],
302 'short_description' => isset( $pluginData['short_description'][ $language ] ) ? $pluginData['short_description'][ $language ] : '',
303 'is_installed' => $isInstalled,
304 'is_active' => $isActive,
305 'slug' => $pluginData['slug'],
306 'recommendation_icon_url' => isset( $pluginData['recommendation_icon_url'] ) ? $pluginData['recommendation_icon_url'] : '',
307 'download_data' => base64_encode( (string) json_encode( $downloadData ) ),
308 ];
309 }
310
311 private function prepareSectionPlugin( $language, $pluginData, $isInstalled, $isActive ) {
312 return [
313 'name' => $pluginData['name'],
314 'is_installed' => $isInstalled,
315 'is_active' => $isActive,
316 'slug' => $pluginData['slug'],
317 'short_description' => isset( $pluginData['short_description'][ $language ] ) ? $pluginData['short_description'][ $language ] : '',
318 'recommendation_icon_url' => isset( $pluginData['recommendation_icon_url'] ) ? $pluginData['recommendation_icon_url'] : '',
319 ];
320 }
321
322 private function shouldBeDisplayed( $pluginData ) {
323 $glueCheckType = isset( $pluginData['glue_check_type'] ) ? $pluginData['glue_check_type'] : null;
324 $glueCheckValue = isset( $pluginData['glue_check_value'] ) ? $pluginData['glue_check_value'] : null;
325
326 if ( $glueCheckType && $glueCheckValue ) {
327 switch ( $glueCheckType ) {
328 case 'class':
329 return class_exists( $glueCheckValue );
330 case 'constant':
331 return defined( $glueCheckValue );
332 case 'function':
333 return function_exists( $glueCheckValue );
334 default:
335 return false;
336 }
337 }
338
339 if ( $pluginData['slug'] === 'wpml-translation-management' ) {
340 return false;
341 }
342
343 return true;
344 }
345
346 private function appendSiteKeyToDownloadUrl( $url, $siteKey, $siteUrl ) {
347 return add_query_arg(
348 [
349 'site_key' => $siteKey,
350 'site_url' => $siteUrl,
351 ],
352 $url
353 );
354 }
355
356 public function getRecommendationNotices( $existingNotices ) {
357 $notices = [];
358
359 foreach ( Storage::getAll() as $repositoryId => $recommendations ) {
360 $repository = $this->repositories->get( $repositoryId );
361
362 $subscription = $repository->get_subscription();
363 if ( ! $subscription ) {
364 continue;
365 }
366
367 foreach ( $recommendations as $recommendationSlug => $recommendation ) {
368 if ( isset( $recommendation['notice_dismissed'] ) && $recommendation['notice_dismissed'] === true ) {
369 continue;
370 }
371
372 if ( ! $this->isGluePluginActive( $recommendation['glue_plugin_slug'] ) ) {
373 $url = $this->appendSiteKeyToDownloadUrl( $recommendation['download_data']['url'], $subscription->get_site_key(), $subscription->get_site_url() );
374
375 $appendedDownloadData = [
376 'url' => $url,
377 'slug' => $recommendation['download_data']['slug'],
378 'repository_id' => $recommendation['download_data']['repository_id'],
379 'nonce' => wp_create_nonce( 'install_plugin_' . $url ),
380 ];
381
382 $notices[ $repositoryId ][ $recommendationSlug ] = $recommendation;
383 $notices[ $repositoryId ][ $recommendationSlug ]['download_data'] = $appendedDownloadData;
384 } else {
385 Storage::delete( $recommendationSlug, $repositoryId );
386 }
387 }
388 }
389
390 return array_merge( $existingNotices, $notices );
391 }
392
393 private function getPluginData( $plugin ) {
394 $pluginSlug = dirname( $plugin );
395 $gluePluginData = $this->getActivatedPluginGlue( $pluginSlug );
396
397 if ( ! $gluePluginData ) {
398 foreach ( $this->repositoriesForRecommendation as $repositoryId ) {
399 if ( isset( $this->settings()[ $repositoryId ]['data']['glue_plugins_mapping'] ) ) {
400 $gluePluginsMapping = $this->settings()[ $repositoryId ]['data']['glue_plugins_mapping'];
401
402 if ( isset( $gluePluginsMapping[ $pluginSlug ] ) ) {
403 $gluePluginSlug = $gluePluginsMapping[ $pluginSlug ]['glue_plugin'];
404 $gluePluginData = $this->getGluePluginData( $gluePluginSlug, $gluePluginsMapping[ $pluginSlug ] );
405 }
406 }
407 }
408
409 }
410
411 return new GluePluginData( $pluginSlug, $gluePluginData );
412 }
413
414 private function prepareRecommendedPluginData( $repositoryId, $pluginData, $language, $mappingData = null ) {
415 $repository = $this->repositories->get( $repositoryId );
416 $subscription = $repository->get_subscription();
417 if ( ! $subscription ) {
418 return null;
419 }
420
421 $downloadData = [
422 'url' => $pluginData['url'],
423 'slug' => $pluginData['slug'],
424 'repository_id' => $repositoryId,
425 ];
426
427
428 return [
429 'repository_id' => $repositoryId,
430 'glue_check_slug' => $mappingData ? $mappingData['glue_check_slug'] : $pluginData['glue_check_slug'],
431 'glue_check_name' => $mappingData ? $mappingData['glue_check_name'] : $pluginData['glue_check_name'],
432 'glue_plugin_name' => $pluginData['name'],
433 'glue_plugin_slug' => $pluginData['slug'],
434 'recommendation_notification' => $this->getNotificationForLanguage( $mappingData ?: $pluginData, $language ),
435 'download_data' => $downloadData,
436 ];
437 }
438 }
439