Test Failed
Push — master ( b9b499...9e2edc )
by Adam
12:31
created

PhoneValidator::validatePhone()   C

Complexity

Conditions 14
Paths 8

Size

Total Lines 71
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 71
rs 5.5568
c 0
b 0
f 0
cc 14
eloc 29
nc 8
nop 2

How to fix   Long Method    Complexity   

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
 * PhoneValidator.php
4
 *
5
 * @copyright      More in license.md
6
 * @license        http://www.ipublikuj.eu
7
 * @author         Adam Kadlec <[email protected]>
8
 * @package        iPublikuj:FormPhone!
9
 * @subpackage     Forms
10
 * @since          1.0.0
11
 *
12
 * @date           12.12.15
13
 */
14
15
declare(strict_types = 1);
16
17
namespace IPub\FormPhone\Forms;
18
19
use Nette;
20
use Nette\Forms;
21
22
use libphonenumber;
23
use libphonenumber\PhoneNumberUtil;
24
25
use IPub\FormPhone;
26
use IPub\FormPhone\Controls;
27
use IPub\FormPhone\Exceptions;
28
29
use IPub\Phone;
30
use Tracy\Debugger;
31
32
/**
33
 * Phone number control form field validator
34
 *
35
 * @package        iPublikuj:FormPhone!
36
 * @subpackage     Forms
37
 *
38
 * @author         Adam Kadlec <[email protected]>
39
 */
40
class PhoneValidator extends Phone\Forms\PhoneValidator
41
{
42
	/**
43
	 * Define validator calling constant
44
	 */
45
	const PHONE = 'IPub\FormPhone\Forms\PhoneValidator::validatePhone';
46
47
	/**
48
	 * @param Forms\IControl $control
49
	 * @param array|NULL $params
50
	 *
51
	 * @return bool
52
	 *
53
	 * @throws Exceptions\NoValidCountryException
54
	 */
55
	public static function validatePhone(Forms\IControl $control, $params = []) : bool
56
	{
57
		if (!$control instanceof Controls\Phone) {
58
			throw new Exceptions\InvalidArgumentException(sprintf('This validator could be used only on text field. You used it on: "%s"', get_class($control)));
59
		}
60
61
		if ($control->getValuePart(Controls\Phone::FIELD_NUMBER) === NULL || $control->getValuePart(Controls\Phone::FIELD_COUNTRY) === NULL) {
62
			return TRUE;
63
		}
64
65
		try {
66
			// Create phone entity
67
			$value = Phone\Entities\Phone::fromNumber($control->getValuePart(Controls\Phone::FIELD_NUMBER), $control->getValuePart(Controls\Phone::FIELD_COUNTRY));
68
69
		} catch (Phone\Exceptions\NoValidCountryException $ex) {
70
			return FALSE;
71
72
		} catch (Phone\Exceptions\NoValidPhoneException $ex) {
73
			return FALSE;
74
		}
75
76
		// Value have to be phone entity
77
		if ($value instanceof Phone\Entities\Phone) {
78
			$number = $value->getRawOutput();
79
80
			// Get instance of phone number util
81
			$phoneNumberUtil = PhoneNumberUtil::getInstance();
82
83
			// Get list of allowed countries from params
84
			$allowedCountries = self::determineCountries($control->getAllowedCountries());
85
86
			// Get list of allowed phone types
87
			$allowedTypes = self::determineTypes($control->getAllowedPhoneTypes());
88
89
			// Perform validation
90
			foreach ($allowedCountries as $country) {
91
				try {
92
					// For default countries or country field, the following throws NumberParseException if
93
					// not parsed correctly against the supplied country
94
					// For automatic detection: tries to discover the country code using from the number itself
95
					$phoneProto = $phoneNumberUtil->parse($number, $country);
96
97
					// For automatic detection, the number should have a country code
98
					// Check if type is allowed
99
					if (
100
						$phoneProto->hasCountryCode() &&
101
						$allowedTypes === [] ||
102
						in_array($phoneNumberUtil->getNumberType($phoneProto), $allowedTypes)
103
					) {
104
						// Automatic detection:
105
						if ($country == 'ZZ') {
106
							// Validate if the international phone number is valid for its contained country
107
							return $phoneNumberUtil->isValidNumber($phoneProto);
108
						}
109
110
						// Validate number against the specified country. Return only if success
111
						// If failure, continue loop to next specified country
112
						if ($phoneNumberUtil->isValidNumberForRegion($phoneProto, $country)) {
113
							return TRUE;
114
						}
115
					}
116
117
				} catch (libphonenumber\NumberParseException $ex) {
118
					// Proceed to default validation error
119
				}
120
			}
121
		}
122
123
		// All specified country validations have failed
124
		return FALSE;
125
	}
126
}
127