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