Completed
Push — master ( c22e8e...3fbe79 )
by Aimeos
02:22
created

Factory::createClientRoot()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 132
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 132
rs 8.1935
c 0
b 0
f 0
cc 4
eloc 12
nc 6
nop 4

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2016
6
 * @package Admin
7
 * @subpackage JsonAdm
8
 */
9
10
11
namespace Aimeos\Admin\JsonAdm;
12
13
14
/**
15
 * Factory which can create all JSON API clients
16
 *
17
 * @package Admin
18
 * @subpackage JsonAdm
19
 */
20
class Factory
21
	extends \Aimeos\Admin\JsonAdm\Common\Factory\Base
0 ignored issues
show
Coding Style introduced by
The extends keyword must be on the same line as the class name
Loading history...
Coding Style introduced by
Expected 0 spaces between "Base" and comma; 1 found
Loading history...
22
	implements \Aimeos\Admin\JsonAdm\Common\Factory\Iface
0 ignored issues
show
Coding Style introduced by
The implements keyword must be on the same line as the class name
Loading history...
23
{
24
	static private $cache = true;
25
	static private $clients = [];
26
27
28
	/**
29
	 * Removes the client objects from the cache.
30
	 *
31
	 * If neither a context ID nor a path is given, the complete cache will be pruned.
32
	 *
33
	 * @param integer $id Context ID the objects have been created with (string of \Aimeos\MShop\Context\Item\Iface)
34
	 * @param string $path Path describing the client to clear, e.g. "product/lists/type"
35
	 */
36
	static public function clear( $id = null, $path = null )
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
37
	{
38
		if( $id !== null )
39
		{
40
			if( $path !== null ) {
41
				self::$clients[$id][$path] = null;
42
			} else {
43
				self::$clients[$id] = [];
44
			}
45
46
			return;
47
		}
48
49
		self::$clients = [];
50
	}
51
52
53
	/**
54
	 * Creates the required client specified by the given path of client names.
55
	 *
56
	 * Clients are created by providing only the domain name, e.g. "product"
57
	 *  for the \Aimeos\Admin\JsonAdm\Product\Standard or a path of names to
58
	 * retrieve a specific sub-client, e.g. "product/type" for the
59
	 * \Aimeos\Admin\JsonAdm\Product\Type\Standard client.
60
	 *
61
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object required by clients
62
	 * @param array $templatePaths List of file system paths where the templates are stored
63
	 * @param string $path Name of the client separated by slashes, e.g "product/stock"
64
	 * @param string|null $name Name of the client implementation ("Standard" if null)
65
	 * @return \Aimeos\Admin\JsonAdm\Iface JSON admin instance
66
	 * @throws \Aimeos\Admin\JsonAdm\Exception If the given path is invalid
67
	 */
68
	static public function createClient( \Aimeos\MShop\Context\Item\Iface $context,
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
69
		array $templatePaths, $path, $name = null )
70
	{
71
		$path = strtolower( trim( $path, "/ \n\t\r\0\x0B" ) );
72
		$id = (string) $context;
73
74
		if( self::$cache === false || !isset( self::$clients[$id][$path] ) ) {
75
			self::$clients[$id][$path] = self::createClientNew( $context, $templatePaths, $path, $name );
76
		}
77
78
		return self::$clients[$id][$path];
79
	}
80
81
82
	/**
83
	 * Enables or disables caching of class instances.
84
	 *
85
	 * @param boolean $value True to enable caching, false to disable it.
86
	 * @return boolean Previous cache setting
87
	 */
88
	static public function setCache( $value )
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
89
	{
90
		$old = self::$cache;
91
		self::$cache = (boolean) $value;
92
93
		return $old;
94
	}
95
96
97
	/**
98
	 * Creates a new client specified by the given path of client names.
99
	 *
100
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object required by clients
101
	 * @param array $templatePaths List of file system paths where the templates are stored
102
	 * @param string $path Name of the client separated by slashes, e.g "product/stock"
103
	 * @param string|null $name Name of the client implementation ("Standard" if null)
104
	 * @return \Aimeos\Admin\JsonAdm\Iface JSON admin instance
105
	 * @throws \Aimeos\Admin\JsonAdm\Exception If the given path is invalid
106
	 */
107
	protected static function createClientNew( \Aimeos\MShop\Context\Item\Iface $context,
108
		array $templatePaths, $path, $name )
109
	{
110
		if( empty( $path ) ) {
111
			return self::createClientRoot( $context, $templatePaths, $path, $name );
112
		}
113
114
115
		$pname = $name;
116
		$parts = explode( '/', $path );
117
118
		foreach( $parts as $key => $part )
119
		{
120
			if( ctype_alnum( $part ) === false )
121
			{
122
				$msg = sprintf( 'Invalid client "%1$s" in "%2$s"', $part, $path );
123
				throw new \Aimeos\Admin\JsonAdm\Exception( $msg, 400 );
124
			}
125
126
			$parts[$key] = ucwords( $part );
127
		}
128
129
		if( $pname === null ) {
130
			$pname = $context->getConfig()->get( 'admin/jsonadm/' . $path . '/name', 'Standard' );
131
		}
132
133
		if( ctype_alnum( $pname ) === false )
134
		{
135
			$classname = is_string( $pname ) ? $classname : '<not a string>';
0 ignored issues
show
Bug introduced by
The variable $classname seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
136
			throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'Invalid class name "%1$s"', $classname ) );
137
		}
138
139
140
		$view = $context->getView();
141
		$iface = '\\Aimeos\\Admin\\JsonAdm\\Iface';
142
		$classname = '\\Aimeos\\Admin\\JsonAdm\\' . join( '\\', $parts ) . '\\' . $pname;
143
144
		if( class_exists( $classname ) === false ) {
145
			return self::createClientRoot( $context, $templatePaths, $path, $name );
146
		}
147
148
		$client = self::createClientBase( $classname, $iface, $context, $view, $templatePaths, $path );
149
		return self::addClientDecorators( $client, $context, $view, $templatePaths, $path );
150
	}
151
152
153
	/**
154
	 * Creates the top level client
155
	 *
156
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object required by clients
157
	 * @param \Aimeos\MW\View\Iface $view View object
0 ignored issues
show
Bug introduced by
There is no parameter named $view. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
158
	 * @param array $templatePaths List of file system paths where the templates are stored
159
	 * @param string $path Name of the client separated by slashes, e.g "product/stock"
160
	 * @param string|null $name Name of the JsonAdm client (default: "Standard")
161
	 * @return \Aimeos\Admin\JsonAdm\Iface JSON admin instance
162
	 * @throws \Aimeos\Admin\JsonAdm\Exception If the client couldn't be created
163
	 */
164
	protected static function createClientRoot( \Aimeos\MShop\Context\Item\Iface $context,
165
		array $templatePaths, $path, $name = null )
166
	{
167
		/** admin/jsonadm/name
168
		 * Class name of the used JSON API client implementation
169
		 *
170
		 * Each default JSON API client can be replace by an alternative imlementation.
171
		 * To use this implementation, you have to set the last part of the class
172
		 * name as configuration value so the client factory knows which class it
173
		 * has to instantiate.
174
		 *
175
		 * For example, if the name of the default class is
176
		 *
177
		 *  \Aimeos\Admin\JsonAdm\Standard
178
		 *
179
		 * and you want to replace it with your own version named
180
		 *
181
		 *  \Aimeos\Admin\JsonAdm\Mycntl
182
		 *
183
		 * then you have to set the this configuration option:
184
		 *
185
		 *  admin/jsonadm/name = Mycntl
186
		 *
187
		 * The value is the last part of your own class name and it's case sensitive,
188
		 * so take care that the configuration value is exactly named like the last
189
		 * part of the class name.
190
		 *
191
		 * The allowed characters of the class name are A-Z, a-z and 0-9. No other
192
		 * characters are possible! You should always start the last part of the class
193
		 * name with an upper case character and continue only with lower case characters
194
		 * or numbers. Avoid chamel case names like "MyCntl"!
195
		 *
196
		 * @param string Last part of the class name
197
		 * @since 2015.12
198
		 * @category Developer
199
		 */
200
		if( $name === null ) {
201
			$name = $context->getConfig()->get( 'admin/jsonadm/name', 'Standard' );
202
		}
203
204
		if( ctype_alnum( $name ) === false )
205
		{
206
			$classname = is_string( $name ) ? '\\Aimeos\\Admin\\JsonAdm\\' . $name : '<not a string>';
207
			throw new \Aimeos\Admin\JsonAdm\Exception( sprintf( 'Invalid class name "%1$s"', $classname ) );
208
		}
209
210
		$view = $context->getView();
211
		$iface = '\\Aimeos\\Admin\\JsonAdm\\Iface';
212
		$classname = '\\Aimeos\\Admin\\JsonAdm\\' . $name;
213
214
		$client = self::createClientBase( $classname, $iface, $context, $view, $templatePaths, $path );
215
216
		/** admin/jsonadm/decorators/excludes
217
		 * Excludes decorators added by the "common" option from the JSON API clients
218
		 *
219
		 * Decorators extend the functionality of a class by adding new aspects
220
		 * (e.g. log what is currently done), executing the methods of the underlying
221
		 * class only in certain conditions (e.g. only for logged in users) or
222
		 * modify what is returned to the caller.
223
		 *
224
		 * This option allows you to remove a decorator added via
225
		 * "admin/jsonadm/common/decorators/default" before they are wrapped
226
		 * around the Jsonadm client.
227
		 *
228
		 *  admin/jsonadm/decorators/excludes = array( 'decorator1' )
229
		 *
230
		 * This would remove the decorator named "decorator1" from the list of
231
		 * common decorators ("\Aimeos\Admin\JsonAdm\Common\Decorator\*") added via
232
		 * "admin/jsonadm/common/decorators/default" for the JSON API client.
233
		 *
234
		 * @param array List of decorator names
235
		 * @since 2016.01
236
		 * @category Developer
237
		 * @see admin/jsonadm/common/decorators/default
238
		 * @see admin/jsonadm/decorators/global
239
		 * @see admin/jsonadm/decorators/local
240
		 */
241
242
		/** admin/jsonadm/decorators/global
243
		 * Adds a list of globally available decorators only to the Jsonadm client
244
		 *
245
		 * Decorators extend the functionality of a class by adding new aspects
246
		 * (e.g. log what is currently done), executing the methods of the underlying
247
		 * class only in certain conditions (e.g. only for logged in users) or
248
		 * modify what is returned to the caller.
249
		 *
250
		 * This option allows you to wrap global decorators
251
		 * ("\Aimeos\Admin\Jsonadm\Common\Decorator\*") around the Jsonadm
252
		 * client.
253
		 *
254
		 *  admin/jsonadm/product/decorators/global = array( 'decorator1' )
255
		 *
256
		 * This would add the decorator named "decorator1" defined by
257
		 * "\Aimeos\Admin\Jsonadm\Common\Decorator\Decorator1" only to the
258
		 * "product" Jsonadm client.
259
		 *
260
		 * @param array List of decorator names
261
		 * @since 2016.01
262
		 * @category Developer
263
		 * @see admin/jsonadm/common/decorators/default
264
		 * @see admin/jsonadm/decorators/excludes
265
		 * @see admin/jsonadm/decorators/local
266
		 */
267
268
		/** admin/jsonadm/decorators/local
269
		 * Adds a list of local decorators only to the Jsonadm client
270
		 *
271
		 * Decorators extend the functionality of a class by adding new aspects
272
		 * (e.g. log what is currently done), executing the methods of the underlying
273
		 * class only in certain conditions (e.g. only for logged in users) or
274
		 * modify what is returned to the caller.
275
		 *
276
		 * This option allows you to wrap local decorators
277
		 * ("\Aimeos\Admin\Jsonadm\Product\Decorator\*") around the Jsonadm
278
		 * client.
279
		 *
280
		 *  admin/jsonadm/product/decorators/local = array( 'decorator2' )
281
		 *
282
		 * This would add the decorator named "decorator2" defined by
283
		 * "\Aimeos\Admin\Jsonadm\Product\Decorator\Decorator2" only to the
284
		 * "product" Jsonadm client.
285
		 *
286
		 * @param array List of decorator names
287
		 * @since 2016.01
288
		 * @category Developer
289
		 * @see admin/jsonadm/common/decorators/default
290
		 * @see admin/jsonadm/decorators/excludes
291
		 * @see admin/jsonadm/decorators/global
292
		 */
293
294
		return self::addClientDecorators( $client, $context, $view, $templatePaths, $path );
295
	}
296
}
297