Test Failed
Push — master ( 9d7f3f...33a504 )
by Alain
01:51
created

Shortcode::enqueue_dependencies()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
nc 8
nop 2
dl 0
loc 27
ccs 0
cts 7
cp 0
crap 42
rs 8.8657
c 0
b 0
f 0
1
<?php
2
/**
3
 * Bright Nucleus Shortcode Component.
4
 *
5
 * @package   BrightNucleus\Shortcode
6
 * @author    Alain Schlesser <[email protected]>
7
 * @license   MIT
8
 * @link      http://www.brightnucleus.com/
9
 * @copyright 2015-2016 Alain Schlesser, Bright Nucleus
10
 */
11
12
namespace BrightNucleus\Shortcode;
13
14
use BrightNucleus\Config\ConfigInterface as Config;
15
use BrightNucleus\Shortcode\ShortcodeAttsParserInterface as ShortcodeAttsParser;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, BrightNucleus\Shortcode\ShortcodeAttsParser.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
16
use BrightNucleus\Config\ConfigTrait;
17
use BrightNucleus\Dependency\DependencyManagerInterface as DependencyManager;
18
use BrightNucleus\Exception\DomainException;
19
use BrightNucleus\Exception\RuntimeException;
20
use BrightNucleus\View\ViewBuilder;
21
use BrightNucleus\Views;
22
23
/**
24
 * Base Implementation of the Shortcode Interface.
25
 *
26
 * This is a basic implementation of the Shortcode Interface that registers one
27
 * view and passes all attributes unfiltered to that view.
28
 *
29
 * @since   0.1.0
30
 *
31
 * @package BrightNucleus\Shortcode
32
 * @author  Alain Schlesser <[email protected]>
33
 */
34
class Shortcode implements ShortcodeInterface {
35
36
	use ConfigTrait;
37
	use CheckNeedTrait;
38
39
	/**
40
	 * Name of the shortcode handler.
41
	 *
42
	 * @since 0.1.0
43
	 *
44
	 * @var string
45
	 */
46
	protected $shortcode_tag;
47
48
	/**
49
	 * Parser to parse and validate the shortcode's attributes.
50
	 *
51
	 * @since 0.1.0
52
	 *
53
	 * @var ShortcodeAttsParserInterface
54
	 */
55
	protected $atts_parser;
56
57
	/**
58
	 * Dependencies of the shortcode.
59
	 *
60
	 * @since 0.1.0
61
	 *
62
	 * @var DependencyManager
63
	 */
64
	protected $dependencies;
65
66
	/**
67
	 * View builder instance to use for creating views to render.
68
	 *
69
	 * @since 0.4.0
70
	 *
71
	 * @var ViewBuilder
72
	 */
73
	protected $view_builder;
74
75
	/**
76
	 * Cache context information so we can pass it on to the render() method.
77
	 *
78
	 * @var
79
	 *
80
	 * @since 0.2.3
81
	 */
82
	protected $context = [];
83
84
	/**
85
	 * Instantiate Basic Shortcode.
86
	 *
87
	 * @since 0.1.0
88
	 * @since 0.4.0 Added optional $view_builder argument.
89
	 *
90
	 * @param string                 $shortcode_tag Tag that identifies the
91
	 *                                              shortcode.
92
	 * @param Config                 $config        Configuration settings.
93
	 * @param ShortcodeAttsParser    $atts_parser   Attributes parser and
94
	 *                                              validator.
95
	 * @param DependencyManager|null $dependencies  Optional. Dependencies of
96
	 *                                              the shortcode.
97
	 * @param ViewBuilder|null       $view_builder  Optional. View builder
98
	 *                                              instance to use.
99
	 * @throws RuntimeException If the config could not be processed.
100
	 */
101
	public function __construct(
102
		$shortcode_tag,
103
		Config $config,
104
		ShortcodeAttsParser $atts_parser,
105
		DependencyManager $dependencies = null,
106
		ViewBuilder $view_builder = null
107
	) {
108
109
		$this->processConfig( $config );
110
111
		$this->shortcode_tag = $shortcode_tag;
112
		$this->atts_parser   = $atts_parser;
113
		$this->dependencies  = $dependencies;
114
		$this->view_builder  = $view_builder ?? Views::getViewBuilder();
115
	}
116
117
	/**
118
	 * Register the shortcode handler function with WordPress.
119
	 *
120
	 * @since 0.1.0
121
	 *
122
	 * @param mixed $context Optional. Arguments to pass on to the Registrable.
123
	 * @return void
124
	 */
125
	public function register( $context = null ) {
126
		if ( null !== $context ) {
127
			$this->add_context( $context );
128
		}
129
130
		if ( ! $this->is_needed( $this->context ) ) {
131
			return;
132
		}
133
134
		\add_shortcode( $this->get_tag(), [ $this, 'render' ] );
135
	}
136
137
	/**
138
	 * Add additional context to the shortcode.
139
	 *
140
	 * This can be used to pass more data to the view to be rendered.
141
	 *
142
	 * This is especially useful for additional preparation through a DI.
143
	 *
144
	 * @param array $context Associative array of context information to add.
145
	 */
146
	public function add_context( $context ) {
147
		$this->context = array_filter(
148
			array_merge( (array) $this->context, (array) $context )
149
		);
150
	}
151
152
	/**
153
	 * Get the shortcode tag.
154
	 *
155
	 * @since 0.1.0
156
	 *
157
	 * @return string Shortcode tag.
158
	 */
159
	public function get_tag() {
160
		return (string) $this->shortcode_tag;
161
	}
162
163
	/**
164
	 * Render the shortcode.
165
	 *
166
	 * @since 0.1.0
167
	 *
168
	 * @throws DomainException
169
	 *
170
	 * @param array       $atts    Attributes to modify the standard behavior
171
	 *                             of the shortcode.
172
	 * @param string|null $content Optional. Content between enclosing
173
	 *                             shortcodes.
174
	 * @param string|null $tag     Optional. The tag of the shortcode to
175
	 *                             render. Ignored by current code.
176
	 * @return string              The shortcode's HTML output.
177
	 */
178
	public function render( $atts, $content = null, $tag = null ) {
179
		$atts    = $this->atts_parser->parse_atts( $atts, $this->get_tag() );
180
		$this->enqueue_dependencies( $this->get_dependency_handles(), $atts );
181
182
		return $this->render_view(
183
			$this->get_view(),
184
			$this->context,
185
			$atts,
186
			$content
187
		);
188
	}
189
190
	/**
191
	 * Enqueue the dependencies that the shortcode needs.
192
	 *
193
	 * @since 0.2.9
194
	 *
195
	 * @param array $handles Array of dependency handles to enqueue.
196
	 * @param mixed $context Optional. Context in which to enqueue.
197
	 */
198
	protected function enqueue_dependencies( $handles, $context = null ) {
199
		if ( null !== $context ) {
200
			$this->add_context( $context );
201
		}
202
203
		if ( ! $this->dependencies || count( $handles ) < 1 ) {
204
			return;
205
		}
206
207
		foreach ( $handles as $handle ) {
208
			$found = $this->dependencies->enqueue_handle(
209
				$handle,
210
				$this->context,
211
				true
212
			);
213
			if ( ! $found ) {
214
				$message = sprintf(
215
					__( 'Could not enqueue dependency "%1$s" for shortcode "%2$s".',
216
						'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 20 spaces, but found 24.
Loading history...
217
					$handle,
218
					$this->get_tag()
219
				);
220
				trigger_error( $message, E_USER_WARNING );
221
			}
222
		}
223
224
	}
225
226
	/**
227
	 * Get an array of dependency handles for the current shortcode.
228
	 *
229
	 * @since 0.2.7
230
	 *
231
	 * @return array Array of strings that are registered dependency handles.
232
	 */
233
	protected function get_dependency_handles() {
234
		if ( ! $this->hasConfigKey( 'dependencies' ) ) {
235
			return [ ];
236
		}
237
		return (array) $this->getConfigKey( 'dependencies' );
238
	}
239
240
	/**
241
	 * Get the rendered HTML for a given view.
242
	 *
243
	 * @since 0.2.6
244
	 *
245
	 * @param string      $uri     URI of the view to render.
246
	 * @param mixed       $context The context to pass through to the view.
247
	 * @param array       $atts    The shortcode attribute values to pass
248
	 *                             through to the view.
249
	 * @param string|null $content Optional. The inner content of the shortcode.
250
	 * @return string HTML rendering of the view.
251
	 */
252
	protected function render_view( $uri, $context, $atts, $content = null ) {
253
		return $this->view_builder
254
			->create( $uri )
255
			->render(
256
				array_merge(
257
					(array) $context,
258
					(array) $atts,
259
					(array) $content )
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...
260
			);
261
	}
262
263
	/**
264
	 * Get the name of the view to render.
265
	 *
266
	 * @since 0.2.6
267
	 *
268
	 * @return string Name of the view to render.
269
	 */
270
	protected function get_view() {
271
		if ( ! $this->hasConfigKey( 'view' ) ) {
272
			return '';
273
		}
274
		$view = $this->getConfigKey( 'view' );
275
276
		return $view;
277
	}
278
279
	/**
280
	 * Execute this shortcode directly from code.
281
	 *
282
	 * @since 0.2.4
283
	 *
284
	 * @param array       $atts    Array of attributes to pass to the shortcode.
285
	 * @param string|null $content Inner content to pass to the shortcode.
286
	 * @return string|false Rendered HTML.
287
	 */
288
	public function do_this( array $atts = [ ], $content = null ) {
289
		return \BrightNucleus\Shortcode\do_tag( $this->get_tag(), $atts, $content );
290
	}
291
}
292