1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the ReportBundle package |
5
|
|
|
* |
6
|
|
|
* (c) symball <http://simonball.me> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE file |
9
|
|
|
* that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
|
13
|
|
|
namespace Symball\ReportBundle\Service; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* The navigation service is responsible for handling the position of the |
17
|
|
|
* spreadsheet pointer |
18
|
|
|
* |
19
|
|
|
* @author Simon Ball <simonball at simonball dot me> |
20
|
|
|
*/ |
21
|
|
|
abstract class Nav |
22
|
|
|
{ |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @var int Used to determine the initial column |
26
|
|
|
*/ |
27
|
|
|
protected $columnInitial; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var int Used to determine the initial row |
31
|
|
|
*/ |
32
|
|
|
protected $rowInitial; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var int Tracks the column to go to when the user resets |
36
|
|
|
*/ |
37
|
|
|
protected $columnSetStart; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var int Tracks the row to go to when the user resets |
41
|
|
|
*/ |
42
|
|
|
protected $rowSetStart; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @var int Head column |
46
|
|
|
*/ |
47
|
|
|
protected $columnCurrent; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* @var int Head row |
51
|
|
|
*/ |
52
|
|
|
protected $rowCurrent; |
53
|
|
|
|
54
|
|
|
protected $status = 'initial'; |
55
|
|
|
|
56
|
|
|
protected $columnCount = 0; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @param int $columnInitial Determine the starting column to use |
60
|
|
|
* @param int $rowInitial Determine the starting row to use |
61
|
|
|
*/ |
62
|
|
|
public function __construct($columnInitial = 2, $rowInitial = 3) |
63
|
|
|
{ |
64
|
|
|
// Set all tracking data to the preset |
65
|
|
|
$this->columnInitial = $this->columnSetStart = $this->columnCurrent = $columnInitial; |
66
|
|
|
$this->rowInitial = $this->rowSetStart = $this->rowCurrent = $rowInitial; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Move the cursor position to the starting area for the next data point or |
71
|
|
|
* later depending on the argument passed |
72
|
|
|
* |
73
|
|
|
* @param integer $count |
74
|
|
|
* @return $this |
75
|
|
|
*/ |
76
|
|
|
public function movePointerAlong($count = 1) |
77
|
|
|
{ |
78
|
|
|
|
79
|
|
|
$this |
80
|
|
|
->columnReset('set') |
81
|
|
|
->rowReset('initial') |
82
|
|
|
->axisYMove($count) |
83
|
|
|
->setStartColumn(); |
84
|
|
|
|
85
|
|
|
return $this; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* @return string Get the current coordinates in an excel friendly manner |
90
|
|
|
*/ |
91
|
|
|
public function __toString() |
92
|
|
|
{ |
93
|
|
|
return $this->coord(); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Move the pointer up x (default 1) amount of places. |
98
|
|
|
* |
99
|
|
|
* @param int $placesToMove |
100
|
|
|
* @return $this |
101
|
|
|
*/ |
102
|
|
|
public function up($placesToMove = 1) |
103
|
|
|
{ |
104
|
|
|
// Check for validity of movement |
105
|
|
|
if (0 >= ($this->rowCurrent - $placesToMove)) { |
106
|
|
|
throw new \Exception('Movement would go out of bounds'); |
107
|
|
|
} |
108
|
|
|
$this->rowCurrent -= $placesToMove; |
109
|
|
|
|
110
|
|
|
return $this; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Move the pointer right x (default 1) amount of places. |
115
|
|
|
* |
116
|
|
|
* @param int $placesToMove |
117
|
|
|
* @return $this |
118
|
|
|
*/ |
119
|
|
|
public function right($placesToMove = 1) |
120
|
|
|
{ |
121
|
|
|
$this->columnCurrent += $placesToMove; |
122
|
|
|
|
123
|
|
|
return $this; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Move the pointer down x (default 1) amount of places. |
128
|
|
|
* |
129
|
|
|
* @param int $placesToMove |
130
|
|
|
* |
131
|
|
|
* @return $this |
132
|
|
|
*/ |
133
|
|
|
public function down($placesToMove = 1) |
134
|
|
|
{ |
135
|
|
|
$this->rowCurrent += $placesToMove; |
136
|
|
|
|
137
|
|
|
return $this; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Move the pointer left x (default 1) amount of places. |
142
|
|
|
* |
143
|
|
|
* @param int $placesToMove |
144
|
|
|
* |
145
|
|
|
* @return $this |
146
|
|
|
*/ |
147
|
|
|
public function left($placesToMove = 1) |
148
|
|
|
{ |
149
|
|
|
if (0 >= ($this->columnCurrent - $placesToMove)) { |
150
|
|
|
throw new \Exception('Movement would go out of bounds'); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
$this->columnCurrent -= $placesToMove; |
154
|
|
|
|
155
|
|
|
return $this; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Reset the row pointer to starting area of either spreadsheet or set |
160
|
|
|
* |
161
|
|
|
* @param string $type |
162
|
|
|
* @return $this |
163
|
|
|
*/ |
164
|
|
|
public function rowReset($type = 'initial') |
165
|
|
|
{ |
166
|
|
|
switch ($type) { |
167
|
|
|
case 'initial': |
168
|
|
|
$this->rowCurrent = $this->rowSetStart = $this->rowInitial; |
169
|
|
|
break; |
170
|
|
|
|
171
|
|
|
case 'set': |
172
|
|
|
$this->rowCurrent = $this->rowSetStart; |
173
|
|
|
break; |
174
|
|
|
|
175
|
|
|
default: |
176
|
|
|
break; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
return $this; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Reset the column pointer to starting area of either spreadsheet or set |
184
|
|
|
* |
185
|
|
|
* @param string $type |
186
|
|
|
* @return $this |
187
|
|
|
*/ |
188
|
|
|
public function columnReset($type = 'initial') |
189
|
|
|
{ |
190
|
|
|
switch ($type) { |
191
|
|
|
case 'initial': |
192
|
|
|
$this->columnCurrent = $this->columnSetStart = $this->columnInitial; |
193
|
|
|
break; |
194
|
|
|
|
195
|
|
|
case 'set': |
196
|
|
|
$this->columnCurrent = $this->columnSetStart; |
197
|
|
|
break; |
198
|
|
|
|
199
|
|
|
default: |
200
|
|
|
break; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
return $this; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Reset both the and column pointer to either spreadsheet or set |
208
|
|
|
* |
209
|
|
|
* @param string $type The human friendly syntax for what position to use |
210
|
|
|
* @return $this |
211
|
|
|
*/ |
212
|
|
|
public function reset($type = 'intitial') |
213
|
|
|
{ |
214
|
|
|
$this->rowReset($type); |
215
|
|
|
$this->columnReset($type); |
216
|
|
|
|
217
|
|
|
return $this; |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* Update the current entry for what is considered the starting column. |
222
|
|
|
* |
223
|
|
|
* @return $this |
224
|
|
|
*/ |
225
|
|
|
public function setStartColumn() |
226
|
|
|
{ |
227
|
|
|
$this->columnSetStart = $this->columnCurrent; |
228
|
|
|
|
229
|
|
|
return $this; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Get the spreadsheet object coord from a numeric value |
234
|
|
|
* If no parameters are used, the context coord will be returned. |
235
|
|
|
* |
236
|
|
|
* @param string|integer $column Either integer index or human friendly syntax |
237
|
|
|
* @param string|integer $row Either integer index or human friendly syntax |
238
|
|
|
* |
239
|
|
|
* @return string|interger [description] |
240
|
|
|
*/ |
241
|
|
|
public function coord($column = false, $row = false) |
242
|
|
|
{ |
243
|
|
|
if (!$column) { |
244
|
|
|
$column = $this->columnCurrent; |
245
|
|
|
} |
246
|
|
|
if (!$row) { |
247
|
|
|
$row = $this->rowCurrent; |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
$column = $this->parseNavReference($column, 'column'); |
251
|
|
|
$row = $this->parseNavReference($row, 'row'); |
252
|
|
|
|
253
|
|
|
return $this->nmbToClm($column) . $row; |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* Parse a number in to letter format. |
258
|
|
|
* |
259
|
|
|
* @param int $num |
260
|
|
|
* |
261
|
|
|
* @return string |
262
|
|
|
*/ |
263
|
|
|
public function nmbToClm($num) |
264
|
|
|
{ |
265
|
|
|
$numeric = ($num - 1) % 26; |
266
|
|
|
$letter = chr(65 + $numeric); |
267
|
|
|
$num2 = intval(($num - 1) / 26); |
268
|
|
|
if ($num2 > 0) { |
269
|
|
|
return $this->nmbToClm($num2) . $letter; |
270
|
|
|
} else { |
271
|
|
|
return $letter; |
272
|
|
|
} |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* A helper function for returning numerical coordinates. |
277
|
|
|
* |
278
|
|
|
* @param string $input |
279
|
|
|
* @param string $axis |
280
|
|
|
* |
281
|
|
|
* @return integer |
282
|
|
|
*/ |
283
|
|
|
public function parseNavReference($input = '', $axis = 'column') |
284
|
|
|
{ |
285
|
|
|
switch ($input) { |
286
|
|
|
case 'initial': |
287
|
|
|
$propertyName = $axis . 'Initial'; |
288
|
|
|
break; |
289
|
|
|
|
290
|
|
|
case 'set': |
291
|
|
|
$propertyName = $axis . 'Start'; |
292
|
|
|
break; |
293
|
|
|
|
294
|
|
|
case 'current': |
295
|
|
|
$propertyName = $axis . 'Current'; |
296
|
|
|
break; |
297
|
|
|
|
298
|
|
|
default: |
299
|
|
|
if (is_int($input)) { |
300
|
|
|
return $input; |
301
|
|
|
} |
302
|
|
|
break; |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
if(isset($propertyName)) { |
306
|
|
|
return $this->$propertyName; |
307
|
|
|
} |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* Return the column value according to various criteria, defaulting to |
312
|
|
|
* current. |
313
|
|
|
* |
314
|
|
|
* @param string $type |
315
|
|
|
* @param bool $asLetter |
316
|
|
|
* |
317
|
|
|
* @return string|integer The column pointer as either index or letter |
318
|
|
|
*/ |
319
|
|
|
public function column($type = 'current', $asLetter = false) |
320
|
|
|
{ |
321
|
|
|
if ($type == false || $type == '') { |
|
|
|
|
322
|
|
|
$type = 'current'; |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
$column = $this->parseNavReference($type); |
326
|
|
|
|
327
|
|
|
if ($asLetter) { |
328
|
|
|
return $this->nmbToClm($column); |
329
|
|
|
} else { |
330
|
|
|
return $column; |
331
|
|
|
} |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* Return the row value according to various criteria, defaulting to current. |
336
|
|
|
* |
337
|
|
|
* @param string $type |
338
|
|
|
* |
339
|
|
|
* @return int The row index |
340
|
|
|
*/ |
341
|
|
|
public function row($type = 'current') |
342
|
|
|
{ |
343
|
|
|
return $this->parseNavReference($type, 'row'); |
344
|
|
|
} |
345
|
|
|
} |
346
|
|
|
|