Fix LegacyProxy::get_instance_of for classesd having an `instance` method.

Pass the arguments as `...$args` instead of `$args`.
Also fix related unit test, and remove unnecessary `is_function`.
This commit is contained in:
Nestor Soriano 2020-07-21 09:07:50 +02:00
parent bd1e6a5db0
commit 408295720c
4 changed files with 48 additions and 7 deletions

View File

@ -88,7 +88,7 @@ abstract class AbstractServiceProvider extends \League\Container\ServiceProvider
} catch ( \ReflectionException $ex ) { } catch ( \ReflectionException $ex ) {
throw new ContainerException( "AbstractServiceProvider::add_with_auto_arguments: error when reflecting class '$class': {$ex->getMessage()}" ); throw new ContainerException( "AbstractServiceProvider::add_with_auto_arguments: error when reflecting class '$class': {$ex->getMessage()}" );
} }
} elseif ( ! is_object( $concrete ) && ! is_callable( $concrete ) && ! function_exists( $concrete ) ) { } elseif ( ! is_object( $concrete ) && ! is_callable( $concrete ) ) {
throw new ContainerException( 'AbstractServiceProvider::add_with_auto_arguments: concrete must be a valid class name, function name, object, or callable.' ); throw new ContainerException( 'AbstractServiceProvider::add_with_auto_arguments: concrete must be a valid class name, function name, object, or callable.' );
} }

View File

@ -49,7 +49,7 @@ class LegacyProxy {
// If the class is a singleton, use the "instance" method. // If the class is a singleton, use the "instance" method.
if ( method_exists( $class_name, 'instance' ) ) { if ( method_exists( $class_name, 'instance' ) ) {
return $class_name::instance( $args ); return $class_name::instance( ...$args );
} }
// Fallback to simply creating a new instance of the class. // Fallback to simply creating a new instance of the class.

View File

@ -0,0 +1,39 @@
<?php
/**
* ClassWithSingleton class file.
*
* @package Automattic\WooCommerce\Tests\Internal\DependencyManagement\ExampleClasses
*/
// This class is in the root namespace on purpose, since it simulates being a legacy class in the 'includes' directory.
/**
* An example of a class that holds a singleton instance.
*/
class ClassWithSingleton {
/**
* @var ClassWithSingleton The singleton instance of the class.
*/
public static $instance;
/**
* @var array The arguments supplied to 'instance'.
*/
public static $instance_args;
/**
* Gets the singleton instance of the class.
*
* @param mixed ...$args Any arguments required by the method.
*
* @return ClassWithSingleton The singleton instance of the class.
*/
public static function instance( ...$args ) {
if ( is_null( self::$instance ) ) {
self::$instance = new ClassWithSingleton();
self::$instance_args = $args;
}
return self::$instance;
}
}

View File

@ -50,13 +50,15 @@ class LegacyProxyTest extends \WC_Unit_Test_Case {
} }
/** /**
* @testdox 'get_instance_of' uses the 'instance' static method in classes that implement it. * @testdox 'get_instance_of' uses the 'instance' static method in classes that implement it, passing the supplied arguments.
*/ */
public function test_get_instance_of_class_with_instance_method_gets_an_instance_of_the_appropriate_class() { public function test_get_instance_of_class_with_instance_method_gets_an_instance_of_the_appropriate_class() {
$instance1 = $this->sut->get_instance_of( \WooCommerce::class ); // ClassWithSingleton is in the root namespace and thus can't be autoloaded.
$instance2 = $this->sut->get_instance_of( \WooCommerce::class ); require_once dirname( __DIR__ ) . '/Internal/DependencyManagement/ExampleClasses/ClassWithSingleton.php';
$this->assertSame( \WooCommerce::instance(), $instance1 );
$this->assertSame( $instance1, $instance2 ); $instance = $this->sut->get_instance_of( \ClassWithSingleton::class, 'foo', 'bar' );
$this->assertSame( \ClassWithSingleton::$instance, $instance );
$this->assertEquals( array( 'foo', 'bar' ), \ClassWithSingleton::$instance_args );
} }
/** /**