| 1 | <?php |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | use Automattic\Jetpack\Constants; |
| 9 | use Automattic\Jetpack\Jetpack_Mu_Wpcom\Expiry_Notices\Expiry_Data; |
| 10 | use Automattic\Jetpack\Jetpack_Mu_Wpcom\Expiry_Notices\Expiry_Notice_Dismiss; |
| 11 | use Automattic\Jetpack\Jetpack_Mu_Wpcom\Expiry_Notices\Expiry_Owner; |
| 12 | use Automattic\Jetpack\Jetpack_Mu_Wpcom\Expiry_Notices\Expiry_Wpcom; |
| 13 | |
| 14 | |
| 15 | require_once __DIR__ . '/class-expiry-data.php'; |
| 16 | require_once __DIR__ . '/class-expiry-domain.php'; |
| 17 | require_once __DIR__ . '/class-expiry-notice-dismiss.php'; |
| 18 | require_once __DIR__ . '/class-expiry-owner.php'; |
| 19 | require_once __DIR__ . '/class-expiry-wpcom.php'; |
| 20 | |
| 21 | |
| 22 | |
| 23 | if ( ! function_exists( 'wpcom_expiry_get_purchases' ) ) { |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | |
| 29 | |
| 30 | |
| 31 | |
| 32 | |
| 33 | function wpcom_expiry_get_purchases() { |
| 34 | if ( function_exists( 'wpcom_get_site_purchases' ) ) { |
| 35 | return wpcom_get_site_purchases(); |
| 36 | } |
| 37 | return array(); |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | if ( ! function_exists( 'wpcom_expiry_get_reverted_transfer' ) ) { |
| 42 | |
| 43 | |
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | |
| 50 | |
| 51 | |
| 52 | function wpcom_expiry_get_reverted_transfer(): ?array { |
| 53 | if ( ! function_exists( 'get_wpcom_blog_id' ) || ! function_exists( 'woa_get_latest_transfer' ) || ! function_exists( 'woa_get_transfer_meta' ) || ! function_exists( 'woa_is_revert_for_expired_plan' ) ) { |
| 54 | return null; |
| 55 | } |
| 56 | $blog_id = get_wpcom_blog_id(); |
| 57 | |
| 58 | |
| 59 | if ( ! $blog_id || ! wpcom_has_blog_sticker( 'blog-transfer-reverted', $blog_id ) ) { |
| 60 | return null; |
| 61 | } |
| 62 | |
| 63 | $cached = Expiry_Wpcom::remember( |
| 64 | 'wpcom_expiry_notices_reverted_transfer_' . $blog_id, |
| 65 | static function () use ( $blog_id ): ?string { |
| 66 | |
| 67 | $transfer = woa_get_latest_transfer( $blog_id ); |
| 68 | if ( ! is_object( $transfer ) || is_wp_error( $transfer ) || 'reverted' !== (string) ( $transfer->status ?? '' ) ) { |
| 69 | return Expiry_Wpcom::NONE; |
| 70 | } |
| 71 | $transfer_id = (int) ( $transfer->atomic_transfer_id ?? 0 ); |
| 72 | |
| 73 | $reverted_at = $transfer_id ? woa_get_transfer_meta( $transfer_id, 'reverted_at' ) : null; |
| 74 | $reverted_ts = is_string( $reverted_at ) ? strtotime( $reverted_at ) : false; |
| 75 | if ( false === $reverted_ts ) { |
| 76 | return Expiry_Wpcom::NONE; |
| 77 | } |
| 78 | return wp_json_encode( |
| 79 | array( |
| 80 | 'reverted_at' => $reverted_ts, |
| 81 | |
| 82 | 'for_expired_plan' => (bool) woa_is_revert_for_expired_plan( $transfer_id ), |
| 83 | ), |
| 84 | JSON_UNESCAPED_SLASHES |
| 85 | ); |
| 86 | } |
| 87 | ); |
| 88 | |
| 89 | if ( null === $cached || Expiry_Wpcom::NONE === $cached ) { |
| 90 | return null; |
| 91 | } |
| 92 | $decoded = json_decode( $cached, true ); |
| 93 | if ( ! is_array( $decoded ) || ! isset( $decoded['reverted_at'] ) || ! isset( $decoded['for_expired_plan'] ) ) { |
| 94 | return null; |
| 95 | } |
| 96 | return array( |
| 97 | 'reverted_at' => (int) $decoded['reverted_at'], |
| 98 | 'for_expired_plan' => (bool) $decoded['for_expired_plan'], |
| 99 | ); |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | |
| 104 | |
| 105 | |
| 106 | |
| 107 | |
| 108 | |
| 109 | |
| 110 | function wpcom_expiry_notices_is_enabled_for_site(): bool { |
| 111 | |
| 112 | |
| 113 | |
| 114 | |
| 115 | |
| 116 | |
| 117 | |
| 118 | |
| 119 | return (bool) apply_filters( 'wpcom_expiry_notices_enabled', true, 100 ); |
| 120 | } |
| 121 | |
| 122 | |
| 123 | |
| 124 | |
| 125 | |
| 126 | |
| 127 | |
| 128 | |
| 129 | |
| 130 | |
| 131 | function wpcom_expiry_notices_eligible_state( bool $flush = false ): ?array { |
| 132 | |
| 133 | static $memo = false; |
| 134 | |
| 135 | if ( $flush ) { |
| 136 | $memo = false; |
| 137 | return null; |
| 138 | } |
| 139 | |
| 140 | if ( false !== $memo ) { |
| 141 | return $memo; |
| 142 | } |
| 143 | |
| 144 | $memo = null; |
| 145 | |
| 146 | if ( ! current_user_can( 'manage_options' ) ) { |
| 147 | return $memo; |
| 148 | } |
| 149 | |
| 150 | |
| 151 | if ( function_exists( 'wpcom_is_vip' ) && wpcom_is_vip() ) { |
| 152 | return $memo; |
| 153 | } |
| 154 | |
| 155 | if ( wpcom_expiry_notices_store_is_sandboxed() ) { |
| 156 | return $memo; |
| 157 | } |
| 158 | |
| 159 | $state = Expiry_Data::get_expiry_state(); |
| 160 | if ( null === $state || Expiry_Data::STATE_ACTIVE === $state['state'] ) { |
| 161 | return $memo; |
| 162 | } |
| 163 | |
| 164 | $memo = $state; |
| 165 | return $memo; |
| 166 | } |
| 167 | |
| 168 | |
| 169 | |
| 170 | |
| 171 | |
| 172 | |
| 173 | |
| 174 | |
| 175 | function wpcom_expiry_notices_store_is_sandboxed(): bool { |
| 176 | if ( ! Constants::is_true( 'IS_WPCOM' ) || ! class_exists( 'Store_Sandbox' ) ) { |
| 177 | return false; |
| 178 | } |
| 179 | |
| 180 | return (bool) \Store_Sandbox::get_instance()->is_sandboxed(); |
| 181 | } |
| 182 | |
| 183 | |
| 184 | |
| 185 | |
| 186 | function wpcom_expiry_notices_current_screen_id(): string { |
| 187 | $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; |
| 188 | return $screen ? (string) $screen->id : ''; |
| 189 | } |
| 190 | |
| 191 | |
| 192 | |
| 193 | |
| 194 | |
| 195 | function wpcom_expiry_notices_is_block_editor_screen(): bool { |
| 196 | $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; |
| 197 | return $screen ? $screen->is_block_editor() : false; |
| 198 | } |
| 199 | |
| 200 | |
| 201 | |
| 202 | |
| 203 | |
| 204 | |
| 205 | |
| 206 | |
| 207 | |
| 208 | |
| 209 | function wpcom_expiry_notices_banner_data(): ?array { |
| 210 | $state = wpcom_expiry_notices_eligible_state(); |
| 211 | if ( null === $state || ! Expiry_Notice_Dismiss::should_show_banner( $state ) ) { |
| 212 | return null; |
| 213 | } |
| 214 | |
| 215 | $is_early_warning = wpcom_expiry_notices_is_early_warning( $state ); |
| 216 | if ( $is_early_warning && 'dashboard' !== wpcom_expiry_notices_current_screen_id() ) { |
| 217 | return null; |
| 218 | } |
| 219 | |
| 220 | $is_owner = Expiry_Owner::current_user_is_owner( $state ); |
| 221 | |
| 222 | return array( |
| 223 | 'state' => $state, |
| 224 | 'is_early_warning' => $is_early_warning, |
| 225 | 'is_dismissible' => Expiry_Notice_Dismiss::is_dismissible( $state ), |
| 226 | 'is_owner' => $is_owner, |
| 227 | 'urls' => $is_owner ? wpcom_expiry_notices_banner_urls( $state, wpcom_expiry_notices_current_url() ) : null, |
| 228 | ); |
| 229 | } |
| 230 | |
| 231 | |
| 232 | |
| 233 | |
| 234 | |
| 235 | |
| 236 | |
| 237 | |
| 238 | |
| 239 | |
| 240 | function wpcom_expiry_notices_plan_name( array $state ): string { |
| 241 | return Expiry_Data::derive_plan_name( (string) ( $state['product_slug'] ?? '' ) ) ?? ''; |
| 242 | } |
| 243 | |
| 244 | |
| 245 | |
| 246 | |
| 247 | |
| 248 | |
| 249 | function wpcom_expiry_notices_expired_heading( array $state ): string { |
| 250 | $plan = wpcom_expiry_notices_plan_name( $state ); |
| 251 | return '' === $plan |
| 252 | ? __( 'Your plan has expired', 'jetpack-mu-wpcom' ) |
| 253 | |
| 254 | : sprintf( __( 'Your %s plan has expired', 'jetpack-mu-wpcom' ), $plan ); |
| 255 | } |
| 256 | |
| 257 | |
| 258 | |
| 259 | |
| 260 | |
| 261 | |
| 262 | |
| 263 | |
| 264 | |
| 265 | |
| 266 | function wpcom_expiry_notices_revert_applies_to_site( array $state ): bool { |
| 267 | if ( Expiry_Data::STATE_EXPIRED === ( $state['state'] ?? '' ) ) { |
| 268 | return true; |
| 269 | } |
| 270 | return Constants::is_true( 'IS_ATOMIC' ); |
| 271 | } |
| 272 | |
| 273 | |
| 274 | |
| 275 | |
| 276 | |
| 277 | |
| 278 | |
| 279 | |
| 280 | |
| 281 | |
| 282 | |
| 283 | function wpcom_expiry_notices_support_cta( array $state ): array { |
| 284 | $plan = wpcom_expiry_notices_plan_name( $state ); |
| 285 | |
| 286 | return array( |
| 287 | 'label' => __( 'Contact support', 'jetpack-mu-wpcom' ), |
| 288 | 'url' => 'https://wordpress.com/help?help-center=home', |
| 289 | |
| 290 | |
| 291 | 'message' => '' === $plan |
| 292 | ? __( 'My plan expired and I need your help getting it restored.', 'jetpack-mu-wpcom' ) |
| 293 | |
| 294 | : sprintf( __( 'My %s plan expired and I need your help getting it restored.', 'jetpack-mu-wpcom' ), $plan ), |
| 295 | ); |
| 296 | } |
| 297 | |
| 298 | |
| 299 | |
| 300 | |
| 301 | |
| 302 | |
| 303 | |
| 304 | |
| 305 | |
| 306 | |
| 307 | |
| 308 | |
| 309 | function wpcom_expiry_notices_track_props( array $state, bool $is_owner, string $surface ): array { |
| 310 | return array( |
| 311 | 'state' => (string) ( $state['state'] ?? '' ), |
| 312 | 'days_remaining' => isset( $state['days_remaining'] ) ? (int) $state['days_remaining'] : 0, |
| 313 | 'product_slug' => isset( $state['product_slug'] ) ? (string) $state['product_slug'] : '', |
| 314 | 'is_plan_owner' => $is_owner ? 'true' : 'false', |
| 315 | 'surface' => $surface, |
| 316 | ); |
| 317 | } |
| 318 | |
| 319 | |
| 320 | |
| 321 | |
| 322 | |
| 323 | |
| 324 | |
| 325 | |
| 326 | |
| 327 | |
| 328 | |
| 329 | |
| 330 | function wpcom_expiry_notices_enqueue_surface( string $script, string $global, array $data, ?string $style = null ): void { |
| 331 | $json = wp_json_encode( $data, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_HEX_APOS ); |
| 332 | if ( false === $json ) { |
| 333 | return; |
| 334 | } |
| 335 | $handle = jetpack_mu_wpcom_enqueue_assets( $script, array( 'js' ) ); |
| 336 | \Automattic\Jetpack\Jetpack_Mu_Wpcom\Common\wpcom_enqueue_tracking_scripts( $handle ); |
| 337 | $dismiss = wp_json_encode( |
| 338 | array( |
| 339 | 'ajaxUrl' => admin_url( 'admin-ajax.php' ), |
| 340 | 'nonce' => wp_create_nonce( 'wpcom_expiry_notice_dismiss' ), |
| 341 | ), |
| 342 | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_HEX_APOS |
| 343 | ); |
| 344 | wp_add_inline_script( $handle, 'window.wpcomExpiryDismiss = ' . $dismiss . ';', 'before' ); |
| 345 | wp_add_inline_script( $handle, 'window.' . $global . ' = ' . $json . ';', 'before' ); |
| 346 | if ( null !== $style ) { |
| 347 | jetpack_mu_wpcom_enqueue_assets( $style, array( 'css' ) ); |
| 348 | } |
| 349 | } |
| 350 | |
| 351 | |
| 352 | |
| 353 | |
| 354 | |
| 355 | |
| 356 | |
| 357 | |
| 358 | |
| 359 | function wpcom_expiry_notices_render_cta_link( array $cta, string $cta_id, string $class ): void { |
| 360 | ?> |
| 361 | <a |
| 362 | class="<?php echo esc_attr( $class ); ?>" |
| 363 | href="<?php echo esc_url( $cta['url'] ); ?>" |
| 364 | data-wpcom-expiry-cta="<?php echo esc_attr( $cta_id ); ?>" |
| 365 | <?php if ( isset( $cta['message'] ) ) : ?> |
| 366 | data-support-message="<?php echo esc_attr( $cta['message'] ); ?>" |
| 367 | <?php endif; ?> |
| 368 | > |
| 369 | <?php echo esc_html( $cta['label'] ); ?> |
| 370 | </a> |
| 371 | <?php |
| 372 | } |
| 373 | |
| 374 | |
| 375 | |
| 376 | |
| 377 | |
| 378 | |
| 379 | |
| 380 | |
| 381 | function wpcom_expiry_notices_banner_urls( array $state, string $redirect_to ): array { |
| 382 | $urls = Expiry_Data::get_cta_urls( $state, $redirect_to ); |
| 383 | if ( Expiry_Data::STATE_EXPIRED === ( $state['state'] ?? '' ) ) { |
| 384 | $urls['primary'] = wpcom_expiry_notices_support_cta( $state ); |
| 385 | } |
| 386 | return $urls; |
| 387 | } |
| 388 | |
| 389 | |
| 390 | |
| 391 | |
| 392 | |
| 393 | |
| 394 | |
| 395 | function wpcom_expiry_notices_is_early_warning( array $state ): bool { |
| 396 | if ( Expiry_Data::STATE_APPROACHING !== ( $state['state'] ?? '' ) ) { |
| 397 | return false; |
| 398 | } |
| 399 | $days = isset( $state['days_remaining'] ) ? (int) $state['days_remaining'] : 0; |
| 400 | return $days > Expiry_Notice_Dismiss::FINAL_WINDOW_DAYS; |
| 401 | } |
| 402 | |
| 403 | |
| 404 | |
| 405 | |
| 406 | |
| 407 | |
| 408 | function wpcom_expiry_notices_banner_heading( array $state ): string { |
| 409 | $plan = wpcom_expiry_notices_plan_name( $state ); |
| 410 | $days = isset( $state['days_remaining'] ) ? (int) $state['days_remaining'] : 0; |
| 411 | |
| 412 | if ( in_array( $state['state'] ?? '', array( Expiry_Data::STATE_EXPIRED_GRACE, Expiry_Data::STATE_EXPIRED ), true ) ) { |
| 413 | return wpcom_expiry_notices_expired_heading( $state ); |
| 414 | } |
| 415 | |
| 416 | |
| 417 | |
| 418 | if ( ! empty( $state['auto_renew'] ) && $days > 0 ) { |
| 419 | return '' === $plan |
| 420 | |
| 421 | ? sprintf( _n( 'Your plan has %d day remaining', 'Your plan has %d days remaining', $days, 'jetpack-mu-wpcom' ), $days ) |
| 422 | |
| 423 | : sprintf( _n( 'Your %1$s plan has %2$d day remaining', 'Your %1$s plan has %2$d days remaining', $days, 'jetpack-mu-wpcom' ), $plan, $days ); |
| 424 | } |
| 425 | |
| 426 | |
| 427 | |
| 428 | if ( $days <= 0 ) { |
| 429 | return '' === $plan |
| 430 | ? __( 'Your plan expires today', 'jetpack-mu-wpcom' ) |
| 431 | |
| 432 | : sprintf( __( 'Your %s plan expires today', 'jetpack-mu-wpcom' ), $plan ); |
| 433 | } |
| 434 | |
| 435 | return '' === $plan |
| 436 | |
| 437 | ? sprintf( _n( 'Your plan expires in %d day', 'Your plan expires in %d days', $days, 'jetpack-mu-wpcom' ), $days ) |
| 438 | |
| 439 | : sprintf( _n( 'Your %1$s plan expires in %2$d day', 'Your %1$s plan expires in %2$d days', $days, 'jetpack-mu-wpcom' ), $plan, $days ); |
| 440 | } |
| 441 | |
| 442 | |
| 443 | |
| 444 | |
| 445 | |
| 446 | |
| 447 | |
| 448 | |
| 449 | |
| 450 | |
| 451 | function wpcom_expiry_notices_banner_body( array $state, bool $is_owner ): string { |
| 452 | if ( ! $is_owner ) { |
| 453 | return __( 'This plan was purchased by a different WordPress.com account. To manage this plan, log in to that account or contact the account owner.', 'jetpack-mu-wpcom' ); |
| 454 | } |
| 455 | |
| 456 | $storage_gb = Expiry_Data::get_plan_storage_gb( isset( $state['product_slug'] ) ? (string) $state['product_slug'] : '' ); |
| 457 | $days = isset( $state['days_remaining'] ) ? (int) $state['days_remaining'] : 0; |
| 458 | $auto_renew = ! empty( $state['auto_renew'] ); |
| 459 | $stage = $state['state'] ?? ''; |
| 460 | |
| 461 | if ( Expiry_Data::STATE_EXPIRED === $stage ) { |
| 462 | |
| 463 | $with_storage = __( 'Your site has been moved to the Free plan and set to private. You no longer have access to plugins, custom themes, or %d GB of storage. Contact support to get help restoring it.', 'jetpack-mu-wpcom' ); |
| 464 | $without_storage = __( 'Your site has been moved to the Free plan and set to private. You no longer have access to plugins, custom themes, or additional storage. Contact support to get help restoring it.', 'jetpack-mu-wpcom' ); |
| 465 | } elseif ( Expiry_Data::STATE_EXPIRED_GRACE === $stage && $auto_renew ) { |
| 466 | |
| 467 | $with_storage = __( 'If renewal doesn’t go through, your site will move to the Free plan. That means losing plugins, custom themes, and %d GB of storage. But it’s not too late. Renew now to keep your site as it is.', 'jetpack-mu-wpcom' ); |
| 468 | $without_storage = __( 'If renewal doesn’t go through, your site will move to the Free plan. That means losing plugins, custom themes, and additional storage. But it’s not too late. Renew now to keep your site as it is.', 'jetpack-mu-wpcom' ); |
| 469 | } elseif ( Expiry_Data::STATE_EXPIRED_GRACE === $stage ) { |
| 470 | |
| 471 | $with_storage = __( 'Your site will move to the Free plan. That means losing plugins, custom themes, and %d GB of storage. But it’s not too late. Renew now to keep your site as it is.', 'jetpack-mu-wpcom' ); |
| 472 | $without_storage = __( 'Your site will move to the Free plan. That means losing plugins, custom themes, and additional storage. But it’s not too late. Renew now to keep your site as it is.', 'jetpack-mu-wpcom' ); |
| 473 | } elseif ( $auto_renew && $days <= Expiry_Notice_Dismiss::FINAL_WINDOW_DAYS ) { |
| 474 | |
| 475 | $with_storage = __( 'If renewal doesn’t go through, your site will move to the Free plan and you’ll lose plugins, custom themes, and %d GB of storage. Renew now to keep everything in place.', 'jetpack-mu-wpcom' ); |
| 476 | $without_storage = __( 'If renewal doesn’t go through, your site will move to the Free plan and you’ll lose plugins, custom themes, and additional storage. Renew now to keep everything in place.', 'jetpack-mu-wpcom' ); |
| 477 | } elseif ( $auto_renew ) { |
| 478 | |
| 479 | $with_storage = __( 'If renewal doesn’t go through, your site will move to the Free plan, and you’ll lose access to plugins, custom themes, and %d GB of storage.', 'jetpack-mu-wpcom' ); |
| 480 | $without_storage = __( 'If renewal doesn’t go through, your site will move to the Free plan, and you’ll lose access to plugins, custom themes, and additional storage.', 'jetpack-mu-wpcom' ); |
| 481 | } elseif ( $days <= 0 ) { |
| 482 | |
| 483 | $with_storage = __( 'Unless you renew your plan, your site will move to the Free plan, and you’ll lose plugins, custom themes, and %d GB of storage. Renew now to keep everything in place.', 'jetpack-mu-wpcom' ); |
| 484 | $without_storage = __( 'Unless you renew your plan, your site will move to the Free plan, and you’ll lose plugins, custom themes, and additional storage. Renew now to keep everything in place.', 'jetpack-mu-wpcom' ); |
| 485 | } elseif ( $days <= Expiry_Notice_Dismiss::FINAL_WINDOW_DAYS ) { |
| 486 | |
| 487 | $with_storage = __( 'Your site will move to the Free plan and you’ll lose plugins, custom themes, and %d GB of storage. Renew now to keep everything in place.', 'jetpack-mu-wpcom' ); |
| 488 | $without_storage = __( 'Your site will move to the Free plan and you’ll lose plugins, custom themes, and additional storage. Renew now to keep everything in place.', 'jetpack-mu-wpcom' ); |
| 489 | } else { |
| 490 | return wpcom_expiry_notices_early_warning_body( $state, $storage_gb ); |
| 491 | } |
| 492 | |
| 493 | return null === $storage_gb ? $without_storage : sprintf( $with_storage, $storage_gb ); |
| 494 | } |
| 495 | |
| 496 | |
| 497 | |
| 498 | |
| 499 | |
| 500 | |
| 501 | |
| 502 | |
| 503 | function wpcom_expiry_notices_early_warning_body( array $state, ?int $storage_gb ): string { |
| 504 | |
| 505 | |
| 506 | $expiry_date = (string) wp_date( (string) get_option( 'date_format' ), Expiry_Data::start_of_utc_day( (int) $state['expiry_ts'] ) ); |
| 507 | |
| 508 | if ( '' === $expiry_date ) { |
| 509 | return null === $storage_gb |
| 510 | ? __( 'Your site will move to the Free plan, which means you’ll lose access to plugins, custom themes, and additional storage.', 'jetpack-mu-wpcom' ) |
| 511 | |
| 512 | : sprintf( __( 'Your site will move to the Free plan, which means you’ll lose access to plugins, custom themes, and %d GB of storage.', 'jetpack-mu-wpcom' ), $storage_gb ); |
| 513 | } |
| 514 | |
| 515 | return null === $storage_gb |
| 516 | |
| 517 | ? sprintf( __( 'After %s, your site will move to the Free plan, which means you’ll lose access to plugins, custom themes, and additional storage.', 'jetpack-mu-wpcom' ), $expiry_date ) |
| 518 | |
| 519 | : sprintf( __( 'After %1$s, your site will move to the Free plan, which means you’ll lose access to plugins, custom themes, and %2$d GB of storage.', 'jetpack-mu-wpcom' ), $expiry_date, $storage_gb ); |
| 520 | } |
| 521 | |
| 522 | |
| 523 | |
| 524 | |
| 525 | |
| 526 | |
| 527 | |
| 528 | function wpcom_expiry_notices_banner_sentence( array $state, bool $is_owner ): string { |
| 529 | return sprintf( |
| 530 | |
| 531 | __( '%1$s. %2$s', 'jetpack-mu-wpcom' ), |
| 532 | wpcom_expiry_notices_banner_heading( $state ), |
| 533 | wpcom_expiry_notices_banner_body( $state, $is_owner ) |
| 534 | ); |
| 535 | } |
| 536 | |
| 537 | |
| 538 | |
| 539 | |
| 540 | |
| 541 | |
| 542 | |
| 543 | function wpcom_expiry_notices_maybe_load_surfaces() { |
| 544 | if ( ! wpcom_expiry_notices_is_enabled_for_site() ) { |
| 545 | return; |
| 546 | } |
| 547 | if ( is_admin() ) { |
| 548 | require_once __DIR__ . '/admin-banner.php'; |
| 549 | require_once __DIR__ . '/admin-modal.php'; |
| 550 | require_once __DIR__ . '/editor-notice.php'; |
| 551 | } else { |
| 552 | require_once __DIR__ . '/frontend-banner.php'; |
| 553 | } |
| 554 | } |
| 555 | add_action( 'init', 'wpcom_expiry_notices_maybe_load_surfaces' ); |
| 556 | |
| 557 | |
| 558 | |
| 559 | |
| 560 | |
| 561 | |
| 562 | |
| 563 | function wpcom_expiry_notices_frontend_banner_is_due(): bool { |
| 564 | if ( is_admin() || is_customize_preview() || ! wpcom_expiry_notices_is_enabled_for_site() ) { |
| 565 | return false; |
| 566 | } |
| 567 | return null !== wpcom_expiry_notices_banner_data(); |
| 568 | } |
| 569 | |
| 570 | |
| 571 | |
| 572 | |
| 573 | |
| 574 | |
| 575 | |
| 576 | |
| 577 | |
| 578 | |
| 579 | function wpcom_expiry_notices_claim_wpcom_banner_slot( $banners ) { |
| 580 | if ( ! is_array( $banners ) || ! wpcom_expiry_notices_frontend_banner_is_due() ) { |
| 581 | return $banners; |
| 582 | } |
| 583 | return array( 'wpcom_expiry_banner' => '__return_null' ); |
| 584 | } |
| 585 | add_filter( 'wpcom_register_banners', 'wpcom_expiry_notices_claim_wpcom_banner_slot', PHP_INT_MAX ); |
| 586 | |
| 587 | |
| 588 | |
| 589 | |
| 590 | function wpcom_expiry_notices_register_meta() { |
| 591 | if ( ! is_admin() && ! ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { |
| 592 | return; |
| 593 | } |
| 594 | if ( ! wpcom_expiry_notices_is_enabled_for_site() ) { |
| 595 | return; |
| 596 | } |
| 597 | Expiry_Notice_Dismiss::register_user_meta(); |
| 598 | } |
| 599 | add_action( 'init', 'wpcom_expiry_notices_register_meta' ); |
| 600 | |
| 601 | |
| 602 | |
| 603 | add_action( 'rest_api_init', 'wpcom_expiry_notices_register_meta' ); |
| 604 | |
| 605 | |
| 606 | |
| 607 | |
| 608 | |
| 609 | |
| 610 | |
| 611 | |
| 612 | |
| 613 | |
| 614 | |
| 615 | function wpcom_expiry_notices_register_meta_for_request( $response ) { |
| 616 | wpcom_expiry_notices_register_meta(); |
| 617 | return $response; |
| 618 | } |
| 619 | add_filter( 'rest_request_before_callbacks', 'wpcom_expiry_notices_register_meta_for_request' ); |
| 620 | |
| 621 | |
| 622 | |
| 623 | |
| 624 | |
| 625 | |
| 626 | |
| 627 | |
| 628 | |
| 629 | |
| 630 | |
| 631 | |
| 632 | function wpcom_expiry_notices_dismiss( string $meta_key, int $user_id ): array { |
| 633 | if ( ! wpcom_expiry_notices_is_enabled_for_site() || ! user_can( $user_id, 'manage_options' ) ) { |
| 634 | return array( |
| 635 | 'status' => 403, |
| 636 | 'body' => array( 'message' => 'forbidden' ), |
| 637 | ); |
| 638 | } |
| 639 | if ( ! Expiry_Notice_Dismiss::dismiss( $user_id, $meta_key ) ) { |
| 640 | return array( |
| 641 | 'status' => 400, |
| 642 | 'body' => array( 'message' => 'unknown notice' ), |
| 643 | ); |
| 644 | } |
| 645 | return array( |
| 646 | 'status' => 200, |
| 647 | 'body' => array(), |
| 648 | ); |
| 649 | } |
| 650 | |
| 651 | |
| 652 | |
| 653 | |
| 654 | function wpcom_expiry_notices_ajax_dismiss(): void { |
| 655 | check_ajax_referer( 'wpcom_expiry_notice_dismiss' ); |
| 656 | $meta_key = isset( $_POST['metaKey'] ) ? sanitize_text_field( wp_unslash( $_POST['metaKey'] ) ) : ''; |
| 657 | $result = wpcom_expiry_notices_dismiss( $meta_key, get_current_user_id() ); |
| 658 | $flags = JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_HEX_APOS; |
| 659 | if ( 200 !== $result['status'] ) { |
| 660 | wp_send_json_error( $result['body'], $result['status'], $flags ); |
| 661 | } |
| 662 | wp_send_json_success( $result['body'], $result['status'], $flags ); |
| 663 | } |
| 664 | add_action( 'wp_ajax_wpcom_expiry_notice_dismiss', 'wpcom_expiry_notices_ajax_dismiss' ); |
| 665 | |
| 666 | |
| 667 | |
| 668 | |
| 669 | |
| 670 | |
| 671 | |
| 672 | function wpcom_expiry_notices_current_url(): string { |
| 673 | $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; |
| 674 | $request_uri = remove_query_arg( wp_removable_query_args(), $request_uri ); |
| 675 | |
| 676 | if ( is_admin() ) { |
| 677 | $admin_path = (string) wp_parse_url( admin_url(), PHP_URL_PATH ); |
| 678 | return 0 === strpos( $request_uri, $admin_path ) |
| 679 | ? admin_url( substr( $request_uri, strlen( $admin_path ) ) ) |
| 680 | : admin_url(); |
| 681 | } |
| 682 | return home_url( '' === $request_uri ? '/' : $request_uri ); |
| 683 | } |