PluginProbe ʕ •ᴥ•ʔ
Kubio AI Page Builder / 2.8.3
Kubio AI Page Builder v2.8.3
2.8.4 2.8.3 2.8.2 2.8.1 trunk 1.0.0 1.0.1 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.9.0 2.0.0 2.1.1 2.1.2 2.1.3 2.2.0 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.5 2.5.0 2.5.1 2.5.2 2.5.3 2.6.0 2.6.1 2.6.2 2.6.3 2.6.5 2.6.6 2.6.7 2.7.0 2.7.1 2.7.2 2.7.3 2.8.0
kubio / lib / src / NotificationsManager.php
kubio / lib / src Last commit date
CLI 1 year ago Core 1 week ago DemoSites 1 month ago AssetsDependencyInjector.php 1 year ago Config.php 1 year ago FileLog.php 1 year ago Flags.php 1 year ago GoogleFontsLocalLoader.php 1 year ago GutenbergControls.php 1 year ago Migrations.php 1 year ago NotificationsManager.php 3 days ago PluginsManager.php 2 years ago
NotificationsManager.php
400 lines
1 <?php
2
3 namespace Kubio;
4
5 use DateTime;
6
7 class NotificationsManager {
8
9 private static $remote_data_url_base = 'https://kubiobuilder.com/wp-json/wp/v2/notification';
10
11 private static $plugins_to_install = array();
12
13 public static function load() {
14 add_action( 'admin_init', array( NotificationsManager::class, 'init' ) );
15 if ( ! wp_next_scheduled( NotificationsManager::class . '::onSchedule' ) ) {
16 wp_schedule_event( time(), 'twicedaily', NotificationsManager::class . '::onSchedule' );
17 }
18 add_action(NotificationsManager::class . '::onSchedule', NotificationsManager::class . '::onSchedule' );
19 }
20
21 /**
22 * Checks if this WordPress instances is declared as a development environment.
23 * Relies on the `KUBIO_NOTIFICATIONS_DEV_MODE` constant.
24 *
25 * @return bool
26 */
27 private static function isDevMode() {
28 return ( defined( 'KUBIO_NOTIFICATIONS_DEV_MODE' ) && KUBIO_NOTIFICATIONS_DEV_MODE );
29 }
30
31 /**
32 * Verifies the data and displays remote notifications accordingly.
33 *
34 * @return void
35 */
36 public static function init() {
37
38 // check if we have cached data in transient
39 $notifications = get_transient( static::getTransientKey() );
40
41 if ( $notifications === false || self::isDevMode() ) {
42 // No notifications, try to get them from remote and cache them.
43 static::prepareRetrieveRemoteNotifications();
44 }
45
46 static::displayNotifications( $notifications );
47
48 add_action('admin_footer', array( NotificationsManager::class, 'printNoticePluginInstallScript' ) );
49
50 add_action( 'wp_ajax_kubio-remote-notifications-retrieve', array( NotificationsManager::class, 'updateNotificationsData' ) );
51 }
52
53 public static function onSchedule() {
54 // check if we have cached data in transient
55 $notifications = get_transient( static::getTransientKey() );
56
57 if ( $notifications === false || self::isDevMode() ) {
58 // No notifications, try to get them from remote and cache them.
59 static::callNotificationsEndpoint();
60 }
61 }
62
63 /**
64 * Adds a JavaScript code which fetches notifications asynchronously.
65 *
66 * @return void
67 */
68 public static function prepareRetrieveRemoteNotifications() {
69
70 add_action(
71 'admin_footer',
72 function () {
73 $fetch_url = add_query_arg(
74 array(
75 'action' => 'kubio-remote-notifications-retrieve',
76 '_wpnonce' => wp_create_nonce( 'kubio-remote-notifications-retrieve-nonce' ),
77
78 ),
79 admin_url( 'admin-ajax.php' )
80 ); ?>
81 <script>
82 window.fetch("<?php echo esc_url_raw( $fetch_url ); ?>")
83 </script>
84 <?php
85 }
86 );
87 }
88
89 /**
90 * Retrieves notifications and saves them in a transient.
91 *
92 * @return void
93 */
94 public static function updateNotificationsData() {
95 check_ajax_referer( 'kubio-remote-notifications-retrieve-nonce' );
96 $done = static::callNotificationsEndpoint();
97 wp_send_json_success( $done );
98
99 }
100
101 public static function callNotificationsEndpoint() {
102
103 $url = add_query_arg(
104 array(
105 '_fields' => 'acf,id',
106 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
107 'meta_key' => 'license_type',
108 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
109 'meta_value' => apply_filters( 'kubio/notifications/license_type', 'free' ),
110 'kubio_version' => KUBIO_VERSION,
111 'kubio_build' => KUBIO_BUILD_NUMBER,
112 'kubio_theme_version' => wp_get_theme()->get( 'Version' ),
113 'template' => get_template(),
114 'stylesheet' => get_stylesheet(),
115 'source' => Flags::get( 'start_source', 'other' ),
116 'f' => Flags::get( 'kubio_f' ),
117 'activated_on' => Flags::get( 'kubio_activation_time', '' ),
118 'pro_activated_on' => Flags::get( 'kubio_pro_activation_time', '' ),
119 ),
120 self::$remote_data_url_base
121 );
122
123 $data = wp_remote_get( $url );
124
125 $code = wp_remote_retrieve_response_code( $data );
126 $body = wp_remote_retrieve_body( $data );
127
128 $posts = json_decode( $body, true );
129
130 if ( $code !== 200 ) {
131 wp_send_json_error( $code );
132 }
133
134 $notifications = array();
135
136 foreach ( $posts as $post ) {
137 $notifications[ $post['id'] ] = $post;
138 }
139
140 $done = set_transient( static::getTransientKey(), $notifications, DAY_IN_SECONDS );
141
142 return $done;
143 }
144
145 /**
146 * Adds the stack of notifications for display using `kubio_add_dismissable_notice`.
147 *
148 * @param array $notifications
149 * @return void
150 */
151 private static function displayNotifications( $notifications ) {
152
153 if ( empty( $notifications ) ) {
154 return;
155 }
156
157 foreach ( $notifications as $notification ) {
158 $params = $notification['acf'];
159 $params['id'] = $notification['id'];
160
161 if ( $params['dev'] === true && ! self::isDevMode() ) {
162 continue;
163 }
164
165 if ( ! self::isTimeToDisplay( $params ) ) {
166 continue;
167 }
168
169 if ( self::isPluginInstallNotice( $params ) && self::isPluginAlreadyInstalled( $params['plugin_slug'] ) ) {
170 continue;
171 }
172
173 $classnames = 'kubio-remote-notification';
174 $allowed_types = array( 'info', 'warning', 'error', 'success' );
175
176 if ( ! empty( $params['type'] ) && in_array( $params['type'], $allowed_types ) ) {
177 $classnames .= ' notice-' . $params['type'] . ' kubio-remote-notification-' . $params['type'];
178 }
179
180 $notice_key = 'kubio-remote-notice-' . $params['id'];
181
182 if ( self::isDevMode() ) {
183 $notice_key .= '-' . time();
184 }
185
186 kubio_add_dismissable_notice(
187 $notice_key,
188 array( NotificationsManager::class, 'displayNotification' ),
189 0,
190 $params,
191 $classnames
192 );
193 }
194 }
195
196
197 /**
198 * Whether the given notification is a plugin-install notice.
199 * Relies on the dedicated `is_plugin_install` / `plugin_slug` ACF fields.
200 *
201 * @param array $params Notification parameters.
202 * @return bool
203 */
204 private static function isPluginInstallNotice( $params ) {
205 return ! empty( $params['is_plugin_install'] ) && ! empty( $params['plugin_slug'] );
206 }
207
208 private static function isPluginAlreadyInstalled($plugin_slug){
209 static $active_plugin_slugs = null;
210
211 if($active_plugin_slugs === null){
212 $active_plugin_paths = get_option( 'active_plugins' );
213 $active_plugin_slugs = array_map('dirname', $active_plugin_paths);
214 }
215 return in_array($plugin_slug, $active_plugin_slugs);
216 }
217
218 /**
219 * Prints the HTML of a notification for the given params.
220 *
221 * @param $params
222 * @return void
223 */
224 public static function displayNotification( $params ) {
225
226 $args = array(
227 'utm_theme' => get_template(),
228 'utm_childtheme' => get_stylesheet(),
229 'utm_install_source' => Flags::get( 'start_source', 'other' ),
230 'utm_activated_on' => Flags::get( 'kubio_activation_time', '' ),
231 'utm_pro_activated_on' => Flags::get( 'kubio_pro_activation_time', '' ),
232 'utm_campaign' => 'wp-notice',
233 'utm_medium' => 'wp',
234 );
235
236 wp_enqueue_script( 'wp-util' ); // make sure to enqueue the admin ajax functions
237
238 $is_plugin_install = self::isPluginInstallNotice( $params );
239 $plugin_slug = $is_plugin_install ? $params['plugin_slug'] : '';
240 $plugin_redirect = $is_plugin_install && ! empty( $params['plugin_redirect'] ) ? $params['plugin_redirect'] : '';
241
242 if ( $is_plugin_install ) {
243 self::$plugins_to_install[ $plugin_slug ] = array(
244 'slug' => $plugin_slug,
245 'label' => $params['plugin_label'] ?? '',
246 'redirect' => $plugin_redirect,
247 );
248 }
249
250 $buttons_to_display = [
251 'primary' => [
252 'link' => $params['primary_link'] && isset($params['primary_link']['url']) ? add_query_arg( $args, $params['primary_link']['url'] ) : '',
253 'text' => $params['primary_link'] && isset($params['primary_link']['title']) ? $params['primary_link']['title'] : '',
254 'class' => 'kubio-remote-notification-primary',
255 // The plugin install/activate flow is driven by the primary button.
256 'plugin_slug' => $plugin_slug,
257 'plugin_redirect' => $plugin_redirect,
258 'plugin_label' => $is_plugin_install ? ( $params['plugin_label'] ?? '' ) : '',
259 ],
260 'secondary' => [
261 'link' => $params['secondary_link'] && isset($params['secondary_link']['url']) ? add_query_arg( $args, $params['secondary_link']['url'] ) : '',
262 'text' => $params['secondary_link'] && isset($params['secondary_link']['title']) ? $params['secondary_link']['title'] : '',
263 'class' => 'kubio-remote-notification-secondary',
264 'plugin_slug' => '',
265 'plugin_redirect' => '',
266 'plugin_label' => '',
267 ]
268 ]
269
270 ?>
271 <div
272 class="kubio-remote-notification-wrapper"
273 id="kubio-remote-notification-<?php echo esc_attr( $params['id'] ); ?>"
274 <?php echo $is_plugin_install ? 'data-has-suggested-plugins="1"' : ''; ?>
275 >
276 <div class="kubio-remote-notification-icon">
277 <?php
278 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
279 echo wp_kses_post( KUBIO_LOGO_SVG );
280 ?>
281 </div>
282 <?php if ( ! empty( $params['message'] ) ) { ?>
283 <div class="kubio-remote-notification-message">
284 <?php
285 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
286 echo wpautop( $params['message'] );
287 ?>
288 </div>
289 <?php } ?>
290 <div class="kubio-remote-notification-buttons">
291 <?php foreach($buttons_to_display as $button){ ?>
292 <?php if(!empty($button['link']) && !empty($button['text'])){ ?>
293 <a
294 href="<?php echo esc_url( $button['link'] ); ?>"
295 class="button button-large <?php echo esc_attr( $button['class'] ); ?>"
296 <?php if(!empty($button['plugin_slug'])){ ?>
297 data-suggested-plugin-slug="<?php echo esc_attr( $button['plugin_slug'] ); ?>"
298 <?php if(!empty($button['plugin_redirect'])){ ?>
299 data-plugin-redirect="<?php echo esc_url( $button['plugin_redirect'] ); ?>"
300 data-plugin-label="<?php echo esc_attr( $button['plugin_label'] ); ?>"
301 <?php } ?>
302 <?php } ?>
303 >
304 <?php echo esc_html( $button['text'] ); ?>
305 </a>
306 <?php } ?>
307 <?php } ?>
308 </div>
309 </div>
310 <?php
311 }
312
313 public static function printNoticePluginInstallScript(){
314
315 if(empty(static::$plugins_to_install)){
316 return;
317 }
318
319 $plugins_states = array();
320 foreach(array_keys(static::$plugins_to_install) as $plugin_slug){
321 $plugins_states[ $plugin_slug ] = PluginsManager::getInstance()->getPluginStatus( $plugin_slug );
322 }
323
324 wp_enqueue_script('kubio-admin-area');
325 $data = array(
326 'ajax_url' => admin_url( 'admin-ajax.php' ),
327 'ajax_nonce' => wp_create_nonce( 'kubio-ajax-demo-site-verification' ),
328 'texts' => array(
329 'importing_template' => '%s',
330 'plugins_states' => array(
331 'ACTIVE' => esc_html__( 'Active', 'kubio' ),
332 'INSTALLED' => esc_html__( 'Installed', 'kubio' ),
333 'NOT_INSTALLED' => esc_html__( 'Not Installed', 'kubio' ),
334 ),
335 'import_stopped' => esc_html__( 'Import stopped', 'kubio' ),
336 ),
337 'plugins_states' => $plugins_states,
338 );
339 wp_add_inline_script(
340 'kubio-admin-area',
341 sprintf( 'kubio.adminArea.initNoticePluginInstall(%s)', wp_json_encode( $data ) ),
342 'after'
343 );
344 }
345
346 /**
347 * Verify if the notification checks the time requirements.
348 *
349 * @param array $params Notification parameters.
350 * @return bool
351 */
352 private static function isTimeToDisplay( array $params ) {
353
354 if ( $params['has_time_boundary'] === true ) {
355 return self::inTimeBoundaries( $params['start_date'], $params['date_end'] );
356 }
357
358 $install_time = Flags::get( 'kubio_activation_time', time() );
359
360 $install_time = apply_filters( 'kubio/notifications/install_time', $install_time );
361
362 $show_after = strtotime( '+' . $params['after'] . ' days', $install_time );
363 $time = new DateTime( 'NOW' );
364
365 if ( $show_after <= $time->getTimeStamp() ) {
366 return true;
367 }
368
369 return false;
370 }
371
372 /**
373 * Checks if the current time is between a given $start and $end date.
374 * If $start or $end are null that generally means there is no restrain for that edge.
375 *
376 * @param $start
377 * @param $end
378 * @return bool
379 */
380 private static function inTimeBoundaries( $start, $end ) {
381 $time = new DateTime( 'today' );
382 $start_date = \DateTime::createFromFormat( 'Ymd', $start );
383
384 if ( $start === null || $start_date && $start_date <= $time ) {
385 $end_date = \DateTime::createFromFormat( 'Ymd', $end );
386
387 if ( $end === null || $end_date && $time <= $end_date ) {
388 return true;
389 }
390 }
391
392 return false;
393 }
394
395 private static function getTransientKey() {
396 $transient = apply_filters( 'kubio/notifications/transient_key', 'kubio_remote_notifications' );
397 return $transient;
398 }
399 }
400