Passed
Push — master ( 3eb4db...99d5ff )
by Kirill
03:12
created

HtmlStyle::getStyle()   A

Complexity

Conditions 6
Paths 7

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 17
rs 9.2222
cc 6
nc 7
nop 2
1
<?php
2
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Exceptions\Style;
13
14
use Spiral\Exceptions\StyleInterface;
15
16
/**
17
 * HTML based styling of given source code. Attention, you have to manually wrap generated code
18
 * using html block.
19
 */
20
class HtmlStyle implements StyleInterface
21
{
22
    /**
23
     * Default code styles.
24
     */
25
    public const DEFAULT = [
26
        'color: blue; font-weight: bold;'   => [
27
            T_STATIC,
28
            T_PUBLIC,
29
            T_PRIVATE,
30
            T_PROTECTED,
31
            T_CLASS,
32
            T_NEW,
33
            T_FINAL,
34
            T_ABSTRACT,
35
            T_IMPLEMENTS,
36
            T_CONST,
37
            T_ECHO,
38
            T_CASE,
39
            T_FUNCTION,
40
            T_GOTO,
41
            T_INCLUDE,
42
            T_INCLUDE_ONCE,
43
            T_REQUIRE,
44
            T_REQUIRE_ONCE,
45
            T_VAR,
46
            T_INSTANCEOF,
47
            T_INTERFACE,
48
            T_THROW,
49
            T_ARRAY,
50
            T_IF,
51
            T_ELSE,
52
            T_ELSEIF,
53
            T_TRY,
54
            T_CATCH,
55
            T_CLONE,
56
            T_WHILE,
57
            T_FOR,
58
            T_DO,
59
            T_UNSET,
60
            T_FOREACH,
61
            T_RETURN,
62
            T_EXIT,
63
        ],
64
        'font-weight: bold;'                => [
65
            ';',
66
            ',',
67
        ],
68
        'color: blue'                       => [
69
            T_DNUMBER,
70
            T_LNUMBER,
71
        ],
72
        'color: black; font: weight: bold;' => [
73
            T_OPEN_TAG,
74
            T_CLOSE_TAG,
75
            T_OPEN_TAG_WITH_ECHO,
76
        ],
77
        'color: gray;'                      => [
78
            T_COMMENT,
79
            T_DOC_COMMENT,
80
        ],
81
        'color: green; font-weight: bold;'  => [
82
            T_CONSTANT_ENCAPSED_STRING,
83
            T_ENCAPSED_AND_WHITESPACE,
84
        ],
85
        'color: #660000;'                   => [
86
            T_VARIABLE,
87
        ],
88
    ];
89
90
    public const INVERTED = [
91
        'color: #FF8B00; font-weight: bold;' => [
92
            T_STATIC,
93
            T_PUBLIC,
94
            T_PRIVATE,
95
            T_PROTECTED,
96
            T_CLASS,
97
            T_NEW,
98
            T_FINAL,
99
            T_ABSTRACT,
100
            T_IMPLEMENTS,
101
            T_CONST,
102
            T_ECHO,
103
            T_CASE,
104
            T_FUNCTION,
105
            T_GOTO,
106
            T_INCLUDE,
107
            T_INCLUDE_ONCE,
108
            T_REQUIRE,
109
            T_REQUIRE_ONCE,
110
            T_VAR,
111
            T_INSTANCEOF,
112
            T_INTERFACE,
113
            T_THROW,
114
            T_ARRAY,
115
            T_IF,
116
            T_ELSE,
117
            T_ELSEIF,
118
            T_TRY,
119
            T_CATCH,
120
            T_CLONE,
121
            T_WHILE,
122
            T_FOR,
123
            T_DO,
124
            T_UNSET,
125
            T_FOREACH,
126
            T_RETURN,
127
            T_EXIT,
128
            T_EXTENDS,
129
            ';',
130
            ',',
131
        ],
132
        'color: black; font: weight: bold;'  => [
133
            T_OPEN_TAG,
134
            T_CLOSE_TAG,
135
            T_OPEN_TAG_WITH_ECHO,
136
        ],
137
        'color: #9C9C9C;'                    => [
138
            T_COMMENT,
139
            T_DOC_COMMENT,
140
        ],
141
        'color: #A5C261;'                    => [
142
            T_CONSTANT_ENCAPSED_STRING,
143
            T_ENCAPSED_AND_WHITESPACE,
144
            T_DNUMBER,
145
            T_LNUMBER,
146
        ],
147
        'color: #D0D0FF;'                    => [
148
            T_VARIABLE,
149
        ],
150
        'color: #E6D100;'                    => [
151
            '->' . T_STRING,
152
            '::' . T_STRING
153
        ]
154
    ];
155
156
    /**
157
     * Style templates.
158
     *
159
     * @var array
160
     */
161
    protected $templates = [
162
        'token'  => '<span style="%s">%s</span>',
163
        'line'   => "<div><span class=\"number\">%d</span>%s</div>\n",
164
        'active' => "<div class=\"active\"><span class=\"number\">%d</span>%s</div>\n",
165
    ];
166
167
    /**
168
     * Style associated with token types.
169
     *
170
     * @var array
171
     */
172
    protected $style = self::DEFAULT;
173
174
    /**
175
     * @param array $style
176
     */
177
    public function __construct(array $style = self::DEFAULT)
178
    {
179
        $this->style = $style;
180
    }
181
182
    /**
183
     * @inheritdoc
184
     */
185
    public function token(array $token, array $previous): string
186
    {
187
        $style = $this->getStyle($token, $previous);
188
189
        if (strpos($token[1], "\n") === false) {
190
            return sprintf($this->templates['token'], $style, htmlspecialchars($token[1]));
191
        }
192
193
        $lines = [];
194
        foreach (explode("\n", $token[1]) as $line) {
195
            $lines[] = sprintf($this->templates['token'], $style, htmlspecialchars($line));
196
        }
197
198
        return implode("\n", $lines);
199
    }
200
201
    /**
202
     * @inheritdoc
203
     */
204
    public function line(int $number, string $code, bool $target = false): string
205
    {
206
        return sprintf($this->templates[$target ? 'active' : 'line'], $number, $code);
207
    }
208
209
    /**
210
     * Get styles for a given token.
211
     *
212
     * @param array $token
213
     * @param array $previous
214
     * @return string
215
     */
216
    private function getStyle(array $token, array $previous): string
217
    {
218
        if (!empty($previous)) {
219
            foreach ($this->style as $style => $tokens) {
220
                if (in_array($previous[1] . $token[0], $tokens)) {
221
                    return $style;
222
                }
223
            }
224
        }
225
226
        foreach ($this->style as $style => $tokens) {
227
            if (in_array($token[0], $tokens)) {
228
                return $style;
229
            }
230
        }
231
232
        return '';
233
    }
234
}
235