Completed
Push — master ( e32eeb...714cda )
by
unknown
89:50 queued 46:29
created

AliasCollection::removeDependedAliases()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 15
rs 8.8571
cc 5
eloc 10
nc 4
nop 2
1
<?php
2
3
namespace Oro\Component\Layout;
4
5
class AliasCollection
6
{
7
    /**
8
     * @var string[]
9
     *
10
     * Example:
11
     *  [
12
     *      'my_header'   => 'header',
13
     *      'my_footer'   => 'footer',
14
     *      'page_header' => 'header', // second alias for the header item
15
     *      'some_header' => 'my_header' // one more alias for the header item
16
     *  ]
17
     */
18
    protected $aliases = [];
19
20
    /**
21
     * @var array
22
     *
23
     * Example:
24
     *  [
25
     *      'header' => ['my_header', 'page_header', 'some_header'],
26
     *      'footer' => ['my_footer'],
27
     *  ]
28
     */
29
    protected $ids = [];
30
31
    /**
32
     * Checks if the given alias is used for some item
33
     *
34
     * @param string $alias The item alias
35
     *
36
     * @return bool
37
     */
38
    public function has($alias)
39
    {
40
        return isset($this->aliases[$alias]);
41
    }
42
43
    /**
44
     * Returns the identifier of the item which has the given alias
45
     *
46
     * @param string $alias The item alias
47
     *
48
     * @return string|null The item identifier or null if no one item has the given alias
49
     */
50
    public function getId($alias)
51
    {
52
        if (!isset($this->aliases[$alias])) {
53
            return null;
54
        }
55
56
        $id = $this->aliases[$alias];
57
        while (isset($this->aliases[$id])) {
58
            $id = $this->aliases[$id];
59
        }
60
61
        return $id;
62
    }
63
64
    /**
65
     * Returns a list of all aliases registered for the given item
66
     *
67
     * @param string $id The item id
68
     *
69
     * @return string[] The list of all aliases for the item with the given id
70
     */
71
    public function getAliases($id)
72
    {
73
        return isset($this->ids[$id])
74
            ? $this->ids[$id]
75
            : [];
76
    }
77
78
    /**
79
     * Registers an alias for the specified identifier
80
     *
81
     * @param string $alias A string that can be used as an alias for the item id
82
     * @param string $id    The item identifier or already registered item alias
83
     *
84
     * @return self
85
     *
86
     * @throws Exception\AliasAlreadyExistsException if the alias is used for another item
87
     */
88
    public function add($alias, $id)
89
    {
90
        if (isset($this->aliases[$alias])) {
91
            if ($this->aliases[$alias] === $id) {
92
                // exactly the same alias for the specified item is already exists
93
                return $this;
94
            }
95
96
            throw new Exception\AliasAlreadyExistsException(
97
                sprintf(
98
                    'The "%s" sting cannot be used as an alias for "%s" item'
99
                    . ' because it is already used for "%s" item.',
100
                    $alias,
101
                    $id,
102
                    $this->aliases[$alias]
103
                )
104
            );
105
        }
106
107
        $this->aliases[$alias] = $id;
108
109
        $id               = $this->getId($alias);
110
        $this->ids[$id][] = $alias;
111
112
        return $this;
113
    }
114
115
    /**
116
     * Removes the alias
117
     *
118
     * @param string $alias The item alias
119
     *
120
     * @return self
121
     */
122
    public function remove($alias)
123
    {
124
        $id = $this->getId($alias);
125
        if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
126
            unset($this->aliases[$alias]);
127
            $aliases = &$this->ids[$id];
128
            unset($aliases[array_search($alias, $aliases, true)]);
129
            if (!empty($aliases)) {
130
                $this->removeDependedAliases($alias, $id);
131
            } else {
132
                unset($this->ids[$id]);
133
            }
134
        }
135
136
        return $this;
137
    }
138
139
    /**
140
     * Removes all aliases for the specified item
141
     *
142
     * @param string $id The identifier of item which aliases should be removed
143
     *
144
     * @return self
145
     */
146
    public function removeById($id)
147
    {
148
        if (isset($this->ids[$id])) {
149
            foreach ($this->ids[$id] as $alias) {
150
                unset($this->aliases[$alias]);
151
            }
152
            unset($this->ids[$id]);
153
        }
154
155
        return $this;
156
    }
157
158
    /**
159
     * Checks whether at least one item has an alias
160
     *
161
     * @return bool
162
     */
163
    public function isEmpty()
164
    {
165
        return empty($this->aliases);
166
    }
167
168
    /**
169
     * Removes all data from this collection
170
     */
171
    public function clear()
172
    {
173
        $this->aliases = [];
174
        $this->ids     = [];
175
    }
176
177
    /**
178
     * Removes all depended aliases
179
     * For example if "alias3" is removed in alias chain like "alias1 -> alias2 -> alias3 -> id"
180
     * than both "alias1" and "alias2" are removed as well
181
     *
182
     * @param string $alias
183
     * @param string $id
184
     */
185
    protected function removeDependedAliases($alias, $id)
186
    {
187
        foreach ($this->ids[$id] as $otherAlias) {
188
            if (isset($this->aliases[$otherAlias]) && $this->aliases[$otherAlias] === $alias) {
189
                unset($this->aliases[$otherAlias]);
190
                $aliases = &$this->ids[$id];
191
                unset($aliases[array_search($otherAlias, $aliases, true)]);
192
                if (!empty($aliases)) {
193
                    $this->removeDependedAliases($otherAlias, $id);
194
                } else {
195
                    unset($this->ids[$id]);
196
                }
197
            }
198
        }
199
    }
200
}
201