Completed
Push — master ( a6a775...c4c1ad )
by Cees-Jan
13s
created

TwigView::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php declare(strict_types=1);
2
/**
3
 * This file is part of TwigView.
4
 *
5
 ** (c) 2014 Cees-Jan Kiewiet
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace WyriHaximus\TwigView\View;
12
13
use Cake\Core\Configure;
14
use Cake\Event\EventManager;
15
use Cake\Network\Request;
16
use Cake\Network\Response;
17
use Cake\View\View;
18
use Exception;
19
use Twig\Environment;
20
use WyriHaximus\TwigView\Event\ConstructEvent;
21
use WyriHaximus\TwigView\Event\EnvironmentConfigEvent;
22
use WyriHaximus\TwigView\Event\LoaderEvent;
23
use WyriHaximus\TwigView\Lib\Twig\Loader;
24
25
/**
26
 * Class TwigView.
27
 * @package WyriHaximus\TwigView\View
28
 */
29
class TwigView extends View
30
{
31
    const EXT = '.twig';
32
33
    const ENV_CONFIG = 'WyriHaximus.TwigView.environment';
34
35
    /**
36
     * Extension to use.
37
     *
38
     * @var string
39
     */
40
    protected $_ext = self::EXT;
41
42
    /**
43
     * @var array
44
     */
45
    protected $extensions = [
46
        self::EXT,
47
        '.tpl',
48
        '.ctp',
49
    ];
50
51
    /**
52
     * Twig instance.
53
     *
54
     * @var \Twig\Environment
55
     */
56
    protected $twig;
57
58
    /**
59
     * Helpers.
60
     *
61
     * @var array
62
     */
63
    protected $helperList = [];
64
65
    /**
66
     * Event manager.
67
     *
68
     * @var EventManager
69
     */
70
    protected $eventManager;
71
72
    /**
73
     * Constructor.
74
     *
75
     * @param Request      $request      Request.
76
     * @param Response     $response     Response.
77
     * @param EventManager $eventManager EventManager.
78
     * @param array        $viewOptions  View options.
79
     */
80 9
    public function __construct(
81
        Request $request = null,
82
        Response $response = null,
83
        EventManager $eventManager = null,
84
        array $viewOptions = []
85
    ) {
86 9
        if ($eventManager === null) {
87 8
            $eventManager = EventManager::instance();
88
        }
89 9
        $this->eventManager = $eventManager;
90
91 9
        $this->twig = new Environment($this->getLoader(), $this->resolveConfig());
92
93 9
        $this->eventManager->dispatch(ConstructEvent::create($this, $this->twig));
94
95 9
        parent::__construct($request, $response, $eventManager, $viewOptions);
96 9
        $this->_ext = self::EXT;
97
98 9
        $this->generateHelperList();
99 9
    }
100
101
    /**
102
     * @param string $extension
103
     */
104
    public function unshiftExtension($extension)
105
    {
106
        array_unshift($this->extensions, $extension);
107
    }
108
109
    /**
110
     * Get twig environment instance.
111
     *
112
     * @return \Twig\Environment
113
     */
114 3
    public function getTwig(): Environment
115
    {
116 3
        return $this->twig;
117
    }
118
119
    /**
120
     * @return array
121
     */
122 9
    protected function resolveConfig(): array
123
    {
124 9
        $charset = 'utf-8';
125 9
        if (Configure::read('App.encoding') !== null) {
126
            $charset = strtolower(Configure::read('App.encoding'));
127
        }
128 9
        $debugFlag = false;
129 9
        if (Configure::read('App.encoding') === true) {
130
            $debugFlag = true;
131
        }
132
        $config = [
133 9
            'cache' => CACHE . 'twigView' . DS,
134 9
            'charset' => $charset,
135 9
            'auto_reload' => $debugFlag,
136 9
            'debug' => $debugFlag,
137
        ];
138
139 9
        $config = array_replace($config, $this->readConfig());
140
141 9
        $configEvent = EnvironmentConfigEvent::create($config);
142 9
        $this->eventManager->dispatch($configEvent);
143
144 9
        return $configEvent->getConfig();
145
    }
146
147
    /**
148
     * @return array
149
     */
150 9
    protected function readConfig(): array
151
    {
152 9
        if (!Configure::check(static::ENV_CONFIG)) {
153 8
            return [];
154
        }
155
156 1
        $config = Configure::read(static::ENV_CONFIG);
157 1
        if (!is_array($config)) {
158
            return [];
159
        }
160
161 1
        return $config;
162
    }
163
164
    /**
165
     * Create the template loader.
166
     *
167
     * @return \WyriHaximus\TwigView\Lib\Twig\Loader
168
     */
169 9
    protected function getLoader(): Loader
170
    {
171 9
        $event = LoaderEvent::create(new Loader());
172 9
        $this->eventManager->dispatch($event);
173
174 9
        return $event->getResultLoader();
175
    }
176
177
    /**
178
     * Create a useful helper list.
179
     *
180
     */
181 9
    protected function generateHelperList()
182
    {
183 9
        $registry = $this->helpers();
184
185 9
        $helpersList = array_merge($this->helpers, $registry->loaded());
186 9
        $helpers = $registry->normalizeArray($helpersList);
187 9
        foreach ($helpers as $properties) {
188 3
            list(, $class) = pluginSplit($properties['class']);
189 3
            $this->helperList[$class] = $this->{$class};
190
        }
191 9
    }
192
193
    /**
194
     * Render the template.
195
     *
196
     * @param string $viewFile Template file.
197
     * @param array  $data     Data that can be used by the template.
198
     *
199
     * @throws \Exception
200
     * @return string
201
     */
202 4
    protected function _render($viewFile, $data = []): string
203
    {
204 4
        if (empty($data)) {
205 4
            $data = $this->viewVars;
206
        }
207
208 4
        if (substr($viewFile, -3) === 'ctp') {
209 1
            $out = parent::_render($viewFile, $data);
210
        } else {
211 3
            $data = array_merge(
212 3
                $data,
213 3
                $this->helperList,
214
                [
215 3
                    '_view' => $this,
216
                ]
217
            );
218
219
            try {
220 3
                $out = $this->getTwig()->loadTemplate($viewFile)->render($data);
221 2
            } catch (Exception $e) {
222 2
                $previous = $e->getPrevious();
223
224 2
                if ($previous !== null && $previous instanceof Exception) {
225 1
                    throw $previous;
226
                } else {
227 1
                    throw $e;
228
                }
229
            }
230
        }
231
232 2
        return $out;
233
    }
234
235
    /**
236
     * @param  string|null $name
237
     * @throws \Exception
238
     * @return string
239
     */
240 2 View Code Duplication
    protected function _getViewFileName($name = null): string
1 ignored issue
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...
241
    {
242 2
        $rethrow = new Exception('You\'re not supposed to get here');
243 2
        foreach ($this->extensions as $extension) {
244 2
            $this->_ext = $extension;
245
            try {
246 2
                return parent::_getViewFileName($name);
247
            } catch (Exception $exception) {
248
                $rethrow = $exception;
249
            }
250
        }
251
252
        throw $rethrow;
253
    }
254
255
    /**
256
     * @param  string|null $name
257
     * @throws \Exception
258
     * @return string
259
     */
260 View Code Duplication
    protected function _getLayoutFileName($name = null): string
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...
261
    {
262
        $rethrow = new Exception('You\'re not supposed to get here');
263
        foreach ($this->extensions as $extension) {
264
            $this->_ext = $extension;
265
            try {
266
                return parent::_getLayoutFileName($name);
267
            } catch (Exception $exception) {
268
                $rethrow = $exception;
269
            }
270
        }
271
272
        throw $rethrow;
273
    }
274
275
    /**
276
     * @param  string      $name
277
     * @param  bool        $pluginCheck
278
     * @return string|bool
279
     */
280
    protected function _getElementFileName($name, $pluginCheck = true)
281
    {
282
        foreach ($this->extensions as $extension) {
283
            $this->_ext = $extension;
284
            $result = parent::_getElementFileName($name, $pluginCheck);
285
            if ($result !== false) {
286
                return $result;
287
            }
288
        }
289
290
        return false;
291
    }
292
293
    /**
294
     * Return empty string when View instance is cast to string.
295
     *
296
     * @return string
297
     */
298
    public function __toString(): string
299
    {
300
        return '';
301
    }
302
}
303