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