Skip to content
This repository has been archived by the owner on Feb 6, 2020. It is now read-only.

Commit

Permalink
Adds the InvokableFactory
Browse files Browse the repository at this point in the history
Most of the component refactors are complete, and will need to be re-done.
However, one item that should likely be retained is usage of the `InvokableFactory`
for invokable instances. This patch adds that factory to the v2 series,
having it implement `Zend\ServiceManager\FactoryInterface`, but retaining the
defined invokable method from v3. It raises an exception if the `$requestedName`
is not provided, ensuring that any tests against the functionality are using
a `ServiceManager` instance.
  • Loading branch information
weierophinney committed Jan 7, 2016
1 parent 3fd0ca3 commit c0655c0
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 0 deletions.
67 changes: 67 additions & 0 deletions src/Factory/InvokableFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\ServiceManager\Factory;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Exception\InvalidServiceNameException;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
* Factory for instantiating classes with no dependencies or which accept a single array.
*
* The InvokableFactory can be used for any class that:
*
* - has no constructor arguments;
* - accepts a single array of arguments via the constructor.
*
* It replaces the "invokables" and "invokable class" functionality of the v2
* service manager, and can also be used in v2 code for forwards compatibility
* with v3.
*/
final class InvokableFactory implements FactoryInterface
{
/**
* Create an instance of the requested class name.
*
* @param ContainerInterface $container
* @param string $requestedName
* @param null|array $options
* @return object
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return (null === $options) ? new $requestedName : new $requestedName($options);
}

/**
* Create an instance of the named service.
*
* If `$requestedName` is not provided, raises an exception; otherwise,
* proxies to the `__invoke()` method to create an instance of the
* requested class.
*
* @param ServiceLocatorInterface $serviceLocator
* @param null|string $canonicalName Ignored
* @param null|string $requestedName
* @return object
* @throws InvalidServiceNameException
*/
public function createService(ServiceLocatorInterface $serviceLocator, $canonicalName = null, $requestedName = null)
{
if (! $requestedName) {
throw new InvalidServiceNameException(sprintf(
'%s requires that the requested name is provided on invocation; please update your tests or consuming container',
__CLASS__
));
}
return $this($serviceLocator, $requestedName);
}
}
32 changes: 32 additions & 0 deletions test/Factory/InvokableFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace ZendTest\ServiceManager\Factory;

use Interop\Container\ContainerInterface;
use PHPUnit_Framework_TestCase as TestCase;
use Zend\ServiceManager\Factory\InvokableFactory;
use ZendTest\ServiceManager\TestAsset\InvokableObject;

/**
* @covers \Zend\ServiceManager\Factory\InvokableFactory
*/
class InvokableFactoryTest extends TestCase
{
public function testCanCreateObject()
{
$container = $this->getMock(ContainerInterface::class);
$factory = new InvokableFactory();

$object = $factory($container, InvokableObject::class, ['foo' => 'bar']);

$this->assertInstanceOf(InvokableObject::class, $object);
$this->assertEquals(['foo' => 'bar'], $object->options);
}
}
34 changes: 34 additions & 0 deletions test/TestAsset/InvokableObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace ZendTest\ServiceManager\TestAsset;

class InvokableObject
{
/**
* @var array
*/
public $options;

/**
* @param array $options
*/
public function __construct(array $options = [])
{
$this->options = $options;
}

/**
* @return array
*/
public function getOptions()
{
return $this->options;
}
}

0 comments on commit c0655c0

Please sign in to comment.