Added mod_rewrite rules to ensure /admin and /user/login are never ever cached.
[project/boost.git] / boost.api.inc
CommitLineData
45b69d54
AB
1<?php
2// $Id$
3
4/**
5 * @file
6 * Implements the Boost API for static page caching.
7 */
8
9//////////////////////////////////////////////////////////////////////////////
10// BOOST API
11
12/**
13 * Determines whether a given Drupal page can be cached or not.
14 *
15 * To avoid potentially troublesome situations, the user login page is never
16 * cached, nor are any admin pages. At present, we also refuse to cache any
17 * RSS feeds provided by Drupal, since they would require special handling
18 * in the mod_rewrite ruleset as they shouldn't be sent out using the
19 * text/html content type.
20 */
21function boost_is_cacheable($path) {
22 $alias = drupal_get_path_alias($path);
23 $path = drupal_get_normal_path($path); // normalize path
24
25 // Never cache the basic user login/registration pages or any administration pages
26 if ($path == 'user' || preg_match('!^user/(login|register|password)!', $path) || preg_match('!^admin!', $path))
27 return FALSE;
28
29 // At present, RSS feeds are not cacheable due to content type restrictions
30 if ($path == 'rss.xml' || preg_match('!/feed$!', $path))
31 return FALSE;
32
33 // Don't cache comment reply pages
34 if (preg_match('!^comment/reply!', $path))
35 return FALSE;
36
37 // Match the user's cacheability settings against the path
38 if (BOOST_CACHEABILITY_OPTION == 2) {
39 $result = drupal_eval(BOOST_CACHEABILITY_PAGES);
40 return !empty($result);
41 }
42 $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'), '/') .'\2'), preg_quote(BOOST_CACHEABILITY_PAGES, '/')) .')$/';
43 return !(BOOST_CACHEABILITY_OPTION xor preg_match($regexp, $alias));
44}
45
46/**
47 * Deletes all static files currently in the cache.
48 */
49function boost_cache_clear_all() {
50 clearstatcache();
51 return _boost_rmdir_rf(boost_cache_directory());
52}
53
54/**
55 * Deletes all expired static files currently in the cache.
56 */
57function boost_cache_expire_all() {
58 clearstatcache();
59 _boost_rmdir_rf(boost_cache_directory(), 'boost_file_is_expired');
60 return TRUE;
61}
62
63/**
64 * Expires the static file cache for a given page, or multiple pages
65 * matching a wildcard.
66 */
67function boost_cache_expire($path, $wildcard = FALSE) {
68 // TODO: handle wildcard.
69
70 $alias = drupal_get_path_alias($path);
71 $path = drupal_get_normal_path($path); // normalize path
72
73 $filename = boost_file_path($path);
74 if (file_exists($filename))
75 @unlink($filename);
76
77 if ($alias != $path) {
78 $symlink = boost_file_path($alias);
79 if (is_link($symlink))
80 @unlink($symlink);
81 }
82
83 return TRUE;
84}
85
86/**
87 * Returns the cached contents of the specified page, if available.
88 */
89function boost_cache_get($path) {
90 $path = drupal_get_normal_path($path); // normalize path
91
92 $filename = boost_file_path($path);
93 if (file_exists($filename) && is_readable($filename))
94 return file_get_contents($filename);
95
96 return NULL;
97}
98
99
100/**
101 * Replaces the cached contents of the specified page, if stale.
102 */
103function boost_cache_set($path, $data = '') {
104 // Append the Boost footer with the current timestamp
105 $data = rtrim($data) . "\n" . str_replace('%date', date('Y-m-d H:i:s'), BOOST_BANNER);
106
107 // Execute the pre-process function if one has been defined
108 if (function_exists(BOOST_PRE_PROCESS_FUNCTION))
109 $data = call_user_func(BOOST_PRE_PROCESS_FUNCTION, $data);
110
111 $alias = drupal_get_path_alias($path);
112 $path = drupal_get_normal_path($path); // normalize path
113
114 // Create or update the static file as needed
115 $filename = boost_file_path($path);
116 _boost_mkdir_p(dirname($filename));
117 if (!file_exists($filename) || boost_file_is_expired($filename)) {
118 if (file_put_contents($filename, $data) === FALSE) {
119 watchdog('boost', t('Unable to write file: %file', array('%file' => $filename)), WATCHDOG_WARNING);
120 }
121 }
122
123 // If a URL alias is defined, create that as a symlink to the actual file
124 if ($alias != $path) {
125 $symlink = boost_file_path($alias);
126 _boost_mkdir_p(dirname($symlink));
127 if (!is_link($symlink) || realpath(readlink($symlink)) != realpath($filename)) {
128 if (file_exists($symlink))
129 @unlink($symlink);
130 if (!_boost_symlink($filename, $symlink)) {
131 watchdog('boost', t('Unable to create symlink: %link to %target', array('%link' => $symlink, '%target' => $filename)), WATCHDOG_WARNING);
132 }
133 }
134 }
135
136 return TRUE;
137}
138
139/**
140 * Returns the full directory path to the static file cache directory.
141 */
142function boost_cache_directory($user_id = 0, $host = NULL) {
143 global $user, $base_url;
144 $user_id = 0; //(!is_null($user_id) ? $user_id : BOOST_USER_ID);
145 $parts = parse_url($base_url);
146 $host = (!empty($host) ? $host : $parts['host']);
147
148 // FIXME: correctly handle Drupal subdirectory installations.
149 return implode('/', array(getcwd(), BOOST_FILE_PATH, $host, $user_id));
150}
151
152/**
153 * Returns the static file path for a Drupal page.
154 */
155function boost_file_path($path) {
156 if ($path == BOOST_FRONTPAGE)
157 $path = 'index'; // special handling for Drupal front page
158 return implode('/', array(boost_cache_directory(), $path)) . BOOST_FILE_EXTENSION;
159}
160
161/**
162 * Returns the age of a cached file, measured in seconds since it was last
163 * updated.
164 */
165function boost_file_get_age($filename) {
166 return time() - filemtime($filename);
167}
168
169/**
170 * Determines whether a cached file has expired, i.e. whether its age exceeds
171 * the maximum cache lifetime as defined by Drupal's system settings.
172 */
173function boost_file_is_expired($filename) {
174 if (is_link($filename))
175 return FALSE;
176 return boost_file_get_age($filename) > variable_get('cache_lifetime', 600);
177}
178
179//////////////////////////////////////////////////////////////////////////////