1<?php
2
3/**
4 * DokuWiki Plugin Numbered Headings: add tiered numbers for hierarchical headings
5 *
6 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @author     Lars J. Metz <dokuwiki@meistermetz.de>
8 * @author     Satoshi Sahara <sahara.satoshi@gmail.com>
9 *
10 * Config settings
11 *     tier1  : heading level corresponding to the 1st tier
12 *     format : numbering format (used in vsprintf) of each tier, JSON array string
13 */
14class helper_plugin_numberedheadings extends DokuWiki_Plugin
15{
16    protected $Tier1Level;   // (int)   heading level corresponding to the 1st tier
17    protected $TierFormat;   // (array) numbering format of each tier
18    protected $HeadingCount; // (array) heading counter
19
20    protected function initHeadingCounter()
21    {
22        $this->HeadingCount = [ 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0 ];
23    }
24
25    /**
26     * Set the first tier level
27     */
28    public function setTier1($level=null)
29    {
30        $this->Tier1Level = $level;
31        return;
32    }
33
34    /**
35     * Get the first tier level
36     */
37    public function getTier1()
38    {
39        return $this->Tier1Level;
40    }
41
42    /**
43     * Set or initialise the numbering format of each tier
44     *
45     * usage: setTierFormat('["Chapter %d."]', 1);
46     */
47    public function setTierFormat($format=null, $tier=null)
48    {
49        if (empty($format)) {
50            $format = $this->getConf('format');  // JSON array string
51        }
52        $TierFormat = json_decode($format, true);
53        if ($TierFormat === null) $TierFormat = [];
54        if ($tier === null) {
55            // initialise numbering format (tier 1 to 5) using config parameter
56            // re-index array from 1, instead of 0
57            array_unshift($TierFormat, '');
58            unset($TierFormat[0]);
59            $this->TierFormat = $TierFormat;
60        } else {
61            // set numbering format of the specified tier and sub-tires
62            foreach ($TierFormat as $k => $value) {
63                $this->TierFormat[$tier + $k] = $value;
64            }
65        }
66        return;
67    }
68
69    /**
70     * Set or initialise the internal heading counter
71     */
72    public function setHeadingCounter($level=null, $number=null)
73    {
74        if (isset($level)) {
75            // prepare the internal heading counter
76            if (!$this->HeadingCount) {
77                $this->initHeadingCounter();
78            }
79            if ($number === '') $number = null;
80            $this->HeadingCount[$level] = isset($number)
81                ? $number
82                : ++$this->HeadingCount[$level];
83            // reset the number of the subheadings
84            for ($i = $level +1; $i <= 5; $i++) {
85                $this->HeadingCount[$i] = 0;
86            }
87        } else {
88            $this->initHeadingCounter();
89        }
90        return;
91    }
92
93    /**
94     * Build tiered numbers
95     */
96    public function getTieredNumbers($level, $offset=null)
97    {
98        if (!$this->TierFormat) {
99            $this->setTierFormat($this->getConf('format'));
100        }
101
102        if (!isset($offset)) {
103            $offset = max(0, $this->Tier1Level -1);
104        }
105        if (isset($level) && $offset < $level) {
106            $tier = $level - $offset;
107            $numbers = array_slice($this->HeadingCount, $offset, $tier);
108            if (isset($this->TierFormat[$tier])) {
109                $tieredNumbers = vsprintf($this->TierFormat[$tier], $numbers);
110            } else {
111                $tieredNumbers = implode('.', $numbers);
112            }
113        } else {
114            $tieredNumbers = '';
115        }
116        return $tieredNumbers;
117    }
118
119}
120