aboutsummaryrefslogtreecommitdiffstats
path: root/includes/skins/components/SkinComponentTableOfContents.php
blob: 143f3d604990e3b62a2b4f8da15a6571954e7523 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<?php
/**
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 */

namespace MediaWiki\Skin;

use MediaWiki\Output\OutputPage;
use MediaWiki\Parser\ParserOutputFlags;

/**
 * @internal for use inside Skin and SkinTemplate classes only
 * @unstable
 */
class SkinComponentTableOfContents implements SkinComponent {
	/** @var OutputPage */
	private $output;

	public function __construct( OutputPage $output ) {
		$this->output = $output;
	}

	/**
	 * Nests child sections within their parent sections.
	 *
	 * @param array $sections
	 * @param int $toclevel
	 * @return array
	 */
	private function getSectionsDataInternal( array $sections, int $toclevel = 1 ): array {
		$data = [];
		foreach ( $sections as $i => $section ) {
			// Child section belongs to a higher parent.
			if ( $section->tocLevel < $toclevel ) {
				return $data;
			}

			// Set all the parent sections at the current top level.
			if ( $section->tocLevel === $toclevel ) {
				$childSections = $this->getSectionsDataInternal(
					array_slice( $sections, $i + 1 ),
					$toclevel + 1
				);
				$data[] = $section->toLegacy() + [
					'array-sections' => $childSections,
					'is-top-level-section' => $toclevel === 1,
					'is-parent-section' => $childSections !== []
				];
			}
		}
		return $data;
	}

	/**
	 * Get table of contents template data
	 *
	 * Enriches section data by nesting child elements within parent elements
	 * such that the table of contents can be rendered in Mustache.
	 *
	 * For an example of how to render the data, see TableOfContents.mustache in
	 * the Vector skin.
	 */
	private function getTOCDataInternal(): array {
		$tocData = $this->output->getTOCData();
		// Return data only if TOC present T298796.
		if ( $tocData === null ) {
			return [];
		}
		// Respect __NOTOC__
		if ( $this->output->getOutputFlag( ParserOutputFlags::NO_TOC ) ) {
			return [];
		}

		$outputSections = $tocData->getSections();

		return count( $outputSections ) > 0 ? [
			'number-section-count' => count( $outputSections ),
			'array-sections' => $this->getSectionsDataInternal( $outputSections, 1 ),
		] : [];
	}

	/**
	 * @inheritDoc
	 */
	public function getTemplateData(): array {
		return $this->getTOCDataInternal();
	}
}