[CHANGE] use new FF-Factories features

This commit is contained in:
Marco Stoll 2019-06-21 10:22:37 +02:00
parent b579d5b9c2
commit 3b0ad843ff
6 changed files with 164 additions and 112 deletions

View File

@ -14,7 +14,8 @@
],
"require": {
"php": ">=7.2",
"fastforward/factories": "^1.0.0"
"fastforward/data-structures": "^1.0.0",
"fastforward/factories": "^1.2.0"
},
"require-dev": {
"phpunit/phpunit": "^8"

View File

@ -10,16 +10,24 @@ declare(strict_types=1);
namespace FF\Services;
use FF\Factories\ClassLocators\ClassIdentifierAwareInterface;
use FF\Services\Exceptions\ConfigurationException;
use FF\Services\Traits\EventEmitterTrait;
use FF\Services\Traits\ServiceLocatorTrait;
/**
* Class AbstractService
*
* @package FF\Services
*/
abstract class AbstractService
abstract class AbstractService implements ClassIdentifierAwareInterface
{
use ServiceLocatorTrait;
use EventEmitterTrait, ServiceLocatorTrait;
/**
* For use with the BaseNamespaceClassLocator of the ServicesFactory
*/
const COMMON_NS_SUFFIX = 'Services';
/**
* @var array
@ -57,6 +65,19 @@ abstract class AbstractService
return $this->options[$key] ?? $default;
}
/**
* {@inheritDoc}
*/
public static function getClassIdentifier(): string
{
$className = get_called_class();
$needle = '\\' . self::COMMON_NS_SUFFIX . '\\';
$pos = strpos($className, $needle);
if ($pos === false) return $className;
return substr($className, $pos + strlen($needle));
}
/**
* Initializes the service
*

View File

@ -11,8 +11,8 @@ declare(strict_types=1);
namespace FF\Services\Factories;
use FF\Factories\AbstractSingletonFactory;
use FF\Factories\ClassLocators\BaseNamespaceClassLocator;
use FF\Factories\ClassLocators\ClassLocatorInterface;
use FF\Factories\ClassLocators\NamespaceClassLocator;
use FF\Factories\Exceptions\ClassNotFoundException;
use FF\Services\AbstractService;
use FF\Services\Exceptions\ConfigurationException;
@ -35,13 +35,14 @@ class ServicesFactory extends AbstractSingletonFactory
protected $servicesOptions;
/**
* Uses a NamespaceClassLocator pre-configured with the FF\Services namespace.
* Uses a BaseNamespaceClassLocator pre-configured with the 'Services' as common suffix and the FF namespace.
*
* @param array $servicesOptions
* @see \FF\Factories\ClassLocators\NamespaceClassLocator
* @see \FF\Factories\ClassLocators\BaseNamespaceClassLocator
*/
public function __construct(array $servicesOptions = [])
{
parent::__construct(new NamespaceClassLocator(__NAMESPACE__));
parent::__construct(new BaseNamespaceClassLocator(AbstractService::COMMON_NS_SUFFIX, 'FF'));
$this->servicesOptions = $servicesOptions;
}
@ -117,7 +118,7 @@ class ServicesFactory extends AbstractSingletonFactory
/**
* {@inheritDoc}
* @return NamespaceClassLocator
* @return BaseNamespaceClassLocator
*/
public function getClassLocator(): ClassLocatorInterface
{

View File

@ -8,14 +8,15 @@
*/
declare(strict_types=1);
namespace FF\Services;
namespace FF\Services\Traits;
use FF\Services\AbstractService;
use FF\Services\Factories\SF;
/**
* Trait ServiceLocatorTrait
*
* @package FF\Services
* @package FF\Services\Traits
*/
trait ServiceLocatorTrait
{

View File

@ -71,6 +71,14 @@ class AbstractServiceTest extends TestCase
new MyService(['foo' => 'baz']);
}
/**
* Tests the namesake method/feature
*/
public function testGetClassIdentifier()
{
$this->assertEquals('MyService', MyService::getClassIdentifier());
}
}
class MyService extends AbstractService

View File

@ -8,119 +8,139 @@
*/
declare(strict_types=1);
namespace FF\Tests\Services\Factories;
namespace FF\Tests\Services\Factories {
use FF\Factories\Exceptions\ClassNotFoundException;
use FF\Services\AbstractService;
use FF\Services\Exceptions\ConfigurationException;
use FF\Services\Factories\ServicesFactory;
use PHPUnit\Framework\TestCase;
/**
* Test ServicesFactoryTest
*
* @package FF\Tests
*/
class ServicesFactoryTest extends TestCase
{
const TEST_OPTIONS = ['ServiceOne' => ['foo' => 'bar']];
use FF\Factories\ClassLocators\BaseNamespaceClassLocator;
use FF\Factories\Exceptions\ClassNotFoundException;
use FF\Services\Exceptions\ConfigurationException;
use FF\Services\Factories\ServicesFactory;
use FF\Tests\Services\ServiceOne;
use FF\Tests\Services\ServiceTwo;
use PHPUnit\Framework\TestCase;
/**
* {@inheritdoc}
*/
public static function setUpBeforeClass(): void
{
ServicesFactory::clearInstance();
}
/**
* Tests the namesake method/feature
*/
public function testGetInstanceConfigException()
{
$this->expectException(ConfigurationException::class);
ServicesFactory::getInstance();
}
/**
* Tests the namesake method/feature
*/
public function testSetGetInstance()
{
$instance = new ServicesFactory(self::TEST_OPTIONS);
$instance->getClassLocator()->prependNamespaces(__NAMESPACE__);
ServicesFactory::setInstance($instance);
$this->assertSame($instance, ServicesFactory::getInstance());
}
/**
* Tests the namesake method/feature
* Test ServicesFactoryTest
*
* @depends testSetGetInstance
* @package FF\Tests
*/
public function testSetServiceOptions()
class ServicesFactoryTest extends TestCase
{
$this->assertEquals(
self::TEST_OPTIONS['ServiceOne'],
ServicesFactory::getInstance()->getServiceOptions('ServiceOne')
);
$this->assertEquals([], ServicesFactory::getInstance()->getServiceOptions('unknown'));
}
const TEST_OPTIONS = ['ServiceOne' => ['foo' => 'bar']];
/**
* Tests the namesake method/feature
*
* @depends testSetGetInstance
*/
public function testGetSingle()
{
$service = ServicesFactory::getInstance()->get('ServiceOne');
$this->assertInstanceOf(ServiceOne::class, $service);
$this->assertEquals(self::TEST_OPTIONS['ServiceOne'], $service->getOptions());
}
/**
* Tests the namesake method/feature
*
* @depends testSetGetInstance
*/
public function testGetMultiples()
{
$services = ServicesFactory::getInstance()->get('ServiceOne', 'ServiceOne');
$this->assertEquals(2, count($services));
$this->assertInstanceOf(ServiceOne::class, $services[0]);
$this->assertInstanceOf(ServiceOne::class, $services[1]);
}
/**
* Tests the namesake method/feature
*
* @depends testSetGetInstance
*/
public function testGetClassNotFound()
{
$this->expectException(ClassNotFoundException::class);
ServicesFactory::getInstance()->get('ServiceUnknown');
}
}
class ServiceOne extends AbstractService
{
protected function validateOptions(array $options, array &$errors): bool
{
if (isset($options['foo']) && $options['foo'] != 'bar') {
$errors[] = 'foo is not bar';
return false;
/**
* {@inheritdoc}
*/
public static function setUpBeforeClass(): void
{
ServicesFactory::clearInstance();
}
return parent::validateOptions($options, $errors);
/**
* Tests the namesake method/feature
*/
public function testGetInstanceConfigException()
{
$this->expectException(ConfigurationException::class);
ServicesFactory::getInstance();
}
/**
* Tests the namesake method/feature
*/
public function testSetGetInstance()
{
$instance = new ServicesFactory(self::TEST_OPTIONS);
$instance->getClassLocator()->prependNamespaces('FF\Tests');
ServicesFactory::setInstance($instance);
$this->assertSame($instance, ServicesFactory::getInstance());
}
/**
* Tests the namesake method/feature
*/
public function testGetClassLocator()
{
$this->assertInstanceOf(
BaseNamespaceClassLocator::class,
ServicesFactory::getInstance()->getClassLocator()
);
}
/**
* Tests the namesake method/feature
*
* @depends testSetGetInstance
*/
public function testSetServiceOptions()
{
$this->assertEquals(
self::TEST_OPTIONS['ServiceOne'],
ServicesFactory::getInstance()->getServiceOptions('ServiceOne')
);
$this->assertEquals([], ServicesFactory::getInstance()->getServiceOptions('ServiceTwo'));
$this->assertEquals([], ServicesFactory::getInstance()->getServiceOptions('unknown'));
}
/**
* Tests the namesake method/feature
*
* @depends testSetGetInstance
*/
public function testGetSingle()
{
$service = ServicesFactory::getInstance()->get('ServiceOne');
$this->assertInstanceOf(ServiceOne::class, $service);
$this->assertEquals(self::TEST_OPTIONS['ServiceOne'], $service->getOptions());
}
/**
* Tests the namesake method/feature
*
* @depends testSetGetInstance
*/
public function testGetMultiples()
{
$services = ServicesFactory::getInstance()->get('ServiceOne', 'ServiceTwo');
$this->assertEquals(2, count($services));
$this->assertInstanceOf(ServiceOne::class, $services[0]);
$this->assertInstanceOf(ServiceTwo::class, $services[1]);
}
/**
* Tests the namesake method/feature
*
* @depends testSetGetInstance
*/
public function testGetClassNotFound()
{
$this->expectException(ClassNotFoundException::class);
ServicesFactory::getInstance()->get('ServiceUnknown');
}
}
}
class ServiceTwo extends AbstractService
{
namespace FF\Tests\Services {
use FF\Services\AbstractService;
class ServiceOne extends AbstractService
{
protected function validateOptions(array $options, array &$errors): bool
{
if (isset($options['foo']) && $options['foo'] != 'bar') {
$errors[] = 'foo is not bar';
return false;
}
return parent::validateOptions($options, $errors);
}
}
class ServiceTwo extends AbstractService
{
}
}