Completed
Push — master ( b68650...58f9ca )
by Stefan
02:39
created

DefaultCellBuilder::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 11
ccs 9
cts 9
cp 1
rs 9.4285
cc 3
eloc 6
nc 3
nop 0
crap 3
1
<?php
2
/**
3
 * @author neun
4
 * @since  2016-07-11
5
 */
6
7
namespace OneSheet;
8
9
/**
10
 * Class DefaultCellBuilder to build xml cell strings.
11
 * Wheter a numeric value is written as a number or string type cell
12
 * is simply determined by type, to allow for some control by typecasting.
13
 * (Premature) performance considerations (50.000 rows x 15 columns):
14
 * - sprintf 8.3s
15
 * - '<c>' . $value . '</c>' 8.1s
16
 * - "<c>{$value}</c>" 7.9s
17
 * @package OneSheet
18
 */
19
class DefaultCellBuilder implements CellBuilderInterface
20
{
21
    /**
22
     * A-Z character array to build cell ids.
23
     *
24
     * @var array
25
     */
26
    private $characters = array();
27
28
    /**
29
     * Array of control characters that should be escaped.
30
     *
31
     * @var array
32
     */
33
    private $controlCharacters = array();
34
35
    /**
36
     * Array of escape characters to replace control characters.
37
     *
38
     * @var array
39
     */
40
    private $escapeCharacters = array();
41
42
    /**
43
     * CellBuilder constructor to instantiate character properties.
44
     */
45 4
    public function __construct()
46
    {
47 4
        $this->characters = range('A', 'Z');
48
49 4
        for ($i = 0; $i <= 255; $i++) {
50 4
            if (ctype_cntrl($char = chr($i))) {
51 4
                $this->controlCharacters[] = $char;
52 4
                $this->escapeCharacters[] = sprintf('_x%04s_', strtoupper(dechex($i)));
53 4
            }
54 4
        }
55 4
    }
56
57
    /**
58
     * Build and return the string for a single cell.
59
     *
60
     * @param int    $rowNumber
61
     * @param int    $cellNumber
62
     * @param string $value
63
     * @param int    $styleId
64
     * @return string
65
     */
66 2
    public function build($rowNumber, $cellNumber, $value, $styleId = 0)
67
    {
68 2
        $cellId = $this->getCellId($cellNumber, $rowNumber);
69
70 2
        if (is_int($value) || is_double($value)) {
71 2
            return sprintf(CellXml::NUMBER_XML, $cellId, $styleId, $value);
72 2
        } elseif (ctype_alnum($value) || is_numeric($value)) {
73 2
            return sprintf(CellXml::STRING_XML, $cellId, $styleId, $value);
74 1
        } elseif (is_bool($value)) {
75 1
            return sprintf(CellXml::BOOLEAN_XML, $cellId, $styleId, (int)$value);
76 1
        } elseif (ctype_print($value)) {
77 1
            return sprintf(CellXml::STRING_XML, $cellId, $styleId, htmlspecialchars($value, ENT_QUOTES));
78 1
        } elseif (0 == strlen($value)) {
79 1
            return '';
80
        } else {
81 1
            return sprintf(CellXml::STRING_XML, $cellId, $styleId, $this->escapeControlCharacters($value));
82
        }
83
    }
84
85
    /**
86
     * Turn a integer cell number + row number into a valid cell identifier
87
     * like e.g. A1, Z1, AA1 etc and return it.
88
     *
89
     * @param int      $cellNumber
90
     * @param int|null $rowNumber
91
     * @return string
92
     */
93 2
    private function getCellId($cellNumber, $rowNumber = null)
94
    {
95 2
        if ($cellNumber / 26 < 1) {
96 2
            return $this->characters[$cellNumber] . $rowNumber;
97
        }
98
99 1
        return $this->getCellId(floor($cellNumber / 26) - 1) . $this->characters[$cellNumber % 26] . $rowNumber;
100
    }
101
102
    /**
103
     * Replace control characters with escape characters.
104
     *
105
     * @param string $value
106
     * @return string
107
     */
108 1
    private function escapeControlCharacters($value)
109
    {
110 1
        return str_replace($this->controlCharacters, $this->escapeCharacters, htmlspecialchars($value, ENT_QUOTES));
111
    }
112
}
113