PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / trunk
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions vtrunk
260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 111216 111220 120213 120219 120301 All 187 releases
s2member / src / includes / classes / admin-notices.inc.php

admin-notices.inc.php in s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions trunk, at src/includes/classes/admin-notices.inc.php

325 lines 14.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // @codingStandardsIgnoreFile
3 /**
4 * Enqueues/displays administrative notices.
5 *
6 * Copyright: © 2009-2011
7 * {@link http://websharks-inc.com/ WebSharks, Inc.}
8 * (coded in the USA)
9 *
10 * Released under the terms of the GNU General Public License.
11 * You should have received a copy of the GNU General Public License,
12 * along with this software. In the main directory, see: /licensing/
13 * If not, see: {@link http://www.gnu.org/licenses/}.
14 *
15 * @package s2Member\Admin_Notices
16 * @since 3.5
17 */
18 if(!defined('WPINC')) // MUST have WordPress.
19 exit('Do not access this file directly.');
20
21 if(!class_exists('c_ws_plugin__s2member_admin_notices'))
22 {
23 /**
24 * Enqueues/displays administrative notices.
25 *
26 * @package s2Member\Admin_Notices
27 * @since 3.5
28 */
29 class c_ws_plugin__s2member_admin_notices
30 {
31 /**
32 * Enqueues administrative notices.
33 *
34 * @package s2Member\Admin_Notices
35 * @since 3.5
36 *
37 * @param string $notice String value of actual notice *(i.e., the message)*.
38 * @param string|array $on_pages Optional. Defaults to any page. String or array of pages to display this notice on.
39 * @param bool $error Optional. True if this notice is regarding an error. Defaults to false.
40 * @param int $time Optional. Unix timestamp indicating when this notice will be displayed.
41 * @param bool $dismiss Optional. If true, the notice will remain persistent, until dismissed. Defaults to false.
42 */
43 public static function enqueue_admin_notice($notice = '', $on_pages = array(), $error = FALSE, $time = 0, $dismiss = FALSE)
44 {
45 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
46 do_action('ws_plugin__s2member_before_enqueue_admin_notice', get_defined_vars());
47 unset($__refs, $__v); // Allow variables to be modified by reference.
48
49 if($notice && is_string($notice))// Have a valid string.
50 {
51 $notices = (array)get_option('ws_plugin__s2member_notices');
52 array_push($notices, array('notice' => $notice, 'on_pages' => $on_pages, 'error' => $error, 'time' => $time, 'dismiss' => $dismiss));
53
54 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
55 do_action('ws_plugin__s2member_during_enqueue_admin_notice', get_defined_vars());
56 unset($__refs, $__v); // Allow variables to be modified by reference.
57
58 update_option('ws_plugin__s2member_notices', c_ws_plugin__s2member_utils_arrays::array_unique($notices));
59 }
60 do_action('ws_plugin__s2member_after_enqueue_admin_notice', get_defined_vars());
61 }
62
63 /**
64 * Displays an administrative notice.
65 *
66 * @package s2Member\Admin_Notices
67 * @since 3.5
68 *
69 * @param string $notice String value of actual notice *(i.e., the message)*.
70 * @param bool $error Optional. True if this notice is regarding an error. Defaults to false.
71 * @param bool $dismiss Optional. If true, the notice will be displayed with a dismissal link. Defaults to false.
72 */
73 public static function display_admin_notice($notice = '', $error = FALSE, $dismiss = FALSE)
74 {
75 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
76 do_action('ws_plugin__s2member_before_display_admin_notice', get_defined_vars());
77 unset($__refs, $__v); // Allow variables to be modified by reference.
78
79 if($dismiss) $dismissal_link = '<div style="float:right; margin:0 0 0 1em; font-weight:bold;">'.
80 '[ <a href="'.esc_attr(add_query_arg('ws-plugin--s2member-dismiss-admin-notice', urlencode(md5($notice)), $_SERVER['REQUEST_URI'])).'">dismiss</a> ]'.
81 '</div>';
82 if($notice && is_string($notice) && $error)
83 {
84 if($dismiss && !empty($dismissal_link))
85 $notice = $dismissal_link.$notice;
86 echo '<div class="notice notice-error"><p>'.wp_kses_post($notice).'</p></div>';
87 }
88 else if($notice && is_string($notice))
89 {
90 if($dismiss && !empty($dismissal_link))
91 $notice = $dismissal_link.$notice;
92 echo '<div class="notice notice-info"><p>'.wp_kses_post($notice).'</p></div>';
93 }
94 do_action('ws_plugin__s2member_after_display_admin_notice', get_defined_vars());
95 }
96
97 /**
98 * Displays a branded s2Member administrative notice.
99 *
100 * @package s2Member\Admin_Notices
101 * @since 260904.1923
102 *
103 * @param string $title Notice title.
104 * @param string $message Main notice message.
105 * @param bool $error Optional. True for an error notice; otherwise an informational notice.
106 */
107 public static function display_branded_notice($title = '', $message = '', $error = FALSE)
108 {
109 $title = trim((string)$title);
110 $message = trim((string)$message);
111 if(!$message)
112 return;
113
114 $_logo_url = $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/src/images/logo-square-big.png';
115 $_notice_class = ($error) ? 'notice notice-error' : 'notice notice-info';
116
117 echo '<div class="'.esc_attr($_notice_class).'" style="margin:0 0 15px 2px !important; padding:8px !important;"><table cellspacing="0" cellpadding="0"><tr><td style="vertical-align:top; padding:0 10px 0 0;"><img src="'.esc_url($_logo_url).'" alt="" width="40" height="40" style="border:0;" /></td><td style="vertical-align:top;">'.(($title !== '') ? '<strong>'.esc_html($title).'</strong><br />' : '').wp_kses_post($message).'</td></tr></table></div>';
118 }
119
120 /**
121 * Displays a branded s2Member security notice.
122 *
123 * @package s2Member\Admin_Notices
124 * @since 260813
125 *
126 * @param string $message Main notice message.
127 * @param string $review Review prompt shown above the items.
128 * @param array $items Notice items, with safe HTML allowed.
129 * @param string $dismiss_url Optional dismissal URL.
130 */
131 public static function display_security_notice($message = '', $review = '', $items = array(), $dismiss_url = '')
132 {
133 $message = trim((string)$message);
134 $review = trim((string)$review);
135 $items = (array)$items;
136 if(!$message)
137 return;
138
139 $_items = array();
140 foreach($items as $_item)
141 if(is_string($_item) && trim($_item) !== '')
142 $_items[] = '<em>&bull;&nbsp; '.wp_kses_post($_item).'</em>';
143
144 $_logo_url = $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/src/images/logo-square-big.png';
145 $_dismiss = (($dismiss_url !== '') ? '<a href="'.esc_url($dismiss_url).'" title="Dismiss until detected again" style="position:absolute; top:8px; right:10px; text-decoration:none;">Dismiss</a>' : '');
146 echo '<div class="notice notice-warning" style="position:relative; margin:0 0 15px 2px !important; padding:8px 60px 8px 8px !important;">'.$_dismiss.'<table cellspacing="0" cellpadding="0"><tr><td style="vertical-align:top; padding:0 10px 0 0;"><img src="'.esc_url($_logo_url).'" alt="" width="40" height="40" style="border:0;" /></td><td style="vertical-align:top;"><strong>s2Member Security Notice</strong><br />'.wp_kses_post($message).(($review !== '') ? '<br />'.wp_kses_post($review) : '').(($_items) ? '<br />'.implode('<br />', $_items) : '').'</td></tr></table></div>';
147 }
148
149 /**
150 * Records a shortcode user field that is not approved for cross-user display.
151 *
152 * @package s2Member\Admin_Notices
153 * @since 260813
154 *
155 * @param string $field User field ID.
156 * @param string $shortcode Shortcode name.
157 * @param int $post_id Post/Page ID.
158 */
159 public static function shortcode_user_field_unapproved($field = '', $shortcode = '', $post_id = 0)
160 {
161 $field = trim((string)$field);
162 $shortcode = trim((string)$shortcode);
163 $post_id = (int)$post_id;
164 if(!$field || !$shortcode)
165 return;
166
167 $_fields = (array)get_option('ws_plugin__s2member_shortcode_user_fields_transition_fields', array());
168 $_entry_key = md5(strtolower($field)."\0".strtolower($shortcode)."\0".$post_id);
169
170 //260813 Keep each detected shortcode location separate, while limiting stored warning data.
171 if(!isset($_fields[$_entry_key]) && count($_fields) >= 40)
172 return;
173 $_old_fields = $_fields;
174 $_fields[$_entry_key] = array('field' => $field, 'shortcode' => $shortcode, 'post_id' => $post_id);
175
176 if($_fields !== $_old_fields)
177 update_option('ws_plugin__s2member_shortcode_user_fields_transition_fields', $_fields, FALSE);
178 }
179
180 /**
181 * Dismisses the shortcode user-fields security notice until another affected shortcode is detected.
182 *
183 * @package s2Member\Admin_Notices
184 * @since 260813
185 */
186 public static function dismiss_shortcode_user_fields_notice()
187 {
188 if(!is_admin() || !current_user_can('create_users') || empty($_GET['s2member-dismiss-shortcode-user-fields-notice']))
189 return;
190
191 check_admin_referer('s2member-dismiss-shortcode-user-fields-notice');
192 delete_option('ws_plugin__s2member_shortcode_user_fields_transition_fields');
193
194 wp_safe_redirect(wp_get_referer() ? wp_get_referer() : admin_url());
195 exit;
196 }
197
198 /**
199 * Displays the shared shortcode user-fields security notice.
200 *
201 * @package s2Member\Admin_Notices
202 * @since 260813
203 */
204 public static function shortcode_user_fields_notice()
205 {
206 if(!current_user_can('create_users'))
207 return;
208
209 $_fields = (array)get_option('ws_plugin__s2member_shortcode_user_fields_transition_fields', array());
210 if(!$_fields)
211 return;
212
213 //260813 Use the submitted whitelist on save so the notice updates immediately.
214 $_using_submitted_whitelist = !empty($_POST['ws_plugin__s2member_options_save']) && is_string($_POST['ws_plugin__s2member_options_save']) && wp_verify_nonce($_POST['ws_plugin__s2member_options_save'], 'ws-plugin--s2member-options-save') && isset($_POST['ws_plugin__s2member_sc_user_fields_whitelist']) && is_string($_POST['ws_plugin__s2member_sc_user_fields_whitelist']);
215 $_field_whitelist = ($_using_submitted_whitelist) ? trim((string)wp_unslash($_POST['ws_plugin__s2member_sc_user_fields_whitelist'])) : trim((string)$GLOBALS['WS_PLUGIN__']['s2member']['o']['sc_user_fields_whitelist']);
216 $_field_whitelist = ($_field_whitelist !== '') ? preg_split('/\s*,\s*/', strtolower($_field_whitelist), -1, PREG_SPLIT_NO_EMPTY) : array();
217 $_field_whitelist = array_flip($_field_whitelist);
218 foreach($_fields as $_key => $_details)
219 {
220 if(!is_array($_details) || empty($_details['field']) || empty($_details['shortcode']))
221 unset($_fields[$_key]);
222 else if(isset($_field_whitelist[strtolower($_details['field'])]))
223 unset($_fields[$_key]);
224 }
225
226 if(!$_fields)
227 {
228 delete_option('ws_plugin__s2member_shortcode_user_fields_transition_fields');
229 return;
230 }
231 update_option('ws_plugin__s2member_shortcode_user_fields_transition_fields', $_fields, FALSE);
232
233 // Build a useful field list with a separate entry for each detected shortcode location.
234 $_field_items = array();
235 foreach($_fields as $_details)
236 {
237 $_item = esc_html($_details['field']).' — ['.esc_html($_details['shortcode']).']';
238 $_post_id = (!empty($_details['post_id'])) ? (int)$_details['post_id'] : 0;
239 if($_post_id > 0 && ($_edit_link = get_edit_post_link($_post_id, '')))
240 {
241 $_post_title = get_the_title($_post_id);
242 $_post_title = ($_post_title !== '') ? $_post_title : '(no title)';
243 $_item .= ' — <a href="'.esc_url($_edit_link).'">'.esc_html($_post_title).' (#'.$_post_id.')</a>';
244 }
245 $_field_items[] = $_item;
246 }
247 unset($_details, $_item, $_post_id, $_edit_link, $_post_title);
248
249 $_settings_url = add_query_arg('s2member-open-panel', 'shortcode-user-fields-whitelist', admin_url('/admin.php?page=ws-plugin--s2member-gen-ops')).'#ws-plugin--s2member-shortcode-user-fields-whitelist';
250 $_dismiss_url = wp_nonce_url(add_query_arg('s2member-dismiss-shortcode-user-fields-notice', '1', admin_url()), 's2member-dismiss-shortcode-user-fields-notice');
251 $_message = 'Some s2Member shortcodes use user fields that are not in <em><a href="'.esc_url($_settings_url).'">s2Member → General Options → Shortcode User Fields Whitelist</a></em>';
252 c_ws_plugin__s2member_admin_notices::display_security_notice($_message, 'Review the fields below and allow the ones that are okay for other users to see:', $_field_items, $_dismiss_url);
253 }
254
255 /**
256 * Processes all administrative notices.
257 *
258 * @package s2Member\Admin_Notices
259 * @since 3.5
260 *
261 * @attaches-to ``add_action('admin_notices');``
262 * @attaches-to ``add_action('user_admin_notices');``
263 * @attaches-to ``add_action('network_admin_notices');``
264 * @todo Update to ``add_action('all_admin_notices');``.
265 */
266 public static function admin_notices()
267 {
268 global $pagenow; // This holds the current page filename.
269
270 do_action('ws_plugin__s2member_before_admin_notices', get_defined_vars());
271
272 if(is_admin() && is_array($notices = get_option('ws_plugin__s2member_notices')) && !empty($notices))
273 {
274 $a = (is_blog_admin()) ? 'blog' : '';
275 $a = (is_user_admin()) ? 'user' : $a;
276 $a = (is_network_admin()) ? 'network' : $a;
277 $a = (!$a) ? 'blog' : $a; // Default blog admin.
278
279 foreach($notices as $i => $notice) // Check several things about each notice.
280 {
281 //250510 Fixed for PHP 8.1+: safely normalize on_pages before foreach
282 $notice = (array)$notice;
283 $notice['on_pages'] = empty($notice['on_pages']) ? array('*') : (array)$notice['on_pages'];
284 foreach($notice['on_pages'] as $page)
285 {
286 if(!preg_match('/^(.+?)\:/', $page)) // NO prefix?
287 $page = 'blog:'.ltrim($page, ':'); // `blog:`
288
289 $adms = preg_split('/\|/', preg_replace('/\:(.*)$/i', '', $page));
290 $page = preg_replace('/^([^\:]*)\:/i', '', $page);
291
292 if(empty($adms) || in_array('*', $adms) || in_array($a, $adms))
293 if(!$page || '*' === $page || $pagenow === $page || @$_GET['page'] === $page)
294 {
295 if(strtotime('now') >= (int)$notice['time']) // Time to show it?
296 {
297 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
298 do_action('ws_plugin__s2member_during_admin_notices_before_display', get_defined_vars());
299 unset($__refs, $__v); // Allow variables to be modified by reference.
300
301 if(!$notice['dismiss'] || (!empty($_GET['ws-plugin--s2member-dismiss-admin-notice']) && $_GET['ws-plugin--s2member-dismiss-admin-notice'] === md5($notice['notice'])))
302 unset($notices[$i]); // Clear this administrative notice now?
303
304 if(!$notice['dismiss'] || empty($_GET['ws-plugin--s2member-dismiss-admin-notice']) || $_GET['ws-plugin--s2member-dismiss-admin-notice'] !== md5($notice['notice']))
305 c_ws_plugin__s2member_admin_notices::display_admin_notice($notice['notice'], $notice['error'], $notice['dismiss']);
306
307 do_action('ws_plugin__s2member_during_admin_notices_after_display', get_defined_vars());
308 }
309 continue 2; // This notice processed; continue.
310 }
311 }
312 }
313 $notices = array_merge($notices); // Re-index array.
314
315 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
316 do_action('ws_plugin__s2member_during_admin_notices', get_defined_vars());
317 unset($__refs, $__v); // Allow variables to be modified by reference.
318
319 update_option('ws_plugin__s2member_notices', $notices);
320 }
321 do_action('ws_plugin__s2member_after_admin_notices', get_defined_vars());
322 }
323 }
324 }
325