PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / 260917
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions v260917
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
← All changes | src/includes/classes/admin-notices.inc.php +58 -8 260909260917 View file →
@@ -102,23 +102,66 @@
102 102 *
103 103 * @param string $title Notice title.
104 104 * @param string $message Main notice message.
105 105 * @param bool $error Optional. True for an error notice; otherwise an informational notice.
106 + * @param string $dismiss_url Optional explicit URL that dismisses the current notice incident.
106 107 */
107 - public static function display_branded_notice($title = '', $message = '', $error = FALSE)
108 + public static function display_branded_notice($title = '', $message = '', $error = FALSE, $dismiss_url = '')
108 109 {
109 110 $title = trim((string)$title);
110 111 $message = trim((string)$message);
112 + $dismiss_url = trim((string)$dismiss_url);
111 113 if(!$message)
112 114 return;
113 115
114 116 $_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';
117 + $_notice_class = ($error) ? 'notice notice-error' : 'notice notice-info'; //260910.0818 Use WordPress's standard error style for the immediate Red problem and the quieter informational style for the persistent Orange review notice.
118 + $_dismiss = (($dismiss_url !== '') ? '<a href="'.esc_url($dismiss_url).'" title="Dismiss this incident" style="position:absolute; top:8px; right:10px; text-decoration:none;">Dismiss</a>' : ''); //260910.0709 The caller owns the nonce-protected incident URL so dismissal follows incident identity, not mutable notice text.
116 119
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>';
120 + //260909.2021 Keep incident dismissal explicit so changing notice text cannot accidentally make a persistent problem look like a new one.
121 + echo '<div class="'.esc_attr($_notice_class).'" style="position:relative; margin:0 0 15px 2px !important; padding:8px '.(($dismiss_url !== '') ? '60px' : '8px').' 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;">'.(($title !== '') ? '<strong>'.esc_html($title).'</strong><br />' : '').wp_kses_post($message).'</td></tr></table></div>';
118 122 }
119 123
120 124 /**
125 + * Warns administrators when Pro is too old to contain the current Pro updater behavior.
126 + *
127 + * @package s2Member\Admin_Notices
128 + * @since 260917.0425
129 + *
130 + * @attaches-to `add_action('admin_notices');`
131 + * @attaches-to `add_action('user_admin_notices');`
132 + * @attaches-to `add_action('network_admin_notices');`
133 + */
134 + public static function outdated_pro_notice()
135 + {
136 + if(!current_user_can('update_plugins') || !defined('WS_PLUGIN__S2MEMBER_PRO_VERSION') || !defined('WS_PLUGIN__S2MEMBER_VERSION'))
137 + return;
138 +
139 + //260917.0425 v260913 introduced the current background Pro updater flow; Framework owns this fallback warning only for older Pro releases.
140 + $_current_updater_version = '260913';
141 + if(version_compare(WS_PLUGIN__S2MEMBER_PRO_VERSION, $_current_updater_version, '>=') || !version_compare(WS_PLUGIN__S2MEMBER_PRO_VERSION, WS_PLUGIN__S2MEMBER_VERSION, '<'))
142 + return;
143 +
144 + $_account_url = 'https://s2member.com/account/';
145 + //260917.2113 s2Member versions begin with yymmdd; show the installed Pro version's approximate age so administrators can immediately see how far behind it is.
146 + $_pro_release_age = '';
147 + if(preg_match('/^(\d{2})(\d{2})(\d{2})/', WS_PLUGIN__S2MEMBER_PRO_VERSION, $_pro_version_parts))
148 + {
149 + $_pro_release_timestamp = mktime(0, 0, 0, (int) $_pro_version_parts[2], (int) $_pro_version_parts[3], 2000 + (int) $_pro_version_parts[1]);
150 + if($_pro_release_timestamp)
151 + $_pro_release_age = human_time_diff($_pro_release_timestamp, current_time('timestamp'));
152 + }
153 +
154 + //260917.1937 Keep this urgent notice compact and skimmable: short paragraphs, prominent version age/security risk, and a clearly separated update action.
155 + $_message = '<p style="line-height:1.3em; margin:.3em 0;"><strong>Your s2Member Pro v'.esc_html(WS_PLUGIN__S2MEMBER_PRO_VERSION).($_pro_release_age ? ' is '.esc_html($_pro_release_age).' old and' : '').' is missing important security fixes</strong>.</p>';
156 + $_message .= '<p style="line-height:1.3em; margin:.3em 0;"><em>Please install the latest ZIP from WP Admin &gt; Plugins &gt; Add Plugin &gt; Upload Plugin.</em></p>';
157 + $_update_button = '<a class="button button-primary" style="margin-top:.3em; background:darkred; border-color:darkred;" href="'.esc_url($_account_url).'" target="_blank" rel="external noopener">Download the Latest s2Member Pro Now</a>';
158 +
159 + //260917.1937 Keep this Framework-owned warning persistent and red; include the action in the message instead of the helper's review slot so no extra <br> is inserted before it.
160 + c_ws_plugin__s2member_admin_notices::display_security_notice($_message.$_update_button, '', array(), '', 'notice-error');
161 + }
162 +
163 + /**
121 164 * Displays a branded s2Member security notice.
122 165 *
123 166 * @package s2Member\Admin_Notices
124 167 * @since 260813
@@ -126,10 +169,11 @@
126 169 * @param string $message Main notice message.
127 170 * @param string $review Review prompt shown above the items.
128 171 * @param array $items Notice items, with safe HTML allowed.
129 172 * @param string $dismiss_url Optional dismissal URL.
173 + * @param string $notice_class Optional WordPress notice severity class.
130 174 */
131 - public static function display_security_notice($message = '', $review = '', $items = array(), $dismiss_url = '')
175 + public static function display_security_notice($message = '', $review = '', $items = array(), $dismiss_url = '', $notice_class = 'notice-warning')
132 176 {
133 177 $message = trim((string)$message);
134 178 $review = trim((string)$review);
135 179 $items = (array)$items;
@@ -135,8 +179,11 @@
135 179 $items = (array)$items;
136 180 if(!$message)
137 181 return;
138 182
183 + //260917.0513 Preserve the existing warning style by default, while allowing especially urgent security notices to use WordPress's stronger error styling.
184 + $_notice_class = (($notice_class === 'notice-error') ? 'notice notice-error' : 'notice notice-warning');
185 +
139 186 $_items = array();
140 187 foreach($items as $_item)
141 188 if(is_string($_item) && trim($_item) !== '')
142 189 $_items[] = '<em>&bull;&nbsp; '.wp_kses_post($_item).'</em>';
@@ -142,9 +189,12 @@
142 189 $_items[] = '<em>&bull;&nbsp; '.wp_kses_post($_item).'</em>';
143 190
144 191 $_logo_url = $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/src/images/logo-square-big.png';
145 192 $_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>';
193 +
194 + //260917.1937 Give urgent red security notices a stronger heading without changing the existing presentation of normal yellow security notices.
195 + $_title = (($notice_class === 'notice-error') ? '<h2 style="margin:0 0 .3em; color:darkred;">s2Member Security Notice</h2>' : '<strong>s2Member Security Notice</strong><br />');
196 + echo '<div class="'.esc_attr($_notice_class).'" 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;">'.$_title.wp_kses_post($message).(($review !== '') ? '<br />'.wp_kses_post($review) : '').(($_items) ? '<br />'.implode('<br />', $_items) : '').'</td></tr></table></div>';
147 197 }
148 198
149 199 /**
150 200 * Records a shortcode user field that is not approved for cross-user display.
@@ -247,10 +297,10 @@
247 297 unset($_details, $_item, $_post_id, $_edit_link, $_post_title);
248 298
249 299 $_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 300 $_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);
301 + $_message = 'Some s2Member shortcodes attempted to display user fields from other accounts that are not in <em><a href="'.esc_url($_settings_url).'">s2Member → General Options → Shortcode User Fields Whitelist</a></em>. Those cross-user field values were blocked.';
302 + c_ws_plugin__s2member_admin_notices::display_security_notice($_message, 'Review the blocked fields below and allow the ones that are okay for other users to see:', $_field_items, $_dismiss_url);
253 303 }
254 304
255 305 /**
256 306 * Processes all administrative notices.
@@ -280,9 +330,9 @@
280 330 {
281 331 //250510 Fixed for PHP 8.1+: safely normalize on_pages before foreach
282 332 $notice = (array)$notice;
283 333 $notice['on_pages'] = empty($notice['on_pages']) ? array('*') : (array)$notice['on_pages'];
284 - foreach($notice['on_pages'] as $page)
334 + foreach($notice['on_pages'] as $page)
285 335 {
286 336 if(!preg_match('/^(.+?)\:/', $page)) // NO prefix?
287 337 $page = 'blog:'.ltrim($page, ':'); // `blog:`
288 338