PluginProbe
WP-Stateless – Google Cloud Storage / 3.0.3
WP-Stateless – Google Cloud Storage v3.0.3
4.4.3 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.3.0 2.3.1 2.3.2 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 All 62 releases
wp-stateless / vendor / udx / lib-wp-bootstrap / lib / classes / class-tgm-plugin-activation.php

class-tgm-plugin-activation.php in WP-Stateless – Google Cloud Storage 3.0.3, at vendor/udx/lib-wp-bootstrap/lib/classes/class-tgm-plugin-activation.php

1,034 lines 47.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin installation and activation for WordPress themes.
4 *
5 * @package TGM-Plugin-Activation
6 * @version 2.4.0
7 * @author Thomas Griffin <thomasgriffinmedia.com>
8 * @author Gary Jones <gamajo.com>
9 * @copyright Copyright (c) 2012, Thomas Griffin
10 * @license http://opensource.org/licenses/gpl-2.0.php GPL v2 or later
11 * @link https://github.com/thomasgriffin/TGM-Plugin-Activation
12 */
13
14 /*
15 Copyright 2014 Thomas Griffin (thomasgriffinmedia.com)
16
17 This program is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License, version 2, as
19 published by the Free Software Foundation.
20
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30
31 namespace UsabilityDynamics\WP {
32
33 if ( ! class_exists( 'UsabilityDynamics\WP\TGM_Plugin_Activation' ) ) {
34 /**
35 * Automatic plugin installation and activation library.
36 *
37 * Creates a way to automatically install and activate plugins from within themes.
38 * The plugins can be either pre-packaged, downloaded from the WordPress
39 * Plugin Repository or downloaded from a private repository.
40 *
41 * @since 1.0.0
42 *
43 * @package TGM-Plugin-Activation
44 * @author Thomas Griffin <thomasgriffinmedia.com>
45 * @author Gary Jones <gamajo.com>
46 */
47 class TGM_Plugin_Activation {
48
49 /**
50 * Holds a copy of itself, so it can be referenced by the class name.
51 *
52 * @since 1.0.0
53 *
54 * @var TGM_Plugin_Activation
55 */
56 public static $instance;
57
58 /**
59 * Holds arrays of plugin details.
60 *
61 * @since 1.0.0
62 *
63 * @var array
64 */
65 public $plugins = array();
66
67 /**
68 *
69 */
70 public $referrers = array();
71
72 /**
73 * Name of the querystring argument for the admin page.
74 *
75 * @since 1.0.0
76 *
77 * @var string
78 */
79 public $menu = 'ud-install-plugins';
80
81 /**
82 * Default absolute path to folder containing pre-packaged plugin zip files.
83 *
84 * @since 2.0.0
85 *
86 * @var string Absolute path prefix to packaged zip file location. Default is empty string.
87 */
88 public $default_path = '';
89
90 /**
91 * Flag to show admin notices or not.
92 *
93 * @since 2.1.0
94 *
95 * @var boolean
96 */
97 public $has_notices = true;
98
99 /**
100 * Flag to determine if the user can dismiss the notice nag.
101 *
102 * @since 2.4.0
103 *
104 * @var boolean
105 */
106 public $dismissable = true;
107
108 /**
109 * Message to be output above nag notice if dismissable is false.
110 *
111 * @since 2.4.0
112 *
113 * @var string
114 */
115 public $dismiss_msg = '';
116
117 /**
118 * Flag to set automatic activation of plugins. Off by default.
119 *
120 * @since 2.2.0
121 *
122 * @var boolean
123 */
124 public $is_automatic = false;
125
126 /**
127 * Optional message to display before the plugins table.
128 *
129 * @since 2.2.0
130 *
131 * @var string Message filtered by wp_kses_post(). Default is empty string.
132 */
133 public $message = '';
134
135 /**
136 * Holds configurable array of strings.
137 *
138 * Default values are added in the constructor.
139 *
140 * @since 2.0.0
141 *
142 * @var array
143 */
144 public $strings = array();
145
146 /**
147 * Error Notice types.
148 *
149 * @var array
150 */
151 public $error_types = array(
152 'notice_can_install_required',
153 'notice_can_activate_required',
154 'notice_ask_to_update',
155 );
156
157 /**
158 * Holds the version of WordPress.
159 *
160 * @since 2.4.0
161 *
162 * @var int
163 */
164 public $wp_version;
165
166 /**
167 * Adds a reference of this object to $instance, populates default strings,
168 * does the tgmpa_init action hook, and hooks in the interactions to init.
169 *
170 * @since 1.0.0
171 *
172 * @see TGM_Plugin_Activation::init()
173 */
174 private function __construct() {
175
176 $this->strings = array(
177 'page_title' => __( 'Install Required Plugins', 'tgmpa' ),
178 'menu_title' => __( 'Install Plugins', 'tgmpa' ),
179 'installing' => __( 'Installing Plugin: %s', 'tgmpa' ),
180 'oops' => __( 'Something went wrong.', 'tgmpa' ),
181 'notice_can_install_required' => _n_noop( '%2$s requires the following plugin: %1$s.', '%2$s requires the following plugins: %1$s.' ),
182 'notice_can_install_recommended' => _n_noop( '%2$s recommends the following plugin: %1$s.', '%2$s recommends the following plugins: %1$s.' ),
183 'notice_cannot_install' => _n_noop( 'Sorry, but you do not have the correct permissions to install the %s plugin. Contact the administrator of this site for help on getting the plugin installed.', 'Sorry, but you do not have the correct permissions to install the %s plugins. Contact the administrator of this site for help on getting the plugins installed.' ),
184 'notice_can_activate_required' => _n_noop( 'The following required plugin is currently inactive: %1$s.', 'The following required plugins are currently inactive: %1$s.' ),
185 'notice_can_activate_recommended'=> _n_noop( 'The following recommended plugin is currently inactive: %1$s.', 'The following recommended plugins are currently inactive: %1$s.' ),
186 'notice_cannot_activate' => _n_noop( 'Sorry, but you do not have the correct permissions to activate the %s plugin. Contact the administrator of this site for help on getting the plugin activated.', 'Sorry, but you do not have the correct permissions to activate the %s plugins. Contact the administrator of this site for help on getting the plugins activated.' ),
187 'notice_ask_to_update' => _n_noop( 'The following plugin needs to be updated to its latest version to ensure maximum compatibility with %2$s: %1$s.', 'The following plugins need to be updated to their latest version to ensure maximum compatibility with %2$s: %1$s.' ),
188 'notice_cannot_update' => _n_noop( 'Sorry, but you do not have the correct permissions to update the %s plugin. Contact the administrator of this site for help on getting the plugin updated.', 'Sorry, but you do not have the correct permissions to update the %s plugins. Contact the administrator of this site for help on getting the plugins updated.' ),
189 'install_link' => _n_noop( 'Begin installing plugin', 'Begin installing plugins' ),
190 'activate_link' => _n_noop( 'Begin activating plugin', 'Begin activating plugins' ),
191 'return' => __( 'Return to Required Plugins Installer', 'tgmpa' ),
192 'dashboard' => __( 'Return to the dashboard', 'tgmpa' ),
193 'plugin_activated' => __( 'Plugin activated successfully.', 'tgmpa' ),
194 'activated_successfully' => __( 'The following plugin was activated successfully:', 'tgmpa' ),
195 'complete' => __( 'All plugins installed and activated successfully. %1$s', 'tgmpa' ),
196 'dismiss' => __( 'Dismiss this notice', 'tgmpa' ),
197 );
198
199 // Set the current WordPress version.
200 global $wp_version;
201 $this->wp_version = $wp_version;
202
203 // Announce that the class is ready, and pass the object (for advanced use).
204 do_action_ref_array( 'tgmpa_init', array( $this ) );
205
206 // When the rest of WP has loaded, kick-start the rest of the class.
207 //add_action( 'plugins_loaded', array( $this, 'init' ), 0 );
208 add_action( 'init', array( $this, 'init' ) );
209
210 }
211
212 /**
213 * Initialise the interactions between this class and WordPress.
214 *
215 * Hooks in three new methods for the class: admin_menu, notices and styles.
216 *
217 * @since 2.0.0
218 *
219 * @see TGM_Plugin_Activation::admin_menu()
220 * @see TGM_Plugin_Activation::notices()
221 * @see TGM_Plugin_Activation::styles()
222 */
223 public function init() {
224
225 // After this point, the plugins should be registered and the configuration set.
226
227 // Proceed only if we have plugins to handle.
228 if ( $this->plugins ) {
229 $sorted = array();
230
231 foreach ( $this->plugins as $plugin ) {
232 $sorted[] = $plugin['name'];
233 }
234
235 array_multisort( $sorted, SORT_ASC, $this->plugins );
236
237 add_action( 'admin_menu', array( $this, 'admin_menu' ) );
238 add_filter( 'install_plugin_complete_actions', array( $this, 'actions' ) );
239 add_action( 'switch_theme', array( $this, 'flush_plugins_cache' ) );
240
241 // Load admin bar in the header to remove flash when installing plugins.
242 if ( $this->is_tgmpa_page() ) {
243 remove_action( 'wp_footer', 'wp_admin_bar_render', 1000 );
244 remove_action( 'admin_footer', 'wp_admin_bar_render', 1000 );
245 add_action( 'wp_head', 'wp_admin_bar_render', 1000 );
246 add_action( 'admin_head', 'wp_admin_bar_render', 1000 );
247 }
248
249 if ( $this->has_notices ) {
250 add_action( 'admin_init', array( $this, 'admin_init' ), 1 );
251 add_action( 'admin_enqueue_scripts', array( $this, 'thickbox' ) );
252 }
253
254 // Setup the force activation hook.
255 foreach ( $this->plugins as $plugin ) {
256 if ( isset( $plugin['force_activation'] ) && true === $plugin['force_activation'] ) {
257 add_action( 'admin_init', array( $this, 'force_activation' ) );
258 break;
259 }
260 }
261
262 // Setup the force deactivation hook.
263 foreach ( $this->plugins as $plugin ) {
264 if ( isset( $plugin['force_deactivation'] ) && true === $plugin['force_deactivation'] ) {
265 add_action( 'switch_theme', array( $this, 'force_deactivation' ) );
266 break;
267 }
268 }
269 }
270
271 }
272
273 /**
274 * Handles calls to show plugin information via links in the notices.
275 *
276 * We get the links in the admin notices to point to the TGMPA page, rather
277 * than the typical plugin-install.php file, so we can prepare everything
278 * beforehand.
279 *
280 * WP doesn't make it easy to show the plugin information in the thickbox -
281 * here we have to require a file that includes a function that does the
282 * main work of displaying it, enqueue some styles, set up some globals and
283 * finally call that function before exiting.
284 *
285 * Down right easy once you know how...
286 *
287 * @since 2.1.0
288 *
289 * @global string $tab Used as iframe div class names, helps with styling
290 * @global string $body_id Used as the iframe body ID, helps with styling
291 * @return null Returns early if not the TGMPA page.
292 */
293 public function admin_init() {
294
295 if ( ! $this->is_tgmpa_page() ) {
296 return;
297 }
298
299 if ( isset( $_REQUEST['tab'] ) && 'plugin-information' == $_REQUEST['tab'] ) {
300 require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; // Need for install_plugin_information().
301
302 wp_enqueue_style( 'plugin-install' );
303
304 global $tab, $body_id;
305 $body_id = $tab = 'plugin-information';
306
307 install_plugin_information();
308
309 exit;
310 }
311
312 }
313
314 /**
315 * Enqueues thickbox scripts/styles for plugin info.
316 *
317 * Thickbox is not automatically included on all admin pages, so we must
318 * manually enqueue it for those pages.
319 *
320 * Thickbox is only loaded if the user has not dismissed the admin
321 * notice or if there are any plugins left to install and activate.
322 *
323 * @since 2.1.0
324 */
325 public function thickbox() {
326 add_thickbox();
327 }
328
329 /**
330 * Adds submenu page under 'Appearance' tab.
331 *
332 * This method adds the submenu page letting users know that a required
333 * plugin needs to be installed.
334 *
335 * This page disappears once the plugin has been installed and activated.
336 *
337 * @since 1.0.0
338 *
339 * @see TGM_Plugin_Activation::init()
340 * @see TGM_Plugin_Activation::install_plugins_page()
341 */
342 public function admin_menu() {
343
344 // Make sure privileges are correct to see the page
345 if ( ! current_user_can( 'install_plugins' ) ) {
346 return;
347 }
348
349 $this->populate_file_path();
350
351 foreach ( $this->plugins as $plugin ) {
352 if ( ! is_plugin_active( $plugin['file_path'] ) ) {
353 add_theme_page(
354 $this->strings['page_title'], // Page title.
355 $this->strings['menu_title'], // Menu title.
356 'edit_theme_options', // Capability.
357 $this->menu, // Menu slug.
358 array( $this, 'install_plugins_page' ) // Callback.
359 );
360 break;
361 }
362 }
363
364 }
365
366 /**
367 * Echoes plugin installation form.
368 *
369 * This method is the callback for the admin_menu method function.
370 * This displays the admin page and form area where the user can select to install and activate the plugin.
371 *
372 * @since 1.0.0
373 *
374 * @return null Aborts early if we're processing a plugin installation action
375 */
376 public function install_plugins_page() {
377
378 // Store new instance of plugin table in object.
379 $plugin_table = new TGMPA_List_Table;
380
381 // Return early if processing a plugin installation action.
382 if ( isset( $_POST['action'] ) && 'tgmpa-bulk-install' == $_POST['action'] && $plugin_table->process_bulk_actions() || $this->do_plugin_install() ) {
383 return;
384 }
385
386 ?>
387 <div class="tgmpa wrap">
388
389 <?php if ( version_compare( $this->wp_version, '3.8', '<' ) ) {
390 screen_icon( apply_filters( 'ud_default_screen_icon', 'themes' ) );
391 } ?>
392 <h2><?php echo esc_html( get_admin_page_title() ); ?></h2>
393 <?php $plugin_table->prepare_items(); ?>
394
395 <?php if ( isset( $this->message ) ) {
396 echo wp_kses_post( $this->message );
397 } ?>
398
399 <form id="tgmpa-plugins" action="" method="post">
400 <input type="hidden" name="tgmpa-page" value="<?php echo $this->menu; ?>" />
401 <?php $plugin_table->display(); ?>
402 </form>
403
404 </div>
405 <?php
406
407 }
408
409 /**
410 * Installs a plugin or activates a plugin depending on the hover
411 * link clicked by the user.
412 *
413 * Checks the $_GET variable to see which actions have been
414 * passed and responds with the appropriate method.
415 *
416 * Uses WP_Filesystem to process and handle the plugin installation
417 * method.
418 *
419 * @since 1.0.0
420 *
421 * @uses WP_Filesystem
422 * @uses WP_Error
423 * @uses WP_Upgrader
424 * @uses Plugin_Upgrader
425 * @uses Plugin_Installer_Skin
426 *
427 * @return boolean True on success, false on failure
428 */
429 protected function do_plugin_install() {
430
431 // All plugin information will be stored in an array for processing.
432 $plugin = array();
433
434 // Checks for actions from hover links to process the installation.
435 if ( isset( $_GET['plugin'] ) && ( isset( $_GET['tgmpa-install'] ) && 'install-plugin' == $_GET['tgmpa-install'] ) ) {
436 check_admin_referer( 'tgmpa-install' );
437
438 $plugin['name'] = $_GET['plugin_name']; // Plugin name.
439 $plugin['slug'] = $_GET['plugin']; // Plugin slug.
440 $plugin['source'] = $_GET['plugin_source']; // Plugin source.
441
442 // Pass all necessary information via URL if WP_Filesystem is needed.
443 $url = wp_nonce_url(
444 esc_url( add_query_arg(
445 array(
446 'page' => $this->menu,
447 'plugin' => $plugin['slug'],
448 'plugin_name' => $plugin['name'],
449 'plugin_source' => $plugin['source'],
450 'tgmpa-install' => 'install-plugin',
451 ),
452 admin_url( 'themes.php' )
453 ) ),
454 'tgmpa-install'
455 );
456 $method = ''; // Leave blank so WP_Filesystem can populate it as necessary.
457 $fields = array( 'tgmpa-install' ); // Extra fields to pass to WP_Filesystem.
458
459 if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, $fields ) ) ) {
460 return true;
461 }
462
463 if ( ! WP_Filesystem( $creds ) ) {
464 request_filesystem_credentials( $url, $method, true, false, $fields ); // Setup WP_Filesystem.
465 return true;
466 }
467
468 require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; // Need for plugins_api.
469 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; // Need for upgrade classes.
470
471 // Set plugin source to WordPress API link if available.
472 if ( isset( $plugin['source'] ) && 'repo' == $plugin['source'] ) {
473 $api = plugins_api( 'plugin_information', array( 'slug' => $plugin['slug'], 'fields' => array( 'sections' => false ) ) );
474
475 if ( is_wp_error( $api ) ) {
476 wp_die( $this->strings['oops'] . var_dump( $api ) );
477 }
478
479 if ( isset( $api->download_link ) ) {
480 $plugin['source'] = $api->download_link;
481 }
482 }
483
484 // Set type, based on whether the source starts with http:// or https://.
485 $type = preg_match( '|^http(s)?://|', $plugin['source'] ) ? 'web' : 'upload';
486
487 // Prep variables for Plugin_Installer_Skin class.
488 $title = sprintf( $this->strings['installing'], $plugin['name'] );
489 $url = esc_url( add_query_arg( array( 'action' => 'install-plugin', 'plugin' => $plugin['slug'] ), 'update.php' ) );
490 if ( isset( $_GET['from'] ) ) {
491 $url .= esc_url( add_query_arg( 'from', urlencode( stripslashes( $_GET['from'] ) ), $url ) );
492 }
493
494 $nonce = 'install-plugin_' . $plugin['slug'];
495
496 // Prefix a default path to pre-packaged plugins.
497 $source = ( 'upload' == $type ) ? $this->default_path . $plugin['source'] : $plugin['source'];
498
499 // Create a new instance of Plugin_Upgrader.
500 $upgrader = new \Plugin_Upgrader( $skin = new \Plugin_Installer_Skin( compact( 'type', 'title', 'url', 'nonce', 'plugin', 'api' ) ) );
501
502 // Perform the action and install the plugin from the $source urldecode().
503 $upgrader->install( $source );
504
505 // Flush plugins cache so we can make sure that the installed plugins list is always up to date.
506 wp_cache_flush();
507
508 // Only activate plugins if the config option is set to true.
509 if ( $this->is_automatic ) {
510 $plugin_activate = $upgrader->plugin_info(); // Grab the plugin info from the Plugin_Upgrader method.
511 $activate = activate_plugin( $plugin_activate ); // Activate the plugin.
512 $this->populate_file_path(); // Re-populate the file path now that the plugin has been installed and activated.
513
514 if ( is_wp_error( $activate ) ) {
515 echo '<div id="message" class="error"><p>' . $activate->get_error_message() . '</p></div>';
516 echo '<p><a href="' . esc_url( add_query_arg( 'page', $this->menu, admin_url( 'themes.php' ) ) ) . '" title="' . esc_attr( $this->strings['return'] ) . '" target="_parent">' . $this->strings['return'] . '</a></p>';
517 return true; // End it here if there is an error with automatic activation
518 }
519 else {
520 echo '<p>' . $this->strings['plugin_activated'] . '</p>';
521 }
522 }
523
524 // Display message based on if all plugins are now active or not.
525 $complete = array();
526 foreach ( $this->plugins as $plugin ) {
527 if ( ! is_plugin_active( $plugin['file_path'] ) ) {
528 echo '<p><a href="' . add_query_arg( 'page', $this->menu, admin_url( 'themes.php' ) ) . '" title="' . esc_attr( $this->strings['return'] ) . '" target="_parent">' . $this->strings['return'] . '</a></p>';
529 $complete[] = $plugin;
530 break;
531 }
532 // Nothing to store.
533 else {
534 $complete[] = '';
535 }
536 }
537
538 // Filter out any empty entries.
539 $complete = array_filter( $complete );
540
541 // All plugins are active, so we display the complete string and hide the plugin menu.
542 if ( empty( $complete ) ) {
543 echo '<p>' . sprintf( $this->strings['complete'], '<a href="' . admin_url() . '" title="' . __( 'Return to the Dashboard', 'tgmpa' ) . '">' . __( 'Return to the Dashboard', 'tgmpa' ) . '</a>' ) . '</p>';
544 echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
545 }
546
547 return true;
548 }
549 // Checks for actions from hover links to process the activation.
550 elseif ( isset( $_GET['plugin'] ) && ( isset( $_GET['tgmpa-activate'] ) && 'activate-plugin' == $_GET['tgmpa-activate'] ) ) {
551 check_admin_referer( 'tgmpa-activate', 'tgmpa-activate-nonce' );
552
553 // Populate $plugin array with necessary information.
554 $plugin['name'] = $_GET['plugin_name'];
555 $plugin['slug'] = $_GET['plugin'];
556 $plugin['source'] = $_GET['plugin_source'];
557
558 $plugin_path = $this->_get_plugin_basename_from_slug($plugin['slug']); // Retrieve all plugins.
559 $activate = activate_plugin( $plugin_path ); // Activate the plugin.
560
561 if ( is_wp_error( $activate ) ) {
562 echo '<div id="message" class="error"><p>' . $activate->get_error_message() . '</p></div>';
563 echo '<p><a href="' . esc_url( add_query_arg( 'page', $this->menu, admin_url( 'themes.php' ) ) ) . '" title="' . esc_attr( $this->strings['return'] ) . '" target="_parent">' . $this->strings['return'] . '</a></p>';
564 return true; // End it here if there is an error with activation.
565 }
566 else {
567 // Make sure message doesn't display again if bulk activation is performed immediately after a single activation.
568 if ( ! isset( $_POST['action'] ) ) {
569 $msg = $this->strings['activated_successfully'] . ' <strong>' . $plugin['name'] . '</strong>';
570 echo '<div id="message" class="updated"><p>' . $msg . '</p></div>';
571 }
572 }
573 }
574
575 return false;
576
577 }
578
579 /**
580 * Echoes required plugin notice.
581 *
582 * Outputs a message telling users that a specific plugin is required for
583 * their theme. If appropriate, it includes a link to the form page where
584 * users can install and activate the plugin.
585 *
586 * @since 1.0.0
587 *
588 * @global object $current_screen
589 * @return null Returns early if we're on the Install page.
590 */
591 public function notices( $referrer = false ) {
592 //** Check if get_plugins() function exists. This is required on the front end of the */
593 //** site, since it is in a file that is normally only loaded in the admin. */
594 if ( ! function_exists( 'get_plugins' ) ) {
595 require_once ABSPATH . 'wp-admin/includes/plugin.php';
596 }
597
598 $installed_plugins = \get_plugins(); // Retrieve a list of all the plugins
599 $this->populate_file_path();
600
601 $message = array(); // Store the messages in an array to be outputted after plugins have looped through.
602
603 $e_install_link = false; // Set to false, change to true in loop if conditions exist, used for action link 'install'.
604 $e_install_link_count = 0; // Used to determine plurality of install action link text.
605 $e_activate_link = false; // Set to false, change to true in loop if conditions exist, used for action link 'activate'.
606 $e_activate_link_count = 0; // Used to determine plurality of activate action link text.
607
608 $m_install_link = false; // Set to false, change to true in loop if conditions exist, used for action link 'install'.
609 $m_install_link_count = 0; // Used to determine plurality of install action link text.
610 $m_activate_link = false; // Set to false, change to true in loop if conditions exist, used for action link 'activate'.
611 $m_activate_link_count = 0; // Used to determine plurality of activate action link text.
612
613 foreach ( $this->referrers as $plugin ) {
614 //** We must return only notices for referrer */
615 if( empty( $referrer ) || $referrer != $plugin[ '_referrer' ] || !isset( $this->plugins[ $plugin[ 'slug' ] ] ) ) {
616 continue;
617 }
618 $plugin[ 'file_path' ] = $this->plugins[ $plugin[ 'slug' ] ][ 'file_path' ];
619 // If the plugin is installed and active, check for minimum version argument before moving forward.
620 if ( is_plugin_active( $plugin['file_path'] ) ) {
621 // A minimum version has been specified.
622 if ( isset( $plugin['version'] ) ) {
623 if ( isset( $installed_plugins[$plugin['file_path']]['Version'] ) ) {
624 // If the current version is less than the minimum required version, we display a message.
625 if ( version_compare( $installed_plugins[$plugin['file_path']]['Version'], $plugin['version'], '<' ) ) {
626 if ( current_user_can( 'install_plugins' ) ) {
627 $message['notice_ask_to_update'][] = $plugin;
628 } else {
629 $message['notice_cannot_update'][] = $plugin;
630 }
631 }
632 }
633 // Can't find the plugin, so iterate to the next condition.
634 else {
635 continue;
636 }
637 }
638 // No minimum version specified, so iterate over the plugin.
639 else {
640 continue;
641 }
642 }
643
644 // Not installed.
645 if ( ! isset( $installed_plugins[$plugin['file_path']] ) ) {
646 if ( current_user_can( 'install_plugins' ) ) {
647 if ( isset( $plugin['required'] ) && $plugin['required'] ) {
648 $e_install_link = true; // We need to display the 'install' action link.
649 $e_install_link_count++; // Increment the install link count.
650 $message['notice_can_install_required'][] = $plugin;
651 }
652 // This plugin is only recommended.
653 else {
654 $m_install_link = true; // We need to display the 'install' action link.
655 $m_install_link_count++; // Increment the install link count.
656 $message['notice_can_install_recommended'][] = $plugin;
657 }
658 } elseif( !is_user_logged_in() && isset( $plugin['required'] ) && $plugin['required'] ) {
659 $message['notice_can_install_required'][] = $plugin;
660 }
661 // Need higher privileges to install the plugin.
662 else {
663 if ( isset( $plugin['required'] ) && $plugin['required'] ) {
664 $message['notice_can_install_required'][] = $plugin;
665 $message['notice_cannot_activate'][] = $plugin;
666 }
667 else {
668 $message['notice_cannot_activate'][] = $plugin;
669 }
670 }
671 }
672 // Installed but not active.
673 elseif ( is_plugin_inactive( $plugin['file_path'] ) ) {
674 if ( current_user_can( 'activate_plugins' ) ) {
675 if ( isset( $plugin['required'] ) && $plugin['required'] ) {
676 $e_activate_link = true; // We need to display the 'activate' action link.
677 $e_activate_link_count++; // Increment the activate link count.
678 $message['notice_can_activate_required'][] = $plugin;
679 }
680 // This plugin is only recommended.
681 else {
682 $m_activate_link = true; // We need to display the 'activate' action link.
683 $m_activate_link_count++; // Increment the activate link count.
684 $message['notice_can_activate_recommended'][] = $plugin;
685 }
686 } elseif( !is_user_logged_in() && isset( $plugin['required'] ) && $plugin['required'] ) {
687 $message['notice_can_install_required'][] = $plugin;
688 }
689 // Need higher privileges to activate the plugin.
690 else {
691 if ( isset( $plugin['required'] ) && $plugin['required'] ) {
692 $message['notice_can_install_required'][] = $plugin;
693 $message['notice_cannot_activate'][] = $plugin;
694 }
695 else {
696 $message['notice_cannot_activate'][] = $plugin;
697 }
698
699 }
700 }
701 }
702
703 //return $message;
704
705 $prepared = array();
706
707 // If we have notices to display, we move forward.
708 if ( ! empty( $message ) ) {
709 krsort( $message ); // Sort messages.
710
711 // Grab all plugin names.
712 foreach ( $message as $type => $plugin_groups ) {
713 $linked_plugin_groups = array();
714
715 // Count number of plugins in each message group to calculate singular/plural message.
716 $count = count( $plugin_groups );
717
718 // Loop through the plugin names to make the ones pulled from the .org repo linked.
719 foreach ( $plugin_groups as $plugin ) {
720 $plugin_group_single_name = $plugin[ 'name' ];
721 $external_url = $this->_get_plugin_data_from_name( $plugin_group_single_name, 'external_url' );
722 $source = $this->_get_plugin_data_from_name( $plugin_group_single_name, 'source' );
723
724 if ( $external_url && preg_match( '|^http(s)?://|', $external_url ) ) {
725 $linked_plugin_groups[] = '<a href="' . esc_url( $external_url ) . '" title="' . $plugin_group_single_name . '" target="_blank">' . $plugin_group_single_name . '</a>';
726 }
727 elseif ( ! $source || preg_match( '|^http://wordpress.org/extend/plugins/|', $source ) ) {
728 $url = esc_url( add_query_arg(
729 array(
730 'tab' => 'plugin-information',
731 'plugin' => $this->_get_plugin_data_from_name( $plugin_group_single_name ),
732 'TB_iframe' => 'true',
733 'width' => '640',
734 'height' => '500',
735 ),
736 admin_url( 'plugin-install.php' )
737 ) );
738
739 $linked_plugin_groups[] = '<a href="' . esc_url( $url ) . '" class="thickbox" title="' . $plugin_group_single_name . '">' . $plugin_group_single_name . '</a>';
740 }
741 else {
742 $linked_plugin_groups[] = $plugin_group_single_name; // No hyperlink.
743 }
744
745 if ( isset( $linked_plugin_groups ) && (array) $linked_plugin_groups ) {
746 $plugin_groups = $linked_plugin_groups;
747 }
748 }
749
750 $last_plugin = array_pop( $plugin_groups ); // Pop off last name to prep for readability.
751 $imploded = empty( $plugin_groups ) ? '<em>' . $last_plugin . '</em>' : '<em>' . ( implode( ', ', $plugin_groups ) . '</em> and <em>' . $last_plugin . '</em>' );
752
753 $prepared['messages'][] = array(
754 'type' => ( in_array( $type, $this->error_types ) && $plugin[ 'required' ] ? 'error' : 'message' ),
755 'value' => sprintf( translate_nooped_plural( $this->strings[$type], $count, 'tgmpa' ), $imploded, $plugin[ '_referrer_name' ], $count ),
756 );
757
758 }
759
760 //** Setup variables to determine if action links are needed. */
761 $e_show_install_link = $e_install_link ? '<a href="' . esc_url( add_query_arg( 'page', $this->menu, admin_url( 'themes.php' ) ) ) . '">' . translate_nooped_plural( $this->strings['install_link'], $e_install_link_count, 'tgmpa' ) . '</a>' : '';
762 $e_show_activate_link = $e_activate_link ? '<a href="' . esc_url( add_query_arg( 'page', $this->menu, admin_url( 'themes.php' ) ) ) . '">' . translate_nooped_plural( $this->strings['activate_link'], $e_activate_link_count, 'tgmpa' ) . '</a>' : '';
763
764 $m_show_install_link = $m_install_link ? '<a href="' . esc_url( add_query_arg( 'page', $this->menu, admin_url( 'themes.php' ) ) ) . '">' . translate_nooped_plural( $this->strings['install_link'], $m_install_link_count, 'tgmpa' ) . '</a>' : '';
765 $m_show_activate_link = $m_activate_link ? '<a href="' . esc_url( add_query_arg( 'page', $this->menu, admin_url( 'themes.php' ) ) ) . '">' . translate_nooped_plural( $this->strings['activate_link'], $m_activate_link_count, 'tgmpa' ) . '</a>' : '';
766
767 //** Define all of the action links. */
768 $prepared[ 'links' ] = array(
769 'error' => array_filter( array(
770 'install' => ( current_user_can( 'install_plugins' ) ) ? $e_show_install_link : false,
771 'activate' => ( current_user_can( 'activate_plugins' ) ) ? $e_show_activate_link : false,
772 ) ),
773 'message' => array_filter( array(
774 'install' => ( current_user_can( 'install_plugins' ) ) ? $m_show_install_link : false,
775 'activate' => ( current_user_can( 'activate_plugins' ) ) ? $m_show_activate_link : false,
776 ) ),
777 );
778 }
779
780 return $prepared;
781 }
782
783 /**
784 * Add individual plugin to our collection of plugins.
785 *
786 * If the required keys are not set or the plugin has already
787 * been registered, the plugin is not added.
788 *
789 * @since 2.0.0
790 *
791 * @param array $plugin Array of plugin arguments.
792 */
793 public function register( $plugin ) {
794 if ( ! isset( $plugin['slug'] ) || ! isset( $plugin['name'] ) ) {
795 return;
796 }
797 if( isset( $this->plugins[ $plugin[ 'slug' ] ] ) ) {
798 $_plugin = $this->plugins[ $plugin[ 'slug' ] ];
799 //** Version must be set the highest to prevent issues. */
800 if( !empty( $_plugin[ 'version' ] ) && !empty( $plugin[ 'version' ] ) ) {
801 $version = version_compare( $_plugin[ 'version' ], $plugin[ 'version' ], '<' ) ? $plugin[ 'version' ] : $_plugin[ 'version' ];
802 } else {
803 $version = !empty( $plugin[ 'version' ] ) ? $plugin[ 'version' ] : ( !empty( $_plugin[ 'version' ] ) ? $_plugin[ 'version' ] : false );
804 }
805 if( !empty( $version ) ) {
806 $this->plugins[ $plugin[ 'slug' ] ][ 'version' ] = $version;
807 }
808 //** Parent plugin must be set as required if any child plugin requires it. */
809 $this->plugins[ $plugin[ 'slug' ] ][ 'required' ] = $_plugin[ 'required' ] == true ? $_plugin[ 'required' ] : $plugin[ 'required' ];
810 } else {
811 $_plugin = $plugin;
812 unset( $_plugin[ '_referrer' ] );
813 unset( $_plugin[ '_referrer_name' ] );
814 $this->plugins[ $plugin[ 'slug' ] ] = $_plugin;
815 }
816 $this->referrers[] = $plugin;
817 }
818
819 /**
820 * Amend default configuration settings.
821 *
822 * @since 2.0.0
823 *
824 * @param array $config Array of config options to pass as class properties.
825 */
826 public function config( $config ) {
827
828 $keys = array( 'default_path', 'has_notices', 'dismissable', 'dismiss_msg', 'menu', 'is_automatic', 'message', 'strings' );
829
830 foreach ( $keys as $key ) {
831 if ( isset( $config[$key] ) ) {
832 if ( is_array( $config[$key] ) ) {
833 foreach ( $config[$key] as $subkey => $value ) {
834 $this->{$key}[$subkey] = $value;
835 }
836 } else {
837 $this->$key = $config[$key];
838 }
839 }
840 }
841
842 }
843
844 /**
845 * Amend action link after plugin installation.
846 *
847 * @since 2.0.0
848 *
849 * @param array $install_actions Existing array of actions.
850 * @return array Amended array of actions.
851 */
852 public function actions( $install_actions ) {
853
854 // Remove action links on the TGMPA install page.
855 if ( $this->is_tgmpa_page() ) {
856 return false;
857 }
858
859 return $install_actions;
860
861 }
862
863 /**
864 * Flushes the plugins cache on theme switch to prevent stale entries
865 * from remaining in the plugin table.
866 *
867 * @since 2.4.0
868 */
869 public function flush_plugins_cache() {
870
871 wp_cache_flush();
872
873 }
874
875 /**
876 * Set file_path key for each installed plugin.
877 *
878 * @since 2.1.0
879 */
880 public function populate_file_path() {
881
882 // Add file_path key for all plugins.
883 foreach ( $this->plugins as $plugin => $values ) {
884 $this->plugins[$plugin]['file_path'] = $this->_get_plugin_basename_from_slug( $values['slug'] );
885 }
886
887 }
888
889 /**
890 * Helper function to extract the file path of the plugin file from the
891 * plugin slug, if the plugin is installed.
892 *
893 * @since 2.0.0
894 *
895 * @param string $slug Plugin slug (typically folder name) as provided by the developer.
896 * @return string Either file path for plugin if installed, or just the plugin slug.
897 */
898 protected function _get_plugin_basename_from_slug( $slug ) {
899 $keys = array_keys( get_plugins() );
900 $_keys = array();
901 /** Try to get slug of activated plugin at first */
902 foreach ( $keys as $key ) {
903 if ( preg_match( '|^' . $slug .'(-v?[0-9\.]+)?/|', $key ) ) {
904 if( is_plugin_active( $key ) ) {
905 return $key;
906 } else {
907 array_push( $_keys, $key );
908 }
909 }
910 }
911 /** Get key from any non activated but installed matched plugin */
912 if( !empty( $_keys ) ) {
913 return $_keys[0];
914 }
915 return $slug;
916 }
917
918 /**
919 * Retrieve plugin data, given the plugin name.
920 *
921 * Loops through the registered plugins looking for $name. If it finds it,
922 * it returns the $data from that plugin. Otherwise, returns false.
923 *
924 * @since 2.1.0
925 *
926 * @param string $name Name of the plugin, as it was registered.
927 * @param string $data Optional. Array key of plugin data to return. Default is slug.
928 * @return string|boolean Plugin slug if found, false otherwise.
929 */
930 protected function _get_plugin_data_from_name( $name, $data = 'slug' ) {
931
932 foreach ( $this->plugins as $plugin => $values ) {
933 if ( $name == $values['name'] && isset( $values[$data] ) ) {
934 return $values[$data];
935 }
936 }
937
938 return false;
939
940 }
941
942 /**
943 * Determine if we're on the TGMPA Install page.
944 *
945 * @since 2.1.0
946 *
947 * @return boolean True when on the TGMPA page, false otherwise.
948 */
949 public function is_tgmpa_page() {
950
951 if ( isset( $_GET['page'] ) && $this->menu === $_GET['page'] ) {
952 return true;
953 }
954
955 return false;
956
957 }
958
959 /**
960 * Forces plugin activation if the parameter 'force_activation' is
961 * set to true.
962 *
963 * This allows theme authors to specify certain plugins that must be
964 * active at all times while using the current theme.
965 *
966 * Please take special care when using this parameter as it has the
967 * potential to be harmful if not used correctly. Setting this parameter
968 * to true will not allow the specified plugin to be deactivated unless
969 * the user switches themes.
970 *
971 * @since 2.2.0
972 */
973 public function force_activation() {
974 // Set file_path parameter for any installed plugins.
975 $this->populate_file_path();
976 $installed_plugins = get_plugins();
977 foreach ( $this->plugins as $plugin ) {
978 // Oops, plugin isn't there so iterate to next condition.
979 if ( isset( $plugin['force_activation'] ) && $plugin['force_activation'] && ! isset( $installed_plugins[$plugin['file_path']] ) ) {
980 continue;
981 }
982 // There we go, activate the plugin.
983 elseif ( isset( $plugin['force_activation'] ) && $plugin['force_activation'] && is_plugin_inactive( $plugin['file_path'] ) ) {
984 activate_plugin( $plugin['file_path'] );
985 }
986 }
987 }
988
989 /**
990 * Forces plugin deactivation if the parameter 'force_deactivation'
991 * is set to true.
992 *
993 * This allows theme authors to specify certain plugins that must be
994 * deactived upon switching from the current theme to another.
995 *
996 * Please take special care when using this parameter as it has the
997 * potential to be harmful if not used correctly.
998 *
999 * @since 2.2.0
1000 */
1001 public function force_deactivation() {
1002
1003 // Set file_path parameter for any installed plugins.
1004 $this->populate_file_path();
1005
1006 foreach ( $this->plugins as $plugin ) {
1007 // Only proceed forward if the paramter is set to true and plugin is active.
1008 if ( isset( $plugin['force_deactivation'] ) && $plugin['force_deactivation'] && is_plugin_active( $plugin['file_path'] ) ) {
1009 deactivate_plugins( $plugin['file_path'] );
1010 }
1011 }
1012
1013 }
1014
1015 /**
1016 * Returns the singleton instance of the class.
1017 *
1018 * @since 2.4.0
1019 *
1020 * @return object The TGM_Plugin_Activation object.
1021 */
1022 public static function get_instance() {
1023 if ( ! isset( self::$instance ) && !( self::$instance instanceof TGM_Plugin_Activation ) ) {
1024 self::$instance = new TGM_Plugin_Activation();
1025 }
1026 return self::$instance;
1027 }
1028
1029 }
1030
1031 }
1032
1033 }
1034