Passed
Push — master ( 2142ca...abaad8 )
by Aimeos
03:08
created

JQAdm::createAdmin()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 4
nop 3
dl 0
loc 22
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2022
6
 * @package Admin
7
 * @subpackage JQAdm
8
 */
9
10
11
namespace Aimeos\Admin;
12
13
14
/**
15
 * Common factory for JQAdm clients
16
 *
17
 * @package Admin
18
 * @subpackage JQAdm
19
 */
20
class JQAdm
21
{
22
	private static $objects = [];
23
24
25
	/**
26
	 * Creates a new client object.
27
	 *
28
	 * @param \Aimeos\MShop\ContextIface $context Shop context instance with necessary objects
29
	 * @param \Aimeos\Bootstrap $aimeos Aimeos object
30
	 * @param string $path Type of the client, e.g 'product' for \Aimeos\Admin\JQAdm\Product\Standard
31
	 * @param string|null $name Admin name (default: "Standard")
32
	 * @return \Aimeos\Admin\JQAdm\Iface admin client implementing \Aimeos\Admin\JQAdm\Iface
33
	 * @throws \Aimeos\Admin\JQAdm\Exception If requested client implementation couldn't be found or initialisation fails
34
	 */
35
	public static function create( \Aimeos\MShop\ContextIface $context, \Aimeos\Bootstrap $aimeos, $path, $name = null )
36
	{
37
		if( empty( $path ) ) {
38
			throw new \Aimeos\Admin\JQAdm\Exception( $context->translate( 'admin', 'Admin JQAdm type is empty' ) );
39
		}
40
41
		$view = $context->view();
42
		$config = $context->config();
43
		$parts = explode( '/', $path );
44
45
		foreach( $parts as $idx => $part )
46
		{
47
			if( ctype_alnum( $part ) === false )
48
			{
49
				$msg = $context->translate( 'admin', 'Invalid characters in client name "%1$s"' );
50
				throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $path ) );
51
			}
52
53
			$parts[$idx] = ucwords( $part );
54
		}
55
56
		if( $view->access( $config->get( 'admin/jqadm/resource/' . $path . '/groups', [] ) ) !== true )
57
		{
58
			$msg = $context->translate( 'admin', 'Not allowed to access JQAdm "%1$s" client' );
59
			throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $path ) );
60
		}
61
62
		if( empty( $name ) ) {
63
			$name = $context->config()->get( 'admin/jqadm/' . $path . '/name', 'Standard' );
64
		}
65
66
		$interface = '\\Aimeos\\Admin\JQAdm\\Iface';
67
		$classname = '\\Aimeos\\Admin\\JQAdm\\' . implode( '\\', $parts ) . '\\' . $name;
68
69
		if( class_exists( $classname ) === false )
70
		{
71
			$msg = $context->translate( 'admin', 'Class "%1$s" not available' );
72
			throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $classname ) );
73
		}
74
75
		$client = self::createAdmin( $context, $classname, $interface );
76
		$client = self::addClientDecorators( $context, $client, $path );
77
78
		return $client->setAimeos( $aimeos )->setView( $view )->setObject( $client );
0 ignored issues
show
Bug introduced by
The method setAimeos() does not exist on Aimeos\Admin\JQAdm\Iface. It seems like you code against a sub-type of said class. However, the method does not exist in Aimeos\Admin\JQAdm\Common\Admin\Factory\Iface or Aimeos\Admin\JQAdm\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 ignore-call  annotation

78
		return $client->/** @scrutinizer ignore-call */ setAimeos( $aimeos )->setView( $view )->setObject( $client );
Loading history...
79
	}
80
81
82
	/**
83
	 * Injects a client object.
84
	 * The object is returned via create() if an instance of the class
85
	 * with the name name is requested.
86
	 *
87
	 * @param string $classname Full name of the class for which the object should be returned
88
	 * @param \Aimeos\Admin\JQAdm\Iface|null $client ExtJS client object
89
	 */
90
	public static function injectClient( string $classname, \Aimeos\Admin\JQAdm\Iface $client = null )
91
	{
92
		self::$objects[$classname] = $client;
93
	}
94
95
96
	/**
97
	 * Adds the decorators to the client object.
98
	 *
99
	 * @param \Aimeos\MShop\ContextIface $context Context instance with necessary objects
100
	 * @param \Aimeos\Admin\JQAdm\Iface $client Admin object
101
	 * @param array $decorators List of decorator name that should be wrapped around the client
102
	 * @param string $classprefix Decorator class prefix, e.g. "\Aimeos\Admin\JQAdm\Catalog\Decorator\"
103
	 * @return \Aimeos\Admin\JQAdm\Iface Admin object
104
	 */
105
	protected static function addDecorators( \Aimeos\MShop\ContextIface $context,
106
		\Aimeos\Admin\JQAdm\Iface $client, array $decorators, string $classprefix ) : \Aimeos\Admin\JQAdm\Iface
107
	{
108
		foreach( $decorators as $name )
109
		{
110
			$classname = $classprefix . $name;
111
112
			if( ctype_alnum( $name ) === false )
113
			{
114
				$msg = $context->translate( 'admin', 'Invalid class name "%1$s"' );
115
				throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $classname ) );
116
			}
117
118
			if( class_exists( $classname ) === false )
119
			{
120
				$msg = $context->translate( 'admin', 'Class "%1$s" not found' );
121
				throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $classname ) );
122
			}
123
124
			$client = new $classname( $client, $context );
125
			$interface = '\\Aimeos\\Admin\\JQAdm\\Common\\Decorator\\Iface';
126
127
			if( !( $client instanceof $interface ) )
128
			{
129
				$msg = $context->translate( 'admin', 'Class "%1$s" does not implement "%2$s"' );
130
				throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $classname, $interface ) );
131
			}
132
		}
133
134
		return $client;
135
	}
136
137
138
	/**
139
	 * Adds the decorators to the client object.
140
	 *
141
	 * @param \Aimeos\MShop\ContextIface $context Context instance with necessary objects
142
	 * @param \Aimeos\Admin\JQAdm\Iface $client Admin object
143
	 * @param string $path Path of the client in lower case, e.g. "catalog/detail"
144
	 * @return \Aimeos\Admin\JQAdm\Iface Admin object
145
	 */
146
	protected static function addClientDecorators( \Aimeos\MShop\ContextIface $context,
147
		\Aimeos\Admin\JQAdm\Iface $client, string $path ) : \Aimeos\Admin\JQAdm\Iface
148
	{
149
		if( empty( $path ) )
150
		{
151
			$msg = $context->translate( 'admin', 'Invalid domain "%1$s"' );
152
			throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $path ) );
153
		}
154
155
		$localClass = str_replace( '/', '\\', ucwords( $path, '/' ) );
156
		$config = $context->config();
157
158
		/** admin/jqadm/common/decorators/default
159
		 * Configures the list of decorators applied to all jqadm clients
160
		 *
161
		 * Decorators extend the functionality of a class by adding new aspects
162
		 * (e.g. log what is currently done), executing the methods of the underlying
163
		 * class only in certain conditions (e.g. only for logged in users) or
164
		 * modify what is returned to the caller.
165
		 *
166
		 * This option allows you to configure a list of decorator names that should
167
		 * be wrapped around the original instance of all created clients:
168
		 *
169
		 *  admin/jqadm/common/decorators/default = array( 'decorator1', 'decorator2' )
170
		 *
171
		 * This would wrap the decorators named "decorator1" and "decorator2" around
172
		 * all client instances in that order. The decorator classes would be
173
		 * "\Aimeos\Admin\JQAdm\Common\Decorator\Decorator1" and
174
		 * "\Aimeos\Admin\JQAdm\Common\Decorator\Decorator2".
175
		 *
176
		 * @param array List of decorator names
177
		 * @since 2014.03
178
		 * @category Developer
179
		 */
180
		$decorators = $config->get( 'admin/jqadm/common/decorators/default', [] );
181
		$excludes = $config->get( 'admin/jqadm/' . $path . '/decorators/excludes', [] );
182
183
		foreach( $decorators as $key => $name )
184
		{
185
			if( in_array( $name, $excludes ) ) {
186
				unset( $decorators[$key] );
187
			}
188
		}
189
190
		$classprefix = '\\Aimeos\\Admin\\JQAdm\\Common\\Decorator\\';
191
		$client = self::addDecorators( $context, $client, $decorators, $classprefix );
192
193
		$classprefix = '\\Aimeos\\Admin\\JQAdm\\Common\\Decorator\\';
194
		$decorators = $config->get( 'admin/jqadm/' . $path . '/decorators/global', [] );
195
		$client = self::addDecorators( $context, $client, $decorators, $classprefix );
196
197
		$classprefix = '\\Aimeos\\Admin\\JQAdm\\' . $localClass . '\\Decorator\\';
198
		$decorators = $config->get( 'admin/jqadm/' . $path . '/decorators/local', [] );
199
		$client = self::addDecorators( $context, $client, $decorators, $classprefix );
200
201
		return $client;
202
	}
203
204
205
	/**
206
	 * Creates a client object.
207
	 *
208
	 * @param \Aimeos\MShop\ContextIface $context Context instance with necessary objects
209
	 * @param string $classname Name of the client class
210
	 * @param string $interface Name of the client interface
211
	 * @return \Aimeos\Admin\JQAdm\Iface Admin object
212
	 * @throws \Aimeos\Admin\JQAdm\Exception If client couldn't be found or doesn't implement the interface
213
	 */
214
	protected static function createAdmin( \Aimeos\MShop\ContextIface $context,
215
		string $classname, string $interface ) : \Aimeos\Admin\JQAdm\Iface
216
	{
217
		if( isset( self::$objects[$classname] ) ) {
218
			return self::$objects[$classname];
219
		}
220
221
		if( class_exists( $classname ) === false )
222
		{
223
			$msg = $context->translate( 'admin', 'Class "%1$s" not available' );
224
			throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $classname ) );
225
		}
226
227
		$client = new $classname( $context );
228
229
		if( !( $client instanceof $interface ) )
230
		{
231
			$msg = $context->translate( 'admin', 'Class "%1$s" does not implement "%2$s"' );
232
			throw new \Aimeos\Admin\JQAdm\Exception( sprintf( $msg, $classname, $interface ) );
233
		}
234
235
		return $client;
236
	}
237
}
238