Passed
Push — master ( df8a5f...c1e10f )
by Roman
05:17
created

AbstractFormatter::initSidebar()   C

Complexity

Conditions 8
Paths 12

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 27
ccs 22
cts 22
cp 1
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 17
nc 12
nop 0
crap 8
1
<?php
2
3
namespace ToolkitLab\ASCII;
4
5
use ToolkitLab\ASCII\Table;
6
7
abstract class AbstractFormatter implements FormatterInterface {
8
    
9
    const
10
        DEFAULT_MODE              = 0x00,
11
12
        HEADER_FIRST_ROW_MODE     = 0X01,
13
        HEADER_NUMERIC_MODE       = 0x02,
14
        HEADER_ABC_MODE           = 0X04,
15
            
16
        SIDEBAR_NUMERIC_MODE      = 0X10,
17
        SIDEBAR_ABC_MODE          = 0x20,
18
            
19
        SPREADSHEET_MODE          = 0X14;
20
21
    /**
22
     * @var Table
23
     */
24
    protected $table;
25
26
    /**
27
     * @var array
28
     */
29
    protected $metadata = [];
30
31
    /**
32
     * @var string
33
     */
34
    protected $output = '';
35
36
    /**
37
     * The data to be formatted
38
     * @var array
39
     */
40
    protected $data = [];
41
    
42
    /**
43
     * @var boolean
44
     */
45
    protected $useHeader = false;
46
47
    /**
48
     * Formatting parameters
49
     * @var array
50
     */
51
    protected $params = [
52
        'mode' => self::DEFAULT_MODE,
53
        'rotate' => false,
54
        'max_cell_length' => 100,
55
        'max_cell_ending' => '...',
56
    ];
57
58
    /**
59
     * Constructor
60
     * @param array $params
61
     */
62 40
    public function __construct($params = []) {
63 40
        $this->setParams($params);
64 38
    }
65
66
    /**
67
     * Converts an array into ASCII-formatted string (table)
68
     * @param mixed $data
69
     * @param array $params
70
     * @return string
71
     */
72 38
    public function format($data, $params = []) {
73 38
        $table = $data instanceof Table ? $data : new Table($data);
74 38
        $this->init($table, $params);
75 34
        $this->addTopBorder();
76 34
        $this->addHeader();
77 34
        $this->addRows();
78 34
        $this->addBottomBorder();
79 34
        return $this->output;
80
    }
81
82
    /**
83
     * Initializes the data/parameters before formatting
84
     * @param Table $table
85
     * @param array $params
86
     * @return void
87
     */
88 38
    protected function init(Table $table, $params = []) {
89 38
        $this->output = '';
90 38
        $this->setParams($params);
91 38
        $this->table = $table;
92 38
        if ($this->getParam('rotate') !== false) {
93 8
            $this->table->rotate($this->getParam('rotate'));
94 8
        }
95 38
        $this->initHeader();
96 36
        $this->initSidebar();
97 34
        $maxLength = $this->getParam('max_cell_length');
98 34
        $ending = $this->getParam('max_cell_ending');
99 34
        $this->table->truncate($maxLength, $ending);
100 34
    }
101
    
102
    /**
103
     * Initializes the header
104
     * @throws \LogicException
105
     */
106 38
    protected function initHeader() {
107 38
        $count = 0;
108 38
        $mode = $this->getParam('mode');
109 38
        $data = $this->table->getData();
110 38
        $x = $this->table->getDimensionX();
111
        
112 38
        if (($mode & self::HEADER_FIRST_ROW_MODE) === self::HEADER_FIRST_ROW_MODE) {
113 10
            $count++;
114 10
        }
115
        
116 38
        if (($mode & self::HEADER_ABC_MODE) === self::HEADER_ABC_MODE) {
117 6
            $data = array_merge([$this->getAbcRange($x)], $data);
118 6
            $count++;
119 6
        }
120
        
121 38
        if (($mode & self::HEADER_NUMERIC_MODE) === self::HEADER_NUMERIC_MODE) {
122 4
            $data = array_merge([range(1, $x)], $data);
123 4
            $count++;
124 4
        }
125
        
126 38
        if ($count > 1) {
127 2
            throw new \LogicException('There should be only one header.');
128
        }
129
        
130 36
        if ($count) {
131 16
            $this->useHeader = true;
132 16
            $this->table->setData($data);
133 16
        }
134 36
    }
135
    
136
    /**
137
     * Initializes the sidebar
138
     * @throws \LogicException
139
     */
140 36
    protected function initSidebar() {
141 36
        $count = 0;
142 36
        $mode = $this->getParam('mode');
143 36
        $data = $this->table->getData();
144
        
145 36
        if (($mode & self::SIDEBAR_ABC_MODE) === self::SIDEBAR_ABC_MODE) {
146 4
            $y = $this->table->getDimensionY();
147 4
            $abc = $this->getAbcRange($y);
148 4
            foreach ($data as $key => $val) {
149 4
                $data[$key] = array_merge([array_shift($abc)], $val);
150 4
            }
151 4
            $count++;
152 4
        }
153
        
154 36
        if (($mode & self::SIDEBAR_NUMERIC_MODE) === self::SIDEBAR_NUMERIC_MODE) {
155 4
            foreach ($data as $key => $val) {
156 4
                $data[$key] = array_merge([$key ? $key : ''], $val);
157 4
            }
158 4
            $count++;
159 4
        }
160
        
161 36
        if ($count > 1) {
162 2
            throw new \LogicException('There should be only one sidebar.');
163
        }
164
        
165 34
        if ($count) {
166 4
            $this->table->setData($data);
167 4
        }
168 34
    }
169
    
170
    /**
171
     * Updates the parameters with new values
172
     * @param array $params
173
     * @throws \InvalidArgumentException
174
     */
175 40
    protected function setParams($params) {
176 40
        $unknownParams = array_diff(array_keys($params), array_keys($this->params));
177 40
        if (count($unknownParams)) {
178 2
            throw new \InvalidArgumentException('Unknown parameter(-s): ' . implode(', ', $unknownParams));
179
        }
180 38
        $this->params = array_merge($this->params, $params);
181 38
    }
182
183
    /**
184
     * Get the specified parameter
185
     * @param string $key
186
     * @return mixed
187
     */
188 38
    protected function getParam($key) {
189 38
        return $this->params[$key];
190
    }
191
    
192
    /**
193
     * Returns an array of letters for a spreadsheet header
194
     * @param int $length
195
     * @return array
196
     */
197 10
    final protected function getAbcRange($length) {
198 10
        $baseRange = range('A', 'Z');
199 10
        $range = range('A', 'Z');
200 10
        while (count($range) < $length && count($baseRange) > 1) {
201 2
            $letter = array_shift($baseRange);
202 2
            $tmpRange = range('A', 'Z');
203
            array_walk($tmpRange, function(&$e) use ($letter) { $e = $letter . $e; });
204 2
            $range = array_merge($range, $tmpRange);
205 2
        }
206 10
        return array_slice($range, 0, $length);
207
    }
208
209
    /**
210
     * Adds the top border to the output
211
     * @return void
212
     */
213 34
    protected function addTopBorder() {
214 34
        if ($this->metadata['top_border']) {
215 30
            $this->addRow(
216 30
                $this->metadata['top_border']['left'],
217 30
                $this->metadata['top_border']['middle'],
218 30
                $this->metadata['top_border']['right'],
219 30
                $this->metadata['top_border']['pad']
220 30
            );
221 30
        }
222 34
    }
223
224
    /**
225
     * Adds the header row to the output
226
     * @return void
227
     */
228 34
    protected function addHeader() {
229 34
        if ($this->useHeader) {
230 16
            $data = $this->table->getData();
231 16
            $x = $this->table->getDimensionX();
232 16
            $y = $this->table->getDimensionY();
233 16
            $this->addDataRow(array_shift($data));
234 16
            $this->addHeaderBorder();
235 16
            $this->table->setData($data, $x, $y);
236 16
        }
237 34
    }
238
239
    /**
240
     * Adds the rows to the output
241
     */
242 34
    protected function addRows() {
243 34
        $data = $this->table->getData();
244 34
        array_walk($data, [$this, 'addDataRow']);
245 34
    }
246
247
    /**
248
     * Adds the row with the specified data to the output
249
     * @param array $row
250
     * @return void
251
     */
252 34
    protected function addDataRow($row) {
253 34
        $this->addRow(
254 34
            $this->metadata['content']['left'],
255 34
            $this->metadata['content']['middle'],
256 34
            $this->metadata['content']['right'],
257 34
            $this->metadata['content']['pad'],
258
            $row
259 34
        );
260 34
    }
261
262
    /**
263
     * Adds the bottom border of the header to the output
264
     * @return void
265
     */
266 16
    protected function addHeaderBorder() {
267 16
        $this->addRow(
268 16
            $this->metadata['header']['left'],
269 16
            $this->metadata['header']['middle'],
270 16
            $this->metadata['header']['right'],
271 16
            $this->metadata['header']['pad']
272 16
        );
273 16
    }
274
275
    /**
276
     * Adds the bottom border to the output
277
     * @return void
278
     */
279 34
    protected function addBottomBorder() {
280 34
        if ($this->metadata['bottom_border']) {
281 30
            $this->addRow(
282 30
                $this->metadata['bottom_border']['left'],
283 30
                $this->metadata['bottom_border']['middle'],
284 30
                $this->metadata['bottom_border']['right'],
285 30
                $this->metadata['bottom_border']['pad']
286 30
            );
287 30
        }
288 34
    }
289
290
    /**
291
     * Adds the row to the output
292
     * @param string $lb
293
     * @param string $bm
294
     * @param string $br
295
     * @param string $pad
296
     * @param array $row
297
     * @return void
298
     */
299 34
    protected function addRow($lb, $bm, $br, $pad, $row = []) {
300 34
        $delimiter = $lb;
301 34
        for ($i = 0; $i < $this->table->getDimensionX(); $i++) {
302 34
            $maxLength = $this->table->getColumnsMaxLength($i);
303 34
            $this->output .= $delimiter;
304 34
            if (count($row)) {
305 34
                $spaces = str_repeat($pad, $maxLength - strlen($row[$i]));
306 34
                $this->output .= " {$row[$i]}{$spaces} ";
307 34
            } else {
308 32
                $this->output .= str_repeat($pad, $maxLength + 2);
309
            }
310 34
            $delimiter = $bm;
311 34
        }
312 34
        $this->output .= $br . PHP_EOL;
313 34
    }
314
315
}
316