GravityView  2.9.2
The best, easiest way to display Gravity Forms entries on your website.
class-gv-widget.php
Go to the documentation of this file.
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  */
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  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  $this->shortcode_name = empty( $this->shortcode_name ) ? strtolower( get_called_class() ) : $this->shortcode_name;
105 
106  if ( $id ) {
107  $this->widget_id = $id;
108  }
109 
110  $this->widget_label = $label;
111  $this->defaults = array_merge( array( 'header' => 0, 'footer' => 0 ), $defaults );
112 
113  // Make sure every widget has a title, even if empty
114  $this->settings = wp_parse_args( $settings, $this->get_default_settings() );
115 
116  // Hook once per unique ID
117  if ( $this->is_registered() ) {
118  return;
119  }
120 
121  // widget options
122  add_filter( 'gravityview_template_widget_options', array( $this, 'assign_widget_options' ), 10, 3 );
123 
124  // frontend logic
125  add_action( sprintf( 'gravityview/widgets/%s/render', $this->get_widget_id() ), array( $this, 'render_frontend' ), 10, 3 );
126 
127  // register shortcodes
128  add_action( 'wp', array( $this, 'add_shortcode' ) );
129 
130  // Use shortcodes in text widgets.
131  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  add_filter( 'gravityview/widgets/register', array( $this, 'register_widget' ) );
136  }
137 
138  /**
139  * Define general widget settings
140  * @since 1.5.4
141  * @return array $settings Default settings
142  */
143  protected function get_default_settings() {
144  $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  $enable_custom_class = apply_filters( 'gravityview/widget/enable_custom_class', false, $this );
152 
153  if ( $enable_custom_class ) {
154  $settings['custom_class'] = array(
155  'type' => 'text',
156  'label' => __( 'Custom CSS Class:', 'gravityview' ),
157  'desc' => __( 'This class will be added to the widget container', 'gravityview' ),
158  'value' => '',
159  'merge_tags' => true,
160  );
161  }
162 
163  return $settings;
164  }
165 
166  /**
167  * Get the Widget ID.
168  *
169  * @return string The Widget ID.
170  */
171  public function get_widget_id() {
172  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  public function get_settings() {
181  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  public function get_setting( $key ) {
194  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  public static function get_default_widget_areas() {
205  $default_areas = array(
206  array( '1-1' => array( array( 'areaid' => 'top', 'title' => __( 'Top', 'gravityview' ) , 'subtitle' => '' ) ) ),
207  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 2.0: Use gravityview/widget/active_areas instead
213  * @param array $default_areas Definition for default widget areas
214  */
215  $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  * @since 2.0
220  * @param array $default_areas Definition for default widget areas
221  */
222  return apply_filters( 'gravityview/widget/active_areas', $default_areas );
223  }
224 
225  /**
226  * Register widget to become available in admin. And for lookup.
227  *
228  * @param array $widgets Usually just empty. Used to gather them all up.
229  *
230  * @return array $widgets
231  */
232  public function register_widget( $widgets ) {
233  if ( ! is_array( $widgets ) ) {
234  $widgets = array();
235  }
236 
237  $widgets[ $this->get_widget_id() ] = array(
238  'label' => $this->widget_label ,
239  'description' => $this->widget_description,
240  'subtitle' => $this->widget_subtitle,
241  'class' => get_called_class(),
242  );
243 
244  return $widgets;
245  }
246 
247  /**
248  * Assign template specific widget options
249  *
250  * @access protected
251  *
252  * @param array $options (default: array())
253  * @param string $template (default: '')
254  *
255  * @return array
256  */
257  public function assign_widget_options( $options = array(), $template = '', $widget = '' ) {
258  if ( $this->get_widget_id() === $widget ) {
259  if( $settings = $this->get_settings() ) {
260  $options = array_merge( $options, $settings );
261  }
262  }
263  return $options;
264  }
265 
266  /**
267  * Do shortcode if the Widget's shortcode exists.
268  *
269  * @param string $text Widget text to check
270  * @param null|\WP_Widget Empty if not called by WP_Widget, or a WP_Widget instance
271  *
272  * @return string Widget text
273  */
274  public function maybe_do_shortcode( $text, $widget = null ) {
275  if ( ! empty( $this->shortcode_name ) && has_shortcode( $text, $this->shortcode_name ) ) {
276  return do_shortcode( $text );
277  }
278  return $text;
279  }
280 
281  /**
282  * Add $this->shortcode_name shortcode to output self::render_frontend()
283  *
284  * @return void
285  */
286  public function add_shortcode() {
287  if ( empty( $this->shortcode_name ) ) {
288  return;
289  }
290 
291  if ( ! gravityview()->plugin->is_compatible() ) {
292  return;
293  }
294 
295  if ( gravityview()->request->is_admin() ) {
296  return;
297  }
298 
299  // If the widget shouldn't output on single entries, don't show it
300  if ( empty( $this->show_on_single ) && gravityview()->request->is_entry() ) {
301  gravityview()->log->debug( 'Skipping; set to not run on single entry.' );
302  add_shortcode( $this->shortcode_name, '__return_null' );
303  return;
304  }
305 
306  global $post;
307 
308  if ( ! is_object( $post ) || empty( $post->post_content ) || ! Shortcode::parse( $post->post_content ) ) {
309  gravityview()->log->debug( 'No shortcode present; not adding render_frontend shortcode.' );
310  add_shortcode( $this->shortcode_name, '__return_null' );
311  return;
312  }
313 
314  add_shortcode( $this->shortcode_name, array( $this, 'render_shortcode') );
315  }
316 
317  /**
318  * Frontend logic.
319  *
320  * Override in child class.
321  *
322  * @param array $widget_args The Widget shortcode args.
323  * @param string $content The content.
324  * @param string|\GV\Template_Context $context The context, if available.
325  *
326  * @return void
327  */
328  public function render_frontend( $widget_args, $content = '', $context = '' ) {
329  }
330 
331  /**
332  * General validations when rendering the widget
333  *
334  * Always call this from your `render_frontend()` override!
335  *
336  * @return boolean True: render frontend; False: don't render frontend
337  */
338  public function pre_render_frontend() {
339  /**
340  * Assume shown regardless of hide_until_search setting.
341  */
342  $whitelist = array(
343  'custom_content',
344  );
345 
346  /**
347  * @filter `gravityview/widget/hide_until_searched/whitelist` Some widgets have got to stay shown.
348  * @param[in,out] string[] $whitelist The widget IDs that have to be shown by default.
349  */
350  $whitelist = apply_filters( 'gravityview/widget/hide_until_searched/whitelist', $whitelist );
351 
352  if ( ( $view = gravityview()->views->get() ) && ! in_array( $this->get_widget_id(), $whitelist ) ) {
353  $hide_until_searched = $view->settings->get( 'hide_until_searched' );
354  } else {
355  $hide_until_searched = false;
356  }
357 
358  /**
359  * @filter `gravityview/widget/hide_until_searched` Modify whether to hide content until search
360  * @param boolean $hide_until_searched Hide until search?
361  * @param \GV\Widget $this Widget instance
362  */
363  $hide_until_searched = apply_filters( 'gravityview/widget/hide_until_searched', $hide_until_searched, $this );
364 
365  if ( $hide_until_searched && ! gravityview()->request->is_search() ) {
366  gravityview()->log->debug( 'Hide View data until search is performed' );
367  return false;
368  }
369 
370  return true;
371  }
372 
373  /**
374  * Shortcode.
375  *
376  * @param array $atts The Widget shortcode args.
377  * @param string $content The content.
378  * @param string|\GV\Template_Context $context The context, if available.
379  *
380  * @return string Whatever the widget echoed.
381  */
382  public function render_shortcode( $atts, $content = '', $context = '' ) {
383  ob_start();
384  $this->render_frontend( $atts, $content, $context );
385  return ob_get_clean();
386  }
387 
388  /**
389  * Create the needed widget from a configuration array.
390  *
391  * @param array $configuration The configuration array.
392  * @see \GV\Widget::as_configuration()
393  * @internal
394  * @since 2.0
395  *
396  * @return \GV\Widget|null The widget implementation from configuration or none.
397  */
398  public static function from_configuration( $configuration ) {
399  $registered_widgets = self::registered();
400 
401  if ( ! $id = Utils::get( $configuration, 'id' ) ) {
402  return null;
403  }
404 
405  if ( ! $widget = Utils::get( $registered_widgets, $id ) ) {
406  return null;
407  }
408 
409  if ( ! class_exists( $class = Utils::get( $widget, 'class' ) ) ) {
410  return null;
411  }
412 
413  $w = new $class( Utils::get( $widget, 'label' ), $id );
414  $w->configuration = new Settings( $configuration );
415 
416  return $w;
417  }
418 
419  /**
420  * Return an array of the old format.
421  *
422  * 'id' => string
423  * + whatever else specific fields may have
424  *
425  * @internal
426  * @since 2.0
427  *
428  * @return array
429  */
430  public function as_configuration() {
431  return array_merge( array(
432  'id' => $this->get_widget_id(),
433  ), $this->configuration->all() );
434  }
435 
436  /**
437  * Return all registered widgets.
438  *
439  * @api
440  * @since 2.0
441  *
442  * @return array
443  */
444  public static function registered() {
445  /**
446  * @filter `gravityview_register_directory_widgets` Get the list of registered widgets. Each item is used to instantiate a GravityView_Admin_View_Widget object
447  * @deprecated Use `gravityview/widgets/register`
448  * @param array $registered_widgets Empty array
449  */
450  $registered_widgets = apply_filters( 'gravityview_register_directory_widgets', array() );
451 
452  /**
453  * @filter `gravityview/widgets/register` Each item is used to instantiate a GravityView_Admin_View_Widget object
454  * @param array $registered_widgets Empty array
455  */
456  return apply_filters( 'gravityview/widgets/register', $registered_widgets );
457  }
458 
459  /**
460  * Whether this Widget's been registered already or not.
461  *
462  * @api
463  * @since 2.0
464  *
465  * @return bool
466  */
467  public function is_registered() {
468  if ( ! $widget_id = $this->get_widget_id() ) {
469  gravityview()->log->warning( 'Widget ID not set before calling Widget::is_registered', array( 'data' => $this ) );
470  return false;
471  }
472  return in_array( $widget_id, array_keys( self::registered() ), true );
473  }
474 }
If this file is called directly, abort.
global $post
Definition: edit-entry.php:7
static registered()
Return all registered widgets.
if(! isset( $gravityview)||empty( $gravityview->template)) $template
The entry loop for the list output.
pre_render_frontend()
General validations when rendering the widget.
$class
render_frontend( $widget_args, $content='', $context='')
Frontend logic.
get_settings()
Get the widget settings.
static get_default_widget_areas()
Default widget areas.
static from_configuration( $configuration)
Create the needed widget from a configuration array.
assign_widget_options( $options=array(), $template='', $widget='')
Assign template specific widget options.
gravityview()
Definition: _stubs.php:26
maybe_do_shortcode( $text, $widget=null)
Do shortcode if the Widget&#39;s shortcode exists.
register_widget( $widgets)
Register widget to become available in admin.
get( $key, $default=null)
Retrieve a setting.
If this file is called directly, abort.
add_shortcode()
Add $this->shortcode_name shortcode to output self::render_frontend()
if(empty( $field_settings['content'])) $content
Definition: custom.php:37
render_shortcode( $atts, $content='', $context='')
Shortcode.
is_registered()
Whether this Widget&#39;s been registered already or not.
defaults()
Default settings.
if(empty( $field_settings['email_field'])) $settings
get_widget_id()
Get the Widget ID.
get_setting( $key)
Get a setting by the setting key.
get_default_settings()
Default settings.
as_configuration()
Return an array of the old format.
get_default_settings()
Define general widget settings.