Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
13 / 13
CRAP
100.00% covered (success)
100.00%
1 / 1
AbstractCss
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
13 / 13
16
100.00% covered (success)
100.00%
1 / 1
 addSelector
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 addSelectors
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 hasSelector
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSelector
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 removeSelector
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 minify
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 isMinified
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getIterator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 count
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
1
 offsetGet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetSet
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 offsetUnset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Css;
16
17use ArrayIterator;
18
19/**
20 * Abstract CSS class
21 *
22 * @category   Pop
23 * @package    Pop\Css
24 * @author     Nick Sagona, III <nick@popphp.org>
25 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
26 * @license    https://www.popphp.org/license     New BSD License
27 * @version    3.0.0
28 */
29abstract class AbstractCss implements \ArrayAccess, \Countable, \IteratorAggregate
30{
31
32    /**
33     * Trait declaration
34     */
35    use CommentTrait;
36
37    /**
38     * Selectors
39     * @var array
40     */
41    protected array $selectors = [];
42
43    /**
44     * Minify flag
45     * @var bool
46     */
47    protected bool $minify = false;
48
49    /**
50     * Add CSS selector
51     *
52     * Merges into an existing same-name selector's properties (last value
53     * for a given property wins) rather than replacing it outright, matching
54     * real CSS cascade semantics for repeated rules on the same selector.
55     *
56     * @param  Selector $selector
57     * @return AbstractCss
58     */
59    public function addSelector(Selector $selector): AbstractCss
60    {
61        $name = $selector->getName();
62
63        if (isset($this->selectors[$name])) {
64            $this->selectors[$name]->setProperties($selector->getProperties());
65        } else {
66            $this->selectors[$name] = $selector;
67        }
68
69        return $this;
70    }
71
72    /**
73     * Add CSS selectors
74     *
75     * @param  array $selectors
76     * @return AbstractCss
77     */
78    public function addSelectors(array $selectors): AbstractCss
79    {
80        foreach ($selectors as $selector) {
81            $this->addSelector($selector);
82        }
83        return $this;
84    }
85
86    /**
87     * Check if the object has CSS selector
88     *
89     * @param  string $selector
90     * @return bool
91     */
92    public function hasSelector(string $selector): bool
93    {
94        return (isset($this->selectors[$selector]));
95    }
96
97    /**
98     * Get CSS selector
99     *
100     * @param  string $selector
101     * @return Selector|null
102     */
103    public function getSelector(string $selector): Selector|null
104    {
105        return $this->selectors[$selector] ?? null;
106    }
107
108    /**
109     * Remove CSS selector
110     *
111     * @param  string $selector
112     * @return AbstractCss
113     */
114    public function removeSelector(string $selector): AbstractCss
115    {
116        unset($this->selectors[$selector]);
117        return $this;
118    }
119
120    /**
121     * Set minify flag
122     *
123     * @param  bool $minify
124     * @return AbstractCss
125     */
126    public function minify(bool $minify = true): AbstractCss
127    {
128        $this->minify = $minify;
129        return $this;
130    }
131
132    /**
133     * Check if minify flag is set
134     *
135     * @return bool
136     */
137    public function isMinified(): bool
138    {
139        return $this->minify;
140    }
141
142   /**
143     * Method to iterate over the properties
144     *
145     * @return ArrayIterator
146     */
147    public function getIterator(): ArrayIterator
148    {
149        return new ArrayIterator($this->selectors);
150    }
151
152    /**
153     * Method to get the count of properties
154     *
155     * @return int
156     */
157    public function count(): int
158    {
159        return count($this->selectors);
160    }
161
162    /**
163     * ArrayAccess offsetExists
164     *
165     * @param  mixed $offset
166     * @return bool
167     */
168    public function offsetExists(mixed $offset): bool
169    {
170        return $this->hasSelector($offset);
171    }
172
173    /**
174     * ArrayAccess offsetGet
175     *
176     * @param  mixed $offset
177     * @return mixed
178     */
179    public function offsetGet(mixed $offset): mixed
180    {
181        return $this->getSelector($offset);
182    }
183
184    /**
185     * ArrayAccess offsetSet
186     *
187     * @param  mixed $offset
188     * @param  mixed $value
189     * @throws Exception
190     * @return void
191     */
192    public function offsetSet(mixed $offset, mixed $value): void
193    {
194        if (!($value instanceof Selector)) {
195            throw new Exception('Error: The value passed must be an instance of Pop\Css\Selector');
196        }
197        $value->setName($offset);
198        $this->addSelector($value);
199    }
200
201    /**
202     * ArrayAccess offsetUnset
203     *
204     * @param  mixed $offset
205     * @return void
206     */
207    public function offsetUnset(mixed $offset): void
208    {
209        $this->removeSelector($offset);
210    }
211
212}