PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.11.1
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.11.1
2.13.0 2.13.1 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 All 80 releases
ablocks / includes / classes / css-generator-v2.php

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

204 lines 6.6 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 use ABlocks\Classes\FontStack;
10
11 class CssGeneratorV2 {
12 private $custom_css = '';
13 private $parent_class;
14 private $class_styles = [];
15
16 public function __construct( $attributes = [] ) {
17 $this->parent_class = '.ablocks-block-' . $attributes['block_id'];
18 if ( isset( $attributes['_custom_css'] ) ) {
19 $this->custom_css = $attributes['_custom_css'];
20 }
21
22 // Alert - don't touch here
23 if ( isset( $attributes['_margin'] ) ) { // check has advanced tab or not
24 $this->add_class_styles(
25 '{{WRAPPER}}',
26 BlockGlobal::get_wrapper_css( $attributes ),
27 BlockGlobal::get_wrapper_css( $attributes, 'Tablet' ),
28 BlockGlobal::get_wrapper_css( $attributes, 'Mobile' )
29 );
30 $this->add_class_styles(
31 '{{WRAPPER}}:hover',
32 BlockGlobal::get_wrapper_hover_css( $attributes ),
33 BlockGlobal::get_wrapper_hover_css( $attributes, 'Tablet' ),
34 BlockGlobal::get_wrapper_hover_css( $attributes, 'Mobile' )
35 );
36 $this->add_class_styles(
37 '{{WRAPPER}}.ablocks-hide-on-desktop,{{WRAPPER}}.ablocks-hide-on-tablet,{{WRAPPER}}.ablocks-hide-on-mobile',
38 BlockGlobal::get_wrapper_device_responsive_css( $attributes ),
39 BlockGlobal::get_wrapper_device_responsive_css( $attributes, 'Tablet' ),
40 BlockGlobal::get_wrapper_device_responsive_css( $attributes, 'Mobile' )
41 );
42 $this->add_class_styles(
43 '{{WRAPPER}}:hover > .ablocks-block-container',
44 BlockGlobal::get_container_hover_css( $attributes ),
45 BlockGlobal::get_container_hover_css( $attributes, 'Tablet' ),
46 BlockGlobal::get_container_hover_css( $attributes, 'Mobile' )
47 );
48 $this->add_class_styles(
49 '{{WRAPPER}} > .ablocks-block-container',
50 BlockGlobal::get_container_css( $attributes ),
51 BlockGlobal::get_container_css( $attributes, 'Tablet' ),
52 BlockGlobal::get_container_css( $attributes, 'Mobile' )
53 );
54 }//end if
55 }
56
57 public function add_class_styles( $class_name, $desktop_styles, $tablet_styles = [], $mobile_styles = [] ) {
58 $this->class_styles[] = [
59 'class_name' => $class_name,
60 'desktop_styles' => $desktop_styles,
61 'tablet_styles' => $tablet_styles,
62 'mobile_styles' => $mobile_styles
63 ];
64 }
65
66 public function generate_css() {
67 $css_output = '';
68
69 foreach ( $this->class_styles as $class_style ) {
70 $desktop_styles = $this->remove_empty_css( $class_style['desktop_styles'] );
71 $tablet_styles = $this->filter_responsive_styles( $desktop_styles, $class_style['tablet_styles'] );
72 $mobile_styles = $this->filter_responsive_styles( array_merge( $desktop_styles, $tablet_styles ), $class_style['mobile_styles'] );
73
74 $desktop_raw = $this->generate_css_for_media_query( 'desktop', $desktop_styles );
75 $tablet_raw = $this->generate_css_for_media_query( 'tablet', $tablet_styles );
76 $mobile_raw = $this->generate_css_for_media_query( 'mobile', $mobile_styles );
77
78 $desktop_css = AssetsGenerator::minify_css( $desktop_raw );
79 $tablet_css = AssetsGenerator::minify_css( $tablet_raw );
80 $mobile_css = AssetsGenerator::minify_css( $mobile_raw );
81
82 $parent_selector = $this->get_parent_selector( $class_style['class_name'] );
83 $css_blocks = [];
84
85 $addToCssBlocks = function ( $mediaQuery, $max_width, $css ) use ( &$css_blocks, $parent_selector ) {
86 if ( ! empty( $css ) ) {
87 $css_blocks[] = ( '' !== $mediaQuery )
88 ? "@media screen and (max-width: $max_width) {\n$parent_selector {\n$css\n}\n}"
89 : "$parent_selector {\n$css\n}";
90 }
91 };
92
93 // Always add desktop CSS
94 $addToCssBlocks( '', '', $desktop_css );
95
96 // Only add tablet CSS if it differs from desktop
97 if ( $tablet_raw !== $desktop_raw ) {
98 $addToCssBlocks( 'tablet', $this->get_breakpoint( 'tablet' ), $tablet_css );
99 }
100
101 // Only add mobile CSS if it differs from desktop AND tablet
102 if ( $mobile_raw !== $tablet_raw ) {
103 $addToCssBlocks( 'mobile', $this->get_breakpoint( 'mobile' ), $mobile_css );
104 }
105
106 $css_output .= implode( "\n\n", $css_blocks ) . "\n\n";
107 }//end foreach
108
109 $css_output .= $this->get_custom_css();
110
111 return preg_replace( '/\s+/', ' ', $css_output );
112 }
113
114 public function get_custom_css() {
115 return preg_replace( '/\bselector\b/', $this->parent_class, $this->custom_css );
116 }
117 public function generate_css_for_media_query( $media_query, $styles ) {
118 if ( empty( $styles ) ) {
119 return '';
120 }
121 $css_string = implode("\n", array_map(
122 function ( $property, $value ) {
123 return "$property: $value;";
124 },
125 array_keys( $styles ),
126 $styles
127 ));
128
129 return $css_string . "\n";
130 }
131
132 public function get_breakpoint( $media_query ) {
133 switch ( $media_query ) {
134 case 'tablet':
135 return '800px';
136 case 'mobile':
137 return '480px';
138 default:
139 return '1200px';
140 }
141 }
142
143 public function get_parent_selector( $class_name ) {
144 return $this->parent_class ? str_replace( '{{WRAPPER}}', $this->parent_class, $class_name ) : $class_name;
145 }
146 private function remove_empty_css( $base_styles ) {
147 if ( empty( $base_styles ) || ! is_array( $base_styles ) || ( is_array( $base_styles ) && ! count( $base_styles ) ) ) {
148 return [];
149 }
150
151 $styles = [];
152
153 foreach ( $base_styles as $prop => $value ) {
154 if ( 'font-family' === $prop ) {
155 // Safety net for styles that bypass the Typography control and set a
156 // bare family name directly. FontStack leaves finished values alone.
157 $value = FontStack::build( $value );
158 }
159 // Trim value to avoid whitespace-only entries
160 $trimmed = trim( $value );
161 // // Remove if empty, or if it matches only a unit (like 'px', '%', 'em') without any number
162 if ( $trimmed === '' || preg_match( '/^(px|em|rem|vh|vw|vmin|vmax|cm|mm|in|pt|pc|%|s|ms|deg|fr|ch|ex)$/i', $trimmed ) ) {
163 continue;
164 }
165
166 $styles[ $prop ] = $trimmed;
167 }
168
169 return $styles;
170 }
171 private function filter_responsive_styles( $base_styles, $responsive_styles ) {
172 if ( empty( $responsive_styles ) || ! is_array( $responsive_styles ) ) {
173 return [];
174 }
175
176 $difference = [];
177
178 foreach ( $responsive_styles as $prop => $value ) {
179 $trimmed = trim( $value );
180
181 // // Remove if empty, or if it matches only a unit (like 'px', '%', 'em') without any number
182 if ( $trimmed === '' || preg_match( '/^(px|em|rem|vh|vw|vmin|vmax|cm|mm|in|pt|pc|%|s|ms|deg|fr|ch|ex)$/i', $trimmed ) ) {
183 continue;
184 }
185
186 // Only include if the value is different from base styles
187 if ( ! isset( $base_styles[ $prop ] ) || $base_styles[ $prop ] !== $trimmed ) {
188 $difference[ $prop ] = $trimmed;
189 }
190 }
191
192 return $difference;
193 }
194
195
196 public function get_font_family_css( string $font_name, string $category = '' ): string {
197 // Kept for back-compat; the stack is built centrally now.
198 return FontStack::build( $font_name );
199 }
200
201
202 }
203
204