store2::jsonSerialize()   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 store2 implements \Serializable, \JsonSerializable {
22
	
23
	protected $color_spaces = array();
24
	
25
	
26
	/**
27
	 * The current color as a hexadecimal string
28
	 * @var string
29
	 */
30
	public $hex;
31
	
32
	/**
33
	 * The current color as a RGB array
34
	 * @var array
35
	 */
36
	public $rgb;
37
	
38
	/**
39
	 * The current color as an instance of hsl (which implements ArrayAccess)
40
	 * @var hsl
41
	 */
42
	public $hsl;
43
	
44
	/**
45
	 * $the current colors alpha channel (Opacity)
46
	 * @var float
47
	 */
48
	protected $alpha = 100.0;
49
	
50
	/**
51
	 * Takes an input color and imports it as its respective type.
52
	 * 
53
	 * @param mixed  $color An RGB (array), HSL (array), Hex (string), Integer (hex), or CMYK (array) representation of a color.
54
	 * @param string $type  (optional) The type to try to import it as
55
	 */
56
	public function __construct($color, string $type = '') {
57
		if (is_a($color, __CLASS__)) {
58
			$type = 'color';
59
		} elseif (empty($type) || !is_callable([__CLASS__, 'import_'.$type])) {
60
			$type = static::get_type($color);
61
		}
62
		call_user_func([__CLASS__, 'import_'.$type], $color);
63
	}
64
	
65
	/**
66
	 * Shortcut for invoking into an HSL array
67
	 * 
68
	 * @return array The HSL array
69
	 */
70
	public function hsl() {
71
		return ($this->hsl)();
72
	}
73
	
74
	/**
75
	 * Serializes this object.
76
	 * 
77
	 * @return string The serialized object
78
	 */
79
	public function serialize() :string {
80
		return json_encode($this->rgb + ['a' => $this->alpha]);
81
	}
82
	
83
	/**
84
	 * Unserializes this object.
85
	 * 
86
	 * @param  string $serialized The object as a serialized string
87
	 * @return void
88
	 */
89
	public function unserialize($serialized) {
90
		$unserialized = (array) json_decode((string) $serialized);
91
		regulate::rgb_array($unserialized);
92
		$this->import_rgb($unserialized);
93
	}
94
	
95
	/**
96
	 * Serializes this object into JSON.
97
	 * 
98
	 * @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...
99
	 */
100
	public function jsonSerialize() :array {
101
		return $this->rgb + ['a' => $this->alpha];
102
	}
103
	
104
	/**
105
	 * Determine the type of color being used.
106
	 * 
107
	 * @param  mized  $color The color in question
108
	 * @return string        The color type as a string, returns 'error' if $color is invalid
109
	 */
110 View Code Duplication
	public static function get_type($color) :string {
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...
111
		if (is_array($color)) {
112
			return static::_get_array_type($color);
113
		} elseif (is_string($color)) {
114
			// return static::_get_str_type($color);
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
115
			return 'str';
116
		} elseif (is_int($color)) {
117
			return 'int';
118
		}
119
		return 'error';
120
	}
121
	
122
	protected function _get_str_type(string $color) {
123
		$color = strtolower(str_replace(array(' ', "\t", "\n", "\r", "\0", "\x0B"), '', $color));
124
		if (regulate::_validate_hex_str($color, TRUE)) {
125
			return 'hex';
126
		} elseif (css::get($color, FALSE)) {
127
			return 'css';
128
		} elseif (x11::get($color)) {
129
			return 'x11';
130
		}
131
		return 'error';
132
	}
133
	
134
	/**
135
	 * Determine the type of color being used if it is an array.
136
	 * 
137
	 * @param  array  $color The color in question
138
	 * @return string        The color type as a string, returns 'error' if $color is invalid
139
	 */
140 View Code Duplication
	protected static function _get_array_type(array $color) :string {
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...
141
		$color = array_change_key_case($color);
142
		unset($color['a']); // ignore alpha channel
143
		ksort($color);
144
		$type  = implode('', array_keys($color));
145
		$types = [
146
			'bgr'  => 'rgb',
147
			'hls'  => 'hsl',
148
			'bhs'  => 'hsb',
149
			'ckmy' => 'cmyk'
150
		];
151
		if (isset($types[$type])) {
152
			return $types[$type];
153
		}
154
		return 'error';
155
	}
156
	
157
	/**
158
	 * Get (and set) the alpha channel
159
	 * 
160
	 * @param  mixed $new_alpha If numeric, the alpha channel is set to this value
161
	 * @return float            The current alpha value
162
	 */
163
	public function alpha($new_alpha = NULL) :float {
164
		if (is_numeric($new_alpha)) {
165
			$this->alpha = (float) $new_alpha;
166
		}
167
		return $this->alpha;
168
	}
169
	
170
	/**
171
	 * Handles general errors when importing, and forces the input to be valid.
172
	 * 
173
	 * @return void
174
	 */
175 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...
176
		error::trigger(error::INVALID_COLOR, sprintf(
177
			'The color supplied to %s\'s constructor was not valid',
178
			__CLASS__
179
		));
180
		$this->import_rgb([0, 0, 0]);
181
	}
182
	
183
	/**
184
	 * Import the alpha channel from a color array, or create one if it doesn't exist
185
	 * 
186
	 * @param  array $color The color array to check
187
	 * @return void
188
	 */
189 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...
190
		if (isset($color['a'])) {
191
			$this->alpha = regulate::max((float) $color['a'], 100);
192
		} else {
193
			$this->alpha = 100.0;
194
		}
195
	}
196
	
197
	/**
198
	 * Handles importing of another instance of color
199
	 * 
200
	 * @return void
201
	 */
202
	protected function import_color(data $color) {
203
		$this->rgb   = $color->rgb;
204
		$this->hex   = $color->hex;
205
		$this->hsl   = clone $color->hsl;
206
		$this->alpha = $color->alpha;
207
	}
208
	
209
	/**
210
	 * Imports a RGB array.
211
	 * 
212
	 * @param  array $color Array with offsets 'r', 'g', 'b'
213
	 * @return void
214
	 */
215
	public function import_rgb(array $color) {
216
		regulate::rgb_array($color);
217
		$this->rgb = array_intersect_key($color, ['r' => 0, 'g' => 0, 'b' => 0]);
218
		$this->hex = convert\rgb::to_hex($this->rgb);
219
		$this->hsl = new hsl($this->rgb);
220
		$this->import_alpha($color);
221
	}
222
	
223
	/**
224
	 * Imports a hsl array.
225
	 * 
226
	 * @param  array $color Array with offsets 'h', 's', 'l'
227
	 * @return void
228
	 */
229 View Code Duplication
	public function import_hsl(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...
230
		regulate::hsl_array($color);
231
		$this->rgb = convert\hsl::to_rgb($color);
232
		$this->hsl = new hsl($this->rgb); // [todo] This should taken from input
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
233
		$this->hex = convert\rgb::to_hex($this->rgb);
234
		$this->import_alpha($color);
235
	}
236
	
237
	/**
238
	 * Imports a hsb array.
239
	 * 
240
	 * @param  array $color Array with offsets 'h', 's', 'b'
241
	 * @return void
242
	 */
243 View Code Duplication
	public function import_hsb(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...
244
		regulate::hsb_array($color);
245
		$this->rgb = convert\hsb::to_rgb($color);
246
		$this->hsl = new hsl($this->rgb);
247
		$this->hex = convert\rgb::to_hex($this->rgb);
248
		$this->import_alpha($color);
249
	}
250
	
251
	/**
252
	 * Converts a hexadecimal string into an RGB array and imports it.
253
	 * 
254
	 * @param  string $color Hexadecimal string
255
	 * @return void
256
	 */
257
	public function import_hex(string $color) {
258
		regulate::hex($color);
259
		$this->import_rgb(convert\hex::to_rgb($color));
260
	}
261
	
262
	public function import_str(string $color) {
263
		$color = strtolower(str_replace(array(' ', "\t", "\n", "\r", "\0", "\x0B"), '', $color));
264
		if (regulate::_validate_hex_str($color, TRUE)) {
265
			$this->import_hex($color);
266
			return;
267
		} elseif (preg_match('/\A(rgb|hsl)a?\((\d+),(\d+),(\d+)(?:,(\d|\d\.\d?|\.\d+))?\)\Z/i', $color, $match)) {
268
			$this->import_regex($match);
269
			return;
270
		} elseif ($x11 = x11::get($color)) {
271
			$this->import_rgb($x11);
272
			return;
273
		}
274
		$this->import_error();
275
	}
276
	
277
	public function import_regex(array $match) {
278
		$alpha = 100;
279
		if (isset($match[5])) {
280
			$alpha = (float) $match[5] * 100;
281
		}
282
		$color = array_combine(str_split($match[1].'a'), [$match[2], $match[3], $match[4], $alpha]);
283
		call_user_func([__CLASS__, 'import_'.$match[1]], $color);
284
	}
285
	
286
	/**
287
	 * Converts an integer to a hexadecimal string and imports it.
288
	 * 
289
	 * @param  int $color An integer
290
	 * @return void
291
	 */
292
	public function import_int(int $color) {
293
		regulate::hex_int($color);
294
		$this->import_hex(str_pad(base_convert($color, 10, 16), 6, '0', STR_PAD_LEFT));
295
	}
296
	
297
	/**
298
	 * Imports a CMYK array
299
	 * 
300
	 * @param  array $color Array with offsets 'c', 'm', 'y', 'k'
301
	 * @return void
302
	 */
303
	public function import_cmyk(array $color) {
304
		regulate::cmyk_array($color);
305
		$this->import_rgb(convert\cmyk::to_rgb($color['c'], $color['m'], $color['y'], $color['k']));
0 ignored issues
show
Unused Code introduced by
The call to cmyk::to_rgb() has too many arguments starting with $color['m'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
306
		$this->import_alpha($color);
307
	}
308
}
309