Skip to content
Snippets Groups Projects
Commit 44c486c7 authored by Vasili Guruli's avatar Vasili Guruli
Browse files

Merge branch 'feature/minimum-plugin-version-check-demo1' into 'master'

Feature/minimum plugin version check demo1

See merge request !19
parents bd96be55 98fa515d
No related branches found
No related tags found
1 merge request!19Feature/minimum plugin version check demo1
Pipeline #10090 failed
......@@ -12,9 +12,16 @@ if ( ! class_exists( 'WPDesk_Basic_Requirement_Checker' ) ) {
class WPDesk_Basic_Requirement_Checker implements WPDesk_Requirement_Checker {
const EXTENSION_NAME_OPENSSL = 'openssl';
const HOOK_ADMIN_NOTICES_ACTION = 'admin_notices';
const HOOK_PLUGIN_DEACTIVATED_ACTION = 'deactivated_plugin';
const HOOK_PLUGIN_ACTIVATED_ACTION = 'activated_plugin';
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_APPEND_PLUGIN_DATA = 'required_version';
const PLUGIN_INFO_TRANSIENT_NAME = 'require_plugins_data';
const PLUGIN_INFO_TRANSIENT_EXPIRATION_TIME = 16;
/** @var string */
protected $plugin_name;
......@@ -107,13 +114,16 @@ if ( ! class_exists( 'WPDesk_Basic_Requirement_Checker' ) ) {
/**
* @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 ) {
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_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;
......@@ -131,7 +141,7 @@ if ( ! class_exists( 'WPDesk_Basic_Requirement_Checker' ) ) {
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,
'version' => $version,
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
);
......@@ -204,6 +214,7 @@ if ( ! class_exists( 'WPDesk_Basic_Requirement_Checker' ) ) {
$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;
}
......@@ -275,6 +286,74 @@ if ( ! class_exists( 'WPDesk_Basic_Requirement_Checker' ) ) {
return defined( 'OPENSSL_VERSION_NUMBER' ) && OPENSSL_VERSION_NUMBER > (int) $required_version;
}
/**
* @param $notices array
*
* @return array
*/
private function check_minimum_require_plugins_version_and_append_notices( $notices ) {
$required_plugins = $this->retrieve_required_plugins_data();
if ( count( $required_plugins ) > 0 ) {
foreach ( $required_plugins as $plugin ) {
if ( version_compare ( $plugin[ 'Version' ], $plugin[ self::PLUGIN_INFO_APPEND_PLUGIN_DATA ] , '<' ) ) {
$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[ self::PLUGIN_INFO_APPEND_PLUGIN_DATA ], $plugin[ 'Version' ] ) );
}
}
}
return $notices;
}
/**
* Check the plugins directory and retrieve all plugin files with plugin data.
*
* @return array In format [ 'plugindir/pluginfile.php' => ['Name' => 'Plugin Name', 'Version' => '1.0.1', ...], ]
*/
private static function retrieve_plugins_data_in_transient() {
$plugins = get_transient( self::PLUGIN_INFO_TRANSIENT_NAME );
if ( $plugins === false ) {
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;
}
/**
* Check the plugins directory and retrieve all required plugin files with plugin data.
*
* @return array In format [ 'plugindir/pluginfile.php' => ['Name' => 'Plugin Name', 'Version' => '1.0.1', 'required_version' => '1.0.2']... ]
*/
private function retrieve_required_plugins_data() {
$require_plugins = array();
$plugins = self::retrieve_plugins_data_in_transient();
if ( is_array( $plugins ) ) {
if ( count( $plugins ) > 0 ) {
if ( ! empty( $this->plugin_require ) ) {
foreach ( $this->plugin_require as $plugin ) {
$plugin_file_name = $plugin[ self::PLUGIN_INFO_KEY_NAME ];
$plugin_version = $plugin[ self::PLUGIN_INFO_VERSION ];
if ( self::is_wp_plugin_active( $plugin_file_name ) ) {
$require_plugins[ $plugin_file_name ] = $plugins[ $plugin_file_name ];
$require_plugins[ $plugin_file_name ][ self::PLUGIN_INFO_APPEND_PLUGIN_DATA ] = $plugin_version;
}
}
}
}
}
return $require_plugins;
}
/**
* @param array $notices
*
......@@ -390,11 +469,9 @@ if ( ! class_exists( 'WPDesk_Basic_Requirement_Checker' ) ) {
* @return bool
*/
public static function is_wp_plugin_installed( $plugin_file ) {
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . '/wp-admin/includes/plugin.php';
}
$plugins_data = self::retrieve_plugins_data_in_transient();
return array_key_exists( $plugin_file, get_plugins() );
return array_key_exists( $plugin_file, (array)$plugins_data );
}
/**
......@@ -490,7 +567,28 @@ if ( ! class_exists( 'WPDesk_Basic_Requirement_Checker' ) ) {
public function handle_deactivate_action() {
if ( isset( $this->plugin_file ) ) {
deactivate_plugins( plugin_basename( $this->plugin_file ) );
delete_transient( self::PLUGIN_INFO_TRANSIENT_NAME );
}
}
/**
* Triggers the transient delete after plugin deactivated
*
*@return void
*/
public function transient_delete_on_plugin_version_changed() {
add_action( self::HOOK_PLUGIN_DEACTIVATED_ACTION, array( $this, 'handle_transient_delete_action' ) );
add_action( self::HOOK_PLUGIN_ACTIVATED_ACTION, array( $this,'handle_transient_delete_action' ) );
}
/**
* Handles the transient delete
*
* @return void
*/
public function handle_transient_delete_action() {
delete_transient(self::PLUGIN_INFO_TRANSIENT_NAME );
}
/**
......
......@@ -24,7 +24,8 @@ class WPDesk_Basic_Requirement_Checker_Factory {
* @return WPDesk_Requirement_Checker
*/
public function create_requirement_checker( $plugin_file, $plugin_name, $text_domain = null ) {
return new WPDesk_Basic_Requirement_Checker( $plugin_file, $plugin_name, $text_domain, null, null );
return new WPDesk_Basic_Requirement_Checker( $plugin_file, $plugin_name,
$this->initialize_translations( $text_domain ), null, null );
}
/**
......@@ -48,8 +49,10 @@ class WPDesk_Basic_Requirement_Checker_Factory {
if ( isset( $requirements['plugins'] ) ) {
foreach ( $requirements['plugins'] as $requirement ) {
$requirements_checker->add_plugin_require( $requirement['name'], $requirement['nice_name'] );
$requirements_checker->add_plugin_require( $requirement['name'], $requirement['nice_name'], $requirement['version'] );
}
$requirements_checker->transient_delete_on_plugin_version_changed();
}
if ( isset( $requirements['repo_plugins'] ) ) {
......
......@@ -15,11 +15,22 @@ class Test_Basic_Requirement_Checker extends PHPUnit\Framework\TestCase {
const HOOK_TYPE_ACTION = 'action';
const ALWAYS_FUNCTION_EXISTS = 'function_exists';
public function setUp() {
WP_Mock::setUp();
WP_Mock::wpFunction( 'get_bloginfo' )
->andReturn( self::ALWAYS_VALID_WP_VERSION );
WP_Mock::wpFunction( 'get_transient' )
->andReturn( self::ALWAYS_FUNCTION_EXISTS );
WP_Mock::wpFunction('set_transient')
->andReturn( self::ALWAYS_FUNCTION_EXISTS );
WP_Mock::wpFunction( 'delete_transient' )
->andReturn( self::ALWAYS_FUNCTION_EXISTS );
}
public function tearDown() {
......@@ -192,9 +203,15 @@ class Test_Basic_Requirement_Checker extends PHPUnit\Framework\TestCase {
$requirements->add_plugin_repository_require( $activated_plugin_name, $random_version );
$this->assertTrue( $requirements->are_requirements_met(), "Should be met for activated plugin" );
$requirements->add_plugin_require( $activated_plugin_name, $random_version );
$this->assertTrue( $requirements->are_requirements_met(), 'Should be met for required plugins' );
$requirements->add_plugin_repository_require( $not_activated_plugin_name, $random_version );
$this->assertFalse( $requirements->are_requirements_met(), "Should NOT be met for only installed plugin" );
$requirements->add_plugin_require( $not_activated_plugin_name, $random_version );
$this->assertFalse( $requirements->are_requirements_met(), "Should NOT be met for only installed plugin" );
$this->expectOutputRegex( "/Activate $not_activated_plugin_name/" );
$requirements->handle_render_notices_action();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment