summaryrefslogtreecommitdiff
path: root/lib/smarty3/sysplugins/smarty_internal_runtime_cacheresourcefile.php
blob: 2870964383418c34f54f8efc1bc796d0a052e2b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<?php
/**
 * Smarty cache resource file clear method
 *
 * @package    Smarty
 * @subpackage PluginsInternal
 * @author     Uwe Tews
 */

/**
 * Smarty Internal Runtime Cache Resource File Class
 *
 * @package    Smarty
 * @subpackage PluginsInternal
 */
class Smarty_Internal_Runtime_CacheResourceFile
{
    /**
     * Empty cache for a specific template
     *
     * @param Smarty  $smarty
     * @param string  $resource_name template name
     * @param string  $cache_id      cache id
     * @param string  $compile_id    compile id
     * @param integer $exp_time      expiration time (number of seconds, not timestamp)
     *
     * @return integer number of cache files deleted
     */
    public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
    {
        $_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null;
        $_compile_id = isset($compile_id) ? preg_replace('![^\w]+!', '_', $compile_id) : null;
        $_dir_sep = $smarty->use_sub_dirs ? '/' : '^';
        $_compile_id_offset = $smarty->use_sub_dirs ? 3 : 0;
        $_dir = $smarty->getCacheDir();
        if ($_dir === '/') { //We should never want to delete this!
            return 0;
        }
        $_dir_length = strlen($_dir);
        if (isset($_cache_id)) {
            $_cache_id_parts = explode('|', $_cache_id);
            $_cache_id_parts_count = count($_cache_id_parts);
            if ($smarty->use_sub_dirs) {
                foreach ($_cache_id_parts as $id_part) {
                    $_dir .= $id_part . '/';
                }
            }
        }
        if (isset($resource_name)) {
            $_save_stat = $smarty->caching;
            $smarty->caching = Smarty::CACHING_LIFETIME_CURRENT;
            $tpl = new $smarty->template_class($resource_name, $smarty);
            $smarty->caching = $_save_stat;
            // remove from template cache
            $tpl->source; // have the template registered before unset()
            if ($tpl->source->exists) {
                $_resourcename_parts = basename(str_replace('^', '/', $tpl->cached->filepath));
            } else {
                return 0;
            }
        }
        $_count = 0;
        $_time = time();
        if (file_exists($_dir)) {
            $_cacheDirs = new RecursiveDirectoryIterator($_dir);
            $_cache = new RecursiveIteratorIterator($_cacheDirs, RecursiveIteratorIterator::CHILD_FIRST);
            foreach ($_cache as $_file) {
                if (substr(basename($_file->getPathname()), 0, 1) === '.') {
                    continue;
                }
                $_filepath = (string)$_file;
                // directory ?
                if ($_file->isDir()) {
                    if (!$_cache->isDot()) {
                        // delete folder if empty
                        @rmdir($_file->getPathname());
                    }
                } else {
                    // delete only php files
                    if (substr($_filepath, -4) !== '.php') {
                        continue;
                    }
                    $_parts = explode($_dir_sep, str_replace('\\', '/', substr($_filepath, $_dir_length)));
                    $_parts_count = count($_parts);
                    // check name
                    if (isset($resource_name)) {
                        if ($_parts[ $_parts_count - 1 ] !== $_resourcename_parts) {
                            continue;
                        }
                    }
                    // check compile id
                    if (isset($_compile_id) && (!isset($_parts[ $_parts_count - 2 - $_compile_id_offset ])
                                                || $_parts[ $_parts_count - 2 - $_compile_id_offset ] !== $_compile_id)
                    ) {
                        continue;
                    }
                    // check cache id
                    if (isset($_cache_id)) {
                        // count of cache id parts
                        $_parts_count = (isset($_compile_id)) ? $_parts_count - 2 - $_compile_id_offset :
                            $_parts_count - 1 - $_compile_id_offset;
                        if ($_parts_count < $_cache_id_parts_count) {
                            continue;
                        }
                        for ($i = 0; $i < $_cache_id_parts_count; $i++) {
                            if ($_parts[ $i ] !== $_cache_id_parts[ $i ]) {
                                continue 2;
                            }
                        }
                    }
                    if (is_file($_filepath)) {
                        // expired ?
                        if (isset($exp_time)) {
                            if ($exp_time < 0) {
                                preg_match('#\'cache_lifetime\' =>\s*(\d*)#', file_get_contents($_filepath), $match);
                                if ($_time < (filemtime($_filepath) + $match[ 1 ])) {
                                    continue;
                                }
                            } else {
                                if ($_time - filemtime($_filepath) < $exp_time) {
                                    continue;
                                }
                            }
                        }
                        $_count += @unlink($_filepath) ? 1 : 0;
                        if (function_exists('opcache_invalidate')
                            && (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1)
                        ) {
                            opcache_invalidate($_filepath, true);
                        } elseif (function_exists('apc_delete_file')) {
                            apc_delete_file($_filepath);
                        }
                    }
                }
            }
        }
        return $_count;
    }
}