PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.9.8
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.9.8
1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 All 34 releases
desktop-mode / includes / plugin-notices.php

plugin-notices.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.9.8, at includes/plugin-notices.php

142 lines 4.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * A small, opt-in allowlist of well-known *library* admin notices that render
4 * globally (so they repeat in every desktop window) and can be re-derived from
5 * authoritative state. Unlike arbitrary plugin `admin_notices` — which we
6 * deliberately leave alone — these are shared
7 * libraries bundled across many plugins, common enough to warrant a targeted
8 * case. Each entry is detached in-window and surfaced once in the shell, the
9 * same pattern as the core notices.
10 *
11 * @package DesktopMode
12 */
13
14 defined( 'ABSPATH' ) || exit;
15
16 /**
17 * The allowlisted plugin/library notices for the current user, as shell
18 * descriptors (same shape as `desktop_mode_get_core_notices()`).
19 *
20 * @return array<int,array{id:string,title:string,message:string,actionLabel:string,actionUrl:string}>
21 */
22 function desktop_mode_get_plugin_notices() {
23 $builders = array(
24 'desktop_mode_plugin_notice_action_scheduler',
25 );
26
27 $notices = array();
28 foreach ( $builders as $builder ) {
29 $notice = $builder();
30 if ( $notice ) {
31 $notices[] = $notice;
32 }
33 }
34
35 /**
36 * Filters the allowlisted plugin/library notices surfaced once in the
37 * desktop shell. Return an empty array to suppress them all, or unset
38 * individual entries by `id`.
39 *
40 * @param array $notices List of notice descriptors.
41 */
42 return apply_filters( 'desktop_mode_plugin_notices', $notices );
43 }
44
45 /**
46 * Action Scheduler's "N past-due actions found" warning — bundled by
47 * WooCommerce, Jetpack, and many other plugins, and printed globally on
48 * `admin_notices` (with no throttle while past-due actions exist, so it
49 * repeats in every window). Re-derived here from Action Scheduler's own store,
50 * mirroring `ActionScheduler_AdminView::check_pastdue_actions()` including its
51 * filters, so the count matches what Action Scheduler would show.
52 *
53 * @return array|null
54 */
55 function desktop_mode_plugin_notice_action_scheduler() {
56 if ( ! class_exists( 'ActionScheduler_Store' ) || ! function_exists( 'as_get_datetime_object' ) ) {
57 return null;
58 }
59
60 // Capability gate — mirrors `action_scheduler_check_pastdue_actions`.
61 if ( ! apply_filters( 'action_scheduler_check_pastdue_actions', current_user_can( 'manage_options' ) ) ) {
62 return null;
63 }
64
65 $threshold_seconds = (int) apply_filters( 'action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS );
66 $threshold_min = (int) apply_filters( 'action_scheduler_pastdue_actions_min', 1 );
67
68 // A third party can preempt Action Scheduler's own check; when it does the
69 // count is opaque, so mirror Action Scheduler and don't surface.
70 if ( ! is_null( apply_filters( 'action_scheduler_pastdue_actions_check_pre', null ) ) ) {
71 return null;
72 }
73
74 $query_args = array(
75 'date' => as_get_datetime_object( time() - $threshold_seconds ),
76 'status' => ActionScheduler_Store::STATUS_PENDING,
77 'per_page' => $threshold_min,
78 );
79
80 $count = (int) ActionScheduler_Store::instance()->query_actions( $query_args, 'count' );
81
82 $check = (bool) apply_filters(
83 'action_scheduler_pastdue_actions_check',
84 $count >= $threshold_min,
85 $count,
86 $threshold_seconds,
87 $threshold_min
88 );
89 if ( ! $check ) {
90 return null;
91 }
92
93 $url = add_query_arg(
94 array(
95 'page' => 'action-scheduler',
96 'status' => 'past-due',
97 'order' => 'asc',
98 ),
99 admin_url( 'tools.php' )
100 );
101
102 return array(
103 'id' => 'action-scheduler-pastdue',
104 'title' => __( 'Scheduled Actions', 'desktop-mode' ),
105 'message' => sprintf(
106 /* translators: %d: number of past-due scheduled actions. */
107 _n(
108 'Action Scheduler: %d past-due action found; something may be wrong.',
109 'Action Scheduler: %d past-due actions found; something may be wrong.',
110 $count,
111 'desktop-mode'
112 ),
113 $count
114 ),
115 'actionLabel' => __( 'View actions', 'desktop-mode' ),
116 'actionUrl' => $url,
117 );
118 }
119
120 /**
121 * Detaches the allowlisted plugin/library notices inside chromeless iframes so
122 * they don't repeat in every window — the shell surfaces each once (see
123 * `desktop_mode_get_plugin_notices()`).
124 */
125 function desktop_mode_chromeless_suppress_plugin_notices() {
126 if ( ! desktop_mode_is_chromeless_request() ) {
127 return;
128 }
129
130 // Action Scheduler registers the notice as an instance method on its
131 // `ActionScheduler_AdminView` singleton (during `init`, before this runs).
132 // Detect the actual priority it registered at rather than assuming 10.
133 if ( class_exists( 'ActionScheduler_AdminView' ) ) {
134 $callback = array( ActionScheduler_AdminView::instance(), 'maybe_check_pastdue_actions' );
135 $priority = has_action( 'admin_notices', $callback );
136 if ( false !== $priority ) {
137 remove_action( 'admin_notices', $callback, $priority );
138 }
139 }
140 }
141 add_action( 'admin_init', 'desktop_mode_chromeless_suppress_plugin_notices' );
142