Failed Conditions
Push — master ( e55052...5b4b12 )
by Adrien
09:31
created

ColumnAndRowAttributes   C

Complexity

Total Complexity 53

Size/Duplication

Total Lines 202
Duplicated Lines 0 %

Test Coverage

Coverage 94.06%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 93
c 1
b 0
f 0
dl 0
loc 202
ccs 95
cts 101
cp 0.9406
rs 6.96
wmc 53

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setRowAttributes() 0 16 6
A readColumnRangeAttributes() 0 19 6
A setColumnAttributes() 0 16 6
B readRowAttributes() 0 23 9
C load() 0 43 15
A isFilteredRow() 0 9 3
A readColumnAttributes() 0 18 4
A isFilteredColumn() 0 9 3

How to fix   Complexity   

Complex Class

Complex classes like ColumnAndRowAttributes often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ColumnAndRowAttributes, and based on these observations, apply Extract Interface, too.

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;
14
15
    private $worksheetXml;
16
17 175
    public function __construct(Worksheet $workSheet, ?SimpleXMLElement $worksheetXml = null)
18
    {
19 175
        $this->worksheet = $workSheet;
20 175
        $this->worksheetXml = $worksheetXml;
21 175
    }
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 35
    private function setColumnAttributes($columnAddress, array $columnAttributes): void
31
    {
32 35
        if (isset($columnAttributes['xfIndex'])) {
33 16
            $this->worksheet->getColumnDimension($columnAddress)->setXfIndex($columnAttributes['xfIndex']);
34
        }
35 35
        if (isset($columnAttributes['visible'])) {
36 3
            $this->worksheet->getColumnDimension($columnAddress)->setVisible($columnAttributes['visible']);
37
        }
38 35
        if (isset($columnAttributes['collapsed'])) {
39 1
            $this->worksheet->getColumnDimension($columnAddress)->setCollapsed($columnAttributes['collapsed']);
40
        }
41 35
        if (isset($columnAttributes['outlineLevel'])) {
42 1
            $this->worksheet->getColumnDimension($columnAddress)->setOutlineLevel($columnAttributes['outlineLevel']);
43
        }
44 35
        if (isset($columnAttributes['width'])) {
45 35
            $this->worksheet->getColumnDimension($columnAddress)->setWidth($columnAttributes['width']);
46
        }
47 35
    }
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 26
    private function setRowAttributes($rowNumber, array $rowAttributes): void
57
    {
58 26
        if (isset($rowAttributes['xfIndex'])) {
59 3
            $this->worksheet->getRowDimension($rowNumber)->setXfIndex($rowAttributes['xfIndex']);
60
        }
61 26
        if (isset($rowAttributes['visible'])) {
62 5
            $this->worksheet->getRowDimension($rowNumber)->setVisible($rowAttributes['visible']);
63
        }
64 26
        if (isset($rowAttributes['collapsed'])) {
65
            $this->worksheet->getRowDimension($rowNumber)->setCollapsed($rowAttributes['collapsed']);
66
        }
67 26
        if (isset($rowAttributes['outlineLevel'])) {
68
            $this->worksheet->getRowDimension($rowNumber)->setOutlineLevel($rowAttributes['outlineLevel']);
69
        }
70 26
        if (isset($rowAttributes['rowHeight'])) {
71 21
            $this->worksheet->getRowDimension($rowNumber)->setRowHeight($rowAttributes['rowHeight']);
72
        }
73 26
    }
74
75
    /**
76
     * @param IReadFilter $readFilter
77
     * @param bool $readDataOnly
78
     */
79 175
    public function load(?IReadFilter $readFilter = null, $readDataOnly = false): void
80
    {
81 175
        if ($this->worksheetXml === null) {
82
            return;
83
        }
84
85 175
        $columnsAttributes = [];
86 175
        $rowsAttributes = [];
87 175
        if (isset($this->worksheetXml->cols)) {
88 35
            $columnsAttributes = $this->readColumnAttributes($this->worksheetXml->cols, $readDataOnly);
89
        }
90
91 175
        if ($this->worksheetXml->sheetData && $this->worksheetXml->sheetData->row) {
92 160
            $rowsAttributes = $this->readRowAttributes($this->worksheetXml->sheetData->row, $readDataOnly);
93
        }
94
95 175
        if ($readFilter !== null && get_class($readFilter) === DefaultReadFilter::class) {
96 172
            $readFilter = null;
97
        }
98
99
        // set columns/rows attributes
100 175
        $columnsAttributesAreSet = [];
101 175
        foreach ($columnsAttributes as $columnCoordinate => $columnAttributes) {
102
            if (
103 35
                $readFilter === null ||
104 35
                !$this->isFilteredColumn($readFilter, $columnCoordinate, $rowsAttributes)
105
            ) {
106 35
                if (!isset($columnsAttributesAreSet[$columnCoordinate])) {
107 35
                    $this->setColumnAttributes($columnCoordinate, $columnAttributes);
108 35
                    $columnsAttributesAreSet[$columnCoordinate] = true;
109
                }
110
            }
111
        }
112
113 175
        $rowsAttributesAreSet = [];
114 175
        foreach ($rowsAttributes as $rowCoordinate => $rowAttributes) {
115
            if (
116 27
                $readFilter === null ||
117 27
                !$this->isFilteredRow($readFilter, $rowCoordinate, $columnsAttributes)
118
            ) {
119 26
                if (!isset($rowsAttributesAreSet[$rowCoordinate])) {
120 26
                    $this->setRowAttributes($rowCoordinate, $rowAttributes);
121 26
                    $rowsAttributesAreSet[$rowCoordinate] = true;
122
                }
123
            }
124
        }
125 175
    }
126
127 2
    private function isFilteredColumn(IReadFilter $readFilter, $columnCoordinate, array $rowsAttributes)
128
    {
129 2
        foreach ($rowsAttributes as $rowCoordinate => $rowAttributes) {
130 1
            if (!$readFilter->readCell($columnCoordinate, $rowCoordinate, $this->worksheet->getTitle())) {
131 1
                return true;
132
            }
133
        }
134
135 2
        return false;
136
    }
137
138 35
    private function readColumnAttributes(SimpleXMLElement $worksheetCols, $readDataOnly)
139
    {
140 35
        $columnAttributes = [];
141
142 35
        foreach ($worksheetCols->col as $column) {
143 35
            $startColumn = Coordinate::stringFromColumnIndex((int) $column['min']);
144 35
            $endColumn = Coordinate::stringFromColumnIndex((int) $column['max']);
145 35
            ++$endColumn;
146 35
            for ($columnAddress = $startColumn; $columnAddress !== $endColumn; ++$columnAddress) {
147 35
                $columnAttributes[$columnAddress] = $this->readColumnRangeAttributes($column, $readDataOnly);
1 ignored issue
show
Bug introduced by
It seems like $column can also be of type null; however, parameter $column of PhpOffice\PhpSpreadsheet...ColumnRangeAttributes() does only seem to accept SimpleXMLElement, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

147
                $columnAttributes[$columnAddress] = $this->readColumnRangeAttributes(/** @scrutinizer ignore-type */ $column, $readDataOnly);
Loading history...
148
149 35
                if ((int) ($column['max']) == 16384) {
150 1
                    break;
151
                }
152
            }
153
        }
154
155 35
        return $columnAttributes;
156
    }
157
158 35
    private function readColumnRangeAttributes(SimpleXMLElement $column, $readDataOnly)
159
    {
160 35
        $columnAttributes = [];
161
162 35
        if ($column['style'] && !$readDataOnly) {
163 16
            $columnAttributes['xfIndex'] = (int) $column['style'];
164
        }
165 35
        if (self::boolean($column['hidden'])) {
166 3
            $columnAttributes['visible'] = false;
167
        }
168 35
        if (self::boolean($column['collapsed'])) {
169 1
            $columnAttributes['collapsed'] = true;
170
        }
171 35
        if (((int) $column['outlineLevel']) > 0) {
172 1
            $columnAttributes['outlineLevel'] = (int) $column['outlineLevel'];
173
        }
174 35
        $columnAttributes['width'] = (float) $column['width'];
175
176 35
        return $columnAttributes;
177
    }
178
179 1
    private function isFilteredRow(IReadFilter $readFilter, $rowCoordinate, array $columnsAttributes)
180
    {
181 1
        foreach ($columnsAttributes as $columnCoordinate => $columnAttributes) {
182 1
            if (!$readFilter->readCell($columnCoordinate, $rowCoordinate, $this->worksheet->getTitle())) {
183 1
                return true;
184
            }
185
        }
186
187
        return false;
188
    }
189
190 160
    private function readRowAttributes(SimpleXMLElement $worksheetRow, $readDataOnly)
191
    {
192 160
        $rowAttributes = [];
193
194 160
        foreach ($worksheetRow as $row) {
195 160
            if ($row['ht'] && !$readDataOnly) {
196 22
                $rowAttributes[(int) $row['r']]['rowHeight'] = (float) $row['ht'];
197
            }
198 160
            if (self::boolean($row['hidden'])) {
199 5
                $rowAttributes[(int) $row['r']]['visible'] = false;
200
            }
201 160
            if (self::boolean($row['collapsed'])) {
202
                $rowAttributes[(int) $row['r']]['collapsed'] = true;
203
            }
204 160
            if ((int) $row['outlineLevel'] > 0) {
205
                $rowAttributes[(int) $row['r']]['outlineLevel'] = (int) $row['outlineLevel'];
206
            }
207 160
            if ($row['s'] && !$readDataOnly) {
208 3
                $rowAttributes[(int) $row['r']]['xfIndex'] = (int) $row['s'];
209
            }
210
        }
211
212 160
        return $rowAttributes;
213
    }
214
}
215