1<?php
2
3namespace dokuwiki\plugin\wordimport\docx;
4
5/**
6 * Numbering information
7 */
8class Numbering extends AbstractXMLFile
9{
10    /** @var array the numbering information numID -> level -> type */
11    protected $numbering = [];
12
13    /**
14     * The files defines "abstract numbers" first. They define a set of rules for each indentation level of a list.
15     * Then the actual numbers are defined. They reference one of the abstract numbers. List items reference one of the
16     * actual numbers.
17     *
18     * @inheritdoc
19     */
20    protected function parse()
21    {
22        $xml = $this->docx->loadXMLFile($this->docx->getRelationships()->getTarget('numbering'));
23        $this->registerNamespaces($xml);
24
25        $types = [];
26        foreach ($xml->xpath('//w:abstractNum') as $num) {
27            $id = (int)$num->attributes('w', true)->abstractNumId;
28            $types[$id] = [];
29
30            foreach ($num->xpath('.//w:lvl') as $lvl) {
31                $depth = (int)$lvl->attributes('w', true)->ilvl;
32                $lvlType = (string)$lvl->xpath('.//w:numFmt')[0]->attributes('w', true)->val;
33                $lvlType = ($lvlType === 'decimal') ? 'ordered' : 'unordered';
34
35                $types[$id][$depth] = $lvlType;
36            }
37        }
38
39        foreach ($xml->xpath('//w:num') as $num) {
40            $id = (int)$num->attributes('w', true)->numId;
41            $typeId = (int)$num->xpath('.//w:abstractNumId')[0]->attributes('w', true)->val;
42            if (isset($types[$typeId])) {
43                $this->numbering[$id] = $types[$typeId];
44            }
45        }
46    }
47
48    /**
49     * Get the type of the numbering for the given ID and depth
50     *
51     * @param string $id
52     * @param int $depth the depth of the list starting at 0
53     * @return string 'ordered' or 'unordered'
54     */
55    public function getType($id, int $depth): string
56    {
57        return $this->numbering[$id][$depth] ?? 'unordered';
58    }
59}
60