Completed
Push — master ( 8206f8...a56904 )
by Stefan
03:17
created

Sheet::setFixedColumnWidths()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 1
Bugs 1 Features 1
Metric Value
c 1
b 1
f 1
dl 0
loc 10
ccs 7
cts 7
cp 1
rs 9.4285
cc 3
eloc 5
nc 2
nop 1
crap 3
1
<?php
2
3
namespace OneSheet;
4
5
use OneSheet\Xml\RowXml;
6
use OneSheet\Style\Style;
7
use OneSheet\Xml\SheetXml;
8
use OneSheet\Width\WidthCalculator;
9
10
/**
11
 * Class Sheet
12
 *
13
 * @package OneSheet
14
 */
15
class Sheet
16
{
17
    /**
18
     * @var CellBuilder
19
     */
20
    private $cellBuilder;
21
22
    /**
23
     * @var WidthCalculator
24
     */
25
    private $widthCalculator;
26
27
    /**
28
     * @var bool
29
     */
30
    private $useCellAutosizing = false;
31
32
    /**
33
     * @var int
34
     */
35
    private $freezePaneId;
36
37
    /**
38
     * Track next row index.
39
     *
40
     * @var int
41
     */
42
    private $rowIndex = 1;
43
44
    /**
45
     * Holds width/column count of the widest row.
46
     *
47
     * @var int
48
     */
49
    private $maxRowWidth;
50
51
    /**
52
     * Holds widths of the widest cells for column sizing.
53
     *
54
     * @var array
55
     */
56
    private $columnWidths = array();
57
58
    /**
59
     * Sheet constructor.
60
     */
61 9
    public function __construct()
62 1
    {
63 9
        $this->cellBuilder = new CellBuilder();
64 9
        $this->widthCalculator = new WidthCalculator();
65 9
    }
66
67
    /**
68
     * Enable cell autosizing (~30% performance hit!).
69
     */
70 3
    public function enableCellAutosizing()
71
    {
72 3
        $this->useCellAutosizing = true;
73 3
    }
74
75
    /**
76
     * Disable cell autosizing (default).
77
     */
78 1
    public function disableCellAutosizing()
79
    {
80 1
        $this->useCellAutosizing = false;
81 1
    }
82
83
    /**
84
     * Set custom column widths with 0 beeing the the first.
85
     *
86
     * @param array $columnWidths
87
     * @throws \InvalidArgumentException
88
     */
89 3
    public function setFixedColumnWidths(array $columnWidths)
90
    {
91 3
        if ($columnWidths !== array_filter($columnWidths, 'is_numeric')
92 3
            || array_keys($columnWidths) !== array_filter(array_keys($columnWidths), 'is_int')
93 3
        ) {
94 2
            throw new \InvalidArgumentException('Array must contain integer keys and numeric values only!');
95
        }
96
97 1
        $this->columnWidths = $columnWidths + $this->columnWidths;
98 1
    }
99
100
    /**
101
     * Return array containing all column widths.
102
     *
103
     * @return array
104
     */
105 4
    public function getColumnWidths()
106
    {
107 4
        return $this->columnWidths;
108
    }
109
110
    /**
111
     * Return cellId for dimensions.
112
     *
113
     * @return string
114
     */
115 1
    public function getDimensionUpperBound()
116
    {
117 1
        return $this->cellBuilder->getCellId($this->maxRowWidth, $this->rowIndex - 1);
118
    }
119
120
    /**
121
     * Add single row and style to sheet.
122
     *
123
     * @param array $row
124
     * @param Style $style
125
     *
126
     * @return string
127
     */
128 4
    public function addRow(array $row, Style $style)
129
    {
130 4
        $rowWidth = count($row);
131 4
        $this->updateMaxRowWidth($rowWidth);
132
133 4
        $this->widthCalculator->setFont($style->getFont());
134 4
        $cellXml = $this->getCellXml($row, $style);
135
136 4
        if (!$this->useCellAutosizing || $style->getFont()->getSize() < 14) {
137 4
            return sprintf(RowXml::DEFAULT_XML, $this->rowIndex++, $rowWidth, $cellXml);
138
        }
139
140 1
        return sprintf(RowXml::HEIGHT_XML, $this->rowIndex++, $rowWidth,
141 1
            $style->getFont()->getSize() * 1.4, $cellXml);
142
    }
143
144
    /**
145
     * @param int $cellId
146
     */
147 1
    public function setFreezePaneId($cellId)
148
    {
149 1
        $this->freezePaneId = $cellId;
150 1
    }
151
152
    /**
153
     * Track widest row for dimensions xml (e.g. A1:K123).
154
     *
155
     * @param int $rowWidth
156
     */
157 4
    private function updateMaxRowWidth($rowWidth)
158
    {
159 4
        if ($this->maxRowWidth < $rowWidth) {
160 4
            $this->maxRowWidth = $rowWidth;
161 4
        }
162 4
    }
163
164
    /**
165
     * Get xml string for single cell and update cell widths.
166
     *
167
     * @param array $row
168
     * @param Style $style
169
     * @return string
170
     */
171 4
    private function getCellXml(array $row, Style $style)
172
    {
173 4
        $cellXml = '';
174 4
        foreach (array_values($row) as $cellIndex => $cellValue) {
175 4
            if (0 < strlen($cellValue)) {
176 4
                $this->updateColumnWidths($cellValue, $cellIndex, $style);
177 4
                $cellXml .= $this->cellBuilder->build($this->rowIndex, $cellIndex, $cellValue, $style->getId());
178 4
            }
179 4
        }
180
181 4
        return $cellXml;
182
    }
183
184
    /**
185
     * Track cell width for column width sizing if its enabled.
186
     *
187
     * @param mixed $value
188
     * @param int   $cellIndex
189
     * @param Style $style
190
     */
191 4
    private function updateColumnWidths($value, $cellIndex, Style $style)
192
    {
193 4
        if ($this->useCellAutosizing) {
194 3
            $cellWidth = $this->widthCalculator->getCellWidth($value, $style->getFont());
195 3
            if (!isset($this->columnWidths[$cellIndex])
196 3
                || $this->columnWidths[$cellIndex] < $cellWidth
197 3
            ) {
198 3
                $this->columnWidths[$cellIndex] = $cellWidth;
199 3
            }
200 3
        }
201 4
    }
202
203
    /**
204
     * Return freeze pane xml string for sheetView.
205
     *
206
     * @return string
207
     */
208 2
    public function getFreezePaneXml()
209
    {
210 2
        if (!$this->freezePaneId
211 2
            || 1 !== preg_match('~^[A-Z]+(\d+)$~', $this->freezePaneId, $m)
212 2
        ) {
213 2
            return '';
214
        }
215 1
        return sprintf(SheetXml::FREEZE_PANE_XML, array_pop($m) - 1, $this->freezePaneId);
216
    }
217
}
218