__('Email', __FILE__), // Module Title 'version' => 102, 'summary' => __('E-Mail address in valid format', __FILE__) // Module Summary ); } /** * Construct * */ public function __construct() { $this->setAttribute('name', 'email'); parent::__construct(); $this->setAttribute('type', 'email'); $this->setAttribute('maxlength', 250); $this->setAttribute('size', 0); $this->set('confirm', 0); // when 1, two inputs will appear and both must match $this->set('confirmLabel', $this->_('Confirm')); $this->set('value2', ''); $this->set('allowIDN', 0); } /** * Render input * * @return string * */ public function ___render() { if(!$this->label || $this->label === $this->attr('name')) { $this->label = $this->_('E-Mail'); // label headline when no default specified } if($this->confirm && count($this->getErrors())) $this->val(''); $attrs = $this->getAttributes(); if((int) $this->allowIDN > 1) { // UTF-8 emails are not supported by HTML5 email input type at least in current Chrome $attrs['pattern'] = '[^@]+@[^\.]+\...+'; $attrs['type'] = 'text'; } $out = "getAttributesString($attrs) . " />"; if($this->confirm) $out .= $this->renderConfirm($attrs); return $out; } /** * Render the secondary “Confirm” email input * * @param array $attrs * @return string * */ protected function ___renderConfirm(array $attrs) { foreach(array('id', 'name') as $key) { if(isset($attrs[$key])) $attrs[$key] = '_' . $attrs[$key] . '_confirm'; } $attrs['aria-label'] = $this->confirmLabel; $attrs['placeholder'] = $this->confirmLabel; return "
getAttributesString($attrs) . " />
"; } /** * Set attribute value * * @param string $value * @return string * */ protected function setAttributeValue($value) { $value = (string) $value; if(strlen($value)) { $value = $this->sanitizeEmail($value); if(!strlen($value)) { $this->error($this->_('Please enter a valid e-mail address')); // Error message when email address is invalid } } else { $value = ''; } return $value; } /** * Process input * * @param WireInputData $input * @return $this * */ public function ___processInput(WireInputData $input) { $sanitizer = $this->wire()->sanitizer; $textTools = $sanitizer->getTextTools(); $field = $this->hasField; $fieldtype = $field ? $field->type : $this->hasFieldtype; /** @var FieldtypeEmail $fieldtype */ $page = $this->hasPage; $errors = array(); $valuePrevious = $this->val(); $name = $this->attr('name'); $idnError = false; parent::___processInput($input); $value = $this->val(); $changed = $textTools->strtolower($value) !== $textTools->strtolower($valuePrevious); if($this->confirm) { $value2 = $this->sanitizeEmail($input["_{$name}_confirm"]); if((strlen($value) || strlen($value2)) && strtolower($value) !== strtolower($value2)) { $errors[] = $this->_('The emails you entered did not match, please enter again'); } } if($changed && $value && $field && $page && $field->hasFlag(Field::flagUnique)) { $fields = $this->wire()->fields; $pageId = $fields->tableTools()->valueExists($field, $value); if($pageId && $pageId != $page->id) { $errors[] = sprintf($this->_('Email “%s” is already in use, please use a different one'), $value); } } if($changed && !$this->allowIDN && strpos($value, 'xn-') !== false) { $idnError = true; } if($changed && empty($value) && $this->allowIDN < 2 && $input->$name) { // value was made empty by sanitization, see if it is because of IDN conversion $inputValue1 = $textTools->strtolower($input->$name); // value as input $inputValue2 = $sanitizer->email($inputValue1, array('allowIDN' => 2)); // input value sanitized if($inputValue1 && $inputValue1 === $inputValue2) $idnError = true; unset($inputValue1, $inputValue2); } if($idnError) { if($this->allowIDN) { $errors[] = $this->_('Email with extended characters in the local-part of local-part@domain.com is not enabled'); } else { $errors[] = $this->_('Internationalized domain name (IDN) emails are not enabled, please use a non-IDN email'); } } if($fieldtype instanceof FieldtypeEmail) { $max = $fieldtype->getMaxEmailLength(); if(strlen($value) > $max) { $errors[] = sprintf($this->_('Email exceeded max allowed length of %d characters'), $max); } } if(count($errors)) { foreach($errors as $error) $this->error($error); $this->val($valuePrevious); } return $this; } /** * Sanitize email address * * @param string $email * @return string * */ protected function sanitizeEmail($email) { return $this->wire()->sanitizer->email($email, array( 'allowIDN' => (int) $this->allowIDN, )); } /** * Field config * * @return InputfieldWrapper * */ public function ___getConfigInputfields() { $inputfields = parent::___getConfigInputfields(); $skips = array('stripTags', 'pattern'); foreach($skips as $name) { $f = $inputfields->get($name); if($f) $inputfields->remove($f); } $f = $inputfields->InputfieldCheckbox; $f->attr('name', 'confirm'); $f->label = $this->_('Confirm email address?'); $f->description = $this->_('When checked, two email inputs will appear and the user will have to enter their email address twice to confirm it. This helps reduce the possibility of typos.'); $f->attr('value', 1); $f->collapsed = $this->confirm ? Inputfield::collapsedNo : Inputfield::collapsedYes; if($this->confirm) $f->attr('checked', 'checked'); $inputfields->add($f); if($this->hasField && $this->hasField->name === 'email') { // do not allow IDN for ProcessWire's system email field } else { $f = $inputfields->InputfieldRadios; $f->attr('name', 'allowIDN'); $f->label = $this->_('Allow internationalized domain name (IDN) emails?'); $f->description = $this->_('Please note that not all email systems support sending/receiving emails that contain IDNs and/or UTF-8 characters.') . ' ' . $this->_('Choose ASCII standard emails for broadest compatibility.'); $f->notes = $this->_('Use ASCII standard if the email address is used for any kind of authentication or login.') . ' ' . $this->_('We also recommend ASCII standard emails if you will be sending messages to the email address.'); $f->addOption(0, $this->_('Use ASCII standard emails') . ' ' . '`' . $this->_('bob@domain.com') . '` ' . '[span.detail] ' . $this->_('(recommended)') . ' [/span]' ); $f->addOption(1, $this->_('Allow IDN host/domain') . ' ' . '`' . $this->_('bob@dømain.com') . '`' ); $f->addOption(2, $this->_('Allow UTF-8 local-part and IDN host/domain') . ' ' . '`' . $this->_('bøb@dømain.com') . '`' ); $f->val($this->allowIDN); $f->collapsed = !$this->allowIDN; $inputfields->add($f); } return $inputfields; } }