Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
97 / 97
100.00% covered (success)
100.00%
23 / 23
CRAP
100.00% covered (success)
100.00%
1 / 1
Hex
100.00% covered (success)
100.00%
97 / 97
100.00% covered (success)
100.00%
23 / 23
50
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setHex
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
6
 setR
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 setG
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 setB
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getHex
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 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
 isValid
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 toRgb
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
4
 toHsl
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toArray
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 render
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __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 Hex 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 Hex implements \ArrayAccess, ColorInterface
29{
30
31    /**
32     * R value
33     * @var string
34     */
35    protected $r = null;
36
37    /**
38     * G value
39     * @var string
40     */
41    protected $g = null;
42
43    /**
44     * B value
45     * @var string
46     */
47    protected $b = null;
48
49    /**
50     * Hex value
51     * @var string
52     */
53    protected $hex = null;
54
55    /**
56     * Constructor
57     *
58     * Instantiate the CSS hex color object
59     *
60     * @param string $hex
61     */
62    public function __construct($hex)
63    {
64        $this->setHex($hex);
65    }
66
67    /**
68     * Set hex value
69     *
70     * @param  string $hex
71     * @throws \OutOfRangeException
72     * @return self
73     */
74    public function setHex($hex)
75    {
76        $hex = strtolower($hex);
77        $hex = (substr($hex, 0, 1) == '#') ? substr($hex, 1) : $hex;
78
79        if ((strlen($hex) != 3) && (strlen($hex) != 6)) {
80            throw new \OutOfRangeException('Error: The hex string was not the correct length.');
81        }
82        if (!$this->isValid($hex)) {
83            throw new \OutOfRangeException('Error: The hex string was out of range.');
84        }
85
86        if (strlen($hex) == 3) {
87            $this->setR(substr($hex, 0, 1));
88            $this->setG(substr($hex, 1, 1));
89            $this->setB(substr($hex, 2, 1));
90        } else {
91            $this->setR(substr($hex, 0, 2));
92            $this->setG(substr($hex, 2, 2));
93            $this->setB(substr($hex, 4, 2));
94        }
95
96        $this->hex = $hex;
97
98        return $this;
99    }
100
101    /**
102     * Set R value
103     *
104     * @param  string $r
105     * @throws \OutOfRangeException
106     * @return self
107     */
108    public function setR($r)
109    {
110        if (!$this->isValid($r)) {
111            throw new \OutOfRangeException('Error: The $r hex string was out of range.');
112        }
113        $this->r = $r;
114        return $this;
115    }
116
117    /**
118     * Set G value
119     *
120     * @param  string $g
121     * @throws \OutOfRangeException
122     * @return self
123     */
124    public function setG($g)
125    {
126        if (!$this->isValid($g)) {
127            throw new \OutOfRangeException('Error: The $g hex string was out of range.');
128        }
129        $this->g = $g;
130        return $this;
131    }
132
133    /**
134     * Set B value
135     *
136     * @param  string $b
137     * @throws \OutOfRangeException
138     * @return self
139     */
140    public function setB($b)
141    {
142        if (!$this->isValid($b)) {
143            throw new \OutOfRangeException('Error: The $b hex string was out of range.');
144        }
145        $this->b = $b;
146        return $this;
147    }
148
149    /**
150     * Get hex value
151     *
152     * @return string
153     */
154    public function getHex()
155    {
156        return $this->hex;
157    }
158
159    /**
160     * Get R value
161     *
162     * @return string
163     */
164    public function getR()
165    {
166        return $this->r;
167    }
168
169    /**
170     * Get G value
171     *
172     * @return string
173     */
174    public function getG()
175    {
176        return $this->g;
177    }
178
179    /**
180     * Get B value
181     *
182     * @return string
183     */
184    public function getB()
185    {
186        return $this->b;
187    }
188
189    /**
190     * Method to determine if the hex value is valid
191     *
192     * @param  string $hex
193     * @return boolean
194     */
195    public function isValid($hex)
196    {
197        $valid     = true;
198        $hexValues = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
199        $hexAry    = str_split($hex);
200
201        foreach ($hexAry as $h) {
202            if (!in_array($h, $hexValues)) {
203                $valid = false;
204                break;
205            }
206        }
207
208        return $valid;
209    }
210
211    /**
212     * Convert to RGB
213     *
214     * @return Rgb
215     */
216    public function toRgb()
217    {
218        $hexR  = $this->r;
219        $hexG  = $this->g;
220        $hexB  = $this->b;
221
222        if (strlen($hexR) == 1) {
223            $hexR .= $hexR;
224        }
225        if (strlen($hexG) == 1) {
226            $hexG .= $hexG;
227        }
228        if (strlen($hexB) == 1) {
229            $hexB .= $hexB;
230        }
231
232        $r = base_convert($hexR, 16, 10);
233        $g = base_convert($hexG, 16, 10);
234        $b = base_convert($hexB, 16, 10);
235
236        return new Rgb($r, $g, $b);
237    }
238
239    /**
240     * Convert to HSL
241     *
242     * @return Hsl
243     */
244    public function toHsl()
245    {
246        return $this->toRgb()->toHsl();
247    }
248
249    /**
250     * Convert to array
251     *
252     * @param  boolean $assoc
253     * @return array
254     */
255    public function toArray($assoc = true)
256    {
257        $hex = [];
258
259        if ($assoc) {
260            $hex['hex'] = '#' . $this->hex;
261            $hex['r']   = $this->r;
262            $hex['g']   = $this->g;
263            $hex['b']   = $this->b;
264        } else {
265            $hex[] = '#' . $this->hex;
266            $hex[] = $this->r;
267            $hex[] = $this->g;
268            $hex[] = $this->b;
269        }
270
271        return $hex;
272    }
273
274    /**
275     * Convert to CSS-formatted string
276     *
277     * @return string
278     */
279    public function render()
280    {
281        return '#' . $this->hex;
282    }
283
284    /**
285     * Return CSS-formatted string
286     *
287     * @return string
288     */
289    public function __toString()
290    {
291        return $this->render();
292    }
293
294    /**
295     * Magic method to set the color value
296     *
297     * @param  string $name
298     * @param  mixed $value
299     * @return void
300     */
301    public function __set($name, $value)
302    {
303        $this->offsetSet($name, $value);
304    }
305
306    /**
307     * Magic method to return the color value
308     *
309     * @param  string $name
310     * @return mixed
311     */
312    public function __get($name)
313    {
314        return $this->offsetGet($name);
315    }
316
317    /**
318     * Magic method to return whether the color value exists
319     *
320     * @param  string $name
321     * @return boolean
322     */
323    public function __isset($name)
324    {
325        return $this->offsetExists($name);
326    }
327
328    /**
329     * Magic method to unset color value
330     *
331     * @param  string $name
332     * @throws Exception
333     * @return void
334     */
335    public function __unset($name)
336    {
337        throw new Exception('You cannot unset the properties of this color object.');
338    }
339
340    /**
341     * ArrayAccess offsetExists
342     *
343     * @param  mixed $offset
344     * @return boolean
345     */
346    public function offsetExists($offset): bool
347    {
348        return (($offset == 'r') || ($offset == 'g') || ($offset == 'b') || ($offset == 'hex'));
349    }
350
351    /**
352     * ArrayAccess offsetGet
353     *
354     * @param  mixed $offset
355     * @throws Exception
356     * @return mixed
357     */
358    #[ReturnTypeWillChange]
359    public function offsetGet($offset)
360    {
361        switch ($offset) {
362            case 'r':
363                return $this->getR();
364                break;
365            case 'g':
366                return $this->getG();
367                break;
368            case 'b':
369                return $this->getB();
370                break;
371            case 'hex':
372                return $this->getHex();
373                break;
374            default:
375                throw new Exception("Error: You can only use 'r', 'g', 'b' or 'hex'.");
376        }
377    }
378
379    /**
380     * ArrayAccess offsetSet
381     *
382     * @param  mixed $offset
383     * @param  mixed $value
384     * @throws Exception
385     * @return void
386     */
387    #[ReturnTypeWillChange]
388    public function offsetSet($offset, $value)
389    {
390        switch ($offset) {
391            case 'r':
392                $this->setR($value);
393                break;
394            case 'g':
395                $this->setG($value);
396                break;
397            case 'b':
398                $this->setB($value);
399                break;
400            case 'hex':
401                $this->setHex($value);
402                break;
403            default:
404                throw new Exception("Error: You can only use 'r', 'g', 'b' or 'hex'.");
405        }
406    }
407
408    /**
409     * ArrayAccess offsetUnset
410     *
411     * @param  mixed $offset
412     * @throws Exception
413     * @return void
414     */
415    #[ReturnTypeWillChange]
416    public function offsetUnset($offset)
417    {
418        throw new Exception('You cannot unset the properties of this color object.');
419    }
420
421}