Completed
Push — master ( 8f2a76...e71d57 )
by Stefan
02:39
created

Sheet::setColumnWidthBoundries()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 5
ccs 0
cts 4
cp 0
rs 9.4285
cc 3
eloc 3
nc 4
nop 2
crap 12
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
     * Holds minimum allowed column width.
60
     *
61
     * @var float
62
     */
63
    private $minColumnWidth = 1;
64
65
    /**
66
     * Holds maximum allowed column width. 254.86 appears
67
     * to be the default maximum width.
68
     *
69
     * @var float
70
     */
71
    private $maxColumnWidth = 254.86;
72
73
    /**
74
     * Sheet constructor.
75
     *
76
     * @param CellBuilder     $cellBuilder
77
     * @param WidthCalculator $widthCalculator
78
     */
79 14
    public function __construct(CellBuilder $cellBuilder, WidthCalculator $widthCalculator)
80
    {
81 14
        $this->cellBuilder = $cellBuilder;
82 14
        $this->widthCalculator = $widthCalculator;
83 14
    }
84
85
    /**
86
     * Enable cell autosizing (~30% performance hit!).
87
     */
88 5
    public function enableCellAutosizing()
89
    {
90 5
        $this->useCellAutosizing = true;
91 5
    }
92
93
    /**
94
     * Disable cell autosizing (default).
95
     */
96 2
    public function disableCellAutosizing()
97
    {
98 2
        $this->useCellAutosizing = false;
99 2
    }
100
101
    /**
102
     * @param int $cellId
103
     */
104 2
    public function setFreezePaneCellId($cellId)
105
    {
106 2
        $this->freezePaneCellId = $cellId;
107 2
    }
108
109
    /**
110
     * Set custom column widths with 0 representing the first column.
111
     *
112
     * @param array $columnWidths
113
     * @throws \InvalidArgumentException
114
     */
115 4
    public function setFixedColumnWidths(array $columnWidths)
116
    {
117 4
        if ($columnWidths !== array_filter($columnWidths, 'is_numeric')
118 4
            || array_keys($columnWidths) !== array_filter(array_keys($columnWidths), 'is_int')
119 4
        ) {
120 2
            throw new \InvalidArgumentException('Array must contain integer keys and numeric values only!');
121
        }
122
123 2
        $this->columnWidths = $columnWidths + $this->columnWidths;
124 2
    }
125
126
    /**
127
     * Set lower and/or upper limits for column widths.
128
     *
129
     * @param float|null $minWidth
130
     * @param float|null $maxWidth
131
     */
132 1
    public function setColumnWidthLimits($minWidth = null, $maxWidth = null)
133
    {
134 1
        $this->minColumnWidth = is_numeric($minWidth) && $minWidth >= 0 ? $minWidth : 0;
0 ignored issues
show
Documentation Bug introduced by
It seems like is_numeric($minWidth) &&...th >= 0 ? $minWidth : 0 can also be of type integer or string. However, the property $minColumnWidth is declared as type double. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
135 1
        $this->maxColumnWidth = is_numeric($maxWidth) && $maxWidth < 255.86 ? $maxWidth : 255.86;
0 ignored issues
show
Documentation Bug introduced by
It seems like is_numeric($maxWidth) &&...86 ? $maxWidth : 255.86 can also be of type integer or string. However, the property $maxColumnWidth is declared as type double. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
136 1
    }
137
138
    /**
139
     * Return array containing all column widths, limited to min or max
140
     * column width, if one or both of them are set.
141
     *
142
     * @return array
143
     */
144 4
    public function getColumnWidths()
145
    {
146 4
        foreach ($this->columnWidths as $column => $width) {
147 4
            if ($this->maxColumnWidth && $width > $this->maxColumnWidth) {
148
                $this->columnWidths[$column] = $this->maxColumnWidth;
149 4
            } elseif ($this->minColumnWidth && $width < $this->minColumnWidth) {
150
                $this->columnWidths[$column] = $this->minColumnWidth;
151
            }
152 4
        }
153
154 4
        return $this->columnWidths;
155
    }
156
157
    /**
158
     * Return cellId for dimensions.
159
     *
160
     * @return string
161
     */
162 1
    public function getDimensionUpperBound()
163
    {
164 1
        return $this->cellBuilder->getCellId($this->maxColumnCount, $this->rowIndex - 1);
165
    }
166
167
    /**
168
     * Add single row and style to sheet.
169
     *
170
     * @param array $row
171
     * @param Style $style
172
     *
173
     * @return string
174
     */
175 4
    public function addRow(array $row, Style $style)
176
    {
177 4
        $columnCount = count($row);
178 4
        $this->updateMaxColumnCount($columnCount);
179
180 4
        $this->widthCalculator->setFont($style->getFont());
181 4
        $cellXml = $this->getCellXml($row, $style);
182
183 4
        if (!$this->useCellAutosizing || $style->getFont()->getSize() < 14) {
184 4
            return sprintf(RowXml::DEFAULT_XML, $this->rowIndex++, $columnCount, $cellXml);
185
        }
186
187 1
        return sprintf(RowXml::HEIGHT_XML, $this->rowIndex++, $columnCount,
188 1
            $style->getFont()->getSize() * 1.4, $cellXml);
189
    }
190
191
    /**
192
     * Track column count for dimensions xml (e.g. A1:K123).
193
     *
194
     * @param int $columnCount
195
     */
196 4
    private function updateMaxColumnCount($columnCount)
197
    {
198 4
        if ($this->maxColumnCount < $columnCount) {
199 4
            $this->maxColumnCount = $columnCount;
200 4
        }
201 4
    }
202
203
    /**
204
     * Get xml string for single cell and update cell widths.
205
     *
206
     * @param array $row
207
     * @param Style $style
208
     * @return string
209
     */
210 4
    private function getCellXml(array $row, Style $style)
211
    {
212 4
        $cellXml = '';
213 4
        foreach (array_values($row) as $cellIndex => $cellValue) {
214 4
            if (0 < strlen($cellValue)) {
215 4
                $this->updateColumnWidths($cellValue, $cellIndex, $style);
216 4
                $cellXml .= $this->cellBuilder->build($this->rowIndex, $cellIndex, $cellValue, $style->getId());
217 4
            }
218 4
        }
219
220 4
        return $cellXml;
221
    }
222
223
    /**
224
     * Track cell width for column width sizing if its enabled.
225
     *
226
     * @param mixed $value
227
     * @param int   $cellIndex
228
     * @param Style $style
229
     */
230 4
    private function updateColumnWidths($value, $cellIndex, Style $style)
231
    {
232 4
        if ($this->useCellAutosizing) {
233 3
            $cellWidth = $this->widthCalculator->getCellWidth($value, $style->getFont());
234 3
            if (!isset($this->columnWidths[$cellIndex])
235 3
                || $this->columnWidths[$cellIndex] < $cellWidth
236 3
            ) {
237 3
                $this->columnWidths[$cellIndex] = $cellWidth;
238 3
            }
239 3
        }
240 4
    }
241
242
    /**
243
     * Return freeze pane xml string for sheetView.
244
     *
245
     * @return string
246
     */
247 2
    public function getFreezePaneXml()
248
    {
249 2
        if (!$this->freezePaneCellId
250 2
            || 1 !== preg_match('~^[A-Z]+(\d+)$~', $this->freezePaneCellId, $m)
251 2
        ) {
252 2
            return '';
253
        }
254 1
        return sprintf(SheetXml::FREEZE_PANE_XML, array_pop($m) - 1, $this->freezePaneCellId);
255
    }
256
}
257