Completed
Push — master ( f339fb...41f35e )
by Filipe
08:39
created

Template::initialize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4285
cc 1
eloc 5
nc 1
nop 0
crap 1
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\Common\Base;
13
use ReflectionClass;
14
15
/**
16
 * Template factory class
17
 *
18
 * @package Slick\Template
19
 * @author  Filipe Silva <[email protected]>
20
 *
21
 * @property array $extensions
22
 * @property string $engine
23
 */
24
final class Template extends Base
25
{
26
27
    /** Known engines */
28
    const ENGINE_TWIG = 'Slick\Template\Engine\Twig';
29
30
    /** Known engine extensions */
31
    const EXTENSION_TWIG_TEXT = 'Slick\Template\Extension\Text';
32
    const EXTENSION_TWIG_I18N = 'Slick\Template\Extension\I18n';
33
34
    /** @var string Engine interface */
35
    private static $interface = 'Slick\Template\TemplateEngineInterface';
36
    private static $extensionInterface =
37
        'Slick\Template\EngineExtensionInterface';
38
39
    /**
40
     * @readwrite
41
     * @var string The engine to use
42
     */
43
    protected $engine = self::ENGINE_TWIG;
44
45
    /**
46
     * @readwrite
47
     * @var array Options for template initializing
48
     */
49
    protected $options = array();
50
51
    /**
52
     * @var string[] a list of available paths
53
     */
54
    protected static $paths = ['./'];
55
56
    /**
57
     * @readwrite
58
     * @var array Array containing template extensions
59
     */
60
    protected $extensions = [
61
        self::EXTENSION_TWIG_TEXT => null,
62
        self::EXTENSION_TWIG_I18N => null,
63
    ];
64
65
    /**
66
     * Prepends a searchable path to available paths list.
67
     *
68
     * @param string $path
69
     */
70 2 View Code Duplication
    public static function addPath($path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
71
    {
72 2
        $path = str_replace('//', '/', rtrim($path, '/'));
73 2
        if (is_dir($path) && !in_array($path, self::$paths)) {
74 2
            array_unshift(self::$paths, $path);
75 2
        }
76 2
    }
77
78
    /**
79
     * Prepends a searchable path to available paths list.
80
     *
81
     * @param string $path
82
     */
83 2 View Code Duplication
    public static function appendPath($path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
84
    {
85 2
        $path = str_replace('//', '/', rtrim($path, '/'));
86 2
        if (is_dir($path) && !in_array($path, self::$paths)) {
87 2
            array_push(self::$paths, $path);
88 2
        }
89 2
    }
90
91
    /**
92
     * Gets the list of defined paths
93
     *
94
     * @return \string[]
95
     */
96 4
    public static function getPaths()
97
    {
98 4
        return self::$paths;
99
    }
100
101
    /**
102
     * Initializes the engine
103
     *
104
     * @throws Exception\InvalidArgumentException
105
     *
106
     * @return TemplateEngineInterface
107
     */
108 4
    public function initialize()
109
    {
110 4
        $this->checkClass();
111
        /** @var TemplateEngineInterface $engine */
112 2
        $engine = new $this->engine($this->options);
113 2
        $engine->setLocations(self::$paths);
114 2
        return $this->applyExtensions($engine);
115
    }
116
117
    /**
118
     * Adds an extension to the template engine
119
     *
120
     * @param string|object $className The class name or an instance
121
     *                                 of EngineExtensionInterface interface
122
     *
123
     * @return self|$this|Template
124
     */
125 4
    public function addExtension($className)
126
    {
127 4
        $object = is_object($className) ? $className : null;
128 4
        $className = is_object($className) ? get_class($object) : $className;
129
130 4
        $this->checkClass($className, self::$extensionInterface);
131
132 2
        $this->extensions[$className] = $object;
133 2
        return $this;
134
135
    }
136
137
    /**
138
     * Apply defined extensions to the provided template engine
139
     *
140
     * @param TemplateEngineInterface $engine
141
     *
142
     * @return TemplateEngineInterface
143
     */
144 2
    protected function applyExtensions(TemplateEngineInterface $engine)
145
    {
146 2
        foreach ($this->extensions as $className => $extension) {
147 2
            $ext = $this->getExtension($className, $extension);
148 2
            if ($ext->appliesTo($engine)) {
149 2
                $ext->update($engine);
150 2
            }
151 2
        }
152 2
        return $engine;
153
    }
154
155
    /**
156
     * @param string $class
157
     * @param EngineExtensionInterface $extension
158
     *
159
     * @return EngineExtensionInterface
160
     */
161 2
    protected function getExtension($class, $extension)
162
    {
163 2
        if (is_object($extension)) {
164 2
            return $extension;
165
        }
166
167 2
        $this->checkClass($class, self::$extensionInterface);
168 2
        return new $class();
169
    }
170
171
    /**
172
     * Check if type is a valid configuration driver
173
     *
174
     * @param null $name
175
     * @param null $interface
176
     */
177 8
    protected function checkClass($name = null, $interface = null)
178
    {
179 8
        $name = null == $name ? $this->engine : $name;
180 8
        $interface = null == $interface ? self::$interface : $interface;
181
182 8
        if (!class_exists($name)) {
183 2
            throw new Exception\InvalidArgumentException(
184 2
                "The class '{$name}' was not found"
185 2
            );
186
        }
187
188 6
        $reflection = new ReflectionClass($name);
189 6
        if (!$reflection->implementsInterface($interface)) {
190 2
            throw new Exception\InvalidArgumentException(
191 2
                "Class '{$name}' does not implement {$interface}"
192 2
            );
193
        }
194 4
    }
195
}
196