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