Skip to content
Snippets Groups Projects
Select Git revision
  • aa354bffb3e6149c934181c2812b28ac42a4b768
  • main default protected
  • v0.10
  • 0.10.6
  • 0.10.5
  • 0.10.4
  • 0.10.3
  • 0.10.2
  • 0.10.1
  • 0.10.0
  • 0.9.1
  • 0.9.0
12 results

Kernel.php

Blame
  • Basic_Requirement_Checker.php 18.92 KiB
    <?php
    	
    	if ( ! interface_exists( 'WPDesk_Requirement_Checker' ) ) {
    		require_once 'Requirement_Checker.php';
    	}
    	
    	if ( ! class_exists( 'WPDesk_Basic_Requirement_Checker' ) ) {
    		/**
    		 * Checks requirements for plugin
    		 * have to be compatible with PHP 5.3.x
    		 */
    		class WPDesk_Basic_Requirement_Checker implements WPDesk_Requirement_Checker {
    			const EXTENSION_NAME_OPENSSL = 'openssl';
    			const HOOK_ADMIN_NOTICES_ACTION = 'admin_notices';
    			
    			const PLUGIN_INFO_KEY_NICE_NAME = 'nice_name';
    			const PLUGIN_INFO_KEY_NAME = 'name';
    			const PLUGIN_INFO_VERSION = 'version';
    			const PLUGIN_INFO_FAKE_REQUIRED_MINIMUM_VERSION = '0.0';
    			const PLUGIN_INFO_TRANSIENT_NAME = 'require_plugins_data';
    			const PLUGIN_INFO_TRANSIENT_EXPIRATION_TIME = 0;
    			
    			/** @var string */
    			protected $plugin_name;
    			/** @var string */
    			private $plugin_file;
    			/** @var string */
    			private $min_php_version;
    			/** @var string */
    			private $min_wp_version;
    			/** @var string|null */
    			private $min_wc_version = null;
    			/** @var int|null */
    			private $min_openssl_version = null;
    			/** @var array */
    			protected $plugin_require;
    			/** @var array */
    			private $module_require;
    			/** @var array */
    			private $setting_require;
    			/** @var array */
    			protected $notices;
    			/** @var @string */
    			private $text_domain;
    			
    			/**
    			 * @param string $plugin_file
    			 * @param string $plugin_name
    			 * @param string $text_domain
    			 * @param string $php_version
    			 * @param string $wp_version
    			 */
    			public function __construct( $plugin_file, $plugin_name, $text_domain, $php_version, $wp_version ) {
    				$this->plugin_file = $plugin_file;
    				$this->plugin_name = $plugin_name;
    				$this->text_domain = $text_domain;
    				
    				$this->set_min_php_require( $php_version );
    				$this->set_min_wp_require( $wp_version );
    				
    				$this->plugin_require  = array();
    				$this->module_require  = array();
    				$this->setting_require = array();
    				$this->notices         = array();
    			}
    			
    			/**
    			 * @param string $version
    			 *
    			 * @return $this
    			 */
    			public function set_min_php_require( $version ) {
    				$this->min_php_version = $version;
    				
    				return $this;
    			}
    			
    			/**
    			 * @param string $version
    			 *
    			 * @return $this
    			 */
    			public function set_min_wp_require( $version ) {
    				$this->min_wp_version = $version;
    				
    				return $this;
    			}
    			
    			/**
    			 * @param string $version
    			 *
    			 * @return $this
    			 */
    			public function set_min_wc_require( $version ) {
    				$this->min_wc_version = $version;
    				
    				return $this;
    			}
    			
    			/**
    			 * @param $version
    			 *
    			 * @return $this
    			 */
    			public function set_min_openssl_require( $version ) {
    				$this->min_openssl_version = $version;
    				
    				return $this;
    			}
    			
    			/**
    			 * @param string $plugin_name Name in wp format dir/file.php
    			 * @param string $nice_plugin_name Nice plugin name for better looks in notice
    			 * @param string $plugin_require_version required plugin minimum version
    			 *
    			 * @return $this
    			 */
    			public function add_plugin_require( $plugin_name, $nice_plugin_name = null, $plugin_require_version = null ) {
    				$this->plugin_require[ $plugin_name ] = array(
    					self::PLUGIN_INFO_KEY_NAME      => $plugin_name,
    					self::PLUGIN_INFO_KEY_NICE_NAME => $nice_plugin_name === null ? $plugin_name : $nice_plugin_name,
    					self::PLUGIN_INFO_VERSION       => $plugin_require_version === null ?
    						self::PLUGIN_INFO_FAKE_REQUIRED_MINIMUM_VERSION : $plugin_require_version,
    				);
    				
    				return $this;
    			}
    			
    			/**
    			 * Add plugin to require list. Plugin is from repository so we can ask for installation.
    			 *
    			 * @param string $plugin_name Name in wp format dir/file.php
    			 * @param string $version Required version of the plugin.
    			 * @param string $nice_plugin_name Nice plugin name for better looks in notice
    			 *
    			 * @return $this
    			 */
    			public function add_plugin_repository_require( $plugin_name, $version, $nice_plugin_name = null ) {
    				$this->plugin_require[ $plugin_name ] = array(
    					self::PLUGIN_INFO_KEY_NAME      => $plugin_name,
    					self::PLUGIN_INFO_VERSION       => $version,
    					'repository_url'                => 'http://downloads.wordpress.org/plugin/' . dirname( $plugin_name ) . '.latest-stable.zip',
    					self::PLUGIN_INFO_KEY_NICE_NAME => $nice_plugin_name === null ? $plugin_name : $nice_plugin_name
    				);
    				
    				return $this;
    			}
    			
    			/**
    			 * @param string $module_name
    			 * @param string $nice_name Nice module name for better looks in notice
    			 *
    			 * @return $this
    			 */
    			public function add_php_module_require( $module_name, $nice_name = null ) {
    				if ( $nice_name === null ) {
    					$this->module_require[ $module_name ] = $module_name;
    				} else {
    					$this->module_require[ $module_name ] = $nice_name;
    				}
    				
    				return $this;
    			}
    			
    			/**
    			 * @param string $setting
    			 * @param mixed $value
    			 *
    			 * @return $this
    			 */
    			public function add_php_setting_require( $setting, $value ) {
    				$this->setting_require[ $setting ] = $value;
    				
    				return $this;
    			}
    			
    			/**
    			 * Returns true if are requirements are met.
    			 *
    			 * @return bool
    			 */
    			public function are_requirements_met() {
    				$this->notices = $this->prepare_requirement_notices();
    				
    				return count( $this->notices ) === 0;
    			}
    			
    			/**
    			 * @return array
    			 */
    			private function prepare_requirement_notices() {
    				$notices = array();
    				if ( ! self::is_php_at_least( $this->min_php_version ) ) {
    					$notices[] = $this->prepare_notice_message( sprintf( __( 'The &#8220;%s&#8221; plugin cannot run on PHP versions older than %s. Please contact your host and ask them to upgrade.',
    						$this->get_text_domain() ), esc_html( $this->plugin_name ), $this->min_php_version ) );
    				}
    				if ( ! self::is_wp_at_least( $this->min_wp_version ) ) {
    					$notices[] = $this->prepare_notice_message( sprintf( __( 'The &#8220;%s&#8221; plugin cannot run on WordPress versions older than %s. Please update WordPress.',
    						$this->get_text_domain() ), esc_html( $this->plugin_name ), $this->min_wp_version ) );
    				}
    				if ( $this->min_wc_version !== null && $this->can_check_plugin_version() && ! self::is_wc_at_least( $this->min_wc_version ) ) {
    					$notices[] = $this->prepare_notice_message( sprintf( __( 'The &#8220;%s&#8221; plugin cannot run on WooCommerce versions older than %s. Please update WooCommerce.',
    						$this->get_text_domain() ), esc_html( $this->plugin_name ), $this->min_wc_version ) );
    				}
    				if ( $this->min_openssl_version !== null && ! self::is_open_ssl_at_least( $this->min_openssl_version ) ) {
    					$notices[] = $this->prepare_notice_message( sprintf( __( 'The &#8220;%s&#8221; plugin cannot run without OpenSSL module version at least %s. Please update OpenSSL module.',
    						$this->get_text_domain() ), esc_html( $this->plugin_name ),
    						'0x' . dechex( $this->min_openssl_version ) ) );
    				}
    				
    				$notices = $this->append_plugin_require_notices( $notices );
    				$notices = $this->append_module_require_notices( $notices );
    				$notices = $this->append_settings_require_notices( $notices );
    				$notices = $this->check_minimum_require_plugins_version_and_append_notices( $notices );
    				
    				return $notices;
    			}
    			
    			/**
    			 * @param $min_version
    			 *
    			 * @return mixed
    			 */
    			public static function is_php_at_least( $min_version ) {
    				return version_compare( PHP_VERSION, $min_version, '>=' );
    			}
    			
    			/**
    			 * Prepares message in html format
    			 *
    			 * @param string $message
    			 *
    			 * @return string
    			 */
    			protected function prepare_notice_message( $message ) {
    				return '<div class="error"><p>' . $message . '</p></div>';
    			}
    			
    			public function get_text_domain() {
    				return $this->text_domain;
    			}
    			
    			/**
    			 * @param string $min_version
    			 *
    			 * @return bool
    			 */
    			public static function is_wp_at_least( $min_version ) {
    				return version_compare( get_bloginfo( 'version' ), $min_version, '>=' );
    			}
    			
    			/**
    			 * Are plugins loaded so we can check the version
    			 *
    			 * @return bool
    			 */
    			private function can_check_plugin_version() {
    				return did_action( 'plugins_loaded' ) > 0;
    			}
    			
    			/**
    			 * Checks if plugin is active and have designated version. Needs to be enabled in deferred way.
    			 *
    			 * @param string $min_version
    			 *
    			 * @return bool
    			 */
    			public static function is_wc_at_least( $min_version ) {
    				return defined( 'WC_VERSION' ) &&
    				       version_compare( WC_VERSION, $min_version, '>=' );
    			}
    			
    			/**
    			 * Checks if ssl version is valid
    			 *
    			 * @param int $required_version Version in hex. Version 9.6 is 0x000906000
    			 *
    			 * @return bool
    			 * @see https://www.openssl.org/docs/man1.1.0/crypto/OPENSSL_VERSION_NUMBER.html
    			 *
    			 */
    			public static function is_open_ssl_at_least( $required_version ) {
    				return defined( 'OPENSSL_VERSION_NUMBER' ) && OPENSSL_VERSION_NUMBER > (int) $required_version;
    			}
    			
    			/**
    			 * @param $notices
    			 *
    			 * @return array
    			 */
    			private function check_minimum_require_plugins_version_and_append_notices( $notices ) {
    				
    				if ( count( $this->retrieve_required_plugins_data() ) > 0 ) {
    					foreach ( $this->retrieve_required_plugins_data() as $plugin ) {
    						if ( $plugin[ ucfirst( self::PLUGIN_INFO_VERSION ) ] < $plugin['required_version'] ) {
    							$notices[] = $this->prepare_notice_message( sprintf( __( 'The &#8220;%s&#8221; plugin requires at least %s version of %s to work correctly. Please update it', $this->get_text_domain() ),
    								esc_html( $this->plugin_name ), $plugin['required_version'], $plugin[ ucfirst( self::PLUGIN_INFO_KEY_NAME ) ] ) );
    						}
    					}
    				}
    				
    				return $notices;
    			}
    			
    			/**
    			 * Check the plugins directory and retrieve all plugin files with plugin data.
    			 *
    			 * @return array
    			 */
    			private function retrieve_plugins_data() {
    				
    				if ( function_exists( 'get_transient' ) ) {
    					$plugins = get_transient( self::PLUGIN_INFO_TRANSIENT_NAME );
    					
    					if ( false === $plugins ) {
    						if ( ! function_exists( 'get_plugins' ) ) {
    							require_once ABSPATH . '/wp-admin/includes/plugin.php';
    						}
    						
    						$plugins = function_exists( 'get_plugins' ) ? get_plugins() : array();
    						
    						set_transient( self::PLUGIN_INFO_TRANSIENT_NAME, $plugins, self::PLUGIN_INFO_TRANSIENT_EXPIRATION_TIME );
    					}
    					
    					return $plugins;
    				}
    				
    				return array();
    			}
    			
    			/**
    			 * Check the plugins directory and retrieve all required plugin files with plugin data.
    			 *
    			 * @return array
    			 */
    			private function retrieve_required_plugins_data() {
    				
    				$require_plugins = array();
    				if ( count( $this->retrieve_plugins_data() ) > 0 ) {
    					$plugins = $this->retrieve_plugins_data();
    					
    					if ( ! empty( $this->plugin_require ) ) {
    						foreach ( $this->plugin_require as $plugin ) {
    							if ( self::is_wp_plugin_active( $plugin[ self::PLUGIN_INFO_KEY_NAME ] ) ) {
    								$require_plugins[ $plugin[ self::PLUGIN_INFO_KEY_NAME ] ] = $plugins[ $plugin[ self::PLUGIN_INFO_KEY_NAME ] ];
    								$require_plugins[ $plugin[ self::PLUGIN_INFO_KEY_NAME ] ]['required_version'] = $plugin[ self::PLUGIN_INFO_VERSION ];
    							}
    						}
    					}
    				}
    				
    				return $require_plugins;
    			}
    			
    			/**
    			 * @param array $notices
    			 *
    			 * @return array
    			 */
    			private function append_plugin_require_notices( $notices ) {
    				if ( count( $this->plugin_require ) > 0 ) {
    					foreach ( $this->plugin_require as $plugin_name => $plugin_info ) {
    						$notice = null;
    						if ( isset( $plugin_info['repository_url'] ) ) {
    							$notice = $this->prepare_plugin_repository_require_notice( $plugin_info );
    						} elseif ( ! self::is_wp_plugin_active( $plugin_name ) ) {
    							$notice = $this->prepare_notice_message( sprintf( __( 'The &#8220;%s&#8221; plugin cannot run without %s active. Please install and activate %s plugin.',
    								$this->get_text_domain() ), esc_html( $this->plugin_name ),
    								esc_html( basename( $plugin_info[ self::PLUGIN_INFO_KEY_NICE_NAME ] ) ),
    								esc_html( basename( $plugin_info[ self::PLUGIN_INFO_KEY_NICE_NAME ] ) ) ) );
    						}
    						
    						if ( $notice !== null ) {
    							$notices[] = $notice;
    						}
    					}
    				}
    				
    				return $notices;
    			}
    			
    			/**
    			 * Prepares WP install url and injects info about plugin to the WP update engine.
    			 *
    			 * @param array $plugin_info
    			 *
    			 * @return string
    			 */
    			private function prepare_plugin_repository_install_url( $plugin_info ) {
    				$slug        = basename( $plugin_info[ self::PLUGIN_INFO_KEY_NAME ] );
    				$install_url = self_admin_url( 'update.php?action=install-plugin&plugin=' . $slug );
    				if ( function_exists( 'wp_nonce_url' ) && function_exists( 'wp_create_nonce' ) ) {
    					$install_url = wp_nonce_url( $install_url, 'install-plugin_' . $slug );
    				}
    				add_filter( 'plugins_api', function ( $api, $action, $args ) use ( $plugin_info, $slug ) {
    					if ( 'plugin_information' !== $action ||
    					     false !== $api ||
    					     ! isset( $args->slug ) ||
    					     $slug !== $args->slug
    					) {
    						return $api;
    					}
    					
    					$api                = new stdClass();
    					$api->name          = $plugin_info['nice_name']; // self in closures requires 5.4
    					$api->version       = $plugin_info['version']; // self in closures requires 5.4
    					$api->download_link = esc_url( $plugin_info['repository_url'] ); // self in closures requires 5.4
    					
    					return $api;
    				}, 10, 3 );
    				
    				return $install_url;
    			}
    			
    			/**
    			 * @param array $plugin_info Internal required plugin info data.
    			 *
    			 * @return string|null Return null if no notice is needed.
    			 */
    			private function prepare_plugin_repository_require_notice( $plugin_info ) {
    				$name      = $plugin_info[ self::PLUGIN_INFO_KEY_NAME ];
    				$nice_name = $plugin_info[ self::PLUGIN_INFO_KEY_NICE_NAME ];
    				
    				if ( ! self::is_wp_plugin_active( $name ) ) {
    					if ( ! self::is_wp_plugin_installed( $name ) ) {
    						$install_url = $this->prepare_plugin_repository_install_url( $plugin_info );
    						
    						return $this->prepare_notice_message( sprintf( wp_kses( __( 'The &#8220;%s&#8221; plugin requires free %s plugin. <a href="%s">Install %s →</a>',
    							$this->get_text_domain() ), array( 'a' => array( 'href' => array() ) ) ),
    							$this->plugin_name, $nice_name, esc_url( $install_url ), $nice_name ) );
    					}
    					$activate_url = 'plugins.php?action=activate&plugin=' . urlencode( $plugin_info[ self::PLUGIN_INFO_KEY_NAME ] ) . '&plugin_status=all&paged=1&s';
    					if ( function_exists( 'wp_create_nonce' ) ) {
    						$activate_url .= '&_wpnonce=' . urlencode( wp_create_nonce( 'activate-plugin_' . $name ) );
    					}
    					
    					return $this->prepare_notice_message( sprintf( wp_kses( __( 'The &#8220;%s&#8221; plugin requires activating %s plugin. <a href="%s">Activate %s →</a>',
    						$this->get_text_domain() ), array( 'a' => array( 'href' => array() ) ) ),
    						$this->plugin_name, $nice_name, esc_url( admin_url( $activate_url ) ), $nice_name ) );
    				}
    				
    				return null;
    			}
    			
    			/**
    			 * Checks if plugin is active. Needs to be used in deferred way.
    			 *
    			 * @param string $plugin_file
    			 *
    			 * @return bool
    			 */
    			public static function is_wp_plugin_active( $plugin_file ) {
    				$active_plugins = (array) get_option( 'active_plugins', array() );
    				
    				if ( is_multisite() ) {
    					$active_plugins = array_merge( $active_plugins, get_site_option( 'active_sitewide_plugins', array() ) );
    				}
    				
    				return in_array( $plugin_file, $active_plugins ) || array_key_exists( $plugin_file, $active_plugins );
    			}
    			
    			/**
    			 * Checks if plugin is installed. Needs to be enabled in deferred way.
    			 *
    			 * @param string $plugin_file
    			 *
    			 * @return bool
    			 */
    			public static function is_wp_plugin_installed( $plugin_file ) {
    				if ( ! function_exists( 'get_plugins' ) ) {
    					require_once ABSPATH . '/wp-admin/includes/plugin.php';
    				}
    				
    				return array_key_exists( $plugin_file, get_plugins() );
    			}
    			
    			/**
    			 * @param array $notices
    			 *
    			 * @return array
    			 */
    			private function append_module_require_notices( $notices ) {
    				if ( count( $this->module_require ) > 0 ) {
    					foreach ( $this->module_require as $module_name => $nice_module_name ) {
    						if ( ! self::is_module_active( $module_name ) ) {
    							$notices[] = $this->prepare_notice_message( sprintf( __( 'The &#8220;%s&#8221; plugin cannot run without %s php module installed. Please contact your host and ask them to install %s.',
    								$this->get_text_domain() ), esc_html( $this->plugin_name ),
    								esc_html( basename( $nice_module_name ) ), esc_html( basename( $nice_module_name ) ) ) );
    						}
    					}
    				}
    				
    				return $notices;
    			}
    			
    			/**
    			 * @param string $name
    			 *
    			 * @return bool
    			 */
    			public static function is_module_active( $name ) {
    				return extension_loaded( $name );
    			}
    			
    			/**
    			 * @param array $notices
    			 *
    			 * @return array
    			 */
    			private function append_settings_require_notices( $notices ) {
    				if ( count( $this->setting_require ) > 0 ) {
    					foreach ( $this->setting_require as $setting => $value ) {
    						if ( ! self::is_setting_set( $setting, $value ) ) {
    							$notices[] = $this->prepare_notice_message( sprintf( __( 'The &#8220;%s&#8221; plugin cannot run without %s php setting set to %s. Please contact your host and ask them to set %s.',
    								$this->get_text_domain() ), esc_html( $this->plugin_name ),
    								esc_html( basename( $setting ) ),
    								esc_html( basename( $value ) ), esc_html( basename( $setting ) ) ) );
    						}
    					}
    				}
    				
    				return $notices;
    			}
    			
    			/**
    			 * @param string $name
    			 * @param mixed $value
    			 *
    			 * @return bool
    			 */
    			public static function is_setting_set( $name, $value ) {
    				return ini_get( $name ) === (string) $value;
    			}
    			
    			/**
    			 * @return void
    			 *
    			 * @deprecated use render_notices or disable_plugin
    			 */
    			public function disable_plugin_render_notice() {
    				add_action( self::HOOK_ADMIN_NOTICES_ACTION, array( $this, 'handle_render_notices_action' ) );
    			}
    			
    			/**
    			 * Renders requirement notices in admin panel
    			 *
    			 * @return void
    			 */
    			public function render_notices() {
    				add_action( self::HOOK_ADMIN_NOTICES_ACTION, array( $this, 'handle_render_notices_action' ) );
    			}
    			
    			/**
    			 * Renders requirement notices in admin panel
    			 *
    			 * @return void
    			 */
    			public function disable_plugin() {
    				add_action( self::HOOK_ADMIN_NOTICES_ACTION, array( $this, 'handle_deactivate_action' ) );
    			}
    			
    			/**
    			 * @return void
    			 * @internal Do not use as public. Public only for wp action.
    			 *
    			 */
    			public function handle_deactivate_action() {
    				if ( isset( $this->plugin_file ) ) {
    					deactivate_plugins( plugin_basename( $this->plugin_file ) );
    					
    					delete_transient( self::PLUGIN_INFO_TRANSIENT_NAME );
    				}
    			}
    			
    			/**
    			 * Should be called as WordPress action
    			 *
    			 * @return void
    			 * @internal Do not use as public. Public only for wp action.
    			 *
    			 */
    			public function handle_render_notices_action() {
    				foreach ( $this->notices as $notice ) {
    					echo $notice;
    				}
    				
    				if ( function_exists( 'delete_transient' ) ) {
    					delete_transient( self::PLUGIN_INFO_TRANSIENT_NAME );
    				}
    			}
    		}
    	}