silverstripe-framework/Forms/PhoneNumberField.php

261 lines
5.9 KiB
PHP
Raw Normal View History

<?php
namespace SilverStripe\Forms;
use SilverStripe\ORM\DataObjectInterface;
/**
* Field for displaying phone numbers. It separates the number, the area code and optionally the country code
* and extension.
*/
class PhoneNumberField extends FieldGroup {
2014-08-15 08:53:05 +02:00
/**
* Default area code
*
* @var string
*/
protected $areaCode;
/**
* Default country code
* @var string
*/
protected $countryCode;
/**
* Default extension
*
* @var string
*/
protected $ext;
2014-08-15 08:53:05 +02:00
/**
* @return NumericField
*/
public function getCountryField() {
return $this->getChildField('Country');
}
2014-08-15 08:53:05 +02:00
/**
* @return NumericField
*/
public function getAreaField() {
return $this->getChildField('Area');
}
2014-08-15 08:53:05 +02:00
/**
* @return NumericField
*/
public function getNumberField() {
return $this->getChildField('Number');
}
2014-08-15 08:53:05 +02:00
2015-06-20 12:11:08 +02:00
/**
* @return NumericField
2015-06-20 12:11:08 +02:00
*/
public function getExtensionField() {
/** @skipUpgrade */
return $this->getChildField('Extension');
}
protected function getChildField($name) {
$endsWith = "[{$name}]";
foreach($this->getChildren() as $child) {
/** @var Formfield $child */
if(substr($child->getName(), 0 - strlen($endsWith)) === $endsWith) {
return $child;
}
}
return null;
}
2014-08-15 08:53:05 +02:00
public function __construct(
$name, $title = null, $value = '', $extension = null, $areaCode = null, $countryCode = null
) {
$this->areaCode = $areaCode;
$this->ext = $extension;
$this->countryCode = $countryCode;
// Build fields
$fields = new FieldList();
if($this->countryCode !== null) {
$countryField = NumericField::create($name.'[Country]', false, $countryCode, 4)
->addExtraClass('phonenumber-field__country');
$fields->push($countryField);
}
2014-08-15 08:53:05 +02:00
if($this->areaCode !== null) {
$areaField = NumericField::create($name.'[Area]', false, $areaCode, 4)
->addExtraClass('phonenumber-field__area');
$fields->push($areaField);
}
$numberField = NumericField::create($name.'[Number]', false, null, 10)
->addExtraClass('phonenumber-field__number');
$fields->push($numberField);
2014-08-15 08:53:05 +02:00
if($this->ext !== null) {
$extensionField = NumericField::create( $name.'[Extension]', false, $extension, 6)
->addExtraClass('phonenumber-field__extension');
$fields->push($extensionField);
}
parent::__construct($title, $fields);
$this->setName($name);
if (isset($value)) {
$this->setValue($value);
}
}
public function setName($name) {
parent::setName($name);
foreach($this->getChildren() as $child) {
/** @var FormField $child */
$thisName = $child->getName();
$thisName = preg_replace('/^.*(\[\\w+\\])$/', $name . '\\1', $thisName);
$child->setName($thisName);
}
}
public function hasData() {
return true;
}
/**
* @param array $properties
* @return string
*/
public function Field($properties = array()) {
foreach($this->getChildren() as $field) {
/** @var FormField $field */
$field->setDisabled($this->isDisabled());
$field->setReadonly($this->IsReadonly());
$field->setForm($this->getForm());
}
return parent::Field($properties);
}
2014-08-15 08:53:05 +02:00
public function setValue( $value ) {
$this->value = self::joinPhoneNumber( $value );
$parts = $this->parseValue();
if($countryField = $this->getCountryField()) {
$countryField->setValue($parts['Country']);
}
if($areaField = $this->getAreaField()) {
$areaField->setValue($parts['Area']);
}
$this->getNumberField()->setValue($parts['Number']);
if ($extensionField = $this->getExtensionField()) {
/** @skipUpgrade */
$extensionField->setValue($parts['Extension']);
}
return $this;
}
2014-08-15 08:53:05 +02:00
/**
* Join phone number into a string
*
* @param array|string $value Input
* @return string
*/
public static function joinPhoneNumber( $value ) {
if( is_array( $value ) ) {
$completeNumber = '';
if( !empty($value['Country'])) {
$completeNumber .= '+' . $value['Country'];
}
if( !empty($value['Area'])) {
$completeNumber .= '(' . $value['Area'] . ')';
}
2014-08-15 08:53:05 +02:00
$completeNumber .= $value['Number'];
2014-08-15 08:53:05 +02:00
/** @skipUpgrade */
if( !empty($value['Extension']) ) {
$completeNumber .= '#' . $value['Extension'];
}
2014-08-15 08:53:05 +02:00
return $completeNumber;
} else {
return $value;
}
}
2014-08-15 08:53:05 +02:00
/**
* Returns array with parsed phone format
*
* @return array Array with Country, Area, Number, and Extension keys (in order)
*/
protected function parseValue() {
if (is_array($this->value)) {
return $this->value;
}
// Parse value in form "+ countrycode (areacode) phone # extension"
$valid = preg_match(
'/^(?:(?:\+(?<Country>\d+))?\s*\((?<Area>\d+)\))?\s*(?<Number>[0-9A-Za-z]*)\s*(?:[#]\s*(?<Extension>\d+))?$/',
$this->value,
$parts
);
if(!$valid) {
$parts = [];
}
/** @skipUpgrade */
return array(
'Country' => isset($parts['Country']) ? $parts['Country'] : '',
'Area' => isset($parts['Area']) ? $parts['Area'] : '',
'Number' => isset($parts['Number']) ? $parts['Number'] : '',
'Extension' => isset($parts['Extension']) ? $parts['Extension'] : '',
);
}
2014-08-15 08:53:05 +02:00
public function saveInto(DataObjectInterface $record) {
$completeNumber = static::joinPhoneNumber($this->parseValue());
$record->setCastedField($this->getName(), $completeNumber);
}
2014-08-15 08:53:05 +02:00
/**
* Validate this field
*
* @todo Very basic validation at the moment
*
* @param Validator $validator
* @return bool
*/
public function validate($validator){
$valid = preg_match(
'/^[0-9\+\-\(\)\s\#]*$/',
$this->joinPhoneNumber($this->value)
);
2014-08-15 08:53:05 +02:00
if(!$valid){
$validator->validationError(
2014-08-15 08:53:05 +02:00
$this->name,
_t('PhoneNumberField.VALIDATION', "Please enter a valid phone number"),
"validation"
);
return false;
}
2014-08-15 08:53:05 +02:00
return true;
}
public function performReadonlyTransformation()
{
// Just setReadonly without casting to NumericField_Readonly
$clone = clone $this;
$clone->setReadonly(true);
return $clone;
}
public function performDisabledTransformation()
{
// Just setDisabled without casting to NumericField_Disabled
$clone = clone $this;
$clone->setDisabled(true);
return $clone;
}
}