PluginProbe ʕ •ᴥ•ʔ
Contact Form 7 / 6.1.6
Contact Form 7 v6.1.6
6.1.6 5.0.2 5.0.3 5.0.4 5.0.5 5.1 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.2 5.2.1 5.2.2 5.3 5.3.1 5.3.2 5.4 5.4.1 5.4.2 5.5 5.5.1 5.5.2 5.5.3 5.5.4 5.5.5 5.5.6 5.5.6.1 5.6 5.6.1 5.6.2 5.6.3 5.6.4 5.7 5.7.1 5.7.2 5.7.3 5.7.4 5.7.5 5.7.5.1 5.7.6 5.7.7 5.8 5.8.1 5.8.2 5.8.3 5.8.4 5.8.5 5.8.6 5.8.7 5.9 5.9.2 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 6.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.0.6 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 trunk 1.1 1.10 1.10.0.1 1.10.1 1.2 1.3 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.5 1.6 1.6.1 1.7 1.7.1 1.7.2 1.7.4 1.7.5 1.7.6 1.7.6.1 1.7.7 1.7.7.1 1.7.8 1.8 1.8.0.1 1.8.0.2 1.8.0.3 1.8.0.4 1.8.1 1.8.1.1 1.9 1.9.1 1.9.2 1.9.2.1 1.9.2.2 1.9.3 1.9.4 1.9.5 1.9.5.1 2.0 2.0-beta 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1 2.1.1 2.1.2 2.2 2.2.1 2.3 2.3.1 2.4 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 3.0 3.0-beta 3.0.1 3.0.2 3.0.2.1 3.1 3.1.1 3.1.2 3.2 3.2.1 3.3 3.3.1 3.3.2 3.3.3 3.4 3.4.1 3.4.2 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.6 3.7 3.7.1 3.7.2 3.8 3.8.1 3.9 3.9-beta 3.9.1 3.9.2 3.9.3 4.0 4.0.1 4.0.2 4.0.3 4.1 4.1-beta 4.1.1 4.1.2 4.2 4.2-beta 4.2.1 4.2.2 4.3 4.3.1 4.4 4.4.1 4.4.2 4.5 4.5.1 4.6 4.6.1 4.7 4.8 4.8.1 4.9 4.9.1 4.9.2 5.0 5.0.1
contact-form-7 / includes / form-tag.php
contact-form-7 / includes Last commit date
block-editor 1 year ago config-validator 11 months ago css 2 weeks ago js 1 year ago swv 9 months ago capabilities.php 7 years ago contact-form-functions.php 11 months ago contact-form-template.php 11 months ago contact-form.php 11 months ago controller.php 11 months ago file.php 9 months ago filesystem.php 11 months ago form-tag.php 7 months ago form-tags-manager.php 11 months ago formatting.php 11 months ago functions.php 9 months ago html-formatter.php 9 months ago integration.php 11 months ago l10n.php 11 months ago mail-tag.php 11 months ago mail.php 3 months ago pipe.php 11 months ago pocket-holder.php 3 years ago rest-api.php 11 months ago shortcodes.php 11 months ago special-mail-tags.php 9 months ago submission.php 9 months ago upgrade.php 11 months ago validation-functions.php 11 months ago validation.php 11 months ago
form-tag.php
619 lines
1 <?php
2
3 /**
4 * A form-tag.
5 *
6 * @link https://contactform7.com/tag-syntax/#form_tag
7 */
8 class WPCF7_FormTag implements ArrayAccess {
9
10 public $type;
11 public $basetype;
12 public $raw_name = '';
13 public $name = '';
14 public $options = array();
15 public $raw_values = array();
16 public $values = array();
17 public $pipes;
18 public $labels = array();
19 public $attr = '';
20 public $content = '';
21
22 public function __construct( $tag = array() ) {
23 if ( is_array( $tag ) or $tag instanceof self ) {
24 foreach ( $tag as $key => $value ) {
25 if ( property_exists( __CLASS__, $key ) ) {
26 $this->{$key} = $value;
27 }
28 }
29 }
30 }
31
32
33 /**
34 * Returns true if the type has a trailing asterisk.
35 */
36 public function is_required() {
37 return str_ends_with( $this->type, '*' );
38 }
39
40
41 /**
42 * Returns true if the form-tag has a specified option.
43 */
44 public function has_option( $option_name ) {
45 $pattern = sprintf( '/^%s(:.+)?$/i', preg_quote( $option_name, '/' ) );
46 return (bool) preg_grep( $pattern, $this->options );
47 }
48
49
50 /**
51 * Retrieves option values with the specified option name.
52 *
53 * @param string $option_name Option name.
54 * @param string $pattern Optional. A regular expression pattern or one of
55 * the keys of preset patterns. If specified, only options
56 * whose value part matches this pattern will be returned.
57 * @param bool $single Optional. If true, only the first matching option
58 * will be returned. Default false.
59 * @return string|array|bool The option value or an array of option values.
60 * False if there is no option matches the pattern.
61 */
62 public function get_option( $option_name, $pattern = '', $single = false ) {
63 $preset_patterns = array(
64 'date' => '[0-9]{4}-[0-9]{2}-[0-9]{2}',
65 'int' => '[0-9]+',
66 'signed_int' => '[-]?[0-9]+',
67 'num' => '(?:[0-9]+|(?:[0-9]+)?[.][0-9]+)',
68 'signed_num' => '[-]?(?:[0-9]+|(?:[0-9]+)?[.][0-9]+)',
69 'class' => '[-0-9a-zA-Z_]+',
70 'id' => '[-0-9a-zA-Z_]+',
71 );
72
73 if ( isset( $preset_patterns[$pattern] ) ) {
74 $pattern = $preset_patterns[$pattern];
75 }
76
77 if ( '' === $pattern ) {
78 $pattern = '.+';
79 }
80
81 $pattern = sprintf(
82 '/^%s:%s$/i',
83 preg_quote( $option_name, '/' ),
84 $pattern
85 );
86
87 if ( $single ) {
88 $matches = $this->get_first_match_option( $pattern );
89
90 if ( ! $matches ) {
91 return false;
92 }
93
94 return substr( $matches[0], strlen( $option_name ) + 1 );
95 } else {
96 $matches_a = $this->get_all_match_options( $pattern );
97
98 if ( ! $matches_a ) {
99 return false;
100 }
101
102 $results = array();
103
104 foreach ( $matches_a as $matches ) {
105 $results[] = substr( $matches[0], strlen( $option_name ) + 1 );
106 }
107
108 return $results;
109 }
110 }
111
112
113 /**
114 * Retrieves the id option value from the form-tag.
115 */
116 public function get_id_option() {
117 static $used = array();
118
119 $option = $this->get_option( 'id', 'id', true );
120
121 if (
122 ! $option or
123 str_starts_with( $option, 'wpcf7' ) or
124 in_array( $option, $used, true )
125 ) {
126 return false;
127 }
128
129 $used[] = $option;
130
131 return $option;
132 }
133
134
135 /**
136 * Retrieves the class option value from the form-tag.
137 *
138 * @param string|array $default_classes Optional. Preset classes as an array
139 * or a whitespace-separated list. Default empty string.
140 * @return string|bool A whitespace-separated list of classes.
141 * False if there is no class to return.
142 */
143 public function get_class_option( $default_classes = '' ) {
144 if ( is_string( $default_classes ) ) {
145 $default_classes = explode( ' ', $default_classes );
146 }
147
148 $options = array_merge(
149 (array) $default_classes,
150 (array) $this->get_option( 'class' )
151 );
152
153 $options = array_map( 'sanitize_html_class', $options );
154 $options = array_filter( array_unique( $options ) );
155
156 if ( empty( $options ) ) {
157 return false;
158 }
159
160 return implode( ' ', $options );
161 }
162
163
164 /**
165 * Retrieves the autocomplete option value from the form-tag.
166 *
167 * @return string|bool A whitespace-separated list of tokens.
168 * False if there is no token to return.
169 */
170 public function get_autocomplete_option() {
171 $options = (array) $this->get_option( 'autocomplete', '[-0-9a-zA-Z|]+' );
172
173 $options = array_reduce( $options, static function ( $carry, $item ) {
174 return array_merge( $carry,
175 array_map( 'strtolower', explode( '|', $item ) )
176 );
177 }, array() );
178
179 $options = array_filter( $options, static function ( $item ) {
180 return preg_match( '/^[a-z]+(?:-[0-9a-z]+)*$/', $item );
181 } );
182
183 $options = array_unique( $options );
184
185 if ( empty( $options ) ) {
186 return false;
187 } elseif ( in_array( 'off', $options, true ) ) {
188 return 'off';
189 } elseif ( in_array( 'on', $options, true ) ) {
190 return 'on';
191 } else {
192 return implode( ' ', $options );
193 }
194 }
195
196
197 /**
198 * Retrieves the size option value from the form-tag.
199 *
200 * @param string $default_value Optional default value.
201 * @return string The option value.
202 */
203 public function get_size_option( $default_value = false ) {
204 $option = $this->get_option( 'size', 'int', true );
205
206 if ( $option ) {
207 return $option;
208 }
209
210 $matches_a = $this->get_all_match_options( '%^([0-9]*)/[0-9]*$%' );
211
212 foreach ( $matches_a as $matches ) {
213 if ( isset( $matches[1] ) and '' !== $matches[1] ) {
214 return $matches[1];
215 }
216 }
217
218 return $default_value;
219 }
220
221
222 /**
223 * Retrieves the maxlength option value from the form-tag.
224 *
225 * @param string $default_value Optional default value.
226 * @return string The option value.
227 */
228 public function get_maxlength_option( $default_value = false ) {
229 $option = $this->get_option( 'maxlength', 'int', true );
230
231 if ( $option ) {
232 return $option;
233 }
234
235 $matches_a = $this->get_all_match_options(
236 '%^(?:[0-9]*x?[0-9]*)?/([0-9]+)$%'
237 );
238
239 foreach ( $matches_a as $matches ) {
240 if ( isset( $matches[1] ) and '' !== $matches[1] ) {
241 return $matches[1];
242 }
243 }
244
245 return $default_value;
246 }
247
248
249 /**
250 * Retrieves the minlength option value from the form-tag.
251 *
252 * @param string $default_value Optional default value.
253 * @return string The option value.
254 */
255 public function get_minlength_option( $default_value = false ) {
256 $option = $this->get_option( 'minlength', 'int', true );
257
258 if ( $option ) {
259 return $option;
260 } else {
261 return $default_value;
262 }
263 }
264
265
266 /**
267 * Retrieves the cols option value from the form-tag.
268 *
269 * @param string $default_value Optional default value.
270 * @return string The option value.
271 */
272 public function get_cols_option( $default_value = false ) {
273 $option = $this->get_option( 'cols', 'int', true );
274
275 if ( $option ) {
276 return $option;
277 }
278
279 $matches_a = $this->get_all_match_options(
280 '%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%'
281 );
282
283 foreach ( $matches_a as $matches ) {
284 if ( isset( $matches[1] ) and '' !== $matches[1] ) {
285 return $matches[1];
286 }
287 }
288
289 return $default_value;
290 }
291
292
293 /**
294 * Retrieves the rows option value from the form-tag.
295 *
296 * @param string $default_value Optional default value.
297 * @return string The option value.
298 */
299 public function get_rows_option( $default_value = false ) {
300 $option = $this->get_option( 'rows', 'int', true );
301
302 if ( $option ) {
303 return $option;
304 }
305
306 $matches_a = $this->get_all_match_options(
307 '%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%'
308 );
309
310 foreach ( $matches_a as $matches ) {
311 if ( isset( $matches[2] ) and '' !== $matches[2] ) {
312 return $matches[2];
313 }
314 }
315
316 return $default_value;
317 }
318
319
320 /**
321 * Retrieves a date-type option value from the form-tag.
322 *
323 * @param string $option_name A date-type option name, such as 'min' or 'max'.
324 * @return string|bool The option value in YYYY-MM-DD format. False if the
325 * option does not exist or the date value is invalid.
326 */
327 public function get_date_option( $option_name ) {
328 $option_value = $this->get_option( $option_name, '', true );
329
330 if ( empty( $option_value ) ) {
331 return false;
332 }
333
334 $date = apply_filters( 'wpcf7_form_tag_date_option',
335 null,
336 array( $option_name => $option_value )
337 );
338
339 if ( $date ) {
340 $date_pattern = '/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/';
341
342 if (
343 preg_match( $date_pattern, $date, $matches ) and
344 checkdate( $matches[2], $matches[3], $matches[1] )
345 ) {
346 return $date;
347 }
348 } else {
349 $datetime_obj = date_create_immutable(
350 preg_replace( '/[_]+/', ' ', $option_value ),
351 wp_timezone()
352 );
353
354 if ( $datetime_obj ) {
355 return $datetime_obj->format( 'Y-m-d' );
356 }
357 }
358
359 return false;
360 }
361
362
363 /**
364 * Retrieves the default option value from the form-tag.
365 *
366 * @param string|array $default_value Optional default value.
367 * @param string|array $args Optional options for the option value retrieval.
368 * @return string|array The option value. If the multiple option is enabled,
369 * an array of option values.
370 */
371 public function get_default_option( $default_value = '', $args = '' ) {
372 $args = wp_parse_args( $args, array(
373 'multiple' => false,
374 'shifted' => false,
375 ) );
376
377 $options = (array) $this->get_option( 'default' );
378 $values = array();
379
380 if ( empty( $options ) ) {
381 return $args['multiple'] ? $values : $default_value;
382 }
383
384 foreach ( $options as $opt ) {
385 $opt = sanitize_key( $opt );
386
387 if ( 'user_' === substr( $opt, 0, 5 ) and is_user_logged_in() ) {
388 $primary_props = array( 'user_login', 'user_email', 'user_url' );
389 $opt = in_array( $opt, $primary_props, true ) ? $opt : substr( $opt, 5 );
390
391 $user = wp_get_current_user();
392 $user_prop = $user->get( $opt );
393
394 if ( ! empty( $user_prop ) ) {
395 if ( $args['multiple'] ) {
396 $values[] = $user_prop;
397 } else {
398 return $user_prop;
399 }
400 }
401
402 } elseif ( 'post_meta' === $opt and in_the_loop() ) {
403 if ( $args['multiple'] ) {
404 $values = array_merge( $values,
405 get_post_meta( get_the_ID(), $this->name )
406 );
407 } else {
408 $val = (string) get_post_meta( get_the_ID(), $this->name, true );
409
410 if ( strlen( $val ) ) {
411 return $val;
412 }
413 }
414
415 } elseif (
416 'get' === $opt and
417 $vals = wpcf7_superglobal_get( $this->name )
418 ) {
419 $vals = array_map( 'wpcf7_sanitize_query_var', (array) $vals );
420
421 if ( $args['multiple'] ) {
422 $values = array_merge( $values, $vals );
423 } else {
424 $val = isset( $vals[0] ) ? (string) $vals[0] : '';
425
426 if ( strlen( $val ) ) {
427 return $val;
428 }
429 }
430
431 } elseif (
432 'post' === $opt and
433 $vals = wpcf7_superglobal_post( $this->name )
434 ) {
435 $vals = array_map( 'wpcf7_sanitize_query_var', (array) $vals );
436
437 if ( $args['multiple'] ) {
438 $values = array_merge( $values, $vals );
439 } else {
440 $val = isset( $vals[0] ) ? (string) $vals[0] : '';
441
442 if ( strlen( $val ) ) {
443 return $val;
444 }
445 }
446
447 } elseif ( 'shortcode_attr' === $opt ) {
448 if ( $contact_form = WPCF7_ContactForm::get_current() ) {
449 $val = $contact_form->shortcode_attr( $this->name );
450
451 if ( isset( $val ) and strlen( $val ) ) {
452 if ( $args['multiple'] ) {
453 $values[] = $val;
454 } else {
455 return $val;
456 }
457 }
458 }
459
460 } elseif ( preg_match( '/^[0-9_]+$/', $opt ) ) {
461 $nums = explode( '_', $opt );
462
463 foreach ( $nums as $num ) {
464 $num = absint( $num );
465 $num = $args['shifted'] ? $num : $num - 1;
466
467 if ( isset( $this->values[$num] ) ) {
468 if ( $args['multiple'] ) {
469 $values[] = $this->values[$num];
470 } else {
471 return $this->values[$num];
472 }
473 }
474 }
475 }
476 }
477
478 if ( $args['multiple'] ) {
479 $values = array_unique( $values );
480 return $values;
481 } else {
482 return $default_value;
483 }
484 }
485
486
487 /**
488 * Retrieves the data option value from the form-tag.
489 *
490 * @param string|array $args Optional options for the option value retrieval.
491 * @return mixed The option value.
492 */
493 public function get_data_option( $args = '' ) {
494 $options = (array) $this->get_option( 'data' );
495
496 return apply_filters( 'wpcf7_form_tag_data_option', null, $options, $args );
497 }
498
499
500 /**
501 * Retrieves the limit option value from the form-tag.
502 *
503 * @param int $default_value Optional default value. Default 1048576.
504 * @return int The option value.
505 */
506 public function get_limit_option( $default_value = MB_IN_BYTES ) {
507 $pattern = '/^limit:([1-9][0-9]*)([kKmM]?[bB])?$/';
508
509 $matches = $this->get_first_match_option( $pattern );
510
511 if ( $matches ) {
512 $size = (int) $matches[1];
513
514 if ( ! empty( $matches[2] ) ) {
515 $kbmb = strtolower( $matches[2] );
516
517 if ( 'kb' === $kbmb ) {
518 $size *= KB_IN_BYTES;
519 } elseif ( 'mb' === $kbmb ) {
520 $size *= MB_IN_BYTES;
521 }
522 }
523
524 return $size;
525 }
526
527 return (int) $default_value;
528 }
529
530
531 /**
532 * Retrieves the value of the first option matches the given
533 * regular expression pattern.
534 *
535 * @param string $pattern Regular expression pattern.
536 * @return array|bool Option value as an array of matched strings.
537 * False if there is no option matches the pattern.
538 */
539 public function get_first_match_option( $pattern ) {
540 foreach ( (array) $this->options as $option ) {
541 if ( preg_match( $pattern, $option, $matches ) ) {
542 return $matches;
543 }
544 }
545
546 return false;
547 }
548
549
550 /**
551 * Retrieves values of options that match the given
552 * regular expression pattern.
553 *
554 * @param string $pattern Regular expression pattern.
555 * @return array Array of arrays of strings that match the pattern.
556 */
557 public function get_all_match_options( $pattern ) {
558 $result = array();
559
560 foreach ( (array) $this->options as $option ) {
561 if ( preg_match( $pattern, $option, $matches ) ) {
562 $result[] = $matches;
563 }
564 }
565
566 return $result;
567 }
568
569
570 /**
571 * Assigns a value to the specified offset.
572 *
573 * @link https://www.php.net/manual/en/arrayaccess.offsetset.php
574 */
575 #[ReturnTypeWillChange]
576 public function offsetSet( $offset, $value ) {
577 if ( property_exists( __CLASS__, $offset ) ) {
578 $this->{$offset} = $value;
579 }
580 }
581
582
583 /**
584 * Returns the value at specified offset.
585 *
586 * @link https://www.php.net/manual/en/arrayaccess.offsetget.php
587 */
588 #[ReturnTypeWillChange]
589 public function offsetGet( $offset ) {
590 if ( property_exists( __CLASS__, $offset ) ) {
591 return $this->{$offset};
592 }
593
594 return null;
595 }
596
597
598 /**
599 * Returns true if the specified offset exists.
600 *
601 * @link https://www.php.net/manual/en/arrayaccess.offsetexists.php
602 */
603 #[ReturnTypeWillChange]
604 public function offsetExists( $offset ) {
605 return property_exists( __CLASS__, $offset );
606 }
607
608
609 /**
610 * Unsets an offset.
611 *
612 * @link https://www.php.net/manual/en/arrayaccess.offsetunset.php
613 */
614 #[ReturnTypeWillChange]
615 public function offsetUnset( $offset ) {
616 }
617
618 }
619