Completed
Push — master ( 5c43e0...f4b826 )
by Chris
02:37
created

Resolver::exists()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
namespace Darya\View;
3
4
/**
5
 * Finds and instantiates views of the given implementation using the given base
6
 * paths and file extensions.
7
 * 
8
 * Optionally shares variables and configurations with all templates that are
9
 * resolved.
10
 * 
11
 * @author Chris Andrew <[email protected]>
12
 */
13
class Resolver {
14
	
15
	/**
16
	 * @var string View implementor to resolve
17
	 */
18
	protected $engine;
19
	
20
	/**
21
	 * @var array Paths to search for templates within
22
	 */
23
	protected $basePaths = array();
24
	
25
	/**
26
	 * @var array Template file extensions to search for
27
	 */
28
	protected $extensions = array();
29
	
30
	/**
31
	 * @var array Extra directories to search within
32
	 */
33
	protected $directories = array('views');
34
	
35
	/**
36
	 * @var array Variables to assign to all views that are resolved
37
	 */
38
	protected $shared = array();
39
	
40
	/**
41
	 * @var array Config variables to set for all views that are resolved
42
	 */
43
	protected $config = array();
44
	
45
	/**
46
	 * Normalise the given path.
47
	 * 
48
	 * @param string $path
49
	 * @return path
50
	 */
51
	public static function normalise($path) {
52
		return preg_replace('~[\\\|/]+~', '/', rtrim($path, '\/'));
53
	}
54
	
55
	/**
56
	 * Create a new view resolver.
57
	 * 
58
	 * @param string $engine View implementor to resolve
59
	 * @param string|array [optional] $path Single path or set of paths
60
	 * @param string|array [optional] $extensions Template file extensions
61
	 */
62
	public function __construct($engine, $basePath = null, $extensions = array()) {
63
		$this->setEngine($engine);
64
		
65
		if ($basePath) {
66
			$this->registerBasePaths($basePath);
67
		}
68
		
69
		if (!empty($extensions)) {
70
			$this->registerExtensions($extensions);
71
		}
72
	}
73
	
74
	/**
75
	 * Set the engine (View implementor) to resolve.
76
	 * 
77
	 * @param string $engine
78
	 */
79
	public function setEngine($engine) {
80
		if (!class_exists($engine) || !is_subclass_of($engine, 'Darya\View\View')) {
81
			throw new \Exception("View engine $engine does not exist or does not extend Darya\View\View");
82
		}
83
		
84
		$this->engine = $engine;
85
	}
86
	
87
	/**
88
	 * Register a base path or set of base paths to resolve views from.
89
	 * 
90
	 * @param string|array $path Single path or set of paths
91
	 */
92
	public function registerBasePaths($path) {
93
		if (is_array($path)) {
94
			$this->basePaths = array_merge($this->basePaths, $path);
95
		} else {
96
			$this->basePaths[] = $path;
97
		}
98
	}
99
	
100
	/**
101
	 * Register file extensions to consider when resolving template files.
102
	 * 
103
	 * @param string|array $extensions
104
	 */
105
	public function registerExtensions($extensions) {
106
		foreach ((array) $extensions as $extension) {
107
			$this->extensions[] = '.' . ltrim($extension, '.');
108
		}
109
	}
110
	
111
	/**
112
	 * Register extra directory names to search within when resolving template
113
	 * files.
114
	 * 
115
	 * 'views' is registered by default.
116
	 * 
117
	 * @param string|array $directories
118
	 */
119
	public function registerDirectories($directories) {
120
		$directories = (array) $directories;
121
		
122
		foreach ($directories as $key => $directory) {
123
			$directories[$key] = ltrim($directory, '\/');
124
		}
125
		
126
		$this->directories = array_merge($this->directories, $directories);
127
	}
128
	
129
	/**
130
	 * Set variables to assign to all resolved views.
131
	 * 
132
	 * @param array $vars
133
	 */
134
	public function share(array $vars = array()) {
135
		$this->shared = array_merge($this->shared, $vars);
136
	}
137
	
138
	/**
139
	 * Set config variables to set for all resolved views.
140
	 * 
141
	 * @param array $config
142
	 */
143
	public function shareConfig(array $config = array()) {
144
		$this->config = array_merge($this->config, $config);
145
	}
146
	
147
	/**
148
	 * Generate file paths to attempt when resolving template files.
149
	 * 
150
	 * @param string $path
151
	 * @return array
152
	 */
153
	public function generate($path) {
154
		$dirname = dirname($path);
155
		$dir = $dirname != '.' ? $dirname : '';
156
		$file = basename($path);
157
		$paths = array();
158
		
159
		foreach ($this->basePaths as $basePath) {
160
			foreach ($this->extensions as $extension) {
161
				$paths[] = "$basePath/$path$extension";
162
				
163
				foreach ($this->directories as $directory) {
164
					$paths[] = "$basePath/$dir/$directory/$file$extension";
165
				}
166
			}
167
		}
168
		
169
		return $paths;
170
	}
171
	
172
	/**
173
	 * Find a template file using the given path.
174
	 * 
175
	 * @param string $path
176
	 * @return string
177
	 */
178
	public function resolve($path) {
179
		$path = static::normalise($path);
180
		
181
		if (is_file($path)) {
182
			return $path;
183
		}
184
		
185
		$filePaths = $this->generate($path);
186
		
187
		foreach ($filePaths as $filePath) {
188
			if (is_file($filePath)) {
189
				return $filePath;
190
			}
191
		}
192
	}
193
	
194
	/**
195
	 * Determine whether a template exists at the given path.
196
	 * 
197
	 * @param string $path
198
	 * @return bool
199
	 */
200
	public function exists($path) {
201
		return $this->resolve($path) !== null;
202
	}
203
	
204
	/**
205
	 * Resolve a view instance with a template at the given path, as well as
206
	 * shared variables and config.
207
	 * 
208
	 * @param string $path [optional] Template path
209
	 * @param array  $vars [optional] Variables to assign to the View
210
	 * @return View
211
	 */
212
	public function create($path = null, $vars = array()) {
213
		$file = $this->resolve($path);
214
		
215
		$engine = $this->engine;
216
		$engine = new $engine($file, array_merge($this->shared, $vars), $this->config);
217
		$engine->setResolver($this);
218
		
219
		return $engine;
220
	}
221
	
222
}