store::serialize()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/**
3
 * Color Data Class
4
 * ================
5
 * Stores data about a particular color in multiple formats.
6
 */
7
8
namespace projectcleverweb\color\data;
9
10
use \projectcleverweb\color\regulate;
11
use \projectcleverweb\color\css;
12
use \projectcleverweb\color\hsl;
13
use \projectcleverweb\color\error;
14
use \projectcleverweb\color\convert; // namespace
15
16
/**
17
 * Color Data Class
18
 * ================
19
 * Stores data about a particular color in multiple formats.
20
 */
21
class store implements \Serializable, \JsonSerializable {
22
	
23
	protected $color_spaces = array();
24
	
25
	/**
26
	 * All the valid color spaces types
27
	 * @var array
28
	 */
29
	protected static $valid_color_spaces = array(
30
		'rgb',
31
		'hsl',
32
		'hsb',
33
		'cmyk'
34
	);
35
	
36
	/**
37
	 * All the valid importable types
38
	 * @var array
39
	 */
40
	protected static $valid_imports = array(
41
		'object',
42
		'hex',
43
		'int',
44
		'css'
45
	);
46
	
47
	/**
48
	 * All the valid types
49
	 * @var array
50
	 */
51
	protected static $valid_types = array(
52
		'rgb',
53
		'hsl',
54
		'hsb',
55
		'cmyk',
56
		'object',
57
		'hex',
58
		'int',
59
		'css'
60
	);
61
	
62
	private $current_space = 'rgb';
63
	
64
	/**
65
	 * $the current colors alpha channel (Opacity)
66
	 * @var float
67
	 */
68
	protected $alpha = 100.0;
69
	
70
	/**
71
	 * Takes an input color and imports it as its respective type.
72
	 * 
73
	 * @param mixed  $color An RGB (array), HSL (array), Hex (string), Integer (hex), or CMYK (array) representation of a color.
74
	 * @param string $type  (optional) The type to try to import it as
75
	 */
76
	public function __construct($color, string $type = '') {
77
		if (empty($type)) {
78
			$type = type::get($color);
79
		}
80
		if (!in_array($type, static::$valid_types)) {
81
			error::trigger(error::INVALID_ARGUMENT, sprintf(
82
				'Invalid color type "%s"',
83
				$type
84
			));
85
			$type = 'rgb';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
86
			$color = array(
87
				'r' => 0,
88
				'g' => 0,
89
				'b' => 0
90
			);
91
		}
92
		if (in_array($type, static::$valid_imports)) {
93
			call_user_func([__CLASS__, 'import_'.$type], $color);
94
		} else {
95
			$this->__set($type, $color);
96
		}
97
	}
98
	
99
	public function __get($key) {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
100
		if (!in_array($key, static::$valid_color_spaces)) {
101
			error::trigger(error::INVALID_ARGUMENT, sprintf(
102
				'Cannot get color space "%s"',
103
				$key
104
			));
105
			return $this->__get($this->current_space);
106
		}
107
		if (!$this->__isset($key)) {
108
			$this->color_spaces[$key] = static::_get_convert($this->color_spaces, $this->current_space, $key);
109
		}
110
		return (array) $this->color_spaces[$key];
111
	}
112
	
113
	public function __set($key, $value) {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
114
		if (in_array($key, static::$valid_color_spaces)) {
115
			$color_space = __NAMESPACE__.'\\color\\space\\'.$key;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 14 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
116
			$this->color_spaces[$key] = new $color_space($value);
117
			$this->current_space = $key;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
118
			return $this->__get($key);
119
		}
120
		error::trigger(error::INVALID_ARGUMENT, sprintf(
121
			'Cannot set color space "%s"',
122
			__CLASS__
123
		));
124
	}
125
	
126
	public function __isset($key) {
127
		return isset($this->color_spaces[$key]);
128
	}
129
	
130
	public function __unset($key) {
131
		if ($this->__isset($key) && count($this->color_spaces) > 1) {
132
			unset($this->color_spaces);
133
		} elseif ($this->__isset($key)) {
134
			$this->clear('rgb', array(
135
				'r' => 0,
136
				'g' => 0,
137
				'b' => 0
138
			));
139
		}
140
	}
141
	
142
	protected static function _get_convert(array $color_spaces, string $current, string $to) {
143
		if (isset($color_spaces[$current])) {
144
			$from = $current;
145
		} else {
146
			reset($color_spaces);
147
			$from = key($color_spaces);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 16 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
148
			$this->current_space = $from; // Original space was unset
0 ignored issues
show
Bug introduced by
The variable $this does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
149
		}
150
		$convert = call_user_func(array('\\projectcleverweb\\color\\convert\\'.$from, 'to_'.$to), $color_spaces[$from]);
151
		$space   = __NAMESPACE__.'\\color\\space\\'.$to;
152
		return new $space($convert);
153
	}
154
	
155
	public function clear_cache() {
156
		
157
		if (is_callable([__CLASS__, 'import_'.$type])) {
158
			call_user_func([__CLASS__, 'import_'.$type], $color);
0 ignored issues
show
Bug introduced by
The variable $type does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $color does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
159
		} else {
160
			error::trigger();
0 ignored issues
show
Bug introduced by
The call to trigger() misses some required arguments starting with $code.
Loading history...
161
		}
162
	}
163
	
164
	protected function _clear() {
165
		$this->color_spaces = array();
166
	}
167
	
168
	protected function get_space() {
169
		return $this->current_space;
170
	}
171
	
172
	protected function set_space(string $color_space) :string {
173
		if (in_array(static::$valid_color_spaces)) {
174
			$this->current_space = $color_space;
175
		}
176
		return $this->current_space;
177
	}
178
	
179
	/**
180
	 * Serializes this object.
181
	 * 
182
	 * @return string The serialized object
183
	 */
184
	public function serialize() :string {
185
		return json_encode($this->rgb + ['a' => $this->alpha]);
186
	}
187
	
188
	/**
189
	 * Unserializes this object.
190
	 * 
191
	 * @param  string $serialized The object as a serialized string
192
	 * @return void
193
	 */
194
	public function unserialize($serialized) {
195
		$unserialized = (array) json_decode((string) $serialized);
196
		regulate::rgb_array($unserialized);
197
		$this->import_rgb($unserialized);
198
	}
199
	
200
	/**
201
	 * Serializes this object into JSON.
202
	 * 
203
	 * @return string The serialized object
0 ignored issues
show
Documentation introduced by
Should the return type not be array? Also, consider making the array more specific, something like array<String>, or String[].

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.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
204
	 */
205
	public function jsonSerialize() :array {
206
		return $this->color_spaces + ['alpha' => $this->alpha];
207
	}
208
	
209
	/**
210
	 * Handles general errors when importing, and forces the input to be valid.
211
	 * 
212
	 * @return void
213
	 */
214 View Code Duplication
	protected function import_error() {
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...
215
		error::trigger(error::INVALID_COLOR, sprintf(
216
			'The color supplied to %s\'s constructor was not valid',
217
			__CLASS__
218
		));
219
		$this->import_rgb([0, 0, 0]);
220
	}
221
	
222
	/**
223
	 * Import the alpha channel from a color array, or create one if it doesn't exist
224
	 * 
225
	 * @param  array $color The color array to check
226
	 * @return void
227
	 */
228 View Code Duplication
	protected function import_alpha(array $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...
229
		if (isset($color['a'])) {
230
			$this->alpha = regulate::max((float) $color['a'], 100);
231
		} else {
232
			$this->alpha = 100.0;
233
		}
234
	}
235
	
236
	/**
237
	 * Handles importing of another instance of color
238
	 * 
239
	 * @return void
240
	 */
241
	protected function import_object(store $color) {
242
		$this->_clear();
243
		foreach ($this->color_spaces as $space => $data) {
244
			$color_space = __NAMESPACE__.'\\space\\'.$space;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 16 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
245
			$this->color_spaces[$space] = new $color_space($data);
246
		}
247
		$this->current_space        = $color->get_space();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 1 space but found 8 spaces

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
248
		$this->alpha                = $color->alpha;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 9 spaces but found 16 spaces

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
249
	}
250
	
251
	/**
252
	 * Imports a RGB array.
253
	 * 
254
	 * @param  array $color Array with offsets 'r', 'g', 'b'
255
	 * @return void
256
	 */
257
	public function import_rgb(array $color) {
258
		$this->_clear();
259
		$this->color_spaces['rgb'] = new color\space\rgb($color);
260
		$this->import_alpha($color);
261
	}
262
	
263
	/**
264
	 * Imports a hsl array.
265
	 * 
266
	 * @param  array $color Array with offsets 'h', 's', 'l'
267
	 * @return void
268
	 */
269
	public function import_hsl(array $color) {
270
		$this->_clear();
271
		$this->color_spaces['hsl'] = new color\space\hsl($color);
272
		$this->import_alpha($color);
273
	}
274
	
275
	/**
276
	 * Imports a hsb array.
277
	 * 
278
	 * @param  array $color Array with offsets 'h', 's', 'b'
279
	 * @return void
280
	 */
281
	public function import_hsb(array $color) {
282
		$this->_clear();
283
		$this->color_spaces['hsb'] = new color\space\hsb($color);
284
		$this->import_alpha($color);
285
	}
286
	
287
	/**
288
	 * Imports a CMYK array
289
	 * 
290
	 * @param  array $color Array with offsets 'c', 'm', 'y', 'k'
291
	 * @return void
292
	 */
293
	public function import_cmyk(array $color) {
294
		$this->_clear();
295
		$this->color_spaces['cmyk'] = new color\space\cmyk($color);
296
		$this->import_alpha($color);
297
	}
298
	
299
	/**
300
	 * Converts a hexadecimal string into an RGB array and imports it.
301
	 * 
302
	 * @param  string $color Hexadecimal string
303
	 * @return void
304
	 */
305
	public function import_hex(string $color) {
306
		$this->import_rgb(convert\hex::to_rgb($color));
307
	}
308
	
309
	/**
310
	 * Converts a hexadecimal string into an RGB array and imports it.
311
	 * 
312
	 * @param  string $color Hexadecimal string
313
	 * @return void
314
	 */
315
	public function import_css(string $color) {
316
		// result will either be an RGB or HSL array
317
		self::__construct(css::get($color));
318
	}
319
	
320
	/**
321
	 * Converts an integer to a hexadecimal string and imports it.
322
	 * 
323
	 * @param  int $color An integer
324
	 * @return void
325
	 */
326
	public function import_int(int $color) {
327
		regulate::hex_int($color);
328
		$this->import_hex(str_pad(base_convert($color, 10, 16), 6, '0', STR_PAD_LEFT));
329
	}
330
}
331