99
1010class Formatter
1111{
12+ /**
13+ * Matches any @ symbol that isn't enclosed in quotes.
14+ */
1215 private const SYMBOL_AT = '/@(?=(?:[^"]*"[^"]*")*[^"]*\Z)/miu ' ;
16+
17+ /**
18+ * Matches any ; symbol that isn't enclosed in quotes, for a "section" split.
19+ */
1320 private const SECTION_SPLIT = '/;(?=(?:[^"]*"[^"]*")*[^"]*\Z)/miu ' ;
1421
1522 /**
1623 * @param mixed $value
17- * @param mixed $val
18- * @param mixed $dfval
24+ * @param mixed $comparisonValue
25+ * @param mixed $defaultComparisonValue
1926 */
20- private static function splitFormatCompare ($ value , ?string $ cond , $ val , string $ dfcond , $ dfval ): bool
21- {
22- if (!$ cond ) {
23- $ cond = $ dfcond ;
24- $ val = $ dfval ;
27+ private static function splitFormatComparison (
28+ $ value ,
29+ ?string $ condition ,
30+ $ comparisonValue ,
31+ string $ defaultCondition ,
32+ $ defaultComparisonValue
33+ ): bool {
34+ if (!$ condition ) {
35+ $ condition = $ defaultCondition ;
36+ $ comparisonValue = $ defaultComparisonValue ;
2537 }
26- switch ($ cond ) {
38+
39+ switch ($ condition ) {
2740 case '> ' :
28- return $ value > $ val ;
41+ return $ value > $ comparisonValue ;
2942
3043 case '< ' :
31- return $ value < $ val ;
44+ return $ value < $ comparisonValue ;
3245
3346 case '<= ' :
34- return $ value <= $ val ;
47+ return $ value <= $ comparisonValue ;
3548
3649 case '<> ' :
37- return $ value != $ val ;
50+ return $ value != $ comparisonValue ;
3851
3952 case '= ' :
40- return $ value == $ val ;
53+ return $ value == $ comparisonValue ;
4154 }
4255
43- return $ value >= $ val ;
56+ return $ value >= $ comparisonValue ;
4457 }
4558
4659 /** @param mixed $value */
47- private static function splitFormat (array $ sections , $ value ): array
60+ private static function splitFormatForSectionSelection (array $ sections , $ value ): array
4861 {
4962 // Extract the relevant section depending on whether number is positive, negative, or zero?
5063 // Text not supported yet.
@@ -53,30 +66,30 @@ private static function splitFormat(array $sections, $value): array
5366 // 2 sections: [POSITIVE/ZERO/TEXT] [NEGATIVE]
5467 // 3 sections: [POSITIVE/TEXT] [NEGATIVE] [ZERO]
5568 // 4 sections: [POSITIVE] [NEGATIVE] [ZERO] [TEXT]
56- $ cnt = count ($ sections );
69+ $ sectionCount = count ($ sections );
5770 $ color_regex = '/ \\[( ' . implode ('| ' , Color::NAMED_COLORS ) . ') \\]/mui ' ;
5871 $ cond_regex = '/ \\[(>|>=|<|<=|=|<>)([+-]? \\d+([.] \\d+)?) \\]/ ' ;
5972 $ colors = ['' , '' , '' , '' , '' ];
60- $ condops = ['' , '' , '' , '' , '' ];
61- $ condvals = [0 , 0 , 0 , 0 , 0 ];
62- for ($ idx = 0 ; $ idx < $ cnt ; ++$ idx ) {
73+ $ conditionOperations = ['' , '' , '' , '' , '' ];
74+ $ conditionComparisonValues = [0 , 0 , 0 , 0 , 0 ];
75+ for ($ idx = 0 ; $ idx < $ sectionCount ; ++$ idx ) {
6376 if (preg_match ($ color_regex , $ sections [$ idx ], $ matches )) {
6477 $ colors [$ idx ] = $ matches [0 ];
6578 $ sections [$ idx ] = (string ) preg_replace ($ color_regex , '' , $ sections [$ idx ]);
6679 }
6780 if (preg_match ($ cond_regex , $ sections [$ idx ], $ matches )) {
68- $ condops [$ idx ] = $ matches [1 ];
69- $ condvals [$ idx ] = $ matches [2 ];
81+ $ conditionOperations [$ idx ] = $ matches [1 ];
82+ $ conditionComparisonValues [$ idx ] = $ matches [2 ];
7083 $ sections [$ idx ] = (string ) preg_replace ($ cond_regex , '' , $ sections [$ idx ]);
7184 }
7285 }
7386 $ color = $ colors [0 ];
7487 $ format = $ sections [0 ];
7588 $ absval = $ value ;
76- switch ($ cnt ) {
89+ switch ($ sectionCount ) {
7790 case 2 :
7891 $ absval = abs ($ value );
79- if (!self ::splitFormatCompare ($ value , $ condops [0 ], $ condvals [0 ], '>= ' , 0 )) {
92+ if (!self ::splitFormatComparison ($ value , $ conditionOperations [0 ], $ conditionComparisonValues [0 ], '>= ' , 0 )) {
8093 $ color = $ colors [1 ];
8194 $ format = $ sections [1 ];
8295 }
@@ -85,8 +98,8 @@ private static function splitFormat(array $sections, $value): array
8598 case 3 :
8699 case 4 :
87100 $ absval = abs ($ value );
88- if (!self ::splitFormatCompare ($ value , $ condops [0 ], $ condvals [0 ], '> ' , 0 )) {
89- if (self ::splitFormatCompare ($ value , $ condops [1 ], $ condvals [1 ], '< ' , 0 )) {
101+ if (!self ::splitFormatComparison ($ value , $ conditionOperations [0 ], $ conditionComparisonValues [0 ], '> ' , 0 )) {
102+ if (self ::splitFormatComparison ($ value , $ conditionOperations [1 ], $ conditionComparisonValues [1 ], '< ' , 0 )) {
90103 $ color = $ colors [1 ];
91104 $ format = $ sections [1 ];
92105 } else {
@@ -105,7 +118,8 @@ private static function splitFormat(array $sections, $value): array
105118 * Convert a value in a pre-defined format to a PHP string.
106119 *
107120 * @param null|bool|float|int|RichText|string $value Value to format
108- * @param string $format Format code, see = NumberFormat::FORMAT_*
121+ * @param string $format Format code: see = self::FORMAT_* for predefined values;
122+ * or can be any valid MS Excel custom format string
109123 * @param array $callBack Callback function for additional formatting of string
110124 *
111125 * @return string Formatted string
@@ -149,7 +163,7 @@ function ($matches) {
149163 // Get the sections, there can be up to four sections, separated with a semi-colon (but only if not a quoted literal)
150164 $ sections = preg_split (self ::SECTION_SPLIT , $ format ) ?: [];
151165
152- [$ colors , $ format , $ value ] = self ::splitFormat ($ sections , $ value );
166+ [$ colors , $ format , $ value ] = self ::splitFormatForSectionSelection ($ sections , $ value );
153167
154168 // In Excel formats, "_" is used to add spacing,
155169 // The following character indicates the size of the spacing, which we can't do in HTML, so we just use a standard space
0 commit comments