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