Completed
Push — master ( 8238b8...39728a )
by Aimeos
01:53
created

JsonAdm::clear()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2018
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 extends \Aimeos\Admin\JsonAdm\Common\Factory\Base
21
{
22
	static private $cache = true;
23
	static private $clients = [];
24
25
26
	/**
27
	 * Enables or disables caching of class instances.
28
	 *
29
	 * @param boolean $value True to enable caching, false to disable it.
30
	 * @return boolean Previous cache setting
31
	 */
32
	static public function cache( $value )
33
	{
34
		$old = self::$cache;
35
		self::$cache = (boolean) $value;
36
37
		return $old;
38
	}
39
40
41
	/**
42
	 * Removes the client objects from the cache.
43
	 *
44
	 * If neither a context ID nor a path is given, the complete cache will be pruned.
45
	 *
46
	 * @param integer $id Context ID the objects have been created with (string of \Aimeos\MShop\Context\Item\Iface)
47
	 * @param string $path Path describing the client to clear, e.g. "product/lists/type"
48
	 */
49
	static public function clear( $id = null, $path = null )
50
	{
51
		if( $id !== null )
52
		{
53
			if( $path !== null ) {
54
				self::$clients[$id][$path] = null;
55
			} else {
56
				self::$clients[$id] = [];
57
			}
58
59
			return;
60
		}
61
62
		self::$clients = [];
63
	}
64
65
66
	/**
67
	 * Creates the required client specified by the given path of client names.
68
	 *
69
	 * Clients are created by providing only the domain name, e.g. "product"
70
	 *  for the \Aimeos\Admin\JsonAdm\Product\Standard or a path of names to
71
	 * retrieve a specific sub-client, e.g. "product/type" for the
72
	 * \Aimeos\Admin\JsonAdm\Product\Type\Standard client.
73
	 *
74
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object required by clients
75
	 * @param \Aimeos\Bootstrap $aimeos Aimeos Bootstrap object
76
	 * @param string $path Name of the client separated by slashes, e.g "product/property"
77
	 * @param string|null $name Name of the client implementation ("Standard" if null)
78
	 * @return \Aimeos\Admin\JsonAdm\Iface JSON admin instance
79
	 * @throws \Aimeos\Admin\JsonAdm\Exception If the given path is invalid
80
	 */
81
	static public function create( \Aimeos\MShop\Context\Item\Iface $context,
82
		\Aimeos\Bootstrap $aimeos, $path, $name = null )
83
	{
84
		$path = strtolower( trim( $path, "/ \n\t\r\0\x0B" ) );
85
		$id = (string) $context;
86
87
		if( self::$cache === false || !isset( self::$clients[$id][$path] ) )
88
		{
89
			if( empty( $path ) ) {
90
				self::$clients[$id][$path] = self::createRoot( $context, $aimeos, $path, $name );
91
			} else {
92
				self::$clients[$id][$path] = self::createNew( $context, $aimeos, $path, $name );
93
			}
94
		}
95
96
		return self::$clients[$id][$path];
97
	}
98
99
100
	/**
101
	 * Creates a new client specified by the given path of client names.
102
	 *
103
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object required by clients
104
	 * @param \Aimeos\Bootstrap $aimeos Aimeos Bootstrap object
105
	 * @param string $path Name of the client separated by slashes, e.g "product/stock"
106
	 * @param string|null $name Name of the client implementation ("Standard" if null)
107
	 * @return \Aimeos\Admin\JsonAdm\Iface JSON admin instance
108
	 * @throws \Aimeos\Admin\JsonAdm\Exception If the given path is invalid
109
	 */
110
	protected static function createNew( \Aimeos\MShop\Context\Item\Iface $context,
111
		\Aimeos\Bootstrap $aimeos, $path, $name )
112
	{
113
		$pname = $name;
114
		$parts = explode( '/', $path );
115
116
		foreach( $parts as $key => $part )
117
		{
118
			if( ctype_alnum( $part ) === false )
119
			{
120
				$msg = sprintf( 'Invalid client "%1$s" in "%2$s"', $part, $path );
121
				throw new \Aimeos\Admin\JsonAdm\Exception( $msg, 400 );
122
			}
123
124
			$parts[$key] = ucwords( $part );
125
		}
126
127
		if( $pname === null ) {
128
			$pname = $context->getConfig()->get( 'admin/jsonadm/' . $path . '/name', 'Standard' );
129
		}
130
131
		$view = $context->getView();
132
		$config = $context->getConfig();
133
134
		if( $view->access( $config->get( 'admin/jsonadm/resource/' . $path . '/groups', [] ) ) !== true ) {
135
			throw new \Aimeos\Admin\JQAdm\Exception( sprintf( 'Not allowed to access JsonAdm "%1$s" client', $path ) );
136
		}
137
138
139
		$view = $context->getView();
140
		$iface = '\\Aimeos\\Admin\\JsonAdm\\Iface';
141
		$classname = '\\Aimeos\\Admin\\JsonAdm\\' . join( '\\', $parts ) . '\\' . $pname;
142
143
		if( ctype_alnum( $pname ) === false )
144
		{
145
			$classname = is_string( $pname ) ? $classname : '<not a string>';
146
			throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'Invalid class name "%1$s"', $classname ) );
147
		}
148
149
		if( class_exists( $classname ) === false ) {
150
			return self::createRoot( $context, $aimeos, $path, $name );
151
		}
152
153
		$client = self::createClientBase( $classname, $iface, $context, $path );
154
		$client = self::addClientDecorators( $client, $context, $path );
155
156
		return $client->setAimeos( $aimeos )->setView( $view );
157
	}
158
159
160
	/**
161
	 * Creates the top level client
162
	 *
163
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object required by clients
164
	 * @param \Aimeos\Bootstrap $aimeos Aimeos Bootstrap object
165
	 * @param string $path Name of the client separated by slashes, e.g "product/property"
166
	 * @param string|null $name Name of the JsonAdm client (default: "Standard")
167
	 * @return \Aimeos\Admin\JsonAdm\Iface JSON admin instance
168
	 * @throws \Aimeos\Admin\JsonAdm\Exception If the client couldn't be created
169
	 */
170
	protected static function createRoot( \Aimeos\MShop\Context\Item\Iface $context,
171
		\Aimeos\Bootstrap $aimeos, $path, $name = null )
172
	{
173
		/** admin/jsonadm/name
174
		 * Class name of the used JSON API client implementation
175
		 *
176
		 * Each default JSON API client can be replace by an alternative imlementation.
177
		 * To use this implementation, you have to set the last part of the class
178
		 * name as configuration value so the client factory knows which class it
179
		 * has to instantiate.
180
		 *
181
		 * For example, if the name of the default class is
182
		 *
183
		 *  \Aimeos\Admin\JsonAdm\Standard
184
		 *
185
		 * and you want to replace it with your own version named
186
		 *
187
		 *  \Aimeos\Admin\JsonAdm\Mycntl
188
		 *
189
		 * then you have to set the this configuration option:
190
		 *
191
		 *  admin/jsonadm/name = Mycntl
192
		 *
193
		 * The value is the last part of your own class name and it's case sensitive,
194
		 * so take care that the configuration value is exactly named like the last
195
		 * part of the class name.
196
		 *
197
		 * The allowed characters of the class name are A-Z, a-z and 0-9. No other
198
		 * characters are possible! You should always start the last part of the class
199
		 * name with an upper case character and continue only with lower case characters
200
		 * or numbers. Avoid chamel case names like "MyCntl"!
201
		 *
202
		 * @param string Last part of the class name
203
		 * @since 2015.12
204
		 * @category Developer
205
		 */
206
		if( $name === null ) {
207
			$name = $context->getConfig()->get( 'admin/jsonadm/name', 'Standard' );
208
		}
209
210
		if( ctype_alnum( $name ) === false )
211
		{
212
			$classname = is_string( $name ) ? '\\Aimeos\\Admin\\JsonAdm\\' . $name : '<not a string>';
213
			throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'Invalid class name "%1$s"', $classname ) );
214
		}
215
216
		$view = $context->getView();
217
		$iface = '\\Aimeos\\Admin\\JsonAdm\\Iface';
218
		$classname = '\\Aimeos\\Admin\\JsonAdm\\' . $name;
219
220
		$client = self::createClientBase( $classname, $iface, $context, $path );
221
222
		/** admin/jsonadm/decorators/excludes
223
		 * Excludes decorators added by the "common" option from the JSON API clients
224
		 *
225
		 * Decorators extend the functionality of a class by adding new aspects
226
		 * (e.g. log what is currently done), executing the methods of the underlying
227
		 * class only in certain conditions (e.g. only for logged in users) or
228
		 * modify what is returned to the caller.
229
		 *
230
		 * This option allows you to remove a decorator added via
231
		 * "admin/jsonadm/common/decorators/default" before they are wrapped
232
		 * around the Jsonadm client.
233
		 *
234
		 *  admin/jsonadm/decorators/excludes = array( 'decorator1' )
235
		 *
236
		 * This would remove the decorator named "decorator1" from the list of
237
		 * common decorators ("\Aimeos\Admin\JsonAdm\Common\Decorator\*") added via
238
		 * "admin/jsonadm/common/decorators/default" for the JSON API client.
239
		 *
240
		 * @param array List of decorator names
241
		 * @since 2016.01
242
		 * @category Developer
243
		 * @see admin/jsonadm/common/decorators/default
244
		 * @see admin/jsonadm/decorators/global
245
		 * @see admin/jsonadm/decorators/local
246
		 */
247
248
		/** admin/jsonadm/decorators/global
249
		 * Adds a list of globally available decorators only to the Jsonadm client
250
		 *
251
		 * Decorators extend the functionality of a class by adding new aspects
252
		 * (e.g. log what is currently done), executing the methods of the underlying
253
		 * class only in certain conditions (e.g. only for logged in users) or
254
		 * modify what is returned to the caller.
255
		 *
256
		 * This option allows you to wrap global decorators
257
		 * ("\Aimeos\Admin\Jsonadm\Common\Decorator\*") around the Jsonadm
258
		 * client.
259
		 *
260
		 *  admin/jsonadm/product/decorators/global = array( 'decorator1' )
261
		 *
262
		 * This would add the decorator named "decorator1" defined by
263
		 * "\Aimeos\Admin\Jsonadm\Common\Decorator\Decorator1" only to the
264
		 * "product" Jsonadm client.
265
		 *
266
		 * @param array List of decorator names
267
		 * @since 2016.01
268
		 * @category Developer
269
		 * @see admin/jsonadm/common/decorators/default
270
		 * @see admin/jsonadm/decorators/excludes
271
		 * @see admin/jsonadm/decorators/local
272
		 */
273
274
		/** admin/jsonadm/decorators/local
275
		 * Adds a list of local decorators only to the Jsonadm client
276
		 *
277
		 * Decorators extend the functionality of a class by adding new aspects
278
		 * (e.g. log what is currently done), executing the methods of the underlying
279
		 * class only in certain conditions (e.g. only for logged in users) or
280
		 * modify what is returned to the caller.
281
		 *
282
		 * This option allows you to wrap local decorators
283
		 * ("\Aimeos\Admin\Jsonadm\Product\Decorator\*") around the Jsonadm
284
		 * client.
285
		 *
286
		 *  admin/jsonadm/product/decorators/local = array( 'decorator2' )
287
		 *
288
		 * This would add the decorator named "decorator2" defined by
289
		 * "\Aimeos\Admin\Jsonadm\Product\Decorator\Decorator2" only to the
290
		 * "product" Jsonadm client.
291
		 *
292
		 * @param array List of decorator names
293
		 * @since 2016.01
294
		 * @category Developer
295
		 * @see admin/jsonadm/common/decorators/default
296
		 * @see admin/jsonadm/decorators/excludes
297
		 * @see admin/jsonadm/decorators/global
298
		 */
299
300
		$client = self::addClientDecorators( $client, $context, $path );
301
302
		return $client->setAimeos( $aimeos )->setView( $view );
303
	}
304
}
305