Diff: STRATO-apps/wordpress_03/app/wp-content/themes/blocksy/inc/classes/class-ct-css-injector.php
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
<?php
2
+
/**
3
+
* CSS Injector
4
+
* Helper object for including dynamic styles into head of the document,
5
+
* with possibilities of extending it.
6
+
*
7
+
* @copyright 2019-present Creative Themes
8
+
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
9
+
* @package Blocksy
10
+
*/
11
+
12
+
class Blocksy_Css_Injector {
13
+
/**
14
+
* Temporary CSS attributes.
15
+
*
16
+
* @var array $attr Attributes.
17
+
*/
18
+
private $attr = [];
19
+
private $additional_symbols = [];
20
+
private $selector_prefix = null;
21
+
private $fonts_manager = null;
22
+
23
+
/**
24
+
* Keyword that allows skiping a certain CSS rule from getting in the output.
25
+
*/
26
+
public static function get_skip_rule_keyword($suffix = '') {
27
+
return 'CT_CSS_SKIP_RULE' . $suffix;
28
+
}
29
+
30
+
public static function get_inline_keyword($suffix = '') {
31
+
return 'CT_CSS_INLINE_CSS' . $suffix;
32
+
}
33
+
34
+
/**
35
+
* Injector constructor.
36
+
*/
37
+
public function __construct($args = []) {
38
+
$args = wp_parse_args(
39
+
$args,
40
+
[
41
+
'selector_prefix' => '',
42
+
'fonts_manager' => null
43
+
]
44
+
);
45
+
46
+
if (! empty($args['selector_prefix'])) {
47
+
$this->selector_prefix = $args['selector_prefix'];
48
+
}
49
+
50
+
$this->additional_symbols = ['-', '%', 'px', 's'];
51
+
52
+
if ($args['fonts_manager']) {
53
+
$this->fonts_manager = $args['fonts_manager'];
54
+
}
55
+
}
56
+
57
+
public function process_matching_typography($value) {
58
+
if (! $this->fonts_manager) {
59
+
return;
60
+
}
61
+
62
+
$this->fonts_manager->process_matching_typography($value);
63
+
}
64
+
65
+
/**
66
+
* Parse each temporary structure and transform it into actual CSS.
67
+
*/
68
+
public function build_css_structure() {
69
+
$content = '';
70
+
71
+
if (isset($this->attr[Blocksy_Css_Injector::get_inline_keyword()])) {
72
+
$content .= implode('', $this->attr[Blocksy_Css_Injector::get_inline_keyword()]);
73
+
unset($this->attr[Blocksy_Css_Injector::get_inline_keyword()]);
74
+
}
75
+
76
+
if (count($this->attr)) {
77
+
$content .= "\n" . $this->convert_to_css();
78
+
}
79
+
80
+
$content = $this->css_minify($content);
81
+
82
+
return $content;
83
+
}
84
+
85
+
public function get_wp_style_engine_rules($args = []) {
86
+
$args = wp_parse_args(
87
+
$args,
88
+
[
89
+
'device' => 'desktop'
90
+
]
91
+
);
92
+
93
+
$media_queries = [
94
+
'tablet' => '@media (max-width: 999.98px)',
95
+
'mobile' => '@media (max-width: 689.98px)'
96
+
];
97
+
98
+
$rules = [];
99
+
100
+
foreach ($this->attr as $selector => $lines) {
101
+
$declarations = [];
102
+
103
+
foreach ($lines as $line) {
104
+
$line = trim($line);
105
+
106
+
if (! $line) {
107
+
continue;
108
+
}
109
+
110
+
$parts = explode(':', $line);
111
+
112
+
if (count($parts) <= 1) {
113
+
continue;
114
+
}
115
+
116
+
$declarations[trim($parts[0])] = trim($parts[1]);
117
+
}
118
+
119
+
$rule = [
120
+
'selector' => $selector,
121
+
'declarations' => $declarations
122
+
];
123
+
124
+
if (isset($media_queries[$args['device']])) {
125
+
$rule['rules_group'] = $media_queries[$args['device']];
126
+
}
127
+
128
+
$rules[] = $rule;
129
+
}
130
+
131
+
return $rules;
132
+
}
133
+
134
+
/**
135
+
* Add new line in CSS structure.
136
+
*
137
+
* @param string|array $selector CSS class, id, tag.
138
+
* @param string|array $rules CSS syntax.
139
+
*/
140
+
public function put($selector, $rules) {
141
+
$normalized = $this->normalize_inputs($selector, $rules);
142
+
143
+
if (! $normalized) {
144
+
return;
145
+
}
146
+
147
+
$selector = $normalized['selector'];
148
+
$rules = $normalized['rules'];
149
+
150
+
if (! isset($this->attr[$selector])) {
151
+
$this->attr[$selector] = [];
152
+
}
153
+
154
+
foreach ($rules as $line) {
155
+
$line = trim($line);
156
+
157
+
if (
158
+
! $line
159
+
||
160
+
in_array($line, $this->attr[$selector], true)
161
+
) {
162
+
continue;
163
+
}
164
+
165
+
if (strpos($line, self::get_skip_rule_keyword()) !== false) {
166
+
continue;
167
+
}
168
+
169
+
$this->attr[$selector][] = $line;
170
+
}
171
+
}
172
+
173
+
private function normalize_inputs($selector, $preliminary_rules) {
174
+
if (is_string($preliminary_rules) && trim($preliminary_rules) === '') {
175
+
return false;
176
+
}
177
+
178
+
if (is_array($selector)) {
179
+
$selector = implode(",\n", $selector);
180
+
}
181
+
182
+
$rules = [];
183
+
184
+
if ($selector === Blocksy_Css_Injector::get_inline_keyword()) {
185
+
$rules = is_array($preliminary_rules) ? $preliminary_rules : [
186
+
$preliminary_rules
187
+
];
188
+
} else {
189
+
// Convert string to array.
190
+
if (! is_array($preliminary_rules)) {
191
+
$rules = explode(';', $preliminary_rules);
192
+
} else {
193
+
// Support nested rules.
194
+
foreach ($preliminary_rules as $maybe_rule) {
195
+
$current_rules = explode(';', $maybe_rule);
196
+
197
+
foreach ($current_rules as $current_rule) {
198
+
$rules[] = $current_rule;
199
+
}
200
+
}
201
+
}
202
+
}
203
+
204
+
$prefix = '';
205
+
206
+
if (! empty($this->selector_prefix)) {
207
+
$prefix = $this->selector_prefix . ' ';
208
+
}
209
+
210
+
return [
211
+
'selector' => $prefix . $selector,
212
+
'rules' => $rules
213
+
];
214
+
}
215
+
216
+
/**
217
+
* Merge selectors that have the same CSS. This has the effect of increasing
218
+
* the weight of the selectors.
219
+
*/
220
+
private function merge_class_with_the_same_css() {
221
+
return;
222
+
223
+
$new_names = [];
224
+
$used = [];
225
+
226
+
foreach ($this->attr as $key => $values) {
227
+
if (isset($used[$key])) {
228
+
continue;
229
+
}
230
+
231
+
foreach ($this->attr as $sub_key => $sub_values) {
232
+
if ($sub_key !== $key && $values === $sub_values) {
233
+
$used[$sub_key] = 1;
234
+
$new_names[$key][] = $sub_key;
235
+
$used[$key] = 1;
236
+
}
237
+
}
238
+
}
239
+
240
+
// Merge classes.
241
+
foreach ($new_names as $parent => $childs) {
242
+
$class_name = $parent . ",\n" . join(",\n", $childs);
243
+
$this->attr[$class_name] = $this->attr[$parent];
244
+
245
+
// Remove CSS from main structure.
246
+
if (isset($this->attr[$parent])) {
247
+
unset($this->attr[$parent]);
248
+
}
249
+
250
+
// Remove all childs css.
251
+
foreach ($childs as $child_class) {
252
+
if (isset($this->attr[$child_class])) {
253
+
unset($this->attr[$child_class]);
254
+
}
255
+
}
256
+
}
257
+
}
258
+
259
+
/**
260
+
* Convert this->attr to a CSS string.
261
+
*/
262
+
private function convert_to_css() {
263
+
$css = '';
264
+
265
+
$this->merge_class_with_the_same_css();
266
+
267
+
foreach ($this->attr as $key => $values) {
268
+
$section = '';
269
+
270
+
$section .= $key . " {\n";
271
+
272
+
$content = '';
273
+
274
+
foreach ($values as $line) {
275
+
$line = trim($line);
276
+
277
+
if (! $this->is_empty_style($line)) {
278
+
if (strpos($key, '@media') === false) {
279
+
$line = str_replace(';', '', $line);
280
+
}
281
+
282
+
$content .= " {$line}";
283
+
284
+
if (strpos($key, '@media') === false) {
285
+
$content .= ";\n";
286
+
}
287
+
}
288
+
}
289
+
290
+
// CSS is not empty.
291
+
if ($content) {
292
+
$section .= $content;
293
+
} else {
294
+
continue;
295
+
}
296
+
297
+
$section .= "}\n\n";
298
+
$css .= $section;
299
+
}
300
+
301
+
// Erase structure.
302
+
$this->attr = [];
303
+
304
+
return $css;
305
+
}
306
+
307
+
/**
308
+
* Check if a CSS rule is empty.
309
+
*
310
+
* @param string $line Single rule.
311
+
*/
312
+
private function is_empty_style($line) {
313
+
$parts = explode(':', $line);
314
+
315
+
if (count($parts) <= 1) {
316
+
return false;
317
+
}
318
+
319
+
if (! isset($parts[1])) {
320
+
return true;
321
+
}
322
+
323
+
$parts[1] = str_replace($this->additional_symbols, '', $parts[1]);
324
+
325
+
return strlen(trim($parts[1])) === 0;
326
+
}
327
+
328
+
/**
329
+
* Very rudimentary CSS minifier.
330
+
*
331
+
* @param string $minify CSS to be minified.
332
+
*/
333
+
private function css_minify($minify) {
334
+
if (defined('WP_DEBUG') && WP_DEBUG) {
335
+
// return $minify;
336
+
}
337
+
338
+
// return $minify;
339
+
340
+
/* remove comments */
341
+
$minify = preg_replace( '!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $minify );
342
+
343
+
/* remove tabs, spaces, newlines, etc. */
344
+
$minify = str_replace( array( "\r\n", "\r", "\n", "\t", ' ', ' ', ' ' ), '', $minify );
345
+
/* remove space after colons */
346
+
$minify = str_replace( ': ', ':', $minify );
347
+
$minify = str_replace( '}[', '} [', $minify );
348
+
349
+
return $minify;
350
+
}
351
+
}
352
+
353
+