Skip to content

Commit

Permalink
[action] add ability to add action by container tag
Browse files Browse the repository at this point in the history
  • Loading branch information
makasim committed May 26, 2014
1 parent 22bbc35 commit b9f035f
Show file tree
Hide file tree
Showing 9 changed files with 640 additions and 4 deletions.
99 changes: 99 additions & 0 deletions DependencyInjection/Compiler/PayumActionsPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php
namespace Payum\Bundle\PayumBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class PayumActionsPass implements CompilerPassInterface
{

/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
foreach ($container->findTaggedServiceIds('payum.action') as $id => $tagAttributes) {

foreach ($tagAttributes as $attributes) {
$paymentIds = array();

if (isset($attributes['all']) && $attributes['all']) {
$paymentIds = array_merge($paymentIds, $this->findAllPaymentIds($container));
}

if (isset($attributes['factory']) && $attributes['factory']) {
$paymentIds = array_merge(
$paymentIds,
$this->findPaymentIdsByFactory($container, $attributes['factory'])
);
}
if (isset($attributes['context']) && $attributes['context']) {
$paymentIds = array_merge(
$paymentIds,
$this->findPaymentIdsByContext($container, $attributes['context'])
);
}

$paymentIds = array_filter(array_unique($paymentIds));
foreach ($paymentIds as $paymentId) {
$payment = $container->getDefinition($paymentId);
$payment->addMethodCall('addAction', array(
new Reference($id),
isset($attributes['prepend']) && $attributes['prepend']
));
}
}
}
}

/**
* @param ContainerBuilder $container
* @param string $factoryName
*
* @return string[]
*/
protected function findPaymentIdsByFactory(ContainerBuilder $container, $factoryName)
{
$paymentIds = array();
foreach ($container->findTaggedServiceIds('payum.payment') as $id => $tagAttributes) {
foreach ($tagAttributes as $attributes) {
if (isset($attributes['factory']) && $attributes['factory'] == $factoryName) {
$paymentIds[] = $id;
}
}
}

return $paymentIds;
}

/**
* @param ContainerBuilder $container
* @param string $contextName
*
* @return string[]
*/
protected function findPaymentIdsByContext(ContainerBuilder $container, $contextName)
{
$paymentIds = array();
foreach ($container->findTaggedServiceIds('payum.payment') as $id => $tagAttributes) {
foreach ($tagAttributes as $attributes) {
if (isset($attributes['context']) && $attributes['context'] == $contextName) {
$paymentIds[] = $id;
}
}
}

return $paymentIds;
}

/**
* @param ContainerBuilder $container
*
* @return string[]
*/
protected function findAllPaymentIds(ContainerBuilder $container)
{
return array_keys($container->findTaggedServiceIds('payum.payment'));
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<?php
namespace Payum\Bundle\PayumBundle\DependencyInjection\Factory\Payment;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;

interface PaymentFactoryInterface
{
/**
* @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
* @param ContainerBuilder $container
* @param string $contextName
* @param array $config
*
Expand All @@ -24,7 +25,7 @@ function create(ContainerBuilder $container, $contextName, array $config);
function getName();

/**
* @param \Symfony\Component\Config\Definition\Builder\NodeDefinition $builder
* @param NodeDefinition $builder
*
* @return void
*/
Expand Down
7 changes: 6 additions & 1 deletion DependencyInjection/PayumExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,12 @@ protected function loadContexts(array $config, ContainerBuilder $container)
$contextConfig[$paymentFactoryName]
);
$paymentsServicesIds[$contextName] = $paymentId;


$container->getDefinition($paymentId)->addTag('payum.payment', array(
'factory' => $paymentFactoryName,
'context' => $contextName
));

foreach ($contextConfig['storages'] as $modelClass => $storageConfig) {
$storageFactoryName = $this->findSelectedStorageFactoryNameInStorageConfig($storageConfig);
$storageId = $this->storageFactories[$storageFactoryName]->create(
Expand Down
3 changes: 3 additions & 0 deletions PayumBundle.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Payum\Bundle\PayumBundle;

use Payum\Bundle\PayumBundle\DependencyInjection\Compiler\PayumActionsPass;
use Payum\Bundle\PayumBundle\DependencyInjection\Factory\Payment\KlarnaCheckoutPaymentFactory;
use Payum\Bundle\PayumBundle\DependencyInjection\Factory\Payment\OfflinePaymentFactory;
use Symfony\Component\HttpKernel\Bundle\Bundle;
Expand Down Expand Up @@ -37,5 +38,7 @@ public function build(ContainerBuilder $container)

$extension->addStorageFactory(new FilesystemStorageFactory);
$extension->addStorageFactory(new DoctrineStorageFactory);

$container->addCompilerPass(new PayumActionsPass);
}
}
90 changes: 90 additions & 0 deletions Resources/doc/custom_action_usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Custom action usage

Payment comes with built in actions but sometime you have to add your own. First you have to define a service:

```yaml
# src/Acme/PaymentBundle/Resources/config/services.yml

services:
acme.payum.action.foo:
class: Acme\PaymentBundle\Payum\Action\FooAction
```
There are several ways to add it to a payment:
* Set it explicitly in config.yml.
```yaml
# app/config/config.yml

payum:
contexts:
a_context:
a_factory:
actions:
- acme.payum.action.foo
```
* Tag it
More powerful method is to add a tag `payum.action` to action server. Payum will do the reset.
You can define a `factory` attribute inside that tag.
In this case the action will be added to all payments created by requested factory.

```yaml
# app/config/config.yml
payum:
contexts:
a_context:
a_factory: ~
```

```yaml
# src/Acme/PaymentBundle/Resources/config/services.yml
services:
acme.payum.action.foo:
class: Acme\PaymentBundle\Payum\Action\FooAction
tags:
- {payum.action, { factory: a_factory }}
```

Or you can set concrete `context` name.
In this case the action will be added only to the payment with requested context name.

```yaml
# app/config/config.yml
payum:
contexts:
a_context:
a_factory: ~
```

```yaml
# src/Acme/PaymentBundle/Resources/config/services.yml
services:
acme.payum.action.foo:
class: Acme\PaymentBundle\Payum\Action\FooAction
tags:
- {payum.action, {context: a_context}}
```

If `prepend` set to true the action is added before the rest.
If you want to add the action to all configured payments set `all` to true.

```yaml
# src/Acme/PaymentBundle/Resources/config/services.yml
services:
acme.payum.action.foo:
class: Acme\PaymentBundle\Payum\Action\FooAction
tags:
- {payum.action, { prepend: true, all: true }}
```

Back to [index](index.md).
1 change: 1 addition & 0 deletions Resources/doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* [Get it started](get_it_started.md)
* [Simple purchase examples](simple_purchase_examples.md).
* [Purchase done action](purchase_done_action.md).
* [Custom action usage](custom_action_usage.md).
* [Custom api usage](custom_api_usage.md).
* [Sandbox](sandbox.md).
* [Console commands](console_commands.md).
Expand Down
Loading

0 comments on commit b9f035f

Please sign in to comment.