Completed
Push — v2/videopress ( 00803f...fad9d3 )
by George
20:00 queued 09:44
created

Jetpack_VideoPress::jetpack_modules_loaded()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 30
rs 8.439
cc 6
eloc 17
nc 8
nop 0
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( 'jetpack_activate_module_videopress', array( $this, 'jetpack_module_activated' ) );
27
		add_action( 'jetpack_deactivate_module_videopress', array( $this, 'jetpack_module_deactivated' ) );
28
29
		require_once( dirname( __FILE__ ) . '/shortcode.php' );
30
	}
31
32
	/**
33
	 * Fires on init since is_connection_owner should wait until the user is initialized by $wp->init();
34
	 */
35
	function on_init() {
36
		$options = $this->get_options();
37
38
		// Only the connection owner can configure this module.
39
		if ( $this->is_connection_owner() ) {
40
			Jetpack::enable_module_configurable( $this->module );
41
			Jetpack::module_configuration_load( $this->module, array( $this, 'jetpack_configuration_load' ) );
42
			Jetpack::module_configuration_screen( $this->module, array( $this, 'jetpack_configuration_screen' ) );
43
		}
44
45
		// Only if the current user can manage the VideoPress library and one has been connected.
46
		if ( $this->can( 'read_videos' ) && $options['blog_id'] ) {
47
			add_action( 'wp_enqueue_media', array( $this, 'enqueue_admin_scripts' ) );
48
			add_action( 'print_media_templates', array( $this, 'print_media_templates' ) );
49
50
			// Load these at priority -1 so they're fired before Core's are.
51
			add_action( 'wp_ajax_query-attachments', array( $this, 'wp_ajax_query_attachments' ), -1 );
52
			add_action( 'wp_ajax_save-attachment', array( $this, 'wp_ajax_save_attachment' ), -1 );
53
			add_action( 'wp_ajax_save-attachment-compat', array( $this, 'wp_ajax_save_attachment' ), -1 );
54
			add_action( 'wp_ajax_delete-post', array( $this, 'wp_ajax_delete_post' ), -1 );
55
56
			add_action( 'admin_menu', array( $this, 'admin_menu' ) );
57
		}
58
59
		if ( $this->can( 'upload_videos' ) && $options['blog_id'] ) {
60
			add_action( 'wp_ajax_videopress-get-upload-token', array( $this, 'wp_ajax_videopress_get_upload_token' ) );
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
	 * Get VideoPress options
83
	 */
84
	function get_options() {
85
		$defaults = array(
86
			'blogs' => array(),
87
			'blog_id' => 0,
88
			'access' => '',
89
			'allow-upload' => false,
90
			'freedom' => false,
91
			'hd' => false,
92
			'meta' => array(
93
				'max_upload_size' => 0,
94
			),
95
		);
96
97
		$options = Jetpack_Options::get_option( $this->option_name, array() );
98
99
		// If options have not been saved yet, check for older VideoPress plugin options.
100
		if ( empty( $options ) ) {
101
			$options['freedom'] = (bool) get_option( 'video_player_freedom', false );
102
			$options['hd'] = (bool) get_option( 'video_player_high_quality', false );
103
		}
104
105
		$options = array_merge( $defaults, $options );
106
		return $options;
107
	}
108
109
	/**
110
	 * Update VideoPress options
111
	 */
112
	function update_options( $options ) {
113
		Jetpack_Options::update_option( $this->option_name, $options );
114
	}
115
116
	/**
117
	 * Runs when the VideoPress module is activated.
118
	 */
119
	function jetpack_module_activated() {
120
		if ( ! $this->is_connection_owner() )
121
			return;
122
123
		$options = $this->get_options();
124
125
		// Ask WordPress.com for a list of VideoPress blogs
126
		$result = $this->query( 'jetpack.vpGetBlogs' );
127
		if ( ! is_wp_error( $result ) )
128
			$options['blogs'] = $result;
129
130
		// If there's at least one available blog, let's use it.
131
		if ( is_array( $options['blogs'] ) && count( $options['blogs'] ) > 0 )
132
			$options['blog_id'] = $options['blogs'][0]['blog_id'];
133
134
		$this->update_options( $options );
135
	}
136
137
	/**
138
	 * Runs when the VideoPress module is deactivated.
139
	 */
140
	function jetpack_module_deactivated() {
141
		Jetpack_Options::delete_option( $this->option_name );
142
	}
143
144
	/**
145
	 * Remote Query
146
	 *
147
	 * Performs a remote XML-RPC query using Jetpack's IXR Client. And also
148
	 * appends some useful stuff about this setup to the query.
149
	 *
150
	 * @return the Jetpack_IXR_Client object after querying.
151
	 */
152
	function query( $method, $args = null ) {
153
		$options = $this->get_options();
154
		Jetpack::load_xml_rpc_client();
155
		$xml = new Jetpack_IXR_Client( array(
156
			'user_id' => JETPACK_MASTER_USER, // All requests are on behalf of the connection owner.
157
		) );
158
159
		$params = array(
160
			'args' => $args,
161
			'video_blog_id' => $options['blog_id'],
162
			'caps' => array(),
163
		);
164
165
		// Let Jetpack know about our local caps.
166 View Code Duplication
		foreach ( array( 'read_videos', 'edit_videos', 'delete_videos', 'upload_videos' ) as $cap )
167
			if ( $this->can( $cap ) )
168
				$params['caps'][] = $cap;
169
170
		$xml->query( $method, $params );
171
172
		if ( $xml->isError() )
173
			return new WP_Error( 'xml_rpc_error', 'An XML-RPC error has occurred.' );
174
175
		$response = $xml->getResponse();
176
177
		// If there's any metadata with the response, save it for future use.
178
		if ( is_array( $response ) && isset( $response['meta'] ) ) {
179
			$options = $this->get_options();
180
			if ( $response['meta'] !== $options['meta'] ) {
181
				$options['meta'] = array_merge( $options['meta'], $response['meta'] );
182
				$this->update_options( $options );
183
			}
184
		}
185
186
		if ( is_array( $response ) && isset( $response['result'] ) )
187
			return $response['result'];
188
189
		return $response;
190
	}
191
192
	/**
193
	 * Runs before the VideoPress Configuration screen loads, useful
194
	 * to update options and yield errors.
195
	 */
196
	function jetpack_configuration_load() {
197
		$this->enqueue_admin_scripts();
198
199
		/**
200
		 * Save configuration
201
		 */
202
		if ( ! empty( $_POST['action'] ) && $_POST['action'] == 'videopress-save' ) {
203
			check_admin_referer( 'videopress-settings' );
204
			$options = $this->get_options();
205
206
			if ( isset( $_POST['blog_id'] ) && in_array( $_POST['blog_id'], wp_list_pluck( $options['blogs'], 'blog_id' ) ) )
207
				$options['blog_id'] = $_POST['blog_id'];
208
209
			// Allow the None setting too.
210
			if ( isset( $_POST['blog_id'] ) && $_POST['blog_id'] == 0 )
211
				$options['blog_id'] = 0;
212
213
			/**
214
			 * @see $this->can()
215
			 */
216
			if ( isset( $_POST['videopress-access'] ) && in_array( $_POST['videopress-access'], array( '', 'read', 'edit', 'delete' ) ) )
217
				$options['access'] = $_POST['videopress-access'];
218
219
			$options['freedom'] = isset( $_POST['videopress-freedom'] );
220
			$options['hd'] = isset( $_POST['videopress-hd'] );
221
222
			// Allow upload only if some level of access has been granted, and uploads were allowed.
223
			$options['allow-upload'] = false;
224
			if ( ! empty( $options['access'] ) && isset( $_POST['videopress-upload'] ) )
225
				$options['allow-upload'] = true;
226
227
			$this->update_options( $options );
228
			Jetpack::state( 'message', 'module_configured' );
229
			wp_safe_redirect( Jetpack::module_configuration_url( $this->module ) );
230
		}
231
232
		/**
233
		 * Refresh the list of available WordPress.com blogs
234
		 */
235
		if ( ! empty( $_GET['videopress'] ) && $_GET['videopress'] == 'refresh-blogs' ) {
236
			check_admin_referer( 'videopress-settings' );
237
			$options = $this->get_options();
238
239
			$result = $this->query( 'jetpack.vpGetBlogs' );
240
			if ( ! is_wp_error( $result ) ) {
241
				$options['blogs'] = $result;
242
				$this->update_options( $options );
243
			}
244
245
			wp_safe_redirect( Jetpack::module_configuration_url( $this->module ) );
246
		}
247
	}
248
249
	/**
250
	 * Renders the VideoPress Configuration screen in Jetpack.
251
	 */
252
	function jetpack_configuration_screen() {
253
		$options = $this->get_options();
254
		$refresh_url = wp_nonce_url( add_query_arg( 'videopress', 'refresh-blogs' ), 'videopress-settings' );
255
		?>
256
		<div class="narrow">
257
			<form method="post" id="videopress-settings">
258
				<input type="hidden" name="action" value="videopress-save" />
259
				<?php wp_nonce_field( 'videopress-settings' ); ?>
260
261
				<table id="menu" class="form-table">
262
					<tr>
263
						<th scope="row" colspan="2">
264
							<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>
265
						</th>
266
					</tr>
267
					<tr>
268
						<th scope="row">
269
							<label><?php _e( 'Connected WordPress.com Blog', 'jetpack' ); ?></label>
270
						</th>
271
						<td>
272
							<select name="blog_id">
273
								<option value="0" <?php selected( $options['blog_id'], 0 ); ?>> <?php esc_html_e( 'None', 'jetpack' ); ?></option>
274
								<?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...
275
								<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>
276
								<?php endforeach; ?>
277
							</select>
278
							<p class="description"><?php _e( 'Only videos from the selected blog will be available in your media library.', 'jetpack' ); ?>
279
								<?php printf( __( '<a href="%s">Click here</a> to refresh this list.', 'jetpack' ), esc_url( $refresh_url ) ); ?>
280
							</p>
281
						</td>
282
					</tr>
283
					<tr>
284
						<th scope="row">
285
							<label><?php _e( 'Video Library Access', 'jetpack' ); ?></label>
286
						</th>
287
						<td>
288
							<label><input type="radio" name="videopress-access" value="" <?php checked( '', $options['access'] ); ?> />
289
								<?php _e( 'Do not allow other users to access my VideoPress library', 'jetpack' ); ?></label><br/>
290
							<label><input type="radio" name="videopress-access" value="read" <?php checked( 'read', $options['access'] ); ?> />
291
								<?php _e( 'Allow users to access my videos', 'jetpack' ); ?></label><br/>
292
							<label><input type="radio" name="videopress-access" value="edit" <?php checked( 'edit', $options['access'] ); ?> />
293
								<?php _e( 'Allow users to access and edit my videos', 'jetpack' ); ?></label><br/>
294
							<label><input type="radio" name="videopress-access" value="delete" <?php checked( 'delete', $options['access'] ); ?> />
295
								<?php _e( 'Allow users to access, edit, and delete my videos', 'jetpack' ); ?></label><br/><br />
296
297
							<label><input type="checkbox" name="videopress-upload" value="1" <?php checked( $options['allow-upload'] ); ?> />
298
								<?php _e( 'Allow users to upload videos', 'jetpack' ); ?></label><br />
299
						</td>
300
					</tr>
301
					<tr>
302
						<th scope="row">
303
							<label for="videopress-freedom"><?php _e( 'Free formats', 'jetpack' ); ?></label>
304
						</th>
305
						<td>
306
							<label><input type="checkbox" name="videopress-freedom" id="videopress-freedom" <?php checked( $options['freedom'] ); ?> />
307
								<?php _e( 'Only display videos in free software formats', 'jetpack' ); ?></label>
308
							<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>
309
						</td>
310
					</tr>
311
					<tr>
312
						<th scope="row">
313
							<label for="videopress-hd"><?php _e( 'Default quality', 'jetpack' ); ?></label>
314
						</th>
315
						<td>
316
							<label><input type="checkbox" name="videopress-hd" id="videopress-hd" <?php checked( $options['hd'] ); ?> />
317
								<?php _e( 'Display higher quality video by default.', 'jetpack' ); ?></label>
318
							<p class="description"><?php _e( 'This setting may be overridden for individual videos.', 'jetpack' ); ?></p>
319
						</td>
320
					</tr>
321
				</table>
322
323
				<?php submit_button(); ?>
324
			</form>
325
		</div>
326
		<?php
327
	}
328
329
	function admin_menu() {
330
		add_media_page( __( 'VideoPress Library', 'jetpack' ), __( 'VideoPress', 'jetpack' ), 'upload_files', 'videopress-library', array( $this, 'admin_menu_library' ) );
331
	}
332
333
	function admin_menu_library() {
334
		wp_enqueue_media();
335
		$this->enqueue_admin_scripts();
336
		?>
337
		<div class="wrap" style="max-width: 600px;">
338
			<?php screen_icon(); ?>
339
	        <h2><?php _e( 'VideoPress Library', 'jetpack' ); ?></h2>
340
	        <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>
341
	        <p class="hide-if-no-js"><a href="#" id="videopress-browse" class="button"><?php _e( 'Browse Your VideoPress Library', 'jetpack' ); ?></a></p>
342
	        <p class="hide-if-js description"><?php _e( 'Please enable JavaScript support in your browser to use VideoPress.', 'jetpack' ); ?></p>
343
	    </div>
344
		<?php
345
	}
346
347
	/**
348
	 * A can of coke
349
	 *
350
	 * Similar to current_user_can, but internal to VideoPress. Returns
351
	 * true if the given VideoPress capability is allowed by the given user.
352
	 */
353
	function can( $cap, $user_id = false ) {
354
		if ( ! $user_id )
355
			$user_id = get_current_user_id();
356
357
		// Connection owners are allowed to do all the things.
358
		if ( $this->is_connection_owner( $user_id ) )
359
			return true;
360
361
		/**
362
		 * The access setting can be set by the connection owner, to allow sets
363
		 * of operations to other site users. Each access value corresponds to
364
		 * an array of things they can do.
365
		 */
366
367
		$options = $this->get_options();
368
		$map = array(
369
			'read'   => array( 'read_videos' ),
370
			'edit'   => array( 'read_videos', 'edit_videos' ),
371
			'delete' => array( 'read_videos', 'edit_videos', 'delete_videos' ),
372
		);
373
374
		if ( ! array_key_exists( $options['access'], $map ) )
375
			return false;
376
377
		if ( ! in_array( $cap, $map[ $options['access'] ] ) && 'upload_videos' != $cap )
378
			return false;
379
380
		// Additional and intrenal caps checks
381
382
		if ( ! user_can( $user_id, 'upload_files' ) )
383
			return false;
384
385
		if ( 'edit_videos' == $cap && ! user_can( $user_id, 'edit_others_posts' ) )
386
			return false;
387
388
		if ( 'delete_videos' == $cap && ! user_can( $user_id, 'delete_others_posts' ) )
389
			return false;
390
391
		if ( 'upload_videos' == $cap && ! $options['allow-upload'] )
392
			return false;
393
394
		return true;
395
	}
396
397
	/**
398
	 * Returns true if the provided user is the Jetpack connection owner.
399
	 */
400
	function is_connection_owner( $user_id = false ) {
401
		if ( ! $user_id )
402
			$user_id = get_current_user_id();
403
404
		$user_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
405
		return $user_token && is_object( $user_token ) && isset( $user_token->external_user_id ) && $user_id === $user_token->external_user_id;
406
	}
407
408
	/**
409
	 * Our custom AJAX callback for the query-attachments action
410
	 * used in the media modal. By-passed if not for VideoPress.
411
	 */
412
	function wp_ajax_query_attachments() {
413
414
		// Watch for VideoPress calls
415
		if ( ! isset( $_POST['query']['videopress'] ) )
416
			return;
417
418
		if ( ! $this->can( 'read_videos' ) )
419
			return wp_send_json_error( 'permission denied' );
420
421
		// Get and sanitize query arguments.
422
		$query_args = $this->sanitize_wp_query_args( $_POST['query'] );
423
424
		// Fire a remote WP_Query
425
		$result = $this->query( 'jetpack.vpQuery', $query_args );
426
427
		if ( is_wp_error( $result ) )
428
			return wp_send_json_error( 'xml rpc request error' );
429
430
		$items = $result;
431
		$shortcode_handler = Jetpack_VideoPress_Shortcode::init();
432
433
		foreach ( $items as $key => $item ) {
434
435
			// Check local permissions
436
			if ( ! $this->can( 'edit_videos' ) )
437
				unset( $item['vp_nonces']['update'] );
438
439
			if ( ! $this->can( 'delete_videos' ) )
440
				unset( $item['vp_nonces']['delete'] );
441
442
			// Add a second pair of nonces for the .org blog.
443
			$item['nonces'] = array();
444 View Code Duplication
			if ( ! empty( $item['vp_nonces']['update'] ) )
445
				$item['nonces']['update'] = wp_create_nonce( 'update-videopress-post_' . $item['id'] );
446
447 View Code Duplication
			if ( ! empty( $item['vp_nonces']['delete'] ) )
448
				$item['nonces']['delete'] = wp_create_nonce( 'delete-videopress-post_' . $item['id'] );
449
450
			$item['vp_embed'] = $shortcode_handler->shortcode_callback( array(
451
				$item['vp_guid'],
452
				'autoplay' => true,
453
				'flashonly' => true,
454
				'w' => 440,
455
			) );
456
457
			$items[ $key ] = $item;
458
		}
459
460
		wp_send_json_success( $items );
461
	}
462
463
	/**
464
	 * Sanitize user-provided WP_Query arguments
465
	 *
466
	 * These might be sent to the VideoPress server, for a remote WP_Query
467
	 * call so let's make sure they're sanitized and safe to send.
468
	 */
469
	function sanitize_wp_query_args( $args ) {
470
		$args = shortcode_atts( array(
471
			'posts_per_page' => 40,
472
			'orderby' => 'date',
473
			'order' => 'desc',
474
			'paged' => 1,
475
			's' => '',
476
		), (array) $args, 'wpvideo' );
477
478
		$args['posts_per_page'] = absint( $args['posts_per_page'] );
479
480
		$args['orderby'] = strtolower( $args['orderby'] );
481
		$args['orderby'] = ( in_array( $args['orderby'], array( 'date' ) ) ) ? $args['orderby'] : 'date';
482
483
		$args['order'] = strtolower( $args['order'] );
484
		$args['order'] = ( in_array( $args['order'], array( 'asc', 'desc' ) ) ) ? $args['order'] : 'desc';
485
486
		$args['paged'] = absint( $args['paged'] );
487
		$args['s'] = sanitize_text_field( $args['s'] );
488
		return $args;
489
	}
490
491
	/**
492
	 * Custom AJAX callback for the save-attachment action. If the request was
493
	 * not for a VideoPress object, core's fallback action will kick in.
494
	 */
495
	function wp_ajax_save_attachment() {
496
		if ( ! isset( $_POST['is_videopress'] ) )
497
			return;
498
499
		if ( ! $this->can( 'edit_videos' ) )
500
			return wp_send_json_error( 'permission denied' );
501
502
		$post_id = 0;
503 View Code Duplication
		if ( ! isset( $_POST['id'] ) || ! $post_id = absint( $_POST['id'] ) )
504
			wp_send_json_error();
505
506
		if ( ! isset( $_POST['vp_nonces']['update'] ) )
507
			wp_send_json_error();
508
509
		check_ajax_referer( 'update-videopress-post_' . $post_id, 'nonce' );
510
511
		$changes = ( ! empty( $_POST['changes'] ) ) ? (array) $_POST['changes'] : array();
512
		$changes = shortcode_atts( array(
513
			'title' => null,
514
			'caption' => null,
515
			'description' => null,
516
517
			'vp_share' => null,
518
			'vp_rating' => null,
519
		), $changes, 'wpvideo' );
520
521
		if ( ! is_null( $changes['vp_share'] ) )
522
			$changes['vp_share'] = (bool) $changes['vp_share'];
523
524
		if ( ! is_null( $changes['vp_rating'] ) )
525
			$changes['vp_rating'] = ( array_key_exists( $changes['vp_rating'], $this->get_available_ratings() ) ) ? $changes['vp_rating'] : null;
526
527
		// Remove null-values
528
		foreach ( $changes as $key => $value )
529
			if ( is_null( $value ) )
530
				unset( $changes[ $key ] );
531
532
		$result = $this->query( 'jetpack.vpSaveAttachment', array(
533
			'post_id' => $post_id,
534
			'changes' => $changes,
535
			'nonce' => $_POST['vp_nonces']['update'],
536
		) );
537
538
		if ( is_wp_error( $result ) )
539
			return wp_send_json_error( 'xml rpc request error' );
540
541
		wp_send_json_success();
542
	}
543
544
	/**
545
	 * Custom AJAX callback for the delete-post action, only for VideoPress objects.
546
	 */
547
	function wp_ajax_delete_post() {
548
		if ( ! isset( $_POST['is_videopress'] ) )
549
			return;
550
551
		if ( ! $this->can( 'delete_videos' ) )
552
			return wp_send_json_error( 'permission denied' );
553
554
		$post_id = 0;
555 View Code Duplication
		if ( ! isset( $_POST['id'] ) || ! $post_id = absint( $_POST['id'] ) )
556
			wp_send_json_error();
557
558
		if ( ! isset( $_POST['vp_nonces']['delete'] ) )
559
			wp_send_json_error();
560
561
		check_ajax_referer( 'delete-videopress-post_' . $post_id );
562
563
		$result = $this->query( 'jetpack.vpDeleteAttachment', array(
564
			'post_id' => $post_id,
565
			'nonce' => $_POST['vp_nonces']['delete'],
566
		) );
567
568
		if ( is_wp_error( $result ) )
569
			return wp_send_json_error( 'xml rpc request error' );
570
571
		wp_send_json_success();
572
	}
573
574
	/**
575
	 * Register VideoPress admin scripts.
576
	 */
577
	function enqueue_admin_scripts() {
578
		if ( did_action( 'videopress_enqueue_admin_scripts' ) )
579
			return;
580
581
		wp_enqueue_script( 'videopress-admin', plugins_url( 'videopress-admin.js', __FILE__ ), array( 'jquery', 'media-views', 'media-models' ), $this->version );
582
		wp_enqueue_style( 'videopress-admin', plugins_url( 'videopress-admin.css', __FILE__ ), array(), $this->version );
583
584
		$caps = array();
585 View Code Duplication
		foreach( array( 'read_videos', 'edit_videos', 'delete_videos', 'upload_videos' ) as $cap )
586
			$caps[ $cap ] = $this->can( $cap );
587
588
		$l10n = array(
589
			'selectVideoFile' => __( 'Please select a video file to upload.', 'jetpack' ),
590
			'videoUploading' => __( 'Your video is uploading... Please do not close this window.', 'jetpack' ),
591
			'unknownError' => __( 'An unknown error has occurred. Please try again later.', 'jetpack' ),
592
			'videoUploaded' => __( 'Your video has successfully been uploaded. It will appear in your VideoPress Library shortly.', 'jetpack' ),
593
			'VideoPressLibraryRouter' => __( 'VideoPress Library', 'jetpack' ),
594
			'uploadVideoRouter' => __( 'Upload a Video', 'jetpack' ),
595
			'insertVideoButton' => __( 'Insert Video', 'jetpack' ),
596
597
		);
598
599
		wp_localize_script( 'videopress-admin', 'VideoPressAdminSettings', array(
600
			'caps' => $caps,
601
			'l10n' => $l10n,
602
		) );
603
		
604
		/**
605
		 * Fires after VideoPress scripts are enqueued in the dashboard.
606
		 *
607
		 * @since 2.5.0
608
		 */
609
		do_action( 'videopress_enqueue_admin_scripts' );
610
	}
611
612
	/**
613
	 * Get an array of available ratings. Keys are options, values are labels.
614
	 */
615
	function get_available_ratings() {
616
		return array(
617
			'G' => 'G',
618
			'PG-13' => 'PG-13',
619
			'R-17' => 'R',
620
			'X-18' => 'X',
621
		);
622
	}
623
624
	/**
625
	 * Additional VideoPress media templates.
626
	 */
627
	function print_media_templates() {
628
		$options = $this->get_options();
629
		?>
630
		<script type="text/html" id="tmpl-videopress-attachment">
631
			<# if ( data.vp_ogg_url ) { #>
632
			<label class="setting vp-setting">
633
				<span><?php _e( 'Ogg File URL', 'jetpack' ); ?></span>
634
				<input type="text" value="{{ data.vp_ogg_url }}" onclick="this.focus();this.select();" readonly />
635
				<p class="help"><?php _e( 'Location of the Ogg video file.', 'jetpack' ); ?></p>
636
			</label>
637
			<# } #>
638
639
			<label class="setting vp-setting">
640
				<span><?php _e( 'Share', 'jetpack' ); ?></span>
641
				<input class="vp-checkbox" type="checkbox" <# if ( '1' === data.vp_share ) { #>checked<# } #> <# if ( ! data.can.save ) { #>disabled<# } #> />
642
				<label>
643
					<?php _e( 'Display share menu and allow viewers to embed or download this video', 'jetpack' ); ?>
644
				</label>
645
				<input class="vp-checkbox-text" type="text" value="{{ data.vp_share }}" data-setting="vp_share" style="display:none;" />
646
			</label>
647
648
			<label class="setting vp-setting">
649
				<span><?php _e( 'Rating', 'jetpack' ); ?></span>
650
651
				<?php foreach ( $this->get_available_ratings() as $value => $label ) : ?>
652
				<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 ); ?>"
653
					<# if ( '<?php echo esc_attr( $value ); ?>' === data.vp_rating ) { #>checked<# } #>
654
					<# if ( ! data.can.save ) { #>disabled<# } #> />
655
				<label for="vp-rating-<?php echo sanitize_html_class( $value ); ?>"><?php echo esc_html( $label ); ?></label>
656
				<?php endforeach; ?>
657
658
				<input class="vp-radio-text" type="text" value="{{ data.vp_rating }}" data-setting="vp_rating" style="display:none;" />
659
			</label>
660
661
			<label class="setting vp-setting">
662
				<span><?php _e( 'Shortcode', 'jetpack' ); ?></span>
663
				<input type="text" value="[wpvideo {{ data.vp_guid }}]" onclick="this.focus();this.select();" readonly />
664
			</label>
665
666
			<label class="setting vp-setting vp-preview">
667
				<span><?php _e( 'Preview', 'jetpack' ); ?></span>
668
				<# if ( ! data.vp_thumbnail_url ) { #>
669
					<span class="videopress-preview-unavailable"><?php esc_html_e( 'The preview is unavailable while this video is being processed.', 'jetpack' ); ?></span>
670
				<# } else { #>
671
				<a href="#" class="videopress-preview" id="videopress-thumbnail-{{ data.vp_guid }}" data-videopress-guid="{{ data.vp_guid }}"><img src="{{ data.vp_thumbnail_url }}" /></a>
672
				<# } #>
673
			</label>
674
		</script>
675
676
		<script type="text/html" id="tmpl-videopress-media-modal">
677
			<div class="videopress-modal">
678
				<p><?php _e( 'Video Preview:', 'jetpack' ); ?></p>
679
				<div class="videopress-video-container">{{{ data.video }}}</div>
680
				<p class="submit">
681
					<a class="videopress-modal-close button" href="#"><?php _e( 'Close', 'jetpack' ); ?></a>
682
				</p>
683
			</div>
684
			<div class="videopress-modal-backdrop"></div>
685
		</script>
686
687
		<script type="text/html" id="tmpl-videopress-uploader">
688
			<div class="videopress-errors"></div>
689
			<form class="videopress-upload-form" action="" method="post" target="videopress_upload_frame" enctype="multipart/form-data">
690
				<input type="hidden" name="action" value="videopress_upload" />
691
				<input type="hidden" name="videopress_blog_id" value="0" />
692
				<input type="hidden" name="videopress_token" value="0" />
693
				<?php $formats = 'ogv, mp4, m4v, mov, wmv, avi, mpg, 3gp, 3g2'; ?>
694
				<?php
695
					$max_upload_size = 0;
696
					if ( ! empty( $options['meta']['max_upload_size'] ) )
697
						$max_upload_size = absint( $options['meta']['max_upload_size'] );
698
699
					$upload_size_unit = $max_upload_size;
700
					$byte_sizes = array( 'KB', 'MB', 'GB' );
701
702
					for ( $u = -1; $upload_size_unit > 1024 && $u < count( $byte_sizes ) - 1; $u++ )
703
						$upload_size_unit /= 1024;
704
705
					if ( $u < 0 ) {
706
						$upload_size_unit = 0;
707
						$u = 0;
708
					} else {
709
						$upload_size_unit = (int) $upload_size_unit;
710
					}
711
				?>
712
				<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>
713
714
				<input type="file" name="videopress_file" />
715
				<?php submit_button( __( 'Upload Video', 'jetpack' ) ); ?>
716
			</form>
717
			<iframe width="0" height="0" name="videopress_upload_frame"></iframe>
718
		</script>
719
		<?php
720
	}
721
722
	/**
723
	 * Filters the VideoPress shortcode options, makes sure that
724
	 * the settings set in Jetpack's VideoPress module are applied.
725
	 */
726
	function videopress_shortcode_options( $options ) {
727
		$videopress_options = $this->get_options();
728
729
		if ( false === $options['freedom'] )
730
			$options['freedom'] = $videopress_options['freedom'];
731
732
		$options['hd'] = $videopress_options['hd'];
733
734
		return $options;
735
	}
736
}
737
738
// Initialize the module.
739
Jetpack_VideoPress::init();
740