PluginProbe ʕ •ᴥ•ʔ
Gallery : FooGallery / 3.1.36
Gallery : FooGallery v3.1.36
3.3.0 3.1.31 3.1.32 3.1.34 3.1.36 3.2.0 3.2.6 trunk 1.10.3 2.0.24 2.1.34 2.2.44 2.3.3 2.4.32 3.0.6 3.1.11 3.1.12 3.1.13 3.1.20 3.1.25 3.1.26 3.1.26.1 3.1.26.2
foogallery / includes / extensions / class-extensions-api.php
foogallery / includes / extensions Last commit date
class-extension.php 2 months ago class-extensions-api.php 2 months ago class-extensions-loader.php 2 months ago
class-extensions-api.php
670 lines
1 <?php
2 /**
3 * @TODO
4 */
5
6 if ( ! class_exists( 'FooGallery_Extensions_API' ) ) {
7
8 define( 'FOOGALLERY_EXTENSIONS_MESSAGE_TRANSIENT_KEY', 'foogallery_extensions_message' );
9 define( 'FOOGALLERY_EXTENSIONS_ACTIVATED_OPTIONS_KEY', 'foogallery_extensions_activated' );
10 define( 'FOOGALLERY_EXTENSIONS_ERRORS_OPTIONS_KEY', 'foogallery_extensions_errors' );
11 define( 'FOOGALLERY_EXTENSIONS_AUTO_ACTIVATED_OPTIONS_KEY', 'foogallery_extensions_auto_activated' );
12 define( 'FOOGALLERY_EXTENSIONS_OVERRIDES_OPTIONS_KEY', 'foogallery_extensions_overrides' );
13
14 /**
15 * FooGallery Extensions Manager Class
16 * Class FooGallery_Extensions_API
17 */
18 class FooGallery_Extensions_API {
19
20 /**
21 * Internal list of all extensions
22 * @var array
23 */
24 private $extensions = false;
25
26 /**
27 * Internal list of all extension slugs
28 * @var array
29 */
30 private $extension_slugs = false;
31
32 /**
33 * Extension API constructor
34 * @param bool $load
35 */
36 function __construct( $load = false ) {
37 if ( $load ) {
38 $this->load_available_extensions();
39 }
40 }
41
42 /**
43 * Reset all previous errors
44 */
45 public function reset_errors() {
46 //delete_option( FOOGALLERY_EXTENSIONS_LOADING_ERRORS );
47 //delete_option( FOOGALLERY_EXTENSIONS_LOADING_ERRORS_RESPONSE );
48 }
49
50 /**
51 * Load all available extensions
52 */
53 private function load_available_extensions() {
54 $this->extensions = array();
55
56 $this->extensions[] = array(
57 'slug' => 'albums',
58 'class' => 'FooGallery_Albums_Extension',
59 'title' => 'Albums',
60 'categories' => array( 'Featured', 'Free' ),
61 'description' => foogallery__( 'Group your galleries into albums. Albums comes with 2 unique album templates to showcase your galleries.', 'foogallery' ),
62 'external_link_text' => foogallery__( 'Read documentation', 'foogallery' ),
63 'external_link_url' => 'https://fooplugins.com/documentation/foogallery/getting-started-foogallery/adding-albums/',
64 'dashicon' => 'dashicons-book-alt',
65 'tags' => array( 'functionality', 'free', ),
66 'source' => 'bundled'
67 );
68
69 // The FooGallery Migrate feature.
70 $this->extensions[] = array(
71 'slug' => 'foogallery-migrate',
72 'class' => 'FooGallery_Migrate_Dummy',
73 'categories' => array( 'Free' ),
74 'title' => 'FooGallery Migrate',
75 'file' => 'migrate.php',
76 'description' => foogallery__( 'Migrate to FooGallery from other gallery plugins', 'foogallery' ),
77 'external_link_text' => foogallery__( 'Read about FooGallery Migrate', 'foogallery' ),
78 'external_link_url' => 'https://fooplugins.com/foogallery-migrate-for-wordpress-galleries/',
79 'dashicon' => 'dashicons-migrate',
80 'tags' => array( 'tools', 'free', ),
81 'source' => 'repo',
82 'download_link' => 'https://downloads.wordpress.org/plugin/foogallery-migrate.latest-stable.zip',
83 );
84 }
85
86 /**
87 * Get all loaded extensions
88 * @return array
89 */
90 function get_all() {
91
92 //check if we need to load
93 if ( false === $this->extensions ) {
94 $this->load_available_extensions();
95 }
96
97 //get any extra extensions from plugins
98 $extra_extensions = apply_filters( 'foogallery_available_extensions', array() );
99
100 if ( count( $extra_extensions ) > 0 ) {
101 //get a list of slugs so we can determine duplicates!
102 $this->extension_slugs = array();
103 foreach ( $this->extensions as $extension ) {
104 $this->extension_slugs[] = $extension['slug'];
105 }
106
107 //only add if not a duplicate
108 foreach ( $extra_extensions as $extension ) {
109 if ( ! in_array( $extension['slug'], $this->extension_slugs ) ) {
110 $this->extensions[] = $extension;
111 $this->extension_slugs[] = $extension['slug'];
112 }
113 }
114 }
115
116 return $this->extensions;
117 }
118
119
120 /**
121 * return a list of all extensions for the extension view.
122 * This list could be changed based on other plugin
123 */
124 function get_all_for_view() {
125 $extensions = array();
126
127 //add all extensions to an array using the slug as the array key
128 foreach ( $this->get_all() as &$extension ) {
129 $active = $this->is_active( $extension['slug'], true );
130 $extension['downloaded'] = $active || $this->is_downloaded( $extension );
131 $extension['is_active'] = $active;
132 $extension['has_errors'] = $this->has_errors( $extension['slug'] );
133
134 $extensions[ $extension['slug'] ] = $extension;
135 }
136
137 $extensions = apply_filters( 'foogallery_extensions_for_view', $extensions );
138
139 return $extensions;
140 }
141 /**
142 * Get all loaded extensions slugs
143 * @return array
144 */
145 function get_all_slugs() {
146 //load all extensions first!
147 $this->get_all();
148
149 return $this->extension_slugs;
150 }
151
152 /**
153 * @TODO
154 * @param $slug
155 *
156 * @return bool
157 */
158 public function get_extension( $slug ) {
159 foreach ( $this->get_all() as $extension ) {
160 if ( $extension['slug'] === $slug ) {
161 return $extension;
162 }
163 }
164 return false;
165 }
166
167 /**
168 * @TODO
169 * @param $file
170 *
171 * @return bool
172 */
173 public function get_extension_by_file( $file ) {
174 $file = basename( $file ); //normalize to just the filename
175
176 foreach ( $this->get_all() as $extension ) {
177 if ( foo_safe_get( $extension, 'file' ) === $file ) {
178 return $extension;
179 }
180 }
181 return false;
182 }
183
184 /**
185 * @TODO
186 * @param $slug
187 *
188 * @return bool
189 */
190 public function is_active( $slug ) {
191 $overrides = $this->get_overrides();
192 if ( array_key_exists( $slug, $overrides ) ) {
193 return $overrides[$slug] === 'active';
194 }
195
196 $active_extensions = $this->get_active_extensions();
197 if ( array_key_exists( $slug, $active_extensions ) ) {
198 //it has been previously activated through the extensions page
199 return true;
200 }
201
202 $extension = $this->get_extension( $slug );
203
204 //if we have an 'plugin_active_class' attribute and that class exists, it means our plugin must be active
205 if ( isset( $extension['plugin_active_class'] ) ) {
206 if ( class_exists( $extension['plugin_active_class'] ) ) {
207 return true;
208 }
209 }
210
211 //if we have an 'activated_by_default' attribute and it is true, it means the extension is active
212 if ( isset( $extension['activated_by_default'] ) && $extension['activated_by_default'] ) {
213 return true;
214 }
215
216 //if we cannot find the extension class in memory, then check to see if the extension plugin is activated
217 if ( isset( $extension['perform_plugin_active_check'] ) && true === $extension['perform_plugin_active_check'] &&
218 isset( $extension['file'] ) ) {
219 $plugin = $this->find_active_wordpress_plugin( $extension );
220
221 return $plugin !== false;
222 }
223
224 return false;
225 }
226
227 /**
228 * @TODO
229 *
230 * @param bool $extension
231 *
232 * @param bool $slug
233 *
234 * @return bool
235 */
236 public function is_downloaded( $extension = false, $slug = false ) {
237 //allow you to pass in a slug rather
238 if ( ! $extension && $slug !== false ) {
239 $extension = $this->get_extension( $slug );
240 }
241 if ( $extension ) {
242 //first check if the class exists
243 if ( class_exists( $extension['class'] ) ) {
244 return true;
245 }
246
247 //next fallback to see if a plugin exists that has the same file name
248 $plugin = $this->find_wordpress_plugin( $extension );
249 return false !== $plugin;
250 }
251 return false;
252 }
253
254 /**
255 * @TODO
256 * @param $slug
257 *
258 * @return bool
259 */
260 public function has_errors( $slug ) {
261 $error_extensions = $this->get_error_extensions();
262
263 if ( $error_extensions ) {
264 return array_key_exists( $slug, $error_extensions );
265 }
266 return false;
267 }
268
269 /**
270 * @TODO
271 * @param $plugin
272 */
273 public function handle_wordpress_plugin_deactivation( $plugin ) {
274 $extension = $this->get_extension_by_file( $plugin );
275 if ( $extension ) {
276 //we have found a matching extension
277 $this->deactivate( $extension['slug'], false );
278 }
279 }
280
281 /**
282 * @TODO
283 * @param $plugin
284 */
285 public function handle_wordpress_plugin_activation( $plugin ) {
286 $extension = $this->get_extension_by_file( $plugin );
287 if ( $extension ) {
288 //we have found a matching extension
289 $this->activate( $extension['slug'], false );
290 }
291 }
292
293 /**
294 * @TODO
295 * @param $slug
296 * @param bool $deactivate_wordpress_plugin
297 * @param bool $error_loading
298 *
299 * @return array|mixed|void
300 */
301 public function deactivate( $slug, $deactivate_wordpress_plugin = true, $error_loading = false ) {
302 $extension = $this->get_extension( $slug );
303 if ( $extension ) {
304 if ( $deactivate_wordpress_plugin && 'bundled' !== foo_safe_get( $extension, 'source', false ) ) {
305 $plugin = $this->find_wordpress_plugin( $extension );
306 if ( $plugin ) {
307 $failure = deactivate_plugins( $plugin['file'], true, false );
308 if ( null !== $failure ) {
309 return array(
310 'message' => sprintf( __( 'The feature %s could NOT be deactivated!', 'foogallery' ), "<strong>{$extension['title']}</strong>" ),
311 'type' => 'error'
312 );
313 }
314 }
315 }
316
317 $active_extensions = $this->get_active_extensions();
318 if ( array_key_exists( $slug, $active_extensions ) ) {
319 unset( $active_extensions[ $slug ] );
320 if ( empty($active_extensions) ) {
321 delete_option( FOOGALLERY_EXTENSIONS_ACTIVATED_OPTIONS_KEY );
322 } else {
323 update_option( FOOGALLERY_EXTENSIONS_ACTIVATED_OPTIONS_KEY, $active_extensions );
324 }
325 }
326
327 $this->set_override( $slug, 'deactivated' );
328
329 if ( $error_loading ) {
330 $this->add_to_error_extensions( $slug );
331 }
332
333 //we are done, allow for extensions to do something after an extension is activated
334 do_action( 'foogallery_extension_deactivated-' . $slug );
335
336 return apply_filters( 'foogallery_extensions_deactivated_message-' . $slug, array(
337 'message' => sprintf( __( 'The feature %s was successfully deactivated', 'foogallery' ), "<strong>{$extension['title']}</strong>" ),
338 'type' => 'success',
339 ) );
340 }
341 return array(
342 'message' => sprintf( __( 'Unknown feature : %s', 'foogallery' ), $slug ),
343 'type' => 'error',
344 );
345 }
346
347 private function set_override( $slug, $status ) {
348 $overrides = $this->get_overrides();
349 $overrides[$slug] = $status;
350 update_option( FOOGALLERY_EXTENSIONS_OVERRIDES_OPTIONS_KEY, $overrides );
351 }
352
353 /**
354 * @TODO
355 *
356 * @param $slug
357 * @param bool $activate_wordpress_plugin
358 *
359 * @return array|mixed|void
360 */
361 public function activate( $slug, $activate_wordpress_plugin = true ) {
362 $extension = $this->get_extension( $slug );
363 if ( $extension ) {
364 //first remove it from our error list (if it was there before)
365 $this->remove_from_error_extensions( $slug );
366
367 if ( $activate_wordpress_plugin && 'bundled' !== foo_safe_get( $extension, 'source', false ) ) {
368 //activate the plugin, WordPress style!
369 $plugin = $this->find_wordpress_plugin( $extension );
370
371 if ( $plugin ) {
372
373 //check min version
374 $minimum_version = foo_safe_get( $extension, 'minimum_version' );
375 if ( !empty($minimum_version) ) {
376 $actual_version = $plugin['plugin']['Version'];
377 if ( version_compare( $actual_version, $minimum_version ) < 0 ) {
378 $this->add_to_error_extensions( $slug, sprintf( __( 'Requires %s version %s','foogallery' ), $extension['title'], $minimum_version ) );
379 return array(
380 'message' => sprintf( __( 'The feature %s could not be activated, because you are using an outdated version! Please update %s to at least version %s.', 'foogallery' ), $extension['title'], $extension['title'], $minimum_version ),
381 'type' => 'error',
382 );
383 }
384 }
385
386 //try to activate the plugin
387 $failure = activate_plugin( $plugin['file'], '', false, false );
388 if ( null !== $failure ) {
389 return array(
390 'message' => sprintf( __( 'The feature %s could NOT be activated!', 'foogallery' ), "<strong>{$extension['title']}</strong>" ),
391 'type' => 'error',
392 );
393 }
394 }
395 }
396 //load an instance of the extension class into memory
397 $loader = new FooGallery_Extensions_Loader();
398 $loader->load_extension( $slug, foo_safe_get( $extension, 'class', false ) );
399
400 //then add the extension to our saved option so that it can be loaded on startup
401 $this->add_to_activated_extensions( $extension );
402
403 $this->set_override( $slug, 'active' );
404
405 //we are done, allow for extensions to do something after an extension is activated
406 do_action( 'foogallery_extension_activated-' . $slug );
407
408 //return our result
409 return apply_filters( 'foogallery_extension_activated_message-' . $slug, array(
410 'message' => sprintf( __( 'The feature %s was successfully activated', 'foogallery' ), "<strong>{$extension['title']}</strong>" ),
411 'type' => 'success',
412 ) );
413 }
414 return array(
415 'message' => sprintf( __( 'Unknown feature : %s', 'foogallery' ), $slug ),
416 'type' => 'error',
417 );
418 }
419
420 /**
421 * @TODO
422 * @param boolean $extension
423 *
424 * @return array|bool
425 */
426 private function find_wordpress_plugin( $extension ) {
427 $plugins = get_plugins();
428 foreach ( $plugins as $plugin_file => $plugin ) {
429 if ( isset($extension['file']) && foo_ends_with( $plugin_file, $extension['file'] ) ) {
430 return array(
431 'file' => $plugin_file,
432 'plugin' => $plugin,
433 'active' => is_plugin_active( $plugin_file ),
434 );
435 }
436 }
437 return false;
438 }
439
440 /**
441 * @TODO
442 * @param boolean $extension
443 *
444 * @return array|bool
445 */
446 private function find_active_wordpress_plugin( $extension ) {
447 $plugins = get_plugins();
448 foreach ( $plugins as $plugin_file => $plugin ) {
449 if ( is_plugin_active( $plugin_file ) && isset($extension['file']) && foo_ends_with( $plugin_file, $extension['file'] ) ) {
450 return array(
451 'file' => $plugin_file,
452 'plugin' => $plugin
453 );
454 }
455 }
456 return false;
457 }
458
459 /**
460 * @TODO
461 * @param $slug
462 *
463 * @return array|mixed|void
464 */
465 public function download( $slug ) {
466 $extension = $this->get_extension( $slug );
467 if ( $extension ) {
468
469 //we need some files!
470 require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; // plugins_api calls
471 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; // Plugin_Upgrader class
472 require_once FOOGALLERY_PATH . 'includes/admin/class-silent-installer-skin.php'; //our silent installer skin
473
474 $download_link = isset( $extension['download_link'] ) ? $extension['download_link'] : false;
475
476 if ( 'repo' === $extension['source'] ) {
477 $plugins_api = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false ) ) );
478
479 if ( is_wp_error( $plugins_api ) ) {
480 return array(
481 'message' => sprintf( __( 'Unable to connect to the WordPress.org plugin API to download %s. Full error log: %s', 'foogallery' ), $slug, '<br />' . var_export( $plugins_api, true ) ),
482 'type' => 'error',
483 );
484 }
485
486 //get the download link from the API call
487 if ( isset( $plugins_api->download_link ) ) {
488 $download_link = $plugins_api->download_link;
489 }
490 }
491
492 //check we have something to download
493 if ( empty( $download_link ) ) {
494 return array(
495 'message' => sprintf( __( 'The feature %s has no download link!', 'foogallery' ), $slug ),
496 'type' => 'error',
497 );
498 }
499
500 $skin = new FooGallery_Silent_Installer_Skin();
501
502 //instantiate Plugin_Upgrader
503 $upgrader = new Plugin_Upgrader( $skin );
504
505 $upgrader->install( $download_link );
506
507 if ( 'process_failed' === $skin->feedback ) {
508 $error_message = is_wp_error( $skin->result ) ? $skin->result->get_error_message() : __( 'Unknown!', 'foogallery' );
509
510 //save the error message for the extension
511 $this->add_to_error_extensions( $slug, sprintf( __('Could not be downloaded! Error : %s', 'foogallery' ), $error_message ) );
512
513 //we had an error along the way
514 return apply_filters( 'foogallery_extensions_download_failure-' . $slug, array(
515 'message' => sprintf( __( 'The feature %s could NOT be downloaded! Error : %s', 'foogallery' ), "<strong>{$extension['title']}</strong>", $error_message ),
516 'type' => 'error'
517 ) );
518 }
519
520 //return our result
521 return apply_filters( 'foogallery_extensions_download_success-' . $slug, array(
522 'message' => sprintf( __( 'The feature %s was successfully downloaded and can now be activated. %s', 'foogallery' ),
523 "<strong>{$extension['title']}</strong>",
524 '<a href="' . esc_url( add_query_arg( array(
525 'action' => 'activate',
526 'extension' => $slug, ) ) ) . '">' . __( 'Activate immediately', 'foogallery' ) . '</a>'
527 ),
528 'type' => 'success',
529 ) );
530 }
531 return array(
532 'message' => sprintf( __( 'Unknown feature : %s', 'foogallery' ), $slug ),
533 'type' => 'error',
534 );
535 }
536
537 /**
538 * @TODO
539 * @return mixed|void
540 */
541 public function get_active_extensions() {
542 return get_option( FOOGALLERY_EXTENSIONS_ACTIVATED_OPTIONS_KEY, array() );
543 }
544
545 /**
546 * Return extensions that should be loaded on startup.
547 *
548 * This mirrors is_active() so explicit active/deactivated overrides and
549 * default/plugin-backed extensions cannot drift from the runtime loader.
550 *
551 * @return array<string,string>
552 */
553 public function get_loadable_extensions() {
554 $loadable_extensions = $this->get_active_extensions();
555 if ( ! is_array( $loadable_extensions ) ) {
556 $loadable_extensions = array();
557 }
558
559 $overrides = $this->get_overrides();
560 if ( ! is_array( $overrides ) ) {
561 $overrides = array();
562 }
563
564 foreach ( $overrides as $slug => $status ) {
565 if ( 'deactivated' === $status ) {
566 unset( $loadable_extensions[ $slug ] );
567 }
568 }
569
570 foreach ( $this->get_all() as $extension ) {
571 $slug = foo_safe_get( $extension, 'slug' );
572 $class = foo_safe_get( $extension, 'class' );
573
574 if ( empty( $slug ) || empty( $class ) ) {
575 continue;
576 }
577
578 if ( $this->is_active( $slug ) && $this->is_downloaded( $extension ) ) {
579 $loadable_extensions[ $slug ] = $class;
580 }
581 }
582
583 return $loadable_extensions;
584 }
585
586 /**
587 * Returns the extension overrides.
588 * @return mixed|void
589 */
590 public function get_overrides() {
591 return get_option( FOOGALLERY_EXTENSIONS_OVERRIDES_OPTIONS_KEY, array() );
592 }
593
594 /**
595 * @TODO
596 * @return mixed|void
597 */
598 public function get_error_extensions() {
599 return get_option( FOOGALLERY_EXTENSIONS_ERRORS_OPTIONS_KEY, array() );
600 }
601
602 public function get_error_message( $slug ) {
603 $error_extensions = $this->get_error_extensions();
604 if ( array_key_exists( $slug, $error_extensions ) ) {
605 return $error_extensions[ $slug ];
606 }
607 return '';
608 }
609
610 /**
611 * @TODO
612 * @param $extension
613 */
614 private function add_to_activated_extensions( $extension ) {
615 $slug = $extension['slug'];
616 $active_extensions = $this->get_active_extensions();
617 if ( !array_key_exists( $slug, $active_extensions ) ) {
618 $active_extensions[ $slug ] = $extension['class'];
619 update_option( FOOGALLERY_EXTENSIONS_ACTIVATED_OPTIONS_KEY, $active_extensions );
620 }
621 }
622
623 /**
624 * @TODO
625 * @param $slug
626 */
627 public function add_to_error_extensions( $slug, $error_message = '' ) {
628 $error_extensions = $this->get_error_extensions();
629
630 if ( empty($error_message) ) {
631 $error_message = __( 'Error loading feature!', 'foogallery' );
632 }
633
634 if ( array_key_exists( $slug, $error_extensions ) &&
635 $error_message === $error_extensions[$slug]) {
636 //do nothing!
637 } else {
638 $error_extensions[$slug] = $error_message;
639 update_option( FOOGALLERY_EXTENSIONS_ERRORS_OPTIONS_KEY, $error_extensions );
640 }
641 }
642
643 /**
644 * @TODO
645 * @param $slug
646 */
647 private function remove_from_error_extensions( $slug ) {
648 $error_extensions = $this->get_error_extensions();
649 if ( array_key_exists( $slug, $error_extensions ) ) {
650 unset( $error_extensions[ $slug ] );
651 update_option( FOOGALLERY_EXTENSIONS_ERRORS_OPTIONS_KEY, $error_extensions );
652 }
653 }
654
655 /**
656 * @TODO
657 */
658 public function auto_activate_extensions() {
659 foreach ( $this->get_all() as $extension ) {
660 if ( true === foo_safe_get( $extension, 'activated_by_default' ) ) {
661 //check to see if the extension is downloaded
662 if ( $this->is_downloaded( $extension ) ) {
663 $this->add_to_activated_extensions( $extension );
664 }
665 }
666 }
667 }
668 }
669 }
670