Test Failed
Push — master ( 0513b2...9d7f3f )
by Alain
01:48
created

Shortcode::add_context()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
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 ( ! $this->is_needed( $context ) ) {
127
			return;
128
		}
129
		$this->context = $context;
130
131
		\add_shortcode( $this->get_tag(), [ $this, 'render' ] );
132
	}
133
134
	/**
135
	 * Add additional context to the shortcode.
136
	 *
137
	 * This can be used to pass more data to the view to be rendered.
138
	 *
139
	 * This is especially useful for additional preparation through a DI.
140
	 *
141
	 * @param array $context Associative array of context information to add.
142
	 */
143
	public function add_context( array $context ) {
144
		$this->context = array_merge( $this->context, $context );
145
	}
146
147
	/**
148
	 * Get the shortcode tag.
149
	 *
150
	 * @since 0.1.0
151
	 *
152
	 * @return string Shortcode tag.
153
	 */
154
	public function get_tag() {
155
		return (string) $this->shortcode_tag;
156
	}
157
158
	/**
159
	 * Render the shortcode.
160
	 *
161
	 * @since 0.1.0
162
	 *
163
	 * @throws DomainException
164
	 *
165
	 * @param array       $atts    Attributes to modify the standard behavior
166
	 *                             of the shortcode.
167
	 * @param string|null $content Optional. Content between enclosing
168
	 *                             shortcodes.
169
	 * @param string|null $tag     Optional. The tag of the shortcode to
170
	 *                             render. Ignored by current code.
171
	 * @return string              The shortcode's HTML output.
172
	 */
173
	public function render( $atts, $content = null, $tag = null ) {
174
		$context = $this->context;
175
		$atts    = $this->atts_parser->parse_atts( $atts, $this->get_tag() );
176
		$this->enqueue_dependencies( $this->get_dependency_handles(), $atts );
177
178
		return $this->render_view(
179
			$this->get_view(),
180
			$context,
181
			$atts,
182
			$content
183
		);
184
	}
185
186
	/**
187
	 * Enqueue the dependencies that the shortcode needs.
188
	 *
189
	 * @since 0.2.9
190
	 *
191
	 * @param array $handles Array of dependency handles to enqueue.
192
	 * @param mixed $context Optional. Context in which to enqueue.
193
	 */
194
	protected function enqueue_dependencies( $handles, $context = null ) {
195
		if ( ! $this->dependencies || count( $handles ) < 1 ) {
196
			return;
197
		}
198
199
		foreach ( $handles as $handle ) {
200
			$found = $this->dependencies->enqueue_handle(
201
				$handle,
202
				$context,
203
				true
204
			);
205
			if ( ! $found ) {
206
				$message = sprintf(
207
					__( 'Could not enqueue dependency "%1$s" for shortcode "%2$s".',
208
						'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...
209
					$handle,
210
					$this->get_tag()
211
				);
212
				trigger_error( $message, E_USER_WARNING );
213
			}
214
		}
215
216
	}
217
218
	/**
219
	 * Get an array of dependency handles for the current shortcode.
220
	 *
221
	 * @since 0.2.7
222
	 *
223
	 * @return array Array of strings that are registered dependency handles.
224
	 */
225
	protected function get_dependency_handles() {
226
		if ( ! $this->hasConfigKey( 'dependencies' ) ) {
227
			return [ ];
228
		}
229
		return (array) $this->getConfigKey( 'dependencies' );
230
	}
231
232
	/**
233
	 * Get the rendered HTML for a given view.
234
	 *
235
	 * @since 0.2.6
236
	 *
237
	 * @param string      $uri     URI of the view to render.
238
	 * @param mixed       $context The context to pass through to the view.
239
	 * @param array       $atts    The shortcode attribute values to pass
240
	 *                             through to the view.
241
	 * @param string|null $content Optional. The inner content of the shortcode.
242
	 * @return string HTML rendering of the view.
243
	 */
244
	protected function render_view( $uri, $context, $atts, $content = null ) {
245
		return $this->view_builder
246
			->create( $uri )
247
			->render(
248
				array_merge(
249
					(array) $context,
250
					(array) $atts,
251
					(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...
252
			);
253
	}
254
255
	/**
256
	 * Get the name of the view to render.
257
	 *
258
	 * @since 0.2.6
259
	 *
260
	 * @return string Name of the view to render.
261
	 */
262
	protected function get_view() {
263
		if ( ! $this->hasConfigKey( 'view' ) ) {
264
			return '';
265
		}
266
		$view = $this->getConfigKey( 'view' );
267
268
		return $view;
269
	}
270
271
	/**
272
	 * Execute this shortcode directly from code.
273
	 *
274
	 * @since 0.2.4
275
	 *
276
	 * @param array       $atts    Array of attributes to pass to the shortcode.
277
	 * @param string|null $content Inner content to pass to the shortcode.
278
	 * @return string|false Rendered HTML.
279
	 */
280
	public function do_this( array $atts = [ ], $content = null ) {
281
		return \BrightNucleus\Shortcode\do_tag( $this->get_tag(), $atts, $content );
282
	}
283
}
284