PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.7
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.7
16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 All 506 releases
jetpack / jetpack_vendor / automattic / jetpack-premium-analytics / src / default-dashboard-sections.php

default-dashboard-sections.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-a.7, at jetpack_vendor/automattic/jetpack-premium-analytics/src/default-dashboard-sections.php

496 lines 13.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The package's own dashboard sections: the built-in tabs, their availability gates and default
4 * layouts, and the filters over those gates. They register through the section API in
5 * dashboard-sections.php, the same way a plugin extending the dashboard does; the Ads tab is
6 * one such plugin section, registered by the WordAds module and by WordPress.com.
7 *
8 * @package automattic/jetpack-premium-analytics
9 */
10
11 namespace Automattic\Jetpack\PremiumAnalytics;
12
13 use Automattic\Jetpack\Modules;
14
15 // Guarded on a symbol the file declares, so a second copy of the package can't
16 // redeclare it. See the include block in Analytics::load_dashboard_components().
17 if ( ! function_exists( __NAMESPACE__ . '\\register_dashboard_section' ) ) {
18 require_once __DIR__ . '/dashboard-sections.php';
19 }
20
21 /**
22 * Filter through which WooCommerce section availability is resolved.
23 */
24 const WOOCOMMERCE_DASHBOARD_SECTION_AVAILABLE_FILTER = 'jetpack_premium_analytics_woocommerce_dashboard_section_available';
25
26 /**
27 * Filter through which Subscribers section availability is resolved.
28 */
29 const SUBSCRIBERS_DASHBOARD_SECTION_AVAILABLE_FILTER = 'jetpack_premium_analytics_subscribers_dashboard_section_available';
30
31 /**
32 * Whether the WooCommerce dashboard section should be exposed.
33 *
34 * @return bool True when WooCommerce is active.
35 */
36 function is_woocommerce_dashboard_section_available() {
37 $is_available = class_exists( 'WooCommerce' ) || function_exists( 'WC' );
38
39 /**
40 * Filters whether the WooCommerce dashboard section is available.
41 *
42 * @param bool $is_available Whether WooCommerce was detected in the current request.
43 */
44 return (bool) apply_filters( WOOCOMMERCE_DASHBOARD_SECTION_AVAILABLE_FILTER, $is_available );
45 }
46
47 /**
48 * Whether the current user should be shown the WooCommerce dashboard section.
49 *
50 * The sibling is_woocommerce_dashboard_section_available() answers "is
51 * WooCommerce here"; this adds "and may this reader see store data".
52 *
53 * @since 0.1.0
54 *
55 * @return bool
56 */
57 function is_woocommerce_dashboard_section_available_to_current_user() {
58 return is_woocommerce_dashboard_section_available() && Capabilities::current_user_can_view_store_reports();
59 }
60
61 /**
62 * Whether the Store dashboard section should be exposed.
63 *
64 * The site's own opt-in needs the Store flag; the blog sticker and the
65 * `jetpack_premium_analytics_enabled` filter leave the option off and keep every section.
66 *
67 * @since 0.10.0
68 *
69 * @return bool
70 */
71 function is_store_dashboard_section_available() {
72 // An older copy of the package may have loaded dashboard-policy.php without the flag.
73 $is_enabled = ! get_option( Enablement_Setting::ENABLED_OPTION )
74 || ( function_exists( __NAMESPACE__ . '\\is_dashboard_store_section_enabled' ) && is_dashboard_store_section_enabled() );
75
76 return $is_enabled && is_woocommerce_dashboard_section_available_to_current_user();
77 }
78
79 /**
80 * Whether the Subscribers dashboard section should be exposed.
81 *
82 * Sites without Jetpack have no module state to check, so the section remains
83 * available. Modules::is_active() also returns true on WPCOM Simple.
84 *
85 * @since 0.3.0
86 *
87 * @return bool True when the subscriptions module is active.
88 */
89 function is_subscribers_dashboard_section_available() {
90 $is_available = ! class_exists( 'Jetpack' ) || ( new Modules() )->is_active( 'subscriptions' );
91
92 /**
93 * Filters whether the Subscribers dashboard section is available.
94 *
95 * @since 0.3.0
96 *
97 * @param bool $is_available Whether the subscriptions module was detected in the current request.
98 */
99 return (bool) apply_filters( SUBSCRIBERS_DASHBOARD_SECTION_AVAILABLE_FILTER, $is_available );
100 }
101
102 /**
103 * The Traffic tab's default widget layout.
104 *
105 * @return array Widget instances.
106 */
107 function get_traffic_section_default_layout() {
108 return array(
109 // Rows fill the three-column grid in the prototype's order. Plan usage
110 // is intentionally not a default; it stays available from the widget
111 // picker.
112 // Row 1: traffic chart.
113 get_dashboard_default_widget_instance(
114 'default-traffic-chart-widget-instance',
115 'jpa/traffic-chart',
116 0,
117 3,
118 2
119 ),
120 // Row 2: most-viewed posts + referrers + devices.
121 get_dashboard_default_widget_instance(
122 'default-stats-top-posts-widget-instance',
123 'jpa/stats-top-posts',
124 1,
125 1,
126 2
127 ),
128 get_dashboard_default_widget_instance(
129 'default-referrers-widget-instance',
130 'jpa/referrers',
131 2,
132 1,
133 2
134 ),
135 get_dashboard_default_widget_instance(
136 'default-devices-widget-instance',
137 'jpa/devices',
138 3,
139 1,
140 2
141 ),
142 // Row 3: locations map + top platforms.
143 get_dashboard_default_widget_instance(
144 'default-locations-widget-instance',
145 'jpa/locations',
146 4,
147 2,
148 2
149 ),
150 get_dashboard_default_widget_instance(
151 'default-top-platforms-widget-instance',
152 'jpa/top-platforms',
153 5,
154 1,
155 2
156 ),
157 // Row 4: UTM insights + clicks + VideoPress (sites running VideoPress only).
158 get_dashboard_default_widget_instance(
159 'default-utm-insights-widget-instance',
160 'jpa/utm-insights',
161 6,
162 1,
163 2,
164 array(
165 'utmDimension' => 'utm_source,utm_medium',
166 )
167 ),
168 get_dashboard_default_widget_instance(
169 'default-clicks-widget-instance',
170 'jpa/clicks',
171 7,
172 1,
173 2
174 ),
175 get_dashboard_default_widget_instance(
176 'default-videopress-widget-instance',
177 'jpa/videopress',
178 8,
179 1,
180 2
181 ),
182 // Row 5: authors + search terms + file downloads (Simple only).
183 get_dashboard_default_widget_instance(
184 'default-authors-widget-instance',
185 'jpa/authors',
186 9,
187 1,
188 2
189 ),
190 get_dashboard_default_widget_instance(
191 'default-search-terms-widget-instance',
192 'jpa/search-terms',
193 10,
194 1,
195 2
196 ),
197 get_dashboard_default_widget_instance(
198 'default-file-downloads-widget-instance',
199 'jpa/file-downloads',
200 11,
201 1,
202 2
203 ),
204 );
205 }
206
207 /**
208 * The Insights tab's default widget layout.
209 *
210 * @return array Widget instances.
211 */
212 function get_insights_section_default_layout() {
213 return array(
214 // Rows follow the design (WOOA7S-2009); Emails lives on the Subscribers tab.
215 // Row 1: highlights banner.
216 get_dashboard_default_widget_instance(
217 'default-annual-highlights-widget-instance',
218 'jpa/annual-highlights',
219 0,
220 3,
221 1
222 ),
223 // Row 2: at-a-glance cards. Two rows tall: their display-sized figures overflow a 200px tile.
224 get_dashboard_default_widget_instance(
225 'default-all-time-stats-widget-instance',
226 'jpa/all-time-stats',
227 1,
228 1,
229 2
230 ),
231 get_dashboard_default_widget_instance(
232 'default-most-popular-time-widget-instance',
233 'jpa/most-popular-time',
234 2,
235 1,
236 2
237 ),
238 get_dashboard_default_widget_instance(
239 'default-most-popular-day-widget-instance',
240 'jpa/most-popular-day',
241 3,
242 1,
243 2
244 ),
245 // Row 3: the two post spotlights.
246 get_dashboard_default_widget_instance(
247 'default-popular-post-widget-instance',
248 'jpa/popular-post',
249 4,
250 2,
251 2
252 ),
253 get_dashboard_default_widget_instance(
254 'default-latest-post-widget-instance',
255 'jpa/latest-post',
256 5,
257 1,
258 2
259 ),
260 // Row 4: posting-activity heatmap.
261 get_dashboard_default_widget_instance(
262 'default-posting-activity-widget-instance',
263 'jpa/posting-activity',
264 6,
265 3,
266 1
267 ),
268 // Row 5: the all-time views table, one row per year. Two rows tall so a
269 // few years fit before the grid scrolls.
270 get_dashboard_default_widget_instance(
271 'default-views-over-years-widget-instance',
272 'jpa/views-over-years',
273 7,
274 3,
275 2
276 ),
277 // Row 6: tags + most commented posts.
278 get_dashboard_default_widget_instance(
279 'default-tags-widget-instance',
280 'jpa/tags',
281 8,
282 2,
283 2
284 ),
285 get_dashboard_default_widget_instance(
286 'default-most-commented-posts-widget-instance',
287 'jpa/most-commented-posts',
288 9,
289 1,
290 2
291 ),
292 // Row 7: shares + most commented authors.
293 get_dashboard_default_widget_instance(
294 'default-shares-widget-instance',
295 'jpa/shares',
296 10,
297 1,
298 2
299 ),
300 get_dashboard_default_widget_instance(
301 'default-most-commented-authors-widget-instance',
302 'jpa/most-commented-authors',
303 11,
304 2,
305 2
306 ),
307 );
308 }
309
310 /**
311 * The Subscribers tab's default widget layout.
312 *
313 * @return array Widget instances.
314 */
315 function get_subscribers_section_default_layout() {
316 return array(
317 // Row 1: subscribers chart.
318 get_dashboard_default_widget_instance(
319 'default-subscribers-chart-widget-instance',
320 'jpa/subscribers-chart',
321 0,
322 3,
323 2
324 ),
325 // Row 2: subscriber highlights.
326 get_dashboard_default_widget_instance(
327 'default-subscriber-highlights-widget-instance',
328 'jpa/subscriber-highlights',
329 1,
330 3,
331 1
332 ),
333 // Row 3: latest subscribers + the wider latest emails sent table.
334 get_dashboard_default_widget_instance(
335 'default-subscribers-list-widget-instance',
336 'jpa/subscribers-list',
337 2,
338 1,
339 2
340 ),
341 get_dashboard_default_widget_instance(
342 'default-subscribers-emails-widget-instance',
343 'jpa/stats-emails',
344 3,
345 2,
346 2,
347 array(
348 'metric' => 'opens',
349 )
350 ),
351 );
352 }
353
354 /**
355 * The Store tab's default widget layout.
356 *
357 * @return array Widget instances.
358 */
359 function get_store_section_default_layout() {
360 return array(
361 get_dashboard_default_widget_instance(
362 'default-store-performance-widget-instance',
363 'jpa/store-performance',
364 0,
365 2,
366 1
367 ),
368 get_dashboard_default_widget_instance(
369 'default-total-sales-over-time-widget-instance',
370 'jpa/total-sales-over-time',
371 1,
372 1,
373 1
374 ),
375 get_dashboard_default_widget_instance(
376 'default-conversion-rate-widget-instance',
377 'jpa/conversion-rate',
378 2,
379 1,
380 1
381 ),
382 get_dashboard_default_widget_instance(
383 'default-orders-over-time-widget-instance',
384 'jpa/orders-over-time',
385 3,
386 1,
387 1
388 ),
389 get_dashboard_default_widget_instance(
390 'default-average-order-value-widget-instance',
391 'jpa/average-order-value',
392 4,
393 1,
394 1
395 ),
396 get_dashboard_default_widget_instance(
397 'default-top-performing-products-widget-instance',
398 'jpa/top-performing-products',
399 5,
400 1,
401 1
402 ),
403 get_dashboard_default_widget_instance(
404 'default-new-vs-returning-customer-widget-instance',
405 'jpa/new-vs-returning-customer',
406 6,
407 1,
408 1
409 ),
410 get_dashboard_default_widget_instance(
411 'default-payment-status-widget-instance',
412 'jpa/payment-status',
413 7,
414 1,
415 1
416 ),
417 get_dashboard_default_widget_instance(
418 'default-orders-fulfillment-widget-instance',
419 'jpa/orders-fulfillment',
420 8,
421 1,
422 1
423 ),
424 );
425 }
426
427 /**
428 * Registers the default Premium Analytics dashboard sections.
429 *
430 * Hooked on the registration action and safe to call directly: a section already registered
431 * is skipped.
432 *
433 * @param Dashboard_Section_Registry|null $registry Optional. The registry being hydrated. Defaults to the main instance.
434 * @return void
435 */
436 function register_default_dashboard_sections( $registry = null ) {
437 if ( ! $registry instanceof Dashboard_Section_Registry ) {
438 $registry = Dashboard_Section_Registry::get_instance();
439 }
440
441 $sections = array(
442 'analytics/traffic' => array(
443 'label' => __( 'Traffic', 'jetpack-premium-analytics-pkg' ),
444 'title' => __( 'Site traffic', 'jetpack-premium-analytics-pkg' ),
445 'order' => 10,
446 'default_layout' => __NAMESPACE__ . '\\get_traffic_section_default_layout',
447 ),
448 'analytics/insights' => array(
449 'label' => __( 'Insights', 'jetpack-premium-analytics-pkg' ),
450 'title' => __( 'Site insights', 'jetpack-premium-analytics-pkg' ),
451 'order' => 20,
452 // Insights reads whole history: all time and single years, with nothing
453 // to compare them against. Most widgets have fixed periods of their own,
454 // so no header control; Highlights hosts the only year control.
455 'date_filter' => Dashboard_Section::DATE_FILTER_YEAR,
456 'date_filter_options' => array(
457 'with_date_comparison' => false,
458 'with_header_date_control' => false,
459 ),
460 'default_layout' => __NAMESPACE__ . '\\get_insights_section_default_layout',
461 ),
462 'analytics/subscribers' => array(
463 'label' => __( 'Subscribers', 'jetpack-premium-analytics-pkg' ),
464 'title' => __( 'Subscribers stats', 'jetpack-premium-analytics-pkg' ),
465 'order' => 30,
466 'is_available' => __NAMESPACE__ . '\\is_subscribers_dashboard_section_available',
467 // Only the summary chart supports dates, so it owns the control. No
468 // Subscribers widget supports comparison.
469 'date_filter_options' => array(
470 'with_date_comparison' => false,
471 'with_header_date_control' => false,
472 ),
473 'default_layout' => __NAMESPACE__ . '\\get_subscribers_section_default_layout',
474 ),
475 // Store registers no heading of its own, so it falls back to the label.
476 'woocommerce/store' => array(
477 'label' => __( 'Store', 'jetpack-premium-analytics-pkg' ),
478 'order' => 40,
479 'is_available' => __NAMESPACE__ . '\\is_store_dashboard_section_available',
480 // Nothing backfills historical orders to WordPress.com but the analytics
481 // full sync. The site sections above read data it already holds.
482 'requires_sync' => true,
483 'default_layout' => __NAMESPACE__ . '\\get_store_section_default_layout',
484 ),
485 );
486
487 foreach ( $sections as $id => $args ) {
488 if ( ! $registry->is_registered( DASHBOARD_NAME, $id ) ) {
489 $registry->register( DASHBOARD_NAME, $id, $args );
490 }
491 }
492 }
493
494 // Registered when the registry hydrates, through the same action a plugin extending the dashboard uses.
495 add_action( Dashboard_Section_Registry::REGISTER_ACTION, __NAMESPACE__ . '\\register_default_dashboard_sections' );
496