PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.8.0
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.8.0
2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 All 78 releases
ablocks / includes / classes / css-generator.php

css-generator.php in aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder 2.8.0, at includes/classes/css-generator.php

229 lines 7.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace ABlocks\Classes;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 use ABlocks\Classes\AssetsGenerator;
9
10 class CssGenerator {
11 private $font_category;
12 private $custom_css = '';
13 private $parent_class;
14 private $class_styles = [];
15
16 public function __construct( $attributes = [] ) {
17 if ( ! isset( $attributes['block_id'] ) ) {
18 return;
19 }
20 $this->parent_class = '.ablocks-block-' . $attributes['block_id'];
21 if ( isset( $attributes['_custom_css'] ) ) {
22 $this->custom_css = $attributes['_custom_css'];
23 }
24
25 $this->font_category = include ABLOCKS_BLOCKS_DIR_PATH . 'fonts.php';
26
27 // Alert - don't touch here
28 if ( isset( $attributes['_margin'] ) ) { // check has advanced tab or not
29 $this->add_class_styles(
30 '{{WRAPPER}}',
31 BlockGlobal::get_wrapper_css( $attributes ),
32 BlockGlobal::get_wrapper_css( $attributes, 'Tablet' ),
33 BlockGlobal::get_wrapper_css( $attributes, 'Mobile' )
34 );
35 $this->add_class_styles(
36 '{{WRAPPER}}:hover',
37 BlockGlobal::get_wrapper_hover_css( $attributes ),
38 BlockGlobal::get_wrapper_hover_css( $attributes, 'Tablet' ),
39 BlockGlobal::get_wrapper_hover_css( $attributes, 'Mobile' )
40 );
41 $this->add_class_styles(
42 '{{WRAPPER}}.ablocks-hide-on-desktop,{{WRAPPER}}.ablocks-hide-on-tablet,{{WRAPPER}}.ablocks-hide-on-mobile',
43 BlockGlobal::get_wrapper_device_responsive_css( $attributes ),
44 BlockGlobal::get_wrapper_device_responsive_css( $attributes, 'Tablet' ),
45 BlockGlobal::get_wrapper_device_responsive_css( $attributes, 'Mobile' )
46 );
47 $this->add_class_styles(
48 '{{WRAPPER}}:hover > .ablocks-block-container',
49 BlockGlobal::get_container_hover_css( $attributes ),
50 BlockGlobal::get_container_hover_css( $attributes, 'Tablet' ),
51 BlockGlobal::get_container_hover_css( $attributes, 'Mobile' )
52 );
53 $this->add_class_styles(
54 '{{WRAPPER}} > .ablocks-block-container',
55 BlockGlobal::get_container_css( $attributes ),
56 BlockGlobal::get_container_css( $attributes, 'Tablet' ),
57 BlockGlobal::get_container_css( $attributes, 'Mobile' )
58 );
59 }//end if
60 }
61
62 public function add_class_styles( $class_name, $desktop_styles, $tablet_styles = [], $mobile_styles = [] ) {
63 $this->class_styles[] = [
64 'class_name' => $class_name,
65 'desktop_styles' => $desktop_styles,
66 'tablet_styles' => $tablet_styles,
67 'mobile_styles' => $mobile_styles
68 ];
69 }
70
71 public function generate_css() {
72 $css_output = '';
73
74 foreach ( $this->class_styles as $class_style ) {
75 $desktop_styles = $this->remove_empty_css( $class_style['desktop_styles'] );
76 $tablet_styles = $this->filter_responsive_styles( $desktop_styles, $class_style['tablet_styles'] );
77 $mobile_styles = $this->filter_responsive_styles( array_merge( $desktop_styles, $tablet_styles ), $class_style['mobile_styles'] );
78
79 $desktop_raw = $this->generate_css_for_media_query( 'desktop', $desktop_styles );
80 $tablet_raw = $this->generate_css_for_media_query( 'tablet', $tablet_styles );
81 $mobile_raw = $this->generate_css_for_media_query( 'mobile', $mobile_styles );
82
83 $desktop_css = AssetsGenerator::minify_css( $desktop_raw );
84 $tablet_css = AssetsGenerator::minify_css( $tablet_raw );
85 $mobile_css = AssetsGenerator::minify_css( $mobile_raw );
86
87 $parent_selector = $this->get_parent_selector( $class_style['class_name'] );
88 $css_blocks = [];
89
90 $addToCssBlocks = function ( $mediaQuery, $max_width, $css ) use ( &$css_blocks, $parent_selector ) {
91 if ( ! empty( $css ) ) {
92 $css_blocks[] = ( '' !== $mediaQuery ) ? "@media screen and (max-width: $max_width) {\n$parent_selector {\n$css\n}\n}" : "$parent_selector {\n$css\n}";
93 }
94 };
95
96 // Always add desktop CSS
97 $addToCssBlocks( '', '', $desktop_css );
98
99 // Only add tablet CSS if it differs from desktop
100 if ( $tablet_raw !== $desktop_raw ) {
101 $addToCssBlocks( 'tablet', $this->get_breakpoint( 'tablet' ), $tablet_css );
102 }
103
104 // Only add mobile CSS if it differs from desktop AND tablet
105 if ( $mobile_raw !== $tablet_raw ) {
106 $addToCssBlocks( 'mobile', $this->get_breakpoint( 'mobile' ), $mobile_css );
107 }
108
109 $css_output .= implode( "\n\n", $css_blocks ) . "\n\n";
110 }//end foreach
111
112 $css_output .= $this->get_custom_css();
113
114 return preg_replace( '/\s+/', ' ', $css_output );
115 }
116 public function get_custom_css() {
117 return preg_replace( '/\bselector\b/', $this->parent_class, $this->custom_css );
118 }
119 public function generate_css_for_media_query( $media_query, $styles ) {
120 if ( empty( $styles ) ) {
121 return '';
122 }
123 $css_string = implode("\n", array_map(
124 function ( $property, $value ) {
125 return "$property: $value;";
126 },
127 array_keys( $styles ),
128 $styles
129 ));
130
131 return $css_string . "\n";
132 }
133
134 public function get_breakpoint( $media_query ) {
135 switch ( $media_query ) {
136 case 'tablet':
137 return '800px';
138 case 'mobile':
139 return '480px';
140 default:
141 return '1200px';
142 }
143 }
144
145 public function get_parent_selector( $class_name ) {
146 return $this->parent_class ? str_replace( '{{WRAPPER}}', $this->parent_class, $class_name ) : $class_name;
147 }
148
149 private function remove_empty_css( $base_styles ) {
150 if ( empty( $base_styles ) || ! is_array( $base_styles ) || ( is_array( $base_styles ) && ! count( $base_styles ) ) ) {
151 return [];
152 }
153
154 $styles = [];
155
156 foreach ( $base_styles as $prop => $value ) {
157 if ( 'font-family' === $prop && isset( $this->font_category[ $value ] ) ) {
158 $value = $this->get_font_family_css( $value, $this->font_category[ $value ] );
159 }
160 // Trim value to avoid whitespace-only entries
161 $trimmed = trim( $value );
162 // // Remove if empty, or if it matches only a unit (like 'px', '%', 'em') without any number
163 if ( $trimmed === '' || preg_match( '/^(px|em|rem|vh|vw|vmin|vmax|cm|mm|in|pt|pc|%)$/i', $trimmed ) ) {
164 continue;
165 }
166
167 $styles[ $prop ] = $trimmed;
168 }
169
170 return $styles;
171 }
172
173 private function filter_responsive_styles( $base_styles, $responsive_styles ) {
174 if ( empty( $responsive_styles ) || ! is_array( $responsive_styles ) ) {
175 return [];
176 }
177
178 $difference = [];
179
180 foreach ( $responsive_styles as $prop => $value ) {
181 $trimmed = trim( $value );
182
183 // // Remove if empty, or if it matches only a unit (like 'px', '%', 'em') without any number
184 if ( $trimmed === '' || preg_match( '/^(px|em|rem|vh|vw|vmin|vmax|cm|mm|in|pt|pc|%)$/i', $trimmed ) ) {
185 continue;
186 }
187
188 // Only include if the value is different from base styles
189 if ( ! isset( $base_styles[ $prop ] ) || $base_styles[ $prop ] !== $trimmed ) {
190 $difference[ $prop ] = $trimmed;
191 }
192 }
193
194 return $difference;
195 }
196
197
198 public function get_font_family_css( string $font_name, string $category ): string {
199 // Quote font name if it contains spaces
200 if ( strpos( $font_name, ' ' ) !== false ) {
201 $font_name = '"' . $font_name . '"';
202 }
203
204 // Map category to fallback
205 switch ( $category ) {
206 case 'serif':
207 $fallback = 'serif';
208 break;
209 case 'sans-serif':
210 $fallback = 'sans-serif';
211 break;
212 case 'monospace':
213 $fallback = 'monospace';
214 break;
215 case 'display':
216 $fallback = 'sans-serif';
217 break;
218 case 'handwriting':
219 $fallback = 'cursive';
220 break;
221 default:
222 $fallback = 'sans-serif';
223 }
224
225 return $font_name . ', ' . $fallback;
226 }
227 }
228
229