PluginProbe
HTML Forms – Simple WordPress Forms Plugin / 1.3.30
HTML Forms – Simple WordPress Forms Plugin v1.3.30
1.7.0 trunk 1.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2.0 1.3.0 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 All 67 releases
← All changes | src/functions.php +390 -131 1.1.11.3.30 View file →
@@ -3,77 +3,112 @@
3 3 use HTML_Forms\Form;
4 4 use HTML_Forms\Submission;
5 5
6 6 /**
7 - * @param $form_id_or_slug int|string
7 + * @param array $args
8 + * @return array
9 + */
10 +function hf_get_forms( array $args = array() ) {
11 + $default_args = array(
12 + 'post_type' => 'html-form',
13 + 'post_status' => array( 'publish', 'draft', 'pending', 'future' ),
14 + 'posts_per_page' => -1,
15 + 'ignore_sticky_posts' => true,
16 + 'no_found_rows' => true,
17 + );
18 + $args = array_merge( $default_args, $args );
19 + $query = new WP_Query;
20 + $posts = $query->query( $args );
21 + $forms = array_map( 'hf_get_form', $posts );
22 + return $forms;
23 +}
24 +
25 +/**
26 + * @param $form_id_or_slug int|string|WP_Post
8 27 * @return Form
9 28 * @throws Exception
10 29 */
11 30 function hf_get_form( $form_id_or_slug ) {
12 31
13 - if( is_numeric( $form_id_or_slug ) ) {
14 - $post = get_post( $form_id_or_slug );
32 + if ( is_numeric( $form_id_or_slug ) || $form_id_or_slug instanceof WP_Post ) {
33 + $post = get_post( $form_id_or_slug );
15 34
16 - if( ! $post || $post->post_type !== 'html-form' ) {
17 - throw new Exception( "Invalid form ID" );
18 - }
19 - } else {
20 - $posts = get_posts(
21 - array(
22 - 'post_type' => 'html-form',
23 - 'name' => $form_id_or_slug,
24 - 'post_status' => 'publish',
25 - 'numberposts' => 1,
26 - )
27 - );
35 + if ( ! $post instanceof WP_Post || $post->post_type !== 'html-form' ) {
36 + throw new Exception( 'Invalid form ID' );
37 + }
38 + } else {
28 39
29 - if( empty( $posts ) ) {
30 - throw new Exception( 'Invalid form slug' );
31 - }
32 - $post = $posts[0];
33 - }
40 + $query = new WP_Query;
41 + $posts = $query->query(
42 + array(
43 + 'post_type' => 'html-form',
44 + 'name' => $form_id_or_slug,
45 + 'post_status' => 'publish',
46 + 'posts_per_page' => 1,
47 + 'ignore_sticky_posts' => true,
48 + 'no_found_rows' => true,
49 + )
50 + );
51 + if ( empty( $posts ) ) {
52 + throw new Exception( 'Invalid form slug' );
53 + }
54 + $post = $posts[0];
55 + }
34 56
35 - static $default_messages;
36 - if( $default_messages === null ) {
37 - $default_messages = array(
38 - 'success' => __('Thank you! We will be in touch soon.', 'html-forms'),
39 - 'invalid_email' => __( 'Sorry, that email address looks invalid.', 'html-forms' ),
40 - 'required_field_missing' => __( "Please fill in the required fields.", "html-forms" ),
41 - 'error' => __( 'Oops. An error occurred.', 'html-forms' ),
42 - );
43 - }
57 + // get all post meta in a single call for performance
58 + $post_meta = get_post_meta( $post->ID );
44 59
45 - static $default_settings = array(
46 - 'hide_after_success' => 0,
47 - 'redirect_url' => '',
48 - 'required_fields' =>'',
49 - 'email_fields' => '',
50 - );
60 + // grab & merge form settings
61 + $default_settings = array(
62 + 'save_submissions' => 1,
63 + 'hide_after_success' => 0,
64 + 'redirect_url' => '',
65 + 'required_fields' => '',
66 + 'email_fields' => '',
67 + );
68 + $default_settings = apply_filters( 'hf_form_default_settings', $default_settings );
69 + $settings = array();
70 + if ( ! empty( $post_meta['_hf_settings'][0] ) ) {
71 + $settings = (array) maybe_unserialize( $post_meta['_hf_settings'][0] );
72 + }
73 + $settings = array_merge( $default_settings, $settings );
51 74
52 - $post_meta = get_post_meta( $post->ID );
75 + // grab & merge form messages
76 + $default_messages = array(
77 + 'success' => __( 'Thank you! We will be in touch soon.', 'html-forms' ),
78 + 'invalid_email' => __( 'Sorry, that email address looks invalid.', 'html-forms' ),
79 + 'required_field_missing' => __( 'Please fill in the required fields.', 'html-forms' ),
80 + 'error' => __( 'Oops. An error occurred.', 'html-forms' ),
81 + );
82 + $default_messages = apply_filters( 'hf_form_default_messages', $default_messages );
83 + $messages = array();
84 + foreach ( $post_meta as $meta_key => $meta_values ) {
85 + if ( strpos( $meta_key, 'hf_message_' ) === 0 ) {
86 + $message_key = substr( $meta_key, strlen( 'hf_message_' ) );
87 + $messages[ $message_key ] = (string) $meta_values[0];
88 + }
89 + }
90 + $messages = array_merge( $default_messages, $messages );
53 91
54 - $settings = array();
55 - if( ! empty( $post_meta['_hf_settings'][0] ) ) {
56 - $settings = (array) maybe_unserialize( $post_meta['_hf_settings'][0] );
57 - }
58 - $settings = array_merge( $default_settings, $settings );
92 + // finally, create form instance
93 + $form = new Form( $post->ID );
94 + $form->title = $post->post_title;
95 + $form->slug = $post->post_name;
96 + $form->markup = $post->post_content;
97 + $form->settings = $settings;
98 + $form->messages = $messages;
99 + return $form;
100 +}
59 101
60 - $messages = array();
61 - foreach( $post_meta as $meta_key => $meta_values ) {
62 - if( strpos( $meta_key, 'hf_message_' ) === 0 ) {
63 - $message_key = substr( $meta_key, strlen( 'hf_message_' ) );
64 - $messages[$message_key] = (string) $meta_values[0];
65 - }
66 - }
67 - $messages = array_merge( $default_messages, $messages );
68 -
69 - $form = new Form( $post->ID );
70 - $form->title = $post->post_title;
71 - $form->slug = $post->post_name;
72 - $form->markup = $post->post_content;
73 - $form->settings = $settings;
74 - $form->messages = $messages;
75 - return $form;
102 +/**
103 + * @param $form_id
104 + * @return int
105 + */
106 +function hf_count_form_submissions( $form_id ) {
107 + global $wpdb;
108 + $table = $wpdb->prefix . 'hf_submissions';
109 + $result = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$table} s WHERE s.form_id = %d;", $form_id ) );
110 + return (int) $result;
76 111 }
77 112
78 113 /**
79 114 * @param $form_id
@@ -80,23 +115,23 @@
80 115 * @param array $args
81 116 * @return Submission[]
82 117 */
83 118 function hf_get_form_submissions( $form_id, array $args = array() ) {
84 - $default_args = array(
85 - 'offset' => 0,
86 - 'limit' => 1000,
87 - );
88 - $args = array_merge( $default_args, $args );
119 + $default_args = array(
120 + 'offset' => 0,
121 + 'limit' => 1000,
122 + );
123 + $args = array_merge( $default_args, $args );
89 124
90 - global $wpdb;
91 - $table = $wpdb->prefix .'hf_submissions';
92 - $results = $wpdb->get_results( $wpdb->prepare( "SELECT s.* FROM {$table} s WHERE s.form_id = %d ORDER BY s.submitted_at DESC LIMIT %d, %d;", $form_id, $args['offset'], $args['limit'] ), OBJECT_K );
93 - $submissions = array();
94 - foreach( $results as $key => $object ) {
95 - $submission = Submission::from_object( $object );
96 - $submissions[$key] = $submission;
97 - }
98 - return $submissions;
125 + global $wpdb;
126 + $table = $wpdb->prefix . 'hf_submissions';
127 + $results = $wpdb->get_results( $wpdb->prepare( "SELECT s.* FROM {$table} s WHERE s.form_id = %d ORDER BY s.submitted_at DESC LIMIT %d, %d;", $form_id, $args['offset'], $args['limit'] ), OBJECT_K );
128 + $submissions = array();
129 + foreach ( $results as $key => $object ) {
130 + $submission = Submission::from_object( $object );
131 + $submissions[ $key ] = $submission;
132 + }
133 + return $submissions;
99 134 }
100 135
101 136 /**
102 137 * @param int $submission_id
@@ -102,24 +137,41 @@
102 137 * @param int $submission_id
103 138 * @return Submission
104 139 */
105 140 function hf_get_form_submission( $submission_id ) {
106 - global $wpdb;
107 - $table = $wpdb->prefix .'hf_submissions';
108 - $object = $wpdb->get_row( $wpdb->prepare( "SELECT s.* FROM {$table} s WHERE s.id = %d;", $submission_id ), OBJECT );
109 - $submission = Submission::from_object( $object );
110 - return $submission;
141 + global $wpdb;
142 + $table = $wpdb->prefix . 'hf_submissions';
143 + $object = $wpdb->get_row( $wpdb->prepare( "SELECT s.* FROM {$table} s WHERE s.id = %d;", $submission_id ), OBJECT );
144 + $submission = Submission::from_object( $object );
145 + return $submission;
111 146 }
112 147 /**
113 148 * @return array
114 149 */
115 150 function hf_get_settings() {
116 - static $default_settings = array(
117 - 'load_stylesheet' => 0,
118 - );
151 + $default_settings = array(
152 + 'load_stylesheet' => 0,
153 + );
119 154
120 - $settings = get_option( 'hf_settings', array() );
121 - return array_merge( $default_settings, $settings );
155 + $settings = get_option( 'hf_settings', null );
156 +
157 + // prevent a SQL query when option does not yet exist
158 + if ( $settings === null ) {
159 + update_option( 'hf_settings', array(), true );
160 + $settings = array();
161 + }
162 +
163 + // merge with default settings
164 + $settings = array_merge( $default_settings, $settings );
165 +
166 + /**
167 + * Filters the global HTML Forms hf_settings
168 + *
169 + * @param array $settings
170 + */
171 + $settings = apply_filters( 'hf_settings', $settings );
172 +
173 + return $settings;
122 174 }
123 175
124 176 /**
125 177 * Get element from array, allows for dot notation eg: "foo.bar"
@@ -129,25 +181,25 @@
129 181 * @param mixed $default
130 182 * @return mixed
131 183 */
132 184 function hf_array_get( $array, $key, $default = null ) {
133 - if ( is_null( $key ) ) {
134 - return $array;
135 - }
185 + if ( is_null( $key ) ) {
186 + return $array;
187 + }
136 188
137 - if ( isset( $array[$key] ) ) {
138 - return $array[$key];
139 - }
189 + if ( isset( $array[ $key ] ) ) {
190 + return $array[ $key ];
191 + }
140 192
141 - foreach (explode( '.', $key ) as $segment) {
142 - if ( ! is_array( $array ) || ! array_key_exists( $segment, $array ) ) {
143 - return $default;
144 - }
193 + foreach ( explode( '.', $key ) as $segment ) {
194 + if ( ! is_array( $array ) || ! array_key_exists( $segment, $array ) ) {
195 + return $default;
196 + }
145 197
146 - $array = $array[$segment];
147 - }
198 + $array = $array[ $segment ];
199 + }
148 200
149 - return $array;
201 + return $array;
150 202 }
151 203
152 204 /**
153 205 * Processes template tags like {{user.user_email}}
@@ -156,55 +208,262 @@
156 208 *
157 209 * @return string
158 210 */
159 211 function hf_template( $template ) {
160 - $replacers = new HTML_Forms\TagReplacers();
161 - $tags = array(
162 - 'user' => array( $replacers, 'user' ),
163 - 'post' => array( $replacers, 'post'),
164 - 'url_params' => array( $replacers, 'url_params' ),
165 - );
212 + $replacers = new HTML_Forms\TagReplacers();
213 + $tags = array(
214 + 'user' => array( $replacers, 'user' ),
215 + 'post' => array( $replacers, 'post' ),
216 + 'url_params' => array( $replacers, 'url_params' ),
217 + );
166 218
167 - /**
168 - * Filters the available tags in HTML Forms templates, like {{user.user_email}}.
169 - *
170 - * Can be used to add simple scalar replacements or more advanced replacement functions that accept a parameter.
171 - *
172 - * @param array $tags
173 - */
174 - $tags = apply_filters( 'hf_template_tags', $tags );
219 + /**
220 + * Filters the available tags in HTML Forms templates, like {{user.user_email}}.
221 + *
222 + * Can be used to add simple scalar replacements or more advanced replacement functions that accept a parameter.
223 + *
224 + * @param array $tags
225 + */
226 + $tags = apply_filters( 'hf_template_tags', $tags );
175 227
176 - $template = preg_replace_callback( '/\{\{ *(\w+)(?:\.([\w\.]+))? *(?:\|\| *(\w+))? *\}\}/', function( $matches ) use ( $tags ) {
177 - $tag = $matches[1];
178 - $param = ! isset( $matches[2] ) ? "" : $matches[2];
179 - $default = ! isset( $matches[3] ) ? "" : $matches[3];
180 - $value = "";
228 + $template = preg_replace_callback(
229 + '/\{\{ *(\w+)(?:\.([\w\.]+))? *(?:\|\| *(\w+))? *\}\}/',
230 + function( $matches ) use ( $tags ) {
231 + $tag = $matches[1];
232 + $param = ! isset( $matches[2] ) ? '' : $matches[2];
233 + $default = ! isset( $matches[3] ) ? '' : $matches[3];
181 234
182 - // do not change anything if we have no replacer with that key, could be custom user logic or another plugin.
183 - if( ! isset( $tags[ $tag] ) ) {
184 - return $matches[0];
185 - }
235 + // do not change anything if we have no replacer with that key, could be custom user logic or another plugin.
236 + if ( ! isset( $tags[ $tag ] ) ) {
237 + return $matches[0];
238 + }
186 239
187 - $replacement = $tags[$tag];
188 - $value = is_callable( $replacement ) ? call_user_func_array( $replacement, array( $param ) ) : $replacement;
189 - return ! empty( $value ) ? $value : $default;
190 - }, $template );
240 + $replacement = $tags[ $tag ];
241 + $value = is_callable( $replacement ) ? call_user_func_array( $replacement, array( $param ) ) : $replacement;
242 + return ! empty( $value ) ? $value : $default;
243 + },
244 + $template
245 + );
191 246
192 - return $template;
247 + return $template;
193 248 }
194 249
195 250 /**
196 251 * @param string $string
197 252 * @param array $data
198 - *
253 + * @param Closure|string $escape_function
199 254 * @return string
200 255 */
201 -function hf_replace_data_variables( $string, $data = array() ) {
202 - $string = preg_replace_callback( '/\[([a-zA-Z0-9\-\._]+)\]/', function( $matches ) use ( $data ) {
203 - $key = $matches[1];
204 - $replacement = hf_array_get( $data, $key, '' );
205 - $replacement = is_array( $replacement ) ? join( ', ', $replacement ) : $replacement;
206 - return $replacement;
207 - }, $string );
208 - return $string;
256 +function hf_replace_data_variables( $string, $data = array(), $escape_function = null ) {
257 + return preg_replace_callback(
258 + '/\[(.+?)\]/',
259 + function( $matches ) use ( $data, $escape_function ) {
260 + $key = $matches[1];
261 + // replace spaces in name with underscores to match PHP requirement for keys in $_POST superglobal
262 + $key = str_replace( ' ', '_', $key );
263 + $replacement = hf_array_get( $data, $key, '' );
264 + $replacement = hf_field_value( $replacement, 0, $escape_function );
265 + return $replacement;
266 + },
267 + $string
268 + );
209 269 }
210 270
271 +/**
272 +* Returns a formatted & HTML-escaped field value. Detects file-, array- and date-types.
273 +*
274 +* Caveat: if value is a file, an HTML string is returned (which means email action should use "Content-Type: html" when it includes a file field).
275 +*
276 +* @param string|array $value
277 +* @param int $limit
278 +* @param Closure|string $escape_function
279 +* @return string
280 +* @since 1.3.1
281 +*/
282 +function hf_field_value( $value, $limit = 0, $escape_function = 'esc_html' ) {
283 + if ( $value === '' ) {
284 + return $value;
285 + }
286 +
287 + if ( hf_is_file( $value ) ) {
288 + $file_url = isset( $value['url'] ) ? $value['url'] : '';
289 + if ( isset( $value['attachment_id'] ) && apply_filters( 'hf_file_upload_use_direct_links', false ) === false ) {
290 + $file_url = admin_url( sprintf( 'post.php?action=edit&post=%d', $value['attachment_id'] ) );
291 + }
292 + $short_name = substr( $value['name'], 0, 20 );
293 + $suffix = strlen( $value['name'] ) > 20 ? '...' : '';
294 + return sprintf( '<a href="%s">%s%s</a> (%s)', esc_attr( $file_url ), esc_html( $short_name ), esc_html( $suffix ), hf_human_filesize( $value['size'] ) );
295 + }
296 +
297 + if ( hf_is_date( $value ) ) {
298 + $date_format = get_option( 'date_format' );
299 + return gmdate( $date_format, strtotime( $value ) );
300 + }
301 +
302 + // join array-values with comma
303 + if ( is_array( $value ) ) {
304 + $value = join( ', ', $value );
305 + }
306 +
307 + // limit string to certain length
308 + if ( $limit > 0 ) {
309 + $limited = strlen( $value ) > $limit;
310 + $value = substr( $value, 0, $limit );
311 +
312 + if ( $limited ) {
313 + $value .= '...';
314 + }
315 + }
316 +
317 + // escape value
318 + if ( $escape_function !== null && is_callable( $escape_function ) ) {
319 + $value = $escape_function( $value );
320 + }
321 +
322 + return $value;
323 +}
324 +
325 +/**
326 +* Returns true if value is a "file"
327 +*
328 +* @param mixed $value
329 +* @return bool
330 +*/
331 +function hf_is_file( $value ) {
332 + return is_array( $value )
333 + && isset( $value['name'] )
334 + && isset( $value['size'] )
335 + && isset( $value['type'] );
336 +}
337 +
338 +/**
339 +* Returns true if value looks like a date-string submitted from a <input type="date">
340 +* @param mixed $value
341 +* @return bool
342 +* @since 1.3.1
343 +*/
344 +function hf_is_date( $value ) {
345 + if ( ! is_string( $value )
346 + || strlen( $value ) !== 10
347 + || (int) preg_match( '/\d{2,4}[-\/]\d{2}[-\/]\d{2,4}/', $value ) === 0 ) {
348 + return false;
349 + }
350 +
351 + $timestamp = strtotime( $value );
352 + return $timestamp != false;
353 +}
354 +
355 +/**
356 + * @param int $size
357 + * @param int $precision
358 + * @return string
359 +*/
360 +function hf_human_filesize( $size, $precision = 2 ) {
361 + for ( $i = 0; ( $size / 1024 ) > 0.9; $i++, $size /= 1024 ) {
362 + // nothing, loop logic contains everything
363 + }
364 + $steps = array( 'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' );
365 + return round( $size, $precision ) . $steps[ $i ];
366 +}
367 +
368 +/**
369 + * Gets all the form tabs to show in the admin.
370 + * @param Form $form
371 + * @return array
372 + */
373 +function hf_get_admin_tabs( Form $form ) {
374 + $tabs = array(
375 + 'fields' => __( 'Fields', 'html-forms' ),
376 + 'messages' => __( 'Messages', 'html-forms' ),
377 + 'settings' => __( 'Settings', 'html-forms' ),
378 + 'actions' => __( 'Actions', 'html-forms' ),
379 + );
380 +
381 + if ( $form->settings['save_submissions'] ) {
382 + $tabs['submissions'] = __( 'Submissions', 'html-forms' );
383 + }
384 + return apply_filters( 'hf_admin_tabs', $tabs, $form );
385 +}
386 +
387 +function _hf_on_plugin_activation() {
388 + if ( is_multisite() ) {
389 + _hf_on_plugin_activation_multisite();
390 + return;
391 + }
392 +
393 + // install table for regular wp install
394 + _hf_create_submissions_table();
395 +
396 + // add "edit_forms" cap to user that activated the plugin
397 + $user = wp_get_current_user();
398 + $user->add_cap( 'edit_forms', true );
399 +}
400 +
401 +function _hf_on_plugin_activation_multisite() {
402 + $added_caps = array();
403 +
404 + foreach ( get_sites( array( 'number' => PHP_INT_MAX ) ) as $site ) {
405 + switch_to_blog( (int) $site->blog_id );
406 +
407 + // install table for current blog
408 + _hf_create_submissions_table();
409 +
410 + // iterate through current blog admins
411 + foreach ( get_users(
412 + array(
413 + 'blog_id' => (int) $site->blog_id,
414 + 'role' => 'administrator',
415 + 'fields' => 'ID',
416 + )
417 + ) as $admin_id ) {
418 + if ( ! (int) $admin_id || in_array( $admin_id, $added_caps ) ) {
419 + continue;
420 + }
421 +
422 + // add "edit_forms" cap to site admin
423 + $user = new \WP_User( (int) $admin_id );
424 + $user->add_cap( 'edit_forms', true );
425 +
426 + $added_caps[] = $admin_id;
427 + }
428 +
429 + restore_current_blog();
430 + }
431 +}
432 +
433 +// install table for main site on regular installs, or active site for multisite
434 +function _hf_create_submissions_table() {
435 + /** @var wpdb */
436 + global $wpdb;
437 +
438 + $charset_collate = $wpdb->get_charset_collate();
439 +
440 + // create table for storing submissions
441 + $table = $wpdb->prefix . 'hf_submissions';
442 + $wpdb->query(
443 + "CREATE TABLE IF NOT EXISTS {$table}(
444 + `id` INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
445 + `form_id` INT UNSIGNED NOT NULL,
446 + `data` TEXT NOT NULL,
447 + `user_agent` TEXT NULL,
448 + `ip_address` VARCHAR(255) NULL,
449 + `referer_url` TEXT NULL,
450 + `submitted_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
451 +) {$charset_collate};"
452 + );
453 +}
454 +
455 +function _hf_on_add_user_to_blog( $user_id, $role, $blog_id ) {
456 + if ( 'administrator' !== $role ) {
457 + return;
458 + }
459 +
460 + // add "edit_forms" cap to site admin
461 + $user = new \WP_User( (int) $user_id );
462 + $user->add_cap( 'edit_forms', true );
463 +}
464 +
465 +function _hf_on_wp_insert_site( \WP_Site $site ) {
466 + switch_to_blog( (int) $site->blog_id );
467 + _hf_create_submissions_table();
468 + restore_current_blog();
469 +}