← All changes
|
modules/videopress/class.jetpack-videopress.php
+483
-0
16.2-beta
→
16.3
View file →
| @@ -1,0 +1,483 @@ | ||
| 1 | +<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName | |
| 2 | + | |
| 3 | +use Automattic\Jetpack\Assets; | |
| 4 | +use Automattic\Jetpack\Current_Plan; | |
| 5 | +use Automattic\Jetpack\Status; | |
| 6 | +use Automattic\Jetpack\VideoPress\Attachment_Handler; | |
| 7 | +use Automattic\Jetpack\VideoPress\Jwt_Token_Bridge; | |
| 8 | +use Automattic\Jetpack\VideoPress\Options as VideoPress_Options; | |
| 9 | + | |
| 10 | +if ( ! defined( 'ABSPATH' ) ) { | |
| 11 | + exit( 0 ); | |
| 12 | +} | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * VideoPress in Jetpack | |
| 16 | + */ | |
| 17 | +class Jetpack_VideoPress { | |
| 18 | + /** | |
| 19 | + * Module name. | |
| 20 | + * | |
| 21 | + * @var string | |
| 22 | + */ | |
| 23 | + public $module = 'videopress'; | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * Singleton | |
| 27 | + */ | |
| 28 | + public static function init() { | |
| 29 | + static $instance = false; | |
| 30 | + | |
| 31 | + if ( ! $instance ) { | |
| 32 | + $instance = new Jetpack_VideoPress(); | |
| 33 | + } | |
| 34 | + | |
| 35 | + return $instance; | |
| 36 | + } | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * Jetpack_VideoPress constructor. | |
| 40 | + * | |
| 41 | + * Sets up the initializer and makes sure that videopress activates and deactivates properly. | |
| 42 | + */ | |
| 43 | + private function __construct() { | |
| 44 | + add_action( 'init', array( $this, 'on_init' ) ); | |
| 45 | + add_action( 'jetpack_deactivate_module_videopress', array( $this, 'jetpack_module_deactivated' ) ); | |
| 46 | + } | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * Fires on init | |
| 50 | + */ | |
| 51 | + public function on_init() { | |
| 52 | + add_action( 'wp_enqueue_media', array( $this, 'enqueue_admin_scripts' ) ); | |
| 53 | + add_filter( 'plupload_default_settings', array( $this, 'videopress_pluploder_config' ) ); | |
| 54 | + | |
| 55 | + add_action( 'admin_print_footer_scripts', array( $this, 'print_in_footer_open_media_add_new' ) ); | |
| 56 | + add_action( 'admin_head', array( $this, 'enqueue_admin_styles' ) ); | |
| 57 | + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_media_new_scripts' ) ); | |
| 58 | + | |
| 59 | + VideoPress_Scheduler::init(); | |
| 60 | + } | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * Enqueues the jwt bridge script. | |
| 64 | + * | |
| 65 | + * @deprecated 11.3 | |
| 66 | + */ | |
| 67 | + public function enqueue_jwt_token_bridge() { | |
| 68 | + _deprecated_function( __METHOD__, 'jetpack-11.3', 'Automattic\Jetpack\VideoPress\Jwt_Token_Bridge::enqueue_jwt_token_bridge' ); | |
| 69 | + return Jwt_Token_Bridge::enqueue_jwt_token_bridge(); | |
| 70 | + } | |
| 71 | + | |
| 72 | + /** | |
| 73 | + * Enqueues the script that routes media-new.php video uploads to VideoPress. | |
| 74 | + * | |
| 75 | + * The classic uploader on media-new.php builds a raw plupload.Uploader | |
| 76 | + * (via plupload-handlers) instead of wp.Uploader, so the override in | |
| 77 | + * videopress-plupload.js never engages there. This companion script | |
| 78 | + * registers the same videopress_check_uploads plupload filter and | |
| 79 | + * re-targets video uploads to VideoPress. The filter is injected into the | |
| 80 | + * uploader settings through the plupload_init filter, which | |
| 81 | + * media_upload_form() applies when it renders later in the request. | |
| 82 | + * | |
| 83 | + * @param string $hook_suffix The current admin page. | |
| 84 | + */ | |
| 85 | + public function enqueue_media_new_scripts( $hook_suffix ) { | |
| 86 | + if ( 'media-new.php' !== $hook_suffix ) { | |
| 87 | + return; | |
| 88 | + } | |
| 89 | + | |
| 90 | + if ( ! $this->is_videopress_enabled() ) { | |
| 91 | + return; | |
| 92 | + } | |
| 93 | + | |
| 94 | + // Version with the served file's mtime so browsers and page caches pick | |
| 95 | + // up new builds even when JETPACK__VERSION has not changed (branch | |
| 96 | + // testing, beta builds). | |
| 97 | + $script_relative = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG | |
| 98 | + ? 'modules/videopress/js/videopress-media-new.js' | |
| 99 | + : '_inc/build/videopress/js/videopress-media-new.min.js'; | |
| 100 | + $script_path = JETPACK__PLUGIN_DIR . $script_relative; | |
| 101 | + $script_version = file_exists( $script_path ) ? (string) filemtime( $script_path ) : JETPACK__VERSION; | |
| 102 | + | |
| 103 | + wp_enqueue_script( | |
| 104 | + 'videopress-media-new', | |
| 105 | + Assets::get_file_url_for_environment( | |
| 106 | + '_inc/build/videopress/js/videopress-media-new.min.js', | |
| 107 | + 'modules/videopress/js/videopress-media-new.js' | |
| 108 | + ), | |
| 109 | + array( | |
| 110 | + 'jquery', | |
| 111 | + 'plupload-handlers', | |
| 112 | + ), | |
| 113 | + $script_version, | |
| 114 | + true | |
| 115 | + ); | |
| 116 | + | |
| 117 | + wp_localize_script( 'videopress-media-new', 'videoPressMediaNew', $this->get_media_new_upload_limits() ); | |
| 118 | + | |
| 119 | + add_filter( 'plupload_init', array( $this, 'videopress_pluploder_config' ) ); | |
| 120 | + } | |
| 121 | + | |
| 122 | + /** | |
| 123 | + * Returns the free-plan upload limit data used by the media-new.php script. | |
| 124 | + * | |
| 125 | + * The free plan includes a single video upload, so the script needs to know | |
| 126 | + * whether the site has a paid VideoPress plan, whether the free upload has | |
| 127 | + * already been used, and where to send the user to upgrade. Mirrors the | |
| 128 | + * checks behind the VideoPress dashboard's upgrade notice: the paid check | |
| 129 | + * matches Admin_UI::initial_state()'s paidFeatures, and the used check | |
| 130 | + * matches the dashboard's VideoPress video count (video/videopress | |
| 131 | + * attachments). | |
| 132 | + * | |
| 133 | + * @return array | |
| 134 | + */ | |
| 135 | + public function get_media_new_upload_limits() { | |
| 136 | + $has_videopress_purchase = Current_Plan::supports( 'videopress-1tb-storage' ) | |
| 137 | + || Current_Plan::supports( 'videopress-unlimited-storage' ) | |
| 138 | + || ( function_exists( 'wpcom_site_has_feature' ) && wpcom_site_has_feature( 'videopress' ) ); | |
| 139 | + | |
| 140 | + $has_used_video = false; | |
| 141 | + if ( ! $has_videopress_purchase ) { | |
| 142 | + $videopress_videos = get_posts( | |
| 143 | + array( | |
| 144 | + 'post_type' => 'attachment', | |
| 145 | + 'post_status' => 'inherit', | |
| 146 | + 'post_mime_type' => 'video/videopress', | |
| 147 | + 'posts_per_page' => 1, | |
| 148 | + 'fields' => 'ids', | |
| 149 | + ) | |
| 150 | + ); | |
| 151 | + | |
| 152 | + $has_used_video = count( $videopress_videos ) > 0; | |
| 153 | + } | |
| 154 | + | |
| 155 | + $upgrade_url = sprintf( | |
| 156 | + 'https://wordpress.com/checkout/%s/jetpack_videopress?redirect_to=%s', | |
| 157 | + rawurlencode( ( new Status() )->get_site_suffix() ), | |
| 158 | + rawurlencode( admin_url( 'media-new.php' ) ) | |
| 159 | + ); | |
| 160 | + | |
| 161 | + $allowed_html = array( | |
| 162 | + 'a' => array( 'href' => array() ), | |
| 163 | + ); | |
| 164 | + | |
| 165 | + return array( | |
| 166 | + 'hasVideoPressPurchase' => $has_videopress_purchase, | |
| 167 | + 'hasUsedVideo' => $has_used_video, | |
| 168 | + 'strings' => array( | |
| 169 | + 'usedVideoUpload' => sprintf( | |
| 170 | + wp_kses( | |
| 171 | + /* translators: %s is the url to upgrade the VideoPress plan */ | |
| 172 | + __( 'You have used your free video upload. The free plan includes one video upload. <a href="%s">Upgrade now</a> to unlock unlimited videos, 1TB of storage, and more!', 'jetpack' ), | |
| 173 | + $allowed_html | |
| 174 | + ), | |
| 175 | + esc_url( $upgrade_url ) | |
| 176 | + ), | |
| 177 | + 'multipleVideos' => sprintf( | |
| 178 | + wp_kses( | |
| 179 | + /* translators: %s is the url to upgrade the VideoPress plan */ | |
| 180 | + __( 'The free plan includes one video upload. <a href="%s">Upgrade now</a> to upload more videos and unlock unlimited videos, 1TB of storage, and more!', 'jetpack' ), | |
| 181 | + $allowed_html | |
| 182 | + ), | |
| 183 | + esc_url( $upgrade_url ) | |
| 184 | + ), | |
| 185 | + 'multipleVideosSelected' => sprintf( | |
| 186 | + wp_kses( | |
| 187 | + /* translators: %s is the url to upgrade the VideoPress plan */ | |
| 188 | + __( 'Uploading multiple videos requires a paid plan. The free plan includes one video upload. <a href="%s">Upgrade now</a> to unlock unlimited videos, 1TB of storage, and more!', 'jetpack' ), | |
| 189 | + $allowed_html | |
| 190 | + ), | |
| 191 | + esc_url( $upgrade_url ) | |
| 192 | + ), | |
| 193 | + ), | |
| 194 | + ); | |
| 195 | + } | |
| 196 | + | |
| 197 | + /** | |
| 198 | + * Runs when the VideoPress module is deactivated. | |
| 199 | + */ | |
| 200 | + public function jetpack_module_deactivated() { | |
| 201 | + VideoPress_Options::delete_options(); | |
| 202 | + } | |
| 203 | + | |
| 204 | + /** | |
| 205 | + * Similar to current_user_can, but internal to VideoPress. | |
| 206 | + * | |
| 207 | + * @param string $cap Capability name. | |
| 208 | + * @param int $user_id User ID. | |
| 209 | + * @return bool Returns true if the given VideoPress capability is allowed by the given user. | |
| 210 | + */ | |
| 211 | + public function can( $cap, $user_id = false ) { | |
| 212 | + if ( ! $user_id ) { | |
| 213 | + $user_id = get_current_user_id(); | |
| 214 | + } | |
| 215 | + | |
| 216 | + // Connection owners are allowed to do all the things. | |
| 217 | + if ( Jetpack::connection()->is_connection_owner( $user_id ) ) { | |
| 218 | + return true; | |
| 219 | + } | |
| 220 | + | |
| 221 | + // Additional and internal caps checks | |
| 222 | + if ( ! user_can( $user_id, 'upload_files' ) ) { | |
| 223 | + return false; | |
| 224 | + } | |
| 225 | + | |
| 226 | + if ( 'edit_videos' === $cap && ! user_can( $user_id, 'edit_others_posts' ) ) { | |
| 227 | + return false; | |
| 228 | + } | |
| 229 | + | |
| 230 | + if ( 'delete_videos' === $cap && ! user_can( $user_id, 'delete_others_posts' ) ) { | |
| 231 | + return false; | |
| 232 | + } | |
| 233 | + | |
| 234 | + return true; | |
| 235 | + } | |
| 236 | + | |
| 237 | + /** | |
| 238 | + * Register and enqueue VideoPress admin styles. | |
| 239 | + */ | |
| 240 | + public function enqueue_admin_styles() { | |
| 241 | + wp_register_style( 'videopress-admin', plugins_url( 'videopress-admin.css', __FILE__ ), array(), JETPACK__VERSION ); | |
| 242 | + wp_enqueue_style( 'videopress-admin' ); | |
| 243 | + } | |
| 244 | + | |
| 245 | + /** | |
| 246 | + * Attempts to delete a VideoPress video from wp.com. | |
| 247 | + * Will block the deletion from continuing if certain errors return from the wp.com API. | |
| 248 | + * | |
| 249 | + * @param Boolean $delete if the deletion should occur or not (unused). | |
| 250 | + * @param WP_Post $post the post object. | |
| 251 | + * | |
| 252 | + * @deprecated 11.3 | |
| 253 | + * | |
| 254 | + * @return null|WP_Error|Boolean null if deletion should continue. | |
| 255 | + */ | |
| 256 | + public function delete_video_wpcom( $delete, $post ) { | |
| 257 | + _deprecated_function( __METHOD__, 'jetpack-11.3', 'Automattic\Jetpack\VideoPress\Attachment_Handler::delete_video_wpcom' ); | |
| 258 | + return Attachment_Handler::delete_video_wpcom( $delete, $post ); | |
| 259 | + } | |
| 260 | + | |
| 261 | + /** | |
| 262 | + * Register VideoPress admin scripts. | |
| 263 | + */ | |
| 264 | + public function enqueue_admin_scripts() { | |
| 265 | + if ( did_action( 'videopress_enqueue_admin_scripts' ) ) { | |
| 266 | + return; | |
| 267 | + } | |
| 268 | + | |
| 269 | + if ( $this->should_override_media_uploader() ) { | |
| 270 | + wp_enqueue_script( | |
| 271 | + 'videopress-plupload', | |
| 272 | + Assets::get_file_url_for_environment( | |
| 273 | + '_inc/build/videopress/js/videopress-plupload.min.js', | |
| 274 | + 'modules/videopress/js/videopress-plupload.js' | |
| 275 | + ), | |
| 276 | + array( | |
| 277 | + 'jquery', | |
| 278 | + 'wp-plupload', | |
| 279 | + ), | |
| 280 | + JETPACK__VERSION, | |
| 281 | + true | |
| 282 | + ); | |
| 283 | + | |
| 284 | + wp_enqueue_script( | |
| 285 | + 'videopress-uploader', | |
| 286 | + Assets::get_file_url_for_environment( | |
| 287 | + '_inc/build/videopress/js/videopress-uploader.min.js', | |
| 288 | + 'modules/videopress/js/videopress-uploader.js' | |
| 289 | + ), | |
| 290 | + array( | |
| 291 | + 'videopress-plupload', | |
| 292 | + ), | |
| 293 | + JETPACK__VERSION, | |
| 294 | + true | |
| 295 | + ); | |
| 296 | + | |
| 297 | + wp_enqueue_script( | |
| 298 | + 'media-video-widget-extensions', | |
| 299 | + Assets::get_file_url_for_environment( | |
| 300 | + '_inc/build/videopress/js/media-video-widget-extensions.min.js', | |
| 301 | + 'modules/videopress/js/media-video-widget-extensions.js' | |
| 302 | + ), | |
| 303 | + array(), | |
| 304 | + JETPACK__VERSION, | |
| 305 | + true | |
| 306 | + ); | |
| 307 | + } | |
| 308 | + | |
| 309 | + /** | |
| 310 | + * Fires after VideoPress scripts are enqueued in the dashboard. | |
| 311 | + * | |
| 312 | + * @since 2.5.0 | |
| 313 | + */ | |
| 314 | + do_action( 'videopress_enqueue_admin_scripts' ); | |
| 315 | + } | |
| 316 | + | |
| 317 | + /** | |
| 318 | + * Returns the VideoPress URL for the give post id, otherwise returns the provided default. | |
| 319 | + * | |
| 320 | + * This is an attachment-based filter handler. | |
| 321 | + * | |
| 322 | + * @deprecated 11.3 | |
| 323 | + * | |
| 324 | + * @param string $default The default return value if post id is not a VideoPress video. | |
| 325 | + * @param int $post_id The post id for the current attachment. | |
| 326 | + */ | |
| 327 | + public function maybe_get_attached_url_for_videopress( $default, $post_id ) { | |
| 328 | + _deprecated_function( __METHOD__, 'jetpack-11.3', 'Automattic\Jetpack\VideoPress\Attachment_Handler::maybe_get_attached_url_for_videopress' ); | |
| 329 | + return Attachment_Handler::maybe_get_attached_url_for_videopress( $default, $post_id ); | |
| 330 | + } | |
| 331 | + | |
| 332 | + /** | |
| 333 | + * Modify the default plupload config to turn on VideoPress specific filters. | |
| 334 | + * | |
| 335 | + * @param array $config The plupload config. | |
| 336 | + */ | |
| 337 | + public function videopress_pluploder_config( $config ) { | |
| 338 | + | |
| 339 | + if ( ! isset( $config['filters']['max_file_size'] ) ) { | |
| 340 | + $config['filters']['max_file_size'] = wp_max_upload_size() . 'b'; | |
| 341 | + } | |
| 342 | + | |
| 343 | + $config['filters']['videopress_check_uploads'] = $config['filters']['max_file_size']; | |
| 344 | + | |
| 345 | + // We're doing our own check in the videopress_check_uploads filter. | |
| 346 | + unset( $config['filters']['max_file_size'] ); | |
| 347 | + | |
| 348 | + return $config; | |
| 349 | + } | |
| 350 | + | |
| 351 | + /** | |
| 352 | + * Helper function to determine if the media uploader should be overridden. | |
| 353 | + * | |
| 354 | + * The rules are simple, only try to load the script when on the edit post or new post pages. | |
| 355 | + * | |
| 356 | + * @return bool | |
| 357 | + */ | |
| 358 | + protected function should_override_media_uploader() { | |
| 359 | + global $pagenow; | |
| 360 | + | |
| 361 | + // Only load in the admin | |
| 362 | + if ( ! is_admin() ) { | |
| 363 | + return false; | |
| 364 | + } | |
| 365 | + | |
| 366 | + $acceptable_pages = array( | |
| 367 | + 'post-new.php', | |
| 368 | + 'post.php', | |
| 369 | + 'upload.php', | |
| 370 | + 'customize.php', | |
| 371 | + ); | |
| 372 | + | |
| 373 | + // Only load on the post, new post, or upload pages. | |
| 374 | + if ( ! in_array( $pagenow, $acceptable_pages, true ) ) { | |
| 375 | + return false; | |
| 376 | + } | |
| 377 | + | |
| 378 | + return $this->is_videopress_enabled(); | |
| 379 | + } | |
| 380 | + | |
| 381 | + /** | |
| 382 | + * Detects if VideoPress is enabled. | |
| 383 | + * | |
| 384 | + * @return bool | |
| 385 | + */ | |
| 386 | + protected function is_videopress_enabled() { | |
| 387 | + $options = VideoPress_Options::get_options(); | |
| 388 | + | |
| 389 | + return $options['shadow_blog_id'] > 0; | |
| 390 | + } | |
| 391 | + | |
| 392 | + /** | |
| 393 | + * A work-around / hack to make it possible to go to the media library with the add new box open. | |
| 394 | + * | |
| 395 | + * @return bool | |
| 396 | + */ | |
| 397 | + public function print_in_footer_open_media_add_new() { | |
| 398 | + global $pagenow; | |
| 399 | + | |
| 400 | + // Only load in the admin | |
| 401 | + if ( ! is_admin() ) { | |
| 402 | + return false; | |
| 403 | + } | |
| 404 | + | |
| 405 | + if ( $pagenow !== 'upload.php' ) { | |
| 406 | + return false; | |
| 407 | + } | |
| 408 | + | |
| 409 | + if ( ! isset( $_GET['action'] ) || $_GET['action'] !== 'add-new' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended | |
| 410 | + return false; | |
| 411 | + } | |
| 412 | + | |
| 413 | + ?> | |
| 414 | + <script type="text/javascript"> | |
| 415 | + ( function( $ ) { | |
| 416 | + window.setTimeout( function() { | |
| 417 | + $('#wp-media-grid .page-title-action').click(); | |
| 418 | + }, 500 ); | |
| 419 | + | |
| 420 | + }( jQuery ) ); | |
| 421 | + </script> | |
| 422 | + <?php | |
| 423 | + } | |
| 424 | + | |
| 425 | + /** | |
| 426 | + * Makes sure that all video mimes are added in, as multi site installs can remove them. | |
| 427 | + * | |
| 428 | + * @deprecated 11.3 | |
| 429 | + * | |
| 430 | + * @param array $existing_mimes Mime types to extend/filter. | |
| 431 | + * @return array | |
| 432 | + */ | |
| 433 | + public function add_video_upload_mimes( $existing_mimes = array() ) { | |
| 434 | + _deprecated_function( __METHOD__, 'jetpack-11.3', 'Automattic\Jetpack\VideoPress\Attachment_Handler::add_video_upload_mimes' ); | |
| 435 | + return Attachment_Handler::add_video_upload_mimes( $existing_mimes ); | |
| 436 | + } | |
| 437 | + | |
| 438 | + /** | |
| 439 | + * Filter designed to get rid of non video mime types. | |
| 440 | + * | |
| 441 | + * @deprecated 11.3 | |
| 442 | + * | |
| 443 | + * @param string $value Mime type to filter. | |
| 444 | + * @return int | |
| 445 | + */ | |
| 446 | + public function filter_video_mimes( $value ) { | |
| 447 | + _deprecated_function( __METHOD__, 'jetpack-11.3', 'Automattic\Jetpack\VideoPress\Attachment_Handler::filter_video_mimes' ); | |
| 448 | + return Attachment_Handler::filter_video_mimes( $value ); | |
| 449 | + } | |
| 450 | + | |
| 451 | + /** | |
| 452 | + * Filter the mime type icon. | |
| 453 | + * | |
| 454 | + * @param string $icon Icon path. | |
| 455 | + * @param string $mime Mime type. | |
| 456 | + * @param int $post_id Post ID. | |
| 457 | + * | |
| 458 | + * @deprecated 11.3 | |
| 459 | + * | |
| 460 | + * @return string | |
| 461 | + */ | |
| 462 | + public function wp_mime_type_icon( $icon, $mime, $post_id ) { | |
| 463 | + _deprecated_function( __METHOD__, 'jetpack-11.3', 'Automattic\Jetpack\VideoPress\Attachment_Handler::wp_mime_type_icon' ); | |
| 464 | + return Attachment_Handler::wp_mime_type_icon( $icon, $mime, $post_id ); | |
| 465 | + } | |
| 466 | + | |
| 467 | + /** | |
| 468 | + * Filter the list of supported video formats. | |
| 469 | + * | |
| 470 | + * @param array $extensions Supported video formats. | |
| 471 | + * | |
| 472 | + * @deprecated 11.3 | |
| 473 | + * | |
| 474 | + * @return array | |
| 475 | + */ | |
| 476 | + public function add_videopress_extenstion( $extensions ) { | |
| 477 | + _deprecated_function( __METHOD__, 'jetpack-11.3', 'Automattic\Jetpack\VideoPress\Attachment_Handler::add_videopress_extenstion' ); | |
| 478 | + return Attachment_Handler::add_videopress_extenstion( $extensions ); | |
| 479 | + } | |
| 480 | +} | |
| 481 | + | |
| 482 | +// Initialize the module. | |
| 483 | +Jetpack_VideoPress::init(); | |