Completed
Push — feature/videopress-uploader ( 7d63f1...a9ff31 )
by
unknown
08:52
created

Jetpack_VideoPress::videopress_pluploder_config()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
/**
3
 * VideoPress in Jetpack
4
 *
5
 */
6
class Jetpack_VideoPress {
7
	public $module = 'videopress';
8
	public $option_name = 'videopress';
9
	public $version = 4;
10
11
	/**
12
	 * Singleton
13
	 */
14
	public static function init() {
15
		static $instance = false;
16
17
		if ( ! $instance )
18
			$instance = new Jetpack_VideoPress;
19
20
		return $instance;
21
	}
22
23
	function __construct() {
24
		$this->version = time(); // <s>ghost</s> cache busters!
25
		add_action( 'init', array( $this, 'on_init' ) );
26
		add_action( 'admin_notices', array( __CLASS__, 'handle_editor_view_js' ) );
27
		add_action( 'jetpack_activate_module_videopress', array( $this, 'jetpack_module_activated' ) );
28
		add_action( 'jetpack_deactivate_module_videopress', array( $this, 'jetpack_module_deactivated' ) );
29
	}
30
31
	/**
32
	 * Fires on init since is_connection_owner should wait until the user is initialized by $wp->init();
33
	 */
34
	function on_init() {
35
		$options = $this->get_options();
36
37
		// Only the connection owner can configure this module.
38
		if ( $this->is_connection_owner() ) {
39
			Jetpack::enable_module_configurable( $this->module );
40
			Jetpack::module_configuration_load( $this->module, array( $this, 'jetpack_configuration_load' ) );
41
			Jetpack::module_configuration_screen( $this->module, array( $this, 'jetpack_configuration_screen' ) );
42
		}
43
44
		// Only if the current user can manage the VideoPress library and one has been connected.
45
		if ( $this->can( 'read_videos' ) && $options['blog_id'] ) {
46
			add_action( 'wp_enqueue_media', array( $this, 'enqueue_admin_scripts' ) );
47
			add_action( 'print_media_templates', array( $this, 'print_media_templates' ) );
48
49
			// Load these at priority -1 so they're fired before Core's are.
50
			add_action( 'wp_ajax_query-attachments', array( $this, 'wp_ajax_query_attachments' ), -1 );
51
			add_action( 'wp_ajax_save-attachment', array( $this, 'wp_ajax_save_attachment' ), -1 );
52
			add_action( 'wp_ajax_save-attachment-compat', array( $this, 'wp_ajax_save_attachment' ), -1 );
53
			add_action( 'wp_ajax_delete-post', array( $this, 'wp_ajax_delete_post' ), -1 );
54
55
			add_action( 'admin_menu', array( $this, 'admin_menu' ) );
56
		}
57
58
		if ( $this->can( 'upload_videos' ) && $options['blog_id'] ) {
59
			add_action( 'wp_ajax_videopress-get-upload-token', array( $this, 'wp_ajax_videopress_get_upload_token' ) );
60
			add_filter( 'plupload_default_settings', array( $this, 'videopress_pluploder_config' ) );
61
		}
62
63
		add_filter( 'videopress_shortcode_options', array( $this, 'videopress_shortcode_options' ) );
64
	}
65
66
	function wp_ajax_videopress_get_upload_token() {
67
		if ( ! $this->can( 'upload_videos' ) )
68
			return wp_send_json_error();
69
70
		$result = $this->query( 'jetpack.vpGetUploadToken' );
71
		if ( is_wp_error( $result ) )
72
			return wp_send_json_error( array( 'message' => __( 'Could not obtain a VideoPress upload token. Please try again later.', 'jetpack' ) ) );
73
74
		$response = $result;
75
		if ( empty( $response['videopress_blog_id'] ) || empty( $response['videopress_token'] ) || empty( $response[ 'videopress_action_url' ] ) )
76
			return wp_send_json_error( array( 'message' => __( 'Could not obtain a VideoPress upload token. Please try again later.', 'jetpack' ) ) );
77
78
		return wp_send_json_success( $response );
79
	}
80
81
	/**
82
	 * Modify the default plupload config to turn on videopress specific filters.
83
	 */
84
	function videopress_pluploder_config( $config ) {
85
		$config['filters']['videopress_check_uploads'] = 1;
86
		return $config;
87
	}
88
89
	/**
90
	 * Get VideoPress options
91
	 */
92
	function get_options() {
93
		$defaults = array(
94
			'blogs' => array(),
95
			'blog_id' => 0,
96
			'access' => '',
97
			'allow-upload' => false,
98
			'freedom' => false,
99
			'hd' => false,
100
			'meta' => array(
101
				'max_upload_size' => 0,
102
			),
103
		);
104
105
		$options = Jetpack_Options::get_option( $this->option_name, array() );
106
107
		// If options have not been saved yet, check for older VideoPress plugin options.
108
		if ( empty( $options ) ) {
109
			$options['freedom'] = (bool) get_option( 'video_player_freedom', false );
110
			$options['hd'] = (bool) get_option( 'video_player_high_quality', false );
111
		}
112
113
		$options = array_merge( $defaults, $options );
114
		return $options;
115
	}
116
117
	/**
118
	 * Update VideoPress options
119
	 */
120
	function update_options( $options ) {
121
		Jetpack_Options::update_option( $this->option_name, $options );
122
	}
123
124
	/**
125
	 * Runs when the VideoPress module is activated.
126
	 */
127
	function jetpack_module_activated() {
128
		if ( ! $this->is_connection_owner() )
129
			return;
130
131
		$options = $this->get_options();
132
133
		// Ask WordPress.com for a list of VideoPress blogs
134
		$result = $this->query( 'jetpack.vpGetBlogs' );
135
		if ( ! is_wp_error( $result ) )
136
			$options['blogs'] = $result;
137
138
		// If there's at least one available blog, let's use it.
139
		if ( is_array( $options['blogs'] ) && count( $options['blogs'] ) > 0 )
140
			$options['blog_id'] = $options['blogs'][0]['blog_id'];
141
142
		$this->update_options( $options );
143
	}
144
145
	/**
146
	 * Runs when the VideoPress module is deactivated.
147
	 */
148
	function jetpack_module_deactivated() {
149
		Jetpack_Options::delete_option( $this->option_name );
150
	}
151
152
	/**
153
	 * Remote Query
154
	 *
155
	 * Performs a remote XML-RPC query using Jetpack's IXR Client. And also
156
	 * appends some useful stuff about this setup to the query.
157
	 *
158
	 * @return the Jetpack_IXR_Client object after querying.
159
	 */
160
	function query( $method, $args = null ) {
161
		$options = $this->get_options();
162
		Jetpack::load_xml_rpc_client();
163
		$xml = new Jetpack_IXR_Client( array(
164
			'user_id' => JETPACK_MASTER_USER, // All requests are on behalf of the connection owner.
165
		) );
166
167
		$params = array(
168
			'args' => $args,
169
			'video_blog_id' => $options['blog_id'],
170
			'caps' => array(),
171
		);
172
173
		// Let Jetpack know about our local caps.
174 View Code Duplication
		foreach ( array( 'read_videos', 'edit_videos', 'delete_videos', 'upload_videos' ) as $cap )
175
			if ( $this->can( $cap ) )
176
				$params['caps'][] = $cap;
177
178
		$xml->query( $method, $params );
179
180
		if ( $xml->isError() )
181
			return new WP_Error( 'xml_rpc_error', 'An XML-RPC error has occurred.' );
182
183
		$response = $xml->getResponse();
184
185
		// If there's any metadata with the response, save it for future use.
186
		if ( is_array( $response ) && isset( $response['meta'] ) ) {
187
			$options = $this->get_options();
188
			if ( $response['meta'] !== $options['meta'] ) {
189
				$options['meta'] = array_merge( $options['meta'], $response['meta'] );
190
				$this->update_options( $options );
191
			}
192
		}
193
194
		if ( is_array( $response ) && isset( $response['result'] ) )
195
			return $response['result'];
196
197
		return $response;
198
	}
199
200
	/**
201
	 * Runs before the VideoPress Configuration screen loads, useful
202
	 * to update options and yield errors.
203
	 */
204
	function jetpack_configuration_load() {
205
		$this->enqueue_admin_scripts();
206
207
		/**
208
		 * Save configuration
209
		 */
210
		if ( ! empty( $_POST['action'] ) && $_POST['action'] == 'videopress-save' ) {
211
			check_admin_referer( 'videopress-settings' );
212
			$options = $this->get_options();
213
214
			if ( isset( $_POST['blog_id'] ) && in_array( $_POST['blog_id'], wp_list_pluck( $options['blogs'], 'blog_id' ) ) )
215
				$options['blog_id'] = $_POST['blog_id'];
216
217
			// Allow the None setting too.
218
			if ( isset( $_POST['blog_id'] ) && $_POST['blog_id'] == 0 )
219
				$options['blog_id'] = 0;
220
221
			/**
222
			 * @see $this->can()
223
			 */
224
			if ( isset( $_POST['videopress-access'] ) && in_array( $_POST['videopress-access'], array( '', 'read', 'edit', 'delete' ) ) )
225
				$options['access'] = $_POST['videopress-access'];
226
227
			$options['freedom'] = isset( $_POST['videopress-freedom'] );
228
			$options['hd'] = isset( $_POST['videopress-hd'] );
229
230
			// Allow upload only if some level of access has been granted, and uploads were allowed.
231
			$options['allow-upload'] = false;
232
			if ( ! empty( $options['access'] ) && isset( $_POST['videopress-upload'] ) )
233
				$options['allow-upload'] = true;
234
235
			$this->update_options( $options );
236
			Jetpack::state( 'message', 'module_configured' );
237
			wp_safe_redirect( Jetpack::module_configuration_url( $this->module ) );
238
		}
239
240
		/**
241
		 * Refresh the list of available WordPress.com blogs
242
		 */
243
		if ( ! empty( $_GET['videopress'] ) && $_GET['videopress'] == 'refresh-blogs' ) {
244
			check_admin_referer( 'videopress-settings' );
245
			$options = $this->get_options();
246
247
			$result = $this->query( 'jetpack.vpGetBlogs' );
248
			if ( ! is_wp_error( $result ) ) {
249
				$options['blogs'] = $result;
250
				$this->update_options( $options );
251
			}
252
253
			wp_safe_redirect( Jetpack::module_configuration_url( $this->module ) );
254
		}
255
	}
256
257
	/**
258
	 * Renders the VideoPress Configuration screen in Jetpack.
259
	 */
260
	function jetpack_configuration_screen() {
261
		$options = $this->get_options();
262
		$refresh_url = wp_nonce_url( add_query_arg( 'videopress', 'refresh-blogs' ), 'videopress-settings' );
263
		?>
264
		<div class="narrow">
265
			<form method="post" id="videopress-settings">
266
				<input type="hidden" name="action" value="videopress-save" />
267
				<?php wp_nonce_field( 'videopress-settings' ); ?>
268
269
				<table id="menu" class="form-table">
270
					<tr>
271
						<th scope="row" colspan="2">
272
							<p><?php _e( 'Please note that the VideoPress module requires a WordPress.com account with an active <a href="http://store.wordpress.com/premium-upgrades/videopress/" target="_blank">VideoPress subscription</a>.', 'jetpack' ); ?></p>
273
						</th>
274
					</tr>
275
					<tr>
276
						<th scope="row">
277
							<label><?php _e( 'Connected WordPress.com Blog', 'jetpack' ); ?></label>
278
						</th>
279
						<td>
280
							<select name="blog_id">
281
								<option value="0" <?php selected( $options['blog_id'], 0 ); ?>> <?php esc_html_e( 'None', 'jetpack' ); ?></option>
282
								<?php foreach ( $options['blogs'] as $blog ) : ?>
0 ignored issues
show
Bug introduced by
The expression $options['blogs'] of type array|integer|string|false is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
283
								<option value="<?php echo absint( $blog['blog_id'] ); ?>" <?php selected( $options['blog_id'], $blog['blog_id'] ); ?>><?php echo esc_html( $blog['name'] ); ?> (<?php echo esc_html( $blog['domain'] ); ?>)</option>
284
								<?php endforeach; ?>
285
							</select>
286
							<p class="description"><?php _e( 'Only videos from the selected blog will be available in your media library.', 'jetpack' ); ?>
287
								<?php printf( __( '<a href="%s">Click here</a> to refresh this list.', 'jetpack' ), esc_url( $refresh_url ) ); ?>
288
							</p>
289
						</td>
290
					</tr>
291
					<tr>
292
						<th scope="row">
293
							<label><?php _e( 'Video Library Access', 'jetpack' ); ?></label>
294
						</th>
295
						<td>
296
							<label><input type="radio" name="videopress-access" value="" <?php checked( '', $options['access'] ); ?> />
297
								<?php _e( 'Do not allow other users to access my VideoPress library', 'jetpack' ); ?></label><br/>
298
							<label><input type="radio" name="videopress-access" value="read" <?php checked( 'read', $options['access'] ); ?> />
299
								<?php _e( 'Allow users to access my videos', 'jetpack' ); ?></label><br/>
300
							<label><input type="radio" name="videopress-access" value="edit" <?php checked( 'edit', $options['access'] ); ?> />
301
								<?php _e( 'Allow users to access and edit my videos', 'jetpack' ); ?></label><br/>
302
							<label><input type="radio" name="videopress-access" value="delete" <?php checked( 'delete', $options['access'] ); ?> />
303
								<?php _e( 'Allow users to access, edit, and delete my videos', 'jetpack' ); ?></label><br/><br />
304
305
							<label><input type="checkbox" name="videopress-upload" value="1" <?php checked( $options['allow-upload'] ); ?> />
306
								<?php _e( 'Allow users to upload videos', 'jetpack' ); ?></label><br />
307
						</td>
308
					</tr>
309
					<tr>
310
						<th scope="row">
311
							<label for="videopress-freedom"><?php _e( 'Free formats', 'jetpack' ); ?></label>
312
						</th>
313
						<td>
314
							<label><input type="checkbox" name="videopress-freedom" id="videopress-freedom" <?php checked( $options['freedom'] ); ?> />
315
								<?php _e( 'Only display videos in free software formats', 'jetpack' ); ?></label>
316
							<p class="description"><?php _e( 'Ogg file container with Theora video and Vorbis audio. Note that some browsers are unable to play free software video formats, including Internet Explorer and Safari.', 'jetpack' ); ?></p>
317
						</td>
318
					</tr>
319
					<tr>
320
						<th scope="row">
321
							<label for="videopress-hd"><?php _e( 'Default quality', 'jetpack' ); ?></label>
322
						</th>
323
						<td>
324
							<label><input type="checkbox" name="videopress-hd" id="videopress-hd" <?php checked( $options['hd'] ); ?> />
325
								<?php _e( 'Display higher quality video by default.', 'jetpack' ); ?></label>
326
							<p class="description"><?php _e( 'This setting may be overridden for individual videos.', 'jetpack' ); ?></p>
327
						</td>
328
					</tr>
329
				</table>
330
331
				<?php submit_button(); ?>
332
			</form>
333
		</div>
334
		<?php
335
	}
336
337
	function admin_menu() {
338
		add_media_page( __( 'VideoPress Library', 'jetpack' ), __( 'VideoPress', 'jetpack' ), 'upload_files', 'videopress-library', array( $this, 'admin_menu_library' ) );
339
	}
340
341
	function admin_menu_library() {
342
		wp_enqueue_media();
343
		$this->enqueue_admin_scripts();
344
		?>
345
		<div class="wrap" style="max-width: 600px;">
346
			<?php screen_icon(); ?>
347
	        <h2><?php _e( 'VideoPress Library', 'jetpack' ); ?></h2>
348
	        <p><?php _e( 'Use the button below to browse your VideoPress Library. Note that you can also browse your VideoPress Library while editing a post or page by using the <strong>Add Media</strong> button in the post editor.', 'jetpack' ); ?></p>
349
	        <p class="hide-if-no-js"><a href="#" id="videopress-browse" class="button"><?php _e( 'Browse Your VideoPress Library', 'jetpack' ); ?></a></p>
350
	        <p class="hide-if-js description"><?php _e( 'Please enable JavaScript support in your browser to use VideoPress.', 'jetpack' ); ?></p>
351
	    </div>
352
		<?php
353
	}
354
355
	/**
356
	 * A can of coke
357
	 *
358
	 * Similar to current_user_can, but internal to VideoPress. Returns
359
	 * true if the given VideoPress capability is allowed by the given user.
360
	 */
361
	function can( $cap, $user_id = false ) {
362
		if ( ! $user_id )
363
			$user_id = get_current_user_id();
364
365
		// Connection owners are allowed to do all the things.
366
		if ( $this->is_connection_owner( $user_id ) )
367
			return true;
368
369
		/**
370
		 * The access setting can be set by the connection owner, to allow sets
371
		 * of operations to other site users. Each access value corresponds to
372
		 * an array of things they can do.
373
		 */
374
375
		$options = $this->get_options();
376
		$map = array(
377
			'read'   => array( 'read_videos' ),
378
			'edit'   => array( 'read_videos', 'edit_videos' ),
379
			'delete' => array( 'read_videos', 'edit_videos', 'delete_videos' ),
380
		);
381
382
		if ( ! array_key_exists( $options['access'], $map ) )
383
			return false;
384
385
		if ( ! in_array( $cap, $map[ $options['access'] ] ) && 'upload_videos' != $cap )
386
			return false;
387
388
		// Additional and intrenal caps checks
389
390
		if ( ! user_can( $user_id, 'upload_files' ) )
391
			return false;
392
393
		if ( 'edit_videos' == $cap && ! user_can( $user_id, 'edit_others_posts' ) )
394
			return false;
395
396
		if ( 'delete_videos' == $cap && ! user_can( $user_id, 'delete_others_posts' ) )
397
			return false;
398
399
		if ( 'upload_videos' == $cap && ! $options['allow-upload'] )
400
			return false;
401
402
		return true;
403
	}
404
405
	/**
406
	 * Returns true if the provided user is the Jetpack connection owner.
407
	 */
408
	function is_connection_owner( $user_id = false ) {
409
		if ( ! $user_id )
410
			$user_id = get_current_user_id();
411
412
		$user_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
413
		return $user_token && is_object( $user_token ) && isset( $user_token->external_user_id ) && $user_id === $user_token->external_user_id;
414
	}
415
416
	/**
417
	 * Our custom AJAX callback for the query-attachments action
418
	 * used in the media modal. By-passed if not for VideoPress.
419
	 */
420
	function wp_ajax_query_attachments() {
421
422
		// Watch for VideoPress calls
423
		if ( ! isset( $_POST['query']['videopress'] ) )
424
			return;
425
426
		if ( ! $this->can( 'read_videos' ) )
427
			return wp_send_json_error( 'permission denied' );
428
429
		// Get and sanitize query arguments.
430
		$query_args = $this->sanitize_wp_query_args( $_POST['query'] );
431
432
		// Fire a remote WP_Query
433
		$result = $this->query( 'jetpack.vpQuery', $query_args );
434
435
		if ( is_wp_error( $result ) )
436
			return wp_send_json_error( 'xml rpc request error' );
437
438
		$items = $result;
439
440
		foreach ( $items as $key => $item ) {
441
442
			// Check local permissions
443
			if ( ! $this->can( 'edit_videos' ) )
444
				unset( $item['vp_nonces']['update'] );
445
446
			if ( ! $this->can( 'delete_videos' ) )
447
				unset( $item['vp_nonces']['delete'] );
448
449
			// Add a second pair of nonces for the .org blog.
450
			$item['nonces'] = array();
451 View Code Duplication
			if ( ! empty( $item['vp_nonces']['update'] ) )
452
				$item['nonces']['update'] = wp_create_nonce( 'update-videopress-post_' . $item['id'] );
453
454 View Code Duplication
			if ( ! empty( $item['vp_nonces']['delete'] ) )
455
				$item['nonces']['delete'] = wp_create_nonce( 'delete-videopress-post_' . $item['id'] );
456
457
			$item['vp_embed'] = videopress_shortcode_callback( array(
458
				$item['vp_guid'],
459
				'autoplay' => true,
460
				'flashonly' => true,
461
				'w' => 440,
462
			) );
463
464
			$items[ $key ] = $item;
465
		}
466
467
		wp_send_json_success( $items );
468
	}
469
470
	/**
471
	 * Sanitize user-provided WP_Query arguments
472
	 *
473
	 * These might be sent to the VideoPress server, for a remote WP_Query
474
	 * call so let's make sure they're sanitized and safe to send.
475
	 */
476
	function sanitize_wp_query_args( $args ) {
477
		$args = shortcode_atts( array(
478
			'posts_per_page' => 40,
479
			'orderby' => 'date',
480
			'order' => 'desc',
481
			'paged' => 1,
482
			's' => '',
483
		), (array) $args, 'wpvideo' );
484
485
		$args['posts_per_page'] = absint( $args['posts_per_page'] );
486
487
		$args['orderby'] = strtolower( $args['orderby'] );
488
		$args['orderby'] = ( in_array( $args['orderby'], array( 'date' ) ) ) ? $args['orderby'] : 'date';
489
490
		$args['order'] = strtolower( $args['order'] );
491
		$args['order'] = ( in_array( $args['order'], array( 'asc', 'desc' ) ) ) ? $args['order'] : 'desc';
492
493
		$args['paged'] = absint( $args['paged'] );
494
		$args['s'] = sanitize_text_field( $args['s'] );
495
		return $args;
496
	}
497
498
	/**
499
	 * Custom AJAX callback for the save-attachment action. If the request was
500
	 * not for a VideoPress object, core's fallback action will kick in.
501
	 */
502
	function wp_ajax_save_attachment() {
503
		if ( ! isset( $_POST['is_videopress'] ) )
504
			return;
505
506
		if ( ! $this->can( 'edit_videos' ) )
507
			return wp_send_json_error( 'permission denied' );
508
509
		$post_id = 0;
510 View Code Duplication
		if ( ! isset( $_POST['id'] ) || ! $post_id = absint( $_POST['id'] ) )
511
			wp_send_json_error();
512
513
		if ( ! isset( $_POST['vp_nonces']['update'] ) )
514
			wp_send_json_error();
515
516
		check_ajax_referer( 'update-videopress-post_' . $post_id, 'nonce' );
517
518
		$changes = ( ! empty( $_POST['changes'] ) ) ? (array) $_POST['changes'] : array();
519
		$changes = shortcode_atts( array(
520
			'title' => null,
521
			'caption' => null,
522
			'description' => null,
523
524
			'vp_share' => null,
525
			'vp_rating' => null,
526
		), $changes, 'wpvideo' );
527
528
		if ( ! is_null( $changes['vp_share'] ) )
529
			$changes['vp_share'] = (bool) $changes['vp_share'];
530
531
		if ( ! is_null( $changes['vp_rating'] ) )
532
			$changes['vp_rating'] = ( array_key_exists( $changes['vp_rating'], $this->get_available_ratings() ) ) ? $changes['vp_rating'] : null;
533
534
		// Remove null-values
535
		foreach ( $changes as $key => $value )
536
			if ( is_null( $value ) )
537
				unset( $changes[ $key ] );
538
539
		$result = $this->query( 'jetpack.vpSaveAttachment', array(
540
			'post_id' => $post_id,
541
			'changes' => $changes,
542
			'nonce' => $_POST['vp_nonces']['update'],
543
		) );
544
545
		if ( is_wp_error( $result ) )
546
			return wp_send_json_error( 'xml rpc request error' );
547
548
		wp_send_json_success();
549
	}
550
551
	/**
552
	 * Custom AJAX callback for the delete-post action, only for VideoPress objects.
553
	 */
554
	function wp_ajax_delete_post() {
555
		if ( ! isset( $_POST['is_videopress'] ) )
556
			return;
557
558
		if ( ! $this->can( 'delete_videos' ) )
559
			return wp_send_json_error( 'permission denied' );
560
561
		$post_id = 0;
562 View Code Duplication
		if ( ! isset( $_POST['id'] ) || ! $post_id = absint( $_POST['id'] ) )
563
			wp_send_json_error();
564
565
		if ( ! isset( $_POST['vp_nonces']['delete'] ) )
566
			wp_send_json_error();
567
568
		check_ajax_referer( 'delete-videopress-post_' . $post_id );
569
570
		$result = $this->query( 'jetpack.vpDeleteAttachment', array(
571
			'post_id' => $post_id,
572
			'nonce' => $_POST['vp_nonces']['delete'],
573
		) );
574
575
		if ( is_wp_error( $result ) )
576
			return wp_send_json_error( 'xml rpc request error' );
577
578
		wp_send_json_success();
579
	}
580
581
	/**
582
	 * Register VideoPress admin scripts.
583
	 */
584
	function enqueue_admin_scripts() {
585
		if ( did_action( 'videopress_enqueue_admin_scripts' ) )
586
			return;
587
588
		wp_enqueue_script( 'videopress-uploader', plugins_url( 'js/videopress-uploader.js', __FILE__) , array( 'jquery', 'wp-plupload' ), $this->version );
589
		wp_enqueue_script( 'videopress-admin', plugins_url( 'js/videopress-admin.js', __FILE__ ), array( 'jquery', 'media-views', 'media-models' ), $this->version );
590
		wp_enqueue_style( 'videopress-admin', plugins_url( 'videopress-admin.css', __FILE__ ), array(), $this->version );
591
592
		$caps = array();
593 View Code Duplication
		foreach( array( 'read_videos', 'edit_videos', 'delete_videos', 'upload_videos' ) as $cap )
594
			$caps[ $cap ] = $this->can( $cap );
595
596
		$l10n = array(
597
			'selectVideoFile' => __( 'Please select a video file to upload.', 'jetpack' ),
598
			'videoUploading' => __( 'Your video is uploading... Please do not close this window.', 'jetpack' ),
599
			'unknownError' => __( 'An unknown error has occurred. Please try again later.', 'jetpack' ),
600
			'videoUploaded' => __( 'Your video has successfully been uploaded. It will appear in your VideoPress Library shortly.', 'jetpack' ),
601
			'VideoPressLibraryRouter' => __( 'VideoPress Library', 'jetpack' ),
602
			'uploadVideoRouter' => __( 'Upload a Video', 'jetpack' ),
603
			'insertVideoButton' => __( 'Insert Video', 'jetpack' ),
604
605
		);
606
607
		wp_localize_script( 'videopress-admin', 'VideoPressAdminSettings', array(
608
			'caps' => $caps,
609
			'l10n' => $l10n,
610
		) );
611
		
612
		/**
613
		 * Fires after VideoPress scripts are enqueued in the dashboard.
614
		 *
615
		 * @since 2.5.0
616
		 */
617
		do_action( 'videopress_enqueue_admin_scripts' );
618
	}
619
620
	/**
621
	 * Get an array of available ratings. Keys are options, values are labels.
622
	 */
623
	function get_available_ratings() {
624
		return array(
625
			'G' => 'G',
626
			'PG-13' => 'PG-13',
627
			'R-17' => 'R',
628
			'X-18' => 'X',
629
		);
630
	}
631
632
	/**
633
	 * Additional VideoPress media templates.
634
	 */
635
	function print_media_templates() {
636
		$options = $this->get_options();
637
		?>
638
		<script type="text/html" id="tmpl-videopress-attachment">
639
			<# if ( data.vp_ogg_url ) { #>
640
			<label class="setting vp-setting">
641
				<span><?php _e( 'Ogg File URL', 'jetpack' ); ?></span>
642
				<input type="text" value="{{ data.vp_ogg_url }}" onclick="this.focus();this.select();" readonly />
643
				<p class="help"><?php _e( 'Location of the Ogg video file.', 'jetpack' ); ?></p>
644
			</label>
645
			<# } #>
646
647
			<label class="setting vp-setting">
648
				<span><?php _e( 'Share', 'jetpack' ); ?></span>
649
				<input class="vp-checkbox" type="checkbox" <# if ( '1' === data.vp_share ) { #>checked<# } #> <# if ( ! data.can.save ) { #>disabled<# } #> />
650
				<label>
651
					<?php _e( 'Display share menu and allow viewers to embed or download this video', 'jetpack' ); ?>
652
				</label>
653
				<input class="vp-checkbox-text" type="text" value="{{ data.vp_share }}" data-setting="vp_share" style="display:none;" />
654
			</label>
655
656
			<label class="setting vp-setting">
657
				<span><?php _e( 'Rating', 'jetpack' ); ?></span>
658
659
				<?php foreach ( $this->get_available_ratings() as $value => $label ) : ?>
660
				<input class="vp-radio" type="radio" name="vp-radio-group" id="vp-rating-<?php echo sanitize_html_class( $value ); ?>" value="<?php echo esc_attr( $value ); ?>"
661
					<# if ( '<?php echo esc_attr( $value ); ?>' === data.vp_rating ) { #>checked<# } #>
662
					<# if ( ! data.can.save ) { #>disabled<# } #> />
663
				<label for="vp-rating-<?php echo sanitize_html_class( $value ); ?>"><?php echo esc_html( $label ); ?></label>
664
				<?php endforeach; ?>
665
666
				<input class="vp-radio-text" type="text" value="{{ data.vp_rating }}" data-setting="vp_rating" style="display:none;" />
667
			</label>
668
669
			<label class="setting vp-setting">
670
				<span><?php _e( 'Shortcode', 'jetpack' ); ?></span>
671
				<input type="text" value="[wpvideo {{ data.vp_guid }}]" onclick="this.focus();this.select();" readonly />
672
			</label>
673
674
			<label class="setting vp-setting vp-preview">
675
				<span><?php _e( 'Preview', 'jetpack' ); ?></span>
676
				<# if ( ! data.vp_thumbnail_url ) { #>
677
					<span class="videopress-preview-unavailable"><?php esc_html_e( 'The preview is unavailable while this video is being processed.', 'jetpack' ); ?></span>
678
				<# } else { #>
679
				<a href="#" class="videopress-preview" id="videopress-thumbnail-{{ data.vp_guid }}" data-videopress-guid="{{ data.vp_guid }}"><img src="{{ data.vp_thumbnail_url }}" /></a>
680
				<# } #>
681
			</label>
682
		</script>
683
684
		<script type="text/html" id="tmpl-videopress-media-modal">
685
			<div class="videopress-modal">
686
				<p><?php _e( 'Video Preview:', 'jetpack' ); ?></p>
687
				<div class="videopress-video-container">{{{ data.video }}}</div>
688
				<p class="submit">
689
					<a class="videopress-modal-close button" href="#"><?php _e( 'Close', 'jetpack' ); ?></a>
690
				</p>
691
			</div>
692
			<div class="videopress-modal-backdrop"></div>
693
		</script>
694
695
		<script type="text/html" id="tmpl-videopress-uploader">
696
			<div class="videopress-errors"></div>
697
			<form class="videopress-upload-form" action="" method="post" target="videopress_upload_frame" enctype="multipart/form-data">
698
				<input type="hidden" name="action" value="videopress_upload" />
699
				<input type="hidden" name="videopress_blog_id" value="0" />
700
				<input type="hidden" name="videopress_token" value="0" />
701
				<?php $formats = 'ogv, mp4, m4v, mov, wmv, avi, mpg, 3gp, 3g2'; ?>
702
				<?php
703
					$max_upload_size = 0;
704
					if ( ! empty( $options['meta']['max_upload_size'] ) )
705
						$max_upload_size = absint( $options['meta']['max_upload_size'] );
706
707
					$upload_size_unit = $max_upload_size;
708
					$byte_sizes = array( 'KB', 'MB', 'GB' );
709
710
					for ( $u = -1; $upload_size_unit > 1024 && $u < count( $byte_sizes ) - 1; $u++ )
711
						$upload_size_unit /= 1024;
712
713
					if ( $u < 0 ) {
714
						$upload_size_unit = 0;
715
						$u = 0;
716
					} else {
717
						$upload_size_unit = (int) $upload_size_unit;
718
					}
719
				?>
720
				<p><?php printf( __( 'Use the form below to upload a video to your VideoPress Library. The following video formats are supported: %s. Maximum upload file size is %d%s.', 'jetpack' ), esc_html( $formats ), esc_html( $upload_size_unit ), esc_html( $byte_sizes[ $u ] ) ); ?></p>
721
722
				<input type="file" name="videopress_file" />
723
				<?php submit_button( __( 'Upload Video', 'jetpack' ) ); ?>
724
			</form>
725
			<iframe width="0" height="0" name="videopress_upload_frame"></iframe>
726
		</script>
727
		<?php
728
	}
729
730
	/**
731
	 * Filters the VideoPress shortcode options, makes sure that
732
	 * the settings set in Jetpack's VideoPress module are applied.
733
	 */
734
	function videopress_shortcode_options( $options ) {
735
		$videopress_options = $this->get_options();
736
737
		if ( false === $options['freedom'] )
738
			$options['freedom'] = $videopress_options['freedom'];
739
740
		$options['hd'] = $videopress_options['hd'];
741
742
		return $options;
743
	}
744
745
	/**
746
	 * WordPress Shortcode Editor View JS Code
747
	 */
748
	public static function handle_editor_view_js() {
749
		global $content_width;
750
		$current_screen = get_current_screen();
751
		if ( ! isset( $current_screen->id ) || $current_screen->base !== 'post' ) {
752
			return;
753
		}
754
755
		add_action( 'admin_print_footer_scripts', array( __CLASS__, 'editor_view_js_templates' ) );
756
757
		wp_enqueue_script( 'videopress-editor-view', plugins_url( 'js/editor-view.js', __FILE__ ), array( 'wp-util', 'jquery' ), false, true );
758
		wp_localize_script( 'videopress-editor-view', 'vpEditorView', array(
759
			'home_url_host'     => parse_url( home_url(), PHP_URL_HOST ),
760
			'min_content_width' => VIDEOPRESS_MIN_WIDTH,
761
			'content_width'     => $content_width,
762
			'modal_labels'      => array(
763
				'title'     => __( 'VideoPress Shortcode', 'jetpack' ),
764
				'guid'      => __( 'Video GUID', 'jetpack' ),
765
				'w'         => __( 'Width (in pixels)', 'jetpack' ),
766
				'at'        => __( 'Start how many seconds in?', 'jetpack' ),
767
				'hd'        => __( 'Default to High Definition version?', 'jetpack' ),
768
				'permalink' => __( 'Link the video title to the video\'s URL on VideoPress.com?', 'jetpack' ),
769
				'autoplay'  => __( 'Autoplay video on load?', 'jetpack' ),
770
				'loop'      => __( 'Loop playback indefinitely?', 'jetpack' ),
771
				'freedom'   => __( 'Use only Open Source codecs? (this may degrade performance)', 'jetpack' ),
772
				'flashonly' => __( 'Use the legacy flash player? (not recommended)', 'jetpack' ),
773
			)
774
		) );
775
	}
776
777
	/**
778
	 * WordPress Editor Views
779
	 */
780
	public static function editor_view_js_templates() {
781
		/**
782
		 * This template uses the following parameters, and displays the video as an iframe:
783
		 *  - data.guid     // The guid of the video.
784
		 *  - data.width    // The width of the iframe.
785
		 *  - data.height   // The height of the iframe.
786
		 *  - data.urlargs  // Arguments serialized into a get string.
787
		 *
788
		 * In addition, the calling script will need to ensure that the following
789
		 * JS file is added to the header of the editor iframe:
790
		 *  - https://s0.wp.com/wp-content/plugins/video/assets/js/next/videopress-iframe.js
791
		 */
792
		?>
793
		<script type="text/html" id="tmpl-videopress_iframe_vnext">
794
			<div class="tmpl-videopress_iframe_next">
795
				<iframe style="display: block;" width="{{ data.width }}" height="{{ data.height }}" src="https://videopress.com/embed/{{ data.guid }}?{{ data.urlargs }}" frameborder='0' allowfullscreen></iframe>
796
			</div>
797
		</script>
798
		<?php
799
	}
800
}
801
802
// Initialize the module.
803
Jetpack_VideoPress::init();
804