MediaWiki  1.34.0
GadgetHooks.php
Go to the documentation of this file.
1 <?php
2 
24 use Wikimedia\WrappedString;
25 
26 class GadgetHooks {
34  public static function onPageContentSaveComplete( WikiPage $wikiPage, $user, $content ) {
35  // update cache if MediaWiki:Gadgets-definition was edited
36  GadgetRepo::singleton()->handlePageUpdate( $wikiPage->getTitle() );
37  }
38 
43  public static function userGetDefaultOptions( array &$defaultOptions ) {
44  $gadgets = GadgetRepo::singleton()->getStructuredList();
45  if ( !$gadgets ) {
46  return;
47  }
48 
52  foreach ( $gadgets as $thisSection ) {
53  foreach ( $thisSection as $gadgetId => $gadget ) {
54  if ( $gadget->isOnByDefault() ) {
55  $defaultOptions['gadget-' . $gadgetId] = 1;
56  }
57  }
58  }
59  }
60 
66  public static function getPreferences( User $user, array &$preferences ) {
67  $gadgets = GadgetRepo::singleton()->getStructuredList();
68  if ( !$gadgets ) {
69  return;
70  }
71 
72  $options = [];
73  $default = [];
74  $skin = RequestContext::getMain()->getSkin();
75  foreach ( $gadgets as $section => $thisSection ) {
76  $available = [];
77 
81  foreach ( $thisSection as $gadget ) {
82  if (
83  !$gadget->isHidden()
84  && $gadget->isAllowed( $user )
85  && $gadget->isSkinSupported( $skin )
86  ) {
87  $gname = $gadget->getName();
88  # bug 30182: dir="auto" because it's often not translated
89  $desc = '<span dir="auto">' . $gadget->getDescription() . '</span>';
90  $available[$desc] = $gname;
91  if ( $gadget->isEnabled( $user ) ) {
92  $default[] = $gname;
93  }
94  }
95  }
96 
97  if ( $section !== '' ) {
98  $section = wfMessage( "gadget-section-$section" )->parse();
99 
100  if ( count( $available ) ) {
101  $options[$section] = $available;
102  }
103  } else {
104  $options = array_merge( $options, $available );
105  }
106  }
107 
108  $preferences['gadgets-intro'] =
109  [
110  'type' => 'info',
111  'default' => wfMessage( 'gadgets-prefstext' )->parseAsBlock(),
112  'section' => 'gadgets',
113  'raw' => true,
114  ];
115 
116  $preferences['gadgets'] =
117  [
118  'type' => 'multiselect',
119  'options' => $options,
120  'section' => 'gadgets',
121  'label' => '&#160;',
122  'prefix' => 'gadget-',
123  'default' => $default,
124  'noglobal' => true,
125  ];
126  }
127 
132  public static function registerModules( ResourceLoader &$resourceLoader ) {
133  $repo = GadgetRepo::singleton();
134  $ids = $repo->getGadgetIds();
135 
136  foreach ( $ids as $id ) {
137  $resourceLoader->register( Gadget::getModuleName( $id ), [
138  'class' => 'GadgetResourceLoaderModule',
139  'id' => $id,
140  ] );
141  }
142  }
143 
148  public static function beforePageDisplay( OutputPage $out ) {
149  $repo = GadgetRepo::singleton();
150  $ids = $repo->getGadgetIds();
151  if ( !$ids ) {
152  return;
153  }
154 
155  $lb = new LinkBatch();
156  $lb->setCaller( __METHOD__ );
157  $enabledLegacyGadgets = [];
158 
162  $user = $out->getUser();
163  $skin = $out->getSkin();
164  foreach ( $ids as $id ) {
165  try {
166  $gadget = $repo->getGadget( $id );
167  } catch ( InvalidArgumentException $e ) {
168  continue;
169  }
170  $peers = [];
171  foreach ( $gadget->getPeers() as $peerName ) {
172  try {
173  $peers[] = $repo->getGadget( $peerName );
174  } catch ( InvalidArgumentException $e ) {
175  // Ignore
176  // @todo: Emit warning for invalid peer?
177  }
178  }
179  if ( $gadget->isEnabled( $user )
180  && $gadget->isAllowed( $user )
181  && $gadget->isSkinSupported( $skin )
182  ) {
183  if ( $gadget->hasModule() ) {
184  if ( $gadget->getType() === 'styles' ) {
185  $out->addModuleStyles( Gadget::getModuleName( $gadget->getName() ) );
186  } else {
187  $out->addModules( Gadget::getModuleName( $gadget->getName() ) );
188  // Load peer modules
189  foreach ( $peers as $peer ) {
190  if ( $peer->getType() === 'styles' ) {
191  $out->addModuleStyles( Gadget::getModuleName( $peer->getName() ) );
192  }
193  // Else, if not type=styles: Use dependencies instead.
194  // Note: No need for recursion as styles modules don't support
195  // either of 'dependencies' and 'peers'.
196  }
197  }
198  }
199 
200  if ( $gadget->getLegacyScripts() ) {
201  $enabledLegacyGadgets[] = $id;
202  }
203  }
204  }
205 
206  $strings = [];
207  foreach ( $enabledLegacyGadgets as $id ) {
208  $strings[] = self::makeLegacyWarning( $id );
209  }
210  $out->addHTML( WrappedString::join( "\n", $strings ) );
211  }
212 
213  private static function makeLegacyWarning( $id ) {
214  $special = SpecialPage::getTitleFor( 'Gadgets' );
215 
216  return ResourceLoader::makeInlineScript(
217  Xml::encodeJsCall( 'mw.log.warn', [
218  "Gadget \"$id\" was not loaded. Please migrate it to use ResourceLoader. " .
219  'See <' . $special->getCanonicalURL() . '>.'
220  ] )
221  );
222  }
223 
236  Status $status,
237  $summary
238  ) {
239  $title = $context->getTitle();
240 
241  if ( !$title->inNamespace( NS_GADGET_DEFINITION ) ) {
242  return true;
243  }
244 
245  if ( !$content instanceof GadgetDefinitionContent ) {
246  // This should not be possible?
247  throw new Exception(
248  "Tried to save non-GadgetDefinitionContent to {$title->getPrefixedText()}"
249  );
250  }
251 
252  $validateStatus = $content->validate();
253  if ( !$validateStatus->isGood() ) {
254  $status->merge( $validateStatus );
255  return false;
256  }
257 
258  return true;
259  }
260 
267  public static function onPageContentInsertComplete( WikiPage $page ) {
268  if ( $page->getTitle()->inNamespace( NS_GADGET_DEFINITION ) ) {
269  GadgetRepo::singleton()->handlePageCreation( $page->getTitle() );
270  }
271  }
272 
281  public static function onContentHandlerDefaultModelFor( Title $title, &$model ) {
282  if ( $title->inNamespace( NS_GADGET ) ) {
283  preg_match( '!\.(css|js)$!u', $title->getText(), $ext );
284  $ext = $ext[1] ?? '';
285  switch ( $ext ) {
286  case 'js':
287  $model = 'javascript';
288  return false;
289  case 'css':
290  $model = 'css';
291  return false;
292  }
293  }
294 
295  return true;
296  }
297 
306  public static function onCodeEditorGetPageLanguage( Title $title, &$lang ) {
307  if ( $title->hasContentModel( 'GadgetDefinition' ) ) {
308  $lang = 'json';
309  return false;
310  }
311 
312  return true;
313  }
314 
319  public static function onwgQueryPages( array &$queryPages ) {
320  $queryPages[] = [ 'SpecialGadgetUsage', 'GadgetUsage' ];
321  }
322 
330  public static function onDeleteUnknownPreferences( array &$where, IDatabase $db ) {
331  $where[] = 'up_property NOT' . $db->buildLike( 'gadget-', $db->anyString() );
332  }
333 }
Gadget\getModuleName
static getModuleName( $id)
Definition: Gadget.php:150
GadgetHooks\onContentHandlerDefaultModelFor
static onContentHandlerDefaultModelFor(Title $title, &$model)
Mark the Title as having a content model of javascript or css for pages in the Gadget namespace based...
Definition: GadgetHooks.php:281
LinkBatch
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition: LinkBatch.php:34
GadgetHooks\onPageContentInsertComplete
static onPageContentInsertComplete(WikiPage $page)
After a new page is created in the Gadget definition namespace, invalidate the list of gadget ids.
Definition: GadgetHooks.php:267
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:33
$resourceLoader
$resourceLoader
Definition: load.php:44
WikiPage
Class representing a MediaWiki article and history.
Definition: WikiPage.php:47
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1264
SpecialPage\getTitleFor
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Definition: SpecialPage.php:83
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
Status
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:40
Xml\encodeJsCall
static encodeJsCall( $name, $args, $pretty=false)
Create a call to a JavaScript function.
Definition: Xml.php:677
GadgetHooks
Definition: GadgetHooks.php:26
WikiPage\getTitle
getTitle()
Get the title object of the article.
Definition: WikiPage.php:298
$title
$title
Definition: testCompression.php:34
GadgetHooks\onDeleteUnknownPreferences
static onDeleteUnknownPreferences(array &$where, IDatabase $db)
Prevent gadget preferences from being deleted.
Definition: GadgetHooks.php:330
GadgetRepo\singleton
static singleton()
Get the configured default GadgetRepo.
Definition: GadgetRepo.php:88
GadgetHooks\onwgQueryPages
static onwgQueryPages(array &$queryPages)
Add the GadgetUsage special page to the list of QueryPages.
Definition: GadgetHooks.php:319
GadgetHooks\beforePageDisplay
static beforePageDisplay(OutputPage $out)
BeforePageDisplay hook handler.
Definition: GadgetHooks.php:148
GadgetHooks\makeLegacyWarning
static makeLegacyWarning( $id)
Definition: GadgetHooks.php:213
GadgetHooks\userGetDefaultOptions
static userGetDefaultOptions(array &$defaultOptions)
UserGetDefaultOptions hook handler.
Definition: GadgetHooks.php:43
GadgetHooks\onEditFilterMergedContent
static onEditFilterMergedContent(IContextSource $context, Content $content, Status $status, $summary)
Valid gadget definition page after content is modified.
Definition: GadgetHooks.php:234
$content
$content
Definition: router.php:78
GadgetDefinitionContent
Definition: GadgetDefinitionContent.php:23
Wikimedia\Rdbms\IDatabase\anyString
anyString()
Returns a token for buildLike() that denotes a '' to be used in a LIKE query.
Wikimedia\Rdbms\IDatabase\buildLike
buildLike( $param)
LIKE statement wrapper.
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:431
GadgetHooks\onCodeEditorGetPageLanguage
static onCodeEditorGetPageLanguage(Title $title, &$lang)
Set the CodeEditor language for Gadget definition pages.
Definition: GadgetHooks.php:306
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:53
$context
$context
Definition: load.php:45
Content
Base interface for content objects.
Definition: Content.php:34
Title
Represents a title within MediaWiki.
Definition: Title.php:42
GadgetHooks\getPreferences
static getPreferences(User $user, array &$preferences)
GetPreferences hook handler.
Definition: GadgetHooks.php:66
$status
return $status
Definition: SyntaxHighlight.php:347
GadgetHooks\registerModules
static registerModules(ResourceLoader &$resourceLoader)
ResourceLoaderRegisterModules hook handler.
Definition: GadgetHooks.php:132
GadgetHooks\onPageContentSaveComplete
static onPageContentSaveComplete(WikiPage $wikiPage, $user, $content)
PageContentSaveComplete hook handler.
Definition: GadgetHooks.php:34
$ext
if(!is_readable( $file)) $ext
Definition: router.php:48
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:51