Completed
Pull Request — master (#40)
by Michael
03:22 queued 50s
created

MenuStyle::getDisabledItemText()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 1
1
<?php
2
3
namespace PhpSchool\CliMenu;
4
5
use PhpSchool\CliMenu\Exception\InvalidInstantiationException;
6
use PhpSchool\CliMenu\Terminal\TerminalFactory;
7
use PhpSchool\CliMenu\Terminal\TerminalInterface;
8
9
//TODO: B/W fallback
10
11
/**
12
 * Class MenuStyle
13
 *
14
 * @package PhpSchool\CliMenu
15
 * @author Michael Woodward <[email protected]>
16
 */
17
class MenuStyle
18
{
19
    /**
20
     * @var TerminalInterface
21
     */
22
    protected $terminal;
23
24
    /**
25
     * @var string
26
     */
27
    protected $fg;
28
29
    /**
30
     * @var string
31
     */
32
    protected $bg;
33
34
    /**
35
     * @var int
36
     */
37
    protected $width;
38
39
    /**
40
     * @var int
41
     */
42
    protected $padding;
43
44
    /**
45
     * @var int
46
     */
47
    protected $margin;
48
49
    /**
50
     * @var int
51
     */
52
    protected $contentWidth;
53
54
    /**
55
     * @var string
56
     */
57
    private $selectedMarker;
58
59
    /**
60
     * @var string
61
     */
62
    private $unselectedMarker;
63
64
    /**
65
     * @var string
66
     */
67
    private $itemExtra;
68
69
    /**
70
     * @var bool
71
     */
72
    private $displaysExtra;
73
74
    /**
75
     * @var string
76
     */
77
    private $titleSeparator;
78
79
    /**
80
     * @var string
81
     */
82
    private $allowedConsumer = 'PhpSchool\CliMenu\CliMenuBuilder';
83
84
    /**
85
     * @var array
86
     */
87
    private static $availableForegroundColors = array(
88
        'black'   => array('set' => 30, 'unset' => 39),
89
        'red'     => array('set' => 31, 'unset' => 39),
90
        'green'   => array('set' => 32, 'unset' => 39),
91
        'yellow'  => array('set' => 33, 'unset' => 39),
92
        'blue'    => array('set' => 34, 'unset' => 39),
93
        'magenta' => array('set' => 35, 'unset' => 39),
94
        'cyan'    => array('set' => 36, 'unset' => 39),
95
        'white'   => array('set' => 37, 'unset' => 39),
96
        'default' => array('set' => 39, 'unset' => 39),
97
    );
98
99
    /**
100
     * @var array
101
     */
102
    private static $availableBackgroundColors = array(
103
        'black'   => array('set' => 40, 'unset' => 49),
104
        'red'     => array('set' => 41, 'unset' => 49),
105
        'green'   => array('set' => 42, 'unset' => 49),
106
        'yellow'  => array('set' => 43, 'unset' => 49),
107
        'blue'    => array('set' => 44, 'unset' => 49),
108
        'magenta' => array('set' => 45, 'unset' => 49),
109
        'cyan'    => array('set' => 46, 'unset' => 49),
110
        'white'   => array('set' => 47, 'unset' => 49),
111
        'default' => array('set' => 49, 'unset' => 49),
112
    );
113
114
    /**
115
     * @var array
116
     */
117
    private static $availableOptions = array(
118
        'bold'       => array('set' => 1, 'unset' => 22),
119
        'dim'        => array('set' => 2, 'unset' => 22),
120
        'underscore' => array('set' => 4, 'unset' => 24),
121
        'blink'      => array('set' => 5, 'unset' => 25),
122
        'reverse'    => array('set' => 7, 'unset' => 27),
123
        'conceal'    => array('set' => 8, 'unset' => 28)
124
    );
125
126
    /**
127
     * Initialise style
128
     *
129
     * @param string $bg
130
     * @param string $fg
131
     * @param int $width
132
     * @param int $padding
133
     * @param int $margin
134
     * @param string $unselectedMarker
135
     * @param string $selectedMarker
136
     * @param string $itemExtra
137
     * @param bool $displaysExtra
138
     * @param string $titleSeparator
139
     * @param TerminalInterface $terminal
140
     * @throws InvalidInstantiationException
141
     */
142
    public function __construct(
143
        $bg = 'blue',
144
        $fg = 'white',
145
        $width = 100,
146
        $padding = 2,
147
        $margin = 2,
148
        $unselectedMarker = '○',
149
        $selectedMarker = '●',
150
        $itemExtra = '✔',
151
        $displaysExtra = false,
152
        $titleSeparator = '=',
153
        TerminalInterface $terminal = null
154
    ) {
155
        $builder = debug_backtrace();
156 View Code Duplication
        if (count($builder) < 2 || !isset($builder[1]['class']) || $builder[1]['class'] !== $this->allowedConsumer) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
157
            throw new InvalidInstantiationException(
158
                sprintf('The MenuStyle must be instantiated by "%s"', $this->allowedConsumer)
159
            );
160
        }
161
162
        $this->terminal        = $terminal ?: TerminalFactory::fromSystem();
163
        $this->bg              = $bg;
164
        $this->fg              = $fg;
165
        $this->padding         = $padding;
166
        $this->margin          = $margin;
167
        $this->itemExtra       = $itemExtra;
168
        $this->displaysExtra   = $displaysExtra;
169
        $this->titleSeparator  = $titleSeparator;
170
171
        $this->setUnselectedMarker($unselectedMarker);
172
        $this->setSelectedMarker($selectedMarker);
173
        $this->setWidth($width);
174
        $this->calculateContentWidth();
175
    }
176
177
    /**
178
     * @return array
179
     */
180
    public static function getAvailableColours()
181
    {
182
        return array_keys(self::$availableBackgroundColors);
183
    }
184
185
    /**
186
     * @param string $text
187
     * @return string
188
     */
189
    public function getDisabledItemText($text)
190
    {
191
        return sprintf(
192
            "\033[%sm%s\033[%sm",
193
            self::$availableOptions['dim']['set'],
194
            $text,
195
            self::$availableOptions['dim']['unset']
196
        );
197
    }
198
    
199
    /**
200
     * Get the colour code set for Bg and Fg
201
     *
202
     * @return string
203
     */
204 View Code Duplication
    public function getSelectedSetCode()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
205
    {
206
        return sprintf(
207
            "\033[%sm",
208
            implode(';', [
209
                self::$availableBackgroundColors[$this->getFg()]['set'],
210
                self::$availableForegroundColors[$this->getBg()]['set'],
211
            ])
212
        );
213
    }
214
215
    /**
216
     * Get the colour unset code for Bg and Fg
217
     *
218
     * @return string
219
     */
220 View Code Duplication
    public function getSelectedUnsetCode()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221
    {
222
        return sprintf(
223
            "\033[%sm",
224
            implode(';', [
225
                self::$availableBackgroundColors[$this->getBg()]['unset'],
226
                self::$availableForegroundColors[$this->getFg()]['unset'],
227
            ])
228
        );
229
    }
230
231
    /**
232
     * Get the inverted colour code
233
     *
234
     * @return string
235
     */
236 View Code Duplication
    public function getUnselectedSetCode()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
237
    {
238
        return sprintf(
239
            "\033[%sm",
240
            implode(';', [
241
                self::$availableBackgroundColors[$this->getBg()]['set'],
242
                self::$availableForegroundColors[$this->getFg()]['set'],
243
            ])
244
        );
245
    }
246
247
    /**
248
     * Get the inverted colour unset code
249
     *
250
     * @return string
251
     */
252 View Code Duplication
    public function getUnselectedUnsetCode()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
253
    {
254
        return sprintf(
255
            "\033[%sm",
256
            implode(';', [
257
                self::$availableBackgroundColors[$this->getBg()]['unset'],
258
                self::$availableForegroundColors[$this->getFg()]['unset'],
259
            ])
260
        );
261
    }
262
263
    /**
264
     * Calculate the contents width
265
     */
266
    protected function calculateContentWidth()
267
    {
268
        $this->contentWidth = $this->width - ($this->padding*2) - ($this->margin*2);
269
    }
270
271
    /**
272
     * @return string
273
     */
274
    public function getFg()
275
    {
276
        return $this->fg;
277
    }
278
279
    /**
280
     * @param string $fg
281
     * @return MenuStyle
282
     */
283
    public function setFg($fg)
284
    {
285
        $this->fg = $fg;
286
287
        return $this;
288
    }
289
290
    /**
291
     * @return string
292
     */
293
    public function getBg()
294
    {
295
        return $this->bg;
296
    }
297
298
    /**
299
     * @param string $bg
300
     * @return MenuStyle
301
     */
302
    public function setBg($bg)
303
    {
304
        $this->bg = $bg;
305
306
        return $this;
307
    }
308
309
    /**
310
     * @return int
311
     */
312
    public function getWidth()
313
    {
314
        return $this->width;
315
    }
316
317
    /**
318
     * @param int $width
319
     * @return MenuStyle
320
     */
321
    public function setWidth($width)
322
    {
323
        $availableWidth = $this->terminal->getWidth() - ($this->margin * 2) - ($this->padding * 2);
324
325
        if ($width >= $availableWidth) {
326
            $width = $availableWidth;
327
        }
328
329
        $this->width = $width;
330
        $this->calculateContentWidth();
331
332
        return $this;
333
    }
334
335
    /**
336
     * @return int
337
     */
338
    public function getPadding()
339
    {
340
        return $this->padding;
341
    }
342
343
    /**
344
     * @param int $padding
345
     * @return MenuStyle
346
     */
347
    public function setPadding($padding)
348
    {
349
        $this->padding = $padding;
350
351
        $this->calculateContentWidth();
352
353
        return $this;
354
    }
355
356
    /**
357
     * @return int
358
     */
359
    public function getMargin()
360
    {
361
        return $this->margin;
362
    }
363
364
    /**
365
     * @param int $margin
366
     * @return MenuStyle
367
     */
368
    public function setMargin($margin)
369
    {
370
        $this->margin = $margin;
371
372
        $this->calculateContentWidth();
373
374
        return $this;
375
    }
376
377
    /**
378
     * @return int
379
     */
380
    public function getContentWidth()
381
    {
382
        return $this->contentWidth;
383
    }
384
385
    /**
386
     * Get padding for right had side of content
387
     *
388
     * @param $contentLength
389
     * @return int
390
     */
391
    public function getRightHandPadding($contentLength)
392
    {
393
        return $this->getContentWidth() - $contentLength + $this->getPadding();
394
    }
395
396
    /**
397
     * @return string
398
     */
399
    public function getSelectedMarker()
400
    {
401
        return $this->selectedMarker;
402
    }
403
404
    /**
405
     * @param string $marker
406
     * @return $this
407
     */
408
    public function setSelectedMarker($marker)
409
    {
410
        $this->selectedMarker = mb_substr($marker, 0, 1);
411
412
        return $this;
413
    }
414
415
    /**
416
     * @return string
417
     */
418
    public function getUnselectedMarker()
419
    {
420
        return $this->unselectedMarker;
421
    }
422
423
    /**
424
     * @param string $marker
425
     * @return $this
426
     */
427
    public function setUnselectedMarker($marker)
428
    {
429
        $this->unselectedMarker = mb_substr($marker, 0, 1);
430
431
        return $this;
432
    }
433
434
    /**
435
     * Get the correct marker for the item
436
     *
437
     * @param bool $selected
438
     * @return string
439
     */
440
    public function getMarker($selected)
441
    {
442
        return $selected ? $this->selectedMarker : $this->unselectedMarker;
443
    }
444
445
    /**
446
     * @param string $itemExtra
447
     */
448
    public function setItemExtra($itemExtra)
449
    {
450
        $this->itemExtra = $itemExtra;
451
    }
452
453
    /**
454
     * @return string
455
     */
456
    public function getItemExtra()
457
    {
458
        return $this->itemExtra;
459
    }
460
461
    /**
462
     * @return bool
463
     */
464
    public function getDisplaysExtra()
465
    {
466
        return $this->displaysExtra;
467
    }
468
469
    /**
470
     * @param bool $displaysExtra
471
     * @return $this
472
     */
473
    public function setDisplaysExtra($displaysExtra)
474
    {
475
        $this->displaysExtra = $displaysExtra;
476
477
        return $this;
478
    }
479
480
    /**
481
     * @return string
482
     */
483
    public function getTitleSeparator()
484
    {
485
        return $this->titleSeparator;
486
    }
487
488
    /**
489
     * @param string $actionSeparator
490
     * @return $this
491
     */
492
    public function setTitleSeparator($actionSeparator)
493
    {
494
        $this->titleSeparator = $actionSeparator;
495
496
        return $this;
497
    }
498
}
499