PluginProbe
HTML Forms – Simple WordPress Forms Plugin / 1.4.2
HTML Forms – Simple WordPress Forms Plugin v1.4.2
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 1.3.17 All 66 releases
html-forms / src / functions.php

functions.php in HTML Forms – Simple WordPress Forms Plugin 1.4.2, at src/functions.php

476 lines 12.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use HTML_Forms\Form;
4 use HTML_Forms\Submission;
5
6 /**
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
27 * @return Form
28 * @throws Exception
29 */
30 function hf_get_form( $form_id_or_slug ) {
31
32 if ( is_numeric( $form_id_or_slug ) || $form_id_or_slug instanceof WP_Post ) {
33 $post = get_post( $form_id_or_slug );
34
35 if ( ! $post instanceof WP_Post || $post->post_type !== 'html-form' ) {
36 throw new Exception( 'Invalid form ID' );
37 }
38 } else {
39
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 }
56
57 // get all post meta in a single call for performance
58 $post_meta = get_post_meta( $post->ID );
59
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 );
74
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 );
91
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 }
101
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;
111 }
112
113 /**
114 * @param $form_id
115 * @param array $args
116 * @return Submission[]
117 */
118 function hf_get_form_submissions( $form_id, array $args = array() ) {
119 $default_args = array(
120 'offset' => 0,
121 'limit' => 1000,
122 );
123 $args = array_merge( $default_args, $args );
124
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;
134 }
135
136 /**
137 * @param int $submission_id
138 * @return Submission
139 */
140 function hf_get_form_submission( $submission_id ) {
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;
146 }
147 /**
148 * @return array
149 */
150 function hf_get_settings() {
151 $default_settings = array(
152 'load_stylesheet' => 0,
153 'wrapper_tag' => 'p',
154 );
155
156 $settings = get_option( 'hf_settings', null );
157
158 // prevent a SQL query when option does not yet exist
159 if ( $settings === null ) {
160 update_option( 'hf_settings', array(), true );
161 $settings = array();
162 }
163
164 // merge with default settings
165 $settings = array_merge( $default_settings, $settings );
166
167 /**
168 * Filters the global HTML Forms hf_settings
169 *
170 * @param array $settings
171 */
172 $settings = apply_filters( 'hf_settings', $settings );
173
174 return $settings;
175 }
176
177 /**
178 * Get element from array, allows for dot notation eg: "foo.bar"
179 *
180 * @param array $array
181 * @param string $key
182 * @param mixed $default
183 * @return mixed
184 */
185 function hf_array_get( $array, $key, $default = null ) {
186 if ( is_null( $key ) ) {
187 return $array;
188 }
189
190 if ( isset( $array[ $key ] ) ) {
191 return $array[ $key ];
192 }
193
194 foreach ( explode( '.', $key ) as $segment ) {
195 if ( ! is_array( $array ) || ! array_key_exists( $segment, $array ) ) {
196 return $default;
197 }
198
199 $array = $array[ $segment ];
200 }
201
202 return $array;
203 }
204
205 /**
206 * Processes template tags like {{user.user_email}}
207 *
208 * @param string $template
209 *
210 * @return string
211 */
212 function hf_template( $template ) {
213 $replacers = new HTML_Forms\TagReplacers();
214 $tags = array(
215 'user' => array( $replacers, 'user' ),
216 'post' => array( $replacers, 'post' ),
217 'url_params' => array( $replacers, 'url_params' ),
218 );
219
220 /**
221 * Filters the available tags in HTML Forms templates, like {{user.user_email}}.
222 *
223 * Can be used to add simple scalar replacements or more advanced replacement functions that accept a parameter.
224 *
225 * @param array $tags
226 */
227 $tags = apply_filters( 'hf_template_tags', $tags );
228
229 $template = preg_replace_callback(
230 '/\{\{ *(\w+)(?:\.([\w\.]+))? *(?:\|\| *(\w+))? *\}\}/',
231 function( $matches ) use ( $tags ) {
232 $tag = $matches[1];
233 $param = ! isset( $matches[2] ) ? '' : $matches[2];
234 $default = ! isset( $matches[3] ) ? '' : $matches[3];
235
236 // do not change anything if we have no replacer with that key, could be custom user logic or another plugin.
237 if ( ! isset( $tags[ $tag ] ) ) {
238 return $matches[0];
239 }
240
241 $replacement = $tags[ $tag ];
242 $value = is_callable( $replacement ) ? call_user_func_array( $replacement, array( $param ) ) : $replacement;
243 return ! empty( $value ) ? $value : $default;
244 },
245 $template
246 );
247
248 return $template;
249 }
250
251 /**
252 * @param string $string
253 * @param array $data
254 * @param Closure|string $escape_function
255 * @return string
256 */
257 function hf_replace_data_variables( $string, $data = array(), $escape_function = null ) {
258 return preg_replace_callback(
259 '/\[(.+?)\]/',
260 function( $matches ) use ( $data, $escape_function ) {
261 $key = $matches[1];
262 // replace spaces in name with underscores to match PHP requirement for keys in $_POST superglobal
263 $key = str_replace( ' ', '_', $key );
264 $replacement = hf_array_get( $data, $key, '' );
265 $replacement = hf_field_value( $replacement, 0, $escape_function );
266 return $replacement;
267 },
268 $string
269 );
270 }
271
272 /**
273 * Returns a formatted & HTML-escaped field value. Detects file-, array- and date-types.
274 *
275 * 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).
276 *
277 * @param string|array $value
278 * @param int $limit
279 * @param Closure|string $escape_function
280 * @return string
281 * @since 1.3.1
282 */
283 function hf_field_value( $value, $limit = 0, $escape_function = 'esc_html' ) {
284 if ( $value === '' ) {
285 return $value;
286 }
287
288 if ( hf_is_file( $value ) ) {
289 $file_url = isset( $value['url'] ) ? $value['url'] : '';
290 if ( isset( $value['attachment_id'] ) && apply_filters( 'hf_file_upload_use_direct_links', false ) === false ) {
291 $file_url = admin_url( sprintf( 'post.php?action=edit&post=%d', $value['attachment_id'] ) );
292 }
293 $short_name = substr( $value['name'], 0, 20 );
294 $suffix = strlen( $value['name'] ) > 20 ? '...' : '';
295 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'] ) );
296 }
297
298 if ( hf_is_date( $value ) ) {
299 $date_format = get_option( 'date_format' );
300 return gmdate( $date_format, strtotime( str_replace( '/', '-', $value ) ) );
301 }
302
303 // join array-values with comma
304 if ( is_array( $value ) ) {
305 $value = join( ', ', $value );
306 }
307
308 // limit string to certain length
309 if ( $limit > 0 ) {
310 $limited = strlen( $value ) > $limit;
311 $value = substr( $value, 0, $limit );
312
313 if ( $limited ) {
314 $value .= '...';
315 }
316 }
317
318 // escape value
319 if ( $escape_function !== null && is_callable( $escape_function ) ) {
320 $value = $escape_function( $value );
321 }
322
323 // add line breaks, if not string limited to certain length
324 if ( $limit === 0 ) {
325 $value = nl2br( $value );
326 }
327
328 return $value;
329 }
330
331 /**
332 * Returns true if value is a "file"
333 *
334 * @param mixed $value
335 * @return bool
336 */
337 function hf_is_file( $value ) {
338 return is_array( $value )
339 && isset( $value['name'] )
340 && isset( $value['size'] )
341 && isset( $value['type'] );
342 }
343
344 /**
345 * Returns true if value looks like a date-string submitted from a <input type="date">
346 * @param mixed $value
347 * @return bool
348 * @since 1.3.1
349 */
350 function hf_is_date( $value ) {
351 if ( ! is_string( $value )
352 || strlen( $value ) !== 10
353 || (int) preg_match( '/\d{2,4}[-\/]\d{2}[-\/]\d{2,4}/', $value ) === 0 ) {
354 return false;
355 }
356
357 $timestamp = strtotime( $value );
358 return $timestamp != false;
359 }
360
361 /**
362 * @param int $size
363 * @param int $precision
364 * @return string
365 */
366 function hf_human_filesize( $size, $precision = 2 ) {
367 for ( $i = 0; ( $size / 1024 ) > 0.9; $i++, $size /= 1024 ) {
368 // nothing, loop logic contains everything
369 }
370 $steps = array( 'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' );
371 return round( $size, $precision ) . $steps[ $i ];
372 }
373
374 /**
375 * Gets all the form tabs to show in the admin.
376 * @param Form $form
377 * @return array
378 */
379 function hf_get_admin_tabs( Form $form ) {
380 $tabs = array(
381 'fields' => __( 'Fields', 'html-forms' ),
382 'messages' => __( 'Messages', 'html-forms' ),
383 'settings' => __( 'Settings', 'html-forms' ),
384 'actions' => __( 'Actions', 'html-forms' ),
385 );
386
387 if ( $form->settings['save_submissions'] ) {
388 $tabs['submissions'] = __( 'Submissions', 'html-forms' );
389 }
390 return apply_filters( 'hf_admin_tabs', $tabs, $form );
391 }
392
393 function _hf_on_plugin_activation() {
394 if ( is_multisite() ) {
395 _hf_on_plugin_activation_multisite();
396 return;
397 }
398
399 // install table for regular wp install
400 _hf_create_submissions_table();
401
402 // add "edit_forms" cap to user that activated the plugin
403 $user = wp_get_current_user();
404 $user->add_cap( 'edit_forms', true );
405 }
406
407 function _hf_on_plugin_activation_multisite() {
408 $added_caps = array();
409
410 foreach ( get_sites( array( 'number' => PHP_INT_MAX ) ) as $site ) {
411 switch_to_blog( (int) $site->blog_id );
412
413 // install table for current blog
414 _hf_create_submissions_table();
415
416 // iterate through current blog admins
417 foreach ( get_users(
418 array(
419 'blog_id' => (int) $site->blog_id,
420 'role' => 'administrator',
421 'fields' => 'ID',
422 )
423 ) as $admin_id ) {
424 if ( ! (int) $admin_id || in_array( $admin_id, $added_caps ) ) {
425 continue;
426 }
427
428 // add "edit_forms" cap to site admin
429 $user = new \WP_User( (int) $admin_id );
430 $user->add_cap( 'edit_forms', true );
431
432 $added_caps[] = $admin_id;
433 }
434
435 restore_current_blog();
436 }
437 }
438
439 // install table for main site on regular installs, or active site for multisite
440 function _hf_create_submissions_table() {
441 /** @var wpdb */
442 global $wpdb;
443
444 $charset_collate = $wpdb->get_charset_collate();
445
446 // create table for storing submissions
447 $table = $wpdb->prefix . 'hf_submissions';
448 $wpdb->query(
449 "CREATE TABLE IF NOT EXISTS {$table}(
450 `id` INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
451 `form_id` INT UNSIGNED NOT NULL,
452 `data` TEXT NOT NULL,
453 `user_agent` TEXT NULL,
454 `ip_address` VARCHAR(255) NULL,
455 `referer_url` TEXT NULL,
456 `submitted_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
457 ) {$charset_collate};"
458 );
459 }
460
461 function _hf_on_add_user_to_blog( $user_id, $role, $blog_id ) {
462 if ( 'administrator' !== $role ) {
463 return;
464 }
465
466 // add "edit_forms" cap to site admin
467 $user = new \WP_User( (int) $user_id );
468 $user->add_cap( 'edit_forms', true );
469 }
470
471 function _hf_on_wp_insert_site( \WP_Site $site ) {
472 switch_to_blog( (int) $site->blog_id );
473 _hf_create_submissions_table();
474 restore_current_blog();
475 }
476