1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
|
4
|
|
|
namespace TraderInteractive\Filter; |
5
|
|
|
|
6
|
|
|
use Throwable; |
7
|
|
|
use TraderInteractive\Exceptions\FilterException; |
8
|
|
|
|
9
|
|
|
final class PhoneFilter |
10
|
|
|
{ |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* The pattern for the separations between numbers. |
14
|
|
|
* |
15
|
|
|
* @var string |
16
|
|
|
*/ |
17
|
|
|
const SEPARATOR_PATTERN = ' *[-.]? *'; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* The pattern for the area code. |
21
|
|
|
* |
22
|
|
|
* @var string |
23
|
|
|
*/ |
24
|
|
|
const AREA_CODE_PATTERN = '(?:\(([2–9]\d\d)\)|([2-9]\d\d))?'; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* The pattern for the exchange code. Also known as the central office code. |
28
|
|
|
* |
29
|
|
|
* @var string |
30
|
|
|
*/ |
31
|
|
|
const EXCHANGE_CODE_PATTERN = '([2-9]\d\d)'; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* The pattern for the station code. Also known as the line number or subscriber number. |
35
|
|
|
* |
36
|
|
|
* @var string |
37
|
|
|
*/ |
38
|
|
|
const STATION_CODE_PATTERN = '(\d{4})'; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* The pattern for phone numbers according to the North American Numbering Plan specification. |
42
|
|
|
* |
43
|
|
|
* @var string |
44
|
|
|
*/ |
45
|
|
|
const PHONE_PATTERN = ('' |
46
|
|
|
. '/^ *' |
47
|
|
|
. self::AREA_CODE_PATTERN |
48
|
|
|
. self::SEPARATOR_PATTERN |
49
|
|
|
. self::EXCHANGE_CODE_PATTERN |
50
|
|
|
. self::SEPARATOR_PATTERN |
51
|
|
|
. self::STATION_CODE_PATTERN |
52
|
|
|
. ' *$/' |
53
|
|
|
); |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @var string |
57
|
|
|
*/ |
58
|
|
|
const ERROR_INVALID_PHONE_NUMBER = "Value '%s' is not a valid phone number."; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @var string |
62
|
|
|
*/ |
63
|
|
|
const ERROR_VALUE_CANNOT_BE_NULL = 'Value cannot be null'; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* @var string |
67
|
|
|
*/ |
68
|
|
|
const DEFAULT_FILTERED_PHONE_FORMAT = '{area}{exchange}{station}'; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @var bool |
72
|
|
|
*/ |
73
|
|
|
private $allowNull; |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* @var string |
77
|
|
|
*/ |
78
|
|
|
private $filteredPhoneFormat; |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* @param bool $allowNull Flag to allow value to be null |
82
|
|
|
* @param string $filteredPhoneFormat The format for which the filtered phone value will be returned. |
83
|
|
|
*/ |
84
|
|
|
public function __construct( |
85
|
|
|
bool $allowNull = false, |
86
|
|
|
string $filteredPhoneFormat = self::DEFAULT_FILTERED_PHONE_FORMAT |
87
|
|
|
) { |
88
|
|
|
$this->allowNull = $allowNull; |
89
|
|
|
$this->filteredPhoneFormat = $filteredPhoneFormat; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @param mixed $value The value to filter. |
94
|
|
|
* |
95
|
|
|
* @return string|null |
96
|
|
|
* |
97
|
|
|
* @throws FilterException Thrown when the value does not pass filtering. |
98
|
|
|
*/ |
99
|
|
|
public function __invoke($value) |
100
|
|
|
{ |
101
|
|
|
return self::filter($value, $this->allowNull, $this->filteredPhoneFormat); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* @param mixed $value The value to filter. |
106
|
|
|
* @param bool $allowNull Flag to allow value to be null |
107
|
|
|
* @param string $filteredPhoneFormat The format for which the filtered phone value will be returned. |
108
|
|
|
* |
109
|
|
|
* @return string|null |
110
|
|
|
* |
111
|
|
|
* @throws FilterException Thrown when the value does not pass filtering. |
112
|
|
|
*/ |
113
|
|
|
public static function filter( |
114
|
|
|
$value, |
115
|
|
|
bool $allowNull = false, |
116
|
|
|
string $filteredPhoneFormat = self::DEFAULT_FILTERED_PHONE_FORMAT |
117
|
|
|
) { |
118
|
|
|
if ($value === null) { |
119
|
|
|
return self::returnNullValue($allowNull); |
|
|
|
|
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
$value = self::getValueAsString($value); |
123
|
|
|
$matches = []; |
124
|
|
|
if (!preg_match(self::PHONE_PATTERN, $value, $matches)) { |
125
|
|
|
$message = sprintf(self::ERROR_INVALID_PHONE_NUMBER, $value); |
126
|
|
|
throw new FilterException($message); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
list($phone, $areaWithParenthesis, $area, $exchange, $station) = $matches; |
130
|
|
|
if ($areaWithParenthesis !== '') { |
131
|
|
|
$area = $areaWithParenthesis; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
$search = ['{area}', '{exchange}', '{station}']; |
135
|
|
|
$replace = [$area, $exchange, $station]; |
136
|
|
|
return str_replace($search, $replace, $filteredPhoneFormat); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
private static function returnNullValue(bool $allowNull) |
140
|
|
|
{ |
141
|
|
|
if ($allowNull === false) { |
142
|
|
|
throw new FilterException(self::ERROR_VALUE_CANNOT_BE_NULL); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
return null; |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
private static function getValueAsString($value) : string |
149
|
|
|
{ |
150
|
|
|
if (is_scalar($value)) { |
151
|
|
|
return (string)$value; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
$message = sprintf(self::ERROR_INVALID_PHONE_NUMBER, var_export($value, true)); |
155
|
|
|
throw new FilterException($message); |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.