This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | class TimberLoader { |
||
4 | |||
5 | const CACHEGROUP = 'timberloader'; |
||
6 | |||
7 | const TRANS_KEY_LEN = 50; |
||
8 | |||
9 | const CACHE_NONE = 'none'; |
||
10 | const CACHE_OBJECT = 'cache'; |
||
11 | const CACHE_TRANSIENT = 'transient'; |
||
12 | const CACHE_SITE_TRANSIENT = 'site-transient'; |
||
13 | const CACHE_USE_DEFAULT = 'default'; |
||
14 | |||
15 | public static $cache_modes = array( |
||
16 | self::CACHE_NONE, |
||
17 | self::CACHE_OBJECT, |
||
18 | self::CACHE_TRANSIENT, |
||
19 | self::CACHE_SITE_TRANSIENT |
||
20 | ); |
||
21 | |||
22 | protected $cache_mode = self::CACHE_TRANSIENT; |
||
23 | |||
24 | public $locations; |
||
25 | |||
26 | /** |
||
27 | * @param bool|string $caller the calling directory or false |
||
28 | */ |
||
29 | function __construct($caller = false) { |
||
0 ignored issues
–
show
|
|||
30 | $this->locations = $this->get_locations($caller); |
||
31 | $this->cache_mode = apply_filters('timber_cache_mode', $this->cache_mode); |
||
32 | $this->cache_mode = apply_filters('timber/cache/mode', $this->cache_mode); |
||
33 | } |
||
34 | |||
35 | /** |
||
36 | * @param string $file |
||
37 | * @param array $data |
||
0 ignored issues
–
show
Should the type for parameter
$data not be array|null ?
This check looks for It makes a suggestion as to what type it considers more descriptive. Most often this is a case of a parameter that can be null in addition to its declared types. ![]() |
|||
38 | * @param bool $expires |
||
39 | * @param string $cache_mode |
||
40 | * @return bool|string |
||
41 | */ |
||
42 | function render($file, $data = null, $expires = false, $cache_mode = self::CACHE_USE_DEFAULT) { |
||
0 ignored issues
–
show
|
|||
43 | // Different $expires if user is anonymous or logged in |
||
44 | if (is_array($expires)) { |
||
45 | if (is_user_logged_in() && isset($expires[1])) { |
||
46 | $expires = $expires[1]; |
||
47 | } else { |
||
48 | $expires = $expires[0]; |
||
49 | } |
||
50 | } |
||
51 | |||
52 | $key = null; |
||
53 | $output = false; |
||
54 | if (false !== $expires) { |
||
55 | ksort($data); |
||
56 | $key = md5($file . json_encode($data)); |
||
57 | $output = $this->get_cache($key, self::CACHEGROUP, $cache_mode); |
||
58 | } |
||
59 | |||
60 | if (false === $output || null === $output) { |
||
61 | $twig = $this->get_twig(); |
||
62 | if (strlen($file)) { |
||
63 | $loader = $this->get_loader(); |
||
64 | $result = $loader->getCacheKey($file); |
||
65 | do_action('timber_loader_render_file', $result); |
||
66 | } |
||
67 | $data = apply_filters('timber_loader_render_data', $data); |
||
68 | $data = apply_filters('timber/loader/render_data', $data); |
||
69 | $output = $twig->render($file, $data); |
||
70 | } |
||
71 | |||
72 | if (false !== $output && false !== $expires && null !== $key) { |
||
73 | $this->set_cache($key, $output, self::CACHEGROUP, $expires, $cache_mode); |
||
74 | } |
||
75 | $output = apply_filters('timber_output', $output); |
||
76 | return apply_filters('timber/output', $output); |
||
77 | } |
||
78 | |||
79 | /** |
||
80 | * @param array $filenames |
||
81 | * @return bool |
||
82 | */ |
||
83 | public function choose_template($filenames) { |
||
84 | if (is_array($filenames)) { |
||
85 | /* its an array so we have to figure out which one the dev wants */ |
||
86 | foreach ($filenames as $filename) { |
||
87 | if (self::template_exists($filename)) { |
||
88 | return $filename; |
||
89 | } |
||
90 | } |
||
91 | return $filenames[0]; |
||
92 | } |
||
93 | return $filenames; |
||
94 | } |
||
95 | |||
96 | /** |
||
97 | * @param string $file |
||
98 | * @return bool |
||
99 | */ |
||
100 | protected function template_exists($file) { |
||
101 | foreach ($this->locations as $dir) { |
||
102 | $look_for = trailingslashit($dir) . $file; |
||
103 | if (file_exists($look_for)) { |
||
104 | return true; |
||
105 | } |
||
106 | } |
||
107 | return false; |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * @return array |
||
112 | */ |
||
113 | function get_locations_theme() { |
||
0 ignored issues
–
show
|
|||
114 | $theme_locs = array(); |
||
115 | $child_loc = get_stylesheet_directory(); |
||
116 | $parent_loc = get_template_directory(); |
||
117 | if (DIRECTORY_SEPARATOR == '\\') { |
||
118 | $child_loc = str_replace('/', '\\', $child_loc); |
||
119 | $parent_loc = str_replace('/', '\\', $parent_loc); |
||
120 | } |
||
121 | $theme_locs[] = $child_loc; |
||
122 | foreach ($this->get_locations_theme_dir() as $dirname) { |
||
123 | $theme_locs[] = trailingslashit($child_loc) . trailingslashit($dirname); |
||
124 | } |
||
125 | if ($child_loc != $parent_loc) { |
||
126 | $theme_locs[] = $parent_loc; |
||
127 | foreach ($this->get_locations_theme_dir() as $dirname) { |
||
128 | $theme_locs[] = trailingslashit($parent_loc) . trailingslashit($dirname); |
||
129 | } |
||
130 | } |
||
131 | //now make sure theres a trailing slash on everything |
||
132 | $theme_locs = array_map('trailingslashit', $theme_locs); |
||
133 | return $theme_locs; |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * returns an array of the directory inside themes that holds twig files |
||
138 | * @return string[] the names of directores, ie: array('templats', 'views'); |
||
139 | */ |
||
140 | private function get_locations_theme_dir() { |
||
141 | if (is_string(Timber::$dirname)) { |
||
142 | return array(Timber::$dirname); |
||
143 | } |
||
144 | return Timber::$dirname; |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * @return array |
||
149 | */ |
||
150 | function get_locations_user() { |
||
0 ignored issues
–
show
|
|||
151 | $locs = array(); |
||
152 | if (isset(Timber::$locations)) { |
||
153 | if (is_string(Timber::$locations)) { |
||
154 | Timber::$locations = array(Timber::$locations); |
||
155 | } |
||
156 | foreach (Timber::$locations as $tloc) { |
||
157 | $tloc = realpath($tloc); |
||
158 | if (is_dir($tloc)) { |
||
159 | $locs[] = $tloc; |
||
160 | } |
||
161 | } |
||
162 | } |
||
163 | return $locs; |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * @param bool|string $caller the calling directory |
||
168 | * @return array |
||
169 | */ |
||
170 | function get_locations_caller($caller = false) { |
||
0 ignored issues
–
show
|
|||
171 | $locs = array(); |
||
172 | if ($caller && is_string($caller)) { |
||
173 | $caller = trailingslashit($caller); |
||
174 | if (is_dir($caller)) { |
||
175 | $locs[] = $caller; |
||
176 | } |
||
177 | foreach ($this->get_locations_theme_dir() as $dirname) { |
||
178 | $caller_sub = $caller . trailingslashit($dirname); |
||
179 | if (is_dir($caller_sub)) { |
||
180 | $locs[] = $caller_sub; |
||
181 | } |
||
182 | } |
||
183 | } |
||
184 | return $locs; |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * @param bool|string $caller the calling directory (or false) |
||
189 | * @return array |
||
190 | */ |
||
191 | function get_locations($caller = false) { |
||
0 ignored issues
–
show
|
|||
192 | //prioirty: user locations, caller (but not theme), child theme, parent theme, caller |
||
193 | $locs = array(); |
||
194 | $locs = array_merge($locs, $this->get_locations_user()); |
||
195 | $locs = array_merge($locs, $this->get_locations_caller($caller)); |
||
196 | //remove themes from caller |
||
197 | $locs = array_diff($locs, $this->get_locations_theme()); |
||
198 | $locs = array_merge($locs, $this->get_locations_theme()); |
||
199 | $locs = array_merge($locs, $this->get_locations_caller($caller)); |
||
200 | $locs = array_unique($locs); |
||
201 | $locs = apply_filters('timber_locations', $locs); |
||
202 | $locs = apply_filters('timber/locations', $locs); |
||
203 | return $locs; |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * @return Twig_Loader_Filesystem |
||
208 | */ |
||
209 | function get_loader() { |
||
0 ignored issues
–
show
|
|||
210 | $paths = array(); |
||
211 | foreach ($this->locations as $loc) { |
||
212 | $loc = realpath($loc); |
||
213 | if (is_dir($loc)) { |
||
214 | $loc = realpath($loc); |
||
215 | $paths[] = $loc; |
||
216 | } else { |
||
0 ignored issues
–
show
This
else statement is empty and can be removed.
This check looks for the These if (rand(1, 6) > 3) {
print "Check failed";
} else {
//print "Check succeeded";
}
could be turned into if (rand(1, 6) > 3) {
print "Check failed";
}
This is much more concise to read. ![]() |
|||
217 | //error_log($loc.' is not a directory'); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
72% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
218 | } |
||
219 | } |
||
220 | if (!ini_get('open_basedir')) { |
||
221 | $paths[] = '/'; |
||
222 | } else { |
||
223 | $paths[] = ABSPATH; |
||
224 | } |
||
225 | $paths = apply_filters('timber/loader/paths', $paths); |
||
226 | $loader = new Twig_Loader_Filesystem($paths); |
||
227 | return $loader; |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * @return Twig_Environment |
||
232 | */ |
||
233 | function get_twig() { |
||
0 ignored issues
–
show
|
|||
234 | $loader = $this->get_loader(); |
||
235 | $params = array('debug' => WP_DEBUG, 'autoescape' => false); |
||
236 | if (isset(Timber::$autoescape)) { |
||
237 | $params['autoescape'] = Timber::$autoescape; |
||
238 | } |
||
239 | if (Timber::$cache === true) { |
||
240 | Timber::$twig_cache = true; |
||
241 | } |
||
242 | if (Timber::$twig_cache) { |
||
243 | $twig_cache_loc = apply_filters( 'timber/cache/location', TIMBER_LOC . '/cache/twig' ); |
||
244 | if (!file_exists($twig_cache_loc)) { |
||
245 | mkdir($twig_cache_loc, 0777, true); |
||
246 | } |
||
247 | $params['cache'] = $twig_cache_loc; |
||
248 | } |
||
249 | $twig = new Twig_Environment($loader, $params); |
||
250 | if ( WP_DEBUG ) { |
||
251 | $twig->addExtension(new Twig_Extension_Debug()); |
||
252 | } |
||
253 | $twig->addExtension($this->_get_cache_extension()); |
||
254 | |||
255 | $twig = apply_filters('twig_apply_filters', $twig); |
||
256 | $twig = apply_filters('timber/twig/filters', $twig); |
||
257 | $twig = apply_filters('timber/loader/twig', $twig); |
||
258 | return $twig; |
||
259 | } |
||
260 | |||
261 | public function clear_cache_timber($cache_mode = self::CACHE_USE_DEFAULT){ |
||
262 | //_transient_timberloader |
||
263 | $object_cache = false; |
||
264 | if (isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache'])) { |
||
265 | $object_cache = true; |
||
266 | } |
||
267 | $cache_mode = $this->_get_cache_mode($cache_mode); |
||
268 | if (self::CACHE_TRANSIENT === $cache_mode) { |
||
269 | global $wpdb; |
||
270 | $query = $wpdb->prepare("DELETE FROM $wpdb->options WHERE option_name LIKE '%s'", '_transient_timberloader_%'); |
||
271 | $wpdb->query( $query ); |
||
272 | return true; |
||
273 | } else if (self::CACHE_SITE_TRANSIENT === $cache_mode) { |
||
274 | global $wpdb; |
||
275 | $query = $wpdb->prepare("DELETE FROM $wpdb->options WHERE option_name LIKE '%s'", '_transient_timberloader_%'); |
||
276 | $wpdb->query( $query ); |
||
277 | return true; |
||
278 | } else if (self::CACHE_OBJECT === $cache_mode && $object_cache) { |
||
279 | global $wp_object_cache; |
||
280 | if (isset($wp_object_cache->cache[self::CACHEGROUP])){ |
||
281 | unset($wp_object_cache->cache[self::CACHEGROUP]); |
||
282 | return true; |
||
283 | } |
||
284 | } |
||
285 | return false; |
||
286 | } |
||
287 | |||
288 | public function clear_cache_twig() { |
||
289 | $twig = $this->get_twig(); |
||
290 | $twig->clearCacheFiles(); |
||
0 ignored issues
–
show
The method
Twig_Environment::clearCacheFiles() has been deprecated with message: since 1.22 (to be removed in 2.0)
This method 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 method will be removed from the class and what other method or class to use instead. ![]() |
|||
291 | $cache = $twig->getCache(); |
||
292 | if ($cache){ |
||
293 | self::rrmdir($twig->getCache()); |
||
0 ignored issues
–
show
It seems like
$twig->getCache() targeting Twig_Environment::getCache() can also be of type object<Twig_CacheInterface> ; however, TimberLoader::rrmdir() does only seem to accept string|false , 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. ![]() |
|||
294 | return true; |
||
295 | } |
||
296 | return false; |
||
297 | } |
||
298 | |||
299 | /** |
||
300 | * @param string|false $dirPath |
||
301 | */ |
||
302 | public static function rrmdir($dirPath) { |
||
303 | if (! is_dir($dirPath)) { |
||
304 | throw new InvalidArgumentException("$dirPath must be a directory"); |
||
305 | } |
||
306 | if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') { |
||
307 | $dirPath .= '/'; |
||
308 | } |
||
309 | $files = glob($dirPath . '*', GLOB_MARK); |
||
310 | foreach ($files as $file) { |
||
311 | if (is_dir($file)) { |
||
312 | self::rrmdir($file); |
||
313 | } else { |
||
314 | unlink($file); |
||
315 | } |
||
316 | } |
||
317 | rmdir($dirPath); |
||
318 | } |
||
319 | |||
320 | /** |
||
321 | * @return \Asm89\Twig\CacheExtension\Extension |
||
322 | */ |
||
323 | private function _get_cache_extension() { |
||
324 | |||
325 | $key_generator = new \Timber\Cache\KeyGenerator(); |
||
326 | $cache_provider = new \Timber\Cache\WPObjectCacheAdapter( $this ); |
||
327 | $cache_strategy = new \Asm89\Twig\CacheExtension\CacheStrategy\GenerationalCacheStrategy( $cache_provider, $key_generator ); |
||
328 | $cache_extension = new \Asm89\Twig\CacheExtension\Extension( $cache_strategy ); |
||
329 | |||
330 | return $cache_extension; |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | * @param string $key |
||
335 | * @param string $group |
||
336 | * @param string $cache_mode |
||
337 | * @return bool |
||
338 | */ |
||
339 | public function get_cache($key, $group = self::CACHEGROUP, $cache_mode = self::CACHE_USE_DEFAULT) { |
||
340 | $object_cache = false; |
||
341 | |||
342 | if (isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache'])) { |
||
343 | $object_cache = true; |
||
344 | } |
||
345 | |||
346 | $cache_mode = $this->_get_cache_mode($cache_mode); |
||
347 | |||
348 | $value = false; |
||
349 | |||
350 | $trans_key = substr($group . '_' . $key, 0, self::TRANS_KEY_LEN); |
||
351 | if (self::CACHE_TRANSIENT === $cache_mode) |
||
352 | $value = get_transient($trans_key); |
||
353 | |||
354 | elseif (self::CACHE_SITE_TRANSIENT === $cache_mode) |
||
355 | $value = get_site_transient($trans_key); |
||
356 | |||
357 | elseif (self::CACHE_OBJECT === $cache_mode && $object_cache) |
||
358 | $value = wp_cache_get($key, $group); |
||
359 | |||
360 | return $value; |
||
361 | } |
||
362 | |||
363 | /** |
||
364 | * @param string $key |
||
365 | * @param string|boolean $value |
||
366 | * @param string $group |
||
367 | * @param int $expires |
||
368 | * @param string $cache_mode |
||
369 | * @return string|boolean |
||
370 | */ |
||
371 | public function set_cache($key, $value, $group = self::CACHEGROUP, $expires = 0, $cache_mode = self::CACHE_USE_DEFAULT) { |
||
372 | $object_cache = false; |
||
373 | |||
374 | if (isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache'])) { |
||
375 | $object_cache = true; |
||
376 | } |
||
377 | |||
378 | if ((int)$expires < 1) |
||
379 | $expires = 0; |
||
380 | |||
381 | $cache_mode = self::_get_cache_mode($cache_mode); |
||
382 | $trans_key = substr($group . '_' . $key, 0, self::TRANS_KEY_LEN); |
||
383 | |||
384 | if (self::CACHE_TRANSIENT === $cache_mode) |
||
385 | set_transient($trans_key, $value, $expires); |
||
386 | |||
387 | elseif (self::CACHE_SITE_TRANSIENT === $cache_mode) |
||
388 | set_site_transient($trans_key, $value, $expires); |
||
389 | |||
390 | elseif (self::CACHE_OBJECT === $cache_mode && $object_cache) |
||
391 | wp_cache_set($key, $value, $group, $expires); |
||
392 | |||
393 | return $value; |
||
394 | } |
||
395 | |||
396 | /** |
||
397 | * @param string $cache_mode |
||
398 | * @return string |
||
399 | */ |
||
400 | private function _get_cache_mode($cache_mode) { |
||
401 | if (empty($cache_mode) || self::CACHE_USE_DEFAULT === $cache_mode) { |
||
402 | $cache_mode = $this->cache_mode; |
||
403 | } |
||
404 | |||
405 | // Fallback if self::$cache_mode did not get a valid value |
||
406 | if (!in_array($cache_mode, self::$cache_modes)) { |
||
407 | $cache_mode = self::CACHE_OBJECT; |
||
408 | } |
||
409 | |||
410 | return $cache_mode; |
||
411 | } |
||
412 | |||
413 | } |
||
414 |
Adding explicit visibility (
private
,protected
, orpublic
) is generally recommend to communicate to other developers how, and from where this method is intended to be used.