PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.13
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.13
1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 1.7.0.9 All 211 releases
← All changes | includes/admin/class-charitable-admin-notices.php +640 -63 1.6.7 → 1.8.13 View file →
@@ -2,13 +2,13 @@
2 2 /**
3 3 * Contains the class that is used to register and retrieve notices in the admin like errors, warnings, success messages, etc.
4 4 *
5 5 * @package Charitable/Classes/Charitable_Admin_Notices
6 - * @author Eric Daams
7 - * @copyright Copyright (c) 2018, Studio 164a
6 + * @author David Bisset
7 + * @copyright Copyright (c) 2023, WP Charitable LLC
8 8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 9 * @since 1.4.6
10 - * @version 1.5.4
10 + * @version 1.6.24
11 11 */
12 12
13 13 // Exit if accessed directly.
14 14 if ( ! defined( 'ABSPATH' ) ) {
@@ -47,39 +47,53 @@
47 47 /**
48 48 * Create class object. A private constructor, so this is used in a singleton context.
49 49 *
50 50 * @since 1.4.6
51 - * @since 1.5.4 Access changed to public.
51 + * @version 1.5.4 Access changed to public.
52 + * @version 1.8.0 Added the 'render_campaign_builder_notice' notice.
53 + * @version 1.8.1 Added 'render_dashboard_reporting_notice' and 'dismiss_dashboard_reporting_notice'. Removed 'render_campaign_builder_notice' notice.
54 + * @version 1.8.1.12 Added 'render_license_expiring_banner'.
55 + *
56 + * @return void
52 57 */
53 58 public function __construct() {
54 59 $this->load_notices();
60 +
61 + add_action( 'admin_notices', array( $this, 'render_upgrade_banner' ) );
62 + add_action( 'admin_notices', array( $this, 'render_license_expiring_banner' ) );
63 + add_action( 'admin_notices', array( $this, 'render_license_expired_banner' ) );
64 + add_action( 'admin_notices', array( $this, 'render_five_star_rating' ) );
65 + add_action( 'admin_notices', array( $this, 'render_square_connection_error' ) );
66 + add_action( 'admin_notices', array( $this, 'render_paypal_account_type_required_notice' ) );
67 + add_action( 'charitable_dismiss_notice', array( $this, 'dismiss_five_star_notice' ), 10, 1 );
68 + add_action( 'charitable_dismiss_notice', array( $this, 'dismiss_campaign_builder_notice' ), 10, 1 );
69 + add_action( 'charitable_dismiss_notice', array( $this, 'dismiss_dashboard_reporting_notice' ), 10, 1 );
70 + add_action( 'charitable_dismiss_notice', array( $this, 'dismiss_square_connection_error_notice' ), 10, 1 );
71 + add_filter( 'charitable_localized_javascript_vars', array( $this, 'render_campaign_upgrade_banner_html' ), 10, 1 );
55 72 }
56 73
57 74 /**
58 75 * Adds a notice message.
59 76 *
60 - * @since 1.4.6
77 + * @since 1.4.6
61 78 *
62 - * @param string $message
63 - * @param string $type
64 - * @param string $key Optional. If not set, next numeric key is used.
65 - * @return void
79 + * @param string $message The message to display.
80 + * @param string $type The type of notice. Accepts 'error', 'warning', 'success', 'info', 'version'.
81 + * @param string $key Optional. If not set, next numeric key is used.
82 + * @param boolean $dismissible Optional. Whether the notice can be dismissed. Defaults to false.
83 + * @return void
66 84 */
67 85 public function add_notice( $message, $type, $key = false, $dismissible = false ) {
68 86 if ( false === $key ) {
69 -
70 87 $this->notices[ $type ][] = array(
71 88 'message' => $message,
72 89 'dismissible' => $dismissible,
73 90 );
74 -
75 91 } else {
76 -
77 92 $this->notices[ $type ][ $key ] = array(
78 93 'message' => $message,
79 94 'dismissible' => $dismissible,
80 95 );
81 -
82 96 }
83 97 }
84 98
85 99 /**
@@ -84,13 +98,14 @@
84 98
85 99 /**
86 100 * Adds an error message.
87 101 *
88 - * @since 1.4.6
102 + * @since 1.4.6
89 103 *
90 - * @param string $message
91 - * @param string $key Optional. If not set, next numeric key is used.
92 - * @return void
104 + * @param string $message The message to display.
105 + * @param string $key Optional. If not set, next numeric key is used.
106 + * @param boolean $dismissible Optional. Set to true by default.
107 + * @return void
93 108 */
94 109 public function add_error( $message, $key = false, $dismissible = false ) {
95 110 $this->add_notice( $message, 'error', $key, $dismissible );
96 111 }
@@ -97,13 +112,14 @@
97 112
98 113 /**
99 114 * Adds a warning message.
100 115 *
101 - * @since 1.4.6
116 + * @since 1.4.6
102 117 *
103 - * @param string $message
104 - * @param string $key Optional. If not set, next numeric key is used.
105 - * @return void
118 + * @param string $message The message to display.
119 + * @param string $key Optional. If not set, next numeric key is used.
120 + * @param boolean $dismissible Optional. Set to true by default.
121 + * @return void
106 122 */
107 123 public function add_warning( $message, $key = false, $dismissible = false ) {
108 124 $this->add_notice( $message, 'warning', $key, $dismissible );
109 125 }
@@ -110,13 +126,14 @@
110 126
111 127 /**
112 128 * Adds a success message.
113 129 *
114 - * @since 1.4.6
130 + * @since 1.4.6
115 131 *
116 - * @param string $message
117 - * @param string $key Optional. If not set, next numeric key is used.
118 - * @return void
132 + * @param string $message The message to display.
133 + * @param string $key Optional. If not set, next numeric key is used.
134 + * @param boolean $dismissible Optional. Set to true by default.
135 + * @return void
119 136 */
120 137 public function add_success( $message, $key = false, $dismissible = false ) {
121 138 $this->add_notice( $message, 'success', $key, $dismissible );
122 139 }
@@ -123,13 +140,14 @@
123 140
124 141 /**
125 142 * Adds an info message.
126 143 *
127 - * @since 1.4.6
144 + * @since 1.4.6
128 145 *
129 - * @param string $message
130 - * @param string $key Optional. If not set, next numeric key is used.
131 - * @return void
146 + * @param string $message The message to display.
147 + * @param string $key Optional. If not set, next numeric key is used.
148 + * @param boolean $dismissible Optional. Set to true by default.
149 + * @return void
132 150 */
133 151 public function add_info( $message, $key = false, $dismissible = false ) {
134 152 $this->add_notice( $message, 'info', $key, $dismissible );
135 153 }
@@ -136,14 +154,14 @@
136 154
137 155 /**
138 156 * Adds a version update message.
139 157 *
140 - * @since 1.4.6
158 + * @since 1.4.6
141 159 *
142 - * @param string $message
143 - * @param string $key Optional. If not set, next numeric key is used.
144 - * @param boolean $dismissible Optional. Set to true by default.
145 - * @return void
160 + * @param string $message The message to display.
161 + * @param string $key Optional. If not set, next numeric key is used.
162 + * @param boolean $dismissible Optional. Set to true by default.
163 + * @return void
146 164 */
147 165 public function add_version_update( $message, $key = false, $dismissible = true ) {
148 166 $this->add_notice( $message, 'version', $key, $dismissible );
149 167 }
@@ -148,20 +166,34 @@
148 166 $this->add_notice( $message, 'version', $key, $dismissible );
149 167 }
150 168
151 169 /**
170 + * Adds a third party warning message.
171 + *
172 + * @since 1.7.0.8
173 + *
174 + * @param string $message The message to display.
175 + * @param string $key Optional. If not set, next numeric key is used.
176 + * @param boolean $dismissible Optional. Set to true by default.
177 + * @return void
178 + */
179 + public function add_third_party_warning( $message, $key = false, $dismissible = true ) {
180 + $this->add_notice( $message, 'warning', $key, $dismissible );
181 + }
182 +
183 + /**
152 184 * Render notices.
153 185 *
154 - * @since 1.4.6
186 + * @since 1.4.6
155 187 *
156 - * @return void
188 + * @return void
157 189 */
158 190 public function render() {
159 -
160 191 foreach ( charitable_get_admin_notices()->get_notices() as $type => $notices ) {
161 -
162 192 foreach ( $notices as $key => $notice ) {
163 - $this->render_notice( $notice['message'], $type, $notice['dismissible'], $key );
193 + if ( ! empty( $notice['message'] ) ) {
194 + $this->render_notice( $notice['message'], $type, $notice['dismissible'], $key );
195 + }
164 196 }
165 197 }
166 198 }
167 199
@@ -167,20 +199,19 @@
167 199
168 200 /**
169 201 * Render a notice.
170 202 *
171 - * @since 1.4.6
203 + * @since 1.4.6
172 204 *
173 - * @param string $notice
174 - * @param string $type
175 - * @param boolean $dismissible
176 - * @param string $notice_key
177 - * @return void
205 + * @param string $notice The notice message.
206 + * @param string $type The type of notice. Accepts 'error', 'warning', 'success', 'info', 'version'.
207 + * @param boolean $dismissible Optional. Whether the notice can be dismissed. Defaults to false.
208 + * @param string $notice_key Optional. If set, the notice will be dismissed when the user dismisses the notice.
209 + * @param boolean $paragraph_tags Optional. Whether to wrap the notice in paragraph tags. Defaults to true.
210 + * @return void
178 211 */
179 - public function render_notice( $notice, $type, $dismissible = false, $notice_key = '' ) {
180 -
212 + public function render_notice( $notice, $type, $dismissible = false, $notice_key = '', $paragraph_tags = true ) {
181 213 if ( ! isset( $this->script_enqueued ) ) {
182 -
183 214 if ( ! wp_script_is( 'charitable-admin-notice' ) ) {
184 215 wp_enqueue_script( 'charitable-admin-notice' );
185 216 }
186 217
@@ -189,25 +220,29 @@
189 220
190 221 $class = 'notice charitable-notice';
191 222
192 223 switch ( $type ) {
193 - case 'error' :
224 + case 'error':
194 225 $class .= ' notice-error';
195 226 break;
196 227
197 - case 'warning' :
228 + case 'warning':
198 229 $class .= ' notice-warning';
199 230 break;
200 231
201 - case 'success' :
232 + case 'success':
202 233 $class .= ' updated';
203 234 break;
204 235
205 - case 'info' :
236 + case 'info':
206 237 $class .= ' notice-info';
207 238 break;
208 239
209 - case 'version' :
240 + case 'five-star-review':
241 + $class .= ' notice-info notice-five-star-review';
242 + break;
243 +
244 + case 'version':
210 245 $class .= ' charitable-upgrade-notice';
211 246 break;
212 247 }
213 248
@@ -214,29 +249,513 @@
214 249 if ( $dismissible ) {
215 250 $class .= ' is-dismissible';
216 251 }
217 252
218 - printf( '<div class="%s" %s><p>%s</p></div>',
253 + $body_text = ( $paragraph_tags ) ? '<p>%s</p>' : '%s';
254 +
255 + printf(
256 + '<div class="%s" %s>' . wp_kses_post( $body_text ) . '</div>',
219 257 esc_attr( $class ),
220 258 strlen( $notice_key ) ? 'data-notice="' . esc_attr( $notice_key ) . '"' : '',
221 - $notice
259 + wp_kses_post( $notice )
222 260 );
223 261
224 262 if ( strlen( $notice_key ) ) {
225 263 unset( $this->notices[ $type ][ $notice_key ] );
226 264 }
265 + }
227 266
267 + /**
268 + * Render a lite to pro banner
269 + *
270 + * @since 1.7.0
271 + */
272 + public function render_upgrade_banner() {
273 + if ( charitable_is_pro() ) {
274 + return;
275 + }
276 + $screen = get_current_screen();
277 + if ( ! is_null( $screen ) && ( in_array( $screen->id, charitable_get_charitable_screens() ) || ( isset( $screen->taxonomy ) && 'campaign_category' === $screen->taxonomy ) || ( isset( $screen->taxonomy ) && 'campaign_tag' === $screen->taxonomy ) ) ) {
278 + $banner = get_transient( 'charitable_charitablelitetopro_banner' );
279 + if ( ! $banner ) {
280 + $utm_link = charitable_pro_upgrade_url( 'Upgrade From Lite Top Banner Link', 'To unlock more features consider upgrading to Pro.' );
281 + $this->render_banner(
282 + 'You\'re using Charitable Lite! To unlock more features consider <a href="' . $utm_link . '" target="_blank" rel="noopener noreferrer">upgrading to Pro</a>.
283 + ',
284 + 'top-of-page',
285 + true
286 + );
287 + }
288 + }
228 289 }
229 290
230 291 /**
292 + * Render a license soon-to-be-expired banner.
293 + *
294 + * @since 1.8.1.12
295 + */
296 + public function render_license_expiring_banner() {
297 +
298 + if ( ! charitable_is_pro() || ! class_exists( 'Charitable_Licenses_Settings' ) || ! class_exists( 'Charitable_Addons_Directory' ) ) {
299 + // This should only show if the user has a license already entered.
300 + return;
301 + }
302 +
303 + $is_legacy = Charitable_Addons_Directory::is_current_plan_legacy();
304 + if ( $is_legacy ) {
305 + return;
306 + }
307 +
308 + // Is the license expiring within 14 days?
309 + $is_license_expiring = Charitable_Licenses_Settings::get_instance()->is_license_expiring( 1209600 );
310 +
311 + if ( $is_license_expiring ) {
312 + $screen = get_current_screen();
313 + if ( ! is_null( $screen ) && ( in_array( $screen->id, charitable_get_charitable_screens(), true ) || ( isset( $screen->taxonomy ) && 'campaign_category' === $screen->taxonomy ) || ( isset( $screen->taxonomy ) && 'campaign_tag' === $screen->taxonomy ) ) ) {
314 + $banner = get_transient( 'charitable_expiringlicense_banner' );
315 + if ( ! $banner ) {
316 + $this->render_banner(
317 + 'Your Charitable license may be expiring soon. <a href="' . admin_url( 'admin.php?page=charitable-settings&tab=general&warning=license-expire' ) . '" target="_blank" rel="noopener noreferrer">View license settings</a> to ensure support and updates are not interrupted.
318 + ',
319 + 'top-of-page',
320 + true,
321 + 'expiringlicense',
322 + 'expiringlicense',
323 + false,
324 + 'charitable-license-expiring-banner'
325 + );
326 + }
327 + }
328 + }
329 + }
330 +
331 + /**
332 + * Render a license soon-to-be-expired banner.
333 + *
334 + * @since 1.8.1.12
335 + */
336 + public function render_license_expired_banner() {
337 + if ( ! charitable_is_pro() || ! class_exists( 'Charitable_Licenses_Settings' ) || ! class_exists( 'Charitable_Addons_Directory' ) ) {
338 + // This should only show if the user has a license already entered.
339 + return;
340 + }
341 +
342 + $is_legacy = Charitable_Addons_Directory::is_current_plan_legacy();
343 + if ( $is_legacy ) {
344 + return;
345 + }
346 +
347 + // Is the license expiring within 14 days?
348 + $is_license_expired = Charitable_Licenses_Settings::get_instance()->is_license_expired();
349 +
350 + if ( $is_license_expired ) {
351 + $screen = get_current_screen();
352 + if ( ! is_null( $screen ) && ( in_array( $screen->id, charitable_get_charitable_screens(), true ) || ( isset( $screen->taxonomy ) && 'campaign_category' === $screen->taxonomy ) || ( isset( $screen->taxonomy ) && 'campaign_tag' === $screen->taxonomy ) ) ) {
353 + $banner = get_transient( 'charitable_expiredlicense_banner' );
354 + if ( ! $banner ) {
355 + $this->render_banner(
356 + 'Your Charitable license may have expired. <a href="' . admin_url( 'admin.php?page=charitable-settings&tab=general&warning=license-expire' ) . '" target="_blank" rel="noopener noreferrer">View license settings</a> to ensure support and updates are not interrupted.
357 + ',
358 + 'top-of-page',
359 + true,
360 + 'expiredlicense',
361 + 'expiredlicense',
362 + false,
363 + 'charitable-license-expiring-banner'
364 + );
365 + }
366 + }
367 + }
368 + }
369 +
370 + /**
371 + * Render a lite to pro banner in campaign lists, add it to the charitable admin vars so it can be injected via JS.
372 + *
373 + * @param array $strings The localized strings.
374 + *
375 + * @since 1.8.0
376 + */
377 + public function render_campaign_upgrade_banner_html( $strings = false ) {
378 + if ( charitable_is_pro() ) {
379 + return $strings;
380 + }
381 + $screen = get_current_screen();
382 + if ( ! is_null( $screen ) && isset( $screen->base ) && 'edit' === $screen->base && isset( $screen->id ) && 'edit-campaign' === $screen->id ) {
383 + $banner = get_transient( 'charitable_charitable_ltp_lb_list_banner' );
384 + if ( ! $banner ) {
385 + $nonce = wp_create_nonce( 'charitable_dismiss_list_banner' );
386 + $banner_text = '<p><strong>Unlock More Donations with Peer-to-Peer Fundraising!</strong><br/>Harness the power of supporter networks and friends to reach more people and raise more money for your cause.</p>';
387 + $strings['banner'] = sprintf(
388 + '<div data-id="charitable_ltp_lb" data-nonce="%1$s" class="charitable-campaign-list-banner">' .
389 + '<button type="button" class="notice-dismiss"><span class="screen-reader-text">Dismiss this notice.</span></button>' .
390 + '<div class="charitable-campaign-list-banner-icon-text">' .
391 + '<div class="charitable-campaign-list-banner-icon"><img src="%2$s" /></div>' .
392 + '<div class="charitable-campaign-list-banner-text">%3$s</div>' .
393 + '</div>' .
394 + '<div class="charitable-campaign-list-banner-button"><a class="button-link" href="#">Learn More</a></div>' .
395 + '</div>',
396 + $nonce,
397 + charitable()->get_path( 'assets', false ) . 'images/icons/ambassador.png',
398 + $banner_text
399 + );
400 + } else {
401 + $strings['banner'] = '';
402 + }
403 + }
404 +
405 + return $strings;
406 + }
407 +
408 + /**
409 + * Render a prompt to ask for a five star rating.
410 + *
411 + * @since 1.7.0
412 + */
413 + public function render_five_star_rating() {
414 +
415 + if ( ! function_exists( 'get_current_screen' ) ) {
416 + return;
417 + }
418 +
419 + // Dashboard has its own inline version of this notice — skip the top-bar one.
420 + $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
421 + if ( 'charitable-dashboard' === $page ) {
422 + return;
423 + }
424 +
425 + $screen = get_current_screen();
426 +
427 + // determine if we are on the current screen.
428 + if ( ! is_null( $screen ) && ( in_array( $screen->id, charitable_get_charitable_screens() ) || ( isset( $screen->taxonomy ) && 'campaign_category' === $screen->taxonomy ) || ( isset( $screen->taxonomy ) && 'campaign_tag' === $screen->taxonomy ) ) ) {
429 +
430 + $slug = 'five-star-review';
431 +
432 + // determine when to display this message. for now, there should be some sensible boundaries before showing the notification: a minimum of 14 days of use, created one donation form and received at least one donation.
433 + $activated_datetime = ( false !== get_option( 'wpcharitable_activated_datetime' ) ) ? get_option( 'wpcharitable_activated_datetime' ) : false;
434 + $days = 0;
435 + if ( $activated_datetime ) {
436 + $diff = current_time( 'timestamp' ) - $activated_datetime; // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
437 + $days = abs( round( $diff / 86400 ) );
438 + }
439 +
440 + $count_campaigns = wp_count_posts( 'campaign' );
441 + $total_campaigns = isset( $count_campaigns->publish ) ? $count_campaigns->publish : 0;
442 + $count_donations = wp_count_posts( 'donation' );
443 + $total_donations = isset( $count_donations->{'charitable-completed'} ) ? $count_donations->{'charitable-completed'} : 0;
444 +
445 + if ( $days >= apply_filters( 'charitable_days_since_activated', 14 ) && $total_campaigns >= 1 && $total_donations >= 1 ) {
446 + // check transient.
447 + $star_review = get_transient( 'charitable_' . $slug . '_banner' );
448 +
449 + // render five star rating banner/notice.
450 + if ( ! $star_review ) {
451 + $message = charitable_admin_view( 'notices/admin-notice-five-star-review', array(), true );
452 + $key = 'five-star-review';
453 + $this->render_notice( $message, 'five-star-review', true, $key, false );
454 + }
455 + }
456 + }
457 + }
458 +
459 + /**
460 + * Render a notice when the Square connection fails.
461 + *
462 + * @since 1.8.7
463 + */
464 + public function render_square_connection_error() {
465 +
466 + $admin_notice = get_option( 'charitable_square_connection_error_notice' );
467 +
468 + if ( false === $admin_notice ) {
469 + return;
470 + }
471 +
472 + $message = charitable_admin_view( 'notices/admin-notice-square-connection-error', array( 'message' => $admin_notice['message'], 'status_code' => $admin_notice['status_code'] ), true ); // phpcs:ignore
473 + $key = 'square-connection-error';
474 + $this->render_notice( $message, 'error', true, $key, false );
475 + }
476 +
477 + /**
478 + * Render a persistent banner across all Charitable admin screens when
479 + * the PayPal Commerce gateway is connected but the merchant has not
480 + * yet chosen an Account Type (Nonprofit vs Business).
481 + *
482 + * Per the 1.8.12 spec (B-strict default-handling) this banner is
483 + * intentionally NOT dismissible — the underlying state blocks
484 + * donations at validate_donation(), so dismissing the banner without
485 + * resolving the setting would mask broken donation processing from
486 + * the merchant. The banner persists until the setting is saved.
487 + *
488 + * @since 1.8.12
489 + *
490 + * @return void
491 + */
492 + public function render_paypal_account_type_required_notice() {
493 + // Gate behind manage_options. The notice exposes gateway
494 + // configuration state and links to the settings page; only users
495 + // who can actually fix it should see it.
496 + if ( ! current_user_can( 'manage_options' ) ) {
497 + return;
498 + }
499 +
500 + // Only fire on Charitable admin screens to avoid leaking into
501 + // unrelated plugins' admin contexts.
502 + $screen = get_current_screen();
503 + if ( is_null( $screen ) || ! in_array( $screen->id, charitable_get_charitable_screens(), true ) ) {
504 + return;
505 + }
506 +
507 + if ( ! class_exists( 'Charitable_Gateway_Paypal_Commerce' ) ) {
508 + return;
509 + }
510 +
511 + // Only fire when PayPal Commerce is actually an enabled gateway.
512 + // Stale merchant ID meta can survive from a prior connected session
513 + // even after the gateway is disabled in Settings > Payment Gateways;
514 + // without this check the notice would scold merchants who are not
515 + // using the gateway at all, and the deep-link target (the
516 + // gateways_paypal_commerce settings group) is not even registered
517 + // when the gateway is off, so clicking the notice's CTA would
518 + // bounce them to the gateway list page instead.
519 + $gateways = charitable_get_helper( 'gateways' );
520 + if ( ! $gateways || ! $gateways->is_active_gateway( Charitable_Gateway_Paypal_Commerce::ID ) ) {
521 + return;
522 + }
523 +
524 + $gateway = new Charitable_Gateway_Paypal_Commerce();
525 +
526 + // Only relevant for sites that have actually connected PayPal
527 + // Commerce. A disconnected gateway has nothing to gate.
528 + if ( ! $gateway->is_seller_connected() ) {
529 + return;
530 + }
531 +
532 + if ( $gateway->is_account_type_configured() ) {
533 + return;
534 + }
535 +
536 + $settings_url = admin_url( 'admin.php?page=charitable-settings&tab=gateways&group=gateways_paypal_commerce' );
537 + $message = sprintf(
538 + /* translators: %s: settings URL */
539 + __( '<strong>PayPal Commerce: Action Required.</strong> Donations are currently blocked because your Account Type has not been set. <a href="%s">Choose Nonprofit or Business</a> on the PayPal Commerce settings page to resume accepting donations.', 'charitable' ),
540 + esc_url( $settings_url )
541 + );
542 +
543 + echo '<div class="notice notice-error" style="border-left-width:4px;"><p>' . wp_kses(
544 + $message,
545 + array(
546 + 'strong' => array(),
547 + 'a' => array(
548 + 'href' => array(),
549 + ),
550 + )
551 + ) . '</p></div>';
552 + }
553 +
554 + /**
555 + * Render a banner to promote the new campaign builder in version 1.8.0.
556 + * This was removed in 1.8.1 in favor of the updated notice render_dashboard_reporting_notice.
557 + *
558 + * @since 1.8.0
559 + */
560 + public function render_campaign_builder_notice() {
561 +
562 + if ( ! function_exists( 'get_current_screen' ) ) {
563 + return;
564 + }
565 +
566 + $screen = get_current_screen();
567 +
568 + // determine if we are on the current screen.
569 + if ( ! is_null( $screen ) && ( in_array( $screen->id, charitable_get_charitable_screens() ) || ( isset( $screen->taxonomy ) && 'campaign_category' === $screen->taxonomy ) || ( isset( $screen->taxonomy ) && 'campaign_tag' === $screen->taxonomy ) ) ) {
570 +
571 + $slug = 'campaign-builder';
572 +
573 + // check transient.
574 + $builder_notice = get_transient( 'charitable_' . $slug . '_banner' );
575 +
576 + // render banner/notice.
577 + if ( ! $builder_notice ) {
578 + $message = charitable_admin_view( 'notices/admin-notice-campaign-builder', array(), true );
579 + $key = 'campaign-builder';
580 + $this->render_notice( $message, 'campaign-builder', true, $key, false );
581 + }
582 + }
583 + }
584 +
585 + /**
586 + * Render a banner to promote
587 + *
588 + * @since 1.8.1
589 + * @version 1.8.1.10
590 + * @version 1.8.2 deprecated.
591 + */
592 + public function render_dashboard_reporting_notice() {
593 +
594 + if ( ! function_exists( 'get_current_screen' ) ) {
595 + return;
596 + }
597 +
598 + $screen = get_current_screen();
599 +
600 + // determine if we are on the current screen.
601 + if ( ! is_null( $screen ) && ( in_array( $screen->id, charitable_get_charitable_screens() ) || ( isset( $screen->taxonomy ) && 'campaign_category' === $screen->taxonomy ) || ( isset( $screen->taxonomy ) && 'campaign_tag' === $screen->taxonomy ) ) ) {
602 +
603 + $slug = 'dashboard-reporting';
604 +
605 + // determine when to display this message. for now, there should be some sensible boundaries before showing the notification: a minimum of 10 days of use.
606 + $activated_datetime = ( false !== get_option( 'wpcharitable_activated_datetime' ) ) ? get_option( 'wpcharitable_activated_datetime' ) : false;
607 + $days = 0;
608 + if ( $activated_datetime ) {
609 + $diff = current_time( 'timestamp' ) - $activated_datetime; // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
610 + $days = abs( round( $diff / 86400 ) );
611 + }
612 +
613 + if ( $days >= apply_filters( 'charitable_days_since_activated', 10, $slug ) ) {
614 + // check transient.
615 + $builder_notice = get_transient( 'charitable_' . $slug . '_banner' );
616 +
617 + // render banner/notice.
618 + if ( ! $builder_notice ) {
619 + $message = charitable_admin_view( 'notices/admin-notice-dashboard-reporting', array(), true );
620 + $key = 'dashboard-reporting';
621 + $this->render_notice( $message, 'dashboard-reporting', true, $key, false );
622 + }
623 + }
624 + }
625 + }
626 +
627 + /**
628 + * Dismiss review request.
629 + *
630 + * @since 1.8.0
631 + * @param array $postdata $_POST data.
632 + */
633 + public function dismiss_five_star_notice( $postdata ) {
634 +
635 + if ( empty( $postdata['notice'] ) || 'five-star-review' !== $postdata['notice'] ) {
636 + return;
637 + }
638 +
639 + $slug = 'five-star-review';
640 +
641 + set_transient( 'charitable_' . $slug . '_banner', 1, 0 );
642 + }
643 +
644 + /**
645 + * Dismiss the new campaign builder notice. Deprecated in 1.8.1.
646 + *
647 + * @since 1.8.0
648 + * @param array $postdata $_POST data.
649 + */
650 + public function dismiss_campaign_builder_notice( $postdata ) {
651 +
652 + if ( empty( $postdata['notice'] ) || 'campaign-builder' !== $postdata['notice'] ) {
653 + return;
654 + }
655 +
656 + $slug = 'campaign-builder';
657 +
658 + set_transient( 'charitable_' . $slug . '_banner', 1, 0 );
659 + }
660 +
661 + /**
662 + * Dismiss the new campaign builder notice.
663 + *
664 + * @since 1.8.1
665 + * @param array $postdata $_POST data.
666 + */
667 + public function dismiss_dashboard_reporting_notice( $postdata ) {
668 +
669 + if ( empty( $postdata['notice'] ) || 'dashboard-reporting' !== $postdata['notice'] ) {
670 + return;
671 + }
672 +
673 + $slug = 'dashboard-reporting';
674 +
675 + set_transient( 'charitable_' . $slug . '_banner', 1, 0 );
676 + }
677 +
678 + /**
679 + * Dismiss the Square connection error notice.
680 + *
681 + * @since 1.8.7
682 + * @param array $postdata $_POST data.
683 + */
684 + public function dismiss_square_connection_error_notice( $postdata ) {
685 + if ( empty( $postdata['notice'] ) || 'square-connection-error' !== $postdata['notice'] ) {
686 + return;
687 + }
688 +
689 + delete_option( 'charitable_square_connection_error_notice' );
690 + wp_send_json_success();
691 + exit;
692 + }
693 +
694 + /**
695 + * Render a banner.
696 + *
697 + * @since 1.7.0
698 + * @version 1.8.1.12 Added css_class.
699 + *
700 + * @param string $message The message to display.
701 + * @param string $type The type of notice. Accepts 'top-of-page'.
702 + * @param boolean $dismissible Optional. Whether the notice can be dismissed. Defaults to false.
703 + * @param mixed $data_nonce Optional. The nonce to use for the notice.
704 + * @param mixed $data_id Optional. The id to use for the notice.
705 + * @param string $data_lifespan Optional. The lifespan of the notice.
706 + * @param string $additional_css_class Optional. The CSS class to use for the notice.
707 + *
708 + * @return void
709 + */
710 + public function render_banner( $message, $type = 'top-of-page', $dismissible = false, $data_nonce = 'charitablelitetopro', $data_id = 'charitablelitetopro', $data_lifespan = false, $additional_css_class = '' ) {
711 + if ( ! isset( $this->script_enqueued ) ) {
712 + if ( ! wp_script_is( 'charitable-admin-notice' ) ) {
713 + wp_enqueue_script( 'charitable-admin-notice' );
714 + }
715 +
716 + $this->script_enqueued = true;
717 + }
718 +
719 + $css_class = trim( 'charitable-banner ' . $additional_css_class );
720 +
721 + switch ( $type ) {
722 + case 'top-of-page':
723 + $css_class .= ' charitable-admin-banner-top-of-page';
724 + break;
725 + }
726 +
727 + if ( $dismissible ) { // phpcs:ignore
728 + // $class .= ' is-dismissible';
729 + }
730 +
731 + printf(
732 + '<div class="%s" %s %s %s>%s <button type="button" class="button-link charitable-banner-dismiss">x</button></div>',
733 + esc_attr( $css_class ),
734 + strlen( $data_nonce ) ? 'data-notice="' . esc_attr( $data_nonce ) . '"' : '',
735 + strlen( $data_id ) ? 'data-id="' . esc_attr( $data_id ) . '"' : '',
736 + strlen( $data_lifespan ) ? 'data-lifespan="' . esc_attr( $data_lifespan ) . '"' : '',
737 + wp_kses_post( $message )
738 + );
739 + }
740 +
741 +
742 + /**
231 743 * When PHP finishes executing, stash any notices that haven't been rendered yet.
232 744 *
233 - * @since 1.4.13
745 + * @since 1.4.13
234 746 *
235 - * @return void
747 + * @return void
236 748 */
237 749 public function shutdown() {
238 - set_transient( 'charitable_notices', $this->notices );
750 + if ( charitable_is_debug( 'square' ) ) {
751 + // phpcs:disable
752 + error_log( 'Saving admin notices to transient' );
753 + error_log( 'Notices to save: ' . print_r( $this->notices, true ) );
754 + // phpcs:enable
755 + }
756 +
757 + set_transient( 'charitable_notices', $this->notices );
239 758 }
240 759
241 760 /**
242 761 * Load the notices array.
@@ -242,15 +761,15 @@
242 761 * Load the notices array.
243 762 *
244 763 * If there are any stuffed in a transient, pull those out. Otherwise, reset a clear array.
245 764 *
246 - * @since 1.4.13
765 + * @since 1.4.13
247 766 *
248 - * @return void
767 + * @return void
249 768 */
250 769 public function load_notices() {
251 770 $this->notices = get_transient( 'charitable_notices' );
252 -
771 +
253 772 if ( ! is_array( $this->notices ) ) {
254 773 $this->clear();
255 774 }
256 775 }
@@ -255,13 +774,32 @@
255 774 }
256 775 }
257 776
258 777 /**
778 + * Fill admin notices from the front-end notices array.
779 + *
780 + * @since 1.6.24
781 + *
782 + * @return void
783 + */
784 + public function fill_notices_from_frontend() {
785 + $notices = charitable_get_notices();
786 +
787 + foreach ( $notices->get_notices() as $type => $type_notices ) {
788 + foreach ( $type_notices as $notice ) {
789 + $this->add_notice( $notice, $type );
790 + }
791 + }
792 +
793 + $notices->clear();
794 + }
795 +
796 + /**
259 797 * Clear out all existing notices.
260 798 *
261 - * @since 1.4.6
799 + * @since 1.4.6
262 800 *
263 - * @return void
801 + * @return void
264 802 */
265 803 public function clear() {
266 804 $clear = array(
267 805 'error' => array(),
@@ -271,8 +809,47 @@
271 809 'version' => array(),
272 810 );
273 811
274 812 $this->notices = $clear;
813 + }
814 +
815 + /**
816 + * Returns an array of screen IDs where the Charitable notices should be displayed.
817 + * (Deprecated in 1.8.1.15)
818 + *
819 + * @uses charitable_admin_screens
820 + *
821 + * @since 1.7.0
822 + * @since 1.8.1 Added the Charitable reports page.
823 + * @since 1.8.1.6 Added the Charitable tools and guide tools page.
824 + * @since 1.8.5 Added the Charitable donors page.
825 + * @return array
826 + */
827 + public function get_charitable_screens() {
828 + /**
829 + * Filter admin screens where Charitable styles & scripts should be loaded.
830 + *
831 + * @since 1.7.0
832 + *
833 + * @param string[] $screens List of screen ids.
834 + */
835 + return apply_filters(
836 + 'charitable_admin_notice_screens',
837 + array(
838 + 'campaign',
839 + 'donation',
840 + 'charitable_page_charitable-settings',
841 + 'charitable_page_charitable-tools',
842 + 'charitable_page_charitable-growth-tools',
843 + 'charitable_page_charitable-reports',
844 + 'charitable_page_charitable-dashboard',
845 + 'edit-campaign',
846 + 'edit-donation',
847 + 'toplevel_page_charitable',
848 + 'charitable_page_charitable-addons',
849 + 'charitable_page_charitable-donors',
850 + )
851 + );
275 852 }
276 853 }
277 854
278 855 endif;