1
|
|
|
<?php |
|
|
|
|
2
|
|
|
namespace GV; |
3
|
|
|
|
4
|
|
|
/** If this file is called directly, abort. */ |
5
|
|
|
if ( ! defined( 'GRAVITYVIEW_DIR' ) ) { |
6
|
|
|
die(); |
7
|
|
|
} |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* The \GV\Widget class. |
11
|
|
|
* |
12
|
|
|
* An interface that most GravityView widgets would want to adhere to and inherit from. |
13
|
|
|
*/ |
14
|
|
|
abstract class Widget { |
15
|
|
|
/** |
16
|
|
|
* Widget admin label |
17
|
|
|
* @var string |
18
|
|
|
*/ |
19
|
|
|
protected $widget_label = ''; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Widget description, shown on the "+ Add Widget" picker |
23
|
|
|
* @var string |
24
|
|
|
*/ |
25
|
|
|
protected $widget_description = ''; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Widget details, shown in the widget lightbox |
29
|
|
|
* @since 1.8 |
30
|
|
|
* @var string |
31
|
|
|
*/ |
32
|
|
|
protected $widget_subtitle = ''; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Widget admin ID |
36
|
|
|
* @var string |
37
|
|
|
*/ |
38
|
|
|
protected $widget_id = ''; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Default configuration for header and footer |
42
|
|
|
* @var array |
43
|
|
|
*/ |
44
|
|
|
protected $defaults = array(); |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Widget admin advanced settings |
48
|
|
|
* @var array |
49
|
|
|
*/ |
50
|
|
|
protected $settings = array(); |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Allow class to automatically add widget_text filter for you in shortcode |
54
|
|
|
* @var string |
55
|
|
|
*/ |
56
|
|
|
protected $shortcode_name; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Hold the widget options. |
60
|
|
|
* @var array() |
61
|
|
|
*/ |
62
|
|
|
private $widget_options = array(); |
|
|
|
|
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* The position of the widget. |
66
|
|
|
* @api |
67
|
|
|
* @since 2.0 |
68
|
|
|
* @var string |
69
|
|
|
*/ |
70
|
|
|
public $position = ''; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* A unique ID for this widget. |
74
|
|
|
* @api |
75
|
|
|
* @since 2.0 |
76
|
|
|
* @var string |
77
|
|
|
*/ |
78
|
|
|
public $UID = ''; |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* The actual configuration for this widget instance. |
82
|
|
|
* |
83
|
|
|
* @api |
84
|
|
|
* @since 2.0 |
85
|
|
|
* @var \GV\Settings |
86
|
|
|
*/ |
87
|
|
|
public $configuration; |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* Constructor. |
91
|
|
|
* |
92
|
|
|
* @param string $label The Widget label as shown in the admin. |
93
|
|
|
* @param string $id The Widget ID, make this something unique. |
94
|
|
|
* @param array $defaults Default footer/header Widget configuration. |
95
|
|
|
* @param array $settings Advanced Widget settings. |
96
|
|
|
* |
97
|
|
|
* @return \GV\Widget |
|
|
|
|
98
|
|
|
*/ |
99
|
7 |
|
public function __construct( $label, $id, $defaults = array(), $settings = array() ) { |
100
|
|
|
/** |
101
|
|
|
* The shortcode name is set to the lowercase name of the widget class, unless overridden by the class specifying a different value for $shortcode_name |
102
|
|
|
* @var string |
103
|
|
|
*/ |
104
|
7 |
|
$this->shortcode_name = empty( $this->shortcode_name ) ? strtolower( get_called_class() ) : $this->shortcode_name; |
105
|
|
|
|
106
|
7 |
|
if ( $id ) { |
107
|
4 |
|
$this->widget_id = $id; |
108
|
|
|
} |
109
|
|
|
|
110
|
7 |
|
$this->widget_label = $label; |
111
|
7 |
|
$this->defaults = array_merge( array( 'header' => 0, 'footer' => 0 ), $defaults ); |
112
|
|
|
|
113
|
|
|
// Make sure every widget has a title, even if empty |
114
|
7 |
|
$this->settings = wp_parse_args( $settings, $this->get_default_settings() ); |
115
|
|
|
|
116
|
|
|
// Hook once per unique ID |
117
|
7 |
|
if ( $this->is_registered() ) { |
118
|
6 |
|
return; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
// widget options |
122
|
2 |
|
add_filter( 'gravityview_template_widget_options', array( $this, 'assign_widget_options' ), 10, 3 ); |
123
|
|
|
|
124
|
|
|
// frontend logic |
125
|
2 |
|
add_action( sprintf( 'gravityview/widgets/%s/render', $this->get_widget_id() ), array( $this, 'render_frontend' ), 10, 3 ); |
126
|
|
|
|
127
|
|
|
// register shortcodes |
128
|
2 |
|
add_action( 'wp', array( $this, 'add_shortcode' ) ); |
129
|
|
|
|
130
|
|
|
// Use shortcodes in text widgets. |
131
|
2 |
|
add_filter( 'widget_text', array( $this, 'maybe_do_shortcode' ) ); |
132
|
|
|
|
133
|
|
|
// register widgets to be listed in the View Configuration |
134
|
|
|
// Important: this has to be the last filter/action added in the constructor. |
135
|
2 |
|
add_filter( 'gravityview/widgets/register', array( $this, 'register_widget' ) ); |
136
|
2 |
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Define general widget settings |
140
|
|
|
* @since 1.5.4 |
141
|
|
|
* @return array $settings Default settings |
142
|
|
|
*/ |
143
|
7 |
|
protected function get_default_settings() { |
144
|
7 |
|
$settings = array(); |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* @filter `gravityview/widget/enable_custom_class` Enable custom CSS class settings for widgets |
148
|
|
|
* @param boolean $enable_custom_class False by default. Return true if you want to enable. |
149
|
|
|
* @param \GV\Widget $this Current instance of \GV\Widget. |
150
|
|
|
*/ |
151
|
7 |
|
$enable_custom_class = apply_filters( 'gravityview/widget/enable_custom_class', false, $this ); |
152
|
|
|
|
153
|
7 |
|
if ( $enable_custom_class ) { |
154
|
1 |
|
$settings['custom_class'] = array( |
155
|
1 |
|
'type' => 'text', |
156
|
1 |
|
'label' => __( 'Custom CSS Class:', 'gravityview' ), |
157
|
1 |
|
'desc' => __( 'This class will be added to the widget container', 'gravityview' ), |
158
|
1 |
|
'value' => '', |
159
|
|
|
'merge_tags' => true, |
160
|
|
|
); |
161
|
|
|
} |
162
|
|
|
|
163
|
7 |
|
return $settings; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Get the Widget ID. |
168
|
|
|
* |
169
|
|
|
* @return string The Widget ID. |
170
|
|
|
*/ |
171
|
7 |
|
public function get_widget_id() { |
172
|
7 |
|
return $this->widget_id; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Get the widget settings |
177
|
|
|
* |
178
|
|
|
* @return array|null Settings array; NULL if not set for some reason. |
179
|
|
|
*/ |
180
|
1 |
|
public function get_settings() { |
181
|
1 |
|
return empty( $this->settings ) ? null : $this->settings; |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Get a setting by the setting key. |
186
|
|
|
* |
187
|
|
|
* @param string $key Key for the setting |
188
|
|
|
* |
189
|
|
|
* @todo Use the \GV\Settings class later. For now subclasses may still expect and array instead. |
190
|
|
|
* |
191
|
|
|
* @return mixed|null Value of the setting; NULL if not set |
192
|
|
|
*/ |
193
|
1 |
|
public function get_setting( $key ) { |
194
|
1 |
|
return Utils::get( $this->settings, $key, null ); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Default widget areas. |
199
|
|
|
* |
200
|
|
|
* Usually overridden by the selected template. |
201
|
|
|
* |
202
|
|
|
* @return array The default areas where widgets can be rendered. |
203
|
|
|
*/ |
204
|
3 |
|
public static function get_default_widget_areas() { |
205
|
|
|
$default_areas = array( |
206
|
3 |
|
array( '1-1' => array( array( 'areaid' => 'top', 'title' => __( 'Top', 'gravityview' ) , 'subtitle' => '' ) ) ), |
|
|
|
|
207
|
3 |
|
array( '1-2' => array( array( 'areaid' => 'left', 'title' => __( 'Left', 'gravityview' ) , 'subtitle' => '' ) ), '2-2' => array( array( 'areaid' => 'right', 'title' => __( 'Right', 'gravityview' ) , 'subtitle' => '' ) ) ), |
|
|
|
|
208
|
|
|
); |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* @filter `gravityview_widget_active_areas` Array of zones available for widgets to be dropped into |
212
|
|
|
* @deprecated Use gravityview/widget/active_areas |
213
|
|
|
* @param array $default_areas Definition for default widget areas |
214
|
|
|
*/ |
215
|
3 |
|
$default_areas = apply_filters( 'gravityview_widget_active_areas', $default_areas ); |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* @filter `gravityview/widget/active_areas` Array of zones available for widgets to be dropped into |
219
|
|
|
* @param array $default_areas Definition for default widget areas |
220
|
|
|
*/ |
221
|
3 |
|
return apply_filters( 'gravityview/widget/active_areas', $default_areas ); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Register widget to become available in admin. And for lookup. |
226
|
|
|
* |
227
|
|
|
* @param array $widgets Usually just empty. Used to gather them all up. |
228
|
|
|
* |
229
|
|
|
* @return array $widgets |
230
|
|
|
*/ |
231
|
7 |
|
public function register_widget( $widgets ) { |
232
|
7 |
|
if ( ! is_array( $widgets ) ) { |
233
|
|
|
$widgets = array(); |
234
|
|
|
} |
235
|
|
|
|
236
|
7 |
|
$widgets[ $this->get_widget_id() ] = array( |
237
|
7 |
|
'label' => $this->widget_label , |
|
|
|
|
238
|
7 |
|
'description' => $this->widget_description, |
239
|
7 |
|
'subtitle' => $this->widget_subtitle, |
240
|
7 |
|
'class' => get_called_class(), |
241
|
|
|
); |
242
|
|
|
|
243
|
7 |
|
return $widgets; |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* Assign template specific widget options |
248
|
|
|
* |
249
|
|
|
* @access protected |
250
|
|
|
* |
251
|
|
|
* @param array $options (default: array()) |
252
|
|
|
* @param string $template (default: '') |
253
|
|
|
* |
254
|
|
|
* @return array |
255
|
|
|
*/ |
256
|
1 |
|
public function assign_widget_options( $options = array(), $template = '', $widget = '' ) { |
257
|
1 |
|
if ( $this->get_widget_id() === $widget ) { |
258
|
1 |
|
if( $settings = $this->get_settings() ) { |
259
|
1 |
|
$options = array_merge( $options, $settings ); |
260
|
|
|
} |
261
|
|
|
} |
262
|
1 |
|
return $options; |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
/** |
266
|
|
|
* Do shortcode if the Widget's shortcode exists. |
267
|
|
|
* |
268
|
|
|
* @param string $text Widget text to check |
269
|
|
|
* @param null|WP_Widget Empty if not called by WP_Widget, or a WP_Widget instance |
270
|
|
|
* |
271
|
|
|
* @return string Widget text |
272
|
|
|
*/ |
273
|
1 |
|
public function maybe_do_shortcode( $text, $widget = null ) { |
|
|
|
|
274
|
1 |
|
if ( ! empty( $this->shortcode_name ) && has_shortcode( $text, $this->shortcode_name ) ) { |
275
|
1 |
|
return do_shortcode( $text ); |
276
|
|
|
} |
277
|
|
|
return $text; |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Add $this->shortcode_name shortcode to output self::render_frontend() |
282
|
|
|
* |
283
|
|
|
* @return void |
284
|
|
|
*/ |
285
|
1 |
|
public function add_shortcode() { |
286
|
1 |
|
if ( empty( $this->shortcode_name ) ) { |
287
|
|
|
return; |
288
|
|
|
} |
289
|
|
|
|
290
|
1 |
|
if ( gravityview()->request->is_admin() ) { |
291
|
|
|
return; |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
// If the widget shouldn't output on single entries, don't show it |
295
|
1 |
|
if ( empty( $this->show_on_single ) && gravityview()->request->is_entry() ) { |
|
|
|
|
296
|
|
|
gravityview()->log->debug( 'Skipping; set to not run on single entry.' ); |
297
|
|
|
add_shortcode( $this->shortcode_name, '__return_null' ); |
298
|
|
|
return; |
299
|
|
|
} |
300
|
|
|
|
301
|
1 |
|
global $post; |
|
|
|
|
302
|
|
|
|
303
|
1 |
|
if ( ! is_object( $post ) || empty( $post->post_content ) || ! Shortcode::parse( $post->post_content ) ) { |
304
|
|
|
gravityview()->log->debug( 'No shortcode present; not adding render_frontend shortcode.' ); |
305
|
|
|
add_shortcode( $this->shortcode_name, '__return_null' ); |
306
|
|
|
return; |
307
|
|
|
} |
308
|
|
|
|
309
|
1 |
|
add_shortcode( $this->shortcode_name, array( $this, 'render_shortcode') ); |
|
|
|
|
310
|
1 |
|
} |
311
|
|
|
|
312
|
|
|
/** |
313
|
|
|
* Frontend logic. |
314
|
|
|
* |
315
|
|
|
* Override in child class. |
316
|
|
|
* |
317
|
|
|
* @param array $widget_args The Widget shortcode args. |
318
|
|
|
* @param string $content The content. |
319
|
|
|
* @param string|\GV\Template_Context $context The context, if available. |
320
|
|
|
* |
321
|
|
|
* @return void |
322
|
|
|
*/ |
323
|
|
|
public function render_frontend( $widget_args, $content = '', $context = '' ) { |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* General validations when rendering the widget |
328
|
|
|
* |
329
|
|
|
* Always call this from your `render_frontend()` override! |
330
|
|
|
* |
331
|
|
|
* @return boolean True: render frontend; False: don't render frontend |
332
|
|
|
*/ |
333
|
3 |
|
public function pre_render_frontend() { |
334
|
3 |
|
if ( $view = gravityview()->views->get() ) { |
|
|
|
|
335
|
2 |
|
$hide_until_searched = $view->settings->get( 'hide_until_searched' ); |
336
|
|
|
} else { |
337
|
1 |
|
$hide_until_searched = false; |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
/** |
341
|
|
|
* @filter `gravityview/widget/hide_until_searched` Modify whether to hide content until search |
342
|
|
|
* @param boolean $hide_until_searched Hide until search? |
343
|
|
|
* @param \GV\Widget $this Widget instance |
344
|
|
|
*/ |
345
|
3 |
|
$hide_until_search = apply_filters( 'gravityview/widget/hide_until_searched', $hide_until_searched, $this ); |
346
|
|
|
|
347
|
3 |
|
if ( $hide_until_search ) { |
348
|
|
|
gravityview()->log->debug( 'Hide View data until search is performed' ); |
349
|
|
|
return false; |
350
|
|
|
} |
351
|
|
|
|
352
|
3 |
|
return true; |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
/** |
356
|
|
|
* Shortcode. |
357
|
|
|
* |
358
|
|
|
* @param array $atts The Widget shortcode args. |
359
|
|
|
* @param string $content The content. |
360
|
|
|
* @param string $context The context, if available. |
361
|
|
|
* |
362
|
|
|
* @return string Whatever the widget echoed. |
363
|
|
|
*/ |
364
|
1 |
|
public function render_shortcode( $atts, $content = '', $context = '' ) { |
365
|
1 |
|
ob_start(); |
366
|
1 |
|
$this->render_frontend( $atts, $content, $context ); |
367
|
1 |
|
return ob_get_clean(); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Create the needed widget from a configuration array. |
372
|
|
|
* |
373
|
|
|
* @param array $configuration The configuration array. |
374
|
|
|
* @see \GV\Widget::as_configuration() |
375
|
|
|
* @internal |
376
|
|
|
* @since 2.0 |
377
|
|
|
* |
378
|
|
|
* @return \GV\Widget|null The widget implementation from configuration or none. |
379
|
|
|
*/ |
380
|
6 |
|
public static function from_configuration( $configuration ) { |
381
|
6 |
|
$registered_widgets = self::registered(); |
382
|
|
|
|
383
|
6 |
|
if ( ! $id = Utils::get( $configuration, 'id' ) ) { |
384
|
|
|
return null; |
385
|
|
|
} |
386
|
|
|
|
387
|
6 |
|
if ( ! $widget = Utils::get( $registered_widgets, $id ) ) { |
388
|
|
|
return null; |
389
|
|
|
} |
390
|
|
|
|
391
|
6 |
|
if ( ! class_exists( $class = Utils::get( $widget, 'class' ) ) ) { |
392
|
|
|
return null; |
393
|
|
|
} |
394
|
|
|
|
395
|
6 |
|
$w = new $class( Utils::get( $widget, 'label' ), $id ); |
396
|
6 |
|
$w->configuration = new Settings( $configuration ); |
397
|
|
|
|
398
|
6 |
|
return $w; |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
/** |
402
|
|
|
* Return an array of the old format. |
403
|
|
|
* |
404
|
|
|
* 'id' => string |
405
|
|
|
* + whatever else specific fields may have |
406
|
|
|
* |
407
|
|
|
* @internal |
408
|
|
|
* @since 2.0 |
409
|
|
|
* |
410
|
|
|
* @return array |
411
|
|
|
*/ |
412
|
3 |
|
public function as_configuration() { |
413
|
3 |
|
return array_merge( array( |
414
|
3 |
|
'id' => $this->get_widget_id(), |
415
|
3 |
|
), $this->configuration->all() ); |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
/** |
419
|
|
|
* Return all registered widgets. |
420
|
|
|
* |
421
|
|
|
* @api |
422
|
|
|
* @since 2.0 |
423
|
|
|
* |
424
|
|
|
* @return array |
425
|
|
|
*/ |
426
|
7 |
|
public static function registered() { |
427
|
|
|
/** |
428
|
|
|
* @filter `gravityview_register_directory_widgets` Get the list of registered widgets. Each item is used to instantiate a GravityView_Admin_View_Widget object |
429
|
|
|
* @deprecated Use `gravityview/widgets/register` |
430
|
|
|
* @param array $registered_widgets Empty array |
431
|
|
|
*/ |
432
|
7 |
|
$registered_widgets = apply_filters( 'gravityview_register_directory_widgets', array() ); |
433
|
|
|
|
434
|
|
|
/** |
435
|
|
|
* @filter `gravityview/widgets/register` Each item is used to instantiate a GravityView_Admin_View_Widget object |
436
|
|
|
* @param array $registered_widgets Empty array |
437
|
|
|
*/ |
438
|
7 |
|
return apply_filters( 'gravityview/widgets/register', $registered_widgets ); |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
/** |
442
|
|
|
* Whether this Widget's been registered already or not. |
443
|
|
|
* |
444
|
|
|
* @api |
445
|
|
|
* @since 2.0 |
446
|
|
|
* |
447
|
|
|
* @return bool |
448
|
|
|
*/ |
449
|
7 |
|
public function is_registered() { |
450
|
7 |
|
if ( ! $widget_id = $this->get_widget_id() ) { |
451
|
|
|
gravityview()->log->warning( 'Widget ID not set before calling Widget::is_registered', array( 'data' => $this ) ); |
452
|
|
|
return false; |
453
|
|
|
} |
454
|
7 |
|
return in_array( $widget_id, array_keys( self::registered() ) ); |
455
|
|
|
} |
456
|
|
|
} |
457
|
|
|
|
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.