From 3aa1b76ae9913a5fa3d51a36fdf9201d63d46299 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Mon, 28 Sep 2015 19:46:52 +0000 Subject: [PATCH] [facade] add ability to pass builders for http requiest verifeir token factory generic token factory core gateway factory. --- PayumBuilder.php | 46 ++++-- Tests/PayumBuilderTest.php | 309 ++++++++++++++++++++++++++++++++++++- 2 files changed, 341 insertions(+), 14 deletions(-) diff --git a/PayumBuilder.php b/PayumBuilder.php index 89736cb..b1cca23 100644 --- a/PayumBuilder.php +++ b/PayumBuilder.php @@ -49,7 +49,7 @@ class PayumBuilder protected $tokenFactory; /** - * @var GenericTokenFactoryInterface + * @var GenericTokenFactoryInterface|callable|null */ protected $genericTokenFactory; @@ -217,15 +217,23 @@ public function setTokenFactory($tokenFactory = null) } /** - * @param GenericTokenFactoryInterface $tokenFactory + * @param GenericTokenFactoryInterface|callable|null $tokenFactory * * @return static */ - public function setGenericTokenFactory(GenericTokenFactoryInterface $tokenFactory = null) + public function setGenericTokenFactory($tokenFactory = null) { - $this->genericTokenFactory = $tokenFactory; + if ( + null === $tokenFactory || + $tokenFactory instanceof GenericTokenFactoryInterface || + is_callable($tokenFactory)) + { + $this->genericTokenFactory = $tokenFactory; - return $this; + return $this; + } + + throw new InvalidArgumentException('Invalid argument'); } /** @@ -330,7 +338,12 @@ public function getPayum() } $tokenFactory = $this->buildTokenFactory($this->tokenStorage, $this->buildRegistry([], $this->storages)); - $genericTokenFactory = $this->buildGenericTokenFactory($tokenFactory); + $genericTokenFactory = $this->buildGenericTokenFactory($tokenFactory, array_replace([ + 'capture' => 'capture.php', + 'notify' => 'notify.php', + 'authorize' => 'authorize.php', + 'refund' => 'refund.php', + ], $this->genericTokenFactoryPaths)); $httpRequestVerifier = $this->buildHttpRequestVerifier($this->tokenStorage); @@ -387,17 +400,24 @@ protected function buildTokenFactory(StorageInterface $tokenStorage, StorageRegi /** * @param TokenFactoryInterface $tokenFactory + * @param string[] $paths * * @return GenericTokenFactoryInterface + * */ - protected function buildGenericTokenFactory(TokenFactoryInterface $tokenFactory) + protected function buildGenericTokenFactory(TokenFactoryInterface $tokenFactory, array $paths) { - return $this->genericTokenFactory ?: new GenericTokenFactory($tokenFactory, $this->genericTokenFactoryPaths ?: [ - 'capture' => 'capture.php', - 'notify' => 'notify.php', - 'authorize' => 'authorize.php', - 'refund' => 'refund.php', - ]); + $genericTokenFactory = $this->genericTokenFactory; + + if (is_callable($genericTokenFactory)) { + $genericTokenFactory = call_user_func($genericTokenFactory, $tokenFactory, $paths); + + if (false == $genericTokenFactory instanceof GenericTokenFactoryInterface) { + throw new \LogicException('Builder returned invalid instance'); + } + } + + return $genericTokenFactory ?: new GenericTokenFactory($tokenFactory, $paths); } /** diff --git a/Tests/PayumBuilderTest.php b/Tests/PayumBuilderTest.php index 65db06e..9931d3f 100644 --- a/Tests/PayumBuilderTest.php +++ b/Tests/PayumBuilderTest.php @@ -5,17 +5,22 @@ use Payum\Be2Bill\Be2BillDirectGatewayFactory; use Payum\Be2Bill\Be2BillOffsiteGatewayFactory; use Payum\Core\Bridge\PlainPhp\Security\HttpRequestVerifier; +use Payum\Core\CoreGatewayFactory; +use Payum\Core\Extension\StorageExtension; use Payum\Core\Gateway; use Payum\Core\GatewayFactoryInterface; +use Payum\Core\GatewayInterface; use Payum\Core\Model\ArrayObject; use Payum\Core\Model\Payment; use Payum\Core\Payum; use Payum\Core\PayumBuilder; use Payum\Core\Registry\RegistryInterface; use Payum\Core\Registry\SimpleRegistry; +use Payum\Core\Registry\StorageRegistryInterface; use Payum\Core\Security\GenericTokenFactory; use Payum\Core\Security\GenericTokenFactoryInterface; use Payum\Core\Security\HttpRequestVerifierInterface; +use Payum\Core\Security\TokenFactoryInterface; use Payum\Core\Storage\StorageInterface; use Payum\Klarna\Checkout\KlarnaCheckoutGatewayFactory; use Payum\Klarna\Invoice\KlarnaInvoiceGatewayFactory; @@ -122,6 +127,9 @@ public function shouldBuildDefaultPayum() $this->assertInstanceOf(StripeJsGatewayFactory::class, $factories['stripe_js']); } + /** + * @test + */ public function shouldUseCustomHttpRequestVerifier() { /** @var HttpRequestVerifierInterface $expectedVerifier */ @@ -137,7 +145,50 @@ public function shouldUseCustomHttpRequestVerifier() $this->assertSame($expectedVerifier, $payum->getHttpRequestVerifier()); } - public function shouldUseCustomTokenFactory() + /** + * @test + */ + public function shouldUseHttpRequestVerifierBuilder() + { + /** @var HttpRequestVerifierInterface $expectedVerifier */ + $expectedVerifier = $this->getMock(HttpRequestVerifierInterface::class); + + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->setHttpRequestVerifier(function($tokenStorage) use ($expectedVerifier) { + $this->assertInstanceOf(StorageInterface::class, $tokenStorage); + + return $expectedVerifier; + }) + ->getPayum() + ; + + $this->assertInstanceOf(Payum::class, $payum); + $this->assertSame($expectedVerifier, $payum->getHttpRequestVerifier()); + } + + /** + * @test + * + * @expectedException \LogicException + * @expectedExceptionMessage Builder returned invalid instance + */ + public function throwsIfHttpRequestVerifierBuilderReturnsInvalidInstance() + { + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->setHttpRequestVerifier(function() { + + return new \stdClass(); + }) + ->getPayum() + ; + } + + /** + * @test + */ + public function shouldUseCustomGenericTokenFactory() { /** @var GenericTokenFactoryInterface $expectedTokenFactory */ $expectedTokenFactory = $this->getMock(GenericTokenFactoryInterface::class); @@ -152,6 +203,133 @@ public function shouldUseCustomTokenFactory() $this->assertSame($expectedTokenFactory, $payum->getTokenFactory()); } + /** + * @test + */ + public function shouldUseGenericTokenFactoryBuilder() + { + /** @var GenericTokenFactoryInterface $expectedTokenFactory */ + $expectedTokenFactory = $this->getMock(GenericTokenFactoryInterface::class); + + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->setGenericTokenFactory(function($tokenFactory, $paths) use ($expectedTokenFactory) { + $this->assertInstanceOf(TokenFactoryInterface::class, $tokenFactory); + + $this->assertInternalType('array', $paths); + $this->assertEquals([ + 'capture' => 'capture.php', + 'notify' => 'notify.php', + 'authorize' => 'authorize.php', + 'refund' => 'refund.php', + ], $paths); + + return $expectedTokenFactory; + }) + ->getPayum() + ; + + $this->assertInstanceOf(Payum::class, $payum); + $this->assertSame($expectedTokenFactory, $payum->getTokenFactory()); + } + + /** + * @test + */ + public function shouldUseCustomGenericTokenFactoryPaths() + { + $expectedPaths = [ + 'capture' => 'capture_custom.php', + 'notify' => 'notify_custom.php', + 'authorize' => 'authorize_custom.php', + 'refund' => 'refund_custom.php', + ]; + + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->setGenericTokenFactoryPaths($expectedPaths) + ->getPayum() + ; + + $this->assertInstanceOf(Payum::class, $payum); + $this->assertAttributeSame($expectedPaths, 'paths', $payum->getTokenFactory()); + } + + /** + * @test + * + * @expectedException \LogicException + * @expectedExceptionMessage Builder returned invalid instance + */ + public function throwsIfGenericTokenFactoryBuilderReturnInvalidInstance() + { + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->setGenericTokenFactory(function() { + return new \stdClass(); + }) + ->getPayum() + ; + } + + /** + * @test + */ + public function shouldUseCustomTokenFactory() + { + /** @var TokenFactoryInterface $expectedTokenFactory */ + $expectedTokenFactory = $this->getMock(TokenFactoryInterface::class); + + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->setTokenFactory($expectedTokenFactory) + ->getPayum() + ; + + $this->assertInstanceOf(Payum::class, $payum); + $this->assertAttributeSame($expectedTokenFactory, 'tokenFactory', $payum->getTokenFactory()); + } + + /** + * @test + */ + public function shouldUseTokenFactoryBuilder() + { + /** @var TokenFactoryInterface $expectedTokenFactory */ + $expectedTokenFactory = $this->getMock(TokenFactoryInterface::class); + + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->setTokenFactory(function($tokenStorage, $storageRegistry) use ($expectedTokenFactory) { + $this->assertInstanceOf(StorageInterface::class, $tokenStorage); + $this->assertInstanceOf(StorageRegistryInterface::class, $storageRegistry); + + return $expectedTokenFactory; + }) + ->getPayum() + ; + + $this->assertInstanceOf(Payum::class, $payum); + $this->assertAttributeSame($expectedTokenFactory, 'tokenFactory', $payum->getTokenFactory()); + } + + /** + * @test + * + * @expectedException \LogicException + * @expectedExceptionMessage Builder returned invalid instance + */ + public function throwsIfTokenFactoryBuilderReturnInvalidInstance() + { + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->setTokenFactory(function() { + return new \stdClass(); + }) + ->getPayum() + ; + } + /** * @test */ @@ -278,6 +456,133 @@ public function shouldReuseGatewaysFromMainRegistryAndFallbackOne() $this->assertSame($fallbackGateway, $payum->getGateway('fallback_factory')); } + /** + * @test + */ + public function shouldAllowSetReuseGatewaysFromMainRegistryAndFallbackOne() + { + $fallbackGateway = new Gateway(); + $mainGateway = new Gateway(); + + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->addGateway('fallback_factory', $fallbackGateway) + ->setMainRegistry(new SimpleRegistry([ + 'main_gateway' => $mainGateway + ])) + ->getPayum() + ; + + $this->assertInstanceOf(Payum::class, $payum); + $this->assertSame($mainGateway, $payum->getGateway('main_gateway')); + $this->assertSame($fallbackGateway, $payum->getGateway('fallback_factory')); + } + + /** + * @test + */ + public function shouldUseCustomCoreGatewayFactory() + { + $expectedCoreGatewayFactory = $this->getMock(GatewayFactoryInterface::class); + + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->setCoreGatewayFactory($expectedCoreGatewayFactory) + ->getPayum() + ; + + $gatewayFactory = $payum->getGatewayFactory('offline'); + + $this->assertInstanceOf(OfflineGatewayFactory::class, $gatewayFactory); + + $this->assertAttributeSame($expectedCoreGatewayFactory, 'coreGatewayFactory', $gatewayFactory); + } + + /** + * @test + */ + public function shouldUseCoreGatewayFactoryBuilder() + { + $expectedCoreGatewayFactory = $this->getMock(GatewayFactoryInterface::class); + + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->setCoreGatewayFactory(function($config) use ($expectedCoreGatewayFactory) { + + $this->assertInternalType('array', $config); + $this->assertNotEmpty($config); + + return $expectedCoreGatewayFactory; + }) + ->getPayum() + ; + + $gatewayFactory = $payum->getGatewayFactory('offline'); + + $this->assertInstanceOf(OfflineGatewayFactory::class, $gatewayFactory); + + $this->assertAttributeSame($expectedCoreGatewayFactory, 'coreGatewayFactory', $gatewayFactory); + } + + /** + * @test + */ + public function shouldAddStorageExtensionForTheAddedStorage() + { + /** @var StorageInterface $expectedStorage */ + $expectedStorage = $this->getMock(StorageInterface::class); + + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->addStorage(TestModel::class, $expectedStorage) + ->setCoreGatewayFactory(function($config) use ($expectedStorage) { + + $this->assertInternalType('array', $config); + $this->assertArrayHasKey('payum.extension.storage_payum_core_tests_testmodel', $config, var_export($config, true)); + $this->assertInstanceOf(StorageExtension::class, $config['payum.extension.storage_payum_core_tests_testmodel']); + $this->assertAttributeSame($expectedStorage, 'storage', $config['payum.extension.storage_payum_core_tests_testmodel']); + + return new CoreGatewayFactory($config); + }) + ->getPayum() + ; + + $gatewayFactory = $payum->getGatewayFactory('offline'); + + $this->assertInstanceOf(OfflineGatewayFactory::class, $gatewayFactory); + + $config = $gatewayFactory->createConfig([]); + + $this->assertArrayHasKey('payum.extension.storage_payum_core_tests_testmodel', $config, var_export($config, true)); + $this->assertInstanceOf(StorageExtension::class, $config['payum.extension.storage_payum_core_tests_testmodel']); + $this->assertAttributeSame($expectedStorage, 'storage', $config['payum.extension.storage_payum_core_tests_testmodel']); + } + + /** + * @test + * + * @expectedException \LogicException + * @expectedExceptionMessage Builder returned invalid instance + */ + public function throwsIfCoreGatewayFactoryBuilderReturnInvalidInstance() + { + $expectedCoreGateway = $this->getMock(GatewayFactoryInterface::class); + + $payum = (new PayumBuilder()) + ->addDefaultStorages() + ->setCoreGatewayFactory(function() { + return new \stdClass(); + }) + ->getPayum() + ; + + $gatewayFactory = $payum->getGatewayFactory('offline'); + + $this->assertInstanceOf(OfflineGatewayFactory::class, $gatewayFactory); + + $this->assertAttributeSame($expectedCoreGateway, 'coreGatewayFactory', $gatewayFactory); + } + /** * @return \PHPUnit_Framework_MockObject_MockObject|RegistryInterface */ @@ -302,3 +607,5 @@ protected function createGenericTokenFactoryMock() return $this->getMock(GenericTokenFactoryInterface::class); } } + +class TestModel {}