PluginProbe
Contact Forms by Cimatti / 2.1.2
Contact Forms by Cimatti v2.1.2
2.3.6 2.3.5 2.3.0 2.2.32 2.2.4 2.2.0 2.1.2 2.1.1 trunk 1.0 1.1 1.2 1.2.1 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 All 62 releases
contact-forms / PFBC / Element.php

Element.php in Contact Forms by Cimatti 2.1.2, at PFBC/Element.php

272 lines 8.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * PFBC (PHP Form Builder Class) - Third-party library
4 * @package PFBC
5 */
6
7 // phpcs:disable WordPress.Security.EscapeOutput, WordPress.NamingConventions.PrefixAllGlobals, PluginCheck.CodeAnalysis.Heredoc, WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput, WordPress.WP.AlternativeFunctions, WordPress.PHP.DevelopmentFunctions -- Third-party library
8
9 abstract class Element extends Base {
10 protected $errors = array();
11
12 protected $attributes;
13 protected $form;
14 protected $label;
15 protected $description;
16 protected $validation = array();
17 protected $preHTML;
18 protected $postHTML;
19 protected $width;
20 protected $wrapperCssClass;
21 protected $wrapperCssId;
22
23 public function __construct($label, $name, ?array $properties = null) {
24 $configuration = array(
25 "label" => $label,
26 "name" => $name
27 );
28
29 /*Merge any properties provided with an associative array containing the label
30 and name properties.*/
31 if(is_array($properties))
32 $configuration = array_merge($configuration, $properties);
33
34 $this->configure($configuration);
35 }
36
37 /*When an element is serialized and stored in the session, this method prevents any non-essential
38 information from being included.*/
39 public function __sleep() {
40 return array("attributes", "label", "validation", "errors");
41 }
42
43 /*If an element requires external stylesheets, this method is used to return an
44 array of entries that will be applied before the form is rendered.*/
45 public function getCSSFiles() {}
46
47 public function getDescription() {
48 return $this->description;
49 }
50
51 public function getErrors() {
52 return $this->errors;
53 }
54
55 /*Set errors on the element (used for accessibility when re-rendering after validation)*/
56 public function setErrors($errors) {
57 if(is_array($errors)) {
58 $this->errors = $errors;
59 }
60 }
61
62 /*Get the error container ID for this element (for aria-describedby)*/
63 public function getErrorID() {
64 $id = $this->getID();
65 if(!empty($id))
66 return $id . '-error';
67 return '';
68 }
69
70 /*Check if element has validation errors*/
71 public function hasErrors() {
72 return !empty($this->errors);
73 }
74
75 public function getID() {
76 if(!empty($this->attributes["id"]))
77 return $this->attributes["id"];
78 else
79 return "";
80 }
81
82 /*If an element requires external javascript file, this method is used to return an
83 array of entries that will be applied after the form is rendered.*/
84 public function getJSFiles() {}
85
86 public function getLabel() {
87 return $this->label;
88 }
89
90 public function getName() {
91 if(!empty($this->attributes["name"]))
92 return $this->attributes["name"];
93 else
94 return "";
95 }
96
97 public function getPostHTML() {
98 return $this->postHTML;
99 }
100
101 public function getPreHTML() {
102 return $this->preHTML;
103 }
104
105 public function getWidth() {
106 return $this->width;
107 }
108
109 public function getWrapperCssClass() {
110 return $this->wrapperCssClass;
111 }
112
113 public function getWrapperCssId() {
114 return $this->wrapperCssId;
115 }
116
117 /*This method provides a shortcut for checking if an element is required.*/
118 public function isRequired() {
119 if(!empty($this->validation)) {
120 foreach($this->validation as $validation) {
121 if($validation instanceof Validation_Required)
122 return true;
123 }
124 }
125 return false;
126 }
127
128 /*The isValid method ensures that the provided value satisfies each of the
129 element's validation rules.*/
130 public function isValid($value) {
131 $valid = true;
132 if(!empty($this->validation)) {
133 if(!empty($this->label)) {
134 $element = $this->label;
135 if(substr($element, -1) == ":")
136 $element = substr($element, 0, -1);
137 }
138 else
139 $element = $this->attributes["name"];
140
141 $this->errors = array();
142
143 foreach($this->validation as $validation) {
144 if(!$validation->isValid($value)) {
145 /*In the error message, %element% will be replaced by the element's label (or
146 name if label is not provided).*/
147 $this->errors[] = str_replace("%element%", $element, $validation->getMessage());
148 $valid = false;
149 }
150 }
151 }
152 return $valid;
153 }
154
155 /*If an element requires jQuery, this method is used to include a section of javascript
156 that will be applied within the jQuery(document).ready(function() {}); section after the
157 form has been rendered.*/
158 public function jQueryDocumentReady() {}
159
160 /*Elements that have the jQueryOptions property included (Date, Sort, Checksort, and Color)
161 can make use of this method to render out the element's appropriate jQuery options.*/
162 public function jQueryOptions() {
163 if(!empty($this->jQueryOptions)) {
164 $options = "";
165 foreach($this->jQueryOptions as $option => $value) {
166 if(!empty($options))
167 $options .= ", ";
168 $options .= $option . ': ';
169 /*When javascript needs to be applied as a jQuery option's value, no quotes are needed.*/
170 if(is_string($value) && substr($value, 0, 3) == "js:")
171 $options .= substr($value, 3);
172 else
173 $options .= var_export($value, true);
174 }
175 echo "{ ", $options, " }";
176 }
177 }
178
179 /*Apply ARIA attributes for accessibility*/
180 public function applyAriaAttributes() {
181 // Add required attribute and aria-required for required fields (W3C/EAA compliance)
182 if($this->isRequired()) {
183 if(!isset($this->attributes['required'])) {
184 $this->attributes['required'] = 'required';
185 }
186 if(!isset($this->attributes['aria-required'])) {
187 $this->attributes['aria-required'] = 'true';
188 }
189 }
190
191 // Add aria-invalid if field has errors
192 if($this->hasErrors() && !isset($this->attributes['aria-invalid'])) {
193 $this->attributes['aria-invalid'] = 'true';
194 }
195
196 // Add aria-describedby for error association
197 $errorID = $this->getErrorID();
198 if($this->hasErrors() && !empty($errorID)) {
199 if(!empty($this->attributes['aria-describedby'])) {
200 // Append to existing aria-describedby
201 if(strpos($this->attributes['aria-describedby'], $errorID) === false) {
202 $this->attributes['aria-describedby'] .= ' ' . $errorID;
203 }
204 } else {
205 $this->attributes['aria-describedby'] = $errorID;
206 }
207 }
208 }
209
210 /*Many of the included elements make use of the <input> tag for display. These include the Hidden, Textbox,
211 Password, Date, Color, Button, Email, and File element classes. The project's other element classes will
212 override this method with their own implementation.*/
213 public function render() {
214 $this->applyAriaAttributes();
215 echo '<input', $this->getAttributes(), '/>';
216 }
217
218 /*If an element requires inline stylesheet definitions, this method is used send them to the browser before
219 the form is rendered.*/
220 public function renderCSS() {}
221
222 /*If an element requires javascript to be loaded, this method is used send them to the browser after
223 the form is rendered.*/
224 public function renderJS() {}
225
226 public function setClass($class) {
227 if(!empty($this->attributes["class"]))
228 $this->attributes["class"] .= " " . $class;
229 else
230 $this->attributes["class"] = $class;
231 }
232
233 public function setForm(Form $form) {
234 $this->form = $form;
235 }
236
237 public function setID($id) {
238 $this->attributes["id"] = $id;
239 }
240
241 public function setValue($value) {
242 $this->attributes["value"] = $value;
243 }
244
245 public function setWidth($width) {
246 if(substr($width, -2) == "px")
247 $width = substr($width, 0, -2);
248 elseif(substr($width, -1) == "%")
249 $width = substr($width, 0, -1);
250 $this->width = $width;
251 }
252
253 /*This method provides a shortcut for applying the Required validation class to an element.*/
254 public function setRequired($required) {
255 if(!empty($required))
256 $this->validation[] = new Validation_Required;
257 }
258
259 /*This method applies one or more validation rules to an element. If can accept a single concrete
260 validation class or an array of entries.*/
261 public function setValidation($validation) {
262 /*If a single validation class is provided, an array is created in order to reuse the same logic.*/
263 if(!is_array($validation))
264 $validation = array($validation);
265 foreach($validation as $object) {
266 /*Ensures $object contains a existing concrete validation class.*/
267 if($object instanceof Validation)
268 $this->validation[] = $object;
269 }
270 }
271 }
272