Index: branches/REL1_19/phase3/RELEASE-NOTES-1.19 |
— | — | @@ -246,6 +246,7 @@ |
247 | 247 | getText() on a non-object |
248 | 248 | * (bug 31676) Group dynamically inserted CSS into a single <style> tag, to work |
249 | 249 | around a bug where not all styles were applied in Internet Explorer |
| 250 | +* (bug 28936, bug 5280) Broken or invalid titles can't be removed from watchlist. |
250 | 251 | |
251 | 252 | === API changes in 1.19 === |
252 | 253 | * Made action=edit less likely to return "unknownerror", by returning the actual error |
Index: branches/REL1_19/phase3/includes/User.php |
— | — | @@ -2602,14 +2602,6 @@ |
2603 | 2603 | } |
2604 | 2604 | |
2605 | 2605 | /** |
2606 | | - * Cleans up watchlist by removing invalid entries from it |
2607 | | - */ |
2608 | | - public function cleanupWatchlist() { |
2609 | | - $dbw = wfGetDB( DB_MASTER ); |
2610 | | - $dbw->delete( 'watchlist', array( 'wl_namespace < 0', 'wl_user' => $this->getId() ), __METHOD__ ); |
2611 | | - } |
2612 | | - |
2613 | | - /** |
2614 | 2606 | * Clear the user's notification timestamp for the given title. |
2615 | 2607 | * If e-notif e-mails are on, they will receive notification mails on |
2616 | 2608 | * the next change of the page if it's watched etc. |
Index: branches/REL1_19/phase3/includes/filerepo/backend/TempFSFile.php |
— | — | @@ -41,9 +41,6 @@ |
42 | 42 | } |
43 | 43 | } |
44 | 44 | $tmpFile = new self( $path ); |
45 | | - if ( php_sapi_name() != 'cli' ) { |
46 | | - self::$instances[] = $tmpFile; // defer purge till shutdown |
47 | | - } |
48 | 45 | return $tmpFile; |
49 | 46 | } |
50 | 47 | |
Index: branches/REL1_19/phase3/includes/OutputPage.php |
— | — | @@ -2681,6 +2681,8 @@ |
2682 | 2682 | ); |
2683 | 2683 | |
2684 | 2684 | // Load embeddable private modules before any loader links |
| 2685 | + // This needs to be TYPE_COMBINED so these modules are properly wrapped |
| 2686 | + // in mw.loader.implement() calls and deferred until mw.user is available |
2685 | 2687 | $embedScripts = array( 'user.options', 'user.tokens' ); |
2686 | 2688 | $scripts .= $this->makeResourceLoaderLink( $embedScripts, ResourceLoaderModule::TYPE_COMBINED ); |
2687 | 2689 | |
— | — | @@ -3268,7 +3270,7 @@ |
3269 | 3271 | |
3270 | 3272 | // Per-user preference styles |
3271 | 3273 | if ( $wgAllowUserCssPrefs ) { |
3272 | | - $moduleStyles[] = 'user.options'; |
| 3274 | + $moduleStyles[] = 'user.cssprefs'; |
3273 | 3275 | } |
3274 | 3276 | |
3275 | 3277 | foreach ( $moduleStyles as $name ) { |
Property changes on: branches/REL1_19/phase3/includes/OutputPage.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
3276 | 3278 | Merged /trunk/phase3/includes/OutputPage.php:r111029,111034,111067,111085,111128,111144 |
Index: branches/REL1_19/phase3/includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php |
— | — | @@ -0,0 +1,136 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * This program is free software; you can redistribute it and/or modify |
| 5 | + * it under the terms of the GNU General Public License as published by |
| 6 | + * the Free Software Foundation; either version 2 of the License, or |
| 7 | + * (at your option) any later version. |
| 8 | + * |
| 9 | + * This program is distributed in the hope that it will be useful, |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | + * GNU General Public License for more details. |
| 13 | + * |
| 14 | + * You should have received a copy of the GNU General Public License along |
| 15 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 16 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 17 | + * http://www.gnu.org/copyleft/gpl.html |
| 18 | + * |
| 19 | + * @file |
| 20 | + * @author Trevor Parscal |
| 21 | + * @author Roan Kattouw |
| 22 | + */ |
| 23 | + |
| 24 | +/** |
| 25 | + * Module for user preference customizations |
| 26 | + */ |
| 27 | +class ResourceLoaderUserCSSPrefsModule extends ResourceLoaderModule { |
| 28 | + |
| 29 | + /* Protected Members */ |
| 30 | + |
| 31 | + protected $modifiedTime = array(); |
| 32 | + |
| 33 | + protected $origin = self::ORIGIN_CORE_INDIVIDUAL; |
| 34 | + |
| 35 | + /* Methods */ |
| 36 | + |
| 37 | + /** |
| 38 | + * @param $context ResourceLoaderContext |
| 39 | + * @return array|int|Mixed |
| 40 | + */ |
| 41 | + public function getModifiedTime( ResourceLoaderContext $context ) { |
| 42 | + $hash = $context->getHash(); |
| 43 | + if ( isset( $this->modifiedTime[$hash] ) ) { |
| 44 | + return $this->modifiedTime[$hash]; |
| 45 | + } |
| 46 | + |
| 47 | + global $wgUser; |
| 48 | + |
| 49 | + if ( $context->getUser() === $wgUser->getName() ) { |
| 50 | + return $this->modifiedTime[$hash] = wfTimestamp( TS_UNIX, $wgUser->getTouched() ); |
| 51 | + } else { |
| 52 | + return 1; |
| 53 | + } |
| 54 | + } |
| 55 | + |
| 56 | + /** |
| 57 | + * Fetch the context's user options, or if it doesn't match current user, |
| 58 | + * the default options. |
| 59 | + * |
| 60 | + * @param $context ResourceLoaderContext: Context object |
| 61 | + * @return Array: List of user options keyed by option name |
| 62 | + */ |
| 63 | + protected function contextUserOptions( ResourceLoaderContext $context ) { |
| 64 | + global $wgUser; |
| 65 | + |
| 66 | + // Verify identity -- this is a private module |
| 67 | + if ( $context->getUser() === $wgUser->getName() ) { |
| 68 | + return $wgUser->getOptions(); |
| 69 | + } else { |
| 70 | + return User::getDefaultOptions(); |
| 71 | + } |
| 72 | + } |
| 73 | + |
| 74 | + /** |
| 75 | + * @param $context ResourceLoaderContext |
| 76 | + * @return array |
| 77 | + */ |
| 78 | + public function getStyles( ResourceLoaderContext $context ) { |
| 79 | + global $wgAllowUserCssPrefs; |
| 80 | + |
| 81 | + if ( $wgAllowUserCssPrefs ) { |
| 82 | + $options = $this->contextUserOptions( $context ); |
| 83 | + |
| 84 | + // Build CSS rules |
| 85 | + $rules = array(); |
| 86 | + |
| 87 | + // Underline: 2 = browser default, 1 = always, 0 = never |
| 88 | + if ( $options['underline'] < 2 ) { |
| 89 | + $rules[] = "a { text-decoration: " . |
| 90 | + ( $options['underline'] ? 'underline' : 'none' ) . "; }"; |
| 91 | + } else { |
| 92 | + # The scripts of these languages are very hard to read with underlines |
| 93 | + $rules[] = 'a:lang(ar), a:lang(ckb), a:lang(fa),a:lang(kk-arab), ' . |
| 94 | + 'a:lang(mzn), a:lang(ps), a:lang(ur) { text-decoration: none; }'; |
| 95 | + } |
| 96 | + if ( $options['highlightbroken'] ) { |
| 97 | + $rules[] = "a.new, #quickbar a.new { color: #ba0000; }\n"; |
| 98 | + } else { |
| 99 | + $rules[] = "a.new, #quickbar a.new, a.stub, #quickbar a.stub { color: inherit; }"; |
| 100 | + $rules[] = "a.new:after, #quickbar a.new:after { content: '?'; color: #ba0000; }"; |
| 101 | + $rules[] = "a.stub:after, #quickbar a.stub:after { content: '!'; color: #772233; }"; |
| 102 | + } |
| 103 | + if ( $options['justify'] ) { |
| 104 | + $rules[] = "#article, #bodyContent, #mw_content { text-align: justify; }\n"; |
| 105 | + } |
| 106 | + if ( !$options['showtoc'] ) { |
| 107 | + $rules[] = "#toc { display: none; }\n"; |
| 108 | + } |
| 109 | + if ( !$options['editsection'] ) { |
| 110 | + $rules[] = ".editsection { display: none; }\n"; |
| 111 | + } |
| 112 | + if ( $options['editfont'] !== 'default' ) { |
| 113 | + $rules[] = "textarea { font-family: {$options['editfont']}; }\n"; |
| 114 | + } |
| 115 | + $style = implode( "\n", $rules ); |
| 116 | + if ( $this->getFlip( $context ) ) { |
| 117 | + $style = CSSJanus::transform( $style, true, false ); |
| 118 | + } |
| 119 | + return array( 'all' => $style ); |
| 120 | + } |
| 121 | + return array(); |
| 122 | + } |
| 123 | + |
| 124 | + /** |
| 125 | + * @return string |
| 126 | + */ |
| 127 | + public function getGroup() { |
| 128 | + return 'private'; |
| 129 | + } |
| 130 | + |
| 131 | + /** |
| 132 | + * @return array |
| 133 | + */ |
| 134 | + public function getDependencies() { |
| 135 | + return array( 'mediawiki.user' ); |
| 136 | + } |
| 137 | +} |
Property changes on: branches/REL1_19/phase3/includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 138 | + native |
Index: branches/REL1_19/phase3/includes/resourceloader/ResourceLoaderUserOptionsModule.php |
— | — | @@ -80,58 +80,6 @@ |
81 | 81 | } |
82 | 82 | |
83 | 83 | /** |
84 | | - * @param $context ResourceLoaderContext |
85 | | - * @return array |
86 | | - */ |
87 | | - public function getStyles( ResourceLoaderContext $context ) { |
88 | | - // FIXME: This stuff should really be in its own module, because it gets double-loaded otherwise |
89 | | - // (once through a <link>, once when embedded as JS) |
90 | | - global $wgAllowUserCssPrefs; |
91 | | - |
92 | | - if ( $wgAllowUserCssPrefs ) { |
93 | | - $options = $this->contextUserOptions( $context ); |
94 | | - |
95 | | - // Build CSS rules |
96 | | - $rules = array(); |
97 | | - |
98 | | - // Underline: 2 = browser default, 1 = always, 0 = never |
99 | | - if ( $options['underline'] < 2 ) { |
100 | | - $rules[] = "a { text-decoration: " . |
101 | | - ( $options['underline'] ? 'underline' : 'none' ) . "; }"; |
102 | | - } else { |
103 | | - # The scripts of these languages are very hard to read with underlines |
104 | | - $rules[] = 'a:lang(ar), a:lang(ckb), a:lang(fa),a:lang(kk-arab), ' . |
105 | | - 'a:lang(mzn), a:lang(ps), a:lang(ur) { text-decoration: none; }'; |
106 | | - } |
107 | | - if ( $options['highlightbroken'] ) { |
108 | | - $rules[] = "a.new, #quickbar a.new { color: #ba0000; }\n"; |
109 | | - } else { |
110 | | - $rules[] = "a.new, #quickbar a.new, a.stub, #quickbar a.stub { color: inherit; }"; |
111 | | - $rules[] = "a.new:after, #quickbar a.new:after { content: '?'; color: #ba0000; }"; |
112 | | - $rules[] = "a.stub:after, #quickbar a.stub:after { content: '!'; color: #772233; }"; |
113 | | - } |
114 | | - if ( $options['justify'] ) { |
115 | | - $rules[] = "#article, #bodyContent, #mw_content { text-align: justify; }\n"; |
116 | | - } |
117 | | - if ( !$options['showtoc'] ) { |
118 | | - $rules[] = "#toc { display: none; }\n"; |
119 | | - } |
120 | | - if ( !$options['editsection'] ) { |
121 | | - $rules[] = ".editsection { display: none; }\n"; |
122 | | - } |
123 | | - if ( $options['editfont'] !== 'default' ) { |
124 | | - $rules[] = "textarea { font-family: {$options['editfont']}; }\n"; |
125 | | - } |
126 | | - $style = implode( "\n", $rules ); |
127 | | - if ( $this->getFlip( $context ) ) { |
128 | | - $style = CSSJanus::transform( $style, true, false ); |
129 | | - } |
130 | | - return array( 'all' => $style ); |
131 | | - } |
132 | | - return array(); |
133 | | - } |
134 | | - |
135 | | - /** |
136 | 84 | * @return string |
137 | 85 | */ |
138 | 86 | public function getGroup() { |
Index: branches/REL1_19/phase3/includes/AutoLoader.php |
— | — | @@ -720,6 +720,7 @@ |
721 | 721 | 'ResourceLoaderNoscriptModule' => 'includes/resourceloader/ResourceLoaderNoscriptModule.php', |
722 | 722 | 'ResourceLoaderSiteModule' => 'includes/resourceloader/ResourceLoaderSiteModule.php', |
723 | 723 | 'ResourceLoaderStartUpModule' => 'includes/resourceloader/ResourceLoaderStartUpModule.php', |
| 724 | + 'ResourceLoaderUserCSSPrefsModule' => 'includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php', |
724 | 725 | 'ResourceLoaderUserGroupsModule' => 'includes/resourceloader/ResourceLoaderUserGroupsModule.php', |
725 | 726 | 'ResourceLoaderUserModule' => 'includes/resourceloader/ResourceLoaderUserModule.php', |
726 | 727 | 'ResourceLoaderUserOptionsModule' => 'includes/resourceloader/ResourceLoaderUserOptionsModule.php', |
Property changes on: branches/REL1_19/phase3/includes/AutoLoader.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
727 | 728 | Merged /trunk/phase3/includes/AutoLoader.php:r111029,111034,111067,111085,111128,111144 |
Index: branches/REL1_19/phase3/includes/specials/SpecialEditWatchlist.php |
— | — | @@ -20,6 +20,8 @@ |
21 | 21 | |
22 | 22 | protected $toc; |
23 | 23 | |
| 24 | + private $badItems = array(); |
| 25 | + |
24 | 26 | public function __construct(){ |
25 | 27 | parent::__construct( 'EditWatchlist' ); |
26 | 28 | } |
— | — | @@ -221,11 +223,15 @@ |
222 | 224 | if( $res->numRows() > 0 ) { |
223 | 225 | foreach ( $res as $row ) { |
224 | 226 | $title = Title::makeTitleSafe( $row->wl_namespace, $row->wl_title ); |
225 | | - if( $title instanceof Title && !$title->isTalkPage() ) |
| 227 | + if ( $this->checkTitle( $title, $row->wl_namespace, $row->wl_title ) |
| 228 | + && !$title->isTalkPage() |
| 229 | + ) { |
226 | 230 | $list[] = $title->getPrefixedText(); |
| 231 | + } |
227 | 232 | } |
228 | 233 | $res->free(); |
229 | 234 | } |
| 235 | + $this->cleanupWatchlist(); |
230 | 236 | return $list; |
231 | 237 | } |
232 | 238 | |
— | — | @@ -260,6 +266,60 @@ |
261 | 267 | } |
262 | 268 | |
263 | 269 | /** |
| 270 | + * Validates watchlist entry |
| 271 | + * |
| 272 | + * @param Title $title |
| 273 | + * @param int $namespace |
| 274 | + * @param String $dbKey |
| 275 | + * @return bool: Whether this item is valid |
| 276 | + */ |
| 277 | + private function checkTitle( $title, $namespace, $dbKey ) { |
| 278 | + if ( $title |
| 279 | + && ( $title->isExternal() |
| 280 | + || $title->getNamespace() < 0 |
| 281 | + ) |
| 282 | + ) { |
| 283 | + $title = false; // unrecoverable |
| 284 | + } |
| 285 | + if ( !$title |
| 286 | + || $title->getNamespace() != $namespace |
| 287 | + || $title->getDBkey() != $dbKey |
| 288 | + ) { |
| 289 | + $this->badItems[] = array( $title, $namespace, $dbKey ); |
| 290 | + } |
| 291 | + return (bool)$title; |
| 292 | + } |
| 293 | + |
| 294 | + /** |
| 295 | + * Attempts to clean up broken items |
| 296 | + */ |
| 297 | + private function cleanupWatchlist() { |
| 298 | + if ( count( $this->badItems ) ) { |
| 299 | + $dbw = wfGetDB( DB_MASTER ); |
| 300 | + } |
| 301 | + foreach ( $this->badItems as $row ) { |
| 302 | + list( $title, $namespace, $dbKey ) = $row; |
| 303 | + wfDebug( "User {$this->getUser()} has broken watchlist item ns($namespace):$dbKey, " |
| 304 | + . ( $title ? 'cleaning up' : 'deleting' ) . ".\n" |
| 305 | + ); |
| 306 | + |
| 307 | + $dbw->delete( 'watchlist', |
| 308 | + array( |
| 309 | + 'wl_user' => $this->getUser()->getId(), |
| 310 | + 'wl_namespace' => $namespace, |
| 311 | + 'wl_title' => $dbKey, |
| 312 | + ), |
| 313 | + __METHOD__ |
| 314 | + ); |
| 315 | + |
| 316 | + // Can't just do an UPDATE instead of DELETE/INSERT due to unique index |
| 317 | + if ( $title ) { |
| 318 | + $this->getUser()->addWatch( $title ); |
| 319 | + } |
| 320 | + } |
| 321 | + } |
| 322 | + |
| 323 | + /** |
264 | 324 | * Remove all titles from a user's watchlist |
265 | 325 | */ |
266 | 326 | private function clearWatchlist() { |
— | — | @@ -372,30 +432,25 @@ |
373 | 433 | $fields = array(); |
374 | 434 | $count = 0; |
375 | 435 | |
376 | | - $haveInvalidNamespaces = false; |
377 | 436 | foreach( $this->getWatchlistInfo() as $namespace => $pages ){ |
378 | | - if ( $namespace < 0 ) { |
379 | | - $haveInvalidNamespaces = true; |
380 | | - continue; |
| 437 | + if ( $namespace >= 0 ) { |
| 438 | + $fields['TitlesNs'.$namespace] = array( |
| 439 | + 'class' => 'EditWatchlistCheckboxSeriesField', |
| 440 | + 'options' => array(), |
| 441 | + 'section' => "ns$namespace", |
| 442 | + ); |
381 | 443 | } |
382 | 444 | |
383 | | - $fields['TitlesNs'.$namespace] = array( |
384 | | - 'class' => 'EditWatchlistCheckboxSeriesField', |
385 | | - 'options' => array(), |
386 | | - 'section' => "ns$namespace", |
387 | | - ); |
388 | | - |
389 | 445 | foreach( array_keys( $pages ) as $dbkey ){ |
390 | 446 | $title = Title::makeTitleSafe( $namespace, $dbkey ); |
391 | | - $text = $this->buildRemoveLine( $title ); |
392 | | - $fields['TitlesNs'.$namespace]['options'][$text] = $title->getEscapedText(); |
393 | | - $count++; |
| 447 | + if ( $this->checkTitle( $title, $namespace, $dbkey ) ) { |
| 448 | + $text = $this->buildRemoveLine( $title ); |
| 449 | + $fields['TitlesNs'.$namespace]['options'][$text] = $title->getEscapedText(); |
| 450 | + $count++; |
| 451 | + } |
394 | 452 | } |
395 | 453 | } |
396 | | - if ( $haveInvalidNamespaces ) { |
397 | | - wfDebug( "User {$this->getContext()->getUser()->getId()} has invalid watchlist entries, cleaning up...\n" ); |
398 | | - $this->getContext()->getUser()->cleanupWatchlist(); |
399 | | - } |
| 454 | + $this->cleanupWatchlist(); |
400 | 455 | |
401 | 456 | if ( count( $fields ) > 1 && $count > 30 ) { |
402 | 457 | $this->toc = Linker::tocIndent(); |
Property changes on: branches/REL1_19/phase3/includes/specials |
___________________________________________________________________ |
Modified: svn:mergeinfo |
403 | 458 | Merged /trunk/phase3/includes/specials:r111085,111128,111144 |
Property changes on: branches/REL1_19/phase3/includes |
___________________________________________________________________ |
Modified: svn:mergeinfo |
404 | 459 | Merged /trunk/phase3/includes:r111029,111034,111067,111085,111128,111144 |
Index: branches/REL1_19/phase3/thumb.php |
— | — | @@ -173,6 +173,17 @@ |
174 | 174 | try { |
175 | 175 | $thumbName = $img->thumbName( $params ); |
176 | 176 | if ( strlen( $thumbName ) ) { // valid params? |
| 177 | + // For 404 handled thumbnails, we only use the the base name of the URI |
| 178 | + // for the thumb params and the parent directory for the source file name. |
| 179 | + // Check that the zone relative path matches up so squid caches won't pick |
| 180 | + // up thumbs that would not be purged on source file deletion (bug 34231). |
| 181 | + if ( isset( $params['rel404'] ) // thumbnail was handled via 404 |
| 182 | + && urldecode( $params['rel404'] ) !== $img->getThumbRel( $thumbName ) ) |
| 183 | + { |
| 184 | + wfThumbError( 404, 'The source file for the specified thumbnail does not exist.' ); |
| 185 | + wfProfileOut( __METHOD__ ); |
| 186 | + return; |
| 187 | + } |
177 | 188 | $thumbPath = $img->getThumbPath( $thumbName ); |
178 | 189 | if ( $img->getRepo()->fileExists( $thumbPath ) ) { |
179 | 190 | $img->getRepo()->streamFile( $thumbPath, $headers ); |
— | — | @@ -244,18 +255,18 @@ |
245 | 256 | $hashDirRegex .= "$subdirRegex/"; |
246 | 257 | } |
247 | 258 | |
248 | | - $thumbUrlRegex = "!^$zoneUrlRegex(/archive|/temp|)/$hashDirRegex([^/]*)/([^/]*)$!"; |
| 259 | + $thumbUrlRegex = "!^$zoneUrlRegex/((archive/|temp/)?$hashDirRegex([^/]*)/([^/]*))$!"; |
249 | 260 | |
250 | 261 | // Check if this is a valid looking thumbnail request... |
251 | 262 | if ( preg_match( $thumbUrlRegex, $uri, $matches ) ) { |
252 | | - list( /* all */, $archOrTemp, $filename, $thumbname ) = $matches; |
| 263 | + list( /* all */, $rel, $archOrTemp, $filename, $thumbname ) = $matches; |
253 | 264 | $filename = urldecode( $filename ); |
254 | 265 | $thumbname = urldecode( $thumbname ); |
255 | 266 | |
256 | | - $params = array( 'f' => $filename ); |
257 | | - if ( $archOrTemp == '/archive' ) { |
| 267 | + $params = array( 'f' => $filename, 'rel404' => $rel ); |
| 268 | + if ( $archOrTemp == 'archive/' ) { |
258 | 269 | $params['archived'] = 1; |
259 | | - } elseif ( $archOrTemp == '/temp' ) { |
| 270 | + } elseif ( $archOrTemp == 'temp/' ) { |
260 | 271 | $params['temp'] = 1; |
261 | 272 | } |
262 | 273 | |
Property changes on: branches/REL1_19/phase3/thumb.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
263 | 274 | Merged /trunk/phase3/thumb.php:r111076,111144 |
Index: branches/REL1_19/phase3/resources/Resources.php |
— | — | @@ -10,6 +10,7 @@ |
11 | 11 | 'user' => array( 'class' => 'ResourceLoaderUserModule' ), |
12 | 12 | 'user.groups' => array( 'class' => 'ResourceLoaderUserGroupsModule' ), |
13 | 13 | 'user.options' => array( 'class' => 'ResourceLoaderUserOptionsModule' ), |
| 14 | + 'user.cssprefs' => array( 'class' => 'ResourceLoaderUserCSSPrefsModule' ), |
14 | 15 | 'user.tokens' => array( 'class' => 'ResourceLoaderUserTokensModule' ), |
15 | 16 | 'filepage' => array( 'class' => 'ResourceLoaderFilePageModule' ), |
16 | 17 | |
— | — | @@ -824,6 +825,7 @@ |
825 | 826 | 'mediawiki.util', |
826 | 827 | 'mediawiki.legacy.wikibits', |
827 | 828 | ), |
| 829 | + 'position' => 'top', // Temporary hack for legacy support |
828 | 830 | ), |
829 | 831 | 'mediawiki.legacy.commonPrint' => array( |
830 | 832 | 'styles' => array( 'common/commonPrint.css' => array( 'media' => 'print' ) ), |
Index: branches/REL1_19/phase3/resources/mediawiki/mediawiki.js |
— | — | @@ -391,21 +391,34 @@ |
392 | 392 | } |
393 | 393 | |
394 | 394 | function addInlineCSS( css, media ) { |
395 | | - var $style = getMarker().prev(); |
| 395 | + var $style = getMarker().prev(), |
| 396 | + $newStyle, |
| 397 | + attrs = { 'type': 'text/css', 'media': media }; |
396 | 398 | if ( $style.is( 'style' ) && $style.data( 'ResourceLoaderDynamicStyleTag' ) === true ) { |
397 | 399 | // There's already a dynamic <style> tag present, append to it |
398 | 400 | // This recycling of <style> tags is for bug 31676 (can't have |
399 | 401 | // more than 32 <style> tags in IE) |
400 | 402 | |
401 | | - // Do cdata sanitization on the provided CSS, and prepend a double newline |
402 | | - css = $( mw.html.element( 'style', {}, new mw.html.Cdata( "\n\n" + css ) ) ).html(); |
403 | | - $style.append( css ); |
| 403 | + // Also, calling .append() on a <style> tag explodes with a JS error in IE, |
| 404 | + // so if the .append() fails we fall back to building a new <style> tag and |
| 405 | + // replacing the existing one |
| 406 | + try { |
| 407 | + // Do cdata sanitization on the provided CSS, and prepend a double newline |
| 408 | + css = $( mw.html.element( 'style', {}, new mw.html.Cdata( "\n\n" + css ) ) ).html(); |
| 409 | + $style.append( css ); |
| 410 | + } catch ( e ) { |
| 411 | + // Generate a new tag with the combined CSS |
| 412 | + css = $style.html() + "\n\n" + css; |
| 413 | + $newStyle = $( mw.html.element( 'style', attrs, new mw.html.Cdata( css ) ) ) |
| 414 | + .data( 'ResourceLoaderDynamicStyleTag', true ); |
| 415 | + // Prevent a flash of unstyled content by inserting the new tag |
| 416 | + // before removing the old one |
| 417 | + $style.after( $newStyle ); |
| 418 | + $style.remove(); |
| 419 | + } |
404 | 420 | } else { |
405 | 421 | // Create a new <style> tag and insert it |
406 | | - $style = $( mw.html.element( 'style', { |
407 | | - 'type': 'text/css', |
408 | | - 'media': media |
409 | | - }, new mw.html.Cdata( css ) ) ); |
| 422 | + $style = $( mw.html.element( 'style', attrs, new mw.html.Cdata( css ) ) ); |
410 | 423 | $style.data( 'ResourceLoaderDynamicStyleTag', true ); |
411 | 424 | getMarker().before( $style ); |
412 | 425 | } |
Property changes on: branches/REL1_19/phase3 |
___________________________________________________________________ |
Modified: svn:mergeinfo |
413 | 426 | Merged /trunk/phase3:r111029,111034,111067,111076,111085,111128,111144 |