Completed
Push — master ( dd049a...0e2519 )
by Gaetano
08:55
created

ChainResolver::hasEmbeddedReferences()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 8

Duplication

Lines 9
Ratio 64.29 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 9
loc 14
ccs 0
cts 0
cp 0
rs 9.2
c 0
b 0
f 0
cc 4
eloc 8
nc 4
nop 1
crap 20
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\ReferenceResolver;
4
5
use Kaliop\eZMigrationBundle\API\ReferenceResolverInterface;
6
use Kaliop\eZMigrationBundle\API\ReferenceBagInterface;
7
use Kaliop\eZMigrationBundle\API\ReferenceResolverBagInterface;
8
use Kaliop\eZMigrationBundle\API\EnumerableReferenceResolverInterface;
9
use Kaliop\eZMigrationBundle\API\EmbeddedReferenceResolverInterface;
10
11
class ChainResolver implements ReferenceResolverBagInterface, EnumerableReferenceResolverInterface, EmbeddedReferenceResolverInterface
12
{
13
    /** @var ReferenceResolverInterface[] $resolvers */
14
    protected $resolvers = array();
15
16
    /**
17
     * @param ReferenceResolverInterface[] $resolvers
18 73
     */
19
    public function __construct(array $resolvers)
20 73
    {
21 73
        $this->resolvers = $resolvers;
22
    }
23 73
24
    public function addResolver(ReferenceResolverInterface $resolver)
25 73
    {
26 73
        $this->resolvers[] = $resolver;
27
    }
28
29
    /**
30
     * @param string $stringIdentifier
31
     * @return bool
32 24
     */
33
    public function isReference($stringIdentifier)
34 24
    {
35 24
        foreach ($this->resolvers as $resolver) {
36 24
            if ($resolver->isReference($stringIdentifier)) {
37
                return true;
38
            }
39
        }
40 20
41
        return false;
42
    }
43
44
    /**
45
     * @param string $stringIdentifier
46
     * @return mixed
47
     * @throws \Exception
48 23
     */
49
    public function getReferenceValue($stringIdentifier)
50 23
    {
51
        $resolvedOnce = false;
52 23
53 23
        foreach ($this->resolvers as $resolver) {
54 23
            if ($resolver->isReference($stringIdentifier)) {
55
                $stringIdentifier = $resolver->getReferenceValue($stringIdentifier);
56 22
                // In case of many resolvers resolving the same ref, the last one wins. Should we default to the 1st winning ?
57
                $resolvedOnce = true;
58
            }
59
        }
60 22
61
        if (!$resolvedOnce) {
62
            throw new \Exception("Could not resolve reference with identifier: '$stringIdentifier'");
63
        }
64 22
65
        return $stringIdentifier;
66
    }
67 24
68
    public function resolveReference($stringIdentifier)
69 24
    {
70 23
        if ($this->isReference($stringIdentifier)) {
71
            return $this->getReferenceValue($stringIdentifier);
72 20
        }
73
        return $stringIdentifier;
74
    }
75
76
    /**
77
     * Tries to add the reference to one of the resolvers in the chain (the first accepting it)
78
     *
79
     * @param string $identifier
80
     * @param mixed $value
81
     * @param bool $overwrite do overwrite the existing ref if it exist without raising an exception
82
     * @return bool
83 24
     */
84
    public function addReference($identifier, $value, $overwrite = false)
85 24
    {
86 24
        foreach ($this->resolvers as $resolver) {
87 24
            if ($resolver instanceof ReferenceBagInterface) {
88 24
                if ($resolver->addReference($identifier, $value, $overwrite)) {
89
                    return true;
90
                }
91
            }
92
        }
93
94
        return false;
95
    }
96 1
97
    public function listReferences()
98 1
    {
99
        $refs = array();
100 1
101 1
        foreach ($this->resolvers as $resolver) {
102
            if (! $resolver instanceof EnumerableReferenceResolverInterface) {
103
                throw new \Exception("Could not enumerate references because of chained resolver of type: " . get_class($resolver));
104
            }
105
106 1
            // later resolvers are stronger (see getReferenceValue)
107
            $refs = array_merge($refs, $resolver->listReferences());
108
        }
109 1
110
        return $refs;
111
    }
112
113
    /**
114
     * @param string $string
115
     * @return bool true if the given $stringIdentifier contains at least one occurrence of the reference(s)
116
     * @throws \Exception if any resolver in the chain is not an EmbeddedReferenceResolverInterface
117
     */
118
    public function hasEmbeddedReferences($string)
119
    {
120 View Code Duplication
        foreach ($this->resolvers as $resolver) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
121
            if ($resolver instanceof EmbeddedReferenceResolverInterface) {
122
                if ($resolver->hasEmbeddedReferences($string)) {
123
                    return true;
124
                }
125
            } else {
126
                throw new \Exception("Could not verify embedded references because of chained resolver of type: " . get_class($resolver));
127
            }
128
        }
129
130
        return false;
131
    }
132
133
    /**
134
     * Returns the $string with eventual refs resolved.
135
     * Q: SHALL WE GUARANTEE THAT ALL RESOLVERS IN THE CHAIN CAN TAKE PART IN THIS?
136
     *
137
     * @param string $string
138
     * @return string
139
     * @throws \Exception if any resolver in the chain is not an EmbeddedReferenceResolverInterface
140
     */
141
    public function resolveEmbeddedReferences($string)
142
    {
143 View Code Duplication
        foreach ($this->resolvers as $resolver) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
            if ($resolver instanceof EmbeddedReferenceResolverInterface) {
145
                $string = $resolver->resolveEmbeddedReferences($string);
146
            } else {
147
                throw new \Exception("Could not resolve embedded references because of chained resolver of type: " . get_class($resolver));
148
            }
149
        }
150
151
        return $string;
152
    }
153
}
154