Stack::current()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 2
eloc 2
nc 2
nop 0
1
<?php namespace nyx\console\output\formatting\styles;
2
3
// Internal dependencies
4
use nyx\console\output\formatting\interfaces;
5
use nyx\console\output\formatting;
6
7
/**
8
 * Output Formatting Styles Stack
9
 *
10
 * @version     0.1.0
11
 * @author      Michal Chojnacki <[email protected]>
12
 * @copyright   2012-2017 Nyx Dev Team
13
 * @link        https://github.com/unyx/nyx
14
 */
15
class Stack
16
{
17
    /**
18
     * @var interfaces\Style[]   The Styles currently being processed.
19
     */
20
    private $styles = [];
21
22
    /**
23
     * @var interfaces\Style     The default Style used when the Stack is empty.
24
     */
25
    private $default;
26
27
    /**
28
     * Constructs a new Output Formatting Styles Stack.
29
     *
30
     * @param   interfaces\Style    $default    The default Style to be used when the Stack is empty.
31
     */
32
    public function __construct(interfaces\Style $default = null)
33
    {
34
        $this->default = $default ?? new formatting\Style(null);
35
    }
36
37
    /**
38
     * Pushes a style onto the Stack.
39
     *
40
     * @param   interfaces\Style    $style
41
     * @return  $this
42
     */
43
    public function push(interfaces\Style $style) : Stack
44
    {
45
        $this->styles[] = $style;
46
47
        return $this;
48
    }
49
50
    /**
51
     * Pops a style from the Stack.
52
     *
53
     * @param   interfaces\Style $searched          An optional, specific Style to pop from the Stack. If it is not
54
     *                                              the current element in the Stack, the Stack will be sliced and
55
     *                                              all Styles present after this instance will also be popped off.
56
     * @return  interfaces\Style                    The popped Style.
57
     * @throws  \InvalidArgumentException           When a Style was given but couldn't be found in the Stack.
58
     */
59
    public function pop(interfaces\Style $searched = null) : interfaces\Style
60
    {
61
        if (empty($this->styles)) {
62
            return $this->default;
63
        }
64
65
        if (!isset($searched)) {
66
            return array_pop($this->styles);
67
        }
68
69
        // Given a specific Style to search for, we need to compare the Styles to find the index at which
70
        // the Style resides, so that we can pop off the part of the Stack starting at the index.
71
        /* @var interfaces\Style $stackedStyle */
72
        foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
73
            // In order to support nested inline styles, we need to compare identity of the output,
74
            // not just of the instances.
75
            // @todo Strict equality of the instances may be sufficient depending on how the Formatter gets implemented.
76
            if ($searched->apply('') === $stackedStyle->apply('')) {
77
                $this->styles = array_slice($this->styles, 0, $index);
78
79
                return $stackedStyle;
80
            }
81
        }
82
83
        throw new \InvalidArgumentException('Encountered an incorrectly nested formatting style tag');
84
    }
85
86
    /**
87
     * Returns the current, topmost Style in the stack, or the default Style if none is stacked.
88
     *
89
     * @return  interfaces\Style
90
     */
91
    public function current() : interfaces\Style
92
    {
93
        return !empty($this->styles) ? end($this->styles) : $this->default;
94
    }
95
96
    /**
97
     * Empties the Stack.
98
     *
99
     * @return  $this
100
     */
101
    public function reset() : Stack
102
    {
103
        $this->styles = [];
104
105
        return $this;
106
    }
107
108
    /**
109
     * Returns the count of the Styles in the Stack, not taking the default Style into account.
110
     *
111
     * @return  int
112
     */
113
    public function count() : int
114
    {
115
        return count($this->styles);
116
    }
117
118
    /**
119
     * Sets the default Style to be used when the Stack is empty.
120
     *
121
     * @param   interfaces\Style $style
122
     * @return  $this
123
     */
124
    public function setDefault(interfaces\Style $style) : Stack
125
    {
126
        $this->default = $style;
127
128
        return $this;
129
    }
130
131
    /**
132
     * Returns the default Style used when the Stack is empty.
133
     *
134
     * @return  interfaces\Style
135
     */
136
    public function getDefault() : interfaces\Style
137
    {
138
        return $this->default;
139
    }
140
}
141