Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
TocGeneratorTrait
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 3
20
0.00% covered (danger)
0.00%
0 / 1
 getTocData
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 addTocSection
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
2
 addTocSubSection
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
2
 getContext
n/a
0 / 0
n/a
0 / 0
0
1<?php
2
3namespace MediaWiki\Html;
4
5use MediaWiki\Context\IContextSource;
6use MediaWiki\Parser\Sanitizer;
7use Wikimedia\Message\MessageParam;
8use Wikimedia\Message\MessageSpecifier;
9use Wikimedia\Parsoid\Core\SectionMetadata;
10use Wikimedia\Parsoid\Core\TOCData;
11
12/**
13 * Trait for special pages that generate a Table of Contents.
14 *
15 * It is expected that the class using this trait inherits from
16 * ContextSource, which will provide the abstract ::getContext()
17 * method.  Another source of context can be provided by
18 * re-implementing ::getContext().
19 *
20 * @since 1.45
21 */
22trait TocGeneratorTrait {
23    private ?TOCData $tocData = null;
24    private int $tocIndex = 0;
25    private int $tocSection = 0;
26    private int $tocSubSection = 0;
27
28    protected function getTocData(): TOCData {
29        if ( $this->tocData === null ) {
30            $this->tocData = new TOCData();
31        }
32        return $this->tocData;
33    }
34
35    /**
36     * Add a section to the table of contents. This doesn't add the
37     * heading to the actual page.
38     *
39     * @param string $id "True" value of the ID attribute for the section,
40     *  not HTML-entity escaped.
41     * @param string $msg Message key to use for the label
42     * @phpcs:ignore Generic.Files.LineLength
43     * @param MessageParam|MessageSpecifier|string|int|float|list<MessageParam|MessageSpecifier|string|int|float> ...$params
44     *   See Message::params()
45     */
46    protected function addTocSection( string $id, string $msg, ...$params ): void {
47        $context = $this->getContext();
48        $this->tocIndex++;
49        $this->tocSection++;
50        $this->tocSubSection = 0;
51        $this->getTocData()->addSection( new SectionMetadata(
52            tocLevel: 1,
53            hLevel: 2,
54            line: $context->msg( $msg, ...$params )->escaped(),
55            number: $context->getLanguage()->formatNum( $this->tocSection ),
56            index: (string)$this->tocIndex,
57            anchor: $id,
58            linkAnchor: Sanitizer::escapeIdForLink( $id ),
59        ) );
60    }
61
62    /**
63     * Add a sub-section to the table of contents. This doesn't add the
64     * heading to the actual page.
65     *
66     * @param string $id "True" value of the ID attribute for the section,
67     *  not HTML-entity escaped.
68     * @param string $msg Message key to use for the label
69     * @phpcs:ignore Generic.Files.LineLength
70     * @param MessageParam|MessageSpecifier|string|int|float|list<MessageParam|MessageSpecifier|string|int|float> ...$params
71     *   See Message::params()
72     */
73    protected function addTocSubSection( string $id, string $msg, ...$params ): void {
74        $context = $this->getContext();
75        $this->tocIndex++;
76        $this->tocSubSection++;
77        $this->getTocData()->addSection( new SectionMetadata(
78            tocLevel: 2,
79            hLevel: 3,
80            line: $context->msg( $msg, ...$params )->escaped(),
81            // See Parser::localizeTOC
82            number: $context->getLanguage()->formatNum( $this->tocSection ) . '.' .
83                $context->getLanguage()->formatNum( $this->tocSubSection ),
84            index: (string)$this->tocIndex,
85            anchor: $id,
86            linkAnchor: Sanitizer::escapeIdForLink( $id ),
87        ) );
88    }
89
90    /**
91     * Returns the base IContextSource to use for this trait.
92     * @note If the using class inherits from ContextSource this
93     * method will be provided by ContextSource::getContext().
94     * @return IContextSource
95     */
96    abstract public function getContext();
97}