Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
110 / 110
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
TOC
100.00% covered (success)
100.00%
110 / 110
100.00% covered (success)
100.00%
4 / 4
18
100.00% covered (success)
100.00%
1 / 1
 write
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
4
 writeTitle
100.00% covered (success)
100.00%
53 / 53
100.00% covered (success)
100.00%
1 / 1
6
 writeStyle
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
7
 writeFieldMark
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * This file is part of PHPWord - A pure PHP library for reading and writing
4 * word processing documents.
5 *
6 * PHPWord is free software distributed under the terms of the GNU Lesser
7 * General Public License version 3 as published by the Free Software Foundation.
8 *
9 * For the full copyright and license information, please read the LICENSE
10 * file that was distributed with this source code. For the full list of
11 * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
12 *
13 * @see         https://github.com/PHPOffice/PHPWord
14 *
15 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16 */
17
18namespace PhpOffice\PhpWord\Writer\Word2007\Element;
19
20use PhpOffice\PhpWord\Element\Title;
21use PhpOffice\PhpWord\Element\TOC as TOCElement;
22use PhpOffice\PhpWord\Shared\XMLWriter;
23use PhpOffice\PhpWord\Style\Font;
24use PhpOffice\PhpWord\Writer\Word2007\Style\Font as FontStyleWriter;
25use PhpOffice\PhpWord\Writer\Word2007\Style\Paragraph as ParagraphStyleWriter;
26use PhpOffice\PhpWord\Writer\Word2007\Style\Tab as TabStyleWriter;
27
28/**
29 * TOC element writer.
30 *
31 * @since 0.10.0
32 */
33class TOC extends AbstractElement
34{
35    /**
36     * Write element.
37     */
38    public function write(): void
39    {
40        $xmlWriter = $this->getXmlWriter();
41        $element = $this->getElement();
42        if (!$element instanceof TOCElement) {
43            return;
44        }
45
46        $titles = $element->getTitles();
47        $writeFieldMark = true;
48
49        foreach ($titles as $title) {
50            $this->writeTitle($xmlWriter, $element, $title, $writeFieldMark);
51            if ($writeFieldMark) {
52                $writeFieldMark = false;
53            }
54        }
55
56        $xmlWriter->startElement('w:p');
57        $xmlWriter->startElement('w:r');
58        $xmlWriter->startElement('w:fldChar');
59        $xmlWriter->writeAttribute('w:fldCharType', 'end');
60        $xmlWriter->endElement();
61        $xmlWriter->endElement();
62        $xmlWriter->endElement();
63    }
64
65    /**
66     * Write title.
67     */
68    private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, Title $title, bool $writeFieldMark): void
69    {
70        $tocStyle = $element->getStyleTOC();
71        $fontStyle = $element->getStyleFont();
72        $isObject = ($fontStyle instanceof Font) ? true : false;
73        $rId = $title->getRelationId();
74        $indent = (int) (($title->getDepth() - 1) * $tocStyle->getIndent());
75
76        $xmlWriter->startElement('w:p');
77
78        // Write style and field mark
79        $this->writeStyle($xmlWriter, $element, $indent);
80        if ($writeFieldMark) {
81            $this->writeFieldMark($xmlWriter, $element);
82        }
83
84        // Hyperlink
85        $xmlWriter->startElement('w:hyperlink');
86        $xmlWriter->writeAttribute('w:anchor', "_Toc{$rId}");
87        $xmlWriter->writeAttribute('w:history', '1');
88
89        // Title text
90        $xmlWriter->startElement('w:r');
91        if ($isObject) {
92            $styleWriter = new FontStyleWriter($xmlWriter, $fontStyle);
93            $styleWriter->write();
94        }
95        $xmlWriter->startElement('w:t');
96
97        $titleText = $title->getText();
98        $this->writeText(is_string($titleText) ? $titleText : '');
99
100        $xmlWriter->endElement(); // w:t
101        $xmlWriter->endElement(); // w:r
102
103        $xmlWriter->startElement('w:r');
104        $xmlWriter->writeElement('w:tab', null);
105        $xmlWriter->endElement();
106
107        $xmlWriter->startElement('w:r');
108        $xmlWriter->startElement('w:fldChar');
109        $xmlWriter->writeAttribute('w:fldCharType', 'begin');
110        $xmlWriter->endElement();
111        $xmlWriter->endElement();
112
113        $xmlWriter->startElement('w:r');
114        $xmlWriter->startElement('w:instrText');
115        $xmlWriter->writeAttribute('xml:space', 'preserve');
116        $xmlWriter->text("PAGEREF _Toc{$rId} \\h");
117        $xmlWriter->endElement();
118        $xmlWriter->endElement();
119
120        if ($title->getPageNumber() !== null) {
121            $xmlWriter->startElement('w:r');
122            $xmlWriter->startElement('w:fldChar');
123            $xmlWriter->writeAttribute('w:fldCharType', 'separate');
124            $xmlWriter->endElement();
125            $xmlWriter->endElement();
126
127            $xmlWriter->startElement('w:r');
128            $xmlWriter->startElement('w:t');
129            $xmlWriter->text((string) $title->getPageNumber());
130            $xmlWriter->endElement();
131            $xmlWriter->endElement();
132        }
133
134        $xmlWriter->startElement('w:r');
135        $xmlWriter->startElement('w:fldChar');
136        $xmlWriter->writeAttribute('w:fldCharType', 'end');
137        $xmlWriter->endElement();
138        $xmlWriter->endElement();
139
140        $xmlWriter->endElement(); // w:hyperlink
141
142        $xmlWriter->endElement(); // w:p
143    }
144
145    /**
146     * Write style.
147     */
148    private function writeStyle(XMLWriter $xmlWriter, TOCElement $element, int $indent): void
149    {
150        $tocStyle = $element->getStyleTOC();
151        $fontStyle = $element->getStyleFont();
152        $isObject = ($fontStyle instanceof Font) ? true : false;
153
154        $xmlWriter->startElement('w:pPr');
155
156        // Paragraph
157        if ($isObject && null !== $fontStyle->getParagraph()) {
158            $styleWriter = new ParagraphStyleWriter($xmlWriter, $fontStyle->getParagraph());
159            $styleWriter->write();
160        }
161
162        // Font
163        if (!empty($fontStyle) && !$isObject) {
164            $xmlWriter->startElement('w:rPr');
165            $xmlWriter->startElement('w:rStyle');
166            $xmlWriter->writeAttribute('w:val', $fontStyle);
167            $xmlWriter->endElement();
168            $xmlWriter->endElement(); // w:rPr
169        }
170
171        // Tab
172        $xmlWriter->startElement('w:tabs');
173        $styleWriter = new TabStyleWriter($xmlWriter, $tocStyle);
174        $styleWriter->write();
175        $xmlWriter->endElement();
176
177        // Indent
178        if ($indent > 0) {
179            $xmlWriter->startElement('w:ind');
180            $xmlWriter->writeAttribute('w:left', $indent);
181            $xmlWriter->endElement();
182        }
183
184        $xmlWriter->endElement(); // w:pPr
185    }
186
187    /**
188     * Write TOC Field.
189     */
190    private function writeFieldMark(XMLWriter $xmlWriter, TOCElement $element): void
191    {
192        $minDepth = $element->getMinDepth();
193        $maxDepth = $element->getMaxDepth();
194
195        $xmlWriter->startElement('w:r');
196        $xmlWriter->startElement('w:fldChar');
197        $xmlWriter->writeAttribute('w:fldCharType', 'begin');
198        $xmlWriter->endElement();
199        $xmlWriter->endElement();
200
201        $xmlWriter->startElement('w:r');
202        $xmlWriter->startElement('w:instrText');
203        $xmlWriter->writeAttribute('xml:space', 'preserve');
204        $xmlWriter->text("TOC \\o {$minDepth}-{$maxDepth} \\h \\z \\u");
205        $xmlWriter->endElement();
206        $xmlWriter->endElement();
207
208        $xmlWriter->startElement('w:r');
209        $xmlWriter->startElement('w:fldChar');
210        $xmlWriter->writeAttribute('w:fldCharType', 'separate');
211        $xmlWriter->endElement();
212        $xmlWriter->endElement();
213    }
214}