at path:ROOT / clients / vendor / punic / punic / src / Unit.php
run:R W Run
DIR
2026-04-08 19:42:30
R W Run
DIR
2026-04-08 19:53:13
R W Run
126.16 KB
2026-04-08 19:35:40
R W Run
4.19 KB
2026-04-08 19:35:40
R W Run
8.96 KB
2026-04-08 19:35:41
R W Run
24.16 KB
2026-04-08 19:35:40
R W Run
2 KB
2026-04-08 19:35:42
R W Run
3.93 KB
2026-04-08 19:35:41
R W Run
12.53 KB
2026-04-08 19:35:40
R W Run
17.07 KB
2026-04-08 19:35:39
R W Run
2.3 KB
2026-04-08 19:35:42
R W Run
6.93 KB
2026-04-08 19:35:39
R W Run
20.49 KB
2026-04-08 19:35:40
R W Run
13.16 KB
2026-04-08 19:35:39
R W Run
error_log
📄Unit.php
1<?php
2
3namespace Punic;
4
5/**
6 * Units helper stuff.
7 */
8class Unit
9{
10 /**
11 * Get the list of all the available units.
12 *
13 * @param string $locale The locale to use. If empty we'll use the default locale set in \Punic\Data
14 */
15 public static function getAvailableUnits($locale = '')
16 {
17 $data = Data::get('units', $locale);
18 $categories = array();
19 foreach ($data as $width => $units) {
20 if ($width[0] !== '_') {
21 foreach ($units as $category => $units) {
22 if ($category[0] !== '_') {
23 $unitIDs = array_keys($units);
24 if (isset($categories[$category])) {
25 $categories[$category] = array_unique(array_merge($categories[$category], $unitIDs));
26 } else {
27 $categories[$category] = array_keys($units);
28 }
29 }
30 }
31 }
32 }
33 ksort($categories);
34 foreach (array_keys($categories) as $category) {
35 sort($categories[$category]);
36 }
37
38 return $categories;
39 }
40
41 /**
42 * Get the localized name of a unit.
43 *
44 * @param string $unit The unit identifier (eg 'duration/millisecond' or 'millisecond')
45 * @param string $width The format name; it can be 'long' ('milliseconds'), 'short' (eg 'millisecs') or 'narrow' (eg 'msec')
46 * @param string $locale The locale to use. If empty we'll use the default locale set in \Punic\Data
47 *
48 * @throws Exception\ValueNotInList
49 *
50 * @return string
51 */
52 public static function getName($unit, $width = 'short', $locale = '')
53 {
54 $data = self::getDataForWidth($width, $locale);
55 $unitData = self::getDataForUnit($data, $unit);
56
57 return $unitData['_name'];
58 }
59
60 /**
61 * Get the "per" localized format string of a unit.
62 *
63 * @param string $unit The unit identifier (eg 'duration/minute' or 'minute')
64 * @param string $width The format name; it can be 'long' ('%1$s per minute'), 'short' (eg '%1$s/min') or 'narrow' (eg '%1$s/min')
65 * @param string $locale The locale to use. If empty we'll use the default locale set in \Punic\Data
66 *
67 * @throws Exception\ValueNotInList
68 *
69 * @return string
70 */
71 public static function getPerFormat($unit, $width = 'short', $locale = '')
72 {
73 $data = self::getDataForWidth($width, $locale);
74 $unitData = self::getDataForUnit($data, $unit);
75
76 if (isset($unitData['_per'])) {
77 return $unitData['_per'];
78 }
79 $pluralRule = Plural::getRuleOfType(1, Plural::RULETYPE_CARDINAL, $locale);
80 $name = trim(sprintf($unitData[$pluralRule], ''));
81
82 return sprintf($data['_compoundPattern'], '%1$s', $name);
83 }
84
85 /**
86 * Format a unit string.
87 *
88 * @param int|float|string $number The unit amount
89 * @param string $unit The unit identifier (eg 'duration/millisecond' or 'millisecond')
90 * @param string $width The format name; it can be 'long' (eg '3 milliseconds'), 'short' (eg '3 ms') or 'narrow' (eg '3ms'). You can also add a precision specifier ('long,2' or just '2')
91 * @param string $locale The locale to use. If empty we'll use the default locale set in \Punic\Data
92 *
93 * @throws Exception\ValueNotInList
94 *
95 * @return string
96 */
97 public static function format($number, $unit, $width = 'short', $locale = '')
98 {
99 $precision = null;
100 if (is_int($width)) {
101 $precision = $width;
102 $width = 'short';
103 } elseif (is_string($width) && preg_match('/^(?:(.*),)?([+\\-]?\\d+)$/', $width, $m)) {
104 $precision = (int) $m[2];
105 $width = (string) $m[1];
106 if ($width === '') {
107 $width = 'short';
108 }
109 }
110 $data = self::getDataForWidth($width, $locale);
111 $rules = self::getDataForUnit($data, $unit);
112 $pluralRule = Plural::getRuleOfType($number, Plural::RULETYPE_CARDINAL, $locale);
113 //@codeCoverageIgnoreStart
114 // These checks aren't necessary since $pluralRule should always be in $rules, but they don't hurt ;)
115 if (!isset($rules[$pluralRule])) {
116 if (isset($rules['other'])) {
117 $pluralRule = 'other';
118 } else {
119 $availableRules = array_keys($rules);
120 $pluralRule = $availableRules[0];
121 }
122 }
123 //@codeCoverageIgnoreEnd
124 return sprintf($rules[$pluralRule], Number::format($number, $precision, $locale));
125 }
126
127 /**
128 * Retrieve the measurement systems and their localized names.
129 *
130 * @param string $locale The locale to use. If empty we'll use the default locale set in \Punic\Data
131 *
132 * @return array The array keys are the measurement system codes (eg 'metric', 'US', 'UK'), the values are the localized measurement system names (eg 'Metric', 'US', 'UK' for English)
133 */
134 public static function getMeasurementSystems($locale = '')
135 {
136 return Data::get('measurementSystemNames', $locale);
137 }
138
139 /**
140 * Retrieve the measurement system for a specific territory.
141 *
142 * @param string $territoryCode The territory code (eg. 'US' for 'United States of America').
143 *
144 * @return string Return the measurement system code (eg: 'metric') for the specified territory. If $territoryCode is not valid we'll return an empty string.
145 */
146 public static function getMeasurementSystemFor($territoryCode)
147 {
148 $result = '';
149 if (is_string($territoryCode) && preg_match('/^[a-z0-9]{2,3}$/i', $territoryCode)) {
150 $territoryCode = strtoupper($territoryCode);
151 $data = Data::getGeneric('measurementData');
152 while ($territoryCode !== '') {
153 if (isset($data['measurementSystem'][$territoryCode])) {
154 $result = $data['measurementSystem'][$territoryCode];
155 break;
156 }
157 $territoryCode = Territory::getParentTerritoryCode($territoryCode);
158 }
159 }
160
161 return $result;
162 }
163
164 /**
165 * Returns the list of countries that use a specific measurement system.
166 *
167 * @param string $measurementSystem The measurement system identifier ('metric', 'US' or 'UK')
168 *
169 * @return array The list of country IDs that use the specified measurement system (if $measurementSystem is invalid you'll get an empty array)
170 */
171 public static function getCountriesWithMeasurementSystem($measurementSystem)
172 {
173 $result = array();
174 if (is_string($measurementSystem) && $measurementSystem !== '') {
175 $someGroup = false;
176 $data = Data::getGeneric('measurementData');
177 foreach ($data['measurementSystem'] as $territory => $ms) {
178 if (strcasecmp($measurementSystem, $ms) === 0) {
179 $children = Territory::getChildTerritoryCodes($territory, true);
180 if (empty($children)) {
181 $result[] = $territory;
182 } else {
183 $someGroup = true;
184 $result = array_merge($result, $children);
185 }
186 }
187 }
188 if ($someGroup) {
189 $otherCountries = array();
190 foreach ($data['measurementSystem'] as $territory => $ms) {
191 if (($territory !== '001') && (strcasecmp($measurementSystem, $ms) !== 0)) {
192 $children = Territory::getChildTerritoryCodes($territory, true);
193 if (empty($children)) {
194 $otherCountries[] = $territory;
195 } else {
196 $otherCountries = array_merge($otherCountries, $children);
197 }
198 }
199 }
200 $result = array_values(array_diff($result, $otherCountries));
201 }
202 }
203
204 return $result;
205 }
206
207 /**
208 * Retrieve the standard paper size for a specific territory.
209 *
210 * @param string $territoryCode The territory code (eg. 'US' for 'United States of America').
211 *
212 * @return string Return the standard paper size (eg: 'A4' or 'US-Letter') for the specified territory. If $territoryCode is not valid we'll return an empty string.
213 */
214 public static function getPaperSizeFor($territoryCode)
215 {
216 $result = '';
217 if (is_string($territoryCode) && preg_match('/^[a-z0-9]{2,3}$/i', $territoryCode)) {
218 $territoryCode = strtoupper($territoryCode);
219 $data = Data::getGeneric('measurementData');
220 while ($territoryCode !== '') {
221 if (isset($data['paperSize'][$territoryCode])) {
222 $result = $data['paperSize'][$territoryCode];
223 break;
224 }
225 $territoryCode = Territory::getParentTerritoryCode($territoryCode);
226 }
227 }
228
229 return $result;
230 }
231
232 /**
233 * Returns the list of countries that use a specific paper size by default.
234 *
235 * @param string $paperSize The paper size identifier ('A4' or 'US-Letter')
236 *
237 * @return array The list of country IDs that use the specified paper size (if $paperSize is invalid you'll get an empty array)
238 */
239 public static function getCountriesWithPaperSize($paperSize)
240 {
241 $result = array();
242 if (is_string($paperSize) && $paperSize !== '') {
243 $someGroup = false;
244 $data = Data::getGeneric('measurementData');
245 foreach ($data['paperSize'] as $territory => $ms) {
246 if (strcasecmp($paperSize, $ms) === 0) {
247 $children = Territory::getChildTerritoryCodes($territory, true);
248 if (empty($children)) {
249 $result[] = $territory;
250 } else {
251 $someGroup = true;
252 $result = array_merge($result, $children);
253 }
254 }
255 }
256 if ($someGroup) {
257 $otherCountries = array();
258 foreach ($data['paperSize'] as $territory => $ms) {
259 if (($territory !== '001') && (strcasecmp($paperSize, $ms) !== 0)) {
260 $children = Territory::getChildTerritoryCodes($territory, true);
261 if (empty($children)) {
262 $otherCountries[] = $territory;
263 } else {
264 $otherCountries = array_merge($otherCountries, $children);
265 }
266 }
267 }
268 $result = array_values(array_diff($result, $otherCountries));
269 }
270 }
271
272 return $result;
273 }
274
275 /**
276 * Get the width-specific unit data.
277 *
278 * @param string $width the data width
279 * @param string $locale The locale to use. If empty we'll use the default locale set in \Punic\Data
280 *
281 * @throws Exception\ValueNotInList
282 *
283 * @return array
284 */
285 private static function getDataForWidth($width, $locale = '')
286 {
287 $data = Data::get('units', $locale);
288 if ($width[0] === '_' || !isset($data[$width])) {
289 $widths = array();
290 foreach (array_keys($data) as $w) {
291 if (strpos($w, '_') !== 0) {
292 $widths[] = $w;
293 }
294 }
295 throw new Exception\ValueNotInList($width, $widths);
296 }
297
298 return $data[$width];
299 }
300
301 /**
302 * Get a unit-specific data.
303 *
304 * @param array $data the width-specific data
305 * @param string $unit The unit identifier (eg 'duration/millisecond' or 'millisecond')
306 *
307 * @throws Exception\ValueNotInList
308 *
309 * @return array
310 */
311 private static function getDataForUnit(array $data, $unit)
312 {
313 $chunks = explode('/', $unit, 2);
314 if (isset($chunks[1])) {
315 list($unitCategory, $unitID) = $chunks;
316 } else {
317 $unitCategory = null;
318 $unitID = null;
319 foreach (array_keys($data) as $c) {
320 if ($c[0] !== '_') {
321 if (isset($data[$c][$unit])) {
322 if ($unitCategory === null) {
323 $unitCategory = $c;
324 $unitID = $unit;
325 } else {
326 $unitCategory = null;
327 break;
328 }
329 }
330 }
331 }
332 }
333 if (
334 $unitCategory === null || $unitCategory[0] === '_'
335 || !isset($data[$unitCategory])
336 || $unitID === null || $unitID[0] === '_'
337 || !isset($data[$unitCategory][$unitID])
338 ) {
339 $units = array();
340 foreach ($data as $c => $us) {
341 if (strpos($c, '_') === false) {
342 foreach (array_keys($us) as $u) {
343 if (strpos($c, '_') === false) {
344 $units[] = "$c/$u";
345 }
346 }
347 }
348 }
349 throw new \Punic\Exception\ValueNotInList($unit, $units);
350 }
351
352 return $data[$unitCategory][$unitID];
353 }
354}
355