PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 10.10.2
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v10.10.2
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
acymailing / back / Libraries / Sabberworm / CSS / src / Value / Size.php

Size.php in AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress 10.10.2, at back/Libraries/Sabberworm/CSS/src/Value/Size.php

211 lines 5.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace AcyMailing\Libraries\Sabberworm\CSS\Value;
6
7 use AcyMailing\Libraries\Sabberworm\CSS\OutputFormat;
8 use AcyMailing\Libraries\Sabberworm\CSS\Parsing\ParserState;
9 use AcyMailing\Libraries\Sabberworm\CSS\Parsing\UnexpectedEOFException;
10 use AcyMailing\Libraries\Sabberworm\CSS\Parsing\UnexpectedTokenException;
11
12 /**
13 * A `Size` consists of a numeric `size` value and a unit.
14 */
15 class Size extends PrimitiveValue
16 {
17 /**
18 * vh/vw/vm(ax)/vmin/rem are absolute insofar as they don’t scale to the immediate parent (only the viewport)
19 *
20 * @var list<non-empty-string>
21 */
22 private const ABSOLUTE_SIZE_UNITS = [
23 'px',
24 'pt',
25 'pc',
26 'cm',
27 'mm',
28 'mozmm',
29 'in',
30 'vh',
31 'dvh',
32 'svh',
33 'lvh',
34 'vw',
35 'vmin',
36 'vmax',
37 'rem',
38 ];
39
40 /**
41 * @var list<non-empty-string>
42 */
43 private const RELATIVE_SIZE_UNITS = ['%', 'em', 'ex', 'ch', 'fr'];
44
45 /**
46 * @var list<non-empty-string>
47 */
48 private const NON_SIZE_UNITS = ['deg', 'grad', 'rad', 's', 'ms', 'turn', 'Hz', 'kHz'];
49
50 /**
51 * @var array<int<1, max>, array<lowercase-string, non-empty-string>>|null
52 */
53 private static $SIZE_UNITS = null;
54
55 /**
56 * @var float
57 */
58 private $size;
59
60 /**
61 * @var string|null
62 */
63 private $unit;
64
65 /**
66 * @var bool
67 */
68 private $isColorComponent;
69
70 /**
71 * @param float|int|string $size
72 * @param int<1, max>|null $lineNumber
73 */
74 public function __construct($size, ?string $unit = null, bool $isColorComponent = false, ?int $lineNumber = null)
75 {
76 parent::__construct($lineNumber);
77 $this->size = (float) $size;
78 $this->unit = $unit;
79 $this->isColorComponent = $isColorComponent;
80 }
81
82 /**
83 * @throws UnexpectedEOFException
84 * @throws UnexpectedTokenException
85 *
86 * @internal since V8.8.0
87 */
88 public static function parse(ParserState $parserState, bool $isColorComponent = false): Size
89 {
90 $size = '';
91 if ($parserState->comes('-')) {
92 $size .= $parserState->consume('-');
93 }
94 while (\is_numeric($parserState->peek()) || $parserState->comes('.') || $parserState->comes('e', true)) {
95 if ($parserState->comes('.')) {
96 $size .= $parserState->consume('.');
97 } elseif ($parserState->comes('e', true)) {
98 $lookahead = $parserState->peek(1, 1);
99 if (\is_numeric($lookahead) || $lookahead === '+' || $lookahead === '-') {
100 $size .= $parserState->consume(2);
101 } else {
102 break; // Reached the unit part of the number like "em" or "ex"
103 }
104 } else {
105 $size .= $parserState->consume(1);
106 }
107 }
108
109 $unit = null;
110 $sizeUnits = self::getSizeUnits();
111 foreach ($sizeUnits as $length => &$values) {
112 $key = \strtolower($parserState->peek($length));
113 if (\array_key_exists($key, $values)) {
114 if (($unit = $values[$key]) !== null) {
115 $parserState->consume($length);
116 break;
117 }
118 }
119 }
120 return new Size((float) $size, $unit, $isColorComponent, $parserState->currentLine());
121 }
122
123 /**
124 * @return array<int<1, max>, array<lowercase-string, non-empty-string>>
125 */
126 private static function getSizeUnits(): array
127 {
128 if (!\is_array(self::$SIZE_UNITS)) {
129 self::$SIZE_UNITS = [];
130 $sizeUnits = \array_merge(self::ABSOLUTE_SIZE_UNITS, self::RELATIVE_SIZE_UNITS, self::NON_SIZE_UNITS);
131 foreach ($sizeUnits as $sizeUnit) {
132 $tokenLength = \strlen($sizeUnit);
133 if (!isset(self::$SIZE_UNITS[$tokenLength])) {
134 self::$SIZE_UNITS[$tokenLength] = [];
135 }
136 self::$SIZE_UNITS[$tokenLength][\strtolower($sizeUnit)] = $sizeUnit;
137 }
138
139 \krsort(self::$SIZE_UNITS, SORT_NUMERIC);
140 }
141
142 return self::$SIZE_UNITS;
143 }
144
145 public function setUnit(string $unit): void
146 {
147 $this->unit = $unit;
148 }
149
150 public function getUnit(): ?string
151 {
152 return $this->unit;
153 }
154
155 /**
156 * @param float|int|string $size
157 */
158 public function setSize($size): void
159 {
160 $this->size = (float) $size;
161 }
162
163 public function getSize(): float
164 {
165 return $this->size;
166 }
167
168 public function isColorComponent(): bool
169 {
170 return $this->isColorComponent;
171 }
172
173 /**
174 * Returns whether the number stored in this Size really represents a size (as in a length of something on screen).
175 *
176 * Returns `false` if the unit is an angle, a duration, a frequency, or the number is a component in a `Color`
177 * object.
178 */
179 public function isSize(): bool
180 {
181 if (\in_array($this->unit, self::NON_SIZE_UNITS, true)) {
182 return false;
183 }
184 return !$this->isColorComponent();
185 }
186
187 public function isRelative(): bool
188 {
189 if (\in_array($this->unit, self::RELATIVE_SIZE_UNITS, true)) {
190 return true;
191 }
192 if ($this->unit === null && $this->size !== 0.0) {
193 return true;
194 }
195 return false;
196 }
197
198 /**
199 * @return non-empty-string
200 */
201 public function render(OutputFormat $outputFormat): string
202 {
203 $locale = \localeconv();
204 $decimalPoint = \preg_quote($locale['decimal_point'], '/');
205 $size = \preg_match('/[\\d\\.]+e[+-]?\\d+/i', (string) $this->size)
206 ? \preg_replace("/$decimalPoint?0+$/", '', \sprintf('%f', $this->size)) : (string) $this->size;
207
208 return \preg_replace(["/$decimalPoint/", '/^(-?)0\\./'], ['.', '$1.'], $size) . ($this->unit ?? '');
209 }
210 }
211