Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
61 / 61
100.00% covered (success)
100.00%
14 / 14
CRAP
100.00% covered (success)
100.00%
1 / 1
Media
100.00% covered (success)
100.00%
61 / 61
100.00% covered (success)
100.00%
14 / 14
35
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 setType
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setCondition
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getCondition
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setTabSize
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getTabSize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setFeatures
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getFeatures
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setFeature
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getFeature
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasFeature
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 render
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
1 / 1
18
 __toString
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
17/**
18 * Pop CSS media class
19 *
20 * @category   Pop
21 * @package    Pop\Css
22 * @author     Nick Sagona, III <nick@popphp.org>
23 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
24 * @license    https://www.popphp.org/license     New BSD License
25 * @version    3.0.0
26 */
27class Media extends AbstractCss
28{
29
30    /**
31     * Media type
32     * @var ?string
33     */
34    protected ?string $type = null;
35
36    /**
37     * Media condition
38     * @var ?string
39     */
40    protected ?string $condition = null;
41
42    /**
43     * Media features
44     * @var array
45     */
46    protected array $features = [];
47
48    /**
49     * Tab size
50     * @var int
51     */
52    protected int $tabSize = 4;
53
54    /**
55     * Constructor
56     *
57     * Instantiate the CSS media object
58     *
59     * @param ?string $type
60     * @param ?array  $features
61     * @param ?string $condition
62     * @param int     $tabSize
63     */
64    public function __construct(?string $type = null, ?array $features = null, ?string $condition = null, int $tabSize = 4)
65    {
66        if ($type !== null) {
67            $this->setType($type);
68        }
69        if ($features !== null) {
70            $this->setFeatures($features);
71        }
72        if ($condition !== null) {
73            $this->setCondition($condition);
74        }
75        $this->setTabSize($tabSize);
76    }
77
78    /**
79     * Set type
80     *
81     * @param  string $type
82     * @return Media
83     */
84    public function setType(string $type): Media
85    {
86        $this->type = $type;
87        return $this;
88    }
89
90    /**
91     * Get type
92     *
93     * @return string|null
94     */
95    public function getType(): string|null
96    {
97        return $this->type;
98    }
99
100    /**
101     * Set condition
102     *
103     * @param  ?string $condition
104     * @return Media
105     */
106    public function setCondition(?string $condition = null): Media
107    {
108        $this->condition = $condition;
109        return $this;
110    }
111
112    /**
113     * Get condition
114     *
115     * @return string|null
116     */
117    public function getCondition(): string|null
118    {
119        return $this->condition;
120    }
121
122    /**
123     * Set tab size
124     *
125     * @param  int $tabSize
126     * @return Media
127     */
128    public function setTabSize(int $tabSize): Media
129    {
130        $this->tabSize = $tabSize;
131        return $this;
132    }
133
134    /**
135     * Get tab size
136     *
137     * @return int
138     */
139    public function getTabSize(): int
140    {
141        return $this->tabSize;
142    }
143
144    /**
145     * Set features
146     *
147     * @param  array $features
148     * @return Media
149     */
150    public function setFeatures(array $features): Media
151    {
152        foreach ($features as $feature => $value) {
153            $this->setFeature($feature, $value);
154        }
155        return $this;
156    }
157
158    /**
159     * Get features
160     *
161     * @return array
162     */
163    public function getFeatures(): array
164    {
165        return $this->features;
166    }
167
168    /**
169     * Set feature
170     *
171     * @param  string $feature
172     * @param  string $value
173     * @return Media
174     */
175    public function setFeature(string $feature, string $value): Media
176    {
177        $this->features[$feature] = $value;
178        return $this;
179    }
180
181    /**
182     * Get feature
183     *
184     * @param  string $feature
185     * @return string|null
186     */
187    public function getFeature(string $feature): string|null
188    {
189        return $this->features[$feature] ?? null;
190    }
191
192    /**
193     * Does media query have feature
194     *
195     * @param  string $feature
196     * @return bool
197     */
198    public function hasFeature(string $feature): bool
199    {
200        return isset($this->features[$feature]);
201    }
202
203    /**
204     * Method to render the selector CSS
205     *
206     * @return string
207     */
208    public function render(): string
209    {
210        $css = '';
211
212        if (!$this->minify) {
213            foreach ($this->comments as $comment) {
214                $css .= $comment . PHP_EOL;
215            }
216        }
217
218        $css .= ($this->minify) ? ' @media': '@media';
219
220        if ($this->condition !== null) {
221            $css .= ' ' . $this->condition;
222        }
223        if ($this->type !== null) {
224            $css .= ' ' . $this->type;
225        }
226
227        if ((!empty($this->condition) || !empty($this->type)) && (count($this->features) > 0)) {
228            $css .= ' and';
229        }
230
231        if (count($this->features) > 0) {
232            $features = [];
233            foreach ($this->features as $feature => $value) {
234                $features[] = '(' . $feature . ': ' . $value .')';
235            }
236            $css .= ' ' . implode(' and ', $features);
237        }
238
239        $css .= ' {';
240        if (!$this->minify) {
241            $css .= PHP_EOL;
242        }
243
244        foreach ($this->selectors as $selector) {
245            $selector->minify($this->minify);
246            $selectorCss = (string)$selector;
247
248            if (!$this->minify) {
249                $selectorCssAry = explode(PHP_EOL, $selectorCss);
250                foreach ($selectorCssAry as $key => $value) {
251                    $selectorCssAry[$key] = str_repeat(' ', $this->tabSize) . $value;
252                }
253                $selectorCss = implode(PHP_EOL, $selectorCssAry);
254            }
255
256            $css .= $selectorCss;
257            if (!$this->minify) {
258                $css .= PHP_EOL;
259            }
260        }
261
262        // Clean up end new lines
263        if (str_ends_with($css, PHP_EOL . str_repeat(' ', $this->tabSize) . PHP_EOL)) {
264            $css = substr($css, 0, 0 - ($this->tabSize + 1));
265        }
266
267        $css .= '}';
268
269        if (!$this->minify) {
270            $css .= PHP_EOL;
271        }
272
273        return $css;
274    }
275
276    /**
277     * To string method
278     *
279     * @return string
280     */
281    public function __toString(): string
282    {
283        return $this->render();
284    }
285
286}