AbstractView::__toString()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Darya\View;
3
4
/**
5
 * Darya's abstract view implementation.
6
 *
7
 * TODO: Remove resolvers and all static members.
8
 *
9
 * @author Chris Andrew <[email protected]>
10
 */
11
abstract class AbstractView implements View
12
{
13
	/**
14
	 * Optional shared base path for selecting template files.
15
	 *
16
	 * @var string
17
	 */
18
	protected static $basePath;
19
20
	/**
21
	 * Set of template file extensions compatible with this view.
22
	 *
23
	 * @var array
24
	 */
25
	protected static $extensions = [];
26
27
	/**
28
	 * Variables to assign to all templates.
29
	 *
30
	 * @var array
31
	 */
32
	protected static $shared = [];
33
34
	/**
35
	 * Shared resolver for selecting template files.
36
	 *
37
	 * @var Resolver
38
	 */
39
	protected static $sharedResolver;
40
41
	/**
42
	 * Instance resolver for selecting template files.
43
	 *
44
	 * @var Resolver
45
	 */
46
	protected $resolver;
47
48
	/**
49
	 * Variables for configuring the view.
50
	 *
51
	 * @var array
52
	 */
53
	protected $config = [];
54
55
	/**
56
	 * Path to the directory containing the view template.
57
	 *
58
	 * @var string
59
	 */
60
	protected $directory;
61
62
	/**
63
	 * Filename of the view template.
64
	 *
65
	 * @var string
66
	 */
67
	protected $file;
68
69
	/**
70
	 * Variables to assign to the template.
71
	 *
72
	 * @var array
73
	 */
74
	protected $arguments = [];
75
76
	/**
77
	 * Set a shared base path for selecting template files.
78
	 *
79
	 * @param string $path
80
	 */
81
	public static function setBasePath($path)
82
	{
83
		$path = realpath($path);
84
85
		if (is_dir($path)) {
86
			static::$basePath = $path;
87
		}
88
	}
89
90
	/**
91
	 * Sets a resolver for all views.
92
	 *
93
	 * @param Resolver $resolver
94
	 */
95
	public static function setSharedResolver(Resolver $resolver)
96
	{
97
		static::$sharedResolver = $resolver;
98
	}
99
100
	/**
101
	 * Register template file extensions.
102
	 *
103
	 * @param string|array $extensions
104
	 */
105
	public static function registerExtensions($extensions)
106
	{
107
		$extensions = array_map(function ($extension) {
108
			return '.' . ltrim(trim($extension), '.');
109
		}, (array) $extensions);
110
111
		static::$extensions = array_merge(static::$extensions, $extensions);
112
	}
113
114
	/**
115
	 * Create a new View.
116
	 *
117
	 * @param string $file      [optional] Path to the template file to use
118
	 * @param array  $arguments [optional] Arguments to assign to the template
119
	 * @param array  $config    [optional] Configuration variables for the view
120
	 */
121
	public function __construct($file = null, $arguments = [], $config = [])
122
	{
123
		$this->select($file, $arguments, $config);
124
	}
125
126
	/**
127
	 * Evaluate the template as a string by rendering it.
128
	 *
129
	 * @return string
130
	 */
131
	public function __toString()
132
	{
133
		return $this->render();
134
	}
135
136
	/**
137
	 * Sets a resolver for this view.
138
	 *
139
	 * @param Resolver $resolver
140
	 */
141
	public function setResolver(Resolver $resolver)
142
	{
143
		$this->resolver = $resolver;
144
	}
145
146
	/**
147
	 * Select a template and optionally assign arguments and configuration variables.
148
	 *
149
	 * @param string $file      The template file to be used
150
	 * @param array  $arguments [optional] Arguments to assign to the template immediately
151
	 * @param array  $config    [optional] Config arguments for the view
152
	 */
153
	public function select($file, array $arguments = [], array $config = [])
154
	{
155
		if (!empty($config)) {
156
			$this->config($config);
157
		}
158
159
		if (!empty($arguments)) {
160
			$this->assign($arguments);
161
		}
162
163
		if ($file) {
164
			$this->file($file);
165
		}
166
	}
167
168
	/**
169
	 * Attempt to load a template file at the given absolute path.
170
	 *
171
	 * @param string $path Absolute file path
172
	 * @return bool
173
	 */
174
	protected function attempt($path)
175
	{
176
		$path = realpath($path);
177
178
		if ($path && is_file($path)) {
179
			$dirname = dirname($path);
180
			$this->directory($dirname);
181
			$this->file = basename($path);
182
183
			return true;
184
		}
185
186
		return false;
187
	}
188
189
	/**
190
	 * Attempt to resolve the given view path to a file path using the view's
191
	 * resolver or that class's shared resolver.
192
	 *
193
	 * @param string $path
194
	 * @return string
195
	 */
196
	protected function resolve($path)
197
	{
198
		if ($this->resolver) {
199
			return $this->resolver->resolve($path);
200
		} else if (static::$sharedResolver) {
201
			return static::$sharedResolver->resolve($path);
202
		}
203
204
		return $path;
205
	}
206
207
	/**
208
	 * Find and set a template file using a given path. Attempts with the shared
209
	 * base path and extensions.
210
	 *
211
	 * @param string $path Path to template file
212
	 * @return bool
213
	 */
214
	public function file($path)
215
	{
216
		// First attempt the given path
217
		if ($this->attempt($path)) {
218
			return true;
219
		}
220
221
		// Otherwise, resolve the path and attempt it with the set extensions
222
		$paths = [];
223
224
		$paths[] = $this->resolve($path);
225
226
		$extensions = array_merge(static::$extensions, ['']);
227
228
		foreach ($extensions as $extension) {
229
			if (static::$basePath) {
230
				$paths[] = static::$basePath . "/$path$extension";
231
			}
232
233
			$paths[] = "$path$extension";
234
		}
235
236
		foreach ($paths as $p) {
237
			if ($this->attempt($p)) {
238
				return true;
239
			}
240
		}
241
242
		return false;
243
	}
244
245
	/**
246
	 * Get and optionally set the template's working directory.
247
	 *
248
	 * @param string $directory [optional] Working directory path
249
	 * @return string
250
	 */
251
	protected function directory($directory = null)
252
	{
253
		$this->directory = $directory !== '.' ? $directory : '';
254
255
		return $this->directory;
256
	}
257
258
	/**
259
	 * Get and optionally set view configuration variables.
260
	 *
261
	 * This merges given variables with any that have been previously set.
262
	 *
263
	 * @param array $config [optional]
264
	 * @return array
265
	 */
266
	public function config(array $config = [])
267
	{
268
		$this->config = array_merge($this->config, $config);
269
270
		return $this->config;
271
	}
272
273
	/**
274
	 * Assign an array of arguments to the template.
275
	 *
276
	 * @param array $arguments
277
	 */
278
	public function assign(array $arguments = [])
279
	{
280
		$this->arguments = array_merge($this->arguments, $arguments);
281
	}
282
283
	/**
284
	 * Get all arguments or a particular argument assigned to the template.
285
	 *
286
	 * @param string $key [optional] The key of the argument to return
287
	 * @return mixed The value of the $key argument if set, all arguments otherwise
288
	 */
289
	public function assigned($key = null)
290
	{
291
		return !is_null($key) && isset($this->arguments[$key]) ? $this->arguments[$key] : $this->arguments;
292
	}
293
294
	/**
295
	 * Assign an array of arguments to all templates.
296
	 *
297
	 * @param array $arguments
298
	 */
299
	public static function share(array $arguments)
300
	{
301
		static::$shared = array_merge(static::$shared, $arguments);
302
	}
303
304
	/**
305
	 * Get all arguments or a particular argument shared with all templates.
306
	 *
307
	 * @param string $key The key of the argument to return
308
	 * @return mixed The value of the $key argument if set, all arguments otherwise
309
	 */
310
	public static function shared($key = null)
311
	{
312
		return !is_null($key) && isset(static::$shared[$key]) ? static::$shared[$key] : static::$shared;
313
	}
314
}
315