PluginProbe ʕ •ᴥ•ʔ
Contact Form 7 / 4.0.2
Contact Form 7 v4.0.2
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 / shortcodes.php
contact-form-7 / includes Last commit date
css 12 years ago js 11 years ago capabilities.php 13 years ago contact-form-template.php 11 years ago contact-form.php 11 years ago controller.php 11 years ago formatting.php 12 years ago functions.php 11 years ago mail.php 11 years ago pipe.php 12 years ago shortcodes.php 12 years ago submission.php 11 years ago upgrade.php 11 years ago
shortcodes.php
420 lines
1 <?php
2
3 class WPCF7_ShortcodeManager {
4
5 private static $instance;
6
7 private $shortcode_tags = array();
8
9 // Taggs scanned at the last time of do_shortcode()
10 private $scanned_tags = null;
11
12 // Executing shortcodes (true) or just scanning (false)
13 private $exec = true;
14
15 private function __construct() {}
16
17 public static function get_instance() {
18 if ( empty( self::$instance ) ) {
19 self::$instance = new self;
20 }
21
22 return self::$instance;
23 }
24
25 public function get_scanned_tags() {
26 return $this->scanned_tags;
27 }
28
29 public function add_shortcode( $tag, $func, $has_name = false ) {
30 if ( ! is_callable( $func ) )
31 return;
32
33 $tags = array_filter( array_unique( (array) $tag ) );
34
35 foreach ( $tags as $tag ) {
36 $this->shortcode_tags[$tag] = array(
37 'function' => $func,
38 'has_name' => (boolean) $has_name );
39 }
40 }
41
42 public function remove_shortcode( $tag ) {
43 unset( $this->shortcode_tags[$tag] );
44 }
45
46 public function normalize_shortcode( $content ) {
47 if ( empty( $this->shortcode_tags ) || ! is_array( $this->shortcode_tags ) )
48 return $content;
49
50 $pattern = $this->get_shortcode_regex();
51 return preg_replace_callback( '/' . $pattern . '/s',
52 array( $this, 'normalize_space_cb' ), $content );
53 }
54
55 private function normalize_space_cb( $m ) {
56 // allow [[foo]] syntax for escaping a tag
57 if ( $m[1] == '[' && $m[6] == ']' )
58 return $m[0];
59
60 $tag = $m[2];
61 $attr = trim( preg_replace( '/[\r\n\t ]+/', ' ', $m[3] ) );
62 $content = trim( $m[5] );
63
64 $content = str_replace( "\n", '<WPPreserveNewline />', $content );
65
66 $result = $m[1] . '[' . $tag
67 . ( $attr ? ' ' . $attr : '' )
68 . ( $m[4] ? ' ' . $m[4] : '' )
69 . ']'
70 . ( $content ? $content . '[/' . $tag . ']' : '' )
71 . $m[6];
72
73 return $result;
74 }
75
76 public function do_shortcode( $content, $exec = true ) {
77 $this->exec = (bool) $exec;
78 $this->scanned_tags = array();
79
80 if ( empty( $this->shortcode_tags ) || ! is_array( $this->shortcode_tags ) )
81 return $content;
82
83 $pattern = $this->get_shortcode_regex();
84 return preg_replace_callback( '/' . $pattern . '/s',
85 array( $this, 'do_shortcode_tag' ), $content );
86 }
87
88 public function scan_shortcode( $content ) {
89 $this->do_shortcode( $content, false );
90 return $this->scanned_tags;
91 }
92
93 private function get_shortcode_regex() {
94 $tagnames = array_keys( $this->shortcode_tags );
95 $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) );
96
97 return '(\[?)'
98 . '\[(' . $tagregexp . ')(?:[\r\n\t ](.*?))?(?:[\r\n\t ](\/))?\]'
99 . '(?:([^[]*?)\[\/\2\])?'
100 . '(\]?)';
101 }
102
103 private function do_shortcode_tag( $m ) {
104 // allow [[foo]] syntax for escaping a tag
105 if ( $m[1] == '[' && $m[6] == ']' ) {
106 return substr( $m[0], 1, -1 );
107 }
108
109 $tag = $m[2];
110 $attr = $this->shortcode_parse_atts( $m[3] );
111
112 $scanned_tag = array(
113 'type' => $tag,
114 'basetype' => trim( $tag, '*' ),
115 'name' => '',
116 'options' => array(),
117 'raw_values' => array(),
118 'values' => array(),
119 'pipes' => null,
120 'labels' => array(),
121 'attr' => '',
122 'content' => '' );
123
124 if ( is_array( $attr ) ) {
125 if ( is_array( $attr['options'] ) ) {
126 if ( $this->shortcode_tags[$tag]['has_name'] && ! empty( $attr['options'] ) ) {
127 $scanned_tag['name'] = array_shift( $attr['options'] );
128
129 if ( ! wpcf7_is_name( $scanned_tag['name'] ) )
130 return $m[0]; // Invalid name is used. Ignore this tag.
131 }
132
133 $scanned_tag['options'] = (array) $attr['options'];
134 }
135
136 $scanned_tag['raw_values'] = (array) $attr['values'];
137
138 if ( WPCF7_USE_PIPE ) {
139 $pipes = new WPCF7_Pipes( $scanned_tag['raw_values'] );
140 $scanned_tag['values'] = $pipes->collect_befores();
141 $scanned_tag['pipes'] = $pipes;
142 } else {
143 $scanned_tag['values'] = $scanned_tag['raw_values'];
144 }
145
146 $scanned_tag['labels'] = $scanned_tag['values'];
147
148 } else {
149 $scanned_tag['attr'] = $attr;
150 }
151
152 $scanned_tag['values'] = array_map( 'trim', $scanned_tag['values'] );
153 $scanned_tag['labels'] = array_map( 'trim', $scanned_tag['labels'] );
154
155 $content = trim( $m[5] );
156 $content = preg_replace( "/<br[\r\n\t ]*\/?>$/m", '', $content );
157 $scanned_tag['content'] = $content;
158
159 $scanned_tag = apply_filters( 'wpcf7_form_tag', $scanned_tag, $this->exec );
160
161 $this->scanned_tags[] = $scanned_tag;
162
163 if ( $this->exec ) {
164 $func = $this->shortcode_tags[$tag]['function'];
165 return $m[1] . call_user_func( $func, $scanned_tag ) . $m[6];
166 } else {
167 return $m[0];
168 }
169 }
170
171 private function shortcode_parse_atts( $text ) {
172 $atts = array( 'options' => array(), 'values' => array() );
173 $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", " ", $text );
174 $text = stripcslashes( trim( $text ) );
175
176 $pattern = '%^([-+*=0-9a-zA-Z:.!?#$&@_/|\%\r\n\t ]*?)((?:[\r\n\t ]*"[^"]*"|[\r\n\t ]*\'[^\']*\')*)$%';
177
178 if ( preg_match( $pattern, $text, $match ) ) {
179 if ( ! empty( $match[1] ) ) {
180 $atts['options'] = preg_split( '/[\r\n\t ]+/', trim( $match[1] ) );
181 }
182 if ( ! empty( $match[2] ) ) {
183 preg_match_all( '/"[^"]*"|\'[^\']*\'/', $match[2], $matched_values );
184 $atts['values'] = wpcf7_strip_quote_deep( $matched_values[0] );
185 }
186 } else {
187 $atts = $text;
188 }
189
190 return $atts;
191 }
192
193 }
194
195 function wpcf7_add_shortcode( $tag, $func, $has_name = false ) {
196 $manager = WPCF7_ShortcodeManager::get_instance();
197
198 return $manager->add_shortcode( $tag, $func, $has_name );
199 }
200
201 function wpcf7_remove_shortcode( $tag ) {
202 $manager = WPCF7_ShortcodeManager::get_instance();
203
204 return $manager->remove_shortcode( $tag );
205 }
206
207 function wpcf7_do_shortcode( $content ) {
208 $manager = WPCF7_ShortcodeManager::get_instance();
209
210 return $manager->do_shortcode( $content );
211 }
212
213 class WPCF7_Shortcode {
214
215 public $type;
216 public $basetype;
217 public $name = '';
218 public $options = array();
219 public $raw_values = array();
220 public $values = array();
221 public $pipes;
222 public $labels = array();
223 public $attr = '';
224 public $content = '';
225
226 public function __construct( $tag ) {
227 foreach ( $tag as $key => $value ) {
228 if ( property_exists( __CLASS__, $key ) )
229 $this->{$key} = $value;
230 }
231 }
232
233 public function is_required() {
234 return ( '*' == substr( $this->type, -1 ) );
235 }
236
237 public function has_option( $opt ) {
238 $pattern = sprintf( '/^%s(:.+)?$/i', preg_quote( $opt, '/' ) );
239 return (bool) preg_grep( $pattern, $this->options );
240 }
241
242 public function get_option( $opt, $pattern = '', $single = false ) {
243 $preset_patterns = array(
244 'date' => '([0-9]{4}-[0-9]{2}-[0-9]{2}|today(.*))',
245 'int' => '[0-9]+',
246 'signed_int' => '-?[0-9]+',
247 'class' => '[-0-9a-zA-Z_]+',
248 'id' => '[-0-9a-zA-Z_]+' );
249
250 if ( isset( $preset_patterns[$pattern] ) )
251 $pattern = $preset_patterns[$pattern];
252
253 if ( '' == $pattern )
254 $pattern = '.+';
255
256 $pattern = sprintf( '/^%s:%s$/i', preg_quote( $opt, '/' ), $pattern );
257
258 if ( $single ) {
259 $matches = $this->get_first_match_option( $pattern );
260
261 if ( ! $matches )
262 return false;
263
264 return substr( $matches[0], strlen( $opt ) + 1 );
265 } else {
266 $matches_a = $this->get_all_match_options( $pattern );
267
268 if ( ! $matches_a )
269 return false;
270
271 $results = array();
272
273 foreach ( $matches_a as $matches )
274 $results[] = substr( $matches[0], strlen( $opt ) + 1 );
275
276 return $results;
277 }
278 }
279
280 public function get_id_option() {
281 return $this->get_option( 'id', 'id', true );
282 }
283
284 public function get_class_option( $default = '' ) {
285 if ( is_string( $default ) )
286 $default = explode( ' ', $default );
287
288 $options = array_merge(
289 (array) $default,
290 (array) $this->get_option( 'class', 'class' ) );
291
292 $options = array_filter( array_unique( $options ) );
293
294 return implode( ' ', $options );
295 }
296
297 public function get_size_option( $default = '' ) {
298 $matches_a = $this->get_all_match_options( '%^([0-9]*)/[0-9]*$%' );
299
300 foreach ( (array) $matches_a as $matches ) {
301 if ( isset( $matches[1] ) && '' !== $matches[1] )
302 return $matches[1];
303 }
304
305 return $default;
306 }
307
308 public function get_maxlength_option( $default = '' ) {
309 $matches_a = $this->get_all_match_options(
310 '%^(?:[0-9]*x?[0-9]*)?/([0-9]+)$%' );
311
312 foreach ( (array) $matches_a as $matches ) {
313 if ( isset( $matches[1] ) && '' !== $matches[1] )
314 return $matches[1];
315 }
316
317 return $default;
318 }
319
320 public function get_cols_option( $default = '' ) {
321 $matches_a = $this->get_all_match_options(
322 '%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%' );
323
324 foreach ( (array) $matches_a as $matches ) {
325 if ( isset( $matches[1] ) && '' !== $matches[1] )
326 return $matches[1];
327 }
328
329 return $default;
330 }
331
332 public function get_rows_option( $default = '' ) {
333 $matches_a = $this->get_all_match_options(
334 '%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%' );
335
336 foreach ( (array) $matches_a as $matches ) {
337 if ( isset( $matches[2] ) && '' !== $matches[2] )
338 return $matches[2];
339 }
340
341 return $default;
342 }
343
344 public function get_date_option( $opt ) {
345 $option = $this->get_option( $opt, 'date', true );
346
347 if ( preg_match( '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $option ) ) {
348 return $option;
349 }
350
351 if ( preg_match( '/^today(?:([+-][0-9]+)([a-z]*))?/', $option, $matches ) ) {
352 $number = isset( $matches[1] ) ? (int) $matches[1] : 0;
353 $unit = isset( $matches[2] ) ? $matches[2] : '';
354
355 if ( ! preg_match( '/^(day|month|year|week)s?$/', $unit ) ) {
356 $unit = 'days';
357 }
358
359 $date = gmdate( 'Y-m-d',
360 strtotime( sprintf( 'today %1$s %2$s', $number, $unit ) ) );
361 return $date;
362 }
363
364 return false;
365 }
366
367 public function get_default_option() {
368 $options = (array) $this->get_option( 'default' );
369
370 if ( empty( $options ) ) {
371 return false;
372 }
373
374 foreach ( $options as $opt ) {
375 $opt = sanitize_key( $opt );
376
377 if ( 'user_' == substr( $opt, 0, 5 ) && is_user_logged_in() ) {
378 $primary_props = array( 'user_login', 'user_email', 'user_url' );
379 $opt = in_array( $opt, $primary_props ) ? $opt : substr( $opt, 5 );
380
381 $user = wp_get_current_user();
382 $user_prop = $user->get( $opt );
383
384 if ( ! empty( $user_prop ) ) {
385 return $user_prop;
386 }
387 }
388 }
389
390 return false;
391 }
392
393 public function get_data_option( $args = '' ) {
394 $options = (array) $this->get_option( 'data' );
395
396 return apply_filters( 'wpcf7_form_tag_data_option', null, $options, $args );
397 }
398
399 public function get_first_match_option( $pattern ) {
400 foreach( (array) $this->options as $option ) {
401 if ( preg_match( $pattern, $option, $matches ) )
402 return $matches;
403 }
404
405 return false;
406 }
407
408 public function get_all_match_options( $pattern ) {
409 $result = array();
410
411 foreach( (array) $this->options as $option ) {
412 if ( preg_match( $pattern, $option, $matches ) )
413 $result[] = $matches;
414 }
415
416 return $result;
417 }
418 }
419
420 ?>