PluginProbe
wpForo Forum / 3.2.0
wpForo Forum v3.2.0
3.2.0 3.1.7 3.1.6 3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 All 140 releases
wpforo / classes / Notices.php

Notices.php in wpForo Forum 3.2.0, at classes/Notices.php

387 lines 11.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace wpforo\classes;
4
5 // Exit if accessed directly
6 if( ! defined( 'ABSPATH' ) ) exit;
7
8
9 class Notices {
10 private $types = [];
11 private $notices = [];
12 private $timeouts = [];
13
14 private function init_types() {
15 $this->types = array_merge(
16 [ 'neutral', 'error', 'success' ],
17 apply_filters( 'wpforo_notice_types', [] )
18 );
19 $this->types = array_map( 'strtolower', array_unique( $this->types ) );
20 }
21
22 private function init_timeouts() {
23 foreach( $this->types as $type ) $this->timeouts[ $type ] = $this->get_timeout( $type );
24 }
25
26 private function get_timeout( $type ) {
27 switch( $type ) {
28 case "success":
29 $durr = 4000;
30 break;
31 case "neutral":
32 $durr = 0;
33 break;
34 default:
35 $durr = 8000;
36 }
37
38 return apply_filters( "wpforo_notice_timeout_{$type}", $durr );
39 }
40
41 public function get_timeouts() {
42 return $this->timeouts;
43 }
44
45 private function reset() {
46 foreach( $this->types as $type ) $this->notices[ $type ] = [];
47 }
48
49 public function is_empty() {
50 foreach( $this->notices as $notice ) if( ! empty( $notice ) ) return false;
51
52 return true;
53 }
54
55 public function __construct() {
56 $this->init_types();
57 $this->reset();
58 add_action( 'wpforo_before_init', [ $this, 'init' ] );
59 }
60
61 public function init() {
62 $this->init_timeouts();
63 if( WPF()->session_token ) {
64 $sql = "SELECT DISTINCT `key`, `value` FROM `" . WPF()->tables->logs . "` WHERE `sessionid` = %s AND `key` IN('" . implode( "','", $this->types ) . "')";
65 if( $notices = (array) WPF()->db->get_results( WPF()->db->prepare( $sql, WPF()->session_token ), ARRAY_A ) ) {
66 foreach( $notices as $notice ) {
67 if( trim( (string) $notice['value'] ) ) {
68 $this->notices[ $notice['key'] ] = array_merge(
69 $this->notices[ $notice['key'] ],
70 wpforo_is_json( $notice['value'] ) ? json_decode( $notice['value'], true ) : (array) $notice['value']
71 );
72 }
73 }
74 }
75 }
76 }
77
78 /**
79 *
80 * @param string|array $args
81 * @param string $type (e.g. success|error)
82 * @param string|array $s
83 *
84 * @return bool
85 */
86 public function add( $args, $type = 'neutral', $s = [] ) {
87 if( ! $args ) return false;
88 $args = (array) $args;
89 if( $s && count( $args ) === 1 && is_array( $s ) && isset( $s[0] ) && ! is_array( $s[0] ) ) {
90 $s = [ $s ];
91 } else {
92 $s = (array) $s;
93 }
94
95 if( WPF()->session_token ) {
96 $type = strtolower( (string) $type );
97 foreach( $args as $key => $arg ) {
98 if( $s && isset( $s[ $key ] ) ) {
99 $args[ $key ] = wpforo_sprintf_array( wpforo_phrase( $arg, false ), $s[ $key ] );
100 } else {
101 $args[ $key ] = wpforo_phrase( $arg, false );
102 }
103 }
104
105 $this->notices[ $type ] = array_merge( (array) $this->notices[ $type ], (array) $args );
106 $this->notices[ $type ] = array_unique( $this->notices[ $type ] );
107
108 if( ! wpforo_is_ajax() ) {
109 $insert_id_backup = WPF()->db->insert_id;
110 WPF()->db->insert( WPF()->tables->logs, [
111 'sessionid' => WPF()->session_token,
112 'key' => $type,
113 'value' => wp_json_encode( (array) $args ),
114 ], [ '%s', '%s', '%s' ] );
115 WPF()->db->insert_id = $insert_id_backup;
116 }
117
118 return true;
119 }
120
121 return false;
122 }
123
124 /**
125 *
126 * @return bool
127 *
128 */
129 public function clear() {
130 if( WPF()->session_token ) {
131 $this->reset();
132
133 WPF()->db->delete( WPF()->tables->logs, [ 'sessionid' => WPF()->session_token ], [ '%s' ] );
134
135 return true;
136 }
137
138 return false;
139 }
140
141 /**
142 * <p class="success">success msg text</p><p class="error">error msg text</p>
143 *
144 * @return string
145 */
146 public function get_notices(): string {
147 $inner = '';
148 if( ! $this->is_empty() ) {
149 foreach( $this->notices as $type => $notice ) {
150 $notice = (array) $notice;
151 foreach( $notice as $msg ) {
152 if( ! is_array( $msg ) ) {
153 if( $msg = trim( (string) $msg ) ) $inner .= sprintf( '<p class="%s">%s</p>', sanitize_html_class( $type ), $msg );
154 }
155 }
156 }
157
158 $this->clear();
159 }
160
161 return $inner;
162 }
163
164 /**
165 *
166 * show collected wpforo notices
167 *
168 * @return void
169 */
170 public function show() {
171 if( $this->is_empty() ) return;
172 if( wpforo_is_admin() ) {
173 $this->backend( $this->notices );
174 } else {
175 $this->frontend( $this->notices );
176 }
177 $this->clear();
178 }
179
180 private function backend( $notices ) {
181 $inner = '';
182 foreach( $notices as $type => $notice ) {
183 $notice = (array) $notice;
184 foreach( $notice as $msg ) {
185 if( ! is_array( $msg ) && ( $msg = trim( (string) $msg ) ) ) {
186 $inner .= sprintf(
187 '<div class="notice is-dismissible notice-%s">
188 <p>%s</p>
189 </div>',
190 sanitize_html_class( $type ),
191 wpforo_kses( $msg )
192 );
193 }
194 }
195 }
196 echo '<div class="wpf-backend-notices-wrap">' . $inner . '</div>';
197 }
198
199 private function frontend( $notices ) {
200 $inner = '';
201 foreach( $notices as $type => $notice ) {
202 $notice = (array) $notice;
203 foreach( $notice as $msg ) {
204 if( ! is_array( $msg ) && ( $msg = trim( (string) $msg ) ) ) {
205 $inner .= sprintf( PHP_EOL . 'wpforo_notice_show("%1$s", "%2$s");' . PHP_EOL, addslashes( wpforo_kses( $msg ) ), sanitize_html_class( $type ) );
206 }
207 }
208 }
209 ?>
210 <script type="text/javascript">
211 window.jQuery(document).ready(function () {
212 <?php echo $inner ?>
213 });
214 </script>
215 <?php
216 }
217
218 public function addonNote() {
219 $lastHash = get_option( 'wpforo_addon_note_dismissed' );
220 if( ! $lastHash ) {
221 $hash = $this->addonHash();
222 update_option( 'wpforo_addon_note_dismissed', $hash );
223 update_option( 'wpforo_addon_note_first', 'true' );
224 } else {
225 $lastHashArray = explode( ',', $lastHash );
226 $currentHash = $this->addonHash();
227 if( $lastHash != $currentHash ) {
228 ?>
229 <div class="updated notice wpforo_addon_note is-dismissible" style="margin-top:10px;">
230 <p style="font-weight:normal; font-size:15px; border-bottom:1px dotted #DCDCDC; padding-bottom:10px; width:95%;"><strong><?php _e(
231 'New Addons for Your Forum!',
232 'wpforo'
233 ); ?></strong><br><span style="font-size:14px;"><?php _e( 'Extend your forum with wpForo addons', 'wpforo' ); ?></span></p>
234 <div style="font-size:14px;">
235 <?php
236 foreach( wpforo_get_addons_info() as $addon ) {
237 if( in_array( $addon['title'], $lastHashArray ) ) {
238 continue;
239 }
240 ?>
241 <div style="display:inline-block; min-width:27%; padding-right:10px; margin-bottom:1px;border-bottom:1px dotted #DCDCDC; border-right:1px dotted #DCDCDC; padding-bottom:10px;">
242 <img src="<?php echo $addon['thumb'] ?>" style="height:40px; width:auto; vertical-align:middle; margin:0 10px; text-decoration:none;"/> <a
243 href="<?php echo $addon['url'] ?>" style="text-decoration:none;" target="_blank">wpForo <?php echo $addon['title']; ?></a></div>
244 <?php
245 }
246 ?>
247 <div style="clear:both;"></div>
248 </div>
249 <p>&nbsp;&nbsp;&nbsp;<a href="<?php echo admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'addons' ) ) ?>"><?php _e( 'View all Addons', 'wpforo' ); ?> &raquo;</a></p>
250 </div>
251 <script>jQuery(document).on('click', '.wpforo_addon_note .notice-dismiss', function () {jQuery.ajax({ url: ajaxurl, data: { action: 'dismiss_wpforo_addon_note' } });});</script>
252 <?php
253 }
254 }
255 }
256
257 public function dismissAddonNote() {
258 $hash = $this->addonHash();
259 update_option( 'wpforo_addon_note_dismissed', $hash );
260 exit();
261 }
262
263 public function dismissAddonNoteOnPage() {
264 $hash = $this->addonHash();
265 update_option( 'wpforo_addon_note_dismissed', $hash );
266 }
267
268 public function addonHash() {
269 $viewed = '';
270 foreach( wpforo_get_addons_info() as $addon ) {
271 $viewed .= $addon['title'] . ',';
272 }
273
274 return $viewed;
275 }
276
277 public function refreshAddonPage() {
278 $lastHash = get_option( 'wpforo_addon_note_dismissed' );
279 $currentHash = $this->addonHash();
280 if( $lastHash != $currentHash ) {
281 ?>
282 <script language="javascript">jQuery(document).ready(function () {
283 location.reload();
284 });</script>
285 <?php
286 }
287 }
288
289 public function dismissCacheConflict() {
290 $excluded = wpforo_get_option( 'wpforo_excluded_cache', '', false );
291 $not_excluded_plugins = WPF()->cache->cache_plugins_status();
292 if( ! empty( $not_excluded_plugins ) ) {
293 foreach( $not_excluded_plugins as $plugin ) {
294 $excluded .= ',' . $plugin['name'];
295 }
296 }
297 wpforo_update_option( 'wpforo_excluded_cache', trim( (string) $excluded, ',' ) );
298 exit();
299 }
300
301 /**
302 * Addons Store Promo Box
303 * Shows a dismissible info box promoting the new Addons Store page
304 * where users can browse, purchase, and manage wpForo addons directly.
305 *
306 * @since 3.1.8
307 */
308 public function addonsStorePromo() {
309 if( ! current_user_can( 'manage_options' ) ) return;
310
311 // Don't show on the addons page itself (they're already there)
312 if( function_exists( 'get_current_screen' ) ) {
313 $screen = get_current_screen();
314 if( $screen && strpos( $screen->id, 'wpforo-addons' ) !== false ) return;
315 }
316
317 // Check if user has already dismissed this promo version
318 $promo_version = '3.2.0';
319 $dismissed = get_user_meta( get_current_user_id(), 'wpforo_addons_store_promo_dismissed', true );
320 if( $dismissed === $promo_version ) return;
321
322 $addons_url = admin_url( 'admin.php?page=wpforo-addons' );
323 $addons = wpforo_get_addons_info();
324 $addon_thumbs = array_slice( array_column( $addons, 'thumb' ), 0, 10 );
325 ?>
326 <div class="notice notice-info wpforo-addons-store-promo is-dismissible" style="padding: 15px 12px; border-left-color: #00a0d2;">
327 <div style="display: flex; align-items: flex-start; gap: 15px;">
328 <div style="flex-shrink: 0;">
329 <span class="dashicons dashicons-store" style="font-size: 50px; width: 50px; height: 50px; color: #00a0d2;"></span>
330 </div>
331 <div style="flex: 1;">
332 <p style="font-size: 16px; font-weight: 600; margin: 0 0 6px 0; color: #1d2327;">
333 <?php
334 printf(
335 __( 'Get Your wpForo Addon Licenses %s', 'wpforo' ),
336 '<span style="background: linear-gradient(90deg, #1d2327, #ff6d00); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;">' . __( 'Directly in Your Dashboard', 'wpforo' ) . '</span>'
337 );
338 ?>
339 </p>
340 <p style="font-size: 15px; margin: 0 0 12px 0; color: #50575e;">
341 <?php _e( 'You can now purchase, install, and manage all wpForo addons directly from the Addons page in your WordPress dashboard, no need to visit the gVectors Store. Activate licenses, get automatic updates, and extend your forum with just a few clicks.', 'wpforo' ); ?>
342 </p>
343 <div style="display: flex; align-items: center; gap: 6px; flex-wrap: wrap;">
344 <?php foreach( $addon_thumbs as $thumb ) : ?>
345 <img src="<?php echo esc_url( $thumb ); ?>" alt="" style="width: 30px; height: 30px; border-radius: 3px; object-fit: cover;" />
346 <?php endforeach; ?>
347 <a href="<?php echo esc_url( $addons_url ); ?>" class="button" style="height: 30px; line-height: 28px; padding: 0 22px; font-size: 13px; min-height: 30px; border-color: #0283aa; color: #0283aa;">
348 <?php _e( 'Browse All', 'wpforo' ); ?> &rarr;
349 </a>
350 </div>
351 </div>
352 </div>
353 </div>
354 <script>
355 jQuery(document).on('click', '.wpforo-addons-store-promo .notice-dismiss', function() {
356 jQuery.ajax({
357 url: ajaxurl,
358 data: {
359 action: 'wpforo_dismiss_addons_store_promo',
360 _wpnonce: '<?php echo wp_create_nonce( 'wpforo_dismiss_addons_store_promo' ); ?>'
361 }
362 });
363 });
364 </script>
365 <?php
366 }
367
368 /**
369 * AJAX handler: dismiss the addons store promo for the current user.
370 *
371 * @since 3.1.8
372 */
373 public function dismissAddonsStorePromo() {
374 check_ajax_referer( 'wpforo_dismiss_addons_store_promo', '_wpnonce' );
375
376 if( ! current_user_can( 'manage_options' ) ) {
377 wp_send_json_error( 'Unauthorized', 403 );
378 }
379
380 $promo_version = '3.2.0';
381 update_user_meta( get_current_user_id(), 'wpforo_addons_store_promo_dismissed', $promo_version );
382
383 wp_send_json_success();
384 }
385
386 }
387