PluginProbe
WebberZone Top 10 — Popular Posts / 4.5.1
WebberZone Top 10 — Popular Posts v4.5.1
4.5.1 4.5.0 4.4.3 4.4.2 4.4.1 4.4.0 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 trunk 1.0 1.0.1 1.1 1.2 1.3 1.4 1.4.1 1.5 1.5.1 1.5.2 1.5.3 1.6 1.6.1 All 117 releases
top-10 / includes / frontend / class-styles-handler.php

class-styles-handler.php in WebberZone Top 10 — Popular Posts 4.5.1, at includes/frontend/class-styles-handler.php

399 lines 10.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Styles Handler class.
4 *
5 * @package WebberZone\Top_Ten\Frontend
6 */
7
8 namespace WebberZone\Top_Ten\Frontend;
9
10 use WebberZone\Top_Ten\Admin\Settings;
11 use WebberZone\Top_Ten\Util\Hook_Registry;
12
13 if ( ! defined( 'WPINC' ) ) {
14 die;
15 }
16
17 /**
18 * Styles Handler Class.
19 *
20 * @since 3.3.0
21 */
22 class Styles_Handler {
23
24 /**
25 * Constructor class.
26 *
27 * @since 3.3.0
28 */
29 public function __construct() {
30 Hook_Registry::add_action( 'wp_head', array( $this, 'header' ) );
31 Hook_Registry::add_action( 'wp_enqueue_scripts', array( $this, 'register_styles' ) );
32 Hook_Registry::add_action( 'elementor/preview/enqueue_styles', array( $this, 'enqueue_all_styles' ) );
33 }
34
35 /**
36 * Function to add CSS to header.
37 *
38 * @since 1.9
39 */
40 public static function header() {
41
42 $custom_css = stripslashes( tptn_get_option( 'custom_css' ) );
43
44 // Add CSS to header.
45 if ( $custom_css ) {
46 echo '<style type="text/css">' . $custom_css . '</style>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
47 }
48 }
49
50 /**
51 * Enqueue every registered style. Elementor's preview iframe can switch widget styles without
52 * a full reload, so all style choices need to be available there.
53 *
54 * @since 4.5.0
55 */
56 public static function enqueue_all_styles() {
57 foreach ( wp_list_pluck( Settings::get_styles(), 'id' ) as $style_id ) {
58 self::enqueue_style( $style_id );
59 }
60 }
61
62 /**
63 * Register and enqueue one style by ID.
64 *
65 * @since 4.5.0
66 *
67 * @param string $style_id Style ID.
68 */
69 public static function enqueue_style( $style_id ) {
70 $style_array = self::get_style( $style_id );
71
72 if ( empty( $style_array['name'] ) ) {
73 return;
74 }
75
76 $style = $style_array['name'];
77 $extra_css = $style_array['extra_css'];
78 $is_rtl = is_rtl();
79 $handle = "tptn-style-{$style}";
80
81 wp_register_style(
82 $handle,
83 plugins_url( self::get_stylesheet_path( $style, $is_rtl ), TOP_TEN_PLUGIN_FILE ),
84 array(),
85 TOP_TEN_VERSION
86 );
87 wp_enqueue_style( $handle );
88
89 if ( ! empty( $extra_css ) ) {
90 wp_add_inline_style( $handle, $extra_css );
91 }
92 }
93
94 /**
95 * Enqueue and print one style immediately when rendering happens after wp_head.
96 *
97 * @since 4.5.0
98 *
99 * @param string $style_id Style ID.
100 */
101 public static function enqueue_style_now( $style_id ) {
102 self::enqueue_style( $style_id );
103
104 if ( ! did_action( 'wp_head' ) ) {
105 return;
106 }
107
108 $style_array = self::get_style( $style_id );
109
110 if ( empty( $style_array['name'] ) ) {
111 return;
112 }
113
114 wp_print_styles( array( "tptn-style-{$style_array['name']}" ) );
115 }
116
117 /**
118 * Resolve a style ID using the same thumbnail-placement precedence everywhere.
119 *
120 * @since 4.5.0
121 *
122 * @param string|null $post_thumb_op Thumbnail placement override.
123 * @param string|null $style_id Style override.
124 * @return string Resolved style ID.
125 */
126 public static function resolve_style_id( $post_thumb_op = null, $style_id = null ) {
127 if ( null === $post_thumb_op || '' === (string) $post_thumb_op ) {
128 $post_thumb_op = tptn_get_option( 'post_thumb_op', 'text_only' );
129 }
130
131 if ( 'text_only' === $post_thumb_op ) {
132 return 'text_only';
133 }
134
135 if ( null === $style_id || '' === (string) $style_id ) {
136 $style_id = tptn_get_option( 'tptn_styles', 'no_style' );
137 }
138
139 return (string) $style_id;
140 }
141
142 /**
143 * Enqueue styles for the site-wide setting and any builder/shortcode instance on the queried
144 * post.
145 *
146 * @since 4.5.0
147 */
148 public static function register_styles() {
149 foreach ( self::get_style_ids_to_load() as $style_id ) {
150 self::enqueue_style( $style_id );
151 }
152 }
153
154 /**
155 * Get the style IDs required for the current request.
156 *
157 * Builder editors load every registered style because an element can change its style live.
158 * Normal requests scan shortcode, Elementor, and Bricks data on the queried post; elements in
159 * theme templates are covered by Builder_Atts::ensure_style_enqueued() at render time.
160 *
161 * @since 4.5.0
162 *
163 * @return string[] Style IDs.
164 */
165 protected static function get_style_ids_to_load() {
166 if ( function_exists( 'vc_is_inline' ) && vc_is_inline() ) {
167 return wp_list_pluck( Settings::get_styles(), 'id' );
168 }
169
170 if ( function_exists( 'bricks_is_builder' ) && bricks_is_builder() ) {
171 return wp_list_pluck( Settings::get_styles(), 'id' );
172 }
173
174 $style_ids = array( (string) tptn_get_option( 'tptn_styles', 'no_style' ) );
175 $post = get_post();
176
177 if ( ! $post ) {
178 return array_unique( $style_ids );
179 }
180
181 if ( preg_match_all( '/\[(?:tptn_list|tptn_popular_posts)\b[^\]]*\]/', $post->post_content, $shortcodes ) ) {
182 foreach ( $shortcodes[0] as $shortcode ) {
183 if ( preg_match( '/\bpost_thumb_op=["\']text_only["\']/', $shortcode ) ) {
184 $style_ids[] = 'text_only';
185 } elseif ( preg_match( '/\btptn_styles=["\']([a-z_]+)["\']/', $shortcode, $match ) ) {
186 $style_ids[] = $match[1];
187 }
188 }
189 }
190
191 array_push( $style_ids, ...self::get_elementor_style_ids( $post->ID ) );
192 array_push( $style_ids, ...self::get_bricks_style_ids( $post->ID ) );
193
194 return array_unique( $style_ids );
195 }
196
197 /**
198 * Extract styles from Top 10 Elementor widgets saved in `_elementor_data`.
199 *
200 * @since 4.5.0
201 *
202 * @param int $post_id Post ID.
203 * @return string[] Style IDs.
204 */
205 protected static function get_elementor_style_ids( $post_id ) {
206 $data = get_post_meta( $post_id, '_elementor_data', true );
207
208 if ( empty( $data ) ) {
209 return array();
210 }
211
212 $elements = is_array( $data ) ? $data : json_decode( (string) $data, true );
213
214 if ( ! is_array( $elements ) ) {
215 return array();
216 }
217
218 $style_ids = array();
219 self::walk_elementor_elements( $elements, $style_ids );
220
221 return array_map( 'strval', $style_ids );
222 }
223
224 /**
225 * Recursively collect style IDs from Top 10 Elementor widgets.
226 *
227 * @since 4.5.0
228 *
229 * @param array $elements Element tree.
230 * @param array $style_ids Collected style IDs, by reference.
231 */
232 protected static function walk_elementor_elements( array $elements, array &$style_ids ) {
233 foreach ( $elements as $element ) {
234 if ( ! is_array( $element ) ) {
235 continue;
236 }
237
238 if ( isset( $element['widgetType'] ) && 'tptn_popular_posts' === $element['widgetType'] ) {
239 $settings = isset( $element['settings'] ) && is_array( $element['settings'] ) ? $element['settings'] : array();
240 $style_ids[] = self::resolve_style_id(
241 $settings['post_thumb_op'] ?? null,
242 $settings['tptn_styles'] ?? null
243 );
244 }
245
246 if ( ! empty( $element['elements'] ) && is_array( $element['elements'] ) ) {
247 self::walk_elementor_elements( $element['elements'], $style_ids );
248 }
249 }
250 }
251
252 /**
253 * Extract styles from Top 10 Bricks elements saved on a post.
254 *
255 * @since 4.5.0
256 *
257 * @param int $post_id Post ID.
258 * @return string[] Style IDs.
259 */
260 protected static function get_bricks_style_ids( $post_id ) {
261 $meta_keys = array();
262
263 foreach ( array( 'BRICKS_DB_PAGE_CONTENT', 'BRICKS_DB_PAGE_HEADER', 'BRICKS_DB_PAGE_FOOTER' ) as $constant ) {
264 if ( defined( $constant ) ) {
265 $meta_keys[] = constant( $constant );
266 }
267 }
268
269 $style_ids = array();
270
271 foreach ( $meta_keys as $meta_key ) {
272 $elements = get_post_meta( $post_id, $meta_key, true );
273
274 if ( ! is_array( $elements ) ) {
275 continue;
276 }
277
278 foreach ( $elements as $element ) {
279 if ( ! is_array( $element ) || 'tptn-popular-posts' !== ( $element['name'] ?? '' ) ) {
280 continue;
281 }
282
283 $settings = isset( $element['settings'] ) && is_array( $element['settings'] ) ? $element['settings'] : array();
284 $style_ids[] = self::resolve_style_id(
285 $settings['post_thumb_op'] ?? null,
286 $settings['tptn_styles'] ?? null
287 );
288 }
289 }
290
291 return $style_ids;
292 }
293
294 /**
295 * Get stylesheet path accounting for minified and pro files.
296 *
297 * @since 4.2.0
298 *
299 * @param string $style Style name.
300 * @param bool $is_rtl Whether RTL stylesheet should be loaded.
301 *
302 * @return string
303 */
304 public static function get_stylesheet_path( $style, $is_rtl = false ) {
305
306 $base_path = 'includes/frontend/css/';
307 if ( false !== strpos( $style, '-pro' ) ) {
308 $base_path = 'includes/pro/frontend/css/';
309 }
310
311 $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
312 $rtl = $is_rtl ? '-rtl' : '';
313
314 return "{$base_path}{$style}{$rtl}{$suffix}.css";
315 }
316
317 /**
318 * Get the current style for the popular posts.
319 *
320 * @since 3.0.0
321 * @since 3.2.0 Added parameter $style
322 *
323 * @param string $style Style parameter.
324 *
325 * @return array Contains two elements:
326 * 'name' holding style name and 'extra_css' to be added inline.
327 */
328 public static function get_style( $style = '' ) {
329
330 $style_array = array();
331 $thumb_width = max( 1, (int) tptn_get_option( 'thumb_width', 150 ) );
332 $thumb_height = max( 1, (int) tptn_get_option( 'thumb_height', 150 ) );
333 $aspect_ratio = $thumb_width / $thumb_height;
334 $tptn_style = ! empty( $style ) ? $style : tptn_get_option( 'tptn_styles' );
335
336 switch ( $tptn_style ) {
337 case 'left_thumbs':
338 $style_array['name'] = 'left-thumbs';
339 $style_array['extra_css'] = "
340 .tptn-left-thumbs {
341 --tptn-thumb-width: {$thumb_width}px;
342 --tptn-thumb-height: {$thumb_height}px;
343 --tptn-thumb-aspect-ratio: {$aspect_ratio};
344 }
345 .tptn-left-thumbs img.tptn_thumb {
346 width: min( var(--tptn-thumb-width), 100% );
347 height: var(--tptn-thumb-height);
348 max-height: var(--tptn-thumb-height);
349 aspect-ratio: var(--tptn-thumb-aspect-ratio);
350 object-fit: cover;
351 }
352 .tptn-left-thumbs li > a.tptn_link {
353 display: block;
354 flex: 0 0 auto;
355 align-self: flex-start;
356 padding: var(--tptn-thumb-frame-padding, 0.25rem );
357 border-width: var(--tptn-thumb-frame-border-width, 1px );
358 border-style: solid;
359 border-color: var(--tptn-thumb-border, #ccc );
360 border-radius: var(--tptn-border-radius, 8px );
361 box-shadow: var(--tptn-shadow, 0 2px 4px rgba(0, 0, 0, 0.15) );
362 transition: transform var(--tptn-transition, 0.2s ease), box-shadow var(--tptn-transition, 0.2s ease);
363 will-change: transform;
364 }
365 .tptn-left-thumbs ul li:hover > a.tptn_link {
366 transform: scale(1.03);
367 box-shadow: var(--tptn-shadow-hover, 0 4px 8px rgba(0, 0, 0, 0.2) );
368 }
369 .tptn-left-thumbs .tptn_title {
370 width: 100%;
371 }
372 ";
373 break;
374
375 case 'text_only':
376 $style_array['name'] = 'text-only';
377 $style_array['extra_css'] = '';
378 break;
379
380 default:
381 $style_array['name'] = '';
382 $style_array['extra_css'] = '';
383 break;
384 }
385
386 /**
387 * Filter the style array which contains the name and extra_css.
388 *
389 * @since 3.2.0
390 *
391 * @param array $style_array Style array containing name and extra_css.
392 * @param string $tptn_style Style name.
393 * @param int $thumb_width Thumbnail width.
394 * @param int $thumb_height Thumbnail height.
395 */
396 return apply_filters( 'tptn_get_style', $style_array, $tptn_style, $thumb_width, $thumb_height );
397 }
398 }
399