MediaWiki REL1_39
TrackingCategories.php
Go to the documentation of this file.
1<?php
26use Psr\Log\LoggerInterface;
27
34
38 public const CONSTRUCTOR_OPTIONS = [
39 MainConfigNames::TrackingCategories,
40 MainConfigNames::EnableMagicLinks,
41 ];
42
44 private $options;
45
47 private $namespaceInfo;
48
50 private $titleParser;
51
53 private $extensionRegistry;
54
56 private $logger;
57
63 private const CORE_TRACKING_CATEGORIES = [
64 'broken-file-category',
65 'duplicate-args-category',
66 'expansion-depth-exceeded-category',
67 'expensive-parserfunction-category',
68 'hidden-category-category',
69 'index-category',
70 'node-count-exceeded-category',
71 'noindex-category',
72 'nonnumeric-formatnum',
73 'post-expand-template-argument-category',
74 'post-expand-template-inclusion-category',
75 'restricted-displaytitle-ignored',
76 # template-equals-category is unused in MW>=1.39, but the category
77 # can be left around for a major release or so for an easier
78 # transition for anyone who didn't do the cleanup. T91154
79 'template-equals-category',
80 'template-loop-category',
81 'unstrip-depth-category',
82 'unstrip-size-category',
83 'bad-double-underscore-category',
84 ];
85
92 public function __construct(
93 ServiceOptions $options,
94 NamespaceInfo $namespaceInfo,
95 TitleParser $titleParser,
96 LoggerInterface $logger
97 ) {
98 $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
99 $this->options = $options;
100 $this->namespaceInfo = $namespaceInfo;
101 $this->titleParser = $titleParser;
102 $this->logger = $logger;
103
104 // TODO convert ExtensionRegistry to a service and inject it
105 $this->extensionRegistry = ExtensionRegistry::getInstance();
106 }
107
118 public function getTrackingCategories() {
119 $categories = array_merge(
120 self::CORE_TRACKING_CATEGORIES,
121 $this->extensionRegistry->getAttribute( MainConfigNames::TrackingCategories ),
122 $this->options->get( MainConfigNames::TrackingCategories ) // deprecated
123 );
124
125 // Only show magic link tracking categories if they are enabled
126 $enableMagicLinks = $this->options->get( MainConfigNames::EnableMagicLinks );
127 if ( $enableMagicLinks['ISBN'] ) {
128 $categories[] = 'magiclink-tracking-isbn';
129 }
130 if ( $enableMagicLinks['RFC'] ) {
131 $categories[] = 'magiclink-tracking-rfc';
132 }
133 if ( $enableMagicLinks['PMID'] ) {
134 $categories[] = 'magiclink-tracking-pmid';
135 }
136
137 $trackingCategories = [];
138 foreach ( $categories as $catMsg ) {
139 /*
140 * Check if the tracking category varies by namespace
141 * Otherwise only pages in the current namespace will be displayed
142 * If it does vary, show pages considering all namespaces
143 *
144 * TODO replace uses of wfMessage with an injected service once that is available
145 */
146 $msgObj = wfMessage( $catMsg )->inContentLanguage();
147 $allCats = [];
148 $catMsgTitle = $this->titleParser->makeTitleValueSafe( NS_MEDIAWIKI, $catMsg );
149 if ( !$catMsgTitle ) {
150 continue;
151 }
152
153 // Match things like {{NAMESPACE}} and {{NAMESPACENUMBER}}.
154 // False positives are ok, this is just an efficiency shortcut
155 if ( strpos( $msgObj->plain(), '{{' ) !== false ) {
156 $ns = $this->namespaceInfo->getValidNamespaces();
157 foreach ( $ns as $namesp ) {
158 $tempTitle = $this->titleParser->makeTitleValueSafe( $namesp, $catMsg );
159 if ( !$tempTitle ) {
160 continue;
161 }
162 // XXX: should be a better way to convert a TitleValue
163 // to a PageReference!
164 $tempTitle = Title::newFromLinkTarget( $tempTitle );
165 $catName = $msgObj->page( $tempTitle )->text();
166 # Allow tracking categories to be disabled by setting them to "-"
167 if ( $catName !== '-' ) {
168 $catTitle = $this->titleParser->makeTitleValueSafe( NS_CATEGORY, $catName );
169 if ( $catTitle ) {
170 $allCats[] = $catTitle;
171 }
172 }
173 }
174 } else {
175 $catName = $msgObj->text();
176 # Allow tracking categories to be disabled by setting them to "-"
177 if ( $catName !== '-' ) {
178 $catTitle = $this->titleParser->makeTitleValueSafe( NS_CATEGORY, $catName );
179 if ( $catTitle ) {
180 $allCats[] = $catTitle;
181 }
182 }
183 }
184 $trackingCategories[$catMsg] = [
185 'cats' => $allCats,
186 'msg' => $catMsgTitle,
187 ];
188 }
189
190 return $trackingCategories;
191 }
192
201 public function resolveTrackingCategory( string $msg, ?PageReference $contextPage ): ?LinkTarget {
202 if ( !$contextPage ) {
203 $this->logger->debug( "Not adding tracking category $msg to missing page!" );
204 return null;
205 }
206
207 if ( $contextPage->getNamespace() === NS_SPECIAL ) {
208 $this->logger->debug( "Not adding tracking category $msg to special page!" );
209 return null;
210 }
211
212 // Important to parse with correct title (T33469)
213 // TODO replace uses of wfMessage with an injected service once that is available
214 $cat = wfMessage( $msg )
215 ->page( $contextPage )
216 ->inContentLanguage()
217 ->text();
218
219 # Allow tracking categories to be disabled by setting them to "-"
220 if ( $cat === '-' ) {
221 return null;
222 }
223
224 $containerCategory = $this->titleParser->makeTitleValueSafe( NS_CATEGORY, $cat );
225 if ( $containerCategory === null ) {
226 $this->logger->debug( "[[MediaWiki:$msg]] is not a valid title!" );
227 return null;
228 }
229 return $containerCategory;
230 }
231
240 public function addTrackingCategory( ParserOutput $parserOutput, string $msg, ?PageReference $contextPage ): bool {
241 $categoryPage = $this->resolveTrackingCategory( $msg, $contextPage );
242 if ( $categoryPage === null ) {
243 return false;
244 }
245 $parserOutput->addCategory(
246 $categoryPage->getDBkey(),
247 $parserOutput->getPageProperty( 'defaultsort' ) ?? ''
248 );
249 return true;
250 }
251}
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'))
The persistent session ID (if any) loaded at startup.
Definition WebStart.php:82
The Registry loads JSON files, and uses a Processor to extract information from them.
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.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
getPageProperty(string $name)
Look up a page property.
addCategory( $c, $sort='')
Add a category.
This class performs some operations related to tracking categories, such as creating a list of all su...
addTrackingCategory(ParserOutput $parserOutput, string $msg, ?PageReference $contextPage)
Add a tracking category to a ParserOutput.
__construct(ServiceOptions $options, NamespaceInfo $namespaceInfo, TitleParser $titleParser, LoggerInterface $logger)
getTrackingCategories()
Read the global and extract title objects from the corresponding messages.
resolveTrackingCategory(string $msg, ?PageReference $contextPage)
Resolve a tracking category.
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.
getNamespace()
Returns the page's namespace number.
A title parser service for MediaWiki.