Plugin Directory

source: jetpack/trunk/jetpack_vendor/automattic/jetpack-videopress/src/class-attachment-handler.php @ 3068647

Last change on this file since 3068647 was 3068647, checked in by zinigor, 3 months ago

Updating trunk to version 13.3.1

File size: 8.2 KB
Line 
1<?php
2/**
3 * VideoPress Attachment_Handler
4 *
5 * @package automattic/jetpack-videopress
6 */
7
8namespace Automattic\Jetpack\VideoPress;
9
10use Automattic\Jetpack\Connection\Client;
11use Automattic\Jetpack\Current_Plan;
12
13/**
14 * VideoPress Attachment_Handler class.
15 */
16class Attachment_Handler {
17
18        /**
19         * Initializer
20         *
21         * This method should be called only once by the Initializer class. Do not call this method again.
22         */
23        public static function init() {
24
25                if ( ! Status::is_active() ) {
26                        return;
27                }
28
29                add_filter( 'wp_get_attachment_url', array( __CLASS__, 'maybe_get_attached_url_for_videopress' ), 10, 2 );
30                add_filter( 'get_attached_file', array( __CLASS__, 'maybe_get_attached_url_for_videopress' ), 10, 2 );
31
32                if ( Current_Plan::supports( 'videopress' ) ) {
33                        add_filter( 'upload_mimes', array( __CLASS__, 'add_video_upload_mimes' ), 999 );
34                }
35
36                add_filter( 'pre_delete_attachment', array( __CLASS__, 'delete_video_wpcom' ), 10, 2 );
37                add_filter( 'wp_mime_type_icon', array( __CLASS__, 'wp_mime_type_icon' ), 10, 3 );
38                add_filter( 'wp_video_extensions', array( __CLASS__, 'add_videopress_extenstion' ) );
39
40                add_filter( 'wp_prepare_attachment_for_js', array( __CLASS__, 'prepare_attachment_for_js' ) );
41                add_filter( 'ajax_query_attachments_args', array( __CLASS__, 'ajax_query_attachments_args' ) );
42                add_action( 'pre_get_posts', array( __CLASS__, 'media_list_table_query' ) );
43
44                add_filter( 'user_has_cap', array( __CLASS__, 'disable_delete_if_disconnected' ), 10, 3 );
45        }
46
47        /**
48         * Returns the VideoPress URL for the give post id, otherwise returns the provided default.
49         *
50         * This is an attachment-based filter handler.
51         *
52         * @param string $default The default return value if post id is not a VideoPress video.
53         * @param int    $post_id The post id for the current attachment.
54         */
55        public static function maybe_get_attached_url_for_videopress( $default, $post_id ) {
56                $videopress_url = videopress_get_attachment_url( $post_id );
57
58                if ( null !== $videopress_url ) {
59                        return $videopress_url;
60                }
61
62                return $default;
63        }
64
65        /**
66         * Makes sure that all video mimes are added in, as multi site installs can remove them.
67         *
68         * @param array $existing_mimes Mime types to extend/filter.
69         * @return array
70         */
71        public static function add_video_upload_mimes( $existing_mimes = array() ) {
72                $mime_types  = wp_get_mime_types();
73                $video_types = array_filter( $mime_types, array( __CLASS__, 'filter_video_mimes' ) );
74
75                foreach ( $video_types as $key => $value ) {
76                        $existing_mimes[ $key ] = $value;
77                }
78
79                // Make sure that videopress mimes are considered videos.
80                $existing_mimes['videopress'] = 'video/videopress';
81
82                return $existing_mimes;
83        }
84
85        /**
86         * Filter designed to get rid of non video mime types.
87         *
88         * @param string $value Mime type to filter.
89         * @return int
90         */
91        public static function filter_video_mimes( $value ) {
92                return preg_match( '@^video/@', $value );
93        }
94
95        /**
96         * Attempts to delete a VideoPress video from wp.com.
97         * Will block the deletion from continuing if certain errors return from the wp.com API.
98         *
99         * @param Boolean $delete if the deletion should occur or not (unused).
100         * @param WP_Post $post the post object.
101         *
102         * @return null|WP_Error|Boolean null if deletion should continue.
103         */
104        public static function delete_video_wpcom( $delete, $post ) {
105                if ( ! is_videopress_attachment( $post->ID ) ) {
106                        return null;
107                }
108
109                $guid = get_post_meta( $post->ID, 'videopress_guid', true );
110                if ( empty( $guid ) ) {
111                        self::delete_video_poster_attachment( $post->ID );
112                        return null;
113                }
114
115                // Phone home and have wp.com delete the VideoPress entry and files.
116                $wpcom_response = Client::wpcom_json_api_request_as_blog(
117                        sprintf( '/videos/%s/delete', $guid ),
118                        '1.1',
119                        array( 'method' => 'POST' )
120                );
121
122                if ( is_wp_error( $wpcom_response ) ) {
123                        return $wpcom_response;
124                }
125
126                // Upon success or a 404 (video already deleted on wp.com), return null to allow the deletion to continue.
127                if ( 200 === $wpcom_response['response']['code'] || 404 === $wpcom_response['response']['code'] ) {
128                        self::delete_video_poster_attachment( $post->ID );
129                        return null;
130                }
131
132                // Otherwise we stop the deletion from proceeding.
133                return false;
134        }
135
136        /**
137         * Deletes a video poster attachment if it exists.
138         *
139         * @param int $attachment_id the WP attachment id.
140         */
141        private static function delete_video_poster_attachment( $attachment_id ) {
142                $thumbnail_id = get_post_meta( $attachment_id, '_thumbnail_id', true );
143                if ( ! empty( $thumbnail_id ) ) {
144                        // Let's ensure this is a VP poster image before we delete it.
145                        if ( '1' === get_post_meta( $thumbnail_id, 'videopress_poster_image', true ) ) {
146                                // This call triggers the `delete_video_wpcom` filter again but it bails early at the is_videopress_attachment() check.
147                                wp_delete_attachment( $thumbnail_id );
148                        }
149                }
150        }
151
152        /**
153         * Filter the mime type icon.
154         *
155         * @param string $icon Icon path.
156         * @param string $mime Mime type.
157         * @param int    $post_id Post ID.
158         *
159         * @return string
160         */
161        public static function wp_mime_type_icon( $icon, $mime, $post_id ) {
162
163                if ( $mime !== 'video/videopress' ) {
164                        return $icon;
165                }
166
167                $status = get_post_meta( $post_id, 'videopress_status', true );
168
169                if ( $status === 'complete' ) {
170                        return $icon;
171                }
172
173                return 'https://wordpress.com/wp-content/mu-plugins/videopress/images/media-video-processing-icon.png';
174        }
175
176        /**
177         * Filter the list of supported video formats.
178         *
179         * @param array $extensions Supported video formats.
180         *
181         * @return array
182         */
183        public static function add_videopress_extenstion( $extensions ) {
184                $extensions[] = 'videopress';
185                return $extensions;
186        }
187
188        /**
189         * Make sure that any Video that has a VideoPress GUID passes that data back.
190         *
191         * @param WP_Post $post Attachment object.
192         */
193        public static function prepare_attachment_for_js( $post ) {
194                if ( 'video' === $post['type'] ) {
195                        $guid = get_post_meta( $post['id'], 'videopress_guid' );
196                        if ( $guid ) {
197                                $post['videopress_guid'] = $guid;
198                        }
199                }
200                return $post;
201        }
202
203        /**
204         * Media Grid:
205         * Filter out any videopress video posters that we've downloaded,
206         * so that they don't seem to display twice.
207         *
208         * @param array $args Query variables.
209         */
210        public static function ajax_query_attachments_args( $args ) {
211                $meta_query = array(
212                        array(
213                                'key'     => 'videopress_poster_image',
214                                'compare' => 'NOT EXISTS',
215                        ),
216                );
217
218                // If there was already a meta query, let's AND it via
219                // nesting it with our new one. No need to specify the
220                // relation, as it defaults to AND.
221                if ( ! empty( $args['meta_query'] ) ) {
222                        $meta_query[] = $args['meta_query'];
223                }
224                $args['meta_query'] = $meta_query;
225
226                return $args;
227        }
228
229        /**
230         * Media List:
231         * Do the same as `videopress_ajax_query_attachments_args()` but for the list view.
232         *
233         * @param array $query WP_Query instance.
234         */
235        public static function media_list_table_query( $query ) {
236
237                if (
238                        ! function_exists( 'get_current_screen' )
239                        || get_current_screen() === null
240                ) {
241                        return;
242                }
243
244                if ( is_admin() && $query->is_main_query() && ( 'upload' === get_current_screen()->id ) ) {
245                        $meta_query = array(
246                                array(
247                                        'key'     => 'videopress_poster_image',
248                                        'compare' => 'NOT EXISTS',
249                                ),
250                        );
251
252                        $old_meta_query = $query->get( 'meta_query' );
253                        if ( $old_meta_query ) {
254                                $meta_query[] = $old_meta_query;
255                        }
256
257                        $query->set( 'meta_query', $meta_query );
258                }
259        }
260
261        /**
262         * Filter to disable the `delete_post` capability
263         * for VideoPress attachments if the current user is
264         * not connected.
265         *
266         * @param array $allcaps All the capabilities of the user.
267         * @param array $cap     [0] Required capability.
268         * @param array $args    [0] Requested capability.
269         *                       [1] User ID.
270         *                       [2] Associated object ID.
271         * @return array the filtered array of capabilities.
272         */
273        public static function disable_delete_if_disconnected( $allcaps, $cap, $args ) {
274
275                // Only apply this filter to `delete_post` checks
276                if ( 'delete_post' !== $args[0] ) {
277                        return $allcaps;
278                }
279
280                // Only apply this filter to VideoPress attachments
281                if ( ! is_videopress_attachment( $args[2] ) ) {
282                        return $allcaps;
283                }
284
285                // Set the capability to false if the user can't perform the actions
286                if ( ! Data::can_perform_action() ) {
287                        $allcaps[ $cap[0] ] = false;
288                }
289
290                return $allcaps;
291        }
292}
Note: See TracBrowser for help on using the repository browser.