Passed
Push — master ( f52ae2...8aee49 )
by
unknown
29:47 queued 15:47
created

ColumnAndRowAttributes::isFilteredColumn()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 4
c 0
b 0
f 0
nc 3
nop 3
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 3
rs 10
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
4
5
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
6
use PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter;
7
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter;
8
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
9
use SimpleXMLElement;
10
11
class ColumnAndRowAttributes extends BaseParserClass
12
{
13
    private Worksheet $worksheet;
14
15
    private ?SimpleXMLElement $worksheetXml;
16
17 666
    public function __construct(Worksheet $workSheet, ?SimpleXMLElement $worksheetXml = null)
18
    {
19 666
        $this->worksheet = $workSheet;
20 666
        $this->worksheetXml = $worksheetXml;
21
    }
22
23
    /**
24
     * Set Worksheet column attributes by attributes array passed.
25
     *
26
     * @param string $columnAddress A, B, ... DX, ...
27
     * @param array $columnAttributes array of attributes (indexes are attribute name, values are value)
28
     *                               'xfIndex', 'visible', 'collapsed', 'outlineLevel', 'width', ... ?
29
     */
30 349
    private function setColumnAttributes(string $columnAddress, array $columnAttributes): void
31
    {
32 349
        if (isset($columnAttributes['xfIndex'])) {
33 247
            $this->worksheet->getColumnDimension($columnAddress)->setXfIndex($columnAttributes['xfIndex']);
34
        }
35 349
        if (isset($columnAttributes['visible'])) {
36 8
            $this->worksheet->getColumnDimension($columnAddress)->setVisible($columnAttributes['visible']);
37
        }
38 349
        if (isset($columnAttributes['collapsed'])) {
39 1
            $this->worksheet->getColumnDimension($columnAddress)->setCollapsed($columnAttributes['collapsed']);
40
        }
41 349
        if (isset($columnAttributes['outlineLevel'])) {
42 1
            $this->worksheet->getColumnDimension($columnAddress)->setOutlineLevel($columnAttributes['outlineLevel']);
43
        }
44 349
        if (isset($columnAttributes['width'])) {
45 349
            $this->worksheet->getColumnDimension($columnAddress)->setWidth($columnAttributes['width']);
46
        }
47
    }
48
49
    /**
50
     * Set Worksheet row attributes by attributes array passed.
51
     *
52
     * @param int $rowNumber 1, 2, 3, ... 99, ...
53
     * @param array $rowAttributes array of attributes (indexes are attribute name, values are value)
54
     *                               'xfIndex', 'visible', 'collapsed', 'outlineLevel', 'rowHeight', ... ?
55
     */
56 302
    private function setRowAttributes(int $rowNumber, array $rowAttributes): void
57
    {
58 302
        if (isset($rowAttributes['xfIndex'])) {
59 196
            $this->worksheet->getRowDimension($rowNumber)->setXfIndex($rowAttributes['xfIndex']);
60
        }
61 302
        if (isset($rowAttributes['visible'])) {
62 20
            $this->worksheet->getRowDimension($rowNumber)->setVisible($rowAttributes['visible']);
63
        }
64 302
        if (isset($rowAttributes['collapsed'])) {
65
            $this->worksheet->getRowDimension($rowNumber)->setCollapsed($rowAttributes['collapsed']);
66
        }
67 302
        if (isset($rowAttributes['outlineLevel'])) {
68
            $this->worksheet->getRowDimension($rowNumber)->setOutlineLevel($rowAttributes['outlineLevel']);
69
        }
70 302
        if (isset($rowAttributes['rowHeight'])) {
71 278
            $this->worksheet->getRowDimension($rowNumber)->setRowHeight($rowAttributes['rowHeight']);
72
        }
73
    }
74
75 666
    public function load(?IReadFilter $readFilter = null, bool $readDataOnly = false, bool $ignoreRowsWithNoCells = false): void
76
    {
77 666
        if ($this->worksheetXml === null) {
78
            return;
79
        }
80 666
        if ($readFilter !== null && $readFilter::class === DefaultReadFilter::class) {
81 662
            $readFilter = null;
82
        }
83
84 666
        $columnsAttributes = [];
85 666
        $rowsAttributes = [];
86 666
        if (isset($this->worksheetXml->cols)) {
87 349
            $columnsAttributes = $this->readColumnAttributes($this->worksheetXml->cols, $readDataOnly);
88
        }
89
90 666
        if ($this->worksheetXml->sheetData && $this->worksheetXml->sheetData->row) {
91 624
            $rowsAttributes = $this->readRowAttributes($this->worksheetXml->sheetData->row, $readDataOnly, $ignoreRowsWithNoCells, $readFilter !== null);
92
        }
93
94
        // set columns/rows attributes
95 666
        $columnsAttributesAreSet = [];
96 666
        foreach ($columnsAttributes as $columnCoordinate => $columnAttributes) {
97
            if (
98 349
                $readFilter === null
99 349
                || !$this->isFilteredColumn($readFilter, $columnCoordinate, $rowsAttributes)
100
            ) {
101 349
                if (!isset($columnsAttributesAreSet[$columnCoordinate])) {
102 349
                    $this->setColumnAttributes($columnCoordinate, $columnAttributes);
103 349
                    $columnsAttributesAreSet[$columnCoordinate] = true;
104
                }
105
            }
106
        }
107
108 666
        $rowsAttributesAreSet = [];
109 666
        foreach ($rowsAttributes as $rowCoordinate => $rowAttributes) {
110
            if (
111 304
                $readFilter === null
112 304
                || !$this->isFilteredRow($readFilter, $rowCoordinate, $columnsAttributes)
113
            ) {
114 302
                if (!isset($rowsAttributesAreSet[$rowCoordinate])) {
115 302
                    $this->setRowAttributes($rowCoordinate, $rowAttributes);
116 302
                    $rowsAttributesAreSet[$rowCoordinate] = true;
117
                }
118
            }
119
        }
120
    }
121
122 3
    private function isFilteredColumn(IReadFilter $readFilter, string $columnCoordinate, array $rowsAttributes): bool
123
    {
124 3
        foreach ($rowsAttributes as $rowCoordinate => $rowAttributes) {
125 3
            if ($readFilter->readCell($columnCoordinate, $rowCoordinate, $this->worksheet->getTitle())) {
126 3
                return false;
127
            }
128
        }
129
130 2
        return true;
131
    }
132
133 349
    private function readColumnAttributes(SimpleXMLElement $worksheetCols, bool $readDataOnly): array
134
    {
135 349
        $columnAttributes = [];
136
137 349
        foreach ($worksheetCols->col as $columnx) {
138 349
            $column = $columnx->attributes();
139 349
            if ($column !== null) {
140 349
                $startColumn = Coordinate::stringFromColumnIndex((int) $column['min']);
141 349
                $endColumn = Coordinate::stringFromColumnIndex((int) $column['max']);
142 349
                ++$endColumn;
143 349
                for ($columnAddress = $startColumn; $columnAddress !== $endColumn; ++$columnAddress) {
144 349
                    $columnAttributes[$columnAddress] = $this->readColumnRangeAttributes($column, $readDataOnly);
145
146 349
                    if ((int) ($column['max']) == 16384) {
147 13
                        break;
148
                    }
149
                }
150
            }
151
        }
152
153 349
        return $columnAttributes;
154
    }
155
156 349
    private function readColumnRangeAttributes(?SimpleXMLElement $column, bool $readDataOnly): array
157
    {
158 349
        $columnAttributes = [];
159 349
        if ($column !== null) {
160 349
            if (isset($column['style']) && !$readDataOnly) {
161 247
                $columnAttributes['xfIndex'] = (int) $column['style'];
162
            }
163 349
            if (isset($column['hidden']) && self::boolean($column['hidden'])) {
164 8
                $columnAttributes['visible'] = false;
165
            }
166 349
            if (isset($column['collapsed']) && self::boolean($column['collapsed'])) {
167 1
                $columnAttributes['collapsed'] = true;
168
            }
169 349
            if (isset($column['outlineLevel']) && ((int) $column['outlineLevel']) > 0) {
170 1
                $columnAttributes['outlineLevel'] = (int) $column['outlineLevel'];
171
            }
172 349
            if (isset($column['width'])) {
173 349
                $columnAttributes['width'] = (float) $column['width'];
174
            }
175
        }
176
177 349
        return $columnAttributes;
178
    }
179
180 4
    private function isFilteredRow(IReadFilter $readFilter, int $rowCoordinate, array $columnsAttributes): bool
181
    {
182 4
        foreach ($columnsAttributes as $columnCoordinate => $columnAttributes) {
183 3
            if (!$readFilter->readCell($columnCoordinate, $rowCoordinate, $this->worksheet->getTitle())) {
184 3
                return true;
185
            }
186
        }
187
188 2
        return false;
189
    }
190
191 624
    private function readRowAttributes(SimpleXMLElement $worksheetRow, bool $readDataOnly, bool $ignoreRowsWithNoCells, bool $readFilterIsNotNull): array
192
    {
193 624
        $rowAttributes = [];
194
195 624
        foreach ($worksheetRow as $rowx) {
196 624
            $row = $rowx->attributes();
197 624
            if ($row !== null && (!$ignoreRowsWithNoCells || isset($rowx->c))) {
198 624
                $rowIndex = (int) $row['r'];
199 624
                if (isset($row['ht']) && !$readDataOnly) {
200 280
                    $rowAttributes[$rowIndex]['rowHeight'] = (float) $row['ht'];
201
                }
202 624
                if (isset($row['hidden']) && self::boolean($row['hidden'])) {
203 20
                    $rowAttributes[$rowIndex]['visible'] = false;
204
                }
205 624
                if (isset($row['collapsed']) && self::boolean($row['collapsed'])) {
206
                    $rowAttributes[$rowIndex]['collapsed'] = true;
207
                }
208 624
                if (isset($row['outlineLevel']) && (int) $row['outlineLevel'] > 0) {
209
                    $rowAttributes[$rowIndex]['outlineLevel'] = (int) $row['outlineLevel'];
210
                }
211 624
                if (isset($row['s']) && !$readDataOnly) {
212 196
                    $rowAttributes[$rowIndex]['xfIndex'] = (int) $row['s'];
213
                }
214 624
                if ($readFilterIsNotNull && empty($rowAttributes[$rowIndex])) {
215 3
                    $rowAttributes[$rowIndex]['exists'] = true;
216
                }
217
            }
218
        }
219
220 624
        return $rowAttributes;
221
    }
222
}
223