Drawer::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
1
<?php namespace Cerbero\Workflow\Console\Drawing;
2
3
use Cerbero\Workflow\Repositories\PipelineRepositoryInterface;
4
5
/**
6
 * Class to generate the drawing.
7
 *
8
 * @author	Andrea Marco Sartori
9
 */
10
class Drawer {
11
12
	const BORDER_X = '║';
13
14
	const BORDER_Y = '═';
15
16
	const BORDER_NW = '╔';
17
18
	const BORDER_NE = '╗';
19
20
	const BORDER_SE = '╝';
21
22
	const BORDER_SW = '╚';
23
24
	const NOCK = '║';
25
26
	const PILE = '∇';
27
28
	const CROSSROADS = '╬';
29
30
	const CROSSROADS_UP = '╩';
31
32
	const CROSSROADS_DOWN = '╦';
33
34
	/**
35
	 * @author	Andrea Marco Sartori
36
	 * @var		Cerbero\Workflow\Repositories\PipelineRepositoryInterface	$pipelines	Pipeline repository.
37
	 */
38
	protected $pipelines;
39
40
	/**
41
	 * @author	Andrea Marco Sartori
42
	 * @var		Cerbero\Workflow\Console\Drawing\Geometry	$geometry	The applied geometry.
43
	 */
44
	protected $geometry;
45
46
	/**
47
	 * @author	Andrea Marco Sartori
48
	 * @var		array	$pipes	List of pipes.
49
	 */
50
	protected $pipes;
51
52
	/**
53
	 * @author	Andrea Marco Sartori
54
	 * @var		string	$drawing	The resulting drawing.
55
	 */
56
	protected $drawing = '';
57
	
58
	/**
59
	 * Set the dependencies.
60
	 *
61
	 * @author	Andrea Marco Sartori
62
	 * @param	Cerbero\Workflow\Repositories\PipelineRepositoryInterface	$pipelines
63
	 * @param	Cerbero\Workflow\Console\Drawing\Geometry	$geometry
64
	 * @return	void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
65
	 */
66
	public function __construct(PipelineRepositoryInterface $pipelines, Geometry $geometry)
67
	{
68
		$this->pipelines = $pipelines;
0 ignored issues
show
Documentation Bug introduced by
It seems like $pipelines of type object<Cerbero\Workflow\...ineRepositoryInterface> is incompatible with the declared type object<Cerbero\Workflow\...ineRepositoryInterface> of property $pipelines.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
69
70
		$this->geometry = $geometry;
0 ignored issues
show
Documentation Bug introduced by
It seems like $geometry of type object<Cerbero\Workflow\Console\Drawing\Geometry> is incompatible with the declared type object<Cerbero\Workflow\...nsole\Drawing\Geometry> of property $geometry.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
71
	}
72
73
	/**
74
	 * Draw the given workflow.
75
	 *
76
	 * @author	Andrea Marco Sartori
77
	 * @param	string	$workflow
78
	 * @return	string
79
	 */
80
	public function draw($workflow)
81
	{
82
		$this->geometry->setCore($workflow);
83
84
		$this->setPipesOfWorkflow($workflow);
85
86
		$this->drawCenteredChar(static::NOCK);
87
88
		$this->drawPipesBeginning();
89
90
		$this->drawCore();
91
92
		$this->drawPipesEnd();
93
94
		$this->drawCenteredChar(static::PILE);
95
96
		return $this->drawing;
97
	}
98
99
	/**
100
	 * Set the pipes of the given workflow.
101
	 *
102
	 * @author	Andrea Marco Sartori
103
	 * @param	string	$workflow
104
	 * @return	void
105
	 */
106
	protected function setPipesOfWorkflow($workflow)
107
	{
108
		$pipes = $this->pipelines->getPipesByPipeline($workflow);
109
110
		$this->pipes = array_map(function($pipe)
111
		{
112
			$chunks = explode('\\', $pipe);
113
114
			return end($chunks);
115
116
		}, $pipes);
117
118
		$this->geometry->setPipes($this->pipes);
119
	}
120
121
	/**
122
	 * Draw a character in the middle of the drawing.
123
	 *
124
	 * @author	Andrea Marco Sartori
125
	 * @param	string	$character
126
	 * @return	void
127
	 */
128
	protected function drawCenteredChar($character)
129
	{
130
		$spaces = str_repeat(' ', $this->geometry->getHalfWidth());
131
132
		$this->drawRow($spaces . $character);
133
	}
134
135
	/**
136
	 * Draw a row of the drawing.
137
	 *
138
	 * @author	Andrea Marco Sartori
139
	 * @param	string	$row
140
	 * @return	void
141
	 */
142
	protected function drawRow($row)
143
	{
144
		$this->drawing .= $row . PHP_EOL;
145
	}
146
147
	/**
148
	 * Draw the beginning of all pipes.
149
	 *
150
	 * @author	Andrea Marco Sartori
151
	 * @return	void
152
	 */
153
	protected function drawPipesBeginning()
154
	{
155
		foreach ($this->pipes as $pipe)
156
		{
157
			$this->drawBorderTop();
158
159
			$this->drawBordered(
160
				$this->geometry->getSpacedPipe($pipe, static::NOCK, 'before()')
161
			);
162
		}
163
	}
164
165
	/**
166
	 * Draw content wrapped by borders.
167
	 *
168
	 * @author	Andrea Marco Sartori
169
	 * @param	string	$content
170
	 * @return	void
171
	 */
172
	protected function drawBordered($content)
173
	{
174
		$left = $this->geometry->getLeftBordersWith(static::BORDER_X);
175
176
		$right = $this->geometry->getRightBordersWith(static::BORDER_X);
177
178
		$this->drawRow($left.$content.$right);
179
	}
180
181
	/**
182
	 * Draw the top border.
183
	 *
184
	 * @author	Andrea Marco Sartori
185
	 * @param	boolean	$isCore
186
	 * @return	void
187
	 */
188
	protected function drawBorderTop($isCore = false)
189
	{
190
		$crossroads = $isCore ? static::CROSSROADS_UP : static::CROSSROADS;
191
192
		$this->drawBorder(static::BORDER_NW, $crossroads, static::BORDER_NE);
193
		
194
		$this->geometry->increaseNesting();
195
	}
196
197
	/**
198
	 * Draw a border with the given bendings.
199
	 *
200
	 * @author	Andrea Marco Sartori
201
	 * @param	string	$left
202
	 * @param	string	$middle
203
	 * @param	string	$right
204
	 * @return	void
205
	 */
206
	protected function drawBorder($left, $middle, $right)
207
	{
208
		$width = $this->geometry->getWidthButBorders();
209
210
		$border = str_repeat(static::BORDER_Y, $width);
211
212
		$this->replaceUtf8($border, $left, 0);
213
		$this->replaceUtf8($border, $middle, floor($width / 2));
214
		$this->replaceUtf8($border, $right, $width - 1);
215
216
		$this->drawBordered($border);
217
	}
218
219
	/**
220
	 * Replace a character in a given position of a string.
221
	 *
222
	 * @author	Andrea Marco Sartori
223
	 * @param	string	$original
224
	 * @param	string	$replacement
225
	 * @param	integer	$position
226
	 * @return	void
227
	 */
228
	private function replaceUtf8(&$original, $replacement, $position)
229
	{
230
		$start = mb_substr($original, 0, $position, "UTF-8");
231
232
		$end = mb_substr($original, $position + 1, mb_strlen($original, 'UTF-8'), "UTF-8");
233
234
		$original = $start . $replacement . $end;
235
	}
236
237
	/**
238
	 * Draw the core of the workflow.
239
	 *
240
	 * @author	Andrea Marco Sartori
241
	 * @return	void
242
	 */
243
	protected function drawCore()
244
	{
245
		$this->drawBorderTop(true);
246
247
		$this->drawBordered($this->geometry->getSpacedCore());
248
249
		$this->drawBorderBottom(true);
250
	}
251
252
	/**
253
	 * Draw the bottom border.
254
	 *
255
	 * @author	Andrea Marco Sartori
256
	 * @param	boolean	$isCore
257
	 * @return	void
258
	 */
259
	protected function drawBorderBottom($isCore = false)
260
	{
261
		$this->geometry->decreaseNesting();
262
263
		$crossroads = $isCore ? static::CROSSROADS_DOWN : static::CROSSROADS;
264
265
		$this->drawBorder(static::BORDER_SW, $crossroads, static::BORDER_SE);
266
	}
267
268
	/**
269
	 * Draw the end of all pipes.
270
	 *
271
	 * @author	Andrea Marco Sartori
272
	 * @return	void
273
	 */
274
	protected function drawPipesEnd()
275
	{
276
		$pipes = array_reverse($this->pipes);
277
278
		foreach ($pipes as $pipe)
279
		{
280
			$this->drawBordered(
281
				$this->geometry->getSpacedPipe($pipe, static::NOCK, 'after()')
282
			);
283
284
			$this->drawBorderBottom();
285
		}
286
	}
287
288
}
289