Passed
Push — master ( b5dddf...91d417 )
by Richard
09:12
created

WideImage   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 326
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 46
eloc 92
dl 0
loc 326
rs 8.72
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A loadFromString() 0 26 6
B load() 0 39 11
A loadFromHandle() 0 11 3
A registerCustomMapper() 0 3 1
A createTrueColorImage() 0 3 1
A isValidImageHandle() 0 3 2
A version() 0 3 1
B loadFromFile() 0 37 8
A path() 0 7 2
A loadFromUpload() 0 27 6
A assertValidImageHandle() 0 4 2
A checkGD() 0 4 2
A createPaletteImage() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like WideImage often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WideImage, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
##DOC-SIGNATURE##
5
6
 This file is part of WideImage.
7
		
8
 WideImage is free software; you can redistribute it and/or modify
9
 it under the terms of the GNU Lesser General Public License as published by
10
 the Free Software Foundation; either version 2.1 of the License, or
11
 (at your option) any later version.
12
		
13
 WideImage is distributed in the hope that it will be useful,
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 GNU Lesser General Public License for more details.
17
		
18
 You should have received a copy of the GNU Lesser General Public License
19
 along with WideImage; if not, write to the Free Software
20
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
 
22
 * @package WideImage
23
**/
24
	
25
namespace WideImage;
26
27
use WideImage\MapperFactory;
28
use WideImage\Exception\Exception;
29
use WideImage\Exception\UnsupportedFormatException;
30
use WideImage\Exception\InvalidImageSourceException;
31
use WideImage\Exception\InvalidImageHandleException;
32
33
/**
34
 * The gateway class for loading images and core library functions
35
 *
36
 * @package WideImage
37
 */
38
class WideImage
39
{
40
	const SIDE_TOP_LEFT = 1;
41
	const SIDE_TOP = 2;
42
	const SIDE_TOP_RIGHT = 4;
43
	const SIDE_RIGHT = 8;
44
	const SIDE_BOTTOM_RIGHT = 16;
45
	const SIDE_BOTTOM = 32;
46
	const SIDE_BOTTOM_LEFT = 64;
47
	const SIDE_LEFT = 128;
48
	const SIDE_ALL = 255;
49
	
50
	/**
51
	 * @var string Path to the library base directory
52
	 */
53
	protected static $path = null;
54
	
55
	/**
56
	 * Returns the library version
57
	 * @return string The library version
58
	 */
59
	public static function version()
60
	{
61
		return '##DEV##';
62
	}
63
	
64
	/**
65
	 * Returns the path to the library
66
	 * @return string
67
	 */
68
	public static function path()
69
	{
70
		if (static::$path === null) {
0 ignored issues
show
introduced by
The condition static::path is always false. If static::path can have other possible types, add them to htdocs/class/libraries/v...WideImage/WideImage.php:51
Loading history...
71
			static::$path = __DIR__ . DIRECTORY_SEPARATOR;
72
		}
73
		
74
		return static::$path;
75
	}
76
	
77
	/**
78
	 * Checks whether the gd library is loaded, and throws an exception otherwise
79
	 */
80
	public static function checkGD()
81
	{
82
		if (!extension_loaded('gd')) {
83
			throw new Exception("WideImage requires the GD extension, but it's apparently not loaded.");
84
		}
85
	}
86
87
	/**
88
	 * Registers a custom mapper for image loading and saving
89
	 * 
90
	 * Example:
91
	 * <code>
92
	 * 	\WideImage\WideImage::registerCustomMapper('\\WideImage\\Mapper\\TGA', 'image/tga', 'tga');
93
	 * </code>
94
	 * 
95
	 * @param string $mapper_class_name
96
	 * @param string $mime_type
97
	 * @param string $extension
98
	 */
99
	public static function registerCustomMapper($mapper_class_name, $mime_type, $extension)
100
	{
101
		MapperFactory::registerMapper($mapper_class_name, $mime_type, strtoupper($extension));
102
	}
103
	
104
	/**
105
	 * Loads an image from a file, URL, HTML input file field, binary string, or a valid image handle.
106
	 * The image format is auto-detected. 
107
	 * 
108
	 * Currently supported formats: PNG, GIF, JPG, BMP, TGA, GD, GD2.
109
	 * 
110
	 * This function analyzes the input and decides whether to use WideImage::loadFromHandle(),
111
	 * WideImage::loadFromFile(), WideImage::loadFromUpload() or WideImage::loadFromString(),
112
	 * all of which you can also call directly to spare WideImage some guessing.
113
	 * 
114
	 * Arrays are supported for upload fields; it returns an array of loaded images. 
115
	 * To load only a single image from an array field, use WideImage::loadFromUpload('img', $i), 
116
	 * where $i is the index of the image you want to load.
117
	 * 
118
	 * <code>
119
	 * $img = WideImage::load('http://url/image.png'); // image URL
120
	 * $img = WideImage::load('/path/to/image.png'); // local file path
121
	 * $img = WideImage::load('img'); // upload field name
122
	 * $img = WideImage::load(imagecreatetruecolor(10, 10)); // a GD resource
123
	 * $img = WideImage::load($image_data); // binary string containing image data
124
	 * </code>
125
	 * 
126
	 * @param mixed $source File name, url, HTML file input field name, binary string, or a GD image resource
127
	 * @return \WideImage\Image|\WideImage\PaletteImage|\WideImage\TrueColorImage
128
	 */
129
	public static function load($source)
130
	{
131
		$predictedSourceType = '';
132
		
133
		if ($source == '') {
134
			$predictedSourceType = 'String';
135
		}
136
		
137
		// Creating image via a valid resource
138
		if (!$predictedSourceType && static::isValidImageHandle($source)) {
139
			$predictedSourceType = 'Handle';
140
		}
141
		
142
		// Check for binary string
143
		if (!$predictedSourceType) {
144
			// search first $binLength bytes (at a maximum) for ord<32 characters (binary image data)
145
			$binLength    = 64;
146
			$sourceLength = strlen($source);
147
			$maxlen       = ($sourceLength > $binLength) ? $binLength : $sourceLength;
148
			
149
			for ($i = 0; $i < $maxlen; $i++) {
150
				if (ord($source[$i]) < 32) {
151
					$predictedSourceType = 'String';
152
					break;
153
				}
154
			}
155
		}
156
		
157
		// Uploaded image (array uploads not supported)
158
		if (isset($_FILES[$source]) && isset($_FILES[$source]['tmp_name'])) {
159
			$predictedSourceType = 'Upload';
160
		}
161
		
162
		// Otherwise, must be a file or an URL
163
		if (!$predictedSourceType) {
164
			$predictedSourceType = 'File';
165
		}
166
		
167
		return call_user_func(array(__CLASS__, 'loadFrom' . $predictedSourceType), $source);
168
	}
169
170
	/**
171
	 * Create and load an image from a file or URL. The image format is auto-detected.
172
	 * 
173
	 * @param string $uri File or url
174
	 * @return \WideImage\Image|\WideImage\PaletteImage|\WideImage\TrueColorImage
175
	 */
176
	public static function loadFromFile($uri)
177
	{
178
		$data   = file_get_contents($uri);
179
		$handle = @imagecreatefromstring($data);
180
		
181
		if (!static::isValidImageHandle($handle)) {
182
			try {
183
				// try to find a mapper first
184
				$mapper = MapperFactory::selectMapper($uri);
185
				
186
				if ($mapper) {
187
					$handle = $mapper->load($uri);
188
				}
189
			} catch (UnsupportedFormatException $e) {
190
				// mapper not found
191
			}
192
			
193
			// try all custom mappers
194
			if (!static::isValidImageHandle($handle)) {
195
				$custom_mappers = MapperFactory::getCustomMappers();
196
				
197
				foreach ($custom_mappers as $mime_type => $mapper_class) {
198
					$mapper = MapperFactory::selectMapper(null, $mime_type);
199
					$handle = $mapper->loadFromString($data);
200
					
201
					if (static::isValidImageHandle($handle)) {
202
						break;
203
					}
204
				}
205
			}
206
		}
207
		
208
		if (!static::isValidImageHandle($handle)) {
209
			throw new InvalidImageSourceException("File '{$uri}' appears to be an invalid image source.");
210
		}
211
		
212
		return static::loadFromHandle($handle);
213
	}
214
215
	/**
216
	 * Create and load an image from a string. Format is auto-detected.
217
	 * 
218
	 * @param string $string Binary data, i.e. from BLOB field in the database
219
	 * @return \WideImage\Image|\WideImage\PaletteImage|\WideImage\TrueColorImage
220
	 */
221
	public static function loadFromString($string)
222
	{
223
		if (strlen($string) < 128) {
224
			throw new InvalidImageSourceException("String doesn't contain image data.");
225
		}
226
		
227
		$handle = @imagecreatefromstring($string);
228
		
229
		if (!static::isValidImageHandle($handle)) {
230
			$custom_mappers = MapperFactory::getCustomMappers();
231
			
232
			foreach ($custom_mappers as $mime_type => $mapper_class) {
233
				$mapper = MapperFactory::selectMapper(null, $mime_type);
234
				$handle = $mapper->loadFromString($string);
235
				
236
				if (static::isValidImageHandle($handle)) {
237
					break;
238
				}
239
			}
240
		}
241
		
242
		if (!static::isValidImageHandle($handle)) {
243
			throw new InvalidImageSourceException("String doesn't contain valid image data.");
244
		}
245
		
246
		return static::loadFromHandle($handle);
247
	}
248
	
249
	/**
250
	 * Create and load an image from an image handle.
251
	 * 
252
	 * <b>Note:</b> the resulting image object takes ownership of the passed 
253
	 * handle. When the newly-created image object is destroyed, the handle is 
254
	 * destroyed too, so it's not a valid image handle anymore. In order to 
255
	 * preserve the handle for use after object destruction, you have to call 
256
	 * \WideImage\Image::releaseHandle() on the created image instance prior to its
257
	 * destruction.
258
	 * 
259
	 * <code>
260
	 * $handle = imagecreatefrompng('file.png');
261
	 * $image = WideImage::loadFromHandle($handle);
262
	 * </code>
263
	 * 
264
	 * @param resource $handle A valid GD image resource
265
	 * @return \WideImage\Image|\WideImage\PaletteImage|\WideImage\TrueColorImage
266
	 */
267
	public static function loadFromHandle($handle)
268
	{
269
		if (!static::isValidImageHandle($handle)) {
270
			throw new InvalidImageSourceException("Handle is not a valid GD image resource.");
271
		}
272
		
273
		if (imageistruecolor($handle)) {
274
			return new TrueColorImage($handle);
275
		}
276
		
277
		return new PaletteImage($handle);
278
	}
279
	
280
	/**
281
	 * This method loads a file from the $_FILES array. The image format is auto-detected.
282
	 * 
283
	 * You only have to pass the field name as the parameter. For array fields, this function will
284
	 * return an array of image objects, unless you specify the $index parameter, which will
285
	 * load the desired image.
286
	 * 
287
	 * @param $field_name Name of the key in $_FILES array
0 ignored issues
show
Bug introduced by
The type WideImage\Name was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
288
	 * @param int $index The index of the file to load (if the input field is an array)
289
	 * @return \WideImage\Image The loaded image
290
	 */
291
	public static function loadFromUpload($field_name, $index = null)
292
	{
293
		if (!array_key_exists($field_name, $_FILES)) {
294
			throw new InvalidImageSourceException("Upload field '{$field_name}' doesn't exist.");
295
		}
296
		
297
		if (is_array($_FILES[$field_name]['tmp_name'])) {
298
			if (isset($_FILES[$field_name]['tmp_name'][$index])) {
299
				$filename = $_FILES[$field_name]['tmp_name'][$index];
300
			} else {
301
				$result = array();
302
				
303
				foreach ($_FILES[$field_name]['tmp_name'] as $idx => $tmp_name) {
304
					$result[$idx] = static::loadFromFile($tmp_name);
305
				}
306
				
307
				return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type array which is incompatible with the documented return type WideImage\Image.
Loading history...
308
			}
309
		} else {
310
			$filename = $_FILES[$field_name]['tmp_name'];
311
		}
312
		
313
		if (!file_exists($filename)) {
314
			throw new InvalidImageSourceException("Uploaded file doesn't exist.");
315
		}
316
		
317
		return static::loadFromFile($filename);
318
	}
319
	
320
	/**
321
	 * Factory method for creating a palette image
322
	 * 
323
	 * @param int $width
324
	 * @param int $height
325
	 * @return \WideImage\PaletteImage
326
	 */
327
	public static function createPaletteImage($width, $height)
328
	{
329
		return PaletteImage::create($width, $height);
330
	}
331
	
332
	/**
333
	 * Factory method for creating a true-color image
334
	 * 
335
	 * @param int $width
336
	 * @param int $height
337
	 * @return \WideImage\TrueColorImage
338
	 */
339
	public static function createTrueColorImage($width, $height)
340
	{
341
		return TrueColorImage::create($width, $height);
342
	}
343
	
344
	/**
345
	 * Check whether the given handle is a valid GD resource
346
	 * 
347
	 * @param mixed $handle The variable to check
348
	 * @return bool
349
	 */
350
	public static function isValidImageHandle($handle)
351
	{
352
		return (is_resource($handle) && get_resource_type($handle) == 'gd');
353
	}
354
	
355
	/**
356
	 * Throws exception if the handle isn't a valid GD resource
357
	 * 
358
	 * @param mixed $handle The variable to check
359
	 */
360
	public static function assertValidImageHandle($handle)
361
	{
362
		if (!static::isValidImageHandle($handle)) {
363
			throw new InvalidImageHandleException("{$handle} is not a valid image handle.");
364
		}
365
	}
366
}
367
	
368
WideImage::checkGD();
369
370
WideImage::registerCustomMapper('\\WideImage\\Mapper\\BMP', 'image/bmp', 'bmp');
371
WideImage::registerCustomMapper('\\WideImage\\Mapper\\TGA', 'image/tga', 'tga');
372