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