PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.5
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.5
16.3-beta 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 All 507 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.5, at jetpack_vendor/automattic/jetpack-premium-analytics/src/default-dashboard-sections.php

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