r114083 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r114082‎ | r114083 | r114084 >
Date:22:26, 17 March 2012
Author:jeroendedauw
Status:deferred
Tags:
Comment:
follow up to r114081
Modified paths:
  • /trunk/extensions/EducationProgram/EducationProgram.i18n.php (modified) (history)
  • /trunk/extensions/EducationProgram/EducationProgram.php (modified) (history)
  • /trunk/extensions/EducationProgram/compat (added) (history)
  • /trunk/extensions/EducationProgram/compat/SpecialCachedPage.php (added) (history)
  • /trunk/extensions/EducationProgram/specials/SpecialCachedPage.php (deleted) (history)

Diff [purge]

Index: trunk/extensions/EducationProgram/compat/SpecialCachedPage.php
@@ -0,0 +1,261 @@
 2+<?php
 3+
 4+/**
 5+ * Abstract special page class with scaffolding for caching the HTML output.
 6+ *
 7+ * To enable the caching functionality, the cacheExpiry field should be set
 8+ * in the constructor.
 9+ *
 10+ * To add HTML that should be cached, use addCachedHTML like this:
 11+ * $this->addCachedHTML( array( $this, 'displayCachedContent' ) );
 12+ *
 13+ * After adding the last HTML that should be cached, call $this->saveCache();
 14+ *
 15+ * @since 0.1
 16+ *
 17+ * @file SpecialCachedPage.php
 18+ * @ingroup EducationProgram
 19+ *
 20+ * @licence GNU GPL v3 or later
 21+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 22+ */
 23+abstract class SpecialCachedPage extends SpecialPage {
 24+
 25+ /**
 26+ * The time to live for the cache, in seconds or a unix timestamp indicating the point of expiry.
 27+ *
 28+ * @since 0.1
 29+ * @var integer|null
 30+ */
 31+ protected $cacheExpiry = null;
 32+
 33+ /**
 34+ * List of HTML chunks to be cached (if !hasCached) or that where cashed (of hasCached).
 35+ * If no cached already, then the newly computed chunks are added here,
 36+ * if it as cached already, chunks are removed from this list as they are needed.
 37+ *
 38+ * @since 0.1
 39+ * @var array
 40+ */
 41+ protected $cachedChunks;
 42+
 43+ /**
 44+ * Indicates if the to be cached content was already cached.
 45+ * Null if this information is not available yet.
 46+ *
 47+ * @since 0.1
 48+ * @var boolean|null
 49+ */
 50+ protected $hasCached = null;
 51+
 52+ /**
 53+ * Main method.
 54+ *
 55+ * @since 0.1
 56+ *
 57+ * @param string|null $subPage
 58+ */
 59+ public function execute( $subPage ) {
 60+ //parent::execute( $subPage );
 61+
 62+ if ( $this->getRequest()->getText( 'action' ) === 'purge' ) {
 63+ $this->hasCached = false;
 64+ }
 65+
 66+ if ( !is_null( $this->cacheExpiry ) ) {
 67+ $this->initCaching();
 68+
 69+ if ( $this->hasCached === true ) {
 70+ $this->getOutput()->setSubtitle( $this->getCachedNotice( $subPage ) );
 71+ }
 72+ }
 73+ }
 74+
 75+ /**
 76+ * Returns a message that notifies the user he/she is looking at
 77+ * a cached version of the page, including a refresh link.
 78+ *
 79+ * @since 0.1
 80+ *
 81+ * @param string|null $subPage
 82+ *
 83+ * @return string
 84+ */
 85+ protected function getCachedNotice( $subPage ) {
 86+ $refreshArgs = $_GET;
 87+ unset( $refreshArgs['title'] );
 88+ $refreshArgs['action'] = 'purge';
 89+
 90+ $refreshLink = Linker::link(
 91+ $this->getTitle( $subPage ),
 92+ $this->msg( 'cachedspecial-refresh-now' )->escaped(),
 93+ array(),
 94+ $refreshArgs
 95+ );
 96+
 97+ if ( $this->cacheExpiry < 1000000000 ) {
 98+ $message = $this->msg(
 99+ 'cachedspecial-viewing-cached-ttl',
 100+ $this->getDurationText( $this->cacheExpiry )
 101+ )->escaped();
 102+ }
 103+ else {
 104+ $message = $this->msg(
 105+ 'cachedspecial-viewing-cached-ts'
 106+ )->escaped();
 107+ }
 108+
 109+ return $message . ' ' . $refreshLink;
 110+ }
 111+
 112+ /**
 113+ * Returns a message with the time to live of the cache.
 114+ * Takes care of compatibility with MW < 1.20, in which Language::duration was introduced.
 115+ *
 116+ * @since 0.1
 117+ *
 118+ * @param integer $seconds
 119+ * @param array $chosenIntervals
 120+ *
 121+ * @return string
 122+ */
 123+ protected function getDurationText( $seconds, array $chosenIntervals = array( 'years', 'days', 'hours', 'minutes', 'seconds' ) ) {
 124+ if ( method_exists( $this->getLanguage(), 'duration' ) ) {
 125+ return $this->getLanguage()->duration( $seconds, $chosenIntervals );
 126+ }
 127+ else {
 128+ $intervals = array(
 129+ 'years' => 31557600, // 86400 * 365.25
 130+ 'weeks' => 604800,
 131+ 'days' => 86400,
 132+ 'hours' => 3600,
 133+ 'minutes' => 60,
 134+ 'seconds' => 1,
 135+ );
 136+
 137+ if ( !empty( $chosenIntervals ) ) {
 138+ $intervals = array_intersect_key( $intervals, array_flip( $chosenIntervals ) );
 139+ }
 140+
 141+ $segments = array();
 142+
 143+ foreach ( $intervals as $name => $length ) {
 144+ $value = floor( $seconds / $length );
 145+
 146+ if ( $value > 0 || ( $name == 'seconds' && empty( $segments ) ) ) {
 147+ $seconds -= $value * $length;
 148+ $segments[] = $this->msg( 'duration-' . $name, array( $value ) )->escaped();
 149+ }
 150+ }
 151+
 152+ return $this->getLanguage()->listToText( $segments );
 153+ }
 154+ }
 155+
 156+ /**
 157+ * Initializes the caching if not already done so.
 158+ * Should be called before any of the caching functionality is used.
 159+ *
 160+ * @since 0.1
 161+ */
 162+ protected function initCaching() {
 163+ if ( is_null( $this->hasCached ) ) {
 164+ $cachedChunks = wfGetCache( CACHE_ANYTHING )->get( $this->getCacheKey() );
 165+
 166+ $this->hasCached = is_array( $cachedChunks );
 167+ $this->cachedChunks = $this->hasCached ? $cachedChunks : array();
 168+ }
 169+ }
 170+
 171+ /**
 172+ * Add some HTML to be cached.
 173+ * This is done by providing a callback function that should
 174+ * return the HTML to be added. It will only be called if the
 175+ * item is not in the cache yet or when the cache has been invalidated.
 176+ *
 177+ * @since 0.1
 178+ *
 179+ * @param {function} $callback
 180+ * @param array $args
 181+ * @param string|null $key
 182+ */
 183+ public function addCachedHTML( $callback, $args = array(), $key = null ) {
 184+ $this->initCaching();
 185+
 186+ if ( $this->hasCached ) {
 187+ $html = '';
 188+
 189+ if ( is_null( $key ) ) {
 190+ $itemKey = array_keys( array_slice( $this->cachedChunks, 0, 1 ) );
 191+ $itemKey = array_shift( $itemKey );
 192+
 193+ if ( !is_integer( $itemKey ) ) {
 194+ wfWarn( "Attempted to get item with non-numeric key while the next item in the queue has a key ($itemKey) in " . __METHOD__ );
 195+ }
 196+ elseif ( is_null( $itemKey ) ) {
 197+ wfWarn( "Attempted to get an item while the queue is empty in " . __METHOD__ );
 198+ }
 199+ else {
 200+ $html = array_shift( $this->cachedChunks );
 201+ }
 202+ }
 203+ else {
 204+ if ( array_key_exists( $key, $this->cachedChunks ) ) {
 205+ $html = $this->cachedChunks[$key];
 206+ unset( $this->cachedChunks[$key] );
 207+ }
 208+ else {
 209+ wfWarn( "There is no item with key '$key' in this->cachedChunks in " . __METHOD__ );
 210+ }
 211+ }
 212+ }
 213+ else {
 214+ $html = call_user_func_array( $callback, $args );
 215+
 216+ if ( is_null( $key ) ) {
 217+ $this->cachedChunks[] = $html;
 218+ }
 219+ else {
 220+ $this->cachedChunks[$key] = $html;
 221+ }
 222+ }
 223+
 224+ $this->getOutput()->addHTML( $html );
 225+ }
 226+
 227+ /**
 228+ * Saves the HTML to the cache in case it got recomputed.
 229+ * Should be called after the last time anything is added via addCachedHTML.
 230+ *
 231+ * @since 0.1
 232+ */
 233+ public function saveCache() {
 234+ if ( $this->hasCached === false && !empty( $this->cachedChunks ) ) {
 235+ wfGetCache( CACHE_ANYTHING )->set( $this->getCacheKey(), $this->cachedChunks, $this->cacheExpiry );
 236+ }
 237+ }
 238+
 239+ /**
 240+ * Sets the time to live for the cache, in seconds or a unix timestamp indicating the point of expiry..
 241+ *
 242+ * @since 0.1
 243+ *
 244+ * @param integer $cacheExpiry
 245+ */
 246+ protected function setExpirey( $cacheExpiry ) {
 247+ $this->cacheExpiry = $cacheExpiry;
 248+ }
 249+
 250+ /**
 251+ * Returns the cache key to use to cache this page's HTML output.
 252+ * Is constructed from the special page name and language code.
 253+ *
 254+ * @since 0.1
 255+ *
 256+ * @return string
 257+ */
 258+ protected function getCacheKey() {
 259+ return wfMemcKey( $this->mName, $this->getLanguage()->getCode() );
 260+ }
 261+
 262+}
Index: trunk/extensions/EducationProgram/EducationProgram.php
@@ -144,8 +144,17 @@
145145 $wgAutoloadClasses['SpecialCAProfile'] = dirname( __FILE__ ) . '/specials/SpecialCAProfile.php';
146146 $wgAutoloadClasses['SpecialAmbassadorProfile'] = dirname( __FILE__ ) . '/specials/SpecialAmbassadorProfile.php';
147147 $wgAutoloadClasses['SpecialStudentActivity'] = dirname( __FILE__ ) . '/specials/SpecialStudentActivity.php';
148 -$wgAutoloadClasses['SpecialCachedPage'] = dirname( __FILE__ ) . '/specials/SpecialCachedPage.php';
149148
 149+// Compat classes
 150+foreach ( array(
 151+ 'SpecialCachedPage' => 'SpecialCachedPage.php' // MW < 1.20
 152+ ) as $className => $fileName ) {
 153+
 154+ if ( !array_key_exists( $className, $wgAutoloadLocalClasses ) ) {
 155+ $wgAutoloadClasses[$className] = dirname( __FILE__ ) . '/compat/' . $fileName;
 156+ }
 157+}
 158+
150159 // Special pages
151160 $wgSpecialPages['MyCourses'] = 'SpecialMyCourses';
152161 $wgSpecialPages['Institutions'] = 'SpecialInstitutions';
Index: trunk/extensions/EducationProgram/specials/SpecialCachedPage.php
@@ -1,261 +0,0 @@
2 -<?php
3 -
4 -/**
5 - * Abstract special page class with scaffolding for caching the HTML output.
6 - *
7 - * To enable the caching functionality, the cacheExpiry field should be set
8 - * in the constructor.
9 - *
10 - * To add HTML that should be cached, use addCachedHTML like this:
11 - * $this->addCachedHTML( array( $this, 'displayCachedContent' ) );
12 - *
13 - * After adding the last HTML that should be cached, call $this->saveCache();
14 - *
15 - * @since 0.1
16 - *
17 - * @file SpecialCachedPage.php
18 - * @ingroup EducationProgram
19 - *
20 - * @licence GNU GPL v3 or later
21 - * @author Jeroen De Dauw < jeroendedauw@gmail.com >
22 - */
23 -abstract class SpecialCachedPage extends SpecialPage {
24 -
25 - /**
26 - * The time to live for the cache, in seconds or a unix timestamp indicating the point of expiry.
27 - *
28 - * @since 0.1
29 - * @var integer|null
30 - */
31 - protected $cacheExpiry = null;
32 -
33 - /**
34 - * List of HTML chunks to be cached (if !hasCached) or that where cashed (of hasCached).
35 - * If no cached already, then the newly computed chunks are added here,
36 - * if it as cached already, chunks are removed from this list as they are needed.
37 - *
38 - * @since 0.1
39 - * @var array
40 - */
41 - protected $cachedChunks;
42 -
43 - /**
44 - * Indicates if the to be cached content was already cached.
45 - * Null if this information is not available yet.
46 - *
47 - * @since 0.1
48 - * @var boolean|null
49 - */
50 - protected $hasCached = null;
51 -
52 - /**
53 - * Main method.
54 - *
55 - * @since 0.1
56 - *
57 - * @param string|null $subPage
58 - */
59 - public function execute( $subPage ) {
60 - //parent::execute( $subPage );
61 -
62 - if ( $this->getRequest()->getText( 'action' ) === 'purge' ) {
63 - $this->hasCached = false;
64 - }
65 -
66 - if ( !is_null( $this->cacheExpiry ) ) {
67 - $this->initCaching();
68 -
69 - if ( $this->hasCached === true ) {
70 - $this->getOutput()->setSubtitle( $this->getCachedNotice( $subPage ) );
71 - }
72 - }
73 - }
74 -
75 - /**
76 - * Returns a message that notifies the user he/she is looking at
77 - * a cached version of the page, including a refresh link.
78 - *
79 - * @since 0.1
80 - *
81 - * @param string|null $subPage
82 - *
83 - * @return string
84 - */
85 - protected function getCachedNotice( $subPage ) {
86 - $refreshArgs = $_GET;
87 - unset( $refreshArgs['title'] );
88 - $refreshArgs['action'] = 'purge';
89 -
90 - $refreshLink = Linker::link(
91 - $this->getTitle( $subPage ),
92 - $this->msg( 'cachedspecial-refresh-now' )->escaped(),
93 - array(),
94 - $refreshArgs
95 - );
96 -
97 - if ( $this->cacheExpiry < 1000000000 ) {
98 - $message = $this->msg(
99 - 'cachedspecial-viewing-cached-ttl',
100 - $this->getDurationText( $this->cacheExpiry )
101 - )->escaped();
102 - }
103 - else {
104 - $message = $this->msg(
105 - 'cachedspecial-viewing-cached-ts'
106 - )->escaped();
107 - }
108 -
109 - return $message . ' ' . $refreshLink;
110 - }
111 -
112 - /**
113 - * Returns a message with the time to live of the cache.
114 - * Takes care of compatibility with MW < 1.20, in which Language::duration was introduced.
115 - *
116 - * @since 0.1
117 - *
118 - * @param integer $seconds
119 - * @param array $chosenIntervals
120 - *
121 - * @return string
122 - */
123 - protected function getDurationText( $seconds, array $chosenIntervals = array( 'years', 'days', 'hours', 'minutes', 'seconds' ) ) {
124 - if ( method_exists( $this->getLanguage(), 'duration' ) ) {
125 - return $this->getLanguage()->duration( $seconds, $chosenIntervals );
126 - }
127 - else {
128 - $intervals = array(
129 - 'years' => 31557600, // 86400 * 365.25
130 - 'weeks' => 604800,
131 - 'days' => 86400,
132 - 'hours' => 3600,
133 - 'minutes' => 60,
134 - 'seconds' => 1,
135 - );
136 -
137 - if ( !empty( $chosenIntervals ) ) {
138 - $intervals = array_intersect_key( $intervals, array_flip( $chosenIntervals ) );
139 - }
140 -
141 - $segments = array();
142 -
143 - foreach ( $intervals as $name => $length ) {
144 - $value = floor( $seconds / $length );
145 -
146 - if ( $value > 0 || ( $name == 'seconds' && empty( $segments ) ) ) {
147 - $seconds -= $value * $length;
148 - $segments[] = $this->msg( 'duration-' . $name, array( $value ) )->escaped();
149 - }
150 - }
151 -
152 - return $this->getLanguage()->listToText( $segments );
153 - }
154 - }
155 -
156 - /**
157 - * Initializes the caching if not already done so.
158 - * Should be called before any of the caching functionality is used.
159 - *
160 - * @since 0.1
161 - */
162 - protected function initCaching() {
163 - if ( is_null( $this->hasCached ) ) {
164 - $cachedChunks = wfGetCache( CACHE_ANYTHING )->get( $this->getCacheKey() );
165 -
166 - $this->hasCached = is_array( $cachedChunks );
167 - $this->cachedChunks = $this->hasCached ? $cachedChunks : array();
168 - }
169 - }
170 -
171 - /**
172 - * Add some HTML to be cached.
173 - * This is done by providing a callback function that should
174 - * return the HTML to be added. It will only be called if the
175 - * item is not in the cache yet or when the cache has been invalidated.
176 - *
177 - * @since 0.1
178 - *
179 - * @param {function} $callback
180 - * @param array $args
181 - * @param string|null $key
182 - */
183 - public function addCachedHTML( $callback, $args = array(), $key = null ) {
184 - $this->initCaching();
185 -
186 - if ( $this->hasCached ) {
187 - $html = '';
188 -
189 - if ( is_null( $key ) ) {
190 - $itemKey = array_keys( array_slice( $this->cachedChunks, 0, 1 ) );
191 - $itemKey = array_shift( $itemKey );
192 -
193 - if ( !is_integer( $itemKey ) ) {
194 - wfWarn( "Attempted to get item with non-numeric key while the next item in the queue has a key ($itemKey) in " . __METHOD__ );
195 - }
196 - elseif ( is_null( $itemKey ) ) {
197 - wfWarn( "Attempted to get an item while the queue is empty in " . __METHOD__ );
198 - }
199 - else {
200 - $html = array_shift( $this->cachedChunks );
201 - }
202 - }
203 - else {
204 - if ( array_key_exists( $key, $this->cachedChunks ) ) {
205 - $html = $this->cachedChunks[$key];
206 - unset( $this->cachedChunks[$key] );
207 - }
208 - else {
209 - wfWarn( "There is no item with key '$key' in this->cachedChunks in " . __METHOD__ );
210 - }
211 - }
212 - }
213 - else {
214 - $html = call_user_func_array( $callback, $args );
215 -
216 - if ( is_null( $key ) ) {
217 - $this->cachedChunks[] = $html;
218 - }
219 - else {
220 - $this->cachedChunks[$key] = $html;
221 - }
222 - }
223 -
224 - $this->getOutput()->addHTML( $html );
225 - }
226 -
227 - /**
228 - * Saves the HTML to the cache in case it got recomputed.
229 - * Should be called after the last time anything is added via addCachedHTML.
230 - *
231 - * @since 0.1
232 - */
233 - public function saveCache() {
234 - if ( $this->hasCached === false && !empty( $this->cachedChunks ) ) {
235 - wfGetCache( CACHE_ANYTHING )->set( $this->getCacheKey(), $this->cachedChunks, $this->cacheExpiry );
236 - }
237 - }
238 -
239 - /**
240 - * Sets the time to live for the cache, in seconds or a unix timestamp indicating the point of expiry..
241 - *
242 - * @since 0.1
243 - *
244 - * @param integer $cacheExpiry
245 - */
246 - protected function setExpirey( $cacheExpiry ) {
247 - $this->cacheExpiry = $cacheExpiry;
248 - }
249 -
250 - /**
251 - * Returns the cache key to use to cache this page's HTML output.
252 - * Is constructed from the special page name and language code.
253 - *
254 - * @since 0.1
255 - *
256 - * @return string
257 - */
258 - protected function getCacheKey() {
259 - return wfMemcKey( $this->mName, $this->getLanguage()->getCode() );
260 - }
261 -
262 -}
Index: trunk/extensions/EducationProgram/EducationProgram.i18n.php
@@ -783,7 +783,7 @@
784784 You can find a full list of students on [[Special:Students|the student list]].',
785785 'ep-studentactivity-count' => 'There {{PLURAL:$1|is|are}} currently $1 {{PLURAL:$1|student|students}} that {{PLURAL:$1|was|where}} active in the last 24 hours.',
786786
787 - // Cached special page
 787+ // Cached special page, back compat for MW < 1.20
788788 'cachedspecial-viewing-cached-ttl' => 'You are viewing a cached version of this page, which can be up to $1 old.',
789789 'cachedspecial-viewing-cached-ts' => 'You are viewing a cached version of this page, which might not be completely actual.',
790790 'cachedspecial-refresh-now' => 'View latest.',

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r114081adding special page with scaffolding for caching chunks of HTMLjeroendedauw22:26, 17 March 2012

Status & tagging log