Completed
Push — 4.x ( d4939e...747949 )
by
unknown
15s
created

TwigView::getLoader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
/**
4
 * This file is part of TwigView.
5
 *
6
 ** (c) 2014 Cees-Jan Kiewiet
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
namespace WyriHaximus\TwigView\View;
12
13
use Cake\Core\Configure;
14
use Cake\View\Exception\MissingLayoutException;
15
use Cake\View\Exception\MissingTemplateException;
16
use Cake\View\View;
17
use Exception;
18
use WyriHaximus\TwigView\Event\ConstructEvent;
19
use WyriHaximus\TwigView\Event\EnvironmentConfigEvent;
20
use WyriHaximus\TwigView\Event\LoaderEvent;
21
use WyriHaximus\TwigView\Lib\Twig\Loader;
22
23
/**
24
 * Class TwigView
25
 * @package WyriHaximus\TwigView\View
26
 */
27
// @codingStandardsIgnoreStart
28
class TwigView extends View
29
// @codingStandardsIgnoreEnd
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
    // @codingStandardsIgnoreStart
41
    protected $_ext = self::EXT;
42
    // @codingStandardsIgnoreEnd
43
44
    /**
45
     * @var array
46
     */
47
    protected $extensions = [
48
        self::EXT,
49
        '.tpl',
50
        '.ctp',
51
    ];
52
53
    /**
54
     * Twig instance.
55
     *
56
     * @var \Twig_Environment
57
     */
58
    protected $twig;
59
60
    /**
61
     * Initialize view.
62
     *
63
     * @return void
64
     */
65 21
    public function initialize()
66
    {
67 21
        $this->twig = new \Twig_Environment($this->getLoader(), $this->resolveConfig());
0 ignored issues
show
Bug introduced by
It seems like $this->getLoader() targeting WyriHaximus\TwigView\View\TwigView::getLoader() can also be of type object<Twig_LoaderInterface>; however, Twig\Environment::__construct() does only seem to accept null|object<Twig\Loader\LoaderInterface>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
68
69 21
        $this->getEventManager()->dispatch(ConstructEvent::create($this, $this->twig));
70
71 21
        $this->_ext = self::EXT;
72
73 21
        parent::initialize();
74 21
    }
75
76
    /**
77
     * @return array
78
     */
79 21
    protected function resolveConfig()
80
    {
81
        $config = [
82 21
            'cache' => CACHE . 'twigView' . DS,
83 21
            'charset' => strtolower(Configure::readOrFail('App.encoding')),
84 21
            'auto_reload' => Configure::read('debug'),
85 21
            'debug' => Configure::read('debug'),
86
        ];
87
88 21
        $config = array_replace($config, $this->readConfig());
89
90 21
        $configEvent = EnvironmentConfigEvent::create($config);
91 21
        $this->getEventManager()->dispatch($configEvent);
92 21
        return $configEvent->getConfig();
93
    }
94
95
    /**
96
     * @return array
97
     */
98 21
    protected function readConfig()
99
    {
100 21
        if (!Configure::check(static::ENV_CONFIG)) {
101 20
            return [];
102
        }
103
104 1
        $config = Configure::read(static::ENV_CONFIG);
105 1
        if (!is_array($config)) {
106
            return [];
107
        }
108
109 1
        return $config;
110
    }
111
112
    /**
113
     * @param string $extension
114
     */
115
    public function unshiftExtension($extension)
116
    {
117
        array_unshift($this->extensions, $extension);
118
    }
119
120
    /**
121
     * Create the template loader.
122
     *
123
     * @return \Twig_LoaderInterface
124
     */
125 21
    protected function getLoader()
126
    {
127 21
        $event = LoaderEvent::create(new Loader());
0 ignored issues
show
Documentation introduced by
new \WyriHaximus\TwigView\Lib\Twig\Loader() is of type object<WyriHaximus\TwigView\Lib\Twig\Loader>, but the function expects a object<Twig_LoaderInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
128 21
        $this->getEventManager()->dispatch($event);
129 21
        return $event->getResultLoader();
130
    }
131
132
    /**
133
     * Get helper list.
134
     *
135
     * @return \Cake\View\Helper[]
136
     */
137 12
    protected function generateHelperList()
138
    {
139 12
        $registry = $this->helpers();
140 12
        $helperList = [];
141
142 12
        foreach ($registry->loaded() as $alias) {
143 11
            $helperList[$alias] = $registry->get($alias);
144
        }
145
146 12
        return $helperList;
147
    }
148
    /**
149
     * Render the template.
150
     *
151
     * @param string $viewFile Template file.
152
     * @param array  $data     Data that can be used by the template.
153
     *
154
     * @throws \Exception
155
     * @return string
156
     */
157
    // @codingStandardsIgnoreStart
158 15
    protected function _render($viewFile, $data = array())
159
    {
160
        // @codingStandardsIgnoreEnd
161 15
        if (empty($data)) {
162 15
            $data = $this->viewVars;
0 ignored issues
show
Deprecated Code introduced by
The property Cake\View\ViewVarsTrait::$viewVars has been deprecated with message: 3.7.0 Use `$this->set()` instead, also see `$this->viewBuilder()->getVar()`.

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
163
        }
164
165 15
        if (substr($viewFile, -3) === 'ctp') {
166 9
            $out = parent::_render($viewFile, $data);
167
            // @codingStandardsIgnoreStart
168
        } else {
169
            // @codingStandardsIgnoreEnd
170 11
            $data = array_merge(
171 11
                $data,
172 11
                $this->generateHelperList(),
173
                [
174 11
                    '_view' => $this,
175
                ]
176
            );
177
178
            // @codingStandardsIgnoreStart
179
            try {
180 11
                $out = $this->getTwig()->loadTemplate($viewFile)->render($data);
181 2
            } catch (Exception $e) {
182 2
                $previous = $e->getPrevious();
183
184 2
                if ($previous !== null && $previous instanceof Exception) {
185 1
                    throw $previous;
186
                } else {
187 1
                    throw $e;
188
                }
189
            }
190
            // @codingStandardsIgnoreEnd
191
        }
192
193 13
        return $out;
194
    }
195
196
    /**
197
     * @param string|null $name
198
     * @return string
199
     * @throws \Exception
200
     */
201
    // @codingStandardsIgnoreStart
202 11
    protected function _getViewFileName($name = null)
203
    {
204
        // @codingStandardsIgnoreEnd
205 11
        $templatePath = $subDir = '';
206
207 11
        if ($this->subDir !== null) {
208
            $subDir = $this->subDir . DIRECTORY_SEPARATOR;
209
        }
210 11
        if ($this->templatePath) {
211
            $templatePath = $this->templatePath . DIRECTORY_SEPARATOR;
212
        }
213
214 11
        if ($name === null) {
215
            $name = $this->template;
216
        }
217
218 11
        list($plugin, $name) = $this->pluginSplit($name);
219 11
        $name = str_replace('/', DIRECTORY_SEPARATOR, $name);
220
221 11
        if (strpos($name, DIRECTORY_SEPARATOR) === false && $name[0] !== '.') {
222 2
            $name = $templatePath . $subDir . $this->_inflectViewFileName($name);
223 9
        } elseif (strpos($name, DIRECTORY_SEPARATOR) !== false) {
224 9
            if ($name[0] === DIRECTORY_SEPARATOR || $name[1] === ':') {
225
                $name = trim($name, DIRECTORY_SEPARATOR);
226 9
            } elseif (!$plugin || $this->templatePath !== $this->name) {
227 9
                $name = $templatePath . $subDir . $name;
228
            } else {
229
                $name = DIRECTORY_SEPARATOR . $subDir . $name;
230
            }
231
        }
232
233 11 View Code Duplication
        foreach ($this->_paths($plugin) as $path) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
234 11
            foreach ($this->extensions as $extension) {
235 11
                if (file_exists($path . $name . $extension)) {
236 11
                    return $this->_checkFilePath($path . $name . $extension, $path);
237
                }
238
            }
239
        }
240
241
        throw new MissingTemplateException(['file' => $name . $this->_ext]);
242
    }
243
244
    /**
245
     * @param string|null $name
246
     * @return string
247
     * @throws \Exception
248
     */
249
    // @codingStandardsIgnoreStart
250 7
    protected function _getLayoutFileName($name = null)
251
    {
252
        // @codingStandardsIgnoreEnd
253 7
        if ($name === null) {
254
            $name = $this->layout;
255
        }
256 7
        $subDir = null;
257
258 7
        if ($this->layoutPath) {
259
            $subDir = $this->layoutPath . DIRECTORY_SEPARATOR;
260
        }
261 7
        list($plugin, $name) = $this->pluginSplit($name);
262
263 7
        $layoutPaths = $this->_getSubPaths('Layout' . DIRECTORY_SEPARATOR . $subDir);
264
265 7
        foreach ($this->_paths($plugin) as $path) {
266 7
            foreach ($layoutPaths as $layoutPath) {
267 7
                $currentPath = $path . $layoutPath;
268 7 View Code Duplication
                foreach ($this->extensions as $extension) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
269 7
                    if (file_exists($currentPath . $name . $extension)) {
270 7
                        return $this->_checkFilePath($currentPath . $name . $extension, $currentPath);
271
                    }
272
                }
273
            }
274
        }
275
        throw new MissingLayoutException([
276
            'file' => $layoutPaths[0] . $name . $this->_ext
277
        ]);
278
    }
279
280
    /**
281
     * @param string $name
282
     * @param bool $pluginCheck
283
     * @return string
284
     * @throws \Exception
285
     */
286
    // @codingStandardsIgnoreStart
287 3
    protected function _getElementFileName($name, $pluginCheck = true)
288
    {
289
        // @codingStandardsIgnoreEnd
290 3
        list($plugin, $name) = $this->pluginSplit($name, $pluginCheck);
291
292 3
        $paths = $this->_paths($plugin);
293 3
        $elementPaths = $this->_getSubPaths('Element');
294
295 3
        foreach ($paths as $path) {
296 3
            foreach ($elementPaths as $elementPath) {
297 3
                foreach ($this->extensions as $extension) {
298 3
                    if (file_exists($path . $elementPath . DIRECTORY_SEPARATOR . $name . $extension)) {
299 3
                        return $path . $elementPath . DIRECTORY_SEPARATOR . $name . $extension;
300
                    }
301
                }
302
            }
303
        }
304
305
        return false;
306
    }
307
308
    /**
309
     * Get twig environment instance.
310
     *
311
     * @return \Twig_Environment
312
     */
313 11
    public function getTwig()
314
    {
315 11
        return $this->twig;
316
    }
317
318
    /**
319
     * Return empty string when View instance is cast to string.
320
     *
321
     * @return string
322
     */
323
    public function __toString()
324
    {
325
        return '';
326
    }
327
}
328