PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.2
Jetpack – WP Security, Backup, Speed, & Growth v16.2
16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 All 506 releases
jetpack / jetpack_vendor / automattic / jetpack-videopress / src / class-uploader.php

class-uploader.php in Jetpack – WP Security, Backup, Speed, & Growth 16.2, at jetpack_vendor/automattic/jetpack-videopress/src/class-uploader.php

310 lines 8.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * VideoPress Uploader
4 *
5 * @package automattic/jetpack-videopress
6 */
7
8 namespace Automattic\Jetpack\VideoPress;
9
10 use Jetpack_Options;
11 use VideoPressUploader\File_Exception;
12 use VideoPressUploader\Tus_Client;
13
14 /**
15 * VideoPress Uploader class
16 *
17 * Handles the upload from the Media Library to VideoPress servers
18 */
19 class Uploader {
20
21 /**
22 * The key of the post meta that holds the ID of the attachment that holds the VideoPress video, in case this attachment was uploaded before.
23 *
24 * @var string
25 */
26 const UPLOADED_KEY = '_videopress_uploaded_id';
27
28 /**
29 * The chunk size of each upload step
30 *
31 * @var int
32 */
33 const CHUNK_SIZE = 5000000;
34
35 /**
36 * The Tus Client instance
37 *
38 * @var Tus_Client
39 */
40 protected $client = null;
41
42 /**
43 * The attachment ID
44 *
45 * @var int
46 */
47 protected $attachment_id;
48
49 /**
50 * Checks whether this feature is supported by the server
51 *
52 * @param int $attachment_id The ID of the video attachment we want to upload to VideoPress.
53 * @return boolean
54 */
55 public static function is_valid_attachment_id( $attachment_id ) {
56 $file_path = get_attached_file( $attachment_id );
57 if ( ! $file_path || ! is_readable( $file_path ) ) {
58 return false;
59 }
60 if ( ! str_starts_with( get_post_mime_type( $attachment_id ), 'video/' ) ) {
61 return false;
62 }
63 return true;
64 }
65
66 /**
67 * Constructs the object
68 *
69 * @throws Upload_Exception If attachment is invalid or server does not support it.
70 * @param int $attachment_id The ID of the video attachment we want to upload to VideoPress.
71 */
72 public function __construct( $attachment_id ) {
73 $this->attachment_id = $attachment_id;
74 if ( ! $this->get_file_path() ) {
75 throw new Upload_Exception( __( 'Invalid attachment ID', 'jetpack-videopress-pkg' ), Upload_Exception::ERROR_INVALID_ATTACHMENT_ID );
76 }
77 if ( ! is_readable( $this->get_file_path() ) ) {
78 throw new Upload_Exception( __( 'File not found', 'jetpack-videopress-pkg' ), Upload_Exception::ERROR_FILE_NOT_FOUND );
79 }
80 if ( ! $this->file_has_supported_mime_type() ) {
81 throw new Upload_Exception( __( 'Mime type not supported', 'jetpack-videopress-pkg' ), Upload_Exception::ERROR_MIME_TYPE_NOT_SUPPORTED );
82 }
83 }
84
85 /**
86 * Gets the path of the video file
87 *
88 * @return string
89 */
90 public function get_file_path() {
91 return get_attached_file( $this->attachment_id );
92 }
93
94 /**
95 * Gets the mime type of the attachment
96 *
97 * @return string
98 */
99 public function get_file_mime_type() {
100 return get_post_mime_type( $this->attachment_id );
101 }
102
103 /**
104 * Gets the name of the video file
105 *
106 * @return string
107 */
108 public function get_file_name() {
109 return basename( $this->get_file_path() );
110 }
111
112 /**
113 * Gets the size of the video file
114 *
115 * @return int
116 */
117 public function get_file_size() {
118 return filesize( $this->get_file_path() );
119 }
120
121 /**
122 * Checks if the mime type of the attachment is supported to be uploaded
123 *
124 * @return boolean
125 */
126 public function file_has_supported_mime_type() {
127 return str_starts_with( $this->get_file_mime_type(), 'video/' );
128 }
129
130 /**
131 * Gets the VideoPress upload token
132 *
133 * @throws Upload_Exception If it fails to fetch the token.
134 *
135 * @return string
136 */
137 public function get_upload_token() {
138 return VideoPressToken::videopress_upload_jwt();
139 }
140
141 /**
142 * Gets a unique upload key for this attachment
143 *
144 * @return string
145 */
146 public function get_key() {
147 return sprintf( 's-%d-v-%d', Jetpack_Options::get_option( 'id' ), $this->attachment_id );
148 }
149
150 /**
151 * Sets the current attachment as uploaded and stores the ID of the VideoPress video attachment ID
152 *
153 * @param int $new_attachment_id The ID of the new attachment created to hold the VideoPress video.
154 * @return void
155 */
156 protected function mark_as_uploaded( $new_attachment_id ) {
157 update_post_meta( $this->attachment_id, self::UPLOADED_KEY, $new_attachment_id );
158 }
159
160 /**
161 * Sets the current attachment as not being uploaded before. Deletes the reference to the videopress attachment
162 *
163 * @return void
164 */
165 protected function unmark_as_uploaded() {
166 delete_post_meta( $this->attachment_id, self::UPLOADED_KEY );
167 }
168
169 /**
170 * Checks whether this attachment was uploaded before
171 *
172 * @return boolean
173 */
174 public function is_uploaded() {
175 return ! empty( $this->get_uploaded_attachment_id() );
176 }
177
178 /**
179 * Gets the ID of the VideoPress video attachment in case this attachment was uploaded before
180 *
181 * @return boolean|string False if value is absent. Post ID on success.
182 */
183 public function get_uploaded_attachment_id() {
184 return get_post_meta( $this->attachment_id, self::UPLOADED_KEY, true );
185 }
186
187 /**
188 * Retrieves the instance of the Tus_Client
189 *
190 * @return Tus_Client
191 */
192 public function get_client() {
193 if ( $this->client !== null ) {
194 return $this->client;
195 }
196
197 $this->client = new Tus_Client( $this->get_key(), $this->get_upload_token(), Jetpack_Options::get_option( 'id' ) );
198
199 return $this->client;
200 }
201
202 /**
203 * Uploads a chunk of the file
204 *
205 * @return array With the status of the upload
206 */
207 public function upload() {
208 if ( $this->is_uploaded() ) {
209 return $this->check_status();
210 }
211 try {
212 $attachment = get_post( $this->attachment_id );
213 $client = $this->get_client();
214 $client->file( $this->get_file_path(), $this->get_file_name() );
215 $client->add_metadata( 'title', $attachment->post_title );
216 if ( '' !== $attachment->post_content ) {
217 $client->add_metadata( 'description', $attachment->post_content );
218 }
219 if ( '' !== $attachment->post_excerpt ) {
220 $client->add_metadata( 'caption', $attachment->post_excerpt );
221 }
222
223 $bytes_uploaded = $client->upload( self::CHUNK_SIZE );
224
225 if ( $bytes_uploaded === $this->get_file_size() ) {
226 $this->mark_as_uploaded( $this->get_client()->get_uploaded_video_details()['media_id'] );
227 return array(
228 'status' => 'complete',
229 'bytes_uploaded' => $bytes_uploaded,
230 'file_size' => $this->get_file_size(),
231 'file_name' => $this->get_file_name(),
232 'upload_key' => $this->get_key(),
233 'uploaded_details' => $this->get_client()->get_uploaded_video_details(),
234 );
235 }
236
237 return array(
238 'status' => 'uploading',
239 'bytes_uploaded' => $bytes_uploaded,
240 'file_size' => $this->get_file_size(),
241 'file_name' => $this->get_file_name(),
242 'upload_key' => $this->get_key(),
243 );
244 } catch ( \Exception $e ) {
245 return array(
246 'status' => 'error',
247 'bytes_uploaded' => -1,
248 'file_size' => $this->get_file_size(),
249 'file_name' => $this->get_file_name(),
250 'upload_key' => $this->get_key(),
251 'error' => $e->getCode() . ': ' . $e->getMessage(),
252 );
253 }
254 }
255
256 /**
257 * Checks the status of the upload of this attachment
258 *
259 * @return array
260 */
261 public function check_status() {
262
263 if ( $this->is_uploaded() ) {
264 $uploaded_attachment_id = $this->get_uploaded_attachment_id();
265 $uploaded_video_guid = get_post_meta( $uploaded_attachment_id, 'videopress_guid', true );
266 if ( $uploaded_video_guid ) {
267 return array(
268 'status' => 'uploaded',
269 'upload_key' => $this->get_key(),
270 'uploaded_post_id' => $uploaded_attachment_id,
271 'uploaded_video_guid' => $uploaded_video_guid,
272 );
273 } else {
274 // VideoPress attachment is gone, allow user to upload it again.
275 $this->unmark_as_uploaded();
276 }
277 }
278
279 try {
280 $offset = $this->get_client()->get_offset();
281 $status = false !== $offset ? 'resume' : 'new';
282 $offset = false === $offset ? 0 : $offset;
283
284 return array(
285 'status' => $status,
286 'bytes_uploaded' => $offset,
287 'file_size' => $this->get_file_size(),
288 'file_name' => $this->get_file_name(),
289 'upload_key' => $this->get_key(),
290 );
291 } catch ( File_Exception $e ) {
292 return array(
293 'status' => 'resume',
294 'bytes_uploaded' => 0,
295 'file_size' => $this->get_file_size(),
296 'file_name' => $this->get_file_name(),
297 'upload_key' => $this->get_key(),
298 );
299 } catch ( \Exception $e ) {
300 return array(
301 'status' => 'error',
302 'bytes_uploaded' => -1,
303 'file_size' => $this->get_file_size(),
304 'file_name' => $this->get_file_name(),
305 'message' => $e->getMessage(),
306 );
307 }
308 }
309 }
310