1
|
|
|
<?php |
|
|
|
|
2
|
|
|
/** |
3
|
|
|
* GravityView templating engine class |
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.0.0 |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
/** If this file is called directly, abort. */ |
15
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
16
|
|
|
die; |
17
|
|
|
} |
18
|
|
|
|
19
|
|
|
if( ! class_exists( 'Gamajo_Template_Loader' ) ) { |
20
|
|
|
require( GRAVITYVIEW_DIR . 'includes/lib/class-gamajo-template-loader.php' ); |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
class GravityView_View extends Gamajo_Template_Loader { |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Prefix for filter names. |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
protected $filter_prefix = 'gravityview'; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Directory name where custom templates for this plugin should be found in the theme. |
33
|
|
|
* @var string |
34
|
|
|
*/ |
35
|
|
|
protected $theme_template_directory = 'gravityview'; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Reference to the root directory path of this plugin. |
39
|
|
|
* @var string |
40
|
|
|
*/ |
41
|
|
|
protected $plugin_directory = GRAVITYVIEW_DIR; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Store templates locations that have already been located |
45
|
|
|
* @var array |
46
|
|
|
*/ |
47
|
|
|
protected $located_templates = array(); |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* The name of the template, like "list", "table", or "datatables" |
51
|
|
|
* @var string |
52
|
|
|
*/ |
53
|
|
|
protected $template_part_slug = ''; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* The name of the file part, like "body" or "single" |
57
|
|
|
* @var string |
58
|
|
|
*/ |
59
|
|
|
protected $template_part_name = ''; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @var int Gravity Forms form ID |
63
|
|
|
*/ |
64
|
|
|
protected $form_id = NULL; |
|
|
|
|
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @var int View ID |
68
|
|
|
* @todo: this needs to be public until extensions support 1.7+ |
69
|
|
|
*/ |
70
|
|
|
public $view_id = NULL; |
|
|
|
|
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* @var array Fields for the form |
74
|
|
|
*/ |
75
|
|
|
protected $fields = array(); |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @var string Current screen. Defaults to "directory" or "single" |
79
|
|
|
*/ |
80
|
|
|
protected $context = 'directory'; |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @var int|null If in embedded post or page, the ID of it |
84
|
|
|
*/ |
85
|
|
|
protected $post_id = NULL; |
|
|
|
|
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* @var array Gravity Forms form array at ID $form_id |
89
|
|
|
*/ |
90
|
|
|
protected $form = NULL; |
|
|
|
|
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @var array Configuration for the View |
94
|
|
|
*/ |
95
|
|
|
protected $atts = array(); |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* @var array Entries for the current result. Single item in array for single entry View |
99
|
|
|
*/ |
100
|
|
|
protected $entries = array(); |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* @var int Total entries count for the current result. |
104
|
|
|
*/ |
105
|
|
|
protected $total_entries = 0; |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @var string The label to display back links |
109
|
|
|
*/ |
110
|
|
|
protected $back_link_label = ''; |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* @var array Array with `offset` and `page_size` keys |
114
|
|
|
*/ |
115
|
|
|
protected $paging = array(); |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* @var array Array with `sort_field` and `sort_direction` keys |
119
|
|
|
*/ |
120
|
|
|
protected $sorting = array(); |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @var bool Whether to hide the results until a search is performed |
124
|
|
|
* @since 1.5.4 |
125
|
|
|
*/ |
126
|
|
|
protected $hide_until_searched = false; |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Current entry in the loop |
130
|
|
|
* @var array |
131
|
|
|
*/ |
132
|
|
|
protected $_current_entry = array(); |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* @var array |
136
|
|
|
*/ |
137
|
|
|
protected $_current_field = array(); |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* @var GravityView_View |
141
|
|
|
*/ |
142
|
|
|
static $instance = NULL; |
|
|
|
|
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Construct the view object |
146
|
|
|
* @param array $atts Associative array to set the data of |
147
|
|
|
*/ |
148
|
58 |
|
function __construct( $atts = array() ) { |
|
|
|
|
149
|
|
|
|
150
|
58 |
|
$atts = wp_parse_args( $atts, array( |
151
|
58 |
|
'form_id' => NULL, |
|
|
|
|
152
|
|
|
'view_id' => NULL, |
|
|
|
|
153
|
|
|
'fields' => NULL, |
|
|
|
|
154
|
|
|
'context' => NULL, |
|
|
|
|
155
|
|
|
'post_id' => NULL, |
|
|
|
|
156
|
|
|
'form' => NULL, |
|
|
|
|
157
|
|
|
'atts' => NULL, |
|
|
|
|
158
|
|
|
) ); |
159
|
|
|
|
160
|
58 |
|
foreach ($atts as $key => $value) { |
|
|
|
|
161
|
58 |
|
if( is_null( $value ) ) { |
162
|
58 |
|
continue; |
163
|
|
|
} |
164
|
3 |
|
$this->{$key} = $value; |
165
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
168
|
|
|
// Add granular overrides |
169
|
58 |
|
add_filter( $this->filter_prefix . '_get_template_part', array( $this, 'add_id_specific_templates' ), 10, 3 ); |
170
|
|
|
|
171
|
|
|
// widget logic |
172
|
58 |
|
add_action( 'gravityview/template/before', array( $this, 'render_widget_hooks' ) ); |
173
|
58 |
|
add_action( 'gravityview/template/after', array( $this, 'render_widget_hooks' ) ); |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Clear the current entry after the loop is done |
177
|
|
|
* @since 1.7.3 |
178
|
|
|
*/ |
179
|
58 |
|
add_action( 'gravityview_footer', array( $this, 'clearCurrentEntry' ), 500 ); |
180
|
|
|
|
181
|
58 |
|
self::$instance = &$this; |
182
|
58 |
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* @param null $passed_post |
186
|
|
|
* |
187
|
|
|
* @return GravityView_View |
188
|
|
|
*/ |
189
|
65 |
|
static function getInstance( $passed_post = NULL ) { |
|
|
|
|
190
|
|
|
|
191
|
65 |
|
if( empty( self::$instance ) ) { |
192
|
58 |
|
self::$instance = new self( $passed_post ); |
193
|
|
|
} |
194
|
|
|
|
195
|
65 |
|
return self::$instance; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* @param string|null $key The key to a specific attribute of the current field |
200
|
|
|
* @return array|mixed|null If $key is set and attribute exists at $key, return that. If not set, return NULL. Otherwise, return current field array |
201
|
|
|
*/ |
202
|
51 |
|
public function getCurrentField( $key = NULL ) { |
|
|
|
|
203
|
|
|
|
204
|
51 |
|
if( !empty( $key ) ) { |
|
|
|
|
205
|
|
|
if( isset( $this->_current_field[ $key ] ) ) { |
206
|
|
|
return $this->_current_field[ $key ]; |
207
|
|
|
} |
208
|
|
|
return NULL; |
|
|
|
|
209
|
|
|
} |
210
|
|
|
|
211
|
51 |
|
return $this->_current_field; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
public function setCurrentFieldSetting( $key, $value ) { |
|
|
|
|
215
|
|
|
|
216
|
|
|
if( !empty( $this->_current_field ) ) { |
|
|
|
|
217
|
|
|
$this->_current_field['field_settings'][ $key ] = $value; |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
public function getCurrentFieldSetting( $key ) { |
|
|
|
|
223
|
|
|
$settings = $this->getCurrentField('field_settings'); |
|
|
|
|
224
|
|
|
|
225
|
|
|
if( $settings && !empty( $settings[ $key ] ) ) { |
|
|
|
|
226
|
|
|
return $settings[ $key ]; |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
return NULL; |
|
|
|
|
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* @param array $passed_field |
234
|
|
|
*/ |
235
|
51 |
|
public function setCurrentField( $passed_field ) { |
|
|
|
|
236
|
|
|
|
237
|
51 |
|
$existing_field = $this->getCurrentField(); |
238
|
|
|
|
239
|
51 |
|
$set_field = wp_parse_args( $passed_field, $existing_field ); |
240
|
|
|
|
241
|
51 |
|
$this->_current_field = $set_field; |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* Backward compatibility |
245
|
|
|
* @deprecated 1.6.2 |
246
|
|
|
*/ |
247
|
51 |
|
$this->field_data = $set_field; |
|
|
|
|
248
|
51 |
|
} |
249
|
|
|
|
250
|
|
|
/** |
251
|
|
|
* @param string|null $key The key to a specific field in the fields array |
252
|
|
|
* @return array|mixed|null If $key is set and field exists at $key, return that. If not set, return NULL. Otherwise, return array of fields. |
253
|
|
|
*/ |
254
|
24 |
|
public function getAtts( $key = NULL ) { |
|
|
|
|
255
|
|
|
|
256
|
24 |
|
if( !empty( $key ) ) { |
|
|
|
|
257
|
2 |
|
if( isset( $this->atts[ $key ] ) ) { |
258
|
2 |
|
return $this->atts[ $key ]; |
259
|
|
|
} |
260
|
|
|
return NULL; |
|
|
|
|
261
|
|
|
} |
262
|
|
|
|
263
|
24 |
|
return $this->atts; |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
/** |
267
|
|
|
* @param array $atts |
268
|
|
|
*/ |
269
|
24 |
|
public function setAtts( $atts ) { |
|
|
|
|
270
|
24 |
|
$this->atts = $atts; |
271
|
24 |
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* @return array |
275
|
|
|
*/ |
276
|
60 |
|
public function getForm() { |
|
|
|
|
277
|
60 |
|
return $this->form; |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* @param array $form |
282
|
|
|
*/ |
283
|
25 |
|
public function setForm( $form ) { |
|
|
|
|
284
|
25 |
|
$this->form = $form; |
285
|
25 |
|
} |
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* @return int|null |
289
|
|
|
*/ |
290
|
25 |
|
public function getPostId() { |
|
|
|
|
291
|
25 |
|
return $this->post_id; |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
/** |
295
|
|
|
* @param int|null $post_id |
296
|
|
|
*/ |
297
|
24 |
|
public function setPostId( $post_id ) { |
|
|
|
|
298
|
24 |
|
$this->post_id = $post_id; |
299
|
24 |
|
} |
300
|
|
|
|
301
|
|
|
/** |
302
|
|
|
* @return string |
303
|
|
|
*/ |
304
|
57 |
|
public function getContext() { |
|
|
|
|
305
|
57 |
|
return $this->context; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* @param string $context |
310
|
|
|
*/ |
311
|
24 |
|
public function setContext( $context ) { |
|
|
|
|
312
|
24 |
|
$this->context = $context; |
313
|
24 |
|
} |
314
|
|
|
|
315
|
|
|
/** |
316
|
|
|
* @param string|null $key The key to a specific field in the fields array |
317
|
|
|
* @return array|mixed|null If $key is set and field exists at $key, return that. If not set, return NULL. Otherwise, return array of fields. |
318
|
|
|
*/ |
319
|
24 |
|
public function getFields( $key = null ) { |
|
|
|
|
320
|
|
|
|
321
|
24 |
|
$fields = empty( $this->fields ) ? NULL : $this->fields; |
|
|
|
|
322
|
|
|
|
323
|
24 |
|
if( $fields && !empty( $key ) ) { |
|
|
|
|
324
|
1 |
|
$fields = isset( $fields[ $key ] ) ? $fields[ $key ] : NULL; |
|
|
|
|
325
|
|
|
} |
326
|
|
|
|
327
|
24 |
|
return $fields; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* Get the fields for a specific context |
332
|
|
|
* |
333
|
|
|
* @since 1.19.2 |
334
|
|
|
* |
335
|
|
|
* @param string $context [Optional] "directory", "single", or "edit" |
336
|
|
|
* |
337
|
|
|
* @return array Array of GravityView field layout configurations |
338
|
|
|
*/ |
339
|
2 |
|
public function getContextFields( $context = '' ) { |
|
|
|
|
340
|
|
|
|
341
|
2 |
|
if( '' === $context ) { |
342
|
2 |
|
$context = $this->getContext(); |
343
|
|
|
} |
344
|
|
|
|
345
|
2 |
|
$fields = $this->getFields(); |
346
|
|
|
|
347
|
2 |
|
foreach ( (array) $fields as $key => $context_fields ) { |
348
|
|
|
|
349
|
|
|
// Formatted as `{context}_{template id}-{zone name}`, so we want just the $context to match against |
350
|
2 |
|
$matches = explode( '_', $key ); |
351
|
|
|
|
352
|
2 |
|
if( isset( $matches[0] ) && $matches[0] === $context ) { |
353
|
2 |
|
return $context_fields; |
354
|
|
|
} |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
return array(); |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* @param array $fields |
362
|
|
|
*/ |
363
|
24 |
|
public function setFields( $fields ) { |
|
|
|
|
364
|
24 |
|
$this->fields = $fields; |
365
|
24 |
|
} |
366
|
|
|
|
367
|
|
|
/** |
368
|
|
|
* @param string $key The key to a specific field in the fields array |
369
|
|
|
* @return array|mixed|null If $key is set and field exists at $key, return that. If not set, return NULL. Otherwise, return array of fields. |
370
|
|
|
*/ |
371
|
2 |
|
public function getField( $key ) { |
|
|
|
|
372
|
|
|
|
373
|
2 |
|
if( !empty( $key ) ) { |
|
|
|
|
374
|
2 |
|
if( isset( $this->fields[ $key ] ) ) { |
375
|
2 |
|
return $this->fields[ $key ]; |
376
|
|
|
} |
377
|
|
|
} |
378
|
|
|
|
379
|
1 |
|
return NULL; |
|
|
|
|
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
/** |
383
|
|
|
* @param string $key The key to a specific field in the fields array |
384
|
|
|
* @param mixed $value The value to set for the field |
385
|
|
|
*/ |
386
|
|
|
public function setField( $key, $value ) { |
|
|
|
|
387
|
|
|
$this->fields[ $key ] = $value; |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
/** |
391
|
|
|
* @return int |
392
|
|
|
*/ |
393
|
29 |
|
public function getViewId() { |
|
|
|
|
394
|
29 |
|
return absint( $this->view_id ); |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
/** |
398
|
|
|
* @param int $view_id |
399
|
|
|
*/ |
400
|
24 |
|
public function setViewId( $view_id ) { |
|
|
|
|
401
|
24 |
|
$this->view_id = intval( $view_id ); |
402
|
24 |
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* @return int |
406
|
|
|
*/ |
407
|
27 |
|
public function getFormId() { |
|
|
|
|
408
|
27 |
|
return $this->form_id; |
409
|
|
|
} |
410
|
|
|
|
411
|
|
|
/** |
412
|
|
|
* @param int $form_id |
413
|
|
|
*/ |
414
|
24 |
|
public function setFormId( $form_id ) { |
|
|
|
|
415
|
24 |
|
$this->form_id = $form_id; |
416
|
24 |
|
} |
417
|
|
|
|
418
|
|
|
/** |
419
|
|
|
* @return array |
420
|
|
|
*/ |
421
|
28 |
|
public function getEntries() { |
|
|
|
|
422
|
28 |
|
return $this->entries; |
423
|
|
|
} |
424
|
|
|
|
425
|
|
|
/** |
426
|
|
|
* @param array $entries |
427
|
|
|
*/ |
428
|
24 |
|
public function setEntries( $entries ) { |
|
|
|
|
429
|
24 |
|
$this->entries = $entries; |
430
|
24 |
|
} |
431
|
|
|
|
432
|
|
|
/** |
433
|
|
|
* @return int |
434
|
|
|
*/ |
435
|
25 |
|
public function getTotalEntries() { |
|
|
|
|
436
|
25 |
|
return (int)$this->total_entries; |
|
|
|
|
437
|
|
|
} |
438
|
|
|
|
439
|
|
|
/** |
440
|
|
|
* @param int $total_entries |
441
|
|
|
*/ |
442
|
25 |
|
public function setTotalEntries( $total_entries ) { |
|
|
|
|
443
|
25 |
|
$this->total_entries = intval( $total_entries ); |
444
|
25 |
|
} |
445
|
|
|
|
446
|
|
|
/** |
447
|
|
|
* @return array |
448
|
|
|
*/ |
449
|
25 |
|
public function getPaging() { |
|
|
|
|
450
|
|
|
|
451
|
|
|
$default_params = array( |
452
|
25 |
|
'offset' => 0, |
453
|
|
|
'page_size' => 20, |
454
|
|
|
); |
455
|
|
|
|
456
|
25 |
|
return wp_parse_args( $this->paging, $default_params ); |
457
|
|
|
} |
458
|
|
|
|
459
|
|
|
/** |
460
|
|
|
* @param array $paging |
461
|
|
|
*/ |
462
|
25 |
|
public function setPaging( $paging ) { |
|
|
|
|
463
|
25 |
|
$this->paging = $paging; |
464
|
25 |
|
} |
465
|
|
|
|
466
|
|
|
/** |
467
|
|
|
* Get an array with pagination information |
468
|
|
|
* |
469
|
|
|
* @since 1.13 |
470
|
|
|
* |
471
|
|
|
* @return array { |
472
|
|
|
* @type int $first The starting entry number (counter, not ID) |
473
|
|
|
* @type int $last The last displayed entry number (counter, not ID) |
474
|
|
|
* @type int $total The total number of entries |
475
|
|
|
* } |
476
|
|
|
*/ |
477
|
2 |
|
public function getPaginationCounts() { |
|
|
|
|
478
|
|
|
|
479
|
2 |
|
$paging = $this->getPaging(); |
480
|
2 |
|
$offset = $paging['offset']; |
481
|
2 |
|
$page_size = $paging['page_size']; |
482
|
2 |
|
$total = $this->getTotalEntries(); |
483
|
|
|
|
484
|
2 |
|
if ( empty( $total ) ) { |
485
|
1 |
|
gravityview()->log->debug( 'No entries. Returning empty array.' ); |
486
|
|
|
|
487
|
1 |
|
return array(); |
488
|
|
|
} |
489
|
|
|
|
490
|
2 |
|
$first = empty( $offset ) ? 1 : $offset + 1; |
491
|
|
|
|
492
|
|
|
// If the page size + starting entry is larger than total, the total is the max. |
493
|
2 |
|
$last = ( $offset + $page_size > $total ) ? $total : $offset + $page_size; |
494
|
|
|
|
495
|
|
|
/** |
496
|
|
|
* @filter `gravityview_pagination_counts` Modify the displayed pagination numbers |
497
|
|
|
* @since 1.13 |
498
|
|
|
* @param array $counts Array with $first, $last, $total numbers in that order |
499
|
|
|
*/ |
500
|
2 |
|
list( $first, $last, $total ) = apply_filters( 'gravityview_pagination_counts', array( $first, $last, $total ) ); |
501
|
|
|
|
502
|
2 |
|
return array( 'first' => (int) $first, 'last' => (int) $last, 'total' => (int) $total ); |
503
|
|
|
} |
504
|
|
|
|
505
|
|
|
/** |
506
|
|
|
* @return array |
507
|
|
|
*/ |
508
|
24 |
|
public function getSorting() { |
|
|
|
|
509
|
|
|
|
510
|
|
|
$defaults_params = array( |
511
|
24 |
|
'sort_field' => 'date_created', |
512
|
|
|
'sort_direction' => 'ASC', |
513
|
|
|
'is_numeric' => false, |
514
|
|
|
); |
515
|
|
|
|
516
|
24 |
|
return wp_parse_args( $this->sorting, $defaults_params ); |
517
|
|
|
} |
518
|
|
|
|
519
|
|
|
/** |
520
|
|
|
* @param array $sorting |
521
|
|
|
*/ |
522
|
30 |
|
public function setSorting( $sorting ) { |
|
|
|
|
523
|
30 |
|
$this->sorting = $sorting; |
524
|
30 |
|
} |
525
|
|
|
|
526
|
|
|
/** |
527
|
|
|
* @param boolean $do_replace Perform merge tag and shortcode processing on the label. Default: true. |
528
|
|
|
* @since 2.0 |
529
|
|
|
* |
530
|
|
|
* @deprecated Use $template->get_back_label(); |
531
|
|
|
* |
532
|
|
|
* @return string |
533
|
|
|
*/ |
534
|
25 |
|
public function getBackLinkLabel( $do_replace = true ) { |
|
|
|
|
535
|
25 |
|
if ( $do_replace ) { |
536
|
2 |
|
$back_link_label = GravityView_API::replace_variables( $this->back_link_label, $this->getForm(), $this->getCurrentEntry() ); |
537
|
2 |
|
return do_shortcode( $back_link_label ); |
538
|
|
|
} |
539
|
|
|
|
540
|
24 |
|
return $this->back_link_label; |
541
|
|
|
} |
542
|
|
|
|
543
|
|
|
/** |
544
|
|
|
* @param string $back_link_label |
545
|
|
|
*/ |
546
|
25 |
|
public function setBackLinkLabel( $back_link_label ) { |
|
|
|
|
547
|
25 |
|
$this->back_link_label = $back_link_label; |
548
|
25 |
|
} |
549
|
|
|
|
550
|
|
|
/** |
551
|
|
|
* @return boolean |
552
|
|
|
*/ |
553
|
2 |
|
public function isHideUntilSearched() { |
|
|
|
|
554
|
2 |
|
return $this->hide_until_searched; |
555
|
|
|
} |
556
|
|
|
|
557
|
|
|
/** |
558
|
|
|
* @param boolean $hide_until_searched |
559
|
|
|
*/ |
560
|
|
|
public function setHideUntilSearched( $hide_until_searched ) { |
|
|
|
|
561
|
|
|
$this->hide_until_searched = $hide_until_searched; |
562
|
|
|
} |
563
|
|
|
|
564
|
|
|
/** |
565
|
|
|
* @return string |
566
|
|
|
*/ |
567
|
2 |
|
public function getTemplatePartSlug() { |
|
|
|
|
568
|
2 |
|
return $this->template_part_slug; |
569
|
|
|
} |
570
|
|
|
|
571
|
|
|
/** |
572
|
|
|
* @param string $template_part_slug |
573
|
|
|
*/ |
574
|
4 |
|
public function setTemplatePartSlug( $template_part_slug ) { |
|
|
|
|
575
|
4 |
|
$this->template_part_slug = $template_part_slug; |
576
|
4 |
|
} |
577
|
|
|
|
578
|
|
|
/** |
579
|
|
|
* @return string |
580
|
|
|
*/ |
581
|
|
|
public function getTemplatePartName() { |
|
|
|
|
582
|
|
|
return $this->template_part_name; |
583
|
|
|
} |
584
|
|
|
|
585
|
|
|
/** |
586
|
|
|
* @param string $template_part_name |
587
|
|
|
*/ |
588
|
4 |
|
public function setTemplatePartName( $template_part_name ) { |
|
|
|
|
589
|
4 |
|
$this->template_part_name = $template_part_name; |
590
|
4 |
|
} |
591
|
|
|
|
592
|
|
|
/** |
593
|
|
|
* Return the current entry. If in the loop, the current entry. If single entry, the currently viewed entry. |
594
|
|
|
* @return array |
595
|
|
|
*/ |
596
|
57 |
|
public function getCurrentEntry() { |
|
|
|
|
597
|
|
|
|
598
|
57 |
|
if( in_array( $this->getContext(), array( 'edit', 'single') ) ) { |
|
|
|
|
599
|
11 |
|
$entries = $this->getEntries(); |
600
|
11 |
|
$entry = $entries[0]; |
601
|
|
|
} else { |
602
|
55 |
|
$entry = $this->_current_entry; |
603
|
|
|
} |
604
|
|
|
|
605
|
|
|
/** @since 1.16 Fixes DataTables empty entry issue */ |
606
|
57 |
|
if ( empty( $entry ) && ! empty( $this->_current_field['entry'] ) ) { |
607
|
5 |
|
$entry = $this->_current_field['entry']; |
608
|
|
|
} |
609
|
|
|
|
610
|
57 |
|
return $entry; |
611
|
|
|
} |
612
|
|
|
|
613
|
|
|
/** |
614
|
|
|
* @param array $current_entry |
615
|
|
|
* @return void |
616
|
|
|
*/ |
617
|
25 |
|
public function setCurrentEntry( $current_entry ) { |
|
|
|
|
618
|
25 |
|
$this->_current_entry = $current_entry; |
619
|
25 |
|
} |
620
|
|
|
|
621
|
|
|
/** |
622
|
|
|
* Clear the current entry after all entries in the loop have been displayed. |
623
|
|
|
* |
624
|
|
|
* @since 1.7.3 |
625
|
|
|
* @return void |
626
|
|
|
*/ |
627
|
17 |
|
public function clearCurrentEntry() { |
|
|
|
|
628
|
17 |
|
$this->_current_entry = NULL; |
|
|
|
|
629
|
17 |
|
} |
630
|
|
|
|
631
|
|
|
/** |
632
|
|
|
* Render an output zone, as configured in the Admin |
633
|
|
|
* |
634
|
|
|
* @since 1.16.4 Added $echo parameter |
635
|
|
|
* |
636
|
|
|
* @param string $zone The zone name, like 'footer-left' |
637
|
|
|
* @param array $atts |
638
|
|
|
* @param bool $echo Whether to print the output |
639
|
|
|
* |
640
|
|
|
* @deprecated This will never get called in new templates. |
641
|
|
|
* |
642
|
|
|
* @return string|null |
643
|
|
|
*/ |
644
|
2 |
|
public function renderZone( $zone = '', $atts = array(), $echo = true ) { |
|
|
|
|
645
|
|
|
|
646
|
2 |
|
if ( empty( $zone ) ) { |
647
|
|
|
gravityview()->log->error( 'No zone defined.'); |
|
|
|
|
648
|
|
|
return NULL; |
|
|
|
|
649
|
|
|
} |
650
|
|
|
|
651
|
|
|
$defaults = array( |
652
|
2 |
|
'slug' => $this->getTemplatePartSlug(), |
653
|
2 |
|
'context' => $this->getContext(), |
654
|
2 |
|
'entry' => $this->getCurrentEntry(), |
655
|
2 |
|
'form' => $this->getForm(), |
656
|
2 |
|
'hide_empty' => $this->getAtts('hide_empty'), |
|
|
|
|
657
|
|
|
); |
658
|
|
|
|
659
|
2 |
|
$final_atts = wp_parse_args( $atts, $defaults ); |
660
|
|
|
|
661
|
2 |
|
$output = ''; |
662
|
|
|
|
663
|
2 |
|
$final_atts['zone_id'] = "{$final_atts['context']}_{$final_atts['slug']}-{$zone}"; |
664
|
|
|
|
665
|
2 |
|
$fields = $this->getField( $final_atts['zone_id'] ); |
666
|
|
|
|
667
|
|
|
// Backward compatibility |
668
|
2 |
|
if ( 'table' === $this->getTemplatePartSlug() ) { |
669
|
|
|
/** |
670
|
|
|
* @filter `gravityview_table_cells` Modify the fields displayed in a table |
671
|
|
|
* @param array $fields |
672
|
|
|
* @param \GravityView_View $this |
673
|
|
|
* @deprecated Use `gravityview/template/table/fields` |
674
|
|
|
*/ |
675
|
1 |
|
$fields = apply_filters("gravityview_table_cells", $fields, $this ); |
|
|
|
|
676
|
|
|
} |
677
|
|
|
|
678
|
2 |
|
if ( empty( $fields ) ) { |
679
|
|
|
|
680
|
1 |
|
gravityview()->log->error( 'Empty View configuration for this context.', array( 'data' => $fields ) ); |
681
|
|
|
|
682
|
1 |
|
return NULL; |
|
|
|
|
683
|
|
|
} |
684
|
|
|
|
685
|
2 |
|
$field_output = ''; |
686
|
2 |
|
foreach ( $fields as $field ) { |
687
|
2 |
|
$final_atts['field'] = $field; |
688
|
|
|
|
689
|
2 |
|
$field_output .= gravityview_field_output( $final_atts ); |
690
|
|
|
} |
691
|
|
|
|
692
|
|
|
/** |
693
|
|
|
* If a zone has no field output, choose whether to show wrapper |
694
|
|
|
* False by default to keep backward compatibility |
695
|
|
|
* @since 1.7.6 |
696
|
|
|
* @param boolean $hide_empty_zone Default: false |
697
|
|
|
* @since 2.0 |
698
|
|
|
* @param \GV\Template_Context $context The context. Null here. Since this path is deprecated. |
699
|
|
|
*/ |
700
|
2 |
|
if ( empty( $field_output ) && apply_filters( 'gravityview/render/hide-empty-zone', false, null ) ) { |
701
|
|
|
return NULL; |
|
|
|
|
702
|
|
|
} |
703
|
|
|
|
704
|
2 |
|
if( !empty( $final_atts['wrapper_class'] ) ) { |
|
|
|
|
705
|
1 |
|
$output .= '<div class="'.gravityview_sanitize_html_class( $final_atts['wrapper_class'] ).'">'; |
706
|
|
|
} |
707
|
|
|
|
708
|
2 |
|
$output .= $field_output; |
709
|
|
|
|
710
|
2 |
|
if( !empty( $final_atts['wrapper_class'] ) ) { |
|
|
|
|
711
|
1 |
|
$output .= '</div>'; |
712
|
|
|
} |
713
|
|
|
|
714
|
2 |
|
if( $echo ) { |
715
|
2 |
|
echo $output; |
|
|
|
|
716
|
|
|
} |
717
|
|
|
|
718
|
2 |
|
return $output; |
719
|
|
|
} |
720
|
|
|
|
721
|
|
|
/** |
722
|
|
|
* In order to improve lookup times, we store located templates in a local array. |
723
|
|
|
* |
724
|
|
|
* This improves performance by up to 1/2 second on a 250 entry View with 7 columns showing |
725
|
|
|
* |
726
|
|
|
* @inheritdoc |
727
|
|
|
* @see Gamajo_Template_Loader::locate_template() |
728
|
|
|
* @return null|string NULL: Template not found; String: path to template |
729
|
|
|
*/ |
730
|
2 |
|
function locate_template( $template_names, $load = false, $require_once = true ) { |
|
|
|
|
731
|
|
|
|
732
|
2 |
|
if( is_string( $template_names ) && isset( $this->located_templates[ $template_names ] ) ) { |
733
|
|
|
|
734
|
|
|
$located = $this->located_templates[ $template_names ]; |
735
|
|
|
|
736
|
|
|
} else { |
737
|
|
|
|
738
|
|
|
// Set $load to always false so we handle it here. |
739
|
2 |
|
$located = parent::locate_template( $template_names, false, $require_once ); |
740
|
|
|
|
741
|
2 |
|
if( is_string( $template_names ) ) { |
742
|
|
|
$this->located_templates[ $template_names ] = $located; |
743
|
|
|
} |
744
|
|
|
} |
745
|
|
|
|
746
|
2 |
|
if ( $load && $located ) { |
747
|
|
|
load_template( $located, $require_once ); |
748
|
|
|
} |
749
|
|
|
|
750
|
2 |
|
return $located; |
751
|
|
|
} |
752
|
|
|
|
753
|
|
|
/** |
754
|
|
|
* Magic Method: Instead of throwing an error when a variable isn't set, return null. |
755
|
|
|
* @param string $name Key for the data retrieval. |
756
|
|
|
* @return mixed|null The stored data. |
757
|
|
|
*/ |
758
|
3 |
|
public function __get( $name ) { |
759
|
3 |
|
if( isset( $this->{$name} ) ) { |
760
|
1 |
|
return $this->{$name}; |
761
|
|
|
} else { |
762
|
2 |
|
return NULL; |
|
|
|
|
763
|
|
|
} |
764
|
|
|
} |
765
|
|
|
|
766
|
|
|
/** |
767
|
|
|
* Enable overrides of GravityView templates on a granular basis |
768
|
|
|
* |
769
|
|
|
* The loading order is: |
770
|
|
|
* |
771
|
|
|
* - view-[View ID]-table-footer.php |
772
|
|
|
* - form-[Form ID]-table-footer.php |
773
|
|
|
* - page-[ID of post or page where view is embedded]-table-footer.php |
774
|
|
|
* - table-footer.php |
775
|
|
|
* |
776
|
|
|
* @see Gamajo_Template_Loader::get_template_file_names() Where the filter is |
777
|
|
|
* @param array $templates Existing list of templates. |
778
|
|
|
* @param string $slug Name of the template base, example: `table`, `list`, `datatables`, `map` |
779
|
|
|
* @param string $name Name of the template part, example: `body`, `footer`, `head`, `single` |
780
|
|
|
* |
781
|
|
|
* @return array $templates Modified template array, merged with existing $templates values |
782
|
|
|
*/ |
783
|
22 |
|
function add_id_specific_templates( $templates, $slug, $name ) { |
|
|
|
|
784
|
|
|
|
785
|
22 |
|
$additional = array(); |
786
|
|
|
|
787
|
|
|
// form-19-table-body.php |
788
|
22 |
|
$additional[] = sprintf( 'form-%d-%s-%s.php', $this->getFormId(), $slug, $name ); |
789
|
|
|
|
790
|
22 |
|
if( $view_id = $this->getViewId() ) { |
791
|
|
|
// view-3-table-body.php |
792
|
21 |
|
$additional[] = sprintf( 'view-%d-%s-%s.php', $view_id, $slug, $name ); |
793
|
|
|
} |
794
|
|
|
|
795
|
22 |
|
if( $this->getPostId() ) { |
|
|
|
|
796
|
|
|
|
797
|
|
|
// page-19-table-body.php |
798
|
21 |
|
$additional[] = sprintf( 'page-%d-%s-%s.php', $this->getPostId(), $slug, $name ); |
799
|
|
|
} |
800
|
|
|
|
801
|
|
|
// Combine with existing table-body.php and table.php |
802
|
22 |
|
$templates = array_merge( $additional, $templates ); |
803
|
|
|
|
804
|
22 |
|
gravityview()->log->debug( 'List of Template Files', array( 'data' => $templates ) ); |
805
|
|
|
|
806
|
22 |
|
return $templates; |
807
|
|
|
} |
808
|
|
|
|
809
|
|
|
// Load the template |
810
|
2 |
|
public function render( $slug, $name, $require_once = true ) { |
811
|
|
|
|
812
|
2 |
|
$this->setTemplatePartSlug( $slug ); |
813
|
|
|
|
814
|
2 |
|
$this->setTemplatePartName( $name ); |
815
|
|
|
|
816
|
2 |
|
$template_file = $this->get_template_part( $slug, $name, false ); |
817
|
|
|
|
818
|
2 |
|
gravityview()->log->debug( 'Rendering Template File: {path}', array( 'path' => $template_file ) ); |
819
|
|
|
|
820
|
2 |
|
if( !empty( $template_file) ) { |
|
|
|
|
821
|
|
|
|
822
|
2 |
|
if ( $require_once ) { |
823
|
|
|
require_once( $template_file ); |
824
|
|
|
} else { |
825
|
2 |
|
require( $template_file ); |
826
|
|
|
} |
827
|
|
|
|
828
|
|
|
} |
829
|
2 |
|
} |
830
|
|
|
|
831
|
|
|
/** |
832
|
|
|
* Output the widgets on before/after hooks. |
833
|
|
|
* |
834
|
|
|
* @param int|\GV\Template_Context $view_id_or_context The View ID or the context. |
835
|
|
|
* |
836
|
|
|
* @return void |
837
|
|
|
*/ |
838
|
21 |
|
public function render_widget_hooks( $view_id_or_context ) { |
839
|
|
|
|
840
|
|
|
/** |
841
|
|
|
* @deprecated Numeric argument is deprecated. Pass a \GV\Template_Context instead. |
842
|
|
|
*/ |
843
|
21 |
|
if ( is_numeric( $view_id_or_context ) ) { |
844
|
4 |
|
$view = \GV\View::by_id( $view_id_or_context ); |
845
|
4 |
|
$is_single = gravityview_get_context() == 'single'; |
846
|
4 |
|
$total_entries = GravityView_View::getInstance()->getTotalEntries(); |
847
|
|
|
|
848
|
19 |
|
} else if ( $view_id_or_context instanceof \GV\Template_Context ) { |
849
|
19 |
|
$view = $view_id_or_context->view; |
850
|
19 |
|
$is_single = (boolean)$view_id_or_context->request->is_entry(); |
|
|
|
|
851
|
19 |
|
$total_entries = $view_id_or_context->entries ? $view_id_or_context->entries->count() : 0; |
852
|
|
|
|
853
|
|
|
} else { |
854
|
|
|
gravityview()->log->error( 'No View ID or template context provided to render_widget_hooks' ); |
855
|
|
|
return; |
856
|
|
|
} |
857
|
|
|
|
858
|
21 |
|
if ( $is_single ) { |
859
|
7 |
|
gravityview()->log->debug( 'Not rendering widgets; single entry' ); |
860
|
7 |
|
return; |
861
|
|
|
} |
862
|
|
|
|
863
|
14 |
|
switch ( current_filter() ) { |
864
|
|
|
default: |
865
|
14 |
|
case 'gravityview/template/before': |
866
|
14 |
|
case 'gravityview_before': |
867
|
14 |
|
$zone = 'header'; |
868
|
14 |
|
break; |
869
|
14 |
|
case 'gravityview/template/after': |
870
|
2 |
|
case 'gravityview_after': |
871
|
14 |
|
$zone = 'footer'; |
872
|
14 |
|
break; |
873
|
|
|
} |
874
|
|
|
|
875
|
14 |
|
$widgets = $view->widgets->by_position( "$zone*" ); |
876
|
|
|
|
877
|
|
|
/** |
878
|
|
|
* Prevent output if no widgets to show. |
879
|
|
|
* @since 1.16 |
880
|
|
|
*/ |
881
|
14 |
|
if ( ! $widgets->count() ) { |
882
|
12 |
|
gravityview()->log->debug( 'No widgets for View #{view_id} in zone {zone}', array( 'view_id' => $view->ID, 'zone' => $zone ) ); |
883
|
12 |
|
return; |
884
|
|
|
} |
885
|
|
|
|
886
|
|
|
// Prevent being called twice |
887
|
3 |
|
if ( did_action( "gravityview/widgets/$zone/{$view->ID}/rendered" ) ) { |
888
|
|
|
gravityview()->log->debug( 'Not rendering {zone}; already rendered', array( 'zone' => $zone.'_'.$view->ID.'_widgets' ) ); |
889
|
|
|
return; |
890
|
|
|
} |
891
|
|
|
|
892
|
3 |
|
$rows = \GV\Widget::get_default_widget_areas(); |
893
|
|
|
|
894
|
|
|
// TODO: Move to sep. method, use an action instead |
895
|
3 |
|
wp_enqueue_style( 'gravityview_default_style' ); |
896
|
|
|
|
897
|
3 |
|
$default_css_class = 'gv-grid gv-widgets-' . $zone; |
898
|
|
|
|
899
|
3 |
|
if ( ! $total_entries ) { |
900
|
1 |
|
$default_css_class .= ' gv-widgets-no-results'; |
901
|
|
|
} |
902
|
|
|
|
903
|
|
|
/** |
904
|
|
|
* @filter `gravityview/widgets/wrapper_css_class` The CSS class applied to the widget container `<div>`. |
905
|
|
|
* @since 1.16.2 |
906
|
|
|
* @param string $css_class Default: `gv-grid gv-widgets-{zone}` where `{zone}` is replaced by the current `$zone` value. If the View has no results, adds ` gv-widgets-no-results` |
907
|
|
|
* @param string $zone Current widget zone, either `header` or `footer` |
908
|
|
|
* @param array $widgets Array of widget configurations for the current zone, as set by `gravityview_get_current_view_data()['widgets']` |
909
|
|
|
*/ |
910
|
3 |
|
$css_class = apply_filters('gravityview/widgets/wrapper_css_class', $default_css_class, $zone, $widgets->as_configuration() ); |
|
|
|
|
911
|
|
|
|
912
|
3 |
|
$css_class = gravityview_sanitize_html_class( $css_class ); |
913
|
|
|
|
914
|
|
|
// TODO Convert to partials |
915
|
|
|
?> |
916
|
|
|
<div class="<?php echo $css_class; ?>"> |
|
|
|
|
917
|
|
|
<?php |
918
|
3 |
|
foreach( $rows as $row ) { |
919
|
3 |
|
foreach( $row as $col => $areas ) { |
920
|
3 |
|
$column = ( $col == '2-2' ) ? '1-2 gv-right' : "$col gv-left"; |
921
|
|
|
?> |
922
|
|
|
<div class="gv-grid-col-<?php echo esc_attr( $column ); ?>"> |
923
|
|
|
<?php |
924
|
3 |
|
if ( ! empty( $areas ) ) { |
925
|
3 |
|
foreach ( $areas as $area ) { |
926
|
3 |
|
foreach ( $widgets->by_position( $zone . '_' . $area['areaid'] )->all() as $widget ) { |
927
|
3 |
|
do_action( sprintf( 'gravityview/widgets/%s/render', $widget->get_widget_id() ), $widget->configuration->all(), null, $view_id_or_context ); |
928
|
|
|
} |
929
|
|
|
} |
930
|
|
|
} ?> |
931
|
3 |
|
</div> |
932
|
|
|
<?php } // $row ?> |
933
|
|
|
<?php } // $rows ?> |
934
|
3 |
|
</div> |
935
|
|
|
|
936
|
|
|
<?php |
937
|
|
|
|
938
|
|
|
/** |
939
|
|
|
* Prevent widgets from being called twice. |
940
|
|
|
* Checking for loop_start prevents themes and plugins that pre-process shortcodes from triggering the action before displaying. Like, ahem, the Divi theme and WordPress SEO plugin |
941
|
|
|
*/ |
942
|
3 |
|
if ( did_action( 'wp_head' ) ) { |
943
|
|
|
do_action( "gravityview/widgets/$zone/{$view->ID}/rendered" ); |
944
|
|
|
} |
945
|
3 |
|
} |
946
|
|
|
|
947
|
|
|
/** |
948
|
|
|
* Include a file inside this context. |
949
|
|
|
* |
950
|
|
|
* @param string $path A path to the legacy template to include. |
951
|
|
|
* |
952
|
|
|
* @return void |
953
|
|
|
*/ |
954
|
2 |
|
public function _include( $path ) { |
955
|
2 |
|
if ( file_exists( $path ) ) { |
956
|
2 |
|
include $path; |
957
|
|
|
} |
958
|
2 |
|
} |
959
|
|
|
|
960
|
|
|
} |
961
|
|
|
|
962
|
|
|
|
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.