Passed
Branch master (4f99e3)
by Aimeos
04:48
created

Standard::getBody()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 40
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 3
nop 1
dl 0
loc 40
rs 9.5555
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2013
6
 * @copyright Aimeos (aimeos.org), 2015-2018
7
 * @package Client
8
 * @subpackage Html
9
 */
10
11
12
namespace Aimeos\Client\Html\Checkout\Standard\Address;
13
14
15
// Strings for translation
16
sprintf( 'address' );
17
18
19
/**
20
 * Default implementation of checkout address HTML client.
21
 *
22
 * @package Client
23
 * @subpackage Html
24
 */
25
class Standard
26
	extends \Aimeos\Client\Html\Common\Client\Factory\Base
27
	implements \Aimeos\Client\Html\Common\Client\Factory\Iface
28
{
29
	/** client/html/checkout/standard/address/standard/subparts
30
	 * List of HTML sub-clients rendered within the checkout standard address section
31
	 *
32
	 * The output of the frontend is composed of the code generated by the HTML
33
	 * clients. Each HTML client can consist of serveral (or none) sub-clients
34
	 * that are responsible for rendering certain sub-parts of the output. The
35
	 * sub-clients can contain HTML clients themselves and therefore a
36
	 * hierarchical tree of HTML clients is composed. Each HTML client creates
37
	 * the output that is placed inside the container of its parent.
38
	 *
39
	 * At first, always the HTML code generated by the parent is printed, then
40
	 * the HTML code of its sub-clients. The order of the HTML sub-clients
41
	 * determines the order of the output of these sub-clients inside the parent
42
	 * container. If the configured list of clients is
43
	 *
44
	 *  array( "subclient1", "subclient2" )
45
	 *
46
	 * you can easily change the order of the output by reordering the subparts:
47
	 *
48
	 *  client/html/<clients>/subparts = array( "subclient1", "subclient2" )
49
	 *
50
	 * You can also remove one or more parts if they shouldn't be rendered:
51
	 *
52
	 *  client/html/<clients>/subparts = array( "subclient1" )
53
	 *
54
	 * As the clients only generates structural HTML, the layout defined via CSS
55
	 * should support adding, removing or reordering content by a fluid like
56
	 * design.
57
	 *
58
	 * @param array List of sub-client names
59
	 * @since 2014.03
60
	 * @category Developer
61
	 */
62
	private $subPartPath = 'client/html/checkout/standard/address/standard/subparts';
63
64
	/** client/html/checkout/standard/address/billing/name
65
	 * Name of the billing part used by the checkout standard address client implementation
66
	 *
67
	 * Use "Myname" if your class is named "\Aimeos\Client\Checkout\Standard\Address\Billing\Myname".
68
	 * The name is case-sensitive and you should avoid camel case names like "MyName".
69
	 *
70
	 * @param string Last part of the client class name
71
	 * @since 2014.03
72
	 * @category Developer
73
	 */
74
75
	/** client/html/checkout/standard/address/delivery/name
76
	 * Name of the delivery part used by the checkout standard address client implementation
77
	 *
78
	 * Use "Myname" if your class is named "\Aimeos\Client\Checkout\Standard\Address\Delivery\Myname".
79
	 * The name is case-sensitive and you should avoid camel case names like "MyName".
80
	 *
81
	 * @param string Last part of the client class name
82
	 * @since 2014.03
83
	 * @category Developer
84
	 */
85
	private $subPartNames = array( 'billing', 'delivery' );
86
87
88
	/**
89
	 * Returns the HTML code for insertion into the body.
90
	 *
91
	 * @param string $uid Unique identifier for the output if the content is placed more than once on the same page
92
	 * @return string HTML code
93
	 */
94
	public function getBody( $uid = '' )
95
	{
96
		$view = $this->getView();
97
		$step = $view->get( 'standardStepActive', 'address' );
98
		$onepage = $view->config( 'client/html/checkout/standard/onepage', [] );
99
100
		if( $step != 'address' && !( in_array( 'address', $onepage ) && in_array( $step, $onepage ) ) ) {
101
			return '';
102
		}
103
104
		$html = '';
105
		foreach( $this->getSubClients() as $subclient ) {
106
			$html .= $subclient->setView( $view )->getBody( $uid );
107
		}
108
		$view->addressBody = $html;
109
110
		/** client/html/checkout/standard/address/standard/template-body
111
		 * Relative path to the HTML body template of the checkout standard address client.
112
		 *
113
		 * The template file contains the HTML code and processing instructions
114
		 * to generate the result shown in the body of the frontend. The
115
		 * configuration string is the path to the template file relative
116
		 * to the templates directory (usually in client/html/templates).
117
		 *
118
		 * You can overwrite the template file configuration in extensions and
119
		 * provide alternative templates. These alternative templates should be
120
		 * named like the default one but with the string "standard" replaced by
121
		 * an unique name. You may use the name of your project for this. If
122
		 * you've implemented an alternative client class as well, "standard"
123
		 * should be replaced by the name of the new class.
124
		 *
125
		 * @param string Relative path to the template creating code for the HTML page body
126
		 * @since 2014.03
127
		 * @category Developer
128
		 * @see client/html/checkout/standard/address/standard/template-header
129
		 */
130
		$tplconf = 'client/html/checkout/standard/address/standard/template-body';
131
		$default = 'checkout/standard/address-body-standard';
132
133
		return $view->render( $view->config( $tplconf, $default ) );
134
	}
135
136
137
	/**
138
	 * Returns the HTML string for insertion into the header.
139
	 *
140
	 * @param string $uid Unique identifier for the output if the content is placed more than once on the same page
141
	 * @return string|null String including HTML tags for the header on error
142
	 */
143
	public function getHeader( $uid = '' )
144
	{
145
		$view = $this->getView();
146
		$step = $view->get( 'standardStepActive' );
147
		$onepage = $view->config( 'client/html/checkout/standard/onepage', [] );
148
149
		if( $step != 'address' && !( in_array( 'address', $onepage ) && in_array( $step, $onepage ) ) ) {
150
			return '';
151
		}
152
153
		return parent::getHeader( $uid );
154
	}
155
156
157
	/**
158
	 * Returns the sub-client given by its name.
159
	 *
160
	 * @param string $type Name of the client type
161
	 * @param string|null $name Name of the sub-client (Default if null)
162
	 * @return \Aimeos\Client\Html\Iface Sub-client object
163
	 */
164
	public function getSubClient( $type, $name = null )
165
	{
166
		/** client/html/checkout/standard/address/decorators/excludes
167
		 * Excludes decorators added by the "common" option from the checkout standard address html client
168
		 *
169
		 * Decorators extend the functionality of a class by adding new aspects
170
		 * (e.g. log what is currently done), executing the methods of the underlying
171
		 * class only in certain conditions (e.g. only for logged in users) or
172
		 * modify what is returned to the caller.
173
		 *
174
		 * This option allows you to remove a decorator added via
175
		 * "client/html/common/decorators/default" before they are wrapped
176
		 * around the html client.
177
		 *
178
		 *  client/html/checkout/standard/address/decorators/excludes = array( 'decorator1' )
179
		 *
180
		 * This would remove the decorator named "decorator1" from the list of
181
		 * common decorators ("\Aimeos\Client\Html\Common\Decorator\*") added via
182
		 * "client/html/common/decorators/default" to the html client.
183
		 *
184
		 * @param array List of decorator names
185
		 * @since 2015.08
186
		 * @category Developer
187
		 * @see client/html/common/decorators/default
188
		 * @see client/html/checkout/standard/address/decorators/global
189
		 * @see client/html/checkout/standard/address/decorators/local
190
		 */
191
192
		/** client/html/checkout/standard/address/decorators/global
193
		 * Adds a list of globally available decorators only to the checkout standard address html client
194
		 *
195
		 * Decorators extend the functionality of a class by adding new aspects
196
		 * (e.g. log what is currently done), executing the methods of the underlying
197
		 * class only in certain conditions (e.g. only for logged in users) or
198
		 * modify what is returned to the caller.
199
		 *
200
		 * This option allows you to wrap global decorators
201
		 * ("\Aimeos\Client\Html\Common\Decorator\*") around the html client.
202
		 *
203
		 *  client/html/checkout/standard/address/decorators/global = array( 'decorator1' )
204
		 *
205
		 * This would add the decorator named "decorator1" defined by
206
		 * "\Aimeos\Client\Html\Common\Decorator\Decorator1" only to the html client.
207
		 *
208
		 * @param array List of decorator names
209
		 * @since 2015.08
210
		 * @category Developer
211
		 * @see client/html/common/decorators/default
212
		 * @see client/html/checkout/standard/address/decorators/excludes
213
		 * @see client/html/checkout/standard/address/decorators/local
214
		 */
215
216
		/** client/html/checkout/standard/address/decorators/local
217
		 * Adds a list of local decorators only to the checkout standard address html client
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 wrap local decorators
225
		 * ("\Aimeos\Client\Html\Checkout\Decorator\*") around the html client.
226
		 *
227
		 *  client/html/checkout/standard/address/decorators/local = array( 'decorator2' )
228
		 *
229
		 * This would add the decorator named "decorator2" defined by
230
		 * "\Aimeos\Client\Html\Checkout\Decorator\Decorator2" only to the html client.
231
		 *
232
		 * @param array List of decorator names
233
		 * @since 2015.08
234
		 * @category Developer
235
		 * @see client/html/common/decorators/default
236
		 * @see client/html/checkout/standard/address/decorators/excludes
237
		 * @see client/html/checkout/standard/address/decorators/global
238
		 */
239
240
		return $this->createSubClient( 'checkout/standard/address/' . $type, $name );
241
	}
242
243
244
	/**
245
	 * Processes the input, e.g. store given values.
246
	 * A view must be available and this method doesn't generate any output
247
	 * besides setting view variables.
248
	 */
249
	public function process()
250
	{
251
		$view = $this->getView();
252
253
		try
254
		{
255
			parent::process();
256
257
			$context = $this->getContext();
258
259
			if( ( $param = $view->param( 'ca_extra' ) ) !== null ) {
260
				$context->getSession()->set( 'client/html/checkout/standard/address/extra', (array) $param );
261
			}
262
263
			$basketCntl = \Aimeos\Controller\Frontend::create( $context, 'basket' );
264
265
			// Test if addresses are available
266
			$addresses = $basketCntl->get()->getAddresses();
1 ignored issue
show
Bug introduced by
The method get() does not exist on Aimeos\Controller\Frontend\Iface. It seems like you code against a sub-type of said class. However, the method does not exist in Aimeos\Controller\Frontend\Common\Iface or Aimeos\Controller\Frontend\Common\Decorator\Iface or Aimeos\Controller\Fronte...ommon\Decorator\Example. 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

266
			$addresses = $basketCntl->/** @scrutinizer ignore-call */ get()->getAddresses();
Loading history...
267
			if( !isset( $view->standardStepActive ) && count( $addresses ) === 0 )
268
			{
269
				$view->standardStepActive = 'address';
270
				return false;
271
			}
272
		}
273
		catch( \Exception $e )
274
		{
275
			$this->getView()->standardStepActive = 'address';
276
			throw $e;
277
		}
278
279
	}
280
281
282
	/**
283
	 * Returns the list of sub-client names configured for the client.
284
	 *
285
	 * @return array List of HTML client names
286
	 */
287
	protected function getSubClientNames()
288
	{
289
		return $this->getContext()->getConfig()->get( $this->subPartPath, $this->subPartNames );
290
	}
291
292
293
	/**
294
	 * Sets the necessary parameter values in the view.
295
	 *
296
	 * @param \Aimeos\MW\View\Iface $view The view object which generates the HTML output
297
	 * @param array &$tags Result array for the list of tags that are associated to the output
298
	 * @param string|null &$expire Result variable for the expiration date of the output (null for no expiry)
299
	 * @return \Aimeos\MW\View\Iface Modified view object
300
	 */
301
	public function addData( \Aimeos\MW\View\Iface $view, array &$tags = [], &$expire = null )
302
	{
303
		$context = $this->getContext();
304
		$controller = \Aimeos\Controller\Frontend::create( $context, 'customer' );
305
		$orderAddressManager = \Aimeos\MShop::create( $context, 'order/base/address' );
306
307
		try
308
		{
309
			$deliveryAddressItems = [];
310
			$item = $controller->getItem( $context->getUserId(), ['customer/address'] );
1 ignored issue
show
Bug introduced by
The method getItem() does not exist on Aimeos\Controller\Frontend\Iface. It seems like you code against a sub-type of said class. However, the method does not exist in Aimeos\Controller\Frontend\Common\Iface or Aimeos\Controller\Frontend\Common\Decorator\Iface or Aimeos\Controller\Fronte...ommon\Decorator\Example. 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

310
			/** @scrutinizer ignore-call */ 
311
   $item = $controller->getItem( $context->getUserId(), ['customer/address'] );
Loading history...
311
312
			foreach( $item->getAddressItems() as $id => $addrItem ) {
313
				$deliveryAddressItems[$id] = $orderAddressManager->createItem()->copyFrom( $addrItem );
0 ignored issues
show
Bug introduced by
The method copyFrom() does not exist on Aimeos\MShop\Attribute\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

313
				$deliveryAddressItems[$id] = $orderAddressManager->createItem()->/** @scrutinizer ignore-call */ copyFrom( $addrItem );

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
314
			}
315
316
			$paymentAddressItem = $orderAddressManager->createItem()->copyFrom( $item->getPaymentAddress() );
317
318
			$view->addressCustomerItem = $item;
319
			$view->addressPaymentItem = $paymentAddressItem;
320
			$view->addressDeliveryItems = $deliveryAddressItems;
321
		}
322
		catch( \Exception $e ) {} // customer has no account yet
323
324
325
		$localeManager = \Aimeos\MShop::create( $context, 'locale' );
326
		$locales = $localeManager->searchItems( $localeManager->createSearch( true ) );
327
328
		$languages = [];
329
		foreach( $locales as $locale ) {
330
			$languages[$locale->getLanguageId()] = $locale->getLanguageId();
1 ignored issue
show
Bug introduced by
The method getLanguageId() 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\Text\Item\Iface or Aimeos\MShop\Media\Item\Iface or Aimeos\MShop\Locale\Item\Iface or Aimeos\MShop\Tag\Item\Iface or Aimeos\MShop\Supplier\Item\Address\Iface or Aimeos\MShop\Common\Item\Address\Iface or Aimeos\MShop\Common\Item\Property\Iface or Aimeos\MShop\Common\Item\Property\Standard or Aimeos\MShop\Tag\Item\Standard or Aimeos\MShop\Common\Item\Address\Base or Aimeos\MShop\Media\Item\Standard or Aimeos\MShop\Text\Item\Standard or Aimeos\MShop\Locale\Item\Standard or Aimeos\MShop\Text\Item\Iface or Aimeos\MShop\Media\Item\Iface or Aimeos\MShop\Locale\Item\Iface or Aimeos\MShop\Text\Item\Iface or Aimeos\MShop\Media\Item\Iface or Aimeos\MShop\Media\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

330
			$languages[$locale->/** @scrutinizer ignore-call */ getLanguageId()] = $locale->getLanguageId();
Loading history...
331
		}
332
333
		$view->addressLanguages = $languages;
334
335
		/** client/html/checkout/standard/address/countries
336
		 * List of available countries that that users can select from in the front-end
337
		 *
338
		 * This configration option is used whenever a list of countries is
339
		 * shown in the front-end users can select from. It's used e.g.
340
		 * if the customer should select the country he is living in the
341
		 * checkout process. In case that the list is empty, no country
342
		 * selection is shown.
343
		 *
344
		 * Each list entry must be a two letter ISO country code that is then
345
		 * translated into its name. The codes have to be upper case
346
		 * characters like "DE" for Germany or "GB" for Great Britain, e.g.
347
		 *
348
		 *  array( 'DE', 'GB', ... )
349
		 *
350
		 * To display the country selection, you have to add the key for the
351
		 * country ID (order.base.address.languageid) to the "mandatory" or
352
		 * "optional" configuration option for billing and delivery addresses.
353
		 *
354
		 * Until 2015-02, the configuration option was available as
355
		 * "client/html/common/address/countries" starting from 2014-03.
356
		 *
357
		 * @param array List of two letter ISO country codes
358
		 * @since 2015.02
359
		 * @category User
360
		 * @category Developer
361
		 * @see client/html/checkout/standard/address/billing/mandatory
362
		 * @see client/html/checkout/standard/address/billing/optional
363
		 * @see client/html/checkout/standard/address/delivery/mandatory
364
		 * @see client/html/checkout/standard/address/delivery/optional
365
		 */
366
		$view->addressCountries = $view->config( 'client/html/checkout/standard/address/countries', [] );
367
368
		/** client/html/checkout/standard/address/states
369
		 * List of available states that that users can select from in the front-end
370
		 *
371
		 * This configration option is used whenever a list of states is
372
		 * shown in the front-end users can select from. It's used e.g.
373
		 * if the customer should select the state he is living in the
374
		 * checkout process. In case that the list is empty, no state
375
		 * selection is shown.
376
		 *
377
		 * A two letter ISO country code must be the key for the list of
378
		 * states that belong to this country. The list of states must then
379
		 * contain the state code as key and its name as values, e.g.
380
		 *
381
		 *  array(
382
		 *      'US' => array(
383
		 *          'CA' => 'California',
384
		 *          'NY' => 'New York',
385
		 *          ...
386
		 *      ),
387
		 *      ...
388
		 *  );
389
		 *
390
		 * The codes have to be upper case characters like "US" for the
391
		 * United States or "DE" for Germany. The order of the country and
392
		 * state codes determine the order of the states in the frontend and
393
		 * the state codes are later used for per state tax calculation.
394
		 *
395
		 * To display the country selection, you have to add the key for the
396
		 * state (order.base.address.state) to the "mandatory" or
397
		 * "optional" configuration option for billing and delivery addresses.
398
		 * You also need to add order.base.address.countryid as well because
399
		 * it is required to display the states that belong to this country.
400
		 *
401
		 * Until 2015-02, the configuration option was available as
402
		 * "client/html/common/address/states" starting from 2014-09.
403
		 *
404
		 * @param array Multi-dimensional list ISO country codes and state codes/names
405
		 * @since 2015.02
406
		 * @category User
407
		 * @category Developer
408
		 * @see client/html/checkout/standard/address/billing/mandatory
409
		 * @see client/html/checkout/standard/address/billing/optional
410
		 * @see client/html/checkout/standard/address/delivery/mandatory
411
		 * @see client/html/checkout/standard/address/delivery/optional
412
		 */
413
		$view->addressStates = $view->config( 'client/html/checkout/standard/address/states', [] );
414
415
		$view->addressExtra = $context->getSession()->get( 'client/html/checkout/standard/address/extra', [] );
416
417
		return parent::addData( $view, $tags, $expire );
418
	}
419
}
420