Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
75 / 75
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
Paragraph
100.00% covered (success)
100.00%
75 / 75
100.00% covered (success)
100.00%
7 / 7
24
100.00% covered (success)
100.00%
1 / 1
 write
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
6
 writeStyle
100.00% covered (success)
100.00%
39 / 39
100.00% covered (success)
100.00%
1 / 1
8
 writeTabs
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 writeNumbering
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
4
 setOutlineLevel
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setWithoutPPR
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setIsInline
100.00% covered (success)
100.00%
1 / 1
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\Style;
20
21use PhpOffice\PhpWord\Shared\XMLWriter;
22use PhpOffice\PhpWord\Style;
23use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle;
24use PhpOffice\PhpWord\Writer\Word2007\Element\ParagraphAlignment;
25
26/**
27 * Paragraph style writer.
28 *
29 * @since 0.10.0
30 */
31class Paragraph extends AbstractStyle
32{
33    /**
34     * Without w:pPr.
35     *
36     * @var bool
37     */
38    private $withoutPPR = false;
39
40    /**
41     * Is inline in element.
42     *
43     * @var bool
44     */
45    private $isInline = false;
46
47    /**
48     * Outline level of a heading style, written as w:outlineLvl.
49     *
50     * @var null|int
51     */
52    private $outlineLevel;
53
54    /**
55     * Write style.
56     */
57    public function write(): void
58    {
59        $xmlWriter = $this->getXmlWriter();
60
61        $isStyleName = $this->isInline && null !== $this->style && is_string($this->style);
62        if ($isStyleName) {
63            if (!$this->withoutPPR) {
64                $xmlWriter->startElement('w:pPr');
65            }
66            $xmlWriter->startElement('w:pStyle');
67            $xmlWriter->writeAttribute('w:val', $this->style);
68            $xmlWriter->endElement();
69            if (!$this->withoutPPR) {
70                $xmlWriter->endElement();
71            }
72        } else {
73            $this->writeStyle();
74        }
75    }
76
77    /**
78     * Write full style.
79     */
80    private function writeStyle(): void
81    {
82        $style = $this->getStyle();
83        if (!$style instanceof ParagraphStyle) {
84            return;
85        }
86        $xmlWriter = $this->getXmlWriter();
87        $styles = $style->getStyleValues();
88
89        if (!$this->withoutPPR) {
90            $xmlWriter->startElement('w:pPr');
91        }
92
93        // Style name
94        if ($this->isInline === true) {
95            $xmlWriter->writeElementIf($styles['name'] !== null, 'w:pStyle', 'w:val', $styles['name']);
96        }
97
98        // Pagination
99        $xmlWriter->writeElementIf($styles['pagination']['widowControl'] === false, 'w:widowControl', 'w:val', '0');
100        $xmlWriter->writeElementIf($styles['pagination']['keepNext'] === true, 'w:keepNext', 'w:val', '1');
101        $xmlWriter->writeElementIf($styles['pagination']['keepLines'] === true, 'w:keepLines', 'w:val', '1');
102        $xmlWriter->writeElementIf($styles['pagination']['pageBreak'] === true, 'w:pageBreakBefore', 'w:val', '1');
103
104        // Paragraph alignment
105        if ('' !== $styles['alignment']) {
106            $paragraphAlignment = new ParagraphAlignment($styles['alignment']);
107            $xmlWriter->startElement($paragraphAlignment->getName());
108            foreach ($paragraphAlignment->getAttributes() as $attributeName => $attributeValue) {
109                $xmlWriter->writeAttribute($attributeName, $attributeValue);
110            }
111            $xmlWriter->endElement();
112        }
113
114        //Right to left
115        $xmlWriter->writeElementIf($styles['bidi'] === true, 'w:bidi');
116
117        //Paragraph contextualSpacing
118        $xmlWriter->writeElementIf($styles['contextualSpacing'] === true, 'w:contextualSpacing');
119
120        //Paragraph textAlignment
121        $xmlWriter->writeElementIf($styles['textAlignment'] !== null, 'w:textAlignment', 'w:val', $styles['textAlignment']);
122
123        // Hyphenation
124        $xmlWriter->writeElementIf($styles['suppressAutoHyphens'] === true, 'w:suppressAutoHyphens');
125
126        // Child style: alignment, indentation, spacing, and shading
127        $this->writeChildStyle($xmlWriter, 'Indentation', $styles['indentation']);
128        $this->writeChildStyle($xmlWriter, 'Spacing', $styles['spacing']);
129        $this->writeChildStyle($xmlWriter, 'Shading', $styles['shading']);
130
131        // Tabs
132        $this->writeTabs($xmlWriter, $styles['tabs']);
133
134        // Numbering
135        $this->writeNumbering($xmlWriter, $styles['numbering']);
136
137        // Border
138        if ($style->hasBorder()) {
139            $xmlWriter->startElement('w:pBdr');
140
141            $styleWriter = new MarginBorder($xmlWriter);
142            $styleWriter->setSizes($style->getBorderSize());
143            $styleWriter->setStyles($style->getBorderStyle());
144            $styleWriter->setColors($style->getBorderColor());
145            $styleWriter->write();
146
147            $xmlWriter->endElement();
148        }
149
150        // Outline level
151        $xmlWriter->writeElementIf($this->outlineLevel !== null, 'w:outlineLvl', 'w:val', $this->outlineLevel);
152
153        if (!$this->withoutPPR) {
154            $xmlWriter->endElement(); // w:pPr
155        }
156    }
157
158    /**
159     * Write tabs.
160     *
161     * @param Style\Tab[] $tabs
162     */
163    private function writeTabs(XMLWriter $xmlWriter, $tabs): void
164    {
165        if (!empty($tabs)) {
166            $xmlWriter->startElement('w:tabs');
167            foreach ($tabs as $tab) {
168                $styleWriter = new Tab($xmlWriter, $tab);
169                $styleWriter->write();
170            }
171            $xmlWriter->endElement();
172        }
173    }
174
175    /**
176     * Write numbering.
177     *
178     * @param array $numbering
179     */
180    private function writeNumbering(XMLWriter $xmlWriter, $numbering): void
181    {
182        $numStyle = $numbering['style'];
183        $numLevel = $numbering['level'];
184
185        /** @var Style\Numbering $numbering */
186        $numbering = Style::getStyle($numStyle);
187        if ($numStyle !== null && $numbering !== null) {
188            $xmlWriter->startElement('w:numPr');
189            $xmlWriter->startElement('w:numId');
190            $xmlWriter->writeAttribute('w:val', $numbering->getIndex());
191            $xmlWriter->endElement(); // w:numId
192            $xmlWriter->startElement('w:ilvl');
193            $xmlWriter->writeAttribute('w:val', $numLevel);
194            $xmlWriter->endElement(); // w:ilvl
195            $xmlWriter->endElement(); // w:numPr
196
197            if ($this->outlineLevel === null) {
198                $xmlWriter->startElement('w:outlineLvl');
199                $xmlWriter->writeAttribute('w:val', $numLevel);
200                $xmlWriter->endElement(); // w:outlineLvl
201            }
202        }
203    }
204
205    /**
206     * Set the outline level of a heading style.
207     */
208    public function setOutlineLevel(?int $value): void
209    {
210        $this->outlineLevel = $value;
211    }
212
213    /**
214     * Set without w:pPr.
215     *
216     * @param bool $value
217     */
218    public function setWithoutPPR($value): void
219    {
220        $this->withoutPPR = $value;
221    }
222
223    /**
224     * Set is inline.
225     *
226     * @param bool $value
227     */
228    public function setIsInline($value): void
229    {
230        $this->isInline = $value;
231    }
232}