Passed
Push — master ( 8fe664...a0eb70 )
by Aimeos
04:13 queued 11s
created

Standard::getSubClient()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 76
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 76
rs 10
c 0
b 0
f 0

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), 2017-2018
6
 * @package Admin
7
 * @subpackage JQAdm
8
 */
9
10
11
namespace Aimeos\Admin\JQAdm\Attribute\Price;
12
13
sprintf( 'price' ); // for translation
14
15
16
/**
17
 * Default implementation of attribute price JQAdm client.
18
 *
19
 * @package Admin
20
 * @subpackage JQAdm
21
 */
22
class Standard
23
	extends \Aimeos\Admin\JQAdm\Common\Admin\Factory\Base
24
	implements \Aimeos\Admin\JQAdm\Common\Admin\Factory\Iface
25
{
26
	/** admin/jqadm/attribute/price/name
27
	 * Name of the price subpart used by the JQAdm attribute implementation
28
	 *
29
	 * Use "Myname" if your class is named "\Aimeos\Admin\Jqadm\Attribute\Price\Myname".
30
	 * The name is case-sensitive and you should avoid camel case names like "MyName".
31
	 *
32
	 * @param string Last part of the JQAdm class name
33
	 * @since 2017.07
34
	 * @category Developer
35
	 */
36
37
38
	/**
39
	 * Copies a resource
40
	 *
41
	 * @return string HTML output
42
	 */
43
	public function copy()
44
	{
45
		$view = $this->addViewData( $this->getView() );
46
47
		$view->priceData = $this->toArray( $view->item, true );
48
		$view->priceBody = '';
49
50
		foreach( $this->getSubClients() as $client ) {
51
			$view->priceBody .= $client->copy();
52
		}
53
54
		return $this->render( $view );
55
	}
56
57
58
	/**
59
	 * Creates a new resource
60
	 *
61
	 * @return string HTML output
62
	 */
63
	public function create()
64
	{
65
		$view = $this->addViewData( $this->getView() );
66
		$siteid = $this->getContext()->getLocale()->getSiteId();
67
		$data = $view->param( 'price', [] );
68
69
		foreach( $data as $idx => $entry )
70
		{
71
			$data[$idx]['attribute.lists.siteid'] = $siteid;
72
			$data[$idx]['price.siteid'] = $siteid;
73
		}
74
75
		$view->priceData = $data;
76
		$view->priceBody = '';
77
78
		foreach( $this->getSubClients() as $client ) {
79
			$view->priceBody .= $client->create();
80
		}
81
82
		return $this->render( $view );
83
	}
84
85
86
	/**
87
	 * Deletes a resource
88
	 */
89
	public function delete()
90
	{
91
		parent::delete();
92
93
		$item = $this->getView()->item;
94
		$item->deleteListItems( $item->getListItems( 'price', null, null, false ), true );
95
	}
96
97
98
	/**
99
	 * Returns a single resource
100
	 *
101
	 * @return string HTML output
102
	 */
103
	public function get()
104
	{
105
		$view = $this->addViewData( $this->getView() );
106
107
		$view->priceData = $this->toArray( $view->item );
108
		$view->priceBody = '';
109
110
		foreach( $this->getSubClients() as $client ) {
111
			$view->priceBody .= $client->get();
112
		}
113
114
		return $this->render( $view );
115
	}
116
117
118
	/**
119
	 * Saves the data
120
	 */
121
	public function save()
122
	{
123
		$view = $this->getView();
124
125
		try
126
		{
127
			$view->item = $this->fromArray( $view->item, $view->param( 'price', [] ) );
128
			$view->priceBody = '';
129
130
			foreach( $this->getSubClients() as $client ) {
131
				$view->priceBody .= $client->save();
132
			}
133
134
			return;
135
		}
136
		catch( \Aimeos\MShop\Exception $e )
137
		{
138
			$error = array( 'attribute-item-price' => $this->getContext()->getI18n()->dt( 'mshop', $e->getMessage() ) );
139
			$view->errors = $view->get( 'errors', [] ) + $error;
140
			$this->logException( $e );
141
		}
142
		catch( \Exception $e )
143
		{
144
			$error = array( 'attribute-item-price' => $e->getMessage() . ', ' . $e->getFile() . ':' . $e->getLine() );
145
			$view->errors = $view->get( 'errors', [] ) + $error;
146
			$this->logException( $e );
147
		}
148
149
		throw new \Aimeos\Admin\JQAdm\Exception();
150
	}
151
152
153
	/**
154
	 * Returns the sub-client given by its name.
155
	 *
156
	 * @param string $type Name of the client type
157
	 * @param string|null $name Name of the sub-client (Default if null)
158
	 * @return \Aimeos\Admin\JQAdm\Iface Sub-client object
159
	 */
160
	public function getSubClient( $type, $name = null )
161
	{
162
		/** admin/jqadm/attribute/price/decorators/excludes
163
		 * Excludes decorators added by the "common" option from the attribute JQAdm client
164
		 *
165
		 * Decorators extend the functionality of a class by adding new aspects
166
		 * (e.g. log what is currently done), executing the methods of the underlying
167
		 * class only in certain conditions (e.g. only for logged in users) or
168
		 * modify what is returned to the caller.
169
		 *
170
		 * This option allows you to remove a decorator added via
171
		 * "admin/jqadm/common/decorators/default" before they are wrapped
172
		 * around the JQAdm client.
173
		 *
174
		 *  admin/jqadm/attribute/price/decorators/excludes = array( 'decorator1' )
175
		 *
176
		 * This would remove the decorator named "decorator1" from the list of
177
		 * common decorators ("\Aimeos\Admin\JQAdm\Common\Decorator\*") added via
178
		 * "admin/jqadm/common/decorators/default" to the JQAdm client.
179
		 *
180
		 * @param array List of decorator names
181
		 * @since 2016.01
182
		 * @category Developer
183
		 * @see admin/jqadm/common/decorators/default
184
		 * @see admin/jqadm/attribute/price/decorators/global
185
		 * @see admin/jqadm/attribute/price/decorators/local
186
		 */
187
188
		/** admin/jqadm/attribute/price/decorators/global
189
		 * Adds a list of globally available decorators only to the attribute JQAdm client
190
		 *
191
		 * Decorators extend the functionality of a class by adding new aspects
192
		 * (e.g. log what is currently done), executing the methods of the underlying
193
		 * class only in certain conditions (e.g. only for logged in users) or
194
		 * modify what is returned to the caller.
195
		 *
196
		 * This option allows you to wrap global decorators
197
		 * ("\Aimeos\Admin\JQAdm\Common\Decorator\*") around the JQAdm client.
198
		 *
199
		 *  admin/jqadm/attribute/price/decorators/global = array( 'decorator1' )
200
		 *
201
		 * This would add the decorator named "decorator1" defined by
202
		 * "\Aimeos\Admin\JQAdm\Common\Decorator\Decorator1" only to the JQAdm client.
203
		 *
204
		 * @param array List of decorator names
205
		 * @since 2016.01
206
		 * @category Developer
207
		 * @see admin/jqadm/common/decorators/default
208
		 * @see admin/jqadm/attribute/price/decorators/excludes
209
		 * @see admin/jqadm/attribute/price/decorators/local
210
		 */
211
212
		/** admin/jqadm/attribute/price/decorators/local
213
		 * Adds a list of local decorators only to the attribute JQAdm client
214
		 *
215
		 * Decorators extend the functionality of a class by adding new aspects
216
		 * (e.g. log what is currently done), executing the methods of the underlying
217
		 * class only in certain conditions (e.g. only for logged in users) or
218
		 * modify what is returned to the caller.
219
		 *
220
		 * This option allows you to wrap local decorators
221
		 * ("\Aimeos\Admin\JQAdm\Attribute\Decorator\*") around the JQAdm client.
222
		 *
223
		 *  admin/jqadm/attribute/price/decorators/local = array( 'decorator2' )
224
		 *
225
		 * This would add the decorator named "decorator2" defined by
226
		 * "\Aimeos\Admin\JQAdm\Attribute\Decorator\Decorator2" only to the JQAdm client.
227
		 *
228
		 * @param array List of decorator names
229
		 * @since 2016.01
230
		 * @category Developer
231
		 * @see admin/jqadm/common/decorators/default
232
		 * @see admin/jqadm/attribute/price/decorators/excludes
233
		 * @see admin/jqadm/attribute/price/decorators/global
234
		 */
235
		return $this->createSubClient( 'attribute/price/' . $type, $name );
236
	}
237
238
239
	/**
240
	 * Returns the list of sub-client names configured for the client.
241
	 *
242
	 * @return array List of JQAdm client names
243
	 */
244
	protected function getSubClientNames()
245
	{
246
		/** admin/jqadm/attribute/price/standard/subparts
247
		 * List of JQAdm sub-clients rendered within the attribute price section
248
		 *
249
		 * The output of the frontend is composed of the code generated by the JQAdm
250
		 * clients. Each JQAdm client can consist of serveral (or none) sub-clients
251
		 * that are responsible for rendering certain sub-parts of the output. The
252
		 * sub-clients can contain JQAdm clients themselves and therefore a
253
		 * hierarchical tree of JQAdm clients is composed. Each JQAdm client creates
254
		 * the output that is placed inside the container of its parent.
255
		 *
256
		 * At first, always the JQAdm code generated by the parent is printed, then
257
		 * the JQAdm code of its sub-clients. The order of the JQAdm sub-clients
258
		 * determines the order of the output of these sub-clients inside the parent
259
		 * container. If the configured list of clients is
260
		 *
261
		 *  array( "subclient1", "subclient2" )
262
		 *
263
		 * you can easily change the order of the output by reordering the subparts:
264
		 *
265
		 *  admin/jqadm/<clients>/subparts = array( "subclient1", "subclient2" )
266
		 *
267
		 * You can also remove one or more parts if they shouldn't be rendered:
268
		 *
269
		 *  admin/jqadm/<clients>/subparts = array( "subclient1" )
270
		 *
271
		 * As the clients only generates structural JQAdm, the layout defined via CSS
272
		 * should support adding, removing or reordering content by a fluid like
273
		 * design.
274
		 *
275
		 * @param array List of sub-client names
276
		 * @since 2016.01
277
		 * @category Developer
278
		 */
279
		return $this->getContext()->getConfig()->get( 'admin/jqadm/attribute/price/standard/subparts', [] );
280
	}
281
282
283
	/**
284
	 * Adds the required data used in the price template
285
	 *
286
	 * @param \Aimeos\MW\View\Iface $view View object
287
	 * @return \Aimeos\MW\View\Iface View object with assigned parameters
288
	 */
289
	protected function addViewData( \Aimeos\MW\View\Iface $view )
290
	{
291
		$context = $this->getContext();
292
293
		$priceTypeManager = \Aimeos\MShop::create( $context, 'price/type' );
294
		$listTypeManager = \Aimeos\MShop::create( $context, 'attribute/lists/type' );
295
		$currencyManager = \Aimeos\MShop::create( $context, 'locale/currency' );
296
297
		$search = $priceTypeManager->createSearch( true )->setSlice( 0, 10000 );
298
		$search->setConditions( $search->compare( '==', 'price.type.domain', 'attribute' ) );
299
		$search->setSortations( [$search->sort( '+', 'price.type.position' )] );
300
301
		$listSearch = $listTypeManager->createSearch( true )->setSlice( 0, 10000 );
302
		$listSearch->setConditions( $listSearch->compare( '==', 'attribute.lists.type.domain', 'price' ) );
303
		$listSearch->setSortations( [$listSearch->sort( '+', 'attribute.lists.type.position' )] );
304
305
		$view->priceTypes = $this->map( $priceTypeManager->searchItems( $search ) );
306
		$view->priceListTypes = $this->map( $listTypeManager->searchItems( $listSearch ) );
307
		$view->priceCurrencies = $currencyManager->searchItems( $currencyManager->createSearch( true )->setSlice( 0, 10000 ) );
308
309
		if( $view->priceCurrencies === [] ) {
310
			throw new \Aimeos\Admin\JQAdm\Exception( 'No currencies available. Please enable at least one currency' );
311
		}
312
313
		return $view;
314
	}
315
316
317
	/**
318
	 * Creates new and updates existing items using the data array
319
	 *
320
	 * @param \Aimeos\MShop\Attribute\Item\Iface $item Attribute item object without referenced domain items
321
	 * @param array $data Data array
322
	 */
323
	protected function fromArray( \Aimeos\MShop\Attribute\Item\Iface $item, array $data )
324
	{
325
		$context = $this->getContext();
326
327
		$priceManager = \Aimeos\MShop::create( $context, 'price' );
328
		$listManager = \Aimeos\MShop::create( $context, 'attribute/lists' );
329
330
		$listItems = $item->getListItems( 'price', null, null, false );
331
332
333
		foreach( $data as $idx => $entry )
334
		{
335
			if( ( $listItem = $item->getListItem( 'price', $entry['attribute.lists.type'], $entry['price.id'], false ) ) === null ) {
336
				$listItem = $listManager->createItem();
337
			}
338
339
			if( ( $refItem = $listItem->getRefItem() ) === null ) {
0 ignored issues
show
Bug introduced by
The method getRefItem() does not exist on Aimeos\MShop\Common\Item\Iface. It seems like you code against a sub-type of Aimeos\MShop\Common\Item\Iface such as Aimeos\MShop\Common\Item\Lists\Iface or Aimeos\MShop\Common\Item\Lists\Standard or Aimeos\MShop\Common\Item\Lists\Iface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

339
			if( ( $refItem = $listItem->/** @scrutinizer ignore-call */ getRefItem() ) === null ) {
Loading history...
340
				$refItem = $priceManager->createItem();
341
			}
342
343
			if( isset( $entry['price.taxrates'] ) && $entry['price.taxrates'] != '' ) {
344
				$entry['price.taxrates'] = json_decode( $entry['price.taxrates'] );
345
			}
346
347
			$refItem->fromArray( $entry, true );
348
			$conf = [];
349
350
			foreach( (array) $this->getValue( $entry, 'config', [] ) as $cfg )
351
			{
352
				if( ( $key = trim( $cfg['key'] ?? '' ) ) !== '' ) {
353
					$conf[$key] = trim( $cfg['val'] ?? '' );
354
				}
355
			}
356
357
			$listItem->fromArray( $entry, true );
358
			$listItem->setPosition( $idx );
0 ignored issues
show
Bug introduced by
The method setPosition() does not exist on Aimeos\MShop\Common\Item\Iface. It seems like you code against a sub-type of Aimeos\MShop\Common\Item\Iface such as Aimeos\MShop\Service\Item\Iface or Aimeos\MShop\Order\Item\Base\Product\Iface or Aimeos\MShop\Order\Item\Base\Service\Iface or Aimeos\MShop\Common\Item\Lists\Iface or Aimeos\MShop\Locale\Item\Iface or Aimeos\MShop\Common\Item\Type\Iface or Aimeos\MShop\Attribute\Item\Iface or Aimeos\MShop\Supplier\Item\Address\Iface or Aimeos\MShop\Plugin\Item\Iface or Aimeos\MShop\Attribute\Item\Standard or Aimeos\MShop\Plugin\Item\Standard or Aimeos\MShop\Common\Item\Type\Standard or Aimeos\MShop\Locale\Item\Standard or Aimeos\MShop\Common\Item\Lists\Standard or Aimeos\MShop\Order\Item\Base\Service\Base or Aimeos\MShop\Service\Item\Standard or Aimeos\MShop\Order\Item\Base\Product\Standard or Aimeos\MShop\Common\Item\Address\Standard or Aimeos\MShop\Order\Item\Base\Address\Standard or Aimeos\MShop\Service\Item\Iface or Aimeos\MShop\Order\Item\Base\Product\Iface or Aimeos\MShop\Common\Item\Lists\Iface or Aimeos\MShop\Locale\Item\Iface or Aimeos\MShop\Common\Item\Type\Iface or Aimeos\MShop\Attribute\Item\Iface or Aimeos\MShop\Plugin\Item\Iface or Aimeos\MShop\Service\Item\Iface or Aimeos\MShop\Attribute\Item\Iface or Aimeos\MShop\Attribute\Item\Iface or Aimeos\MShop\Customer\Item\Address\Iface or Aimeos\MShop\Common\Item\Address\Standard or Aimeos\MShop\Order\Item\Base\Address\Iface or Aimeos\MShop\Supplier\Item\Address\Iface or Aimeos\MShop\Common\Item\Address\Standard or Aimeos\MShop\Order\Item\Base\Address\Standard. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

358
			$listItem->/** @scrutinizer ignore-call */ 
359
              setPosition( $idx );
Loading history...
359
			$listItem->setConfig( $conf );
0 ignored issues
show
Bug introduced by
The method setConfig() does not exist on Aimeos\MShop\Common\Item\Iface. It seems like you code against a sub-type of Aimeos\MShop\Common\Item\Iface such as Aimeos\MShop\Product\Item\Iface or Aimeos\MShop\Service\Item\Iface or Aimeos\MShop\Locale\Item\Site\Iface or Aimeos\MShop\Coupon\Item\Iface or Aimeos\MShop\Common\Item\Lists\Iface or Aimeos\MShop\Catalog\Item\Iface or Aimeos\MShop\Plugin\Item\Iface or Aimeos\MShop\Catalog\Item\Standard or Aimeos\MShop\Plugin\Item\Standard or Aimeos\MShop\Locale\Item\Site\Standard or Aimeos\MShop\Common\Item\Lists\Standard or Aimeos\MShop\Service\Item\Standard or Aimeos\MShop\Coupon\Item\Standard or Aimeos\MShop\Product\Item\Standard or Aimeos\MShop\Product\Item\Iface or Aimeos\MShop\Service\Item\Iface or Aimeos\MShop\Coupon\Item\Iface or Aimeos\MShop\Common\Item\Lists\Iface or Aimeos\MShop\Plugin\Item\Iface or Aimeos\MShop\Locale\Item\Site\Iface or Aimeos\MShop\Catalog\Item\Iface or Aimeos\MShop\Product\Item\Iface or Aimeos\MShop\Service\Item\Iface or Aimeos\MShop\Catalog\Item\Iface or Aimeos\MShop\Product\Item\Iface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

359
			$listItem->/** @scrutinizer ignore-call */ 
360
              setConfig( $conf );
Loading history...
360
361
			$item->addListItem( 'price', $listItem, $refItem );
362
363
			unset( $listItems[$listItem->getId()] );
364
		}
365
366
		return $item->deleteListItems( $listItems, true );
367
	}
368
369
370
	/**
371
	 * Constructs the data array for the view from the given item
372
	 *
373
	 * @param \Aimeos\MShop\Attribute\Item\Iface $item Attribute item object including referenced domain items
374
	 * @param boolean $copy True if items should be copied, false if not
375
	 * @return string[] Multi-dimensional associative list of item data
376
	 */
377
	protected function toArray( \Aimeos\MShop\Attribute\Item\Iface $item, $copy = false )
378
	{
379
		$data = [];
380
		$siteId = $this->getContext()->getLocale()->getSiteId();
381
382
		foreach( $item->getListItems( 'price', null, null, false ) as $listItem )
383
		{
384
			if( ( $refItem = $listItem->getRefItem() ) === null ) {
385
				continue;
386
			}
387
388
			$list = $listItem->toArray( true ) + $refItem->toArray( true );
389
390
			if( $copy === true )
391
			{
392
				$list['attribute.lists.siteid'] = $siteId;
393
				$list['attribute.lists.id'] = '';
394
				$list['price.siteid'] = $siteId;
395
				$list['price.id'] = null;
396
			}
397
398
			$list['attribute.lists.datestart'] = str_replace( ' ', 'T', $list['attribute.lists.datestart'] );
399
			$list['attribute.lists.dateend'] = str_replace( ' ', 'T', $list['attribute.lists.dateend'] );
400
			$list['config'] = [];
401
402
			foreach( $listItem->getConfig() as $key => $value ) {
403
				$list['config'][] = ['key' => $key, 'val' => $value];
404
			}
405
406
			if( empty( $refItem->getTaxRates() ) ) {
407
				$list['price.taxrates'] = ['' => ''];
408
			}
409
410
			$data[] = $list;
411
		}
412
413
		return $data;
414
	}
415
416
417
	/**
418
	 * Returns the rendered template including the view data
419
	 *
420
	 * @param \Aimeos\MW\View\Iface $view View object with data assigned
421
	 * @return string HTML output
422
	 */
423
	protected function render( \Aimeos\MW\View\Iface $view )
424
	{
425
		/** admin/jqadm/attribute/price/template-item
426
		 * Relative path to the HTML body template of the price subpart for attributes.
427
		 *
428
		 * The template file contains the HTML code and processing instructions
429
		 * to generate the result shown in the body of the frontend. The
430
		 * configuration string is the path to the template file relative
431
		 * to the templates directory (usually in admin/jqadm/templates).
432
		 *
433
		 * You can overwrite the template file configuration in extensions and
434
		 * provide alternative templates. These alternative templates should be
435
		 * named like the default one but with the string "default" replaced by
436
		 * an unique name. You may use the name of your project for this. If
437
		 * you've implemented an alternative client class as well, "default"
438
		 * should be replaced by the name of the new class.
439
		 *
440
		 * @param string Relative path to the template creating the HTML code
441
		 * @since 2016.04
442
		 * @category Developer
443
		 */
444
		$tplconf = 'admin/jqadm/attribute/price/template-item';
445
		$default = 'attribute/item-price-standard';
446
447
		return $view->render( $view->config( $tplconf, $default ) );
448
	}
449
}
450