├── .github ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── src ├── Field │ ├── UrlField.php │ ├── EmailField.php │ ├── TelField.php │ ├── ImageListField.php │ ├── HiddenField.php │ ├── TextareaField.php │ ├── FileField.php │ ├── CheckboxField.php │ ├── LanguageField.php │ ├── PasswordField.php │ ├── IntegerField.php │ ├── TextField.php │ ├── DatabaseConnectionField.php │ ├── TimezoneField.php │ ├── FolderListField.php │ ├── SpacerField.php │ ├── RadioField.php │ ├── FileListField.php │ ├── ListField.php │ ├── CheckboxesField.php │ └── GroupedListField.php ├── Rule │ ├── BooleanRule.php │ ├── OptionsRule.php │ ├── ColorRule.php │ ├── EqualsRule.php │ ├── EmailRule.php │ ├── TelRule.php │ └── UrlRule.php ├── Rule.php ├── FormHelper.php ├── Field.php ├── Html │ └── Select.php └── Form.php ├── composer.json └── LICENSE /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Pull Request for Issue # 2 | 3 | ### Summary of Changes 4 | 5 | ### Testing Instructions 6 | 7 | ### Documentation Changes Required 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Steps to reproduce the issue 2 | 3 | 4 | ### Expected result 5 | 6 | 7 | ### Actual result 8 | 9 | 10 | ### System information (as much as possible) 11 | 12 | 13 | ### Additional comments 14 | 15 | -------------------------------------------------------------------------------- /src/Field/UrlField.php: -------------------------------------------------------------------------------- 1 | =5.0 <5.4", 22 | "phpunit/dbunit": "~1.3", 23 | "squizlabs/php_codesniffer": "1.*" 24 | }, 25 | "suggest": { 26 | "joomla/database": "Install joomla/database if you would like to use the DatabaseConnection field type." 27 | }, 28 | "autoload": { 29 | "psr-4": { 30 | "Joomla\\Form\\": "src/" 31 | } 32 | }, 33 | "autoload-dev": { 34 | "psr-4": { 35 | "Joomla\\Form\\Tests\\": "Tests" 36 | } 37 | }, 38 | "extra": { 39 | "branch-alias": { 40 | "dev-master": "2.x-dev" 41 | } 42 | }, 43 | "prefer-stable": true 44 | } 45 | -------------------------------------------------------------------------------- /src/Field/ImageListField.php: -------------------------------------------------------------------------------- 1 | element->addAttribute('filter', $filter); 49 | 50 | // Get the field options. 51 | return parent::getOptions(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Field/HiddenField.php: -------------------------------------------------------------------------------- 1 | element['class'] ? ' class="' . (string) $this->element['class'] . '"' : ''; 41 | $disabled = ((string) $this->element['disabled'] == 'true') ? ' disabled="disabled"' : ''; 42 | 43 | // Initialize JavaScript field attributes. 44 | $onchange = $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : ''; 45 | 46 | return ''; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Field/TextareaField.php: -------------------------------------------------------------------------------- 1 | element['class'] ? ' class="' . (string) $this->element['class'] . '"' : ''; 42 | $disabled = ((string) $this->element['disabled'] == 'true') ? ' disabled="disabled"' : ''; 43 | $columns = $this->element['cols'] ? ' cols="' . (int) $this->element['cols'] . '"' : ''; 44 | $rows = $this->element['rows'] ? ' rows="' . (int) $this->element['rows'] . '"' : ''; 45 | 46 | // Initialize JavaScript field attributes. 47 | $onchange = $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : ''; 48 | 49 | return ''; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Field/FileField.php: -------------------------------------------------------------------------------- 1 | element['accept'] ? ' accept="' . (string) $this->element['accept'] . '"' : ''; 44 | $size = $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : ''; 45 | $class = $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : ''; 46 | $disabled = ((string) $this->element['disabled'] == 'true') ? ' disabled="disabled"' : ''; 47 | 48 | // Initialize JavaScript field attributes. 49 | $onchange = $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : ''; 50 | 51 | return ''; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Rule/OptionsRule.php: -------------------------------------------------------------------------------- 1 | tag for the form field object. 29 | * @param mixed $value The form field value to validate. 30 | * @param string $group The field name group control value. This acts as as an array container for the field. 31 | * For example if the field has name="foo" and the group value is set to "bar" then the 32 | * full field name would end up being "bar[foo]". 33 | * @param Registry $input An optional Registry object with the entire data set to validate against the entire form. 34 | * @param Form $form The form object for which the field is being tested. 35 | * 36 | * @return boolean True if the value is valid, false otherwise. 37 | * 38 | * @since 1.0 39 | */ 40 | public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null) 41 | { 42 | // Check each value and return true if we get a match 43 | foreach ($element->option as $option) 44 | { 45 | if ($value == (string) $option->attributes()->value) 46 | { 47 | return true; 48 | } 49 | } 50 | 51 | return false; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Field/CheckboxField.php: -------------------------------------------------------------------------------- 1 | element['class'] ? ' class="' . (string) $this->element['class'] . '"' : ''; 43 | $disabled = ((string) $this->element['disabled'] == 'true') ? ' disabled="disabled"' : ''; 44 | $value = $this->element['value'] ? (string) $this->element['value'] : '1'; 45 | 46 | if ($this->value === "") 47 | { 48 | $checked = (isset($this->element['checked'] )) ? ' checked="checked"' : ''; 49 | } 50 | else 51 | { 52 | $checked = ' checked="checked"'; 53 | } 54 | 55 | // Initialize JavaScript field attributes. 56 | $onclick = $this->element['onclick'] ? ' onclick="' . (string) $this->element['onclick'] . '"' : ''; 57 | 58 | return ''; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Field/LanguageField.php: -------------------------------------------------------------------------------- 1 | element['base_path'] ? (string) $this->element['base_path'] : JPATH_ROOT; 44 | 45 | // Merge any additional options in the XML definition. 46 | $options = array_merge( 47 | parent::getOptions(), 48 | $this->createLanguageList($this->value, $basePath) 49 | ); 50 | 51 | return $options; 52 | } 53 | 54 | /** 55 | * Builds a list of the system languages which can be used in a select option 56 | * 57 | * @param string $selected Client key for the area 58 | * @param string $basePath Base path to use 59 | * 60 | * @return array List of system languages 61 | * 62 | * @since 1.0 63 | */ 64 | protected function createLanguageList($selected = null, $basePath = JPATH_ROOT) 65 | { 66 | $list = array(); 67 | 68 | $langHelper = new LanguageHelper; 69 | $langs = $langHelper->getKnownLanguages($basePath); 70 | 71 | foreach ($langs as $lang => $metadata) 72 | { 73 | $option = array(); 74 | 75 | $option['text'] = $metadata['name']; 76 | $option['value'] = $lang; 77 | 78 | if ($selected && $lang == $selected) 79 | { 80 | $option['selected'] = 'selected="selected"'; 81 | } 82 | 83 | $list[] = (object) $option; 84 | } 85 | 86 | return $list; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Rule/ColorRule.php: -------------------------------------------------------------------------------- 1 | tag for the form field object. 29 | * @param mixed $value The form field value to validate. 30 | * @param string $group The field name group control value. This acts as as an array container for the field. 31 | * For example if the field has name="foo" and the group value is set to "bar" then the 32 | * full field name would end up being "bar[foo]". 33 | * @param Registry $input An optional Registry object with the entire data set to validate against the entire form. 34 | * @param Form $form The form object for which the field is being tested. 35 | * 36 | * @return boolean True if the value is valid, false otherwise. 37 | * 38 | * @since 1.0 39 | */ 40 | public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null) 41 | { 42 | $value = trim($value); 43 | 44 | if ($value === '') 45 | { 46 | // A color field can't be empty, we default to black. This is the same as the HTML5 spec. 47 | $value = '#000000'; 48 | 49 | return true; 50 | } 51 | 52 | if ($value[0] != '#') 53 | { 54 | return false; 55 | } 56 | 57 | // Remove the leading # if present to validate the numeric part 58 | $value = ltrim($value, '#'); 59 | 60 | // The value must be 6 or 3 characters long 61 | if (!((strlen($value) == 6 || strlen($value) == 3) && ctype_xdigit($value))) 62 | { 63 | return false; 64 | } 65 | 66 | // Prepend the # again 67 | $value = '#' . $value; 68 | 69 | return true; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Field/PasswordField.php: -------------------------------------------------------------------------------- 1 | element['size'] ? ' size="' . (int) $this->element['size'] . '"' : ''; 42 | $maxLength = $this->element['maxlength'] ? ' maxlength="' . (int) $this->element['maxlength'] . '"' : ''; 43 | $class = $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : ''; 44 | $auto = ((string) $this->element['autocomplete'] == 'off') ? ' autocomplete="off"' : ''; 45 | $readonly = ((string) $this->element['readonly'] == 'true') ? ' readonly="readonly"' : ''; 46 | $disabled = ((string) $this->element['disabled'] == 'true') ? ' disabled="disabled"' : ''; 47 | 48 | // Temporary workaround to make sure the placeholder can be set without coupling to joomla/language 49 | $placeholder = ''; 50 | 51 | if ($this->element['placeholder']) 52 | { 53 | try 54 | { 55 | $placeholder = ' placeholder="' . $this->getText()->translate((string) $this->element['placeholder']) . '"'; 56 | } 57 | catch (\RuntimeException $e) 58 | { 59 | $placeholder = ' placeholder="' . (string) $this->element['placeholder'] . '"'; 60 | } 61 | } 62 | 63 | return ''; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Field/IntegerField.php: -------------------------------------------------------------------------------- 1 | setText($this->getText()); 51 | } 52 | catch (\RuntimeException $exception) 53 | { 54 | // A Text object was not set, ignore the error and try to continue processing 55 | } 56 | 57 | // Initialize some field attributes. 58 | $first = (int) $this->element['first']; 59 | $last = (int) $this->element['last']; 60 | $step = (int) $this->element['step']; 61 | 62 | // Sanity checks. 63 | if ($step == 0) 64 | { 65 | // Step of 0 will create an endless loop. 66 | return $options; 67 | } 68 | elseif ($first < $last && $step < 0) 69 | { 70 | // A negative step will never reach the last number. 71 | return $options; 72 | } 73 | elseif ($first > $last && $step > 0) 74 | { 75 | // A position step will never reach the last number. 76 | return $options; 77 | } 78 | elseif ($step < 0) 79 | { 80 | // Build the options array backwards. 81 | for ($i = $first; $i >= $last; $i += $step) 82 | { 83 | $options[] = $select->option($i); 84 | } 85 | } 86 | else 87 | { 88 | // Build the options array. 89 | for ($i = $first; $i <= $last; $i += $step) 90 | { 91 | $options[] = $select->option($i); 92 | } 93 | } 94 | 95 | // Merge any additional options in the XML definition. 96 | $options = array_merge(parent::getOptions(), $options); 97 | 98 | return $options; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Field/TextField.php: -------------------------------------------------------------------------------- 1 | element['size'] ? ' size="' . (int) $this->element['size'] . '"' : ''; 41 | $maxLength = $this->element['maxlength'] ? ' maxlength="' . (int) $this->element['maxlength'] . '"' : ''; 42 | $class = $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : ''; 43 | $readonly = ((string) $this->element['readonly'] == 'true') ? ' readonly="readonly"' : ''; 44 | $disabled = ((string) $this->element['disabled'] == 'true') ? ' disabled="disabled"' : ''; 45 | $autofocus = ((string) $this->element['autofocus'] == 'true') ? ' autofocus' : ''; 46 | $autocomplete = $this->element['autocomplete'] ? ' autocomplete="' . (string) $this->element['autocomplete'] . '"' : ''; 47 | 48 | // Temporary workaround to make sure the placeholder can be set without coupling to joomla/language 49 | $placeholder = ''; 50 | 51 | if ($this->element['placeholder']) 52 | { 53 | try 54 | { 55 | $placeholder = ' placeholder="' . $this->getText()->translate((string) $this->element['placeholder']) . '"'; 56 | } 57 | catch (\RuntimeException $e) 58 | { 59 | $placeholder = ' placeholder="' . (string) $this->element['placeholder'] . '"'; 60 | } 61 | } 62 | 63 | // Initialize JavaScript field attributes. 64 | $onchange = $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : ''; 65 | 66 | return ''; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Rule/EqualsRule.php: -------------------------------------------------------------------------------- 1 | tag for the form field object. 31 | * @param mixed $value The form field value to validate. 32 | * @param string $group The field name group control value. This acts as as an array container for the field. 33 | * For example if the field has name="foo" and the group value is set to "bar" then the 34 | * full field name would end up being "bar[foo]". 35 | * @param Registry $input An optional Registry object with the entire data set to validate against the entire form. 36 | * @param Form $form The form object for which the field is being tested. 37 | * 38 | * @return boolean True if the value is valid, false otherwise. 39 | * 40 | * @since 1.0 41 | * @throws \InvalidArgumentException 42 | * @throws \UnexpectedValueException 43 | */ 44 | public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null) 45 | { 46 | $field = (string) $element['field']; 47 | 48 | // Check that a validation field is set. 49 | if (!$field) 50 | { 51 | throw new \UnexpectedValueException(sprintf('$field empty in %s::test', get_class($this))); 52 | } 53 | 54 | if (is_null($form)) 55 | { 56 | throw new \InvalidArgumentException(sprintf('The value for $form must not be null in %s', get_class($this))); 57 | } 58 | 59 | if (is_null($input)) 60 | { 61 | throw new \InvalidArgumentException(sprintf('The value for $input must not be null in %s', get_class($this))); 62 | } 63 | 64 | $test = $input->get($field); 65 | 66 | if (isset($group) && $group !== '') 67 | { 68 | $test = $input->get("$group.$field"); 69 | } 70 | 71 | // Test the two values against each other. 72 | return $value == $test; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Rule.php: -------------------------------------------------------------------------------- 1 | tag for the form field object. 47 | * @param mixed $value The form field value to validate. 48 | * @param string $group The field name group control value. This acts as as an array container for the field. 49 | * For example if the field has name="foo" and the group value is set to "bar" then the 50 | * full field name would end up being "bar[foo]". 51 | * @param Registry $input An optional Registry object with the entire data set to validate against the entire form. 52 | * @param Form $form The form object for which the field is being tested. 53 | * 54 | * @return boolean True if the value is valid, false otherwise. 55 | * 56 | * @since 1.0 57 | * @throws \UnexpectedValueException if rule is invalid. 58 | */ 59 | public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null) 60 | { 61 | // Check for a valid regex. 62 | if (empty($this->regex)) 63 | { 64 | throw new \UnexpectedValueException(sprintf('%s has invalid regex.', get_class($this))); 65 | } 66 | 67 | // Add unicode property support if available. 68 | if (JCOMPAT_UNICODE_PROPERTIES) 69 | { 70 | $this->modifiers = (strpos($this->modifiers, 'u') !== false) ? $this->modifiers : $this->modifiers . 'u'; 71 | } 72 | 73 | // Test the value against the regular expression. 74 | if (preg_match(chr(1) . $this->regex . chr(1) . $this->modifiers, $value)) 75 | { 76 | return true; 77 | } 78 | 79 | return false; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Field/DatabaseConnectionField.php: -------------------------------------------------------------------------------- 1 | element['supported']; 61 | 62 | if (!empty($supported)) 63 | { 64 | $supported = explode(',', $supported); 65 | 66 | foreach ($supported as $support) 67 | { 68 | if (in_array(ucfirst($support), $available)) 69 | { 70 | $options[lcfirst($support)] = $this->translateOptions ? $this->getText()->translate(ucfirst($support)) : ucfirst($support); 71 | } 72 | } 73 | } 74 | else 75 | { 76 | foreach ($available as $support) 77 | { 78 | $options[lcfirst($support)] = $this->translateOptions ? $this->getText()->translate(ucfirst($support)) : ucfirst($support); 79 | $options[lcfirst($support)] = $this->getText()->translate(ucfirst($support)); 80 | } 81 | } 82 | 83 | // This will come into play if an application is installed that requires 84 | // a database that is not available on the server. 85 | if (empty($options)) 86 | { 87 | $options[''] = $this->translateOptions ? $this->getText()->translate('JNONE') : 'None'; 88 | } 89 | 90 | return $options; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Field/TimezoneField.php: -------------------------------------------------------------------------------- 1 | setText($this->getText()); 59 | } 60 | catch (\RuntimeException $exception) 61 | { 62 | // A Text object was not set, ignore the error and try to continue processing 63 | } 64 | 65 | // Get the list of time zones from the server. 66 | $zones = \DateTimeZone::listIdentifiers(); 67 | 68 | // Build the group lists. 69 | foreach ($zones as $zone) 70 | { 71 | // Time zones not in a group we will ignore. 72 | if (strpos($zone, '/') === false) 73 | { 74 | continue; 75 | } 76 | 77 | // Get the group/locale from the timezone. 78 | list ($group, $locale) = explode('/', $zone, 2); 79 | 80 | // Only use known groups. 81 | if (in_array($group, self::$zones)) 82 | { 83 | // Initialize the group if necessary. 84 | if (!isset($groups[$group])) 85 | { 86 | $groups[$group] = array(); 87 | } 88 | 89 | // Only add options where a locale exists. 90 | if (!empty($locale)) 91 | { 92 | $groups[$group][$zone] = $select->option($zone, str_replace('_', ' ', $locale), 'value', 'text', false); 93 | } 94 | } 95 | } 96 | 97 | // Sort the group lists. 98 | ksort($groups); 99 | 100 | foreach ($groups as &$location) 101 | { 102 | sort($location); 103 | } 104 | 105 | // Merge any additional groups in the XML definition. 106 | $groups = array_merge(parent::getGroups(), $groups); 107 | 108 | return $groups; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Field/FolderListField.php: -------------------------------------------------------------------------------- 1 | setText($this->getText()); 52 | } 53 | catch (\RuntimeException $exception) 54 | { 55 | // A Text object was not set, ignore the error and try to continue processing 56 | } 57 | 58 | // Initialize some field attributes. 59 | $filter = (string) $this->element['filter']; 60 | $exclude = (string) $this->element['exclude']; 61 | $hideNone = (string) $this->element['hide_none']; 62 | $hideDefault = (string) $this->element['hide_default']; 63 | 64 | // Get the path in which to search for file options. 65 | $path = (string) $this->element['directory']; 66 | 67 | if (!is_dir($path)) 68 | { 69 | $path = JPATH_ROOT . '/' . $path; 70 | } 71 | 72 | // Prepend some default options based on field attributes. 73 | if (!$hideNone) 74 | { 75 | $text = $this->translateOptions 76 | ? $this->getText()->alt('JOPTION_DO_NOT_USE', preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)) 77 | : '- None Selected -'; 78 | 79 | $options[] = $select->option('-1', $text); 80 | } 81 | 82 | if (!$hideDefault) 83 | { 84 | $text = $this->translateOptions 85 | ? $this->getText()->alt('JOPTION_USE_DEFAULT', preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)) 86 | : '- Use Default -'; 87 | 88 | $options[] = $select->option('', $text); 89 | } 90 | 91 | // Get a list of folders in the search path with the given filter. 92 | $folders = Folder::folders($path, $filter); 93 | 94 | // Build the options list from the list of folders. 95 | if (is_array($folders)) 96 | { 97 | foreach ($folders as $folder) 98 | { 99 | // Check to see if the file is in the exclude mask. 100 | if ($exclude) 101 | { 102 | if (preg_match(chr(1) . $exclude . chr(1), $folder)) 103 | { 104 | continue; 105 | } 106 | } 107 | 108 | $options[] = $select->option($folder, $folder); 109 | } 110 | } 111 | 112 | // Merge any additional options in the XML definition. 113 | $options = array_merge(parent::getOptions(), $options); 114 | 115 | return $options; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/Field/SpacerField.php: -------------------------------------------------------------------------------- 1 | element['class'] ? (string) $this->element['class'] : ''; 55 | 56 | $html[] = ''; 57 | $html[] = ''; 58 | $html[] = ''; 59 | 60 | if ((string) $this->element['hr'] == 'true') 61 | { 62 | $html[] = '
'; 63 | } 64 | else 65 | { 66 | $label = ''; 67 | 68 | // Get the label text from the XML element, defaulting to the element name. 69 | $text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name']; 70 | $text = $this->translateLabel ? $this->getText()->translate($text) : $text; 71 | 72 | // Build the class for the label. 73 | $class = !empty($this->description) ? 'hasTip' : ''; 74 | $class = $this->required == true ? $class . ' required' : $class; 75 | 76 | // Add the opening label tag and main attributes attributes. 77 | $label .= ''; 91 | $html[] = $label; 92 | } 93 | 94 | $html[] = '
'; 95 | $html[] = ''; 96 | $html[] = '
'; 97 | 98 | return implode('', $html); 99 | } 100 | 101 | /** 102 | * Method to get the field title. 103 | * 104 | * @return string The field title. 105 | * 106 | * @since 1.0 107 | */ 108 | protected function getTitle() 109 | { 110 | return $this->getLabel(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/Rule/EmailRule.php: -------------------------------------------------------------------------------- 1 | tag for the form field object. 38 | * @param mixed $value The form field value to validate. 39 | * @param string $group The field name group control value. This acts as as an array container for the field. 40 | * For example if the field has name="foo" and the group value is set to "bar" then the 41 | * full field name would end up being "bar[foo]". 42 | * @param Registry $input An optional Registry object with the entire data set to validate against the entire form. 43 | * @param Form $form The form object for which the field is being tested. 44 | * 45 | * @return boolean True if the value is valid, false otherwise. 46 | * 47 | * @since 1.0 48 | */ 49 | public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null) 50 | { 51 | // If the field is empty and not required, the field is valid. 52 | $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required'); 53 | 54 | if (!$required && $value === '') 55 | { 56 | return true; 57 | } 58 | 59 | // If the tld attribute is present, change the regular expression to require at least 2 characters for it. 60 | $tld = ((string) $element['tld'] == 'tld' || (string) $element['tld'] == 'required'); 61 | 62 | if ($tld) 63 | { 64 | $this->regex = '^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])' 65 | . '?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$'; 66 | } 67 | 68 | // Determine if the multiple attribute is present 69 | $multiple = ((string) $element['multiple'] == 'true' || (string) $element['multiple'] == 'multiple'); 70 | 71 | if ($multiple) 72 | { 73 | $values = explode(',', $value); 74 | } 75 | 76 | if (!$multiple) 77 | { 78 | // Test the value against the regular expression. 79 | if (!parent::test($element, $value, $group, $input, $form)) 80 | { 81 | return false; 82 | } 83 | } 84 | else 85 | { 86 | foreach ($values as $value) 87 | { 88 | // Test the value against the regular expression. 89 | if (!parent::test($element, $value, $group, $input, $form)) 90 | { 91 | return false; 92 | } 93 | } 94 | } 95 | 96 | return true; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Field/RadioField.php: -------------------------------------------------------------------------------- 1 | element['class'] ? ' class="radio ' . (string) $this->element['class'] . '"' : ' class="radio"'; 45 | 46 | // Start the radio field output. 47 | $html[] = '
'; 48 | 49 | // Get the field options. 50 | $options = $this->getOptions(); 51 | 52 | // Build the radio field output. 53 | foreach ($options as $i => $option) 54 | { 55 | // Initialize some option attributes. 56 | $checked = ((string) $option->value == (string) $this->value) ? ' checked="checked"' : ''; 57 | $class = !empty($option->class) ? ' class="' . $option->class . '"' : ''; 58 | $disabled = !empty($option->disable) ? ' disabled="disabled"' : ''; 59 | 60 | // Initialize some JavaScript option attributes. 61 | $onclick = !empty($option->onclick) ? ' onclick="' . $option->onclick . '"' : ''; 62 | 63 | $html[] = ''; 65 | 66 | $html[] = ''; 67 | } 68 | 69 | // End the radio field output. 70 | $html[] = '
'; 71 | 72 | return implode($html); 73 | } 74 | 75 | /** 76 | * Method to get the field options for radio buttons. 77 | * 78 | * @return array The field option objects. 79 | * 80 | * @since 1.0 81 | */ 82 | protected function getOptions() 83 | { 84 | $options = array(); 85 | 86 | /** @var \SimpleXMLElement $option */ 87 | foreach ($this->element->children() as $option) 88 | { 89 | // Only add