PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / trunk
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar vtrunk
3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 All 156 releases
← All changes | blocks/style-handler/style-handler.php +291 -0 0.2.5.6trunk View file →
@@ -1,0 +1,291 @@
1 +<?php
2 +
3 +namespace NotificationX\Blocks;
4 +
5 +use NotificationX\GetInstance;
6 +
7 +/**
8 + *
9 + * @method static StyleHandler get_instance($args = null)
10 + */
11 +final class StyleHandler {
12 + /**
13 + * Instance of NotificationX
14 + *
15 + * @var StyleHandler
16 + */
17 + use GetInstance;
18 +
19 + private $media_desktop = [
20 + 'name' => 'desktop',
21 + 'screen_size' => '',
22 + ];
23 + private $media_tab = [
24 + 'name' => 'tab',
25 + 'screen_size' => 1024,
26 + ];
27 + private $media_mobile = [
28 + 'name' => 'mobile',
29 + 'screen_size' => 767,
30 + ];
31 + private $eb_prefix = 'eb-style';
32 +
33 + public function __construct() {
34 + add_action( 'admin_enqueue_scripts', [ $this, 'notificationx_pro_blocks_edit_post' ] );
35 + add_action( 'wp_ajax_notificationx_pro_write_block_css', [ $this, 'write_block_css' ] );
36 + add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_frontend_css' ] );
37 + }
38 +
39 + /**
40 + * Enqueue a script in the WordPress admin on edit.php.
41 + *
42 + * @param int $hook Hook suffix for the current admin page.
43 + */
44 + public function notificationx_pro_blocks_edit_post( $hook ) {
45 + $current_screen = get_current_screen();
46 + $post_type = !empty( $current_screen->post_type ) ? $current_screen->post_type : '';
47 + $dir = dirname( __FILE__ );
48 + if ( ($hook == 'post-new.php' || $hook == 'post.php') && $post_type == 'nx_bar_eb' ) {
49 + wp_enqueue_script(
50 + 'notificationx-pro-blocks-edit-post',
51 + NOTIFICATIONX_URL . 'blocks/style-handler/style-handler.js',
52 + array(
53 + 'lodash',
54 + 'wp-i18n',
55 + 'wp-element',
56 + 'wp-hooks',
57 + 'wp-util',
58 + 'wp-components',
59 + 'wp-blocks',
60 + 'wp-editor',
61 + 'wp-block-editor',
62 + 'wp-edit-post',
63 + ),
64 + filemtime( NOTIFICATIONX_PATH . 'blocks/style-handler/style-handler.js' ),
65 + true
66 + );
67 + wp_localize_script('notificationx-pro-blocks-edit-post', 'nx_style_handler', [
68 + 'sth_nonce' => wp_create_nonce( 'nx_style_handler_nonce' ),
69 + 'editor_type' => 'edit-post',
70 + ]
71 + );
72 + } elseif ( $hook == 'site-editor.php' ) {
73 + wp_enqueue_script(
74 + 'notificationx-pro-blocks-edit-post',
75 + NOTIFICATIONX_URL . 'blocks/style-handler/style-handler.js',
76 + array(
77 + 'lodash',
78 + 'wp-i18n',
79 + 'wp-element',
80 + 'wp-hooks',
81 + 'wp-util',
82 + 'wp-components',
83 + 'wp-blocks',
84 + 'wp-editor',
85 + 'wp-block-editor',
86 + 'wp-edit-site',
87 + ),
88 + filemtime( NOTIFICATIONX_PATH . 'blocks/style-handler/style-handler.js' ),
89 + true
90 + );
91 + wp_localize_script('notificationx-pro-blocks-edit-post', 'nx_style_handler', [
92 + 'sth_nonce' => wp_create_nonce( 'nx_style_handler_nonce' ),
93 + 'editor_type' => 'edit-site',
94 + ]
95 + );
96 + // Override the default 'edit-post' global (set on the controls handle
97 + // in Blocks.php) so the inline block reads the core/edit-site store
98 + // when used inside the Full Site Editor.
99 + wp_localize_script('notificationx-block-controls', 'nx_style_handler', [
100 + 'sth_nonce' => wp_create_nonce( 'nx_style_handler_nonce' ),
101 + 'editor_type' => 'edit-site',
102 + ]
103 + );
104 + }
105 + }
106 +
107 + /**
108 + * Ajax callback to write css in upload directory
109 + *
110 + * @retun void
111 + * @since 1.0.2
112 + */
113 + public function write_block_css() {
114 + if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'nx_style_handler_nonce' ) || ! current_user_can( 'manage_options' ) ) {
115 + echo 'Invalid request';
116 + wp_die();
117 + }
118 +
119 + // The payload is a JSON blob of block styles, so it cannot be run through a
120 + // scalar sanitiser without destroying it. It is decoded structurally below and
121 + // this endpoint is already gated on a nonce plus manage_options above.
122 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
123 + $block_styles = isset( $_POST['data'] ) ? (array) json_decode( wp_unslash( $_POST['data'] ) ) : array();
124 +
125 + $editor_type = isset( $_POST['editorType'] ) ? sanitize_key( wp_unslash( $_POST['editorType'] ) ) : '';
126 + if ( $editor_type === 'edit-site' ) {
127 + $upload_dir = wp_upload_dir()['basedir'] . '/nx-style/';
128 + $editSiteCssPath = $upload_dir . 'nx-style-' . $editor_type . '.min.css';
129 + if ( file_exists( $editSiteCssPath ) ) {
130 + $existingCss = file_get_contents( $editSiteCssPath );
131 + $pattern = '~\/\*(.*?)\*\/~';
132 + preg_match_all( $pattern, $existingCss, $result, PREG_PATTERN_ORDER );
133 + $allComments = $result[0];
134 + $seperatedIds = array();
135 + foreach ( $allComments as $comment ) {
136 + $id = preg_replace( '/[^A-Za-z0-9\-]|Ends|Starts/', '', $comment );
137 +
138 + if ( strpos( $comment, 'Starts' ) ) {
139 + $seperatedIds[ $id ]['start'] = $comment;
140 + } elseif ( strpos( $comment, 'Ends' ) ) {
141 + $seperatedIds[ $id ]['end'] = $comment;
142 + }
143 + }
144 +
145 + $seperateStyles = array();
146 + foreach ( $seperatedIds as $key => $ids ) {
147 + $data = $this->get_between_data( $existingCss, $ids['start'], $ids['end'] );
148 + $seperateStyles[ $key ] = $data;
149 + }
150 +
151 + $finalCSSArray = array_merge( $seperateStyles, $block_styles );
152 +
153 + if ( ! empty( $css = $this->build_css( $finalCSSArray ) ) ) {
154 + $upload_dir = wp_upload_dir()['basedir'] . '/nx-style/';
155 + if ( ! file_exists( $upload_dir ) ) {
156 + wp_mkdir_p( $upload_dir );
157 + }
158 +
159 + file_put_contents( $editSiteCssPath, $css );
160 + }
161 + } else {
162 + if ( ! empty( $css = $this->build_css( $block_styles ) ) ) {
163 + $upload_dir = wp_upload_dir()['basedir'] . '/nx-style/';
164 + if ( ! file_exists( $upload_dir ) ) {
165 + wp_mkdir_p( $upload_dir );
166 + }
167 +
168 + file_put_contents( $editSiteCssPath, $css );
169 + }
170 + }
171 + } else {
172 + if ( ! empty( $css = $this->build_css( $block_styles ) ) ) {
173 + $upload_dir = wp_upload_dir()['basedir'] . '/nx-style/';
174 + if ( ! file_exists( $upload_dir ) ) {
175 + wp_mkdir_p( $upload_dir );
176 + }
177 + $style_id = isset( $_POST['id'] ) ? absint( wp_unslash( $_POST['id'] ) ) : 0;
178 + file_put_contents( $upload_dir . 'nx-style-' . $style_id . '.min.css', $css );
179 + }
180 + }
181 +
182 + wp_die();
183 + }
184 +
185 + /**
186 + * Enqueue frontend css for post if have one
187 + *
188 + * @return void
189 + * @since 1.0.2
190 + */
191 + public function enqueue_frontend_css() {
192 + global $post;
193 + if ( ! empty( $post ) && ! empty( $post->ID ) ) {
194 + $upload_dir = wp_upload_dir();
195 + $args = [ 'enabled' => true, 'source' => 'press_bar', 'updated_at' => ['<=', current_time('mysql') ] ];
196 + $pressbar_notifications = \NotificationX\Core\PostType::get_instance()->get_posts($args);
197 + foreach ($pressbar_notifications as $pressbar) {
198 + if( !empty( $pressbar['gutenberg_id'] ) ) {
199 + $style_file = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'eb-style' . DIRECTORY_SEPARATOR . $this->eb_prefix . '-' . $pressbar['gutenberg_id'] . '.min.css';
200 + $style_url = set_url_scheme($upload_dir['baseurl']) . '/' . 'eb-style' . '/' . $this->eb_prefix . '-' . $pressbar['gutenberg_id'] . '.min.css';
201 + if (file_exists($style_file)) {
202 + wp_enqueue_style(
203 + 'nx-style-' . $pressbar['gutenberg_id'], // Handle based only on post ID
204 + $style_url,
205 + [],
206 + filemtime($style_file) // Cache busting with last modified time
207 + );
208 + }
209 + }
210 +
211 + }
212 +
213 + if ( file_exists( $upload_dir['basedir'] . '/nx-style/nx-style-' . $post->ID . '.min.css' ) ) {
214 + wp_enqueue_style( 'nx-block-style-' . $post->ID, $upload_dir['baseurl'] . '/nx-style/nx-style-' . $post->ID . '.min.css', [], substr( md5( microtime( true ) ), 0, 10 ) );
215 + } elseif ( function_exists( 'icl_object_id' ) ) {
216 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Reviewed for the NotificationX codebase: acceptable in this context.
217 + $default_language = apply_filters( 'wpml_default_language', null );
218 + $english_version = icl_object_id( $post->ID, 'post', false, $default_language );
219 + if ( file_exists( $upload_dir['basedir'] . '/nx-style/nx-style-' . $english_version . '.min.css' ) ) {
220 + wp_enqueue_style( 'nx-block-style-' . $english_version, $upload_dir['baseurl'] . '/nx-style/nx-style-' . $english_version . '.min.css', [], substr( md5( microtime( true ) ), 0, 10 ) );
221 + }
222 + }
223 + if ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() && file_exists( $upload_dir['basedir'] . '/nx-style/nx-style-edit-site.min.css' ) ) {
224 + wp_enqueue_style( 'nx-fullsite-style', $upload_dir['baseurl'] . '/nx-style/nx-style-edit-site.min.css', [], substr( md5( microtime( true ) ), 0, 10 ) );
225 + }
226 + }
227 + }
228 +
229 + /**
230 + * Enqueue frontend css for post if have one
231 + *
232 + * @param string
233 + * @return string
234 + * @since 1.0.2
235 + */
236 + private function build_css( $style_object ) {
237 + // $block_styles = (array)json_decode(stripslashes($style_object));
238 + $block_styles = $style_object;
239 +
240 + $css = '';
241 + foreach ( $block_styles as $block_style_key => $block_style ) {
242 + if ( ! empty( $block_css = (array) $block_style ) ) {
243 + $css .= sprintf(
244 + '/* %1$s Starts */',
245 + $block_style_key
246 + );
247 + foreach ( $block_css as $media => $style ) {
248 + switch ( $media ) {
249 + case $this->media_desktop['name']:
250 + $css .= preg_replace( '/\s+/', ' ', $style );
251 + break;
252 + case $this->media_tab['name']:
253 + $css .= ' @media(max-width: 1024px){';
254 + $css .= preg_replace( '/\s+/', ' ', $style );
255 + $css .= '}';
256 + break;
257 + case $this->media_mobile['name']:
258 + $css .= ' @media(max-width: 767px){';
259 + $css .= preg_replace( '/\s+/', ' ', $style );
260 + $css .= '}';
261 + break;
262 + }
263 + }
264 + $css .= sprintf(
265 + '/* =%1$s= Ends */',
266 + $block_style_key
267 + );
268 + }
269 + }
270 + return trim( $css );
271 + }
272 +
273 + /**
274 + * Helper function to get string between 2 string
275 + *
276 + * @since 3.3.0
277 + */
278 + private function get_between_data( $string, $start, $end ) {
279 + $pos_string = stripos( $string, $start );
280 + $substr_data = substr( $string, $pos_string );
281 + $string_two = substr( $substr_data, strlen( $start ) );
282 + $second_pos = stripos( $string_two, $end );
283 + $string_three = substr( $string_two, 0, $second_pos );
284 +
285 + // remove whitespaces from result
286 + $result_unit = trim( $string_three );
287 +
288 + // return result_unit
289 + return $result_unit;
290 + }
291 +}