summaryrefslogtreecommitdiff
blob: 81ef74b4cf4622245357998180665e9aef8b2047 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
<?php
/**
 * The Image Class.
 *
 * @package automattic/jetpack
 */

/**
 * Represents a resizable image, exposing properties necessary for properly generating srcset.
 */
class Jetpack_Photon_Image {

	/**
	 * @var string $filename Attachment's Filename.
	 */
	public $filename;

	/**
	 * @var string/WP_Erorr $mime_type Attachment's mime-type, WP_Error on failure when recalculating the dimensions.
	 */
	private $mime_type;

	/**
	 * @var int $original_width Image original width.
	 */
	private $original_width;

	/**
	 * @var int $original_width Image original height.
	 */
	private $original_height;

	/**
	 * @var int $width Current attachment's width.
	 */
	private $width;

	/**
	 * @var int $height Current attachment's height.
	 */
	private $height;

	/**
	 * @var bool $is_resized Whether the attachment has been resized yet, or not.
	 */
	private $is_resized = false;

	/**
	 * Constructs the image object.
	 *
	 * The $data array should provide at least
	 *  file   : string Image file path
	 *  width  : int    Image width
	 *  height : int    Image height
	 *
	 * @param array $data                 Array of attachment metadata, typically value of _wp_attachment_metadata postmeta
	 * @param string|\WP_Error $mime_type Typically value returned from get_post_mime_type function.
	 */
	public function __construct( $data, $mime_type ) {
		$this->filename = $data['file'];
		$this->width = $this->original_width = $data['width'];
		$this->height = $this->original_height = $data['height'];
		$this->mime_type = $mime_type;
	}

	/**
	 * Resizes the image to given size.
	 *
	 * @param array $size_data Array of width, height, and crop properties of a size.
	 *
	 * @return bool|\WP_Error True if resize was successful, WP_Error on failure.
	 */
	public function resize( $size_data ) {

		$dimensions = $this->image_resize_dimensions( $size_data['width'], $size_data['height'], $size_data['crop'] );

		if ( true === is_wp_error( $dimensions ) ) {
			return $dimensions; // Returns \WP_Error.
		}

		if ( true === is_wp_error( $this->mime_type ) ) {
			return $this->mime_type; // Returns \WP_Error.
		}

		$this->set_width_height( $dimensions );

		return $this->is_resized = true;
	}

	/**
	 * Generates size data for usage in $metadata['sizes'];.
	 *
	 * @param array $size_data Array of width, height, and crop properties of a size.
	 *
	 * @return array|\WP_Error An array containing file, width, height, and mime-type keys and it's values. WP_Error on failure.
	 */
	public function get_size( $size_data ) {

		$is_resized = $this->resize( $size_data );

		if ( true === is_wp_error( $is_resized ) ) {
			return $is_resized;
		}

		return array(
			'file'      => $this->get_filename(),
			'width'     => $this->get_width(),
			'height'    => $this->get_height(),
			'mime-type' => $this->get_mime_type(),
		);
	}

	/**
	 * Resets the image to it's original dimensions.
	 *
	 * @return bool True on successful reset to original dimensions.
	 */
	public function reset_to_original() {
		$this->width      = $this->original_width;
		$this->height     = $this->original_height;
		$this->is_resized = false;

		return true;
	}

	/**
	 * Return the basename filename. If the image has been resized, including
	 * the resizing params for Jetpack CDN.
	 *
	 * @return string Basename of the filename.
	 */
	public function get_filename() {
		return wp_basename( $this->get_raw_filename() );
	}

	/**
	 * Return the absolute filename. If the image has been resized, including
	 * the resizing params for Jetpack CDN.
	 *
	 * @return string Filename.
	 */
	public function get_raw_filename() {
		return $this->is_resized() ? $this->get_resized_filename() : $this->filename;
	}

	/**
	 * Returns current image width. Either original, or after resize.
	 *
	 * @return int
	 */
	public function get_width() {
		return (int) $this->width;
	}

	/**
	 * Returns current image height. Either original, or after resize.
	 *
	 * @return int
	 */
	public function get_height() {
		return (int) $this->height;
	}

	/**
	 * Returns image mime type.
	 *
	 * @return string|WP_Error Image's mime type or WP_Error if it was not determined.
	 */
	public function get_mime_type() {
		return $this->mime_type;
	}

	/**
	 * Checks the resize status of the image.
	 *
	 * @return bool If the image has been resized.
	 */
	public function is_resized() {
		return ( true === $this->is_resized );
	}

	/**
	 * Get filename with proper args for the Photon service.
	 *
	 * @return string Filename with query args for Photon service
	 */
	protected function get_resized_filename() {
		$query_args = array(
			'resize' => join(
				',',
				array(
					$this->get_width(),
					$this->get_height(),
				)
			),
		);

		return add_query_arg( $query_args, $this->filename );
	}

	/**
	 * Get resize dimensions used for the Jetpack CDN service.
	 *
	 * Converts the list of values returned from `image_resize_dimensions()` to
	 * associative array for the sake of more readable code no relying on index
	 * nor `list`.
	 *
	 * @param int $max_width
	 * @param int $max_height
	 * @param bool|array $crop
	 *
	 * @return array|\WP_Error Array of dimensions matching the parameters to imagecopyresampled. WP_Error on failure.
	 */
	protected function image_resize_dimensions( $max_width, $max_height, $crop ) {
		$dimensions = image_resize_dimensions( $this->original_width, $this->original_height, $max_width, $max_height, $crop );
		if ( ! $dimensions ) {
			return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions' ), $this->filename );
		}

		return array_combine(
			array(
				'dst_x',
				'dst_y',
				'src_x',
				'src_y',
				'dst_w',
				'dst_h',
				'src_w',
				'src_h',
			),
			$dimensions
		);
	}

	/**
	 * Sets proper width and height from dimensions.
	 *
	 * @param array $dimensions an array of image dimensions.
	 * @return void
	 */
	protected function set_width_height( $dimensions ) {
		$this->width  = (int) $dimensions['dst_w'];
		$this->height = (int) $dimensions['dst_h'];
	}

}