PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
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
jetpack / jetpack_vendor / automattic / jetpack-videopress / src / class-analytics-dashboard.php

class-analytics-dashboard.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3, at jetpack_vendor/automattic/jetpack-videopress/src/class-analytics-dashboard.php

201 lines 6.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The Top videos widget of the Premium Analytics dashboard.
4 *
5 * @package automattic/jetpack-videopress
6 */
7
8 namespace Automattic\Jetpack\VideoPress;
9
10 use Automattic\Jetpack\Status\Host;
11 use function Automattic\Jetpack\PremiumAnalytics\get_dashboard_default_widget_instance;
12 use function Automattic\Jetpack\PremiumAnalytics\register_widget_types_from_manifest;
13
14 /**
15 * Registers the Top videos widget type on the Premium Analytics dashboard and seeds it into the
16 * Traffic section's default layout.
17 *
18 * The package decides nothing about who gets the widget: `Initializer` calls `init()` where
19 * VideoPress is active outside the WordPress.com platform, jetpack-mu-wpcom calls the registrants
20 * on Simple and Atomic where the plan includes VideoPress. Everything registers when the
21 * dashboard's widget registry hydrates, so a call on a site without the dashboard is inert.
22 *
23 * @since 0.55.0
24 */
25 class Analytics_Dashboard {
26
27 /**
28 * Widget type name the package builds, from `widgets/top-videos/widget.json`.
29 */
30 const TOP_VIDEOS_TYPE = 'videopress/top-videos';
31
32 /**
33 * Names the widget type registered under before it moved here. A persisted layout that still
34 * carries one resolves to TOP_VIDEOS_TYPE.
35 */
36 const TOP_VIDEOS_FORMER_NAMES = array( 'jpa/videopress' );
37
38 /**
39 * The dashboard section whose default layout seeds the widget, and the seeded instance.
40 */
41 const TRAFFIC_SECTION_ID = 'analytics/traffic';
42 const TOP_VIDEOS_INSTANCE_UUID = 'default-videopress-widget-instance';
43
44 /**
45 * Registry action and default-layout filter of the dashboard package.
46 */
47 const REGISTER_WIDGET_TYPES_ACTION = 'jetpack_premium_analytics_register_widget_types';
48 const DEFAULT_LAYOUT_FILTER = 'jetpack_premium_analytics_dashboard_default_layout';
49
50 /**
51 * Text domain of the widget metadata and of the built widget bundle.
52 */
53 const TEXTDOMAIN = 'jetpack-videopress-pkg';
54
55 /**
56 * Lowest widget contract the build works against: the CSV download action the widget imports
57 * reached the SDK in 1.3.0.
58 */
59 const MIN_WIDGET_API_VERSION = '1.3.0';
60
61 /**
62 * Hook the registrant on the dashboard's registry action and the seed on its layout filter.
63 *
64 * Priority 20 for the registrant, after the dashboard package's own; priority 10 for the seed,
65 * before the dashboard drops the instances of unregistered types at 100.
66 *
67 * @return void
68 */
69 public static function init() {
70 // Simple and Atomic decide by plan feature, from jetpack-mu-wpcom.
71 if ( ( new Host() )->is_wpcom_platform() ) {
72 return;
73 }
74
75 add_action( self::REGISTER_WIDGET_TYPES_ACTION, array( __CLASS__, 'register_widget_types' ), 20 );
76 add_filter( self::DEFAULT_LAYOUT_FILTER, array( __CLASS__, 'add_default_layout_instance' ), 10, 2 );
77 }
78
79 /**
80 * Register the widget types from the package's build manifest.
81 *
82 * Loads the generated build first: after `init` it registers the widget script modules on the
83 * spot, so they reach the page import map the same request.
84 *
85 * @param object $registry The widget type registry being hydrated.
86 * @return void
87 */
88 public static function register_widget_types( $registry ) {
89 if ( ! self::widget_contract_is_supported() ) {
90 return;
91 }
92
93 register_widget_types_from_manifest(
94 self::get_widget_manifest(),
95 array(
96 'textdomain' => self::TEXTDOMAIN,
97 'i18n_manifest' => add_query_arg( 'ver', Package_Version::PACKAGE_VERSION, plugins_url( 'i18n-manifest.json', self::build_dir() . '/build.php' ) ),
98 'former_names' => array( self::TOP_VIDEOS_TYPE => self::TOP_VIDEOS_FORMER_NAMES ),
99 ),
100 $registry
101 );
102 }
103
104 /**
105 * Seed the Top videos instance into the Traffic section's default layout.
106 *
107 * Order 8 keeps the place the dashboard seeded it in before the widget moved here. A layout
108 * that already holds the instance, under this name or a former one, is left alone; and one
109 * seeded on a site where the type never registers loses it to the dashboard's own policy.
110 *
111 * @param mixed $layout The section's default widget instances; anything but an array passes through.
112 * @param string $section_id Namespaced section identifier.
113 * @return mixed The layout, with the instance appended when it is an array.
114 */
115 public static function add_default_layout_instance( $layout, $section_id ) {
116 if ( self::TRAFFIC_SECTION_ID !== $section_id || ! is_array( $layout ) ) {
117 return $layout;
118 }
119
120 foreach ( $layout as $item ) {
121 if ( ! is_array( $item ) ) {
122 continue;
123 }
124 if ( self::TOP_VIDEOS_INSTANCE_UUID === ( $item['uuid'] ?? null ) || self::is_top_videos_type( $item['type'] ?? null ) ) {
125 return $layout;
126 }
127 }
128
129 $layout[] = get_dashboard_default_widget_instance( self::TOP_VIDEOS_INSTANCE_UUID, self::TOP_VIDEOS_TYPE, 8, 1, 2 );
130
131 return $layout;
132 }
133
134 /**
135 * Whether a widget type name is the Top videos type, current or former.
136 *
137 * @param mixed $type A widget type name.
138 * @return bool
139 */
140 private static function is_top_videos_type( $type ) {
141 return is_string( $type ) && ( self::TOP_VIDEOS_TYPE === $type || in_array( $type, self::TOP_VIDEOS_FORMER_NAMES, true ) );
142 }
143
144 /**
145 * Whether the dashboard's widget contract is one this build works against.
146 *
147 * Undefined is a request that never loaded the dashboard's widget types, such as the sections
148 * REST route: the widgets wait for one that does.
149 *
150 * @return bool
151 */
152 private static function widget_contract_is_supported() {
153 if ( ! defined( 'Automattic\\Jetpack\\PremiumAnalytics\\WIDGET_API_VERSION' ) ) {
154 return false;
155 }
156
157 $version = \Automattic\Jetpack\PremiumAnalytics\WIDGET_API_VERSION;
158
159 return version_compare( $version, self::MIN_WIDGET_API_VERSION, '>=' ) && version_compare( $version, '2', '<' );
160 }
161
162 /**
163 * The widget manifest the package registers from: what its build generated, none without a build.
164 *
165 * @return array[] Manifest entries, as `jetpack_videopress_get_registered_widget_modules()` returns them.
166 */
167 private static function get_widget_manifest() {
168 self::load_build();
169 if ( ! function_exists( 'jetpack_videopress_get_registered_widget_modules' ) ) {
170 return array();
171 }
172
173 return (array) jetpack_videopress_get_registered_widget_modules();
174 }
175
176 /**
177 * Load the generated build once. Guarded by symbol, not by path: on WordPress.com two copies of
178 * the package can share a request.
179 *
180 * @return void
181 */
182 private static function load_build() {
183 if ( function_exists( 'jetpack_videopress_get_registered_widget_modules' ) ) {
184 return;
185 }
186 $loader = self::build_dir() . '/build.php';
187 if ( file_exists( $loader ) ) {
188 require_once $loader;
189 }
190 }
191
192 /**
193 * Directory of the wp-build output.
194 *
195 * @return string
196 */
197 private static function build_dir() {
198 return dirname( __DIR__ ) . '/build';
199 }
200 }
201