1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of slick/template package |
5
|
|
|
* |
6
|
|
|
* For the full copyright and license information, please view the LICENSE |
7
|
|
|
* file that was distributed with this source code. |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace Slick\Template; |
11
|
|
|
|
12
|
|
|
use Slick\Template\Engine\Twig; |
13
|
|
|
use Slick\Template\Exception\InvalidArgumentException; |
14
|
|
|
use Slick\Template\Extension\Text; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Template |
18
|
|
|
* |
19
|
|
|
* @package Slick\Template |
20
|
|
|
*/ |
21
|
|
|
class Template |
22
|
|
|
{ |
23
|
|
|
|
24
|
|
|
/** Known engines */ |
25
|
|
|
const ENGINE_TWIG = Twig::class; |
26
|
|
|
|
27
|
|
|
/** Known engine extensions */ |
28
|
|
|
const EXTENSION_TWIG_TEXT = Text::class; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @var array |
32
|
|
|
*/ |
33
|
|
|
private $defaultOptions = []; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var array |
37
|
|
|
*/ |
38
|
|
|
private $options; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @var string |
42
|
|
|
*/ |
43
|
|
|
private $engine; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @var string[] a list of available paths |
47
|
|
|
*/ |
48
|
|
|
private static $paths = ['./']; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @var array Array containing template extensions |
52
|
|
|
*/ |
53
|
|
|
private static $extensions = [ |
54
|
|
|
self::EXTENSION_TWIG_TEXT => null, |
55
|
|
|
]; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Creates a template factory |
59
|
|
|
* |
60
|
|
|
* @param array $options |
61
|
|
|
*/ |
62
|
|
|
public function __construct(array $options = []) |
63
|
|
|
{ |
64
|
|
|
$this->engine = array_key_exists('engine', $options) |
65
|
|
|
? $this->checkEngine($options['engine']) |
66
|
|
|
: self::ENGINE_TWIG; |
67
|
|
|
|
68
|
|
|
$this->options = array_key_exists('options', $options) |
69
|
|
|
? array_merge($this->defaultOptions, $options['options']) |
70
|
|
|
: $this->defaultOptions; |
71
|
|
|
} |
72
|
|
|
|
73
|
2 |
|
/** |
74
|
|
|
* Prepends a searchable path to available paths list. |
75
|
2 |
|
* |
76
|
2 |
|
* @param string $path |
77
|
2 |
|
*/ |
78
|
1 |
View Code Duplication |
public static function addPath($path) |
|
|
|
|
79
|
2 |
|
{ |
80
|
|
|
$path = str_replace('//', '/', rtrim($path, '/')); |
81
|
|
|
if (is_dir($path) && !in_array($path, self::$paths)) { |
82
|
|
|
array_unshift(self::$paths, $path); |
83
|
|
|
} |
84
|
|
|
} |
85
|
|
|
|
86
|
2 |
|
/** |
87
|
|
|
* Appends a searchable path to available paths list. |
88
|
2 |
|
* |
89
|
2 |
|
* @param string $path |
90
|
2 |
|
*/ |
91
|
1 |
View Code Duplication |
public static function appendPath($path) |
|
|
|
|
92
|
2 |
|
{ |
93
|
|
|
$path = str_replace('//', '/', rtrim($path, '/')); |
94
|
|
|
if (is_dir($path) && !in_array($path, self::$paths)) { |
95
|
|
|
array_push(self::$paths, $path); |
96
|
|
|
} |
97
|
|
|
} |
98
|
|
|
|
99
|
4 |
|
/** |
100
|
|
|
* Adds an extension to the template engine |
101
|
4 |
|
* |
102
|
|
|
* @param string|object $className The class name or an instance |
103
|
|
|
* of EngineExtensionInterface interface |
104
|
|
|
* |
105
|
|
|
* @return self|$this|Template |
106
|
|
|
*/ |
107
|
|
|
public function addExtension($className) |
108
|
|
|
{ |
109
|
|
|
$object = is_object($className) ? $className : null; |
110
|
|
|
$className = is_object($className) ? get_class($object) : $className; |
111
|
4 |
|
|
112
|
|
|
$this->checkExtension($className); |
113
|
4 |
|
|
114
|
2 |
|
self::$extensions[$className] = $object; |
115
|
|
|
return $this; |
116
|
2 |
|
} |
117
|
2 |
|
|
118
|
2 |
|
/** |
119
|
|
|
* Initializes the engine |
120
|
|
|
* |
121
|
|
|
* @return TemplateEngineInterface |
122
|
|
|
*/ |
123
|
|
|
public function initialize() |
124
|
|
|
{ |
125
|
|
|
/** @var TemplateEngineInterface $engine */ |
126
|
|
|
$engine = new $this->engine($this->options); |
127
|
|
|
$engine->setLocations(self::$paths); |
128
|
|
|
$this->applyExtensions($engine); |
129
|
6 |
|
return $engine; |
130
|
|
|
} |
131
|
6 |
|
|
132
|
6 |
|
/** |
133
|
|
|
* Checks if provided class implements the TemplateEngineInterface |
134
|
6 |
|
* |
135
|
|
|
* @param string $engine |
136
|
4 |
|
* |
137
|
4 |
|
* @return string |
138
|
|
|
*/ |
139
|
|
|
private function checkEngine($engine) |
140
|
|
|
{ |
141
|
|
|
if (! is_subclass_of($engine, TemplateEngineInterface::class)) { |
142
|
|
|
$name = TemplateEngineInterface::class; |
143
|
|
|
throw new InvalidArgumentException( |
144
|
|
|
"Class '{$engine}' does not implement '{$name}'." |
145
|
|
|
); |
146
|
|
|
} |
147
|
|
|
return $engine; |
148
|
2 |
|
} |
149
|
|
|
|
150
|
2 |
|
/** |
151
|
2 |
|
* Apply defined extensions to the provided template engine |
152
|
|
|
* |
153
|
|
|
* @param TemplateEngineInterface $engine |
154
|
|
|
* |
155
|
|
|
* @return TemplateEngineInterface |
156
|
|
|
*/ |
157
|
|
|
private function applyExtensions(TemplateEngineInterface $engine) |
158
|
|
|
{ |
159
|
|
|
foreach (static::$extensions as $className => $extension) { |
|
|
|
|
160
|
|
|
$ext = $this->getExtension($className, $extension); |
161
|
2 |
|
if ($ext->appliesTo($engine)) { |
162
|
|
|
$ext->update($engine); |
163
|
2 |
|
} |
164
|
2 |
|
} |
165
|
2 |
|
return $engine; |
166
|
2 |
|
} |
167
|
1 |
|
|
168
|
1 |
|
/** |
169
|
2 |
|
* Creates the extension |
170
|
|
|
* |
171
|
|
|
* @param string $class |
172
|
|
|
* @param EngineExtensionInterface $extension |
173
|
|
|
* |
174
|
|
|
* @return EngineExtensionInterface |
175
|
|
|
*/ |
176
|
|
|
private function getExtension($class, $extension) |
177
|
|
|
{ |
178
|
2 |
|
if (is_object($extension)) { |
179
|
|
|
return $extension; |
180
|
2 |
|
} |
181
|
2 |
|
$this->checkExtension($class); |
182
|
|
|
return new $class(); |
183
|
|
|
} |
184
|
2 |
|
|
185
|
2 |
|
/** |
186
|
|
|
* Checks if provided class implements the EngineExtensionInterface |
187
|
|
|
* |
188
|
|
|
* @param string $class |
189
|
|
|
* |
190
|
|
|
* @return string |
191
|
|
|
*/ |
192
|
|
|
private function checkExtension($class) |
193
|
|
|
{ |
194
|
10 |
|
if (! is_subclass_of($class, EngineExtensionInterface::class)) { |
195
|
|
|
$name = TemplateEngineInterface::class; |
196
|
10 |
|
throw new InvalidArgumentException( |
197
|
10 |
|
"Engine extension '{$class}' does not implement '{$name}'." |
198
|
|
|
); |
199
|
10 |
|
} |
200
|
2 |
|
return $class; |
201
|
2 |
|
} |
202
|
|
|
} |
203
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.