PhpViewEngine   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 5
Bugs 0 Features 1
Metric Value
wmc 16
eloc 43
dl 0
loc 172
ccs 34
cts 34
cp 1
rs 10
c 5
b 0
f 1

10 Methods

Rating   Name   Duplication   Size   Complexity  
A renderView() 0 7 1
A getLayoutContent() 0 12 2
A canonical() 0 2 1
A popLayoutContent() 0 2 1
A exists() 0 2 1
A pushLayoutContent() 0 2 1
A __construct() 0 3 1
A getViewLayout() 0 17 3
A makeView() 0 12 2
A make() 0 9 3
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
/**
13
 * Render view files with php.
14
 */
15
class PhpViewEngine implements ViewEngineInterface {
16
	/**
17
	 * Name of view file header based on which to resolve layouts.
18
	 *
19
	 * @var string
20
	 */
21
	protected $layout_file_header = 'Layout';
22
23
	/**
24
	 * View compose action.
25
	 *
26
	 * @var callable
27
	 */
28
	protected $compose = null;
29
30
	/**
31
	 * View finder.
32
	 *
33
	 * @var PhpViewFilesystemFinder
34
	 */
35
	protected $finder = null;
36
37
	/**
38
	 * Stack of views ready to be rendered.
39
	 *
40
	 * @var PhpView[]
41
	 */
42
	protected $layout_content_stack = [];
43
44
	/**
45
	 * Constructor.
46
	 *
47
	 * @codeCoverageIgnore
48
	 * @param callable                $compose
49
	 * @param PhpViewFilesystemFinder $finder
50
	 */
51
	public function __construct( callable $compose, PhpViewFilesystemFinder $finder ) {
52
		$this->compose = $compose;
53
		$this->finder = $finder;
54
	}
55
56
	/**
57
	 * {@inheritDoc}
58
	 */
59 1
	public function exists( $view ) {
60 1
		return $this->finder->exists( $view );
61
	}
62
63
	/**
64
	 * {@inheritDoc}
65
	 */
66 1
	public function canonical( $view ) {
67 1
		return $this->finder->canonical( $view );
68
	}
69
70
	/**
71
	 * {@inheritDoc}
72
	 * @throws ViewNotFoundException
73
	 */
74 2
	public function make( $views ) {
75 2
		foreach ( $views as $view ) {
76 2
			if ( $this->exists( $view ) ) {
77 1
				$filepath = $this->finder->resolveFilepath( $view );
78 1
				return $this->makeView( $view, $filepath );
79
			}
80
		}
81
82 1
		throw new ViewNotFoundException( 'View not found for "' . implode( ', ', $views ) . '"' );
83
	}
84
85
	/**
86
	 * Create a view instance.
87
	 *
88
	 * @param  string $name
89
	 * @param  string $filepath
90
	 * @return ViewInterface
91
	 * @throws ViewNotFoundException
92
	 */
93 2
	protected function makeView( $name, $filepath ) {
94 2
		$view = (new PhpView( $this ))
95 2
			->setName( $name )
96 2
			->setFilepath( $filepath );
97
98 2
		$layout = $this->getViewLayout( $view );
99
100 2
		if ( $layout !== null ) {
101 1
			$view->setLayout( $layout );
102
		}
103
104 2
		return $view;
105
	}
106
107
	/**
108
	 * Create a view instance for the given view's layout header, if any.
109
	 *
110
	 * @param  PhpView $view
111
	 * @return ViewInterface|null
112
	 * @throws ViewNotFoundException
113
	 */
114 2
	protected function getViewLayout( PhpView $view ) {
115 2
		$layout_headers = array_filter( get_file_data(
116 2
			$view->getFilepath(),
117 2
			[$this->layout_file_header]
118
		) );
119
120 2
		if ( empty( $layout_headers ) ) {
121 1
			return null;
122
		}
123
124 2
		$layout_file = trim( $layout_headers[0] );
125
126 2
		if ( ! $this->exists( $layout_file ) ) {
127 1
			throw new ViewNotFoundException( 'View layout not found for "' . $layout_file . '"' );
128
		}
129
130 1
		return $this->makeView( $this->canonical( $layout_file ), $this->finder->resolveFilepath( $layout_file ) );
131
	}
132
133
	/**
134
	 * Render a view.
135
	 *
136
	 * @param  PhpView $__view
137
	 * @return string
138
	 */
139 1
	protected function renderView( PhpView $__view ) {
140 1
		$__context = $__view->getContext();
141 1
		ob_start();
142 1
		extract( $__context, EXTR_OVERWRITE );
143
		/** @noinspection PhpIncludeInspection */
144 1
		include $__view->getFilepath();
145 1
		return ob_get_clean();
146
	}
147
148
	/**
149
	 * Push layout content to the top of the stack.
150
	 *
151
	 * @codeCoverageIgnore
152
	 * @param PhpView $view
153
	 * @return void
154
	 */
155
	public function pushLayoutContent( PhpView $view ) {
156
		$this->layout_content_stack[] = $view;
157
	}
158
159
	/**
160
	 * Pop the top-most layout content from the stack.
161
	 *
162
	 * @codeCoverageIgnore
163
	 * @return PhpView|null
164
	 */
165
	public function popLayoutContent() {
166
		return array_pop( $this->layout_content_stack );
167
	}
168
169
	/**
170
	 * Pop the top-most layout content from the stack, render and return it.
171
	 *
172
	 * @codeCoverageIgnore
173
	 * @return string
174
	 */
175
	public function getLayoutContent() {
176
		$view = $this->popLayoutContent();
177
178
		if ( ! $view ) {
179
			return '';
180
		}
181
182
		$clone = clone $view;
183
184
		call_user_func( $this->compose, $clone );
185
186
		return $this->renderView( $clone );
187
	}
188
}
189