Completed
Pull Request — master (#1559)
by Adrien
09:36
created

PageSettings::readPageSettingStyles()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 38
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 6
eloc 32
nc 5
nop 1
dl 0
loc 38
rs 8.7857
c 3
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Reader\Ods;
4
5
use DOMDocument;
6
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
7
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
8
9
class PageSettings
10
{
11
    private $officeNs;
12
13
    private $stylesNs;
14
15
    private $stylesFo;
16
17
    private $pageLayoutStyles = [];
18
19
    private $masterStylesCrossReference = [];
20
21
    private $masterPrintStylesCrossReference = [];
22
23
    public function __construct(DOMDocument $styleDom)
24
    {
25
        $this->setDomNameSpaces($styleDom);
26
        $this->readPageSettingStyles($styleDom);
27
        $this->readStyleMasterLookup($styleDom);
28
    }
29
30
    private function setDomNameSpaces(DOMDocument $styleDom): void
31
    {
32
        $this->officeNs = $styleDom->lookupNamespaceUri('office');
33
        $this->stylesNs = $styleDom->lookupNamespaceUri('style');
34
        $this->stylesFo = $styleDom->lookupNamespaceUri('fo');
35
    }
36
37
    private function readPageSettingStyles(DOMDocument $styleDom): void
38
    {
39
        $styles = $styleDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles')
40
            ->item(0)
41
            ->getElementsByTagNameNS($this->stylesNs, 'page-layout');
42
43
        foreach ($styles as $styleSet) {
44
            $styleName = $styleSet->getAttributeNS($this->stylesNs, 'name');
45
            $pageLayoutProperties = $styleSet->getElementsByTagNameNS($this->stylesNs, 'page-layout-properties')[0];
46
            $styleOrientation = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'print-orientation');
47
            $styleScale = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'scale-to');
48
            $stylePrintOrder = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'print-page-order');
49
            $centered = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'table-centering');
50
51
            $marginLeft = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-left');
52
            $marginRight = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-right');
53
            $marginTop = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-top');
54
            $marginBottom = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-bottom');
55
            $header = $styleSet->getElementsByTagNameNS($this->stylesNs, 'header-style')[0];
56
            $headerProperties = $header->getElementsByTagNameNS($this->stylesNs, 'header-footer-properties')[0];
57
            $marginHeader = $headerProperties->getAttributeNS($this->stylesFo, 'min-height');
58
            $footer = $styleSet->getElementsByTagNameNS($this->stylesNs, 'footer-style')[0];
59
            $footerProperties = $footer->getElementsByTagNameNS($this->stylesNs, 'header-footer-properties')[0];
60
            $marginFooter = $footerProperties->getAttributeNS($this->stylesFo, 'min-height');
61
62
            $this->pageLayoutStyles[$styleName] = (object) [
63
                'orientation' => $styleOrientation ?: PageSetup::ORIENTATION_DEFAULT,
64
                'scale' => $styleScale ?: 100,
65
                'printOrder' => $stylePrintOrder,
66
                'horizontalCentered' => $centered === 'horizontal' || $centered === 'both',
67
                'verticalCentered' => $centered === 'vertical' || $centered === 'both',
68
                // margin size is already stored in inches, so no UOM conversion is required
69
                'marginLeft' => (float) $marginLeft ?? 0.7,
70
                'marginRight' => (float) $marginRight ?? 0.7,
71
                'marginTop' => (float) $marginTop ?? 0.3,
72
                'marginBottom' => (float) $marginBottom ?? 0.3,
73
                'marginHeader' => (float) $marginHeader ?? 0.45,
74
                'marginFooter' => (float) $marginFooter ?? 0.45,
75
            ];
76
        }
77
    }
78
79
    private function readStyleMasterLookup(DOMDocument $styleDom): void
80
    {
81
        $styleMasterLookup = $styleDom->getElementsByTagNameNS($this->officeNs, 'master-styles')
82
            ->item(0)
83
            ->getElementsByTagNameNS($this->stylesNs, 'master-page');
84
85
        foreach ($styleMasterLookup as $styleMasterSet) {
86
            $styleMasterName = $styleMasterSet->getAttributeNS($this->stylesNs, 'name');
87
            $pageLayoutName = $styleMasterSet->getAttributeNS($this->stylesNs, 'page-layout-name');
88
            $this->masterPrintStylesCrossReference[$styleMasterName] = $pageLayoutName;
89
        }
90
    }
91
92
    public function readStyleCrossReferences(DOMDocument $contentDom): void
93
    {
94
        $styleXReferences = $contentDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles')
95
            ->item(0)
96
            ->getElementsByTagNameNS($this->stylesNs, 'style');
97
98
        foreach ($styleXReferences as $styleXreferenceSet) {
99
            $styleXRefName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'name');
100
            $stylePageLayoutName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'master-page-name');
101
            if (!empty($stylePageLayoutName)) {
102
                $this->masterStylesCrossReference[$styleXRefName] = $stylePageLayoutName;
103
            }
104
        }
105
    }
106
107
    public function setPrintSettingsForWorksheet(Worksheet $worksheet, string $styleName): void
108
    {
109
        if (!array_key_exists($styleName, $this->masterStylesCrossReference)) {
110
            return;
111
        }
112
        $masterStyleName = $this->masterStylesCrossReference[$styleName];
113
114
        if (!array_key_exists($masterStyleName, $this->masterPrintStylesCrossReference)) {
115
            return;
116
        }
117
        $printSettingsIndex = $this->masterPrintStylesCrossReference[$masterStyleName];
118
119
        if (!array_key_exists($printSettingsIndex, $this->pageLayoutStyles)) {
120
            return;
121
        }
122
        $printSettings = $this->pageLayoutStyles[$printSettingsIndex];
123
124
        $worksheet->getPageSetup()
125
            ->setOrientation($printSettings->orientation ?? PageSetup::ORIENTATION_DEFAULT)
126
            ->setPageOrder($printSettings->printOrder === 'ltr' ? PageSetup::PAGEORDER_OVER_THEN_DOWN : PageSetup::PAGEORDER_DOWN_THEN_OVER)
127
            ->setScale((int) trim($printSettings->scale, '%'))
128
            ->setHorizontalCentered($printSettings->horizontalCentered)
129
            ->setVerticalCentered($printSettings->verticalCentered);
130
131
        $worksheet->getPageMargins()
132
            ->setLeft($printSettings->marginLeft)
133
            ->setRight($printSettings->marginRight)
134
            ->setTop($printSettings->marginTop)
135
            ->setBottom($printSettings->marginBottom)
136
            ->setHeader($printSettings->marginHeader)
137
            ->setFooter($printSettings->marginFooter);
138
    }
139
}
140