1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Cerbero\Workflow\Console\Drawing; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Geometry applied to the drawing. |
7
|
|
|
* |
8
|
|
|
* @author Andrea Marco Sartori |
9
|
|
|
*/ |
10
|
|
|
class Geometry |
11
|
|
|
{ |
12
|
|
|
const BORDER_WIDTH = 1; |
13
|
|
|
|
14
|
|
|
const MIN_SPACE_FROM_BORDER_X = 1; |
15
|
|
|
|
16
|
|
|
const MIN_SPACE_FROM_BORDER_Y = 0; |
17
|
|
|
|
18
|
|
|
const ARROW_WIDTH = 1; |
19
|
|
|
|
20
|
|
|
const MIN_PIPE_LENGTH = 8; |
21
|
|
|
|
22
|
|
|
const SPACE_FROM_ARROW = 1; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @author Andrea Marco Sartori |
26
|
|
|
* |
27
|
|
|
* @var string $core The name of the core. |
28
|
|
|
*/ |
29
|
|
|
protected $core; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @author Andrea Marco Sartori |
33
|
|
|
* |
34
|
|
|
* @var array $pipes List of pipes. |
35
|
|
|
*/ |
36
|
|
|
protected $pipes; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @author Andrea Marco Sartori |
40
|
|
|
* |
41
|
|
|
* @var int $nesting Nesting level. |
42
|
|
|
*/ |
43
|
|
|
protected $nesting = 0; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Set the name of the core. |
47
|
|
|
* |
48
|
|
|
* @author Andrea Marco Sartori |
49
|
|
|
* |
50
|
|
|
* @param string $core |
51
|
|
|
* |
52
|
|
|
* @return void |
53
|
|
|
*/ |
54
|
12 |
|
public function setCore($core) |
55
|
|
|
{ |
56
|
12 |
|
$this->core = $core; |
57
|
12 |
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Set the pipes. |
61
|
|
|
* |
62
|
|
|
* @author Andrea Marco Sartori |
63
|
|
|
* |
64
|
|
|
* @param array $pipes |
65
|
|
|
* |
66
|
|
|
* @return void |
67
|
|
|
*/ |
68
|
12 |
|
public function setPipes(array $pipes) |
69
|
|
|
{ |
70
|
12 |
|
$this->pipes = $pipes; |
71
|
12 |
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* Calculate the half width of the drawing. |
75
|
|
|
* |
76
|
|
|
* @author Andrea Marco Sartori |
77
|
|
|
* |
78
|
|
|
* @param bool $up |
79
|
|
|
* |
80
|
|
|
* @return int |
81
|
|
|
*/ |
82
|
12 |
|
public function getHalfWidth($up = false) |
83
|
|
|
{ |
84
|
12 |
|
$number = $this->getTotalWidth(); |
85
|
|
|
|
86
|
12 |
|
return $this->roundHalf($number, $up); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* Round the half of a number, either up or down. |
91
|
|
|
* |
92
|
|
|
* @author Andrea Marco Sartori |
93
|
|
|
* |
94
|
|
|
* @param int $number |
95
|
|
|
* @param bool $up |
96
|
|
|
* |
97
|
|
|
* @return int |
98
|
|
|
*/ |
99
|
12 |
|
private function roundHalf($number, $up) |
100
|
|
|
{ |
101
|
12 |
|
$round = $up ? 'ceil' : 'floor'; |
102
|
|
|
|
103
|
12 |
|
return $round($number / 2); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Calculate the total width of the drawing. |
108
|
|
|
* |
109
|
|
|
* @author Andrea Marco Sartori |
110
|
|
|
* |
111
|
|
|
* @return int |
112
|
|
|
*/ |
113
|
12 |
|
protected function getTotalWidth() |
114
|
|
|
{ |
115
|
12 |
|
$borders = (static::BORDER_WIDTH + static::MIN_SPACE_FROM_BORDER_X) * 2; |
116
|
|
|
|
117
|
12 |
|
if (empty($this->pipes)) { |
118
|
3 |
|
return $borders + $this->getCoreLength(); |
119
|
|
|
} |
120
|
|
|
|
121
|
9 |
|
$borders *= count($this->pipes); |
122
|
|
|
|
123
|
9 |
|
$name = ($this->getLongestPipeLength() + static::SPACE_FROM_ARROW) * 2; |
124
|
|
|
|
125
|
9 |
|
return $borders + $name + static::ARROW_WIDTH; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Calculate the length of the core name. |
130
|
|
|
* |
131
|
|
|
* @author Andrea Marco Sartori |
132
|
|
|
* |
133
|
|
|
* @return int |
134
|
|
|
*/ |
135
|
12 |
|
protected function getCoreLength() |
136
|
|
|
{ |
137
|
12 |
|
return strlen($this->core); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Calculate the length of the longest pipe name. |
142
|
|
|
* |
143
|
|
|
* @author Andrea Marco Sartori |
144
|
|
|
* |
145
|
|
|
* @return int |
146
|
|
|
*/ |
147
|
9 |
|
protected function getLongestPipeLength() |
148
|
|
|
{ |
149
|
9 |
|
if (empty($this->pipes)) { |
150
|
|
|
return 0; |
151
|
|
|
} |
152
|
|
|
|
153
|
9 |
|
return array_reduce($this->pipes, function ($carry, $pipe) { |
154
|
9 |
|
return strlen($pipe) > $carry ? strlen($pipe) : $carry; |
155
|
|
|
|
156
|
9 |
|
}, static::MIN_PIPE_LENGTH); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* Retrieve the spaced pipe and method pair. |
161
|
|
|
* |
162
|
|
|
* @author Andrea Marco Sartori |
163
|
|
|
* |
164
|
|
|
* @param string $pipe |
165
|
|
|
* @param string $arrow |
166
|
|
|
* @param string $method |
167
|
|
|
* |
168
|
|
|
* @return string |
169
|
|
|
*/ |
170
|
9 |
|
public function getSpacedPipe($pipe, $arrow, $method) |
171
|
|
|
{ |
172
|
9 |
|
$left = $this->getSpacesByWord($pipe); |
173
|
|
|
|
174
|
9 |
|
$arrow = $this->addSpacesToArrow($arrow); |
175
|
|
|
|
176
|
9 |
|
$right = $this->getSpacesByWord($method); |
177
|
|
|
|
178
|
9 |
|
return $left.$pipe.$arrow.$method.$right; |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* Retrieve the blank spaces close to a word. |
183
|
|
|
* |
184
|
|
|
* @author Andrea Marco Sartori |
185
|
|
|
* |
186
|
|
|
* @param string $word |
187
|
|
|
* |
188
|
|
|
* @return string |
189
|
|
|
*/ |
190
|
9 |
|
protected function getSpacesByWord($word) |
191
|
|
|
{ |
192
|
9 |
|
$length = $this->getSideBordersLength() + static::SPACE_FROM_ARROW + static::ARROW_WIDTH; |
193
|
|
|
|
194
|
9 |
|
$extra = $this->getHalfWidth(true) - $length - strlen($word); |
195
|
|
|
|
196
|
9 |
|
return $extra > 0 ? str_repeat(' ', $extra) : ''; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* Retrieve the length of the borders of a side. |
201
|
|
|
* |
202
|
|
|
* @author Andrea Marco Sartori |
203
|
|
|
* |
204
|
|
|
* @return int |
205
|
|
|
*/ |
206
|
12 |
|
protected function getSideBordersLength() |
207
|
|
|
{ |
208
|
12 |
|
$border = (static::BORDER_WIDTH + static::MIN_SPACE_FROM_BORDER_X); |
209
|
|
|
|
210
|
12 |
|
return $border * $this->nesting; |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Add spaces around the given arrow. |
215
|
|
|
* |
216
|
|
|
* @author Andrea Marco Sartori |
217
|
|
|
* |
218
|
|
|
* @param string $arrow |
219
|
|
|
* |
220
|
|
|
* @return string |
221
|
|
|
*/ |
222
|
9 |
|
protected function addSpacesToArrow($arrow) |
223
|
|
|
{ |
224
|
9 |
|
$spaces = str_repeat(' ', static::SPACE_FROM_ARROW); |
225
|
|
|
|
226
|
9 |
|
return "{$spaces}{$arrow}{$spaces}"; |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Retrieve the left borders formatted with the given border. |
231
|
|
|
* |
232
|
|
|
* @author Andrea Marco Sartori |
233
|
|
|
* |
234
|
|
|
* @param string $border |
235
|
|
|
* |
236
|
|
|
* @return string |
237
|
|
|
*/ |
238
|
12 |
|
public function getLeftBordersWith($border) |
239
|
|
|
{ |
240
|
12 |
|
$border = str_repeat($border, static::BORDER_WIDTH); |
241
|
|
|
|
242
|
12 |
|
$space = str_repeat(' ', static::MIN_SPACE_FROM_BORDER_X); |
243
|
|
|
|
244
|
12 |
|
return str_repeat("{$border}{$space}", $this->nesting); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* Retrieve the right borders formatted with the given border. |
249
|
|
|
* |
250
|
|
|
* @author Andrea Marco Sartori |
251
|
|
|
* |
252
|
|
|
* @param string $border |
253
|
|
|
* |
254
|
|
|
* @return string |
255
|
|
|
*/ |
256
|
12 |
|
public function getRightBordersWith($border) |
257
|
|
|
{ |
258
|
12 |
|
$space = str_repeat(' ', static::MIN_SPACE_FROM_BORDER_X); |
259
|
|
|
|
260
|
12 |
|
$border = str_repeat($border, static::BORDER_WIDTH); |
261
|
|
|
|
262
|
12 |
|
return str_repeat("{$space}{$border}", $this->nesting); |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
/** |
266
|
|
|
* Increase the nesting level. |
267
|
|
|
* |
268
|
|
|
* @author Andrea Marco Sartori |
269
|
|
|
* |
270
|
|
|
* @return void |
271
|
|
|
*/ |
272
|
12 |
|
public function increaseNesting() |
273
|
|
|
{ |
274
|
12 |
|
$this->nesting++; |
275
|
12 |
|
} |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* Calculate the width of the drawing without the borders. |
279
|
|
|
* |
280
|
|
|
* @author Andrea Marco Sartori |
281
|
|
|
* |
282
|
|
|
* @return int |
283
|
|
|
*/ |
284
|
12 |
|
public function getWidthButBorders() |
285
|
|
|
{ |
286
|
12 |
|
return $this->getTotalWidth() - $this->getBordersLength(); |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
/** |
290
|
|
|
* Calculate the length of the borders. |
291
|
|
|
* |
292
|
|
|
* @author Andrea Marco Sartori |
293
|
|
|
* |
294
|
|
|
* @return int |
295
|
|
|
*/ |
296
|
12 |
|
protected function getBordersLength() |
297
|
|
|
{ |
298
|
12 |
|
return $this->getSideBordersLength() * 2; |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
/** |
302
|
|
|
* Retrieve the spaced core name. |
303
|
|
|
* |
304
|
|
|
* @author Andrea Marco Sartori |
305
|
|
|
* |
306
|
|
|
* @return string |
307
|
|
|
*/ |
308
|
12 |
|
public function getSpacedCore() |
309
|
|
|
{ |
310
|
12 |
|
$left = $this->getSpacesByCore(); |
311
|
|
|
|
312
|
12 |
|
$right = $this->getSpacesByCore(true); |
313
|
|
|
|
314
|
12 |
|
return $left.$this->core.$right; |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
/** |
318
|
|
|
* Retrieve the blank spaces close to the core. |
319
|
|
|
* |
320
|
|
|
* @author Andrea Marco Sartori |
321
|
|
|
* |
322
|
|
|
* @param bool $up |
323
|
|
|
* |
324
|
|
|
* @return string |
325
|
|
|
*/ |
326
|
12 |
|
protected function getSpacesByCore($up = false) |
327
|
|
|
{ |
328
|
12 |
|
$free = $this->getTotalWidth() - $this->getBordersLength() - $this->getCoreLength(); |
329
|
|
|
|
330
|
12 |
|
return $free < 1 ? '' : str_repeat(' ', $this->roundHalf($free, $up)); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
/** |
334
|
|
|
* Decrease the nesting level. |
335
|
|
|
* |
336
|
|
|
* @author Andrea Marco Sartori |
337
|
|
|
* |
338
|
|
|
* @return void |
339
|
|
|
*/ |
340
|
12 |
|
public function decreaseNesting() |
341
|
|
|
{ |
342
|
12 |
|
$this->nesting--; |
343
|
12 |
|
} |
344
|
|
|
} |
345
|
|
|
|