Index: trunk/phase3/maintenance/language/messages.inc |
— | — | @@ -2058,8 +2058,11 @@ |
2059 | 2059 | 'allmessagescurrent', |
2060 | 2060 | 'allmessagestext', |
2061 | 2061 | 'allmessagesnotsupportedDB', |
2062 | | - 'allmessagesfilter', |
2063 | | - 'allmessagesmodified', |
| 2062 | + 'allmessages-filter', |
| 2063 | + 'allmessages-filter-unmodified', |
| 2064 | + 'allmessages-filter-all', |
| 2065 | + 'allmessages-filter-modified', |
| 2066 | + 'allmessages-prefix', |
2064 | 2067 | ), |
2065 | 2068 | 'thumbnails' => array( |
2066 | 2069 | 'thumbnail-more', |
Index: trunk/phase3/skins/monobook/main.css |
— | — | @@ -1259,25 +1259,6 @@ |
1260 | 1260 | font-weight:bold; |
1261 | 1261 | } |
1262 | 1262 | |
1263 | | -/* Allmessages table */ |
1264 | | - |
1265 | | -#allmessagestable th { |
1266 | | - background-color: #b2b2ff; |
1267 | | -} |
1268 | | - |
1269 | | -#allmessagestable tr.orig { |
1270 | | - background-color: #ffe2e2; |
1271 | | -} |
1272 | | - |
1273 | | -#allmessagestable tr.new { |
1274 | | - background-color: #e2ffe2; |
1275 | | -} |
1276 | | - |
1277 | | -#allmessagestable tr.def { |
1278 | | - background-color: #f0f0ff; |
1279 | | -} |
1280 | | - |
1281 | | - |
1282 | 1263 | /* noarticletext */ |
1283 | 1264 | div.noarticletext { |
1284 | 1265 | border: 1px solid #ccc; |
Index: trunk/phase3/skins/modern/main.css |
— | — | @@ -775,25 +775,6 @@ |
776 | 776 | font-weight:bold; |
777 | 777 | } |
778 | 778 | |
779 | | -/* Allmessages table */ |
780 | | - |
781 | | -#allmessagestable th { |
782 | | - background-color: #b2b2ff; |
783 | | -} |
784 | | - |
785 | | -#allmessagestable tr.orig { |
786 | | - background-color: #ffe2e2; |
787 | | -} |
788 | | - |
789 | | -#allmessagestable tr.new { |
790 | | - background-color: #e2ffe2; |
791 | | -} |
792 | | - |
793 | | -#allmessagestable tr.def { |
794 | | - background-color: #f0f0ff; |
795 | | -} |
796 | | - |
797 | | - |
798 | 779 | /* noarticletext */ |
799 | 780 | div.noarticletext { |
800 | 781 | border: 1px solid #ccc; |
Index: trunk/phase3/skins/common/allmessages.js |
— | — | @@ -1,83 +0,0 @@ |
2 | | -var allmessages_nodelist = false; |
3 | | -var allmessages_modified = false; |
4 | | -var allmessages_timeout = false; |
5 | | -var allmessages_running = false; |
6 | | - |
7 | | -function allmessagesmodified() { |
8 | | - allmessages_modified = !allmessages_modified; |
9 | | - allmessagesfilter(); |
10 | | -} |
11 | | - |
12 | | -function allmessagesfilter() { |
13 | | - if ( allmessages_timeout ) |
14 | | - window.clearTimeout( allmessages_timeout ); |
15 | | - |
16 | | - if ( !allmessages_running ) |
17 | | - allmessages_timeout = window.setTimeout( 'allmessagesfilter_do();', 500 ); |
18 | | -} |
19 | | - |
20 | | -function allmessagesfilter_do() { |
21 | | - if ( !allmessages_nodelist ) |
22 | | - return; |
23 | | - |
24 | | - var text = document.getElementById('allmessagesinput').value.toLowerCase(); |
25 | | - var nodef = allmessages_modified; |
26 | | - |
27 | | - allmessages_running = true; |
28 | | - |
29 | | - for ( var name in allmessages_nodelist ) { |
30 | | - var nodes = allmessages_nodelist[name]; |
31 | | - var display = ( name.toLowerCase().indexOf( text ) == -1 ? 'none' : '' ); |
32 | | - |
33 | | - for ( var i = 0; i < nodes.length; i++) |
34 | | - nodes[i].style.display = |
35 | | - ( nodes[i].className == "def" && nodef |
36 | | - ? 'none' : display ); |
37 | | - } |
38 | | - |
39 | | - if ( text != document.getElementById('allmessagesinput').value.toLowerCase() || |
40 | | - nodef != allmessages_modified ) |
41 | | - allmessagesfilter_do(); // repeat |
42 | | - |
43 | | - allmessages_running = false; |
44 | | -} |
45 | | - |
46 | | -function allmessagesfilter_init() { |
47 | | - if ( allmessages_nodelist ) |
48 | | - return; |
49 | | - |
50 | | - var nodelist = new Array(); |
51 | | - var templist = new Array(); |
52 | | - |
53 | | - var table = document.getElementById('allmessagestable'); |
54 | | - if ( !table ) return; |
55 | | - |
56 | | - var rows = document.getElementsByTagName('tr'); |
57 | | - for ( var i = 0; i < rows.length; i++ ) { |
58 | | - var id = rows[i].getAttribute('id') |
59 | | - if ( id && id.substring(0,16) != 'sp-allmessages-r' ) continue; |
60 | | - templist[ id ] = rows[i]; |
61 | | - } |
62 | | - |
63 | | - var spans = table.getElementsByTagName('span'); |
64 | | - for ( var i = 0; i < spans.length; i++ ) { |
65 | | - var id = spans[i].getAttribute('id') |
66 | | - if ( id && id.substring(0,17) != 'sp-allmessages-i-' ) continue; |
67 | | - if ( !spans[i].firstChild || spans[i].firstChild.nodeType != 3 ) continue; |
68 | | - |
69 | | - var nodes = new Array(); |
70 | | - var row1 = templist[ id.replace('i', 'r1') ]; |
71 | | - var row2 = templist[ id.replace('i', 'r2') ]; |
72 | | - |
73 | | - if ( row1 ) nodes[nodes.length] = row1; |
74 | | - if ( row2 ) nodes[nodes.length] = row2; |
75 | | - nodelist[ spans[i].firstChild.nodeValue ] = nodes; |
76 | | - } |
77 | | - |
78 | | - var k = document.getElementById('allmessagesfilter'); |
79 | | - if (k) { k.style.display = ''; } |
80 | | - |
81 | | - allmessages_nodelist = nodelist; |
82 | | -} |
83 | | - |
84 | | -hookEvent( "load", allmessagesfilter_init ); |
Index: trunk/phase3/skins/common/shared.css |
— | — | @@ -620,6 +620,23 @@ |
621 | 621 | .imagelist .TablePager_col_img_description { white-space: normal } |
622 | 622 | .imagelist th.TablePager_sort { background-color: #ccccff } |
623 | 623 | |
| 624 | + /* Allmessages table */ |
| 625 | +#allmessagestable .allmessages-customised td.am_default { |
| 626 | + background-color: #fcffc4; |
| 627 | +} |
| 628 | + |
| 629 | +#allmessagestable tr.allmessages-customised:hover td.am_default { |
| 630 | + background-color: #faff90; |
| 631 | +} |
| 632 | + |
| 633 | +#allmessagestable td.am_actual { |
| 634 | + background-color: #e2ffe2; |
| 635 | +} |
| 636 | + |
| 637 | +#allmessagestable tr.allmessages-customised:hover + tr.allmessages-customised td.am_actual { |
| 638 | + background-color: #b1ffb1; |
| 639 | +} |
| 640 | + |
624 | 641 | /* filetoc */ |
625 | 642 | ul#filetoc { |
626 | 643 | text-align: center; |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -479,6 +479,7 @@ |
480 | 480 | 'MWTidy' => 'includes/parser/Tidy.php', |
481 | 481 | |
482 | 482 | # includes/specials |
| 483 | + 'SpecialAllmessages' => 'includes/specials/SpecialAllmessages.php', |
483 | 484 | 'AncientPagesPage' => 'includes/specials/SpecialAncientpages.php', |
484 | 485 | 'BrokenRedirectsPage' => 'includes/specials/SpecialBrokenRedirects.php', |
485 | 486 | 'ContribsPager' => 'includes/specials/SpecialContributions.php', |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -1566,7 +1566,7 @@ |
1567 | 1567 | * to ensure that client-side caches do not keep obsolete copies of global |
1568 | 1568 | * styles. |
1569 | 1569 | */ |
1570 | | -$wgStyleVersion = '231'; |
| 1570 | +$wgStyleVersion = '232'; |
1571 | 1571 | |
1572 | 1572 | |
1573 | 1573 | # Server-side caching: |
Index: trunk/phase3/includes/specials/SpecialAllmessages.php |
— | — | @@ -4,249 +4,380 @@ |
5 | 5 | * @file |
6 | 6 | * @ingroup SpecialPage |
7 | 7 | */ |
8 | | - |
9 | | -/** |
10 | | - * Constructor. |
11 | | - */ |
12 | | -function wfSpecialAllmessages() { |
13 | | - global $wgOut, $wgRequest, $wgMessageCache; |
14 | | - global $wgUseDatabaseMessages, $wgLang; |
15 | | - |
16 | | - # The page isn't much use if the MediaWiki namespace is not being used |
17 | | - if( !$wgUseDatabaseMessages ) { |
18 | | - $wgOut->addWikiMsg( 'allmessagesnotsupportedDB' ); |
19 | | - return; |
| 8 | +class SpecialAllmessages extends SpecialPage { |
| 9 | + |
| 10 | + /** |
| 11 | + * Constructor |
| 12 | + */ |
| 13 | + public function __construct() { |
| 14 | + parent::__construct( 'Allmessages' ); |
20 | 15 | } |
| 16 | + |
| 17 | + /** |
| 18 | + * Execute |
| 19 | + */ |
| 20 | + function execute( $par ) { |
| 21 | + global $wgOut, $wgRequest; |
| 22 | + |
| 23 | + $this->setHeaders(); |
| 24 | + |
| 25 | + global $wgUseDatabaseMessages; |
| 26 | + if( !$wgUseDatabaseMessages ) { |
| 27 | + $wgOut->addWikiMsg( 'allmessagesnotsupportedDB' ); |
| 28 | + return; |
| 29 | + } else { |
| 30 | + $this->outputHeader( 'allmessagestext' ); |
| 31 | + } |
21 | 32 | |
22 | | - wfProfileIn( __METHOD__ ); |
23 | | - |
24 | | - wfProfileIn( __METHOD__ . '-setup' ); |
25 | | - $ot = $wgRequest->getText( 'ot' ); |
26 | | - |
27 | | - $navText = wfMsg( 'allmessagestext' ); |
28 | | - |
29 | | - # Make sure all extension messages are available |
30 | | - |
31 | | - $wgMessageCache->loadAllMessages(); |
32 | | - |
33 | | - $sortedArray = Language::getMessagesFor( 'en' ); |
34 | | - ksort( $sortedArray ); |
35 | | - |
36 | | - $messages = array(); |
37 | | - foreach( $sortedArray as $key => $value ) { |
38 | | - $messages[$key]['enmsg'] = $value; |
39 | | - $messages[$key]['statmsg'] = wfMsgReal( $key, array(), false, false, false ); |
40 | | - $messages[$key]['msg'] = wfMsgNoTrans( $key ); |
41 | | - $sortedArray[$key] = NULL; // trade bytes from $sortedArray to this |
| 33 | + $this->filter = $wgRequest->getVal( 'filter', 'all' ); |
| 34 | + $this->prefix = $wgRequest->getVal( 'prefix', '' ); |
42 | 35 | |
| 36 | + $this->table = new AllmessagesTablePager( $this, |
| 37 | + $conds=array(), |
| 38 | + wfGetLangObj( $wgRequest->getVal( 'lang', false ) ) ); |
| 39 | + |
| 40 | + $this->langCode = $this->table->lang->getCode(); |
| 41 | + |
| 42 | + $wgOut->addHTML( $this->buildForm() . |
| 43 | + $this->table->getNavigationBar() . |
| 44 | + $this->table->getLimitForm() . |
| 45 | + $this->table->getBody() . |
| 46 | + $this->table->getNavigationBar() ); |
| 47 | + |
43 | 48 | } |
44 | | - unset($sortedArray); // trade bytes from $sortedArray to this |
45 | | - |
46 | | - wfProfileOut( __METHOD__ . '-setup' ); |
47 | | - |
48 | | - wfProfileIn( __METHOD__ . '-output' ); |
49 | | - $wgOut->addScriptFile( 'allmessages.js' ); |
50 | | - $title = SpecialPage::getTitleFor( 'Allmessages' ); |
51 | | - if ( $ot == 'php' ) { |
52 | | - $navText .= wfAllMessagesMakePhp( $messages ); |
53 | | - $wgOut->addHTML( $wgLang->pipeList( array( |
54 | | - 'PHP', |
55 | | - '<a href="' . $title->escapeLocalUrl( array( 'ot' => 'html' ) ) . '">HTML</a>', |
56 | | - '<a href="' . $title->escapeLocalUrl( array( 'ot' => 'xml' ) ) . '">XML</a>' . |
57 | | - '<pre>' . htmlspecialchars( $navText ) . '</pre>' |
58 | | - ) ) ); |
59 | | - } else if ( $ot == 'xml' ) { |
60 | | - $wgOut->disable(); |
61 | | - header( 'Content-type: text/xml' ); |
62 | | - echo wfAllMessagesMakeXml( $messages ); |
63 | | - } else { |
64 | | - $wgOut->addHTML( $wgLang->pipeList( array( |
65 | | - '<a href="' . $title->escapeLocalUrl( array( 'ot' => 'php' ) ) . '">PHP</a>', |
66 | | - 'HTML', |
67 | | - '<a href="' . $title->escapeLocalUrl( array( 'ot' => 'xml' ) ) . '">XML</a>' |
68 | | - ) ) ); |
69 | | - $wgOut->addWikiText( $navText ); |
70 | | - $wgOut->addHTML( wfAllMessagesMakeHTMLText( $messages ) ); |
| 49 | + |
| 50 | + function buildForm() { |
| 51 | + $url = $this->getTitle()->escapeLocalURL(); |
| 52 | + $languages = Language::getLanguageNames( false ); |
| 53 | + ksort( $languages ); |
| 54 | + |
| 55 | + $out = "<form method=\"get\" action=\"$url\"><fieldset>\n" . |
| 56 | + Xml::element( 'legend', null, wfMsg( 'allmessages' ) ) . "<table><tr>\n" . |
| 57 | + "<td class=\"mw-label\">" . |
| 58 | + Xml::label( wfMsg('allmessages-prefix'), 'am-form-prefix' ) . |
| 59 | + "</td>\n<td class=\"mw-input\">" . |
| 60 | + Xml::input( 'prefix', 20, str_replace('_',' ',$this->prefix), array( 'id' => 'am-form-prefix' ) ) . |
| 61 | + "</select>" . |
| 62 | + "</td>\n</tr><tr>\n<td class='mw-label'>" . |
| 63 | + Xml::label( wfMsg('allmessages-filter'), 'am-form-filter' ) . |
| 64 | + "</td>\n<td class='mw-input'>" . |
| 65 | + Xml::radioLabel( wfMsg('allmessages-filter-unmodified'), |
| 66 | + 'filter', |
| 67 | + 'unmodified', |
| 68 | + 'am-form-filter-unmodified', |
| 69 | + ( $this->filter == 'unmodified' ? true : false ) |
| 70 | + ) . |
| 71 | + Xml::radioLabel( wfMsg('allmessages-filter-all'), |
| 72 | + 'filter', |
| 73 | + 'all', |
| 74 | + 'am-form-filter-all', |
| 75 | + ( $this->filter == 'all' ? true : false ) |
| 76 | + ) . |
| 77 | + Xml::radioLabel( wfMsg('allmessages-filter-modified'), |
| 78 | + 'filter', |
| 79 | + 'modified', |
| 80 | + 'am-form-filter-modified', |
| 81 | + ( $this->filter == 'modified' ? true : false ) |
| 82 | + ) . |
| 83 | + "</td>\n</tr><tr>\n<td class=\"mw-label\">" . |
| 84 | + Xml::label( wfMsg('yourlanguage'), 'am-form-lang' ) . |
| 85 | + "</td>\n<td class=\"mw-input\">" . |
| 86 | + Xml::openElement( 'select', array( 'id' => 'am-form-lang', 'name' => 'lang' ) ); |
| 87 | + foreach( $languages as $lang => $name ) { |
| 88 | + $selected = $lang == $this->langCode ? 'selected="selected"' : ''; |
| 89 | + $out .= "<option value=\"$lang\" $selected>$name</option>\n"; |
| 90 | + } |
| 91 | + $out .= "</td>\n</tr><tr>\n<td></td><td>" . Xml::submitButton( wfMsg('allpagessubmit') ) . |
| 92 | + "</table>" . |
| 93 | + $this->table->getHiddenFields( array( 'title', 'prefix', 'filter', 'lang' ) ) . |
| 94 | + "</fieldset></form>"; |
| 95 | + return $out; |
71 | 96 | } |
72 | | - wfProfileOut( __METHOD__ . '-output' ); |
73 | | - |
74 | | - wfProfileOut( __METHOD__ ); |
75 | 97 | } |
76 | 98 | |
77 | | -function wfAllMessagesMakeXml( &$messages ) { |
78 | | - global $wgLang; |
79 | | - $lang = $wgLang->getCode(); |
80 | | - $txt = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; |
81 | | - $txt .= "<messages lang=\"$lang\">\n"; |
82 | | - foreach( $messages as $key => $m ) { |
83 | | - $txt .= "\t" . Xml::element( 'message', array( 'name' => $key ), $m['msg'] ) . "\n"; |
84 | | - $messages[$key] = NULL; // trade bytes |
85 | | - } |
86 | | - $txt .= "</messages>"; |
87 | | - return $txt; |
88 | | -} |
89 | | - |
90 | | -/** |
91 | | - * Create the messages array, formatted in PHP to copy to language files. |
92 | | - * @param $messages Messages array. |
93 | | - * @return The PHP messages array. |
94 | | - * @todo Make suitable for language files. |
| 99 | +/* use TablePager for prettified output. We have to pretend that we're |
| 100 | + * getting data from a table when in fact not all of it comes from the database. |
95 | 101 | */ |
96 | | -function wfAllMessagesMakePhp( &$messages ) { |
97 | | - global $wgLang; |
98 | | - $txt = "\n\n\$messages = array(\n"; |
99 | | - foreach( $messages as $key => $m ) { |
100 | | - if( $wgLang->getCode() != 'en' && $m['msg'] == $m['enmsg'] ) { |
101 | | - continue; |
102 | | - } else if ( wfEmptyMsg( $key, $m['msg'] ) ) { |
103 | | - $m['msg'] = ''; |
104 | | - $comment = ' #empty'; |
| 102 | +class AllmessagesTablePager extends TablePager { |
| 103 | + |
| 104 | + var $messages = NULL; |
| 105 | + var $talkPages = NULL; |
| 106 | + |
| 107 | + function __construct( $page, $conds, $langObj = NULL ) { |
| 108 | + parent::__construct(); |
| 109 | + $this->mIndexField = 'am_title'; |
| 110 | + $this->mPage = $page; |
| 111 | + $this->mConds = $conds; |
| 112 | + $this->mDefaultDirection = true; //always sort ascending |
| 113 | + |
| 114 | + global $wgLang, $wgContLang, $wgRequest; |
| 115 | + |
| 116 | + $this->talk = $wgLang->lc( htmlspecialchars( wfMsg( 'talkpagelinktext' ) ) ); |
| 117 | + |
| 118 | + $this->lang = ( $langObj ? $langObj : $wgContLang ); |
| 119 | + $this->langcode = $this->lang->getCode(); |
| 120 | + $this->foreign = $this->langcode != $wgContLang->getCode(); |
| 121 | + |
| 122 | + if( $wgRequest->getVal( 'filter', 'all' ) === 'all' ){ |
| 123 | + $this->custom = NULL; //So won't match in either case |
105 | 124 | } else { |
106 | | - $comment = ''; |
| 125 | + $this->custom = $wgRequest->getVal( 'filter' ) == 'unmodified' ? 1 : 0; |
107 | 126 | } |
108 | | - $txt .= "'$key' => '" . preg_replace( '/(?<!\\\\)\'/', "\'", $m['msg']) . "',$comment\n"; |
109 | | - $messages[$key] = NULL; // trade bytes |
| 127 | + |
| 128 | + $prefix = $wgLang->ucfirst( $wgRequest->getVal( 'prefix', '' ) ); |
| 129 | + $prefix = $prefix != '' ? Title::makeTitleSafe( NS_MEDIAWIKI, $wgRequest->getVal( 'prefix', NULL ) ) : NULL; |
| 130 | + if( $prefix !== NULL ){ |
| 131 | + $this->prefix = '/^' . preg_quote( $prefix->getDBkey() ) . '/i'; |
| 132 | + } else { |
| 133 | + $this->prefix = false; |
| 134 | + } |
| 135 | + $this->getSkin(); |
| 136 | + |
| 137 | + //The suffix that may be needed for message names if we're in a |
| 138 | + //different language (eg [[MediaWiki:Foo/fr]]: $suffix = '/fr' |
| 139 | + if( $this->foreign ) { |
| 140 | + $this->suffix = '/' . $this->langcode; |
| 141 | + } else { |
| 142 | + $this->suffix = ''; |
| 143 | + } |
110 | 144 | } |
111 | | - $txt .= ');'; |
112 | | - return $txt; |
113 | | -} |
114 | | - |
115 | | -/** |
116 | | - * Create a list of messages, formatted in HTML as a list of messages and values and showing differences between the default language file message and the message in MediaWiki: namespace. |
117 | | - * @param $messages Messages array. |
118 | | - * @return The HTML list of messages. |
119 | | - */ |
120 | | -function wfAllMessagesMakeHTMLText( &$messages ) { |
121 | | - global $wgLang, $wgContLang, $wgUser; |
122 | | - wfProfileIn( __METHOD__ ); |
123 | | - |
124 | | - $sk = $wgUser->getSkin(); |
125 | | - $talk = wfMsg( 'talkpagelinktext' ); |
126 | | - |
127 | | - $input = Xml::element( 'input', array( |
128 | | - 'type' => 'text', |
129 | | - 'id' => 'allmessagesinput', |
130 | | - 'onkeyup' => 'allmessagesfilter()' |
131 | | - ), '' ); |
132 | | - $checkbox = Xml::element( 'input', array( |
133 | | - 'type' => 'button', |
134 | | - 'value' => wfMsgHtml( 'allmessagesmodified' ), |
135 | | - 'id' => 'allmessagescheckbox', |
136 | | - 'onclick' => 'allmessagesmodified()' |
137 | | - ), '' ); |
138 | | - |
139 | | - $txt = '<span id="allmessagesfilter" style="display: none;">' . wfMsgHtml( 'allmessagesfilter' ) . |
140 | | - " {$input}{$checkbox} " . '</span>'; |
141 | | - |
142 | | - $txt .= ' |
143 | | -<table border="1" cellspacing="0" width="100%" id="allmessagestable"> |
144 | | - <tr> |
145 | | - <th rowspan="2">' . wfMsgHtml( 'allmessagesname' ) . '</th> |
146 | | - <th>' . wfMsgHtml( 'allmessagesdefault' ) . '</th> |
147 | | - </tr> |
148 | | - <tr> |
149 | | - <th>' . wfMsgHtml( 'allmessagescurrent' ) . '</th> |
150 | | - </tr>'; |
151 | | - |
152 | | - wfProfileIn( __METHOD__ . "-check" ); |
153 | | - |
154 | | - # This is a nasty hack to avoid doing independent existence checks |
155 | | - # without sending the links and table through the slow wiki parser. |
156 | | - $pageExists = array( |
157 | | - NS_MEDIAWIKI => array(), |
158 | | - NS_MEDIAWIKI_TALK => array() |
159 | | - ); |
160 | | - $dbr = wfGetDB( DB_SLAVE ); |
161 | | - $res = $dbr->select( 'page', |
162 | | - array( 'page_namespace', 'page_title' ), |
163 | | - array( 'page_namespace' => array(NS_MEDIAWIKI,NS_MEDIAWIKI_TALK) ), |
164 | | - __METHOD__, |
165 | | - array( 'USE INDEX' => 'name_title' ) |
166 | | - ); |
167 | | - while( $s = $dbr->fetchObject( $res ) ) { |
168 | | - $pageExists[$s->page_namespace][$s->page_title] = 1; |
| 145 | + |
| 146 | + function getAllMessages( $desc ){ |
| 147 | + |
| 148 | + wfProfileIn( __METHOD__ . '-cache' ); |
| 149 | + |
| 150 | + # Make sure all extension messages are available |
| 151 | + global $wgMessageCache; |
| 152 | + $wgMessageCache->loadAllMessages( 'en' ); |
| 153 | + $sortedArray = Language::getMessagesFor( 'en' ); |
| 154 | + if( $desc ){ |
| 155 | + krsort( $sortedArray ); |
| 156 | + } else { |
| 157 | + ksort( $sortedArray ); |
| 158 | + } |
| 159 | + |
| 160 | + $this->messages = array(); |
| 161 | + foreach( $sortedArray as $key => $value ) { |
| 162 | + // All messages start with lowercase, but wikis might have both |
| 163 | + // upper and lowercase MediaWiki: pages if $wgCapitalLinks=false. |
| 164 | + $ukey = $this->lang->ucfirst( $key ); |
| 165 | + |
| 166 | + // The value without any overrides from the MediaWiki: namespace |
| 167 | + $this->messages[$ukey]['default'] = wfMsgGetKey( $key, /*useDB*/false, $this->langcode, false ); |
| 168 | + |
| 169 | + // The message that's actually used by the site |
| 170 | + $this->messages[$ukey]['actual'] = wfMsgGetKey( $key, /*useDB*/true, $this->langcode, false ); |
| 171 | + |
| 172 | + $this->messages[$ukey]['customised'] = 0; //for now |
| 173 | + |
| 174 | + $sortedArray[$key] = NULL; // trade bytes from $sortedArray to this |
| 175 | + } |
| 176 | + |
| 177 | + wfProfileOut( __METHOD__ . '-cache' ); |
| 178 | + |
| 179 | + return true; |
169 | 180 | } |
170 | | - $dbr->freeResult( $res ); |
171 | | - wfProfileOut( __METHOD__ . "-check" ); |
| 181 | + |
| 182 | + # We only need a list of which messages have *been* customised; |
| 183 | + # their content is already in the message cache. |
| 184 | + function markCustomisedMessages(){ |
| 185 | + $this->talkPages = array(); |
| 186 | + |
| 187 | + wfProfileIn( __METHOD__ . "-db" ); |
172 | 188 | |
173 | | - wfProfileIn( __METHOD__ . "-output" ); |
174 | | - |
175 | | - $i = 0; |
176 | | - |
177 | | - foreach( $messages as $key => $m ) { |
178 | | - $title = $wgLang->ucfirst( $key ); |
179 | | - if( $wgLang->getCode() != $wgContLang->getCode() ) { |
180 | | - $title .= '/' . $wgLang->getCode(); |
| 189 | + $dbr = wfGetDB( DB_SLAVE ); |
| 190 | + $res = $dbr->select( 'page', |
| 191 | + array( 'page_namespace', 'page_title' ), |
| 192 | + array( 'page_namespace' => array(NS_MEDIAWIKI,NS_MEDIAWIKI_TALK) ), |
| 193 | + __METHOD__, |
| 194 | + array( 'USE INDEX' => 'name_title' ) |
| 195 | + ); |
| 196 | + |
| 197 | + while( $s = $dbr->fetchObject( $res ) ) { |
| 198 | + if( $s->page_namespace == NS_MEDIAWIKI ){ |
| 199 | + if( $this->foreign ){ |
| 200 | + $title = explode( '/', $s->page_title ); |
| 201 | + if( $this->langcode == $title[1] && array_key_exists( $title[0], $this->messages ) ){ |
| 202 | + $this->messages["{$title[0]}"]['customised'] = 1; |
| 203 | + } |
| 204 | + } else if( array_key_exists( $s->page_title , $this->messages ) ){ |
| 205 | + $this->messages[$s->page_title]['customised'] = 1; |
| 206 | + } |
| 207 | + } else if( $s->page_namespace == NS_MEDIAWIKI_TALK ){ |
| 208 | + $this->talkPages[$s->page_title] = 1; |
| 209 | + } |
181 | 210 | } |
| 211 | + $dbr->freeResult( $res ); |
| 212 | + |
| 213 | + wfProfileOut( __METHOD__ . "-db" ); |
| 214 | + |
| 215 | + return true; |
| 216 | + } |
| 217 | + |
| 218 | + /* This function normally does a database query to get the results; we need |
| 219 | + * to make a pretend result using a FakeResultWrapper. |
| 220 | + */ |
| 221 | + function reallyDoQuery( $offset , $limit , $descending ){ |
| 222 | + $mResult = new FakeResultWrapper( array() ); |
| 223 | + |
| 224 | + if( !$this->messages ) $this->getAllMessages( $descending ); |
| 225 | + if( $this->talkPages === NULL ) $this->markCustomisedMessages(); |
| 226 | + |
| 227 | + $count = 0; |
| 228 | + foreach( $this->messages as $key => $value ){ |
| 229 | + if( $value['customised'] !== $this->custom && |
| 230 | + ( $descending && ( $key < $offset || !$offset ) || !$descending && $key > $offset ) && |
| 231 | + (( $this->prefix && preg_match( $this->prefix, $key ) ) || $this->prefix === false ) |
| 232 | + ){ |
| 233 | + $mResult->result[] = array( 'am_title' => $key, |
| 234 | + 'am_actual' => $value['actual'], |
| 235 | + 'am_default' => $value['default'], |
| 236 | + 'am_customised' => $value['customised'], |
| 237 | + ); |
| 238 | + unset( $this->messages[$key] ); // save a few bytes |
| 239 | + $count++; |
| 240 | + } |
| 241 | + if( $count == $limit ) break; |
| 242 | + } |
| 243 | + unset( $this->messages ); //no longer needed, free up some memory |
| 244 | + return $mResult; |
| 245 | + } |
| 246 | + |
| 247 | + function getStartBody() { |
| 248 | + return "<table border=\"1\" class=\"TablePager\" style=\"width:100%;\" id=\"allmessagestable\"><thead>\n<tr>" . |
| 249 | + "<th rowspan=\"2\">" . wfMsg('allmessagesname') . "</th><th>" . wfMsg('allmessagesdefault') . |
| 250 | + "</tr>\n<tr><th>" . wfMsg('allmessagescurrent') . "</th></tr>\n"; |
| 251 | + } |
| 252 | + |
| 253 | + function formatValue( $field , $value ){ |
| 254 | + global $wgLang; |
| 255 | + switch( $field ){ |
| 256 | + |
| 257 | + case 'am_title' : |
| 258 | + |
| 259 | + $title = Title::makeTitle( NS_MEDIAWIKI, $value . $this->suffix ); |
| 260 | + $talk = Title::makeTitle( NS_MEDIAWIKI_TALK, $value . $this->suffix ); |
182 | 261 | |
183 | | - $titleObj = Title::makeTitle( NS_MEDIAWIKI, $title ); |
184 | | - $talkPage = Title::makeTitle( NS_MEDIAWIKI_TALK, $title ); |
185 | | - |
186 | | - $changed = ( $m['statmsg'] != $m['msg'] ); |
187 | | - $message = htmlspecialchars( $m['statmsg'] ); |
188 | | - $mw = htmlspecialchars( $m['msg'] ); |
189 | | - |
190 | | - $linkText = "<span id=\"sp-allmessages-i-$i\">" . htmlspecialchars( $key ) . '</span>'; |
191 | | - |
192 | | - if( array_key_exists( $title, $pageExists[NS_MEDIAWIKI] ) ) { |
193 | | - // FIXME: the span should be taken care of in $customAttribs, shouldn't it? |
194 | | - $pageLink = $sk->linkKnown( |
195 | | - $titleObj, |
196 | | - $linkText |
197 | | - ); |
198 | | - } else { |
199 | | - $pageLink = $sk->link( |
200 | | - $titleObj, |
201 | | - $linkText, |
202 | | - array(), |
203 | | - array(), |
204 | | - array( 'broken' ) |
205 | | - ); |
| 262 | + if( $this->mCurrentRow->am_customised ){ |
| 263 | + $title = $this->mSkin->linkKnown( $title, $wgLang->lcfirst( $value ) ); |
| 264 | + } else { |
| 265 | + $title = $this->mSkin->link( $title, |
| 266 | + $wgLang->lcfirst( $value ), |
| 267 | + array(), |
| 268 | + array(), |
| 269 | + array( 'broken' ) ); |
| 270 | + } |
| 271 | + if( array_key_exists( $talk->getDBkey() , $this->talkPages ) ) { |
| 272 | + $talk = $this->mSkin->linkKnown( $talk , $this->talk ); |
| 273 | + } else { |
| 274 | + $talk = $this->mSkin->link( $talk, |
| 275 | + $this->talk, |
| 276 | + array(), |
| 277 | + array(), |
| 278 | + array( 'broken' ) ); |
| 279 | + } |
| 280 | + return $title . ' (' . $talk . ')'; |
| 281 | + |
| 282 | + case 'am_default' : |
| 283 | + return Sanitizer::escapeHtmlAllowEntities( $value, ENT_QUOTES ); |
| 284 | + case 'am_actual' : |
| 285 | + return Sanitizer::escapeHtmlAllowEntities( $value, ENT_QUOTES ); |
206 | 286 | } |
207 | | - if( array_key_exists( $title, $pageExists[NS_MEDIAWIKI_TALK] ) ) { |
208 | | - $talkLink = $sk->linkKnown( $talkPage, htmlspecialchars( $talk ) ); |
209 | | - } else { |
210 | | - $talkLink = $sk->link( |
211 | | - $talkPage, |
212 | | - htmlspecialchars( $talk ), |
213 | | - array(), |
214 | | - array(), |
215 | | - array( 'broken' ) |
216 | | - ); |
| 287 | + return ''; |
| 288 | + } |
| 289 | + |
| 290 | + function formatRow( $row ){ |
| 291 | + //Do all the normal stuff |
| 292 | + $s = parent::formatRow( $row ); |
| 293 | + |
| 294 | + //But if there's a customised message, add that too. |
| 295 | + if( $row->am_customised ){ |
| 296 | + $s .= Xml::openElement( 'tr', $this->getRowAttrs( $row, true ) ); |
| 297 | + $formatted = strval( $this->formatValue( 'am_actual', $row->am_actual ) ); |
| 298 | + if ( $formatted == '' ) { |
| 299 | + $formatted = ' '; |
| 300 | + } |
| 301 | + $s .= Xml::tags( 'td', $this->getCellAttrs( 'am_actual', $row->am_actual ), $formatted ) |
| 302 | + . "</tr>\n"; |
217 | 303 | } |
218 | | - |
219 | | - $anchor = 'msg_' . htmlspecialchars( strtolower( $title ) ); |
220 | | - $anchor = "<a id=\"$anchor\" name=\"$anchor\"></a>"; |
221 | | - |
222 | | - if( $changed ) { |
223 | | - $txt .= " |
224 | | - <tr class=\"orig\" id=\"sp-allmessages-r1-$i\"> |
225 | | - <td rowspan=\"2\"> |
226 | | - $anchor$pageLink<br />$talkLink |
227 | | - </td><td> |
228 | | - $message |
229 | | - </td> |
230 | | - </tr><tr class=\"new\" id=\"sp-allmessages-r2-$i\"> |
231 | | - <td> |
232 | | - $mw |
233 | | - </td> |
234 | | - </tr>"; |
| 304 | + return $s; |
| 305 | + } |
| 306 | + |
| 307 | + function getRowAttrs( $row, $isSecond=false ){ |
| 308 | + $arr = array(); |
| 309 | + global $wgLang; |
| 310 | + if( $row->am_customised ){ |
| 311 | + $arr['class'] = 'allmessages-customised'; |
| 312 | + } |
| 313 | + if( !$isSecond ){ |
| 314 | + $arr['id'] = Sanitizer::escapeId( 'msg_' . $wgLang->lcfirst( $row->am_title ) ); |
| 315 | + } |
| 316 | + return $arr; |
| 317 | + } |
| 318 | + |
| 319 | + function getCellAttrs( $field, $value ){ |
| 320 | + if( $this->mCurrentRow->am_customised && $field == 'am_title' ){ |
| 321 | + return array( 'rowspan' => '2', 'class' => $field ); |
235 | 322 | } else { |
236 | | - $txt .= " |
237 | | - <tr class=\"def\" id=\"sp-allmessages-r1-$i\"> |
238 | | - <td> |
239 | | - $anchor$pageLink<br />$talkLink |
240 | | - </td><td> |
241 | | - $mw |
242 | | - </td> |
243 | | - </tr>"; |
| 323 | + return array( 'class' => $field ); |
244 | 324 | } |
245 | | - $messages[$key] = NULL; // trade bytes |
246 | | - $i++; |
247 | 325 | } |
248 | | - $txt .= '</table>'; |
249 | | - wfProfileOut( __METHOD__ . '-output' ); |
| 326 | + |
| 327 | + // This is not actually used, as getStartBody is overridden above |
| 328 | + function getFieldNames() { |
| 329 | + return array( 'am_title' => wfMsg('allmessagesname'), |
| 330 | + 'am_default' => wfMsg('allmessagesdefault') ); |
| 331 | + } |
| 332 | + function getTitle() { |
| 333 | + return SpecialPage::getTitleFor( 'Allmessages', false ); |
| 334 | + } |
| 335 | + function isFieldSortable( $x ){ |
| 336 | + return false; |
| 337 | + } |
| 338 | + function getDefaultSort(){ |
| 339 | + return ''; |
| 340 | + } |
| 341 | + function getQueryInfo(){ |
| 342 | + return ''; |
| 343 | + } |
| 344 | +} |
| 345 | +/* Overloads the relevant methods of the real ResultsWrapper so it |
| 346 | + * doesn't go anywhere near an actual database. |
| 347 | + */ |
| 348 | +class FakeResultWrapper extends ResultWrapper { |
| 349 | + |
| 350 | + var $result = array(); |
| 351 | + var $db = NULL; //And it's going to stay that way :D |
| 352 | + var $pos = 0; |
| 353 | + var $currentRow = NULL; |
| 354 | + |
| 355 | + function __construct( $array ){ |
| 356 | + $this->result = $array; |
| 357 | + } |
| 358 | + |
| 359 | + function numRows() { |
| 360 | + return count( $this->result ); |
| 361 | + } |
| 362 | + |
| 363 | + function fetchRow() { |
| 364 | + $this->currentRow = $this->result[$this->pos++]; |
| 365 | + return $this->currentRow; |
| 366 | + } |
| 367 | + |
| 368 | + function seek( $row ) { |
| 369 | + $this->pos = $row; |
| 370 | + } |
250 | 371 | |
251 | | - wfProfileOut( __METHOD__ ); |
252 | | - return $txt; |
| 372 | + function free() {} |
| 373 | + |
| 374 | + // Callers want to be able to access fields with $this->fieldName |
| 375 | + function fetchObject(){ |
| 376 | + $this->currentRow = $this->result[$this->pos++]; |
| 377 | + return (object)$this->currentRow; |
| 378 | + } |
| 379 | + |
| 380 | + function rewind() { |
| 381 | + $this->pos = 0; |
| 382 | + $this->currentRow = NULL; |
| 383 | + } |
253 | 384 | } |
Index: trunk/phase3/includes/SpecialPage.php |
— | — | @@ -145,7 +145,7 @@ |
146 | 146 | |
147 | 147 | # Wiki data and tools |
148 | 148 | 'Statistics' => 'SpecialStatistics', |
149 | | - 'Allmessages' => array( 'SpecialPage', 'Allmessages' ), |
| 149 | + 'Allmessages' => 'SpecialAllmessages', |
150 | 150 | 'Version' => 'SpecialVersion', |
151 | 151 | 'Lockdb' => array( 'SpecialPage', 'Lockdb', 'siteadmin' ), |
152 | 152 | 'Unlockdb' => array( 'SpecialPage', 'Unlockdb', 'siteadmin' ), |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -3047,8 +3047,11 @@ |
3048 | 3048 | 'allmessagestext' => 'This is a list of system messages available in the MediaWiki namespace. |
3049 | 3049 | Please visit [http://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [http://translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.', |
3050 | 3050 | 'allmessagesnotsupportedDB' => "This page cannot be used because '''\$wgUseDatabaseMessages''' has been disabled.", |
3051 | | -'allmessagesfilter' => 'Message name filter:', |
3052 | | -'allmessagesmodified' => 'Show only modified', |
| 3051 | +'allmessages-filter' => 'Filter by customisation state:', |
| 3052 | +'allmessages-filter-unmodified' => 'Unmodified', |
| 3053 | +'allmessages-filter-all' => 'All', |
| 3054 | +'allmessages-filter-modified' => 'Modified', |
| 3055 | +'allmessages-prefix' => 'Filter by prefix:', |
3053 | 3056 | |
3054 | 3057 | # Thumbnails |
3055 | 3058 | 'thumbnail-more' => 'Enlarge', |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -254,6 +254,7 @@ |
255 | 255 | * Log in and log out links no longer return to page view when clicked from |
256 | 256 | history view, edit page, or something similar |
257 | 257 | * (bug 19513) RTL fixes for new Search UI |
| 258 | +* (bug 16497) Special:Allmessages is paginated |
258 | 259 | |
259 | 260 | == API changes in 1.16 == |
260 | 261 | |