angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-plugin-installer-skin.php (11864B)


      1 <?php
      2 /**
      3  * Upgrader API: Plugin_Installer_Skin class
      4  *
      5  * @package WordPress
      6  * @subpackage Upgrader
      7  * @since 4.6.0
      8  */
      9 
     10 /**
     11  * Plugin Installer Skin for WordPress Plugin Installer.
     12  *
     13  * @since 2.8.0
     14  * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php.
     15  *
     16  * @see WP_Upgrader_Skin
     17  */
     18 class Plugin_Installer_Skin extends WP_Upgrader_Skin {
     19 	public $api;
     20 	public $type;
     21 	public $url;
     22 	public $overwrite;
     23 
     24 	private $is_downgrading = false;
     25 
     26 	/**
     27 	 * @param array $args
     28 	 */
     29 	public function __construct( $args = array() ) {
     30 		$defaults = array(
     31 			'type'      => 'web',
     32 			'url'       => '',
     33 			'plugin'    => '',
     34 			'nonce'     => '',
     35 			'title'     => '',
     36 			'overwrite' => '',
     37 		);
     38 		$args     = wp_parse_args( $args, $defaults );
     39 
     40 		$this->type      = $args['type'];
     41 		$this->url       = $args['url'];
     42 		$this->api       = isset( $args['api'] ) ? $args['api'] : array();
     43 		$this->overwrite = $args['overwrite'];
     44 
     45 		parent::__construct( $args );
     46 	}
     47 
     48 	/**
     49 	 * Action to perform before installing a plugin.
     50 	 *
     51 	 * @since 2.8.0
     52 	 */
     53 	public function before() {
     54 		if ( ! empty( $this->api ) ) {
     55 			$this->upgrader->strings['process_success'] = sprintf(
     56 				$this->upgrader->strings['process_success_specific'],
     57 				$this->api->name,
     58 				$this->api->version
     59 			);
     60 		}
     61 	}
     62 
     63 	/**
     64 	 * Hides the `process_failed` error when updating a plugin by uploading a zip file.
     65 	 *
     66 	 * @since 5.5.0
     67 	 *
     68 	 * @param WP_Error $wp_error WP_Error object.
     69 	 * @return bool
     70 	 */
     71 	public function hide_process_failed( $wp_error ) {
     72 		if (
     73 			'upload' === $this->type &&
     74 			'' === $this->overwrite &&
     75 			$wp_error->get_error_code() === 'folder_exists'
     76 		) {
     77 			return true;
     78 		}
     79 
     80 		return false;
     81 	}
     82 
     83 	/**
     84 	 * Action to perform following a plugin install.
     85 	 *
     86 	 * @since 2.8.0
     87 	 */
     88 	public function after() {
     89 		// Check if the plugin can be overwritten and output the HTML.
     90 		if ( $this->do_overwrite() ) {
     91 			return;
     92 		}
     93 
     94 		$plugin_file = $this->upgrader->plugin_info();
     95 
     96 		$install_actions = array();
     97 
     98 		$from = isset( $_GET['from'] ) ? wp_unslash( $_GET['from'] ) : 'plugins';
     99 
    100 		if ( 'import' === $from ) {
    101 			$install_actions['activate_plugin'] = sprintf(
    102 				'<a class="button button-primary" href="%s" target="_parent">%s</a>',
    103 				wp_nonce_url( 'plugins.php?action=activate&amp;from=import&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ),
    104 				__( 'Activate Plugin &amp; Run Importer' )
    105 			);
    106 		} elseif ( 'press-this' === $from ) {
    107 			$install_actions['activate_plugin'] = sprintf(
    108 				'<a class="button button-primary" href="%s" target="_parent">%s</a>',
    109 				wp_nonce_url( 'plugins.php?action=activate&amp;from=press-this&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ),
    110 				__( 'Activate Plugin &amp; Go to Press This' )
    111 			);
    112 		} else {
    113 			$install_actions['activate_plugin'] = sprintf(
    114 				'<a class="button button-primary" href="%s" target="_parent">%s</a>',
    115 				wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ),
    116 				__( 'Activate Plugin' )
    117 			);
    118 		}
    119 
    120 		if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) {
    121 			$install_actions['network_activate'] = sprintf(
    122 				'<a class="button button-primary" href="%s" target="_parent">%s</a>',
    123 				wp_nonce_url( 'plugins.php?action=activate&amp;networkwide=1&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ),
    124 				__( 'Network Activate' )
    125 			);
    126 			unset( $install_actions['activate_plugin'] );
    127 		}
    128 
    129 		if ( 'import' === $from ) {
    130 			$install_actions['importers_page'] = sprintf(
    131 				'<a href="%s" target="_parent">%s</a>',
    132 				admin_url( 'import.php' ),
    133 				__( 'Go to Importers' )
    134 			);
    135 		} elseif ( 'web' === $this->type ) {
    136 			$install_actions['plugins_page'] = sprintf(
    137 				'<a href="%s" target="_parent">%s</a>',
    138 				self_admin_url( 'plugin-install.php' ),
    139 				__( 'Go to Plugin Installer' )
    140 			);
    141 		} elseif ( 'upload' === $this->type && 'plugins' === $from ) {
    142 			$install_actions['plugins_page'] = sprintf(
    143 				'<a href="%s">%s</a>',
    144 				self_admin_url( 'plugin-install.php' ),
    145 				__( 'Go to Plugin Installer' )
    146 			);
    147 		} else {
    148 			$install_actions['plugins_page'] = sprintf(
    149 				'<a href="%s" target="_parent">%s</a>',
    150 				self_admin_url( 'plugins.php' ),
    151 				__( 'Go to Plugins page' )
    152 			);
    153 		}
    154 
    155 		if ( ! $this->result || is_wp_error( $this->result ) ) {
    156 			unset( $install_actions['activate_plugin'], $install_actions['network_activate'] );
    157 		} elseif ( ! current_user_can( 'activate_plugin', $plugin_file ) || is_plugin_active( $plugin_file ) ) {
    158 			unset( $install_actions['activate_plugin'] );
    159 		}
    160 
    161 		/**
    162 		 * Filters the list of action links available following a single plugin installation.
    163 		 *
    164 		 * @since 2.7.0
    165 		 *
    166 		 * @param string[] $install_actions Array of plugin action links.
    167 		 * @param object   $api             Object containing WordPress.org API plugin data. Empty
    168 		 *                                  for non-API installs, such as when a plugin is installed
    169 		 *                                  via upload.
    170 		 * @param string   $plugin_file     Path to the plugin file relative to the plugins directory.
    171 		 */
    172 		$install_actions = apply_filters( 'install_plugin_complete_actions', $install_actions, $this->api, $plugin_file );
    173 
    174 		if ( ! empty( $install_actions ) ) {
    175 			$this->feedback( implode( ' ', (array) $install_actions ) );
    176 		}
    177 	}
    178 
    179 	/**
    180 	 * Check if the plugin can be overwritten and output the HTML for overwriting a plugin on upload.
    181 	 *
    182 	 * @since 5.5.0
    183 	 *
    184 	 * @return bool Whether the plugin can be overwritten and HTML was outputted.
    185 	 */
    186 	private function do_overwrite() {
    187 		if ( 'upload' !== $this->type || ! is_wp_error( $this->result ) || 'folder_exists' !== $this->result->get_error_code() ) {
    188 			return false;
    189 		}
    190 
    191 		$folder = $this->result->get_error_data( 'folder_exists' );
    192 		$folder = ltrim( substr( $folder, strlen( WP_PLUGIN_DIR ) ), '/' );
    193 
    194 		$current_plugin_data = false;
    195 		$all_plugins         = get_plugins();
    196 
    197 		foreach ( $all_plugins as $plugin => $plugin_data ) {
    198 			if ( strrpos( $plugin, $folder ) !== 0 ) {
    199 				continue;
    200 			}
    201 
    202 			$current_plugin_data = $plugin_data;
    203 		}
    204 
    205 		$new_plugin_data = $this->upgrader->new_plugin_data;
    206 
    207 		if ( ! $current_plugin_data || ! $new_plugin_data ) {
    208 			return false;
    209 		}
    210 
    211 		echo '<h2 class="update-from-upload-heading">' . esc_html__( 'This plugin is already installed.' ) . '</h2>';
    212 
    213 		$this->is_downgrading = version_compare( $current_plugin_data['Version'], $new_plugin_data['Version'], '>' );
    214 
    215 		$rows = array(
    216 			'Name'        => __( 'Plugin name' ),
    217 			'Version'     => __( 'Version' ),
    218 			'Author'      => __( 'Author' ),
    219 			'RequiresWP'  => __( 'Required WordPress version' ),
    220 			'RequiresPHP' => __( 'Required PHP version' ),
    221 		);
    222 
    223 		$table  = '<table class="update-from-upload-comparison"><tbody>';
    224 		$table .= '<tr><th></th><th>' . esc_html_x( 'Current', 'plugin' ) . '</th>';
    225 		$table .= '<th>' . esc_html_x( 'Uploaded', 'plugin' ) . '</th></tr>';
    226 
    227 		$is_same_plugin = true; // Let's consider only these rows.
    228 
    229 		foreach ( $rows as $field => $label ) {
    230 			$old_value = ! empty( $current_plugin_data[ $field ] ) ? (string) $current_plugin_data[ $field ] : '-';
    231 			$new_value = ! empty( $new_plugin_data[ $field ] ) ? (string) $new_plugin_data[ $field ] : '-';
    232 
    233 			$is_same_plugin = $is_same_plugin && ( $old_value === $new_value );
    234 
    235 			$diff_field   = ( 'Version' !== $field && $new_value !== $old_value );
    236 			$diff_version = ( 'Version' === $field && $this->is_downgrading );
    237 
    238 			$table .= '<tr><td class="name-label">' . $label . '</td><td>' . wp_strip_all_tags( $old_value ) . '</td>';
    239 			$table .= ( $diff_field || $diff_version ) ? '<td class="warning">' : '<td>';
    240 			$table .= wp_strip_all_tags( $new_value ) . '</td></tr>';
    241 		}
    242 
    243 		$table .= '</tbody></table>';
    244 
    245 		/**
    246 		 * Filters the compare table output for overwriting a plugin package on upload.
    247 		 *
    248 		 * @since 5.5.0
    249 		 *
    250 		 * @param string $table               The output table with Name, Version, Author, RequiresWP, and RequiresPHP info.
    251 		 * @param array  $current_plugin_data Array with current plugin data.
    252 		 * @param array  $new_plugin_data     Array with uploaded plugin data.
    253 		 */
    254 		echo apply_filters( 'install_plugin_overwrite_comparison', $table, $current_plugin_data, $new_plugin_data );
    255 
    256 		$install_actions = array();
    257 		$can_update      = true;
    258 
    259 		$blocked_message  = '<p>' . esc_html__( 'The plugin cannot be updated due to the following:' ) . '</p>';
    260 		$blocked_message .= '<ul class="ul-disc">';
    261 
    262 		$requires_php = isset( $new_plugin_data['RequiresPHP'] ) ? $new_plugin_data['RequiresPHP'] : null;
    263 		$requires_wp  = isset( $new_plugin_data['RequiresWP'] ) ? $new_plugin_data['RequiresWP'] : null;
    264 
    265 		if ( ! is_php_version_compatible( $requires_php ) ) {
    266 			$error = sprintf(
    267 				/* translators: 1: Current PHP version, 2: Version required by the uploaded plugin. */
    268 				__( 'The PHP version on your server is %1$s, however the uploaded plugin requires %2$s.' ),
    269 				phpversion(),
    270 				$requires_php
    271 			);
    272 
    273 			$blocked_message .= '<li>' . esc_html( $error ) . '</li>';
    274 			$can_update       = false;
    275 		}
    276 
    277 		if ( ! is_wp_version_compatible( $requires_wp ) ) {
    278 			$error = sprintf(
    279 				/* translators: 1: Current WordPress version, 2: Version required by the uploaded plugin. */
    280 				__( 'Your WordPress version is %1$s, however the uploaded plugin requires %2$s.' ),
    281 				get_bloginfo( 'version' ),
    282 				$requires_wp
    283 			);
    284 
    285 			$blocked_message .= '<li>' . esc_html( $error ) . '</li>';
    286 			$can_update       = false;
    287 		}
    288 
    289 		$blocked_message .= '</ul>';
    290 
    291 		if ( $can_update ) {
    292 			if ( $this->is_downgrading ) {
    293 				$warning = sprintf(
    294 					/* translators: %s: Documentation URL. */
    295 					__( 'You are uploading an older version of a current plugin. You can continue to install the older version, but be sure to <a href="%s">back up your database and files</a> first.' ),
    296 					__( 'https://wordpress.org/support/article/wordpress-backups/' )
    297 				);
    298 			} else {
    299 				$warning = sprintf(
    300 					/* translators: %s: Documentation URL. */
    301 					__( 'You are updating a plugin. Be sure to <a href="%s">back up your database and files</a> first.' ),
    302 					__( 'https://wordpress.org/support/article/wordpress-backups/' )
    303 				);
    304 			}
    305 
    306 			echo '<p class="update-from-upload-notice">' . $warning . '</p>';
    307 
    308 			$overwrite = $this->is_downgrading ? 'downgrade-plugin' : 'update-plugin';
    309 
    310 			$install_actions['overwrite_plugin'] = sprintf(
    311 				'<a class="button button-primary update-from-upload-overwrite" href="%s" target="_parent">%s</a>',
    312 				wp_nonce_url( add_query_arg( 'overwrite', $overwrite, $this->url ), 'plugin-upload' ),
    313 				_x( 'Replace current with uploaded', 'plugin' )
    314 			);
    315 		} else {
    316 			echo $blocked_message;
    317 		}
    318 
    319 		$cancel_url = add_query_arg( 'action', 'upload-plugin-cancel-overwrite', $this->url );
    320 
    321 		$install_actions['plugins_page'] = sprintf(
    322 			'<a class="button" href="%s">%s</a>',
    323 			wp_nonce_url( $cancel_url, 'plugin-upload-cancel-overwrite' ),
    324 			__( 'Cancel and go back' )
    325 		);
    326 
    327 		/**
    328 		 * Filters the list of action links available following a single plugin installation failure
    329 		 * when overwriting is allowed.
    330 		 *
    331 		 * @since 5.5.0
    332 		 *
    333 		 * @param string[] $install_actions Array of plugin action links.
    334 		 * @param object   $api             Object containing WordPress.org API plugin data.
    335 		 * @param array    $new_plugin_data Array with uploaded plugin data.
    336 		 */
    337 		$install_actions = apply_filters( 'install_plugin_overwrite_actions', $install_actions, $this->api, $new_plugin_data );
    338 
    339 		if ( ! empty( $install_actions ) ) {
    340 			printf(
    341 				'<p class="update-from-upload-expired hidden">%s</p>',
    342 				__( 'The uploaded file has expired. Please go back and upload it again.' )
    343 			);
    344 			echo '<p class="update-from-upload-actions">' . implode( ' ', (array) $install_actions ) . '</p>';
    345 		}
    346 
    347 		return true;
    348 	}
    349 }