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
41 private const CORE_TRACKING_CATEGORIES = [
42 'broken-file-category',
43 'duplicate-args-category',
44 'expansion-depth-exceeded-category',
45 'expensive-parserfunction-category',
46 'hidden-category-category',
47 'index-category',
48 'node-count-exceeded-category',
49 'noindex-category',
50 'nonnumeric-formatnum',
51 'post-expand-template-argument-category',
52 'post-expand-template-inclusion-category',
53 'restricted-displaytitle-ignored',
54 # template-equals-category is unused in MW>=1.39, but the category
55 # can be left around for a major release or so for an easier
56 # transition for anyone who didn't do the cleanup. T91154
57 'template-equals-category',
58 'template-loop-category',
59 'unstrip-depth-category',
60 'unstrip-size-category',
61 'bad-language-code-category',
62 'bad-double-underscore-category',
63 'double-px-category',
64 # Emitted in Parsoid
65 'media-limit-reached',
66 ];
67
68 public function __construct(
69 private readonly ServiceOptions $options,
70 private readonly ExtensionRegistry $extensionRegistry,
71 private readonly NamespaceInfo $namespaceInfo,
72 private readonly TitleParser $titleParser,
73 private readonly LoggerInterface $logger,
74 ) {
75 $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
76 }
77
88 public function getTrackingCategories() {
89 $categories = array_merge(
90 self::CORE_TRACKING_CATEGORIES,
91 $this->extensionRegistry->getAttribute( MainConfigNames::TrackingCategories ),
92 $this->options->get( MainConfigNames::TrackingCategories ) // deprecated
93 );
94
95 // Only show magic link tracking categories if they are enabled
96 $enableMagicLinks = $this->options->get( MainConfigNames::EnableMagicLinks );
97 if ( $enableMagicLinks['ISBN'] ) {
98 $categories[] = 'magiclink-tracking-isbn';
99 }
100 if ( $enableMagicLinks['RFC'] ) {
101 $categories[] = 'magiclink-tracking-rfc';
102 }
103 if ( $enableMagicLinks['PMID'] ) {
104 $categories[] = 'magiclink-tracking-pmid';
105 }
106
107 $trackingCategories = [];
108 foreach ( $categories as $catMsg ) {
109 /*
110 * Check if the tracking category varies by namespace
111 * Otherwise only pages in the current namespace will be displayed
112 * If it does vary, show pages considering all namespaces
113 *
114 * TODO replace uses of wfMessage with an injected service once that is available
115 */
116 $msgObj = wfMessage( $catMsg )->inContentLanguage();
117 $allCats = [];
118 $catMsgTitle = $this->titleParser->makeTitleValueSafe( NS_MEDIAWIKI, $catMsg );
119 if ( !$catMsgTitle ) {
120 continue;
121 }
122
123 // Match things like {{NAMESPACE}} and {{NAMESPACENUMBER}}.
124 // False positives are ok, this is just an efficiency shortcut
125 if ( str_contains( $msgObj->plain(), '{{' ) ) {
126 $ns = $this->namespaceInfo->getValidNamespaces();
127 foreach ( $ns as $namesp ) {
128 $tempTitle = $this->titleParser->makeTitleValueSafe( $namesp, $catMsg );
129 if ( !$tempTitle ) {
130 continue;
131 }
132 // XXX: should be a better way to convert a TitleValue
133 // to a PageReference!
134 $tempTitle = Title::newFromLinkTarget( $tempTitle );
135 $allCats[] = $msgObj->page( $tempTitle )->text();
136 }
137 } else {
138 $allCats[] = $msgObj->text();
139 }
140 $titles = [];
141 foreach ( $allCats as $catName ) {
142 // Extra check in case a message does fancy stuff with {{#if:… and such
143 if ( $catName !== '-' ) {
144 $catTitle = $this->titleParser->makeTitleValueSafe( NS_CATEGORY, $catName );
145 if ( $catTitle ) {
146 $titles[] = $catTitle;
147 }
148 }
149 }
150 $trackingCategories[$catMsg] = [
151 'cats' => $titles,
152 'msg' => $catMsgTitle,
153 ];
154 }
155
156 return $trackingCategories;
157 }
158
167 public function resolveTrackingCategory( string $msg, ?PageReference $contextPage ): ?LinkTarget {
168 if ( !$contextPage ) {
169 $this->logger->debug( "Not adding tracking category $msg to missing page!" );
170 return null;
171 }
172
173 if ( $contextPage->getNamespace() === NS_SPECIAL ) {
174 $this->logger->debug( "Not adding tracking category $msg to special page!" );
175 return null;
176 }
177
178 // Important to parse with correct title (T33469)
179 // TODO replace uses of wfMessage with an injected service once that is available
180 $cat = wfMessage( $msg )
181 ->page( $contextPage )
182 ->inContentLanguage()
183 ->text();
184
185 # Allow tracking categories to be disabled by setting them to "-"
186 if ( $cat === '-' ) {
187 return null;
188 }
189
190 $containerCategory = $this->titleParser->makeTitleValueSafe( NS_CATEGORY, $cat );
191 if ( $containerCategory === null ) {
192 $this->logger->debug( "[[MediaWiki:$msg]] is not a valid title!" );
193 return null;
194 }
195 return $containerCategory;
196 }
197
215 public function addTrackingCategory(
216 ContentMetadataCollector $parserOutput,
217 string $msg,
218 ?PageReference $contextPage
219 ): bool {
220 $categoryPage = $this->resolveTrackingCategory( $msg, $contextPage );
221 if ( $categoryPage === null ) {
222 return false;
223 }
224 $parserOutput->addCategory( $categoryPage );
225 return true;
226 }
227}
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:71
This class performs some operations related to tracking categories, such as adding a tracking categor...
A class for passing options to services.
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:138
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.