├── .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[] = '
';
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 elements.
90 | if ($option->getName() != 'option')
91 | {
92 | continue;
93 | }
94 |
95 | $text = $this->translateOptions
96 | ? $this->getText()->alt(trim((string) $option), preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname))
97 | : trim((string) $option);
98 |
99 | // Set up option elements.
100 | $tmp = new stdClass;
101 | $tmp->value = (string) $option['value'];
102 | $tmp->text = $text;
103 | $tmp->disable = ((string) $option['disabled'] == 'true');
104 | $tmp->class = (string) $option['class'];
105 | $tmp->onclick = (string) $option['onclick'];
106 |
107 | // Add the option object to the result set.
108 | $options[] = $tmp;
109 | }
110 |
111 | reset($options);
112 |
113 | return $options;
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/Field/FileListField.php:
--------------------------------------------------------------------------------
1 | setText($this->getText());
57 | }
58 | catch (\RuntimeException $exception)
59 | {
60 | // A Text object was not set, ignore the error and try to continue processing
61 | }
62 |
63 | // Initialize some field attributes.
64 | $filter = (string) $this->element['filter'];
65 | $exclude = (string) $this->element['exclude'];
66 | $stripExt = (string) $this->element['stripext'];
67 | $hideNone = (string) $this->element['hide_none'];
68 | $hideDefault = (string) $this->element['hide_default'];
69 |
70 | // Get the path in which to search for file options.
71 | $path = (string) $this->element['directory'];
72 |
73 | if (!is_dir($path))
74 | {
75 | $path = JPATH_ROOT . '/' . $path;
76 | }
77 |
78 | // Prepend some default options based on field attributes.
79 | if (!$hideNone)
80 | {
81 | $text = $this->translateOptions
82 | ? $this->getText()->alt('JOPTION_DO_NOT_USE', preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname))
83 | : '- None Selected -';
84 |
85 | $options[] = $select->option('-1', $text);
86 | }
87 |
88 | if (!$hideDefault)
89 | {
90 | $text = $this->translateOptions
91 | ? $this->getText()->alt('JOPTION_USE_DEFAULT', preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname))
92 | : '- Use Default -';
93 |
94 | $options[] = $select->option('', $text);
95 | }
96 |
97 | // Get a list of files in the search path with the given filter.
98 | $files = Folder::files($path, $filter);
99 |
100 | // Build the options list from the list of files.
101 | if (is_array($files))
102 | {
103 | foreach ($files as $file)
104 | {
105 | // Check to see if the file is in the exclude mask.
106 | if ($exclude)
107 | {
108 | if (preg_match(chr(1) . $exclude . chr(1), $file))
109 | {
110 | continue;
111 | }
112 | }
113 |
114 | // If the extension is to be stripped, do it.
115 | if ($stripExt)
116 | {
117 | $file = File::stripExt($file);
118 | }
119 |
120 | $options[] = $select->option($file, $file);
121 | }
122 | }
123 |
124 | // Merge any additional options in the XML definition.
125 | $options = array_merge(parent::getOptions(), $options);
126 |
127 | return $options;
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/src/Rule/TelRule.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 | // If the field is empty and not required, the field is valid.
43 | $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required');
44 |
45 | if (!$required && $value === '')
46 | {
47 | return true;
48 | }
49 |
50 | /*
51 | * @link https://www.nationalnanpa.com/
52 | * @link https://tools.ietf.org/html/rfc4933
53 | * @link https://www.itu.int/rec/T-REC-E.164/en
54 | *
55 | * Regex by Steve Levithan
56 | * @link http://blog.stevenlevithan.com/archives/validate-phone-number
57 | * @note that valid ITU-T and EPP must begin with +.
58 | */
59 | $regexarray = array('NANP' => '/^(?:\+?1[-. ]?)?\(?([2-9][0-8][0-9])\)?[-. ]?([2-9][0-9]{2})[-. ]?([0-9]{4})$/',
60 | 'ITU-T' => '/^\+(?:[0-9] ?){6,14}[0-9]$/', 'EPP' => '/^\+[0-9]{1,3}\.[0-9]{4,14}(?:x.+)?$/');
61 |
62 | if (isset($element['plan']))
63 | {
64 | $plan = (string) $element['plan'];
65 |
66 | if ($plan == 'northamerica' || $plan == 'us')
67 | {
68 | $plan = 'NANP';
69 | }
70 | elseif ($plan == 'International' || $plan == 'int' || $plan == 'missdn' || !$plan)
71 | {
72 | $plan = 'ITU-T';
73 | }
74 | elseif ($plan == 'IETF')
75 | {
76 | $plan = 'EPP';
77 | }
78 |
79 | $regex = $regexarray[$plan];
80 |
81 | // Test the value against the regular expression.
82 | if (preg_match($regex, $value) == false)
83 | {
84 | return false;
85 | }
86 | }
87 | else
88 | {
89 | /*
90 | * If the rule is set but no plan is selected just check that there are between
91 | * 7 and 15 digits inclusive and no illegal characters (but common number separators
92 | * are allowed).
93 | */
94 | $cleanvalue = preg_replace('/[+. \-(\)]/', '', $value);
95 | $regex = '/^[0-9]{7,15}?$/';
96 |
97 | if (preg_match($regex, $cleanvalue) == true)
98 | {
99 | return true;
100 | }
101 | else
102 | {
103 | return false;
104 | }
105 | }
106 |
107 | return true;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/Rule/UrlRule.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 | * @link http://www.w3.org/Addressing/URL/url-spec.txt
42 | * @see \Joomla\String\StringHelper
43 | */
44 | public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null)
45 | {
46 | // If the field is empty and not required, the field is valid.
47 | $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required');
48 |
49 | if (!$required && $value === '')
50 | {
51 | return true;
52 | }
53 |
54 | $urlParts = UriHelper::parse_url($value);
55 |
56 | // See http://www.w3.org/Addressing/URL/url-spec.txt
57 | // Use the full list or optionally specify a list of permitted schemes.
58 | if ($element['schemes'] == '')
59 | {
60 | $scheme = array('http', 'https', 'ftp', 'ftps', 'gopher', 'mailto', 'news', 'prospero', 'telnet', 'rlogin', 'tn3270', 'wais', 'url',
61 | 'mid', 'cid', 'nntp', 'tel', 'urn', 'ldap', 'file', 'fax', 'modem', 'git');
62 | }
63 | else
64 | {
65 | $scheme = explode(',', $element['schemes']);
66 | }
67 |
68 | /*
69 | * This rule is only for full URLs with schemes because parse_url does not parse
70 | * accurately without a scheme.
71 | * @link https://secure.php.net/manual/en/function.parse-url.php
72 | */
73 | if ($urlParts && !array_key_exists('scheme', $urlParts))
74 | {
75 | return false;
76 | }
77 |
78 | $urlScheme = (string) $urlParts['scheme'];
79 | $urlScheme = strtolower($urlScheme);
80 |
81 | if (in_array($urlScheme, $scheme) == false)
82 | {
83 | return false;
84 | }
85 |
86 | // For some schemes here must be two slashes.
87 | $scheme = array('http', 'https', 'ftp', 'ftps', 'gopher', 'wais', 'prospero', 'sftp', 'telnet', 'git');
88 |
89 | if (in_array($urlScheme, $scheme) && substr($value, strlen($urlScheme), 3) !== '://')
90 | {
91 | return false;
92 | }
93 |
94 | // The best we can do for the rest is make sure that the strings are valid UTF-8
95 | // and the port is an integer.
96 | if (array_key_exists('host', $urlParts) && !StringHelper::valid((string) $urlParts['host']))
97 | {
98 | return false;
99 | }
100 |
101 | if (array_key_exists('port', $urlParts) && !is_int((int) $urlParts['port']))
102 | {
103 | return false;
104 | }
105 |
106 | if (array_key_exists('path', $urlParts) && !StringHelper::valid((string) $urlParts['path']))
107 | {
108 | return false;
109 | }
110 |
111 | return true;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/Field/ListField.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 | $attr .= $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : '';
59 |
60 | // To avoid user's confusion, readonly="true" should imply disabled="true".
61 | if ((string) $this->element['readonly'] == 'true' || (string) $this->element['disabled'] == 'true')
62 | {
63 | $attr .= ' disabled="disabled"';
64 | }
65 |
66 | $attr .= $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : '';
67 | $attr .= $this->multiple ? ' multiple="multiple"' : '';
68 |
69 | // Initialize JavaScript field attributes.
70 | $attr .= $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : '';
71 |
72 | // Get the field options.
73 | $options = (array) $this->getOptions();
74 |
75 | // Create a read-only list (no name) with a hidden input to store the value.
76 | if ((string) $this->element['readonly'] == 'true')
77 | {
78 | $html[] = $select->genericlist($options, '', trim($attr), 'value', 'text', $this->value, $this->id);
79 | $html[] = '';
80 | }
81 | else
82 | // Create a regular list.
83 | {
84 | $html[] = $select->genericlist($options, $this->name, trim($attr), 'value', 'text', $this->value, $this->id);
85 | }
86 |
87 | return implode($html);
88 | }
89 |
90 | /**
91 | * Method to get the field options.
92 | *
93 | * @return array The field option objects.
94 | *
95 | * @since 1.0
96 | */
97 | protected function getOptions()
98 | {
99 | $options = array();
100 |
101 | $select = new HtmlSelect;
102 |
103 | // Try to inject the text object into the field
104 | try
105 | {
106 | $select->setText($this->getText());
107 | }
108 | catch (\RuntimeException $exception)
109 | {
110 | // A Text object was not set, ignore the error and try to continue processing
111 | }
112 |
113 | /** @var \SimpleXMLElement $option */
114 | foreach ($this->element->children() as $option)
115 | {
116 | // Only add elements.
117 | if ($option->getName() != 'option')
118 | {
119 | continue;
120 | }
121 |
122 | $text = $this->translateOptions
123 | ? $this->getText()->alt(trim((string) $option), preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname))
124 | : trim((string) $option);
125 |
126 | // Create a new option object based on the element.
127 | $tmp = $select->option((string) $option['value'], $text, 'value', 'text', ((string) $option['disabled'] == 'true'));
128 |
129 | // Set some option attributes.
130 | $tmp->class = (string) $option['class'];
131 |
132 | // Set some JavaScript option attributes.
133 | $tmp->onclick = (string) $option['onclick'];
134 |
135 | // Add the option object to the result set.
136 | $options[] = $tmp;
137 | }
138 |
139 | reset($options);
140 |
141 | return $options;
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/Field/CheckboxesField.php:
--------------------------------------------------------------------------------
1 | element['class'] ? ' class="checkboxes ' . (string) $this->element['class'] . '"' : ' class="checkboxes"';
51 | $checkedOptions = explode(',', (string) $this->element['checked']);
52 |
53 | // Start the checkbox field output.
54 | $html[] = '';
94 |
95 | return implode($html);
96 | }
97 |
98 | /**
99 | * Method to get the field options.
100 | *
101 | * @return array The field option objects.
102 | *
103 | * @since 1.0
104 | */
105 | protected function getOptions()
106 | {
107 | $options = array();
108 |
109 | $select = new HtmlSelect;
110 |
111 | // Try to inject the text object into the field
112 | try
113 | {
114 | $select->setText($this->getText());
115 | }
116 | catch (\RuntimeException $exception)
117 | {
118 | // A Text object was not set, ignore the error and try to continue processing
119 | }
120 |
121 | /** @var \SimpleXMLElement $option */
122 | foreach ($this->element->children() as $option)
123 | {
124 | // Only add elements.
125 | if ($option->getName() != 'option')
126 | {
127 | continue;
128 | }
129 |
130 | // Create a new option object based on the element.
131 | $tmp = $select->option(
132 | (string) $option['value'], trim((string) $option), 'value', 'text', ((string) $option['disabled'] == 'true')
133 | );
134 |
135 | // Set some option attributes.
136 | $tmp->class = (string) $option['class'];
137 |
138 | // Set some JavaScript option attributes.
139 | $tmp->onclick = (string) $option['onclick'];
140 |
141 | // Add the option object to the result set.
142 | $options[] = $tmp;
143 | }
144 |
145 | reset($options);
146 |
147 | return $options;
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/src/FormHelper.php:
--------------------------------------------------------------------------------
1 |
29 | * paths:
30 | * {ENTITY_NAME}:
31 | * - /path/1
32 | * - /path/2
33 | *
34 | *
35 | * @var array
36 | * @since 1.0
37 | *
38 | */
39 | protected static $paths;
40 |
41 | /**
42 | * Attempt to import the Field class file if it isn't already imported.
43 | *
44 | * You can use this method outside of Joomla\Form for loading a field for inheritance or composition.
45 | *
46 | * @param string $type Type of a field whose class should be loaded.
47 | *
48 | * @return mixed Class name on success or false otherwise.
49 | *
50 | * @since 1.0
51 | */
52 | public static function loadFieldClass($type)
53 | {
54 | return self::loadClass('field', $type);
55 | }
56 |
57 | /**
58 | * Attempt to import the Rule class file if it isn't already imported.
59 | *
60 | * You can use this method outside of Joomla\Form for loading a rule for inheritance or composition.
61 | *
62 | * @param string $type Type of a rule whose class should be loaded.
63 | *
64 | * @return mixed Class name on success or false otherwise.
65 | *
66 | * @since 1.0
67 | */
68 | public static function loadRuleClass($type)
69 | {
70 | return self::loadClass('rule', $type);
71 | }
72 |
73 | /**
74 | * Load a class for one of the form's entities of a particular type.
75 | *
76 | * Currently, it makes sense to use this method for the "field" and "rule" entities
77 | * (but you can support more entities in your subclass).
78 | *
79 | * @param string $entity One of the form entities (field or rule).
80 | * @param string $type Type of an entity.
81 | *
82 | * @return boolean|string Class name on success or false otherwise.
83 | *
84 | * @since 1.0
85 | */
86 | protected static function loadClass($entity, $type)
87 | {
88 | if (strpos($type, '.'))
89 | {
90 | list($prefix, $type) = explode('.', $type);
91 | }
92 | else
93 | {
94 | $prefix = 'Joomla';
95 | }
96 |
97 | $class = ucfirst($prefix) . '\\Form\\' . ucfirst($entity);
98 |
99 | // If type is complex like modal\foo, do uppercase each term
100 | if (strpos($type, '\\'))
101 | {
102 | $class .= '\\' . StringHelper::ucfirst($type, '\\');
103 | }
104 | else
105 | {
106 | $class .= '\\' . ucfirst($type);
107 | }
108 |
109 | $class .= ucfirst($entity);
110 |
111 | // Check for all if the class exists.
112 | return class_exists($class) ? $class : false;
113 | }
114 |
115 | /**
116 | * Method to add a path to the list of form include paths.
117 | *
118 | * @param mixed $new A path or array of paths to add.
119 | *
120 | * @return array The list of paths that have been added.
121 | *
122 | * @since 1.0
123 | */
124 | public static function addFormPath($new = null)
125 | {
126 | return self::addPath('form', $new);
127 | }
128 |
129 | /**
130 | * Method to add a path to the list of include paths for one of the form's entities.
131 | * Currently supported entities: field, rule and form. You are free to support your own in a subclass.
132 | *
133 | * @param string $entity Form's entity name for which paths will be added.
134 | * @param mixed $new A path or array of paths to add.
135 | *
136 | * @return array The list of paths that have been added.
137 | *
138 | * @since 1.0
139 | */
140 | protected static function addPath($entity, $new = null)
141 | {
142 | // Reference to an array with paths for current entity
143 | $paths = &self::$paths[$entity];
144 |
145 | // Add the default entity's search path if not set.
146 | if (empty($paths))
147 | {
148 | // While we support limited number of entities (form, field and rule)
149 | // we can do this simple pluralisation:
150 | $entity_plural = $entity . 's';
151 |
152 | /*
153 | * But when someday we would want to support more entities, then we should consider adding
154 | * an inflector class to "libraries/joomla/utilities" and use it here (or somebody can use a real inflector in his subclass).
155 | * See also: pluralization snippet by Paul Osman in JControllerForm's constructor.
156 | */
157 | $paths[] = __DIR__ . '/' . $entity;
158 | }
159 |
160 | // Force the new path(s) to an array.
161 | settype($new, 'array');
162 |
163 | // Add the new paths to the stack if not already there.
164 | foreach ($new as $path)
165 | {
166 | if (!in_array($path, $paths))
167 | {
168 | array_unshift($paths, trim($path));
169 | }
170 |
171 | if (!is_dir($path))
172 | {
173 | array_unshift($paths, trim($path));
174 | }
175 | }
176 |
177 | return $paths;
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/src/Field/GroupedListField.php:
--------------------------------------------------------------------------------
1 | setText($this->getText());
50 | }
51 | catch (\RuntimeException $exception)
52 | {
53 | // A Text object was not set, ignore the error and try to continue processing
54 | }
55 |
56 | /** @var \SimpleXMLElement $element */
57 | foreach ($this->element->children() as $element)
58 | {
59 | switch ($element->getName())
60 | {
61 | // The element is an
62 | case 'option':
63 | // Initialize the group if necessary.
64 | if (!isset($groups[$label]))
65 | {
66 | $groups[$label] = array();
67 | }
68 |
69 | // Create a new option object based on the element.
70 | $tmp = $select->option(
71 | ($element['value']) ? (string) $element['value'] : trim((string) $element),
72 | $this->getText()->alt(trim((string) $element), preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)), 'value', 'text',
73 | ((string) $element['disabled'] == 'true')
74 | );
75 |
76 | // Set some option attributes.
77 | $tmp->class = (string) $element['class'];
78 |
79 | // Set some JavaScript option attributes.
80 | $tmp->onclick = (string) $element['onclick'];
81 |
82 | // Add the option.
83 | $groups[$label][] = $tmp;
84 | break;
85 |
86 | // The element is a
87 | case 'group':
88 | // Get the group label.
89 | if ($groupLabel = (string) $element['label'])
90 | {
91 | $label = $this->translateLabel ? $this->getText()->translate($groupLabel) : $groupLabel;
92 | }
93 |
94 | // Initialize the group if necessary.
95 | if (!isset($groups[$label]))
96 | {
97 | $groups[$label] = array();
98 | }
99 |
100 | // Iterate through the children and build an array of options.
101 | /** @var \SimpleXMLElement $option */
102 | foreach ($element->children() as $option)
103 | {
104 | // Only add elements.
105 | if ($option->getName() != 'option')
106 | {
107 | continue;
108 | }
109 |
110 | // Create a new option object based on the element.
111 | $tmp = $select->option(
112 | ($option['value']) ? (string) $option['value'] : $this->getText()->translate(trim((string) $option)),
113 | $this->getText()->translate(trim((string) $option)), 'value', 'text', ((string) $option['disabled'] == 'true')
114 | );
115 |
116 | // Set some option attributes.
117 | $tmp->class = (string) $option['class'];
118 |
119 | // Set some JavaScript option attributes.
120 | $tmp->onclick = (string) $option['onclick'];
121 |
122 | // Add the option.
123 | $groups[$label][] = $tmp;
124 | }
125 |
126 | if ($groupLabel)
127 | {
128 | $label = count($groups);
129 | }
130 | break;
131 |
132 | // Unknown element type.
133 | default:
134 | throw new \UnexpectedValueException(
135 | sprintf('Unsupported element %1$s in %2$s', $element->getName(), __CLASS__),
136 | 500
137 | );
138 | }
139 | }
140 |
141 | reset($groups);
142 |
143 | return $groups;
144 | }
145 |
146 | /**
147 | * Method to get the field input markup fora grouped list.
148 | * Multiselect is enabled by using the multiple attribute.
149 | *
150 | * @return string The field input markup.
151 | *
152 | * @since 1.0
153 | */
154 | protected function getInput()
155 | {
156 | $html = array();
157 | $attr = '';
158 |
159 | $select = new HtmlSelect;
160 |
161 | // Try to inject the text object into the field
162 | try
163 | {
164 | $select->setText($this->getText());
165 | }
166 | catch (\RuntimeException $exception)
167 | {
168 | // A Text object was not set, ignore the error and try to continue processing
169 | }
170 |
171 | // Initialize some field attributes.
172 | $attr .= $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : '';
173 | $attr .= ((string) $this->element['disabled'] == 'true') ? ' disabled="disabled"' : '';
174 | $attr .= $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : '';
175 | $attr .= $this->multiple ? ' multiple="multiple"' : '';
176 |
177 | // Initialize JavaScript field attributes.
178 | $attr .= $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : '';
179 |
180 | // Get the field groups.
181 | $groups = (array) $this->getGroups();
182 |
183 | // Create a read-only list (no name) with a hidden input to store the value.
184 | if ((string) $this->element['readonly'] == 'true')
185 | {
186 | $html[] = $select->groupedlist(
187 | $groups,
188 | null,
189 | array(
190 | 'list.attr' => $attr, 'id' => $this->id, 'list.select' => $this->value, 'group.items' => null, 'option.key.toHtml' => false,
191 | 'option.text.toHtml' => false
192 | )
193 | );
194 | $html[] = '';
195 | }
196 | else
197 | // Create a regular list.
198 | {
199 | $html[] = $select->groupedlist(
200 | $groups,
201 | $this->name,
202 | array(
203 | 'list.attr' => $attr, 'id' => $this->id, 'list.select' => $this->value, 'group.items' => null, 'option.key.toHtml' => false,
204 | 'option.text.toHtml' => false
205 | )
206 | );
207 | }
208 |
209 | return implode($html);
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/src/Field.php:
--------------------------------------------------------------------------------
1 | XML element that describes the form field.
32 | *
33 | * @var SimpleXMLElement
34 | * @since 1.0
35 | */
36 | protected $element;
37 |
38 | /**
39 | * The Form object of the form attached to the form field.
40 | *
41 | * @var Form
42 | * @since 1.0
43 | */
44 | protected $form;
45 |
46 | /**
47 | * The form control prefix for field names from the Form object attached to the form field.
48 | *
49 | * @var string
50 | * @since 1.0
51 | */
52 | protected $formControl;
53 |
54 | /**
55 | * The hidden state for the form field.
56 | *
57 | * @var boolean
58 | * @since 1.0
59 | */
60 | protected $hidden = false;
61 |
62 | /**
63 | * True to translate the field label string.
64 | *
65 | * @var boolean
66 | * @since 1.0
67 | */
68 | protected $translateLabel = true;
69 |
70 | /**
71 | * True to translate the field description string.
72 | *
73 | * @var boolean
74 | * @since 1.0
75 | */
76 | protected $translateDescription = true;
77 |
78 | /**
79 | * True to translate the field's options.
80 | *
81 | * @var boolean
82 | * @since __DEPLOY_VERSION__
83 | */
84 | protected $translateOptions = true;
85 |
86 | /**
87 | * The document id for the form field.
88 | *
89 | * @var string
90 | * @since 1.0
91 | */
92 | protected $id;
93 |
94 | /**
95 | * The input for the form field.
96 | *
97 | * @var string
98 | * @since 1.0
99 | */
100 | protected $input;
101 |
102 | /**
103 | * The label for the form field.
104 | *
105 | * @var string
106 | * @since 1.0
107 | */
108 | protected $label;
109 |
110 | /**
111 | * The multiple state for the form field.
112 | *
113 | * If true then multiple values are allowed for the field. Most often used for list field types.
114 | *
115 | * @var boolean
116 | * @since 1.0
117 | */
118 | protected $multiple = false;
119 |
120 | /**
121 | * The name of the form field.
122 | *
123 | * @var string
124 | * @since 1.0
125 | */
126 | protected $name;
127 |
128 | /**
129 | * The name of the field.
130 | *
131 | * @var string
132 | * @since 1.0
133 | */
134 | protected $fieldname;
135 |
136 | /**
137 | * The group of the field.
138 | *
139 | * @var string
140 | * @since 1.0
141 | */
142 | protected $group;
143 |
144 | /**
145 | * The required state for the form field.
146 | *
147 | * If true then there must be a value for the field to be considered valid.
148 | *
149 | * @var boolean
150 | * @since 1.0
151 | */
152 | protected $required = false;
153 |
154 | /**
155 | * The disabled state for the form field.
156 | *
157 | * If true then there must not be a possibility to change the pre-selected value, and the value must not be submitted by the browser.
158 | *
159 | * @var boolean
160 | * @since 1.0
161 | */
162 | protected $disabled = false;
163 |
164 | /**
165 | * The readonly state for the form field.
166 | *
167 | * If true then there must not be a possibility to change the pre-selected value, and the value must submitted by the browser.
168 | *
169 | * @var boolean
170 | * @since 1.0
171 | */
172 | protected $readonly = false;
173 |
174 | /**
175 | * The form field type.
176 | *
177 | * @var string
178 | * @since 1.0
179 | */
180 | protected $type;
181 |
182 | /**
183 | * The validation method for the form field.
184 | *
185 | * This value will determine which method is used to validate the value for a field.
186 | *
187 | * @var string
188 | * @since 1.0
189 | */
190 | protected $validate;
191 |
192 | /**
193 | * The value of the form field.
194 | *
195 | * @var mixed
196 | * @since 1.0
197 | */
198 | protected $value;
199 |
200 | /**
201 | * The label's CSS class of the form field
202 | *
203 | * @var mixed
204 | * @since 1.0
205 | */
206 | protected $labelClass;
207 |
208 | /**
209 | * Container for the Text object
210 | *
211 | * @var Text
212 | * @since __DEPLOY_VERSION__
213 | */
214 | private $text;
215 |
216 | /**
217 | * The count value for generated name field
218 | *
219 | * @var integer
220 | * @since 1.0
221 | */
222 | protected static $count = 0;
223 |
224 | /**
225 | * The string used for generated fields names
226 | *
227 | * @var string
228 | * @since 1.0
229 | */
230 | protected static $generated_fieldname = '__field';
231 |
232 | /**
233 | * Method to instantiate the form field object.
234 | *
235 | * @param Form $form The form to attach to the form field object.
236 | *
237 | * @since 1.0
238 | */
239 | public function __construct(Form $form = null)
240 | {
241 | // If there is a form passed into the constructor set the form and form control properties.
242 | if ($form instanceof Form)
243 | {
244 | $this->form = $form;
245 | $this->formControl = $form->getFormControl();
246 | }
247 |
248 | // Detect the field type if not set
249 | if (!isset($this->type))
250 | {
251 | $parts = explode('\\', get_called_class());
252 |
253 | if ($parts[0] != 'J')
254 | {
255 | $this->type = ucfirst($parts[0]);
256 | }
257 | else
258 | {
259 | $this->type = '';
260 | }
261 |
262 | for ($i = array_search('Field', $parts); 0 < $i && $i < count($parts); $i++)
263 | {
264 | $this->type .= '\\' . ucfirst($parts[$i]);
265 | }
266 | }
267 | }
268 |
269 | /**
270 | * Method to get certain otherwise inaccessible properties from the form field object.
271 | *
272 | * @param string $name The property name for which to the the value.
273 | *
274 | * @return mixed The property value or null.
275 | *
276 | * @since 1.0
277 | */
278 | public function __get($name)
279 | {
280 | switch ($name)
281 | {
282 | case 'description':
283 | case 'formControl':
284 | case 'hidden':
285 | case 'id':
286 | case 'multiple':
287 | case 'name':
288 | case 'required':
289 | case 'disabled':
290 | case 'readonly':
291 | case 'type':
292 | case 'validate':
293 | case 'value':
294 | case 'labelClass':
295 | case 'fieldname':
296 | case 'group':
297 | return $this->$name;
298 |
299 | case 'input':
300 | // If the input hasn't yet been generated, generate it.
301 | if (empty($this->input))
302 | {
303 | $this->input = $this->getInput();
304 | }
305 |
306 | return $this->input;
307 |
308 | case 'label':
309 | // If the label hasn't yet been generated, generate it.
310 | if (empty($this->label))
311 | {
312 | $this->label = $this->getLabel();
313 | }
314 |
315 | return $this->label;
316 |
317 | case 'title':
318 | return $this->getTitle();
319 | }
320 |
321 | return null;
322 | }
323 |
324 | /**
325 | * Method to checks whether the value of certain inaccessible properties has been set or is it null.
326 | *
327 | * @param string $name The property name.
328 | *
329 | * @return boolean True if the value is set, false otherwise.
330 | *
331 | * @since __DEPLOY_VERSION__
332 | */
333 | public function __isset($name)
334 | {
335 | // These properties aren't directly accessible, so always return true
336 | if ($name == 'input' || $name == 'label')
337 | {
338 | return true;
339 | }
340 |
341 | // Check if a property has an assigned value
342 | if ($this->$name !== null)
343 | {
344 | return true;
345 | }
346 |
347 | return false;
348 | }
349 |
350 | /**
351 | * Method to attach a Form object to the field.
352 | *
353 | * @param Form $form The Form object to attach to the form field.
354 | *
355 | * @return Field The form field object so that the method can be used in a chain.
356 | *
357 | * @since 1.0
358 | */
359 | public function setForm(Form $form)
360 | {
361 | $this->form = $form;
362 | $this->formControl = $form->getFormControl();
363 |
364 | return $this;
365 | }
366 |
367 | /**
368 | * Method to attach a Form object to the field.
369 | *
370 | * @param SimpleXMLElement $element The SimpleXMLElement object representing the tag for the form field object.
371 | * @param mixed $value The form field value to validate.
372 | * @param string $group The field name group control value. This acts as as an array container for the field.
373 | * For example if the field has name="foo" and the group value is set to "bar" then the
374 | * full field name would end up being "bar[foo]".
375 | *
376 | * @return boolean True on success.
377 | *
378 | * @since 1.0
379 | */
380 | public function setup(SimpleXMLElement $element, $value, $group = null)
381 | {
382 | // Make sure there is a valid FormField XML element.
383 | if ((string) $element->getName() != 'field')
384 | {
385 | return false;
386 | }
387 |
388 | // Reset the input and label values.
389 | $this->input = null;
390 | $this->label = null;
391 |
392 | // Set the XML element object.
393 | $this->element = $element;
394 |
395 | // Get some important attributes from the form field element.
396 | $class = (string) $element['class'];
397 | $id = (string) $element['id'];
398 | $multiple = (string) $element['multiple'];
399 | $name = (string) $element['name'];
400 | $required = (string) $element['required'];
401 | $disabled = (string) $element['disabled'];
402 | $readonly = (string) $element['readonly'];
403 |
404 | // Set the required, disabled and validation options.
405 | $this->required = $required == 'true';
406 | $this->disabled = $disabled == 'true';
407 | $this->readonly = $readonly == 'true';
408 | $this->validate = (string) $element['validate'];
409 |
410 | // Set the multiple values option.
411 | $this->multiple = ($multiple == 'true' || $multiple == 'multiple');
412 |
413 | // Allow for field classes to force the multiple values option.
414 | if (isset($this->forceMultiple))
415 | {
416 | $this->multiple = (bool) $this->forceMultiple;
417 | }
418 |
419 | // Set the field description text.
420 | $this->description = (string) $element['description'];
421 |
422 | // Set the visibility.
423 | $this->hidden = ((string) $element['type'] == 'hidden' || (string) $element['hidden'] == 'true');
424 |
425 | // Determine whether to translate the field label, description, and options.
426 | $this->translateLabel = !(string) $this->element['translate_label'] == 'false';
427 | $this->translateDescription = !(string) $this->element['translate_description'] == 'false';
428 | $this->translateOptions = !(string) $this->element['translate_options'] == 'false';
429 |
430 | // Set the group of the field.
431 | $this->group = $group;
432 |
433 | // Set the field name and id.
434 | $this->fieldname = $this->getFieldName($name);
435 | $this->name = $this->getName($this->fieldname);
436 | $this->id = $this->getId($id, $this->fieldname);
437 |
438 | // Set the field default value.
439 | $this->value = $value;
440 |
441 | // Set the CSS class of field label
442 | $this->labelClass = (string) $element['labelclass'];
443 |
444 | return true;
445 | }
446 |
447 | /**
448 | * Method to get the id used for the field input tag.
449 | *
450 | * @param string $fieldId The field element id.
451 | * @param string $fieldName The field element name.
452 | *
453 | * @return string The id to be used for the field input tag.
454 | *
455 | * @since 1.0
456 | */
457 | protected function getId($fieldId, $fieldName)
458 | {
459 | $id = '';
460 |
461 | // If there is a form control set for the attached form add it first.
462 | if ($this->formControl)
463 | {
464 | $id .= $this->formControl;
465 | }
466 |
467 | // If the field is in a group add the group control to the field id.
468 | if ($this->group)
469 | {
470 | // If we already have an id segment add the group control as another level.
471 | if ($id)
472 | {
473 | $id .= '_' . str_replace('.', '_', $this->group);
474 | }
475 | else
476 | {
477 | $id .= str_replace('.', '_', $this->group);
478 | }
479 | }
480 |
481 | // If we already have an id segment add the field id/name as another level.
482 | if ($id)
483 | {
484 | $id .= '_' . ($fieldId ? $fieldId : $fieldName);
485 | }
486 | else
487 | {
488 | $id .= ($fieldId ? $fieldId : $fieldName);
489 | }
490 |
491 | // Clean up any invalid characters.
492 | $id = preg_replace('#\W#', '_', $id);
493 |
494 | return $id;
495 | }
496 |
497 | /**
498 | * Method to get the field input markup.
499 | *
500 | * @return string The field input markup.
501 | *
502 | * @since 1.0
503 | */
504 | abstract protected function getInput();
505 |
506 | /**
507 | * Retrieves the Text object
508 | *
509 | * @return Text
510 | *
511 | * @since __DEPLOY_VERSION__
512 | * @throws \RuntimeException
513 | */
514 | public function getText()
515 | {
516 | if (!($this->text instanceof Text))
517 | {
518 | throw new \RuntimeException('A Joomla\\Language\\Text object is not set.');
519 | }
520 |
521 | return $this->text;
522 | }
523 |
524 | /**
525 | * Method to get the field title.
526 | *
527 | * @return string The field title.
528 | *
529 | * @since 1.0
530 | */
531 | protected function getTitle()
532 | {
533 | $title = '';
534 |
535 | if ($this->hidden)
536 | {
537 | return $title;
538 | }
539 |
540 | // Get the label text from the XML element, defaulting to the element name.
541 | $title = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
542 | $title = $this->translateLabel ? $this->getText()->translate($title) : $title;
543 |
544 | return $title;
545 | }
546 |
547 | /**
548 | * Method to get the field label markup.
549 | *
550 | * @return string The field label markup.
551 | *
552 | * @since 1.0
553 | */
554 | protected function getLabel()
555 | {
556 | $label = '';
557 |
558 | if ($this->hidden)
559 | {
560 | return $label;
561 | }
562 |
563 | // Get the label text from the XML element, defaulting to the element name.
564 | $text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
565 | $text = $this->translateLabel ? $this->getText()->translate($text) : $text;
566 |
567 | // Build the class for the label.
568 | $class = !empty($this->description) ? 'hasTip' : '';
569 | $class = $this->required == true ? $class . ' required' : $class;
570 | $class = !empty($this->labelClass) ? $class . ' ' . $this->labelClass : $class;
571 |
572 | // Add the opening label tag and main attributes attributes.
573 | $label .= '';
587 |
588 | return $label;
589 | }
590 |
591 | /**
592 | * Method to get the name used for the field input tag.
593 | *
594 | * @param string $fieldName The field element name.
595 | *
596 | * @return string The name to be used for the field input tag.
597 | *
598 | * @since 1.0
599 | */
600 | protected function getName($fieldName)
601 | {
602 | $name = '';
603 |
604 | // If there is a form control set for the attached form add it first.
605 | if ($this->formControl)
606 | {
607 | $name .= $this->formControl;
608 | }
609 |
610 | // If the field is in a group add the group control to the field name.
611 | if ($this->group)
612 | {
613 | // If we already have a name segment add the group control as another level.
614 | $groups = explode('.', $this->group);
615 |
616 | if ($name)
617 | {
618 | foreach ($groups as $group)
619 | {
620 | $name .= '[' . $group . ']';
621 | }
622 | }
623 | else
624 | {
625 | $name .= array_shift($groups);
626 |
627 | foreach ($groups as $group)
628 | {
629 | $name .= '[' . $group . ']';
630 | }
631 | }
632 | }
633 |
634 | // If we already have a name segment add the field name as another level.
635 | if ($name)
636 | {
637 | $name .= '[' . $fieldName . ']';
638 | }
639 | else
640 | {
641 | $name .= $fieldName;
642 | }
643 |
644 | // If the field should support multiple values add the final array segment.
645 | if ($this->multiple)
646 | {
647 | $name .= '[]';
648 | }
649 |
650 | return $name;
651 | }
652 |
653 | /**
654 | * Method to get the field name used.
655 | *
656 | * @param string $fieldName The field element name.
657 | *
658 | * @return string The field name
659 | *
660 | * @since 1.0
661 | */
662 | protected function getFieldName($fieldName)
663 | {
664 | if ($fieldName)
665 | {
666 | return $fieldName;
667 | }
668 | else
669 | {
670 | self::$count = self::$count + 1;
671 |
672 | return self::$generated_fieldname . self::$count;
673 | }
674 | }
675 |
676 | /**
677 | * Sets the Text object
678 | *
679 | * @param Text $text The Text object to store
680 | *
681 | * @return Field Instance of this class.
682 | *
683 | * @since __DEPLOY_VERSION__
684 | */
685 | public function setText(Text $text)
686 | {
687 | $this->text = $text;
688 |
689 | return $this;
690 | }
691 | }
692 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Library General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 |
294 | Copyright (C)
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License
307 | along with this program; if not, write to the Free Software
308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
309 |
310 |
311 | Also add information on how to contact you by electronic and paper mail.
312 |
313 | If the program is interactive, make it output a short notice like this
314 | when it starts in an interactive mode:
315 |
316 | Gnomovision version 69, Copyright (C) year name of author
317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318 | This is free software, and you are welcome to redistribute it
319 | under certain conditions; type `show c' for details.
320 |
321 | The hypothetical commands `show w' and `show c' should show the appropriate
322 | parts of the General Public License. Of course, the commands you use may
323 | be called something other than `show w' and `show c'; they could even be
324 | mouse-clicks or menu items--whatever suits your program.
325 |
326 | You should also get your employer (if you work as a programmer) or your
327 | school, if any, to sign a "copyright disclaimer" for the program, if
328 | necessary. Here is a sample; alter the names:
329 |
330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
332 |
333 | , 1 April 1989
334 | Ty Coon, President of Vice
335 |
336 | This General Public License does not permit incorporating your program into
337 | proprietary programs. If your program is a subroutine library, you may
338 | consider it more useful to permit linking proprietary applications with the
339 | library. If this is what you want to do, use the GNU Library General
340 | Public License instead of this License.
341 |
--------------------------------------------------------------------------------
/src/Html/Select.php:
--------------------------------------------------------------------------------
1 | 0, 'format.eol' => "\n", 'format.indent' => "\t");
35 |
36 | /**
37 | * Default values for options. Organized by option group.
38 | *
39 | * @var array
40 | * @since 1.0
41 | */
42 | protected $optionDefaults = array(
43 | 'option' => array(
44 | 'option.attr' => null, 'option.disable' => 'disable', 'option.id' => null, 'option.key' => 'value',
45 | 'option.key.toHtml' => true, 'option.label' => null, 'option.label.toHtml' => true, 'option.text' => 'text',
46 | 'option.text.toHtml' => true
47 | )
48 | );
49 |
50 | /**
51 | * Container for the Text object
52 | *
53 | * @var Text
54 | * @since __DEPLOY_VERSION__
55 | */
56 | private $text;
57 |
58 | /**
59 | * Generates a yes/no radio list.
60 | *
61 | * @param string $name The value of the HTML name attribute
62 | * @param array $attribs Additional HTML attributes for the