Completed
Push — rendered-cell-sizes ( a9b1a2...a767c5 )
by Stefan
02:34
created

Sheet::getFonts()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
namespace OneSheet;
4
5
use OneSheet\Style\Font;
6
use OneSheet\Xml\RowXml;
7
use OneSheet\Style\Style;
8
use OneSheet\Xml\SheetXml;
9
use OneSheet\Size\SizeCalculator;
10
11
/**
12
 * Class Sheet
13
 *
14
 * @package OneSheet
15
 */
16
class Sheet
17
{
18
    /**
19
     * @var CellBuilder
20
     */
21
    private $cellBuilder;
22
23
    /**
24
     * @var SizeCalculator
25
     */
26
    private $sizeCalculator;
27
28
    /**
29
     * @var bool
30
     */
31
    private $useCellAutosizing = false;
32
33
    /**
34
     * @var int
35
     */
36
    private $freezePaneCellId;
37
38
    /**
39
     * Track next row index.
40
     *
41
     * @var int
42
     */
43
    private $rowIndex = 1;
44
45
    /**
46
     * Holds width/column count of the widest row.
47
     *
48
     * @var int
49
     */
50
    private $maxColumnCount;
51
52
    /**
53
     * Holds widths of the widest cells for column sizing.
54
     *
55
     * @var array
56
     */
57
    private $columnWidths = array();
58
59
    /**
60
     * Holds minimum allowed column width.
61
     *
62
     * @var float|int
63
     */
64
    private $minColumnWidth = 0;
65
66
    /**
67
     * Holds maximum allowed column width. 254.86 appears
68
     * to be the default maximum width.
69
     *
70
     * @var float|int
71
     */
72
    private $maxColumnWidth = 254.86;
73
74
    /**
75
     * Sheet constructor.
76
     *
77
     * @param CellBuilder    $cellBuilder
78
     * @param SizeCalculator $sizeCalculator
79
     */
80 15
    public function __construct(CellBuilder $cellBuilder, SizeCalculator $sizeCalculator)
81
    {
82 15
        $this->cellBuilder = $cellBuilder;
83 15
        $this->sizeCalculator = $sizeCalculator;
84 15
    }
85
86
    /**
87
     * Enable cell autosizing (~30-100% performance hit!).
88
     */
89 6
    public function enableCellAutosizing()
90
    {
91 6
        $this->useCellAutosizing = true;
92 6
    }
93
94
    /**
95
     * Disable cell autosizing (default).
96
     */
97 2
    public function disableCellAutosizing()
98
    {
99 2
        $this->useCellAutosizing = false;
100 2
    }
101
102
    /**
103
     * @param string $cellId
104
     */
105 2
    public function setFreezePaneCellId($cellId)
106
    {
107 2
        $this->freezePaneCellId = $cellId;
0 ignored issues
show
Documentation Bug introduced by
The property $freezePaneCellId was declared of type integer, but $cellId is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
108 2
    }
109
110
    /**
111
     * Set custom column widths with 0 representing the first column.
112
     *
113
     * @param array $columnWidths
114
     * @throws \InvalidArgumentException
115
     */
116 4
    public function setFixedColumnWidths(array $columnWidths)
117
    {
118 4
        if ($columnWidths !== array_filter($columnWidths, 'is_numeric')
119 4
            || array_keys($columnWidths) !== array_filter(array_keys($columnWidths), 'is_int')
120 4
        ) {
121 2
            throw new \InvalidArgumentException('Array must contain integer keys and numeric values only!');
122
        }
123
124 2
        $this->columnWidths = $columnWidths + $this->columnWidths;
125 2
    }
126
127
    /**
128
     * Set lower and/or upper limits for column widths.
129
     *
130
     * @param float|null $minWidth
131
     * @param float|null $maxWidth
132
     */
133 2
    public function setColumnWidthLimits($minWidth = null, $maxWidth = null)
134
    {
135 2
        $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 string. However, the property $minColumnWidth is declared as type double|integer. 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 2
        $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 string. However, the property $maxColumnWidth is declared as type double|integer. 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...
137 2
    }
138
139
    /**
140
     * Return array containing all column widths, limited to min or max
141
     * column width, if one or both of them are set.
142
     *
143
     * @return array
144
     */
145 5
    public function getColumnWidths()
146
    {
147 5
        foreach ($this->columnWidths as $column => $width) {
148 5
            if ($width > $this->maxColumnWidth) {
149 1
                $this->columnWidths[$column] = $this->maxColumnWidth;
150 5
            } elseif ($width < $this->minColumnWidth) {
151 1
                $this->columnWidths[$column] = $this->minColumnWidth;
152 1
            }
153 5
        }
154
155 5
        return $this->columnWidths;
156
    }
157
158
    /**
159
     * Add single row and style to sheet.
160
     *
161
     * @param array $row
162
     * @param Style $style
163
     *
164
     * @return string
165
     */
166 5
    public function addRow(array $row, Style $style)
167
    {
168 5
        $columnCount = count($row);
169 5
        $this->updateMaxColumnCount($columnCount);
170 5
        $cellXml = $this->getCellXml($row, $style);
171
172 5
        return $this->getRowXml($columnCount, $cellXml);
173
    }
174
175
    /**
176
     * Track column count for dimensions xml (e.g. A1:K123).
177
     *
178
     * @param int $columnCount
179
     */
180 5
    private function updateMaxColumnCount($columnCount)
181
    {
182 5
        if ($this->maxColumnCount < $columnCount) {
183 5
            $this->maxColumnCount = $columnCount;
184 5
        }
185 5
    }
186
187
    /**
188
     * Build and return xml string for single row.
189
     *
190
     * @param int    $columnCount
191
     * @param string $cellXml
192
     * @return string
193
     */
194 5
    private function getRowXml($columnCount, $cellXml)
195
    {
196 5
        return sprintf(RowXml::DEFAULT_XML, $this->rowIndex++, $columnCount, $cellXml);
197
    }
198
199
    /**
200
     * Build and return xml string for single cell and update cell widths.
201
     *
202
     * @param array $row
203
     * @param Style $style
204
     * @return string
205
     */
206 5
    private function getCellXml(array $row, Style $style)
207
    {
208 5
        $cellXml = '';
209 5
        foreach (array_values($row) as $cellIndex => $cellValue) {
210 5
            $this->updateColumnWidths($cellValue, $cellIndex, $style->getFont());
211 5
            $cellXml .= $this->cellBuilder->build(
212 5
                $this->rowIndex, $cellIndex, $cellValue, $style->getId()
213 5
            );
214 5
        }
215
216 5
        return $cellXml;
217
    }
218
219
    /**
220
     * Track cell width for column width sizing if its enabled.
221
     *
222
     * @param mixed $value
223
     * @param int   $cellIndex
224
     * @param Font  $font
225
     */
226 5
    private function updateColumnWidths($value, $cellIndex, Font $font)
227
    {
228 5
        if ($this->useCellAutosizing) {
229 4
            $cellWidth = $this->sizeCalculator->getCellWidth($font->getName(), $font->getSize(), $value);
230 4
            if (!isset($this->columnWidths[$cellIndex])
231 4
                || $this->columnWidths[$cellIndex] < $cellWidth
232 4
            ) {
233 4
                $this->columnWidths[$cellIndex] = $cellWidth;
234 4
            }
235 4
        }
236 5
    }
237
238
    /**
239
     * Return <dimension> xml string.
240
     *
241
     * @return string
242
     */
243 1
    public function getDimensionXml()
244
    {
245 1
        return sprintf(SheetXml::DIMENSION_XML,
246 1
            $this->cellBuilder->getCellId($this->maxColumnCount - 1, $this->rowIndex - 1)
247 1
        );
248
    }
249
250
    /**
251
     * Return <sheetViews> xml containing the freeze pane.
252
     *
253
     * @return string
254
     */
255 2
    public function getSheetViewsXml()
256
    {
257 2
        if (1 !== preg_match('~^[A-Z]+(\d+)$~', $this->freezePaneCellId, $m)) {
258 2
            return '';
259
        }
260
261 1
        return sprintf(SheetXml::SHEETVIEWS_XML, array_pop($m) - 1, $this->freezePaneCellId);
262
    }
263
264
    /**
265
     * Return <cols> xml for column widths or an empty string,
266
     * if there are no column widths.
267
     * Format widths to account for locales with comma as decimal point.
268
     *
269
     * @return string
270
     */
271 1
    public function getColsXml()
272
    {
273 1
        $colsXml = '';
274 1
        if (0 !== count($this->getColumnWidths())) {
275 1
            foreach ($this->getColumnWidths() as $columnIndex => $columnWidth) {
276 1
                $columnNumber = $columnIndex + 1;
277 1
                $colsXml .= sprintf(
278 1
                    SheetXml::COLUMN_XML, $columnNumber, $columnNumber, number_format($columnWidth, 3, '.', '')
279 1
                );
280 1
            }
281 1
            $colsXml = sprintf('<cols>%s</cols>', $colsXml);
282 1
        }
283
284 1
        return $colsXml;
285
    }
286
287
    /**
288
     * Return array of available font names and paths.
289
     *
290
     * @return array
291
     */
292
    public function getFonts()
293
    {
294
        return $this->sizeCalculator->getFonts();
295
    }
296
}
297