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