Standard::validateFields()   A
last analyzed

Complexity

Conditions 6
Paths 7

Size

Total Lines 135
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 9
c 1
b 0
f 0
nc 7
nop 2
dl 0
loc 135
rs 9.2222

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), 2015-2025
6
 * @package Client
7
 * @subpackage Html
8
 */
9
10
11
namespace Aimeos\Client\Html\Checkout\Standard\Address\Payment;
12
13
14
/**
15
 * Default implementation of checkout payment address HTML client.
16
 *
17
 * @package Client
18
 * @subpackage Html
19
 */
20
class Standard
21
	extends \Aimeos\Client\Html\Common\Client\Factory\Base
22
	implements \Aimeos\Client\Html\Common\Client\Factory\Iface
23
{
24
	/**
25
	 * Stores the given or fetched payment address in the basket.
26
	 *
27
	 * A view must be available and this method doesn't generate any output
28
	 * besides setting view variables if necessary.
29
	 */
30
	public function init()
31
	{
32
		$view = $this->view();
33
34
		try
35
		{
36
			// only start if there's something to do
37
			if( $view->param( 'ca_paymentoption', null ) === null ) {
38
				return;
39
			}
40
41
			$this->setAddress( $view );
42
43
			parent::init();
44
		}
45
		catch( \Aimeos\Controller\Frontend\Exception $e )
46
		{
47
			$view->addressPaymentError = $e->getErrorList();
48
			throw $e;
49
		}
50
	}
51
52
53
	/**
54
	 * Sets the necessary parameter values in the view.
55
	 *
56
	 * @param \Aimeos\Base\View\Iface $view The view object which generates the HTML output
57
	 * @param array &$tags Result array for the list of tags that are associated to the output
58
	 * @param string|null &$expire Result variable for the expiration date of the output (null for no expiry)
59
	 * @return \Aimeos\Base\View\Iface Modified view object
60
	 */
61
	public function data( \Aimeos\Base\View\Iface $view, array &$tags = [], ?string &$expire = null ) : \Aimeos\Base\View\Iface
62
	{
63
		$context = $this->context();
64
		$basketCntl = \Aimeos\Controller\Frontend::create( $context, 'basket' );
65
66
		$addr = current( $basketCntl->get()->getAddress( 'payment' ) );
67
68
		$values = $addr ? $addr->toArray() : [];
69
		$id = $view->get( 'addressCustomerItem' ) && $view->addressCustomerItem->getId() ? $view->addressCustomerItem->getId() : 'null';
70
		$id = ( $values['order.address.addressid'] ?? null ) ?: $id;
71
72
		$view->addressPaymentString = $this->getAddressString( $view, $view->addressPaymentItem );
73
		$view->addressPaymentValuesNew = array_merge( $values, $view->param( 'ca_payment', [] ) );
74
		$view->addressPaymentValues = array_merge( $values, $view->param( 'ca_payment_' . $id, [] ) );
75
		$view->addressPaymentOption = $view->param( 'ca_paymentoption', $id );
76
		$view->addressPaymentCss = $this->cssPayment();
77
78
		return parent::data( $view, $tags, $expire );
79
	}
80
81
82
	/**
83
	 * Checks the address fields for missing data and sanitizes the given parameter list.
84
	 *
85
	 * @param array $params Associative list of address keys (order.address.*) and their values
86
	 * @return array List of missing field names
87
	 */
88
	protected function checkFields( array $params ) : array
89
	{
90
		$view = $this->view();
91
92
		/** client/html/common/address/payment/mandatory
93
		 * List of payment address input fields that are required
94
		 *
95
		 * You can configure the list of payment address fields that are
96
		 * necessary and must be filled by the customer before he can
97
		 * continue the checkout process. Available field keys are:
98
		 *
99
		 * * company
100
		 * * vatid
101
		 * * salutation
102
		 * * firstname
103
		 * * lastname
104
		 * * address1
105
		 * * address2
106
		 * * address3
107
		 * * postal
108
		 * * city
109
		 * * state
110
		 * * languageid
111
		 * * countryid
112
		 * * telephone
113
		 * * telefax
114
		 * * mobile
115
		 * * email
116
		 * * website
117
		 *
118
		 * Until 2015-02, the configuration option was available as
119
		 * "client/html/common/address/payment/mandatory" starting from 2014-03.
120
		 *
121
		 * @param array List of field keys
122
		 * @since 2015.02
123
		 * @see client/html/checkout/standard/address/payment/disable-new
124
		 * @see client/html/common/address/validate
125
		 * @see client/html/common/address/payment/optional
126
		 * @see client/html/common/address/payment/hidden
127
		 * @see client/html/common/address/salutations
128
		 * @see common/countries
129
		 * @see common/states
130
		 */
131
		$mandatory = $view->config( 'client/html/common/address/payment/mandatory', [] );
132
133
		/** client/html/common/address/payment/optional
134
		 * List of payment address input fields that are optional
135
		 *
136
		 * You can configure the list of payment address fields that
137
		 * customers can fill but don't have to before they can
138
		 * continue the checkout process. Available field keys are:
139
		 *
140
		 * * company
141
		 * * vatid
142
		 * * salutation
143
		 * * firstname
144
		 * * lastname
145
		 * * address1
146
		 * * address2
147
		 * * address3
148
		 * * postal
149
		 * * city
150
		 * * state
151
		 * * languageid
152
		 * * countryid
153
		 * * telephone
154
		 * * telefax
155
		 * * mobile
156
		 * * email
157
		 * * website
158
		 *
159
		 * Until 2015-02, the configuration option was available as
160
		 * "client/html/common/address/payment/optional" starting from 2014-03.
161
		 *
162
		 * @param array List of field keys
163
		 * @since 2015.02
164
		 * @see client/html/checkout/standard/address/payment/disable-new
165
		 * @see client/html/common/address/validate
166
		 * @see client/html/common/address/payment/mandatory
167
		 * @see client/html/common/address/payment/hidden
168
		 * @see client/html/common/address/salutations
169
		 * @see common/countries
170
		 * @see common/states
171
		 */
172
		$optional = $view->config( 'client/html/common/address/payment/optional', [] );
173
174
		/** client/html/common/address/payment/hidden
175
		 * List of payment address input fields that are optional and should be hidden
176
		 *
177
		 * You can configure the list of payment address fields that
178
		 * are hidden when a customer enters his new payment address.
179
		 * Available field keys are:
180
		 *
181
		 * * company
182
		 * * vatid
183
		 * * salutation
184
		 * * firstname
185
		 * * lastname
186
		 * * address1
187
		 * * address2
188
		 * * address3
189
		 * * postal
190
		 * * city
191
		 * * state
192
		 * * languageid
193
		 * * countryid
194
		 * * telephone
195
		 * * telefax
196
		 * * mobile
197
		 * * email
198
		 * * website
199
		 *
200
		 * Caution: Only hide fields that don't require any input
201
		 *
202
		 * @param array List of field keys
203
		 * @since 2015.02
204
		 * @see client/html/checkout/standard/address/payment/disable-new
205
		 * @see client/html/common/address/payment/mandatory
206
		 * @see client/html/common/address/payment/optional
207
		 * @see client/html/common/address/salutations
208
		 * @see common/countries
209
		 * @see common/states
210
		 */
211
		$hidden = $view->config( 'client/html/common/address/payment/hidden', [] );
212
213
		/** client/html/common/address/validate
214
		 * List of regular expressions to validate the data of the address fields
215
		 *
216
		 * To validate the address input data of the customer, an individual
217
		 * {@link http://php.net/manual/en/pcre.pattern.php Perl compatible regular expression}
218
		 * can be applied to each field. Available fields are:
219
		 *
220
		 * * company
221
		 * * vatid
222
		 * * salutation
223
		 * * firstname
224
		 * * lastname
225
		 * * address1
226
		 * * address2
227
		 * * address3
228
		 * * postal
229
		 * * city
230
		 * * state
231
		 * * languageid
232
		 * * countryid
233
		 * * telephone
234
		 * * telefax
235
		 * * mobile
236
		 * * email
237
		 * * website
238
		 *
239
		 * Some fields are validated automatically because they are not
240
		 * dependent on a country specific rule. These fields are:
241
		 *
242
		 * * salutation
243
		 * * email
244
		 * * website
245
		 *
246
		 * To validate e.g the postal/zip code, you can define a regular
247
		 * expression like this if you want to allow only digits:
248
		 *
249
		 *  client/html/common/address/validate/postal = '^[0-9]+$'
250
		 *
251
		 * Several regular expressions can be defined line this:
252
		 *
253
		 *  client/html/common/address/validate = array(
254
		 *      'postal' = '^[0-9]+$',
255
		 *      'vatid' = '^[A-Z]{2}[0-9]{8}$',
256
		 *  )
257
		 *
258
		 * Don't add any delimiting characters like slashes (/) to the beginning
259
		 * or the end of the regular expression. They will be added automatically.
260
		 * Any slashes inside the expression must be escaped by backlashes,
261
		 * i.e. "\/".
262
		 *
263
		 * Until 2015-02, the configuration option was available as
264
		 * "client/html/common/address/payment/validate" starting from 2014-09.
265
		 *
266
		 * @param array Associative list of field names and regular expressions
267
		 * @since 2014.09
268
		 * @see client/html/common/address/payment/mandatory
269
		 * @see client/html/common/address/payment/optional
270
		 */
271
272
		$allFields = array_flip( array_merge( $mandatory, $optional, $hidden ) );
273
		$invalid = $this->validateFields( $params, $allFields );
274
		$this->checkSalutation( $params, $mandatory );
275
276
		$msg = $view->translate( 'client', 'Billing address part "%1$s" is invalid' );
277
278
		foreach( $invalid as $key => $name ) {
279
			$invalid[$key] = sprintf( $msg, $name );
280
		}
281
282
		$msg = $view->translate( 'client', 'Billing address part "%1$s" is missing' );
283
284
		foreach( $mandatory as $key )
285
		{
286
			if( !isset( $params['order.address.' . $key] ) || $params['order.address.' . $key] == '' ) {
287
				$invalid[$key] = sprintf( $msg, $key );
288
			}
289
		}
290
291
		return $invalid;
292
	}
293
294
295
	/**
296
	 * Additional checks for the salutation
297
	 *
298
	 * @param array $params Associative list of address keys (order.address.*) and their values
299
	 * @param array &$mandatory List of mandatory field names
300
	 * @since 2016.05
301
	 */
302
	protected function checkSalutation( array $params, array &$mandatory )
303
	{
304
		if( isset( $params['order.address.salutation'] )
305
			&& $params['order.address.salutation'] === 'company'
306
			&& in_array( 'company', $mandatory ) === false
307
		) {
308
			$mandatory[] = 'company';
309
		}
310
	}
311
312
313
	/**
314
	 * Returns the CSS classes for the payment address fields
315
	 *
316
	 * @return array Associative list of CSS classes for the payment address fields
317
	 */
318
	protected function cssPayment() : array
319
	{
320
		$config = $this->context()->config();
321
322
		$mandatory = $config->get( 'client/html/common/address/payment/mandatory', [] );
323
		$optional = $config->get( 'client/html/common/address/payment/optional', [] );
324
		$hidden = $config->get( 'client/html/common/address/payment/hidden', [] );
325
326
		$css = [];
327
328
		foreach( $mandatory as $name ) {
329
			$css[$name][] = 'mandatory';
330
		}
331
332
		foreach( $optional as $name ) {
333
			$css[$name][] = 'optional';
334
		}
335
336
		foreach( $hidden as $name ) {
337
			$css[$name][] = 'hidden';
338
		}
339
340
		return $css;
341
	}
342
343
344
	/**
345
	 * Returns the address as string
346
	 *
347
	 * @param \Aimeos\Base\View\Iface $view The view object which generates the HTML output
348
	 * @param \Aimeos\MShop\Order\Item\Address\Iface $addr Order address item
349
	 * @return string Address as string
350
	 */
351
	protected function getAddressString( \Aimeos\Base\View\Iface $view, \Aimeos\MShop\Order\Item\Address\Iface $addr )
352
	{
353
		return preg_replace( "/\n+/m", "\n", trim( sprintf(
354
			/// Address format with company (%1$s), salutation (%2$s), title (%3$s), first name (%4$s), last name (%5$s),
355
			/// address part one (%6$s, e.g street), address part two (%7$s, e.g house number), address part three (%8$s, e.g additional information),
356
			/// postal/zip code (%9$s), city (%10$s), state (%11$s), country (%12$s), language (%13$s),
357
			/// e-mail (%14$s), phone (%15$s), facsimile/telefax (%16$s), mobile number (%17$s), web site (%18$s), vatid (%19$s)
358
			$view->translate( 'client', '%1$s
359
%2$s %3$s %4$s %5$s
360
%6$s %7$s
361
%8$s
362
%9$s %10$s
363
%11$s
364
%12$s
365
%13$s
366
%14$s
367
%15$s
368
%16$s
369
%17$s
370
%18$s
371
%19$s
372
'
373
			),
374
			$addr->getCompany(),
375
			$view->translate( 'mshop/code', (string) $addr->getSalutation() ),
376
			$addr->getTitle(),
377
			$addr->getFirstName(),
378
			$addr->getLastName(),
379
			$addr->getAddress1(),
380
			$addr->getAddress2(),
381
			$addr->getAddress3(),
382
			$addr->getPostal(),
383
			$addr->getCity(),
384
			$addr->getState(),
385
			$view->translate( 'country', (string) $addr->getCountryId() ),
386
			$view->translate( 'language', (string) $addr->getLanguageId() ),
387
			$addr->getEmail(),
388
			$addr->getTelephone(),
389
			$addr->getTelefax(),
390
			$addr->getMobile(),
391
			$addr->getWebsite(),
392
			$addr->getVatID()
393
		) ) );
394
	}
395
396
397
	/**
398
	 * Sets the new address
399
	 *
400
	 * @param \Aimeos\Base\View\Iface $view View object
401
	 * @throws \Aimeos\Client\Html\Exception If an error occurs
402
	 * @since 2016.05
403
	 */
404
	protected function setAddress( \Aimeos\Base\View\Iface $view )
405
	{
406
		$context = $this->context();
407
		$basketCtrl = \Aimeos\Controller\Frontend::create( $context, 'basket' );
408
409
410
		/** client/html/checkout/standard/address/payment/disable-new
411
		 * Disables the option to enter a new payment address for an order
412
		 *
413
		 * Besides the main payment address, customers can usually enter a new
414
		 * payment address as well. To suppress displaying the form fields for
415
		 * a payment address, you can set this configuration option to "1".
416
		 *
417
		 * Until 2015-02, the configuration option was available as
418
		 * "client/html/common/address/payment/disable-new" starting from 2014-03.
419
		 *
420
		 * @param boolean A value of "1" to disable, "0" enables the payment address form
421
		 * @since 2015.02
422
		 * @see client/html/common/address/payment/mandatory
423
		 * @see client/html/common/address/payment/optional
424
		 * @see client/html/common/address/payment/hidden
425
		 * @see client/html/common/address/salutations
426
		 */
427
		$disable = $view->config( 'client/html/checkout/standard/address/payment/disable-new', false );
428
		$type = \Aimeos\MShop\Order\Item\Address\Base::TYPE_PAYMENT;
429
430
		if( ( $option = $view->param( 'ca_paymentoption', 'null' ) ) === 'null' && $disable === false ) // new address
431
		{
432
			$params = $view->param( 'ca_payment', [] );
433
434
			if( ( $view->addressPaymentError = $this->checkFields( $params ) ) !== [] ) {
435
				throw new \Aimeos\Client\Html\Exception( sprintf( 'At least one payment address part is missing or invalid' ) );
436
			}
437
		}
438
		else // existing address
439
		{
440
			$params = $view->param( 'ca_payment_' . $option, [] );
441
442
			if( !empty( $params ) && ( $view->addressPaymentError = $this->checkFields( $params ) ) !== [] ) {
443
				throw new \Aimeos\Client\Html\Exception( sprintf( 'At least one payment address part is missing or invalid' ) );
444
			}
445
446
			$cntl = \Aimeos\Controller\Frontend::create( $context, 'customer' )->uses( [] );
447
			$params = $cntl->add( $params )->store()->get()->getPaymentAddress()->toArray();
448
		}
449
450
		$basketCtrl->addAddress( $type, $params, 0 );
451
	}
452
453
454
	/**
455
	 * Validate the address key/value pairs using regular expressions
456
	 *
457
	 * @param array $params Associative list of address keys (order.address.*) and their values
458
	 * @param array $fields List of field names to validate
459
	 * @return array List of invalid address keys
460
	 * @since 2016.05
461
	 */
462
	protected function validateFields( array $params, array $fields ) : array
463
	{
464
		$config = $this->context()->config();
465
466
		/** client/html/common/address/validate/company
467
		 * Regular expression to check the "company" address value
468
		 *
469
		 * @see client/html/common/address/validate
470
		 */
471
472
		/** client/html/common/address/validate/vatid
473
		 * Regular expression to check the "vatid" address value
474
		 *
475
		 * @see client/html/common/address/validate
476
		 */
477
478
		/** client/html/common/address/validate/salutation
479
		 * Regular expression to check the "salutation" address value
480
		 *
481
		 * @see client/html/common/address/validate
482
		 */
483
484
		/** client/html/common/address/validate/title
485
		 * Regular expression to check the "title" address value
486
		 *
487
		 * @see client/html/common/address/validate
488
		 */
489
490
		/** client/html/common/address/validate/firstname
491
		 * Regular expression to check the "firstname" address value
492
		 *
493
		 * @see client/html/common/address/validate
494
		 */
495
496
		/** client/html/common/address/validate/lastname
497
		 * Regular expression to check the "lastname" address value
498
		 *
499
		 * @see client/html/common/address/validate
500
		 */
501
502
		/** client/html/common/address/validate/address1
503
		 * Regular expression to check the "address1" address value
504
		 *
505
		 * @see client/html/common/address/validate
506
		 */
507
508
		/** client/html/common/address/validate/address2
509
		 * Regular expression to check the "address2" address value
510
		 *
511
		 * @see client/html/common/address/validate
512
		 */
513
514
		/** client/html/common/address/validate/address3
515
		 * Regular expression to check the "address3" address value
516
		 *
517
		 * @see client/html/common/address/validate
518
		 */
519
520
		/** client/html/common/address/validate/postal
521
		 * Regular expression to check the "postal" address value
522
		 *
523
		 * @see client/html/common/address/validate
524
		 */
525
526
		/** client/html/common/address/validate/city
527
		 * Regular expression to check the "city" address value
528
		 *
529
		 * @see client/html/common/address/validate
530
		 */
531
532
		/** client/html/common/address/validate/state
533
		 * Regular expression to check the "state" address value
534
		 *
535
		 * @see client/html/common/address/validate
536
		 */
537
538
		/** client/html/common/address/validate/languageid
539
		 * Regular expression to check the "languageid" address value
540
		 *
541
		 * @see client/html/common/address/validate
542
		 */
543
544
		/** client/html/common/address/validate/countryid
545
		 * Regular expression to check the "countryid" address value
546
		 *
547
		 * @see client/html/common/address/validate
548
		 */
549
550
		/** client/html/common/address/validate/telephone
551
		 * Regular expression to check the "telephone" address value
552
		 *
553
		 * @see client/html/common/address/validate
554
		 */
555
556
		/** client/html/common/address/validate/telefax
557
		 * Regular expression to check the "telefax" address value
558
		 *
559
		 * @see client/html/common/address/validate
560
		 */
561
562
		/** client/html/common/address/validate/mobile
563
		 * Regular expression to check the "mobile" address value
564
		 *
565
		 * @see client/html/common/address/validate
566
		 */
567
568
		/** client/html/common/address/validate/email
569
		 * Regular expression to check the "email" address value
570
		 *
571
		 * @see client/html/common/address/validate
572
		 */
573
574
		/** client/html/common/address/validate/website
575
		 * Regular expression to check the "website" address value
576
		 *
577
		 * @see client/html/common/address/validate
578
		 */
579
580
		$invalid = [];
581
582
		foreach( $params as $key => $value )
583
		{
584
			$name = ( $pos = strrpos( $key, '.' ) ) ? substr( $key, $pos + 1 ) : $key;
585
586
			if( isset( $fields[$name] ) )
587
			{
588
				$regex = $config->get( 'client/html/common/address/validate/' . $name );
589
590
				if( $regex && preg_match( '/' . $regex . '/', $value ) !== 1 ) {
591
					$invalid[$name] = $name;
592
				}
593
			}
594
		}
595
596
		return $invalid;
597
	}
598
599
600
	/** client/html/checkout/standard/address/payment/template-body
601
	 * Relative path to the HTML body template of the checkout standard address payment client.
602
	 *
603
	 * The template file contains the HTML code and processing instructions
604
	 * to generate the result shown in the body of the frontend. The
605
	 * configuration string is the path to the template file relative
606
	 * to the templates directory (usually in templates/client/html).
607
	 *
608
	 * You can overwrite the template file configuration in extensions and
609
	 * provide alternative templates. These alternative templates should be
610
	 * named like the default one but suffixed by
611
	 * an unique name. You may use the name of your project for this. If
612
	 * you've implemented an alternative client class as well, it
613
	 * should be suffixed by the name of the new class.
614
	 *
615
	 * @param string Relative path to the template creating code for the HTML page body
616
	 * @since 2014.03
617
	 * @see client/html/checkout/standard/address/payment/template-header
618
	 */
619
}
620