From 3b0ad843ff3c02a92e51668d234d2354ca36fc9a Mon Sep 17 00:00:00 2001 From: Marco Stoll <marco.stoll@rocketmail.com> Date: Fri, 21 Jun 2019 10:22:37 +0200 Subject: [PATCH] [CHANGE] use new FF-Factories features --- composer.json | 3 +- src/Services/AbstractService.php | 25 +- src/Services/Factories/ServicesFactory.php | 11 +- .../{ => Traits}/ServiceLocatorTrait.php | 5 +- tests/Services/AbstractServiceTest.php | 8 + .../Factories/ServicesFactoryTest.php | 224 ++++++++++-------- 6 files changed, 164 insertions(+), 112 deletions(-) rename src/Services/{ => Traits}/ServiceLocatorTrait.php (85%) diff --git a/composer.json b/composer.json index c444b5a..97a09de 100644 --- a/composer.json +++ b/composer.json @@ -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" diff --git a/src/Services/AbstractService.php b/src/Services/AbstractService.php index 29f1495..8c5ab33 100644 --- a/src/Services/AbstractService.php +++ b/src/Services/AbstractService.php @@ -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 * diff --git a/src/Services/Factories/ServicesFactory.php b/src/Services/Factories/ServicesFactory.php index 9c0b150..b528cc0 100644 --- a/src/Services/Factories/ServicesFactory.php +++ b/src/Services/Factories/ServicesFactory.php @@ -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 { diff --git a/src/Services/ServiceLocatorTrait.php b/src/Services/Traits/ServiceLocatorTrait.php similarity index 85% rename from src/Services/ServiceLocatorTrait.php rename to src/Services/Traits/ServiceLocatorTrait.php index b32fc8a..4dde715 100644 --- a/src/Services/ServiceLocatorTrait.php +++ b/src/Services/Traits/ServiceLocatorTrait.php @@ -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 { diff --git a/tests/Services/AbstractServiceTest.php b/tests/Services/AbstractServiceTest.php index 37090d7..067f7d9 100644 --- a/tests/Services/AbstractServiceTest.php +++ b/tests/Services/AbstractServiceTest.php @@ -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 diff --git a/tests/Services/Factories/ServicesFactoryTest.php b/tests/Services/Factories/ServicesFactoryTest.php index 4f7407b..3dce62b 100644 --- a/tests/Services/Factories/ServicesFactoryTest.php +++ b/tests/Services/Factories/ServicesFactoryTest.php @@ -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 + { + + } } \ No newline at end of file