plugin_name = $plugin_name; $this->plugin_slug = $plugin_slug; $this->plugin_file_path = $plugin_file_path; $this->parent_plugin_name = $parent_plugin_name; $this->parent_plugin_slug = $parent_plugin_slug; $this->parent_plugin_required_version = $parent_plugin_required_version; $this->parent_plugin_filename = $parent_plugin_filename; $this->deactivate_if_not_compatible = $deactivate_if_not_compatible; $this->parent_plugin_url = $parent_plugin_url; add_action( 'admin_notices', array( $this, 'hook_admin_notices' ) ); add_action( 'network_admin_notices', array( $this, 'hook_admin_notices' ) ); } /** * Is the plugin compatible? * * @return bool */ function is_compatible() { $compatible = $this->get_error_msg() ? false : true; $GLOBALS['aws_meta'][ $this->plugin_slug ]['compatible'] = $compatible; return $compatible; } /** * Is a plugin active * * @param string $plugin_base * * @return bool */ function is_plugin_active( $plugin_base ) { include_once ABSPATH . 'wp-admin/includes/plugin.php'; return is_plugin_active( $plugin_base ); } /** * Get the basename for the plugin * * @return string */ function get_plugin_basename() { return plugin_basename( $this->plugin_file_path ); } /** * Get the name of the parent plugin * * @return string */ function get_parent_plugin_name() { if ( ! is_null( $this->parent_plugin_name ) ) { return $this->parent_plugin_name; } return ''; } /** * Get the class of the parent plugin * * @return string */ function get_parent_plugin_class() { if ( ! is_null( $this->parent_plugin_slug ) ) { $class = ucwords( str_replace( '-', ' ', $this->parent_plugin_slug ) ); return str_replace( ' ', '_', $class ); } return ''; } /** * Get the filename of the main parent plugin file * * @return string */ function get_parent_plugin_filename() { if ( ! is_null( $this->parent_plugin_slug ) ) { $filename = $this->parent_plugin_slug; if ( ! is_null( $this->parent_plugin_filename ) ) { $filename = basename( $this->parent_plugin_filename, '.php' ); } return $filename . '.php'; } return ''; } /** * Get the basename of the parent plugin {slug}/{slug}.php * * @return string */ function get_parent_plugin_basename() { if ( ! is_null( $this->parent_plugin_slug ) ) { $file_name = $this->get_parent_plugin_filename(); return $this->parent_plugin_slug . '/' . $file_name; } return ''; } /** * Get the URL for the parent plugin. Defaults to a wordpress.org URL. * * @return string */ function get_parent_plugin_url() { if ( ! is_null( $this->parent_plugin_slug ) ) { $url = 'https://wordpress.org/extend/plugins/' . $this->parent_plugin_slug . '/'; if ( ! is_null( $this->parent_plugin_url ) ) { $url = $this->parent_plugin_url; } return $url; } return ''; } /** * Generate a URL to perform core actions on for a plugin * * @param string $action Such as activate, deactivate, install, upgrade * @param string|null $basename * * @return string */ function get_plugin_action_url( $action, $basename = null ) { if ( is_null( $basename ) ) { $basename = $this->get_plugin_basename(); } $nonce_action = $action . '-plugin_' . $basename; $page = 'plugins'; if ( in_array( $action, array( 'upgrade', 'install' ) ) ) { $page = 'update'; $action .= '-plugin'; } $url = wp_nonce_url( network_admin_url( $page . '.php?action=' . $action . '&plugin=' . $basename ), $nonce_action ); return $url; } /** * Set the error message to be returned for the admin notice * * @param string $message * * @return string */ function set_error_msg( $message ) { // Replace the space between the last two words with   to prevent typographic widows $message = preg_replace( '/\s([\w]+[.,!\:;\\"-?]{0,1})$/', ' \\1', $message, 1 ); $this->error_message = $message; return $this->error_message; } /** * Check if the parent plugin is active and enabled, ie. not disabled due to * compatibility issues up the chain. * * @return bool */ function is_parent_plugin_enabled() { $class = $this->get_parent_plugin_class(); if ( ! class_exists( $class ) ) { // Class not even loaded return false; } // call_user_func overcomes parse errors on PHP versions < 5.3 if ( method_exists( $class, 'is_compatible' ) && ! call_user_func( array( $class, 'is_compatible' ) ) ) { // The plugin is active but not compatible return false; } return true; } /** * Check the parent plugin is at a specific version * * @param string $version * * @return bool */ function is_parent_plugin_at_version( $version ) { $current_parent_plugin_version = isset( $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['version'] ) ? $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['version'] : 0; return version_compare( $current_parent_plugin_version, $version, '>=' ); } /** * Get the compatibility error message * * @return string|bool */ public function get_error_msg() { if ( ! is_null( $this->error_message ) ) { return $this->error_message; } $plugin_basename = $this->get_plugin_basename(); $deactivate_url = $this->get_plugin_action_url( 'deactivate', $plugin_basename ); $deactivate_link = sprintf( '%s', $deactivate_url, __( 'deactivate' ) ); $hide_notice_msg = '
' . sprintf( __( 'You can %s the %s plugin to get rid of this notice.' ), $deactivate_link, $this->plugin_name ) . ''; // Check basic requirements for AWS SDK. $sdk_errors = $this->get_sdk_requirements_errors(); if ( ! empty( $sdk_errors ) ) { $sdk_errors = $this->get_sdk_error_msg() . $hide_notice_msg; return $this->set_error_msg( $sdk_errors ); } // Remainder of tests are for addons. if ( is_null( $this->parent_plugin_slug ) ) { return false; } $parent_basename = $this->get_parent_plugin_basename(); $parent_plugin_link_html = sprintf( '%s', $this->get_parent_plugin_url(), $this->get_parent_plugin_name() ); if ( ! $this->is_parent_plugin_enabled() ) { $msg = sprintf( __( '%s has been disabled as it requires the %s plugin.' ), $this->plugin_name, $parent_plugin_link_html ); if ( file_exists( WP_PLUGIN_DIR . '/' . $parent_basename ) ) { if ( isset( $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['compatible'] ) && ! $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['compatible'] ) { $msg = rtrim( $msg, '.' ) . ', ' . __( 'which is currently disabled.' ); } else { $msg .= ' ' . __( 'It appears to be installed already.' ); $activate_url = $this->get_plugin_action_url( 'activate', $parent_basename ); $msg .= ' ' . _x( 'Activate it now.', 'Activate plugin' ) . ''; } } else { $install_url = 'https://deliciousbrains.com/my-account/'; if ( is_null( $this->parent_plugin_url ) ) { $install_url = $this->get_plugin_action_url( 'install', $this->parent_plugin_slug ); } $msg .= ' ' . sprintf( __( 'Install and activate it.' ), $install_url ); } $msg .= $hide_notice_msg; return $this->set_error_msg( $msg ); } $current_parent_plugin_version = isset( $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['version'] ) ? $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['version'] : 0; if ( ! version_compare( $current_parent_plugin_version, $this->parent_plugin_required_version, '>=' ) ) { $msg = sprintf( __( '%s has been disabled as it requires version %s or later of the %s plugin.' ), $this->plugin_name, $this->parent_plugin_required_version, $parent_plugin_link_html ); if ( $current_parent_plugin_version ) { $msg .= ' ' . sprintf( __( 'You currently have version %s installed.' ), $current_parent_plugin_version ); } global $as3cfpro; $update_url = $this->get_plugin_action_url( 'upgrade', $parent_basename ); $msg .= ' ' . __( 'Update to the latest version' ) . ''; $msg .= $hide_notice_msg; return $this->set_error_msg( $msg ); } if ( ! isset( $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['supported_addon_versions'] ) ) { return false; } if ( ! isset( $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['supported_addon_versions'][ $this->plugin_slug ] ) ) { $msg = sprintf( __( '%1$s has been disabled because it is not a supported addon of the %2$s plugin.' ), $this->plugin_name, $this->get_parent_plugin_name() ); return $this->set_error_msg( $msg ); } $this_plugin_version_required = $GLOBALS['aws_meta'][ $this->parent_plugin_slug ]['supported_addon_versions'][ $this->plugin_slug ]; $this_plugin_version = $GLOBALS['aws_meta'][ $this->plugin_slug ]['version']; if ( ! version_compare( $this_plugin_version, $this_plugin_version_required, '>=' ) ) { $msg = sprintf( __( '%1$s has been disabled because it will not work with the version of the %2$s plugin installed. %1$s %3$s or later is required.' ), $this->plugin_name, $this->get_parent_plugin_name(), $this_plugin_version_required ); $update_url = $this->get_plugin_action_url( 'upgrade', $plugin_basename ); $upgrade_msg = ' ' . sprintf( __( 'Update %s to the latest version' ), $this->plugin_name ) . ''; global $as3cfpro; $msg .= $upgrade_msg; $msg .= $hide_notice_msg; return $this->set_error_msg( $msg ); } return false; } /** * Check plugin capabilities for a user * * @return bool */ function check_capabilities() { if ( is_multisite() ) { if ( ! current_user_can( 'manage_network_plugins' ) ) { return false; // Don't allow if the user can't manage network plugins } } else { // Don't allow if user doesn't have plugin management privileges $caps = array( 'activate_plugins', 'update_plugins', 'install_plugins' ); foreach ( $caps as $cap ) { if ( ! current_user_can( $cap ) ) { return false; } } } return true; } /** * Display compatibility notices to users who can manage plugins */ function hook_admin_notices() { if ( ! $this->check_capabilities() ) { return; } if ( self::is_installing_or_updating_plugins() ) { // Don't show notice when installing or updating plugins return; } $this->get_admin_notice(); } /** * Get the admin notice to be displayed */ function get_admin_notice() { $error_msg = $this->get_error_msg(); if ( false === $error_msg || '' === $error_msg ) { return; } if ( $this->deactivate_if_not_compatible ) { $deactivated_msg = sprintf( __( 'The %s plugin has been deactivated.' ), $this->plugin_name ); $error_msg = $deactivated_msg . ' ' . $error_msg; $this->render_notice( $error_msg ); require_once ABSPATH . 'wp-admin/includes/plugin.php'; deactivate_plugins( $this->plugin_file_path ); } else { $this->render_notice( $error_msg ); } } /** * Render the notice HTML * * @param string $message */ function render_notice( $message ) { printf( '

%s

', $message ); } /** * Is the current process an install or upgrade of plugin(s) * * @return bool */ public static function is_installing_or_updating_plugins() { if ( ! is_null( self::$is_installing_or_updating_plugins ) ) { return self::$is_installing_or_updating_plugins; } self::$is_installing_or_updating_plugins = false; global $pagenow; if ( 'update.php' === $pagenow && isset( $_GET['action'] ) && 'install-plugin' === $_GET['action'] ) { // We are installing a plugin self::$is_installing_or_updating_plugins = true; } if ( 'plugins.php' === $pagenow && isset( $_POST['action'] ) ) { $action = $_POST['action']; if ( isset( $_POST['action2'] ) && '-1' !== $_POST['action2'] ) { $action = $_POST['action2']; } if ( 'update-selected' === $action ) { // We are updating plugins from the plugin page self::$is_installing_or_updating_plugins = true; } } if ( 'update-core.php' === $pagenow && isset( $_GET['action'] ) && 'do-plugin-upgrade' === $_GET['action'] ) { // We are updating plugins from the updates page self::$is_installing_or_updating_plugins = true; } return self::$is_installing_or_updating_plugins; } /** * Checks if another version of WP Offload Media (Lite) is active and deactivates it. * To be hooked on `activated_plugin` so other plugin is deactivated when current plugin is activated. * * @param string $plugin * * @return bool */ public static function deactivate_other_instances( $plugin ) { if ( ! in_array( basename( $plugin ), array( 'amazon-s3-and-cloudfront-pro.php', 'wordpress-s3.php' ) ) ) { return false; } $plugin_to_deactivate = 'wordpress-s3.php'; $deactivated_notice_id = '1'; $activated_plugin_min_version = '1.1'; $plugin_to_deactivate_min_version = '1.0'; if ( basename( $plugin ) === $plugin_to_deactivate ) { $plugin_to_deactivate = 'amazon-s3-and-cloudfront-pro.php'; $deactivated_notice_id = '2'; $activated_plugin_min_version = '1.0'; $plugin_to_deactivate_min_version = '1.1'; } $version = self::get_plugin_version_from_basename( $plugin ); if ( version_compare( $version, $activated_plugin_min_version, '<' ) ) { return false; } if ( is_multisite() ) { $active_plugins = (array) get_site_option( 'active_sitewide_plugins', array() ); $active_plugins = array_keys( $active_plugins ); } else { $active_plugins = (array) get_option( 'active_plugins', array() ); } foreach ( $active_plugins as $basename ) { if ( false !== strpos( $basename, $plugin_to_deactivate ) ) { $version = self::get_plugin_version_from_basename( $basename ); if ( version_compare( $version, $plugin_to_deactivate_min_version, '<' ) ) { return false; } set_transient( 'as3cf_deactivated_notice_id', $deactivated_notice_id, HOUR_IN_SECONDS ); deactivate_plugins( $basename ); return true; } } return false; } /** * Get plugin data from basename * * @param string $basename * * @return string */ public static function get_plugin_version_from_basename( $basename ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; $plugin_path = WP_PLUGIN_DIR . '/' . $basename; $plugin_data = get_plugin_data( $plugin_path ); return $plugin_data['Version']; } /** * Return an array of issues with the server's compatibility with the AWS SDK * * @return array */ public function get_sdk_requirements_errors() { static $errors; if ( ! is_null( $errors ) ) { return $errors; } $errors = array(); if ( version_compare( PHP_VERSION, '5.5', '<' ) ) { $errors[] = __( 'a PHP version less than 5.5', 'amazon-s3-and-cloudfront' ); } if ( ! class_exists( 'SimpleXMLElement' ) ) { $errors[] = __( 'no SimpleXML PHP module', 'amazon-s3-and-cloudfront' ); } if ( ! class_exists( 'XMLWriter' ) ) { $errors[] = __( 'no XMLWriter PHP module', 'amazon-s3-and-cloudfront' ); } if ( ! function_exists( 'curl_version' ) ) { $errors[] = __( 'no PHP cURL library activated', 'amazon-s3-and-cloudfront' ); return $errors; } if ( ! ( $curl = curl_version() ) || empty( $curl['version'] ) || empty( $curl['features'] ) || version_compare( $curl['version'], '7.16.2', '<' ) ) { $errors[] = __( 'a cURL version less than 7.16.2', 'amazon-s3-and-cloudfront' ); } if ( ! empty( $curl['features'] ) ) { $curl_errors = array(); if ( ! CURL_VERSION_SSL ) { $curl_errors[] = 'OpenSSL'; } if ( ! CURL_VERSION_LIBZ ) { $curl_errors[] = 'zlib'; } if ( $curl_errors ) { $errors[] = __( 'cURL compiled without', 'amazon-s3-and-cloudfront' ) . ' ' . implode( ' or ', $curl_errors ); // xss ok } } if ( ! function_exists( 'curl_multi_exec' ) ) { $errors[] = __( 'the function curl_multi_exec disabled', 'amazon-s3-and-cloudfront' ); } return $errors; } /** * Prepare an error message with compatibility issues * * @return string */ public function get_sdk_error_msg() { $errors = $this->get_sdk_requirements_errors(); if ( ! $errors ) { return ''; } $msg = __( 'The official Amazon Web Services SDK requires PHP 5.5+ with SimpleXML and XMLWriter modules, and cURL 7.16.2+ compiled with OpenSSL and zlib. Your server currently has', 'amazon-s3-and-cloudfront' ); if ( count( $errors ) > 1 ) { $last_one = ' and ' . array_pop( $errors ); } else { $last_one = ''; } $msg .= ' ' . implode( ', ', $errors ) . $last_one . '.'; return $msg; } } }