PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / 260814
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions v260814
260917 260913 260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 111216 111220 120213 All 189 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 260814, at src/includes/classes/admin-notices.inc.php

302 lines 13.6 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 security notice.
99 *
100 * @package s2Member\Admin_Notices
101 * @since 260813
102 *
103 * @param string $message Main notice message.
104 * @param string $review Review prompt shown above the items.
105 * @param array $items Notice items, with safe HTML allowed.
106 * @param string $dismiss_url Optional dismissal URL.
107 */
108 public static function display_security_notice($message = '', $review = '', $items = array(), $dismiss_url = '')
109 {
110 $message = trim((string)$message);
111 $review = trim((string)$review);
112 $items = (array)$items;
113 if(!$message)
114 return;
115
116 $_items = array();
117 foreach($items as $_item)
118 if(is_string($_item) && trim($_item) !== '')
119 $_items[] = '<em>&bull;&nbsp; '.wp_kses_post($_item).'</em>';
120
121 $_logo_url = $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/src/images/logo-square-big.png';
122 $_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>' : '');
123 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>';
124 }
125
126 /**
127 * Records a shortcode user field that is not approved for cross-user display.
128 *
129 * @package s2Member\Admin_Notices
130 * @since 260813
131 *
132 * @param string $field User field ID.
133 * @param string $shortcode Shortcode name.
134 * @param int $post_id Post/Page ID.
135 */
136 public static function shortcode_user_field_unapproved($field = '', $shortcode = '', $post_id = 0)
137 {
138 $field = trim((string)$field);
139 $shortcode = trim((string)$shortcode);
140 $post_id = (int)$post_id;
141 if(!$field || !$shortcode)
142 return;
143
144 $_fields = (array)get_option('ws_plugin__s2member_shortcode_user_fields_transition_fields', array());
145 $_entry_key = md5(strtolower($field)."\0".strtolower($shortcode)."\0".$post_id);
146
147 //260813 Keep each detected shortcode location separate, while limiting stored warning data.
148 if(!isset($_fields[$_entry_key]) && count($_fields) >= 40)
149 return;
150 $_old_fields = $_fields;
151 $_fields[$_entry_key] = array('field' => $field, 'shortcode' => $shortcode, 'post_id' => $post_id);
152
153 if($_fields !== $_old_fields)
154 update_option('ws_plugin__s2member_shortcode_user_fields_transition_fields', $_fields, FALSE);
155 }
156
157 /**
158 * Dismisses the shortcode user-fields security notice until another affected shortcode is detected.
159 *
160 * @package s2Member\Admin_Notices
161 * @since 260813
162 */
163 public static function dismiss_shortcode_user_fields_notice()
164 {
165 if(!is_admin() || !current_user_can('create_users') || empty($_GET['s2member-dismiss-shortcode-user-fields-notice']))
166 return;
167
168 check_admin_referer('s2member-dismiss-shortcode-user-fields-notice');
169 delete_option('ws_plugin__s2member_shortcode_user_fields_transition_fields');
170
171 wp_safe_redirect(wp_get_referer() ? wp_get_referer() : admin_url());
172 exit;
173 }
174
175 /**
176 * Displays the shared shortcode user-fields security notice.
177 *
178 * @package s2Member\Admin_Notices
179 * @since 260813
180 */
181 public static function shortcode_user_fields_notice()
182 {
183 if(!current_user_can('create_users'))
184 return;
185
186 $_fields = (array)get_option('ws_plugin__s2member_shortcode_user_fields_transition_fields', array());
187 if(!$_fields)
188 return;
189
190 //260813 Use the submitted whitelist on save so the notice updates immediately.
191 $_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']);
192 $_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']);
193 $_field_whitelist = ($_field_whitelist !== '') ? preg_split('/\s*,\s*/', strtolower($_field_whitelist), -1, PREG_SPLIT_NO_EMPTY) : array();
194 $_field_whitelist = array_flip($_field_whitelist);
195 foreach($_fields as $_key => $_details)
196 {
197 if(!is_array($_details) || empty($_details['field']) || empty($_details['shortcode']))
198 unset($_fields[$_key]);
199 else if(isset($_field_whitelist[strtolower($_details['field'])]))
200 unset($_fields[$_key]);
201 }
202
203 if(!$_fields)
204 {
205 delete_option('ws_plugin__s2member_shortcode_user_fields_transition_fields');
206 return;
207 }
208 update_option('ws_plugin__s2member_shortcode_user_fields_transition_fields', $_fields, FALSE);
209
210 // Build a useful field list with a separate entry for each detected shortcode location.
211 $_field_items = array();
212 foreach($_fields as $_details)
213 {
214 $_item = esc_html($_details['field']).' — ['.esc_html($_details['shortcode']).']';
215 $_post_id = (!empty($_details['post_id'])) ? (int)$_details['post_id'] : 0;
216 if($_post_id > 0 && ($_edit_link = get_edit_post_link($_post_id, '')))
217 {
218 $_post_title = get_the_title($_post_id);
219 $_post_title = ($_post_title !== '') ? $_post_title : '(no title)';
220 $_item .= ' — <a href="'.esc_url($_edit_link).'">'.esc_html($_post_title).' (#'.$_post_id.')</a>';
221 }
222 $_field_items[] = $_item;
223 }
224 unset($_details, $_item, $_post_id, $_edit_link, $_post_title);
225
226 $_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';
227 $_dismiss_url = wp_nonce_url(add_query_arg('s2member-dismiss-shortcode-user-fields-notice', '1', admin_url()), 's2member-dismiss-shortcode-user-fields-notice');
228 $_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>';
229 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);
230 }
231
232 /**
233 * Processes all administrative notices.
234 *
235 * @package s2Member\Admin_Notices
236 * @since 3.5
237 *
238 * @attaches-to ``add_action('admin_notices');``
239 * @attaches-to ``add_action('user_admin_notices');``
240 * @attaches-to ``add_action('network_admin_notices');``
241 * @todo Update to ``add_action('all_admin_notices');``.
242 */
243 public static function admin_notices()
244 {
245 global $pagenow; // This holds the current page filename.
246
247 do_action('ws_plugin__s2member_before_admin_notices', get_defined_vars());
248
249 if(is_admin() && is_array($notices = get_option('ws_plugin__s2member_notices')) && !empty($notices))
250 {
251 $a = (is_blog_admin()) ? 'blog' : '';
252 $a = (is_user_admin()) ? 'user' : $a;
253 $a = (is_network_admin()) ? 'network' : $a;
254 $a = (!$a) ? 'blog' : $a; // Default blog admin.
255
256 foreach($notices as $i => $notice) // Check several things about each notice.
257 {
258 //250510 Fixed for PHP 8.1+: safely normalize on_pages before foreach
259 $notice = (array)$notice;
260 $notice['on_pages'] = empty($notice['on_pages']) ? array('*') : (array)$notice['on_pages'];
261 foreach($notice['on_pages'] as $page)
262 {
263 if(!preg_match('/^(.+?)\:/', $page)) // NO prefix?
264 $page = 'blog:'.ltrim($page, ':'); // `blog:`
265
266 $adms = preg_split('/\|/', preg_replace('/\:(.*)$/i', '', $page));
267 $page = preg_replace('/^([^\:]*)\:/i', '', $page);
268
269 if(empty($adms) || in_array('*', $adms) || in_array($a, $adms))
270 if(!$page || '*' === $page || $pagenow === $page || @$_GET['page'] === $page)
271 {
272 if(strtotime('now') >= (int)$notice['time']) // Time to show it?
273 {
274 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
275 do_action('ws_plugin__s2member_during_admin_notices_before_display', get_defined_vars());
276 unset($__refs, $__v); // Allow variables to be modified by reference.
277
278 if(!$notice['dismiss'] || (!empty($_GET['ws-plugin--s2member-dismiss-admin-notice']) && $_GET['ws-plugin--s2member-dismiss-admin-notice'] === md5($notice['notice'])))
279 unset($notices[$i]); // Clear this administrative notice now?
280
281 if(!$notice['dismiss'] || empty($_GET['ws-plugin--s2member-dismiss-admin-notice']) || $_GET['ws-plugin--s2member-dismiss-admin-notice'] !== md5($notice['notice']))
282 c_ws_plugin__s2member_admin_notices::display_admin_notice($notice['notice'], $notice['error'], $notice['dismiss']);
283
284 do_action('ws_plugin__s2member_during_admin_notices_after_display', get_defined_vars());
285 }
286 continue 2; // This notice processed; continue.
287 }
288 }
289 }
290 $notices = array_merge($notices); // Re-index array.
291
292 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
293 do_action('ws_plugin__s2member_during_admin_notices', get_defined_vars());
294 unset($__refs, $__v); // Allow variables to be modified by reference.
295
296 update_option('ws_plugin__s2member_notices', $notices);
297 }
298 do_action('ws_plugin__s2member_after_admin_notices', get_defined_vars());
299 }
300 }
301 }
302