1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0 |
||||
5 | * @copyright Aimeos (aimeos.org), 2015-2025 |
||||
6 | * @package Admin |
||||
7 | * @subpackage JsonAdm |
||||
8 | */ |
||||
9 | |||||
10 | |||||
11 | namespace Aimeos\Admin; |
||||
12 | |||||
13 | |||||
14 | /** |
||||
15 | * Factory which can create all JSON API clients |
||||
16 | * |
||||
17 | * @package Admin |
||||
18 | * @subpackage JsonAdm |
||||
19 | */ |
||||
20 | class JsonAdm |
||||
21 | { |
||||
22 | /** admin/jsonadm/name |
||||
23 | * Class name of the used JSON API client implementation |
||||
24 | * |
||||
25 | * Each default JSON API client can be replace by an alternative imlementation. |
||||
26 | * To use this implementation, you have to set the last part of the class |
||||
27 | * name as configuration value so the client factory knows which class it |
||||
28 | * has to instantiate. |
||||
29 | * |
||||
30 | * For example, if the name of the default class is |
||||
31 | * |
||||
32 | * \Aimeos\Admin\JsonAdm\Standard |
||||
33 | * |
||||
34 | * and you want to replace it with your own version named |
||||
35 | * |
||||
36 | * \Aimeos\Admin\JsonAdm\Mycntl |
||||
37 | * |
||||
38 | * then you have to set the this configuration option: |
||||
39 | * |
||||
40 | * admin/jsonadm/name = Mycntl |
||||
41 | * |
||||
42 | * The value is the last part of your own class name and it's case sensitive, |
||||
43 | * so take care that the configuration value is exactly named like the last |
||||
44 | * part of the class name. |
||||
45 | * |
||||
46 | * The allowed characters of the class name are A-Z, a-z and 0-9. No other |
||||
47 | * characters are possible! You should always start the last part of the class |
||||
48 | * name with an upper case character and continue only with lower case characters |
||||
49 | * or numbers. Avoid chamel case names like "MyCntl"! |
||||
50 | * |
||||
51 | * @param string Last part of the class name |
||||
52 | * @since 2015.12 |
||||
53 | * @category Developer |
||||
54 | */ |
||||
55 | |||||
56 | /** admin/jsonadm/decorators/excludes |
||||
57 | * Excludes decorators added by the "common" option from the JSON API clients |
||||
58 | * |
||||
59 | * Decorators extend the functionality of a class by adding new aspects |
||||
60 | * (e.g. log what is currently done), executing the methods of the underlying |
||||
61 | * class only in certain conditions (e.g. only for logged in users) or |
||||
62 | * modify what is returned to the caller. |
||||
63 | * |
||||
64 | * This option allows you to remove a decorator added via |
||||
65 | * "admin/jsonadm/common/decorators/default" before they are wrapped |
||||
66 | * around the Jsonadm client. |
||||
67 | * |
||||
68 | * admin/jsonadm/decorators/excludes = array( 'decorator1' ) |
||||
69 | * |
||||
70 | * This would remove the decorator named "decorator1" from the list of |
||||
71 | * common decorators ("\Aimeos\Admin\JsonAdm\Common\Decorator\*") added via |
||||
72 | * "admin/jsonadm/common/decorators/default" for the JSON API client. |
||||
73 | * |
||||
74 | * @param array List of decorator names |
||||
75 | * @since 2016.01 |
||||
76 | * @category Developer |
||||
77 | * @see admin/jsonadm/common/decorators/default |
||||
78 | * @see admin/jsonadm/decorators/global |
||||
79 | * @see admin/jsonadm/decorators/local |
||||
80 | */ |
||||
81 | |||||
82 | /** admin/jsonadm/decorators/global |
||||
83 | * Adds a list of globally available decorators only to the Jsonadm client |
||||
84 | * |
||||
85 | * Decorators extend the functionality of a class by adding new aspects |
||||
86 | * (e.g. log what is currently done), executing the methods of the underlying |
||||
87 | * class only in certain conditions (e.g. only for logged in users) or |
||||
88 | * modify what is returned to the caller. |
||||
89 | * |
||||
90 | * This option allows you to wrap global decorators |
||||
91 | * ("\Aimeos\Admin\Jsonadm\Common\Decorator\*") around the Jsonadm |
||||
92 | * client. |
||||
93 | * |
||||
94 | * admin/jsonadm/product/decorators/global = array( 'decorator1' ) |
||||
95 | * |
||||
96 | * This would add the decorator named "decorator1" defined by |
||||
97 | * "\Aimeos\Admin\Jsonadm\Common\Decorator\Decorator1" only to the |
||||
98 | * "product" Jsonadm client. |
||||
99 | * |
||||
100 | * @param array List of decorator names |
||||
101 | * @since 2016.01 |
||||
102 | * @category Developer |
||||
103 | * @see admin/jsonadm/common/decorators/default |
||||
104 | * @see admin/jsonadm/decorators/excludes |
||||
105 | * @see admin/jsonadm/decorators/local |
||||
106 | */ |
||||
107 | |||||
108 | /** admin/jsonadm/decorators/local |
||||
109 | * Adds a list of local decorators only to the Jsonadm client |
||||
110 | * |
||||
111 | * Decorators extend the functionality of a class by adding new aspects |
||||
112 | * (e.g. log what is currently done), executing the methods of the underlying |
||||
113 | * class only in certain conditions (e.g. only for logged in users) or |
||||
114 | * modify what is returned to the caller. |
||||
115 | * |
||||
116 | * This option allows you to wrap local decorators |
||||
117 | * ("\Aimeos\Admin\Jsonadm\Product\Decorator\*") around the Jsonadm |
||||
118 | * client. |
||||
119 | * |
||||
120 | * admin/jsonadm/product/decorators/local = array( 'decorator2' ) |
||||
121 | * |
||||
122 | * This would add the decorator named "decorator2" defined by |
||||
123 | * "\Aimeos\Admin\Jsonadm\Product\Decorator\Decorator2" only to the |
||||
124 | * "product" Jsonadm client. |
||||
125 | * |
||||
126 | * @param array List of decorator names |
||||
127 | * @since 2016.01 |
||||
128 | * @category Developer |
||||
129 | * @see admin/jsonadm/common/decorators/default |
||||
130 | * @see admin/jsonadm/decorators/excludes |
||||
131 | * @see admin/jsonadm/decorators/global |
||||
132 | */ |
||||
133 | |||||
134 | |||||
135 | private static $objects = []; |
||||
136 | |||||
137 | |||||
138 | /** |
||||
139 | * Creates the required client specified by the given path of client names. |
||||
140 | * |
||||
141 | * Clients are created by providing only the domain name, e.g. "product" |
||||
142 | * for the \Aimeos\Admin\JsonAdm\Product\Standard or a path of names to |
||||
143 | * retrieve a specific sub-client, e.g. "product/type" for the |
||||
144 | * \Aimeos\Admin\JsonAdm\Product\Type\Standard client. |
||||
145 | * |
||||
146 | * @param \Aimeos\MShop\ContextIface $context Context object required by clients |
||||
147 | * @param \Aimeos\Bootstrap $aimeos Aimeos Bootstrap object |
||||
148 | * @param string $path Name of the client separated by slashes, e.g "product/property" |
||||
149 | * @param string|null $name Name of the client implementation ("Standard" if null) |
||||
150 | * @return \Aimeos\Admin\JsonAdm\Iface JSON admin instance |
||||
151 | * @throws \Aimeos\Admin\JsonAdm\Exception If the given path is invalid |
||||
152 | */ |
||||
153 | public static function create( \Aimeos\MShop\ContextIface $context, \Aimeos\Bootstrap $aimeos, |
||||
154 | string $path, ?string $name = null ) : \Aimeos\Admin\JsonAdm\Iface |
||||
155 | { |
||||
156 | if( preg_match( '/^[a-z0-9\/]*$/', $path ) !== 1 ) { |
||||
157 | throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'Invalid component path "%1$s"', $path, 400 ) ); |
||||
158 | } |
||||
159 | |||||
160 | empty( $path = trim( $path, '/' ) ) ?: $path .= '/'; |
||||
161 | |||||
162 | $view = $context->view(); |
||||
163 | $config = $context->config(); |
||||
164 | |||||
165 | if( $view->access( $config->get( 'admin/jsonadm/resource/' . $path . 'groups', [] ) ) !== true ) { |
||||
166 | throw new \Aimeos\Admin\JQAdm\Exception( sprintf( 'Not allowed to access JsonAdm "%1$s" client', $path ), 403 ); |
||||
0 ignored issues
–
show
|
|||||
167 | } |
||||
168 | |||||
169 | $cname = $name ?: $context->config()->get( 'admin/jsonadm/' . $path . 'name', 'Standard' ); |
||||
170 | |||||
171 | $classname = '\\Aimeos\\Admin\\JsonAdm\\' . str_replace( '/', '\\', ucwords( $path, '/' ) ) . $cname; |
||||
172 | $interface = '\\Aimeos\\Admin\\JsonAdm\\Iface'; |
||||
173 | |||||
174 | if( class_exists( $classname ) === false ) |
||||
175 | { |
||||
176 | $cname = $name ?: $context->config()->get( 'admin/jsonadm/name', 'Standard' ); |
||||
177 | $classname = '\\Aimeos\\Admin\\JsonAdm\\' . $cname; |
||||
178 | |||||
179 | if( class_exists( $classname ) === false ) { |
||||
180 | throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'Class "%1$s" not found', $classname, 404 ) ); |
||||
181 | } |
||||
182 | } |
||||
183 | |||||
184 | $client = self::createComponent( $context, $classname, $interface, $path ); |
||||
185 | |||||
186 | return $client->setAimeos( $aimeos )->setView( $view ); |
||||
0 ignored issues
–
show
The method
setAimeos() does not exist on Aimeos\Admin\JsonAdm\Iface . It seems like you code against a sub-type of said class. However, the method does not exist in Aimeos\Admin\JsonAdm\Common\Iface or Aimeos\Admin\JsonAdm\Common\Decorator\Iface . Are you sure you never get one of those?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
187 | } |
||||
188 | |||||
189 | |||||
190 | /** |
||||
191 | * Injects a client object |
||||
192 | * |
||||
193 | * The object is returned via create() if an instance of the class |
||||
194 | * with the name name is requested. |
||||
195 | * |
||||
196 | * @param string $classname Full name of the class for which the object should be returned |
||||
197 | * @param \Aimeos\Admin\JsonAdm\Iface|null $client JSON API client object |
||||
198 | */ |
||||
199 | public static function inject( string $classname, ?\Aimeos\Admin\JsonAdm\Iface $client = null ) |
||||
200 | { |
||||
201 | self::$objects['\\' . ltrim( $classname, '\\' )] = $client; |
||||
202 | } |
||||
203 | |||||
204 | |||||
205 | /** |
||||
206 | * Adds the decorators to the JSON API client object |
||||
207 | * |
||||
208 | * @param \Aimeos\MShop\ContextIface $context Context instance with necessary objects |
||||
209 | * @param \Aimeos\Admin\JsonAdm\Common\Iface $client Client object |
||||
210 | * @param string $path Name of the client separated by slashes, e.g "product/property" |
||||
211 | * @return \Aimeos\Admin\JsonAdm\Iface Client object |
||||
212 | */ |
||||
213 | protected static function addComponentDecorators( \Aimeos\MShop\ContextIface $context, |
||||
214 | \Aimeos\Admin\JsonAdm\Iface $client, string $path ) : \Aimeos\Admin\JsonAdm\Iface |
||||
215 | { |
||||
216 | $config = $context->config(); |
||||
217 | $localClass = str_replace( '/', '\\', ucwords( $path, '/' ) ); |
||||
218 | |||||
219 | $classprefix = '\\Aimeos\\Admin\\JsonAdm\\' . ucfirst( $localClass ) . 'Decorator\\'; |
||||
220 | $decorators = array_reverse( $config->get( 'admin/jsonadm/' . $path . 'decorators/local', [] ) ); |
||||
221 | $client = self::addDecorators( $context, $client, $path, $decorators, $classprefix ); |
||||
222 | |||||
223 | $classprefix = '\\Aimeos\\Admin\\JsonAdm\\Common\\Decorator\\'; |
||||
224 | $decorators = array_reverse( $config->get( 'admin/jsonadm/' . $path . 'decorators/global', [] ) ); |
||||
225 | $client = self::addDecorators( $context, $client, $path, $decorators, $classprefix ); |
||||
226 | |||||
227 | /** admin/jsonadm/common/decorators/default |
||||
228 | * Configures the list of decorators applied to all JSON API clients |
||||
229 | * |
||||
230 | * Decorators extend the functionality of a class by adding new aspects |
||||
231 | * (e.g. log what is currently done), executing the methods of the underlying |
||||
232 | * class only in certain conditions (e.g. only for logged in users) or |
||||
233 | * modify what is returned to the caller. |
||||
234 | * |
||||
235 | * This option allows you to configure a list of decorator names that should |
||||
236 | * be wrapped around the original instance of all created clients: |
||||
237 | * |
||||
238 | * admin/jsonadm/common/decorators/default = array( 'decorator1', 'decorator2' ) |
||||
239 | * |
||||
240 | * This would wrap the decorators named "decorator1" and "decorator2" around |
||||
241 | * all client instances in that order. The decorator classes would be |
||||
242 | * "\Aimeos\Admin\JsonAdm\Common\Decorator\Decorator1" and |
||||
243 | * "\Aimeos\Admin\JsonAdm\Common\Decorator\Decorator2". |
||||
244 | * |
||||
245 | * @param array List of decorator names |
||||
246 | * @since 2015.12 |
||||
247 | * @category Developer |
||||
248 | */ |
||||
249 | $decorators = array_reverse( $config->get( 'admin/jsonadm/common/decorators/default', [] ) ); |
||||
250 | $excludes = $config->get( 'admin/jsonadm/' . $path . 'decorators/excludes', [] ); |
||||
251 | |||||
252 | foreach( $decorators as $key => $name ) |
||||
253 | { |
||||
254 | if( in_array( $name, $excludes ) ) { |
||||
255 | unset( $decorators[$key] ); |
||||
256 | } |
||||
257 | } |
||||
258 | |||||
259 | $classprefix = '\\Aimeos\\Admin\\JsonAdm\\Common\\Decorator\\'; |
||||
260 | $client = self::addDecorators( $context, $client, $path, $decorators, $classprefix ); |
||||
261 | |||||
262 | return $client; |
||||
263 | } |
||||
264 | |||||
265 | |||||
266 | /** |
||||
267 | * Adds the decorators to the client object |
||||
268 | * |
||||
269 | * @param \Aimeos\MShop\ContextIface $context Context instance with necessary objects |
||||
270 | * @param \Aimeos\Admin\JsonAdm\Iface $client Client object |
||||
271 | * @param array $decorators List of decorator names |
||||
272 | * @param string $classprefix Decorator class prefix, e.g. "\Aimeos\Admin\JsonAdm\Product\Decorator\" |
||||
273 | * @param string $path Name of the client separated by slashes, e.g "product/stock" |
||||
274 | * @return \Aimeos\Admin\JsonAdm\Iface Client object |
||||
275 | * @throws \LogicException If class can't be instantiated |
||||
276 | */ |
||||
277 | protected static function addDecorators( \Aimeos\MShop\ContextIface $context, \Aimeos\Admin\JsonAdm\Iface $client, |
||||
278 | string $path, array $decorators, string $classprefix ) : \Aimeos\Admin\JsonAdm\Iface |
||||
279 | { |
||||
280 | $interface = \Aimeos\Admin\JsonAdm\Common\Decorator\Iface::class; |
||||
281 | |||||
282 | foreach( $decorators as $name ) |
||||
283 | { |
||||
284 | if( ctype_alnum( $name ) === false ) { |
||||
285 | throw new \LogicException( sprintf( 'Invalid class name "%1$s"', $name ), 400 ); |
||||
286 | } |
||||
287 | |||||
288 | $client = \Aimeos\Utils::create( $classprefix . $name, [$client, $context, $path], $interface ); |
||||
289 | } |
||||
290 | |||||
291 | return $client; |
||||
292 | } |
||||
293 | |||||
294 | |||||
295 | /** |
||||
296 | * Creates a new client object |
||||
297 | * |
||||
298 | * @param \Aimeos\MShop\ContextIface $context Context object |
||||
299 | * @param string $classname Name of the client class |
||||
300 | * @param string $interface Name of the client interface |
||||
301 | * @param string $path Name of the client separated by slashes, e.g "product/property" |
||||
302 | * @return \Aimeos\Admin\JsonAdm\Iface Client object |
||||
303 | */ |
||||
304 | protected static function createComponent( \Aimeos\MShop\ContextIface $context, |
||||
305 | string $classname, string $interface, string $path ) : \Aimeos\Admin\JsonAdm\Iface |
||||
306 | { |
||||
307 | if( isset( self::$objects[$classname] ) ) { |
||||
308 | return self::$objects[$classname]; |
||||
309 | } |
||||
310 | |||||
311 | $client = \Aimeos\Utils::create( $classname, [$context, trim( $path, '/' )], $interface ); |
||||
312 | |||||
313 | return self::addComponentDecorators( $context, $client, $path ); |
||||
314 | } |
||||
315 | } |
||||
316 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths