Index: trunk/extensions/EducationProgram/specials/SpecialEPPage.php |
— | — | @@ -12,7 +12,7 @@ |
13 | 13 | * @licence GNU GPL v3 or later |
14 | 14 | * @author Jeroen De Dauw < jeroendedauw@gmail.com > |
15 | 15 | */ |
16 | | -abstract class SpecialEPPage extends SpecialPage { |
| 16 | +abstract class SpecialEPPage extends SpecialCachedPage { |
17 | 17 | |
18 | 18 | /** |
19 | 19 | * The subpage, ie the part after Special:PageName/ |
— | — | @@ -54,6 +54,8 @@ |
55 | 55 | * @return boolean |
56 | 56 | */ |
57 | 57 | public function execute( $subPage ) { |
| 58 | + parent::execute( $subPage ); |
| 59 | + |
58 | 60 | $subPage = is_null( $subPage ) ? '' : $subPage; |
59 | 61 | $this->subPage = trim( str_replace( '_', ' ', $subPage ) ); |
60 | 62 | |
Index: trunk/extensions/EducationProgram/specials/SpecialStudentActivity.php |
— | — | @@ -20,6 +20,7 @@ |
21 | 21 | */ |
22 | 22 | public function __construct() { |
23 | 23 | parent::__construct( 'StudentActivity' ); |
| 24 | + $this->cacheExpiry = 600; |
24 | 25 | } |
25 | 26 | |
26 | 27 | /** |
— | — | @@ -30,34 +31,40 @@ |
31 | 32 | * @param string $subPage |
32 | 33 | */ |
33 | 34 | public function execute( $subPage ) { |
34 | | - parent::execute( $subPage ); |
| 35 | + //parent::execute( $subPage ); |
35 | 36 | |
36 | | - $cache = wfGetCache( CACHE_ANYTHING ); |
37 | | - $cacheKey = wfMemcKey( get_class( $this ), $this->getLanguage()->getCode() ); |
38 | | - $cachedHTML = $cache->get( $cacheKey ); |
| 37 | + if ( !is_null( $this->cacheExpiry ) ) { |
| 38 | + $cache = wfGetCache( CACHE_ANYTHING ); |
| 39 | + $cacheKey = $this->getCacheKey(); |
| 40 | + $cachedHTML = $cache->get( $cacheKey ); |
39 | 41 | |
40 | | - $out = $this->getOutput(); |
| 42 | + $out = $this->getOutput(); |
41 | 43 | |
42 | | - if ( $this->getRequest()->getText( 'action' ) !== 'purge' && is_string( $cachedHTML ) ) { |
43 | | - $html = $cachedHTML; |
44 | | - } |
45 | | - else { |
46 | | - $conds = array( 'last_active > ' . wfGetDB( DB_SLAVE )->addQuotes( |
47 | | - wfTimestamp( TS_MW, time() - ( EPSettings::get( 'recentActivityLimit' ) ) ) |
48 | | - ) ); |
| 44 | + if ( $this->getRequest()->getText( 'action' ) !== 'purge' && is_string( $cachedHTML ) ) { |
| 45 | + $html = $cachedHTML; |
| 46 | + } |
| 47 | + else { |
| 48 | + $this->displayCachedContent(); |
49 | 49 | |
50 | | - $this->displayStudentMeter( $conds ); |
51 | | - $this->displayPager( $conds ); |
| 50 | + $html = $out->getHTML(); |
| 51 | + $cache->set( $cacheKey, $html, $this->cacheExpiry ); |
| 52 | + } |
52 | 53 | |
53 | | - $html = $out->getHTML(); |
54 | | - $cache->set( $cacheKey, $html, 3600 ); |
| 54 | + $out->clearHTML(); |
| 55 | + |
| 56 | + $this->displayBeforeCached(); |
| 57 | + $out->addHTML( $html ); |
| 58 | + $this->displayAfterCached(); |
55 | 59 | } |
| 60 | + } |
56 | 61 | |
57 | | - $out->clearHTML(); |
| 62 | + protected function displayCachedContent() { |
| 63 | + $conds = array( 'last_active > ' . wfGetDB( DB_SLAVE )->addQuotes( |
| 64 | + wfTimestamp( TS_MW, time() - ( EPSettings::get( 'recentActivityLimit' ) ) ) |
| 65 | + ) ); |
58 | 66 | |
59 | | - $this->displayNavigation(); |
60 | | - |
61 | | - $out->addHTML( $html ); |
| 67 | + $this->displayStudentMeter( $conds ); |
| 68 | + $this->displayPager( $conds ); |
62 | 69 | } |
63 | 70 | |
64 | 71 | public function displayPager( array $conds ) { |
Index: trunk/extensions/EducationProgram/specials/SpecialCachedPage.php |
— | — | @@ -1,5 +1,142 @@ |
2 | 2 | <?php |
3 | 3 | |
| 4 | +class CachedOutput { |
| 5 | + |
| 6 | + /** |
| 7 | + * The time to live for the cache, in seconds or a unix timestamp indicating the point of expiry. |
| 8 | + * |
| 9 | + * @since 0.1 |
| 10 | + * @var integer |
| 11 | + */ |
| 12 | + protected $cacheExpiry = 3600; |
| 13 | + |
| 14 | + protected $cachedChunks; |
| 15 | + |
| 16 | + protected $hasCached = null; |
| 17 | + |
| 18 | + protected $out; |
| 19 | + |
| 20 | + public function __construct( OutputPage $out ) { |
| 21 | + $this->out = $out; |
| 22 | + } |
| 23 | + |
| 24 | + public function invalidateCache() { |
| 25 | + $this->hasCached = false; |
| 26 | + } |
| 27 | + |
| 28 | + /** |
| 29 | + * Initializes the caching. |
| 30 | + * Should be called ONCE before any of the caching functionality is used, |
| 31 | + * only when $this->hasCached is null. |
| 32 | + * |
| 33 | + * @since 0.1 |
| 34 | + */ |
| 35 | + protected function initCaching() { |
| 36 | + $cachedChunks = wfGetCache( CACHE_ANYTHING )->get( $this->getCacheKey() ); |
| 37 | + |
| 38 | + $this->hasCached = is_array( $cachedChunks ); |
| 39 | + $this->cachedChunks = $this->hasCached ? $cachedChunks : array(); |
| 40 | + } |
| 41 | + |
| 42 | + /** |
| 43 | + * Add some HTML to be cached. |
| 44 | + * This is done by providing a callback function that should |
| 45 | + * return the HTML to be added. It will only be called if the |
| 46 | + * item is not in the cache yet or when the cache has been invalidated. |
| 47 | + * |
| 48 | + * @since 0.1 |
| 49 | + * |
| 50 | + * @param {function} $callback |
| 51 | + * @param array $args |
| 52 | + * @param string|null $key |
| 53 | + */ |
| 54 | + public function addCachedHTML( $callback, $args = array(), $key = null ) { |
| 55 | + if ( is_null( $this->hasCached ) ) { |
| 56 | + $this->initCaching(); |
| 57 | + } |
| 58 | + |
| 59 | + if ( $this->hasCached ) { |
| 60 | + $html = ''; |
| 61 | + |
| 62 | + if ( is_null( $key ) ) { |
| 63 | + $itemKey = array_flip( array_slice( $this->cachedChunks, 0, 1 ) ); |
| 64 | + $itemKey = array_shift( $itemKey ); |
| 65 | + |
| 66 | + if ( is_integer( $itemKey ) ) { |
| 67 | + wfWarn( "Attempted to get item with non-numeric key while the next item in the queue has a key ($itemKey) in " . __METHOD__ ); |
| 68 | + } |
| 69 | + elseif ( is_null( $itemKey ) ) { |
| 70 | + wfWarn( "Attempted to get an item while the queue is empty in " . __METHOD__ ); |
| 71 | + } |
| 72 | + else { |
| 73 | + $html = array_shift( $key ); |
| 74 | + } |
| 75 | + } |
| 76 | + else { |
| 77 | + if ( array_key_exists( $key, $this->cachedChunks ) ) { |
| 78 | + $html = $this->cachedChunks[$key]; |
| 79 | + unset( $this->cachedChunks[$key] ); |
| 80 | + } |
| 81 | + else { |
| 82 | + wfWarn( "There is no item with key '$key' in this->cachedChunks in " . __METHOD__ ); |
| 83 | + } |
| 84 | + } |
| 85 | + } |
| 86 | + else { |
| 87 | + $html = call_user_func_array( $callback, $args ); |
| 88 | + |
| 89 | + if ( is_null( $key ) ) { |
| 90 | + $this->cachedChunks[] = $html; |
| 91 | + } |
| 92 | + else { |
| 93 | + $this->cachedChunks[$key] = $html; |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | + $this->addHTML( $html ); |
| 98 | + } |
| 99 | + |
| 100 | + public function addHTML( $html ) { |
| 101 | + $this->out->addHTML( $html ); |
| 102 | + } |
| 103 | + |
| 104 | + /** |
| 105 | + * Saves the HTML to the cache in case it got recomputed. |
| 106 | + * Should be called after the last time anything is added via addCachedHTML. |
| 107 | + * |
| 108 | + * @since 0.1 |
| 109 | + */ |
| 110 | + public function saveCache() { |
| 111 | + if ( !$this->hasCached && !empty( $this->cachedChunks ) ) { |
| 112 | + wfGetCache( CACHE_ANYTHING )->set( $this->getCacheKey(), $this->cachedChunks, $this->cacheExpiry ); |
| 113 | + } |
| 114 | + } |
| 115 | + |
| 116 | + /** |
| 117 | + * Sets the time to live for the cache, in seconds or a unix timestamp indicating the point of expiry.. |
| 118 | + * |
| 119 | + * @since 0.1 |
| 120 | + * |
| 121 | + * @param integer $cacheExpiry |
| 122 | + */ |
| 123 | + protected function setExpirey( $cacheExpiry ) { |
| 124 | + $this->cacheExpiry = $cacheExpiry; |
| 125 | + } |
| 126 | + |
| 127 | + /** |
| 128 | + * Returns the cache key to use to cache this page's HTML output. |
| 129 | + * Is constructed from the special page name and language code. |
| 130 | + * |
| 131 | + * @since 0.1 |
| 132 | + * |
| 133 | + * @return string |
| 134 | + */ |
| 135 | + protected function getCacheKey() { |
| 136 | + return wfMemcKey( $this->mName, $this->getLanguage()->getCode() ); |
| 137 | + } |
| 138 | + |
| 139 | +} |
| 140 | + |
4 | 141 | /** |
5 | 142 | * Abstract special page class with scaffolding for caching the HTML output. |
6 | 143 | * |
— | — | @@ -14,13 +151,15 @@ |
15 | 152 | abstract class SpecialCachedPage extends SpecialPage { |
16 | 153 | |
17 | 154 | /** |
18 | | - * The time to live for the cache, in seconds. |
| 155 | + * The time to live for the cache, in seconds or a unix timestamp indicating the point of expiry. |
19 | 156 | * |
20 | 157 | * @since 0.1 |
21 | | - * @var integer |
| 158 | + * @var integer|null |
22 | 159 | */ |
23 | | - protected $cacheExpiry = 3600; |
| 160 | + protected $cacheExpiry = null; |
24 | 161 | |
| 162 | + protected $cachedOutput = null; |
| 163 | + |
25 | 164 | /** |
26 | 165 | * Main method. |
27 | 166 | * |
— | — | @@ -29,33 +168,35 @@ |
30 | 169 | * @param string $subPage |
31 | 170 | */ |
32 | 171 | public function execute( $subPage ) { |
33 | | - parent::execute( $subPage ); |
| 172 | + //parent::execute( $subPage ); |
34 | 173 | |
35 | | - $cache = wfGetCache( CACHE_ANYTHING ); |
36 | | - $cacheKey = $this->getCacheKey(); |
37 | | - $cachedHTML = $cache->get( $cacheKey ); |
| 174 | + if ( !is_null( $this->cacheExpiry ) ) { |
| 175 | + $cache = wfGetCache( CACHE_ANYTHING ); |
| 176 | + $cacheKey = $this->getCacheKey(); |
| 177 | + $cachedHTML = $cache->get( $cacheKey ); |
38 | 178 | |
39 | | - $out = $this->getOutput(); |
| 179 | + $out = $this->getOutput(); |
40 | 180 | |
41 | | - if ( $this->getRequest()->getText( 'action' ) !== 'purge' && is_string( $cachedHTML ) ) { |
42 | | - $html = $cachedHTML; |
43 | | - } |
44 | | - else { |
45 | | - $this->displayCachedContent(); |
| 181 | + if ( $this->getRequest()->getText( 'action' ) !== 'purge' && is_string( $cachedHTML ) ) { |
| 182 | + $html = $cachedHTML; |
| 183 | + } |
| 184 | + else { |
| 185 | + $this->displayCachedContent(); |
46 | 186 | |
47 | | - $html = $out->getHTML(); |
48 | | - $cache->set( $cacheKey, $html, $this->cacheExpiry ); |
49 | | - } |
| 187 | + $html = $out->getHTML(); |
| 188 | + $cache->set( $cacheKey, $html, $this->cacheExpiry ); |
| 189 | + } |
50 | 190 | |
51 | | - $out->clearHTML(); |
| 191 | + $out->clearHTML(); |
52 | 192 | |
53 | | - $this->displayBeforeCached(); |
54 | | - $out->addHTML( $html ); |
55 | | - $this->displayAfterCached(); |
| 193 | + $this->displayBeforeCached(); |
| 194 | + $out->addHTML( $html ); |
| 195 | + $this->displayAfterCached(); |
| 196 | + } |
56 | 197 | } |
57 | 198 | |
58 | 199 | /** |
59 | | - * Sets the time to live for the cache, in seconds. |
| 200 | + * Sets the time to live for the cache, in seconds or a unix timestamp indicating the point of expiry.. |
60 | 201 | * |
61 | 202 | * @since 0.1 |
62 | 203 | * |