Passed
Push — master ( cb2ca1...d63df3 )
by Aimeos
08:16
created

Standard::__clone()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2012
6
 * @copyright Aimeos (aimeos.org), 2015-2022
7
 * @package Controller
8
 * @subpackage Frontend
9
 */
10
11
12
namespace Aimeos\Controller\Frontend\Service;
13
14
use \Psr\Http\Message\ServerRequestInterface;
0 ignored issues
show
Bug introduced by
The type \Psr\Http\Message\ServerRequestInterface was not found. Maybe you did not declare it correctly or list all dependencies?

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:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use \Psr\Http\Message\ResponseInterface;
0 ignored issues
show
Bug introduced by
The type \Psr\Http\Message\ResponseInterface was not found. Maybe you did not declare it correctly or list all dependencies?

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:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
17
18
/**
19
 * Default implementation of the service frontend controller.
20
 *
21
 * @package Controller
22
 * @subpackage Frontend
23
 */
24
class Standard
25
	extends \Aimeos\Controller\Frontend\Base
26
	implements Iface, \Aimeos\Controller\Frontend\Common\Iface
27
{
28
	/** controller/frontend/service/name
29
	 * Class name of the used service frontend controller implementation
30
	 *
31
	 * Each default frontend controller can be replace by an alternative imlementation.
32
	 * To use this implementation, you have to set the last part of the class
33
	 * name as configuration value so the controller factory knows which class it
34
	 * has to instantiate.
35
	 *
36
	 * For example, if the name of the default class is
37
	 *
38
	 *  \Aimeos\Controller\Frontend\Service\Standard
39
	 *
40
	 * and you want to replace it with your own version named
41
	 *
42
	 *  \Aimeos\Controller\Frontend\Service\Myservice
43
	 *
44
	 * then you have to set the this configuration option:
45
	 *
46
	 *  controller/jobs/frontend/service/name = Myservice
47
	 *
48
	 * The value is the last part of your own class name and it's case sensitive,
49
	 * so take care that the configuration value is exactly named like the last
50
	 * part of the class name.
51
	 *
52
	 * The allowed characters of the class name are A-Z, a-z and 0-9. No other
53
	 * characters are possible! You should always start the last part of the class
54
	 * name with an upper case character and continue only with lower case characters
55
	 * or numbers. Avoid chamel case names like "MyService"!
56
	 *
57
	 * @param string Last part of the class name
58
	 * @since 2014.03
59
	 * @category Developer
60
	 */
61
62
	/** controller/frontend/service/decorators/excludes
63
	 * Excludes decorators added by the "common" option from the service frontend controllers
64
	 *
65
	 * Decorators extend the functionality of a class by adding new aspects
66
	 * (e.g. log what is currently done), executing the methods of the underlying
67
	 * class only in certain conditions (e.g. only for logged in users) or
68
	 * modify what is returned to the caller.
69
	 *
70
	 * This option allows you to remove a decorator added via
71
	 * "controller/frontend/common/decorators/default" before they are wrapped
72
	 * around the frontend controller.
73
	 *
74
	 *  controller/frontend/service/decorators/excludes = array( 'decorator1' )
75
	 *
76
	 * This would remove the decorator named "decorator1" from the list of
77
	 * common decorators ("\Aimeos\Controller\Frontend\Common\Decorator\*") added via
78
	 * "controller/frontend/common/decorators/default" for the service frontend controller.
79
	 *
80
	 * @param array List of decorator names
81
	 * @since 2014.03
82
	 * @category Developer
83
	 * @see controller/frontend/common/decorators/default
84
	 * @see controller/frontend/service/decorators/global
85
	 * @see controller/frontend/service/decorators/local
86
	 */
87
88
	/** controller/frontend/service/decorators/global
89
	 * Adds a list of globally available decorators only to the service frontend controllers
90
	 *
91
	 * Decorators extend the functionality of a class by adding new aspects
92
	 * (e.g. log what is currently done), executing the methods of the underlying
93
	 * class only in certain conditions (e.g. only for logged in users) or
94
	 * modify what is returned to the caller.
95
	 *
96
	 * This option allows you to wrap global decorators
97
	 * ("\Aimeos\Controller\Frontend\Common\Decorator\*") around the frontend controller.
98
	 *
99
	 *  controller/frontend/service/decorators/global = array( 'decorator1' )
100
	 *
101
	 * This would add the decorator named "decorator1" defined by
102
	 * "\Aimeos\Controller\Frontend\Common\Decorator\Decorator1" only to the frontend controller.
103
	 *
104
	 * @param array List of decorator names
105
	 * @since 2014.03
106
	 * @category Developer
107
	 * @see controller/frontend/common/decorators/default
108
	 * @see controller/frontend/service/decorators/excludes
109
	 * @see controller/frontend/service/decorators/local
110
	 */
111
112
	/** controller/frontend/service/decorators/local
113
	 * Adds a list of local decorators only to the service frontend controllers
114
	 *
115
	 * Decorators extend the functionality of a class by adding new aspects
116
	 * (e.g. log what is currently done), executing the methods of the underlying
117
	 * class only in certain conditions (e.g. only for logged in users) or
118
	 * modify what is returned to the caller.
119
	 *
120
	 * This option allows you to wrap local decorators
121
	 * ("\Aimeos\Controller\Frontend\Service\Decorator\*") around the frontend controller.
122
	 *
123
	 *  controller/frontend/service/decorators/local = array( 'decorator2' )
124
	 *
125
	 * This would add the decorator named "decorator2" defined by
126
	 * "\Aimeos\Controller\Frontend\Catalog\Decorator\Decorator2" only to the frontend
127
	 * controller.
128
	 *
129
	 * @param array List of decorator names
130
	 * @since 2014.03
131
	 * @category Developer
132
	 * @see controller/frontend/common/decorators/default
133
	 * @see controller/frontend/service/decorators/excludes
134
	 * @see controller/frontend/service/decorators/global
135
	 */
136
137
138
	private $domains = [];
139
	private $filter;
140
	private $manager;
141
142
143
	/**
144
	 * Common initialization for controller classes
145
	 *
146
	 * @param \Aimeos\MShop\ContextIface $context Common MShop context object
147
	 */
148
	public function __construct( \Aimeos\MShop\ContextIface $context )
149
	{
150
		parent::__construct( $context );
151
152
		$this->manager = \Aimeos\MShop::create( $context, 'service' );
153
		$this->filter = $this->manager->filter( true );
154
155
		$this->addExpression( $this->filter->sort( '+', 'service.position' ) );
156
	}
157
158
159
	/**
160
	 * Clones objects in controller
161
	 */
162
	public function __clone()
163
	{
164
		$this->filter = clone $this->filter;
165
		parent::__clone();
166
	}
167
168
169
	/**
170
	 * Adds generic condition for filtering services
171
	 *
172
	 * @param string $operator Comparison operator, e.g. "==", "!=", "<", "<=", ">=", ">", "=~", "~="
173
	 * @param string $key Search key defined by the service manager, e.g. "service.status"
174
	 * @param array|string $value Value or list of values to compare to
175
	 * @return \Aimeos\Controller\Frontend\Service\Iface Service controller for fluent interface
176
	 * @since 2019.04
177
	 */
178
	public function compare( string $operator, string $key, $value ) : Iface
179
	{
180
		$this->addExpression( $this->filter->compare( $operator, $key, $value ) );
181
		return $this;
182
	}
183
184
185
	/**
186
	 * Returns the service for the given code
187
	 *
188
	 * @param string $code Unique service code
189
	 * @return \Aimeos\MShop\Service\Item\Iface Service item including the referenced domains items
190
	 * @since 2019.04
191
	 */
192
	public function find( string $code ) : \Aimeos\MShop\Service\Item\Iface
193
	{
194
		return $this->manager->find( $code, $this->domains, null, null, null );
195
	}
196
197
198
	/**
199
	 * Creates a search function string for the given name and parameters
200
	 *
201
	 * @param string $name Name of the search function without parenthesis, e.g. "service:has"
202
	 * @param array $params List of parameters for the search function with numeric keys starting at 0
203
	 * @return string Search function string that can be used in compare()
204
	 */
205
	public function function( string $name, array $params ) : string
206
	{
207
		return $this->filter->make( $name, $params );
208
	}
209
210
211
	/**
212
	 * Returns the service for the given ID
213
	 *
214
	 * @param string $id Unique service ID
215
	 * @return \Aimeos\MShop\Service\Item\Iface Service item including the referenced domains items
216
	 * @since 2019.04
217
	 */
218
	public function get( string $id ) : \Aimeos\MShop\Service\Item\Iface
219
	{
220
		return $this->manager->get( $id, $this->domains, null );
221
	}
222
223
224
	/**
225
	 * Returns the service item for the given ID
226
	 *
227
	 * @param string $serviceId Unique service ID
228
	 * @return \Aimeos\MShop\Service\Provider\Iface Service provider object
229
	 */
230
	public function getProvider( string $serviceId ) : \Aimeos\MShop\Service\Provider\Iface
231
	{
232
		$item = $this->manager->get( $serviceId, $this->domains, true );
233
		return $this->manager->getProvider( $item, $item->getType() );
234
	}
235
236
237
	/**
238
	 * Returns the service providers of the given type
239
	 *
240
	 * @return \Aimeos\Map List of service IDs as keys and service provider objects as values
241
	 */
242
	public function getProviders() : \Aimeos\Map
243
	{
244
		$list = [];
245
		$this->addExpression( $this->filter->getConditions() );
246
		$this->filter->setConditions( $this->filter->and( $this->getConditions() ) )->order( 'service.position' );
247
248
		foreach( $this->manager->search( $this->filter, $this->domains ) as $id => $item ) {
249
			$list[$id] = $this->manager->getProvider( $item, $item->getType() );
250
		}
251
252
		return map( $list );
253
	}
254
255
256
	/**
257
	 * Parses the given array and adds the conditions to the list of conditions
258
	 *
259
	 * @param array $conditions List of conditions, e.g. ['&&' => [['>' => ['service.status' => 0]], ['==' => ['service.type' => 'default']]]]
260
	 * @return \Aimeos\Controller\Frontend\Service\Iface Service controller for fluent interface
261
	 * @since 2019.04
262
	 */
263
	public function parse( array $conditions ) : Iface
264
	{
265
		if( ( $cond = $this->filter->parse( $conditions ) ) !== null ) {
266
			$this->addExpression( $cond );
267
		}
268
269
		return $this;
270
	}
271
272
273
	/**
274
	 * Processes the payment service for the given order
275
	 *
276
	 * @param \Aimeos\MShop\Order\Item\Iface $orderItem Order which should be processed
277
	 * @param string $serviceId Unique service item ID
278
	 * @param array $urls Associative list of keys and the corresponding URLs
279
	 * 	(keys are payment.url-self, payment.url-success, payment.url-update)
280
	 * @param array $params Request parameters and order service attributes
281
	 * @return \Aimeos\MShop\Common\Helper\Form\Iface|null Form object with URL, parameters, etc.
282
	 * 	or null if no form data is required
283
	 */
284
	public function process( \Aimeos\MShop\Order\Item\Iface $orderItem,
285
		string $serviceId, array $urls, array $params ) : ?\Aimeos\MShop\Common\Helper\Form\Iface
286
	{
287
		$item = $this->manager->get( $serviceId, [], true );
288
289
		$provider = $this->manager->getProvider( $item, $item->getType() );
290
		$provider->injectGlobalConfigBE( $urls );
291
292
		return $provider->process( $orderItem, $params );
293
	}
294
295
296
	/**
297
	 * Returns the services filtered by the previously assigned conditions
298
	 *
299
	 * @param int &$total Parameter where the total number of found services will be stored in
300
	 * @return \Aimeos\Map Ordered list of service items implementing \Aimeos\MShop\Service\Item\Iface
301
	 * @since 2019.04
302
	 */
303
	public function search( int &$total = null ) : \Aimeos\Map
304
	{
305
		$this->addExpression( $this->filter->getConditions() );
306
307
		$this->filter->setSortations( $this->getSortations() );
308
		$this->filter->setConditions( $this->filter->and( $this->getConditions() ) );
309
310
		return $this->manager->search( $this->filter, $this->domains, $total );
311
	}
312
313
314
	/**
315
	 * Sets the start value and the number of returned services for slicing the list of found services
316
	 *
317
	 * @param int $start Start value of the first attribute in the list
318
	 * @param int $limit Number of returned services
319
	 * @return \Aimeos\Controller\Frontend\Service\Iface Service controller for fluent interface
320
	 * @since 2019.04
321
	 */
322
	public function slice( int $start, int $limit ) : Iface
323
	{
324
		$maxsize = $this->context()->config()->get( 'controller/frontend/common/max-size', 500 );
325
		$this->filter->slice( $start, min( $limit, $maxsize ) );
326
		return $this;
327
	}
328
329
330
	/**
331
	 * Sets the sorting of the result list
332
	 *
333
	 * @param string|null $key Sorting of the result list like "position", null for no sorting
334
	 * @return \Aimeos\Controller\Frontend\Service\Iface Service controller for fluent interface
335
	 * @since 2019.04
336
	 */
337
	public function sort( string $key = null ) : Iface
338
	{
339
		$list = $this->splitKeys( $key );
340
341
		foreach( $list as $sortkey )
342
		{
343
			$direction = ( $sortkey[0] === '-' ? '-' : '+' );
344
			$sortkey = ltrim( $sortkey, '+-' );
345
346
			switch( $sortkey )
347
			{
348
				case 'type':
349
					$this->addExpression( $this->filter->sort( $direction, 'service.type' ) ); break;
350
				default:
351
					$this->addExpression( $this->filter->sort( $direction, $sortkey ) );
352
			}
353
		}
354
355
		return $this;
356
	}
357
358
359
	/**
360
	 * Adds attribute types for filtering
361
	 *
362
	 * @param array|string $code Service type or list of types
363
	 * @return \Aimeos\Controller\Frontend\Service\Iface Service controller for fluent interface
364
	 * @since 2019.04
365
	 */
366
	public function type( $code ) : Iface
367
	{
368
		if( $code ) {
369
			$this->addExpression( $this->filter->compare( '==', 'service.type', $code ) );
370
		}
371
372
		return $this;
373
	}
374
375
376
	/**
377
	 * Updates the order status sent by payment gateway notifications
378
	 *
379
	 * @param ServerRequestInterface $request Request object
380
	 * @param ResponseInterface $response Response object that will contain HTTP status and response body
381
	 * @param string $code Unique code of the service used for the current order
382
	 * @return \Psr\Http\Message\ResponseInterface Response object
383
	 */
384
	public function updatePush( ServerRequestInterface $request, ResponseInterface $response,
385
		string $code ) : \Psr\Http\Message\ResponseInterface
386
	{
387
		$item = $this->manager->find( $code );
388
		$provider = $this->manager->getProvider( $item, $item->getType() );
389
390
		return $provider->updatePush( $request, $response );
391
	}
392
393
394
	/**
395
	 * Updates the payment or delivery status for the given request
396
	 *
397
	 * @param ServerRequestInterface $request Request object with parameters and request body
398
	 * @param string $code Unique code of the service used for the current order
399
	 * @param string $orderid ID of the order whose payment status should be updated
400
	 * @return \Aimeos\MShop\Order\Item\Iface $orderItem Order item that has been updated
401
	 */
402
	public function updateSync( ServerRequestInterface $request,
403
		string $code, string $orderid ) : \Aimeos\MShop\Order\Item\Iface
404
	{
405
		$orderItem = \Aimeos\MShop::create( $this->context(), 'order' )->get( $orderid );
406
		$serviceItem = $this->manager->find( $code );
407
408
		$provider = $this->manager->getProvider( $serviceItem, $serviceItem->getType() );
409
410
411
		if( ( $orderItem = $provider->updateSync( $request, $orderItem ) ) !== null )
412
		{
413
			if( $orderItem->getStatusPayment() === \Aimeos\MShop\Order\Item\Base::PAY_UNFINISHED
414
				&& $provider->isImplemented( \Aimeos\MShop\Service\Provider\Payment\Base::FEAT_QUERY )
415
			) {
416
				$provider->query( $orderItem );
417
			}
418
		}
419
420
		return $orderItem;
421
	}
422
423
424
	/**
425
	 * Sets the referenced domains that will be fetched too when retrieving items
426
	 *
427
	 * @param array $domains Domain names of the referenced items that should be fetched too
428
	 * @return \Aimeos\Controller\Frontend\Service\Iface Service controller for fluent interface
429
	 * @since 2019.04
430
	 */
431
	public function uses( array $domains ) : Iface
432
	{
433
		$this->domains = $domains;
434
		return $this;
435
	}
436
437
438
	/**
439
	 * Returns the manager used by the controller
440
	 *
441
	 * @return \Aimeos\MShop\Common\Manager\Iface Manager object
442
	 */
443
	protected function getManager() : \Aimeos\MShop\Common\Manager\Iface
444
	{
445
		return $this->manager;
446
	}
447
}
448