Completed
Push — master ( 46844c...fc14d1 )
by Jonathan
05:09
created

buildDecoratorDefinition()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
cc 2
eloc 4
nc 2
nop 2
crap 2
1
<?php
2
namespace Jsq\Cache\DependencyInjection\Compiler;
3
4
use Jsq\Cache\EnvelopeEncryption\Decorator as EnvelopeEncryptionDecorator;
5
use Jsq\Cache\PasswordEncryption\Decorator as PasswordEncryptionDecorator;
6
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
7
use Symfony\Component\DependencyInjection\ContainerBuilder;
8
use Symfony\Component\DependencyInjection\Definition;
9
use Symfony\Component\DependencyInjection\Reference;
10
11
class CacheEncrypterCompilerPass implements CompilerPassInterface
12
{
13 9
    public function process(ContainerBuilder $container)
14
    {
15 9
        $taggedServices = $container->findTaggedServiceIds('cache.encrypted');
16
17 9
        foreach ($taggedServices as $id => $tags) {
18 9
            $this->inflateServicesInTag($tags);
19
20 9
            foreach ($tags as $tag) {
21 9
                $container->setDefinition(
22 9
                    isset($tag['alias']) ? $tag['alias'] : "$id.encrypted",
23 9
                    $this->buildDecoratorDefinition($id, $tag)
24 9
                );
25 9
            }
26 9
        }
27 9
    }
28
29 12
    private function buildDecoratorDefinition($decorated, array $tags)
30
    {
31 12
        if ($this->arrayHasKeys($tags, ['certificate', 'key'])) {
32 9
            return $this->buildPkiDecoratorDefinition($decorated, $tags);
33
        }
34
35 12
        return $this->buildPasswordDecoratorDefinition($decorated, $tags);
36
    }
37
38 12
    private function buildPasswordDecoratorDefinition($decorated, array $tags)
39
    {
40 12
        if (empty($tags['password'])) {
41 3
            throw new \DomainException('Cannot encrypt a cache'
42 3
                . ' with an empty password.');
43
        }
44
45 9
        $args = [new Reference($decorated), $tags['password']];
46 9
        if (isset($tags['cipher'])) {
47 3
            $args []= $tags['cipher'];
48 3
        }
49
50 9
        return new Definition(PasswordEncryptionDecorator::class, $args);
51
    }
52
53 9
    private function buildPkiDecoratorDefinition($decorated, array $tag)
54
    {
55 9
        $args = [new Reference($decorated), $tag['certificate'], $tag['key']];
56 9
        foreach (['password', 'cipher'] as $optionalParameter) {
57 9
            if (isset($tag[$optionalParameter])) {
58 3
                $args []= $tag[$optionalParameter];
59 3
            }
60 9
        }
61
62 9
        return new Definition(EnvelopeEncryptionDecorator::class, $args);
63
    }
64
65 12
    private function arrayHasKeys(array $array, array $keys)
66
    {
67 12
        foreach ($keys as $key) {
68 12
            if (!isset($array[$key])) {
69 12
                return false;
70
            }
71 9
        }
72
73 9
        return true;
74
    }
75
76
    private function inflateServicesInTag(array &$config)
77
    {
78 15
        array_walk($config, function (&$value) {
79 15
            if (is_array($value)) {
80 15
                $this->inflateServicesInTag($value);
81 15
            }
82
83 15
            if (is_string($value) && 0 === strpos($value, '@')) {
84
                // this is either a service reference or a string meant to
85
                // start with an '@' symbol. In any case, lop off the first '@'
86 15
                $value = substr($value, 1);
87 15
                if (0 !== strpos($value, '@')) {
88
                    // this is a service reference, not a string literal
89 12
                    $value = new Reference($value);
90 12
                }
91 15
            }
92 15
        });
93 15
    }
94
}
95