Passed
Branch facadeless (50a555)
by Atanas
02:42
created

ViewService::getComposersForView()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 12
ccs 7
cts 7
cp 1
rs 10
cc 3
nc 3
nop 1
crap 3
1
<?php
2
/**
3
 * @package   WPEmerge
4
 * @author    Atanas Angelov <[email protected]>
5
 * @copyright 2018 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
	 * View engine.
23
	 *
24
	 * @var ViewEngineInterface
25
	 */
26
	protected $engine = null;
27
28
	/**
29
	 * Handler factory.
30
	 *
31
	 * @var HandlerFactory
32
	 */
33
	protected $handler_factory = null;
34
35
	/**
36
	 * Global variables.
37
	 *
38
	 * @var array
39
	 */
40
	protected $globals = [];
41
42
	/**
43
	 * View composers.
44
	 *
45
	 * @var array
46
	 */
47
	protected $composers = [];
48
49
	/**
50
	 * Constructor.
51
	 *
52
	 * @codeCoverageIgnore
53
	 * @param ViewEngineInterface $engine
54
	 * @param HandlerFactory $handler_factory
55
	 */
56
	public function __construct( ViewEngineInterface $engine, HandlerFactory $handler_factory ) {
57
		$this->engine = $engine;
58
		$this->handler_factory = $handler_factory;
59
	}
60
61
	/**
62
	 * Get global variables.
63
	 *
64
	 * @return array
65
	 */
66 2
	public function getGlobals() {
67 2
		return $this->globals;
68
	}
69
70
	/**
71
	 * Set a global variable.
72
	 *
73
	 * @param  string $key
74
	 * @param  mixed  $value
75
	 * @return void
76
	 */
77 1
	public function addGlobal( $key, $value ) {
78 1
		$this->globals[ $key ] = $value;
79 1
	}
80
81
	/**
82
	 * Set an array of global variables.
83
	 *
84
	 * @param  array $globals
85
	 * @return void
86
	 */
87 1
	public function addGlobals( $globals ) {
88 1
		foreach ( $globals as $key => $value ) {
89 1
			$this->addGlobal( $key, $value );
90
		}
91 1
	}
92
93
	/**
94
	 * Get view composer.
95
	 *
96
	 * @param  string         $view
97
	 * @return array<Handler>
98
	 */
99 1
	public function getComposersForView( $view ) {
100 1
		$view = $this->engine->canonical( $view );
101
102 1
		$composers = [];
103
104 1
		foreach ( $this->composers as $composer ) {
105 1
			if ( in_array( $view, $composer['views'], true ) ) {
106 1
				$composers[] = $composer['composer'];
107
			}
108
		}
109
110 1
		return $composers;
111
	}
112
113
	/**
114
	 * Add view composer.
115
	 *
116
	 * @param  string|array<string> $views
117
	 * @param  string|Closure       $composer
118
	 * @return void
119
	 */
120
	public function addComposer( $views, $composer ) {
121 1
		$views = array_map( function ( $view ) {
122 1
			return $this->engine->canonical( $view );
123 1
		}, MixedType::toArray( $views ) );
124
125 1
		$handler = $this->handler_factory->make( $composer, 'compose', '\\App\\ViewComposers\\' );
126
127 1
		$this->composers[] = [
128 1
			'views' => $views,
129 1
			'composer' => $handler,
130
		];
131 1
	}
132
133
	/**
134
	 * Composes a view instance with contexts in the following order: Global, Composers, Local.
135
	 *
136
	 * @param  ViewInterface $view
137
	 * @return void
138
	 */
139 4
	public function compose( ViewInterface $view ) {
140 4
		$global = ['global' => $this->getGlobals()];
141 4
		$local = $view->getContext();
142
143 4
		$view->with( $global );
144
145 4
		$composers = $this->getComposersForView( $view->getName() );
146 4
		foreach ( $composers as $composer ) {
147 3
			$composer->execute( $view );
148
		}
149
150 4
		$view->with( $local );
151 4
	}
152
153
	/**
154
	 * Create a view instance.
155
	 *
156
	 * @param  string|array<string> $views
157
	 * @return ViewInterface
158
	 */
159 1
	public function make( $views ) {
160 1
		return $this->engine->make( MixedType::toArray( $views ) );
161
	}
162
163
	/**
164
	 * Trigger core hooks for a partial, if any.
165
	 *
166
	 * @codeCoverageIgnore
167
	 * @param  string $name
168
	 * @return void
169
	 */
170
	public function triggerPartialHooks( $name ) {
171
		$core_partial = '/^(header|sidebar|footer)(?:-(.*?))?(\.|$)/i';
172
		if ( preg_match( $core_partial, $name, $matches ) && apply_filters( "wpemerge.partials.{$matches[1]}.hook", true ) ) {
173
			do_action( "get_{$matches[1]}", $matches[2] );
174
		}
175
	}
176
177
	/**
178
	 * Render a view.
179
	 *
180
	 * @codeCoverageIgnore
181
	 * @param  string|array<string> $views
182
	 * @param  array<string, mixed> $context
183
	 * @return void
184
	 */
185
	public function render( $views, $context = [] ) {
186
		$view = $this->make( $views )->with( $context );
187
		$this->triggerPartialHooks( $view->getName() );
188
		echo $view->toString();
189
	}
190
}
191