Failed Conditions
Push — master ( 141f54...437209 )
by Atanas
03:01
created

ViewService::canonical()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 2
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * @package   WPEmerge
4
 * @author    Atanas Angelov <[email protected]>
5
 * @copyright 2017-2019 Atanas Angelov
6
 * @license   https://www.gnu.org/licenses/gpl-2.0.html GPL-2.0
7
 * @link      https://wpemerge.com/
8
 */
9
10
namespace WPEmerge\View;
11
12
use Closure;
13
use WPEmerge\Helpers\Handler;
14
use WPEmerge\Helpers\HandlerFactory;
15
use WPEmerge\Helpers\MixedType;
16
17
/**
18
 * Provide general view-related functionality.
19
 */
20
class ViewService {
21
	/**
22
	 * Configuration.
23
	 *
24
	 * @var array<string, mixed>
25
	 */
26
	protected $config = [];
27
28
	/**
29
	 * View engine.
30
	 *
31
	 * @var ViewEngineInterface
32
	 */
33
	protected $engine = null;
34
35
	/**
36
	 * Handler factory.
37
	 *
38
	 * @var HandlerFactory
39
	 */
40
	protected $handler_factory = null;
41
42
	/**
43
	 * Global variables.
44
	 *
45
	 * @var array
46
	 */
47
	protected $globals = [];
48
49
	/**
50
	 * View composers.
51
	 *
52
	 * @var array
53
	 */
54
	protected $composers = [];
55
56
	/**
57
	 * Constructor.
58
	 *
59
	 * @codeCoverageIgnore
60
	 * @param array<string, mixed> $config
61
	 * @param ViewEngineInterface  $engine
62
	 * @param HandlerFactory       $handler_factory
63
	 */
64
	public function __construct( $config, ViewEngineInterface $engine, HandlerFactory $handler_factory ) {
65
		$this->config = $config;
66
		$this->engine = $engine;
67
		$this->handler_factory = $handler_factory;
68
	}
69
70
	/**
71
	 * Get global variables.
72
	 *
73
	 * @return array
74
	 */
75 2
	public function getGlobals() {
76 2
		return $this->globals;
77
	}
78
79
	/**
80
	 * Set a global variable.
81
	 *
82
	 * @param  string $key
83
	 * @param  mixed  $value
84
	 * @return void
85
	 */
86 1
	public function addGlobal( $key, $value ) {
87 1
		$this->globals[ $key ] = $value;
88 1
	}
89
90
	/**
91
	 * Set an array of global variables.
92
	 *
93
	 * @param  array $globals
94
	 * @return void
95
	 */
96 1
	public function addGlobals( $globals ) {
97 1
		foreach ( $globals as $key => $value ) {
98 1
			$this->addGlobal( $key, $value );
99
		}
100 1
	}
101
102
	/**
103
	 * Get view composer.
104
	 *
105
	 * @param  string    $view
106
	 * @return Handler[]
107
	 */
108 1
	public function getComposersForView( $view ) {
109 1
		$view = $this->engine->canonical( $view );
110
111 1
		$composers = [];
112
113 1
		foreach ( $this->composers as $composer ) {
114 1
			if ( in_array( $view, $composer['views'], true ) ) {
115 1
				$composers[] = $composer['composer'];
116
			}
117
		}
118
119 1
		return $composers;
120
	}
121
122
	/**
123
	 * Add view composer.
124
	 *
125
	 * @param  string|string[] $views
126
	 * @param  string|Closure  $composer
127
	 * @return void
128
	 */
129 1
	public function addComposer( $views, $composer ) {
130
		$views = array_map( function ( $view ) {
131 1
			return $this->engine->canonical( $view );
132 1
		}, MixedType::toArray( $views ) );
133
134 1
		$handler = $this->handler_factory->make( $composer, 'compose', $this->config['namespace'] );
135
136 1
		$this->composers[] = [
137 1
			'views' => $views,
138 1
			'composer' => $handler,
139
		];
140 1
	}
141
142
	/**
143
	 * Composes a view instance with contexts in the following order: Global, Composers, Local.
144
	 *
145
	 * @param  ViewInterface $view
146
	 * @return void
147
	 */
148 4
	public function compose( ViewInterface $view ) {
149 4
		$global = ['global' => $this->getGlobals()];
150 4
		$local = $view->getContext();
151
152 4
		$view->with( $global );
153
154 4
		$composers = $this->getComposersForView( $view->getName() );
155 4
		foreach ( $composers as $composer ) {
156 3
			$composer->execute( $view );
157
		}
158
159 4
		$view->with( $local );
160 4
	}
161
162
	/**
163
	 * Check if a view exists.
164
	 *
165
	 * @param  string  $view
166
	 * @return boolean
167
	 */
168 1
	public function exists( $view ) {
169 1
		return $this->engine->exists( $view );
170
	}
171
172
	/**
173
	 * Return a canonical string representation of the view name.
174
	 *
175
	 * @param  string $view
176
	 * @return string
177
	 */
178 1
	public function canonical( $view ) {
179 1
		return $this->engine->canonical( $view );
180
	}
181
182
	/**
183
	 * Create a view instance from the first view name that exists.
184
	 *
185
	 * @param  string|string[] $views
186
	 * @return ViewInterface
187
	 */
188 1
	public function make( $views ) {
189 1
		return $this->engine->make( MixedType::toArray( $views ) );
190
	}
191
192
	/**
193
	 * Trigger core hooks for a partial, if any.
194
	 *
195
	 * @codeCoverageIgnore
196
	 * @param  string $name
197
	 * @return void
198
	 */
199
	public function triggerPartialHooks( $name ) {
200
		if ( ! function_exists( 'apply_filters' ) ) {
201
			// We are not in a WordPress environment - skip triggering hooks.
202
			return;
203
		}
204
205
		$core_partial = '/^(header|sidebar|footer)(?:-(.*?))?(\.|$)/i';
206
		$matches = [];
207
		$is_partial = preg_match( $core_partial, $name, $matches );
208
209
		if ( $is_partial && apply_filters( "wpemerge.partials.{$matches[1]}.hook", true ) ) {
210
			do_action( "get_{$matches[1]}", $matches[2] );
211
		}
212
	}
213
214
	/**
215
	 * Render a view.
216
	 *
217
	 * @codeCoverageIgnore
218
	 * @param  string|string[]      $views
219
	 * @param  array<string, mixed> $context
220
	 * @return void
221
	 */
222
	public function render( $views, $context = [] ) {
223
		$view = $this->make( $views )->with( $context );
224
		$this->triggerPartialHooks( $view->getName() );
225
		echo $view->toString();
226
	}
227
}
228