diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index d0cb6784ce..7868ec5ef7 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -283,7 +283,7 @@ class Calculation ], 'AND' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Logical::class, 'logicalAnd'], + 'functionCall' => [Logical\Operations::class, 'logicalAnd'], 'argumentCount' => '1+', ], 'ARABIC' => [ @@ -999,7 +999,7 @@ class Calculation ], 'FALSE' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Logical::class, 'FALSE'], + 'functionCall' => [Logical\Boolean::class, 'FALSE'], 'argumentCount' => '0', ], 'FDIST' => [ @@ -1257,22 +1257,22 @@ class Calculation ], 'IF' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Logical::class, 'statementIf'], + 'functionCall' => [Logical\Conditional::class, 'statementIf'], 'argumentCount' => '1-3', ], 'IFERROR' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Logical::class, 'IFERROR'], + 'functionCall' => [Logical\Conditional::class, 'IFERROR'], 'argumentCount' => '2', ], 'IFNA' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Logical::class, 'IFNA'], + 'functionCall' => [Logical\Conditional::class, 'IFNA'], 'argumentCount' => '2', ], 'IFS' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Logical::class, 'IFS'], + 'functionCall' => [Logical\Conditional::class, 'IFS'], 'argumentCount' => '2+', ], 'IMABS' => [ @@ -1815,7 +1815,7 @@ class Calculation ], 'NOT' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Logical::class, 'NOT'], + 'functionCall' => [Logical\Operations::class, 'NOT'], 'argumentCount' => '1', ], 'NOW' => [ @@ -1887,7 +1887,7 @@ class Calculation ], 'OR' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Logical::class, 'logicalOr'], + 'functionCall' => [Logical\Operations::class, 'logicalOr'], 'argumentCount' => '1+', ], 'PDURATION' => [ @@ -2349,7 +2349,7 @@ class Calculation ], 'SWITCH' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Logical::class, 'statementSwitch'], + 'functionCall' => [Logical\Conditional::class, 'statementSwitch'], 'argumentCount' => '3+', ], 'SYD' => [ @@ -2469,7 +2469,7 @@ class Calculation ], 'TRUE' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Logical::class, 'TRUE'], + 'functionCall' => [Logical\Boolean::class, 'TRUE'], 'argumentCount' => '0', ], 'TRUNC' => [ @@ -2619,7 +2619,7 @@ class Calculation ], 'XOR' => [ 'category' => Category::CATEGORY_LOGICAL, - 'functionCall' => [Logical::class, 'logicalXor'], + 'functionCall' => [Logical\Operations::class, 'logicalXor'], 'argumentCount' => '1+', ], 'YEAR' => [ diff --git a/src/PhpSpreadsheet/Calculation/Logical.php b/src/PhpSpreadsheet/Calculation/Logical.php index 69c543cef9..802ceb263d 100644 --- a/src/PhpSpreadsheet/Calculation/Logical.php +++ b/src/PhpSpreadsheet/Calculation/Logical.php @@ -2,6 +2,8 @@ namespace PhpOffice\PhpSpreadsheet\Calculation; +use PhpOffice\PhpSpreadsheet\Calculation\Logical\Boolean; + class Logical { /** @@ -12,11 +14,13 @@ class Logical * Excel Function: * =TRUE() * + * @Deprecated Use the TRUE() method in the Logical\Boolean class instead + * * @return bool True */ - public static function true() + public static function true(): bool { - return true; + return Boolean::true(); } /** @@ -27,37 +31,13 @@ public static function true() * Excel Function: * =FALSE() * + * @Deprecated Use the FALSE() method in the Logical\Boolean class instead + * * @return bool False */ - public static function false() + public static function false(): bool { - return false; - } - - private static function countTrueValues(array $args) - { - $returnValue = 0; - - foreach ($args as $arg) { - // Is it a boolean value? - if (is_bool($arg)) { - $returnValue += $arg; - } elseif ((is_numeric($arg)) && (!is_string($arg))) { - $returnValue += ((int) $arg != 0); - } elseif (is_string($arg)) { - $arg = strtoupper($arg); - if (($arg == 'TRUE') || ($arg == Calculation::getTRUE())) { - $arg = true; - } elseif (($arg == 'FALSE') || ($arg == Calculation::getFALSE())) { - $arg = false; - } else { - return Functions::VALUE(); - } - $returnValue += ($arg != 0); - } - } - - return $returnValue; + return Boolean::false(); } /** @@ -73,8 +53,10 @@ private static function countTrueValues(array $args) * * Boolean arguments are treated as True or False as appropriate * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False - * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds - * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string + * holds the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * + * @Deprecated Use the logicalAnd() method in the Logical\Operations class instead * * @param mixed ...$args Data values * @@ -82,23 +64,7 @@ private static function countTrueValues(array $args) */ public static function logicalAnd(...$args) { - $args = Functions::flattenArray($args); - - if (count($args) == 0) { - return Functions::VALUE(); - } - - $args = array_filter($args, function ($value) { - return $value !== null || (is_string($value) && trim($value) == ''); - }); - $argCount = count($args); - - $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { - return $returnValue; - } - - return ($returnValue > 0) && ($returnValue == $argCount); + return Logical\Operations::logicalAnd(...$args); } /** @@ -114,8 +80,10 @@ public static function logicalAnd(...$args) * * Boolean arguments are treated as True or False as appropriate * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False - * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds - * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string + * holds the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * + * @Deprecated Use the logicalOr() method in the Logical\Operations class instead * * @param mixed $args Data values * @@ -123,29 +91,15 @@ public static function logicalAnd(...$args) */ public static function logicalOr(...$args) { - $args = Functions::flattenArray($args); - - if (count($args) == 0) { - return Functions::VALUE(); - } - - $args = array_filter($args, function ($value) { - return $value !== null || (is_string($value) && trim($value) == ''); - }); - - $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { - return $returnValue; - } - - return $returnValue > 0; + return Logical\Operations::logicalOr(...$args); } /** * LOGICAL_XOR. * * Returns the Exclusive Or logical operation for one or more supplied conditions. - * i.e. the Xor function returns TRUE if an odd number of the supplied conditions evaluate to TRUE, and FALSE otherwise. + * i.e. the Xor function returns TRUE if an odd number of the supplied conditions evaluate to TRUE, + * and FALSE otherwise. * * Excel Function: * =XOR(logical1[,logical2[, ...]]) @@ -155,8 +109,10 @@ public static function logicalOr(...$args) * * Boolean arguments are treated as True or False as appropriate * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False - * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds - * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string + * holds the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * + * @Deprecated Use the logicalXor() method in the Logical\Operations class instead * * @param mixed $args Data values * @@ -164,22 +120,7 @@ public static function logicalOr(...$args) */ public static function logicalXor(...$args) { - $args = Functions::flattenArray($args); - - if (count($args) == 0) { - return Functions::VALUE(); - } - - $args = array_filter($args, function ($value) { - return $value !== null || (is_string($value) && trim($value) == ''); - }); - - $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { - return $returnValue; - } - - return $returnValue % 2 == 1; + return Logical\Operations::logicalXor(...$args); } /** @@ -194,8 +135,10 @@ public static function logicalXor(...$args) * * Boolean arguments are treated as True or False as appropriate * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False - * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds - * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string + * holds the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * + * @Deprecated Use the NOT() method in the Logical\Operations class instead * * @param mixed $logical A value or expression that can be evaluated to TRUE or FALSE * @@ -203,20 +146,7 @@ public static function logicalXor(...$args) */ public static function NOT($logical = false) { - $logical = Functions::flattenSingleValue($logical); - - if (is_string($logical)) { - $logical = strtoupper($logical); - if (($logical == 'TRUE') || ($logical == Calculation::getTRUE())) { - return false; - } elseif (($logical == 'FALSE') || ($logical == Calculation::getFALSE())) { - return true; - } - - return Functions::VALUE(); - } - - return !$logical; + return Logical\Operations::NOT($logical); } /** @@ -232,18 +162,20 @@ public static function NOT($logical = false) * the expression evaluates to TRUE. Otherwise, the expression evaluates to FALSE. * This argument can use any comparison calculation operator. * ReturnIfTrue is the value that is returned if condition evaluates to TRUE. - * For example, if this argument is the text string "Within budget" and the condition argument evaluates to TRUE, - * then the IF function returns the text "Within budget" - * If condition is TRUE and ReturnIfTrue is blank, this argument returns 0 (zero). To display the word TRUE, use - * the logical value TRUE for this argument. + * For example, if this argument is the text string "Within budget" and the condition argument + * evaluates to TRUE, then the IF function returns the text "Within budget" + * If condition is TRUE and ReturnIfTrue is blank, this argument returns 0 (zero). + * To display the word TRUE, use the logical value TRUE for this argument. * ReturnIfTrue can be another formula. * ReturnIfFalse is the value that is returned if condition evaluates to FALSE. - * For example, if this argument is the text string "Over budget" and the condition argument evaluates to FALSE, - * then the IF function returns the text "Over budget". + * For example, if this argument is the text string "Over budget" and the condition argument + * evaluates to FALSE, then the IF function returns the text "Over budget". * If condition is FALSE and ReturnIfFalse is omitted, then the logical value FALSE is returned. * If condition is FALSE and ReturnIfFalse is blank, then the value 0 (zero) is returned. * ReturnIfFalse can be another formula. * + * @Deprecated Use the statementIf() method in the Logical\Conditional class instead + * * @param mixed $condition Condition to evaluate * @param mixed $returnIfTrue Value to return when condition is true * @param mixed $returnIfFalse Optional value to return when condition is false @@ -252,15 +184,7 @@ public static function NOT($logical = false) */ public static function statementIf($condition = true, $returnIfTrue = 0, $returnIfFalse = false) { - if (Functions::isError($condition)) { - return $condition; - } - - $condition = ($condition === null) ? true : (bool) Functions::flattenSingleValue($condition); - $returnIfTrue = ($returnIfTrue === null) ? 0 : Functions::flattenSingleValue($returnIfTrue); - $returnIfFalse = ($returnIfFalse === null) ? false : Functions::flattenSingleValue($returnIfFalse); - - return ($condition) ? $returnIfTrue : $returnIfFalse; + return Logical\Conditional::statementIf($condition, $returnIfTrue, $returnIfFalse); } /** @@ -274,11 +198,16 @@ public static function statementIf($condition = true, $returnIfTrue = 0, $return * Expression * The expression to compare to a list of values. * value1, value2, ... value_n - * A list of values that are compared to expression. The SWITCH function is looking for the first value that matches the expression. + * A list of values that are compared to expression. + * The SWITCH function is looking for the first value that matches the expression. * result1, result2, ... result_n - * A list of results. The SWITCH function returns the corresponding result when a value matches expression. + * A list of results. The SWITCH function returns the corresponding result when a value + * matches expression. * default - * Optional. It is the default to return if expression does not match any of the values (value1, value2, ... value_n). + * Optional. It is the default to return if expression does not match any of the values + * (value1, value2, ... value_n). + * + * @Deprecated Use the statementSwitch() method in the Logical\Conditional class instead * * @param mixed $arguments Statement arguments * @@ -286,33 +215,7 @@ public static function statementIf($condition = true, $returnIfTrue = 0, $return */ public static function statementSwitch(...$arguments) { - $result = Functions::VALUE(); - - if (count($arguments) > 0) { - $targetValue = Functions::flattenSingleValue($arguments[0]); - $argc = count($arguments) - 1; - $switchCount = floor($argc / 2); - $switchSatisfied = false; - $hasDefaultClause = $argc % 2 !== 0; - $defaultClause = $argc % 2 === 0 ? null : $arguments[count($arguments) - 1]; - - if ($switchCount) { - for ($index = 0; $index < $switchCount; ++$index) { - if ($targetValue == $arguments[$index * 2 + 1]) { - $result = $arguments[$index * 2 + 2]; - $switchSatisfied = true; - - break; - } - } - } - - if (!$switchSatisfied) { - $result = $hasDefaultClause ? $defaultClause : Functions::NA(); - } - } - - return $result; + return Logical\Conditional::statementSwitch(...$arguments); } /** @@ -321,6 +224,8 @@ public static function statementSwitch(...$arguments) * Excel Function: * =IFERROR(testValue,errorpart) * + * @Deprecated Use the IFERROR() method in the Logical\Conditional class instead + * * @param mixed $testValue Value to check, is also the value returned when no error * @param mixed $errorpart Value to return when testValue is an error condition * @@ -328,10 +233,7 @@ public static function statementSwitch(...$arguments) */ public static function IFERROR($testValue = '', $errorpart = '') { - $testValue = ($testValue === null) ? '' : Functions::flattenSingleValue($testValue); - $errorpart = ($errorpart === null) ? '' : Functions::flattenSingleValue($errorpart); - - return self::statementIf(Functions::isError($testValue), $errorpart, $testValue); + return Logical\Conditional::IFERROR($testValue, $errorpart); } /** @@ -340,6 +242,8 @@ public static function IFERROR($testValue = '', $errorpart = '') * Excel Function: * =IFNA(testValue,napart) * + * @Deprecated Use the IFNA() method in the Logical\Conditional class instead + * * @param mixed $testValue Value to check, is also the value returned when not an NA * @param mixed $napart Value to return when testValue is an NA condition * @@ -347,10 +251,7 @@ public static function IFERROR($testValue = '', $errorpart = '') */ public static function IFNA($testValue = '', $napart = '') { - $testValue = ($testValue === null) ? '' : Functions::flattenSingleValue($testValue); - $napart = ($napart === null) ? '' : Functions::flattenSingleValue($napart); - - return self::statementIf(Functions::isNa($testValue), $napart, $testValue); + return Logical\Conditional::IFNA($testValue, $napart); } /** @@ -364,27 +265,14 @@ public static function IFNA($testValue = '', $napart = '') * returnIfTrue1 ... returnIfTrue_n * Value returned if corresponding testValue (nth) was true * + * @Deprecated Use the IFS() method in the Logical\Conditional class instead + * * @param mixed ...$arguments Statement arguments * * @return mixed|string The value of returnIfTrue_n, if testValue_n was true. #N/A if none of testValues was true */ public static function IFS(...$arguments) { - if (count($arguments) % 2 != 0) { - return Functions::NA(); - } - // We use instance of Exception as a falseValue in order to prevent string collision with value in cell - $falseValueException = new Exception(); - for ($i = 0; $i < count($arguments); $i += 2) { - $testValue = ($arguments[$i] === null) ? '' : Functions::flattenSingleValue($arguments[$i]); - $returnIfTrue = ($arguments[$i + 1] === null) ? '' : Functions::flattenSingleValue($arguments[$i + 1]); - $result = self::statementIf($testValue, $returnIfTrue, $falseValueException); - - if ($result !== $falseValueException) { - return $result; - } - } - - return Functions::NA(); + return Logical\Conditional::IFS(...$arguments); } } diff --git a/src/PhpSpreadsheet/Calculation/Logical/Boolean.php b/src/PhpSpreadsheet/Calculation/Logical/Boolean.php new file mode 100644 index 0000000000..8f1e9354d8 --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/Logical/Boolean.php @@ -0,0 +1,36 @@ + 0) { + $targetValue = Functions::flattenSingleValue($arguments[0]); + $argc = count($arguments) - 1; + $switchCount = floor($argc / 2); + $switchSatisfied = false; + $hasDefaultClause = $argc % 2 !== 0; + $defaultClause = $argc % 2 === 0 ? null : $arguments[count($arguments) - 1]; + + if ($switchCount) { + for ($index = 0; $index < $switchCount; ++$index) { + if ($targetValue == $arguments[$index * 2 + 1]) { + $result = $arguments[$index * 2 + 2]; + $switchSatisfied = true; + + break; + } + } + } + + if (!$switchSatisfied) { + $result = $hasDefaultClause ? $defaultClause : Functions::NA(); + } + } + + return $result; + } + + /** + * IFERROR. + * + * Excel Function: + * =IFERROR(testValue,errorpart) + * + * @param mixed $testValue Value to check, is also the value returned when no error + * @param mixed $errorpart Value to return when testValue is an error condition + * + * @return mixed The value of errorpart or testValue determined by error condition + */ + public static function IFERROR($testValue = '', $errorpart = '') + { + $testValue = ($testValue === null) ? '' : Functions::flattenSingleValue($testValue); + $errorpart = ($errorpart === null) ? '' : Functions::flattenSingleValue($errorpart); + + return self::statementIf(Functions::isError($testValue), $errorpart, $testValue); + } + + /** + * IFNA. + * + * Excel Function: + * =IFNA(testValue,napart) + * + * @param mixed $testValue Value to check, is also the value returned when not an NA + * @param mixed $napart Value to return when testValue is an NA condition + * + * @return mixed The value of errorpart or testValue determined by error condition + */ + public static function IFNA($testValue = '', $napart = '') + { + $testValue = ($testValue === null) ? '' : Functions::flattenSingleValue($testValue); + $napart = ($napart === null) ? '' : Functions::flattenSingleValue($napart); + + return self::statementIf(Functions::isNa($testValue), $napart, $testValue); + } + + /** + * IFS. + * + * Excel Function: + * =IFS(testValue1;returnIfTrue1;testValue2;returnIfTrue2;...;testValue_n;returnIfTrue_n) + * + * testValue1 ... testValue_n + * Conditions to Evaluate + * returnIfTrue1 ... returnIfTrue_n + * Value returned if corresponding testValue (nth) was true + * + * @param mixed ...$arguments Statement arguments + * + * @return mixed|string The value of returnIfTrue_n, if testValue_n was true. #N/A if none of testValues was true + */ + public static function IFS(...$arguments) + { + if (count($arguments) % 2 != 0) { + return Functions::NA(); + } + // We use instance of Exception as a falseValue in order to prevent string collision with value in cell + $falseValueException = new Exception(); + for ($i = 0; $i < count($arguments); $i += 2) { + $testValue = ($arguments[$i] === null) ? '' : Functions::flattenSingleValue($arguments[$i]); + $returnIfTrue = ($arguments[$i + 1] === null) ? '' : Functions::flattenSingleValue($arguments[$i + 1]); + $result = self::statementIf($testValue, $returnIfTrue, $falseValueException); + + if ($result !== $falseValueException) { + return $result; + } + } + + return Functions::NA(); + } +} diff --git a/src/PhpSpreadsheet/Calculation/Logical/Operations.php b/src/PhpSpreadsheet/Calculation/Logical/Operations.php new file mode 100644 index 0000000000..6bfb6a545b --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/Logical/Operations.php @@ -0,0 +1,198 @@ + 0) && ($returnValue == $argCount); + } + + /** + * LOGICAL_OR. + * + * Returns boolean TRUE if any argument is TRUE; returns FALSE if all arguments are FALSE. + * + * Excel Function: + * =OR(logical1[,logical2[, ...]]) + * + * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays + * or references that contain logical values. + * + * Boolean arguments are treated as True or False as appropriate + * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string + * holds the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * + * @param mixed $args Data values + * + * @return bool|string the logical OR of the arguments + */ + public static function logicalOr(...$args) + { + $args = Functions::flattenArray($args); + + if (count($args) == 0) { + return Functions::VALUE(); + } + + $args = array_filter($args, function ($value) { + return $value !== null || (is_string($value) && trim($value) == ''); + }); + + $returnValue = self::countTrueValues($args); + if (is_string($returnValue)) { + return $returnValue; + } + + return $returnValue > 0; + } + + /** + * LOGICAL_XOR. + * + * Returns the Exclusive Or logical operation for one or more supplied conditions. + * i.e. the Xor function returns TRUE if an odd number of the supplied conditions evaluate to TRUE, + * and FALSE otherwise. + * + * Excel Function: + * =XOR(logical1[,logical2[, ...]]) + * + * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays + * or references that contain logical values. + * + * Boolean arguments are treated as True or False as appropriate + * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string + * holds the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * + * @param mixed $args Data values + * + * @return bool|string the logical XOR of the arguments + */ + public static function logicalXor(...$args) + { + $args = Functions::flattenArray($args); + + if (count($args) == 0) { + return Functions::VALUE(); + } + + $args = array_filter($args, function ($value) { + return $value !== null || (is_string($value) && trim($value) == ''); + }); + + $returnValue = self::countTrueValues($args); + if (is_string($returnValue)) { + return $returnValue; + } + + return $returnValue % 2 == 1; + } + + /** + * NOT. + * + * Returns the boolean inverse of the argument. + * + * Excel Function: + * =NOT(logical) + * + * The argument must evaluate to a logical value such as TRUE or FALSE + * + * Boolean arguments are treated as True or False as appropriate + * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string + * holds the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * + * @param mixed $logical A value or expression that can be evaluated to TRUE or FALSE + * + * @return bool|string the boolean inverse of the argument + */ + public static function NOT($logical = false) + { + $logical = Functions::flattenSingleValue($logical); + + if (is_string($logical)) { + $logical = mb_strtoupper($logical, 'UTF-8'); + if (($logical == 'TRUE') || ($logical == Calculation::getTRUE())) { + return false; + } elseif (($logical == 'FALSE') || ($logical == Calculation::getFALSE())) { + return true; + } + + return Functions::VALUE(); + } + + return !$logical; + } + + /** + * @return int|string + */ + private static function countTrueValues(array $args) + { + $trueValueCount = 0; + + foreach ($args as $arg) { + // Is it a boolean value? + if (is_bool($arg)) { + $trueValueCount += $arg; + } elseif ((is_numeric($arg)) && (!is_string($arg))) { + $trueValueCount += ((int) $arg != 0); + } elseif (is_string($arg)) { + $arg = mb_strtoupper($arg, 'UTF-8'); + if (($arg == 'TRUE') || ($arg == Calculation::getTRUE())) { + $arg = true; + } elseif (($arg == 'FALSE') || ($arg == Calculation::getFALSE())) { + $arg = false; + } else { + return Functions::VALUE(); + } + $trueValueCount += ($arg != 0); + } + } + + return $trueValueCount; + } +}