Completed
Push — master ( 8ad9a8...120f60 )
by
unknown
01:43 queued 56s
created

TimberImageHelper::_operate()   C

Complexity

Conditions 8
Paths 15

Size

Total Lines 51
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 51
rs 6.5978
cc 8
eloc 32
nc 15
nop 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Implements the Twig image filters:
5
 * https://github.com/jarednova/timber/wiki/Image-cookbook#arbitrary-resizing-of-images
6
 * - resize
7
 * - retina
8
 * - letterbox
9
 * - tojpg
10
 *
11
 * Implementation:
12
 * - public static functions provide the methods that are called by the filter
13
 * - most of the work is common to all filters (URL analysis, directory gymnastics, file caching, error management) and done by private static functions
14
 * - the specific part (actual image processing) is delegated to dedicated subclasses of TimberImageOperation
15
 */
16
class TimberImageHelper {
17
18
	const BASE_UPLOADS = 1;
19
	const BASE_CONTENT = 2;
20
21
	public static function init() {
22
		self::add_constants();
23
		self::add_actions();
24
		self::add_filters();
25
	}
26
27
	/**
28
	 * Generates a new image with the specified dimensions.
29
	 * New dimensions are achieved by cropping to maintain ratio.
30
	 *
31
	 * @api
32
	 * @param string  		$src an URL (absolute or relative) to the original image
33
	 * @param int|string	$w target width(int) or WordPress image size (WP-set or user-defined)
34
	 * @param int     		$h target height (ignored if $w is WP image size)
35
	 * @param string  		$crop your choices are 'default', 'center', 'top', 'bottom', 'left', 'right'
36
	 * @param bool    		$force
37
	 * @example
38
	 * ```twig
39
	 * <img src="{{ image.src | resize(300, 200, 'top') }}" />
40
	 * ```
41
	 * ```html
42
	 * <img src="http://example.org/wp-content/uploads/pic-300x200-c-top.jpg" />
43
	 * ```
44
	 * @return string (ex: )
45
	 */
46
	public static function resize( $src, $w, $h = 0, $crop = 'default', $force = false ) {
47
		if (!is_numeric($w) && is_string($w)) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
Expected 1 space before "!"; 0 found
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
48
			if ($sizes = self::find_wp_dimensions($w)) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
49
				$w = $sizes['w'];
50
				$h = $sizes['h'];
51
			} else {
52
				return $src;
53
			}
54
		}
55
		$op = new TimberImageOperationResize($w, $h, $crop);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
56
		return self::_operate($src, $op, $force);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
57
	}
58
59
	/**
60
	 * Find the sizes of an image based on a defined image size
61
	 * @param  string $size the image size to search for
62
	 *                      can be WordPress-defined ("medium")
63
	 *                      or user-defined ("my-awesome-size")
64
	 * @return array {
0 ignored issues
show
Documentation introduced by
Should the return type not be array|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
65
	 *     @type int w
66
	 *     @type int h
67
	 * }
68
	 */
69
	private static function find_wp_dimensions( $size ) {
70
		global $_wp_additional_image_sizes;
71
		if (isset($_wp_additional_image_sizes[$size])) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
72
			$w = $_wp_additional_image_sizes[$size]['width'];
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
73
			$h = $_wp_additional_image_sizes[$size]['height'];
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
74
		} else if (in_array($size, array('thumbnail', 'medium', 'large'))) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
introduced by
No space after opening parenthesis of array is bad style
Loading history...
introduced by
No space before closing parenthesis of array is bad style
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
75
			$w = get_option($size.'_size_w');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
76
			$h = get_option($size.'_size_h');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
77
		}
78
		if (isset($w) && isset($h) && ($w || $h)) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
79
			return array('w' => $w, 'h' => $h);
0 ignored issues
show
introduced by
No space after opening parenthesis of array is bad style
Loading history...
introduced by
No space before closing parenthesis of array is bad style
Loading history...
80
		}
81
		return false;
82
	}
83
84
	/**
85
	 * Generates a new image with increased size, for display on Retina screens.
86
	 *
87
	 * @param string  $src
88
	 * @param float   $multiplier
1 ignored issue
show
Documentation introduced by
Should the type for parameter $multiplier not be integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
89
	 * @param boolean $force
90
	 *
91
	 * @return string url to the new image
92
	 */
93
	public static function retina_resize( $src, $multiplier = 2, $force = false ) {
94
		$op = new TimberImageOperationRetina($multiplier);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
95
		return self::_operate($src, $op, $force);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
96
	}
97
98
	/**
99
	 * checks to see if the given file is an aimated gif
100
	 * @param  string  $file local filepath to a file, not a URL
101
	 * @return boolean true if it's an animated gif, false if not
102
	 */
103
	public static function is_animated_gif( $file ) {
104
		if ( strpos(strtolower($file), '.gif') == -1 ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
105
			//doesn't have .gif, bail
106
			return false;
107
		}
108
		//its a gif so test
109
		if( !($fh = @fopen($file, 'rb')) ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
Coding Style introduced by
Silencing errors is discouraged
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
110
		  	return false;
111
	    }
112
	    $count = 0;
113
	    //an animated gif contains multiple "frames", with each frame having a
114
	    //header made up of:
115
	    // * a static 4-byte sequence (\x00\x21\xF9\x04)
116
	    // * 4 variable bytes
117
	    // * a static 2-byte sequence (\x00\x2C)
118
119
	    // We read through the file til we reach the end of the file, or we've found
120
	    // at least 2 frame headers
121
	    while(!feof($fh) && $count < 2) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
Expected 1 space before "!"; 0 found
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
122
	        $chunk = fread($fh, 1024 * 100); //read 100kb at a time
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
123
	        $count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00[\x2C\x21]#s', $chunk, $matches);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
124
	    }
125
126
	    fclose($fh);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
127
	    return $count > 1;
128
	}
129
130
	/**
131
	 * Generate a new image with the specified dimensions.
132
	 * New dimensions are achieved by adding colored bands to maintain ratio.
133
	 *
134
	 * @param string  $src
135
	 * @param int     $w
136
	 * @param int     $h
137
	 * @param string  $color
138
	 * @param bool    $force
139
	 * @return mixed|null|string
140
	 */
141
	public static function letterbox( $src, $w, $h, $color = '#000000', $force = false ) {
142
		$op = new TimberImageOperationLetterbox($w, $h, $color);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
143
		return self::_operate($src, $op, $force);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
144
	}
145
146
	/**
147
	 * Generates a new image by converting the source GIF or PNG into JPG
148
	 *
149
	 * @param string  $src   a url or path to the image (http://example.org/wp-content/uploads/2014/image.jpg) or (/wp-content/uploads/2014/image.jpg)
150
	 * @param string  $bghex
151
	 * @return string
152
	 */
153
	public static function img_to_jpg( $src, $bghex = '#FFFFFF', $force = false ) {
154
		$op = new TimberImageOperationToJpg($bghex);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
155
		return self::_operate($src, $op, $force);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
156
	}
157
158
	/**
159
	 * Deletes all resized versions of an image when the source is deleted
160
	 */
161
	protected static function add_actions() {
162
		add_action( 'delete_attachment', function ( $post_id ) {
163
			$post = get_post( $post_id );
164
			$image_types = array( 'image/jpeg', 'image/png', 'image/gif', 'image/jpg' );
165
			if ( in_array( $post->post_mime_type, $image_types ) ) {
166
				$attachment = new TimberImage( $post_id );
167
				if ( $attachment->file_loc ) {
168
					TimberImageHelper::delete_generated_files( $attachment->file_loc );
169
				}
170
			}
171
		} );
172
	}
173
174
	/**
175
	 * Adds a constant defining the path to the content directory relative to the site
176
	 * for example /wp-content or /content
177
	 */
178
	protected static function add_constants() {
179
		if ( !defined( 'WP_CONTENT_SUBDIR' ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
180
			$wp_content_path = str_replace( home_url(), '', WP_CONTENT_URL );
181
			define( 'WP_CONTENT_SUBDIR', $wp_content_path );
182
		}
183
	}
184
185
	/**
186
	 * adds a 'relative' key to wp_upload_dir() result.
187
	 * It will contain the relative url to upload dir.
188
	 * @return void
189
	 */
190
	static function add_filters() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
191
		add_filter( 'upload_dir', function ( $arr ) {
192
			$arr['relative'] = str_replace( home_url(), '', $arr['baseurl'] );
193
			return $arr;
194
		} );
195
	}
196
197
	//-- end of public methods --//
198
	/**
199
	 * Deletes the auto-generated files for resize and letterboxing created by Timber
200
	 * @param string  $local_file   ex: /var/www/wp-content/uploads/2015/my-pic.jpg
201
	 *                              or: http://example.org/wp-content/uploads/2015/my-pic.jpg
202
	 */
203
	static function delete_generated_files( $local_file ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
204
		if (TimberURLHelper::is_absolute( $local_file ) ) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
205
			$local_file = TimberURLHelper::url_to_file_system( $local_file );
206
		}
207
		$info = pathinfo( $local_file );
208
		$dir = $info['dirname'];
209
		$ext = $info['extension'];
210
		$filename = $info['filename'];
211
		self::process_delete_generated_files( $filename, $ext, $dir, '-[0-9999999]*', '-[0-9]*x[0-9]*-c-[a-z]*.' );
212
		self::process_delete_generated_files( $filename, $ext, $dir, '-lbox-[0-9999999]*', '-lbox-[0-9]*x[0-9]*-[a-zA-Z0-9]*.' );
213
	}
214
215
	/**
216
	 * Deletes resized versions of the supplied file name.
217
	 * So if passed a value like my-pic.jpg, this function will delete my-pic-500x200-c-left.jpg, my-pic-400x400-c-default.jpg, etc.
218
	 *
219
	 * keeping these here so I know what the hell we're matching
220
	 * $match = preg_match("/\/srv\/www\/wordpress-develop\/src\/wp-content\/uploads\/2014\/05\/$filename-[0-9]*x[0-9]*-c-[a-z]*.jpg/", $found_file);
221
	 * $match = preg_match("/\/srv\/www\/wordpress-develop\/src\/wp-content\/uploads\/2014\/05\/arch-[0-9]*x[0-9]*-c-[a-z]*.jpg/", $filename);
222
	 *
223
	 * @param string 	$filename   ex: my-pic
224
	 * @param string 	$ext ex: jpg
225
	 * @param string 	$dir var/www/wp-content/uploads/2015/
226
	 * @param string 	$search_pattern pattern of files to pluck from
227
	 * @param string 	$match_pattern pattern of files to go forth and delete
228
	 */
229
	protected static function process_delete_generated_files( $filename, $ext, $dir, $search_pattern, $match_pattern ) {
230
		$searcher = '/' . $filename . $search_pattern;
231
		foreach ( glob( $dir . $searcher ) as $found_file ) {
232
			$regexdir = str_replace( '/', '\/', $dir );
233
			$pattern = '/' . ( $regexdir ) . '\/' . $filename . $match_pattern . $ext . '/';
234
			$match = preg_match( $pattern, $found_file );
235
			if ( $match ) {
236
				unlink( $found_file );
0 ignored issues
show
introduced by
Filesystem writes are forbidden, you should not be using unlink()
Loading history...
237
			}
238
		}
239
	}
240
241
242
	/**
243
	 * Determines the filepath corresponding to a given URL
244
	 *
245
	 * @param string  $url
246
	 * @return string
247
	 */
248
	public static function get_server_location( $url ) {
249
		// if we're already an absolute dir, just return
250
		if ( 0 === strpos( $url, ABSPATH ) ) {
251
			return $url;
252
		}
253
		// otherwise, analyze URL then build mapping path
254
		$au = self::analyze_url($url);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
255
		$result = self::_get_file_path($au['base'], $au['subdir'], $au['basename']);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
256
		return $result;
257
	}
258
259
	/**
260
	 * Determines the filepath where a given external file will be stored.
261
	 *
262
	 * @param string  $file
263
	 * @return string
264
	 */
265
	public static function get_sideloaded_file_loc( $file ) {
266
		$upload = wp_upload_dir();
267
		$dir = $upload['path'];
268
		$filename = $file;
269
		$file = parse_url( $file );
270
		$path_parts = pathinfo( $file['path'] );
271
		$basename = md5( $filename );
272
		$ext = 'jpg';
273
		if ( isset( $path_parts['extension'] ) ) {
274
			$ext = $path_parts['extension'];
275
		}
276
		return $dir . '/' . $basename . '.' . $ext;
277
	}
278
279
	/**
280
	 * downloads an external image to the server and stores it on the server
281
	 *
282
	 * @param string  $file the URL to the original file
283
	 * @return string the URL to the downloaded file
284
	 */
285
	public static function sideload_image( $file ) {
286
		$loc = self::get_sideloaded_file_loc( $file );
287
		if ( file_exists( $loc ) ) {
288
			return TimberURLHelper::preslashit( TimberURLHelper::get_rel_path( $loc ) );
289
		}
290
		// Download file to temp location
291
		if ( !function_exists( 'download_url' ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
292
			require_once ABSPATH . '/wp-admin/includes/file.php';
293
		}
294
		$tmp = download_url( $file );
295
		preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $file, $matches );
296
		$file_array = array();
297
		$file_array['name'] = basename( $matches[0] );
298
		$file_array['tmp_name'] = $tmp;
299
		// If error storing temporarily, unlink
300
		if ( is_wp_error( $tmp ) ) {
301
			@unlink( $file_array['tmp_name'] );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Coding Style introduced by
Silencing errors is discouraged
Loading history...
introduced by
Filesystem writes are forbidden, you should not be using unlink()
Loading history...
302
			$file_array['tmp_name'] = '';
303
		}
304
		// do the validation and storage stuff
305
		$locinfo = pathinfo( $loc );
306
		$file = wp_upload_bits( $locinfo['basename'], null, file_get_contents( $file_array['tmp_name'] ) );
0 ignored issues
show
introduced by
file_get_contents is highly discouraged, please use wpcom_vip_file_get_contents() instead.
Loading history...
307
		return $file['url'];
308
	}
309
310
	/**
311
	 * Takes in an URL and breaks it into components,
312
	 * that will then be used in the different steps of image processing.
313
	 * The image is expected to be either part of a theme, plugin, or an upload.
314
	 *
315
	 * @param  string $url an URL (absolute or relative) pointing to an image
316
	 * @return array       an array (see keys in code below)
317
	 */
318
	private static function analyze_url($url) {
319
		$result = array(
320
			'url' => $url, // the initial url
321
			'absolute' => TimberURLHelper::is_absolute($url), // is the url absolute or relative (to home_url)
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
322
			'base' => 0, // is the image in uploads dir, or in content dir (theme or plugin)
323
			'subdir' => '', // the path between base (uploads or content) and file
324
			'filename' => '', // the filename, without extension
325
			'extension' => '', // the file extension
326
			'basename' => '', // full file name
327
		);
328
		$upload_dir = wp_upload_dir();
329
		$tmp = $url;
330
		if ( 0 === strpos($tmp, ABSPATH) ) { // we've been given a dir, not an url
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
331
			$result['absolute'] = true;
332 View Code Duplication
			if ( 0 === strpos($tmp, $upload_dir['basedir']) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
333
				$result['base']= self::BASE_UPLOADS; // upload based
0 ignored issues
show
introduced by
Expected 1 space before "="; 0 found
Loading history...
334
				$tmp = str_replace($upload_dir['basedir'], '', $tmp);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
335
			}
336 View Code Duplication
			if ( 0 === strpos($tmp, WP_CONTENT_DIR) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
337
				$result['base']= self::BASE_CONTENT; // content based
0 ignored issues
show
introduced by
Expected 1 space before "="; 0 found
Loading history...
338
				$tmp = str_replace(WP_CONTENT_DIR, '', $tmp);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
339
			}
340
		} else {
341
			if (!$result['absolute']) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
Expected 1 space before "!"; 0 found
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
342
				$tmp = home_url().$tmp;
343
			}
344 View Code Duplication
			if (0 === strpos($tmp, $upload_dir['baseurl'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
introduced by
No space after opening parenthesis is prohibited
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
345
				$result['base']= self::BASE_UPLOADS; // upload based
0 ignored issues
show
introduced by
Expected 1 space before "="; 0 found
Loading history...
346
				$tmp = str_replace($upload_dir['baseurl'], '', $tmp);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
347
			}
348 View Code Duplication
			if (0 === strpos($tmp, content_url())) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
introduced by
No space after opening parenthesis is prohibited
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
349
				$result['base']= self::BASE_CONTENT; // content-based
0 ignored issues
show
introduced by
Expected 1 space before "="; 0 found
Loading history...
350
				$tmp = str_replace(content_url(), '', $tmp);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
351
			}
352
		}
353
		$parts = pathinfo($tmp);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
354
		$result['subdir'] = $parts['dirname'];
355
		$result['filename'] = $parts['filename'];
356
		$result['extension'] = $parts['extension'];
357
		$result['basename'] = $parts['basename'];
358
		// todo filename
359
		return $result;
360
	}
361
362
	/**
363
	 * Builds the public URL of a file based on its different components
364
	 *
365
	 * @param  int    $base     one of self::BASE_UPLOADS, self::BASE_CONTENT to indicate if file is an upload or a content (theme or plugin)
366
	 * @param  string $subdir   subdirectory in which file is stored, relative to $base root folder
367
	 * @param  string $filename file name, including extension (but no path)
368
	 * @param  bool   $absolute should the returned URL be absolute (include protocol+host), or relative
369
	 * @return string           the URL
370
	 */
371
	private static function _get_file_url($base, $subdir, $filename, $absolute) {
372
		$url = '';
373
		if( self::BASE_UPLOADS == $base ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
374
			$upload_dir = wp_upload_dir();
375
			$url = $upload_dir['baseurl'];
376
		}
377
		if( self::BASE_CONTENT == $base ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
378
			$url = content_url();
379
		}
380
		if(!empty($subdir)) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
Expected 1 space before "!"; 0 found
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
381
			$url .= $subdir;
382
		}
383
		$url .= '/'.$filename;
384
		if(!$absolute) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
Expected 1 space before "!"; 0 found
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
385
			$url = str_replace(home_url(), '', $url);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
386
		}
387
		// $url = TimberURLHelper::remove_double_slashes( $url);
388
		return $url;
389
	}
390
391
	/**
392
	 * Builds the absolute file system location of a file based on its different components
393
	 *
394
	 * @param  int    $base     one of self::BASE_UPLOADS, self::BASE_CONTENT to indicate if file is an upload or a content (theme or plugin)
395
	 * @param  string $subdir   subdirectory in which file is stored, relative to $base root folder
396
	 * @param  string $filename file name, including extension (but no path)
397
	 * @return string           the file location
398
	 */
399
	private static function _get_file_path($base, $subdir, $filename) {
400
		$path = '';
401
		if(self::BASE_UPLOADS == $base) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
402
			$upload_dir = wp_upload_dir();
403
			$path = $upload_dir['basedir'];
404
		}
405
		if(self::BASE_CONTENT == $base) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
406
			$path = WP_CONTENT_DIR;
407
		}
408
		if(!empty($subdir)) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
Expected 1 space before "!"; 0 found
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
409
			$path .= $subdir;
410
		}
411
		$path .= '/'.$filename;
412
		return $path;
413
	}
414
415
416
	/**
417
	 * Main method that applies operation to src image:
418
	 * 1. break down supplied URL into components
419
	 * 2. use components to determine result file and URL
420
	 * 3. check if a result file already exists
421
	 * 4. otherwise, delegate to supplied TimberImageOperation
422
	 *
423
	 * @param  string  $src   an URL (absolute or relative) to an image
424
	 * @param  object  $op    object of class TimberImageOperation
425
	 * @param  boolean $force if true, remove any already existing result file and forces file generation
426
	 * @return string         URL to the new image - or the source one if error
427
	 *
428
	 */
429
	private static function _operate( $src, $op, $force = false ) {
430
		if ( empty( $src ) ) {
431
			return '';
432
		}
433
		$external = false;
434
435
		// if external image, load it first
436
		if ( TimberURLHelper::is_external_content( $src ) ) {
437
			$src = self::sideload_image( $src );
438
			$external = true;
439
		}
440
		// break down URL into components
441
		$au = self::analyze_url($src);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
442
		// build URL and filenames
443
		$new_url = self::_get_file_url(
444
			$au['base'],
445
			$au['subdir'],
446
			$op->filename($au['filename'], $au['extension']),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
447
			$au['absolute']
448
		);
449
		$new_server_path = self::_get_file_path(
450
			$au['base'],
451
			$au['subdir'],
452
			$op->filename($au['filename'], $au['extension'])
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
453
		);
454
		$old_server_path = self::_get_file_path(
455
			$au['base'],
456
			$au['subdir'],
457
			$au['basename']
458
		);
459
		// if already exists...
460
		if ( file_exists( $new_server_path ) ) {
461
			if ( $force ) {
462
				// Force operation - warning: will regenerate the image on every pageload, use for testing purposes only!
463
				unlink( $new_server_path );
0 ignored issues
show
introduced by
Filesystem writes are forbidden, you should not be using unlink()
Loading history...
464
			} else {
465
				// return existing file (caching)
466
				return $new_url;
467
			}
468
		}
469
		// otherwise generate result file
470
		if($op->run($old_server_path, $new_server_path)) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
introduced by
No space after opening parenthesis is prohibited
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
471
			if( get_class( $op ) === 'TimberImageOperationResize' && $external ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
472
				$new_url = strtolower( $new_url );
473
			}
474
			return $new_url;
475
		} else {
476
			// in case of error, we return source file itself
477
			return $src;
478
		}
479
	}
480
481
482
// -- the below methods are just used for unit testing the URL generation code
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 1 tabs, found 0
Loading history...
483
//
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 1 tabs, found 0
Loading history...
484 View Code Duplication
	static function get_letterbox_file_url($url, $w, $h, $color) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method 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...
485
		$au = self::analyze_url($url);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
486
		$op = new TimberImageOperationLetterbox($w, $h, $color);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
487
		$new_url = self::_get_file_url(
488
			$au['base'],
489
			$au['subdir'],
490
			$op->filename($au['filename'], $au['extension']),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
491
			$au['absolute']
492
		);
493
		return $new_url;
494
	}
495 View Code Duplication
	public static function get_letterbox_file_path($url, $w, $h, $color ) {
0 ignored issues
show
Duplication introduced by
This method 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...
496
		$au = self::analyze_url($url);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
497
		$op = new TimberImageOperationLetterbox($w, $h, $color);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
498
		$new_path = self::_get_file_path(
499
			$au['base'],
500
			$au['subdir'],
501
			$op->filename($au['filename'], $au['extension'])
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
502
		);
503
		return $new_path;
504
	}
505 View Code Duplication
	static function get_resize_file_url($url, $w, $h, $crop) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method 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...
506
		$au = self::analyze_url($url);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
507
		$op = new TimberImageOperationResize($w, $h, $crop);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
508
		$new_url = self::_get_file_url(
509
			$au['base'],
510
			$au['subdir'],
511
			$op->filename($au['filename'], $au['extension']),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
512
			$au['absolute']
513
		);
514
		return $new_url;
515
	}
516 View Code Duplication
	static function get_resize_file_path($url, $w, $h, $crop) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method 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...
517
		$au = self::analyze_url($url);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
518
		$op = new TimberImageOperationResize($w, $h, $crop);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
519
		$new_path = self::_get_file_path(
520
			$au['base'],
521
			$au['subdir'],
522
			$op->filename($au['filename'], $au['extension'])
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
523
		);
524
		return $new_path;
525
	}
526
527
528
}
529