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',
48 'node-count-exceeded-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',
65 'media-limit-reached',
68 public function __construct(
73 private readonly LoggerInterface $logger,
75 $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
88 public function getTrackingCategories() {
89 $categories = array_merge(
90 self::CORE_TRACKING_CATEGORIES,
97 if ( $enableMagicLinks[
'ISBN'] ) {
98 $categories[] =
'magiclink-tracking-isbn';
100 if ( $enableMagicLinks[
'RFC'] ) {
101 $categories[] =
'magiclink-tracking-rfc';
103 if ( $enableMagicLinks[
'PMID'] ) {
104 $categories[] =
'magiclink-tracking-pmid';
107 $trackingCategories = [];
108 foreach ( $categories as $catMsg ) {
116 $msgObj =
wfMessage( $catMsg )->inContentLanguage();
118 $catMsgTitle = $this->titleParser->makeTitleValueSafe(
NS_MEDIAWIKI, $catMsg );
119 if ( !$catMsgTitle ) {
125 if ( str_contains( $msgObj->plain(),
'{{' ) ) {
126 $ns = $this->namespaceInfo->getValidNamespaces();
127 foreach ( $ns as $namesp ) {
128 $tempTitle = $this->titleParser->makeTitleValueSafe( $namesp, $catMsg );
134 $tempTitle = Title::newFromLinkTarget( $tempTitle );
135 $allCats[] = $msgObj->page( $tempTitle )->text();
138 $allCats[] = $msgObj->text();
141 foreach ( $allCats as $catName ) {
143 if ( $catName !==
'-' ) {
144 $catTitle = $this->titleParser->makeTitleValueSafe(
NS_CATEGORY, $catName );
146 $titles[] = $catTitle;
150 $trackingCategories[$catMsg] = [
152 'msg' => $catMsgTitle,
156 return $trackingCategories;
167 public function resolveTrackingCategory(
string $msg, ?PageReference $contextPage ): ?LinkTarget {
168 if ( !$contextPage ) {
169 $this->logger->debug(
"Not adding tracking category $msg to missing page!" );
173 if ( $contextPage->getNamespace() ===
NS_SPECIAL ) {
174 $this->logger->debug(
"Not adding tracking category $msg to special page!" );
181 ->page( $contextPage )
182 ->inContentLanguage()
185 # Allow tracking categories to be disabled by setting them to "-"
186 if ( $cat ===
'-' ) {
190 $containerCategory = $this->titleParser->makeTitleValueSafe(
NS_CATEGORY, $cat );
191 if ( $containerCategory ===
null ) {
192 $this->logger->debug(
"[[MediaWiki:$msg]] is not a valid title!" );
195 return $containerCategory;
215 public function addTrackingCategory(
216 ContentMetadataCollector $parserOutput,
218 ?PageReference $contextPage
220 $categoryPage = $this->resolveTrackingCategory( $msg, $contextPage );
221 if ( $categoryPage ===
null ) {
224 $parserOutput->addCategory( $categoryPage );