PluginProbe ʕ •ᴥ•ʔ
Photo Gallery by FooGallery : Responsive Image Gallery, Masonry Gallery & Carousel / trunk
Photo Gallery by FooGallery : Responsive Image Gallery, Masonry Gallery & Carousel vtrunk
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 7 months ago class-extensions-api.php 7 months ago class-extensions-loader.php 7 months ago
class-extensions-api.php
628 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 }
112 }
113 }
114
115 return $this->extensions;
116 }
117
118
119 /**
120 * return a list of all extensions for the extension view.
121 * This list could be changed based on other plugin
122 */
123 function get_all_for_view() {
124 $extensions = array();
125
126 //add all extensions to an array using the slug as the array key
127 foreach ( $this->get_all() as &$extension ) {
128 $active = $this->is_active( $extension['slug'], true );
129 $extension['downloaded'] = $active || $this->is_downloaded( $extension );
130 $extension['is_active'] = $active;
131 $extension['has_errors'] = $this->has_errors( $extension['slug'] );
132
133 $extensions[ $extension['slug'] ] = $extension;
134 }
135
136 $extensions = apply_filters( 'foogallery_extensions_for_view', $extensions );
137
138 return $extensions;
139 }
140 /**
141 * Get all loaded extensions slugs
142 * @return array
143 */
144 function get_all_slugs() {
145 //load all extensions first!
146 $this->get_all();
147
148 return $this->extension_slugs;
149 }
150
151 /**
152 * @TODO
153 * @param $slug
154 *
155 * @return bool
156 */
157 public function get_extension( $slug ) {
158 foreach ( $this->get_all() as $extension ) {
159 if ( $extension['slug'] === $slug ) {
160 return $extension;
161 }
162 }
163 return false;
164 }
165
166 /**
167 * @TODO
168 * @param $file
169 *
170 * @return bool
171 */
172 public function get_extension_by_file( $file ) {
173 $file = basename( $file ); //normalize to just the filename
174
175 foreach ( $this->get_all() as $extension ) {
176 if ( foo_safe_get( $extension, 'file' ) === $file ) {
177 return $extension;
178 }
179 }
180 return false;
181 }
182
183 /**
184 * @TODO
185 * @param $slug
186 *
187 * @return bool
188 */
189 public function is_active( $slug ) {
190 $overrides = $this->get_overrides();
191 if ( array_key_exists( $slug, $overrides ) ) {
192 return $overrides[$slug] === 'active';
193 }
194
195 $active_extensions = $this->get_active_extensions();
196 if ( array_key_exists( $slug, $active_extensions ) ) {
197 //it has been previously activated through the extensions page
198 return true;
199 }
200
201 $extension = $this->get_extension( $slug );
202
203 //if we have an 'plugin_active_class' attribute and that class exists, it means our plugin must be active
204 if ( isset( $extension['plugin_active_class'] ) ) {
205 if ( class_exists( $extension['plugin_active_class'] ) ) {
206 return true;
207 }
208 }
209
210 //if we have an 'activated_by_default' attribute and it is true, it means the extension is active
211 if ( isset( $extension['activated_by_default'] ) && $extension['activated_by_default'] ) {
212 return true;
213 }
214
215 //if we cannot find the extension class in memory, then check to see if the extension plugin is activated
216 if ( isset( $extension['perform_plugin_active_check'] ) && true === $extension['perform_plugin_active_check'] &&
217 isset( $extension['file'] ) ) {
218 $plugin = $this->find_active_wordpress_plugin( $extension );
219
220 return $plugin !== false;
221 }
222
223 return false;
224 }
225
226 /**
227 * @TODO
228 *
229 * @param bool $extension
230 *
231 * @param bool $slug
232 *
233 * @return bool
234 */
235 public function is_downloaded( $extension = false, $slug = false ) {
236 //allow you to pass in a slug rather
237 if ( ! $extension && $slug !== false ) {
238 $extension = $this->get_extension( $slug );
239 }
240 if ( $extension ) {
241 //first check if the class exists
242 if ( class_exists( $extension['class'] ) ) {
243 return true;
244 }
245
246 //next fallback to see if a plugin exists that has the same file name
247 $plugin = $this->find_wordpress_plugin( $extension );
248 return false !== $plugin;
249 }
250 return false;
251 }
252
253 /**
254 * @TODO
255 * @param $slug
256 *
257 * @return bool
258 */
259 public function has_errors( $slug ) {
260 $error_extensions = $this->get_error_extensions();
261
262 if ( $error_extensions ) {
263 return array_key_exists( $slug, $error_extensions );
264 }
265 return false;
266 }
267
268 /**
269 * @TODO
270 * @param $plugin
271 */
272 public function handle_wordpress_plugin_deactivation( $plugin ) {
273 $extension = $this->get_extension_by_file( $plugin );
274 if ( $extension ) {
275 //we have found a matching extension
276 $this->deactivate( $extension['slug'], false );
277 }
278 }
279
280 /**
281 * @TODO
282 * @param $plugin
283 */
284 public function handle_wordpress_plugin_activation( $plugin ) {
285 $extension = $this->get_extension_by_file( $plugin );
286 if ( $extension ) {
287 //we have found a matching extension
288 $this->activate( $extension['slug'], false );
289 }
290 }
291
292 /**
293 * @TODO
294 * @param $slug
295 * @param bool $deactivate_wordpress_plugin
296 * @param bool $error_loading
297 *
298 * @return array|mixed|void
299 */
300 public function deactivate( $slug, $deactivate_wordpress_plugin = true, $error_loading = false ) {
301 $extension = $this->get_extension( $slug );
302 if ( $extension ) {
303 if ( $deactivate_wordpress_plugin && 'bundled' !== foo_safe_get( $extension, 'source', false ) ) {
304 $plugin = $this->find_wordpress_plugin( $extension );
305 if ( $plugin ) {
306 $failure = deactivate_plugins( $plugin['file'], true, false );
307 if ( null !== $failure ) {
308 return array(
309 'message' => sprintf( __( 'The feature %s could NOT be deactivated!', 'foogallery' ), "<strong>{$extension['title']}</strong>" ),
310 'type' => 'error'
311 );
312 }
313 }
314 }
315
316 $active_extensions = $this->get_active_extensions();
317 if ( array_key_exists( $slug, $active_extensions ) ) {
318 unset( $active_extensions[ $slug ] );
319 if ( empty($active_extensions) ) {
320 delete_option( FOOGALLERY_EXTENSIONS_ACTIVATED_OPTIONS_KEY );
321 } else {
322 update_option( FOOGALLERY_EXTENSIONS_ACTIVATED_OPTIONS_KEY, $active_extensions );
323 }
324 }
325
326 $this->set_override( $slug, 'deactivated' );
327
328 if ( $error_loading ) {
329 $this->add_to_error_extensions( $slug );
330 }
331
332 //we are done, allow for extensions to do something after an extension is activated
333 do_action( 'foogallery_extension_deactivated-' . $slug );
334
335 return apply_filters( 'foogallery_extensions_deactivated_message-' . $slug, array(
336 'message' => sprintf( __( 'The feature %s was successfully deactivated', 'foogallery' ), "<strong>{$extension['title']}</strong>" ),
337 'type' => 'success',
338 ) );
339 }
340 return array(
341 'message' => sprintf( __( 'Unknown feature : %s', 'foogallery' ), $slug ),
342 'type' => 'error',
343 );
344 }
345
346 private function set_override( $slug, $status ) {
347 $overrides = $this->get_overrides();
348 $overrides[$slug] = $status;
349 update_option( FOOGALLERY_EXTENSIONS_OVERRIDES_OPTIONS_KEY, $overrides );
350 }
351
352 /**
353 * @TODO
354 *
355 * @param $slug
356 * @param bool $activate_wordpress_plugin
357 *
358 * @return array|mixed|void
359 */
360 public function activate( $slug, $activate_wordpress_plugin = true ) {
361 $extension = $this->get_extension( $slug );
362 if ( $extension ) {
363 //first remove it from our error list (if it was there before)
364 $this->remove_from_error_extensions( $slug );
365
366 if ( $activate_wordpress_plugin && 'bundled' !== foo_safe_get( $extension, 'source', false ) ) {
367 //activate the plugin, WordPress style!
368 $plugin = $this->find_wordpress_plugin( $extension );
369
370 if ( $plugin ) {
371
372 //check min version
373 $minimum_version = foo_safe_get( $extension, 'minimum_version' );
374 if ( !empty($minimum_version) ) {
375 $actual_version = $plugin['plugin']['Version'];
376 if ( version_compare( $actual_version, $minimum_version ) < 0 ) {
377 $this->add_to_error_extensions( $slug, sprintf( __( 'Requires %s version %s','foogallery' ), $extension['title'], $minimum_version ) );
378 return array(
379 '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 ),
380 'type' => 'error',
381 );
382 }
383 }
384
385 //try to activate the plugin
386 $failure = activate_plugin( $plugin['file'], '', false, false );
387 if ( null !== $failure ) {
388 return array(
389 'message' => sprintf( __( 'The feature %s could NOT be activated!', 'foogallery' ), "<strong>{$extension['title']}</strong>" ),
390 'type' => 'error',
391 );
392 }
393 }
394 }
395 //load an instance of the extension class into memory
396 $loader = new FooGallery_Extensions_Loader();
397 $loader->load_extension( $slug, foo_safe_get( $extension, 'class', false ) );
398
399 //then add the extension to our saved option so that it can be loaded on startup
400 $this->add_to_activated_extensions( $extension );
401
402 $this->set_override( $slug, 'active' );
403
404 //we are done, allow for extensions to do something after an extension is activated
405 do_action( 'foogallery_extension_activated-' . $slug );
406
407 //return our result
408 return apply_filters( 'foogallery_extension_activated_message-' . $slug, array(
409 'message' => sprintf( __( 'The feature %s was successfully activated', 'foogallery' ), "<strong>{$extension['title']}</strong>" ),
410 'type' => 'success',
411 ) );
412 }
413 return array(
414 'message' => sprintf( __( 'Unknown feature : %s', 'foogallery' ), $slug ),
415 'type' => 'error',
416 );
417 }
418
419 /**
420 * @TODO
421 * @param boolean $extension
422 *
423 * @return array|bool
424 */
425 private function find_wordpress_plugin( $extension ) {
426 $plugins = get_plugins();
427 foreach ( $plugins as $plugin_file => $plugin ) {
428 if ( isset($extension['file']) && foo_ends_with( $plugin_file, $extension['file'] ) ) {
429 return array(
430 'file' => $plugin_file,
431 'plugin' => $plugin,
432 'active' => is_plugin_active( $plugin_file ),
433 );
434 }
435 }
436 return false;
437 }
438
439 /**
440 * @TODO
441 * @param boolean $extension
442 *
443 * @return array|bool
444 */
445 private function find_active_wordpress_plugin( $extension ) {
446 $plugins = get_plugins();
447 foreach ( $plugins as $plugin_file => $plugin ) {
448 if ( is_plugin_active( $plugin_file ) && isset($extension['file']) && foo_ends_with( $plugin_file, $extension['file'] ) ) {
449 return array(
450 'file' => $plugin_file,
451 'plugin' => $plugin
452 );
453 }
454 }
455 return false;
456 }
457
458 /**
459 * @TODO
460 * @param $slug
461 *
462 * @return array|mixed|void
463 */
464 public function download( $slug ) {
465 $extension = $this->get_extension( $slug );
466 if ( $extension ) {
467
468 //we need some files!
469 require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; // plugins_api calls
470 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; // Plugin_Upgrader class
471 require_once FOOGALLERY_PATH . 'includes/admin/class-silent-installer-skin.php'; //our silent installer skin
472
473 $download_link = isset( $extension['download_link'] ) ? $extension['download_link'] : false;
474
475 if ( 'repo' === $extension['source'] ) {
476 $plugins_api = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false ) ) );
477
478 if ( is_wp_error( $plugins_api ) ) {
479 return array(
480 '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 ) ),
481 'type' => 'error',
482 );
483 }
484
485 //get the download link from the API call
486 if ( isset( $plugins_api->download_link ) ) {
487 $download_link = $plugins_api->download_link;
488 }
489 }
490
491 //check we have something to download
492 if ( empty( $download_link ) ) {
493 return array(
494 'message' => sprintf( __( 'The feature %s has no download link!', 'foogallery' ), $slug ),
495 'type' => 'error',
496 );
497 }
498
499 $skin = new FooGallery_Silent_Installer_Skin();
500
501 //instantiate Plugin_Upgrader
502 $upgrader = new Plugin_Upgrader( $skin );
503
504 $upgrader->install( $download_link );
505
506 if ( 'process_failed' === $skin->feedback ) {
507 $error_message = is_wp_error( $skin->result ) ? $skin->result->get_error_message() : __( 'Unknown!', 'foogallery' );
508
509 //save the error message for the extension
510 $this->add_to_error_extensions( $slug, sprintf( __('Could not be downloaded! Error : %s', 'foogallery' ), $error_message ) );
511
512 //we had an error along the way
513 return apply_filters( 'foogallery_extensions_download_failure-' . $slug, array(
514 'message' => sprintf( __( 'The feature %s could NOT be downloaded! Error : %s', 'foogallery' ), "<strong>{$extension['title']}</strong>", $error_message ),
515 'type' => 'error'
516 ) );
517 }
518
519 //return our result
520 return apply_filters( 'foogallery_extensions_download_success-' . $slug, array(
521 'message' => sprintf( __( 'The feature %s was successfully downloaded and can now be activated. %s', 'foogallery' ),
522 "<strong>{$extension['title']}</strong>",
523 '<a href="' . esc_url( add_query_arg( array(
524 'action' => 'activate',
525 'extension' => $slug, ) ) ) . '">' . __( 'Activate immediately', 'foogallery' ) . '</a>'
526 ),
527 'type' => 'success',
528 ) );
529 }
530 return array(
531 'message' => sprintf( __( 'Unknown feature : %s', 'foogallery' ), $slug ),
532 'type' => 'error',
533 );
534 }
535
536 /**
537 * @TODO
538 * @return mixed|void
539 */
540 public function get_active_extensions() {
541 return get_option( FOOGALLERY_EXTENSIONS_ACTIVATED_OPTIONS_KEY, array() );
542 }
543
544 /**
545 * Returns the extension overrides.
546 * @return mixed|void
547 */
548 public function get_overrides() {
549 return get_option( FOOGALLERY_EXTENSIONS_OVERRIDES_OPTIONS_KEY, array() );
550 }
551
552 /**
553 * @TODO
554 * @return mixed|void
555 */
556 public function get_error_extensions() {
557 return get_option( FOOGALLERY_EXTENSIONS_ERRORS_OPTIONS_KEY, array() );
558 }
559
560 public function get_error_message( $slug ) {
561 $error_extensions = $this->get_error_extensions();
562 if ( array_key_exists( $slug, $error_extensions ) ) {
563 return $error_extensions[ $slug ];
564 }
565 return '';
566 }
567
568 /**
569 * @TODO
570 * @param $extension
571 */
572 private function add_to_activated_extensions( $extension ) {
573 $slug = $extension['slug'];
574 $active_extensions = $this->get_active_extensions();
575 if ( !array_key_exists( $slug, $active_extensions ) ) {
576 $active_extensions[ $slug ] = $extension['class'];
577 update_option( FOOGALLERY_EXTENSIONS_ACTIVATED_OPTIONS_KEY, $active_extensions );
578 }
579 }
580
581 /**
582 * @TODO
583 * @param $slug
584 */
585 public function add_to_error_extensions( $slug, $error_message = '' ) {
586 $error_extensions = $this->get_error_extensions();
587
588 if ( empty($error_message) ) {
589 $error_message = __( 'Error loading feature!', 'foogallery' );
590 }
591
592 if ( array_key_exists( $slug, $error_extensions ) &&
593 $error_message === $error_extensions[$slug]) {
594 //do nothing!
595 } else {
596 $error_extensions[$slug] = $error_message;
597 update_option( FOOGALLERY_EXTENSIONS_ERRORS_OPTIONS_KEY, $error_extensions );
598 }
599 }
600
601 /**
602 * @TODO
603 * @param $slug
604 */
605 private function remove_from_error_extensions( $slug ) {
606 $error_extensions = $this->get_error_extensions();
607 if ( array_key_exists( $slug, $error_extensions ) ) {
608 unset( $error_extensions[ $slug ] );
609 update_option( FOOGALLERY_EXTENSIONS_ERRORS_OPTIONS_KEY, $error_extensions );
610 }
611 }
612
613 /**
614 * @TODO
615 */
616 public function auto_activate_extensions() {
617 foreach ( $this->get_all() as $extension ) {
618 if ( true === foo_safe_get( $extension, 'activated_by_default' ) ) {
619 //check to see if the extension is downloaded
620 if ( $this->is_downloaded( $extension ) ) {
621 $this->add_to_activated_extensions( $extension );
622 }
623 }
624 }
625 }
626 }
627 }
628