Completed
Push — master ( 829924...fb7d68 )
by Stefan
09:58
created

Sheet::setFreezePaneCellId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
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 $freezePaneCellId;
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 $maxColumnCount;
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
     * @param CellBuilder     $cellBuilder
62
     * @param WidthCalculator $widthCalculator
63
     */
64 13
    public function __construct(CellBuilder $cellBuilder, WidthCalculator $widthCalculator)
65
    {
66 13
        $this->cellBuilder = $cellBuilder;
67 13
        $this->widthCalculator = $widthCalculator;
68 13
    }
69
70
    /**
71
     * Enable cell autosizing (~30% performance hit!).
72
     */
73 5
    public function enableCellAutosizing()
74
    {
75 5
        $this->useCellAutosizing = true;
76 5
    }
77
78
    /**
79
     * Disable cell autosizing (default).
80
     */
81 2
    public function disableCellAutosizing()
82
    {
83 2
        $this->useCellAutosizing = false;
84 2
    }
85
86
    /**
87
     * @param int $cellId
88
     */
89 2
    public function setFreezePaneCellId($cellId)
90
    {
91 2
        $this->freezePaneCellId = $cellId;
92 2
    }
93
94
    /**
95
     * Set custom column widths with 0 representing the first column.
96
     *
97
     * @param array $columnWidths
98
     * @throws \InvalidArgumentException
99
     */
100 4
    public function setFixedColumnWidths(array $columnWidths)
101
    {
102 4
        if ($columnWidths !== array_filter($columnWidths, 'is_numeric')
103 4
            || array_keys($columnWidths) !== array_filter(array_keys($columnWidths), 'is_int')
104 4
        ) {
105 2
            throw new \InvalidArgumentException('Array must contain integer keys and numeric values only!');
106
        }
107
108 2
        $this->columnWidths = $columnWidths + $this->columnWidths;
109 2
    }
110
111
    /**
112
     * Return array containing all column widths.
113
     *
114
     * @return array
115
     */
116 4
    public function getColumnWidths()
117
    {
118 4
        return $this->columnWidths;
119
    }
120
121
    /**
122
     * Return cellId for dimensions.
123
     *
124
     * @return string
125
     */
126 1
    public function getDimensionUpperBound()
127
    {
128 1
        return $this->cellBuilder->getCellId($this->maxColumnCount, $this->rowIndex - 1);
129
    }
130
131
    /**
132
     * Add single row and style to sheet.
133
     *
134
     * @param array $row
135
     * @param Style $style
136
     *
137
     * @return string
138
     */
139 4
    public function addRow(array $row, Style $style)
140
    {
141 4
        $columnCount = count($row);
142 4
        $this->updateMaxColumnCount($columnCount);
143
144 4
        $this->widthCalculator->setFont($style->getFont());
145 4
        $cellXml = $this->getCellXml($row, $style);
146
147 4
        if (!$this->useCellAutosizing || $style->getFont()->getSize() < 14) {
148 4
            return sprintf(RowXml::DEFAULT_XML, $this->rowIndex++, $columnCount, $cellXml);
149
        }
150
151 1
        return sprintf(RowXml::HEIGHT_XML, $this->rowIndex++, $columnCount,
152 1
            $style->getFont()->getSize() * 1.4, $cellXml);
153
    }
154
155
    /**
156
     * Track column count for dimensions xml (e.g. A1:K123).
157
     *
158
     * @param int $columnCount
159
     */
160 4
    private function updateMaxColumnCount($columnCount)
161
    {
162 4
        if ($this->maxColumnCount < $columnCount) {
163 4
            $this->maxColumnCount = $columnCount;
164 4
        }
165 4
    }
166
167
    /**
168
     * Get xml string for single cell and update cell widths.
169
     *
170
     * @param array $row
171
     * @param Style $style
172
     * @return string
173
     */
174 4
    private function getCellXml(array $row, Style $style)
175
    {
176 4
        $cellXml = '';
177 4
        foreach (array_values($row) as $cellIndex => $cellValue) {
178 4
            if (0 < strlen($cellValue)) {
179 4
                $this->updateColumnWidths($cellValue, $cellIndex, $style);
180 4
                $cellXml .= $this->cellBuilder->build($this->rowIndex, $cellIndex, $cellValue, $style->getId());
181 4
            }
182 4
        }
183
184 4
        return $cellXml;
185
    }
186
187
    /**
188
     * Track cell width for column width sizing if its enabled.
189
     *
190
     * @param mixed $value
191
     * @param int   $cellIndex
192
     * @param Style $style
193
     */
194 4
    private function updateColumnWidths($value, $cellIndex, Style $style)
195
    {
196 4
        if ($this->useCellAutosizing) {
197 3
            $cellWidth = $this->widthCalculator->getCellWidth($value, $style->getFont());
198 3
            if (!isset($this->columnWidths[$cellIndex])
199 3
                || $this->columnWidths[$cellIndex] < $cellWidth
200 3
            ) {
201 3
                $this->columnWidths[$cellIndex] = $cellWidth;
202 3
            }
203 3
        }
204 4
    }
205
206
    /**
207
     * Return freeze pane xml string for sheetView.
208
     *
209
     * @return string
210
     */
211 2
    public function getFreezePaneXml()
212
    {
213 2
        if (!$this->freezePaneCellId
214 2
            || 1 !== preg_match('~^[A-Z]+(\d+)$~', $this->freezePaneCellId, $m)
215 2
        ) {
216 2
            return '';
217
        }
218 1
        return sprintf(SheetXml::FREEZE_PANE_XML, array_pop($m) - 1, $this->freezePaneCellId);
219
    }
220
}
221