r43005 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r43004‎ | r43005 | r43006 >
Date:18:05, 1 November 2008
Author:brion
Status:old
Tags:
Comment:
Modified paths:
  • /trunk/extensions/CentralNotice (modified) (history)
  • /trunk/extensions/CentralNotice/CentralNotice.i18n.php (modified) (history)
  • /trunk/extensions/CentralNotice/CentralNotice.php (modified) (history)
  • /trunk/extensions/CentralNotice/CentralNotice.sql (added) (history)
  • /trunk/extensions/CentralNotice/NoticePage.php (modified) (history)
  • /trunk/extensions/CentralNotice/NoticeRender.php (deleted) (history)
  • /trunk/extensions/CentralNotice/SpecialCentralNotice.php (added) (history)
  • /trunk/extensions/CentralNotice/SpecialNoticeLocal.php (modified) (history)
  • /trunk/extensions/CentralNotice/SpecialNoticeRender.php (deleted) (history)
  • /trunk/extensions/CentralNotice/SpecialNoticeTemplate.php (added) (history)
  • /trunk/extensions/CentralNotice/SpecialNoticeText.php (modified) (history)
  • /trunk/extensions/CentralNotice/rebuildLocalTemplates.php (added) (history)
  • /trunk/extensions/CentralNotice/rebuildTemplates.php (added) (history)

Diff [purge]

Index: trunk/extensions/CentralNotice/NoticeRender.php
@@ -1,98 +0,0 @@
2 -<?php
3 -
4 -/**
5 - * Generated parameters:
6 - * lang=en
7 - * dir=ltr
8 - * count=10,549 # localized
9 - * percent=10.549 # percentage
10 - *
11 - * Template defaults could be, eg:
12 - * progress=<tspan class="count">{{{count}}}</tspan> have donated
13 - * headline=<tspan class="you">You</tspan> can help Wikipedia change the world!
14 - * button=» Donate now!
15 - * font=Gill Sans
16 - * boldfont=Gill Sans Ultra Bold
17 - *
18 - * Per-language overrides for each...
19 - */
20 -
21 -class NoticeRender {
22 - // svg-o-matic!
23 -
24 - function __construct() {
25 - // fixme :D
26 - $this->languageCode = 'en';
27 - $this->languageObj = Language::factory( $this->languageCode );
28 - }
29 -
30 - function expandTemplate( $template ) {
31 - $count = 10550;
32 - $max = 100000;
33 - $params = array(
34 - // Locale information
35 - 'lang' => $this->languageCode,
36 - 'dir' => $this->languageObj->isRTL() ? 'rtl' : 'ltr',
37 -
38 - // Progress information...
39 - 'rawcount' => $count,
40 - 'count' => $this->languageObj->formatNum( $count ),
41 - 'percent' => strval( $count / $max * 100.0 ),
42 -
43 - // And the localized text...
44 - // @fixme
45 - );
46 -
47 - global $wgParser;
48 - $wgParser->firstCallInit();
49 - $parser = clone( $wgParser );
50 - // a damn dirty hack
51 - $parser->clearState();
52 - //$parser->setOutputType( OT_PREPROCESS );
53 - $parser->setOutputType( OT_HTML );
54 - $parser->mOptions = new ParserOptions();
55 - $parser->mTitle = Title::makeTitle( NS_MEDIAWIKI, 'Centralnotice-svg-template' );
56 - // and go!
57 - return $parser->replaceVariables( $template, $params );
58 - }
59 -
60 - function rasterize( $svg ) {
61 - global $wgNoticeRenderDirectory, $wgNoticeRenderPath;
62 -
63 - $hash = md5( $svg );
64 - $svgFile = "$wgNoticeRenderDirectory/$hash.svg";
65 - $pngFile = "$wgNoticeRenderDirectory/$hash.png";
66 - $pngUrl = "$wgNoticeRenderPath/$hash.png";
67 -
68 - if( file_exists( $pngFile ) ) {
69 - wfDebug( __METHOD__ . " $pngFile already rendered.\n" );
70 - return $pngUrl;
71 - }
72 -
73 - if( !file_exists( $wgNoticeRenderDirectory ) ) {
74 - wfDebug( __METHOD__ . " lazy-creating $wgNoticeRenderDirectory\n" );
75 - wfMkdirParents( $wgNoticeRenderDirectory );
76 - }
77 -
78 - file_put_contents( $svgFile, $svg );
79 -
80 - $command = strtr( 'inkscape -z -w $width -f $input -e $output',
81 - array(
82 - '$width' => 622,
83 - '$input' => wfEscapeShellArg( $svgFile ),
84 - '$output' => wfEscapeShellArg( $pngFile ) ) );
85 -
86 - $retval = 0;
87 - $out = wfShellExec( $command, $retval );
88 -
89 - if( $retval ) {
90 - // Error! error!
91 - wfDebug( __METHOD__ . " returned $retval from '$command'\n" );
92 - return false;
93 - }
94 -
95 - return $pngUrl;
96 - }
97 -}
98 -
99 -?>
\ No newline at end of file
Index: trunk/extensions/CentralNotice/SpecialNoticeRender.php
@@ -1,46 +0,0 @@
2 -<?php
3 -
4 -
5 -/**
6 - * Generated parameters:
7 - * lang=en
8 - * dir=ltr
9 - * count=10,549 # localized
10 - * percent=10.549 # percentage
11 - *
12 - * Template defaults could be, eg:
13 - * progress=<tspan class="count">{{{count}}}</tspan> have donated
14 - * headline=<tspan class="you">You</tspan> can help Wikipedia change the world!
15 - * button=» Donate now!
16 - * font=Gill Sans
17 - * boldfont=Gill Sans Ultra Bold
18 - *
19 - * Per-language overrides for each...
20 - *
21 - * {{#expr:ceil(20*{{{rawcount}}}/{{{rawmax}}})}}
22 - */
23 -class SpecialNoticeRender extends UnlistedSpecialPage {
24 - function __construct() {
25 - parent::__construct( "NoticeRender" );
26 - }
27 -
28 - function execute( $par ) {
29 - global $wgOut;
30 - $wgOut->disable();
31 - $this->sendHeaders();
32 - echo $this->getSvgOutput( $par );
33 - }
34 -
35 - private function sendHeaders() {
36 - header( "Content-type: image/svg+xml" );
37 - //header( "Content-type: image/png" );
38 - }
39 -
40 - private function getSvgOutput( $par ) {
41 - $render = new NoticeRender();
42 - $template = wfMsgForContentNoTrans( 'centralnotice-svg-template' );
43 - $svg = $render->expandTemplate( $template );
44 - $pngUrl = $render->rasterize( $svg );
45 - return $svg;
46 - }
47 -}
\ No newline at end of file
Index: trunk/extensions/CentralNotice/CentralNotice.php
@@ -1,34 +1,70 @@
22 <?php
33
4 -/// Override this URL to point to the central loader...
5 -/// This guy gets loaded from every page on every wiki, and is heavily cached.
6 -/// Its contents are small, and just load up another cached JS page, but this
7 -/// allows us to update everything with a single purge. Nice, eh?
8 -$wgNoticeLoader = 'http://example.com/trunk/index.php/Special:NoticeLoader';
 4+/// Override this URL to point to the central notice text loader...
 5+/// This guy gets loaded from every page on every wiki, so caching helps!
 6+////
 7+/// Can be set to a directory where static files will be made --
 8+/// match that up with $wgNoticeStaticDirectory and use rebuildTemplates.php
 9+/// to fill out the directory tree.
 10+///
 11+/// Default: Local path to Special:NoticeText
 12+///
 13+/// Loads: $wgNoticeCentralPath/<project>/<lang>/centralnotice.js
 14+///
 15+$wgNoticeCentralPath = false;
916
 17+/// This guy does much the same, but with the local sitenotice/anonnotice.
 18+/// Static generation isn't quite supported yet.
 19+///
 20+/// Default: Local path to Special:NoticeLocal
 21+///
 22+/// Loads: $wgNoticeLocalPath/sitenotice.js
 23+/// -or- $wgNoticeLocalPath/anonnotice.js
 24+///
 25+$wgNoticeLocalPath = false;
 26+
1027 /// Override these per-wiki to pass on via the loader to the text system
1128 /// for localization by language and project.
1229 /// Actual user language is used for localization; $wgNoticeLang is used
1330 /// for selective enabling/disabling on sites.
14 -$wgNoticeLang = 'en';
 31+$wgNoticeLang = $wgLanguageCode;
1532 $wgNoticeProject = 'wikipedia';
1633
 34+/// List of available projects, which will be used to generate static
 35+/// output .js in the batch generation...
 36+$wgNoticeProjects = array(
 37+ 'wikipedia',
 38+ 'wiktionary',
 39+ 'wikiquote',
 40+ 'wikibooks',
 41+ 'wikinews',
 42+ 'wikisource',
 43+ 'wikiversity',
 44+ 'wikimedia',
 45+ 'commons',
 46+ 'meta',
 47+ 'wikispecies',
 48+);
1749
 50+/// Local filesystem path under which static .js output is written
 51+/// for the central notice system.
 52+///
 53+/// $wgNoticeCentralDirectory = "/mnt/uploads/centralnotice";
 54+///
 55+$wgNoticeCentralDirectory = false;
 56+
 57+/// Local filesystem path under which static .js output is written
 58+/// for this wiki's local sitenotice and anonnotice.
 59+///
 60+/// $wgNoticeLocalDirectory = "/mnt/uploads/sitenotice/$wgDBname";
 61+///
 62+$wgNoticeLocalDirectory = false;
 63+
1864 /// Enable the notice-hosting infrastructure on this wiki...
1965 /// Leave at false for wikis that only use a sister site for the control.
2066 /// All remaining options apply only to the infrastructure wiki.
21 -$wgNoticeInfrastructure = false;
 67+$wgNoticeInfrastructure = true;
2268
23 -/// Enable the loader itself
24 -/// Allows to control the loader visibility, without destroying infrastructure
25 -/// for cached content
26 -$wgCentralNoticeLoader = true;
27 -
28 -/// URL prefix to the raw-text loader special.
29 -/// Project/language and timestamp epoch keys get appended to this
30 -/// via the loader stub.
31 -$wgNoticeText = 'http://example.com/trunk/index.php/Special:NoticeText';
32 -
3369 /// If true, notice only displays if 'sitenotice=yes' is in the query string
3470 $wgNoticeTestMode = false;
3571
@@ -45,16 +81,9 @@
4682 /// smallish if you will. :)
4783 $wgNoticeServerTimeout = 0;
4884
49 -/// Use a god-forsaken <marquee> to scroll multiple quotes...
50 -$wgNoticeScroll = true;
51 -
5285 /// Source for live counter information
5386 $wgNoticeCounterSource = "http://donate.wikimedia.org/counter.php";
5487
55 -/// Directory for SVG-to-PNG rasterizations
56 -$wgNoticeRenderDirectory = false; // "$wgUploadDirectory/notice"
57 -$wgNoticeRenderPath = false; // $wgUploadPath/notice
58 -
5988 $wgExtensionFunctions[] = 'efCentralNoticeSetup';
6089
6190 $wgExtensionCredits['other'][] = array(
@@ -66,82 +95,87 @@
6796 'description' => 'Adds a central sitenotice',
6897 'descriptionmsg' => 'centralnotice-desc',
6998 );
70 -$wgExtensionMessagesFiles['CentralNotice'] = dirname(__FILE__) . '/CentralNotice.i18n.php';
7199
 100+$dir = dirname( __FILE__ ) . '/';
 101+
 102+$wgExtensionMessagesFiles['CentralNotice'] = $dir . 'CentralNotice.i18n.php';
 103+$wgAutoloadClasses['CentralNotice'] = $dir . 'SpecialCentralNotice.php';
 104+
 105+$wgAvailableRights[] = 'centralnotice_admin_rights';
 106+$wgGroupPermissions['sysop']['centralnotice_admin_rights'] = true; // Only sysops can make change
 107+$wgGroupPermissions['sysop']['centralnotice_translate_rights'] = true; // Only sysops can make change
 108+
 109+$wgSpecialPages['CentralNotice'] = 'CentralNotice';
 110+$wgSpecialPages['NoticeTemplate'] = 'SpecialNoticeTemplate';
 111+$wgSpecialPageGroups['CentralNotice'] = 'wiki'; // Wiki data and tools"
 112+
72113 function efCentralNoticeSetup() {
73 - global $wgHooks, $wgNoticeInfrastructure;
74 - global $wgAutoloadClasses, $wgSpecialPages;
75 -
 114+ global $wgHooks, $wgNoticeInfrastructure, $wgAutoloadClasses, $wgSpecialPages;
76115 global $wgCentralNoticeLoader;
77 -
78 - if ($wgCentralNoticeLoader) {
79 - $wgHooks['SiteNoticeAfter'][] = 'efCentralNoticeLoader';
80 - }
81116
 117+ $dir = dirname( __FILE__ ) . '/';
 118+
 119+ $wgHooks['SiteNoticeAfter'][] = 'efCentralNoticeLoader';
 120+
82121 $wgHooks['ArticleSaveComplete'][] = 'efCentralNoticeLocalSaveHook';
83122 $wgHooks['ArticleSaveComplete'][] = 'efCentralNoticeLocalDeleteHook';
84123
85 - $wgAutoloadClasses['NoticePage'] =
86 - dirname( __FILE__ ) . '/NoticePage.php';
 124+ $wgAutoloadClasses['NoticePage'] = $dir . 'NoticePage.php';
87125
88126 $wgSpecialPages['NoticeLocal'] = 'SpecialNoticeLocal';
89 - $wgAutoloadClasses['SpecialNoticeLocal'] =
90 - dirname( __FILE__ ) . '/SpecialNoticeLocal.php';
 127+ $wgAutoloadClasses['SpecialNoticeLocal'] = $dir . 'SpecialNoticeLocal.php';
91128
92 -
93129 if( $wgNoticeInfrastructure ) {
94130 $wgHooks['ArticleSaveComplete'][] = 'efCentralNoticeSaveHook';
95131 $wgHooks['ArticleSaveComplete'][] = 'efCentralNoticeDeleteHook';
96 -
 132+
97133 $wgSpecialPages['NoticeLoader'] = 'SpecialNoticeLoader';
98 - $wgAutoloadClasses['SpecialNoticeLoader'] =
99 - dirname( __FILE__ ) . '/SpecialNoticeLoader.php';
100 -
 134+ $wgAutoloadClasses['SpecialNoticeLoader'] = $dir . 'SpecialNoticeLoader.php';
 135+
101136 $wgSpecialPages['NoticeText'] = 'SpecialNoticeText';
102 - $wgAutoloadClasses['SpecialNoticeText'] =
103 - dirname( __FILE__ ) . '/SpecialNoticeText.php';
 137+ $wgAutoloadClasses['SpecialNoticeText'] = $dir . 'SpecialNoticeText.php';
104138
105 - // The new SVG stuff
106 - /*
107 - $wgSpecialPages['NoticeRender'] = 'SpecialNoticeRender';
108 - $wgAutoloadClasses['SpecialNoticeRender'] = dirname( __FILE__ ) . '/SpecialNoticeRender.php';
109 - $wgAutoloadClasses['NoticeRender'] = dirname( __FILE__ ) . '/NoticeRender.php';
110 -
111 - global $wgNoticeRenderDirectory, $wgNoticeRenderPath;
112 - global $wgUploadDirectory, $wgUploadPath;
113 - if( !$wgNoticeRenderDirectory )
114 - $wgNoticeRenderDirectory = "$wgUploadDirectory/notice";
115 - if( !$wgNoticeRenderPath )
116 - $wgNoticeRenderPath = "$wgUploadPath/notice";
117 - */
 139+ $wgSpecialPages['NoticeTemplate'] = 'SpecialNoticeTemplate';
 140+ $wgAutoloadClasses['SpecialNoticeTemplate'] = $dir . 'SpecialNoticeTemplate.php';
118141 }
119142 }
120143
121 -
122144 function efCentralNoticeLoader( &$notice ) {
123 - global $wgScript, $wgUser;
124 - global $wgNoticeLoader, $wgNoticeLang, $wgNoticeProject;
 145+ global $wgScript, $wgUser, $wgLang;
 146+ global $wgNoticeProject;
 147+
 148+ global $wgNoticeCentralPath;
 149+ global $wgNoticeLocalPath;
 150+
 151+ $lang = $wgLang->getCode();
 152+ $centralNotice = "$wgNoticeProject/$lang/centralnotice.js";
 153+ $localNotice = (is_object( $wgUser ) && $wgUser->isLoggedIn())
 154+ ? 'sitenotice.js'
 155+ : 'anonnotice.js';
125156
126 - $encNoticeLoader = htmlspecialchars( $wgNoticeLoader );
127 - $encProject = Xml::encodeJsVar( $wgNoticeProject );
128 - $encLang = Xml::encodeJsVar( $wgNoticeLang );
129157
130 - $anon = (is_object( $wgUser ) && $wgUser->isLoggedIn())
131 - ? ''
132 - : '/anon';
133 - $localText = "$wgScript?title=Special:NoticeLocal$anon&action=raw";
134 - $encNoticeLocal = htmlspecialchars( $localText );
135 -
 158+ if( $wgNoticeCentralPath === false ) {
 159+ $centralLoader = SpecialPage::getTitleFor( 'NoticeText', $centralNotice )->getLocalUrl();
 160+ } else {
 161+ $centralLoader = "$wgNoticeCentralPath/$centralNotice";
 162+ }
 163+ $encCentralLoader = htmlspecialchars( $centralLoader );
 164+
 165+ if( $wgNoticeLocalPath === false ) {
 166+ $localLoader = SpecialPage::getTitleFor( 'NoticeLocal', $localNotice )->getLocalUrl();
 167+ } else {
 168+ $localLoader = "$wgNoticeLocalPath/$localNotice";
 169+ }
 170+ $encLocalLoader = htmlspecialchars( $localLoader );
 171+
136172 // Throw away the classic notice, use the central loader...
137173 $notice = <<<EOT
138174 <script type="text/javascript">
139175 var wgNotice = "";
140176 var wgNoticeLocal = "";
141 -var wgNoticeLang = $encLang;
142 -var wgNoticeProject = $encProject;
143177 </script>
144 -<script type="text/javascript" src="$encNoticeLoader"></script>
145 -<script type="text/javascript" src="$encNoticeLocal"></script>
 178+<script type="text/javascript" src="$encCentralLoader"></script>
 179+<script type="text/javascript" src="$encLocalLoader"></script>
146180 <script type="text/javascript">
147181 if (wgNotice != "") {
148182 document.writeln(wgNotice);
@@ -151,7 +185,6 @@
152186 }
153187 </script>
154188 EOT;
155 -
156189 return true;
157190 }
158191
@@ -160,9 +193,11 @@
161194 * Trigger a purge of the notice loader when we've updated the source pages.
162195 */
163196 function efCentralNoticeSaveHook( $article, $user, $text, $summary, $isMinor,
164 - $isWatch, $section, $flags, $revision ) {
 197+ $isWatch, $section, $flags, $revision ) {
165198 efCentralNoticeMaybePurge( $article->getTitle() );
166 - return true; // Continue hook processing
 199+
 200+ // Continue
 201+ return true;
167202 }
168203
169204 /**
@@ -170,9 +205,11 @@
171206 * Trigger a purge of the local notice when we've updated the source pages.
172207 */
173208 function efCentralNoticeLocalSaveHook( $article, $user, $text, $summary, $isMinor,
174 - $isWatch, $section, $flags, $revision ) {
 209+ $isWatch, $section, $flags, $revision ) {
175210 efCentralNoticeMaybePurgeLocal( $article->getTitle() );
176 - return true; // Continue hook processing
 211+
 212+ // Continue
 213+ return true;
177214 }
178215
179216 /**
@@ -181,7 +218,9 @@
182219 */
183220 function efCentralNoticeDeleteHook( $article, $user, $reason ) {
184221 efCentralNoticeMaybePurge( $article->getTitle() );
185 - return true; // Continue hook processing
 222+
 223+ // Continue
 224+ return true;
186225 }
187226
188227 /**
@@ -190,7 +229,9 @@
191230 */
192231 function efCentralNoticeLocalDeleteHook( $article, $user, $reason ) {
193232 efCentralNoticeMaybePurgeLocal( $article->getTitle() );
194 - return true; // Continue hook processing
 233+
 234+ // Continue
 235+ return true;
195236 }
196237
197238 /**
@@ -248,6 +289,7 @@
249290 */
250291 function efCentralNoticeEpoch() {
251292 global $wgMemc;
 293+
252294 $epoch = $wgMemc->get( 'centralnotice-epoch' );
253295 if( $epoch ) {
254296 return wfTimestamp( TS_MW, $epoch );
@@ -262,6 +304,7 @@
263305 */
264306 function efCentralNoticeUpdateEpoch() {
265307 global $wgMemc, $wgNoticeServerTimeout;
 308+
266309 $epoch = wfTimestamp( TS_MW );
267310 $wgMemc->set( "centralnotice-epoch", $epoch, $wgNoticeServerTimeout );
268311 return $epoch;
Index: trunk/extensions/CentralNotice/SpecialCentralNotice.php
@@ -0,0 +1,1189 @@
 2+<?php
 3+
 4+if ( !defined( 'MEDIAWIKI' ) ) {
 5+ echo "CentralNotice extension\n";
 6+ exit( 1 );
 7+}
 8+
 9+class CentralNotice extends SpecialPage {
 10+
 11+ /* Functions */
 12+
 13+ function CentralNotice() {
 14+ // Register special page
 15+ SpecialPage::SpecialPage( 'CentralNotice' );
 16+
 17+ // Internationalization
 18+ wfLoadExtensionMessages( 'CentralNotice' );
 19+ }
 20+
 21+ function execute( $sub ) {
 22+ global $wgOut, $wgUser, $wgRequest;
 23+
 24+ // Begin output
 25+ $this->setHeaders();
 26+
 27+ // Get current skin
 28+ $sk = $wgUser->getSkin();
 29+
 30+ // Check permissions
 31+ if ( !$wgUser->isAllowed( 'centralnotice_admin_rights' ) ) {
 32+ $wgOut->permissionRequired( 'centralnotice_admin_rights' );
 33+ return;
 34+ }
 35+
 36+ // Show summary
 37+ $wgOut->addWikiText( wfMsg( 'centralnotice-summary' ) );
 38+
 39+ // Show header
 40+ $this->printHeader( $sub );
 41+
 42+ // Handle form sumissions
 43+ if ( $wgRequest->wasPosted() ) {
 44+
 45+ // Handle removing
 46+ $toRemove = $wgRequest->getArray( 'removeNotices' );
 47+ if ( isset( $toRemove ) ) {
 48+ // Remove notices in list
 49+ foreach ( $toRemove as $template ) {
 50+ $this->removeNotice( $template );
 51+ }
 52+
 53+ // Show list of notices
 54+ $this->listNotices();
 55+ return;
 56+ }
 57+
 58+ // Handle locking/unlocking
 59+ $lockedNotices = $wgRequest->getArray( 'locked' );
 60+ if ( isset( $lockedNotices ) ) {
 61+ // Build list of notices to lock
 62+ $unlockedNotices = array_diff( $this->getNoticesName(), $lockedNotices);
 63+
 64+ // Set locked/unlocked flag accordingly
 65+ foreach( $lockedNotices as $notice ) {
 66+ $this->updateLock( $notice, '1' );
 67+ }
 68+ foreach( $unlockedNotices as $notice ) {
 69+ $this->updateLock( $notice, '0' );
 70+ }
 71+ }
 72+
 73+ // Handle enabling/disabling
 74+ $enabledNotices = $wgRequest->getArray('enabled');
 75+ if ( isset( $enabledNotices ) ) {
 76+ // Build list of notices to disable
 77+ $disabledNotices = array_diff( $this->getNoticesName(), $enabledNotices);
 78+
 79+ // Set enabled/disabled flag accordingly
 80+ foreach ( $enabledNotices as $notice) {
 81+ $this->updateEnabled( $notice, '1');
 82+ }
 83+ foreach ( $disabledNotices as $notice) {
 84+ $this->updateEnabled( $notice, '0');
 85+ }
 86+ }
 87+
 88+ $noticeName = $wgRequest->getVal( 'notice' );
 89+
 90+ // Handle range setting
 91+ $start = $wgRequest->getArray( 'start' );
 92+ $end = $wgRequest->getArray( 'end' );
 93+ if ( isset( $start ) && isset( $end )) {
 94+ $updatedStart = sprintf( "%04d%02d%02d%02d%02d00",
 95+ $start['year'],
 96+ $start['month'],
 97+ $start['day'],
 98+ $start['hour'],
 99+ $start['min'] );
 100+ $updatedEnd = sprintf( "%04d%02d%02d000000",
 101+ $end['year'],
 102+ $end['month'],
 103+ $end['day'] );
 104+ $this->updateNoticeDate( $noticeName, $updatedStart, $updatedEnd );
 105+ }
 106+
 107+ // Handle updates if no post content came through
 108+ if ( !isset( $lockedNotices ) && $wgRequest->getText( 'change' ) !== 'weight' ) {
 109+ $allNotices = $this->getNoticesName();
 110+ foreach ( $allNotices as $notice ) {
 111+ $this->updateLock( $notice, '0' );
 112+ }
 113+ }
 114+
 115+ if ( !isset( $enabledNotices ) && $wgRequest->getText( 'change' ) !== 'weight' ) {
 116+ $allNotices = $this->getNoticesName();
 117+ foreach ( $allNotices as $notice ) {
 118+ $this->updateEnabled( $notice, '0' );
 119+ }
 120+ }
 121+
 122+ // Handle weight change
 123+ $updatedWeights = $wgRequest->getArray( 'weight' );
 124+ if ( isset( $updatedWeights ) ) {
 125+ foreach( $updatedWeights as $templateName => $weight ) {
 126+ $this->updateWeight( $noticeName, $templateName, $weight );
 127+ }
 128+ }
 129+ }
 130+
 131+ // Handle adding
 132+ $method = $wgRequest->getVal('method');
 133+ $this->showAll = $wgRequest->getVal('showAll');
 134+ if ( $method == 'addNotice' ) {
 135+ $noticeName = $wgRequest->getVal( 'noticeName' );
 136+ $start = $wgRequest->getArray( 'start' );
 137+ $project_name = $wgRequest->getVal( 'project_name' );
 138+ $project_language = $wgRequest->getVal( 'wpUserLanguage' );
 139+ if ( $noticeName == '' ) {
 140+ $wgOut->addHtml( wfMsg ( 'centralnotice-null-string' ) );
 141+ }
 142+ else {
 143+ $this->addNotice( $noticeName, '0', $start, $project_name, $project_language );
 144+ }
 145+ }
 146+
 147+ // Handle removing
 148+ if ( $method == 'removeNotice' ) {
 149+ $noticeName = $wgRequest->getVal ( 'noticeName' );
 150+ $this->removeNotice ( $noticeName );
 151+ }
 152+
 153+ // Handle adding of template
 154+ if ( $method == 'addTemplateTo' ) {
 155+ $noticeName = $wgRequest->getVal( 'noticeName' );
 156+ $templateName = $wgRequest->getVal( 'templateName' );
 157+ $templateWeight = $wgRequest->getVal ( 'weight' );
 158+ $this->addTemplateTo( $noticeName, $templateName, $weight );
 159+ $this->listNoticeDetail( $noticeName );
 160+ return;
 161+ }
 162+
 163+ // Handle removing of template
 164+ if ( $method == 'removeTemplateFor' ) {
 165+ $noticeName = $wgRequest->getVal ( 'noticeName' );
 166+ $templateName = $wgRequest->getVal ( 'templateName ');
 167+ $this->removeTemplateFor( $noticeName , $templateName );
 168+ }
 169+
 170+ // Handle showing detail
 171+ if ( $method == 'listNoticeDetail' ) {
 172+ $notice = $wgRequest->getVal ( 'notice' );
 173+ $this->listNoticeDetail( $notice );
 174+ return;
 175+ }
 176+
 177+ // Show list of notices
 178+ $this->listNotices();
 179+ }
 180+
 181+ // Update the enabled/disabled state of notice
 182+ private function updateEnabled( $notice, $state ) {
 183+ $dbw = wfGetDB( DB_MASTER );
 184+ $res = $dbw->update( 'cn_notices',
 185+ array( 'not_enabled' => $state ),
 186+ array( 'not_name' => $notice )
 187+ );
 188+ }
 189+
 190+ static public function printHeader() {
 191+ global $wgOut, $wgTitle, $wgUser;
 192+ $sk = $wgUser->getSkin();
 193+
 194+ $pages = array(
 195+ 'CentralNotice' => wfMsg( 'centralnotice-notices' ),
 196+ 'NoticeTemplate' => wfMsg ( 'centralnotice-templates' )
 197+ );
 198+ $htmlOut = Xml::openElement( 'table', array( 'cellpadding' => 9 ) );
 199+ $htmlOut .= Xml::openElement( 'tr' );
 200+ foreach ( $pages as $page => $msg ) {
 201+ $title = SpecialPage::getTitleFor( $page );
 202+
 203+ $style = array( 'style' => 'border-bottom:solid 1px silver;' );
 204+ if ( $page == $wgTitle->getText() ) {
 205+ $style = array( 'style' => 'border-bottom:solid 1px black;' );
 206+ }
 207+
 208+ $htmlOut .= Xml::tags( 'td', $style,
 209+ $sk->makeLinkObj( $title, htmlspecialchars( $msg ) )
 210+ );
 211+ }
 212+ $htmlOut .= Xml::closeElement( 'tr' );
 213+ $htmlOut .= Xml::closeElement( 'table' );
 214+
 215+ $wgOut->addHTML( $htmlOut );
 216+ }
 217+
 218+ function getNoticesName() {
 219+ $dbr = wfGetDB( DB_SLAVE );
 220+ $res = $dbr->select( 'cn_notices', 'not_name' );
 221+ $notices = array();
 222+ while ( $row = $dbr->fetchObject( $res )) {
 223+ array_push( $notices, $row->not_name);
 224+ }
 225+ return $notices;
 226+ }
 227+
 228+ function tableRow( $fields, $element='td' ) {
 229+ $cells = array();
 230+ foreach( $fields as $field ) {
 231+ $cells[] = Xml::tags( $element, array(), $field );
 232+ }
 233+ return Xml::tags( 'tr', array(), implode( "\n", $cells ) ) . "\n";
 234+ }
 235+
 236+ function dateSelector( $prefix, $timestamp=null ) {
 237+ // Default ranges...
 238+ $years = range( 2007, 2012 );
 239+ $months = range( 1, 12 );
 240+ $months = array_map( array( $this, 'addZero' ), $months );
 241+ $days = range( 1 , 31 );
 242+ $days = array_map( array( $this, 'addZero' ), $days);
 243+
 244+ // Normalize timestamp format...
 245+ $ts = wfTimestamp( TS_MW, $timestamp );
 246+
 247+ $fields = array(
 248+ array( "month", "centralnotice-month", $months, substr( $ts, 4, 2 ) ),
 249+ array( "day", "centralnotice-day", $days, substr( $ts, 6, 2 ) ),
 250+ array( "year", "centralnotice-year", $years, substr( $ts, 0, 4 ) ),
 251+ );
 252+
 253+ return $this->genSelector( $prefix, $fields );
 254+ }
 255+
 256+ function timeSelector( $prefix, $timestamp=null ) {
 257+ // Default ranges...
 258+ $minutes = range( 0, 59 ); // formerly in 15-minute increments
 259+ $minutes = array_map( array( $this, 'addZero' ), $minutes);
 260+ $hours = range( 0 , 23 );
 261+ $hours = array_map( array( $this, 'addZero' ), $hours);
 262+
 263+ // Normalize timestamp format...
 264+ $ts = wfTimestamp( TS_MW, $timestamp );
 265+
 266+ $fields = array(
 267+ array( "hour", "centralnotice-hours", $hours, substr( $ts, 8, 2 ) ),
 268+ array( "min", "centralnotice-min", $minutes, substr( $ts, 10, 2 ) ),
 269+ );
 270+
 271+ return $this->genSelector( $prefix, $fields );
 272+ }
 273+
 274+ private function genSelector( $prefix, $fields ) {
 275+ $out = '';
 276+ foreach( $fields as $data ) {
 277+ list( $field, $label, $set, $current ) = $data;
 278+ $out .= Xml::listDropDown( "{$prefix}[{$field}]",
 279+ $this->dropDownList( wfMsg( $label ), $set ),
 280+ '',
 281+ $current );
 282+ }
 283+ return $out;
 284+ }
 285+
 286+ /*
 287+ * listNotices
 288+ *
 289+ * Print out all campaigns found in db
 290+ */
 291+
 292+ function listNotices() {
 293+ global $wgOut, $wgRequest, $wgTitle, $wgScript, $wgUser;
 294+ global $wgNoticeProject, $wpUserLang;
 295+
 296+ // Get connection
 297+ $dbr = wfGetDB( DB_SLAVE );
 298+ $sk = $wgUser->getSkin();
 299+
 300+ /*
 301+ * This is temporarily hard-coded
 302+ */
 303+ $this->showAll = 'Y';
 304+
 305+ // If all languages should be shown
 306+ if ( isset( $this->showAll )) {
 307+ // Get only notices for all languages
 308+ $res = $dbr->select( 'cn_notices',
 309+ array(
 310+ 'not_name',
 311+ 'not_start',
 312+ 'not_end',
 313+ 'not_enabled',
 314+ 'not_project',
 315+ 'not_language',
 316+ 'not_locked'
 317+ ),
 318+ null,
 319+ __METHOD__,
 320+ array('ORDER BY' => 'not_id')
 321+ );
 322+ } else {
 323+ // Get only notices for this language
 324+ $res = $dbr->select( 'cn_notices',
 325+ array(
 326+ 'not_name',
 327+ 'not_start',
 328+ 'not_end',
 329+ 'not_enabled',
 330+ 'not_project',
 331+ 'not_locked'
 332+ ),
 333+ array ( 'not_language' => $wgNoticeLang ),
 334+ __METHOD__,
 335+ array('ORDER BY' => 'not_id')
 336+ );
 337+ }
 338+
 339+ // Build HTML
 340+ $htmlOut = Xml::openElement( 'form',
 341+ array(
 342+ 'method' => 'post',
 343+ 'action' => SpecialPage::getTitleFor( 'CentralNotice' )->getFullUrl()
 344+ )
 345+ );
 346+ $htmlOut .= Xml::fieldset( wfMsgHtml( "centralnotice-manage" ) );
 347+ $htmlOut .= Xml::openElement( 'table', array ( 'cellpadding' => 9 ) );
 348+
 349+ // Headers
 350+ $headers = array(
 351+ wfMsgHtml( 'centralnotice-notice-name' ),
 352+ wfMsgHtml( 'centralnotice-project-name' ),
 353+ wfMsgHtml( 'centralnotice-project-lang' ),
 354+ wfMsgHtml( 'centralnotice-start-date' ),
 355+ wfMsgHtml( 'centralnotice-end-date' ),
 356+ wfMsgHtml( 'centralnotice-enabled' ),
 357+ wfMsgHtml( 'centralnotice-locked' ),
 358+ wfMsgHtml( 'centralnotice-remove' ),
 359+ );
 360+ $htmlOut .= $this->tableRow( $headers, 'th' );
 361+
 362+ // Rows
 363+ if ( $dbr->numRows( $res ) >= 1 ) {
 364+ while ( $row = $dbr->fetchObject( $res ) ) {
 365+ $fields = array();
 366+
 367+ // Name
 368+ $fields[] = $sk->makeLinkObj( $this->getTitle(),
 369+ htmlspecialchars( $row->not_name ),
 370+ 'method=listNoticeDetail&notice=' . urlencode( $row->not_name ) );
 371+
 372+ // Project
 373+ $fields[] = htmlspecialchars( $this->getProjectName( $row->not_project ) );
 374+
 375+ // Language
 376+ if ( isset ( $this->showAll ) ) {
 377+ $fields[] = htmlspecialchars( $row->not_language );
 378+ }
 379+
 380+ // Date and time calculations
 381+ $start_timestamp = $row->not_start;
 382+ $start_year = substr( $start_timestamp, 0 , 4 );
 383+ $start_month = substr( $start_timestamp, 4, 2 );
 384+ $start_day = substr( $start_timestamp, 6, 2 );
 385+ $start_hour = substr( $start_timestamp, 8, 2 );
 386+ $start_min = substr( $start_timestamp, 10, 2 );
 387+ $end_timestamp = $row->not_end;
 388+ $end_year = substr( $end_timestamp, 0 , 4 );
 389+ $end_month = substr( $end_timestamp, 4, 2);
 390+ $end_day = substr( $end_timestamp, 6, 2 );
 391+
 392+ // Start
 393+ $fields[] = "{$start_year}/{$start_month}/{$start_day} {$start_hour}:{$start_min}";
 394+
 395+ // End
 396+ $fields[] = "{$end_year}/{$end_month}/{$end_day}";
 397+
 398+ // Enabled
 399+ $fields[] =
 400+ Xml::check( 'enabled[]', ( $row->not_enabled == '1' ),
 401+ array( 'value' => $row->not_name) );
 402+
 403+ // Locked
 404+ $fields[] =
 405+ Xml::check( 'locked[]', ( $row->not_locked == '1' ),
 406+ array( 'value' => $row->not_name) );
 407+
 408+ // Remove
 409+ $fields[] = Xml::check( 'removeNotices[]', false,
 410+ array( 'value' => $row->not_name) );
 411+
 412+ $htmlOut .= $this->tableRow( $fields );
 413+ }
 414+ $htmlOut .= $this->tableRow(
 415+ array(
 416+ Xml::submitButton( wfMsgHtml('centralnotice-modify'),
 417+ array(
 418+ 'id' => 'centralnoticesubmit',
 419+ 'name' => 'centralnoticesubmit'
 420+ )
 421+ )
 422+ )
 423+ );
 424+
 425+ $htmlOut .= Xml::closeElement( 'table' );
 426+ $htmlOut .= Xml::closeElement( 'fieldset' );
 427+ $htmlOut .= Xml::closeElement( 'form' );
 428+
 429+
 430+ // No notices to show
 431+ } else {
 432+ $htmlOut = wfMsg('centralnotice-no-notices-exist');
 433+ }
 434+
 435+ // Notice Adding
 436+ $htmlOut .= Xml::openElement( 'form',
 437+ array(
 438+ 'method' => 'post',
 439+ 'action' => SpecialPage::getTitleFor( 'CentralNotice' )->getLocalUrl()
 440+ )
 441+ );
 442+ $htmlOut .= Xml::openElement( 'fieldset' );
 443+ $htmlOut .= Xml::element( 'legend', null, wfMsg( 'centralnotice-add-notice' ) );
 444+ $htmlOut .= Xml::hidden( 'title', $this->getTitle()->getPrefixedText() );
 445+ $htmlOut .= Xml::hidden( 'method', 'addNotice' );
 446+
 447+ $htmlOut .= Xml::openElement( 'table', array ( 'cellpadding' => 9 ) );
 448+
 449+ $table = array(
 450+ // Name
 451+ array(
 452+ wfMsgHtml( 'centralnotice-notice-name' ),
 453+ Xml::inputLabel( '', 'noticeName', 'noticeName', 25 ),
 454+ ),
 455+ // Start Date
 456+ array(
 457+ Xml::label( wfMsg('centralnotice-start-date' ), 'start-date' ),
 458+ $this->dateSelector( 'start' ),
 459+ ),
 460+ // Start Time
 461+ array(
 462+ wfMsgHtml( 'centralnotice-start-hour' ) . "(GMT)",
 463+ $this->timeSelector( 'start' ),
 464+ ),
 465+ // Project
 466+ array(
 467+ wfMsgHtml( 'centralnotice-project-name' ),
 468+ $this->projectDropDownList(),
 469+ ),
 470+ // Languages + All
 471+ $this->languageDropDownList( $wpUserLang ),
 472+ // Submit
 473+ array(
 474+ Xml::submitButton( wfMsg( 'centralnotice-modify' ) ),
 475+ ),
 476+ );
 477+
 478+ foreach( $table as $cells ) {
 479+ $htmlOut .= $this->tableRow( $cells );
 480+ }
 481+
 482+ $htmlOut .= Xml::hidden( 'change', 'weight');
 483+ $htmlOut .= Xml::closeElement( 'table' );
 484+ $htmlOut .= Xml::closeElement( 'fieldset' );
 485+ $htmlOut .= Xml::closeElement( 'form' );
 486+ // Output HTML
 487+ $wgOut->addHTML( $htmlOut );
 488+ }
 489+
 490+ function listNoticeDetail( $notice ) {
 491+ global $wgOut, $wgRequest;
 492+
 493+ if ( $wgRequest->wasPosted() ) {
 494+ // Handle removing of templates
 495+ $templateToRemove = $wgRequest->getArray( 'removeTemplates' );
 496+ if ( isset( $templateToRemove ) ) {
 497+ foreach ( $templateToRemove as $template ) {
 498+ $this->removeTemplateFor( $notice, $template );
 499+ }
 500+ }
 501+
 502+ // Handle new project name
 503+ $projectName = $wgRequest->getVal( 'project_name' );
 504+ if ( isset( $projectName ) ) {
 505+ $this->updateProjectName ( $notice, $projectName );
 506+ }
 507+
 508+ $projectLang = $wgRequest->getVal( 'wpUserLanguage' );
 509+ if ( isset( $projectLang ) ) {
 510+ $this->updateProjectLanguage( $notice, $projectLang );
 511+ }
 512+
 513+ // Handle adding of templates
 514+ $templatesToAdd = $wgRequest->getArray( 'addTemplates' );
 515+ if ( isset( $templatesToAdd ) ) {
 516+ $weight = $wgRequest->getArray( 'weight' );
 517+ foreach ( $templatesToAdd as $template ) {
 518+ $this->addTemplateTo( $notice, $template, $weight[$template] );
 519+ }
 520+ }
 521+ }
 522+
 523+ $htmlOut = Xml::openElement( 'form',
 524+ array(
 525+ 'method' => 'post',
 526+ 'action' => ''
 527+ )
 528+ );
 529+
 530+ /*
 531+ * Temporarily hard coded
 532+ */
 533+ $this->showAll = 'Y';
 534+
 535+ $output = $this->noticeDetailForm( $notice );
 536+
 537+ // No notices returned
 538+ if ( $output == '') {
 539+ $htmlOut .= wfMsg( 'centralnotice-no-notices-exist' );
 540+ } else {
 541+ $htmlOut .= $output;
 542+ }
 543+
 544+ $output = $this->assignedTemplatesForm( $notice );
 545+
 546+ // No templates assigned returned
 547+ if ( $output == '') {
 548+ $htmlOut .= wfMsg( 'centralnotice-no-templates-assigned' );
 549+ } else {
 550+ $htmlOut .= $output;
 551+ }
 552+
 553+
 554+ $output = $this->addTemplatesForm( $notice );
 555+
 556+ // No templates in the system
 557+ if ( $output == '') {
 558+ $htmlOut .= wfMsg( 'centralnotice-no-templates' );
 559+ } else {
 560+ $htmlOut .= $output;
 561+ }
 562+
 563+ #$htmlOut .= Xml::closeElement( 'table');
 564+ #$htmlOut .= Xml::closeElement( 'fieldset' );
 565+ $htmlOut .= Xml::tags( 'tr', null,
 566+ Xml::tags( 'td', array( 'collspan' => 2),
 567+ Xml::submitButton( wfMsg( 'centralnotice-modify') )
 568+ )
 569+ );
 570+ $htmlOut .= Xml::closeElement( 'form' );
 571+ $wgOut->addHTML( $htmlOut );
 572+ }
 573+
 574+ function noticeDetailForm( $notice ) {
 575+ $dbr = wfGetDB( DB_SLAVE );
 576+
 577+ $row = $dbr->selectRow( 'cn_notices',
 578+ array(
 579+ 'not_id',
 580+ 'not_name',
 581+ 'not_start',
 582+ 'not_end',
 583+ 'not_enabled',
 584+ 'not_project',
 585+ 'not_language',
 586+ 'not_locked'
 587+ ),
 588+ array( 'not_name' => $notice ),
 589+ __METHOD__,
 590+ array( 'ORDER BY' => 'not_id' )
 591+ );
 592+
 593+ if( $row ) {
 594+ // Build Html
 595+ $htmlOut = Xml::fieldset( $notice );
 596+ $htmlOut .= Xml::openElement( 'table', array( 'cellpadding' => 9 ) );
 597+
 598+ // Rows
 599+ $table = array(
 600+ // Day
 601+ array(
 602+ wfMsgHtml( 'centralnotice-start-date' ),
 603+ $this->dateSelector( "start", $row->not_start ),
 604+ ),
 605+ // Time of day
 606+ array(
 607+ wfMsgHtml( 'centralnotice-start-time' ),
 608+ $this->timeSelector( "start", $row->not_start, "[$row->not_name]" ),
 609+ ),
 610+ // End
 611+ array(
 612+ wfMsgHtml( 'centralnotice-end-date'),
 613+ $this->dateSelector( "end", $row->not_end, "[$row->not_name]" ),
 614+ ),
 615+ // Project
 616+ array(
 617+ wfMsgHtml( 'centralnotice-project-name' ),
 618+ $this->projectDropDownList( $row->not_project )
 619+ ),
 620+ // Language
 621+ $this->languageDropDownList( $row->not_language ),
 622+ // Enabled
 623+ array(
 624+ wfMsgHtml( 'centralnotice-enabled'),
 625+ Xml::check( 'enabled[]', ( $row->not_enabled == '1' ),
 626+ array( 'value' => $row->not_name) )
 627+ ),
 628+ // Locked
 629+ array(
 630+ wfMsgHtml( 'centralnotice-locked' ),
 631+ Xml::check( 'locked[]', ( $row->not_locked == '1' ),
 632+ array( 'value' => $row->not_name) ),
 633+ ),
 634+ // Remove
 635+ array(
 636+ wfMsgHtml( 'centralnotice-remove' ),
 637+ Xml::check( 'removeNotices[]', false,
 638+ array( 'value' => $row->not_name) )
 639+ ),
 640+ );
 641+ foreach( $table as $cells ) {
 642+ $htmlOut .= $this->tableRow( $cells );
 643+ }
 644+ $htmlOut .= Xml::closeElement( 'table' );
 645+ $htmlOut .= Xml::closeElement( 'fieldset' ) ;
 646+ return $htmlOut;
 647+ } else {
 648+ return '';
 649+ }
 650+ }
 651+
 652+
 653+ function assignedTemplatesForm( $notice ) {
 654+ global $wgUser;
 655+ $sk = $wgUser->getSkin();
 656+
 657+ $dbr = wfGetDB( DB_SLAVE );
 658+ $res = $dbr->select(
 659+ array(
 660+ 'cn_notices',
 661+ 'cn_assignments',
 662+ 'cn_templates'
 663+ ),
 664+ array(
 665+ 'cn_templates.tmp_name',
 666+ 'cn_assignments.tmp_weight'
 667+ ),
 668+ array(
 669+ 'cn_notices.not_name' => $notice,
 670+ 'cn_notices.not_id = cn_assignments.not_id',
 671+ 'cn_assignments.tmp_id = cn_templates.tmp_id'
 672+ ),
 673+ __METHOD__,
 674+ array('ORDER BY' => 'cn_notices.not_id')
 675+ );
 676+
 677+ // No templates found
 678+ if ( $dbr->numRows( $res ) < 1) {
 679+ return;
 680+ }
 681+
 682+ // Build Assigned Template HTML
 683+ $htmlOut = Xml::hidden( 'change', 'weight' );
 684+ $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-assigned-templates' ));
 685+ $htmlOut .= Xml::openElement( 'table',
 686+ array(
 687+ 'cellpadding' => 9,
 688+ 'width' => '100%'
 689+ )
 690+ );
 691+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
 692+ wfMsg ( "centralnotice-remove" ) );
 693+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
 694+ wfMsg ( "centralnotice-weight" ) );
 695+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '70%' ),
 696+ wfMsg ( "centralnotice-templates" ) );
 697+
 698+ // Rows
 699+ while ( $row = $dbr->fetchObject( $res )) {
 700+
 701+ $htmlOut .= Xml::openElement( 'tr' );
 702+
 703+ // Remove
 704+ $htmlOut .= Xml::tags( 'td', null,
 705+ Xml::check( 'removeTemplates[]', false, array( 'value' => $row->tmp_name) )
 706+ );
 707+
 708+ // Weight
 709+ $htmlOut .= Xml::tags( 'td', null,
 710+ Xml::listDropDown( "weight[$row->tmp_name]",
 711+ $this->dropDownList( wfMsg( 'centralnotice-weight' ),
 712+ range ( 0, 100, 5) ),
 713+ '',
 714+ $row->tmp_weight,
 715+ '',
 716+ 1)
 717+ );
 718+
 719+ $viewPage = SpecialPage::getTitleFor( 'NoticeTemplate/view' );
 720+ $render = new SpecialNoticeText();
 721+ $render->project = 'wikipedia';
 722+ global $wgRequest;
 723+ $render->language = $wgRequest->getVal( 'wpUserLanguage' );
 724+ $htmlOut .= Xml::tags( 'td', null,
 725+ $sk->makeLinkObj( $viewPage,
 726+ htmlspecialchars( $row->tmp_name ),
 727+ 'template=' . urlencode( $row->tmp_name ) ) .
 728+ Xml::fieldset( wfMsg( 'centralnotice-preview' ),
 729+ $render->getHtmlNotice( $row->tmp_name )
 730+ )
 731+ );
 732+
 733+ $htmlOut .= Xml::closeElement( 'tr' );
 734+ }
 735+ $htmlOut .= XMl::closeElement( 'table' );
 736+ $htmlOut .= Xml::closeElement( 'fieldset' );
 737+ return $htmlOut;
 738+
 739+ }
 740+
 741+
 742+ function addTemplatesForm( $notice ) {
 743+ global $wgUser;
 744+ $sk = $wgUser->getSkin();
 745+ $dbr = wfGetDB( DB_SLAVE );
 746+ $res = $dbr->select( 'cn_templates', 'tmp_name', '', '', array( 'ORDER BY' => 'tmp_id' ) );
 747+
 748+ $res_assignments = $dbr->select(
 749+ array(
 750+ 'cn_notices',
 751+ 'cn_assignments',
 752+ 'cn_templates'
 753+ ),
 754+ array(
 755+ 'cn_templates.tmp_name',
 756+ ),
 757+ array(
 758+ 'cn_notices.not_name' => $notice,
 759+ 'cn_notices.not_id = cn_assignments.not_id',
 760+ 'cn_assignments.tmp_id = cn_templates.tmp_id'
 761+ ),
 762+ __METHOD__,
 763+ array('ORDER BY' => 'cn_notices.not_id')
 764+ );
 765+
 766+ if ( $dbr->numRows( $res ) > 0 ) {
 767+ // Build HTML
 768+ $htmlOut = Xml::fieldset( wfMsg( "centralnotice-available-templates") );
 769+ $htmlOut .= Xml::openElement( 'table', array( 'cellpadding' => 9 ) );
 770+
 771+
 772+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
 773+ wfMsg ( "centralnotice-add" ) );
 774+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
 775+ wfMsg ( "centralnotice-weight" ) );
 776+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '70%' ),
 777+ wfMsg ( "centralnotice-templates" ) );
 778+ // Find dups
 779+ $templatesAssigned = $this->selectTemplatesAssigned( $notice );
 780+
 781+ // Build rows
 782+ while ( $row = $dbr->fetchObject( $res )) {
 783+ if ( !in_array ( $row->tmp_name, $templatesAssigned ) ) {
 784+ $htmlOut .= Xml::openElement( 'tr' );
 785+
 786+ // Add
 787+ $htmlOut .= Xml::tags( 'td', null,
 788+ Xml::check( 'addTemplates[]', '', array ( 'value' => $row->tmp_name))
 789+ );
 790+
 791+ // Weight
 792+ $htmlOut .= Xml::tags( 'td', null,
 793+ Xml::listDropDown( "weight[$row->tmp_name]",
 794+ $this->dropDownList( wfMsg( 'centralnotice-weight' ), range ( 0, 100, 5)) ,
 795+ '',
 796+ 0,
 797+ '',
 798+ 16)
 799+ );
 800+
 801+ // Render preview
 802+ $viewPage = SpecialPage::getTitleFor( 'NoticeTemplate/view' );
 803+ $render = new SpecialNoticeText();
 804+ $render->project = 'wikipedia';
 805+ global $wgRequest;
 806+ $render->language = $wgRequest->getVal( 'wpUserLanguage' );
 807+ $htmlOut .= Xml::tags( 'td', null,
 808+ $sk->makeLinkObj( $viewPage,
 809+ htmlspecialchars( $row->tmp_name ),
 810+ 'template=' . urlencode( $row->tmp_name ) ) .
 811+ Xml::fieldset( wfMsg( 'centralnotice-preview' ),
 812+ $render->getHtmlNotice( $row->tmp_name )
 813+ )
 814+ );
 815+
 816+ $htmlOut .= Xml::closeElement( 'tr' );
 817+ }
 818+ }
 819+
 820+ $htmlOut .= Xml::closeElement( 'table' );
 821+ $htmlOut .= Xml::closeElement( 'fieldset' );
 822+ } else {
 823+ // Nothing found
 824+ return;
 825+ }
 826+ return $htmlOut;
 827+ }
 828+
 829+
 830+ function selectTemplatesAssigned ( $notice ) {
 831+ $dbr = wfGetDB( DB_SLAVE );
 832+ $res = $dbr->select(
 833+ array(
 834+ 'cn_notices',
 835+ 'cn_assignments',
 836+ 'cn_templates'
 837+ ),
 838+ array(
 839+ 'cn_templates.tmp_name',
 840+ ),
 841+ array(
 842+ 'cn_notices.not_name' => $notice,
 843+ 'cn_notices.not_id = cn_assignments.not_id',
 844+ 'cn_assignments.tmp_id = cn_templates.tmp_id'
 845+ ),
 846+ __METHOD__,
 847+ array('ORDER BY' => 'cn_notices.not_id')
 848+ );
 849+ $templateNames = array();
 850+ foreach ( $res as $row ) {
 851+ array_push( $templateNames, $row->tmp_name ) ;
 852+ }
 853+ return $templateNames;
 854+ }
 855+ /**
 856+ * Lookup function for active notice under a given language and project
 857+ * Returns an id for the running notice
 858+ */
 859+ function selectNoticeTemplates( $project, $language ) {
 860+ $dbr = wfGetDB( DB_SLAVE );
 861+ $encTimestamp = $dbr->addQuotes( $dbr->timestamp() );
 862+ $res = $dbr->select(
 863+ array(
 864+ 'cn_notices',
 865+ 'cn_assignments',
 866+ 'cn_templates',
 867+ ),
 868+ array(
 869+ 'tmp_name',
 870+ 'SUM(tmp_weight) AS total_weight'
 871+ ),
 872+ array (
 873+ "not_start <= $encTimestamp",
 874+ "not_end >= $encTimestamp",
 875+ "not_enabled = 1",
 876+ "not_language" => array( '', $language ),
 877+ "not_project" => array( '', $project ),
 878+ 'cn_notices.not_id=cn_assignments.not_id',
 879+ 'cn_assignments.tmp_id=cn_templates.tmp_id',
 880+ ),
 881+ __METHOD__,
 882+ array(
 883+ 'GROUP BY' => 'tmp_name',
 884+ )
 885+ );
 886+ $templateWeights = array();
 887+ foreach( $res as $row ) {
 888+ $name = $row->tmp_name;
 889+ $weight = intval( $row->total_weight );
 890+ $templateWeights[$name] = $weight;
 891+ }
 892+ return $templateWeights;
 893+ }
 894+
 895+ function addNotice( $noticeName, $enabled, $start, $project_name, $project_language ) {
 896+ global $wgOut;
 897+
 898+ $dbr = wfGetDB( DB_SLAVE );
 899+ $res = $dbr->select( 'cn_notices', 'not_name', array( 'not_name' => $noticeName ) );
 900+ if ( $dbr->numRows( $res ) > 0 ) {
 901+ $wgOut->addHTML( wfMsg( 'centralnotice-notice-exists' ) );
 902+ return;
 903+ } else {
 904+ $dbw = wfGetDB( DB_MASTER );
 905+ $start['hour'] = substr( $start['hour'], 0 , 2 );
 906+ if ( $start['month'] == 12 ) {
 907+ $end['month'] = '01';
 908+ $end['year'] = ($start['year'] + 1);
 909+ } elseif ( $start['month'] == '09' ) {
 910+ $end['month'] = '10';
 911+ $end['year'] = $start['year'];
 912+ } else {
 913+ $end['month'] = ( substr( $start['month'], 0, 1) ) == 0 ? 0 . ( intval( $start['month'] ) + 1 ) : ( $start['month'] + 1 );
 914+ $end['year'] = $start['year'];
 915+ }
 916+
 917+ $startTs = wfTimeStamp( TS_MW, "{$start['year']}:{$start['month']}:{$start['day']} {$start['hour']}:00:00" );
 918+ $endTs = wfTimeStamp( TS_MW, "{$end['year']}:{$end['month']}:{$start['day']} {$start['hour']}:00:00" );
 919+
 920+ $res = $dbr->select( 'cn_notices', 'not_name',
 921+ array (
 922+ 'not_start >= ' . $dbr->addQuotes( $dbr->timestamp( $startTs ) ),
 923+ 'not_end <= ' . $dbr->addQuotes( $dbr->timestamp( $endTs ) ),
 924+ 'not_project' => $project_name,
 925+ 'not_language' => $project_language
 926+ )
 927+ );
 928+ if ( $dbr->numRows( $res ) > 0 ) {
 929+ $wgOut->addHtml( wfMsg( 'centralnotice-overlap' ) );
 930+ } else {
 931+ $res = $dbw->insert( 'cn_notices',
 932+ array( 'not_name' => $noticeName,
 933+ 'not_enabled' => $enabled,
 934+ 'not_start' => $dbr->timestamp( $startTs ),
 935+ 'not_end' => $dbr->timestamp( $endTs ),
 936+ 'not_project' => $project_name,
 937+ 'not_language' => $project_language
 938+ )
 939+ );
 940+ }
 941+ return;
 942+ }
 943+ }
 944+
 945+ function removeNotice( $noticeName ) {
 946+ global $wgOut;
 947+ $dbr = wfGetDB( DB_SLAVE );
 948+
 949+ $res = $dbr->select( 'cn_notices', 'not_name, not_locked',
 950+ array( 'not_name' => $noticeName )
 951+ );
 952+ if ( $dbr->numRows( $res ) < 1 ) {
 953+ $wgOut->addHTML( wfMsg( 'centralnotice-notice-doesnt-exist' ) );
 954+ return;
 955+ }
 956+ $row = $dbr->fetchObject( $res );
 957+ if ( $row->not_locked == '1' ) {
 958+ $wgOut->addHTML( wfMsg( 'centralnotice-notice-is-locked' ) );
 959+ return;
 960+ } else {
 961+ $dbw = wfGetDB( DB_MASTER );
 962+ $noticeId = htmlspecialchars( $this->getNoticeId( $noticeName ) );
 963+ $res = $dbw->delete( 'cn_assignments', array ( 'not_id' => $noticeId ) );
 964+ $res = $dbw->delete( 'cn_notices', array ( 'not_name' => $noticeName ) );
 965+ return;
 966+ }
 967+ }
 968+
 969+ function addTemplateTo( $noticeName, $templateName, $weight ) {
 970+ global $wgOut;
 971+
 972+ $dbr = wfGetDB( DB_SLAVE );
 973+
 974+ $eNoticeName = htmlspecialchars ( $noticeName );
 975+ $noticeId = $this->getNoticeId( $eNoticeName );
 976+ $templateId = $this->getTemplateId( $templateName );
 977+ $res = $dbr->select( 'cn_assignments', 'asn_id',
 978+ array(
 979+ 'tmp_id' => $templateId,
 980+ 'not_id' => $noticeId
 981+ )
 982+ );
 983+ if ( $dbr->numRows( $res ) > 0 ) {
 984+ $wgOut->addHTML( wfMsg( 'centralnotice-template-already-exists' ) );
 985+ } else {
 986+ $dbw = wfGetDB( DB_MASTER );
 987+ $noticeId = $this->getNoticeId( $eNoticeName );
 988+ $res = $dbw->insert('cn_assignments',
 989+ array(
 990+ 'tmp_id' => $templateId,
 991+ 'tmp_weight' => $weight,
 992+ 'not_id' => $noticeId
 993+ )
 994+ );
 995+ }
 996+ }
 997+
 998+ function getNoticeId ( $noticeName ) {
 999+ $dbr = wfGetDB( DB_SLAVE );
 1000+ $eNoticeName = htmlspecialchars( $noticeName );
 1001+ $res = $dbr->select( 'cn_notices', 'not_id', array( 'not_name' => $eNoticeName ) );
 1002+ $row = $dbr->fetchObject( $res );
 1003+ return $row->not_id;
 1004+ }
 1005+
 1006+ function getNoticeLanguage ( $noticeName ) {
 1007+ $dbr = wfGetDB( DB_SLAVE );
 1008+ $eNoticeName = htmlspecialchars( $noticeName );
 1009+ $res = $dbr->select( 'cn_notices', 'not_language', array( 'not_name' => $eNoticeName ) );
 1010+ $row = $dbr->fetchObject( $res );
 1011+ return $row->not_language;
 1012+ }
 1013+
 1014+ function getNoticeProjectName ( $noticeName ) {
 1015+ $dbr = wfGetDB( DB_SLAVE );
 1016+ $eNoticeName = htmlspecialchars( $noticeName );
 1017+ $res = $dbr->select( 'cn_notices', 'not_project', array( 'not_name' => $eNoticeName ) );
 1018+ $row = $dbr->fetchObject( $res );
 1019+ return $row->not_project;
 1020+ }
 1021+
 1022+ function getTemplateId ( $templateName ) {
 1023+ $dbr = wfGetDB( DB_SLAVE );
 1024+ $templateName = htmlspecialchars ( $templateName );
 1025+ $res = $dbr->select( 'cn_templates', 'tmp_id', array( 'tmp_name' => $templateName ) );
 1026+ $row = $dbr->fetchObject( $res );
 1027+ return $row->tmp_id;
 1028+ }
 1029+
 1030+ function removeTemplateFor( $noticeName, $templateName) {
 1031+ global $wgOut;
 1032+
 1033+ $dbw = wfGetDB( DB_MASTER );
 1034+ $noticeId = $this->getNoticeId( $noticeName );
 1035+ $templateId = $this->getTemplateId( $templateName );
 1036+ $res = $dbw->delete( 'cn_assignments', array ( 'tmp_id' => $templateId, 'not_id' => $noticeId ) );
 1037+ }
 1038+
 1039+ function updateNoticeDate ( $noticeName, $start, $end ) {
 1040+ global $wgOut;
 1041+
 1042+ $dbr = wfGetDB( DB_SLAVE );
 1043+ $project_name = $this->getNoticeProjectname( $noticeName );
 1044+ $project_language = $this->getNoticeLanguage( $noticeName );
 1045+
 1046+ // Start / end dont line up
 1047+ if ( $start > $end || $end < $start) {
 1048+ $wgOut->addHtml( wfMsg( 'centralnotice-invalid-date-range3' ) );
 1049+ return;
 1050+ }
 1051+
 1052+ // Invalid notice name
 1053+ $res = $dbr->select( 'cn_notices', 'not_name', array( 'not_name' => $noticeName ) );
 1054+ if ( $dbr->numRows( $res ) < 1 ) {
 1055+ $wgOut->addHTML( wfMsg( 'centralnotice-doesnt-exist' ) );
 1056+ }
 1057+
 1058+ // Overlap over a date within the same project and language
 1059+ $startDate = $dbr->timestamp( $start );
 1060+ $endDate = $dbr->timestamp( $end );
 1061+ $res = $dbr->select( 'cn_notices', 'not_id',
 1062+ array(
 1063+ 'not_language' => $project_language,
 1064+ 'not_project' => $project_name,
 1065+ "not_end <= {$endDate}",
 1066+ "not_start >= {$startDate}"
 1067+ )
 1068+ );
 1069+ if ( $dbr->numRows( $res ) > 1 ) {
 1070+ $wgOut->addHtml( wfMsg( 'centralnotice-overlap-with-existing-notice' ) );
 1071+ return;
 1072+ } else {
 1073+ $dbw = wfGetDB( DB_MASTER );
 1074+ $res = $dbw->update( 'cn_notices',
 1075+ array(
 1076+ 'not_start' => $start,
 1077+ 'not_end' => $end
 1078+ ),
 1079+ array( 'not_name' => $noticeName )
 1080+ );
 1081+ }
 1082+ }
 1083+
 1084+ function updateLock ( $noticeName, $isLocked ) {
 1085+ global $wgOut;
 1086+
 1087+ $dbr = wfGetDB( DB_SLAVE );
 1088+ $res = $dbr->select( 'cn_notices', 'not_name',
 1089+ array( 'not_name' => $noticeName )
 1090+ );
 1091+ if ( $dbr->numRows( $res ) < 1 ) {
 1092+ $wgOut->addHTML( wfMsg( 'centralnotice-doesnt-exist') );
 1093+ } else {
 1094+ $dbw = wfGetDB( DB_MASTER );
 1095+ $res = $dbw->update( 'cn_notices',
 1096+ array( 'not_locked' => $isLocked ),
 1097+ array( 'not_name' => $noticeName )
 1098+ );
 1099+ }
 1100+ }
 1101+
 1102+ function updateWeight ( $noticeName, $templateName, $weight ) {
 1103+ $dbw = wfGetDB( DB_MASTER );
 1104+ $noticeId = $this->getNoticeId( $noticeName );
 1105+ $templateId = $this->getTemplateId( $templateName );
 1106+ $res = $dbw->update( 'cn_assignments',
 1107+ array ( 'tmp_weight' => $weight ),
 1108+ array(
 1109+ 'tmp_id' => $templateId,
 1110+ 'not_id' => $noticeId
 1111+ )
 1112+ );
 1113+ }
 1114+
 1115+ function projectDropDownList( $selected='' ) {
 1116+ global $wgNoticeProjects;
 1117+
 1118+ $htmlOut = Xml::openElement( 'select', array( 'name' => 'project_name' ) );
 1119+ $htmlOut .= Xml::option( 'All projects', '', ($selected == '') );
 1120+ foreach( $wgNoticeProjects as $value ) {
 1121+ $htmlOut .= Xml::option( $value, $value, ($selected == $value) );
 1122+ }
 1123+ $htmlOut .= Xml::closeElement( 'select' );
 1124+ return $htmlOut;
 1125+ }
 1126+
 1127+ function languageDropDownList( $selected='' ) {
 1128+ // Language
 1129+ list( $lsLabel, $lsSelect) = Xml::languageSelector( $selected );
 1130+
 1131+ /*
 1132+ * Dirty hack to add our very own "All" option
 1133+ */
 1134+ // Strip selected flag
 1135+ if( $selected == '' ) {
 1136+ $lsSelect = str_replace( ' selected="selected"', '', $lsSelect );
 1137+ }
 1138+
 1139+ // Find the first select tag
 1140+ $insertPoint = stripos( $lsSelect , '<option' );
 1141+
 1142+ // Create our own option
 1143+ $option = Xml::option( 'All languages', '', ($selected == '') );
 1144+
 1145+ // Insert our option
 1146+ $lsSelect = substr( $lsSelect, 0, $insertPoint ) . $option . substr( $lsSelect, $insertPoint );
 1147+
 1148+ return array( $lsLabel, $lsSelect );
 1149+ }
 1150+
 1151+ function getProjectName( $value ) {
 1152+ return $value; // @fixme -- use wfMsg()
 1153+ }
 1154+
 1155+ function updateProjectName( $notice, $projectName ) {
 1156+ $dbw = wfGetDB( DB_MASTER );
 1157+ $res = $dbw->update( 'cn_notices',
 1158+ array ( 'not_project' => $projectName ),
 1159+ array(
 1160+ 'not_name' => $notice
 1161+ )
 1162+ );
 1163+ }
 1164+
 1165+ function updateProjectLanguage( $notice, $language ) {
 1166+ $dbw = wfGetDB( DB_MASTER );
 1167+ $res = $dbw->update( 'cn_notices',
 1168+ array ( 'not_language' => $language ),
 1169+ array(
 1170+ 'not_name' => $notice
 1171+ )
 1172+ );
 1173+ }
 1174+
 1175+ function dropDownList ( $text, $values ) {
 1176+ $dropDown = "* {$text}\n";
 1177+ foreach( $values as $value ) {
 1178+ $dropDown .= "**{$value}\n";
 1179+ }
 1180+ return $dropDown;
 1181+ }
 1182+
 1183+ function addZero ( $text ) {
 1184+ // Prepend a 0 for text needing it
 1185+ if ( strlen( $text ) == 1 ) {
 1186+ $text = "0{$text}";
 1187+ }
 1188+ return $text;
 1189+ }
 1190+}
Property changes on: trunk/extensions/CentralNotice/SpecialCentralNotice.php
___________________________________________________________________
Added: svn:eol-style
11191 + native
Index: trunk/extensions/CentralNotice/SpecialNoticeLocal.php
@@ -15,7 +15,7 @@
1616
1717 function getJsOutput( $par ) {
1818 $text = '';
19 - if( $par == 'anon' ) {
 19+ if( $par == 'anonnotice.js' ) {
2020 $text = wfGetCachedNotice( 'anonnotice' );
2121 }
2222 if( !$text ) {
Index: trunk/extensions/CentralNotice/NoticePage.php
@@ -16,11 +16,11 @@
1717 }
1818
1919 protected function sharedMaxAge() {
20 - return 86400;
 20+ return 600;
2121 }
2222
2323 protected function maxAge() {
24 - return 86400;
 24+ return 600;
2525 }
2626
2727 private function sendHeaders() {
@@ -43,4 +43,4 @@
4444 function getJsOutput( $par ) {
4545 return "";
4646 }
47 -}
\ No newline at end of file
 47+}
Index: trunk/extensions/CentralNotice/SpecialNoticeTemplate.php
@@ -0,0 +1,502 @@
 2+<?php
 3+
 4+if ( !defined( 'MEDIAWIKI' ) ) {
 5+ echo "CentralNotice extension\n";
 6+ exit( 1 );
 7+}
 8+
 9+class SpecialNoticeTemplate extends UnlistedSpecialPage {
 10+
 11+ /* Functions */
 12+
 13+ function __construct() {
 14+ // Initialize special page
 15+ parent::__construct( 'NoticeTemplate' );
 16+
 17+ // Internationalization
 18+ wfLoadExtensionMessages( 'CentralNotice' );
 19+ }
 20+
 21+ function execute( $sub ) {
 22+ global $wgOut, $wgUser, $wgRequest;
 23+
 24+ // Begin output
 25+ $this->setHeaders();
 26+
 27+ // Get current skin
 28+ $sk = $wgUser->getSkin();
 29+
 30+ // Check permissions
 31+ if ( !$wgUser->isAllowed( 'centralnotice_admin_rights' ) ) {
 32+ $wgOut->permissionRequired( 'centralnotice_admin_rights' );
 33+ return;
 34+ }
 35+
 36+ // Show summary
 37+ $wgOut->addWikiText( wfMsg( 'centralnotice-summary' ) );
 38+
 39+ // Show header
 40+ CentralNotice::printHeader();
 41+
 42+ // Handle forms
 43+ if ( $wgRequest->wasPosted() ) {
 44+
 45+ // Handle removing
 46+ $toRemove = $wgRequest->getArray( 'removeTemplates' );
 47+ if ( isset( $toRemove ) ) {
 48+ // Remove templates in list
 49+ foreach ( $toRemove as $template ) {
 50+ $this->removeTemplate( $template );
 51+ }
 52+ }
 53+
 54+ // Handle translation message update
 55+ $update = $wgRequest->getArray('updateText');
 56+ $token = $wgRequest->getArray('token');
 57+ if (isset ( $update ) ) {
 58+ foreach ( $update as $lang => $messages ) {
 59+ foreach ( $messages as $text => $translation) {
 60+ // If we actually have text
 61+ if ( $translation ) {
 62+ $this->updateMessage( $text, $translation, $lang, $token );
 63+ }
 64+ }
 65+ }
 66+ }
 67+ }
 68+
 69+ // Handle adding
 70+ if ( $wgRequest->getVal( 'wpMethod' ) == 'addTemplate' ) {
 71+ $this->addTemplate(
 72+ $wgRequest->getVal( 'templateName' ),
 73+ $wgRequest->getVal( 'templateBody' )
 74+ );
 75+ $sub = 'view';
 76+ }
 77+
 78+ // Handle Editing
 79+ if ( $wgRequest->getVal( 'wpMethod' ) == 'editTemplate' ) {
 80+ $this->editTemplate(
 81+ $wgRequest->getVal( 'template' ),
 82+ $wgRequest->getVal( 'templateBody' )
 83+ );
 84+ $sub = 'view';
 85+ }
 86+
 87+ // Handle viewing a specific template
 88+ if ( $sub == 'view' && $wgRequest->getText( 'template' ) != '' ) {
 89+ $this->showView();
 90+ return;
 91+ }
 92+
 93+ // Handle viewing a specific template
 94+ if ( $sub == 'add' ) {
 95+ $this->showAdd();
 96+ return;
 97+ }
 98+
 99+ // Show list by default
 100+ $this->showList();
 101+ }
 102+
 103+ function showList() {
 104+ global $wgOut, $wgTitle, $wgUser, $wgRequest;
 105+
 106+ $sk = $wgUser->getSkin();
 107+
 108+ // Templates
 109+ $templates = $this->queryTemplates();
 110+ if ( count( $templates ) > 0 ) {
 111+ $htmlOut = Xml::openElement( 'form',
 112+ array(
 113+ 'method' => 'post',
 114+ 'action' => ''
 115+ )
 116+ );
 117+ $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-available-templates' ) );
 118+ $htmlOut .= Xml::openElement( 'table',
 119+ array(
 120+ 'cellpadding' => 9,
 121+ 'width' => '100%'
 122+ )
 123+ ) ;
 124+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
 125+ wfMsg ( 'centralnotice-remove' )
 126+ );
 127+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left' ),
 128+ wfMsg ( 'centralnotice-template-name' )
 129+ );
 130+
 131+ $msgConfirmDelete = wfMsgHTML( 'centralnotice-confirm-delete' );
 132+ foreach ( $templates as $templateName ) {
 133+ $viewPage = SpecialPage::getTitleFor( 'NoticeTemplate/view' );
 134+ $htmlOut .= Xml::openElement( 'tr' );
 135+
 136+ // Remove box
 137+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 138+ Xml::check( 'removeTemplates[]', false,
 139+ array(
 140+ 'value' => $templateName,
 141+ 'onchange' => "if(this.checked){this.checked=confirm('{$msgConfirmDelete}')}"
 142+ )
 143+ )
 144+ );
 145+
 146+ // Link and Preview
 147+ $render = new SpecialNoticeText();
 148+ $render->project = 'wikipedia';
 149+ $render->language = $wgRequest->getVal( 'wpUserLanguage' );
 150+ $htmlOut .= Xml::tags( 'td', null,
 151+ $sk->makeLinkObj( $viewPage,
 152+ htmlspecialchars( $templateName ),
 153+ 'template=' . urlencode( $templateName ) ) .
 154+ Xml::fieldset( wfMsg( 'centralnotice-preview' ),
 155+ $render->getHtmlNotice( $templateName )
 156+ )
 157+ );
 158+
 159+ $htmlOut .= Xml::closeElement( 'tr' );
 160+ }
 161+ $htmlOut .= Xml::tags( 'tr', null,
 162+ Xml::tags( 'td', array( 'colspan' => 3 ),
 163+ Xml::submitButton( wfMsg( 'centralnotice-modify' ) )
 164+ )
 165+ );
 166+ } else {
 167+ $htmlOut = Xml::tags( 'tr', null,
 168+ Xml::element( 'td', null, wfMsg( 'centralnotice-no-templates' ) )
 169+ );
 170+ }
 171+ $htmlOut .= Xml::closeElement( 'table' );
 172+ $htmlOut .= Xml::closeElement( 'fieldset' );
 173+ $htmlOut .= Xml::closeElement( 'form' );
 174+
 175+ // Show add link
 176+ $newPage = SpecialPage::getTitleFor( 'NoticeTemplate/add' );
 177+ $htmlOut .= $sk->makeLinkObj( $newPage, wfMsgHtml( 'centralnotice-add-template' ) );
 178+
 179+ // Output HTML
 180+ $wgOut->addHtml( $htmlOut );
 181+ }
 182+
 183+ function showAdd() {
 184+ global $wgOut, $wgTitle, $wgUser;
 185+
 186+ // Build HTML
 187+ $htmlOut = Xml::openElement( 'form', array( 'method' => 'post' ) );
 188+ $htmlOut .= Xml::openElement( 'fieldset' );
 189+ $htmlOut .= Xml::element( 'legend', null, wfMsg( 'centralnotice-add-template' ) );
 190+ $htmlOut .= Xml::hidden( 'wpMethod', 'addTemplate' );
 191+ $htmlOut .= Xml::tags( 'p', null,
 192+ Xml::inputLabel(
 193+ wfMsg( 'centralnotice-template-name' ),
 194+ 'templateName',
 195+ 'templateName',
 196+ 25
 197+ )
 198+ );
 199+ $htmlOut .= Xml::tags( 'p', null,
 200+ Xml::textarea( 'templateBody', '', 60, 20 )
 201+ );
 202+ $htmlOut .= Xml::tags( 'p', null,
 203+ Xml::submitButton( wfMsg( 'centralnotice-modify' ) )
 204+ );
 205+ $htmlOut .= Xml::closeElement( 'fieldset' );
 206+ $htmlOut .= Xml::closeElement( 'form' );
 207+
 208+ // Output HTML
 209+ $wgOut->addHtml( $htmlOut );
 210+ }
 211+
 212+ private function showView() {
 213+ global $wgOut, $wgUser, $wgRequest, $wgContLanguageCode;
 214+
 215+ $sk = $wgUser->getSkin();
 216+
 217+ // Get token
 218+ $token = $wgUser->editToken();
 219+
 220+ // Get user's language
 221+ $wpUserLang = $wgRequest->getVal('wpUserLanguage') ? $wgRequest->getVal('wpUserLanguage') : $wgContLanguageCode;
 222+
 223+ // Get current template
 224+ $currentTemplate = $wgRequest->getText( 'template' );
 225+
 226+ // Show preview
 227+ $render = new SpecialNoticeText();
 228+ $render->project = 'wikipedia';
 229+ $render->language = $wgRequest->getVal( 'wpUserLanguage' );
 230+ $htmlOut = Xml::fieldset( wfMsg( 'centralnotice-preview' ),
 231+ $render->getHtmlNotice( $wgRequest->getText( 'template' ) )
 232+ );
 233+
 234+ // Build HTML
 235+ $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
 236+ $htmlOut .= Xml::fieldset( wfMsgHtml( 'centralnotice-translate-heading', $currentTemplate ) );
 237+ $htmlOut .= Xml::openElement( 'table',
 238+ array (
 239+ 'cellpadding' => 9,
 240+ 'width' => '100%'
 241+ )
 242+ );
 243+
 244+ // Headers
 245+ $htmlOut .= Xml::element( 'th', array( 'width' => '15%' ), wfMsg( 'centralnotice-message' ) );
 246+ $htmlOut .= Xml::element( 'th', array( 'width' => '5%' ), wfMsg ( 'centralnotice-number-uses') );
 247+ $htmlOut .= Xml::element( 'th', array( 'width' => '40%' ), wfMsg ( 'centralnotice-english') );
 248+ $languages = Language::getLanguageNames();
 249+ $htmlOut .= Xml::element( 'th', array( 'width' => '40%' ), $languages[$wpUserLang] );
 250+
 251+ $body = wfMsg( "Centralnotice-template-{$currentTemplate}" );
 252+
 253+ // Generate fields from parsing the body
 254+ $fields = array();
 255+ preg_match_all( '/\{\{\{([A-Za-z0-9\_\-}]+)\}\}\}/', $body, $fields );
 256+
 257+ // Remove duplicates
 258+ $filteredFields = array();
 259+ foreach( $fields[1] as $field ) {
 260+ $filteredFields[$field] = array_key_exists( $field, $filteredFields ) ? $filteredFields[$field] + 1 : 1;
 261+ }
 262+
 263+ // Rows
 264+ foreach( $filteredFields as $field => $count ) {
 265+ // Message
 266+ $message = ( $wpUserLang == 'en' ) ? "Centralnotice-{$currentTemplate}-{$field}" : "Centralnotice-{$currentTemplate}-{$field}/{$wpUserLang}";
 267+
 268+ // English value
 269+ $htmlOut .= Xml::openElement( 'tr' );
 270+
 271+ $title = Title::newFromText( "MediaWiki:{$message}" );
 272+ $htmlOut .= Xml::tags( 'td', null,
 273+ $sk->makeLinkObj( $title, htmlspecialchars( $field ) )
 274+ );
 275+
 276+ $htmlOut .= Xml::element( 'td', null, $count);
 277+
 278+ // English text
 279+ $englishText = wfMsg( 'centralnotice-message-not-set' );
 280+ $englishTextExists = false;
 281+ if( Title::newFromText( "Centralnotice-{$currentTemplate}-{$field}", NS_MEDIAWIKI )->exists() ) {
 282+ $englishText = wfMsgExt( "Centralnotice-{$currentTemplate}-{$field}",
 283+ array( 'language' => 'en' )
 284+ );
 285+ $englishTextExists = true;
 286+ }
 287+ $htmlOut .= Xml::tags( 'td', null,
 288+ Xml::element( 'span',
 289+ array( 'style' => 'font-style:italic;' . ( !$englishTextExists ? 'color:silver' : '' ) ),
 290+ $englishText
 291+ )
 292+ );
 293+
 294+ // Foreign text input
 295+ $foreignText = '';
 296+ $foreignTextExists = false;
 297+ if( Title::newFromText( $message, NS_MEDIAWIKI )->exists() ) {
 298+ $foreignText = wfMsgExt( "Centralnotice-{$currentTemplate}-{$field}",
 299+ array( 'language' => $wpUserLang )
 300+ );
 301+ $foreignTextExists = true;
 302+ }
 303+ $htmlOut .= Xml::tags( 'td', null,
 304+ Xml::input( "updateText[{$wpUserLang}][{$currentTemplate}-{$field}]", '', $foreignText,
 305+ array( 'style' => 'width:100%;' . ( !$foreignTextExists ? 'color:red' : '' ) )
 306+ )
 307+ );
 308+
 309+ $htmlOut .= Xml::closeElement( 'tr' );
 310+ }
 311+ $htmlOut .= Xml::hidden( 'token', $token );
 312+ $htmlOut .= Xml::hidden( 'wpUserLanguage', $wpUserLang );
 313+ $htmlOut .= Xml::openElement( 'tr' );
 314+ $htmlOut .= Xml::tags( 'td', array( 'colspan' => 4 ),
 315+ Xml::submitButton( wfMsg('centralnotice-modify', array( 'name' => 'update') ) )
 316+ );
 317+
 318+ $htmlOut .= Xml::closeElement( 'tr' );
 319+ $htmlOut .= Xml::closeElement( 'table' );
 320+ $htmlOut .= Xml::closeElement( 'fieldset' );
 321+ $htmlOut .= Xml::closeElement( 'form' );
 322+
 323+ /*
 324+ * Show language selection form
 325+ */
 326+ $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
 327+ $htmlOut .= Xml::fieldset( wfMsgHtml( 'centralnotice-change-lang' ) );
 328+ $htmlOut .= Xml::openElement( 'table', array ( 'cellpadding' => 9 ) );
 329+ list( $lsLabel, $lsSelect) = Xml::languageSelector( $wpUserLang );
 330+ $htmlOut .= Xml::tags( 'tr', null,
 331+ Xml::tags( 'td', null, $lsLabel ) .
 332+ Xml::tags( 'td', null, $lsSelect ) .
 333+ Xml::tags( 'td', array( 'colspan' => 2 ),
 334+ Xml::submitButton( wfMsgHtml('centralnotice-modify') )
 335+ )
 336+ );
 337+ $htmlOut .= Xml::closeElement( 'table' );
 338+ $htmlOut .= Xml::closeElement( 'fieldset' );
 339+ $htmlOut .= Xml::closeElement( 'form' );
 340+
 341+ /*
 342+ * Show edit form
 343+ */
 344+ $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
 345+ $htmlOut .= Xml::fieldset( wfMsgHtml( 'centralnotice-edit-template' ) );
 346+ $htmlOut .= Xml::hidden( 'wpMethod', 'editTemplate' );
 347+ $htmlOut .= Xml::openElement( 'table',
 348+ array(
 349+ 'cellpadding' => 9,
 350+ 'width' => '100%'
 351+ )
 352+ );
 353+ $htmlOut .= Xml::tags( 'tr', null,
 354+ Xml::tags( 'td', null, Xml::textarea( 'templateBody', $body, 60, 20 ) )
 355+ );
 356+ $htmlOut .= Xml::tags( 'tr', null,
 357+ Xml::tags( 'td', null, Xml::submitButton( wfMsgHtml('centralnotice-modify') ) )
 358+ );
 359+ $htmlOut .= Xml::closeElement( 'table' );
 360+ $htmlOut .= Xml::closeElement( 'fieldset' );
 361+ $htmlOut .= Xml::closeElement( 'form' );
 362+
 363+ // Output HTML
 364+ $wgOut->addHTML( $htmlOut );
 365+ }
 366+
 367+ private function updateMessage( $text, $translation, $lang, $token ) {
 368+ global $wgUser;
 369+
 370+ $title = Title::newFromText(
 371+ ( $lang == 'en' ) ? "Centralnotice-{$text}" : "Centralnotice-{$text}/{$lang}",
 372+ NS_MEDIAWIKI
 373+ );
 374+ $article = new Article( $title );
 375+ $article->doEdit( $translation, '' );
 376+ }
 377+
 378+ static function queryTemplates() {
 379+ $dbr = wfGetDB( DB_SLAVE );
 380+ $res = $dbr->select( 'cn_templates',
 381+ array( 'tmp_name', 'tmp_id' ),
 382+ '',
 383+ __METHOD__,
 384+ array( 'ORDER BY' => 'tmp_id' )
 385+ );
 386+
 387+ $templates = array();
 388+ while ( $row = $dbr->fetchObject( $res ) ) {
 389+ array_push( $templates, $row->tmp_name );
 390+ }
 391+
 392+ return $templates;
 393+ }
 394+
 395+ private function getTemplateId ( $templateName ) {
 396+ global $wgOut, $egCentralNoticeTables;
 397+
 398+ $dbr = wfGetDB( DB_SLAVE );
 399+ $res = $dbr->select( 'cn_templates', 'tmp_id',
 400+ array( 'tmp_name' => $templateName ),
 401+ __METHOD__
 402+ );
 403+
 404+ $row = $dbr->fetchObject( $res );
 405+ if( $row ) {
 406+ return $row->tmp_id;
 407+ }
 408+ return null;
 409+ }
 410+
 411+ private function removeTemplate ( $name ) {
 412+ global $wgOut, $egCentralNoticeTables;
 413+
 414+ if ( $name == '' ) {
 415+ $wgOut->addHtml( wfMsg( 'centralnotice-template-doesnt-exist' ) );
 416+ return;
 417+ }
 418+
 419+ $id = $this->getTemplateId( $name );
 420+ $dbr = wfGetDB( DB_SLAVE );
 421+ $res = $dbr->select( 'cn_assignments', 'asn_id', array( 'tmp_id' => $id ), __METHOD__ );
 422+
 423+ if ( $dbr->numRows( $res ) > 0 ) {
 424+ $wgOut->addHtml( wfMsg( 'centralnotice-template-still-bound' ) );
 425+ return;
 426+ } else {
 427+ $dbw = wfGetDB( DB_MASTER );
 428+ $res = $dbw->delete( 'cn_templates',
 429+ array( 'tmp_id' => $id ),
 430+ __METHOD__
 431+ );
 432+
 433+ $article = new Article(
 434+ Title::newFromText( "centralnotice-template-{$name}", NS_MEDIAWIKI )
 435+ );
 436+ $article->doDeleteArticle( 'CentralNotice Automated Removal' );
 437+ }
 438+ }
 439+
 440+ private function addTemplate ( $name, $body ) {
 441+ global $wgOut, $egCentralNoticeTables;
 442+
 443+ if ( $body == '' || $name == '' ) {
 444+ $wgOut->addHtml( wfMsg( 'centralnotice-null-string' ) );
 445+ return;
 446+ }
 447+
 448+ // Format name so there are only letters, numbers, and underscores
 449+ $name = ereg_replace( '[^A-Za-z0-9\_]', '', $name );
 450+
 451+ $dbr = wfGetDB( DB_SLAVE );
 452+ $res = $dbr->select( 'cn_templates', 'tmp_name',
 453+ array( 'tmp_name' => $name ),
 454+ __METHOD__
 455+ );
 456+
 457+ if ( $dbr->numRows( $res ) > 0 ) {
 458+ $wgOut->addHTML( wfMsg( 'centralnotice-template-exists' ) );
 459+ return;
 460+ } else {
 461+ $dbw = wfGetDB( DB_MASTER );
 462+ $res = $dbw->insert( 'cn_templates',
 463+ array( 'tmp_name' => $name ),
 464+ __METHOD__
 465+ );
 466+
 467+ /*
 468+ * Perhaps these should move into the db as blob
 469+ */
 470+ $article = new Article(
 471+ Title::newFromText( "centralnotice-template-{$name}", NS_MEDIAWIKI )
 472+ );
 473+ $article->doEdit( $body, '' );
 474+ return;
 475+ }
 476+ }
 477+
 478+ private function editTemplate ( $name, $body ) {
 479+ global $wgOut, $egCentralNoticeTables;
 480+
 481+ if ( $body == '' || $name == '' ) {
 482+ $wgOut->addHtml( wfMsg( 'centralnotice-null-string' ) );
 483+ return;
 484+ }
 485+
 486+ $dbr = wfGetDB( DB_SLAVE );
 487+ $res = $dbr->select( 'cn_templates', 'tmp_name',
 488+ array( 'tmp_name' => $name ),
 489+ __METHOD__
 490+ );
 491+
 492+ if ( $dbr->numRows( $res ) > 0 ) {
 493+ /*
 494+ * Perhaps these should move into the db as blob
 495+ */
 496+ $article = new Article(
 497+ Title::newFromText( "centralnotice-template-{$name}", NS_MEDIAWIKI )
 498+ );
 499+ $article->doEdit( $body, '' );
 500+ return;
 501+ }
 502+ }
 503+}
Property changes on: trunk/extensions/CentralNotice/SpecialNoticeTemplate.php
___________________________________________________________________
Added: svn:eol-style
1504 + native
Index: trunk/extensions/CentralNotice/rebuildLocalTemplates.php
@@ -0,0 +1,38 @@
 2+<?php
 3+
 4+require_once dirname( dirname( dirname( __FILE__ ) ) ) . "/maintenance/commandLine.inc";
 5+
 6+if( !$wgNoticeLocalDirectory ) {
 7+ echo "\$wgNoticeLocalDirectory isn't set -- we're not configured to build static templates.";
 8+}
 9+
 10+if( isset( $options['help'] ) ) {
 11+ echo "Rebuilds templates for local sitenotices for this DB.\n";
 12+ echo "Usage:\n";
 13+ echo " php extensions/CentralNotice/rebuildLocalTemplates.php --wiki=<dbname>\n";
 14+} else {
 15+ echo "Rebuilding templates ...\n";
 16+
 17+ // Hack for parser to avoid barfing from no $wgTitle
 18+ $wgTitle = Title::newFromText( wfMsg( 'mainpage' ) );
 19+
 20+ $notices = array( 'sitenotice.js', 'anonnotice.js' );
 21+ foreach( $notices as $notice ) {
 22+ $key = $notice;
 23+ echo "$wgDBname/$key\n";
 24+
 25+ $builder = new SpecialNoticeLocal();
 26+ $js = $builder->getJsOutput( $key );
 27+
 28+ $outputDir = $wgNoticeLocalDirectory;
 29+ if( wfMkDirParents( $outputDir ) ) {
 30+ $outputFile = "$outputDir/$notice";
 31+ $ok = file_put_contents( $outputFile, $js );
 32+ if( !$ok ) {
 33+ echo "FAILED to write $outputFile!\n";
 34+ }
 35+ } else {
 36+ echo "FAILED to create $outputDir!\n";
 37+ }
 38+ }
 39+}
Property changes on: trunk/extensions/CentralNotice/rebuildLocalTemplates.php
___________________________________________________________________
Added: svn:eol-style
140 + native
Index: trunk/extensions/CentralNotice/CentralNotice.sql
@@ -0,0 +1,25 @@
 2+CREATE TABLE `cn_notices` (
 3+ `not_id` int NOT NULL auto_increment,
 4+ `not_name` varchar(255) NOT NULL,
 5+ `not_start` char(14) NOT NULL,
 6+ `not_end` char(14) NOT NULL,
 7+ `not_enabled` bool NOT NULL default '0',
 8+ `not_locked` bool NOT NULL default '0',
 9+ `not_language` varchar(32) NOT NULL,
 10+ `not_project` varchar(255) NOT NULL,
 11+ PRIMARY KEY (`not_id`)
 12+) /*$wgDBTableOptions*/;
 13+
 14+CREATE TABLE `cn_assignments` (
 15+ `asn_id` int NOT NULL auto_increment,
 16+ `not_id` int NOT NULL,
 17+ `tmp_id` int NOT NULL,
 18+ `tmp_weight` int NOT NULL,
 19+ PRIMARY KEY (`asn_id`)
 20+) /*$wgDBTableOptions*/;
 21+
 22+CREATE TABLE `cn_templates` (
 23+ `tmp_id` int NOT NULL auto_increment,
 24+ `tmp_name` varchar(255) default NULL,
 25+ PRIMARY KEY (`tmp_id`)
 26+) /*$wgDBTableOptions*/;
Property changes on: trunk/extensions/CentralNotice/CentralNotice.sql
___________________________________________________________________
Added: svn:eol-style
127 + native
Index: trunk/extensions/CentralNotice/rebuildTemplates.php
@@ -0,0 +1,43 @@
 2+<?php
 3+
 4+require_once dirname( dirname( dirname( __FILE__ ) ) ) . "/maintenance/commandLine.inc";
 5+
 6+if( !$wgNoticeCentralDirectory ) {
 7+ echo "\$wgNoticeCentralDirectory isn't set -- we're not configured to build static templates.";
 8+}
 9+
 10+if( isset( $options['help'] ) ) {
 11+ echo "Rebuilds templates for all notices in DB.\n";
 12+ echo "Usage:\n";
 13+ echo " php extensions/CentralNotice/rebuildTemplates\n";
 14+} else {
 15+ echo "Rebuilding templates ...\n";
 16+
 17+ // Hack for parser to avoid barfing from no $wgTitle
 18+ $wgTitle = Title::newFromText( wfMsg( 'mainpage' ) );
 19+
 20+ $projects = $wgNoticeProjects;
 21+ $langs = array_keys( Language::getLanguageNames() );
 22+ //$langs = array( 'en' );
 23+
 24+ foreach( $projects as $project ) {
 25+ foreach( $langs as $lang ) {
 26+ $key = "$project/$lang";
 27+ echo "$key\n";
 28+
 29+ $builder = new SpecialNoticeText();
 30+ $js = $builder->getJsOutput( $key );
 31+
 32+ $outputDir = "$wgNoticeCentralDirectory/$project/$lang";
 33+ if( wfMkDirParents( $outputDir ) ) {
 34+ $outputFile = "$outputDir/centralnotice.js";
 35+ $ok = file_put_contents( $outputFile, $js );
 36+ if( !$ok ) {
 37+ echo "FAILED to write $outputFile!\n";
 38+ }
 39+ } else {
 40+ echo "FAILED to create $outputDir!\n";
 41+ }
 42+ }
 43+ }
 44+}
Property changes on: trunk/extensions/CentralNotice/rebuildTemplates.php
___________________________________________________________________
Added: svn:eol-style
145 + native
Index: trunk/extensions/CentralNotice/SpecialNoticeText.php
@@ -20,47 +20,38 @@
2121
2222 function getJsOutput( $par ) {
2323 $this->setLanguage( $par );
 24+ //need to return all site notices here
 25+ $templates = CentralNotice::selectNoticeTemplates( $this->project, $this->language );
 26+ $templateNames = array_keys( $templates );
 27+
 28+ $templateTexts = array_map(
 29+ array( $this, 'getHtmlNotice' ),
 30+ $templateNames );
 31+ $weights = array_values( $templates );
2432 return
25 - 'wgNotice="' .
26 - strtr(
27 - Xml::escapeJsString( $this->getHtmlNotice() ),
28 - array_merge(
29 - array_map(
30 - array( $this, 'interpolateScroller' ),
31 - array(
32 - '$quote' => $this->getQuotes(),
33 - )
34 - ),
35 - array_map(
36 - array( $this, 'interpolateStrings' ),
37 - array(
38 - '$headline' => $this->getHeadlines(),
39 - '$meter' => $this->getMeter(),
40 - '$progress' => $this->getMessage( 'centralnotice-progress' ),
41 - '$target' => $this->getTarget(),
42 - '$media' => $this->getMessage( 'centralnotice-media' ),
43 - '$show' => $this->getMessage( 'centralnotice-show' ),
44 - '$hide' => $this->getMessage( 'centralnotice-hide' ),
45 - '$donate' => $this->getMessage( 'centralnotice-donate' ),
46 - '$counter' => $this->getMessage( 'centralnotice-counter',
47 - array( $this->formatNum( $this->getDonorCount() ) ) ),
48 - '$blog' => $this->getBlog(),
49 - '$subheading' => $this->getSubheading(),
50 - '$thanks' => $this->getThanks(),
51 - )
52 - )
53 - )
54 - ) .
55 - '";' .
56 - $this->getScripts();
 33+ $this->getScriptFunctions() .
 34+ $this->getToggleScripts() .
 35+ 'wgNotice=pickTemplate(' .
 36+ Xml::encodeJsVar($templateTexts) .
 37+ "," .
 38+ Xml::encodeJsVar($weights) .
 39+ ");\n";
5740 }
5841
59 - function getScripts() {
 42+ function getHtmlNotice( $noticeName ) {
 43+ $this->noticeName = $noticeName;
 44+ return preg_replace_callback(
 45+ '/{{{(.*?)}}}/',
 46+ array( $this, 'getNoticeField' ),
 47+ $this->getNoticeTemplate() );
 48+ }
 49+
 50+ function getToggleScripts() {
6051 $showStyle = <<<END
61 -<style type="text/css">#siteNoticeSmall{display:none;}</style>
 52+<style type="text/css">.siteNoticeSmall{display:none;}</style>
6253 END;
6354 $hideStyle = <<<END
64 -<style type="text/css">#siteNoticeBig{display:none;}</style>
 55+<style type="text/css">.siteNoticeBig{display:none;}</style>
6556 END;
6657 $hideToggleStyle = <<<END
6758 <style type="text/css">.siteNoticeToggle{display:none;}</style>
@@ -68,36 +59,63 @@
6960 $encShowStyle = Xml::encodeJsVar( $showStyle );
7061 $encHideStyle = Xml::encodeJsVar( $hideStyle );
7162 $encHideToggleStyle = Xml::encodeJsVar( $hideToggleStyle );
72 - $script = <<<END
73 - var wgNoticeToggleState = (document.cookie.indexOf("hidesnmessage=1")==-1);
74 - document.writeln(
75 - wgNoticeToggleState
76 - ? $encShowStyle
77 - : $encHideStyle);
78 - if(wgUserName == null) {
79 - document.writeln($encHideToggleStyle);
 63+
 64+ $script = "
 65+var wgNoticeToggleState = (document.cookie.indexOf('hidesnmessage=1')==-1);
 66+document.writeln(
 67+ wgNoticeToggleState
 68+ ? $encShowStyle
 69+ : $encHideStyle);
 70+document.writeln($encHideToggleStyle);\n\n";
 71+ return $script;
 72+ }
 73+
 74+ function getScriptFunctions() {
 75+ $script = "
 76+function toggleNotice() {
 77+ var big = getElementsByClassName(document,'div','siteNoticeBig');
 78+ var small = getElementsByClassName(document,'div','siteNoticeSmall');
 79+ if (!wgNoticeToggleState) {
 80+ toggleNoticeStyle(big,'block');
 81+ toggleNoticeStyle(small,'none');
 82+ toggleNoticeCookie('0');
 83+ } else {
 84+ toggleNoticeStyle(big,'none');
 85+ toggleNoticeStyle(small,'block');
 86+ toggleNoticeCookie('1');
 87+ }
 88+ wgNoticeToggleState = !wgNoticeToggleState;
 89+}
 90+function toggleNoticeStyle(elems, display) {
 91+ if(elems)
 92+ for(var i=0;i<elems.length;i++)
 93+ elems[i].style.display = display;
 94+}
 95+function toggleNoticeCookie(state) {
 96+ var e = new Date();
 97+ e.setTime( e.getTime() + (7*24*60*60*1000) ); // one week
 98+ var work='hidesnmessage='+state+'; expires=' + e.toGMTString() + '; path=/';
 99+ document.cookie = work;
 100+}
 101+function pickTemplate(templates, weights) {
 102+ var weightedTemplates = new Array();
 103+ var currentTemplate = 0;
 104+ var totalWeight = 0;
 105+
 106+ if (templates.length == 0)
 107+ return '';
 108+
 109+ while (currentTemplate < templates.length) {
 110+ totalWeight += weights[currentTemplate];
 111+ for (i=0; i<weights[currentTemplate]; i++) {
 112+ weightedTemplates[weightedTemplates.length] = templates[currentTemplate];
80113 }
81 - function toggleNotice() {
82 - var big = document.getElementById('siteNoticeBig');
83 - var small = document.getElementById('siteNoticeSmall');
84 - if (!wgNoticeToggleState) {
85 - if(big) big.style.display = 'block';
86 - if(small) small.style.display = 'none';
87 - toggleNoticeCookie("0");
88 - } else {
89 - if(big) big.style.display = 'none';
90 - if(small) small.style.display = 'block';
91 - toggleNoticeCookie("1");
92 - }
93 - wgNoticeToggleState = !wgNoticeToggleState;
94 - }
95 - function toggleNoticeCookie(state) {
96 - var e = new Date();
97 - e.setTime( e.getTime() + (7*24*60*60*1000) ); // one week
98 - var work="hidesnmessage="+state+"; expires=" + e.toGMTString() + "; path=/";
99 - document.cookie = work;
100 - }
101 -END;
 114+ currentTemplate++;
 115+ }
 116+
 117+ var randomnumber=Math.floor(Math.random()*totalWeight);
 118+ return weightedTemplates[randomnumber];
 119+}\n\n";
102120 return $script;
103121 }
104122
@@ -113,12 +131,12 @@
114132
115133 // Special:NoticeText/project/language
116134 $bits = explode( '/', $par );
117 - if( count( $bits ) == 2 ) {
 135+ if( count( $bits ) >= 2 ) {
118136 $this->project = $bits[0];
119137 $this->language = $bits[1];
120138 }
121139 }
122 -
 140+ /*
123141 private function interpolateStrings( $data ) {
124142 if( is_array( $data ) ) {
125143 if( count( $data ) == 1 ) {
@@ -176,11 +194,42 @@
177195 'return r.join(" ");' .
178196 '}()';
179197 }
 198+ */
180199
181 - function getHtmlNotice() {
182 - return $this->getMessage( 'centralnotice-template' );
 200+ function chooseTemplate ( $notice ) {
 201+ $dbr = wfGetDB( DB_SLAVE );
 202+ /*
 203+ * This select statement is really wrong, and needs to be fixed.
 204+ * What's wrong is the use of just id instead of not_id, tmp_id or asn_id
 205+ */
 206+ $res = $dbr->select( 'cn_assignments',
 207+ array( 'not_name', 'not_weight' ),
 208+ array( 'not_name' => $notice, 'not_id = id'),
 209+ __METHOD__,
 210+ array('ORDER BY' => 'id')
 211+ );
 212+ $templates = array();
 213+ while ( $row = $dbr->fetchObject( $res )) {
 214+ push ( $templates, $row->name);
 215+ }
 216+
183217 }
 218+ function getNoticeTemplate() {
 219+ return $this->getMessage( "centralnotice-template-{$this->noticeName}" );
 220+ }
184221
 222+ function getNoticeField( $matches ) {
 223+ $field = $matches[1];
 224+ $params = array();
 225+ if( $field == 'amount' ) {
 226+ $params = array( $this->formatNum( $this->getDonationAmount() ) );
 227+ }
 228+ $message = "centralnotice-{$this->noticeName}-$field";
 229+ $source = $this->getMessage( $message, $params );
 230+ return $source;
 231+ }
 232+
 233+ /*
185234 private function getHeadlines() {
186235 return $this->splitListMessage( 'centralnotice-headlines' );
187236 }
@@ -192,7 +241,7 @@
193242
194243 private function getMeter() {
195244 return $this->getMessage( 'centralnotice-meter' );
196 - // return "<img src=\"http://upload.wikimedia.org/fundraising/2007/meter.png\" width='407' height='14' />";
 245+ #return "<img src=\"http://upload.wikimedia.org/fundraising/2007/meter.png\" width='407' height='14' />";
197246 }
198247
199248 private function getTarget() {
@@ -203,83 +252,26 @@
204253 $text = $this->getMessage( $msg );
205254 return $this->splitList( $text, $callback );
206255 }
 256+ */
207257
208258 private function getMessage( $msg, $params=array() ) {
209 - $guard = array();
210 - for( $lang = $this->language; $lang; $lang = $this->safeLangFallback( $lang ) ) {
211 - if( isset( $guard[$lang] ) )
212 - break; // avoid loops...
213 - $guard[$lang] = true;
214 - if( $text = $this->getRawMessage( "$msg/$lang", $params ) ) {
215 - return $text;
216 - }
217 - }
218 - return $this->getRawMessage( $msg, $params );
219 - }
220 -
221 - private function safeLangFallback( $lang ) {
222 - $fallback = Language::getFallbackFor( $lang );
223 - if( $fallback == 'en' ) {
224 - // We want to be able to special-case English
225 - // This lets us put _regular_ English in 'blah' and special-case in 'blah/en'
226 - return false;
227 - } else {
228 - return $fallback;
229 - }
230 - }
231 -
232 - private function getRawMessage( $msg, $params ) {
233 - $searchPath = array(
234 - "$msg/{$this->project}",
235 - "$msg" );
236 - foreach( $searchPath as $rawMsg ) {
237 - wfDebug( __METHOD__ . ": $rawMsg\n" );
238 - $xparams = array_merge( array( $rawMsg ), $params );
239 - wfDebug( __METHOD__ . ': ' . str_replace( "\n", " ", var_export( $xparams, true ) ) . "\n" );
240 - $text = call_user_func_array( 'wfMsgForContentNoTrans',
241 - $xparams );
242 - if( !wfEmptyMsg( $rawMsg, $text ) ) {
243 - return $text;
244 - }
245 - }
246 - return false;
247 - }
248 -
249 - private function splitList( $text, $callback=false ) {
250 - $list = array_filter(
251 - array_map(
252 - array( $this, 'filterListLine' ),
253 - explode( "\n", $text ) ) );
254 - if( is_callable( $callback ) ) {
255 - return array_map( $callback, $list );
256 - } else {
257 - return $list;
258 - }
259 - }
260 -
261 - private function filterListLine( $line ) {
262 - if( substr( $line, 0, 1 ) == '#' ) {
263 - return '';
264 - } else {
265 - return $this->parse( trim( ltrim( $line, '*' ) ) );
266 - }
267 - }
268 -
269 - private function parse( $text ) {
270 - global $wgOut, $wgSitename;
271 -
272 - // A god-damned dirty hack!
 259+ // A god-damned dirty hack! :D
 260+ global $wgSitename;
273261 $old = array();
274262 $old['wgSitename'] = $wgSitename;
275263 $wgSitename = $this->projectName();
276264
277 - $out = preg_replace(
278 - '/^<p>(.*)\n?<\/p>\n?$/sU',
279 - '$1',
280 - $wgOut->parse( $text ) );
 265+ $options = array(
 266+ 'language' => $this->language,
 267+ 'parsemag',
 268+ );
 269+ array_unshift( $params, $options );
 270+ array_unshift( $params, $msg );
 271+ $out = call_user_func_array( 'wfMsgExt', $params );
281272
282273 // Restore globals
283274 $wgSitename = $old['wgSitename'];
 275+
284276 return $out;
285277 }
286278
@@ -311,6 +303,7 @@
312304 }
313305 }
314306
 307+ /*
315308 function wrapQuote( $text ) {
316309 return "<span class='fundquote'>" .
317310 $this->getMessage(
@@ -318,7 +311,8 @@
319312 array( $text ) ) .
320313 "</span>";
321314 }
322 -
 315+ */
 316+
323317 private function getDonorCount() {
324318 global $wgNoticeCounterSource, $wgMemc;
325319 $count = intval( $wgMemc->get( 'centralnotice:counter' ) );
@@ -336,6 +330,10 @@
337331 return $count;
338332 }
339333
 334+ private function getDonationAmount() {
 335+ return 2543454;
 336+ }
 337+
340338 private function getFallbackDonorCount() {
341339 global $wgMemc;
342340 $count = intval( $wgMemc->get( 'centralnotice:counter:fallback' ) );
@@ -345,6 +343,7 @@
346344 return $count;
347345 }
348346
 347+ /*
349348 private function getBlog() {
350349 $url = $this->getMessage( 'centralnotice-blog-url' );
351350 $entry = $this->getCachedRssEntry( $url );
@@ -357,19 +356,7 @@
358357 return '';
359358 }
360359 }
361 -
362 - private function getSubheading() {
363 - // Sigh... hack in another one real quick
364 - return $this->parse(
365 - $this->getMessage( 'centralnotice-subheading' ) );
366 - }
367 -
368 - private function getThanks() {
369 - // Sigh... hack in another one real quick
370 - return $this->parse(
371 - $this->getMessage( 'centralnotice-thanks' ) );
372 - }
373 -
 360+
374361 private function getCachedRssEntry( $url ) {
375362 global $wgMemc;
376363 $key = 'centralnotice:rss:' . md5( $url );
@@ -384,10 +371,13 @@
385372 }
386373 return $title;
387374 }
 375+ */
 376+
388377 /**
389378 * Fetch the first link and title from an RSS feed
390379 * @return array
391380 */
 381+ /*
392382 private function getFirstRssEntry( $url ) {
393383 wfSuppressWarnings();
394384 $feed = simplexml_load_file( $url );
@@ -401,5 +391,6 @@
402392 return array();
403393 }
404394 }
 395+ */
405396
406397 }
Index: trunk/extensions/CentralNotice/CentralNotice.i18n.php
@@ -8,16 +8,89 @@
99 $messages = array();
1010
1111 $messages['en'] = array(
 12+ 'centralnotice' => 'Central notice admin',
 13+ 'noticetemplate' => 'Central notice template',
 14+ 'noticetranslate' => 'Central notice translate',
1215 'centralnotice-desc' => 'Adds a central sitenotice',
 16+ 'centralnotice-summary' =>'This module allows you to edit your currently setup central notices.
 17+It can also be used to add or remove old notices.',
 18+ 'centralnotice-query' => 'Modify current notices',
 19+ 'centralnotice-notice-name' => 'Notice name',
 20+ 'centralnotice-end-date' => 'End date',
 21+ 'centralnotice-enabled' => 'Enabled',
 22+ 'centralnotice-modify' => 'Submit',
 23+ 'centralnotice-preview' => 'Preview',
 24+ 'centralnotice-add-new' => 'Add a new central notice',
 25+ 'centralnotice-remove' => 'Remove',
 26+ 'centralnotice-translate-heading' => 'Translation for $1',
 27+ 'centralnotice-manage' => 'Manage central notice',
 28+ 'centralnotice-add' => 'Add',
 29+ 'centralnotice-add-notice' => 'Add a notice',
 30+ 'centralnotice-add-template' => 'Add a template',
 31+ 'centralnotice-show-notices' => 'Show notices',
 32+ 'centralnotice-list-templates' => 'List Templates',
 33+ 'centralnotice-translations' => 'Translations',
 34+ 'centralnotice-translate-to' => 'Translate to',
 35+ 'centralnotice-translate' => 'Translate',
 36+ 'centralnotice-english' => 'English',
 37+ 'centralnotice-template-name' => 'Template name',
 38+ 'centralnotice-templates' => 'Templates',
 39+ 'centralnotice-weight' => 'Weight',
 40+ 'centralnotice-locked' => 'Locked',
 41+ 'centralnotice-notices' => 'Notices',
 42+ 'centralnotice-notice-exists' => 'Notice already exists.
 43+Not adding',
 44+ 'centralnotice-template-exists' => 'Template already exists.
 45+Not adding',
 46+ 'centralnotice-notice-doesnt-exist' => 'Notice doesnt exist.
 47+Nothing to remove',
 48+ 'centralnotice-template-still-bound' => 'Template is still bound to a notice.
 49+Not removing.',
 50+ 'centralnotice-template-body' => 'Template body:',
 51+ 'centralnotice-day' => 'Day',
 52+ 'centralnotice-year' => 'Year',
 53+ 'centralnotice-month' => 'Month',
 54+ 'centralnotice-hours' => 'Hour',
 55+ 'centralnotice-min' => 'Minute',
 56+ 'centralnotice-project-lang' => 'Project language',
 57+ 'centralnotice-project-name' => 'Project name',
 58+ 'centralnotice-start-date' => 'Start date',
 59+ 'centralnotice-start-time' => 'Start time (UTC) ',
 60+ 'centralnotice-assigned-templates' => 'Assigned templates',
 61+ 'centralnotice-no-templates' => 'No templates found.
 62+Add some!',
 63+ 'centralnotice-no-templates-assigned' => 'No templates assigned to notice.
 64+Add some!',
 65+ 'centralnotice-available-templates' => 'Available templates',
 66+ 'centralnotice-template-already-exists' => 'Template is already tied to campaing.
 67+Not adding',
 68+ 'centralnotice-preview-template' => 'Preview template',
 69+ 'centralnotice-start-hour' => 'Start time',
 70+ 'centralnotice-change-lang' => 'Change translation language',
 71+ 'centralnotice-weights' => 'Weights',
 72+ 'centralnotice-notice-is-locked' => 'Notice is locked.
 73+Not removing',
 74+ 'centralnotice-overlap' => 'Notice overlaps within the time of another notice.
 75+Not adding',
 76+ 'centralnotice-invalid-date-range' => 'Invalid date range.
 77+Not updating',
 78+ 'centralnotice-null-string' => 'Cannot add a null string.
 79+Not adding',
 80+ 'centralnotice-confirm-delete' => 'Are you sure you want to delete this item?
 81+This action will be unrecoverable.',
 82+ 'centralnotice-no-notices-exist' => 'No notices exist.
 83+Add one below',
 84+ 'centralnotice-confirm-delete' => 'Are you sure you want to delete this item?
 85+This action will be unrecoverable.',
 86+ 'centralnotice-no-templates-translate' => 'There are not any templates to edit translations for',
 87+ 'centralnotice-no-templates' => 'There are no templates in the system.
 88+Create one',
 89+ 'centralnotice-number-uses' => 'Uses',
 90+ 'centralnotice-edit-template' => 'Edit template',
 91+ 'centralnotice-message' => 'Message',
 92+ 'centralnotice-message-not-set' => 'Message not set',
1393 );
1494
15 -/** Message documentation (Message documentation)
16 - * @author Purodha
17 - */
18 -$messages['qqq'] = array(
19 - 'centralnotice-desc' => 'Short description of the Centralnotice extension, shown in [[Special:Version]]. Do not translate or change links.',
20 -);
21 -
2295 /** Afrikaans (Afrikaans)
2396 * @author Naudefj
2497 */
@@ -258,13 +331,6 @@
259332 'centralnotice-desc' => "Voegt 'n centrale sitemededeling toe",
260333 );
261334
262 -/** Macedonian (Македонски)
263 - * @author Brest
264 - */
265 -$messages['mk'] = array(
266 - 'centralnotice-desc' => 'Додава централизирано известување',
267 -);
268 -
269335 /** Malayalam (മലയാളം)
270336 * @author Shijualex
271337 */
@@ -311,7 +377,7 @@
312378 * @author Cedric31
313379 */
314380 $messages['oc'] = array(
315 - 'centralnotice-desc' => 'Apond un sitenotice central',
 381+ 'centralnotice-desc' => 'Apondís un sitenotice central',
316382 );
317383
318384 /** Polish (Polski)
Property changes on: trunk/extensions/CentralNotice
___________________________________________________________________
Added: svn:ignore
319385 + .project

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r41613Creating branch for SpecialPage integrationtomasz20:51, 3 October 2008

Status & tagging log