PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 1.07.11
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v1.07.11
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | classes/models/FrmForm.php +307 -1356 6.311.07.11 View file →
@@ -1,1398 +1,349 @@
1 1 <?php
2 -if ( ! defined( 'ABSPATH' ) ) {
3 - die( 'You are not allowed to call this page directly.' );
4 -}
2 +if(!defined('ABSPATH')) die(__('You are not allowed to call this page directly.', 'formidable'));
5 3
6 -class FrmForm {
4 +if(class_exists('FrmForm'))
5 + return;
7 6
8 - /**
9 - * @param array $values
10 - *
11 - * @return bool|int id on success or false on failure.
12 - */
13 - public static function create( $values ) {
14 - global $wpdb;
7 +class FrmForm{
15 8
16 - $values = FrmAppHelper::maybe_filter_array( $values, array( 'name', 'description' ) );
9 + function create( $values ) {
10 + global $wpdb, $frm_settings;
17 11
18 - $new_values = array(
19 - 'form_key' => FrmAppHelper::get_unique_key( $values['form_key'], $wpdb->prefix . 'frm_forms', 'form_key' ),
20 - 'name' => FrmAppHelper::truncate( $values['name'], 255, 1, '', true ),
21 - 'description' => $values['description'],
22 - 'status' => $values['status'] ?? 'published',
23 - 'logged_in' => $values['logged_in'] ?? 0,
24 - 'is_template' => isset( $values['is_template'] ) ? (int) $values['is_template'] : 0,
25 - 'parent_form_id' => isset( $values['parent_form_id'] ) ? absint( $values['parent_form_id'] ) : 0,
26 - 'editable' => isset( $values['editable'] ) ? (int) $values['editable'] : 0,
27 - 'created_at' => $values['created_at'] ?? current_time( 'mysql', 1 ),
28 - );
12 + $new_values = array(
13 + 'form_key' => FrmAppHelper::get_unique_key($values['form_key'], $wpdb->prefix .'frm_forms', 'form_key'),
14 + 'name' => $values['name'],
15 + 'description' => $values['description'],
16 + 'status' => isset($values['status']) ? $values['status'] : 'draft',
17 + 'is_template' => isset($values['is_template']) ? (int) $values['is_template'] : 0,
18 + 'editable' => isset($values['editable']) ? (int) $values['editable'] : 0,
19 + 'default_template' => isset($values['default_template']) ? (int) $values['default_template'] : 0,
20 + 'created_at' => isset($values['created_at']) ? $values['created_at'] : current_time('mysql', 1),
21 + );
22 +
23 + $options = array();
29 24
30 - $options = isset( $values['options'] ) ? (array) $values['options'] : array();
31 - FrmFormsHelper::fill_form_options( $options, $values );
25 + $defaults = FrmFormsHelper::get_default_opts();
26 + foreach ($defaults as $var => $default) {
27 + $options[$var] = isset($values['options'][$var]) ? $values['options'][$var] : $default;
28 + unset($var);
29 + unset($default);
30 + }
32 31
33 - $options['before_html'] = $values['options']['before_html'] ?? FrmFormsHelper::get_default_html( 'before' );
34 - $options['after_html'] = $values['options']['after_html'] ?? FrmFormsHelper::get_default_html( 'after' );
35 - $options['submit_html'] = $values['options']['submit_html'] ?? FrmFormsHelper::get_default_html( 'submit' );
32 + $options['before_html'] = isset($values['options']['before_html']) ? $values['options']['before_html'] : FrmFormsHelper::get_default_html('before');
33 + $options['after_html'] = isset($values['options']['after_html']) ? $values['options']['after_html'] : FrmFormsHelper::get_default_html('after');
34 + $options['submit_html'] = isset($values['options']['submit_html']) ? $values['options']['submit_html'] : FrmFormsHelper::get_default_html('submit');
36 35
37 - /**
38 - * Allows modifying form options before updating or creating.
39 - *
40 - * @since 5.4 Add the third param.
41 - *
42 - * @param array $options Form options.
43 - * @param array $values Form data.
44 - * @param bool $update Is form updating or creating. It's `true` if is updating.
45 - */
46 - $options = apply_filters( 'frm_form_options_before_update', $options, $values, false );
47 - $options = self::maybe_filter_form_options( $options );
48 - $new_values['options'] = serialize( $options );
36 + $options = apply_filters('frm_form_options_before_update', $options, $values);
37 + $new_values['options'] = serialize($options);
49 38
50 - $wpdb->insert( $wpdb->prefix . 'frm_forms', $new_values );
39 + //if(isset($values['id']) && is_numeric($values['id']))
40 + // $new_values['id'] = $values['id'];
51 41
52 - $id = $wpdb->insert_id;
42 + $query_results = $wpdb->insert( $wpdb->prefix .'frm_forms', $new_values );
53 43
54 - // Clear form caching
55 - self::clear_form_cache();
44 + return $wpdb->insert_id;
45 + }
46 +
47 + function duplicate( $id, $template = false, $copy_keys = false, $blog_id = false ) {
48 + global $wpdb;
56 49
57 - return $id;
58 - }
50 + $frm_form = new FrmForm();
51 + $values = $frm_form->getOne( $id, $blog_id );
52 + if ( !$values ) {
53 + return false;
54 + }
55 +
56 + $new_key = $copy_keys ? $values->form_key : '';
57 +
58 + $new_values = array(
59 + 'form_key' => FrmAppHelper::get_unique_key($new_key, $wpdb->prefix .'frm_forms', 'form_key'),
60 + 'name' => $values->name,
61 + 'description' => $values->description,
62 + 'status' => $template ? '' : 'draft',
63 + 'logged_in' => $values->logged_in ? $values->logged_in : 0,
64 + 'editable' => $values->editable ? $values->editable : 0,
65 + 'created_at' => current_time('mysql', 1),
66 + 'is_template' => $template ? 1 : 0,
67 + );
59 68
60 - /**
61 - * @since 5.0.08
62 - *
63 - * @param array $options
64 - *
65 - * @return array
66 - */
67 - private static function maybe_filter_form_options( $options ) {
68 - if ( ! FrmAppHelper::allow_unfiltered_html() && ! empty( $options['submit_html'] ) ) {
69 - $options['submit_html'] = FrmAppHelper::kses_submit_button( $options['submit_html'] );
70 - }
71 - return FrmAppHelper::maybe_filter_array( $options, array( 'submit_value', 'success_msg', 'before_html', 'after_html' ) );
72 - }
69 + if ( $blog_id ) {
70 + $new_values['status'] = 'published';
71 + $new_options = maybe_unserialize($values->options);
72 + $new_options['email_to'] = get_option('admin_email');
73 + $new_options['copy'] = false;
74 + $new_values['options'] = $new_options;
75 + } else {
76 + $new_values['options'] = $values->options;
77 + }
73 78
74 - /**
75 - * Duplicate a form.
76 - *
77 - * @param int $id Form ID to duplicate.
78 - * @param bool $template Whether the duplicated form is a template.
79 - * @param bool $copy_keys Whether to copy the original form key.
80 - * @param false|int $blog_id Blog ID when duplicating across sites, or false for current site.
81 - *
82 - * @return bool|int ID on success or false on failure
83 - */
84 - public static function duplicate( $id, $template = false, $copy_keys = false, $blog_id = false ) {
85 - global $wpdb;
79 + if ( is_array($new_values['options']) ) {
80 + $new_values['options'] = serialize($new_values['options']);
81 + }
86 82
87 - $values = self::getOne( $id, $blog_id );
83 + $query_results = $wpdb->insert( $wpdb->prefix .'frm_forms', $new_values );
84 +
85 + if ( $query_results ) {
86 + global $frm_field;
87 + $form_id = $wpdb->insert_id;
88 + $frm_field->duplicate($id, $form_id, $copy_keys, $blog_id);
89 +
90 + // update form settings after fields are created
91 + do_action('frm_after_duplicate_form', $form_id, $new_values);
92 + return $form_id;
93 + } else {
94 + return false;
95 + }
96 + }
97 +
98 + function after_duplicate($form_id, $values) {
99 + $new_opts = $values['options'] = maybe_unserialize($values['options']);
100 +
101 + if ( isset($new_opts['success_msg']) ) {
102 + $new_opts['success_msg'] = FrmFieldsHelper::switch_field_ids($new_opts['success_msg']);
103 + }
104 +
105 + $new_opts = apply_filters('frm_after_duplicate_form_values', $new_opts, $form_id);
106 +
107 + if ( $new_opts != $values['options'] ) {
108 + global $wpdb;
109 + $wpdb->update($wpdb->prefix .'frm_forms', array('options' => maybe_serialize($new_opts)), array('id' => $form_id));
110 + }
111 + }
88 112
89 - if ( ! $values ) {
90 - return false;
91 - }
113 + function update( $id, $values, $create_link = false ) {
114 + global $wpdb, $frm_field, $frm_settings;
92 115
93 - $new_key = $copy_keys ? $values->form_key : '';
116 + if ( $create_link || isset($values['options']) || isset($values['item_meta']) || isset($values['field_options']) ) {
117 + $values['status'] = 'published';
118 + }
94 119
95 - $new_values = array(
96 - 'form_key' => FrmAppHelper::get_unique_key( $new_key, $wpdb->prefix . 'frm_forms', 'form_key' ),
97 - 'name' => $values->name,
98 - 'description' => $values->description,
99 - 'status' => $values->status ? $values->status : 'published',
100 - 'logged_in' => $values->logged_in ? $values->logged_in : 0,
101 - 'editable' => $values->editable ? $values->editable : 0,
102 - 'created_at' => current_time( 'mysql', 1 ),
103 - 'is_template' => $template ? 1 : 0,
104 - );
120 + if ( isset($values['form_key']) ) {
121 + $values['form_key'] = FrmAppHelper::get_unique_key($values['form_key'], $wpdb->prefix .'frm_forms', 'form_key', $id);
122 + }
105 123
106 - if ( $blog_id ) {
107 - $new_values['status'] = 'published';
108 - $new_options = $values->options;
109 - FrmAppHelper::unserialize_or_decode( $new_options );
110 - $new_options['email_to'] = get_option( 'admin_email' );
111 - $new_options['copy'] = false;
112 - $new_values['options'] = $new_options;
113 - } else {
114 - $new_values['options'] = $values->options;
115 - }
124 + $form_fields = array( 'form_key', 'name', 'description', 'status', 'prli_link_id' );
116 125
117 - if ( is_array( $new_values['options'] ) ) {
118 - $new_values['options'] = serialize( $new_values['options'] );
119 - }
126 + $new_values = array();
120 127
121 - $query_results = $wpdb->insert( $wpdb->prefix . 'frm_forms', $new_values );
128 + if (isset($values['options'])){
129 + $options = array();
122 130
123 - if ( $query_results ) {
124 - // Clear form caching
125 - self::clear_form_cache();
131 + $defaults = FrmFormsHelper::get_default_opts();
132 + foreach ($defaults as $var => $default) {
133 + if ( $var == 'notification' && !defined('WP_IMPORTING')) {
134 + $options[$var] = isset($values[$var]) ? $values[$var] : $default;
135 + } else {
136 + $options[$var] = isset($values['options'][$var]) ? $values['options'][$var] : $default;
137 + }
138 + }
139 +
140 + $options['custom_style'] = isset($values['options']['custom_style']) ? $values['options']['custom_style'] : 0;
141 + $options['before_html'] = isset($values['options']['before_html']) ? $values['options']['before_html'] : FrmFormsHelper::get_default_html('before');
142 + $options['after_html'] = isset($values['options']['after_html']) ? $values['options']['after_html'] : FrmFormsHelper::get_default_html('after');
143 + $options['submit_html'] = (isset($values['options']['submit_html']) && $values['options']['submit_html'] != '') ? $values['options']['submit_html'] : FrmFormsHelper::get_default_html('submit');
126 144
127 - $form_id = $wpdb->insert_id;
128 - FrmField::duplicate( $id, $form_id, $copy_keys, $blog_id );
145 + $options = apply_filters('frm_form_options_before_update', $options, $values);
146 + $new_values['options'] = serialize($options);
147 + }
129 148
130 - // Update form settings after fields are created
131 - do_action( 'frm_after_duplicate_form', $form_id, $new_values, array( 'old_id' => $id ) );
149 + foreach ( $values as $value_key => $value ) {
150 + if ( in_array($value_key, $form_fields) ) {
151 + $new_values[$value_key] = $value;
152 + }
153 + }
132 154
133 - return $form_id;
134 - }
155 + if ( !empty($new_values) ) {
156 + $query_results = $wpdb->update( $wpdb->prefix .'frm_forms', $new_values, array( 'id' => $id ) );
157 + if ( $query_results ) {
158 + wp_cache_delete( $id, 'frm_form');
159 + }
160 + } else {
161 + $query_results = true;
162 + }
135 163
136 - return false;
137 - }
164 + $all_fields = $frm_field->getAll(array('fi.form_id' => $id), 'field_order');
165 + if ( $all_fields && (isset($values['options']) || isset($values['item_meta']) || isset($values['field_options'])) ) {
166 + if ( !isset($values['item_meta']) ) {
167 + $values['item_meta'] = array();
168 + }
169 + $existing_keys = array_keys($values['item_meta']);
138 170
139 - /**
140 - * @param int $form_id
141 - * @param array $values
142 - *
143 - * @return void
144 - */
145 - public static function after_duplicate( $form_id, $values ) {
146 - $new_opts = $values['options'];
147 - FrmAppHelper::unserialize_or_decode( $new_opts );
148 - $values['options'] = $new_opts;
171 + foreach ( $all_fields as $fid ) {
172 + if ( !in_array($fid->id, $existing_keys) && ( isset($values['frm_fields_submitted']) && in_array($fid->id, $values['frm_fields_submitted']) ) || isset($values['options']) ) {
173 + $values['item_meta'][$fid->id] = '';
174 + }
175 + }
176 +
177 + foreach ( $values['item_meta'] as $field_id => $default_value ) {
178 + $field = $frm_field->getOne($field_id);
179 + if (!$field) continue;
180 + $field_options = maybe_unserialize($field->field_options);
149 181
150 - if ( isset( $new_opts['success_msg'] ) ) {
151 - $new_opts['success_msg'] = FrmFieldsHelper::switch_field_ids( $new_opts['success_msg'] );
152 - }
182 + if ( isset($values['options']) || isset($values['field_options']['custom_html_'. $field_id]) ) {
183 + //updating the settings page
184 + if(isset($values['field_options']['custom_html_'.$field_id])){
185 + $field_options['custom_html'] = isset($values['field_options']['custom_html_'.$field_id]) ? $values['field_options']['custom_html_'.$field_id] : (isset($field_options['custom_html']) ? $field_options['custom_html'] : FrmFieldsHelper::get_default_html($field->type));
186 + $field_options = apply_filters('frm_update_form_field_options', $field_options, $field, $values);
187 + $frm_field->update($field_id, array('field_options' => $field_options));
188 + }else if($field->type == 'hidden' || $field->type == 'user_id'){
189 + $prev_opts = $field_options;
190 + $field_options = apply_filters('frm_update_form_field_options', $field_options, $field, $values);
191 + if($prev_opts != $field_options)
192 + $frm_field->update($field_id, array('field_options' => $field_options));
193 + unset($prev_opts);
194 + }
195 + }
196 +
197 + if ( (!isset($values['options']) && !isset($values['field_options']['custom_html_'. $field_id])) || defined('WP_IMPORTING') ) {
198 + //updating the form
199 + foreach ( array('size', 'max', 'label', 'invalid', 'blank', 'classes') as $opt ) {
200 + $field_options[$opt] = isset($values['field_options'][$opt.'_'.$field_id]) ? trim($values['field_options'][$opt.'_'.$field_id]) : '';
201 + }
153 202
154 - $new_opts = apply_filters( 'frm_after_duplicate_form_values', $new_opts, $form_id );
203 + $field_options['required_indicator'] = isset($values['field_options']['required_indicator_'. $field_id]) ? trim($values['field_options']['required_indicator_'. $field_id]) : '*';
204 + $field_options['separate_value'] = isset($values['field_options']['separate_value_'.$field_id]) ? trim($values['field_options']['separate_value_'.$field_id]) : 0;
155 205
156 - // phpcs:ignore Universal.Operators.StrictComparisons
157 - if ( $new_opts != $values['options'] ) {
158 - global $wpdb;
159 - $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'options' => maybe_serialize( $new_opts ) ), array( 'id' => $form_id ) );
160 - }
206 + $field_options = apply_filters('frm_update_field_options', $field_options, $field, $values);
207 + $default_value = maybe_serialize($values['item_meta'][$field_id]);
208 + $field_key = (isset($values['field_options']['field_key_'.$field_id])) ? $values['field_options']['field_key_'.$field_id] : $field->field_key;
209 + $required = (isset($values['field_options']['required_'.$field_id])) ? $values['field_options']['required_'.$field_id] : false;
210 + $field_type = (isset($values['field_options']['type_'.$field_id])) ? $values['field_options']['type_'.$field_id] : $field->type;
211 + $field_description = (isset($values['field_options']['description_'.$field_id])) ? $values['field_options']['description_'.$field_id] : $field->description;
161 212
162 - self::switch_field_ids_in_fields( $form_id );
163 - }
213 + $frm_field->update($field_id, array('field_key' => $field_key, 'type' => $field_type, 'default_value' => $default_value, 'field_options' => $field_options, 'description' => $field_description, 'required' => $required));
214 + }
215 + }
216 + }
217 +
218 + do_action('frm_update_form', $id, $values);
219 + do_action('frm_update_form_'. $id, $values);
164 220
165 - /**
166 - * Switches field ID in fields.
167 - *
168 - * @since 5.3
169 - *
170 - * @param int $form_id Form ID.
171 - *
172 - * @return void
173 - */
174 - private static function switch_field_ids_in_fields( $form_id ) {
175 - global $wpdb;
221 + return $query_results;
222 + }
176 223
177 - // Keys of fields that you want to check to replace field ID.
178 - $keys = array( 'default_value', 'field_options' );
179 - $sql_cols = 'fi.id';
224 + function destroy( $id ){
225 + global $wpdb, $frm_entry;
180 226
181 - foreach ( $keys as $key ) {
182 - $sql_cols .= ',fi.' . $key;
183 - }
227 + $form = $this->getOne($id);
228 + if ( !$form || $form->default_template ) {
229 + return false;
230 + }
184 231
185 - $fields = FrmDb::get_results(
186 - "{$wpdb->prefix}frm_fields AS fi LEFT OUTER JOIN {$wpdb->prefix}frm_forms AS fr ON fi.form_id = fr.id",
187 - array(
188 - 'or' => 1,
189 - 'fi.form_id' => $form_id,
190 - 'fr.parent_form_id' => $form_id,
191 - ),
192 - $sql_cols
193 - );
232 + // Disconnect the items from this form
233 + $entries = $frm_entry->getAll(array('it.form_id' => $id));
234 + foreach ( $entries as $item ) {
235 + $frm_entry->destroy($item->id);
236 + unset($item);
237 + }
238 + // Disconnect the fields from this form
239 + $query_results = $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}frm_fields WHERE form_id=%d", $id));
194 240
195 - if ( ! $fields || ! is_array( $fields ) ) {
196 - return;
197 - }
241 + $query_results = $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}frm_forms WHERE id=%d", $id));
242 + if ( $query_results ) {
243 + do_action('frm_destroy_form', $id);
244 + do_action('frm_destroy_form_'. $id);
245 + }
246 + return $query_results;
247 + }
248 +
249 + function getName( $id ) {
250 + global $wpdb;
251 + $cache = wp_cache_get($id, 'frm_form');
252 + if ( $cache ) {
253 + return stripslashes($cache->name);
254 + }
255 + $query = "SELECT name FROM {$wpdb->prefix}frm_forms WHERE ";
256 + $query .= (is_numeric($id)) ? "id=%d" : "form_key=%s";
257 + $query = $wpdb->prepare($query, $id);
258 +
259 + $r = $wpdb->get_var($query);
260 + return stripslashes($r);
261 + }
262 +
263 + function getIdByKey( $key ){
264 + global $wpdb;
265 + $query = $wpdb->prepare("SELECT id FROM {$wpdb->prefix}frm_forms WHERE form_key=%s LIMIT 1", $key);
266 + return $wpdb->get_var($query);
267 + }
198 268
199 - foreach ( $fields as $field ) {
200 - self::switch_field_ids_in_field( (array) $field );
201 - }
202 - }
269 + function getOne( $id, $blog_id=false ){
270 + global $wpdb, $frmdb;
271 +
272 + if ( $blog_id && is_multisite() ) {
273 + global $wpmuBaseTablePrefix;
274 + $prefix = $wpmuBaseTablePrefix ? "{$wpmuBaseTablePrefix}{$blog_id}_" : $wpdb->get_blog_prefix( $blog_id );
275 +
276 + $table_name = "{$prefix}frm_forms";
277 + } else {
278 + $table_name = $wpdb->prefix .'frm_forms';
279 + $cache = wp_cache_get($id, 'frm_form');
280 + if ( $cache ) {
281 + if ( isset($cache->options) ) {
282 + $cache->options = maybe_unserialize($cache->options);
283 + }
284 +
285 + return stripslashes_deep($cache);
286 + }
287 + }
288 +
289 + $where = $wpdb->prepare( is_numeric($id) ? 'id=%d' : 'form_key=%s', $id );
290 +
291 + $results = $wpdb->get_row("SELECT * FROM $table_name WHERE $where");
292 +
293 + if ( isset($results->options) ) {
294 + wp_cache_set($results->id, $results, 'frm_form');
295 + $results->options = maybe_unserialize($results->options);
296 + }
297 + return stripslashes_deep($results);
298 + }
203 299
204 - /**
205 - * Switches field ID in a field.
206 - *
207 - * @since 5.3
208 - *
209 - * @param array $field Field array.
210 - *
211 - * @return void
212 - */
213 - private static function switch_field_ids_in_field( $field ) {
214 - $new_values = array();
300 + function getAll( $where = array(), $order_by = '', $limit = '' ){
301 + global $wpdb, $frmdb;
302 +
303 + if(is_numeric($limit))
304 + $limit = " LIMIT {$limit}";
305 +
306 + $query = 'SELECT * FROM ' . $wpdb->prefix .'frm_forms' . FrmAppHelper::prepend_and_or_where(' WHERE ', $where) . $order_by . $limit;
307 +
308 + if ($limit == ' LIMIT 1' || $limit == 1){
309 + if(is_array($where))
310 + $results = $frmdb->get_one_record($wpdb->prefix .'frm_forms', $where, '*', $order_by);
311 + else
312 + $results = $wpdb->get_row($query);
313 +
314 + if($results){
315 + wp_cache_set($results->id, $results, 'frm_form');
316 + $results->options = maybe_unserialize($results->options);
317 + }
318 + }else{
319 + if ( is_array($where) && !empty($where) ) {
320 + $results = $frmdb->get_records($wpdb->prefix .'frm_forms', $where, $order_by, $limit);
321 + } else {
322 + $results = $wpdb->get_results($query);
323 + }
324 +
325 + if($results){
326 + foreach($results as $result){
327 + wp_cache_set($result->id, $result, 'frm_form');
328 + $result->options = maybe_unserialize($result->options);
329 + }
330 + }
331 + }
332 +
333 + return stripslashes_deep($results);
334 + }
215 335
216 - foreach ( $field as $key => $value ) {
217 - if ( 'id' === $key || ! $value ) {
218 - continue;
219 - }
336 + function validate( $values ){
337 + $errors = array();
220 338
221 - if ( ! is_string( $value ) && ! is_array( $value ) ) {
222 - continue;
223 - }
339 + /*if( $values['form_key'] == null || $values['form_key'] == '' ){
340 + if( $values['name'] == null || $values['name'] == '' )
341 + $errors[] = "Key can't be blank";
342 + else
343 + $_POST['form_key'] = $values['name'];
344 + }*/
345 +
346 + return apply_filters('frm_validate_form', $errors, $values);
347 + }
224 348
225 - if ( 'field_options' === $key ) {
226 - // Need to loop through field_options to prevent breaking serialized string when length changed.
227 - FrmAppHelper::unserialize_or_decode( $value );
228 - $new_val = FrmFieldsHelper::switch_field_ids( $value );
229 - $new_val = serialize( $new_val );
230 - } else {
231 - $new_val = FrmFieldsHelper::switch_field_ids( $value );
232 - }
233 -
234 - if ( $new_val !== $value ) {
235 - $new_values[ $key ] = $new_val;
236 - }
237 - }//end foreach
238 -
239 - if ( $new_values ) {
240 - FrmField::update( $field['id'], $new_values );
241 - }
242 - }
243 -
244 - /**
245 - * Update a form.
246 - *
247 - * @param int $id Form ID.
248 - * @param array $values Form values to update.
249 - * @param bool $create_link Whether this is being called from link creation.
250 - *
251 - * @return bool|int
252 - */
253 - public static function update( $id, $values, $create_link = false ) {
254 - global $wpdb;
255 -
256 - $values = FrmAppHelper::maybe_filter_array( $values, array( 'name', 'description' ) );
257 -
258 - if ( ! isset( $values['status'] ) && ( $create_link || isset( $values['options'] ) || isset( $values['item_meta'] ) || isset( $values['field_options'] ) ) ) {
259 - $values['status'] = 'published';
260 - }
261 -
262 - if ( isset( $values['form_key'] ) ) {
263 - $values['form_key'] = FrmAppHelper::get_unique_key( $values['form_key'], $wpdb->prefix . 'frm_forms', 'form_key', $id );
264 - }
265 -
266 - $form_fields = array( 'form_key', 'name', 'description', 'status', 'parent_form_id' );
267 - $new_values = self::set_update_options( array(), $values, array( 'form_id' => $id ) );
268 -
269 - foreach ( $values as $value_key => $value ) {
270 - if ( $value_key && in_array( $value_key, $form_fields, true ) ) {
271 - $new_values[ $value_key ] = 'name' === $value_key ? FrmAppHelper::truncate( $value, 255, 1, '', true ) : $value;
272 - }
273 - }
274 -
275 - if ( ! empty( $values['new_status'] ) ) {
276 - $new_values['status'] = $values['new_status'];
277 - }
278 -
279 - if ( $new_values ) {
280 - $query_results = $wpdb->update( $wpdb->prefix . 'frm_forms', $new_values, array( 'id' => $id ) );
281 -
282 - if ( $query_results ) {
283 - self::clear_form_cache();
284 - }
285 - } else {
286 - $query_results = true;
287 - }
288 - unset( $new_values );
289 -
290 - $values = self::update_fields( $id, $values );
291 -
292 - do_action( 'frm_update_form', $id, $values );
293 - do_action( 'frm_update_form_' . $id, $values );
294 -
295 - return $query_results;
296 - }
297 -
298 - /**
299 - * @param array $new_values
300 - * @param array $values
301 - * @param array $args
302 - *
303 - * @return array
304 - */
305 - public static function set_update_options( $new_values, $values, $args = array() ) {
306 - if ( ! isset( $values['options'] ) ) {
307 - return $new_values;
308 - }
309 -
310 - $options = ! empty( $values['options'] ) ? (array) $values['options'] : array();
311 - FrmFormsHelper::fill_form_options( $options, $values );
312 -
313 - $options['custom_style'] = $values['options']['custom_style'] ?? 0;
314 - $options['before_html'] = $values['options']['before_html'] ?? FrmFormsHelper::get_default_html( 'before' );
315 - $options['after_html'] = $values['options']['after_html'] ?? FrmFormsHelper::get_default_html( 'after' );
316 - $options['submit_html'] = isset( $values['options']['submit_html'] ) && '' !== $values['options']['submit_html'] ? $values['options']['submit_html'] : FrmFormsHelper::get_default_html( 'submit' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
317 -
318 - /**
319 - * Allows modifying form options before updating or creating.
320 - *
321 - * @since 5.4 Added the third param.
322 - *
323 - * @param array $options Form options.
324 - * @param array $values Form data.
325 - * @param bool $update Is form updating or creating. It's `true` if is updating.
326 - */
327 - $options = apply_filters( 'frm_form_options_before_update', $options, $values, true );
328 - $options = self::maybe_filter_form_options( $options );
329 - $new_values['options'] = serialize( $options );
330 -
331 - return $new_values;
332 - }
333 -
334 - /**
335 - * @param int $id Form ID.
336 - * @param array $values Form values array.
337 - *
338 - * @return array
339 - */
340 - public static function update_fields( $id, $values ) { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
341 -
342 - if ( ! isset( $values['item_meta'] ) && ! isset( $values['field_options'] ) ) {
343 - return $values;
344 - }
345 -
346 - $all_fields = FrmField::get_all_for_form( $id );
347 -
348 - if ( ! $all_fields ) {
349 - return $values;
350 - }
351 -
352 - if ( ! isset( $values['item_meta'] ) ) {
353 - $values['item_meta'] = array();
354 - }
355 -
356 - $field_array = array();
357 - $existing_keys = array_keys( $values['item_meta'] );
358 -
359 - foreach ( $all_fields as $fid ) {
360 - // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict, SlevomatCodingStandard.Files.LineLength.LineTooLong
361 - if ( ! in_array( $fid->id, $existing_keys ) && ( isset( $values['frm_fields_submitted'] ) && in_array( $fid->id, $values['frm_fields_submitted'] ) ) || isset( $values['options'] ) ) {
362 - $values['item_meta'][ $fid->id ] = '';
363 - }
364 -
365 - $field_array[ $fid->id ] = $fid;
366 - }
367 - unset( $all_fields );
368 -
369 - foreach ( $values['item_meta'] as $field_id => $default_value ) {
370 - $field = $field_array[ $field_id ] ?? FrmField::getOne( $field_id );
371 -
372 - if ( ! $field ) {
373 - continue;
374 - }
375 -
376 - $is_settings_page = isset( $values['options'] ) || isset( $values['field_options'][ 'custom_html_' . $field_id ] );
377 -
378 - if ( $is_settings_page ) {
379 - self::get_settings_page_html( $values, $field );
380 -
381 - if ( ! defined( 'WP_IMPORTING' ) ) {
382 - continue;
383 - }
384 - }
385 -
386 - // Updating the form.
387 - $update_options = FrmFieldsHelper::get_default_field_options_from_field( $field );
388 - // Don't check for POST html.
389 - unset( $update_options['custom_html'] );
390 - $update_options = apply_filters( 'frm_field_options_to_update', $update_options );
391 -
392 - if ( ! is_array( $field->field_options ) ) {
393 - $field->field_options = array();
394 - }
395 -
396 - foreach ( $update_options as $opt => $default ) {
397 - $field->field_options[ $opt ] = $values['field_options'][ $opt . '_' . $field_id ] ?? $default;
398 - self::sanitize_field_opt( $opt, $field->field_options[ $opt ] );
399 - }
400 -
401 - $field->field_options = apply_filters( 'frm_update_field_options', $field->field_options, $field, $values );
402 -
403 - $new_field = array(
404 - 'field_options' => $field->field_options,
405 - 'default_value' => isset( $values[ 'default_value_' . $field_id ] ) ? FrmAppHelper::maybe_json_encode( $values[ 'default_value_' . $field_id ] ) : '',
406 - );
407 -
408 - if ( ! FrmAppHelper::allow_unfiltered_html() && isset( $values['field_options'][ 'options_' . $field_id ] ) && is_array( $values['field_options'][ 'options_' . $field_id ] ) ) { // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
409 - foreach ( $values['field_options'][ 'options_' . $field_id ] as $option_key => $option ) {
410 - if ( ! is_array( $option ) ) {
411 - continue;
412 - }
413 -
414 - foreach ( $option as $key => $item ) {
415 - $values['field_options'][ 'options_' . $field_id ][ $option_key ][ $key ] = FrmAppHelper::kses( $item, 'all' );
416 - }
417 - }
418 - }
419 -
420 - self::prepare_field_update_values( $field, $values, $new_field );
421 - self::maybe_update_max_option( $field, $values, $new_field );
422 -
423 - FrmField::update( $field_id, $new_field );
424 -
425 - FrmField::delete_form_transient( $field->form_id );
426 - }//end foreach
427 - self::clear_form_cache();
428 -
429 - return $values;
430 - }
431 -
432 - /**
433 - * Resets the 'max' option of a field when changing paragraph field type to other field types like text, email etc.
434 - *
435 - * @since 6.7
436 - *
437 - * @param object $field
438 - * @param array $values
439 - * @param array $new_field
440 - *
441 - * @return void
442 - */
443 - private static function maybe_update_max_option( $field, $values, &$new_field ) {
444 - if ( $field->type !== 'textarea' ||
445 - empty( $values['field_options'][ 'type_' . $field->id ] ) ||
446 - ! in_array( $values['field_options'][ 'type_' . $field->id ], array( 'text', 'email', 'url', 'password', 'phone' ), true ) ) {
447 - return;
448 - }
449 -
450 - $new_field['field_options']['max'] = '';
451 -
452 - /**
453 - * Update posted field setting so that new 'max' option is displayed after form is saved and page reloads.
454 - * FrmFieldsHelper::fill_default_field_opts populates field options by calling self::get_posted_field_setting.
455 - */
456 - $_POST['field_options'][ 'max_' . $field->id ] = '';
457 - }
458 -
459 - /**
460 - * @param string $opt
461 - * @param mixed $value
462 - *
463 - * @return void
464 - */
465 - private static function sanitize_field_opt( $opt, &$value ) {
466 - if ( ! is_string( $value ) ) {
467 - return;
468 - }
469 -
470 - /**
471 - * Allow the option to turn off sanitization for a field. This way a custom rule can be used instead.
472 - * Make sure to add custom sanitization using the frm_update_field_options filter as the data will no longer be sanitized.
473 - *
474 - * @since 6.0
475 - *
476 - * @param bool $should_sanitize
477 - * @param string $opt
478 - */
479 - $should_sanitize = apply_filters( 'frm_should_sanitize_field_opt_string', true, $opt );
480 -
481 - if ( ! $should_sanitize ) {
482 - return;
483 - }
484 -
485 - $value = $opt === 'calc' ? self::sanitize_calc( $value ) : FrmAppHelper::kses( $value, 'all' );
486 - $value = trim( $value );
487 - }
488 -
489 - /**
490 - * @param string $value
491 - *
492 - * @return string
493 - */
494 - private static function sanitize_calc( $value ) {
495 - if ( str_contains( $value, '<' ) ) {
496 - $value = self::normalize_calc_spaces( $value );
497 - }
498 - // Allow <= and >=.
499 - $allow = array( '<= ', ' >=' );
500 - $temp = array( '< = ', ' > =' );
501 - $value = str_replace( $allow, $temp, $value );
502 - $value = strip_tags( $value );
503 - return str_replace( $temp, $allow, $value );
504 - }
505 -
506 - /**
507 - * Format a comparison like 5<10 to 5 < 10. Also works on 5< 10, 5 <10, 5<=10 variations.
508 - * This is to avoid an issue with unspaced calculations being recognized as HTML that gets removed when strip_tags is called.
509 - *
510 - * @param string $calc
511 - *
512 - * @return string
513 - */
514 - private static function normalize_calc_spaces( $calc ) {
515 - // Check for a pattern with 5 parts
516 - // $1 \d|\] the first comparison digit or the end of a comparison shortcode.
517 - // $2 a space (optional).
518 - // $3 an equals sign (optional) that follows the < operator for <= comparisons.
519 - // $4 another space (optional).
520 - // $5 \d|\[ the second comparison digit or the start of a comparison shortcode.
521 - return preg_replace( '/(\d|\])( ){0,1}<(=){0,1}( ){0,1}(\d|\[)/', '$1 <$3 $5', $calc );
522 - }
523 -
524 - /**
525 - * Updating the settings page
526 - *
527 - * @param array $values Form values array.
528 - * @param object $field Field object, passed by reference.
529 - *
530 - * @return void
531 - */
532 - private static function get_settings_page_html( $values, &$field ) {
533 - if ( isset( $values['field_options'][ 'custom_html_' . $field->id ] ) ) {
534 - $prev_opts = array();
535 - $fallback_html = $field->field_options['custom_html'] ?? FrmFieldsHelper::get_default_html( $field->type );
536 -
537 - $field->field_options['custom_html'] = $values['field_options'][ 'custom_html_' . $field->id ] ?? $fallback_html;
538 - } elseif ( $field->type === 'hidden' || $field->type === 'user_id' ) {
539 - $prev_opts = $field->field_options;
540 - }
541 -
542 - if ( ! isset( $prev_opts ) ) {
543 - return;
544 - }
545 -
546 - $field->field_options = apply_filters( 'frm_update_form_field_options', $field->field_options, $field, $values );
547 -
548 - // phpcs:ignore Universal.Operators.StrictComparisons
549 - if ( $prev_opts != $field->field_options ) {
550 - FrmField::update( $field->id, array( 'field_options' => $field->field_options ) );
551 - }
552 - }
553 -
554 - /**
555 - * @param object $field
556 - * @param array $values
557 - * @param array $new_field
558 - *
559 - * @return void
560 - */
561 - private static function prepare_field_update_values( $field, $values, &$new_field ) {
562 - $field_cols = array(
563 - 'field_order' => 0,
564 - 'field_key' => '',
565 - 'required' => false,
566 - 'type' => '',
567 - 'description' => '',
568 - 'options' => '',
569 - 'name' => '',
570 - );
571 -
572 - foreach ( $field_cols as $col => $default ) {
573 - $default = $default === '' ? $field->{$col} : $default;
574 - $new_field[ $col ] = $values['field_options'][ $col . '_' . $field->id ] ?? $default;
575 - }
576 -
577 - if ( $field->type === 'submit' && isset( $new_field['field_order'] ) && (int) $new_field['field_order'] === FrmSubmitHelper::DEFAULT_ORDER ) {
578 - $new_field['field_order'] = $field->field_order;
579 - }
580 -
581 - // Don't save the template option.
582 - if ( is_array( $new_field['options'] ) && isset( $new_field['options']['000'] ) ) {
583 - unset( $new_field['options']['000'] );
584 - }
585 - }
586 -
587 - /**
588 - * Get a list of all form settings that should be translated
589 - * on a multilingual site.
590 - *
591 - * @since 3.06.01
592 - *
593 - * @param object $form The form object.
594 - *
595 - * @return array
596 - */
597 - public static function translatable_strings( $form ) {
598 - $strings = array(
599 - 'name',
600 - 'description',
601 - 'submit_value',
602 - 'submit_msg',
603 - 'success_msg',
604 - 'invalid_msg',
605 - 'failed_msg',
606 - 'login_msg',
607 - 'admin_permission',
608 - );
609 -
610 - return apply_filters( 'frm_form_strings', $strings, $form );
611 - }
612 -
613 - /**
614 - * @param array|int $id
615 - * @param string $status
616 - *
617 - * @return bool|int
618 - */
619 - public static function set_status( $id, $status ) {
620 - if ( 'trash' === $status ) {
621 - return self::trash( $id );
622 - }
623 -
624 - $statuses = array( 'published', 'draft', 'trash' );
625 -
626 - if ( ! in_array( $status, $statuses, true ) ) {
627 - return false;
628 - }
629 -
630 - global $wpdb;
631 -
632 - if ( is_array( $id ) ) {
633 - $where = array(
634 - 'id' => $id,
635 - 'parent_form_id' => $id,
636 - 'or' => 1,
637 - );
638 - FrmDb::get_where_clause_and_values( $where );
639 - array_unshift( $where['values'], $status );
640 -
641 - $query_results = $wpdb->query( $wpdb->prepare( 'UPDATE ' . $wpdb->prefix . 'frm_forms SET status = %s ' . $where['where'], $where['values'] ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, SlevomatCodingStandard.Files.LineLength.LineTooLong
642 - } else {
643 - $query_results = $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'status' => $status ), array( 'id' => $id ) );
644 - $wpdb->update( $wpdb->prefix . 'frm_forms', array( 'status' => $status ), array( 'parent_form_id' => $id ) );
645 - }
646 -
647 - if ( $query_results ) {
648 - self::clear_form_cache();
649 - }
650 -
651 - return $query_results;
652 - }
653 -
654 - /**
655 - * @param int|string $id Form ID.
656 - *
657 - * @return bool|int
658 - */
659 - public static function trash( $id ) {
660 - if ( ! EMPTY_TRASH_DAYS ) {
661 - return self::destroy( $id );
662 - }
663 -
664 - $form = self::getOne( $id );
665 -
666 - if ( ! $form ) {
667 - return false;
668 - }
669 -
670 - if ( $form->status === 'trash' ) {
671 - return false;
672 - }
673 -
674 - $options = $form->options;
675 - $options['trash_time'] = time();
676 -
677 - global $wpdb;
678 - $query_results = $wpdb->update(
679 - $wpdb->prefix . 'frm_forms',
680 - array(
681 - 'status' => 'trash',
682 - 'options' => serialize( $options ),
683 - ),
684 - array(
685 - 'id' => $id,
686 - )
687 - );
688 -
689 - $wpdb->update(
690 - $wpdb->prefix . 'frm_forms',
691 - array(
692 - 'status' => 'trash',
693 - 'options' => serialize( $options ),
694 - ),
695 - array(
696 - 'parent_form_id' => $id,
697 - )
698 - );
699 -
700 - if ( $query_results ) {
701 - self::clear_form_cache();
702 - }
703 -
704 - return $query_results;
705 - }
706 -
707 - /**
708 - * @param int|string $id Form ID.
709 - *
710 - * @return bool|int
711 - */
712 - public static function destroy( $id ) {
713 - global $wpdb;
714 -
715 - $form = self::getOne( $id );
716 -
717 - if ( ! $form ) {
718 - return false;
719 - }
720 -
721 - $id = $form->id;
722 -
723 - // Disconnect the entries from this form
724 - $entries = FrmDb::get_col( 'frm_items', array( 'form_id' => $id ) );
725 -
726 - foreach ( $entries as $entry_id ) {
727 - FrmEntry::destroy( $entry_id );
728 - unset( $entry_id );
729 - }
730 -
731 - // Disconnect the fields from this form
732 - $wpdb->query( $wpdb->prepare( 'DELETE fi FROM ' . $wpdb->prefix . 'frm_fields AS fi LEFT JOIN ' . $wpdb->prefix . 'frm_forms fr ON (fi.form_id = fr.id) WHERE fi.form_id=%d OR parent_form_id=%d', $id, $id ) ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
733 -
734 - $query_results = $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_forms WHERE id=%d OR parent_form_id=%d', $id, $id ) );
735 -
736 - if ( ! $query_results ) {
737 - return $query_results;
738 - }
739 -
740 - // Delete all form actions linked to this form
741 - /**
742 - * @var FrmFormAction
743 - */
744 - $action_control = FrmFormActionsController::get_form_actions( 'email' );
745 - $action_control->destroy( $id, 'all' );
746 -
747 - // Clear form caching
748 - self::clear_form_cache();
749 -
750 - do_action( 'frm_destroy_form', $id );
751 - do_action( 'frm_destroy_form_' . $id );
752 -
753 - return $query_results;
754 - }
755 -
756 - /**
757 - * Delete trashed forms based on how long they have been trashed
758 - *
759 - * @param int|string $delete_timestamp Timestamp cutoff for deletion.
760 - *
761 - * @return int The number of forms deleted
762 - */
763 - public static function scheduled_delete( $delete_timestamp = '' ) {
764 - $trash_forms = FrmDb::get_results( 'frm_forms', array( 'status' => 'trash' ), 'id, parent_form_id, options' );
765 -
766 - if ( ! $trash_forms ) {
767 - return 0;
768 - }
769 -
770 - if ( ! $delete_timestamp ) {
771 - $delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
772 - }
773 -
774 - $count = 0;
775 -
776 - foreach ( $trash_forms as $form ) {
777 - FrmAppHelper::unserialize_or_decode( $form->options );
778 -
779 - if ( ! isset( $form->options['trash_time'] ) || $form->options['trash_time'] < $delete_timestamp ) {
780 - self::destroy( $form->id );
781 -
782 - if ( empty( $form->parent_form_id ) ) {
783 - ++$count;
784 - }
785 - }
786 -
787 - unset( $form );
788 - }
789 -
790 - return $count;
791 - }
792 -
793 - /**
794 - * @param int|string $id Form ID or key.
795 - *
796 - * @return string form name
797 - */
798 - public static function getName( $id ) {
799 - $form = FrmDb::check_cache( $id, 'frm_form' );
800 -
801 - if ( $form ) {
802 - return stripslashes( $form->name );
803 - }
804 -
805 - $query_key = is_numeric( $id ) ? 'id' : 'form_key';
806 - $r = FrmDb::get_var( 'frm_forms', array( $query_key => $id ), 'name' );
807 -
808 - // An empty form name can result in a null value.
809 - return is_null( $r ) ? '' : stripslashes( $r );
810 - }
811 -
812 - /**
813 - * @since 3.0
814 - *
815 - * @param string $key
816 - *
817 - * @return int form id
818 - */
819 - public static function get_id_by_key( $key ) {
820 - return (int) FrmDb::get_var( 'frm_forms', array( 'form_key' => sanitize_title( $key ) ) );
821 - }
822 -
823 - /**
824 - * @since 3.0
825 - *
826 - * @param int|string $id
827 - *
828 - * @return string form key
829 - */
830 - public static function get_key_by_id( $id ) {
831 - $id = (int) $id;
832 - $cache = FrmDb::check_cache( $id, 'frm_form' );
833 -
834 - if ( $cache ) {
835 - return $cache->form_key;
836 - }
837 -
838 - return FrmDb::get_var( 'frm_forms', array( 'id' => $id ), 'form_key' );
839 - }
840 -
841 - /**
842 - * If $form is numeric, get the form object
843 - *
844 - * @since 2.0.9
845 - *
846 - * @param array|int|object $form
847 - *
848 - * @return void
849 - */
850 - public static function maybe_get_form( &$form ) {
851 - if ( ! is_object( $form ) && ! is_array( $form ) && $form ) {
852 - $form = self::getOne( $form );
853 - }
854 - }
855 -
856 - /**
857 - * @param int|string $id
858 - * @param false|int $blog_id
859 - *
860 - * @return stdClass|null
861 - */
862 - public static function getOne( $id, $blog_id = false ) {
863 - global $wpdb;
864 -
865 - if ( $blog_id && is_multisite() ) {
866 - $prefix = $wpdb->get_blog_prefix( $blog_id );
867 - $table_name = $prefix . 'frm_forms';
868 - } else {
869 - $table_name = $wpdb->prefix . 'frm_forms';
870 - $cache = wp_cache_get( $id, 'frm_form' );
871 -
872 - if ( $cache ) {
873 - if ( isset( $cache->options ) ) {
874 - FrmAppHelper::unserialize_or_decode( $cache->options );
875 - }
876 -
877 - return self::prepare_form_row_data( $cache );
878 - }
879 - }
880 -
881 - $where = is_numeric( $id ) ? array( 'id' => $id ) : array( 'form_key' => $id );
882 - $results = FrmDb::get_row( $table_name, $where );
883 -
884 - if ( isset( $results->options ) ) {
885 - FrmDb::set_cache( $results->id, $results, 'frm_form' );
886 - FrmAppHelper::unserialize_or_decode( $results->options );
887 - }
888 -
889 - return self::prepare_form_row_data( $results );
890 - }
891 -
892 - /**
893 - * Make sure that if $row is an object, that $row->options is an array and not a string.
894 - *
895 - * @since 6.8.3
896 - *
897 - * @param stdClass|null $row The database row for a target form.
898 - *
899 - * @return stdClass|null
900 - */
901 - private static function prepare_form_row_data( $row ) {
902 - $row = wp_unslash( $row );
903 -
904 - if ( ! is_object( $row ) ) {
905 - return $row;
906 - }
907 -
908 - if ( ! is_array( $row->options ) ) {
909 - $row->options = FrmFormsHelper::get_default_opts();
910 - }
911 -
912 - /**
913 - * @since 4.03.02
914 - *
915 - * @param stdClass $row
916 - */
917 - return apply_filters( 'frm_form_object', $row );
918 - }
919 -
920 - /**
921 - * @param array|string $where Where conditions array or raw WHERE string.
922 - * @param string $order_by Order by clause.
923 - * @param int|string $limit Limit clause or number.
924 - *
925 - * @return array|object Array of objects. If $limit is 1, a single object is returned.
926 - */
927 - public static function getAll( $where = array(), $order_by = '', $limit = '' ) {
928 - if ( is_array( $where ) && $where ) {
929 - if ( ! empty( $where['is_template'] ) && ! isset( $where['status'] ) && ! isset( $where['status !'] ) ) {
930 - // Don't get trashed templates
931 - $where['status'] = array( null, '', 'published' );
932 - }
933 -
934 - $results = FrmDb::get_results( 'frm_forms', $where, '*', compact( 'order_by', 'limit' ) );
935 - } else {
936 - global $wpdb;
937 -
938 - // The query has already been prepared if this is not an array.
939 - $query = 'SELECT * FROM ' . $wpdb->prefix . 'frm_forms' . FrmDb::prepend_and_or_where( ' WHERE ', $where ) . FrmDb::esc_order( $order_by ) . FrmDb::esc_limit( $limit ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
940 - $results = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
941 - }
942 -
943 - if ( $results ) {
944 - foreach ( $results as $result ) {
945 - FrmDb::set_cache( $result->id, $result, 'frm_form' );
946 - FrmAppHelper::unserialize_or_decode( $result->options );
947 - }
948 - }
949 -
950 - if ( $limit === ' LIMIT 1' || (int) $limit === 1 ) {
951 - // Return the first form object if we are only getting one form
952 - $results = reset( $results );
953 - }
954 -
955 - return wp_unslash( $results );
956 - }
957 -
958 - /**
959 - * Get all published forms
960 - *
961 - * @since 2.0
962 - *
963 - * @param array $query
964 - * @param int $limit
965 - * @param string $inc_children
966 - *
967 - * @return array|object Array of forms. A single form object is returned if $limit is set to 1.
968 - */
969 - public static function get_published_forms( $query = array(), $limit = 999, $inc_children = 'exclude' ) {
970 - $query['is_template'] = 0;
971 - $query['status'] = array( null, '', 'published' );
972 -
973 - if ( $inc_children === 'exclude' ) {
974 - $query['parent_form_id'] = array( null, 0 );
975 - }
976 -
977 - return self::getAll( $query, 'name', $limit );
978 - }
979 -
980 - /**
981 - * @return object count of forms
982 - */
983 - public static function get_count() {
984 - $cache_key = 'frm_form_counts';
985 - $counts = wp_cache_get( $cache_key, 'frm_form' );
986 -
987 - if ( false !== $counts ) {
988 - return $counts;
989 - }
990 -
991 - $results = FrmDb::get_results(
992 - 'frm_forms',
993 - array(
994 - 'or' => 1,
995 - 'parent_form_id' => null,
996 - 'parent_form_id <' => 0,
997 - ),
998 - 'status, is_template'
999 - );
1000 -
1001 - $statuses = array( 'published', 'draft', 'template', 'trash' );
1002 - $counts = array_fill_keys( $statuses, 0 );
1003 -
1004 - foreach ( $results as $row ) {
1005 - if ( 'trash' === $row->status ) {
1006 - ++$counts['trash'];
1007 - } elseif ( $row->is_template ) {
1008 - ++$counts['template'];
1009 - } else {
1010 - ++$counts['published'];
1011 - }
1012 -
1013 - if ( 'draft' === $row->status ) {
1014 - ++$counts['draft'];
1015 - }
1016 -
1017 - unset( $row );
1018 - }
1019 -
1020 - $counts = (object) $counts;
1021 - FrmDb::set_cache( $cache_key, $counts, 'frm_form' );
1022 -
1023 - return $counts;
1024 - }
1025 -
1026 - /**
1027 - * Clear form caching
1028 - * Called when a form is created, updated, duplicated, or deleted
1029 - * or when the form status is changed
1030 - *
1031 - * @since 2.0.4
1032 - *
1033 - * @return void
1034 - */
1035 - public static function clear_form_cache() {
1036 - FrmDb::cache_delete_group( 'frm_form' );
1037 - }
1038 -
1039 - /**
1040 - * @param array $values Form values to validate.
1041 - *
1042 - * @return array of errors
1043 - */
1044 - public static function validate( $values ) {
1045 - $errors = array();
1046 - return apply_filters( 'frm_validate_form', $errors, $values );
1047 - }
1048 -
1049 - /**
1050 - * @param object|null $form
1051 - *
1052 - * @return array
1053 - */
1054 - public static function get_params( $form = null ) {
1055 - global $frm_vars;
1056 -
1057 - if ( $form ) {
1058 - self::maybe_get_form( $form );
1059 - } else {
1060 - $form = self::getAll( array(), 'name', 1 );
1061 - }
1062 -
1063 - if ( isset( $frm_vars['form_params'] ) && is_array( $frm_vars['form_params'] ) && isset( $frm_vars['form_params'][ $form->id ] ) ) {
1064 - return $frm_vars['form_params'][ $form->id ];
1065 - }
1066 -
1067 - $action_var = isset( $_REQUEST['frm_action'] ) ? 'frm_action' : 'action'; // phpcs:ignore WordPress.Security.NonceVerification.Missing
1068 - $action = apply_filters( 'frm_show_new_entry_page', FrmAppHelper::get_param( $action_var, 'new', 'get', 'sanitize_title' ), $form );
1069 -
1070 - $default_values = array(
1071 - 'id' => '',
1072 - 'form_name' => '',
1073 - 'paged' => 1,
1074 - 'form' => $form->id,
1075 - 'form_id' => $form->id,
1076 - 'field_id' => '',
1077 - 'search' => '',
1078 - 'sort' => '',
1079 - 'sdir' => '',
1080 - 'action' => $action,
1081 - );
1082 -
1083 - $values = array();
1084 - $values['posted_form_id'] = FrmAppHelper::get_param( 'form_id', '', 'get', 'absint' );
1085 -
1086 - if ( ! $values['posted_form_id'] ) {
1087 - $values['posted_form_id'] = FrmAppHelper::get_param( 'form', '', 'get', 'absint' );
1088 - }
1089 -
1090 - // phpcs:ignore Universal.Operators.StrictComparisons
1091 - if ( $form->id == $values['posted_form_id'] ) {
1092 - // If there are two forms on the same page, make sure not to submit both.
1093 - foreach ( $default_values as $var => $default ) {
1094 - if ( $var === 'action' ) {
1095 - $values[ $var ] = FrmAppHelper::get_param( $action_var, $default, 'get', 'sanitize_title' );
1096 - } else {
1097 - $values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
1098 - }
1099 - unset( $var, $default );
1100 - }
1101 - } else {
1102 - foreach ( $default_values as $var => $default ) {
1103 - $values[ $var ] = $default;
1104 - unset( $var, $default );
1105 - }
1106 - }
1107 -
1108 - if ( in_array( $values['action'], array( 'create', 'update' ), true ) &&
1109 - ( ! $_POST || ( ! isset( $_POST['action'] ) && ! isset( $_POST['frm_action'] ) ) ) // phpcs:ignore WordPress.Security.NonceVerification.Missing
1110 - ) {
1111 - $values['action'] = 'new';
1112 - }
1113 -
1114 - return $values;
1115 - }
1116 -
1117 - /**
1118 - * @return array
1119 - */
1120 - public static function list_page_params() {
1121 - $values = array();
1122 - $defaults = array(
1123 - 'template' => 0,
1124 - 'id' => '',
1125 - 'paged' => 1,
1126 - 'form' => '',
1127 - 'search' => '',
1128 - 'sort' => '',
1129 - 'sdir' => '',
1130 - );
1131 -
1132 - foreach ( $defaults as $var => $default ) {
1133 - $values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
1134 - }
1135 -
1136 - return $values;
1137 - }
1138 -
1139 - /**
1140 - * @param int|object|string|null $form
1141 - *
1142 - * @return array
1143 - */
1144 - public static function get_admin_params( $form = null ) {
1145 - $form_id = $form;
1146 -
1147 - if ( $form === null ) {
1148 - $form_id = self::get_current_form_id();
1149 - } elseif ( $form && is_object( $form ) ) {
1150 - $form_id = $form->id;
1151 - }
1152 -
1153 - $values = array();
1154 - $defaults = array(
1155 - 'id' => '',
1156 - 'form_name' => '',
1157 - 'paged' => 1,
1158 - 'form' => $form_id,
1159 - 'field_id' => '',
1160 - 'search' => '',
1161 - 'sort' => '',
1162 - 'sdir' => '',
1163 - 'fid' => '',
1164 - 'keep_post' => '',
1165 - );
1166 -
1167 - foreach ( $defaults as $var => $default ) {
1168 - $values[ $var ] = FrmAppHelper::get_param( $var, $default, 'get', 'sanitize_text_field' );
1169 - }
1170 -
1171 - return $values;
1172 - }
1173 -
1174 - /**
1175 - * @param string $default_form
1176 - *
1177 - * @return int|string
1178 - */
1179 - public static function get_current_form_id( $default_form = 'none' ) {
1180 - $form = 'first' === $default_form ? self::get_current_form() : self::maybe_get_current_form();
1181 - return $form ? $form->id : 0;
1182 - }
1183 -
1184 - /**
1185 - * @param int|string $form_id
1186 - *
1187 - * @return false|int|object|string
1188 - */
1189 - public static function maybe_get_current_form( $form_id = 0 ) {
1190 - global $frm_vars;
1191 -
1192 - if ( ! empty( $frm_vars['current_form'] ) && ( ! $form_id || (int) $form_id === (int) $frm_vars['current_form']->id ) ) {
1193 - return $frm_vars['current_form'];
1194 - }
1195 -
1196 - $form_id = FrmAppHelper::get_param( 'form', $form_id, 'get', 'absint' );
1197 -
1198 - return $form_id ? self::set_current_form( $form_id ) : $form_id;
1199 - }
1200 -
1201 - /**
1202 - * @param int $form_id
1203 - *
1204 - * @return false|object
1205 - */
1206 - public static function get_current_form( $form_id = 0 ) {
1207 - $form = self::maybe_get_current_form( $form_id );
1208 - return is_numeric( $form ) ? self::set_current_form( $form ) : $form;
1209 - }
1210 -
1211 - /**
1212 - * @param int $form_id
1213 - *
1214 - * @return false|object
1215 - */
1216 - public static function set_current_form( $form_id ) {
1217 - global $frm_vars;
1218 -
1219 - $query = array();
1220 -
1221 - if ( $form_id ) {
1222 - $query['id'] = $form_id;
1223 - }
1224 -
1225 - $frm_vars['current_form'] = self::get_published_forms( $query, 1 );
1226 -
1227 - return $frm_vars['current_form'];
1228 - }
1229 -
1230 - /**
1231 - * @param object $form
1232 - * @param int|string $this_load
1233 - * @param bool $global_load
1234 - *
1235 - * @return bool
1236 - */
1237 - public static function is_form_loaded( $form, $this_load, $global_load ) {
1238 - global $frm_vars;
1239 - $small_form = new stdClass();
1240 -
1241 - foreach ( array( 'id', 'form_key', 'name' ) as $var ) {
1242 - $small_form->{$var} = $form->{$var};
1243 - unset( $var );
1244 - }
1245 -
1246 - $frm_vars['forms_loaded'][] = $small_form;
1247 -
1248 - if ( $this_load && ! $global_load ) {
1249 - $global_load = true;
1250 - $frm_vars['load_css'] = true;
1251 - }
1252 -
1253 - return empty( $frm_vars['css_loaded'] ) && $global_load;
1254 - }
1255 -
1256 - /**
1257 - * @since 4.06.03
1258 - *
1259 - * @param object $form
1260 - *
1261 - * @return bool
1262 - */
1263 - public static function is_visible_to_user( $form ) {
1264 - if ( $form->logged_in && isset( $form->options['logged_in_role'] ) ) {
1265 - $visible = FrmAppHelper::user_has_permission( $form->options['logged_in_role'] );
1266 - } else {
1267 - $visible = true;
1268 - }
1269 -
1270 - /**
1271 - * @since 6.25
1272 - *
1273 - * @param bool $visible
1274 - * @param object $form
1275 - */
1276 - return (bool) apply_filters( 'frm_form_is_visible', $visible, $form );
1277 - }
1278 -
1279 - /**
1280 - * @param object $form
1281 - *
1282 - * @return bool
1283 - */
1284 - public static function show_submit( $form ) {
1285 - $show = ! $form->is_template && $form->status === 'published' && ! FrmAppHelper::is_admin();
1286 - return apply_filters( 'frm_show_submit_button', $show, $form );
1287 - }
1288 -
1289 - /**
1290 - * @since 2.3
1291 - *
1292 - * @param array $atts Attributes including form, option, and default.
1293 - *
1294 - * @return mixed
1295 - */
1296 - public static function get_option( $atts ) {
1297 - $form = $atts['form'];
1298 - $default = $atts['default'] ?? '';
1299 -
1300 - return $form->options[ $atts['option'] ] ?? $default;
1301 - }
1302 -
1303 - /**
1304 - * Get the link to edit this form.
1305 - *
1306 - * @since 4.0
1307 - *
1308 - * @param int $form_id The id of the form.
1309 - *
1310 - * @return string
1311 - */
1312 - public static function get_edit_link( $form_id ) {
1313 - return admin_url( 'admin.php?page=formidable&frm_action=edit&id=' . $form_id );
1314 - }
1315 -
1316 - /**
1317 - * Check if the "Submit this form with AJAX" setting is toggled on.
1318 - *
1319 - * @since 6.2
1320 - *
1321 - * @param stdClass $form
1322 - *
1323 - * @return bool
1324 - */
1325 - public static function is_ajax_on( $form ) {
1326 - return ! empty( $form->options['ajax_submit'] );
1327 - }
1328 -
1329 - /**
1330 - * Get the latest form available.
1331 - *
1332 - * @since 6.8
1333 - *
1334 - * @return object
1335 - */
1336 - public static function get_latest_form() {
1337 - $args = array(
1338 - array(
1339 - 'or' => 1,
1340 - 'parent_form_id' => null,
1341 - 'parent_form_id <' => 1,
1342 - ),
1343 - 'is_template' => 0,
1344 - 'status !' => 'trash',
1345 - );
1346 -
1347 - return self::getAll( $args, 'created_at desc', 1 );
1348 - }
1349 -
1350 - /**
1351 - * Count and return total forms.
1352 - *
1353 - * @since 6.8
1354 - *
1355 - * @return int
1356 - */
1357 - public static function get_forms_count() {
1358 - $args = array(
1359 - array(
1360 - 'or' => 1,
1361 - 'parent_form_id' => null,
1362 - 'parent_form_id <' => 1,
1363 - ),
1364 - 'is_template' => 0,
1365 - 'status !' => 'trash',
1366 - );
1367 -
1368 - return FrmDb::get_count( 'frm_forms', $args );
1369 - }
1370 -
1371 - /**
1372 - * @deprecated 2.03.05 This is still referenced in a few add ons (API, locations).
1373 - *
1374 - * @codeCoverageIgnore
1375 - *
1376 - * @param string $key
1377 - *
1378 - * @return int form id
1379 - */
1380 - public static function getIdByKey( $key ) {
1381 - _deprecated_function( __FUNCTION__, '2.03.05', 'FrmForm::get_id_by_key' );
1382 - return self::get_id_by_key( $key );
1383 - }
1384 -
1385 - /**
1386 - * @deprecated 2.03.05 This is still referenced in the API add on as of v1.13.
1387 - *
1388 - * @codeCoverageIgnore
1389 - *
1390 - * @param int|string $id
1391 - *
1392 - * @return string
1393 - */
1394 - public static function getKeyById( $id ) {
1395 - _deprecated_function( __FUNCTION__, '2.03.05', 'FrmForm::get_key_by_id' );
1396 - return self::get_key_by_id( $id );
1397 - }
1398 349 }