Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
99 / 99
100.00% covered (success)
100.00%
24 / 24
CRAP
100.00% covered (success)
100.00%
1 / 1
Rgb
100.00% covered (success)
100.00%
99 / 99
100.00% covered (success)
100.00%
24 / 24
58
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 setR
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 setG
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 setB
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
 getR
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getG
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getB
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
 toHsl
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
9
 toHex
100.00% covered (success)
100.00%
2 / 2
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 RGB 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 Rgb implements \ArrayAccess, ColorInterface
29{
30
31    /**
32     * R value
33     * @var int
34     */
35    protected $r = 0;
36
37    /**
38     * G value
39     * @var int
40     */
41    protected $g = 0;
42
43    /**
44     * B value
45     * @var int
46     */
47    protected $b = 0;
48
49    /**
50     * Alpha value
51     * @var int
52     */
53    protected $a = null;
54
55    /**
56     * Constructor
57     *
58     * Instantiate the CSS RGB color object
59     *
60     * @param int   $r
61     * @param int   $g
62     * @param int   $b
63     * @param float $a
64     */
65    public function __construct($r, $g, $b, $a = null)
66    {
67        $this->setR($r);
68        $this->setG($g);
69        $this->setB($b);
70        if (null !== $a) {
71            $this->setA($a);
72        }
73    }
74
75    /**
76     * Set R value
77     *
78     * @param  int $r
79     * @throws \OutOfRangeException
80     * @return self
81     */
82    public function setR($r)
83    {
84        $r = (int)$r;
85        if (($r > 255) || ($r < 0)) {
86            throw new \OutOfRangeException('Error: The value of $r must be between 0 and 255.');
87        }
88        $this->r = $r;
89        return $this;
90    }
91
92    /**
93     * Set G value
94     *
95     * @param  int $g
96     * @throws \OutOfRangeException
97     * @return self
98     */
99    public function setG($g)
100    {
101        $g = (int)$g;
102        if (($g > 255) || ($g < 0)) {
103            throw new \OutOfRangeException('Error: The value of $g must be between 0 and 255.');
104        }
105        $this->g = $g;
106        return $this;
107    }
108
109    /**
110     * Set B value
111     *
112     * @param  int $b
113     * @throws \OutOfRangeException
114     * @return self
115     */
116    public function setB($b)
117    {
118        $b = (int)$b;
119        if (($b > 255) || ($b < 0)) {
120            throw new \OutOfRangeException('Error: The value of $b must be between 0 and 255.');
121        }
122        $this->b = $b;
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 R value
145     *
146     * @return int
147     */
148    public function getR()
149    {
150        return $this->r;
151    }
152
153    /**
154     * Get G value
155     *
156     * @return int
157     */
158    public function getG()
159    {
160        return $this->g;
161    }
162
163    /**
164     * Get B value
165     *
166     * @return int
167     */
168    public function getB()
169    {
170        return $this->b;
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 HSL
205     *
206     * @return Hsl
207     */
208    public function toHsl()
209    {
210        $r = $this->getR();
211        $g = $this->getG();
212        $b = $this->getB();
213
214        $min = min($r, min($g, $b));
215        $max = max($r, max($g, $b));
216        $delta = $max - $min;
217        $h = 0;
218
219        if ($delta > 0) {
220            if ($max == $r && $max != $g) $h += ($g - $b) / $delta;
221            if ($max == $g && $max != $b) $h += (2 + ($b - $r) / $delta);
222            if ($max == $b && $max != $r) $h += (4 + ($r - $g) / $delta);
223            $h /= 6;
224        }
225
226        // Calculate the saturation and brightness.
227        $r = $this->getR() / 255;
228        $g = $this->getG() / 255;
229        $b = $this->getB() / 255;
230
231        $max = max($r, $g, $b);
232        $min = min($r, $g, $b);
233
234        $l = $max;
235        $d = $max - $min;
236        $s = ($d == 0) ? 0 : $d / $max;
237
238        return new Hsl(round($h * 360), round($s * 100), round($l * 100), $this->a);
239    }
240
241    /**
242     * Convert to hex
243     *
244     * @return Hex
245     */
246    public function toHex()
247    {
248        $hex = dechex($this->r) . dechex($this->g) . dechex($this->b);
249        return new Hex($hex);
250    }
251
252    /**
253     * Convert to array
254     *
255     * @param  boolean $assoc
256     * @return array
257     */
258    public function toArray($assoc = true)
259    {
260        $rgb = [];
261
262        if ($assoc) {
263            $rgb['r'] = $this->r;
264            $rgb['g'] = $this->g;
265            $rgb['b'] = $this->b;
266            if (null !== $this->a) {
267                $rgb['a'] = $this->a;
268            }
269        } else {
270            $rgb[] = $this->r;
271            $rgb[] = $this->g;
272            $rgb[] = $this->b;
273            if (null !== $this->a) {
274                $rgb[] = $this->a;
275            }
276        }
277
278        return $rgb;
279    }
280
281    /**
282     * Convert to CSS-formatted string
283     *
284     * @return string
285     */
286    public function render()
287    {
288        return ((null !== $this->a) ? 'rgba(' : 'rgb(') . implode(', ', $this->toArray()) . ')';
289    }
290
291    /**
292     * Return CSS-formatted string
293     *
294     * @return string
295     */
296    public function __toString()
297    {
298        return $this->render();
299    }
300
301    /**
302     * Magic method to set the color value
303     *
304     * @param  string $name
305     * @param  mixed $value
306     * @return void
307     */
308    public function __set($name, $value)
309    {
310        $this->offsetSet($name, $value);
311    }
312
313    /**
314     * Magic method to return the color value
315     *
316     * @param  string $name
317     * @return mixed
318     */
319    public function __get($name)
320    {
321        return $this->offsetGet($name);
322    }
323
324    /**
325     * Magic method to return whether the color value exists
326     *
327     * @param  string $name
328     * @return boolean
329     */
330    public function __isset($name)
331    {
332        return $this->offsetExists($name);
333    }
334
335    /**
336     * Magic method to unset color value
337     *
338     * @param  string $name
339     * @throws Exception
340     * @return void
341     */
342    public function __unset($name)
343    {
344        throw new Exception('You cannot unset the properties of this color object.');
345    }
346
347    /**
348     * ArrayAccess offsetExists
349     *
350     * @param  mixed $offset
351     * @return boolean
352     */
353    public function offsetExists($offset): bool
354    {
355        return (($offset == 'r') || ($offset == 'g') || ($offset == 'b') || ($offset == 'a'));
356    }
357
358    /**
359     * ArrayAccess offsetGet
360     *
361     * @param  mixed $offset
362     * @throws Exception
363     * @return mixed
364     */
365    #[ReturnTypeWillChange]
366    public function offsetGet($offset)
367    {
368        switch ($offset) {
369            case 'r':
370                return $this->getR();
371                break;
372            case 'g':
373                return $this->getG();
374                break;
375            case 'b':
376                return $this->getB();
377                break;
378            case 'a':
379                return $this->getA();
380                break;
381            default:
382                throw new Exception("Error: You can only use 'r', 'g', 'b' or 'a'.");
383        }
384    }
385
386    /**
387     * ArrayAccess offsetSet
388     *
389     * @param  mixed $offset
390     * @param  mixed $value
391     * @throws Exception
392     * @return void
393     */
394    #[ReturnTypeWillChange]
395    public function offsetSet($offset, $value)
396    {
397        switch ($offset) {
398            case 'r':
399                $this->setR($value);
400                break;
401            case 'g':
402                $this->setG($value);
403                break;
404            case 'b':
405                $this->setB($value);
406                break;
407            case 'a':
408                $this->setA($value);
409                break;
410            default:
411                throw new Exception("Error: You can only use 'r', 'g', 'b' or 'a'.");
412        }
413    }
414
415    /**
416     * ArrayAccess offsetUnset
417     *
418     * @param  mixed $offset
419     * @throws Exception
420     * @return void
421     */
422    #[ReturnTypeWillChange]
423    public function offsetUnset($offset)
424    {
425        throw new Exception('You cannot unset the properties of this color object.');
426    }
427
428}