Issues (209)

src/LightSaml/Context/AbstractContext.php (3 issues)

1
<?php
2
3
/*
4
 * This file is part of the LightSAML-Core package.
5
 *
6
 * (c) Milos Tomic <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace LightSaml\Context;
13
14
abstract class AbstractContext implements ContextInterface
15
{
16
    /** @var ContextInterface|null */
17
    private $parent;
18
19
    /** @var ContextInterface[] */
20
    private $subContexts = [];
21
22
    /**
23
     * @return ContextInterface|null
24
     */
25
    public function getParent()
26
    {
27
        return $this->parent;
28
    }
29
30
    /**
31
     * @return ContextInterface
32
     */
33
    public function getTopParent()
34
    {
35
        if ($this->getParent()) {
36
            return $this->getParent()->getTopParent();
37
        }
38
39
        return $this;
40
    }
41
42
    /**
43
     * @return ContextInterface
44
     */
45
    public function setParent(ContextInterface $parent = null)
46
    {
47
        $this->parent = $parent;
48
49
        return $this;
50
    }
51
52
    /**
53
     * @param string      $name
54
     * @param string|null $class
55
     *
56
     * @return ContextInterface|null
57
     */
58
    public function getSubContext($name, $class = null)
59
    {
60
        if (isset($this->subContexts[$name])) {
61
            return $this->subContexts[$name];
62
        }
63
64
        if ($class) {
65
            $result = $this->createSubContext($class);
66
            $this->addSubContext($name, $result);
67
68
            return $result;
69
        }
70
71
        return null;
72
    }
73
74
    /**
75
     * @param string $class
76
     * @param bool   $autoCreate
77
     *
78
     * @return ContextInterface|null
79
     */
80
    public function getSubContextByClass($class, $autoCreate)
81
    {
82
        return $this->getSubContext($class, $autoCreate ? $class : null);
83
    }
84
85
    /**
86
     * @param string                  $name
87
     * @param object|ContextInterface $subContext
88
     *
89
     * @return AbstractContext
90
     */
91
    public function addSubContext($name, $subContext)
92
    {
93
        if (false === is_object($subContext)) {
94
            throw new \InvalidArgumentException('Expected object or ContextInterface');
95
        }
96
97
        $existing = isset($this->subContexts[$name]) ? $this->subContexts[$name] : null;
98
        if ($existing === $subContext) {
99
            return $this;
100
        }
101
102
        $this->subContexts[$name] = $subContext;
103
        if ($subContext instanceof ContextInterface) {
104
            $subContext->setParent($this);
105
        }
106
107
        if ($existing instanceof ContextInterface) {
108
            $existing->setParent(null);
109
        }
110
111
        return $this;
112
    }
113
114
    /**
115
     * @param string $name
116
     *
117
     * @return ContextInterface
118
     */
119
    public function removeSubContext($name)
120
    {
121
        $subContext = $this->getSubContext($name, false);
0 ignored issues
show
false of type false is incompatible with the type null|string expected by parameter $class of LightSaml\Context\AbstractContext::getSubContext(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

121
        $subContext = $this->getSubContext($name, /** @scrutinizer ignore-type */ false);
Loading history...
122
123
        if ($subContext) {
124
            $subContext->setParent(null);
125
            unset($this->subContexts[$name]);
126
        }
127
128
        return $this;
129
    }
130
131
    /**
132
     * @param string $name
133
     *
134
     * @return bool
135
     */
136
    public function containsSubContext($name)
137
    {
138
        return isset($this->subContexts[$name]);
139
    }
140
141
    /**
142
     * @return ContextInterface
143
     */
144
    public function clearSubContexts()
145
    {
146
        foreach ($this->subContexts as $subContext) {
147
            $subContext->setParent(null);
148
        }
149
        $this->subContexts = [];
150
151
        return $this;
152
    }
153
154
    /**
155
     * @return \ArrayIterator
156
     */
157
    public function getIterator()
158
    {
159
        return new \ArrayIterator($this->subContexts);
160
    }
161
162
    /**
163
     * @param string $ownName
164
     *
165
     * @return array
166
     */
167
    public function debugPrintTree($ownName = 'root')
168
    {
169
        $result = [
170
            $ownName => static::class,
171
        ];
172
173
        if ($this->subContexts) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->subContexts of type LightSaml\Context\ContextInterface[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
174
            $arr = [];
175
            foreach ($this->subContexts as $name => $subContext) {
176
                if ($subContext instanceof ContextInterface) {
177
                    $arr = array_merge($arr, $subContext->debugPrintTree($name));
178
                } else {
179
                    $arr = array_merge($arr, [$name => get_class($subContext)]);
180
                }
181
            }
182
            $result[$ownName.'__children'] = $arr;
183
        }
184
185
        return $result;
186
    }
187
188
    /**
189
     * @return string
190
     */
191
    public function __toString()
192
    {
193
        return json_encode($this->debugPrintTree(), JSON_PRETTY_PRINT);
194
    }
195
196
    /**
197
     * @param string $path
198
     *
199
     * @return ContextInterface
200
     */
201
    public function getPath($path)
202
    {
203
        if (is_string($path)) {
0 ignored issues
show
The condition is_string($path) is always true.
Loading history...
204
            $path = explode('/', $path);
205
        } elseif (false === is_array($path)) {
206
            throw new \InvalidArgumentException('Expected string or array');
207
        }
208
209
        $name = array_shift($path);
210
        $subContext = $this->getSubContext($name);
211
        if (null == $subContext) {
212
            return null;
213
        }
214
215
        if (empty($path)) {
216
            return $subContext;
217
        } else {
218
            return $subContext->getPath($path);
219
        }
220
    }
221
222
    /**
223
     * @param string $class
224
     *
225
     * @return ContextInterface
226
     */
227
    protected function createSubContext($class)
228
    {
229
        $result = new $class();
230
231
        return $result;
232
    }
233
}
234