Completed
Branch improve-hot-spots (e4b40a)
by Olivier
01:40
created

TransformationPass::buildMappingAndRefMap()   B

Complexity

Conditions 4
Paths 2

Size

Total Lines 27
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 15
nc 2
nop 1
dl 0
loc 27
rs 8.5806
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the ICanBoogie package.
5
 *
6
 * (c) Olivier Laviale <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ICanBoogie\Transformation\Symfony;
13
14
use ICanBoogie\Transformation\PSR\TransformationProvider;
15
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
17
use Symfony\Component\DependencyInjection\ContainerBuilder;
18
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
19
use Symfony\Component\DependencyInjection\Exception\LogicException;
20
use Symfony\Component\DependencyInjection\TypedReference;
21
22
/**
23
 * Registers the transformation provider.
24
 */
25
class TransformationPass implements CompilerPassInterface
26
{
27
    const DEFAULT_SERVICE_ID = 'transformation.provider';
28
    const DEFAULT_TAG = 'transformation';
29
    const DEFAULT_TYPE_PROPERTY = 'type';
30
31
    /**
32
     * @var string
33
     */
34
    private $serviceId;
35
36
    /**
37
     * @var string
38
     */
39
    private $tag;
40
41
    /**
42
     * @var string
43
     */
44
    private $typeProperty;
45
46
    /**
47
     * @param string $serviceId
48
     * @param string $tag
49
     * @param string $typeProperty
50
     */
51
    public function __construct(
52
        $serviceId = self::DEFAULT_SERVICE_ID,
53
        $tag = self::DEFAULT_TAG,
54
        $typeProperty = self::DEFAULT_TYPE_PROPERTY
55
    ) {
56
        $this->serviceId = $serviceId;
57
        $this->tag = $tag;
58
        $this->typeProperty = $typeProperty;
59
    }
60
61
    /**
62
     * @inheritdoc
63
     */
64
    public function process(ContainerBuilder $container)
65
    {
66
        list($mapping, $refMap) = $this->buildMappingAndRefMap($container);
67
68
        $container
69
            ->register($this->serviceId, TransformationProvider::class)
70
            ->setArguments([
71
                $mapping,
72
                ServiceLocatorTagPass::register($container, $refMap),
73
            ]);
74
    }
75
76
    /**
77
     * @param ContainerBuilder $container
78
     *
79
     * @return array
80
     */
81
    private function buildMappingAndRefMap(ContainerBuilder $container)
82
    {
83
        $transformers = $container->findTaggedServiceIds($this->tag, true);
84
        $typeProperty = $this->typeProperty;
85
        $mapping = [];
86
        $refMap = [];
87
88
        foreach ($transformers as $id => $tags) {
89
            if (empty($tags[0][$typeProperty])) {
90
                throw new InvalidArgumentException(
91
                    "The `$typeProperty` property is required for service `$id`."
92
                );
93
            }
94
95
            $type = $tags[0][$typeProperty];
96
97
            if (isset($mapping[$type])) {
98
                throw new LogicException(
99
                    "The type `$type` already has a transformation: `{$mapping[$type]}`."
100
                );
101
            }
102
103
            $mapping[$type] = $id;
104
            $refMap[$id] = new TypedReference($id, $container->getDefinition($id)->getClass());
105
        }
106
107
        return [ $mapping, $refMap ];
108
    }
109
}
110