PluginProbe
GutSlider – All in One Slider and Carousel Blocks for Gutenberg / 2.13.2
GutSlider – All in One Slider and Carousel Blocks for Gutenberg v2.13.2
3.1.0 3.0.0 2.13.2 2.13.1 2.13.0 trunk 1.0.0 2.1.0 2.10.0 2.10.1 2.11.0 2.11.1 2.11.2 2.11.3 2.11.4 2.12.0 2.2.1 2.2.2 2.3.0 2.4.0 2.5.1 2.5.3 2.5.4 2.5.5 2.6.1 All 56 releases
slider-blocks / includes / Style / DynamicStyle.php

DynamicStyle.php in GutSlider – All in One Slider and Carousel Blocks for Gutenberg 2.13.2, at includes/Style/DynamicStyle.php

181 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 declare( strict_types=1 );
3
4 namespace GutSlider\Style;
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit;
8 }
9
10 /**
11 * Generates and enqueues dynamic CSS for rendered slider blocks.
12 *
13 * Collects block-level styles during rendering, combines and minifies
14 * them into a single CSS file, and enqueues it for the current page.
15 *
16 * @package GutSlider\Style
17 * @since 3.0.0
18 */
19 final class DynamicStyle {
20
21 /**
22 * Collected CSS styles from rendered blocks.
23 *
24 * @since 3.0.0
25 * @var array<int, string>
26 */
27 private array $styles = array();
28
29 /**
30 * Absolute path to the CSS upload directory.
31 *
32 * @since 3.0.0
33 * @var string
34 */
35 private string $upload_dir;
36
37 /**
38 * Public URL to the CSS upload directory.
39 *
40 * @since 3.0.0
41 * @var string
42 */
43 private string $upload_url;
44
45 /**
46 * Constructor.
47 *
48 * Sets up the upload directory and registers rendering hooks.
49 *
50 * @since 3.0.0
51 */
52 public function __construct() {
53 add_filter( 'render_block', array( $this, 'collect_block_styles' ), 10, 2 );
54
55 if ( wp_is_block_theme() ) {
56 add_action( 'wp_enqueue_scripts', array( $this, 'generate_and_enqueue_combined_css' ) );
57 } else {
58 add_action( 'wp_footer', array( $this, 'generate_and_enqueue_combined_css' ) );
59 }
60
61 $upload_dir = wp_upload_dir();
62 $this->upload_dir = $upload_dir['basedir'] . '/gutslider-styles/';
63 $this->upload_url = $upload_dir['baseurl'] . '/gutslider-styles/';
64
65 if ( ! file_exists( $this->upload_dir ) ) {
66 wp_mkdir_p( $this->upload_dir );
67 }
68 }
69
70 /**
71 * Collect CSS styles from a rendered block.
72 *
73 * Inspects the block's attributes for inline styles and stores
74 * them for later combination into a single CSS file.
75 *
76 * @since 3.0.0
77 *
78 * @param string $block_content The rendered block HTML.
79 * @param array<string, mixed> $block The block data array.
80 * @return string The unmodified block content.
81 */
82 public function collect_block_styles( string $block_content, array $block ): string {
83 if ( isset( $block['blockName'] ) && str_contains( $block['blockName'], 'gutsliders/' ) ) {
84 do_action( 'gutsliders_render_block', $block );
85
86 if ( isset( $block['attrs']['blockStyle'] ) ) {
87 $style = $block['attrs']['blockStyle'];
88
89 if ( is_array( $style ) && ! empty( $style ) ) {
90 $style = implode( ' ', $style );
91 }
92
93 if ( is_string( $style ) && '' !== $style ) {
94 $this->styles[] = wp_strip_all_tags( $style );
95 }
96 }
97 }
98
99 return $block_content;
100 }
101
102 /**
103 * Generate and enqueue the combined CSS file.
104 *
105 * Combines all collected styles, minifies the result, writes it
106 * to a file in the uploads directory, and enqueues it.
107 *
108 * @since 3.0.0
109 *
110 * @return void
111 */
112 public function generate_and_enqueue_combined_css(): void {
113 if ( empty( $this->styles ) ) {
114 return;
115 }
116
117 $combined_css = implode( "\n", $this->styles );
118 $minified_css = $this->minify_css( $combined_css );
119
120 $post_id = get_the_ID();
121 $file_suffix = $post_id ? (string) $post_id : 'archive-' . md5( wp_json_encode( array_keys( $this->styles ) ) );
122 $css_file_name = 'gutslider-styles-' . $file_suffix . '.min.css';
123 $css_file_path = $this->upload_dir . $css_file_name;
124 $css_file_url = $this->upload_url . $css_file_name;
125
126 global $wp_filesystem;
127
128 if ( empty( $wp_filesystem ) ) {
129 require_once ABSPATH . 'wp-admin/includes/file.php';
130 WP_Filesystem();
131 }
132
133 $existing_content = $wp_filesystem->exists( $css_file_path )
134 ? $wp_filesystem->get_contents( $css_file_path )
135 : '';
136
137 if ( $existing_content !== $minified_css ) {
138 $wp_filesystem->put_contents( $css_file_path, $minified_css, FS_CHMOD_FILE );
139 }
140
141 if ( file_exists( $css_file_path ) && is_readable( $css_file_path ) ) {
142 $version = (string) filemtime( $css_file_path );
143 } else {
144 $version = (string) time();
145 }
146
147 if ( file_exists( $css_file_path ) ) {
148 wp_enqueue_style(
149 'gutslider-combined-styles',
150 $css_file_url,
151 array(),
152 $version
153 );
154 }
155 }
156
157 /**
158 * Minify a CSS string.
159 *
160 * Removes comments, unnecessary whitespace, and extra spaces
161 * around colons to reduce file size.
162 *
163 * @since 3.0.0
164 *
165 * @param string $css The raw CSS string.
166 * @return string The minified CSS string.
167 */
168 private function minify_css( string $css ): string {
169 // Remove comments.
170 $css = (string) preg_replace( '!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css );
171
172 // Remove space after colons.
173 $css = str_replace( ': ', ':', $css );
174
175 // Remove whitespace.
176 $css = str_replace( array( "\r\n", "\r", "\n", "\t", ' ', ' ', ' ' ), '', $css );
177
178 return $css;
179 }
180 }
181