Ansi::wrapCodes()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace League\CLImate\Decorator\Parser;
4
5
use League\CLImate\Util\Helper;
6
7
class Ansi extends Parser
8
{
9
    /**
10
     * Wrap the string in the current style
11
     *
12
     * @param  string $str
13
     *
14
     * @return string
15
     */
16
17 556
    public function apply($str)
18
    {
19 556
        return $this->start() . $this->parse($str) . $this->end();
20
    }
21
22
    /**
23
     * Get the string that begins the style
24
     *
25
     * @param string $codes
26
     * @return string
27
     */
28 556
    protected function start($codes = null)
29
    {
30 556
        $codes = $codes ?: $this->currentCode();
31 556
        $codes = $this->codeStr($codes);
32
33 556
        return $this->wrapCodes($codes);
34
    }
35
36
    /**
37
     * Get the string that ends the style
38
     *
39
     * @param string|array $codes
40
     * @return string
41
     */
42 556
    protected function end($codes = null)
43
    {
44 556
        if (empty($codes)) {
45 556
            $codes = [0];
46 556
        } else {
47 8
            $codes = Helper::toArray($codes);
48
49
            // Reset everything back to normal up front
50 8
            array_unshift($codes, 0);
51
        }
52
53 556
        return $this->wrapCodes($this->codeStr($codes));
54
    }
55
56
    /**
57
     * Wrap the code string in the full escaped sequence
58
     *
59
     * @param  string $codes
60
     *
61
     * @return string
62
     */
63
64 556
    protected function wrapCodes($codes)
65
    {
66 556
        return "\e[{$codes}m";
67
    }
68
69
    /**
70
     * Parse the string for tags and replace them with their codes
71
     *
72
     * @param  string $str
73
     *
74
     * @return string
75
     */
76
77 556
    protected function parse($str)
78
    {
79 556
        $count = preg_match_all($this->tags->regex(), $str, $matches);
80
81
        // If we didn't find anything, return the string right back
82 556
        if (!$count || !is_array($matches)) {
83 504
            return $str;
84
        }
85
86
        // All we want is the array of actual strings matched
87 72
        $matches = reset($matches);
88
89 72
        return $this->parseTags($str, $matches);
90
    }
91
92
    /**
93
     * Parse the given string for the tags and replace them with the appropriate codes
94
     *
95
     * @param string $str
96
     * @param array $tags
97
     *
98
     * @return string
99
     */
100
101 72
    protected function parseTags($str, $tags)
102
    {
103
        // Let's keep a history of styles applied
104 72
        $history = ($this->currentCode()) ? [$this->currentCode()] : [];
105
106 72
        foreach ($tags as $tag) {
107 72
            $str = $this->replaceTag($str, $tag, $history);
108 72
        }
109
110 72
        return $str;
111
    }
112
113
    /**
114
     * Replace the tag in the str
115
     *
116
     * @param string $str
117
     * @param string $tag
118
     * @param array $history
119
     *
120
     * @return string
121
     */
122
123 72
    protected function replaceTag($str, $tag, &$history)
124
    {
125
        // We will be replacing tags one at a time, can't pass this by reference
126 72
        $replace_count = 1;
127
128 72
        if (strpos($tag, '/')) {
129
            // We are closing out the tag, pop off the last element and get the codes that are left
130 56
            array_pop($history);
131 56
            $replace = $this->end($history);
132 56
        } else {
133
            // We are starting a new tag, add it onto the history and replace with correct color code
134 72
            $history[] = $this->tags->value($tag);
135 72
            $replace = $this->start($this->tags->value($tag));
136
        }
137
138 72
        return str_replace($tag, $replace, $str, $replace_count);
139
    }
140
141
    /**
142
     * Stringify the codes
143
     *
144
     * @param  mixed  $codes
145
     *
146
     * @return string
147
     */
148
149 556
    protected function codeStr($codes)
150
    {
151
        // If we get something that is already a code string, just pass it back
152 556
        if (!is_array($codes) && strpos($codes, ';')) {
153 28
            return $codes;
154
        }
155
156 556
        $codes = Helper::toArray($codes);
157
158
        // Sort for the sake of consistency and testability
159 556
        sort($codes);
160
161 556
        return implode(';', $codes);
162
    }
163
164
    /**
165
     * Retrieve the current style code
166
     *
167
     * @return string
168
     */
169
170 556
    protected function currentCode()
171
    {
172 556
        return $this->codeStr($this->current);
173
    }
174
}
175