Completed
Push — master ( 12c65b...25c6af )
by Aimeos
02:28
created

Standard::updateSync()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 33
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 8.439
c 0
b 0
f 0
cc 5
eloc 18
nc 4
nop 3
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-2017
7
 * @package Controller
8
 * @subpackage Frontend
9
 */
10
11
12
namespace Aimeos\Controller\Frontend\Service;
13
14
use \Psr\Http\Message\ServerRequestInterface;
15
use \Psr\Http\Message\ResponseInterface;
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
	private $providers = array();
29
30
31
	/**
32
	 * Returns a list of attributes that are invalid
33
	 *
34
	 * @param string $serviceId Unique service ID
35
	 * @param string[] $attributes List of attribute codes as keys and strings entered by the customer as value
36
	 * @return string[] List of attributes codes as keys and error messages as values for invalid or missing values
37
	 */
38
	public function checkAttributes( $serviceId, array $attributes )
39
	{
40
		$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'service' );
41
		$provider = $manager->getProvider( $manager->getItem( $serviceId, [], true ) );
0 ignored issues
show
Unused Code introduced by
The call to Iface::getItem() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
42
43
		return array_filter( $provider->checkConfigFE( $attributes ) );
44
	}
45
46
47
	/**
48
	 * Returns the service item for the given ID
49
	 *
50
	 * @param string $serviceId Unique service ID
51
	 * @param string[] $ref List of domain names whose items should be fetched too
52
	 * @return \Aimeos\MShop\Service\Provider\Iface Service provider object
53
	 */
54
	public function getProvider( $serviceId, $ref = ['media', 'price', 'text'] )
55
	{
56
		$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'service' );
57
		return $manager->getProvider( $manager->getItem( $serviceId, $ref, true ) );
0 ignored issues
show
Unused Code introduced by
The call to Iface::getItem() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
58
	}
59
60
61
	/**
62
	 * Returns the service providers of the given type
63
	 *
64
	 * @param string|null $type Service type, e.g. "delivery" (shipping related), "payment" (payment related) or null for all
65
	 * @param string[] $ref List of domain names whose items should be fetched too
66
	 * @return \Aimeos\MShop\Service\Provider\Iface[] List of service IDs as keys and service provider objects as values
67
	 */
68
	public function getProviders( $type = null, $ref = ['media', 'price', 'text'] )
69
	{
70
		$list = [];
71
		$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'service' );
72
73
		$search = $manager->createSearch( true );
74
		$search->setSortations( array( $search->sort( '+', 'service.position' ) ) );
75
76
		if( $type != null )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $type of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
77
		{
78
			$expr = array(
79
				$search->getConditions(),
80
				$search->compare( '==', 'service.type.code', $type ),
81
				$search->compare( '==', 'service.type.domain', 'service' ),
82
			);
83
			$search->setConditions( $search->combine( '&&', $expr ) );
84
		}
85
86
		foreach( $manager->searchItems( $search, $ref ) as $id => $item ) {
87
			$list[$id] = $manager->getProvider( $item );
88
		}
89
90
		return $list;
91
	}
92
93
94
	/**
95
	 * Processes the service for the given order, e.g. payment and delivery services
96
	 *
97
	 * @param \Aimeos\MShop\Order\Item\Iface $orderItem Order which should be processed
98
	 * @param string $serviceId Unique service item ID
99
	 * @param array $urls Associative list of keys and the corresponding URLs
100
	 * 	(keys are <type>.url-self, <type>.url-success, <type>.url-update where type can be "delivery" or "payment")
101
	 * @param array $params Request parameters and order service attributes
102
	 * @return \Aimeos\MShop\Common\Item\Helper\Form\Iface|null Form object with URL, parameters, etc.
103
	 * 	or null if no form data is required
104
	 */
105
	public function process( \Aimeos\MShop\Order\Item\Iface $orderItem, $serviceId, array $urls, array $params )
106
	{
107
		$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'service' );
108
109
		$provider = $manager->getProvider( $manager->getItem( $serviceId, [], true ) );
0 ignored issues
show
Unused Code introduced by
The call to Iface::getItem() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
110
		$provider->injectGlobalConfigBE( $urls );
111
112
		return $provider->process( $orderItem, $params );
113
	}
114
115
116
	/**
117
	 * Updates the payment or delivery status for the given request
118
	 *
119
	 * @param ServerRequestInterface $request Request object with parameters and request body
120
	 * @param ResponseInterface &$response Response object that will contain HTTP status and response body
121
	 * @param array $urls Associative list of keys and the corresponding URLs
122
	 * 	(keys are <type>.url-self, <type>.url-success, <type>.url-update where type can be "delivery" or "payment")
123
	 * @return \Aimeos\MShop\Order\Item\Iface $orderItem Order item that has been updated
124
	 */
125
	public function updateSync( ServerRequestInterface $request, ResponseInterface &$response, array $urls )
126
	{
127
		$queryParams = $request->getQueryParams();
128
129
		if( !isset( $queryParams['code'] ) ) {
130
			return;
131
		}
132
133
		$context = $this->getContext();
134
		$manager = \Aimeos\MShop\Factory::createManager( $context, 'service' );
135
136
		$provider = $manager->getProvider( $manager->findItem( $queryParams['code'] ) );
137
		$provider->injectGlobalConfigBE( $urls );
138
139
		$params = array_merge( $queryParams, (array) $request->getParsedBody() );
140
		$body = (string) $request->getBody();
141
		$response = null;
142
		$headers = [];
143
144
		if( ( $orderItem = $provider->updateSync( $params, $body, $response, $headers ) ) !== null )
145
		{
146
			if( $orderItem->getPaymentStatus() === \Aimeos\MShop\Order\Item\Base::PAY_UNFINISHED
147
				&& $provider->isImplemented( \Aimeos\MShop\Service\Provider\Payment\Base::FEAT_QUERY )
148
			) {
149
				$provider->query( $orderItem );
150
			}
151
152
			 // update stock, coupons, etc.
153
			\Aimeos\Controller\Frontend\Factory::createController( $context, 'order' )->update( $orderItem );
154
		}
155
156
		return $orderItem;
157
	}
158
159
160
	/**
161
	 * Returns the service items that are available for the service type and the content of the basket.
162
	 *
163
	 * @param string $type Service type, e.g. "delivery" (shipping related) or "payment" (payment related)
164
	 * @param \Aimeos\MShop\Order\Item\Base\Iface $basket Basket of the user
165
	 * @param array $ref List of domains for which the items referenced by the services should be fetched too
166
	 * @return array List of service items implementing \Aimeos\MShop\Service\Item\Iface with referenced items
167
	 * @throws \Exception If an error occurs
168
	 * @deprecated Use getProviders() instead
169
	 */
170
	public function getServices( $type, \Aimeos\MShop\Order\Item\Base\Iface $basket, $ref = ['media', 'price', 'text'] )
171
	{
172
		$serviceManager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'service' );
173
174
		$search = $serviceManager->createSearch( true );
175
		$expr = array(
176
			$search->getConditions(),
177
			$search->compare( '==', 'service.type.domain', 'service' ),
178
			$search->compare( '==', 'service.type.code', $type ),
179
		);
180
		$search->setConditions( $search->combine( '&&', $expr ) );
181
		$search->setSortations( array( $search->sort( '+', 'service.position' ) ) );
182
183
		$items = $serviceManager->searchItems( $search, $ref );
184
185
186
		foreach( $items as $id => $service )
187
		{
188
			try
189
			{
190
				$provider = $serviceManager->getProvider( $service );
191
192
				if( $provider->isAvailable( $basket ) ) {
193
					$this->providers[$type][$id] = $provider;
194
				} else {
195
					unset( $items[$id] );
196
				}
197
			}
198
			catch( \Aimeos\MShop\Service\Exception $e )
199
			{
200
				$msg = sprintf( 'Unable to create provider "%1$s" for service with ID "%2$s"', $service->getCode(), $id );
201
				$this->getContext()->getLogger()->log( $msg, \Aimeos\MW\Logger\Base::WARN );
202
			}
203
		}
204
205
		return $items;
206
	}
207
208
209
	/**
210
	 * Returns the list of attribute definitions which must be used to render the input form where the customer can
211
	 * enter or chose the required data necessary by the service provider.
212
	 *
213
	 * @param string $type Service type, e.g. "delivery" (shipping related) or "payment" (payment related)
214
	 * @param string $serviceId Identifier of one of the service option returned by getService()
215
	 * @param \Aimeos\MShop\Order\Item\Base\Iface $basket Basket object
216
	 * @return array List of attribute definitions implementing \Aimeos\MW\Criteria\Attribute\Iface
217
	 * @throws \Aimeos\Controller\Frontend\Service\Exception If no active service provider for this ID is available
218
	 * @throws \Aimeos\MShop\Exception If service provider isn't available
219
	 * @throws \Exception If an error occurs
220
	 * @deprecated Use getProvider() instead
221
	 */
222
	public function getServiceAttributes( $type, $serviceId, \Aimeos\MShop\Order\Item\Base\Iface $basket )
223
	{
224
		if( isset( $this->providers[$type][$serviceId] ) ) {
225
			return $this->providers[$type][$serviceId]->getConfigFE( $basket );
226
		}
227
228
		$serviceManager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'service' );
229
		$item = $serviceManager->getItem( $serviceId, ['price'], true );
0 ignored issues
show
Unused Code introduced by
The call to Iface::getItem() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
230
231
		return $serviceManager->getProvider( $item )->getConfigFE( $basket );
232
	}
233
234
235
	/**
236
	 * Returns the price of the service.
237
	 *
238
	 * @param string $type Service type, e.g. "delivery" (shipping related) or "payment" (payment related)
239
	 * @param string $serviceId Identifier of one of the service option returned by getService()
240
	 * @param \Aimeos\MShop\Order\Item\Base\Iface $basket Basket with products
241
	 * @return \Aimeos\MShop\Price\Item\Iface Price item
242
	 * @throws \Aimeos\Controller\Frontend\Service\Exception If no active service provider for this ID is available
243
	 * @throws \Aimeos\MShop\Exception If service provider isn't available
244
	 * @throws \Exception If an error occurs
245
	 * @deprecated Use getProvider() instead
246
	 */
247
	public function getServicePrice( $type, $serviceId, \Aimeos\MShop\Order\Item\Base\Iface $basket )
248
	{
249
		if( isset( $this->providers[$type][$serviceId] ) ) {
250
			return $this->providers[$type][$serviceId]->calcPrice( $basket );
251
		}
252
253
		$serviceManager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'service' );
254
		$item = $serviceManager->getItem( $serviceId, ['price'], true );
0 ignored issues
show
Unused Code introduced by
The call to Iface::getItem() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
255
256
		return $serviceManager->getProvider( $item )->calcPrice( $basket );
257
	}
258
259
260
	/**
261
	 * Returns a list of attributes that are invalid.
262
	 *
263
	 * @param string $type Service type, e.g. "delivery" (shipping related) or "payment" (payment related)
264
	 * @param string $serviceId Identifier of the service option chosen by the customer
265
	 * @param array $attributes List of key/value pairs with name of the attribute from attribute definition object as
266
	 * 	key and the string entered by the customer as value
267
	 * @return array An array with the attribute keys as key and an error message as values for all attributes that are
268
	 * 	known by the provider but aren't valid resp. null for attributes whose values are OK
269
	 * @throws \Aimeos\Controller\Frontend\Service\Exception If no active service provider for this ID is available
270
	 * @deprecated Use checkAttributes() instead
271
	 */
272
	public function checkServiceAttributes( $type, $serviceId, array $attributes )
273
	{
274
		if( !isset( $this->providers[$type][$serviceId] ) )
275
		{
276
			$serviceManager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'service' );
277
			$item = $serviceManager->getItem( $serviceId, ['price'], true );
0 ignored issues
show
Unused Code introduced by
The call to Iface::getItem() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
278
279
			$this->providers[$type][$serviceId] = $serviceManager->getProvider( $item );
280
		}
281
282
		$errors = $this->providers[$type][$serviceId]->checkConfigFE( $attributes );
283
284
		foreach( $errors as $key => $msg )
285
		{
286
			if( $msg === null ) {
287
				unset( $errors[$key] );
288
			}
289
		}
290
291
		return $errors;
292
	}
293
}
294