PluginProbe
Boxzilla – WordPress Popup Builder / 3.4.9
Boxzilla – WordPress Popup Builder v3.4.9
3.4.11 3.4.10 3.4.9 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 trunk 3.0 3.0.1 3.0.2 3.0.3 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 All 72 releases
boxzilla / src / di / class-container.php

class-container.php in Boxzilla – WordPress Popup Builder 3.4.9, at src/di/class-container.php

257 lines 7.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // phpcs:ignoreFile
3 /*
4 * This is a modified version of Pimple, a dependency injection container for PHP originally developed by Fabien Potencier.
5 *
6 * Copyright (c) 2009 Fabien Potencier
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is furnished
13 * to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in all
16 * copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
27 namespace Boxzilla\DI;
28
29 /**
30 * Container main class.
31 *
32 * @author Fabien Potencier
33 */
34 class Container implements \ArrayAccess {
35
36 private $values = array();
37 private $factories;
38 private $protected;
39 private $frozen = array();
40 private $raw = array();
41 private $keys = array();
42
43 /**
44 * Instantiate the container.
45 *
46 * Objects and parameters can be passed as argument to the constructor.
47 *
48 * @param array $values The parameters or objects.
49 */
50 public function __construct( array $values = array() ) {
51 $this->factories = new \SplObjectStorage();
52 $this->protected = new \SplObjectStorage();
53
54 foreach ( $values as $key => $value ) {
55 $this->offsetSet( $key, $value );
56 }
57 }
58
59 /**
60 * Sets a parameter or an object.
61 *
62 * Objects must be defined as Closures.
63 *
64 * Allowing any PHP callable leads to difficult to debug problems
65 * as function names (strings) are callable (creating a function with
66 * the same name as an existing parameter would break your container).
67 *
68 * @param string $id The unique identifier for the parameter or object
69 * @param mixed $value The value of the parameter or a closure to define an object
70 * @throws \RuntimeException Prevent override of a frozen service
71 */
72 #[\ReturnTypeWillChange]
73 public function offsetSet( $id, $value ) {
74 if ( isset( $this->frozen[ $id ] ) ) {
75 throw new \RuntimeException( sprintf( 'Cannot override frozen service "%s".', $id ) );
76 }
77
78 $this->values[ $id ] = $value;
79 $this->keys[ $id ] = true;
80 }
81
82 /**
83 * Gets a parameter or an object.
84 *
85 * @param string $id The unique identifier for the parameter or object
86 *
87 * @return mixed The value of the parameter or an object
88 *
89 * @throws \InvalidArgumentException if the identifier is not defined
90 */
91 #[\ReturnTypeWillChange]
92 public function offsetGet( $id ) {
93 if ( ! isset( $this->keys[ $id ] ) ) {
94 throw new \InvalidArgumentException( sprintf( 'Identifier "%s" is not defined.', $id ) );
95 }
96
97 if (
98 isset( $this->raw[ $id ] )
99 || ! is_object( $this->values[ $id ] )
100 || isset( $this->protected[ $this->values[ $id ] ] )
101 || ! method_exists( $this->values[ $id ], '__invoke' )
102 ) {
103 return $this->values[ $id ];
104 }
105
106 if ( isset( $this->factories[ $this->values[ $id ] ] ) ) {
107 return $this->values[ $id ]($this);
108 }
109
110 $raw = $this->values[ $id ];
111 $val = $this->values[ $id ] = $raw( $this );
112 $this->raw[ $id ] = $raw;
113
114 $this->frozen[ $id ] = true;
115
116 return $val;
117 }
118
119 /**
120 * Checks if a parameter or an object is set.
121 *
122 * @param string $id The unique identifier for the parameter or object
123 *
124 * @return bool
125 */
126 #[\ReturnTypeWillChange]
127 public function offsetExists( $id ) {
128 return isset( $this->keys[ $id ] );
129 }
130
131 /**
132 * Unsets a parameter or an object.
133 *
134 * @param string $id The unique identifier for the parameter or object
135 */
136 #[\ReturnTypeWillChange]
137 public function offsetUnset( $id ) {
138 if ( isset( $this->keys[ $id ] ) ) {
139 if ( is_object( $this->values[ $id ] ) ) {
140 unset( $this->factories[ $this->values[ $id ] ], $this->protected[ $this->values[ $id ] ] );
141 }
142
143 unset( $this->values[ $id ], $this->frozen[ $id ], $this->raw[ $id ], $this->keys[ $id ] );
144 }
145 }
146
147 /**
148 * Marks a callable as being a factory service.
149 *
150 * @param callable $callable A service definition to be used as a factory
151 *
152 * @return callable The passed callable
153 *
154 * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object
155 */
156 public function factory( $callable ) {
157 if ( ! is_object( $callable ) || ! method_exists( $callable, '__invoke' ) ) {
158 throw new \InvalidArgumentException( 'Service definition is not a Closure or invokable object.' );
159 }
160
161 $this->factories->attach( $callable );
162
163 return $callable;
164 }
165
166 /**
167 * Protects a callable from being interpreted as a service.
168 *
169 * This is useful when you want to store a callable as a parameter.
170 *
171 * @param callable $callable A callable to protect from being evaluated
172 *
173 * @return callable The passed callable
174 *
175 * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object
176 */
177 public function protect( $callable ) {
178 if ( ! is_object( $callable ) || ! method_exists( $callable, '__invoke' ) ) {
179 throw new \InvalidArgumentException( 'Callable is not a Closure or invokable object.' );
180 }
181
182 $this->protected->attach( $callable );
183
184 return $callable;
185 }
186
187 /**
188 * Gets a parameter or the closure defining an object.
189 *
190 * @param string $id The unique identifier for the parameter or object
191 *
192 * @return mixed The value of the parameter or the closure defining an object
193 *
194 * @throws \InvalidArgumentException if the identifier is not defined
195 */
196 public function raw( $id ) {
197 if ( ! isset( $this->keys[ $id ] ) ) {
198 throw new \InvalidArgumentException( sprintf( 'Identifier "%s" is not defined.', $id ) );
199 }
200
201 if ( isset( $this->raw[ $id ] ) ) {
202 return $this->raw[ $id ];
203 }
204
205 return $this->values[ $id ];
206 }
207
208 /**
209 * Extends an object definition.
210 *
211 * Useful when you want to extend an existing object definition,
212 * without necessarily loading that object.
213 *
214 * @param string $id The unique identifier for the object
215 * @param callable $callable A service definition to extend the original
216 *
217 * @return callable The wrapped callable
218 *
219 * @throws \InvalidArgumentException if the identifier is not defined or not a service definition
220 */
221 public function extend( $id, $callable ) {
222 if ( ! isset( $this->keys[ $id ] ) ) {
223 throw new \InvalidArgumentException( sprintf( 'Identifier "%s" is not defined.', $id ) );
224 }
225
226 if ( ! is_object( $this->values[ $id ] ) || ! method_exists( $this->values[ $id ], '__invoke' ) ) {
227 throw new \InvalidArgumentException( sprintf( 'Identifier "%s" does not contain an object definition.', $id ) );
228 }
229
230 if ( ! is_object( $callable ) || ! method_exists( $callable, '__invoke' ) ) {
231 throw new \InvalidArgumentException( 'Extension service definition is not a Closure or invokable object.' );
232 }
233
234 $factory = $this->values[ $id ];
235
236 $extended = function ( $c ) use ( $callable, $factory ) {
237 return $callable( $factory( $c ), $c );
238 };
239
240 if ( isset( $this->factories[ $factory ] ) ) {
241 $this->factories->detach( $factory );
242 $this->factories->attach( $extended );
243 }
244
245 return $this[ $id ] = $extended;
246 }
247
248 /**
249 * Returns all defined value names.
250 *
251 * @return array An array of value names
252 */
253 public function keys() {
254 return array_keys( $this->values );
255 }
256 }
257