PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.3-beta
16.3 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 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-premium-analytics/src/class-dashboard-section.php +284 -0 16.2-beta → 16.3-beta View file →
@@ -1,0 +1,284 @@
1 +<?php
2 +/**
3 + * Dashboard Sections API: Dashboard_Section class.
4 + *
5 + * @package automattic/jetpack-premium-analytics
6 + */
7 +
8 +namespace Automattic\Jetpack\PremiumAnalytics;
9 +
10 +/**
11 + * Represents a dashboard section.
12 + *
13 + * The server-owned model behind a top-level dashboard tab.
14 + */
15 +final class Dashboard_Section {
16 +
17 + /**
18 + * Date-filter surface offering the rolling date-range picker (today, last 7
19 + * days, a custom range, …) plus the comparison control. The default.
20 + *
21 + * @since 0.2.0
22 + * @var string
23 + */
24 + const DATE_FILTER_RANGE = 'range';
25 +
26 + /**
27 + * Date-filter surface offering all time plus one entry per calendar year,
28 + * for sections whose data is read as whole history rather than as a
29 + * rolling window.
30 + *
31 + * @since 0.2.0
32 + * @var string
33 + */
34 + const DATE_FILTER_YEAR = 'year';
35 +
36 + /**
37 + * Date-filter surfaces a section may declare.
38 + *
39 + * @since 0.2.0
40 + * @var string[]
41 + */
42 + const DATE_FILTERS = array( self::DATE_FILTER_RANGE, self::DATE_FILTER_YEAR );
43 +
44 + /**
45 + * Dashboard identifier.
46 + *
47 + * @var string
48 + */
49 + public $dashboard_name;
50 +
51 + /**
52 + * Section identifier.
53 + *
54 + * @var string
55 + */
56 + public $id;
57 +
58 + /**
59 + * URL-facing section slug, derived from the identifier.
60 + *
61 + * @var string
62 + */
63 + public $slug;
64 +
65 + /**
66 + * Display label, naming the section's tab.
67 + *
68 + * @var string
69 + */
70 + public $label;
71 +
72 + /**
73 + * Section heading, deliberately distinct from the tab label: the tab reads
74 + * `Traffic` where the heading reads `Site traffic`. Null falls back to the label.
75 + *
76 + * @since 0.3.0
77 + * @var string|null
78 + */
79 + public $title = null;
80 +
81 + /**
82 + * Sort order.
83 + *
84 + * @var int
85 + */
86 + public $order = 10;
87 +
88 + /**
89 + * Which shape the section's date filter takes, as one of self::DATE_FILTERS.
90 + *
91 + * Shape only. Where it renders and what it supports are
92 + * self::$date_filter_options.
93 + *
94 + * @since 0.2.0
95 + * @var string
96 + */
97 + public $date_filter = self::DATE_FILTER_RANGE;
98 +
99 + /**
100 + * What the section's date filter supports, and where it renders.
101 + *
102 + * - `with_date_comparison`: false drops the comparison param from every widget fetch in the
103 + * section, not just the chrome.
104 + * - `with_header_date_control`: false hands the control to the section's widgets, which may
105 + * save the range onto the widget instance rather than the URL.
106 + *
107 + * @since 0.3.0
108 + * @since 0.5.0 Added `with_header_date_control`.
109 + * @var array
110 + */
111 + public $date_filter_options = array(
112 + 'with_date_comparison' => true,
113 + 'with_header_date_control' => true,
114 + );
115 +
116 + /**
117 + * Whether the section's data only reaches WordPress.com through the analytics
118 + * full sync, so its numbers are incomplete until that sync has finished once.
119 + *
120 + * @since 0.4.0
121 + * @var bool
122 + */
123 + public $requires_sync = false;
124 +
125 + /**
126 + * Availability flag or callback.
127 + *
128 + * @var bool|callable
129 + */
130 + private $is_available = true;
131 +
132 + /**
133 + * Default layout array or callback.
134 + *
135 + * @var array|callable
136 + */
137 + private $default_layout = array();
138 +
139 + /**
140 + * Constructor.
141 + *
142 + * @param string $dashboard_name Dashboard identifier.
143 + * @param string $id Section identifier.
144 + * @param array $args Optional. Section arguments.
145 + */
146 + public function __construct( $dashboard_name, $id, $args = array() ) {
147 + $this->dashboard_name = $dashboard_name;
148 + $this->id = $id;
149 + $this->slug = self::derive_slug( $id );
150 + $this->label = $id;
151 +
152 + $this->set_props( $args );
153 + }
154 +
155 + /**
156 + * Derives the URL-facing slug from a namespaced section identifier.
157 + *
158 + * @param string $id Section identifier, e.g. `analytics/traffic`.
159 + * @return string The segment after the namespace, e.g. `traffic`.
160 + */
161 + private static function derive_slug( $id ) {
162 + $separator = strpos( (string) $id, '/' );
163 +
164 + return false === $separator ? (string) $id : substr( $id, $separator + 1 );
165 + }
166 +
167 + /**
168 + * Returns whether this section should be exposed.
169 + *
170 + * @return bool
171 + */
172 + public function is_available() {
173 + if ( is_callable( $this->is_available ) ) {
174 + return (bool) call_user_func( $this->is_available, $this );
175 + }
176 +
177 + return (bool) $this->is_available;
178 + }
179 +
180 + /**
181 + * Returns the section's default widget layout, run through the default-layout filter.
182 + *
183 + * @return array Array of widget instances.
184 + */
185 + public function get_default_layout() {
186 + $layout = is_callable( $this->default_layout )
187 + ? call_user_func( $this->default_layout, $this )
188 + : $this->default_layout;
189 + $layout = is_array( $layout ) ? array_values( $layout ) : array();
190 +
191 + /**
192 + * Filters a dashboard section's default widget layout.
193 + *
194 + * Each entry matches the dashboard's widget instance shape: `uuid`, `type`, optional
195 + * `attributes`, optional `placement`. Runs for every section, so a callback adding an
196 + * instance to one switches on `$section_id`.
197 + *
198 + * @since 0.8.0 Runs from the section, with its declared layout and its
199 + * namespaced id; it received an empty array and any alias before.
200 + *
201 + * @param array $layout The section's declared default widget instances.
202 + * @param string $section_id Namespaced section identifier, e.g. `analytics/traffic`.
203 + * @param Dashboard_Section $section The section.
204 + */
205 + $layout = apply_filters( DASHBOARD_DEFAULT_LAYOUT_FILTER, $layout, $this->id, $this );
206 +
207 + return is_array( $layout ) ? array_values( $layout ) : array();
208 + }
209 +
210 + /**
211 + * Returns the public REST representation.
212 + *
213 + * @return array
214 + */
215 + public function to_array() {
216 + return array(
217 + 'id' => $this->id,
218 + 'slug' => $this->slug,
219 + 'label' => $this->label,
220 + 'title' => $this->title,
221 + 'order' => (int) $this->order,
222 + 'date_filter' => $this->date_filter,
223 + 'date_filter_options' => $this->date_filter_options,
224 + 'requires_sync' => $this->requires_sync,
225 + 'default_layout' => $this->get_default_layout(),
226 + );
227 + }
228 +
229 + /**
230 + * Hydrates section properties from the args array.
231 + *
232 + * @param array $args Section arguments.
233 + * @return void
234 + */
235 + private function set_props( $args ) {
236 + if ( ! is_array( $args ) ) {
237 + return;
238 + }
239 +
240 + if ( isset( $args['label'] ) ) {
241 + $this->label = (string) $args['label'];
242 + }
243 +
244 + // An empty string is a registrant saying "none", not a heading: kept as-is it
245 + // would defeat the label fallback and render an `<h2>` with no accessible name.
246 + if ( isset( $args['title'] ) ) {
247 + $title = (string) $args['title'];
248 + $this->title = '' === $title ? null : $title;
249 + }
250 +
251 + if ( isset( $args['order'] ) ) {
252 + $this->order = (int) $args['order'];
253 + }
254 +
255 + // An unrecognized surface keeps the default rather than reaching the
256 + // dashboard, where the frontend has no filter to render for it.
257 + if ( isset( $args['date_filter'] ) && in_array( $args['date_filter'], self::DATE_FILTERS, true ) ) {
258 + $this->date_filter = (string) $args['date_filter'];
259 + }
260 +
261 + // Merged over the defaults so a partial array keeps the rest, and narrowed
262 + // to the known options, which is all the dashboard renders.
263 + if ( isset( $args['date_filter_options'] ) && is_array( $args['date_filter_options'] ) ) {
264 + $options = array_merge( $this->date_filter_options, $args['date_filter_options'] );
265 +
266 + $this->date_filter_options = array(
267 + 'with_date_comparison' => (bool) $options['with_date_comparison'],
268 + 'with_header_date_control' => (bool) $options['with_header_date_control'],
269 + );
270 + }
271 +
272 + if ( isset( $args['requires_sync'] ) ) {
273 + $this->requires_sync = (bool) $args['requires_sync'];
274 + }
275 +
276 + if ( array_key_exists( 'is_available', $args ) ) {
277 + $this->is_available = $args['is_available'];
278 + }
279 +
280 + if ( array_key_exists( 'default_layout', $args ) ) {
281 + $this->default_layout = $args['default_layout'];
282 + }
283 + }
284 +}