PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 3.0.1
Defender Security – Malware Scanner, Login Security & Firewall v3.0.1
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / vendor / gettext / languages / src / FormulaConverter.php

FormulaConverter.php in Defender Security – Malware Scanner, Login Security & Firewall 3.0.1, at vendor/gettext/languages/src/FormulaConverter.php

173 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Gettext\Languages;
4
5 use Exception;
6
7 /**
8 * A helper class to convert a CLDR formula to a gettext formula.
9 */
10 class FormulaConverter
11 {
12 /**
13 * Converts a formula from the CLDR representation to the gettext representation.
14 *
15 * @param string $cldrFormula the CLDR formula to convert
16 *
17 * @throws \Exception
18 *
19 * @return bool|string returns true if the gettext will always evaluate to true, false if gettext will always evaluate to false, return the gettext formula otherwise
20 */
21 public static function convertFormula($cldrFormula)
22 {
23 if (strpbrk($cldrFormula, '()') !== false) {
24 throw new Exception("Unable to convert the formula '{$cldrFormula}': parenthesis handling not implemented");
25 }
26 $orSeparatedChunks = array();
27 foreach (explode(' or ', $cldrFormula) as $cldrFormulaChunk) {
28 $gettextFormulaChunk = null;
29 $andSeparatedChunks = array();
30 foreach (explode(' and ', $cldrFormulaChunk) as $cldrAtom) {
31 $gettextAtom = self::convertAtom($cldrAtom);
32 if ($gettextAtom === false) {
33 // One atom joined by 'and' always evaluates to false => the whole 'and' group is always false
34 $gettextFormulaChunk = false;
35 break;
36 }
37 if ($gettextAtom !== true) {
38 $andSeparatedChunks[] = $gettextAtom;
39 }
40 }
41 if (!isset($gettextFormulaChunk)) {
42 if (empty($andSeparatedChunks)) {
43 // All the atoms joined by 'and' always evaluate to true => the whole 'and' group is always true
44 $gettextFormulaChunk = true;
45 } else {
46 $gettextFormulaChunk = implode(' && ', $andSeparatedChunks);
47 // Special cases simplification
48 switch ($gettextFormulaChunk) {
49 case 'n >= 0 && n <= 2 && n != 2':
50 $gettextFormulaChunk = 'n == 0 || n == 1';
51 break;
52 }
53 }
54 }
55 if ($gettextFormulaChunk === true) {
56 // One part of the formula joined with the others by 'or' always evaluates to true => the whole formula always evaluates to true
57 return true;
58 }
59 if ($gettextFormulaChunk !== false) {
60 $orSeparatedChunks[] = $gettextFormulaChunk;
61 }
62 }
63 if (empty($orSeparatedChunks)) {
64 // All the parts joined by 'or' always evaluate to false => the whole formula always evaluates to false
65 return false;
66 }
67
68 return implode(' || ', $orSeparatedChunks);
69 }
70
71 /**
72 * Converts an atomic part of the CLDR formula to its gettext representation.
73 *
74 * @param string $cldrAtom the CLDR formula atom to convert
75 *
76 * @throws \Exception
77 *
78 * @return bool|string returns true if the gettext will always evaluate to true, false if gettext will always evaluate to false, return the gettext formula otherwise
79 */
80 private static function convertAtom($cldrAtom)
81 {
82 $m = null;
83 $gettextAtom = $cldrAtom;
84 $gettextAtom = str_replace(' = ', ' == ', $gettextAtom);
85 $gettextAtom = str_replace('i', 'n', $gettextAtom);
86 if (preg_match('/^n( % \d+)? (!=|==) \d+$/', $gettextAtom)) {
87 return $gettextAtom;
88 }
89 if (preg_match('/^n( % \d+)? (!=|==) \d+(,\d+|\.\.\d+)+$/', $gettextAtom)) {
90 return self::expandAtom($gettextAtom);
91 }
92 if (preg_match('/^(?:v|w)(?: % 10+)? == (\d+)(?:\.\.\d+)?$/', $gettextAtom, $m)) { // For gettext: v == 0, w == 0
93 return (int) $m[1] === 0 ? true : false;
94 }
95 if (preg_match('/^(?:v|w)(?: % 10+)? != (\d+)(?:\.\.\d+)?$/', $gettextAtom, $m)) { // For gettext: v == 0, w == 0
96 return (int) $m[1] === 0 ? false : true;
97 }
98 if (preg_match('/^(?:f|t|c|e)(?: % 10+)? == (\d+)(?:\.\.\d+)?$/', $gettextAtom, $m)) { // f == empty, t == empty, c == empty, e == empty
99 return (int) $m[1] === 0 ? true : false;
100 }
101 if (preg_match('/^(?:f|t|c|e)(?: % 10+)? != (\d+)(?:\.\.\d+)?$/', $gettextAtom, $m)) { // f == empty, t == empty, c == empty, e == empty
102 return (int) $m[1] === 0 ? false : true;
103 }
104 throw new Exception("Unable to convert the formula chunk '{$cldrAtom}' from CLDR to gettext");
105 }
106
107 /**
108 * Expands an atom containing a range (for instance: 'n == 1,3..5').
109 *
110 * @param string $atom
111 *
112 * @throws \Exception
113 *
114 * @return string
115 */
116 private static function expandAtom($atom)
117 {
118 $m = null;
119 if (preg_match('/^(n(?: % \d+)?) (==|!=) (\d+(?:\.\.\d+|,\d+)+)$/', $atom, $m)) {
120 $what = $m[1];
121 $op = $m[2];
122 $chunks = array();
123 foreach (explode(',', $m[3]) as $range) {
124 $chunk = null;
125 if ((!isset($chunk)) && preg_match('/^\d+$/', $range)) {
126 $chunk = "{$what} {$op} {$range}";
127 }
128 if ((!isset($chunk)) && preg_match('/^(\d+)\.\.(\d+)$/', $range, $m)) {
129 $from = (int) $m[1];
130 $to = (int) $m[2];
131 if (($to - $from) === 1) {
132 switch ($op) {
133 case '==':
134 $chunk = "({$what} == {$from} || {$what} == {$to})";
135 break;
136 case '!=':
137 $chunk = "{$what} != {$from} && {$what} == {$to}";
138 break;
139 }
140 } else {
141 switch ($op) {
142 case '==':
143 $chunk = "{$what} >= {$from} && {$what} <= {$to}";
144 break;
145 case '!=':
146 if ($what === 'n' && $from <= 0) {
147 $chunk = "{$what} > {$to}";
148 } else {
149 $chunk = "({$what} < {$from} || {$what} > {$to})";
150 }
151 break;
152 }
153 }
154 }
155 if (!isset($chunk)) {
156 throw new Exception("Unhandled range '{$range}' in '{$atom}'");
157 }
158 $chunks[] = $chunk;
159 }
160 if (count($chunks) === 1) {
161 return $chunks[0];
162 }
163 switch ($op) {
164 case '==':
165 return '(' . implode(' || ', $chunks) . ')'; break;
166 case '!=':
167 return implode(' && ', $chunks);
168 }
169 }
170 throw new Exception("Unable to expand '{$atom}'");
171 }
172 }
173