Passed
Push — master ( 054f95...d111a7 )
by Alain
04:18
created

Shortcode::render()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 7
Bugs 0 Features 2
Metric Value
c 7
b 0
f 2
dl 0
loc 23
ccs 0
cts 14
cp 0
rs 8.5906
cc 5
eloc 16
nc 2
nop 3
crap 30
1
<?php
0 ignored issues
show
Coding Style introduced by
End of line character is invalid; expected "\n" but found "\r\n"
Loading history...
2
/**
3
 * Shortcode Base Implementation.
4
 *
5
 * @package   BrightNucleus\Shortcode
6
 * @author    Alain Schlesser <[email protected]>
7
 * @license   GPL-2.0+
8
 * @link      http://www.brightnucleus.com/
9
 * @copyright 2015-2016 Alain Schlesser, Bright Nucleus
10
 */
11
12
namespace BrightNucleus\Shortcode;
13
14
use Assert;
15
use BrightNucleus\Config\ConfigInterface;
16
use BrightNucleus\Config\ConfigTrait;
17
use BrightNucleus\Dependency\DependencyManagerInterface as DependencyManager;
18
use BrightNucleus\Exception\DomainException;
19
use BrightNucleus\Exception\RuntimeException;
20
21
/**
22
 * Base Implementation of the Shortcode Interface.
23
 *
24
 * This is a basic implementation of the Shortcode Interface that registers one
25
 * view and passes all attributes unfiltered to that view.
26
 *
27
 * @since   0.1.0
28
 *
29
 * @package BrightNucleus\Shortcode
30
 * @author  Alain Schlesser <[email protected]>
31
 */
32
class Shortcode implements ShortcodeInterface {
33
34
	use ConfigTrait;
35
36
	/**
37
	 * Name of the shortcode handler.
38
	 *
39
	 * @since 0.1.0
40
	 *
41
	 * @var string
42
	 */
43
	protected $shortcode_tag;
44
45
	/**
46
	 * Parser to parse and validate the shortcode's attributes.
47
	 *
48
	 * @since 0.1.0
49
	 *
50
	 * @var ShortcodeAttsParserInterface
51
	 */
52
	protected $atts_parser;
53
54
	/**
55
	 * Dependencies of the shortcode.
56
	 *
57
	 * @since 0.1.0
58
	 *
59
	 * @var DependencyManager
60
	 */
61
	protected $dependencies;
62
63
	/**
64
	 * Cache context information so we can pass it on to the render() method.
65
	 *
66
	 * @var
67
	 *
68
	 * @since 0.2.3
69
	 */
70
	protected $context;
71
72
	/**
73
	 * Instantiate Basic Shortcode.
74
	 *
75
	 * @since 0.1.0
76
	 *
77
	 * @param string                 $shortcode_tag Tag that identifies the
78
	 *                                              shortcode.
79
	 * @param ConfigInterface        $config        Configuration settings.
80
	 * @param ShortcodeAttsParser    $atts_parser   Attributes parser and
81
	 *                                              validator.
82
	 * @param DependencyManager|null $dependencies  Optional. Dependencies of
83
	 *                                              the shortcode.
84
	 * @throws RuntimeException If the config could not be processed.
85
	 */
86 View Code Duplication
	public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
87
		$shortcode_tag,
88
		ConfigInterface $config,
89
		ShortcodeAttsParser $atts_parser,
90
		DependencyManager $dependencies = null
91
	) {
92
93
		Assert\that( $shortcode_tag )->string()->notEmpty();
94
95
		$this->processConfig( $config );
96
97
		$this->shortcode_tag = $shortcode_tag;
98
		$this->atts_parser   = $atts_parser;
99
		$this->dependencies  = $dependencies;
100
	}
101
102
	/**
103
	 * Register the shortcode handler function with WordPress.
104
	 *
105
	 * @since 0.1.0
106
	 *
107
	 * @param mixed $context Optional. Arguments to pass on to the Registrable.
108
	 * @return void
109
	 */
110
	public function register( $context = null ) {
111
		if ( ! $this->is_needed( $context ) ) {
112
			return;
113
		}
114
		$this->context = $context;
115
116
		\add_shortcode( $this->get_tag(), [ $this, 'render' ] );
117
	}
118
119
	/**
120
	 * Check whether the shortcode is needed.
121
	 *
122
	 * @since 0.2.0
123
	 *
124
	 * @param mixed $context Data about the context in which the call is made.
125
	 * @return boolean Whether the shortcode is needed or not.
126
	 */
127 View Code Duplication
	protected function is_needed( $context = null ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
128
129
		$is_needed = $this->hasConfigKey( 'is_needed' )
130
			? $this->getConfigKey( 'is_needed' )
131
			: true;
132
133
		if ( is_callable( $is_needed ) ) {
134
			return $is_needed( $context );
135
		}
136
137
		return (bool) $is_needed;
138
	}
139
140
	/**
141
	 * Get the shortcode tag.
142
	 *
143
	 * @since 0.1.0
144
	 *
145
	 * @return string Shortcode tag.
146
	 */
147
	public function get_tag() {
148
		return (string) $this->shortcode_tag;
149
	}
150
151
	/**
152
	 * Render the shortcode.
153
	 *
154
	 * @since 0.1.0
155
	 *
156
	 * @throws DomainException
157
	 *
158
	 * @param  array       $atts    Attributes to modify the standard behavior
159
	 *                              of the shortcode.
160
	 * @param  string|null $content Optional. Content between enclosing
161
	 *                              shortcodes.
162
	 * @param string|null  $tag     Optional. The tag of the shortcode to
163
	 *                              render.
164
	 * @return string               The shortcode's HTML output.
165
	 */
166
	public function render( $atts, $content = null, $tag = null ) {
167
		$context = $this->context;
168
		$atts    = $this->atts_parser->parse_atts( $atts, $this->get_tag() );
169
		$handles = $this->get_dependency_handles();
170
171
		if ( $this->dependencies && count( $handles ) > 0 ) {
172
			foreach ( $handles as $handle ) {
173
				$handle_found = $this->dependencies->enqueue_handle( $handle,
0 ignored issues
show
Bug introduced by
The method enqueue_handle() does not exist on BrightNucleus\Dependency...endencyManagerInterface. Did you maybe mean enqueue()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
174
					$atts );
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 16 spaces, but found 20.
Loading history...
175
				if ( ! $handle_found ) {
176
					trigger_error( sprintf(
177
							__( 'Could not enqueue dependency "%1$s" for shortcode "%2$s".',
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 24 spaces, but found 28.
Loading history...
178
								'bn-shortcodes' ),
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 28 spaces, but found 32.
Loading history...
179
							$handle,
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 24 spaces, but found 28.
Loading history...
180
							$this->get_tag() ),
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 20 spaces, but found 28.
Loading history...
181
						E_USER_WARNING
182
					);
183
				}
184
			}
185
		}
186
187
		return $this->render_view( $this->get_view(), $context );
188
	}
189
190
	/**
191
	 * Get an array of dependency handles for the current shortcode.
192
	 *
193
	 * @since 0.2.7
194
	 *
195
	 * @return array Array of strings that are registered dependency handles.
196
	 */
197
	protected function get_dependency_handles() {
198
		if ( ! $this->hasConfigKey( 'dependencies' ) ) {
199
			return [ ];
200
		}
201
		return (array) $this->getConfigKey( 'dependencies' );
202
	}
203
204
	/**
205
	 * Get the rendered HTML for a given view.
206
	 *
207
	 * @since 0.2.6
208
	 *
209
	 * @param string $view    The view to render.
210
	 * @param mixed  $context The context to pass through to the view.
211
	 * @return string HTML rendering of the view.
212
	 */
213
	protected function render_view( $view, $context ) {
214
		if ( empty( $view ) ) {
215
			return '';
216
		}
217
218
		ob_start();
219
		include( $view );
220
		return ob_get_clean();
221
	}
222
223
	/**
224
	 * Get the name of the view to render.
225
	 *
226
	 * @since 0.2.6
227
	 *
228
	 * @return string Name of the view to render.
229
	 */
230
	protected function get_view() {
231
		if ( ! $this->hasConfigKey( 'view' ) ) {
232
			return '';
233
		}
234
		$view = $this->getConfigKey( 'view' );
235
236
		Assert\that( $view )->string()->notEmpty()->file();
237
238
		return $view;
239
	}
240
241
	/**
242
	 * Execute this shortcode directly from code.
243
	 *
244
	 * @since 0.2.4
245
	 *
246
	 * @param array       $atts    Array of attributes to pass to the shortcode.
247
	 * @param string|null $content Inner content to pass to the shortcode.
248
	 * @return string|false Rendered HTML.
0 ignored issues
show
Documentation introduced by
Should the return type not be string|false|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
249
	 */
250
	public function do_this( array $atts = [ ], $content = null ) {
251
		\BrightNucleus\Shortcode\do_tag( $this->get_tag(), $atts, $content );
252
	}
253
}
254