Completed
Push — develop ( a61784...aed985 )
by Zack
27:19 queued 14:49
created

Widget::get_setting()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
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
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
98
	 */
99 40
	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 40
		$this->shortcode_name = empty( $this->shortcode_name ) ? strtolower( get_called_class() ) : $this->shortcode_name;
105
106 40
		if ( $id ) {
107 5
			$this->widget_id = $id;
108
		}
109
110 40
		$this->widget_label = $label;
111 40
		$this->defaults = array_merge( array( 'header' => 0, 'footer' => 0 ), $defaults );
112
113
		// Make sure every widget has a title, even if empty
114 40
		$this->settings = wp_parse_args( $settings, $this->get_default_settings() );
115
116
		// Hook once per unique ID
117 40
		if ( $this->is_registered() ) {
118 39
			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 40
	protected function get_default_settings() {
144 40
		$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 40
		$enable_custom_class = apply_filters( 'gravityview/widget/enable_custom_class', false, $this );
152
153 40
		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 40
		return $settings;
164
	}
165
166
    /**
167
	 * Get the Widget ID.
168
	 *
169
     * @return string The Widget ID.
170
     */
171 46
    public function get_widget_id() {
172 46
        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 6
	public static function get_default_widget_areas() {
205
		$default_areas = array(
206 6
			array( '1-1' => array( array( 'areaid' => 'top', 'title' => __( 'Top', 'gravityview' ) , 'subtitle' => '' ) ) ),
207 6
			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 6
		$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 6
		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 40
	public function register_widget( $widgets ) {
233 40
		if ( ! is_array( $widgets ) ) {
234
			$widgets = array();
235
		}
236
237 40
		$widgets[ $this->get_widget_id() ] = array(
238 40
			'label' => $this->widget_label ,
239 40
			'description' => $this->widget_description,
240 40
			'subtitle' => $this->widget_subtitle,
241 40
			'class' => get_called_class(),
242
		);
243
244 40
		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 1
	public function assign_widget_options( $options = array(), $template = '', $widget = '' ) {
258 1
		if ( $this->get_widget_id() === $widget ) {
259 1
			if( $settings = $this->get_settings() ) {
260 1
				$options = array_merge( $options, $settings );
261
			}
262
		}
263 1
		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 1
	public function maybe_do_shortcode( $text, $widget = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $widget is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
275 1
		if ( ! empty( $this->shortcode_name ) && has_shortcode( $text, $this->shortcode_name ) ) {
276 1
			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 3
	public function add_shortcode() {
287 3
		if ( empty( $this->shortcode_name ) ) {
288
			return;
289
		}
290
291 3
		if ( ! gravityview()->plugin->is_compatible() ) {
292
			return;
293
		}
294
295 3
		if ( gravityview()->request->is_admin() ) {
296
			return;
297
		}
298
299
		// If the widget shouldn't output on single entries, don't show it
300 3
		if ( empty( $this->show_on_single ) && gravityview()->request->is_entry() ) {
0 ignored issues
show
Bug introduced by
The property show_on_single does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
301 1
			gravityview()->log->debug( 'Skipping; set to not run on single entry.' );
302 1
			add_shortcode( $this->shortcode_name, '__return_null' );
303 1
			return;
304
		}
305
306 2
		global $post;
307
308 2
		if ( ! is_object( $post ) || empty( $post->post_content ) || ! Shortcode::parse( $post->post_content ) ) {
309 1
			gravityview()->log->debug( 'No shortcode present; not adding render_frontend shortcode.' );
310 1
			add_shortcode( $this->shortcode_name, '__return_null' );
311 1
			return;
312
		}
313
314 2
		add_shortcode( $this->shortcode_name, array( $this, 'render_shortcode') );
315 2
	}
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 4
	public function pre_render_frontend() {
339
		/**
340
		 * Assume shown regardless of hide_until_search setting.
341
		 */
342
		$whitelist = array(
343 4
			'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 4
		$whitelist = apply_filters( 'gravityview/widget/hide_until_searched/whitelist', $whitelist );
351
352 4
		if ( ( $view = gravityview()->views->get() ) && ! in_array( $this->get_widget_id(), $whitelist ) ) {
0 ignored issues
show
Documentation introduced by
The property views does not exist on object<GV\Core>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
353 4
			$hide_until_searched = $view->settings->get( 'hide_until_searched' );
354
		} else {
355 2
			$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 4
		$hide_until_searched = apply_filters( 'gravityview/widget/hide_until_searched', $hide_until_searched, $this );
364
365 4
		if ( $hide_until_searched && ! gravityview()->request->is_search() ) {
366 1
			gravityview()->log->debug( 'Hide View data until search is performed' );
367 1
			return false;
368
		}
369
370 4
		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 1
	public function render_shortcode( $atts, $content = '', $context = '' ) {
383 1
		ob_start();
384 1
		$this->render_frontend( $atts, $content, $context );
385 1
		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 39
	public static function from_configuration( $configuration ) {
399 39
		$registered_widgets = self::registered();
400
401 39
		if ( ! $id = Utils::get( $configuration, 'id' ) ) {
402
			return null;
403
		}
404
405 39
		if ( ! $widget = Utils::get( $registered_widgets, $id ) ) {
406
			return null;
407
		}
408
409 39
		if ( ! class_exists( $class = Utils::get( $widget, 'class' ) ) ) {
410
			return null;
411
		}
412
413 39
		$w = new $class( Utils::get( $widget, 'label' ), $id );
414 39
		$w->configuration = new Settings( $configuration );
415
416 39
		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 6
	public function as_configuration() {
431 6
		return array_merge( array(
432 6
			'id' => $this->get_widget_id(),
433 6
		), $this->configuration->all() );
434
	}
435
436
	/**
437
	 * Return all registered widgets.
438
	 *
439
	 * @api
440
	 * @since 2.0
441
	 *
442
	 * @return array
443
	 */
444 40
	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 40
		$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 40
		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 40
	public function is_registered() {
468 40
		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 40
		return in_array( $widget_id, array_keys( self::registered() ), true );
473
	}
474
}
475