MediaWiki  master
TrackingCategories.php
Go to the documentation of this file.
1 <?php
22 namespace MediaWiki\Category;
23 
32 use ParserOutput;
33 use Psr\Log\LoggerInterface;
34 
42 
46  public const CONSTRUCTOR_OPTIONS = [
49  ];
50 
52  private $options;
53 
55  private $namespaceInfo;
56 
58  private $titleParser;
59 
61  private $extensionRegistry;
62 
64  private $logger;
65 
71  private const CORE_TRACKING_CATEGORIES = [
72  'broken-file-category',
73  'duplicate-args-category',
74  'expansion-depth-exceeded-category',
75  'expensive-parserfunction-category',
76  'hidden-category-category',
77  'index-category',
78  'node-count-exceeded-category',
79  'noindex-category',
80  'nonnumeric-formatnum',
81  'post-expand-template-argument-category',
82  'post-expand-template-inclusion-category',
83  'restricted-displaytitle-ignored',
84  # template-equals-category is unused in MW>=1.39, but the category
85  # can be left around for a major release or so for an easier
86  # transition for anyone who didn't do the cleanup. T91154
87  'template-equals-category',
88  'template-loop-category',
89  'unstrip-depth-category',
90  'unstrip-size-category',
91  ];
92 
99  public function __construct(
100  ServiceOptions $options,
101  NamespaceInfo $namespaceInfo,
102  TitleParser $titleParser,
103  LoggerInterface $logger
104  ) {
105  $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
106  $this->options = $options;
107  $this->namespaceInfo = $namespaceInfo;
108  $this->titleParser = $titleParser;
109  $this->logger = $logger;
110 
111  // TODO convert ExtensionRegistry to a service and inject it
112  $this->extensionRegistry = ExtensionRegistry::getInstance();
113  }
114 
125  public function getTrackingCategories() {
126  $categories = array_merge(
127  self::CORE_TRACKING_CATEGORIES,
128  $this->extensionRegistry->getAttribute( MainConfigNames::TrackingCategories ),
129  $this->options->get( MainConfigNames::TrackingCategories ) // deprecated
130  );
131 
132  // Only show magic link tracking categories if they are enabled
133  $enableMagicLinks = $this->options->get( MainConfigNames::EnableMagicLinks );
134  if ( $enableMagicLinks['ISBN'] ) {
135  $categories[] = 'magiclink-tracking-isbn';
136  }
137  if ( $enableMagicLinks['RFC'] ) {
138  $categories[] = 'magiclink-tracking-rfc';
139  }
140  if ( $enableMagicLinks['PMID'] ) {
141  $categories[] = 'magiclink-tracking-pmid';
142  }
143 
144  $trackingCategories = [];
145  foreach ( $categories as $catMsg ) {
146  /*
147  * Check if the tracking category varies by namespace
148  * Otherwise only pages in the current namespace will be displayed
149  * If it does vary, show pages considering all namespaces
150  *
151  * TODO replace uses of wfMessage with an injected service once that is available
152  */
153  $msgObj = wfMessage( $catMsg )->inContentLanguage();
154  $allCats = [];
155  $catMsgTitle = $this->titleParser->makeTitleValueSafe( NS_MEDIAWIKI, $catMsg );
156  if ( !$catMsgTitle ) {
157  continue;
158  }
159 
160  // Match things like {{NAMESPACE}} and {{NAMESPACENUMBER}}.
161  // False positives are ok, this is just an efficiency shortcut
162  if ( strpos( $msgObj->plain(), '{{' ) !== false ) {
163  $ns = $this->namespaceInfo->getValidNamespaces();
164  foreach ( $ns as $namesp ) {
165  $tempTitle = $this->titleParser->makeTitleValueSafe( $namesp, $catMsg );
166  if ( !$tempTitle ) {
167  continue;
168  }
169  // XXX: should be a better way to convert a TitleValue
170  // to a PageReference!
171  $tempTitle = Title::newFromLinkTarget( $tempTitle );
172  $catName = $msgObj->page( $tempTitle )->text();
173  # Allow tracking categories to be disabled by setting them to "-"
174  if ( $catName !== '-' ) {
175  $catTitle = $this->titleParser->makeTitleValueSafe( NS_CATEGORY, $catName );
176  if ( $catTitle ) {
177  $allCats[] = $catTitle;
178  }
179  }
180  }
181  } else {
182  $catName = $msgObj->text();
183  # Allow tracking categories to be disabled by setting them to "-"
184  if ( $catName !== '-' ) {
185  $catTitle = $this->titleParser->makeTitleValueSafe( NS_CATEGORY, $catName );
186  if ( $catTitle ) {
187  $allCats[] = $catTitle;
188  }
189  }
190  }
191  $trackingCategories[$catMsg] = [
192  'cats' => $allCats,
193  'msg' => $catMsgTitle,
194  ];
195  }
196 
197  return $trackingCategories;
198  }
199 
208  public function resolveTrackingCategory( string $msg, ?PageReference $contextPage ): ?LinkTarget {
209  if ( !$contextPage ) {
210  $this->logger->debug( "Not adding tracking category $msg to missing page!" );
211  return null;
212  }
213 
214  if ( $contextPage->getNamespace() === NS_SPECIAL ) {
215  $this->logger->debug( "Not adding tracking category $msg to special page!" );
216  return null;
217  }
218 
219  // Important to parse with correct title (T33469)
220  // TODO replace uses of wfMessage with an injected service once that is available
221  $cat = wfMessage( $msg )
222  ->page( $contextPage )
223  ->inContentLanguage()
224  ->text();
225 
226  # Allow tracking categories to be disabled by setting them to "-"
227  if ( $cat === '-' ) {
228  return null;
229  }
230 
231  $containerCategory = $this->titleParser->makeTitleValueSafe( NS_CATEGORY, $cat );
232  if ( $containerCategory === null ) {
233  $this->logger->debug( "[[MediaWiki:$msg]] is not a valid title!" );
234  return null;
235  }
236  return $containerCategory;
237  }
238 
256  public function addTrackingCategory( ParserOutput $parserOutput, string $msg, ?PageReference $contextPage ): bool {
257  $categoryPage = $this->resolveTrackingCategory( $msg, $contextPage );
258  if ( $categoryPage === null ) {
259  return false;
260  }
261  $parserOutput->addCategory(
262  $categoryPage->getDBkey(),
263  $parserOutput->getPageProperty( 'defaultsort' ) ?? ''
264  );
265  return true;
266  }
267 }
268 
272 class_alias( TrackingCategories::class, 'TrackingCategories' );
const NS_MEDIAWIKI
Definition: Defines.php:72
const NS_SPECIAL
Definition: Defines.php:53
const NS_CATEGORY
Definition: Defines.php:78
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
if(!defined('MW_SETUP_CALLBACK'))
Definition: WebStart.php:88
Load JSON files, and uses a Processor to extract information.
This class performs some operations related to tracking categories, such as adding a tracking categor...
A class for passing options to services.
assertRequiredOptions(array $expectedKeys)
Assert that the list of options provided in this instance exactly match $expectedKeys,...
A class containing constants representing the names of configuration variables.
const EnableMagicLinks
Name constant for the EnableMagicLinks setting, for use with Config::get()
const TrackingCategories
Name constant for the TrackingCategories setting, for use with Config::get()
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Represents a title within MediaWiki.
Definition: Title.php:76
static newFromLinkTarget(LinkTarget $linkTarget, $forceClone='')
Returns a Title given a LinkTarget.
Definition: Title.php:290
__construct(IContextSource $context=null)
Definition: MediaWiki.php:70
getPageProperty(string $name)
Look up a page property.
addCategory( $c, $sort='')
Add a category.
Represents the target of a wiki link.
Definition: LinkTarget.php:30
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.
A title parser service for MediaWiki.
Definition: TitleParser.php:35
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...