r98733 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r98732‎ | r98733 | r98734 >
Date:02:32, 3 October 2011
Author:krinkle
Status:ok
Tags:
Comment:
[RL2] GadgetHooks -> Gadgets.hooks.php
Modified paths:
  • /branches/RL2/extensions/Gadgets/GadgetHooks.php (deleted) (history)
  • /branches/RL2/extensions/Gadgets/Gadgets.hooks.php (added) (history)
  • /branches/RL2/extensions/Gadgets/Gadgets.php (modified) (history)
  • /branches/RL2/extensions/Gadgets/SpecialGadgets.php (modified) (history)
  • /branches/RL2/extensions/Gadgets/tests/GadgetsTest.php (modified) (history)

Diff [purge]

Index: branches/RL2/extensions/Gadgets/GadgetHooks.php
@@ -1,431 +0,0 @@
2 -<?php
3 -/**
4 - * Gadgets extension - lets users select custom javascript gadgets
5 - *
6 - *
7 - * For more info see http://mediawiki.org/wiki/Extension:Gadgets
8 - *
9 - * @file
10 - * @ingroup Extensions
11 - * @author Daniel Kinzler, brightbyte.de
12 - * @copyright © 2007 Daniel Kinzler
13 - * @license GNU General Public Licence 2.0 or later
14 - */
15 -
16 -class GadgetHooks {
17 - /**
18 - * Get the gadget ID from a title
19 - * @param $title Title object
20 - * @return string Gadget id or null if not a gadget definition page
21 - */
22 - public static function getIDFromTitle( Title $title ) {
23 - $id = $title->getText();
24 - if ( $title->getNamespace() !== NS_GADGET_DEFINITION || !preg_match( '!\.js$!u', $id ) ) {
25 - // Not a gadget definition page
26 - return null;
27 - }
28 - // Trim .js from the page name to obtain the gadget ID
29 - return substr( $id, 0, -3 );
30 - }
31 -
32 - /**
33 - * Get a Title object of the gadget definition page from a gadget id
34 - * @param $is String
35 - * @return Title|null
36 - */
37 - public static function getDefinitionTitleFromID( $id ) {
38 - return Title::makeTitleSafe( NS_GADGET_DEFINITION, $id . '.js' );
39 - }
40 -
41 - /**
42 - * ArticleDeleteComplete hook handler.
43 - *
44 - * @param $article Article
45 - * @param $user User
46 - * @param $reason String: Deletion summary
47 - * @param $id Int: Page ID
48 - */
49 - public static function gadgetDefinitionDelete( $article, $user, $reason, $id ) {
50 - $id = self::getIDFromTitle( $article->getTitle() );
51 - if ( !$id ) {
52 - return true;
53 - }
54 -
55 - $repo = LocalGadgetRepo::singleton();
56 - $repo->deleteGadget( $id );
57 - // deleteGadget() may return an error if the Gadget didn't exist, but we don't care here
58 - return true;
59 - }
60 -
61 - /**
62 - * ArticleSaveComplete hook handler.
63 - *
64 - * @param $article Article
65 - * @param $user User
66 - * @param $text String: New page text
67 - * @param $summary String: Edit summary
68 - * @param $isMinor Bool: Whether this was a minor edit
69 - * @param $isWatch unused
70 - * @param $section unused
71 - * @param $flags: Int: Bitmap of flags passed to WikiPage::doEdit()
72 - * @param $revision: Revision object for the new revision
73 - */
74 - public static function gadgetDefinitionSave( $article, $user, $text, $summary, $isMinor,
75 - $isWatch, $section, $flags, $revision )
76 - {
77 - $id = self::getIDFromTitle( $article->getTitle() );
78 - if ( !$id ) {
79 - return true;
80 - }
81 -
82 - $previousRev = $revision->getPrevious();
83 - $prevTs = $previousRev instanceof Revision ? $previousRev->getTimestamp() : wfTimestampNow();
84 -
85 - // Update the database entry for this gadget
86 - $repo = LocalGadgetRepo::singleton();
87 - // TODO: Timestamp in the constructor is ugly
88 - $gadget = new Gadget( $id, $repo, $text, $prevTs );
89 - $repo->modifyGadget( $gadget, $revision->getTimestamp() );
90 -
91 - // modifyGadget() returns a Status object with an error if there was a conflict,
92 - // but we don't care. If a conflict occurred, that must be because a newer edit's
93 - // DB update occurred before ours, in which case the right thing to do is to occu
94 -
95 - return true;
96 - }
97 -
98 - /**
99 - * Update the database entry for a gadget if the description page is
100 - * newer than the database entry.
101 - * @param $title Title object
102 - */
103 - public static function gadgetDefinitionUpdateIfChanged( $title ) {
104 - $id = self::getIDFromTitle( $title );
105 - if ( !$id ) {
106 - return;
107 - }
108 -
109 - // Check whether this undeletion changed the latest revision of the page, by comparing
110 - // the timestamp of the latest revision with the timestamp in the DB
111 - $repo = LocalGadgetRepo::singleton();
112 - $gadget = $repo->getGadget( $id );
113 - $gadgetTS = $gadget ? $gadget->getTimestamp() : 0;
114 -
115 - $rev = Revision::newFromTitle( $title );
116 - if ( wfTimestamp( TS_MW, $rev->getTimestamp() ) ===
117 - wfTimestamp( TS_MW, $gadgetTS ) ) {
118 - // The latest rev didn't change. Someone must've undeleted an older revision
119 - return;
120 - }
121 -
122 - // Update the database entry for this gadget
123 - $newGadget = new Gadget( $id, $repo, $rev->getRawText(), $gadgetTS );
124 - $repo->modifyGadget( $newGadget, $rev->getTimestamp() );
125 -
126 - // modifyGadget() returns a Status object with an error if there was a conflict,
127 - // but we do't care, see similar comment in articleSaveComplete()
128 - return;
129 - }
130 -
131 - /**
132 - * ArticleUndelete hook handler
133 - * @param $title Title object
134 - * @param $created Bool: Whether this undeletion recreated the page
135 - * @param $comment String: Undeletion summary
136 - */
137 - public static function gadgetDefinitionUndelete( $title, $created, $comment ) {
138 - self::gadgetDefinitionUpdateIfChanged( $title );
139 - return true;
140 - }
141 -
142 - public static function gadgetDefinitionImport( $title, $origTitle, $revCount, $sRevCount, $pageInfo ) {
143 - self::gadgetDefinitionUpdateIfChanged( $title );
144 - return true;
145 - }
146 -
147 - /**
148 - * ArticleDeleteComplete hook handler.
149 - *
150 - * @param $article Article
151 - * @param $user User
152 - * @param $reason String: Deletion summary
153 - * @param $id Int: Page ID
154 - */
155 - public static function cssJsPageDelete( $article, $user, $reason, $id ) {
156 - GadgetPageList::delete( $article->getTitle() );
157 - return true;
158 - }
159 -
160 - /**
161 - * ArticleSaveComplete hook handler.
162 - *
163 - * @param $article Article
164 - * @param $user User
165 - * @param $text String: New page text
166 - * @param $summary String: Edit summary
167 - * @param $isMinor Bool: Whether this was a minor edit
168 - * @param $isWatch unused
169 - * @param $section unused
170 - * @param $flags: Int: Bitmap of flags passed to WikiPage::doEdit()
171 - * @param $revision: Revision object for the new revision
172 - */
173 - public static function cssOrJsPageSave( $article, $user, $text, $summary, $isMinor,
174 - $isWatch, $section, $flags, $revision )
175 - {
176 - $title = $article->getTitle();
177 - GadgetPageList::updatePageStatus( $title );
178 - return true;
179 - }
180 -
181 - /**
182 - * ArticleUndelete hook handler
183 - * @param $title Title object
184 - * @param $created Bool: Whether this undeletion recreated the page
185 - * @param $comment String: Undeletion summary
186 - */
187 - public static function cssOrJsPageUndelete( $title, $created, $comment ) {
188 - GadgetPageList::updatePageStatus( $title );
189 - return true;
190 - }
191 -
192 - public static function cssOrJsPageMove( $oldTitle, $newTitle, $user, $pageid, $redirid ) {
193 - // Delete the old title from the list. Even if it still exists after the move,
194 - // it'll be a redirect and we don't want those in there
195 - GadgetPageList::delete( $oldTitle );
196 -
197 - GadgetPageList::updatePageStatus( $newTitle );
198 - return true;
199 - }
200 -
201 - /**
202 - * UserGetDefaultOptions hook handler
203 - * @param $defaultOptions Array of default preference keys and values
204 - */
205 - public static function userGetDefaultOptions( &$defaultOptions ) {
206 - $repo = LocalGadgetRepo::singleton();
207 - $gadgetIds = $repo->getGadgetIds();
208 - foreach ( $gadgetIds as $gadgetId ) {
209 - $gadget = $repo->getGadget( $gadgetId );
210 - if ( $gadget->isEnabledByDefault() ) {
211 - $defaultOptions['gadget-' . $gadget->getId()] = 1;
212 - }
213 - }
214 - return true;
215 - }
216 -
217 - /**
218 - * GetPreferences hook handler.
219 - * @param $user User
220 - * @param $preferences Array: Preference descriptions
221 - */
222 - public static function getPreferences( $user, &$preferences ) {
223 - $repo = LocalGadgetRepo::singleton();
224 - $gadgets = $repo->getGadgetIds();
225 - $categories = array(); // array( category => array( desc => title ) )
226 - $default = array(); // array of Gadget ids
227 - foreach ( $gadgets as $id ) {
228 - $gadget = $repo->getGadget( $id );
229 - if ( !$gadget->isAllowed( $user ) || $gadget->isHidden() ) {
230 - continue;
231 - }
232 - $category = $gadget->getCategory();
233 -
234 - // Add the Gadget to the right category
235 - $title = htmlspecialchars( $gadget->getTitleMessage() );
236 - $description = $gadget->getDescriptionMessage(); // Is parsed, doesn't need escaping
237 - if ( $description === '' ) {
238 - // Empty description, just use the title
239 - $text = $title;
240 - } else {
241 - $text = wfMessage( 'gadgets-preference-description' )->rawParams( $title, $description )->parse();
242 - }
243 - $categories[$category][$text] = $id;
244 - // Add the Gadget to the default list if enabled
245 - if ( $gadget->isEnabledForUser( $user ) ) {
246 - $default[] = $id;
247 - }
248 - }
249 -
250 - $options = array(); // array( desc1 => gadget1, category1 => array( desc2 => gadget2 ) )
251 - foreach ( $categories as $category => $gadgets ) {
252 - if ( $category !== '' ) {
253 - $categoryMsg = htmlspecialchars( $repo->getCategoryTitle( $category ) );
254 - $options[$categoryMsg] = $gadgets;
255 - } else {
256 - $options += $gadgets;
257 - }
258 - }
259 -
260 - $preferences['gadgets-intro'] =
261 - array(
262 - 'type' => 'info',
263 - 'label' => '&#160;',
264 - 'default' => Xml::tags( 'tr', array(),
265 - Xml::tags( 'td', array( 'colspan' => 2 ),
266 - wfMsgExt( 'gadgets-prefstext', 'parse' ) ) ),
267 - 'section' => 'gadgets',
268 - 'raw' => 1,
269 - 'rawrow' => 1,
270 - );
271 - $preferences['gadgets'] =
272 - array(
273 - 'type' => 'multiselect',
274 - 'options' => $options,
275 - 'section' => 'gadgets',
276 - 'label' => '&#160;',
277 - 'prefix' => 'gadget-',
278 - 'default' => $default,
279 - );
280 -
281 - // Add tab for shared gadgets
282 - $preferences['gadgets-intro-shared'] =
283 - array(
284 - 'type' => 'info',
285 - 'label' => '&#160;',
286 - 'default' => Xml::tags( 'tr', array(),
287 - Xml::tags( 'td', array( 'colspan' => 2 ),
288 - wfMsgExt( 'gadgets-sharedprefstext', 'parse' ) ) ),
289 - 'section' => 'gadgets-shared',
290 - 'raw' => 1,
291 - 'rawrow' => 1,
292 - );
293 - $preferences['gadgets-shared'] =
294 - array(
295 - 'type' => 'multiselect',
296 - 'options' => array(), // TODO: Maybe fill in stuff anyway? The backend may need that
297 - 'section' => 'gadgets-shared',
298 - 'label' => '&#160;',
299 - 'prefix' => 'gadget-',
300 - 'default' => array(),
301 - );
302 - return true;
303 - }
304 -
305 - /**
306 - * ResourceLoaderRegisterModules hook handler.
307 - * @param $resourceLoader ResourceLoader
308 - */
309 - public static function registerModules( &$resourceLoader ) {
310 - $gadgets = GadgetRepo::getAllGadgets();
311 - foreach ( $gadgets as $gadget ) {
312 - $resourceLoader->register( $gadget->getModuleName(), $gadget->getModule() );
313 - }
314 - return true;
315 - }
316 -
317 - /**
318 - * BeforePageDisplay hook handler.
319 - * @param $out OutputPage
320 - */
321 - public static function beforePageDisplay( $out ) {
322 - wfProfileIn( __METHOD__ );
323 -
324 - $user = $out->getUser();
325 - $gadgets = GadgetRepo::getAllGadgets();
326 - foreach ( $gadgets as $gadget ) {
327 - if ( $gadget->isEnabledForUser( $user ) && $gadget->isAllowed( $user ) ) {
328 - $out->addModules( $gadget->getModuleName() );
329 - }
330 - }
331 -
332 - // Add preferences JS if we're on Special:Preferences
333 - if ( $out->getTitle()->equals( SpecialPage::getTitleFor( 'Preferences' ) ) ) {
334 - $out->addModules( 'ext.gadgets.preferences' );
335 - }
336 -
337 - wfProfileOut( __METHOD__ );
338 - return true;
339 - }
340 -
341 - /**
342 - * MakeGlobalVariablesScript hook handler
343 - * @param $vars Array: Key/value pars for mw.config.set on this page.
344 - * @param $out OutputPage
345 - */
346 - public static function makeGlobalVariablesScript( &$vars, $out ) {
347 - $title = $out->getTitle();
348 - $user = $out->getUser();
349 - // FIXME: This is not a nice way to do it. Maybe we should check for the presence
350 - // of a module instead or something.
351 - if ( $title->equals( SpecialPage::getTitleFor( 'Gadgets' ) ) ||
352 - $title->equals( SpecialPage::getTitleFor( 'Preferences' ) ) )
353 - {
354 - global $wgGadgetEnableSharing;
355 -
356 - // Pass the source data for each source that is used by a repository
357 - $repos = GadgetRepo::getAllRepos();
358 - $sources = $out->getResourceLoader()->getSources();
359 - $repoData = array();
360 - foreach ( $repos as $repo ) {
361 - $repoData[$repo->getSource()] = $sources[$repo->getSource()];
362 - }
363 -
364 - $vars['gadgetsConf'] = array(
365 - 'enableSharing' => $wgGadgetEnableSharing,
366 - 'allRights' => User::getAllRights(),
367 - 'repos' => $repoData,
368 - 'userIsAllowed' => array(
369 - 'editinterface' => $user->isAllowed( 'editinterface' ),
370 - 'gadgets-definition-create' => $user->isAllowed( 'gadgets-definition-create' ),
371 - 'gadgets-definition-edit' => $user->isAllowed( 'gadgets-definition-edit' ),
372 - 'gadgets-definition-delete' => $user->isAllowed( 'gadgets-definition-delete' ),
373 - ),
374 - );
375 - }
376 - return true;
377 - }
378 -
379 - /**
380 - * UnitTestsList hook handler
381 - * @param $files Array: List of extension test files
382 - */
383 - public static function unitTestsList( &$files ) {
384 - $files[] = dirname( __FILE__ ) . '/tests/GadgetsTest.php';
385 - return true;
386 - }
387 -
388 - public static function loadExtensionSchemaUpdates( $updater ) {
389 - $dir = dirname( __FILE__ );
390 - $updater->addExtensionUpdate( array( 'addtable', 'gadgets', "$dir/sql/gadgets.sql", true ) );
391 - $updater->addExtensionUpdate( array( 'addtable', 'gadgetpagelist', "$dir/sql/patch-gadgetpagelist.sql", true ) );
392 - return true;
393 - }
394 -
395 - public static function canonicalNamespaces( &$list ) {
396 - $list[NS_GADGET] = 'Gadget';
397 - $list[NS_GADGET_TALK] = 'Gadget_talk';
398 - $list[NS_GADGET_DEFINITION] = 'Gadget_definition';
399 - $list[NS_GADGET_DEFINITION_TALK] = 'Gadget_definition_talk';
400 - return true;
401 - }
402 -
403 - public static function titleIsCssOrJsPage( $title, &$result ) {
404 - if ( ( $title->getNamespace() == NS_GADGET || $title->getNamespace() == NS_GADGET_DEFINITION ) &&
405 - preg_match( '!\.(css|js)$!u', $title->getText() ) )
406 - {
407 - $result = true;
408 - }
409 - return true;
410 - }
411 -
412 - public static function titleIsMovable( $title, &$result ) {
413 - if ( $title->getNamespace() == NS_GADGET_DEFINITION ) {
414 - $result = false;
415 - }
416 - return true;
417 - }
418 -
419 - public static function getUserPermissionsErrors( $title, $user, $action, &$result ) {
420 - if ( $title->getNamespace() == NS_GADGET_DEFINITION ) {
421 - // Enforce restrictions on the Gadget_definition namespace
422 - if ( $action == 'create' && !$user->isAllowed( 'gadgets-definition-create' ) ) {
423 - $result[] = array( 'gadgets-cant-create' );
424 - return false;
425 - } elseif ( $action == 'delete' && !$user->isAllowed( 'gadgets-definition-delete' ) ) {
426 - $result[] = array( 'gadgets-cant-delete' );
427 - return false;
428 - }
429 - }
430 - return true;
431 - }
432 -}
Index: branches/RL2/extensions/Gadgets/tests/GadgetsTest.php
@@ -68,7 +68,7 @@
6969 * baz [rights=embezzle] |baz.js
7070 ==keep-section2==
7171 * quux [rights=read] | quux.js' );
72 - $this->assertTrue( GadgetHooks::getPreferences( $wgUser, $prefs ), 'GetPrefences hook should return true' );
 72+ $this->assertTrue( GadgetsHooks::getPreferences( $wgUser, $prefs ), 'GetPrefences hook should return true' );
7373
7474 $options = $prefs['gadgets']['options'];
7575 $this->assertFalse( isset( $options['&lt;gadget-section-remove-section&gt;'] ), 'Must not show empty sections' );
Index: branches/RL2/extensions/Gadgets/Gadgets.php
@@ -95,25 +95,25 @@
9696 #$wgGroupPermissions['gadgetmanagers']['gadgets-definition-edit'] = true;
9797 #$wgGroupPermissions['gadgetmanagers']['gadgets-definition-delete'] = true;
9898
99 -$wgHooks['AfterImportPage'][] = 'GadgetHooks::gadgetDefinitionImport';
100 -$wgHooks['ArticleDeleteComplete'][] = 'GadgetHooks::gadgetDefinitionDelete';
101 -$wgHooks['ArticleDeleteComplete'][] = 'GadgetHooks::cssJsPageDelete';
102 -$wgHooks['ArticleSaveComplete'][] = 'GadgetHooks::gadgetDefinitionSave';
103 -$wgHooks['ArticleSaveComplete'][] = 'GadgetHooks::cssOrJsPageSave';
104 -$wgHooks['ArticleUndelete'][] = 'GadgetHooks::gadgetDefinitionUndelete';
105 -$wgHooks['ArticleUndelete'][] = 'GadgetHooks::cssOrJsPageUndelete';
106 -$wgHooks['BeforePageDisplay'][] = 'GadgetHooks::beforePageDisplay';
107 -$wgHooks['MakeGlobalVariablesScript'][] = 'GadgetHooks::makeGlobalVariablesScript';
108 -$wgHooks['CanonicalNamespaces'][] = 'GadgetHooks::canonicalNamespaces';
109 -$wgHooks['GetPreferences'][] = 'GadgetHooks::getPreferences';
110 -$wgHooks['UserGetDefaultOptions'][] = 'GadgetHooks::userGetDefaultOptions';
111 -$wgHooks['LoadExtensionSchemaUpdates'][] = 'GadgetHooks::loadExtensionSchemaUpdates';
112 -$wgHooks['ResourceLoaderRegisterModules'][] = 'GadgetHooks::registerModules';
113 -$wgHooks['TitleIsCssOrJsPage'][] = 'GadgetHooks::titleIsCssOrJsPage';
114 -$wgHooks['TitleIsMovable'][] = 'GadgetHooks::titleIsMovable';
115 -$wgHooks['TitleMoveComplete'][] = 'GadgetHooks::cssOrJsPageMove';
116 -$wgHooks['getUserPermissionsErrors'][] = 'GadgetHooks::getUserPermissionsErrors';
117 -#$wgHooks['UnitTestsList'][] = 'GadgetHooks::unitTestsList'; // FIXME: broken
 99+$wgHooks['AfterImportPage'][] = 'GadgetsHooks::gadgetDefinitionImport';
 100+$wgHooks['ArticleDeleteComplete'][] = 'GadgetsHooks::gadgetDefinitionDelete';
 101+$wgHooks['ArticleDeleteComplete'][] = 'GadgetsHooks::cssJsPageDelete';
 102+$wgHooks['ArticleSaveComplete'][] = 'GadgetsHooks::gadgetDefinitionSave';
 103+$wgHooks['ArticleSaveComplete'][] = 'GadgetsHooks::cssOrJsPageSave';
 104+$wgHooks['ArticleUndelete'][] = 'GadgetsHooks::gadgetDefinitionUndelete';
 105+$wgHooks['ArticleUndelete'][] = 'GadgetsHooks::cssOrJsPageUndelete';
 106+$wgHooks['BeforePageDisplay'][] = 'GadgetsHooks::beforePageDisplay';
 107+$wgHooks['MakeGlobalVariablesScript'][] = 'GadgetsHooks::makeGlobalVariablesScript';
 108+$wgHooks['CanonicalNamespaces'][] = 'GadgetsHooks::canonicalNamespaces';
 109+$wgHooks['GetPreferences'][] = 'GadgetsHooks::getPreferences';
 110+$wgHooks['UserGetDefaultOptions'][] = 'GadgetsHooks::userGetDefaultOptions';
 111+$wgHooks['LoadExtensionSchemaUpdates'][] = 'GadgetsHooks::loadExtensionSchemaUpdates';
 112+$wgHooks['ResourceLoaderRegisterModules'][] = 'GadgetsHooks::registerModules';
 113+$wgHooks['TitleIsCssOrJsPage'][] = 'GadgetsHooks::titleIsCssOrJsPage';
 114+$wgHooks['TitleIsMovable'][] = 'GadgetsHooks::titleIsMovable';
 115+$wgHooks['TitleMoveComplete'][] = 'GadgetsHooks::cssOrJsPageMove';
 116+$wgHooks['getUserPermissionsErrors'][] = 'GadgetsHooks::getUserPermissionsErrors';
 117+#$wgHooks['UnitTestsList'][] = 'GadgetsHooks::unitTestsList'; // FIXME: broken
118118
119119 $dir = dirname(__FILE__) . '/';
120120 $wgExtensionMessagesFiles['Gadgets'] = $dir . 'Gadgets.i18n.php';
@@ -125,7 +125,7 @@
126126 $wgAutoloadClasses['ApiQueryGadgets'] = $dir . 'api/ApiQueryGadgets.php';
127127 $wgAutoloadClasses['ForeignDBGadgetRepo'] = $dir . 'backend/ForeignDBGadgetRepo.php';
128128 $wgAutoloadClasses['Gadget'] = $dir . 'backend/Gadget.php';
129 -$wgAutoloadClasses['GadgetHooks'] = $dir . 'GadgetHooks.php';
 129+$wgAutoloadClasses['GadgetsHooks'] = $dir . 'Gadgets.hooks.php';
130130 $wgAutoloadClasses['GadgetPageList'] = $dir . 'backend/GadgetPageList.php';
131131 $wgAutoloadClasses['GadgetRepo'] = $dir . 'backend/GadgetRepo.php';
132132 $wgAutoloadClasses['GadgetResourceLoaderModule'] = $dir . 'backend/GadgetResourceLoaderModule.php';
Index: branches/RL2/extensions/Gadgets/SpecialGadgets.php
@@ -124,7 +124,7 @@
125125 );
126126 if ( $user->isAllowed( 'gadgets-definition-edit' ) ) {
127127 $extra[] = Linker::link(
128 - GadgetHooks::getDefinitionTitleFromID( $gadget->getId() ),
 128+ GadgetsHooks::getDefinitionTitleFromID( $gadget->getId() ),
129129 wfMessage( 'gadgets-gadget-modify' )->escaped(),
130130 array(
131131 'title' => wfMessage( 'gadgets-gadget-modify-tooltip' )->plain(),
@@ -136,7 +136,7 @@
137137
138138 if ( $user->isAllowed( 'gadgets-definition-delete' ) ) {
139139 $extra[] = Linker::link(
140 - GadgetHooks::getDefinitionTitleFromID( $gadget->getId() ),
 140+ GadgetsHooks::getDefinitionTitleFromID( $gadget->getId() ),
141141 wfMessage( 'gadgets-gadget-delete' )->escaped(),
142142 array(
143143 'title' => wfMessage( 'gadgets-gadget-delete-tooltip' )->plain(),
@@ -327,7 +327,7 @@
328328 $exportTitles = array();
329329
330330 // NS_GADGET_DEFINITION page of this gadget
331 - $exportTitles[] = GadgetHooks::getDefinitionTitleFromID( $gadget->getId() );
 331+ $exportTitles[] = GadgetsHooks::getDefinitionTitleFromID( $gadget->getId() );
332332
333333 // Title message in NS_MEDIAWIKI
334334 $exportTitles[] = Title::makeTitleSafe( NS_MEDIAWIKI, $gadget->getTitleMessageKey() );
Index: branches/RL2/extensions/Gadgets/Gadgets.hooks.php
@@ -0,0 +1,431 @@
 2+<?php
 3+/**
 4+ * Gadgets extension - lets users select custom javascript gadgets
 5+ *
 6+ *
 7+ * For more info see http://mediawiki.org/wiki/Extension:Gadgets
 8+ *
 9+ * @file
 10+ * @ingroup Extensions
 11+ * @author Daniel Kinzler, brightbyte.de
 12+ * @copyright © 2007 Daniel Kinzler
 13+ * @license GNU General Public Licence 2.0 or later
 14+ */
 15+
 16+class GadgetsHooks {
 17+ /**
 18+ * Get the gadget ID from a title
 19+ * @param $title Title object
 20+ * @return string Gadget id or null if not a gadget definition page
 21+ */
 22+ public static function getIDFromTitle( Title $title ) {
 23+ $id = $title->getText();
 24+ if ( $title->getNamespace() !== NS_GADGET_DEFINITION || !preg_match( '!\.js$!u', $id ) ) {
 25+ // Not a gadget definition page
 26+ return null;
 27+ }
 28+ // Trim .js from the page name to obtain the gadget ID
 29+ return substr( $id, 0, -3 );
 30+ }
 31+
 32+ /**
 33+ * Get a Title object of the gadget definition page from a gadget id
 34+ * @param $is String
 35+ * @return Title|null
 36+ */
 37+ public static function getDefinitionTitleFromID( $id ) {
 38+ return Title::makeTitleSafe( NS_GADGET_DEFINITION, $id . '.js' );
 39+ }
 40+
 41+ /**
 42+ * ArticleDeleteComplete hook handler.
 43+ *
 44+ * @param $article Article
 45+ * @param $user User
 46+ * @param $reason String: Deletion summary
 47+ * @param $id Int: Page ID
 48+ */
 49+ public static function gadgetDefinitionDelete( $article, $user, $reason, $id ) {
 50+ $id = self::getIDFromTitle( $article->getTitle() );
 51+ if ( !$id ) {
 52+ return true;
 53+ }
 54+
 55+ $repo = LocalGadgetRepo::singleton();
 56+ $repo->deleteGadget( $id );
 57+ // deleteGadget() may return an error if the Gadget didn't exist, but we don't care here
 58+ return true;
 59+ }
 60+
 61+ /**
 62+ * ArticleSaveComplete hook handler.
 63+ *
 64+ * @param $article Article
 65+ * @param $user User
 66+ * @param $text String: New page text
 67+ * @param $summary String: Edit summary
 68+ * @param $isMinor Bool: Whether this was a minor edit
 69+ * @param $isWatch unused
 70+ * @param $section unused
 71+ * @param $flags: Int: Bitmap of flags passed to WikiPage::doEdit()
 72+ * @param $revision: Revision object for the new revision
 73+ */
 74+ public static function gadgetDefinitionSave( $article, $user, $text, $summary, $isMinor,
 75+ $isWatch, $section, $flags, $revision )
 76+ {
 77+ $id = self::getIDFromTitle( $article->getTitle() );
 78+ if ( !$id ) {
 79+ return true;
 80+ }
 81+
 82+ $previousRev = $revision->getPrevious();
 83+ $prevTs = $previousRev instanceof Revision ? $previousRev->getTimestamp() : wfTimestampNow();
 84+
 85+ // Update the database entry for this gadget
 86+ $repo = LocalGadgetRepo::singleton();
 87+ // TODO: Timestamp in the constructor is ugly
 88+ $gadget = new Gadget( $id, $repo, $text, $prevTs );
 89+ $repo->modifyGadget( $gadget, $revision->getTimestamp() );
 90+
 91+ // modifyGadget() returns a Status object with an error if there was a conflict,
 92+ // but we don't care. If a conflict occurred, that must be because a newer edit's
 93+ // DB update occurred before ours, in which case the right thing to do is to occu
 94+
 95+ return true;
 96+ }
 97+
 98+ /**
 99+ * Update the database entry for a gadget if the description page is
 100+ * newer than the database entry.
 101+ * @param $title Title object
 102+ */
 103+ public static function gadgetDefinitionUpdateIfChanged( $title ) {
 104+ $id = self::getIDFromTitle( $title );
 105+ if ( !$id ) {
 106+ return;
 107+ }
 108+
 109+ // Check whether this undeletion changed the latest revision of the page, by comparing
 110+ // the timestamp of the latest revision with the timestamp in the DB
 111+ $repo = LocalGadgetRepo::singleton();
 112+ $gadget = $repo->getGadget( $id );
 113+ $gadgetTS = $gadget ? $gadget->getTimestamp() : 0;
 114+
 115+ $rev = Revision::newFromTitle( $title );
 116+ if ( wfTimestamp( TS_MW, $rev->getTimestamp() ) ===
 117+ wfTimestamp( TS_MW, $gadgetTS ) ) {
 118+ // The latest rev didn't change. Someone must've undeleted an older revision
 119+ return;
 120+ }
 121+
 122+ // Update the database entry for this gadget
 123+ $newGadget = new Gadget( $id, $repo, $rev->getRawText(), $gadgetTS );
 124+ $repo->modifyGadget( $newGadget, $rev->getTimestamp() );
 125+
 126+ // modifyGadget() returns a Status object with an error if there was a conflict,
 127+ // but we do't care, see similar comment in articleSaveComplete()
 128+ return;
 129+ }
 130+
 131+ /**
 132+ * ArticleUndelete hook handler
 133+ * @param $title Title object
 134+ * @param $created Bool: Whether this undeletion recreated the page
 135+ * @param $comment String: Undeletion summary
 136+ */
 137+ public static function gadgetDefinitionUndelete( $title, $created, $comment ) {
 138+ self::gadgetDefinitionUpdateIfChanged( $title );
 139+ return true;
 140+ }
 141+
 142+ public static function gadgetDefinitionImport( $title, $origTitle, $revCount, $sRevCount, $pageInfo ) {
 143+ self::gadgetDefinitionUpdateIfChanged( $title );
 144+ return true;
 145+ }
 146+
 147+ /**
 148+ * ArticleDeleteComplete hook handler.
 149+ *
 150+ * @param $article Article
 151+ * @param $user User
 152+ * @param $reason String: Deletion summary
 153+ * @param $id Int: Page ID
 154+ */
 155+ public static function cssJsPageDelete( $article, $user, $reason, $id ) {
 156+ GadgetPageList::delete( $article->getTitle() );
 157+ return true;
 158+ }
 159+
 160+ /**
 161+ * ArticleSaveComplete hook handler.
 162+ *
 163+ * @param $article Article
 164+ * @param $user User
 165+ * @param $text String: New page text
 166+ * @param $summary String: Edit summary
 167+ * @param $isMinor Bool: Whether this was a minor edit
 168+ * @param $isWatch unused
 169+ * @param $section unused
 170+ * @param $flags: Int: Bitmap of flags passed to WikiPage::doEdit()
 171+ * @param $revision: Revision object for the new revision
 172+ */
 173+ public static function cssOrJsPageSave( $article, $user, $text, $summary, $isMinor,
 174+ $isWatch, $section, $flags, $revision )
 175+ {
 176+ $title = $article->getTitle();
 177+ GadgetPageList::updatePageStatus( $title );
 178+ return true;
 179+ }
 180+
 181+ /**
 182+ * ArticleUndelete hook handler
 183+ * @param $title Title object
 184+ * @param $created Bool: Whether this undeletion recreated the page
 185+ * @param $comment String: Undeletion summary
 186+ */
 187+ public static function cssOrJsPageUndelete( $title, $created, $comment ) {
 188+ GadgetPageList::updatePageStatus( $title );
 189+ return true;
 190+ }
 191+
 192+ public static function cssOrJsPageMove( $oldTitle, $newTitle, $user, $pageid, $redirid ) {
 193+ // Delete the old title from the list. Even if it still exists after the move,
 194+ // it'll be a redirect and we don't want those in there
 195+ GadgetPageList::delete( $oldTitle );
 196+
 197+ GadgetPageList::updatePageStatus( $newTitle );
 198+ return true;
 199+ }
 200+
 201+ /**
 202+ * UserGetDefaultOptions hook handler
 203+ * @param $defaultOptions Array of default preference keys and values
 204+ */
 205+ public static function userGetDefaultOptions( &$defaultOptions ) {
 206+ $repo = LocalGadgetRepo::singleton();
 207+ $gadgetIds = $repo->getGadgetIds();
 208+ foreach ( $gadgetIds as $gadgetId ) {
 209+ $gadget = $repo->getGadget( $gadgetId );
 210+ if ( $gadget->isEnabledByDefault() ) {
 211+ $defaultOptions['gadget-' . $gadget->getId()] = 1;
 212+ }
 213+ }
 214+ return true;
 215+ }
 216+
 217+ /**
 218+ * GetPreferences hook handler.
 219+ * @param $user User
 220+ * @param $preferences Array: Preference descriptions
 221+ */
 222+ public static function getPreferences( $user, &$preferences ) {
 223+ $repo = LocalGadgetRepo::singleton();
 224+ $gadgets = $repo->getGadgetIds();
 225+ $categories = array(); // array( category => array( desc => title ) )
 226+ $default = array(); // array of Gadget ids
 227+ foreach ( $gadgets as $id ) {
 228+ $gadget = $repo->getGadget( $id );
 229+ if ( !$gadget->isAllowed( $user ) || $gadget->isHidden() ) {
 230+ continue;
 231+ }
 232+ $category = $gadget->getCategory();
 233+
 234+ // Add the Gadget to the right category
 235+ $title = htmlspecialchars( $gadget->getTitleMessage() );
 236+ $description = $gadget->getDescriptionMessage(); // Is parsed, doesn't need escaping
 237+ if ( $description === '' ) {
 238+ // Empty description, just use the title
 239+ $text = $title;
 240+ } else {
 241+ $text = wfMessage( 'gadgets-preference-description' )->rawParams( $title, $description )->parse();
 242+ }
 243+ $categories[$category][$text] = $id;
 244+ // Add the Gadget to the default list if enabled
 245+ if ( $gadget->isEnabledForUser( $user ) ) {
 246+ $default[] = $id;
 247+ }
 248+ }
 249+
 250+ $options = array(); // array( desc1 => gadget1, category1 => array( desc2 => gadget2 ) )
 251+ foreach ( $categories as $category => $gadgets ) {
 252+ if ( $category !== '' ) {
 253+ $categoryMsg = htmlspecialchars( $repo->getCategoryTitle( $category ) );
 254+ $options[$categoryMsg] = $gadgets;
 255+ } else {
 256+ $options += $gadgets;
 257+ }
 258+ }
 259+
 260+ $preferences['gadgets-intro'] =
 261+ array(
 262+ 'type' => 'info',
 263+ 'label' => '&#160;',
 264+ 'default' => Xml::tags( 'tr', array(),
 265+ Xml::tags( 'td', array( 'colspan' => 2 ),
 266+ wfMsgExt( 'gadgets-prefstext', 'parse' ) ) ),
 267+ 'section' => 'gadgets',
 268+ 'raw' => 1,
 269+ 'rawrow' => 1,
 270+ );
 271+ $preferences['gadgets'] =
 272+ array(
 273+ 'type' => 'multiselect',
 274+ 'options' => $options,
 275+ 'section' => 'gadgets',
 276+ 'label' => '&#160;',
 277+ 'prefix' => 'gadget-',
 278+ 'default' => $default,
 279+ );
 280+
 281+ // Add tab for shared gadgets
 282+ $preferences['gadgets-intro-shared'] =
 283+ array(
 284+ 'type' => 'info',
 285+ 'label' => '&#160;',
 286+ 'default' => Xml::tags( 'tr', array(),
 287+ Xml::tags( 'td', array( 'colspan' => 2 ),
 288+ wfMsgExt( 'gadgets-sharedprefstext', 'parse' ) ) ),
 289+ 'section' => 'gadgets-shared',
 290+ 'raw' => 1,
 291+ 'rawrow' => 1,
 292+ );
 293+ $preferences['gadgets-shared'] =
 294+ array(
 295+ 'type' => 'multiselect',
 296+ 'options' => array(), // TODO: Maybe fill in stuff anyway? The backend may need that
 297+ 'section' => 'gadgets-shared',
 298+ 'label' => '&#160;',
 299+ 'prefix' => 'gadget-',
 300+ 'default' => array(),
 301+ );
 302+ return true;
 303+ }
 304+
 305+ /**
 306+ * ResourceLoaderRegisterModules hook handler.
 307+ * @param $resourceLoader ResourceLoader
 308+ */
 309+ public static function registerModules( &$resourceLoader ) {
 310+ $gadgets = GadgetRepo::getAllGadgets();
 311+ foreach ( $gadgets as $gadget ) {
 312+ $resourceLoader->register( $gadget->getModuleName(), $gadget->getModule() );
 313+ }
 314+ return true;
 315+ }
 316+
 317+ /**
 318+ * BeforePageDisplay hook handler.
 319+ * @param $out OutputPage
 320+ */
 321+ public static function beforePageDisplay( $out ) {
 322+ wfProfileIn( __METHOD__ );
 323+
 324+ $user = $out->getUser();
 325+ $gadgets = GadgetRepo::getAllGadgets();
 326+ foreach ( $gadgets as $gadget ) {
 327+ if ( $gadget->isEnabledForUser( $user ) && $gadget->isAllowed( $user ) ) {
 328+ $out->addModules( $gadget->getModuleName() );
 329+ }
 330+ }
 331+
 332+ // Add preferences JS if we're on Special:Preferences
 333+ if ( $out->getTitle()->equals( SpecialPage::getTitleFor( 'Preferences' ) ) ) {
 334+ $out->addModules( 'ext.gadgets.preferences' );
 335+ }
 336+
 337+ wfProfileOut( __METHOD__ );
 338+ return true;
 339+ }
 340+
 341+ /**
 342+ * MakeGlobalVariablesScript hook handler
 343+ * @param $vars Array: Key/value pars for mw.config.set on this page.
 344+ * @param $out OutputPage
 345+ */
 346+ public static function makeGlobalVariablesScript( &$vars, $out ) {
 347+ $title = $out->getTitle();
 348+ $user = $out->getUser();
 349+ // FIXME: This is not a nice way to do it. Maybe we should check for the presence
 350+ // of a module instead or something.
 351+ if ( $title->equals( SpecialPage::getTitleFor( 'Gadgets' ) ) ||
 352+ $title->equals( SpecialPage::getTitleFor( 'Preferences' ) ) )
 353+ {
 354+ global $wgGadgetEnableSharing;
 355+
 356+ // Pass the source data for each source that is used by a repository
 357+ $repos = GadgetRepo::getAllRepos();
 358+ $sources = $out->getResourceLoader()->getSources();
 359+ $repoData = array();
 360+ foreach ( $repos as $repo ) {
 361+ $repoData[$repo->getSource()] = $sources[$repo->getSource()];
 362+ }
 363+
 364+ $vars['gadgetsConf'] = array(
 365+ 'enableSharing' => $wgGadgetEnableSharing,
 366+ 'allRights' => User::getAllRights(),
 367+ 'repos' => $repoData,
 368+ 'userIsAllowed' => array(
 369+ 'editinterface' => $user->isAllowed( 'editinterface' ),
 370+ 'gadgets-definition-create' => $user->isAllowed( 'gadgets-definition-create' ),
 371+ 'gadgets-definition-edit' => $user->isAllowed( 'gadgets-definition-edit' ),
 372+ 'gadgets-definition-delete' => $user->isAllowed( 'gadgets-definition-delete' ),
 373+ ),
 374+ );
 375+ }
 376+ return true;
 377+ }
 378+
 379+ /**
 380+ * UnitTestsList hook handler
 381+ * @param $files Array: List of extension test files
 382+ */
 383+ public static function unitTestsList( &$files ) {
 384+ $files[] = dirname( __FILE__ ) . '/tests/GadgetsTest.php';
 385+ return true;
 386+ }
 387+
 388+ public static function loadExtensionSchemaUpdates( $updater ) {
 389+ $dir = dirname( __FILE__ );
 390+ $updater->addExtensionUpdate( array( 'addtable', 'gadgets', "$dir/sql/gadgets.sql", true ) );
 391+ $updater->addExtensionUpdate( array( 'addtable', 'gadgetpagelist', "$dir/sql/patch-gadgetpagelist.sql", true ) );
 392+ return true;
 393+ }
 394+
 395+ public static function canonicalNamespaces( &$list ) {
 396+ $list[NS_GADGET] = 'Gadget';
 397+ $list[NS_GADGET_TALK] = 'Gadget_talk';
 398+ $list[NS_GADGET_DEFINITION] = 'Gadget_definition';
 399+ $list[NS_GADGET_DEFINITION_TALK] = 'Gadget_definition_talk';
 400+ return true;
 401+ }
 402+
 403+ public static function titleIsCssOrJsPage( $title, &$result ) {
 404+ if ( ( $title->getNamespace() == NS_GADGET || $title->getNamespace() == NS_GADGET_DEFINITION ) &&
 405+ preg_match( '!\.(css|js)$!u', $title->getText() ) )
 406+ {
 407+ $result = true;
 408+ }
 409+ return true;
 410+ }
 411+
 412+ public static function titleIsMovable( $title, &$result ) {
 413+ if ( $title->getNamespace() == NS_GADGET_DEFINITION ) {
 414+ $result = false;
 415+ }
 416+ return true;
 417+ }
 418+
 419+ public static function getUserPermissionsErrors( $title, $user, $action, &$result ) {
 420+ if ( $title->getNamespace() == NS_GADGET_DEFINITION ) {
 421+ // Enforce restrictions on the Gadget_definition namespace
 422+ if ( $action == 'create' && !$user->isAllowed( 'gadgets-definition-create' ) ) {
 423+ $result[] = array( 'gadgets-cant-create' );
 424+ return false;
 425+ } elseif ( $action == 'delete' && !$user->isAllowed( 'gadgets-definition-delete' ) ) {
 426+ $result[] = array( 'gadgets-cant-delete' );
 427+ return false;
 428+ }
 429+ }
 430+ return true;
 431+ }
 432+}
Property changes on: branches/RL2/extensions/Gadgets/Gadgets.hooks.php
___________________________________________________________________
Added: svn:mergeinfo
1433 Merged /branches/Gadgets-work/Gadgets_body.php:r73145-76526
2434 Merged /branches/wmf/1.17wmf1/extensions/Gadgets/Gadgets_body.php:r81884
Added: svn:eol-style
3435 + native
Added: svn:keywords
4436 + LastChangedDate LastChangedRevision

Status & tagging log