Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
95 / 95
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
Paragraph
100.00% covered (success)
100.00%
95 / 95
100.00% covered (success)
100.00%
1 / 1
30
100.00% covered (success)
100.00%
1 / 1
 write
100.00% covered (success)
100.00%
95 / 95
100.00% covered (success)
100.00%
1 / 1
30
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\ODText\Style;
20
21use PhpOffice\PhpWord\Settings;
22use PhpOffice\PhpWord\Shared\Converter;
23use PhpOffice\PhpWord\SimpleType\Jc;
24use PhpOffice\PhpWord\Style;
25
26/**
27 * Font style writer.
28 *
29 * @since 0.10.0
30 */
31class Paragraph extends AbstractStyle
32{
33    private const BIDI_MAP = [
34        Jc::END => Jc::LEFT,
35        Jc::START => Jc::RIGHT,
36    ];
37
38    private const NON_BIDI_MAP = [
39        Jc::START => Jc::LEFT,
40        Jc::END => Jc::RIGHT,
41    ];
42
43    /**
44     * Write style.
45     */
46    public function write(): void
47    {
48        $style = $this->getStyle();
49        if (!$style instanceof Style\Paragraph) {
50            return;
51        }
52        $xmlWriter = $this->getXmlWriter();
53
54        $marginTop = $style->getSpaceBefore();
55        $marginBottom = $style->getSpaceAfter();
56
57        $xmlWriter->startElement('style:style');
58
59        $styleName = (string) $style->getStyleName();
60        $styleAuto = false;
61        $mpm = '';
62        $psm = '';
63        $pagestart = -1;
64        $breakafter = $breakbefore = $breakauto = false;
65        if ($style->isAuto()) {
66            if (substr($styleName, 0, 2) === 'PB') {
67                $styleAuto = true;
68                $breakafter = true;
69            } elseif (substr($styleName, 0, 2) === 'SB') {
70                $styleAuto = true;
71                $mpm = 'Standard' . substr($styleName, 2);
72                $psn = $style->getNumLevel();
73                $pagestart = $psn;
74            } elseif (substr($styleName, 0, 2) === 'HD') {
75                $styleAuto = true;
76                $psm = 'Heading_' . substr($styleName, 2);
77                $stylep = Style::getStyle($psm);
78                if ($stylep instanceof Style\Font) {
79                    $stylep = $stylep->getParagraph();
80                }
81                if ($stylep instanceof Style\Paragraph) {
82                    if ($stylep->hasPageBreakBefore()) {
83                        $breakbefore = true;
84                    }
85                }
86            } elseif (substr($styleName, 0, 2) === 'HE') {
87                $styleAuto = true;
88                $psm = 'Heading_' . substr($styleName, 2);
89                $breakauto = true;
90            } else {
91                $styleAuto = true;
92                $psm = 'Normal';
93                if (preg_match('/^P\\d+_(\\w+)$/', $styleName, $matches)) {
94                    $psm = $matches[1];
95                }
96            }
97        }
98
99        $xmlWriter->writeAttribute('style:name', $style->getStyleName());
100        $xmlWriter->writeAttribute('style:family', 'paragraph');
101        if ($styleAuto) {
102            $xmlWriter->writeAttributeIf($psm !== '', 'style:parent-style-name', $psm);
103            $xmlWriter->writeAttributeIf($mpm !== '', 'style:master-page-name', $mpm);
104        }
105
106        $xmlWriter->startElement('style:paragraph-properties');
107        if ($styleAuto) {
108            if ($breakafter) {
109                $xmlWriter->writeAttribute('fo:break-after', 'page');
110                $xmlWriter->writeAttribute('fo:margin-top', '0cm');
111                $xmlWriter->writeAttribute('fo:margin-bottom', '0cm');
112            } elseif ($breakbefore) {
113                $xmlWriter->writeAttribute('fo:break-before', 'page');
114            } elseif ($breakauto) {
115                $xmlWriter->writeAttribute('fo:break-before', 'auto');
116            }
117            if ($pagestart > 0) {
118                $xmlWriter->writeAttribute('style:page-number', $pagestart);
119            }
120        }
121        if (!$breakafter && !$breakbefore && !$breakauto) {
122            $twipToPoint = Converter::INCH_TO_TWIP / Converter::INCH_TO_POINT; // 20
123            $xmlWriter->writeAttributeIf($marginTop !== null, 'fo:margin-top', ($marginTop / $twipToPoint) . 'pt');
124            $xmlWriter->writeAttributeIf($marginBottom !== null, 'fo:margin-bottom', ($marginBottom / $twipToPoint) . 'pt');
125        }
126        $alignment = $style->getAlignment();
127        $bidi = $style->isBidi();
128        $defaultRtl = Settings::isDefaultRtl();
129        if ($alignment === '' && $bidi !== null) {
130            $alignment = Jc::START;
131        }
132        if ($bidi) {
133            $alignment = self::BIDI_MAP[$alignment] ?? $alignment;
134        } elseif ($defaultRtl !== null) {
135            $alignment = self::NON_BIDI_MAP[$alignment] ?? $alignment;
136        }
137        $xmlWriter->writeAttributeIf($alignment !== '', 'fo:text-align', $alignment);
138        $temp = $style->getLineHeight();
139        $xmlWriter->writeAttributeIf($temp !== null, 'fo:line-height', ((string) ($temp * 100) . '%'));
140        $xmlWriter->writeAttributeIf($style->hasPageBreakBefore() === true, 'fo:break-before', 'page');
141
142        $tabs = $style->getTabs();
143        if ($tabs !== null && count($tabs) > 0) {
144            $xmlWriter->startElement('style:tab-stops');
145            foreach ($tabs as $tab) {
146                $xmlWriter->startElement('style:tab-stop');
147                $xmlWriter->writeAttribute('style:type', $tab->getType());
148                $xmlWriter->writeAttribute('style:position', (string) ($tab->getPosition() / Converter::INCH_TO_TWIP) . 'in');
149                $xmlWriter->endElement();
150            }
151            $xmlWriter->endElement();
152        }
153
154        //Right to left
155        $xmlWriter->writeAttributeIf($style->isBidi(), 'style:writing-mode', 'rl-tb');
156
157        //Indentation
158        $indent = $style->getIndentation();
159        //if ($indent instanceof \PhpOffice\PhpWord\Style\Indentation) {
160        if (!empty($indent)) {
161            $marg = $indent->getLeft();
162            $xmlWriter->writeAttributeIf($marg !== null, 'fo:margin-left', (string) ($marg / Converter::INCH_TO_TWIP) . 'in');
163            $marg = $indent->getRight();
164            $xmlWriter->writeAttributeIf($marg !== null, 'fo:margin-right', (string) ($marg / Converter::INCH_TO_TWIP) . 'in');
165        }
166
167        $xmlWriter->endElement(); //style:paragraph-properties
168
169        if ($styleAuto && substr($styleName, 0, 2) === 'SB') {
170            $xmlWriter->startElement('style:text-properties');
171            $xmlWriter->writeAttribute('text:display', 'none');
172            $xmlWriter->endElement();
173        }
174
175        $xmlWriter->endElement(); //style:style
176    }
177}