Test Failed
Push — master ( a28393...a400a4 )
by David
06:01 queued 03:02
created

lib/Dwoo/Template/File.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Copyright (c) 2013-2017
4
 *
5
 * @category  Library
6
 * @package   Dwoo\Template
7
 * @author    Jordi Boggiano <[email protected]>
8
 * @author    David Sanchez <[email protected]>
9
 * @copyright 2008-2013 Jordi Boggiano
10
 * @copyright 2013-2017 David Sanchez
11
 * @license   http://dwoo.org/LICENSE Modified BSD License
12
 * @version   1.3.4
13
 * @date      2017-03-07
14
 * @link      http://dwoo.org/
15
 */
16
17
namespace Dwoo\Template;
18
19
use Dwoo\Exception as DwooException;
20
use Dwoo\Core as Core;
21
use Dwoo\ICompiler;
22
use Dwoo\ITemplate as ITemplate;
23
use Dwoo\Security\Exception as SecurityException;
24
use Dwoo\Template\File as TemplateFile;
25
26
/**
27
 * Represents a Dwoo template contained in a file.
28
 * This software is provided 'as-is', without any express or implied warranty.
29
 * In no event will the authors be held liable for any damages arising from the use of this software.
30
 */
31
class File extends Str
32
{
33
    /**
34
     * Template filename.
35
     *
36
     * @var string
37
     */
38
    protected $file;
39
40
    /**
41
     * Include path(s) to look into to find this template.
42
     *
43
     * @var array
44
     */
45
    protected $includePath = array();
46
47
    /**
48
     * Resolved path cache when looking for a file in multiple include paths.
49
     * this is reset when the include path is changed
50
     *
51
     * @var string
52
     */
53
    protected $resolvedPath = null;
54
55
    /**
56
     * Creates a template from a file.
57
     *
58
     * @param string $file        the path to the template file, make sure it exists
59
     * @param int    $cacheTime   duration of the cache validity for this template,
60
     *                            if null it defaults to the Dwoo instance that will
61
     *                            render this template
62
     * @param string $cacheId     the unique cache identifier of this page or anything else that
63
     *                            makes this template's content unique, if null it defaults
64
     *                            to the current url
65
     * @param string $compileId   the unique compiled identifier, which is used to distinguish this
66
     *                            template from others, if null it defaults to the filename+bits of the path
67
     * @param mixed  $includePath a string for a single path to look into for the given file, or an array of paths
68
     */
69
    public function __construct($file, $cacheTime = null, $cacheId = null, $compileId = null, $includePath = array())
70
    {
71
        parent::__construct($file, $cacheTime, $cacheId, $compileId);
72
        $this->template = null;
73
        $this->file     = $file;
74
        $this->name     = basename($file);
75
        $this->setIncludePath($includePath);
76
    }
77
78
    /**
79
     * Sets the include path(s) to where the given template filename must be looked up.
80
     *
81
     * @param mixed $paths the path to look into, can be string for a single path or an array of paths
82
     */
83
    public function setIncludePath($paths)
84
    {
85
        if (is_array($paths) === false) {
86
            $paths = array($paths);
87
        }
88
89
        $this->includePath  = $paths;
90
        $this->resolvedPath = null;
91
    }
92
93
    /**
94
     * Return the current include path(s).
95
     *
96
     * @return array
97
     */
98
    public function getIncludePath()
99
    {
100
        return $this->includePath;
101
    }
102
103
    /**
104
     * Checks if compiled file is valid (exists and it's the modification is greater or
105
     * equal to the modification time of the template file).
106
     *
107
     * @param string file
108
     *
109
     * @return bool True cache file existance and it's modification time
110
     */
111
    protected function isValidCompiledFile($file)
112
    {
113
        return parent::isValidCompiledFile($file) && (int)$this->getUid() <= filemtime($file);
114
    }
115
116
    /**
117
     * Returns the template source of this template.
118
     *
119
     * @return string
120
     */
121
    public function getSource()
122
    {
123
        return file_get_contents($this->getResourceIdentifier());
124
    }
125
126
    /**
127
     * Returns the resource name for this template class.
128
     *
129
     * @return string
130
     */
131
    public function getResourceName()
132
    {
133
        return 'file';
134
    }
135
136
    /**
137
     * Returns this template's source filename.
138
     *
139
     * @return string
140
     * @throws DwooException
141
     */
142
    public function getResourceIdentifier()
143
    {
144
        if ($this->resolvedPath !== null) {
145
            return $this->resolvedPath;
146
        } elseif (array_filter($this->getIncludePath()) == array()) {
147
            return $this->file;
148
        } else {
149
            foreach ($this->getIncludePath() as $path) {
150
                $path = rtrim($path, DIRECTORY_SEPARATOR);
151
                if (file_exists($path . DIRECTORY_SEPARATOR . $this->file) === true) {
152
                    return $this->resolvedPath = $path . DIRECTORY_SEPARATOR . $this->file;
153
                }
154
            }
155
156
            throw new DwooException('Template "' . $this->file . '" could not be found in any of your include path(s)');
157
        }
158
    }
159
160
    /**
161
     * Returns an unique value identifying the current version of this template,
162
     * in this case it's the unix timestamp of the last modification.
163
     *
164
     * @return string
165
     */
166
    public function getUid()
167
    {
168
        return (string)filemtime($this->getResourceIdentifier());
169
    }
170
171
    /**
172
     * Returns a new template object from the given include name, null if no include is
173
     * possible (resource not found), or false if include is not permitted by this resource type.
174
     *
175
     * @param Core      $core           the dwoo instance requiring it
176
     * @param mixed     $resourceId     the filename (relative to this template's dir) of the template to
177
     *                                  include
178
     * @param int       $cacheTime      duration of the cache validity for this template, if null it defaults
179
     *                                  to the Dwoo instance that will render this template if null it
180
     *                                  defaults to the Dwoo instance that will render this template if null
181
     *                                  it defaults to the Dwoo instance that will render this template
182
     * @param string    $cacheId        the unique cache identifier of this page or anything else that makes
183
     *                                  this template's content unique, if null it defaults to the current
184
     *                                  url makes this template's content unique, if null it defaults to the
185
     *                                  current url makes this template's content unique, if null it defaults
186
     *                                  to the current url
187
     * @param string    $compileId      the unique compiled identifier, which is used to distinguish this
188
     *                                  template from others, if null it defaults to the filename+bits of the
189
     *                                  path template from others, if null it defaults to the filename+bits
190
     *                                  of the path template from others, if null it defaults to the
191
     *                                  filename+bits of the path
192
     * @param ITemplate $parentTemplate the template that is requesting a new template object (through an
193
     *                                  include, extends or any other plugin) an include, extends or any
194
     *                                  other plugin) an include, extends or any other plugin)
195
     *
196
     * @return TemplateFile|null
197
     * @throws DwooException
198
     * @throws SecurityException
199
     */
200
    public static function templateFactory(Core $core, $resourceId, $cacheTime = null, $cacheId = null,
201
                                           $compileId = null, ITemplate $parentTemplate = null)
202
    {
203
        if (DIRECTORY_SEPARATOR === '\\') {
204
            $resourceId = str_replace(array("\t", "\n", "\r", "\f", "\v"), array(
205
                '\\t',
206
                '\\n',
207
                '\\r',
208
                '\\f',
209
                '\\v'
210
            ), $resourceId);
211
        }
212
        $resourceId = strtr($resourceId, '\\', '/');
213
214
        $includePath = null;
215
216
        if (file_exists($resourceId) === false) {
217
            if ($parentTemplate === null) {
218
                $parentTemplate = $core->getTemplate();
219
            }
220
            if ($parentTemplate instanceof self) {
221
                if ($includePath = $parentTemplate->getIncludePath()) {
222
                    if (strstr($resourceId, '../')) {
223
                        throw new DwooException('When using an include path you can not reference a template into a parent directory (using ../)');
224
                    }
225
                } else {
226
                    $resourceId = dirname($parentTemplate->getResourceIdentifier()) . DIRECTORY_SEPARATOR . $resourceId;
227
                    if (file_exists($resourceId) === false) {
228
                        return null;
229
                    }
230
                }
231
            } else {
232
                return null;
233
            }
234
        }
235
236
        if ($policy = $core->getSecurityPolicy()) {
237
            while (true) {
238
                if (preg_match('{^([a-z]+?)://}i', $resourceId)) {
239
                    throw new SecurityException('The security policy prevents you to read files from external sources : <em>' . $resourceId . '</em>.');
240
                }
241
242
                if ($includePath) {
243
                    break;
244
                }
245
246
                $resourceId = realpath($resourceId);
247
                $dirs       = $policy->getAllowedDirectories();
248
                foreach ($dirs as $dir => $dummy) {
249
                    if (strpos($resourceId, $dir) === 0) {
250
                        break 2;
251
                    }
252
                }
253
                throw new SecurityException('The security policy prevents you to read <em>' . $resourceId . '</em>');
254
            }
255
        }
256
257
        $class = 'Dwoo\Template\File';
258
        if ($parentTemplate) {
259
            $class = get_class($parentTemplate);
260
        }
261
262
        return new $class($resourceId, $cacheTime, $cacheId, $compileId, $includePath);
263
    }
264
265
    /**
266
     * Returns the full compiled file name and assigns a default value to it if
267
     * required.
268
     *
269
     * @param Core $core the Core instance that requests the file name
270
     *
271
     * @return string the full path to the compiled file
272
     */
273 View Code Duplication
    protected function getCompiledFilename(Core $core)
0 ignored issues
show
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...
274
    {
275
        // no compile id was provided, set default
276
        if ($this->compileId === null) {
277
            $this->compileId = $this->getResourceIdentifier();
278
        }
279
280
        return $this->compileId . '.d' . Core::RELEASE_TAG . '.php';
281
    }
282
283
    /**
284
     * Returns some php code that will check if this template has been modified or not.
285
     * if the function returns null, the template will be instanciated and then the Uid checked
286
     *
287
     * @return string
288
     */
289
    public function getIsModifiedCode()
290
    {
291
        return '"' . $this->getUid() . '" == filemtime(' . var_export($this->getResourceIdentifier(), true) . ')';
292
    }
293
}
294