-
Notifications
You must be signed in to change notification settings - Fork 198
/
Copy pathclass-sensei-course-theme-styles.php
250 lines (209 loc) · 5.91 KB
/
class-sensei-course-theme-styles.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
<?php
/**
* File containing Sensei_Course_Theme_Styles class.
*
* @package sensei-lms
* @since 4.7.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Add support for global styles colors.
*
* @since 4.7.0
*/
class Sensei_Course_Theme_Styles {
/**
* Add hooks.
*/
public static function init() {
add_action( 'wp_head', [ self::class, 'output_global_styles_colors' ] );
add_action( 'render_block', [ self::class, 'apply_block_support' ], 10, 2 );
}
/**
* Add block colors as inline style with CSS variables.
*
* @access private
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
*
* @return string Filtered block content.
*/
public static function apply_block_support( $block_content, $block ) {
if ( ! $block_content ) {
return $block_content;
}
$colors = self::get_block_colors( $block['attrs'] );
if ( empty( $colors ) ) {
return $block_content;
}
$style = esc_attr( implode( ' ', $colors ) );
return self::set_style_attribute( $block_content, $style );
}
/**
* Get global styles colors and output them as CSS variables.
*
* @access private
*/
public static function output_global_styles_colors() {
if ( ! function_exists( 'wp_get_global_styles' ) ) {
return;
}
$styles = wp_get_global_styles();
$colors = self::get_colors( $styles );
$vars = self::format_css_variables( $colors, '-global' );
if ( ! empty( $vars ) ) {
self::output_style( implode( "\n", $vars ) );
}
}
/**
* Get colors from a styles configuration and generate CSS variables.
*
* @param array $styles Styles object.
*
* @return array Name-value pairs of CSS variables
*/
private static function get_colors_as_css_variables( $styles ) {
if ( empty( $styles ) ) {
return [];
}
}
/**
* Get relevant colors from global styles or a block's attributes.
*
* @param array $styles Styles object.
*
* @return array
*/
private static function get_colors( $styles ) {
if ( empty( $styles ) ) {
return [];
}
$vars = [];
$element_colors = $styles['color'] ?? $styles['elements']['color'] ?? null;
$vars['--sensei-text-color'] = $element_colors['text'] ?? $styles['textColor'] ?? null;
$vars['--sensei-background-color'] = $element_colors['background'] ?? $styles['backgroundColor'] ?? null;
$vars['--sensei-primary-contrast-color'] = $vars['--sensei-background-color'];
$link = $styles['elements']['link']['color'] ?? null;
if ( ! empty( $link ) ) {
$vars['--sensei-primary-color'] = $link['text'];
}
return $vars;
}
/**
* Get CSS variables for the block from its style attributes.
*
* @param array $attributes Block attributes.
*
* @return array
*/
private static function get_block_colors( $attributes ) {
$styles = $attributes['style'] ?? [];
foreach ( [ 'textColor', 'backgroundColor' ] as $color ) {
if ( ! empty( $attributes[ $color ] ) ) {
$styles[ $color ] = $attributes[ $color ];
}
}
if ( empty( $styles ) ) {
return [];
}
$colors = self::get_colors( $styles );
return self::format_css_variables( $colors );
}
/**
* Generate CSS variables.
*
* @param array $variables Key-value pair of variable names and values.
* @param array $postfix Optional variable name postfix.
*/
private static function format_css_variables( $variables, $postfix = '' ) {
$css = [];
foreach ( $variables as $variable => $value ) {
if ( $postfix ) {
$variable = $variable . $postfix;
}
if ( $value ) {
$css[] = sprintf( '%s: %s;', $variable, self::get_property_value( $value ) );
}
}
return $css;
}
/**
* Generate a style tag with the given CSS properties.
*
* @param string $css CSS properties.
*/
private static function output_style( $css ) {
?>
<style>
body {
<?php echo esc_html( $css ); ?>
}
</style>
<?php
}
/**
* Converts CSS Custom Property stored as
* "var:preset|color|secondary", or single named values stored as 'secondary' to the form
* "--wp--preset--color--secondary".
*
* Based on \WP_Theme_JSON::get_property_value
*
* @param string $value CSS value.
*
* @return string Style property value.
*/
private static function get_property_value( $value ) {
$prefix = 'var:';
$prefix_len = strlen( $prefix );
$token_in = '|';
$token_out = '--';
if ( 0 === strncmp( $value, $prefix, $prefix_len ) ) {
$unwrapped_name = str_replace(
$token_in,
$token_out,
substr( $value, $prefix_len )
);
$value = "var(--wp--$unwrapped_name)";
} elseif ( preg_match( '/^[a-z0-9-]+$/i', $value ) ) {
$value = "var(--wp--preset--color--{$value})";
}
return $value;
}
/**
* Update the style attribute on the block wrapper element.
*
* Based on wp_render_elements_support
*
* @param string $block_content Block HTML.
* @param string $style Inline styles to add.
*
* @return string
*/
private static function set_style_attribute( string $block_content, string $style ) {
// Like core hooks, this assumes the hook only applies to blocks with a single wrapper.
// Retrieve the opening tag of the first HTML element.
$html_element_matches = array();
$match = preg_match( '/<[^>]+>/', $block_content, $html_element_matches, PREG_OFFSET_CAPTURE );
if ( ! $match ) {
return $block_content;
}
$first_element = $html_element_matches[0][0];
// Add new styles if there is already a style attribute.
if ( strpos( $first_element, 'style="' ) !== false ) {
$content = preg_replace(
'/' . preg_quote( 'style="', '/' ) . '/',
'style="' . $style . ' ',
$block_content,
1
);
} else {
// Add as new style attribute to the element.
$first_element_offset = $html_element_matches[0][1];
$content = substr_replace( $block_content, ' style="' . $style . '"', $first_element_offset + strlen( $first_element ) - 1, 0 );
}
return $content;
}
}