MediaWiki master
TrackingCategories.php
Go to the documentation of this file.
1<?php
8namespace MediaWiki\Category;
9
19use Psr\Log\LoggerInterface;
20use Wikimedia\Parsoid\Core\ContentMetadataCollector;
21
29
33 public const CONSTRUCTOR_OPTIONS = [
36 ];
37
39 private $options;
40
42 private $namespaceInfo;
43
45 private $titleParser;
46
48 private $extensionRegistry;
49
51 private $logger;
52
56 private const CORE_TRACKING_CATEGORIES = [
57 'broken-file-category',
58 'duplicate-args-category',
59 'expansion-depth-exceeded-category',
60 'expensive-parserfunction-category',
61 'hidden-category-category',
62 'index-category',
63 'node-count-exceeded-category',
64 'noindex-category',
65 'nonnumeric-formatnum',
66 'post-expand-template-argument-category',
67 'post-expand-template-inclusion-category',
68 'restricted-displaytitle-ignored',
69 # template-equals-category is unused in MW>=1.39, but the category
70 # can be left around for a major release or so for an easier
71 # transition for anyone who didn't do the cleanup. T91154
72 'template-equals-category',
73 'template-loop-category',
74 'unstrip-depth-category',
75 'unstrip-size-category',
76 'bad-language-code-category',
77 'bad-double-underscore-category',
78 'double-px-category',
79 ];
80
81 public function __construct(
82 ServiceOptions $options,
83 NamespaceInfo $namespaceInfo,
84 TitleParser $titleParser,
85 LoggerInterface $logger
86 ) {
87 $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
88 $this->options = $options;
89 $this->namespaceInfo = $namespaceInfo;
90 $this->titleParser = $titleParser;
91 $this->logger = $logger;
92
93 // TODO convert ExtensionRegistry to a service and inject it
94 $this->extensionRegistry = ExtensionRegistry::getInstance();
95 }
96
107 public function getTrackingCategories() {
108 $categories = array_merge(
109 self::CORE_TRACKING_CATEGORIES,
110 $this->extensionRegistry->getAttribute( MainConfigNames::TrackingCategories ),
111 $this->options->get( MainConfigNames::TrackingCategories ) // deprecated
112 );
113
114 // Only show magic link tracking categories if they are enabled
115 $enableMagicLinks = $this->options->get( MainConfigNames::EnableMagicLinks );
116 if ( $enableMagicLinks['ISBN'] ) {
117 $categories[] = 'magiclink-tracking-isbn';
118 }
119 if ( $enableMagicLinks['RFC'] ) {
120 $categories[] = 'magiclink-tracking-rfc';
121 }
122 if ( $enableMagicLinks['PMID'] ) {
123 $categories[] = 'magiclink-tracking-pmid';
124 }
125
126 $trackingCategories = [];
127 foreach ( $categories as $catMsg ) {
128 /*
129 * Check if the tracking category varies by namespace
130 * Otherwise only pages in the current namespace will be displayed
131 * If it does vary, show pages considering all namespaces
132 *
133 * TODO replace uses of wfMessage with an injected service once that is available
134 */
135 $msgObj = wfMessage( $catMsg )->inContentLanguage();
136 $allCats = [];
137 $catMsgTitle = $this->titleParser->makeTitleValueSafe( NS_MEDIAWIKI, $catMsg );
138 if ( !$catMsgTitle ) {
139 continue;
140 }
141
142 // Match things like {{NAMESPACE}} and {{NAMESPACENUMBER}}.
143 // False positives are ok, this is just an efficiency shortcut
144 if ( str_contains( $msgObj->plain(), '{{' ) ) {
145 $ns = $this->namespaceInfo->getValidNamespaces();
146 foreach ( $ns as $namesp ) {
147 $tempTitle = $this->titleParser->makeTitleValueSafe( $namesp, $catMsg );
148 if ( !$tempTitle ) {
149 continue;
150 }
151 // XXX: should be a better way to convert a TitleValue
152 // to a PageReference!
153 $tempTitle = Title::newFromLinkTarget( $tempTitle );
154 $allCats[] = $msgObj->page( $tempTitle )->text();
155 }
156 } else {
157 $allCats[] = $msgObj->text();
158 }
159 $titles = [];
160 foreach ( $allCats as $catName ) {
161 // Extra check in case a message does fancy stuff with {{#if:… and such
162 if ( $catName !== '-' ) {
163 $catTitle = $this->titleParser->makeTitleValueSafe( NS_CATEGORY, $catName );
164 if ( $catTitle ) {
165 $titles[] = $catTitle;
166 }
167 }
168 }
169 $trackingCategories[$catMsg] = [
170 'cats' => $titles,
171 'msg' => $catMsgTitle,
172 ];
173 }
174
175 return $trackingCategories;
176 }
177
186 public function resolveTrackingCategory( string $msg, ?PageReference $contextPage ): ?LinkTarget {
187 if ( !$contextPage ) {
188 $this->logger->debug( "Not adding tracking category $msg to missing page!" );
189 return null;
190 }
191
192 if ( $contextPage->getNamespace() === NS_SPECIAL ) {
193 $this->logger->debug( "Not adding tracking category $msg to special page!" );
194 return null;
195 }
196
197 // Important to parse with correct title (T33469)
198 // TODO replace uses of wfMessage with an injected service once that is available
199 $cat = wfMessage( $msg )
200 ->page( $contextPage )
201 ->inContentLanguage()
202 ->text();
203
204 # Allow tracking categories to be disabled by setting them to "-"
205 if ( $cat === '-' ) {
206 return null;
207 }
208
209 $containerCategory = $this->titleParser->makeTitleValueSafe( NS_CATEGORY, $cat );
210 if ( $containerCategory === null ) {
211 $this->logger->debug( "[[MediaWiki:$msg]] is not a valid title!" );
212 return null;
213 }
214 return $containerCategory;
215 }
216
234 public function addTrackingCategory(
235 ContentMetadataCollector $parserOutput,
236 string $msg,
237 ?PageReference $contextPage
238 ): bool {
239 $categoryPage = $this->resolveTrackingCategory( $msg, $contextPage );
240 if ( $categoryPage === null ) {
241 return false;
242 }
243 $parserOutput->addCategory( $categoryPage );
244 return true;
245 }
246}
const NS_MEDIAWIKI
Definition Defines.php:59
const NS_SPECIAL
Definition Defines.php:40
const NS_CATEGORY
Definition Defines.php:65
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:68
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()
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition Parser.php:135
Load JSON files, and uses a Processor to extract information.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
A title parser service for MediaWiki.
Represents a title within MediaWiki.
Definition Title.php:69
Represents the target of a wiki link.
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.