Completed
Push — master ( ff34a2...c00646 )
by Zack
46:25 queued 35:42
created

Widget::get_widget_id()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 14 and the first side effect is on line 6.

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.

Loading history...
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();
0 ignored issues
show
Unused Code introduced by
The property $widget_options is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
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 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' => '' ) ) ),
0 ignored issues
show
introduced by
Expected 0 spaces between ")" and comma; 1 found
Loading history...
207 3
			array( '1-2' => array( array( 'areaid' => 'left', 'title' => __( 'Left', 'gravityview' ) , 'subtitle' => '' ) ), '2-2' => array( array( 'areaid' => 'right', 'title' => __( 'Right', 'gravityview' ) , 'subtitle' => '' ) ) ),
0 ignored issues
show
introduced by
Expected 0 spaces between ")" and comma; 1 found
Loading history...
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 ,
0 ignored issues
show
introduced by
Expected 0 spaces between "widget_label" and comma; 1 found
Loading history...
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 ) {
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...
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() ) {
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...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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') );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
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() ) {
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...
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