Automattic /
jetpack
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * We won't have any videos less than sixty pixels wide. That would be silly. |
||
| 5 | */ |
||
| 6 | defined( 'VIDEOPRESS_MIN_WIDTH' ) or define( 'VIDEOPRESS_MIN_WIDTH', 60 ); |
||
|
0 ignored issues
–
show
|
|||
| 7 | |||
| 8 | /** |
||
| 9 | * Validate user-supplied guid values against expected inputs |
||
| 10 | * |
||
| 11 | * @since 1.1 |
||
| 12 | * @param string $guid video identifier |
||
| 13 | * @return bool true if passes validation test |
||
| 14 | */ |
||
| 15 | function videopress_is_valid_guid( $guid ) { |
||
| 16 | View Code Duplication | if ( ! empty( $guid ) && strlen( $guid ) === 8 && ctype_alnum( $guid ) ) { |
|
| 17 | return true; |
||
| 18 | } |
||
| 19 | return false; |
||
| 20 | } |
||
| 21 | |||
| 22 | /** |
||
| 23 | * Get details about a specific video by GUID: |
||
| 24 | * |
||
| 25 | * @param $guid string |
||
| 26 | * @return object |
||
| 27 | */ |
||
| 28 | function videopress_get_video_details( $guid ) { |
||
| 29 | if ( ! videopress_is_valid_guid( $guid ) ) { |
||
| 30 | return new WP_Error( 'bad-guid-format', __( 'Invalid Video GUID!', 'jetpack' ) ); |
||
| 31 | } |
||
| 32 | |||
| 33 | $version = '1.1'; |
||
| 34 | $endpoint = sprintf( '/videos/%1$s', $guid ); |
||
| 35 | $query_url = sprintf( |
||
| 36 | 'https://public-api.wordpress.com/rest/v%1$s%2$s', |
||
| 37 | $version, |
||
| 38 | $endpoint |
||
| 39 | ); |
||
| 40 | |||
| 41 | // Look for data in our transient. If nothing, let's make a new query. |
||
| 42 | $data_from_cache = get_transient( 'jetpack_videopress_' . $guid ); |
||
| 43 | if ( false === $data_from_cache ) { |
||
| 44 | $response = wp_remote_get( esc_url_raw( $query_url ) ); |
||
| 45 | $data = json_decode( wp_remote_retrieve_body( $response ) ); |
||
| 46 | |||
| 47 | // Cache the response for an hour. |
||
| 48 | set_transient( 'jetpack_videopress_' . $guid, $data, HOUR_IN_SECONDS ); |
||
| 49 | } else { |
||
| 50 | $data = $data_from_cache; |
||
| 51 | } |
||
| 52 | |||
| 53 | /** |
||
| 54 | * Allow functions to modify fetched video details. |
||
| 55 | * |
||
| 56 | * This filter allows third-party code to modify the return data |
||
| 57 | * about a given video. It may involve swapping some data out or |
||
| 58 | * adding new parameters. |
||
| 59 | * |
||
| 60 | * @since 4.0.0 |
||
| 61 | * |
||
| 62 | * @param object $data The data returned by the WPCOM API. See: https://developer.wordpress.com/docs/api/1.1/get/videos/%24guid/ |
||
| 63 | * @param string $guid The GUID of the VideoPress video in question. |
||
| 64 | */ |
||
| 65 | return apply_filters( 'videopress_get_video_details', $data, $guid ); |
||
| 66 | } |
||
| 67 | |||
| 68 | |||
| 69 | /** |
||
| 70 | * Get an attachment ID given a URL. |
||
| 71 | * |
||
| 72 | * Modified from http://wpscholar.com/blog/get-attachment-id-from-wp-image-url/ |
||
| 73 | * |
||
| 74 | * @todo: Add some caching in here. |
||
|
0 ignored issues
–
show
Comment refers to a TODO task
This check looks ``TODO``s show that something is left unfinished and should be attended to. Loading history...
|
|||
| 75 | * |
||
| 76 | * @param string $url |
||
| 77 | * |
||
| 78 | * @return int|bool Attachment ID on success, false on failure |
||
| 79 | */ |
||
| 80 | View Code Duplication | function videopress_get_attachment_id_by_url( $url ) { |
|
|
0 ignored issues
–
show
This function seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 81 | $wp_upload_dir = wp_upload_dir(); |
||
| 82 | // Strip out protocols, so it doesn't fail because searching for http: in https: dir. |
||
| 83 | $dir = set_url_scheme( trailingslashit( $wp_upload_dir['baseurl'] ), 'relative' ); |
||
| 84 | |||
| 85 | // Is URL in uploads directory? |
||
| 86 | if ( false !== strpos( $url, $dir ) ) { |
||
| 87 | |||
| 88 | $file = basename( $url ); |
||
| 89 | |||
| 90 | $query_args = array( |
||
| 91 | 'post_type' => 'attachment', |
||
| 92 | 'post_status' => 'inherit', |
||
| 93 | 'fields' => 'ids', |
||
| 94 | 'meta_query' => array( |
||
| 95 | array( |
||
| 96 | 'key' => '_wp_attachment_metadata', |
||
| 97 | 'compare' => 'LIKE', |
||
| 98 | 'value' => $file, |
||
| 99 | ), |
||
| 100 | ) |
||
| 101 | ); |
||
| 102 | |||
| 103 | $query = new WP_Query( $query_args ); |
||
| 104 | |||
| 105 | if ( $query->have_posts() ) { |
||
| 106 | foreach ( $query->posts as $attachment_id ) { |
||
| 107 | $meta = wp_get_attachment_metadata( $attachment_id ); |
||
| 108 | $original_file = basename( $meta['file'] ); |
||
| 109 | $cropped_files = wp_list_pluck( $meta['sizes'], 'file' ); |
||
| 110 | |||
| 111 | if ( $original_file === $file || in_array( $file, $cropped_files ) ) { |
||
| 112 | return (int) $attachment_id; |
||
| 113 | } |
||
| 114 | } |
||
| 115 | } |
||
| 116 | |||
| 117 | } |
||
| 118 | |||
| 119 | return false; |
||
| 120 | } |
||
| 121 | |||
| 122 | /** |
||
| 123 | * Similar to `media_sideload_image` -- but returns an ID. |
||
| 124 | * |
||
| 125 | * @param $url |
||
| 126 | * @param $attachment_id |
||
| 127 | * |
||
| 128 | * @return int|mixed|object|WP_Error |
||
| 129 | */ |
||
| 130 | View Code Duplication | function videopress_download_poster_image( $url, $attachment_id ) { |
|
|
0 ignored issues
–
show
This function seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 131 | // Set variables for storage, fix file filename for query strings. |
||
| 132 | preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $url, $matches ); |
||
| 133 | if ( ! $matches ) { |
||
|
0 ignored issues
–
show
The expression
$matches of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using Loading history...
|
|||
| 134 | return new WP_Error( 'image_sideload_failed', __( 'Invalid image URL', 'jetpack' ) ); |
||
| 135 | } |
||
| 136 | |||
| 137 | $file_array = array(); |
||
| 138 | $file_array['name'] = basename( $matches[0] ); |
||
| 139 | $file_array['tmp_name'] = download_url( $url ); |
||
| 140 | |||
| 141 | // If error storing temporarily, return the error. |
||
| 142 | if ( is_wp_error( $file_array['tmp_name'] ) ) { |
||
| 143 | return $file_array['tmp_name']; |
||
| 144 | } |
||
| 145 | |||
| 146 | // Do the validation and storage stuff. |
||
| 147 | $thumbnail_id = media_handle_sideload( $file_array, $attachment_id, null ); |
||
| 148 | |||
| 149 | // Flag it as poster image, so we can exclude it from display. |
||
| 150 | update_post_meta( $thumbnail_id, 'videopress_poster_image', 1 ); |
||
| 151 | |||
| 152 | return $thumbnail_id; |
||
| 153 | } |
||
| 154 | |||
| 155 | /** |
||
| 156 | * Creates a local media library item of a remote VideoPress video. |
||
| 157 | * |
||
| 158 | * @param $guid |
||
| 159 | * @param int $parent_id |
||
| 160 | * |
||
| 161 | * @return int|object |
||
| 162 | */ |
||
| 163 | View Code Duplication | function create_local_media_library_for_videopress_guid( $guid, $parent_id = 0 ) { |
|
|
0 ignored issues
–
show
This function seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 164 | $vp_data = videopress_get_video_details( $guid ); |
||
| 165 | if ( ! $vp_data || is_wp_error( $vp_data ) ) { |
||
| 166 | return $vp_data; |
||
| 167 | } |
||
| 168 | |||
| 169 | $args = array( |
||
| 170 | 'post_date' => $vp_data->upload_date, |
||
| 171 | 'post_title' => wp_kses( $vp_data->title, array() ), |
||
| 172 | 'post_content' => wp_kses( $vp_data->description, array() ), |
||
| 173 | 'post_mime_type' => 'video/videopress', |
||
| 174 | 'guid' => sprintf( 'https://videopress.com/v/%s', $guid ), |
||
| 175 | ); |
||
| 176 | |||
| 177 | $attachment_id = wp_insert_attachment( $args, null, $parent_id ); |
||
| 178 | |||
| 179 | if ( ! is_wp_error( $attachment_id ) ) { |
||
| 180 | update_post_meta( $attachment_id, 'videopress_guid', $guid ); |
||
| 181 | wp_update_attachment_metadata( $attachment_id, array( |
||
| 182 | 'width' => $vp_data->width, |
||
| 183 | 'height' => $vp_data->height, |
||
| 184 | ) ); |
||
| 185 | |||
| 186 | $thumbnail_id = videopress_download_poster_image( $vp_data->poster, $attachment_id ); |
||
| 187 | update_post_meta( $attachment_id, '_thumbnail_id', $thumbnail_id ); |
||
| 188 | } |
||
| 189 | |||
| 190 | return $attachment_id; |
||
| 191 | } |
||
| 192 | |||
| 193 | /** |
||
| 194 | * Helper that will look for VideoPress media items that are more than 30 minutes old, |
||
| 195 | * that have not had anything attached to them by a wpcom upload and deletes the ghost |
||
| 196 | * attachment. |
||
| 197 | * |
||
| 198 | * These happen primarily because of failed upload attempts. |
||
| 199 | * |
||
| 200 | * @return int The number of items that were cleaned up. |
||
| 201 | */ |
||
| 202 | function videopress_cleanup_media_library() { |
||
| 203 | $query_args = array( |
||
| 204 | 'post_type' => 'attachment', |
||
| 205 | 'post_status' => 'inherit', |
||
| 206 | 'post_mime_type' => 'video/videopress', |
||
| 207 | 'meta_query' => array( |
||
| 208 | array( |
||
| 209 | 'key' => 'videopress_status', |
||
| 210 | 'value' => 'new', |
||
| 211 | ), |
||
| 212 | ) |
||
| 213 | ); |
||
| 214 | |||
| 215 | $query = new WP_Query( $query_args ); |
||
| 216 | |||
| 217 | $cleaned = 0; |
||
| 218 | |||
| 219 | $now = current_time( 'timestamp' ); |
||
| 220 | |||
| 221 | if ( $query->have_posts() ) { |
||
| 222 | foreach ( $query->posts as $post ) { |
||
| 223 | $post_time = strtotime( $post->post_date_gmt ); |
||
| 224 | |||
| 225 | // If the post is older than 30 minutes, it is safe to delete it. |
||
| 226 | if ( $now - $post_time > MINUTE_IN_SECONDS * 30 ) { |
||
| 227 | // Force delete the attachment, because we don't want it appearing in the trash. |
||
| 228 | wp_delete_attachment( $post->ID, true ); |
||
| 229 | |||
| 230 | $cleaned++; |
||
| 231 | } |
||
| 232 | } |
||
| 233 | } |
||
| 234 | |||
| 235 | return $cleaned; |
||
| 236 | } |
||
| 237 | |||
| 238 | /** |
||
| 239 | * Return an absolute URI for a given filename and guid on the CDN. |
||
| 240 | * No check is performed to ensure the guid exists or the file is present. Simple centralized string builder. |
||
| 241 | * |
||
| 242 | * @param string $guid VideoPress identifier |
||
| 243 | * @param string $filename name of file associated with the guid (video file name or thumbnail file name) |
||
| 244 | * |
||
| 245 | * @return string Absolute URL of VideoPress file for the given guid. |
||
| 246 | */ |
||
| 247 | function videopress_cdn_file_url( $guid, $filename ) { |
||
| 248 | return "https://videos.files.wordpress.com/{$guid}/{$filename}"; |
||
| 249 | } |
||
| 250 | |||
| 251 | /** |
||
| 252 | * Get an array of the transcoding status for the given video post. |
||
| 253 | * |
||
| 254 | * @since 4.4 |
||
| 255 | * @param int $post_id |
||
| 256 | * @return array|bool Returns an array of statuses if this is a VideoPress post, otherwise it returns false. |
||
| 257 | */ |
||
| 258 | function videopress_get_transcoding_status( $post_id ) { |
||
| 259 | $meta = wp_get_attachment_metadata( $post_id ); |
||
| 260 | |||
| 261 | // If this has not been processed by videopress, we can skip the rest. |
||
| 262 | if ( !$meta || ! isset( $meta['videopress'] ) ) { |
||
| 263 | return false; |
||
| 264 | } |
||
| 265 | |||
| 266 | $info = (object) $meta['videopress']; |
||
| 267 | |||
| 268 | $status = array( |
||
| 269 | 'std_mp4' => isset( $info->files_status['std']['mp4'] ) ? $info->files_status['std']['mp4'] : null, |
||
| 270 | 'std_ogg' => isset( $info->files_status['std']['ogg'] ) ? $info->files_status['std']['ogg'] : null, |
||
| 271 | 'dvd_mp4' => isset( $info->files_status['dvd']['mp4'] ) ? $info->files_status['dvd']['mp4'] : null, |
||
| 272 | 'hd_mp4' => isset( $info->files_status['hd']['mp4'] ) ? $info->files_status['hd']['mp4'] : null, |
||
| 273 | ); |
||
| 274 | |||
| 275 | return $status; |
||
| 276 | } |
||
| 277 | |||
| 278 | /** |
||
| 279 | * Get the direct url to the video. |
||
| 280 | * |
||
| 281 | * @since 4.4 |
||
| 282 | * @param string $guid |
||
| 283 | * @return string |
||
| 284 | */ |
||
| 285 | function videopress_build_url( $guid ) { |
||
| 286 | return 'https://videopress.com/v/' . $guid; |
||
| 287 | } |
||
| 288 | |||
| 289 | /** |
||
| 290 | * Create an empty videopress media item that will be filled out later by an xmlrpc |
||
| 291 | * callback from the VideoPress servers. |
||
| 292 | * |
||
| 293 | * @since 4.4 |
||
| 294 | * @param string $title |
||
| 295 | * @return int|WP_Error |
||
| 296 | */ |
||
| 297 | function videopress_create_new_media_item( $title ) { |
||
| 298 | $post = array( |
||
| 299 | 'post_type' => 'attachment', |
||
| 300 | 'post_mime_type' => 'video/videopress', |
||
| 301 | 'post_title' => $title, |
||
| 302 | 'post_content' => '', |
||
| 303 | ); |
||
| 304 | |||
| 305 | $media_id = wp_insert_post( $post ); |
||
| 306 | |||
| 307 | add_post_meta( $media_id, 'videopress_status', 'new' ); |
||
| 308 | |||
| 309 | return $media_id; |
||
| 310 | } |
||
| 311 | |||
| 312 | |||
| 313 | /** |
||
| 314 | * Check to see if a video has completed processing. |
||
| 315 | * |
||
| 316 | * @since 4.4 |
||
| 317 | * @param int $post_id |
||
| 318 | * @return bool |
||
| 319 | */ |
||
| 320 | function videopress_is_finished_processing( $post_id ) { |
||
| 321 | $post = get_post( $post_id ); |
||
| 322 | |||
| 323 | if ( is_wp_error( $post ) ) { |
||
| 324 | return false; |
||
| 325 | } |
||
| 326 | |||
| 327 | $meta = wp_get_attachment_metadata( $post->ID ); |
||
| 328 | |||
| 329 | if ( ! isset( $meta['videopress'] ) || ! is_array( $meta['videopress'] ) ) { |
||
| 330 | return false; |
||
| 331 | } |
||
| 332 | |||
| 333 | // These are explicitly declared to avoid doing unnecessary loops across two levels of arrays. |
||
| 334 | View Code Duplication | if ( isset( $meta['videopress']['files_status']['hd'] ) && $meta['videopress']['files_status']['hd'] != 'DONE' ) { |
|
| 335 | return false; |
||
| 336 | } |
||
| 337 | |||
| 338 | View Code Duplication | if ( isset( $meta['videopress']['files_status']['dvd'] ) && $meta['videopress']['files_status']['dvd'] != 'DONE' ) { |
|
| 339 | return false; |
||
| 340 | } |
||
| 341 | |||
| 342 | View Code Duplication | if ( isset( $meta['videopress']['files_status']['std']['mp4'] ) && $meta['videopress']['files_status']['std']['mp4'] != 'DONE' ) { |
|
| 343 | return false; |
||
| 344 | } |
||
| 345 | |||
| 346 | View Code Duplication | if ( isset( $meta['videopress']['files_status']['std']['ogg'] ) && $meta['videopress']['files_status']['std']['ogg'] != 'DONE' ) { |
|
| 347 | return false; |
||
| 348 | } |
||
| 349 | |||
| 350 | return true; |
||
| 351 | } |
||
| 352 | |||
| 353 | |||
| 354 | /** |
||
| 355 | * Update the meta information status for the given video post. |
||
| 356 | * |
||
| 357 | * @since 4.4 |
||
| 358 | * @param int $post_id |
||
| 359 | * @return bool |
||
| 360 | */ |
||
| 361 | function videopress_update_meta_data( $post_id ) { |
||
| 362 | |||
| 363 | $meta = wp_get_attachment_metadata( $post_id ); |
||
| 364 | |||
| 365 | // If this has not been processed by VideoPress, we can skip the rest. |
||
| 366 | if ( ! $meta || ! isset( $meta['videopress'] ) ) { |
||
| 367 | return false; |
||
| 368 | } |
||
| 369 | |||
| 370 | $info = (object) $meta['videopress']; |
||
| 371 | |||
| 372 | $result = wp_remote_get( videopress_make_video_get_path( $info->guid ) ); |
||
| 373 | |||
| 374 | if ( is_wp_error( $result ) ) { |
||
| 375 | return false; |
||
| 376 | } |
||
| 377 | |||
| 378 | $response = json_decode( $result['body'], true ); |
||
| 379 | |||
| 380 | // Update the attachment metadata. |
||
| 381 | $meta['videopress'] = $response; |
||
| 382 | |||
| 383 | wp_update_attachment_metadata( $post_id, $meta ); |
||
| 384 | |||
| 385 | return true; |
||
| 386 | } |
||
| 387 | |||
| 388 | |||
| 389 | |||
| 390 | /** |
||
| 391 | * Get the video update path |
||
| 392 | * |
||
| 393 | * @since 4.4 |
||
| 394 | * @param string $guid |
||
| 395 | * @return string |
||
| 396 | */ |
||
| 397 | function videopress_make_video_get_path( $guid ) { |
||
| 398 | return sprintf( |
||
| 399 | '%s://%s/rest/v%s/videos/%s', |
||
| 400 | 'https', |
||
| 401 | JETPACK__WPCOM_JSON_API_HOST, |
||
| 402 | Jetpack_Client::WPCOM_JSON_API_VERSION, |
||
| 403 | $guid |
||
| 404 | ); |
||
| 405 | } |
||
| 406 | |||
| 407 | /** |
||
| 408 | * Get the upload api path. |
||
| 409 | * |
||
| 410 | * @since 4.4 |
||
| 411 | * @param int $blog_id The id of the blog we're uploading to. |
||
| 412 | * @return string |
||
| 413 | */ |
||
| 414 | function videopress_make_media_upload_path( $blog_id ) { |
||
| 415 | return sprintf( |
||
| 416 | 'https://%s/rest/v1.1/sites/%s/videos/new', |
||
| 417 | JETPACK__WPCOM_JSON_API_HOST, |
||
| 418 | $blog_id |
||
| 419 | ); |
||
| 420 | } |
PHP has two types of connecting operators (logical operators, and boolean operators):
and&&or||The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like
&&, or||.Let’s take a look at a few examples:
Logical Operators are used for Control-Flow
One case where you explicitly want to use logical operators is for control-flow such as this:
Since
dieintroduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined withthrowat this point:These limitations lead to logical operators rarely being of use in current PHP code.