PluginProbe ʕ •ᴥ•ʔ
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More / 4.0.7
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More v4.0.7
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 trunk 1.0.0 2.0.0 2.0.1 2.0.2 2.0.3 3.0 3.0.1 3.0.2 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.2 3.1.3 3.2.0 3.2.1 3.2.2 3.2.4 3.2.5 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.4.5 3.4.6 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1
superb-blocks / src / admin / controllers / class-notice-controller.php
superb-blocks / src / admin / controllers Last commit date
wizard 3 days ago class-dashboard-controller.php 3 days ago class-license-resolve-controller.php 3 days ago class-newsletter-signup-controller.php 3 days ago class-notice-controller.php 3 days ago class-plugin-reset-controller.php 3 days ago class-review-controller.php 3 days ago class-rewrite-check-controller.php 3 days ago class-settings-controller.php 3 days ago class-troubleshooting-controller.php 3 days ago
class-notice-controller.php
234 lines
1 <?php
2
3 namespace SuperbAddons\Admin\Controllers;
4
5 use SuperbAddons\Admin\Controllers\Wizard\WizardController;
6
7 defined('ABSPATH') || exit();
8
9 // 1.0
10
11 class AdminNoticeController
12 {
13 const PREFIX = 'spbaddons_notice_';
14 const PREFIX_DELAY = 'spbaddons_notice_delay_';
15 const LAST_DISMISS_META = 'spbaddons_notice_last_dismiss';
16
17 const ALLOWED_HTML = [
18 'div' => [
19 'class' => [],
20 'style' => [],
21 ],
22 'p' => [
23 'class' => [],
24 ],
25 'h2' => [
26 'class' => [],
27 ],
28 'ul' => [
29 'class' => [],
30 ],
31 'li' => [
32 'class' => [],
33 ],
34 'span' => [
35 'class' => [],
36 ],
37 'a' => [
38 'class' => [],
39 'href' => [],
40 'rel' => [],
41 'target' => [],
42 ],
43 'em' => [
44 'class' => [],
45 ],
46 'strong' => [
47 'class' => [],
48 ],
49 'img' => [
50 'class' => [],
51 'alt' => [],
52 'src' => [],
53 'width' => [],
54 'height' => [],
55 ],
56 'br' => [],
57 'style' => [],
58 ];
59
60 private static $notices = [];
61
62 public static function init($options)
63 {
64 $notices = [];
65 if (isset($options['notices']) && is_array($options['notices'])) {
66 foreach ($options['notices'] as $notice) {
67 if (!isset($notice['unique_id']) || !isset($notice['content'])) {
68 continue;
69 }
70
71 $notices[] = $notice;
72 }
73 }
74
75 self::$notices = $notices;
76
77 add_action('admin_notices', array(__CLASS__, 'AdminNotices'));
78 add_action('wp_ajax_spbtic_dismiss_notice', array(__CLASS__, 'MaybeDismissNotice'));
79 }
80
81 public static function AdminNotices()
82 {
83 // Cooldown: suppress notices for a day after the user dismissed any of
84 // our notices, so dismissing one never instantly surfaces another.
85 $last_dismiss = get_user_meta(get_current_user_id(), self::LAST_DISMISS_META, true);
86 $in_cooldown = $last_dismiss && (time() - intval($last_dismiss)) < DAY_IN_SECONDS;
87
88 foreach (self::$notices as $notice) {
89 $notice_path = trailingslashit(SUPERBADDONS_PLUGIN_DIR) . 'src/admin/notices/' . $notice['content'];
90 if (!file_exists($notice_path)) {
91 continue;
92 }
93
94 // Check if the notice has been dismissed.
95 if (get_user_meta(get_current_user_id(), self::PREFIX . $notice['unique_id'], true)) {
96 continue;
97 }
98
99 // Respect the post-dismissal cooldown.
100 if ($in_cooldown) {
101 continue;
102 }
103
104 // Check if the notice is delayed
105 if (isset($notice['delay'])) {
106 $delay_init = get_user_meta(get_current_user_id(), self::PREFIX_DELAY . $notice['unique_id'], true);
107 if (!$delay_init) {
108 update_user_meta(get_current_user_id(), self::PREFIX_DELAY . $notice['unique_id'], time());
109 continue;
110 }
111
112 $delay = strtotime($notice['delay'], $delay_init);
113 if ($delay > time()) {
114 continue;
115 }
116 }
117
118 ob_start();
119 include_once $notice_path;
120 $content = ob_get_clean();
121 echo wp_kses($content, self::ALLOWED_HTML);
122 }
123
124 self::PrintScripts();
125 }
126
127 public static function PrintScripts()
128 {
129 ?>
130 <script>
131 window.addEventListener("load", function() {
132 setTimeout(function() {
133 const notice_ids = <?php echo wp_json_encode(array_column(self::$notices, 'unique_id'), JSON_HEX_TAG); ?>;
134 const nonce = "<?php echo esc_attr(wp_create_nonce('spbtic_dismiss_notice')); ?>";
135 const ajaxurl = "<?php echo esc_url(admin_url('admin-ajax.php')); ?>";
136
137 function dismissNotice(noticeId) {
138 const httpRequest = new XMLHttpRequest();
139
140 // Build the data to send in our request.
141 // Data has to be formatted as a string here.
142 let postData = "id=" + noticeId;
143 postData += "&action=spbtic_dismiss_notice";
144 postData += "&nonce=" + nonce;
145
146 httpRequest.open("POST", ajaxurl);
147 httpRequest.setRequestHeader(
148 "Content-Type",
149 "application/x-www-form-urlencoded"
150 );
151 httpRequest.send(postData);
152 }
153
154 notice_ids.forEach(function(notice) {
155 const wrapper = document.querySelector("." + notice);
156 if (!wrapper) return;
157
158 // Standard WordPress dismiss (X) button.
159 const dismissBtn = wrapper.querySelector(".notice-dismiss");
160 if (dismissBtn) {
161 dismissBtn.addEventListener("click", function() {
162 dismissNotice(notice);
163 });
164 }
165
166 // Extra in-notice dismiss links (e.g. the review notice choices).
167 const dismissLinks = wrapper.querySelectorAll(".superbaddons-notice-dismiss");
168 dismissLinks.forEach(function(link) {
169 link.addEventListener("click", function(event) {
170 const href = link.getAttribute("href");
171 if (!href || href === "#") {
172 event.preventDefault();
173 }
174 dismissNotice(notice);
175 wrapper.style.display = "none";
176 });
177 });
178 });
179 }, 0);
180 });
181 </script>
182 <?php
183 }
184
185 public static function MaybeDismissNotice()
186 {
187 // Sanity check: Early exit if we're not on a spbtic_dismiss_notice action.
188 if (!isset($_POST['action']) || 'spbtic_dismiss_notice' !== $_POST['action']) {
189 return;
190 }
191
192 // Sanity check: Early exit if the ID of the notice does not exist.
193 if (!isset($_POST['id']) || !in_array($_POST['id'], array_column(self::$notices, 'unique_id'))) {
194 return;
195 }
196
197 // Notice ID exists in array, so we can safely use it.
198 $notice_id = sanitize_text_field(wp_unslash($_POST['id']));
199
200 // Security check: Make sure nonce is OK. check_ajax_referer exits if it fails.
201 check_ajax_referer('spbtic_dismiss_notice', 'nonce', true);
202
203 // Record the dismissal time so our other notices respect the cooldown.
204 update_user_meta(get_current_user_id(), self::LAST_DISMISS_META, time());
205
206 // Dismiss the notice.
207 self::DismissNotice($notice_id);
208 }
209
210 public static function DismissNotice($notice_id)
211 {
212 if ($notice_id == 'wizard_recommender') {
213 WizardController::RemoveWizardRecommenderTransient();
214 } elseif ($notice_id == 'wizard_woocommerce') {
215 WizardController::RemoveWizardWooCommerceTransient();
216 } else {
217 update_user_meta(get_current_user_id(), self::PREFIX . $notice_id, true);
218 }
219 }
220
221 public static function Cleanup()
222 {
223 foreach (self::$notices as $notice) {
224 delete_metadata('user', 0, self::PREFIX . $notice['unique_id'], false, true);
225 if (isset($notice['delay'])) {
226 delete_metadata('user', 0, self::PREFIX_DELAY . $notice['unique_id'], false, true);
227 }
228 }
229 delete_metadata('user', 0, self::LAST_DISMISS_META, false, true);
230 WizardController::RemoveWizardRecommenderTransient();
231 WizardController::RemoveWizardWooCommerceTransient();
232 }
233 }
234