mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2026-10-04 14:47:02 +00:00
Upgrade/Install: Introduce Plugin Dependencies.
Introduces a new "Requires Plugins" plugin header so that plugin developers can list the slugs of the plugins theirs depends on. This will inform users of the requirements, and provide links to the WordPress.org Plugins Repository that they can click to install and activate the dependencies first. Plugins whose requirements are not met cannot be installed or activated, and they will be deactivated automatically if their requirements become unmet. Plugins that others rely on cannot be deactivated or deleted until their dependent plugins are deactivated or deleted. In memory of Alex Mills and Alex King. WordPress Remembers. Props ahoereth, afragen, alanfuller, alexkingorg, amykamala, anonymized_10690803, apeatling, ashfame, atimmer, audrasjb, aristath, azaozz, batmoo, beaulebens, blobaugh, bobbingwide, boonebgorges, brianhenryie, chanthaboune, chrisdavidmiles, coolmann, costdev, courane01, danielbachhuber, davidperez, dd32, Denis-de-Bernardy, dingo_d, DJPaul, dougal, DrewAPicture, ethitter, filosofo, georgestephanis, giuseppemazzapica-1, goldenapples, griffinjt, hellofromTonya, husobj, ideag, jarednova, jbobich, jbrinley, jltallon, joedolson, johnciacia, johnjamesjacoby, joppuyo, jsmoriss, karmatosed, kebbet, knutsp, kraftbj, kraftner, kurtpayne, lkraav, logikal16, luisherranz, man4toman, markjaquith, matt, mbijon, megphillips91, mikeschinkel, mordauk, morehawes, mrwweb, mte90, mukesh27, mzaweb, nacin, norcross, nvwd, nwjames, obliviousharmony, ocean90, oglekler, paaljoachim, pauldewouters, pbaylies, pbiron, peterwilsoncc, Philipp15b, poena, pogidude, retlehs, rmccue, ryan, sabreuse, sc0ttkclark, scribu, sereedmedia, SergeyBiryukov, ShaneF, shidouhikari, soean, spacedmonkey, stephenh1988, swissspidy, taylorde, tazotodua, threadi, TimothyBlynJacobs, TJNowell, tollmanz, toscho, tropicalista, Viper007Bond, westi, whiteshadow, williamsba1, wpsmith, ZaneMatthew. Fixes #22316. git-svn-id: https://develop.svn.wordpress.org/trunk@57545 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* Test case for the Plugin Dependencies tests.
|
||||
*
|
||||
* @package WP_Plugin_Dependencies
|
||||
*
|
||||
* Abstracts the common properties and tasks for the Plugin Dependencies tests.
|
||||
*/
|
||||
abstract class WP_PluginDependencies_UnitTestCase extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Stores an instance of WP_Plugin_Dependencies
|
||||
* for managing property visibility during tests.
|
||||
*
|
||||
* @var WP_Plugin_Dependencies
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* Stores a list of static properties and their default values.
|
||||
* for resetting after each test runs.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $static_properties = array(
|
||||
'plugins' => null,
|
||||
'plugin_dirnames' => null,
|
||||
'dependencies' => null,
|
||||
'dependency_slugs' => null,
|
||||
'dependent_slugs' => null,
|
||||
'dependency_api_data' => null,
|
||||
'dependency_filepaths' => null,
|
||||
'circular_dependencies_pairs' => null,
|
||||
'circular_dependencies_slugs' => null,
|
||||
);
|
||||
|
||||
/**
|
||||
* An array of reflected class members.
|
||||
*
|
||||
* @var ReflectionMethod[]|ReflectionProperty[]
|
||||
*/
|
||||
protected static $reflected_members = array();
|
||||
|
||||
/**
|
||||
* Sets up the WP_Plugin_Dependencies instance before any tests run.
|
||||
*/
|
||||
public static function set_up_before_class() {
|
||||
parent::set_up_before_class();
|
||||
|
||||
self::$instance = new WP_Plugin_Dependencies();
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the '$reflected_members' property after all tests run.
|
||||
*/
|
||||
public static function tear_down_after_class() {
|
||||
self::$reflected_members = array();
|
||||
|
||||
parent::tear_down_after_class();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all static properties to a default value after each test.
|
||||
*/
|
||||
public function set_up() {
|
||||
parent::set_up();
|
||||
|
||||
foreach ( self::$static_properties as $name => $default_value ) {
|
||||
$this->set_property_value( $name, $default_value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily modifies the accessibility of a property to change its value.
|
||||
*
|
||||
* @param string $property The property's name.
|
||||
* @param mixed $value The new value.
|
||||
*/
|
||||
public function set_property_value( $property, $value ) {
|
||||
if ( ! isset( self::$reflected_members[ $property ] ) ) {
|
||||
self::$reflected_members[ $property ] = new ReflectionProperty( self::$instance, $property );
|
||||
}
|
||||
|
||||
self::$reflected_members[ $property ]->setAccessible( true );
|
||||
self::$reflected_members[ $property ]->setValue( self::$instance, $value );
|
||||
self::$reflected_members[ $property ]->setAccessible( false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily modifies the accessibility of a property to get its value.
|
||||
*
|
||||
* @param string $property The property's name.
|
||||
* @return mixed The value of the property.
|
||||
*/
|
||||
public function get_property_value( $property ) {
|
||||
if ( ! isset( self::$reflected_members[ $property ] ) ) {
|
||||
self::$reflected_members[ $property ] = new ReflectionProperty( self::$instance, $property );
|
||||
}
|
||||
|
||||
self::$reflected_members[ $property ]->setAccessible( true );
|
||||
$value = self::$reflected_members[ $property ]->getValue( self::$instance );
|
||||
self::$reflected_members[ $property ]->setAccessible( false );
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily modifies the accessibility of a method to invoke it
|
||||
* and return its result.
|
||||
*
|
||||
* @param string $method The method's name.
|
||||
* @param mixed ...$args Arguments for the method.
|
||||
* @return mixed The result of the method call.
|
||||
*/
|
||||
protected function call_method( $method, ...$args ) {
|
||||
if ( ! isset( self::$reflected_members[ $method ] ) ) {
|
||||
self::$reflected_members[ $method ] = new ReflectionMethod( self::$instance, $method );
|
||||
}
|
||||
|
||||
self::$reflected_members[ $method ]->setAccessible( true );
|
||||
$value = self::$reflected_members[ $method ]->invokeArgs( self::$instance, $args );
|
||||
self::$reflected_members[ $method ]->setAccessible( false );
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::get_dependencies() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::get_dependencies
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_GetDependencies extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that a plugin with no dependencies will return an empty array.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_an_empty_array_when_a_plugin_has_no_dependencies() {
|
||||
$this->assertSame( array(), self::$instance::get_dependencies( 'dependent/dependent.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with dependencies will return an array of dependencies.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_an_array_of_dependencies_when_a_plugin_has_dependencies() {
|
||||
$expected = array( 'dependency', 'dependency2' );
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent/dependent.php' => $expected )
|
||||
);
|
||||
$this->assertSame( $expected, self::$instance::get_dependencies( 'dependent/dependent.php' ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::get_dependency_data() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::get_dependency_data
|
||||
* @covers WP_Plugin_Dependencies::get_dependency_api_data
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_GetDependencyData extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that dependency data is retrieved.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @global string $pagenow The filename of the current screen.
|
||||
*/
|
||||
public function test_should_get_dependency_data() {
|
||||
global $pagenow;
|
||||
|
||||
// Backup $pagenow.
|
||||
$old_pagenow = $pagenow;
|
||||
|
||||
// Ensure is_admin() and screen checks pass.
|
||||
$pagenow = 'plugins.php';
|
||||
set_current_screen( 'plugins.php' );
|
||||
|
||||
$expected = array( 'name' => 'Dependency 1' );
|
||||
$this->set_property_value( 'dependency_api_data', array( 'dependency' => $expected ) );
|
||||
|
||||
$actual = self::$instance::get_dependency_data( 'dependency' );
|
||||
|
||||
// Restore $pagenow.
|
||||
$pagenow = $old_pagenow;
|
||||
|
||||
$this->assertSame( $expected, $actual );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that false is returned when no dependency data exists.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @global string $pagenow The filename of the current screen.
|
||||
*/
|
||||
public function test_should_return_false_when_no_dependency_data_exists() {
|
||||
global $pagenow;
|
||||
|
||||
// Backup $pagenow.
|
||||
$old_pagenow = $pagenow;
|
||||
|
||||
// Ensure is_admin() and screen checks pass.
|
||||
$pagenow = 'plugins.php';
|
||||
set_current_screen( 'plugins.php' );
|
||||
|
||||
$this->set_property_value( 'dependency_api_data', array() );
|
||||
|
||||
$actual = self::$instance::get_dependency_data( 'dependency' );
|
||||
|
||||
// Restore $pagenow.
|
||||
$pagenow = $old_pagenow;
|
||||
|
||||
$this->assertFalse( $actual );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::get_dependency_filepath() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::get_dependency_filepath
|
||||
* @covers WP_Plugin_Dependencies::get_dependency_filepaths
|
||||
* @covers WP_Plugin_Dependencies::get_plugin_dirnames
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_GetDependencyFilepath extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that the expected dependency filepaths are retrieved for installed dependencies.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @dataProvider data_get_dependency_filepath
|
||||
*
|
||||
* @param string[] $dependency_slug The dependency slug.
|
||||
* @param string[] $plugins An array of plugin paths.
|
||||
* @param string|false $expected The expected result.
|
||||
*/
|
||||
public function test_should_return_filepaths_for_installed_dependencies( $dependency_slug, $plugins, $expected ) {
|
||||
$this->set_property_value( 'plugins', $plugins );
|
||||
$this->assertNull( $this->get_property_value( 'dependency_filepaths' ) );
|
||||
self::$instance::initialize();
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
self::$instance::get_dependency_filepath( $dependency_slug ),
|
||||
'The incorrect filepath was returned.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function data_get_dependency_filepath() {
|
||||
return array(
|
||||
'no plugins' => array(
|
||||
'dependency_slug' => 'dependency',
|
||||
'plugins' => array(),
|
||||
'expected' => false,
|
||||
),
|
||||
'a plugin that starts with slug/' => array(
|
||||
'dependency_slug' => 'dependency',
|
||||
'plugins' => array(
|
||||
'dependency-pro/dependency.php' => array( 'RequiresPlugins' => '' ),
|
||||
'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency' ),
|
||||
),
|
||||
'expected' => false,
|
||||
),
|
||||
'a plugin that ends with slug/' => array(
|
||||
'dependency_slugs' => 'dependency',
|
||||
'plugins' => array(
|
||||
'addon-for-dependency/dependency.php' => array( 'RequiresPlugins' => '' ),
|
||||
'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency' ),
|
||||
),
|
||||
'expected' => false,
|
||||
),
|
||||
'a plugin that does not exist' => array(
|
||||
'dependency_slugs' => 'dependency2',
|
||||
'plugins' => array(
|
||||
'dependency/dependency.php' => array( 'RequiresPlugins' => '' ),
|
||||
'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency2' ),
|
||||
),
|
||||
'expected' => false,
|
||||
),
|
||||
'a plugin that exists' => array(
|
||||
'dependency_slugs' => 'dependency',
|
||||
'plugins' => array(
|
||||
'dependency/dependency.php' => array( 'RequiresPlugins' => '' ),
|
||||
'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency' ),
|
||||
),
|
||||
'expected' => 'dependency/dependency.php',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that an existing value for dependency filepaths is returned.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_existing_value_for_dependency_filepaths() {
|
||||
$expected = 'dependency/dependency.php';
|
||||
|
||||
$this->set_property_value( 'dependency_filepaths', array( 'dependency' => $expected ) );
|
||||
|
||||
/*
|
||||
* If existing dependency filepaths are not returned,
|
||||
* they'll be built from this data.
|
||||
*
|
||||
* This data is explicitly set to ensure that no
|
||||
* test plugins ever interfere with this test.
|
||||
*/
|
||||
$this->set_property_value(
|
||||
'dependency_slugs',
|
||||
array( 'dependency', 'dependency2', 'dependency3' )
|
||||
);
|
||||
|
||||
$this->set_property_value(
|
||||
'plugins',
|
||||
array(
|
||||
// This is flipped as paths are stored in the keys.
|
||||
'dependency/dependency.php' => array(),
|
||||
'dependency2/dependency2.php' => array(),
|
||||
'dependency3/dependency3.php' => array(),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSame( $expected, self::$instance::get_dependency_filepath( 'dependency' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that an empty array is returned when
|
||||
* no plugin directory names are stored.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_empty_array_for_no_plugin_dirnames() {
|
||||
$this->set_property_value( 'dependency_slugs', array() );
|
||||
$this->assertFalse( self::$instance::get_dependency_filepath( 'dependency' ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::get_dependency_names() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::get_dependency_names
|
||||
* @covers WP_Plugin_Dependencies::get_dependency_api_data
|
||||
* @covers WP_Plugin_Dependencies::get_dependencies
|
||||
* @covers WP_Plugin_Dependencies::get_dependency_filepaths
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_GetDependencyNames extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that dependency names are retrieved.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @global string $pagenow The filename of the current screen.
|
||||
*/
|
||||
public function test_should_get_dependency_names() {
|
||||
global $pagenow;
|
||||
|
||||
// Backup $pagenow.
|
||||
$old_pagenow = $pagenow;
|
||||
|
||||
// Ensure is_admin() and screen checks pass.
|
||||
$pagenow = 'plugins.php';
|
||||
set_current_screen( 'plugins.php' );
|
||||
|
||||
$this->set_property_value(
|
||||
'plugins',
|
||||
array( 'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency, dependency2' ) )
|
||||
);
|
||||
|
||||
self::$instance::initialize();
|
||||
|
||||
$this->set_property_value(
|
||||
'dependency_filepaths',
|
||||
array(
|
||||
'dependency' => 'dependency/dependency.php',
|
||||
'dependency2' => 'dependency2/dependency2.php',
|
||||
)
|
||||
);
|
||||
|
||||
$this->set_property_value(
|
||||
'dependency_api_data',
|
||||
array(
|
||||
'dependency' => array(
|
||||
'name' => 'Dependency 1',
|
||||
),
|
||||
'dependency2' => array(
|
||||
'name' => 'Dependency 2',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$actual = self::$instance::get_dependency_names( 'dependent/dependent.php' );
|
||||
|
||||
// Restore $pagenow.
|
||||
$pagenow = $old_pagenow;
|
||||
|
||||
$this->assertSame(
|
||||
array(
|
||||
'dependency' => 'Dependency 1',
|
||||
'dependency2' => 'Dependency 2',
|
||||
),
|
||||
$actual
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that dependency slugs are used if their name is not available.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @global string $pagenow The filename of the current screen.
|
||||
*/
|
||||
public function test_should_use_dependency_name_from_file() {
|
||||
global $pagenow;
|
||||
|
||||
// Backup $pagenow.
|
||||
$old_pagenow = $pagenow;
|
||||
|
||||
// Ensure is_admin() and screen checks pass.
|
||||
$pagenow = 'plugins.php';
|
||||
set_current_screen( 'plugins.php' );
|
||||
|
||||
$this->set_property_value(
|
||||
'plugins',
|
||||
array(
|
||||
'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency, dependency2' ),
|
||||
'dependency/dependency.php' => array(
|
||||
'Name' => 'Dependency 1',
|
||||
'RequiresPlugins' => '',
|
||||
),
|
||||
'dependency2/dependency2.php' => array(
|
||||
'Name' => 'Dependency 2',
|
||||
'RequiresPlugins' => '',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
self::$instance::initialize();
|
||||
|
||||
$this->set_property_value(
|
||||
'dependency_filepaths',
|
||||
array(
|
||||
'dependency' => 'dependency/dependency.php',
|
||||
'dependency2' => 'dependency2/dependency2.php',
|
||||
)
|
||||
);
|
||||
|
||||
// The plugins are not in the Plugins repository.
|
||||
$this->set_property_value( 'dependency_api_data', array() );
|
||||
|
||||
$actual = self::$instance::get_dependency_names( 'dependent/dependent.php' );
|
||||
|
||||
// Restore $pagenow.
|
||||
$pagenow = $old_pagenow;
|
||||
|
||||
$this->assertSame(
|
||||
array(
|
||||
'dependency' => 'Dependency 1',
|
||||
'dependency2' => 'Dependency 2',
|
||||
),
|
||||
$actual
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that dependency slugs are used if their name is not available.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @global string $pagenow The filename of the current screen.
|
||||
*/
|
||||
public function test_should_use_dependency_slugs() {
|
||||
global $pagenow;
|
||||
|
||||
// Backup $pagenow.
|
||||
$old_pagenow = $pagenow;
|
||||
|
||||
// Ensure is_admin() and screen checks pass.
|
||||
$pagenow = 'plugins.php';
|
||||
set_current_screen( 'plugins.php' );
|
||||
|
||||
$this->set_property_value(
|
||||
'plugins',
|
||||
array( 'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency, dependency2' ) )
|
||||
);
|
||||
|
||||
self::$instance::initialize();
|
||||
|
||||
// The plugins are not in the Plugins repository.
|
||||
$this->set_property_value( 'dependency_api_data', array() );
|
||||
|
||||
$actual = self::$instance::get_dependency_names( 'dependent/dependent.php' );
|
||||
|
||||
// Restore $pagenow.
|
||||
$pagenow = $old_pagenow;
|
||||
|
||||
$this->assertSame(
|
||||
array(
|
||||
'dependency' => 'dependency',
|
||||
'dependency2' => 'dependency2',
|
||||
),
|
||||
$actual
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that `$dependency_api_data` is set when it's not already available.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @global string $pagenow The filename of the current screen.
|
||||
*/
|
||||
public function test_should_set_dependency_data_when_not_already_available() {
|
||||
global $pagenow;
|
||||
|
||||
// Backup $pagenow.
|
||||
$old_pagenow = $pagenow;
|
||||
|
||||
// Ensure is_admin() and screen checks pass.
|
||||
$pagenow = 'plugins.php';
|
||||
set_current_screen( 'plugins.php' );
|
||||
|
||||
$this->set_property_value(
|
||||
'plugins',
|
||||
array(
|
||||
'dependent/dependent.php' => array(
|
||||
'Name' => 'Dependent 1',
|
||||
'RequiresPlugins' => 'dependency',
|
||||
),
|
||||
'dependency/dependency.php' => array(
|
||||
'Name' => 'Dependency 1',
|
||||
'RequiresPlugins' => '',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$this->set_property_value( 'dependency_slugs', array( 'dependency' ) );
|
||||
|
||||
set_site_transient( 'wp_plugin_dependencies_plugin_data', array( 'dependency' => false ) );
|
||||
set_site_transient( 'wp_plugin_dependencies_plugin_timeout_dependency', true, 12 * HOUR_IN_SECONDS );
|
||||
self::$instance::get_dependency_names( 'dependent' );
|
||||
|
||||
// Restore $pagenow.
|
||||
$pagenow = $old_pagenow;
|
||||
|
||||
$this->assertSame(
|
||||
array( 'dependency' => array( 'Name' => 'Dependency 1' ) ),
|
||||
$this->get_property_value( 'dependency_api_data' )
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::get_dependent_filepath() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::get_dependent_filepath
|
||||
* @covers WP_Plugin_Dependencies::get_plugin_dirnames
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_GetDependentFilepath extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that the expected dependent filepath is retrieved.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @dataProvider data_get_dependent_filepath
|
||||
*
|
||||
* @param string $dependent_slug The dependent slug.
|
||||
* @param string[] $plugins An array of plugin data.
|
||||
* @param string|false $expected The expected result.
|
||||
*/
|
||||
public function test_should_return_filepaths_for_installed_dependents( $dependent_slug, $plugins, $expected ) {
|
||||
$this->set_property_value( 'plugins', $plugins );
|
||||
self::$instance::initialize();
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
self::$instance::get_dependent_filepath( $dependent_slug ),
|
||||
'The incorrect filepath was returned.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function data_get_dependent_filepath() {
|
||||
return array(
|
||||
'a plugin that exists' => array(
|
||||
'dependent_slug' => 'dependent',
|
||||
'plugins' => array( 'dependent/dependent.php' => array( 'RequiresPlugins' => 'woocommerce' ) ),
|
||||
'expected' => 'dependent/dependent.php',
|
||||
),
|
||||
'no plugins' => array(
|
||||
'dependent_slug' => 'dependent',
|
||||
'plugins' => array(),
|
||||
'expected' => false,
|
||||
),
|
||||
'a plugin that starts with slug/' => array(
|
||||
'dependent_slug' => 'dependent',
|
||||
'plugins' => array( 'dependent-pro/dependent.php' => array( 'RequiresPlugins' => 'woocommerce' ) ),
|
||||
'expected' => false,
|
||||
),
|
||||
'a plugin that ends with slug/' => array(
|
||||
'dependent_slug' => 'dependent',
|
||||
'plugins' => array( 'not-dependent/not-dependent.php' => array( 'RequiresPlugins' => 'woocommerce' ) ),
|
||||
'expected' => false,
|
||||
),
|
||||
'a plugin that does not exist' => array(
|
||||
'dependent_slug' => 'dependent2',
|
||||
'plugins' => array( 'dependent/dependent.php' => array( 'RequiresPlugins' => 'woocommerce' ) ),
|
||||
'expected' => false,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::get_dependent_names() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::get_dependent_names
|
||||
* @covers WP_Plugin_Dependencies::get_plugins
|
||||
* @covers WP_Plugin_Dependencies::convert_to_slug
|
||||
* @covers WP_Plugin_Dependencies::get_dependents
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_GetDependentNames extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that dependent names are retrieved.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_get_dependent_names() {
|
||||
$this->set_property_value(
|
||||
'plugins',
|
||||
array(
|
||||
'dependent/dependent.php' => array(
|
||||
'Name' => 'Dependent 1',
|
||||
'RequiresPlugins' => 'dependency',
|
||||
),
|
||||
'dependent2/dependent2.php' => array(
|
||||
'Name' => 'Dependent 2',
|
||||
'RequiresPlugins' => 'dependency',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
self::$instance::initialize();
|
||||
|
||||
$this->assertSame(
|
||||
array( 'Dependent 1', 'Dependent 2' ),
|
||||
self::$instance::get_dependent_names( 'dependency/dependency.php' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that dependent names are sorted.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_sort_dependent_names() {
|
||||
$this->set_property_value(
|
||||
'plugins',
|
||||
array(
|
||||
'dependent2/dependent2.php' => array(
|
||||
'Name' => 'Dependent 2',
|
||||
'RequiresPlugins' => 'dependency',
|
||||
),
|
||||
'dependent/dependent.php' => array(
|
||||
'Name' => 'Dependent 1',
|
||||
'RequiresPlugins' => 'dependency',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
self::$instance::initialize();
|
||||
|
||||
$this->assertSame(
|
||||
array( 'Dependent 1', 'Dependent 2' ),
|
||||
self::$instance::get_dependent_names( 'dependency/dependency.php' )
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::get_dependents() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::get_dependents
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_GetDependents extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that a plugin with no dependents will return an empty array.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_an_empty_array_when_a_plugin_has_no_dependents() {
|
||||
self::$instance::initialize();
|
||||
$this->assertSame(
|
||||
array(),
|
||||
self::$instance::get_dependents( 'dependency' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with dependents will return an array of dependents.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_an_array_of_dependents_when_a_plugin_has_dependents() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array(
|
||||
'dependent/dependent.php' => array( 'dependency' ),
|
||||
'dependent2/dependent2.php' => array( 'dependency' ),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
array( 'dependent/dependent.php', 'dependent2/dependent2.php' ),
|
||||
self::$instance::get_dependents( 'dependency' )
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::has_active_dependents() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::has_active_dependents
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_HasActiveDependents extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that a plugin with no dependents will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_false_when_a_plugin_has_no_dependents() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent/dependent.php' => array( 'dependency' ) )
|
||||
);
|
||||
|
||||
update_option( 'active_plugins', array( 'dependent/dependent.php' ) );
|
||||
|
||||
$this->assertFalse( self::$instance::has_active_dependents( 'dependency2/dependency2.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with active dependents will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_a_plugin_has_active_dependents() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent/dependent.php' => array( 'dependency' ) )
|
||||
);
|
||||
|
||||
update_option( 'active_plugins', array( 'dependent/dependent.php' ) );
|
||||
|
||||
$this->assertTrue( self::$instance::has_active_dependents( 'dependency/dependency.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with one inactive and one active dependent will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_a_plugin_has_one_inactive_and_one_active_dependent() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array(
|
||||
'dependent2/dependent2.php' => array( 'dependency' ),
|
||||
'dependent/dependent.php' => array( 'dependency' ),
|
||||
)
|
||||
);
|
||||
|
||||
update_option( 'active_plugins', array( 'dependent/dependent.php' ) );
|
||||
|
||||
$this->assertTrue( self::$instance::has_active_dependents( 'dependency/dependency.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with one active and one inactive dependent will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_a_plugin_has_one_active_and_one_inactive_dependent() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array(
|
||||
'dependent/dependent.php' => array( 'dependency' ),
|
||||
'dependent2/dependent2.php' => array( 'dependency' ),
|
||||
)
|
||||
);
|
||||
|
||||
update_option( 'active_plugins', array( 'dependent/dependent.php' ) );
|
||||
|
||||
$this->assertTrue( self::$instance::has_active_dependents( 'dependency/dependency.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that when a plugin with active dependents is earlier in the list,
|
||||
* it will return true if a later plugin has no active dependents.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_the_earlier_plugin_has_active_dependents_but_the_later_plugin_does_not() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent2/dependent2.php' => array( 'dependency' ) )
|
||||
);
|
||||
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array(
|
||||
'dependent/dependent.php' => array( 'dependency' ),
|
||||
'dependent2/dependent2.php' => array( 'dependency2' ),
|
||||
)
|
||||
);
|
||||
|
||||
update_option( 'active_plugins', array( 'dependent/dependent.php' ) );
|
||||
|
||||
$this->assertTrue( self::$instance::has_active_dependents( 'dependency/dependency.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that when a plugin with active dependents is later in the list,
|
||||
* it will return true if an earlier plugin has no active dependents.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_the_later_plugin_has_active_dependents_but_the_earlier_plugin_does_not() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent2/dependent2.php' => array( 'dependency' ) )
|
||||
);
|
||||
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array(
|
||||
'dependent/dependent.php' => array( 'dependency' ),
|
||||
'dependent2/dependent2.php' => array( 'dependency2' ),
|
||||
)
|
||||
);
|
||||
|
||||
update_option( 'active_plugins', array( 'dependent2/dependent2.php' ) );
|
||||
|
||||
$this->assertTrue( self::$instance::has_active_dependents( 'dependency2/dependency2.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with no dependents will return false.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_false_when_a_plugin_has_no_active_dependents() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent/dependent.php' => array( 'dependency' ) )
|
||||
);
|
||||
|
||||
$this->assertFalse( self::$instance::has_active_dependents( 'dependency/dependency.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that when a plugin with no active dependents is earlier in the list,
|
||||
* it will return false if a later plugin has active dependents.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_false_when_the_earlier_plugin_has_no_active_dependents_but_the_later_plugin_does() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent2/dependent2.php' => array( 'dependency' ) )
|
||||
);
|
||||
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array(
|
||||
'dependent/dependent.php' => array( 'dependency' ),
|
||||
'dependent2/dependent2.php' => array( 'dependency2' ),
|
||||
)
|
||||
);
|
||||
|
||||
update_option( 'active_plugins', array( 'dependent2/dependent2.php' ) );
|
||||
|
||||
$this->assertFalse( self::$instance::has_active_dependents( 'dependency/dependency.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that when a plugin with no active dependents is later in the list,
|
||||
* it will return false if an earlier plugin has active dependents.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_false_when_the_later_plugin_has_no_active_dependents_but_the_earlier_plugin_does() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent2/dependent2.php' => array( 'dependency' ) )
|
||||
);
|
||||
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array(
|
||||
'dependent/dependent.php' => array( 'dependency' ),
|
||||
'dependent2/dependent2.php' => array( 'dependency2' ),
|
||||
)
|
||||
);
|
||||
|
||||
update_option( 'active_plugins', array( 'dependent/dependent.php' ) );
|
||||
|
||||
$this->assertFalse( self::$instance::has_active_dependents( 'dependency2/dependency2.php' ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::has_circular_dependency() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::has_circular_dependency
|
||||
* @covers WP_Plugin_Dependencies::get_circular_dependencies
|
||||
* @covers WP_Plugin_Dependencies::check_for_circular_dependencies
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_HasCircularDependency extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that a plugin with a circular dependency will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @dataProvider data_circular_dependencies
|
||||
*
|
||||
* @param string $plugin_to_check The plugin file of the plugin to check.
|
||||
* @param array[] $plugins An array of plugins.
|
||||
*/
|
||||
public function test_should_return_true_when_a_plugin_has_circular_dependency( $plugin_to_check, $plugins ) {
|
||||
$this->set_property_value( 'plugins', $plugins );
|
||||
self::$instance::initialize();
|
||||
|
||||
$this->assertTrue( self::$instance::has_circular_dependency( $plugin_to_check ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function data_circular_dependencies() {
|
||||
return array(
|
||||
'a plugin that depends on itself' => array(
|
||||
'plugin_to_check' => 'dependency/dependency.php',
|
||||
'plugins' => array(
|
||||
'dependency/dependency.php' => array(
|
||||
'Name' => 'Dependency 1',
|
||||
'RequiresPlugins' => 'dependency',
|
||||
),
|
||||
),
|
||||
),
|
||||
'two plugins' => array(
|
||||
'plugin_to_check' => 'dependency/dependency.php',
|
||||
'plugins' => array(
|
||||
'dependency/dependency.php' => array(
|
||||
'Name' => 'Dependency 1',
|
||||
'RequiresPlugins' => 'dependency2',
|
||||
),
|
||||
'dependency2/dependency2.php' => array(
|
||||
'Name' => 'Dependency 2',
|
||||
'RequiresPlugins' => 'dependency',
|
||||
),
|
||||
),
|
||||
),
|
||||
'three plugins' => array(
|
||||
'plugin_to_check' => 'dependency/dependency.php',
|
||||
'plugins' => array(
|
||||
'dependency/dependency.php' => array(
|
||||
'Name' => 'Dependency 1',
|
||||
'RequiresPlugins' => 'dependency2',
|
||||
),
|
||||
'dependency2/dependency2.php' => array(
|
||||
'Name' => 'Dependency 2',
|
||||
'RequiresPlugins' => 'dependency3',
|
||||
),
|
||||
'dependency3/dependency3.php' => array(
|
||||
'Name' => 'Dependency 3',
|
||||
'RequiresPlugins' => 'dependency',
|
||||
),
|
||||
),
|
||||
),
|
||||
'four plugins' => array(
|
||||
'plugin_to_check' => 'dependency/dependency.php',
|
||||
'plugins' => array(
|
||||
'dependency/dependency.php' => array(
|
||||
'Name' => 'Dependency 1',
|
||||
'RequiresPlugins' => 'dependency4',
|
||||
),
|
||||
'dependency2/dependency2.php' => array(
|
||||
'Name' => 'Dependency 2',
|
||||
'RequiresPlugins' => 'dependency3',
|
||||
),
|
||||
'dependency3/dependency3.php' => array(
|
||||
'Name' => 'Dependency 3',
|
||||
'RequiresPlugins' => 'dependency',
|
||||
),
|
||||
'dependency4/dependency4.php' => array(
|
||||
'Name' => 'Dependency 4',
|
||||
'RequiresPlugins' => 'dependency2',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with no circular dependencies will return false.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_false_when_a_plugin_has_no_circular_dependency() {
|
||||
$this->set_property_value(
|
||||
'plugins',
|
||||
array(
|
||||
'dependency/dependency.php' => array(
|
||||
'Name' => 'Dependency 1',
|
||||
'RequiresPlugins' => 'dependency2',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
self::$instance::initialize();
|
||||
|
||||
$this->assertFalse( self::$instance::has_circular_dependency( 'dependent/dependent.php' ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::has_dependencies() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::has_dependencies
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_HasDependencies extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that a plugin with dependencies will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_a_plugin_has_dependencies() {
|
||||
$this->set_property_value( 'dependencies', array( 'dependent/dependent.php' => array() ) );
|
||||
$this->assertTrue( self::$instance::has_dependencies( 'dependent/dependent.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with no dependencies will return false.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_false_when_a_plugin_has_no_dependencies() {
|
||||
$this->set_property_value( 'dependencies', array( 'dependent2/dependent2.php' => array() ) );
|
||||
$this->assertFalse( self::$instance::has_dependencies( 'dependent/dependent.php' ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::has_dependents() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::has_dependents
|
||||
* @covers WP_Plugin_Dependencies::convert_to_slug
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_HasDependents extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that a plugin with dependents will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_a_plugin_has_dependents() {
|
||||
$this->set_property_value( 'dependency_slugs', array( 'dependent' ) );
|
||||
$this->assertTrue( self::$instance::has_dependents( 'dependent/dependent.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a single file plugin with dependents will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_a_single_file_plugin_has_dependents() {
|
||||
$this->set_property_value( 'dependency_slugs', array( 'dependent' ) );
|
||||
$this->assertTrue( self::$instance::has_dependents( 'dependent.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with no dependents will return false.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_false_when_a_plugin_has_no_dependents() {
|
||||
$this->set_property_value( 'dependency_slugs', array( 'dependent2' ) );
|
||||
$this->assertFalse( self::$instance::has_dependents( 'dependent/dependent.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that 'hello.php' is converted to 'hello-dolly'.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_convert_hellophp_to_hello_dolly() {
|
||||
$this->set_property_value( 'dependency_slugs', array( 'hello-dolly' ) );
|
||||
$this->assertTrue( self::$instance::has_dependents( 'hello.php' ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::has_unmet_dependencies() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::has_unmet_dependencies
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_HasUnmetDependencies extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that a plugin with no dependencies will return false.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_false_when_a_plugin_has_no_dependencies() {
|
||||
$this->set_property_value( 'dependencies', array( 'dependent/dependent.php' => array( 'dependency' ) ) );
|
||||
$this->assertFalse( self::$instance::has_unmet_dependencies( 'dependent2/dependent2.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin whose dependencies are installed and active will return false.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_false_when_a_plugin_has_no_unmet_dependencies() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent/dependent.php' => array( 'dependency' ) )
|
||||
);
|
||||
|
||||
$this->set_property_value(
|
||||
'dependency_filepaths',
|
||||
array( 'dependency' => 'dependency/dependency.php' )
|
||||
);
|
||||
|
||||
update_option( 'active_plugins', array( 'dependency/dependency.php' ) );
|
||||
|
||||
$this->assertFalse( self::$instance::has_unmet_dependencies( 'dependent/dependent.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with a dependency that is not installed will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_a_plugin_has_a_dependency_that_is_not_installed() {
|
||||
self::$instance::initialize();
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent/dependent.php' => array( 'dependency' ) )
|
||||
);
|
||||
|
||||
$this->assertTrue( self::$instance::has_unmet_dependencies( 'dependent/dependent.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with a dependency that is inactive will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_a_plugin_has_a_dependency_that_is_inactive() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent/dependent.php' => array( 'dependency' ) )
|
||||
);
|
||||
|
||||
$this->set_property_value(
|
||||
'dependency_filepaths',
|
||||
array( 'dependency' => 'dependency/dependency.php' )
|
||||
);
|
||||
|
||||
$this->assertTrue( self::$instance::has_unmet_dependencies( 'dependent/dependent.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with one dependency that is active and one dependency that is inactive will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_a_plugin_has_one_active_dependency_and_one_inactive_dependency() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent/dependent.php' => array( 'dependency', 'dependency2' ) )
|
||||
);
|
||||
|
||||
$this->set_property_value(
|
||||
'dependency_filepaths',
|
||||
array(
|
||||
'dependency' => 'dependency/dependency.php',
|
||||
'dependency2' => 'dependency2/dependency2.php',
|
||||
)
|
||||
);
|
||||
|
||||
update_option( 'active_plugins', array( 'dependency/dependency.php' ) );
|
||||
|
||||
$this->assertTrue( self::$instance::has_unmet_dependencies( 'dependent/dependent.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with one dependency that is active and one dependency that is not installed will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_a_plugin_has_one_active_dependency_and_one_that_is_not_installed() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent/dependent.php' => array( 'dependency', 'dependency2' ) )
|
||||
);
|
||||
|
||||
$this->set_property_value(
|
||||
'dependency_filepaths',
|
||||
array( 'dependency' => 'dependency/dependency.php' )
|
||||
);
|
||||
|
||||
update_option( 'active_plugins', array( 'dependency/dependency.php' ) );
|
||||
|
||||
$this->assertTrue( self::$instance::has_unmet_dependencies( 'dependent/dependent.php' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a plugin with one dependency that is inactive and one dependency that is not installed will return true.
|
||||
*
|
||||
* @ticket 22316
|
||||
*/
|
||||
public function test_should_return_true_when_a_plugin_has_one_inactive_dependency_and_one_that_is_not_installed() {
|
||||
$this->set_property_value(
|
||||
'dependencies',
|
||||
array( 'dependent/dependent.php' => array( 'dependency', 'dependency2' ) )
|
||||
);
|
||||
|
||||
$this->set_property_value(
|
||||
'dependency_filepaths',
|
||||
array( 'dependency' => 'dependency/dependency.php' )
|
||||
);
|
||||
|
||||
$this->assertTrue( self::$instance::has_unmet_dependencies( 'dependent/dependent.php' ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the WP_Plugin_Dependencies::initialize() method.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* @group admin
|
||||
* @group plugins
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::initialize
|
||||
*/
|
||||
class Tests_Admin_WPPluginDependencies_Initialize extends WP_PluginDependencies_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that `$dependency_api_data` is set on certain screens.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::get_dependency_api_data
|
||||
* @covers WP_Plugin_Dependencies::get_plugins
|
||||
*
|
||||
* @dataProvider data_screens
|
||||
*
|
||||
* @global string $pagenow The filename of the current screen.
|
||||
*
|
||||
* @param string $screen The screen file.
|
||||
*/
|
||||
public function test_should_set_dependency_api_data_on_certain_screens( $screen ) {
|
||||
global $pagenow;
|
||||
|
||||
// Backup $pagenow.
|
||||
$old_pagenow = $pagenow;
|
||||
|
||||
// Ensure is_admin() and screen checks pass.
|
||||
$pagenow = $screen;
|
||||
set_current_screen( $screen );
|
||||
|
||||
self::$instance::initialize();
|
||||
|
||||
// Restore $pagenow.
|
||||
$pagenow = $old_pagenow;
|
||||
|
||||
$dependency_api_data = $this->get_property_value( 'dependency_api_data' );
|
||||
|
||||
$this->assertIsArray( $dependency_api_data, '$dependency_api_data is not an array.' );
|
||||
$this->assertEmpty( $dependency_api_data, '$dependency_api_data is not empty.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function data_screens() {
|
||||
return array(
|
||||
'plugins.php' => array(
|
||||
'screen' => 'plugins.php',
|
||||
),
|
||||
'plugin-install.php' => array(
|
||||
'screen' => 'plugin-install.php',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that `$dependency_api_data` is not set by default.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::get_dependency_api_data
|
||||
*/
|
||||
public function test_should_not_set_dependency_api_data() {
|
||||
self::$instance::initialize();
|
||||
|
||||
$dependency_api_data = $this->get_property_value( 'dependency_api_data' );
|
||||
|
||||
$this->assertNull( $dependency_api_data, '$dependency_api_data was set.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that dependency slugs are loaded and sanitized.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::read_dependencies_from_plugin_headers
|
||||
* @covers WP_Plugin_Dependencies::sanitize_dependency_slugs
|
||||
*
|
||||
* @dataProvider data_should_sanitize_slugs
|
||||
*
|
||||
* @param string $requires_plugins The unsanitized dependency slug(s).
|
||||
* @param array $expected Optional. The sanitized dependency slug(s). Default empty array.
|
||||
*/
|
||||
public function test_initialize_should_load_and_sanitize_dependency_slugs_from_plugin_headers( $requires_plugins, $expected = array() ) {
|
||||
$this->set_property_value( 'plugins', array( 'dependent/dependent.php' => array( 'RequiresPlugins' => $requires_plugins ) ) );
|
||||
self::$instance->initialize();
|
||||
$this->assertSame( $expected, $this->get_property_value( 'dependency_slugs' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function data_should_sanitize_slugs() {
|
||||
return array(
|
||||
// Valid slugs.
|
||||
'one dependency' => array(
|
||||
'requires_plugins' => 'hello-dolly',
|
||||
'expected' => array( 'hello-dolly' ),
|
||||
),
|
||||
'two dependencies in alphabetical order' => array(
|
||||
'requires_plugins' => 'hello-dolly, woocommerce',
|
||||
'expected' => array(
|
||||
'hello-dolly',
|
||||
'woocommerce',
|
||||
),
|
||||
),
|
||||
'two dependencies in reverse alphabetical order' => array(
|
||||
'requires_plugins' => 'woocommerce, hello-dolly',
|
||||
'expected' => array(
|
||||
'hello-dolly',
|
||||
'woocommerce',
|
||||
),
|
||||
),
|
||||
'two dependencies with a space' => array(
|
||||
'requires_plugins' => 'hello-dolly , woocommerce',
|
||||
'expected' => array(
|
||||
'hello-dolly',
|
||||
'woocommerce',
|
||||
),
|
||||
),
|
||||
'a repeated dependency' => array(
|
||||
'requires_plugins' => 'hello-dolly, woocommerce, hello-dolly',
|
||||
'expected' => array(
|
||||
'hello-dolly',
|
||||
'woocommerce',
|
||||
),
|
||||
),
|
||||
'a dependency with multiple dashes' => array(
|
||||
'requires_plugins' => 'this-is-a-valid-slug',
|
||||
'expected' => array( 'this-is-a-valid-slug' ),
|
||||
),
|
||||
'a dependency starting with numbers' => array(
|
||||
'requires_plugins' => '123slug',
|
||||
'expected' => array( '123slug' ),
|
||||
),
|
||||
'a dependency with a trailing comma' => array(
|
||||
'requires_plugins' => 'hello-dolly,',
|
||||
'expected' => array( 'hello-dolly' ),
|
||||
),
|
||||
'a dependency with a leading comma' => array(
|
||||
'requires_plugins' => ',hello-dolly',
|
||||
'expected' => array( 'hello-dolly' ),
|
||||
),
|
||||
'a dependency with leading and trailing commas' => array(
|
||||
'requires_plugins' => ',hello-dolly,',
|
||||
'expected' => array( 'hello-dolly' ),
|
||||
),
|
||||
'a dependency with a trailing comma and a space' => array(
|
||||
'requires_plugins' => 'hello-dolly, ',
|
||||
'expected' => array( 'hello-dolly' ),
|
||||
),
|
||||
|
||||
// Invalid or empty slugs.
|
||||
'no dependencies' => array(
|
||||
'requires_plugins' => '',
|
||||
),
|
||||
'a dependency with an underscore' => array(
|
||||
'requires_plugins' => 'hello_dolly',
|
||||
),
|
||||
'a dependency with a space' => array(
|
||||
'requires_plugins' => 'hello dolly',
|
||||
),
|
||||
'a dependency in quotes' => array(
|
||||
'requires_plugins' => '"hello-dolly"',
|
||||
),
|
||||
'two dependencies in quotes' => array(
|
||||
'requires_plugins' => '"hello-dolly, woocommerce"',
|
||||
),
|
||||
'a dependency with trailing dash' => array(
|
||||
'requires_plugins' => 'ending-dash-',
|
||||
),
|
||||
'a dependency with leading dash' => array(
|
||||
'requires_plugins' => '-slug',
|
||||
),
|
||||
'a dependency with double dashes' => array(
|
||||
'requires_plugins' => 'abc--123',
|
||||
),
|
||||
'cyrillic dependencies' => array(
|
||||
'requires_plugins' => 'я-делюсь',
|
||||
),
|
||||
'arabic dependencies' => array(
|
||||
'requires_plugins' => 'لينوكس-ويكى',
|
||||
),
|
||||
'chinese dependencies' => array(
|
||||
'requires_plugins' => '唐诗宋词chinese-poem,社交登录,腾讯微博一键登录,豆瓣秀-for-wordpress',
|
||||
),
|
||||
'symbol dependencies' => array(
|
||||
'requires_plugins' => '★-wpsymbols-★',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that dependent files are loaded and slugified.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::read_dependencies_from_plugin_headers
|
||||
* @covers WP_Plugin_Dependencies::convert_to_slug
|
||||
*/
|
||||
public function test_should_slugify_dependent_files() {
|
||||
$plugins = get_plugins();
|
||||
|
||||
$expected_slugs = array();
|
||||
foreach ( $plugins as $plugin_file => &$headers ) {
|
||||
// Create the expected slugs.
|
||||
if ( 'hello.php' === $plugin_file ) {
|
||||
$slug = 'hello-dolly';
|
||||
} else {
|
||||
$slug = str_replace( '.php', '', explode( '/', $plugin_file )[0] );
|
||||
}
|
||||
|
||||
$expected_slugs[ $plugin_file ] = $slug;
|
||||
|
||||
// While here, ensure the plugins are all dependents.
|
||||
$headers['RequiresPlugins'] = 'dependency';
|
||||
}
|
||||
unset( $headers );
|
||||
|
||||
// Set the plugins property with the plugin data modified to make them dependents.
|
||||
$this->set_property_value( 'plugins', $plugins );
|
||||
|
||||
self::$instance->initialize();
|
||||
$this->assertSame( $expected_slugs, $this->get_property_value( 'dependent_slugs' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that dependents with unmet dependencies are deactivated.
|
||||
*
|
||||
* @ticket 22316
|
||||
*
|
||||
* @covers WP_Plugin_Dependencies::deactivate_dependents_with_unmet_dependencies
|
||||
* @covers WP_Plugin_Dependencies::has_unmet_dependencies
|
||||
* @covers WP_Plugin_Dependencies::get_active_dependents_in_dependency_tree
|
||||
*
|
||||
* @dataProvider data_should_only_deactivate_dependents_with_unmet_dependencies
|
||||
*
|
||||
* @param array $active_plugins An array of active plugin paths.
|
||||
* @param array $plugins An array of installed plugins.
|
||||
* @param array $expected The expected value of 'active_plugins' after initialization.
|
||||
*/
|
||||
public function test_should_deactivate_dependents_with_uninstalled_dependencies( $active_plugins, $plugins, $expected ) {
|
||||
update_option( 'active_plugins', $active_plugins );
|
||||
|
||||
$this->set_property_value( 'plugins', $plugins );
|
||||
self::$instance::initialize();
|
||||
|
||||
$this->assertSame( $expected, array_values( get_option( 'active_plugins', array() ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function data_should_only_deactivate_dependents_with_unmet_dependencies() {
|
||||
return array(
|
||||
'a dependent with an uninstalled dependency' => array(
|
||||
'active_plugins' => array( 'dependent/dependent.php' ),
|
||||
'plugins' => array(
|
||||
'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency' ),
|
||||
),
|
||||
'expected' => array(),
|
||||
),
|
||||
'a dependent with an inactive dependency' => array(
|
||||
'active_plugins' => array( 'dependent/dependent.php' ),
|
||||
'plugins' => array(
|
||||
'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency' ),
|
||||
'dependency/dependency.php' => array( 'RequiresPlugins' => '' ),
|
||||
),
|
||||
'expected' => array(),
|
||||
),
|
||||
'a dependent with two dependencies, one uninstalled, one inactive' => array(
|
||||
'active_plugins' => array( 'dependent/dependent.php' ),
|
||||
'plugins' => array(
|
||||
'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency, dependency2' ),
|
||||
'dependency2/dependency2.php' => array( 'RequiresPlugins' => '' ),
|
||||
),
|
||||
'expected' => array(),
|
||||
),
|
||||
'a dependent with a dependency that is installed and active' => array(
|
||||
'active_plugins' => array( 'dependent/dependent.php', 'dependency/dependency.php' ),
|
||||
'plugins' => array(
|
||||
'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency' ),
|
||||
'dependency/dependency.php' => array( 'RequiresPlugins' => '' ),
|
||||
),
|
||||
'expected' => array( 'dependent/dependent.php', 'dependency/dependency.php' ),
|
||||
),
|
||||
'one dependent with two dependencies that are installed and active' => array(
|
||||
'active_plugins' => array(
|
||||
'dependent/dependent.php',
|
||||
'dependency/dependency.php',
|
||||
'dependency2/dependency2.php',
|
||||
),
|
||||
'plugins' => array(
|
||||
'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency, dependency2' ),
|
||||
'dependency/dependency.php' => array( 'RequiresPlugins' => '' ),
|
||||
'dependency2/dependency2.php' => array( 'RequiresPlugins' => '' ),
|
||||
),
|
||||
'expected' => array(
|
||||
'dependent/dependent.php',
|
||||
'dependency/dependency.php',
|
||||
'dependency2/dependency2.php',
|
||||
),
|
||||
),
|
||||
'two dependents, one with an uninstalled dependency, and one with an active dependency' => array(
|
||||
'active_plugins' => array(
|
||||
'dependent/dependent.php',
|
||||
'dependent2/dependent2.php',
|
||||
'dependency2/dependency2.php',
|
||||
),
|
||||
'plugins' => array(
|
||||
'dependent/dependent.php' => array( 'RequiresPlugins' => 'dependency' ),
|
||||
'dependent2/dependent2.php' => array( 'RequiresPlugins' => 'dependency2' ),
|
||||
'dependency2/dependency2.php' => array( 'RequiresPlugins' => '' ),
|
||||
),
|
||||
'expected' => array( 'dependent2/dependent2.php', 'dependency2/dependency2.php' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user