PluginProbe
Gutenberg / 8.3.0
Gutenberg v8.3.0
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / lib / image-editor / class-image-editor.php

class-image-editor.php in Gutenberg 8.3.0, at lib/image-editor/class-image-editor.php

296 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Start: Include for phase 2
4 * Image Editor: Image_Editor class
5 *
6 * @package gutenberg
7 * @since 7.x ?
8 */
9
10 /**
11 * Image flip/mirror modifier.
12 */
13 require_once __DIR__ . '/class-image-editor-flip.php';
14
15 /**
16 * Image rotate modifier.
17 */
18 require_once __DIR__ . '/class-image-editor-rotate.php';
19
20 /**
21 * Image crop modifier.
22 */
23 require_once __DIR__ . '/class-image-editor-crop.php';
24
25 /**
26 * Image editor.
27 *
28 * @since 7.x ?
29 */
30 class Image_Editor {
31 const META_KEY = 'richimage';
32
33 /**
34 * Constructs an Image_Editor.
35 */
36 public function __construct() {
37 $this->all_modifiers = array(
38 'Image_Editor_Crop',
39 'Image_Editor_Flip',
40 'Image_Editor_Rotate',
41 );
42 }
43
44 /**
45 * Modifies an image.
46 *
47 * @param integer $media_id Media id.
48 * @param Image_Editor_Modifier $modifier Modifier to apply to the image.
49 * @return array|WP_Error If successful image JSON containing the mediaId and url of modified image, otherwise WP_Error.
50 */
51 public function modify_image( $media_id, $modifier ) {
52 // Get image information.
53 $info = $this->load_image_info( $media_id );
54 if ( is_wp_error( $info ) ) {
55 return $info;
56 }
57
58 // Update it with our modifier.
59 $info['meta'] = $modifier->apply_to_meta( $info['meta'] );
60
61 // Generate filename based on current attributes.
62 $target_file = $this->get_filename( $info['meta'] );
63
64 // Does the image already exist?
65 $image = $this->get_existing_image( $info, $target_file );
66 if ( $image ) {
67 // Return the existing image.
68 return $image;
69 }
70
71 // Try and load the image itself.
72 $image = $this->load_image( $media_id, $info );
73 if ( is_wp_error( $image ) ) {
74 return $image;
75 }
76
77 // Finally apply the modification.
78 $modified = $modifier->apply_to_image( $image['editor'] );
79 if ( is_wp_error( $modified ) ) {
80 return $modified;
81 }
82
83 // And save.
84 return $this->save_image( $image, $target_file, $info );
85 }
86
87 /**
88 * Loads an image for editing.
89 *
90 * @param integer $media_id Image ID.
91 * @return array|WP_Error The WP_Image_Editor and image path if successful, WP_Error otherwise.
92 */
93 private function load_image( $media_id ) {
94 require_once ABSPATH . 'wp-admin/includes/image.php';
95
96 $image_path = get_attached_file( $media_id );
97
98 if ( empty( $image_path ) ) {
99 return new WP_Error( 'fileunknown', 'Unable to find original media file' );
100 }
101
102 $image_editor = wp_get_image_editor( $image_path );
103 if ( ! $image_editor->load() ) {
104 return new WP_Error( 'fileload', 'Unable to load original media file' );
105 }
106
107 return array(
108 'editor' => $image_editor,
109 'path' => $image_path,
110 );
111 }
112
113 /**
114 * Gets the JSON response object for an image.
115 *
116 * @param integer $id Image ID.
117 * @return array Image JSON.
118 */
119 private function get_image_as_json( $id ) {
120 return array(
121 'mediaID' => $id,
122 'url' => wp_get_attachment_image_url( $id, 'original' ),
123 );
124 }
125
126 /**
127 * Checks for the existence of an image and if it exists, return the image.
128 *
129 * @param array $attachment Attachment with url to look up.
130 * @param string $target_file Target file name to look up.
131 * @return array|false Image JSON if exists, otherwise false.
132 */
133 private function get_existing_image( $attachment, $target_file ) {
134 $url = str_replace( basename( $attachment['url'] ), $target_file, $attachment['url'] );
135
136 $new_id = attachment_url_to_postid( $url );
137 if ( $new_id > 0 ) {
138 return $this->get_image_as_json( $new_id );
139 }
140
141 return false;
142 }
143
144 /**
145 * Saves an edited image.
146 *
147 * @param array $image_edit Image path and editor to save.
148 * @param string $target_name Target file name to save as.
149 * @param array $attachment Attachment with metadata to apply.
150 * @return array|WP_Error Image JSON if successful, WP_Error otherwise
151 */
152 private function save_image( $image_edit, $target_name, $attachment ) {
153 $filename = rtrim( dirname( $image_edit['path'] ), '/' ) . '/' . $target_name;
154
155 // Save to disk.
156 $saved = $image_edit['editor']->save( $filename );
157
158 if ( is_wp_error( $saved ) ) {
159 return $saved;
160 }
161
162 // Update attachment details.
163 $attachment_post = array(
164 'guid' => $saved['path'],
165 'post_mime_type' => $saved['mime-type'],
166 'post_title' => pathinfo( $target_name, PATHINFO_FILENAME ),
167 'post_content' => '',
168 'post_status' => 'inherit',
169 );
170
171 // Add this as an attachment.
172 $attachment_id = wp_insert_attachment( $attachment_post, $saved['path'], 0 );
173 if ( 0 === $attachment_id ) {
174 return new WP_Error( 'attachment', 'Unable to add image as attachment' );
175 }
176
177 // Generate thumbnails.
178 $metadata = wp_generate_attachment_metadata( $attachment_id, $saved['path'] );
179
180 // Store out meta data.
181 $metadata[ self::META_KEY ] = $attachment['meta'];
182
183 wp_update_attachment_metadata( $attachment_id, $metadata );
184
185 return $this->get_image_as_json( $attachment_id );
186 }
187
188 /**
189 * Computes the filename based on metadata.
190 *
191 * @param array $meta Metadata for the image.
192 * @return string Name of the edited file.
193 */
194 private function get_filename( $meta ) {
195 $parts = array();
196
197 foreach ( $this->all_modifiers as $modifier ) {
198 $parts[] = $modifier::get_filename( $meta );
199 }
200
201 $parts = array_filter( $parts );
202
203 if ( count( $parts ) > 0 ) {
204 return sprintf( '%s-%s', implode( '-', $parts ), $meta['original_name'] );
205 }
206
207 return $meta['original_name'];
208 }
209
210 /**
211 * Loads image info.
212 *
213 * @param integer $media_id Image ID.
214 * @return array|WP_Error If successful image info, otherwise a WP_Error
215 */
216 private function load_image_info( $media_id ) {
217 $attachment_info = wp_get_attachment_metadata( $media_id );
218 $media_url = wp_get_attachment_image_url( $media_id, 'original' );
219
220 if ( ! $attachment_info || ! $media_url ) {
221 return new WP_Error( 'unknown', 'Unable to get meta information for file' );
222 }
223
224 $default_meta = array();
225 foreach ( $this->all_modifiers as $modifier ) {
226 $default_meta = array_merge( $default_meta, $modifier::get_default_meta() );
227 }
228
229 $info = array(
230 'url' => $media_url,
231 'media_id' => $media_id,
232 'meta' => array_merge(
233 $default_meta,
234 array( 'original_name' => basename( $media_url ) )
235 ),
236 );
237
238 if ( isset( $attachment_info[ self::META_KEY ] ) ) {
239 $info['meta'] = array_merge( $info['meta'], $attachment_info[ self::META_KEY ] );
240 }
241
242 return $info;
243 }
244 }
245
246 /**
247 * Abstract class for image modifiers. Any modifier to an image should implement this.
248 *
249 * @abstract
250 */
251 abstract class Image_Editor_Modifier {
252
253 /**
254 * Update the image metadata with the modifier.
255 *
256 * @abstract
257 * @access public
258 *
259 * @param array $meta Metadata to update.
260 * @return array Updated metadata.
261 */
262 abstract public function apply_to_meta( $meta );
263
264 /**
265 * Apply the modifier to the image
266 *
267 * @abstract
268 * @access public
269 *
270 * @param WP_Image_Editor $image Image editor.
271 * @return bool|WP_Error True on success, WP_Error object or false on failure.
272 */
273 abstract public function apply_to_image( $image );
274
275 /**
276 * Gets the new filename based on metadata.
277 *
278 * @abstract
279 * @access public
280 *
281 * @param array $meta Image metadata.
282 * @return string Filename for the edited image.
283 */
284 abstract public static function get_filename( $meta );
285
286 /**
287 * Gets the default metadata for an image modifier.
288 *
289 * @abstract
290 * @access public
291 *
292 * @return array Default metadata.
293 */
294 abstract public static function get_default_meta();
295 }
296