Completed
Push — renovate/debug-4.x ( f92d53...830252 )
by
unknown
07:08
created

VideoPress_Gutenberg::override_video_upload()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 0
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
1
<?php
2
/**
3
 * Block Editor functionality for VideoPress users.
4
 *
5
 * @package Jetpack
6
 */
7
8
use Automattic\Jetpack\Assets;
9
10
/**
11
 * Register a VideoPress extension to replace the default Core Video block.
12
 */
13
class VideoPress_Gutenberg {
14
15
	/**
16
	 * Singleton
17
	 */
18
	public static function init() {
19
		static $instance = false;
20
21
		if ( ! $instance ) {
22
			$instance = new VideoPress_Gutenberg();
23
		}
24
25
		return $instance;
26
	}
27
28
	/**
29
	 * VideoPress_Gutenberg constructor.
30
	 *
31
	 * Initialize the VideoPress Gutenberg extension
32
	 */
33
	private function __construct() {
34
		add_action( 'init', array( $this, 'register_video_block_with_videopress' ) );
35
		add_action( 'jetpack_register_gutenberg_extensions', array( $this, 'set_extension_availability' ) );
36
		add_action( 'enqueue_block_editor_assets', array( $this, 'override_video_upload' ) );
37
	}
38
39
	/**
40
	 * Used to check whether VideoPress is enabled for given site.
41
	 *
42
	 * @todo Create a global `jetpack_check_module_availability( $module )` helper so we can re-use it on other modules.
43
	 *       This global helper should be created in a file synced with WordPress.com so we can use it there too.
44
	 * @see https://github.com/Automattic/jetpack/pull/11321#discussion_r255477815
45
	 *
46
	 * @return array Associative array indicating if the module is available (key `available`) and the reason why it is
47
	 * unavailable (key `unavailable_reason`)
48
	 */
49
	public function check_videopress_availability() {
50
		// It is available on Simple Sites having the appropriate a plan.
51
		if (
52
			defined( 'IS_WPCOM' ) && IS_WPCOM
53
			&& method_exists( 'Store_Product_List', 'get_site_specific_features_data' )
54
		) {
55
			$features = Store_Product_List::get_site_specific_features_data();
56
			if ( in_array( 'videopress', $features['active'], true ) ) {
57
				return array( 'available' => true );
58
			} else {
59
				return array(
60
					'available'          => false,
61
					'unavailable_reason' => 'missing_plan',
62
				);
63
			}
64
		}
65
66
		// It is available on Jetpack Sites having the module active.
67
		if (
68
			method_exists( 'Jetpack', 'is_active' ) && Jetpack::is_active()
69
			&& method_exists( 'Jetpack', 'is_module_active' )
70
			&& method_exists( 'Jetpack_Plan', 'supports' )
71
		) {
72
			if ( Jetpack::is_module_active( 'videopress' ) ) {
73
				return array( 'available' => true );
74
			} elseif ( ! Jetpack_Plan::supports( 'videopress' ) ) {
75
				return array(
76
					'available'          => false,
77
					'unavailable_reason' => 'missing_plan',
78
				);
79
			} else {
80
				return array(
81
					'available'          => false,
82
					'unavailable_reason' => 'missing_module',
83
				);
84
			}
85
		}
86
87
		return array(
88
			'available'          => false,
89
			'unavailable_reason' => 'unknown',
90
		);
91
	}
92
93
	/**
94
	 * Set the Jetpack Gutenberg extension availability.
95
	 */
96
	public function set_extension_availability() {
97
		$availability = $this->check_videopress_availability();
98
		if ( $availability['available'] ) {
99
			Jetpack_Gutenberg::set_extension_available( 'jetpack/videopress' );
100
		} else {
101
			Jetpack_Gutenberg::set_extension_unavailable( 'jetpack/videopress', $availability['unavailable_reason'] );
0 ignored issues
show
Bug introduced by
It seems like $availability['unavailable_reason'] can also be of type boolean; however, Jetpack_Gutenberg::set_extension_unavailable() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
102
		}
103
	}
104
105
	/**
106
	 * Register the core video block as a dynamic block.
107
	 *
108
	 * It defines a server-side rendering that adds VideoPress support to the core video block.
109
	 */
110
	public function register_video_block_with_videopress() {
111
		jetpack_register_block(
112
			'core/video',
113
			array(
114
				'render_callback' => array( $this, 'render_video_block_with_videopress' ),
115
			)
116
		);
117
	}
118
119
	/**
120
	 * Render the core video block replacing the src attribute with the VideoPress URL
121
	 *
122
	 * @param array  $attributes Array containing the video block attributes.
123
	 * @param string $content    String containing the video block content.
124
	 *
125
	 * @return string
126
	 */
127
	public function render_video_block_with_videopress( $attributes, $content ) {
128
		if ( ! isset( $attributes['id'] ) || isset( $attributes['guid'] ) ) {
129
			return $content;
130
		}
131
132
		if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
133
			$blog_id = get_current_blog_id();
134
		} elseif ( method_exists( 'Jetpack', 'is_active' ) && Jetpack::is_active() ) {
135
			/**
136
			 * We're intentionally not using `get_current_blog_id` because it was returning unexpected values.
137
			 *
138
			 * @see https://github.com/Automattic/jetpack/pull/11193#issuecomment-457883886
139
			 * @see https://github.com/Automattic/jetpack/pull/11193/commits/215cf789f3d8bd03ff9eb1bbdb693acb8831d273
140
			 */
141
			$blog_id = Jetpack_Options::get_option( 'id' );
142
		}
143
144
		if ( ! isset( $blog_id ) ) {
145
			return $content;
146
		}
147
148
		$post_id         = absint( $attributes['id'] );
149
		$videopress_id   = video_get_info_by_blogpostid( $blog_id, $post_id )->guid;
150
		$videopress_data = videopress_get_video_details( $videopress_id );
151
152
		if ( empty( $videopress_data->file_url_base->https ) || empty( $videopress_data->files->hd->mp4 ) ) {
153
			return $content;
154
		}
155
156
		$videopress_url = $videopress_data->file_url_base->https . $videopress_data->files->hd->mp4;
157
158
		$pattern = '/(\s)src=([\'"])(?:(?!\2).)+?\2/';
159
160
		return preg_replace(
161
			$pattern,
162
			sprintf(
163
				'\1src="%1$s"',
164
				esc_url_raw( $videopress_url )
165
			),
166
			$content,
167
			1
168
		);
169
	}
170
171
	/**
172
	 * Replaces the video uploaded in the block editor.
173
	 *
174
	 * Enqueues a script that registers an API fetch middleware replacing the video uploads in Gutenberg so they are
175
	 * uploaded against the WP.com API media endpoint and thus transcoded by VideoPress.
176
	 */
177
	public function override_video_upload() {
178
		// Bail if Jetpack or VideoPress is not active.
179
		if ( ! Jetpack::is_active() || ! Jetpack::is_module_active( 'videopress' ) ) {
180
			return;
181
		}
182
183
		wp_enqueue_script(
184
			'jetpack-videopress-gutenberg-override-video-upload',
185
			Assets::get_file_url_for_environment(
186
				'_inc/build/videopress/js/gutenberg-video-upload.min.js',
187
				'modules/videopress/js/gutenberg-video-upload.js'
188
			),
189
			array( 'wp-api-fetch', 'wp-polyfill', 'lodash' ),
190
			JETPACK__VERSION,
191
			false
192
		);
193
	}
194
}
195
196
VideoPress_Gutenberg::init();
197