PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.1-beta.3
Jetpack – WP Security, Backup, Speed, & Growth v16.1-beta.3
16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / jetpack_vendor / automattic / jetpack-premium-analytics / src / widget-availability.php
jetpack / jetpack_vendor / automattic / jetpack-premium-analytics / src Last commit date
REST 3 weeks ago Reports 3 weeks ago Sync 3 weeks ago class-analytics.php 3 weeks ago class-capabilities.php 3 weeks ago class-connection-configuration.php 3 weeks ago class-dashboard-section-registry.php 3 weeks ago class-dashboard-section.php 3 weeks ago class-dashboard-support-routes.php 3 weeks ago class-jetpack-stats-tracker.php 3 weeks ago class-notices.php 3 weeks ago class-widget-type-registry.php 3 weeks ago class-widget-type.php 3 weeks ago class-woocommerce-analytics-tracker.php 3 weeks ago csv-exports.php 3 weeks ago dashboard-grammar.php 3 weeks ago dashboard-layout.php 3 weeks ago dashboard-sections.php 3 weeks ago rest-namespace.php 3 weeks ago widget-availability.php 3 weeks ago widget-i18n.json 3 weeks ago widget-modules.php 3 weeks ago widget-type-support.php 3 weeks ago widget-types.php 3 weeks ago
widget-availability.php
215 lines
1 <?php
2 /**
3 * Widget availability policy (consumer layer).
4 *
5 * Premium Analytics' policy over the neutral filters in widget-types.php:
6 * availability is the consumer's job, core only offers the hooks.
7 *
8 * Policies are hooked on the registry-time filter (a hard hide, which keeps
9 * every registry consumer correct without a filtered accessor): developer-only
10 * widget types are never registered in production, Simple-only types are only
11 * registered on WPCOM Simple, and commerce categories require their plugins.
12 *
13 * @package automattic/jetpack-premium-analytics
14 */
15
16 namespace Automattic\Jetpack\PremiumAnalytics;
17
18 require_once __DIR__ . '/widget-types.php';
19 require_once __DIR__ . '/widget-type-support.php';
20
21 /**
22 * Widget categories that are only meaningful with WooCommerce active.
23 */
24 const WOOCOMMERCE_WIDGET_CATEGORIES = array( 'store', 'orders', 'coupons' );
25
26 /**
27 * Widget categories that are only meaningful with WooCommerce Bookings active.
28 *
29 * Checked independently of WOOCOMMERCE_WIDGET_CATEGORIES: the Bookings
30 * extension cannot run without WooCommerce, so its presence implies both.
31 */
32 const WOOCOMMERCE_BOOKINGS_WIDGET_CATEGORIES = array( 'bookings' );
33
34 /**
35 * Widget categories whose data counts as a store report.
36 *
37 * The membership rule is the data source, not the subject matter: every
38 * category here reaches WPCOM through the proxy's `analytics` prefix, which
39 * {@see \Automattic\Jetpack\PremiumAnalytics\REST\Api_Proxy_Controller} gates
40 * on `view_woocommerce_reports`. That is why `visitors` is in the list: its
41 * widgets read `sessions/…` from the same prefix.
42 */
43 const STORE_REPORT_WIDGET_CATEGORIES = array( 'store', 'orders', 'coupons', 'bookings', 'visitors' );
44
45 /**
46 * Removes developer-only candidates in production.
47 *
48 * Split from the hook callback so both branches are testable without touching
49 * the global environment.
50 *
51 * @param array $widget_candidates Manifest candidates, each with a `name` and `category`.
52 * @param string $environment Site environment type.
53 * @return array The candidates, minus developer-only types in production.
54 */
55 function remove_dev_only_widget_types( $widget_candidates, $environment ) {
56 if ( 'production' !== $environment ) {
57 return $widget_candidates;
58 }
59
60 return array_values(
61 array_filter(
62 $widget_candidates,
63 static function ( $widget ) {
64 return 'developer' !== ( $widget['category'] ?? '' );
65 }
66 )
67 );
68 }
69
70 /**
71 * Registry-time callback: hides developer-only types in production.
72 *
73 * Defaults to `production`; a site opts in via `WP_ENVIRONMENT_TYPE`
74 * (`local`, `development`, `staging`).
75 *
76 * @param array $widget_candidates Manifest candidates.
77 * @return array The candidates, minus developer-only types in production.
78 */
79 function filter_registrable_widget_types_by_environment( $widget_candidates ) {
80 return remove_dev_only_widget_types( $widget_candidates, wp_get_environment_type() );
81 }
82
83 add_filter( REGISTRABLE_WIDGET_TYPES_FILTER, __NAMESPACE__ . '\\filter_registrable_widget_types_by_environment' );
84
85 /**
86 * Applies shared type-level availability at registry time.
87 *
88 * @param array $widget_candidates Manifest candidates.
89 * @return array Filtered candidates.
90 */
91 function filter_registrable_widget_types_by_availability( $widget_candidates ) {
92 return remove_unsupported_widget_items(
93 $widget_candidates,
94 'name',
95 get_widget_support_context()
96 );
97 }
98
99 add_filter( REGISTRABLE_WIDGET_TYPES_FILTER, __NAMESPACE__ . '\\filter_registrable_widget_types_by_availability' );
100
101 /**
102 * Removes candidates whose commerce category lacks its backing plugin.
103 *
104 * Split from the hook callback so the branches are testable without touching
105 * global plugin state.
106 *
107 * @param array $widget_candidates Manifest candidates, each with a `category`.
108 * @param bool $woocommerce_available Whether WooCommerce is available.
109 * @param bool $bookings_available Whether WooCommerce Bookings is available.
110 * @return array The candidates, minus commerce categories missing their plugin.
111 */
112 function remove_plugin_gated_widget_types( $widget_candidates, $woocommerce_available, $bookings_available ) {
113 return array_values(
114 array_filter(
115 $widget_candidates,
116 static function ( $widget ) use ( $woocommerce_available, $bookings_available ) {
117 $category = $widget['category'] ?? '';
118
119 if ( ! $woocommerce_available && in_array( $category, WOOCOMMERCE_WIDGET_CATEGORIES, true ) ) {
120 return false;
121 }
122
123 if ( ! $bookings_available && in_array( $category, WOOCOMMERCE_BOOKINGS_WIDGET_CATEGORIES, true ) ) {
124 return false;
125 }
126
127 return true;
128 }
129 )
130 );
131 }
132
133 /**
134 * Whether the WooCommerce Bookings extension is active.
135 *
136 * Mirrors the detection in woocommerce-analytics' Bookings sync module;
137 * `is_plugin_active()` only exists in admin contexts, hence the guard.
138 *
139 * @return bool Whether WooCommerce Bookings was detected in the current request.
140 */
141 function is_bookings_plugin_active() {
142 return class_exists( 'WC_Bookings' )
143 || ( function_exists( 'is_plugin_active' ) && \is_plugin_active( 'woocommerce-bookings/woocommerce-bookings.php' ) );
144 }
145
146 /**
147 * Registry-time callback: hides commerce widget categories without their plugin.
148 *
149 * WooCommerce availability is read through the store section's signal
150 * (dashboard-sections.php, including its availability filter) so section and
151 * widgets can't disagree — a consumer overriding the section filter gets
152 * matching widget types. Both dashboard entry points load
153 * dashboard-sections.php before the widget registry can hydrate, so the
154 * function is always defined by the time this callback runs.
155 *
156 * @param array $widget_candidates Manifest candidates.
157 * @return array The candidates, minus commerce categories missing their plugin.
158 */
159 function filter_registrable_widget_types_by_plugin( $widget_candidates ) {
160 return remove_plugin_gated_widget_types(
161 $widget_candidates,
162 is_woocommerce_dashboard_section_available(),
163 is_bookings_plugin_active()
164 );
165 }
166
167 add_filter( REGISTRABLE_WIDGET_TYPES_FILTER, __NAMESPACE__ . '\\filter_registrable_widget_types_by_plugin' );
168
169 /**
170 * Removes candidates the reader could not load data for anyway.
171 *
172 * Split from the hook callback so both branches are testable without a user.
173 *
174 * @since 0.1.0
175 *
176 * @param array $widget_candidates Manifest candidates, each with a `category`.
177 * @param bool $can_view_store_reports Whether the reader may see the store reports.
178 * @return array The candidates, minus the store-report categories for readers who can't.
179 */
180 function remove_capability_gated_widget_types( $widget_candidates, $can_view_store_reports ) {
181 if ( $can_view_store_reports ) {
182 return $widget_candidates;
183 }
184
185 return array_values(
186 array_filter(
187 $widget_candidates,
188 static function ( $widget ) {
189 return ! in_array( $widget['category'] ?? '', STORE_REPORT_WIDGET_CATEGORIES, true );
190 }
191 )
192 );
193 }
194
195 /**
196 * Registry-time callback: hides widgets whose data the reader cannot fetch.
197 *
198 * A `view_stats` reader reaching one of them would only collect 403s from the
199 * proxy's `analytics` prefix, so the types are never registered for them. The
200 * registry is request-scoped, so filtering on the current user is safe here.
201 *
202 * @since 0.1.0
203 *
204 * @param array $widget_candidates Manifest candidates.
205 * @return array The candidates, minus the store-report categories for readers who can't see them.
206 */
207 function filter_registrable_widget_types_by_capability( $widget_candidates ) {
208 return remove_capability_gated_widget_types(
209 $widget_candidates,
210 Capabilities::current_user_can_view_store_reports()
211 );
212 }
213
214 add_filter( REGISTRABLE_WIDGET_TYPES_FILTER, __NAMESPACE__ . '\\filter_registrable_widget_types_by_capability' );
215