1
|
|
|
<?php |
|
|
|
|
2
|
|
|
/** |
3
|
|
|
* Set of common functions to separate main plugin from Gravity Forms API and other cross-plugin methods |
4
|
|
|
* |
5
|
|
|
* @package GravityView |
6
|
|
|
* @license GPL2+ |
7
|
|
|
* @author Katz Web Services, Inc. |
8
|
|
|
* @link http://gravityview.co |
9
|
|
|
* @copyright Copyright 2014, Katz Web Services, Inc. |
10
|
|
|
* |
11
|
|
|
* @since 1.5.2 |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
/** If this file is called directly, abort. */ |
15
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
16
|
|
|
die; |
17
|
|
|
} |
18
|
|
|
|
19
|
|
|
class GVCommon { |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Returns the form object for a given Form ID. |
23
|
|
|
* |
24
|
|
|
* @access public |
25
|
|
|
* @param mixed $form_id |
26
|
|
|
* @return mixed False: no form ID specified or Gravity Forms isn't active. Array: Form returned from Gravity Forms |
27
|
|
|
*/ |
28
|
|
|
public static function get_form( $form_id ) { |
29
|
|
|
if ( empty( $form_id ) ) { |
30
|
|
|
return false; |
31
|
|
|
} |
32
|
|
|
|
33
|
|
|
// Only get_form_meta is cached. ::facepalm:: |
34
|
|
|
if ( class_exists( 'RGFormsModel' ) ) { |
35
|
|
|
return GFFormsModel::get_form_meta( $form_id ); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
if ( class_exists( 'GFAPI' ) ) { |
39
|
|
|
return GFAPI::get_form( $form_id ); |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
return false; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Alias of GravityView_Roles_Capabilities::has_cap() |
47
|
|
|
* |
48
|
|
|
* @since 1.15 |
49
|
|
|
* |
50
|
|
|
* @see GravityView_Roles_Capabilities::has_cap() |
51
|
|
|
* |
52
|
|
|
* @param string|array $caps Single capability or array of capabilities |
53
|
|
|
* @param int $object_id (optional) Parameter can be used to check for capabilities against a specific object, such as a post or user |
54
|
|
|
* @param int|null $user_id (optional) Check the capabilities for a user who is not necessarily the currently logged-in user |
55
|
|
|
* |
56
|
|
|
* @return bool True: user has at least one passed capability; False: user does not have any defined capabilities |
57
|
|
|
*/ |
58
|
|
|
public static function has_cap( $caps = '', $object_id = null, $user_id = null ) { |
59
|
|
|
return GravityView_Roles_Capabilities::has_cap( $caps, $object_id, $user_id ); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Return a Gravity Forms field array, whether using GF 1.9 or not |
64
|
|
|
* |
65
|
|
|
* @since 1.7 |
66
|
|
|
* |
67
|
|
|
* @param array|GF_Fields $field Gravity Forms field or array |
68
|
|
|
* @return array Array version of $field |
69
|
|
|
*/ |
70
|
|
|
public static function get_field_array( $field ) { |
71
|
|
|
|
72
|
|
|
if ( class_exists( 'GF_Fields' ) ) { |
73
|
|
|
|
74
|
|
|
$field_object = GF_Fields::create( $field ); |
75
|
|
|
|
76
|
|
|
// Convert the field object in 1.9 to an array for backward compatibility |
77
|
|
|
$field_array = get_object_vars( $field_object ); |
78
|
|
|
|
79
|
|
|
} else { |
80
|
|
|
$field_array = $field; |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
return $field_array; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Get all existing Views |
88
|
|
|
* |
89
|
|
|
* @since 1.5.4 |
90
|
|
|
* @since TODO Added $args array |
91
|
|
|
* |
92
|
|
|
* @param array $args Pass custom array of args, formatted as if for `get_posts()` |
93
|
|
|
* |
94
|
|
|
* @return array Array of Views as `WP_Post`. Empty array if none found. |
95
|
|
|
*/ |
96
|
|
|
public static function get_all_views( $args = array() ) { |
97
|
|
|
|
98
|
|
|
$default_params = array( |
99
|
|
|
'post_type' => 'gravityview', |
100
|
|
|
'posts_per_page' => -1, |
|
|
|
|
101
|
|
|
'post_status' => 'publish', |
102
|
|
|
); |
103
|
|
|
|
104
|
|
|
$params = wp_parse_args( $args, $default_params ); |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* @filter `gravityview/get_all_views/params` Modify the parameters sent to get all views. |
108
|
|
|
* @param[in,out] array $params Array of parameters to pass to `get_posts()` |
109
|
|
|
*/ |
110
|
|
|
$views_params = apply_filters( 'gravityview/get_all_views/params', $params ); |
111
|
|
|
|
112
|
|
|
$views = get_posts( $views_params ); |
113
|
|
|
|
114
|
|
|
return $views; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Get the form array for an entry based only on the entry ID |
120
|
|
|
* @param int|string $entry_slug Entry slug |
121
|
|
|
* @return array Gravity Forms form array |
122
|
|
|
*/ |
123
|
|
|
public static function get_form_from_entry_id( $entry_slug ) { |
124
|
|
|
|
125
|
|
|
$entry = self::get_entry( $entry_slug, true ); |
126
|
|
|
|
127
|
|
|
$form = self::get_form( $entry['form_id'] ); |
128
|
|
|
|
129
|
|
|
return $form; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Check whether a form has product fields |
134
|
|
|
* |
135
|
|
|
* @since 1.16 |
136
|
|
|
* |
137
|
|
|
* @param array $form Gravity Forms form array |
138
|
|
|
* |
139
|
|
|
* @return bool|GF_Field[] |
140
|
|
|
*/ |
141
|
|
|
public static function has_product_field( $form = array() ) { |
142
|
|
|
|
143
|
|
|
$product_fields = apply_filters( 'gform_product_field_types', array( 'option', 'quantity', 'product', 'total', 'shipping', 'calculation', 'price' ) ); |
144
|
|
|
|
145
|
|
|
$fields = GFAPI::get_fields_by_type( $form, $product_fields ); |
146
|
|
|
|
147
|
|
|
return empty( $fields ) ? false : $fields; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* Get the entry ID from the entry slug, which may or may not be the entry ID |
152
|
|
|
* |
153
|
|
|
* @since 1.5.2 |
154
|
|
|
* @param string $slug The entry slug, as returned by GravityView_API::get_entry_slug() |
155
|
|
|
* @return int|null The entry ID, if exists; `NULL` if not |
156
|
|
|
*/ |
157
|
|
|
public static function get_entry_id_from_slug( $slug ) { |
158
|
|
|
global $wpdb; |
|
|
|
|
159
|
|
|
|
160
|
|
|
$search_criteria = array( |
161
|
|
|
'field_filters' => array( |
162
|
|
|
array( |
163
|
|
|
'key' => 'gravityview_unique_id', // Search the meta values |
164
|
|
|
'value' => $slug, |
165
|
|
|
'operator' => 'is', |
166
|
|
|
'type' => 'meta', |
167
|
|
|
), |
168
|
|
|
) |
169
|
|
|
); |
170
|
|
|
|
171
|
|
|
// Limit to one for speed |
172
|
|
|
$paging = array( |
173
|
|
|
'page_size' => 1, |
174
|
|
|
); |
175
|
|
|
|
176
|
|
|
$results = GFAPI::get_entries( 0, $search_criteria, null, $paging ); |
177
|
|
|
|
178
|
|
|
$result = ( ! empty( $results ) && ! empty( $results[0]['id'] ) ) ? $results[0]['id'] : null; |
179
|
|
|
|
180
|
|
|
return $result; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Returns the list of available forms |
186
|
|
|
* |
187
|
|
|
* @access public |
188
|
|
|
* @param mixed $form_id |
|
|
|
|
189
|
|
|
* @return array Empty array if GFAPI isn't available or no forms. Otherwise, associative array with id, title keys |
190
|
|
|
*/ |
191
|
|
|
public static function get_forms() { |
192
|
|
|
$forms = array(); |
193
|
|
|
if ( class_exists( 'GFAPI' ) ) { |
194
|
|
|
$gf_forms = GFAPI::get_forms(); |
195
|
|
|
foreach ( $gf_forms as $form ) { |
196
|
|
|
$forms[] = array( |
197
|
|
|
'id' => $form['id'], |
198
|
|
|
'title' => $form['title'], |
199
|
|
|
); |
200
|
|
|
} |
201
|
|
|
} |
202
|
|
|
return $forms; |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* Return array of fields' id and label, for a given Form ID |
207
|
|
|
* |
208
|
|
|
* @access public |
209
|
|
|
* @param string|array $form_id (default: '') or $form object |
|
|
|
|
210
|
|
|
* @return array |
211
|
|
|
*/ |
212
|
|
|
public static function get_form_fields( $form = '', $add_default_properties = false, $include_parent_field = true ) { |
213
|
|
|
|
214
|
|
|
if ( ! is_array( $form ) ) { |
215
|
|
|
$form = self::get_form( $form ); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
$fields = array(); |
219
|
|
|
$has_product_fields = false; |
220
|
|
|
$has_post_fields = false; |
221
|
|
|
$has_quiz_fields = false; |
222
|
|
|
$has_poll_fields = false; |
223
|
|
|
|
224
|
|
|
// If GF_Field exists, we're using GF 1.9+, where add_default_properties has been deprecated. |
225
|
|
|
if ( false === class_exists( 'GF_Field' ) && $add_default_properties ) { |
226
|
|
|
$form = RGFormsModel::add_default_properties( $form ); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
if ( $form ) { |
230
|
|
|
foreach ( $form['fields'] as $field ) { |
231
|
|
|
if ( $include_parent_field || empty( $field['inputs'] ) ) { |
232
|
|
|
$fields[ $field['id'] ] = array( |
233
|
|
|
'label' => rgar( $field, 'label' ), |
234
|
|
|
'parent' => null, |
235
|
|
|
'type' => rgar( $field, 'type' ), |
236
|
|
|
'adminLabel' => rgar( $field, 'adminLabel' ), |
237
|
|
|
'adminOnly' => rgar( $field, 'adminOnly' ), |
238
|
|
|
); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
if ( $add_default_properties && ! empty( $field['inputs'] ) ) { |
242
|
|
|
foreach ( $field['inputs'] as $input ) { |
243
|
|
|
/** |
244
|
|
|
* @hack |
245
|
|
|
* In case of email/email confirmation, the input for email has the same id as the parent field |
246
|
|
|
*/ |
247
|
|
|
if( 'email' == rgar( $field, 'type' ) && false === strpos( $input['id'], '.' ) ) { |
|
|
|
|
248
|
|
|
continue; |
249
|
|
|
} |
250
|
|
|
$fields[ (string)$input['id'] ] = array( |
|
|
|
|
251
|
|
|
'label' => rgar( $input, 'label' ), |
252
|
|
|
'customLabel' => rgar( $input, 'customLabel' ), |
253
|
|
|
'parent' => $field, |
254
|
|
|
'type' => rgar( $field, 'type' ), |
255
|
|
|
'adminLabel' => rgar( $field, 'adminLabel' ), |
256
|
|
|
'adminOnly' => rgar( $field, 'adminOnly' ), |
257
|
|
|
); |
258
|
|
|
} |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** @since 1.14 */ |
262
|
|
|
if( 'list' === $field['type'] && !empty( $field['enableColumns'] ) ) { |
|
|
|
|
263
|
|
|
|
264
|
|
|
foreach ( (array)$field['choices'] as $key => $input ) { |
|
|
|
|
265
|
|
|
|
266
|
|
|
$input_id = sprintf( '%d.%d', $field['id'], $key ); // {field_id}.{column_key} |
|
|
|
|
267
|
|
|
|
268
|
|
|
$fields[ $input_id ] = array( |
269
|
|
|
'label' => rgar( $input, 'text' ), |
270
|
|
|
'customLabel' => '', |
271
|
|
|
'parent' => $field, |
272
|
|
|
'type' => rgar( $field, 'type' ), |
273
|
|
|
'adminLabel' => rgar( $field, 'adminLabel' ), |
274
|
|
|
'adminOnly' => rgar( $field, 'adminOnly' ), |
275
|
|
|
); |
276
|
|
|
} |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
/** |
280
|
|
|
* @since 1.8 |
281
|
|
|
*/ |
282
|
|
|
if( 'quiz' === $field['type'] ) { |
|
|
|
|
283
|
|
|
$has_quiz_fields = true; |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* @since 1.8 |
288
|
|
|
*/ |
289
|
|
|
if( 'poll' === $field['type'] ) { |
|
|
|
|
290
|
|
|
$has_poll_fields = true; |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
if( GFCommon::is_product_field( $field['type'] ) ){ |
|
|
|
|
294
|
|
|
$has_product_fields = true; |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* @hack Version 1.9 |
299
|
|
|
*/ |
300
|
|
|
$field_for_is_post_field = class_exists( 'GF_Fields' ) ? (object) $field : (array) $field; |
301
|
|
|
|
302
|
|
|
if ( GFCommon::is_post_field( $field_for_is_post_field ) ) { |
303
|
|
|
$has_post_fields = true; |
304
|
|
|
} |
305
|
|
|
} |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* @since 1.7 |
310
|
|
|
*/ |
311
|
|
|
if ( $has_post_fields ) { |
312
|
|
|
$fields['post_id'] = array( |
313
|
|
|
'label' => __( 'Post ID', 'gravityview' ), |
314
|
|
|
'type' => 'post_id', |
315
|
|
|
); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
if ( $has_product_fields ) { |
319
|
|
|
|
320
|
|
|
$payment_fields = GravityView_Fields::get_all( 'pricing' ); |
321
|
|
|
|
322
|
|
|
foreach ( $payment_fields as $payment_field ) { |
323
|
|
|
if( isset( $fields["{$payment_field->name}"] ) ) { |
|
|
|
|
324
|
|
|
continue; |
325
|
|
|
} |
326
|
|
|
$fields["{$payment_field->name}"] = array( |
|
|
|
|
327
|
|
|
'label' => $payment_field->label, |
328
|
|
|
'desc' => $payment_field->description, |
329
|
|
|
'type' => $payment_field->name, |
330
|
|
|
); |
331
|
|
|
} |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* @since 1.8 |
336
|
|
|
*/ |
337
|
|
|
if( $has_quiz_fields ) { |
|
|
|
|
338
|
|
|
|
339
|
|
|
$fields['gquiz_score'] = array( |
340
|
|
|
'label' => __( 'Quiz Score Total', 'gravityview' ), |
341
|
|
|
'type' => 'quiz_score', |
342
|
|
|
'desc' => __( 'Displays the number of correct Quiz answers the user submitted.', 'gravityview' ), |
343
|
|
|
); |
344
|
|
|
$fields['gquiz_percent'] = array( |
345
|
|
|
'label' => __( 'Quiz Percentage Grade', 'gravityview' ), |
346
|
|
|
'type' => 'quiz_percent', |
347
|
|
|
'desc' => __( 'Displays the percentage of correct Quiz answers the user submitted.', 'gravityview' ), |
348
|
|
|
); |
349
|
|
|
$fields['gquiz_grade'] = array( |
350
|
|
|
'label' => __( 'Quiz Letter Grade', 'gravityview' ), |
351
|
|
|
'type' => 'quiz_grade', |
352
|
|
|
'desc' => __( 'Displays the Grade the user achieved based on Letter Grading configured in the Quiz Settings.', 'gravityview' ), |
353
|
|
|
); |
354
|
|
|
$fields['gquiz_is_pass'] = array( |
355
|
|
|
'label' => __( 'Quiz Pass/Fail', 'gravityview' ), |
356
|
|
|
'type' => 'quiz_is_pass', |
357
|
|
|
'desc' => __( 'Displays either Passed or Failed based on the Pass/Fail settings configured in the Quiz Settings.', 'gravityview' ), |
358
|
|
|
); |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
return $fields; |
362
|
|
|
|
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
/** |
366
|
|
|
* get extra fields from entry meta |
367
|
|
|
* @param string $form_id (default: '') |
368
|
|
|
* @return array |
369
|
|
|
*/ |
370
|
|
|
public static function get_entry_meta( $form_id, $only_default_column = true ) { |
371
|
|
|
|
372
|
|
|
$extra_fields = GFFormsModel::get_entry_meta( $form_id ); |
373
|
|
|
|
374
|
|
|
$fields = array(); |
375
|
|
|
|
376
|
|
|
foreach ( $extra_fields as $key => $field ){ |
377
|
|
|
if ( ! empty( $only_default_column ) && ! empty( $field['is_default_column'] ) ) { |
378
|
|
|
$fields[ $key ] = array( 'label' => $field['label'], 'type' => 'entry_meta' ); |
379
|
|
|
} |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
return $fields; |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
|
386
|
|
|
/** |
387
|
|
|
* Wrapper for the Gravity Forms GFFormsModel::search_lead_ids() method |
388
|
|
|
* |
389
|
|
|
* @see GFEntryList::leads_page() |
390
|
|
|
* @param int $form_id ID of the Gravity Forms form |
391
|
|
|
* @since 1.1.6 |
392
|
|
|
* @return array|void Array of entry IDs. Void if Gravity Forms isn't active. |
393
|
|
|
*/ |
394
|
|
|
public static function get_entry_ids( $form_id, $search_criteria = array() ) { |
395
|
|
|
|
396
|
|
|
if ( ! class_exists( 'GFFormsModel' ) ) { |
397
|
|
|
return; |
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
return GFFormsModel::search_lead_ids( $form_id, $search_criteria ); |
401
|
|
|
} |
402
|
|
|
|
403
|
|
|
/** |
404
|
|
|
* Calculates the Search Criteria used on the self::get_entries / self::get_entry methods |
405
|
|
|
* |
406
|
|
|
* @since 1.7.4 |
407
|
|
|
* |
408
|
|
|
* @param array $passed_criteria array Input Criteria (search_criteria, sorting, paging) |
409
|
|
|
* @param array $form_ids array Gravity Forms form IDs |
410
|
|
|
* @return array |
411
|
|
|
*/ |
412
|
|
|
public static function calculate_get_entries_criteria( $passed_criteria = array(), $form_ids = array() ) { |
413
|
|
|
|
414
|
|
|
$search_criteria_defaults = array( |
415
|
|
|
'search_criteria' => null, |
416
|
|
|
'sorting' => null, |
417
|
|
|
'paging' => null, |
418
|
|
|
'cache' => (isset( $passed_criteria['cache'] ) ? $passed_criteria['cache'] : true), |
419
|
|
|
); |
420
|
|
|
|
421
|
|
|
$criteria = wp_parse_args( $passed_criteria, $search_criteria_defaults ); |
422
|
|
|
|
423
|
|
|
if ( ! empty( $criteria['search_criteria']['field_filters'] ) ) { |
424
|
|
|
foreach ( $criteria['search_criteria']['field_filters'] as &$filter ) { |
425
|
|
|
|
426
|
|
|
if ( ! is_array( $filter ) ) { |
427
|
|
|
continue; |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
// By default, we want searches to be wildcard for each field. |
431
|
|
|
$filter['operator'] = empty( $filter['operator'] ) ? 'contains' : $filter['operator']; |
432
|
|
|
|
433
|
|
|
/** |
434
|
|
|
* @filter `gravityview_search_operator` Modify the search operator for the field (contains, is, isnot, etc) |
435
|
|
|
* @param string $operator Existing search operator |
436
|
|
|
* @param array $filter array with `key`, `value`, `operator`, `type` keys |
437
|
|
|
*/ |
438
|
|
|
$filter['operator'] = apply_filters( 'gravityview_search_operator', $filter['operator'], $filter ); |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
// don't send just the [mode] without any field filter. |
442
|
|
|
if( count( $criteria['search_criteria']['field_filters'] ) === 1 && array_key_exists( 'mode' , $criteria['search_criteria']['field_filters'] ) ) { |
|
|
|
|
443
|
|
|
unset( $criteria['search_criteria']['field_filters']['mode'] ); |
444
|
|
|
} |
|
|
|
|
445
|
|
|
|
446
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
449
|
|
|
|
450
|
|
|
/** |
451
|
|
|
* Prepare date formats to be in Gravity Forms DB format; |
452
|
|
|
* $passed_criteria may include date formats incompatible with Gravity Forms. |
453
|
|
|
*/ |
454
|
|
|
foreach ( array('start_date', 'end_date' ) as $key ) { |
|
|
|
|
455
|
|
|
|
456
|
|
|
if ( ! empty( $criteria['search_criteria'][ $key ] ) ) { |
457
|
|
|
|
458
|
|
|
// Use date_create instead of new DateTime so it returns false if invalid date format. |
459
|
|
|
$date = date_create( $criteria['search_criteria'][ $key ] ); |
460
|
|
|
|
461
|
|
|
if ( $date ) { |
462
|
|
|
// Gravity Forms wants dates in the `Y-m-d H:i:s` format. |
463
|
|
|
$criteria['search_criteria'][ $key ] = $date->format( 'Y-m-d H:i:s' ); |
464
|
|
|
} else { |
465
|
|
|
// If it's an invalid date, unset it. Gravity Forms freaks out otherwise. |
466
|
|
|
unset( $criteria['search_criteria'][ $key ] ); |
467
|
|
|
|
468
|
|
|
do_action( 'gravityview_log_error', '[filter_get_entries_criteria] '.$key.' Date format not valid:', $criteria['search_criteria'][ $key ] ); |
469
|
|
|
} |
470
|
|
|
} |
471
|
|
|
} |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
474
|
|
|
// When multiple views are embedded, OR single entry, calculate the context view id and send it to the advanced filter |
475
|
|
|
if ( class_exists( 'GravityView_View_Data' ) && GravityView_View_Data::getInstance()->has_multiple_views() || GravityView_frontend::getInstance()->getSingleEntry() ) { |
476
|
|
|
$criteria['context_view_id'] = GravityView_frontend::getInstance()->get_context_view_id(); |
477
|
|
|
} elseif ( 'delete' === RGForms::get( 'action' ) ) { |
478
|
|
|
$criteria['context_view_id'] = isset( $_GET['view_id'] ) ? $_GET['view_id'] : null; |
|
|
|
|
479
|
|
|
} elseif( !isset( $criteria['context_view_id'] ) ) { |
|
|
|
|
480
|
|
|
// Prevent overriding the Context View ID: Some widgets could set the context_view_id (e.g. Recent Entries widget) |
481
|
|
|
$criteria['context_view_id'] = null; |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
/** |
485
|
|
|
* @filter `gravityview_search_criteria` Apply final criteria filter (Used by the Advanced Filter extension) |
486
|
|
|
* @param array $criteria Search criteria used by GravityView |
487
|
|
|
* @param array $form_ids Forms to search |
488
|
|
|
* @param int $view_id ID of the view being used to search |
489
|
|
|
*/ |
490
|
|
|
$criteria = apply_filters( 'gravityview_search_criteria', $criteria, $form_ids, $criteria['context_view_id'] ); |
491
|
|
|
|
492
|
|
|
return (array)$criteria; |
|
|
|
|
493
|
|
|
|
494
|
|
|
} |
495
|
|
|
|
496
|
|
|
|
497
|
|
|
/** |
498
|
|
|
* Retrieve entries given search, sort, paging criteria |
499
|
|
|
* |
500
|
|
|
* @see GFAPI::get_entries() |
501
|
|
|
* @see GFFormsModel::get_field_filters_where() |
502
|
|
|
* @access public |
503
|
|
|
* @param int|array $form_ids The ID of the form or an array IDs of the Forms. Zero for all forms. |
504
|
|
|
* @param mixed $passed_criteria (default: null) |
505
|
|
|
* @param mixed &$total Optional. An output parameter containing the total number of entries. Pass a non-null value to generate the total count. (default: null) |
506
|
|
|
* @return mixed False: Error fetching entries. Array: Multi-dimensional array of Gravity Forms entry arrays |
507
|
|
|
*/ |
508
|
|
|
public static function get_entries( $form_ids = null, $passed_criteria = null, &$total = null ) { |
509
|
|
|
|
510
|
|
|
// Filter the criteria before query (includes Adv Filter) |
511
|
|
|
$criteria = self::calculate_get_entries_criteria( $passed_criteria, $form_ids ); |
512
|
|
|
|
513
|
|
|
do_action( 'gravityview_log_debug', '[gravityview_get_entries] Final Parameters', $criteria ); |
514
|
|
|
|
515
|
|
|
// Return value |
516
|
|
|
$return = null; |
517
|
|
|
|
518
|
|
|
/** Reduce # of database calls */ |
519
|
|
|
add_filter( 'gform_is_encrypted_field', '__return_false' ); |
520
|
|
|
|
521
|
|
|
if ( ! empty( $criteria['cache'] ) ) { |
522
|
|
|
|
523
|
|
|
$Cache = new GravityView_Cache( $form_ids, $criteria ); |
524
|
|
|
|
525
|
|
|
if ( $entries = $Cache->get() ) { |
526
|
|
|
|
527
|
|
|
// Still update the total count when using cached results |
528
|
|
|
if ( ! is_null( $total ) ) { |
529
|
|
|
$total = GFAPI::count_entries( $form_ids, $criteria['search_criteria'] ); |
530
|
|
|
} |
531
|
|
|
|
532
|
|
|
$return = $entries; |
533
|
|
|
} |
534
|
|
|
} |
535
|
|
|
|
536
|
|
|
if ( is_null( $return ) && class_exists( 'GFAPI' ) && ( is_numeric( $form_ids ) || is_array( $form_ids ) ) ) { |
537
|
|
|
|
538
|
|
|
/** |
539
|
|
|
* @filter `gravityview_pre_get_entries` Define entries to be used before GFAPI::get_entries() is called |
540
|
|
|
* @since 1.14 |
541
|
|
|
* @param null $return If you want to override GFAPI::get_entries() and define entries yourself, tap in here. |
542
|
|
|
* @param array $criteria The final search criteria used to generate the request to `GFAPI::get_entries()` |
543
|
|
|
* @param array $passed_criteria The original search criteria passed to `GVCommon::get_entries()` |
544
|
|
|
* @param int|null $total Optional. An output parameter containing the total number of entries. Pass a non-null value to generate |
545
|
|
|
*/ |
546
|
|
|
$entries = apply_filters( 'gravityview_before_get_entries', null, $criteria, $passed_criteria, $total ); |
547
|
|
|
|
548
|
|
|
// No entries returned from gravityview_before_get_entries |
549
|
|
|
if( is_null( $entries ) ) { |
|
|
|
|
550
|
|
|
|
551
|
|
|
$entries = GFAPI::get_entries( $form_ids, $criteria['search_criteria'], $criteria['sorting'], $criteria['paging'], $total ); |
552
|
|
|
|
553
|
|
|
if ( is_wp_error( $entries ) ) { |
554
|
|
|
do_action( 'gravityview_log_error', $entries->get_error_message(), $entries ); |
555
|
|
|
|
556
|
|
|
return false; |
557
|
|
|
} |
558
|
|
|
} |
559
|
|
|
|
560
|
|
|
if ( ! empty( $criteria['cache'] ) && isset( $Cache ) ) { |
561
|
|
|
|
562
|
|
|
// Cache results |
563
|
|
|
$Cache->set( $entries, 'entries' ); |
564
|
|
|
|
565
|
|
|
} |
566
|
|
|
|
567
|
|
|
$return = $entries; |
568
|
|
|
} |
569
|
|
|
|
570
|
|
|
/** Remove filter added above */ |
571
|
|
|
remove_filter( 'gform_is_encrypted_field', '__return_false' ); |
572
|
|
|
|
573
|
|
|
/** |
574
|
|
|
* @filter `gravityview_entries` Modify the array of entries returned to GravityView after it has been fetched from the cache or from `GFAPI::get_entries()`. |
575
|
|
|
* @param array|null $entries Array of entries as returned by the cache or by `GFAPI::get_entries()` |
576
|
|
|
* @param array $criteria The final search criteria used to generate the request to `GFAPI::get_entries()` |
577
|
|
|
* @param array $passed_criteria The original search criteria passed to `GVCommon::get_entries()` |
578
|
|
|
* @param int|null $total Optional. An output parameter containing the total number of entries. Pass a non-null value to generate |
579
|
|
|
*/ |
580
|
|
|
$return = apply_filters( 'gravityview_entries', $return, $criteria, $passed_criteria, $total ); |
581
|
|
|
|
582
|
|
|
return $return; |
583
|
|
|
} |
584
|
|
|
|
585
|
|
|
|
586
|
|
|
/** |
587
|
|
|
* Return a single entry object |
588
|
|
|
* |
589
|
|
|
* Since 1.4, supports custom entry slugs. The way that GravityView fetches an entry based on the custom slug is by searching `gravityview_unique_id` meta. The `$entry_slug` is fetched by getting the current query var set by `is_single_entry()` |
590
|
|
|
* |
591
|
|
|
* @access public |
592
|
|
|
* @param string|int $entry_slug Either entry ID or entry slug string |
593
|
|
|
* @param boolean $force_allow_ids Force the get_entry() method to allow passed entry IDs, even if the `gravityview_custom_entry_slug_allow_id` filter returns false. |
594
|
|
|
* @param boolean $check_entry_display Check whether the entry is visible for the current View configuration. Default: true. {@since 1.14} |
595
|
|
|
* @return array|boolean |
596
|
|
|
*/ |
597
|
|
|
public static function get_entry( $entry_slug, $force_allow_ids = false, $check_entry_display = true ) { |
598
|
|
|
|
599
|
|
|
if ( class_exists( 'GFAPI' ) && ! empty( $entry_slug ) ) { |
600
|
|
|
|
601
|
|
|
/** |
602
|
|
|
* @filter `gravityview_custom_entry_slug` Whether to enable and use custom entry slugs. |
603
|
|
|
* @param boolean True: Allow for slugs based on entry values. False: always use entry IDs (default) |
604
|
|
|
*/ |
605
|
|
|
$custom_slug = apply_filters( 'gravityview_custom_entry_slug', false ); |
606
|
|
|
|
607
|
|
|
/** |
608
|
|
|
* @filter `gravityview_custom_entry_slug_allow_id` When using a custom slug, allow access to the entry using the original slug (the Entry ID). |
609
|
|
|
* - If disabled (default), only allow access to an entry using the custom slug value. (example: `/entry/custom-slug/` NOT `/entry/123/`) |
610
|
|
|
* - If enabled, you could access using the custom slug OR the entry id (example: `/entry/custom-slug/` OR `/entry/123/`) |
611
|
|
|
* @param boolean $custom_slug_id_access True: allow accessing the slug by ID; False: only use the slug passed to the method. |
612
|
|
|
*/ |
613
|
|
|
$custom_slug_id_access = $force_allow_ids || apply_filters( 'gravityview_custom_entry_slug_allow_id', false ); |
614
|
|
|
|
615
|
|
|
/** |
616
|
|
|
* If we're using custom entry slugs, we do a meta value search |
617
|
|
|
* instead of doing a straightup ID search. |
618
|
|
|
*/ |
619
|
|
|
if ( $custom_slug ) { |
620
|
|
|
|
621
|
|
|
$entry_id = self::get_entry_id_from_slug( $entry_slug ); |
622
|
|
|
|
623
|
|
|
} |
624
|
|
|
|
625
|
|
|
// If custom slug is off, search using the entry ID |
626
|
|
|
// ID allow ID access is on, also use entry ID as a backup |
627
|
|
|
if ( empty( $custom_slug ) || ! empty( $custom_slug_id_access ) ) { |
628
|
|
|
// Search for IDs matching $entry_slug |
629
|
|
|
$entry_id = $entry_slug; |
630
|
|
|
} |
631
|
|
|
|
632
|
|
|
if ( empty( $entry_id ) ) { |
633
|
|
|
return false; |
634
|
|
|
} |
635
|
|
|
|
636
|
|
|
// fetch the entry |
637
|
|
|
$entry = GFAPI::get_entry( $entry_id ); |
638
|
|
|
|
639
|
|
|
/** |
640
|
|
|
* @filter `gravityview/common/get_entry/check_entry_display` Override whether to check entry display rules against filters |
641
|
|
|
* @since 1.16.2 |
642
|
|
|
* @param bool $check_entry_display Check whether the entry is visible for the current View configuration. Default: true. |
643
|
|
|
* @param array $entry Gravity Forms entry array |
644
|
|
|
*/ |
645
|
|
|
$check_entry_display = apply_filters( 'gravityview/common/get_entry/check_entry_display', $check_entry_display, $entry ); |
646
|
|
|
|
647
|
|
|
if( $check_entry_display ) { |
|
|
|
|
648
|
|
|
// Is the entry allowed |
649
|
|
|
$entry = self::check_entry_display( $entry ); |
650
|
|
|
} |
651
|
|
|
|
652
|
|
|
return is_wp_error( $entry ) ? false : $entry; |
653
|
|
|
|
654
|
|
|
} |
655
|
|
|
|
656
|
|
|
return false; |
657
|
|
|
} |
658
|
|
|
|
659
|
|
|
/** |
660
|
|
|
* Wrapper for the GFFormsModel::matches_operation() method that adds additional comparisons, including: |
661
|
|
|
* 'equals', 'greater_than_or_is', 'greater_than_or_equals', 'less_than_or_is', 'less_than_or_equals', |
662
|
|
|
* and 'not_contains' |
663
|
|
|
* |
664
|
|
|
* @since 1.13 You can define context, which displays/hides based on what's being displayed (single, multiple, edit) |
665
|
|
|
* |
666
|
|
|
* @see http://docs.gravityview.co/article/252-gvlogic-shortcode |
667
|
|
|
* @uses GFFormsModel::matches_operation |
668
|
|
|
* @since 1.7.5 |
669
|
|
|
* |
670
|
|
|
* @param string $val1 Left side of comparison |
671
|
|
|
* @param string $val2 Right side of comparison |
672
|
|
|
* @param string $operation Type of comparison |
673
|
|
|
* |
674
|
|
|
* @return bool True: matches, false: not matches |
675
|
|
|
*/ |
676
|
|
|
public static function matches_operation( $val1, $val2, $operation ) { |
677
|
|
|
|
678
|
|
|
$value = false; |
679
|
|
|
|
680
|
|
|
if( 'context' === $val1 ) { |
|
|
|
|
681
|
|
|
|
682
|
|
|
$matching_contexts = array( $val2 ); |
683
|
|
|
|
684
|
|
|
// We allow for non-standard contexts. |
685
|
|
|
switch( $val2 ) { |
|
|
|
|
686
|
|
|
// Check for either single or edit |
687
|
|
|
case 'singular': |
688
|
|
|
$matching_contexts = array( 'single', 'edit' ); |
689
|
|
|
break; |
690
|
|
|
// Use multiple as alias for directory for consistency |
691
|
|
|
case 'multiple': |
692
|
|
|
$matching_contexts = array( 'directory' ); |
693
|
|
|
break; |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
$val1 = in_array( gravityview_get_context(), $matching_contexts ) ? $val2 : false; |
697
|
|
|
} |
698
|
|
|
|
699
|
|
|
switch ( $operation ) { |
700
|
|
|
case 'equals': |
701
|
|
|
$value = GFFormsModel::matches_operation( $val1, $val2, 'is' ); |
702
|
|
|
break; |
703
|
|
|
case 'greater_than_or_is': |
704
|
|
|
case 'greater_than_or_equals': |
705
|
|
|
$is = GFFormsModel::matches_operation( $val1, $val2, 'is' ); |
706
|
|
|
$gt = GFFormsModel::matches_operation( $val1, $val2, 'greater_than' ); |
707
|
|
|
$value = ( $is || $gt ); |
708
|
|
|
break; |
709
|
|
|
case 'less_than_or_is': |
710
|
|
|
case 'less_than_or_equals': |
711
|
|
|
$is = GFFormsModel::matches_operation( $val1, $val2, 'is' ); |
712
|
|
|
$gt = GFFormsModel::matches_operation( $val1, $val2, 'less_than' ); |
713
|
|
|
$value = ( $is || $gt ); |
714
|
|
|
break; |
715
|
|
|
case 'not_contains': |
716
|
|
|
$contains = GFFormsModel::matches_operation( $val1, $val2, 'contains' ); |
717
|
|
|
$value = ! $contains; |
718
|
|
|
break; |
719
|
|
|
default: |
720
|
|
|
$value = GFFormsModel::matches_operation( $val1, $val2, $operation ); |
721
|
|
|
} |
722
|
|
|
|
723
|
|
|
return $value; |
724
|
|
|
} |
725
|
|
|
|
726
|
|
|
/** |
727
|
|
|
* |
728
|
|
|
* Checks if a certain entry is valid according to the View search filters (specially the Adv Filters) |
729
|
|
|
* |
730
|
|
|
* @see GFFormsModel::is_value_match() |
731
|
|
|
* |
732
|
|
|
* @since 1.7.4 |
733
|
|
|
* @todo Return WP_Error instead of boolean |
734
|
|
|
* |
735
|
|
|
* @param array $entry Gravity Forms Entry object |
736
|
|
|
* @return bool|array Returns 'false' if entry is not valid according to the view search filters (Adv Filter) |
737
|
|
|
*/ |
738
|
|
|
public static function check_entry_display( $entry ) { |
739
|
|
|
|
740
|
|
|
if ( ! $entry || is_wp_error( $entry ) ) { |
|
|
|
|
741
|
|
|
do_action( 'gravityview_log_debug', __METHOD__ . ' Entry was not found.', $entry ); |
742
|
|
|
return false; |
743
|
|
|
} |
744
|
|
|
|
745
|
|
|
if ( empty( $entry['form_id'] ) ) { |
746
|
|
|
do_action( 'gravityview_log_debug', '[apply_filters_to_entry] Entry is empty! Entry:', $entry ); |
747
|
|
|
return false; |
748
|
|
|
} |
749
|
|
|
|
750
|
|
|
$criteria = self::calculate_get_entries_criteria(); |
751
|
|
|
|
752
|
|
|
// Make sure the current View is connected to the same form as the Entry |
753
|
|
|
if( ! empty( $criteria['context_view_id'] ) ) { |
|
|
|
|
754
|
|
|
$context_view_id = intval( $criteria['context_view_id'] ); |
755
|
|
|
$context_form_id = gravityview_get_form_id( $context_view_id ); |
756
|
|
|
if( intval( $context_form_id ) !== intval( $entry['form_id'] ) ) { |
|
|
|
|
757
|
|
|
do_action( 'gravityview_log_debug', sprintf( '[apply_filters_to_entry] Entry form ID does not match current View connected form ID:', $entry['form_id'] ), $criteria['context_view_id'] ); |
758
|
|
|
return false; |
759
|
|
|
} |
760
|
|
|
} |
761
|
|
|
|
762
|
|
|
if ( empty( $criteria['search_criteria'] ) || ! is_array( $criteria['search_criteria'] ) ) { |
763
|
|
|
do_action( 'gravityview_log_debug', '[apply_filters_to_entry] Entry approved! No search criteria found:', $criteria ); |
764
|
|
|
return $entry; |
765
|
|
|
} |
766
|
|
|
|
767
|
|
|
$search_criteria = $criteria['search_criteria']; |
768
|
|
|
unset( $criteria ); |
769
|
|
|
|
770
|
|
|
// check entry status |
771
|
|
|
if ( array_key_exists( 'status', $search_criteria ) && $search_criteria['status'] != $entry['status'] ) { |
772
|
|
|
do_action( 'gravityview_log_debug', sprintf( '[apply_filters_to_entry] Entry status - %s - is not valid according to filter:', $entry['status'] ), $search_criteria ); |
773
|
|
|
return false; |
774
|
|
|
} |
775
|
|
|
|
776
|
|
|
// check entry date |
777
|
|
|
// @todo: Does it make sense to apply the Date create filters to the single entry? |
778
|
|
|
|
779
|
|
|
// field_filters |
780
|
|
|
if ( empty( $search_criteria['field_filters'] ) || ! is_array( $search_criteria['field_filters'] ) ) { |
781
|
|
|
do_action( 'gravityview_log_debug', '[apply_filters_to_entry] Entry approved! No field filters criteria found:', $search_criteria ); |
782
|
|
|
return $entry; |
783
|
|
|
} |
784
|
|
|
|
785
|
|
|
$filters = $search_criteria['field_filters']; |
786
|
|
|
unset( $search_criteria ); |
787
|
|
|
|
788
|
|
|
$mode = array_key_exists( 'mode', $filters ) ? strtolower( $filters['mode'] ) : 'all'; |
789
|
|
|
unset( $filters['mode'] ); |
790
|
|
|
|
791
|
|
|
$form = self::get_form( $entry['form_id'] ); |
792
|
|
|
|
793
|
|
|
foreach ( $filters as $filter ) { |
794
|
|
|
|
795
|
|
|
if ( ! isset( $filter['key'] ) ) { |
796
|
|
|
continue; |
797
|
|
|
} |
798
|
|
|
|
799
|
|
|
$k = $filter['key']; |
800
|
|
|
|
801
|
|
|
if ( in_array( $k, array( 'created_by', 'payment_status' ) ) ) { |
802
|
|
|
$field_value = $entry[ $k ]; |
803
|
|
|
$field = null; |
804
|
|
|
} else { |
805
|
|
|
$field = self::get_field( $form, $k ); |
806
|
|
|
$field_value = GFFormsModel::get_lead_field_value( $entry, $field ); |
807
|
|
|
} |
808
|
|
|
|
809
|
|
|
$operator = isset( $filter['operator'] ) ? strtolower( $filter['operator'] ) : 'is'; |
810
|
|
|
$is_value_match = GFFormsModel::is_value_match( $field_value, $filter['value'], $operator, $field ); |
811
|
|
|
|
812
|
|
|
// verify if we are already free to go! |
813
|
|
|
if ( ! $is_value_match && 'all' === $mode ) { |
814
|
|
|
do_action( 'gravityview_log_debug', '[apply_filters_to_entry] Entry cannot be displayed. Failed one criteria for ALL mode', $filter ); |
815
|
|
|
return false; |
816
|
|
|
} elseif ( $is_value_match && 'any' === $mode ) { |
817
|
|
|
return $entry; |
818
|
|
|
} |
819
|
|
|
} |
820
|
|
|
|
821
|
|
|
// at this point, if in ALL mode, then entry is approved - all conditions were met. |
822
|
|
|
// Or, for ANY mode, means none of the conditions were satisfied, so entry is not approved |
823
|
|
|
if ( 'all' === $mode ) { |
824
|
|
|
return $entry; |
825
|
|
|
} else { |
826
|
|
|
do_action( 'gravityview_log_debug', '[apply_filters_to_entry] Entry cannot be displayed. Failed all the criteria for ANY mode', $filters ); |
827
|
|
|
return false; |
828
|
|
|
} |
829
|
|
|
|
830
|
|
|
} |
831
|
|
|
|
832
|
|
|
|
833
|
|
|
/** |
834
|
|
|
* Allow formatting date and time based on GravityView standards |
835
|
|
|
* |
836
|
|
|
* @since 1.16 |
837
|
|
|
* |
838
|
|
|
* @see GVCommon_Test::test_format_date for examples |
839
|
|
|
* |
840
|
|
|
* @param string $date_string The date as stored by Gravity Forms (`Y-m-d h:i:s` GMT) |
841
|
|
|
* @param string|array $args Array or string of settings for output parsed by `wp_parse_args()`; Can use `raw=1` or `array('raw' => true)` \n |
842
|
|
|
* - `raw` Un-formatted date string in original `Y-m-d h:i:s` format |
843
|
|
|
* - `timestamp` Integer timestamp returned by GFCommon::get_local_timestamp() |
844
|
|
|
* - `diff` "%s ago" format, unless other `format` is defined |
845
|
|
|
* - `human` Set $is_human parameter to true for `GFCommon::format_date()`. Shows `diff` within 24 hours or date after. Format based on blog setting, unless `format` is defined. |
846
|
|
|
* - `time` Include time in the `GFCommon::format_date()` output |
847
|
|
|
* - `format` Define your own date format, or `diff` format |
848
|
|
|
* |
849
|
|
|
* @return int|null|string Formatted date based on the original date |
850
|
|
|
*/ |
851
|
|
|
public static function format_date( $date_string = '', $args = array() ) { |
852
|
|
|
|
853
|
|
|
$default_atts = array( |
854
|
|
|
'raw' => false, |
855
|
|
|
'timestamp' => false, |
856
|
|
|
'diff' => false, |
857
|
|
|
'human' => false, |
858
|
|
|
'format' => '', |
859
|
|
|
'time' => false, |
860
|
|
|
); |
861
|
|
|
|
862
|
|
|
$atts = wp_parse_args( $args, $default_atts ); |
863
|
|
|
|
864
|
|
|
/** |
865
|
|
|
* Gravity Forms code to adjust date to locally-configured Time Zone |
866
|
|
|
* @see GFCommon::format_date() for original code |
867
|
|
|
*/ |
868
|
|
|
$date_gmt_time = mysql2date( 'G', $date_string ); |
869
|
|
|
$date_local_timestamp = GFCommon::get_local_timestamp( $date_gmt_time ); |
870
|
|
|
|
871
|
|
|
$format = rgar( $atts, 'format' ); |
872
|
|
|
$is_human = ! empty( $atts['human'] ); |
873
|
|
|
$is_diff = ! empty( $atts['diff'] ); |
874
|
|
|
$is_raw = ! empty( $atts['raw'] ); |
875
|
|
|
$is_timestamp = ! empty( $atts['timestamp'] ); |
876
|
|
|
$include_time = ! empty( $atts['time'] ); |
877
|
|
|
|
878
|
|
|
// If we're using time diff, we want to have a different default format |
879
|
|
|
if( empty( $format ) ) { |
|
|
|
|
880
|
|
|
$format = $is_diff ? esc_html__( '%s ago', 'gravityview' ) : get_option( 'date_format' ); |
881
|
|
|
} |
882
|
|
|
|
883
|
|
|
// If raw was specified, don't modify the stored value |
884
|
|
|
if ( $is_raw ) { |
885
|
|
|
$formatted_date = $date_string; |
886
|
|
|
} elseif( $is_timestamp ) { |
|
|
|
|
887
|
|
|
$formatted_date = $date_local_timestamp; |
888
|
|
|
} elseif ( $is_diff ) { |
889
|
|
|
$formatted_date = sprintf( $format, human_time_diff( $date_gmt_time ) ); |
890
|
|
|
} else { |
891
|
|
|
$formatted_date = GFCommon::format_date( $date_string, $is_human, $format, $include_time ); |
892
|
|
|
} |
893
|
|
|
|
894
|
|
|
unset( $format, $is_diff, $is_human, $is_timestamp, $is_raw, $date_gmt_time, $date_local_timestamp, $default_atts ); |
895
|
|
|
|
896
|
|
|
return $formatted_date; |
897
|
|
|
} |
898
|
|
|
|
899
|
|
|
/** |
900
|
|
|
* Retrieve the label of a given field id (for a specific form) |
901
|
|
|
* |
902
|
|
|
* @access public |
903
|
|
|
* @param array $form |
904
|
|
|
* @param string $field_id |
905
|
|
|
* @return string |
906
|
|
|
*/ |
907
|
|
|
public static function get_field_label( $form = array(), $field_id = '' ) { |
908
|
|
|
|
909
|
|
|
if ( empty( $form ) || empty( $field_id ) ) { |
910
|
|
|
return ''; |
911
|
|
|
} |
912
|
|
|
|
913
|
|
|
$field = self::get_field( $form, $field_id ); |
914
|
|
|
return isset( $field['label'] ) ? $field['label'] : ''; |
915
|
|
|
|
916
|
|
|
} |
917
|
|
|
|
918
|
|
|
|
919
|
|
|
/** |
920
|
|
|
* Returns the field details array of a specific form given the field id |
921
|
|
|
* |
922
|
|
|
* Alias of GFFormsModel::get_field |
923
|
|
|
* |
924
|
|
|
* @uses GFFormsModel::get_field |
925
|
|
|
* @see GFFormsModel::get_field |
926
|
|
|
* @access public |
927
|
|
|
* @param array $form |
928
|
|
|
* @param string|int $field_id |
929
|
|
|
* @return array|null Array: Gravity Forms field array; NULL: Gravity Forms GFFormsModel does not exist |
930
|
|
|
*/ |
931
|
|
|
public static function get_field( $form, $field_id ) { |
932
|
|
|
if ( class_exists( 'GFFormsModel' ) ){ |
933
|
|
|
return GFFormsModel::get_field( $form, $field_id ); |
934
|
|
|
} else { |
935
|
|
|
return null; |
936
|
|
|
} |
937
|
|
|
} |
938
|
|
|
|
939
|
|
|
|
940
|
|
|
/** |
941
|
|
|
* Check whether the post is GravityView |
942
|
|
|
* |
943
|
|
|
* - Check post type. Is it `gravityview`? |
944
|
|
|
* - Check shortcode |
945
|
|
|
* |
946
|
|
|
* @param WP_Post $post WordPress post object |
947
|
|
|
* @return boolean True: yep, GravityView; No: not! |
948
|
|
|
*/ |
949
|
|
|
public static function has_gravityview_shortcode( $post = null ) { |
950
|
|
|
if ( ! is_a( $post, 'WP_Post' ) ) { |
951
|
|
|
return false; |
952
|
|
|
} |
953
|
|
|
|
954
|
|
|
if ( 'gravityview' === get_post_type( $post ) ) { |
955
|
|
|
return true; |
956
|
|
|
} |
957
|
|
|
|
958
|
|
|
return self::has_shortcode_r( $post->post_content, 'gravityview' ) ? true : false; |
959
|
|
|
|
960
|
|
|
} |
961
|
|
|
|
962
|
|
|
|
963
|
|
|
/** |
964
|
|
|
* Placeholder until the recursive has_shortcode() patch is merged |
965
|
|
|
* @see https://core.trac.wordpress.org/ticket/26343#comment:10 |
966
|
|
|
* @param string $content Content to check whether there's a shortcode |
967
|
|
|
* @param string $tag Current shortcode tag |
968
|
|
|
*/ |
969
|
|
|
public static function has_shortcode_r( $content, $tag = 'gravityview' ) { |
970
|
|
|
if ( false === strpos( $content, '[' ) ) { |
971
|
|
|
return false; |
972
|
|
|
} |
973
|
|
|
|
974
|
|
|
if ( shortcode_exists( $tag ) ) { |
975
|
|
|
|
976
|
|
|
$shortcodes = array(); |
977
|
|
|
|
978
|
|
|
preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches, PREG_SET_ORDER ); |
979
|
|
|
if ( empty( $matches ) ){ |
980
|
|
|
return false; |
981
|
|
|
} |
982
|
|
|
|
983
|
|
|
foreach ( $matches as $shortcode ) { |
984
|
|
|
if ( $tag === $shortcode[2] ) { |
985
|
|
|
|
986
|
|
|
// Changed this to $shortcode instead of true so we get the parsed atts. |
987
|
|
|
$shortcodes[] = $shortcode; |
988
|
|
|
|
989
|
|
|
} else if ( isset( $shortcode[5] ) && $result = self::has_shortcode_r( $shortcode[5], $tag ) ) { |
990
|
|
|
$shortcodes = $result; |
991
|
|
|
} |
992
|
|
|
} |
993
|
|
|
|
994
|
|
|
return $shortcodes; |
995
|
|
|
} |
996
|
|
|
return false; |
997
|
|
|
} |
998
|
|
|
|
999
|
|
|
|
1000
|
|
|
|
1001
|
|
|
/** |
1002
|
|
|
* Get the views for a particular form |
1003
|
|
|
* |
1004
|
|
|
* @since 1.15.2 Add $args array and limit posts_per_page to 500 |
1005
|
|
|
* |
1006
|
|
|
* @uses get_posts() |
1007
|
|
|
* |
1008
|
|
|
* @param int $form_id Gravity Forms form ID |
1009
|
|
|
* @param array $args Pass args sent to get_posts() |
1010
|
|
|
* |
1011
|
|
|
* @return array Array with view details, as returned by get_posts() |
1012
|
|
|
*/ |
1013
|
|
|
public static function get_connected_views( $form_id, $args = array() ) { |
1014
|
|
|
|
1015
|
|
|
$defaults = array( |
1016
|
|
|
'post_type' => 'gravityview', |
1017
|
|
|
'posts_per_page' => 100, |
|
|
|
|
1018
|
|
|
'meta_key' => '_gravityview_form_id', |
|
|
|
|
1019
|
|
|
'meta_value' => (int)$form_id, |
|
|
|
|
1020
|
|
|
); |
1021
|
|
|
|
1022
|
|
|
$args = wp_parse_args( $args, $defaults ); |
1023
|
|
|
|
1024
|
|
|
$views = get_posts( $args ); |
1025
|
|
|
|
1026
|
|
|
return $views; |
1027
|
|
|
} |
1028
|
|
|
|
1029
|
|
|
/** |
1030
|
|
|
* Get the Gravity Forms form ID connected to a View |
1031
|
|
|
* |
1032
|
|
|
* @param int $view_id The ID of the View to get the connected form of |
1033
|
|
|
* |
1034
|
|
|
* @return string ID of the connected Form, if exists. Empty string if not. |
1035
|
|
|
*/ |
1036
|
|
|
public static function get_meta_form_id( $view_id ) { |
1037
|
|
|
return get_post_meta( $view_id, '_gravityview_form_id', true ); |
1038
|
|
|
} |
1039
|
|
|
|
1040
|
|
|
/** |
1041
|
|
|
* Get the template ID (`list`, `table`, `datatables`, `map`) for a View |
1042
|
|
|
* |
1043
|
|
|
* @see GravityView_Template::template_id |
1044
|
|
|
* |
1045
|
|
|
* @param int $view_id The ID of the View to get the layout of |
1046
|
|
|
* |
1047
|
|
|
* @return string GravityView_Template::template_id value. Empty string if not. |
1048
|
|
|
*/ |
1049
|
|
|
public static function get_meta_template_id( $view_id ) { |
1050
|
|
|
return get_post_meta( $view_id, '_gravityview_directory_template', true ); |
1051
|
|
|
} |
1052
|
|
|
|
1053
|
|
|
|
1054
|
|
|
/** |
1055
|
|
|
* Get all the settings for a View |
1056
|
|
|
* |
1057
|
|
|
* @uses GravityView_View_Data::get_default_args() Parses the settings with the plugin defaults as backups. |
1058
|
|
|
* @param int $post_id View ID |
1059
|
|
|
* @return array Associative array of settings with plugin defaults used if not set by the View |
1060
|
|
|
*/ |
1061
|
|
|
public static function get_template_settings( $post_id ) { |
1062
|
|
|
|
1063
|
|
|
$settings = get_post_meta( $post_id, '_gravityview_template_settings', true ); |
1064
|
|
|
|
1065
|
|
|
if ( class_exists( 'GravityView_View_Data' ) ) { |
1066
|
|
|
|
1067
|
|
|
$defaults = GravityView_View_Data::get_default_args(); |
1068
|
|
|
|
1069
|
|
|
return wp_parse_args( (array)$settings, $defaults ); |
|
|
|
|
1070
|
|
|
|
1071
|
|
|
} |
1072
|
|
|
|
1073
|
|
|
// Backup, in case GravityView_View_Data isn't loaded yet. |
1074
|
|
|
return $settings; |
1075
|
|
|
} |
1076
|
|
|
|
1077
|
|
|
/** |
1078
|
|
|
* Get the setting for a View |
1079
|
|
|
* |
1080
|
|
|
* If the setting isn't set by the View, it returns the plugin default. |
1081
|
|
|
* |
1082
|
|
|
* @param int $post_id View ID |
1083
|
|
|
* @param string $key Key for the setting |
1084
|
|
|
* @return mixed|null Setting value, or NULL if not set. |
1085
|
|
|
*/ |
1086
|
|
|
public static function get_template_setting( $post_id, $key ) { |
1087
|
|
|
|
1088
|
|
|
$settings = self::get_template_settings( $post_id ); |
1089
|
|
|
|
1090
|
|
|
if ( isset( $settings[ $key ] ) ) { |
1091
|
|
|
return $settings[ $key ]; |
1092
|
|
|
} |
1093
|
|
|
|
1094
|
|
|
return null; |
1095
|
|
|
} |
1096
|
|
|
|
1097
|
|
|
/** |
1098
|
|
|
* Get the field configuration for the View |
1099
|
|
|
* |
1100
|
|
|
* array( |
1101
|
|
|
* |
1102
|
|
|
* [other zones] |
1103
|
|
|
* |
1104
|
|
|
* 'directory_list-title' => array( |
1105
|
|
|
* |
1106
|
|
|
* [other fields] |
1107
|
|
|
* |
1108
|
|
|
* '5372653f25d44' => array( |
1109
|
|
|
* 'id' => string '9' (length=1) |
1110
|
|
|
* 'label' => string 'Screenshots' (length=11) |
1111
|
|
|
* 'show_label' => string '1' (length=1) |
1112
|
|
|
* 'custom_label' => string '' (length=0) |
1113
|
|
|
* 'custom_class' => string 'gv-gallery' (length=10) |
1114
|
|
|
* 'only_loggedin' => string '0' (length=1) |
1115
|
|
|
* 'only_loggedin_cap' => string 'read' (length=4) |
1116
|
|
|
* ) |
1117
|
|
|
* |
1118
|
|
|
* [other fields] |
1119
|
|
|
* ) |
1120
|
|
|
* |
1121
|
|
|
* [other zones] |
1122
|
|
|
* ) |
1123
|
|
|
* |
1124
|
|
|
* @param int $post_id View ID |
1125
|
|
|
* @return array Multi-array of fields with first level being the field zones. See code comment. |
1126
|
|
|
*/ |
1127
|
|
|
public static function get_directory_fields( $post_id ) { |
1128
|
|
|
return get_post_meta( $post_id, '_gravityview_directory_fields', true ); |
1129
|
|
|
} |
1130
|
|
|
|
1131
|
|
|
|
1132
|
|
|
/** |
1133
|
|
|
* Render dropdown (select) with the list of sortable fields from a form ID |
1134
|
|
|
* |
1135
|
|
|
* @access public |
1136
|
|
|
* @param int $formid Form ID |
1137
|
|
|
* @return string html |
1138
|
|
|
*/ |
1139
|
|
|
public static function get_sortable_fields( $formid, $current = '' ) { |
1140
|
|
|
$output = '<option value="" ' . selected( '', $current, false ).'>' . esc_html__( 'Default', 'gravityview' ) .'</option>'; |
1141
|
|
|
|
1142
|
|
|
if ( empty( $formid ) ) { |
1143
|
|
|
return $output; |
1144
|
|
|
} |
1145
|
|
|
|
1146
|
|
|
$fields = self::get_sortable_fields_array( $formid ); |
1147
|
|
|
|
1148
|
|
|
if ( ! empty( $fields ) ) { |
1149
|
|
|
|
1150
|
|
|
$blacklist_field_types = apply_filters( 'gravityview_blacklist_field_types', array( 'list', 'textarea' ), null ); |
1151
|
|
|
|
1152
|
|
|
foreach ( $fields as $id => $field ) { |
1153
|
|
|
if ( in_array( $field['type'], $blacklist_field_types ) ) { |
1154
|
|
|
continue; |
1155
|
|
|
} |
1156
|
|
|
|
1157
|
|
|
$output .= '<option value="'. $id .'" '. selected( $id, $current, false ).'>'. esc_attr( $field['label'] ) .'</option>'; |
1158
|
|
|
} |
1159
|
|
|
} |
1160
|
|
|
|
1161
|
|
|
return $output; |
1162
|
|
|
} |
1163
|
|
|
|
1164
|
|
|
/** |
1165
|
|
|
* |
1166
|
|
|
* @param int $formid Gravity Forms form ID |
1167
|
|
|
* @param array $blacklist Field types to exclude |
1168
|
|
|
* |
1169
|
|
|
* @since TODO |
1170
|
|
|
* |
1171
|
|
|
* @todo Get all fields, check if sortable dynamically |
1172
|
|
|
* |
1173
|
|
|
* @return array |
1174
|
|
|
*/ |
1175
|
|
|
public static function get_sortable_fields_array( $formid, $blacklist = array( 'list', 'textarea' ) ) { |
1176
|
|
|
|
1177
|
|
|
// Get fields with sub-inputs and no parent |
1178
|
|
|
$fields = self::get_form_fields( $formid, true, false ); |
1179
|
|
|
|
1180
|
|
|
$date_created = array( |
1181
|
|
|
'date_created' => array( |
1182
|
|
|
'type' => 'date_created', |
1183
|
|
|
'label' => __( 'Date Created', 'gravityview' ), |
1184
|
|
|
), |
1185
|
|
|
); |
1186
|
|
|
|
1187
|
|
|
$fields = $date_created + $fields; |
1188
|
|
|
|
1189
|
|
|
$blacklist_field_types = apply_filters( 'gravityview_blacklist_field_types', $blacklist, NULL ); |
|
|
|
|
1190
|
|
|
|
1191
|
|
|
// TODO: Convert to using array_filter |
1192
|
|
|
foreach( $fields as $id => $field ) { |
|
|
|
|
1193
|
|
|
|
1194
|
|
|
if( in_array( $field['type'], $blacklist_field_types ) ) { |
|
|
|
|
1195
|
|
|
unset( $fields[ $id ] ); |
1196
|
|
|
} |
1197
|
|
|
} |
1198
|
|
|
|
1199
|
|
|
/** |
1200
|
|
|
* @filter `gravityview/common/sortable_fields` Filter the sortable fields |
1201
|
|
|
* @since 1.12 |
1202
|
|
|
* @param array $fields Sub-set of GF form fields that are sortable |
1203
|
|
|
* @param int $formid The Gravity Forms form ID that the fields are from |
1204
|
|
|
*/ |
1205
|
|
|
$fields = apply_filters( 'gravityview/common/sortable_fields', $fields, $formid ); |
1206
|
|
|
|
1207
|
|
|
return $fields; |
1208
|
|
|
} |
1209
|
|
|
|
1210
|
|
|
/** |
1211
|
|
|
* Returns the GF Form field type for a certain field(id) of a form |
1212
|
|
|
* @param object $form Gravity Forms form |
1213
|
|
|
* @param mixed $field_id Field ID or Field array |
1214
|
|
|
* @return string field type |
1215
|
|
|
*/ |
1216
|
|
|
public static function get_field_type( $form = null, $field_id = '' ) { |
1217
|
|
|
|
1218
|
|
|
if ( ! empty( $field_id ) && ! is_array( $field_id ) ) { |
1219
|
|
|
$field = self::get_field( $form, $field_id ); |
1220
|
|
|
} else { |
1221
|
|
|
$field = $field_id; |
1222
|
|
|
} |
1223
|
|
|
|
1224
|
|
|
return class_exists( 'RGFormsModel' ) ? RGFormsModel::get_input_type( $field ) : ''; |
1225
|
|
|
|
1226
|
|
|
} |
1227
|
|
|
|
1228
|
|
|
|
1229
|
|
|
/** |
1230
|
|
|
* Checks if the field type is a 'numeric' field type (e.g. to be used when sorting) |
1231
|
|
|
* @param int|array $form form ID or form array |
1232
|
|
|
* @param int|array $field field key or field array |
1233
|
|
|
* @return boolean |
1234
|
|
|
*/ |
1235
|
|
|
public static function is_field_numeric( $form = null, $field = '' ) { |
1236
|
|
|
|
1237
|
|
|
if ( ! is_array( $form ) && ! is_array( $field ) ) { |
1238
|
|
|
$form = self::get_form( $form ); |
1239
|
|
|
} |
1240
|
|
|
|
1241
|
|
|
// If entry meta, it's a string. Otherwise, numeric |
1242
|
|
|
if( ! is_numeric( $field ) && is_string( $field ) ) { |
|
|
|
|
1243
|
|
|
$type = $field; |
1244
|
|
|
} else { |
1245
|
|
|
$type = self::get_field_type( $form, $field ); |
1246
|
|
|
} |
1247
|
|
|
|
1248
|
|
|
/** |
1249
|
|
|
* @filter `gravityview/common/numeric_types` What types of fields are numeric? |
1250
|
|
|
* @since 1.5.2 |
1251
|
|
|
* @param array $numeric_types Fields that are numeric. Default: `[ number, time ]` |
1252
|
|
|
*/ |
1253
|
|
|
$numeric_types = apply_filters( 'gravityview/common/numeric_types', array( 'number', 'time' ) ); |
1254
|
|
|
|
1255
|
|
|
// Defer to GravityView_Field setting, if the field type is registered and `is_numeric` is true |
1256
|
|
|
if( $gv_field = GravityView_Fields::get( $type ) ) { |
|
|
|
|
1257
|
|
|
if( true === $gv_field->is_numeric ) { |
|
|
|
|
1258
|
|
|
$numeric_types[] = $gv_field->is_numeric; |
1259
|
|
|
} |
1260
|
|
|
} |
1261
|
|
|
|
1262
|
|
|
$return = in_array( $type, $numeric_types ); |
1263
|
|
|
|
1264
|
|
|
return $return; |
1265
|
|
|
} |
1266
|
|
|
|
1267
|
|
|
/** |
1268
|
|
|
* Encrypt content using Javascript so that it's hidden when JS is disabled. |
1269
|
|
|
* |
1270
|
|
|
* This is mostly used to hide email addresses from scraper bots. |
1271
|
|
|
* |
1272
|
|
|
* @param string $content Content to encrypt |
1273
|
|
|
* @param string $message Message shown if Javascript is disabled |
1274
|
|
|
* |
1275
|
|
|
* @see https://github.com/jnicol/standalone-phpenkoder StandalonePHPEnkoder on Github |
1276
|
|
|
* |
1277
|
|
|
* @since 1.7 |
1278
|
|
|
* |
1279
|
|
|
* @return string Content, encrypted |
1280
|
|
|
*/ |
1281
|
|
|
public static function js_encrypt( $content, $message = '' ) { |
1282
|
|
|
|
1283
|
|
|
$output = $content; |
1284
|
|
|
|
1285
|
|
|
if ( ! class_exists( 'StandalonePHPEnkoder' ) ) { |
1286
|
|
|
include_once( GRAVITYVIEW_DIR . 'includes/lib/standalone-phpenkoder/StandalonePHPEnkoder.php' ); |
1287
|
|
|
} |
1288
|
|
|
|
1289
|
|
|
if ( class_exists( 'StandalonePHPEnkoder' ) ) { |
1290
|
|
|
|
1291
|
|
|
$enkoder = new StandalonePHPEnkoder; |
1292
|
|
|
|
1293
|
|
|
$message = empty( $message ) ? __( 'Email hidden; Javascript is required.', 'gravityview' ) : $message; |
1294
|
|
|
|
1295
|
|
|
/** |
1296
|
|
|
* @filter `gravityview/phpenkoder/msg` Modify the message shown when Javascript is disabled and an encrypted email field is displayed |
1297
|
|
|
* @since 1.7 |
1298
|
|
|
* @param string $message Existing message |
1299
|
|
|
* @param string $content Content to encrypt |
1300
|
|
|
*/ |
1301
|
|
|
$enkoder->enkode_msg = apply_filters( 'gravityview/phpenkoder/msg', $message, $content ); |
1302
|
|
|
|
1303
|
|
|
$output = $enkoder->enkode( $content ); |
1304
|
|
|
} |
1305
|
|
|
|
1306
|
|
|
return $output; |
1307
|
|
|
} |
1308
|
|
|
|
1309
|
|
|
/** |
1310
|
|
|
* |
1311
|
|
|
* Do the same than parse_str without max_input_vars limitation: |
1312
|
|
|
* Parses $string as if it were the query string passed via a URL and sets variables in the current scope. |
1313
|
|
|
* @param $string array string to parse (not altered like in the original parse_str(), use the second parameter!) |
1314
|
|
|
* @param $result array If the second parameter is present, variables are stored in this variable as array elements |
1315
|
|
|
* @return bool true or false if $string is an empty string |
1316
|
|
|
* @since 1.5.3 |
1317
|
|
|
* |
1318
|
|
|
* @author rubo77 at https://gist.github.com/rubo77/6821632 |
1319
|
|
|
**/ |
1320
|
|
|
public static function gv_parse_str( $string, &$result ) { |
1321
|
|
|
if ( empty( $string ) ) { |
1322
|
|
|
return false; |
1323
|
|
|
} |
1324
|
|
|
|
1325
|
|
|
$result = array(); |
1326
|
|
|
|
1327
|
|
|
// find the pairs "name=value" |
1328
|
|
|
$pairs = explode( '&', $string ); |
1329
|
|
|
|
1330
|
|
|
foreach ( $pairs as $pair ) { |
1331
|
|
|
// use the original parse_str() on each element |
1332
|
|
|
parse_str( $pair, $params ); |
1333
|
|
|
|
1334
|
|
|
$k = key( $params ); |
1335
|
|
|
if ( ! isset( $result[ $k ] ) ) { |
1336
|
|
|
$result += $params; |
1337
|
|
|
} elseif ( array_key_exists( $k, $params ) && is_array( $params[ $k ] ) ) { |
1338
|
|
|
$result[ $k ] = self::array_merge_recursive_distinct( $result[ $k ], $params[ $k ] ); |
1339
|
|
|
} |
1340
|
|
|
} |
1341
|
|
|
return true; |
1342
|
|
|
} |
1343
|
|
|
|
1344
|
|
|
|
1345
|
|
|
/** |
1346
|
|
|
* Generate an HTML anchor tag with a list of supported attributes |
1347
|
|
|
* |
1348
|
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a Supported attributes defined here |
1349
|
|
|
* @uses esc_url_raw() to sanitize $href |
1350
|
|
|
* @uses esc_attr() to sanitize $atts |
1351
|
|
|
* |
1352
|
|
|
* @since 1.6 |
1353
|
|
|
* |
1354
|
|
|
* @param string $href URL of the link. Sanitized using `esc_url_raw()` |
1355
|
|
|
* @param string $anchor_text The text or HTML inside the anchor. This is not sanitized in the function. |
1356
|
|
|
* @param array|string $atts Attributes to be added to the anchor tag. Parsed by `wp_parse_args()`, sanitized using `esc_attr()` |
1357
|
|
|
* |
1358
|
|
|
* @return string HTML output of anchor link. If empty $href, returns NULL |
1359
|
|
|
*/ |
1360
|
|
|
public static function get_link_html( $href = '', $anchor_text = '', $atts = array() ) { |
1361
|
|
|
|
1362
|
|
|
// Supported attributes for anchor tags. HREF left out intentionally. |
1363
|
|
|
$allowed_atts = array( |
1364
|
|
|
'href' => null, // Will override the $href argument if set |
1365
|
|
|
'title' => null, |
1366
|
|
|
'rel' => null, |
1367
|
|
|
'id' => null, |
1368
|
|
|
'class' => null, |
1369
|
|
|
'target' => null, |
1370
|
|
|
'style' => null, |
1371
|
|
|
|
1372
|
|
|
// Used by GravityView |
1373
|
|
|
'data-viewid' => null, |
1374
|
|
|
|
1375
|
|
|
// Not standard |
1376
|
|
|
'hreflang' => null, |
1377
|
|
|
'type' => null, |
1378
|
|
|
'tabindex' => null, |
1379
|
|
|
|
1380
|
|
|
// Deprecated HTML4 but still used |
1381
|
|
|
'name' => null, |
1382
|
|
|
'onclick' => null, |
1383
|
|
|
'onchange' => null, |
1384
|
|
|
'onkeyup' => null, |
1385
|
|
|
|
1386
|
|
|
// HTML5 only |
1387
|
|
|
'download' => null, |
1388
|
|
|
'media' => null, |
1389
|
|
|
'ping' => null, |
1390
|
|
|
); |
1391
|
|
|
|
1392
|
|
|
/** |
1393
|
|
|
* @filter `gravityview/get_link/allowed_atts` Modify the attributes that are allowed to be used in generating links |
1394
|
|
|
* @param array $allowed_atts Array of attributes allowed |
1395
|
|
|
*/ |
1396
|
|
|
$allowed_atts = apply_filters( 'gravityview/get_link/allowed_atts', $allowed_atts ); |
1397
|
|
|
|
1398
|
|
|
// Make sure the attributes are formatted as array |
1399
|
|
|
$passed_atts = wp_parse_args( $atts ); |
1400
|
|
|
|
1401
|
|
|
// Make sure the allowed attributes are only the ones in the $allowed_atts list |
1402
|
|
|
$final_atts = shortcode_atts( $allowed_atts, $passed_atts ); |
1403
|
|
|
|
1404
|
|
|
// Remove attributes with empty values |
1405
|
|
|
$final_atts = array_filter( $final_atts ); |
1406
|
|
|
|
1407
|
|
|
// If the href wasn't passed as an attribute, use the value passed to the function |
1408
|
|
|
if ( empty( $final_atts['href'] ) && ! empty( $href ) ) { |
1409
|
|
|
$final_atts['href'] = $href; |
1410
|
|
|
} |
1411
|
|
|
|
1412
|
|
|
$final_atts['href'] = esc_url_raw( $href ); |
1413
|
|
|
|
1414
|
|
|
// For each attribute, generate the code |
1415
|
|
|
$output = ''; |
1416
|
|
|
foreach ( $final_atts as $attr => $value ) { |
1417
|
|
|
$output .= sprintf( ' %s="%s"', $attr, esc_attr( $value ) ); |
1418
|
|
|
} |
1419
|
|
|
|
1420
|
|
|
$output = '<a'. $output .'>'. $anchor_text .'</a>'; |
1421
|
|
|
|
1422
|
|
|
return $output; |
1423
|
|
|
} |
1424
|
|
|
|
1425
|
|
|
/** |
1426
|
|
|
* array_merge_recursive does indeed merge arrays, but it converts values with duplicate |
1427
|
|
|
* keys to arrays rather than overwriting the value in the first array with the duplicate |
1428
|
|
|
* value in the second array, as array_merge does. |
1429
|
|
|
* |
1430
|
|
|
* @see http://php.net/manual/en/function.array-merge-recursive.php |
1431
|
|
|
* |
1432
|
|
|
* @since 1.5.3 |
1433
|
|
|
* @param array $array1 |
1434
|
|
|
* @param array $array2 |
1435
|
|
|
* @return array |
1436
|
|
|
* @author Daniel <daniel (at) danielsmedegaardbuus (dot) dk> |
1437
|
|
|
* @author Gabriel Sobrinho <gabriel (dot) sobrinho (at) gmail (dot) com> |
1438
|
|
|
*/ |
1439
|
|
|
public static function array_merge_recursive_distinct( array &$array1, array &$array2 ) { |
1440
|
|
|
$merged = $array1; |
1441
|
|
|
|
1442
|
|
|
foreach ( $array2 as $key => &$value ) { |
1443
|
|
|
if ( is_array( $value ) && isset( $merged[ $key ] ) && is_array( $merged[ $key ] ) ) { |
1444
|
|
|
$merged[ $key ] = self::array_merge_recursive_distinct( $merged[ $key ], $value ); |
1445
|
|
|
} else { |
1446
|
|
|
$merged[ $key ] = $value; |
1447
|
|
|
} |
1448
|
|
|
} |
1449
|
|
|
|
1450
|
|
|
return $merged; |
1451
|
|
|
} |
1452
|
|
|
|
1453
|
|
|
/** |
1454
|
|
|
* Get WordPress users with reasonable limits set |
1455
|
|
|
* |
1456
|
|
|
* @param string $context Where are we using this information (e.g. change_entry_creator, search_widget ..) |
1457
|
|
|
* @param array $args Arguments to modify the user query. See get_users() {@since 1.14} |
1458
|
|
|
* @return array Array of WP_User objects. |
1459
|
|
|
*/ |
1460
|
|
|
public static function get_users( $context = 'change_entry_creator', $args = array() ) { |
1461
|
|
|
|
1462
|
|
|
$default_args = array( |
1463
|
|
|
'number' => 2000, |
1464
|
|
|
'orderby' => 'display_name', |
1465
|
|
|
'order' => 'ASC', |
1466
|
|
|
'fields' => array( 'ID', 'display_name', 'user_login', 'user_nicename' ) |
1467
|
|
|
); |
1468
|
|
|
|
1469
|
|
|
// Merge in the passed arg |
1470
|
|
|
$get_users_settings = wp_parse_args( $args, $default_args ); |
1471
|
|
|
|
1472
|
|
|
/** |
1473
|
|
|
* @filter `gravityview/get_users/{$context}` There are issues with too many users using [get_users()](http://codex.wordpress.org/Function_Reference/get_users) where it breaks the select. We try to keep it at a reasonable number. \n |
1474
|
|
|
* `$context` is where are we using this information (e.g. change_entry_creator, search_widget ..) |
1475
|
|
|
* @param array $settings Settings array, with `number` key defining the # of users to display |
1476
|
|
|
*/ |
1477
|
|
|
$get_users_settings = apply_filters( 'gravityview/get_users/'. $context, apply_filters( 'gravityview_change_entry_creator_user_parameters', $get_users_settings ) ); |
1478
|
|
|
|
1479
|
|
|
return get_users( $get_users_settings ); |
1480
|
|
|
} |
1481
|
|
|
|
1482
|
|
|
|
1483
|
|
|
/** |
1484
|
|
|
* Display updated/error notice |
1485
|
|
|
* |
1486
|
|
|
* @param string $notice text/HTML of notice |
1487
|
|
|
* @param string $class CSS class for notice (`updated` or `error`) |
1488
|
|
|
* |
1489
|
|
|
* @return string |
1490
|
|
|
*/ |
1491
|
|
|
public static function generate_notice( $notice, $class = '' ) { |
1492
|
|
|
return '<div class="gv-notice '.gravityview_sanitize_html_class( $class ) .'">'. $notice .'</div>'; |
1493
|
|
|
} |
1494
|
|
|
|
1495
|
|
|
|
1496
|
|
|
|
1497
|
|
|
|
1498
|
|
|
} //end class |
1499
|
|
|
|
1500
|
|
|
|
1501
|
|
|
/** |
1502
|
|
|
* Generate an HTML anchor tag with a list of supported attributes |
1503
|
|
|
* |
1504
|
|
|
* @see GVCommon::get_link_html() |
1505
|
|
|
* |
1506
|
|
|
* @since 1.6 |
1507
|
|
|
* |
1508
|
|
|
* @param string $href URL of the link. |
1509
|
|
|
* @param string $anchor_text The text or HTML inside the anchor. This is not sanitized in the function. |
1510
|
|
|
* @param array|string $atts Attributes to be added to the anchor tag |
1511
|
|
|
* |
1512
|
|
|
* @return string HTML output of anchor link. If empty $href, returns NULL |
1513
|
|
|
*/ |
1514
|
|
|
function gravityview_get_link( $href = '', $anchor_text = '', $atts = array() ) { |
1515
|
|
|
return GVCommon::get_link_html( $href, $anchor_text, $atts ); |
1516
|
|
|
} |
1517
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.