Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
78.23% covered (success)
78.23%
97 / 124
95.83% covered (success)
95.83%
23 / 24
CRAP
0.00% covered (danger)
0.00%
0 / 1
Hsl
78.23% covered (success)
78.23%
97 / 124
95.83% covered (success)
95.83%
23 / 24
92.73
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 setH
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 setS
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 setL
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 setA
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getH
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getS
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getL
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getA
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasA
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasAlpha
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toRgb
42.55% covered (warning)
42.55%
20 / 47
0.00% covered (danger)
0.00%
0 / 1
24.36
 toHex
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toArray
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
4
 render
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __set
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __get
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __isset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __unset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetExists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
4
 offsetGet
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
6
 offsetSet
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
6
 offsetUnset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Css\Color;
15
16use ReturnTypeWillChange;
17
18/**
19 * Pop CSS HSL color class
20 *
21 * @category   Pop
22 * @package    Pop\Css
23 * @author     Nick Sagona, III <dev@nolainteractive.com>
24 * @copyright  Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com)
25 * @license    http://www.popphp.org/license     New BSD License
26 * @version    1.1.0
27 */
28class Hsl implements \ArrayAccess, ColorInterface
29{
30
31    /**
32     * H value
33     * @var int
34     */
35    protected $h = 0;
36
37    /**
38     * S value
39     * @var int
40     */
41    protected $s = 0;
42
43    /**
44     * L value
45     * @var int
46     */
47    protected $l = 0;
48
49    /**
50     * Alpha value
51     * @var int
52     */
53    protected $a = null;
54
55    /**
56     * Constructor
57     *
58     * Instantiate the CSS HSL color object
59     *
60     * @param int   $h
61     * @param int   $s
62     * @param int   $l
63     * @param float $a
64     */
65    public function __construct($h, $s, $l, $a = null)
66    {
67        $this->setH($h);
68        $this->setS($s);
69        $this->setL($l);
70        if (null !== $a) {
71            $this->setA($a);
72        }
73    }
74
75    /**
76     * Set H value
77     *
78     * @param  int $h
79     * @throws \OutOfRangeException
80     * @return self
81     */
82    public function setH($h)
83    {
84        $h = (int)$h;
85        if (($h > 360) || ($h < 0)) {
86            throw new \OutOfRangeException('Error: The value of $h must be between 0 and 360.');
87        }
88        $this->h = $h;
89        return $this;
90    }
91
92    /**
93     * Set S value
94     *
95     * @param  int $s
96     * @throws \OutOfRangeException
97     * @return self
98     */
99    public function setS($s)
100    {
101        $s = (int)$s;
102        if (($s > 100) || ($s < 0)) {
103            throw new \OutOfRangeException('Error: The value of $s must be between 0 and 100.');
104        }
105        $this->s = $s;
106        return $this;
107    }
108
109    /**
110     * Set L value
111     *
112     * @param  int $l
113     * @throws \OutOfRangeException
114     * @return self
115     */
116    public function setL($l)
117    {
118        $l = (int)$l;
119        if (($l > 100) || ($l < 0)) {
120            throw new \OutOfRangeException('Error: The value of $l must be between 0 and 100.');
121        }
122        $this->l = $l;
123        return $this;
124    }
125
126    /**
127     * Set A value
128     *
129     * @param  float $a
130     * @throws \OutOfRangeException
131     * @return self
132     */
133    public function setA($a)
134    {
135        $a = (float)$a;
136        if (($a > 1) || ($a < 0)) {
137            throw new \OutOfRangeException('Error: The value of $l must be between 0 and 1.');
138        }
139        $this->a = $a;
140        return $this;
141    }
142
143    /**
144     * Get H value
145     *
146     * @return int
147     */
148    public function getH()
149    {
150        return $this->h;
151    }
152
153    /**
154     * Get S value
155     *
156     * @return int
157     */
158    public function getS()
159    {
160        return $this->s;
161    }
162
163    /**
164     * Get L value
165     *
166     * @return int
167     */
168    public function getL()
169    {
170        return $this->l;
171    }
172
173    /**
174     * Get A value
175     *
176     * @return float
177     */
178    public function getA()
179    {
180        return $this->a;
181    }
182
183    /**
184     * Determine if the color object has an alpha value
185     *
186     * @return boolean
187     */
188    public function hasA()
189    {
190        return (null !== $this->a);
191    }
192
193    /**
194     * Determine if the color object has an alpha value (alias)
195     *
196     * @return boolean
197     */
198    public function hasAlpha()
199    {
200        return (null !== $this->a);
201    }
202
203    /**
204     * Convert to RGB
205     *
206     * @return Rgb
207     */
208    public function toRgb()
209    {
210        $s = $this->s / 100;
211        $v = $this->l / 100;
212
213        if ($this->s == 0) {
214            $r = round($v * 255);
215            $g = round($v * 255);
216            $b = round($v * 255);
217        } else {
218            $h = $this->h / 360;
219            $h = $h * 6;
220            if ($h == 6) {
221                $h = 0;
222            }
223
224            $i  = floor($h);
225            $v1 = $v * (1 - $s);
226            $v2 = $v * (1 - ($s * ($h - $i)));
227            $v3 = $v * (1 - ($s * (1 - ($h - $i))));
228
229            switch ($i) {
230                case 0:
231                    $r = $v;
232                    $g = $v3;
233                    $b = $v1;
234                    break;
235                case 1:
236                    $r = $v2;
237                    $g = $v;
238                    $b = $v1;
239                    break;
240                case 2:
241                    $r = $v1;
242                    $g = $v;
243                    $b = $v3;
244                    break;
245                case 3:
246                    $r = $v1;
247                    $g = $v;
248                    $b = $v3;
249                    break;
250                case 4:
251                    $r = $v3;
252                    $g = $v1;
253                    $b = $v;
254                    break;
255                default:
256                    $r = $v;
257                    $g = $v1;
258                    $b = $v2;
259            }
260
261            $r = round($r * 255);
262            $g = round($g * 255);
263            $b = round($b * 255);
264        }
265
266        return new Rgb($r, $g, $b, $this->a);
267    }
268
269    /**
270     * Convert to hex
271     *
272     * @return Hex
273     */
274    public function toHex()
275    {
276        return $this->toRgb()->toHex();
277    }
278
279    /**
280     * Convert to array
281     *
282     * @param  boolean $assoc
283     * @return array
284     */
285    public function toArray($assoc = true)
286    {
287        $hsl = [];
288
289        if ($assoc) {
290            $hsl['h'] = $this->h;
291            $hsl['s'] = $this->s . '%';
292            $hsl['l'] = $this->l . '%';
293            if (null !== $this->a) {
294                $hsl['a'] = $this->a;
295            }
296        } else {
297            $hsl[] = $this->h;
298            $hsl[] = $this->s . '%';
299            $hsl[] = $this->l . '%';
300            if (null !== $this->a) {
301                $hsl[] = $this->a;
302            }
303        }
304
305        return $hsl;
306    }
307
308    /**
309     * Convert to CSS-formatted string
310     *
311     * @return string
312     */
313    public function render()
314    {
315        return ((null !== $this->a) ? 'hsla(' : 'hsl(') . implode(', ', $this->toArray()) . ')';
316    }
317
318    /**
319     * Return CSS-formatted string
320     *
321     * @return string
322     */
323    public function __toString()
324    {
325        return $this->render();
326    }
327
328    /**
329     * Magic method to set the color value
330     *
331     * @param  string $name
332     * @param  mixed $value
333     * @return void
334     */
335    public function __set($name, $value)
336    {
337        $this->offsetSet($name, $value);
338    }
339
340    /**
341     * Magic method to return the color value
342     *
343     * @param  string $name
344     * @return mixed
345     */
346    public function __get($name)
347    {
348        return $this->offsetGet($name);
349    }
350
351    /**
352     * Magic method to return whether the color value exists
353     *
354     * @param  string $name
355     * @return boolean
356     */
357    public function __isset($name)
358    {
359        return $this->offsetExists($name);
360    }
361
362    /**
363     * Magic method to unset color value
364     *
365     * @param  string $name
366     * @throws Exception
367     * @return void
368     */
369    public function __unset($name)
370    {
371        throw new Exception('You cannot unset the properties of this color object.');
372    }
373
374    /**
375     * ArrayAccess offsetExists
376     *
377     * @param  mixed $offset
378     * @return boolean
379     */
380    public function offsetExists($offset): bool
381    {
382        return (($offset == 'h') || ($offset == 's') || ($offset == 'l') || ($offset == 'a'));
383    }
384
385    /**
386     * ArrayAccess offsetGet
387     *
388     * @param  mixed $offset
389     * @throws Exception
390     * @return mixed
391     */
392    #[ReturnTypeWillChange]
393    public function offsetGet($offset)
394    {
395        switch ($offset) {
396            case 'h':
397                return $this->getH();
398                break;
399            case 's':
400                return $this->getS();
401                break;
402            case 'l':
403                return $this->getL();
404                break;
405            case 'a':
406                return $this->getA();
407                break;
408            default:
409                throw new Exception("Error: You can only use 'h', 's', 'l' or 'a'.");
410        }
411    }
412
413    /**
414     * ArrayAccess offsetSet
415     *
416     * @param  mixed $offset
417     * @param  mixed $value
418     * @throws Exception
419     * @return void
420     */
421    #[ReturnTypeWillChange]
422    public function offsetSet($offset, $value)
423    {
424        switch ($offset) {
425            case 'h':
426                $this->setH($value);
427                break;
428            case 's':
429                $this->setS($value);
430                break;
431            case 'l':
432                $this->setL($value);
433                break;
434            case 'a':
435                $this->setA($value);
436                break;
437            default:
438                throw new Exception("Error: You can only use 'h', 's', 'l' or 'a'.");
439        }
440    }
441
442    /**
443     * ArrayAccess offsetUnset
444     *
445     * @param  mixed $offset
446     * @throws Exception
447     * @return void
448     */
449    #[ReturnTypeWillChange]
450    public function offsetUnset($offset)
451    {
452        throw new Exception('You cannot unset the properties of this color object.');
453    }
454
455}