1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace LeKoala\PhoneNumber; |
4
|
|
|
|
5
|
|
|
use Exception; |
6
|
|
|
use SilverStripe\Forms\FieldGroup; |
7
|
|
|
use libphonenumber\PhoneNumberFormat; |
8
|
|
|
use SilverStripe\Forms\DropdownField; |
9
|
|
|
use SilverStripe\ORM\DataObject; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* A country/phone combo field |
13
|
|
|
* You might want to use https://github.com/lekoala/silverstripe-form-elements/blob/master/src/TelInputField.php instead |
14
|
|
|
*/ |
15
|
|
|
class CountryPhoneField extends FieldGroup |
16
|
|
|
{ |
17
|
|
|
const COUNTRY_CODE_FIELD = "CountryCode"; |
18
|
|
|
const NUMBER_FIELD = 'Number'; |
19
|
|
|
/** |
20
|
|
|
* @var int |
21
|
|
|
*/ |
22
|
|
|
protected $dataformat = 0; // E164, see libphonenumber/PhoneNumberFormat |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @param string $name |
26
|
|
|
* @param string|null $title |
27
|
|
|
* @param mixed $value |
28
|
|
|
*/ |
29
|
|
|
public function __construct($name, $title = null, $value = null) |
30
|
|
|
{ |
31
|
|
|
$country = new DropdownField($name . "[" . self::COUNTRY_CODE_FIELD . "]", ""); |
32
|
|
|
$country->setSource(PhoneHelper::getCountriesList()); |
33
|
|
|
$country->setHasEmptyDefault(true); |
34
|
|
|
$country->setAttribute('style', 'max-width:166px'); // Match FieldGroup min width |
35
|
|
|
$country->setAttribute('size', 1); // fix some weird sizing issue in cms |
36
|
|
|
|
37
|
|
|
$number = new PhoneField($name . "[" . self::NUMBER_FIELD . "]", ""); |
38
|
|
|
$number->setAttribute('data-value', $value); |
39
|
|
|
// We can use a national friendly format because it's next to the country |
40
|
|
|
$number->setDisplayFormat(PhoneNumberFormat::NATIONAL); |
41
|
|
|
|
42
|
|
|
parent::__construct($title, $country, $number); |
43
|
|
|
|
44
|
|
|
$this->name = $name; |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
public function hasData() |
48
|
|
|
{ |
49
|
|
|
// Turn this into a datafield |
50
|
|
|
return true; |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @return DropdownField |
55
|
|
|
*/ |
56
|
|
|
public function getCountryField() |
57
|
|
|
{ |
58
|
|
|
return $this->fieldByName($this->name . "[" . self::COUNTRY_CODE_FIELD . "]"); |
|
|
|
|
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @return PhoneField |
63
|
|
|
*/ |
64
|
|
|
public function getPhoneField() |
65
|
|
|
{ |
66
|
|
|
return $this->fieldByName($this->name . "[" . self::NUMBER_FIELD . "]"); |
|
|
|
|
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @return int |
71
|
|
|
*/ |
72
|
|
|
public function getDataFormat() |
73
|
|
|
{ |
74
|
|
|
return $this->dataformat; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @param int $v Any of the libphonenumber/PhoneNumberFormat constant |
79
|
|
|
* @return $this |
80
|
|
|
*/ |
81
|
|
|
public function setDataFormat($v) |
82
|
|
|
{ |
83
|
|
|
$this->dataformat = $v; |
84
|
|
|
return $this; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* @param mixed $value Either the parent object, or array of source data being loaded |
89
|
|
|
* @param array<mixed>|DataObject|null $data {@see Form::loadDataFrom} |
90
|
|
|
* @return $this |
91
|
|
|
*/ |
92
|
|
|
public function setValue($value, $data = null) |
93
|
|
|
{ |
94
|
|
|
$this->fieldByName($this->name . "[" . self::NUMBER_FIELD . "]")->setAttribute('data-value', $value); |
|
|
|
|
95
|
|
|
|
96
|
|
|
// An array of value to assign to sub fields |
97
|
|
|
if (is_array($value)) { |
98
|
|
|
$countryCode = $value[self::COUNTRY_CODE_FIELD] ?? null; |
99
|
|
|
$number = $value[self::NUMBER_FIELD] ?? null; |
100
|
|
|
if ($countryCode) { |
101
|
|
|
$this->getCountryField()->setValue($countryCode); |
102
|
|
|
} |
103
|
|
|
if ($number) { |
104
|
|
|
$this->getPhoneField()->setValue($number); |
105
|
|
|
$this->getPhoneField()->setCountryCode($countryCode); |
106
|
|
|
} |
107
|
|
|
return $this; |
108
|
|
|
} |
109
|
|
|
// It's an international number |
110
|
|
|
if (strpos((string)$value, '+') === 0) { |
111
|
|
|
$util = PhoneHelper::getPhoneNumberUtil(); |
112
|
|
|
try { |
113
|
|
|
$number = $util->parse($value); |
114
|
|
|
$regionCode = $util->getRegionCodeForNumber($number); |
115
|
|
|
$this->getCountryField()->setValue($regionCode); |
116
|
|
|
$phone = $util->format($number, PhoneNumberFormat::NATIONAL); |
117
|
|
|
$this->getPhoneField()->setValue($phone); |
118
|
|
|
} catch (Exception $ex) { |
119
|
|
|
// We were unable to parse, simply set the value as is |
120
|
|
|
$this->getPhoneField()->setValue($value); |
121
|
|
|
} |
122
|
|
|
} else { |
123
|
|
|
$this->getPhoneField()->setValue($value); |
124
|
|
|
} |
125
|
|
|
return $this; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Value in E164 format (no formatting) |
130
|
|
|
* |
131
|
|
|
* @return string |
132
|
|
|
*/ |
133
|
|
|
public function dataValue() |
134
|
|
|
{ |
135
|
|
|
$countryValue = $this->getCountryField()->Value(); |
136
|
|
|
$phoneValue = $this->getPhoneField()->Value(); |
137
|
|
|
if (!$phoneValue) { |
138
|
|
|
return ''; |
139
|
|
|
} |
140
|
|
|
if (!$countryValue && strpos((string)$phoneValue, '+') !== 0) { |
141
|
|
|
return $phoneValue; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
$util = PhoneHelper::getPhoneNumberUtil(); |
145
|
|
|
|
146
|
|
|
try { |
147
|
|
|
$number = $util->parse($phoneValue, $countryValue); |
148
|
|
|
$format = $this->dataformat; |
149
|
|
|
return $util->format($number, $format); |
150
|
|
|
} catch (Exception $ex) { |
151
|
|
|
// We were unable to parse, simply return the value as is |
152
|
|
|
return $phoneValue; |
153
|
|
|
} |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Get the value of isMobile |
158
|
|
|
* @return bool |
159
|
|
|
*/ |
160
|
|
|
public function getIsMobile() |
161
|
|
|
{ |
162
|
|
|
return $this->getPhoneField()->getIsMobile(); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Set the value of isMobile |
167
|
|
|
* |
168
|
|
|
* @param bool $isMobile |
169
|
|
|
* @return $this |
170
|
|
|
*/ |
171
|
|
|
public function setIsMobile(bool $isMobile) |
172
|
|
|
{ |
173
|
|
|
$this->getPhoneField()->setIsMobile($isMobile); |
174
|
|
|
return $this; |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
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.