Completed
Pull Request — master (#29)
by Paulo Rodrigues
06:55
created

AssetCompilerPass::addPackages()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 2
crap 2
1
<?php
2
3
namespace Rj\FrontendBundle\DependencyInjection\Compiler;
4
5
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
6
use Symfony\Component\DependencyInjection\ContainerBuilder;
7
use Symfony\Component\DependencyInjection\Definition;
8
use Symfony\Component\DependencyInjection\Reference;
9
10
class AssetCompilerPass implements CompilerPassInterface
11
{
12
    /**
13
     * @inheritdoc
14
     */
15 19
    public function process(ContainerBuilder $container)
16
    {
17 19
        $packages = array();
18 19
        $registeredPackages = $this->getRegisteredPackages($container);
19
20 18
        foreach ($this->getTaggedPackages($container) as $id => $tags) {
21 10
            if (empty($tags) || !isset($tags[0]['alias'])) {
22 1
                throw new \LogicException(
23 1
                    "The tag for the service with id '$id' must define an 'alias' attribute"
24
                );
25
            }
26
27 9
            $packageName = $tags[0]['alias'];
28
29 9
            if (isset($registeredPackages[$packageName])) {
30 1
                throw new \LogicException(
31 1
                    "A package named '$packageName' has already been registered"
32
                );
33
            }
34
35 8
            if (isset($packages[$packageName])) {
36 1
                throw new \LogicException(
37 1
                    "Multiple packages were found with alias '$packageName'. Package alias' must be unique"
38
                );
39
            }
40
41 8
            $packages[$packageName] = $id;
42
        }
43
44 15
        $this->addPackages($packages, $container);
45
46 15
        if ($container->hasDefinition($this->namespaceService('package.fallback'))) {
47 12
            $this->setDefaultPackage($container);
48
        }
49 15
    }
50
51
    /**
52
     * @param ContainerBuilder $container
53
     * @return Definition[]
54
     */
55 18
    private function getTaggedPackages(ContainerBuilder $container)
56
    {
57 18
        return $container->findTaggedServiceIds($this->namespaceService('package.asset'));
58
    }
59
60
    /**
61
     * @param ContainerBuilder $container
62
     * @return Definition
63
     */
64 19
    private function getPackagesService(ContainerBuilder $container)
65
    {
66 19
        if (!$container->hasDefinition('assets.packages')) {
67 1
            throw new \LogicException('The Asset component is not registered in the container');
68
        }
69
70 18
        return $container->getDefinition('assets.packages');
71
    }
72
73
    /**
74
     * @param Definition[] $packages
75
     * @param ContainerBuilder $container
76
     */
77 15
    private function addPackages($packages, ContainerBuilder $container)
78
    {
79 15
        $packagesService = $this->getPackagesService($container);
80
81 15
        foreach ($packages as $name => $id) {
82 7
            $packagesService->addMethodCall(
83 7
                'addPackage',
84 7
                array($name, new Reference($id))
0 ignored issues
show
Documentation introduced by
$id is of type object<Symfony\Component...cyInjection\Definition>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
85
            );
86
        }
87 15
    }
88
89
    /**
90
     * @param ContainerBuilder $container
91
     */
92 12
    private function setDefaultPackage(ContainerBuilder $container)
93
    {
94 12
        $packagesService = $this->getPackagesService($container);
95 12
        $defaultPackage = $this->getRegisteredDefaultPackage($container);
96 12
        $fallbackPackageId = $this->namespaceService('package.fallback');
97
98 12
        $container->getDefinition($fallbackPackageId)->addMethodCall('setFallback', array($defaultPackage));
99
100 12
        $packagesService->replaceArgument(0, new Reference($fallbackPackageId));
101 12
    }
102
103
    /**
104
     * Retrieve packages that have already been registered.
105
     *
106
     * @param ContainerBuilder $container
107
     * @return array with the packages' name as keys
108
     */
109 19
    private function getRegisteredPackages(ContainerBuilder $container)
110
    {
111 19
        $arguments = $this->getPackagesService($container)->getArguments();
112
113 18
        if (!isset($arguments[1]) || count($arguments[1]) < 2) {
114 16
            return array();
115
        }
116
117 2
        $argPackages = $arguments[1];
118
119 2
        $packages = array();
120 2
        $argCount = count($argPackages);
121 2
        for ($i = 0; $i < $argCount; $i++) {
122 2
            $packages[$argPackages[$i]] = $argPackages[++$i];
123
        }
124
125 2
        return $packages;
126
    }
127
128
    /**
129
     * @param ContainerBuilder $container
130
     * @return Definition|null
131
     */
132 12
    private function getRegisteredDefaultPackage(ContainerBuilder $container)
133
    {
134 12
        $arguments = $this->getPackagesService($container)->getArguments();
135
136 12
        if (!isset($arguments[0])) {
137
            return null;
138
        }
139
140 12
        return $arguments[0];
141
    }
142
143
    /**
144
     * @param string $id
145
     * @return string
146
     */
147 18
    private function namespaceService($id)
148
    {
149 18
        return "rj_frontend.$id";
150
    }
151
}
152