Fix Remainder of Calculation vs. Phpstan Issues (#3108)

* Fix Remainder of Calculation vs. Phpstan Issues

I had tried to include these changes as part of an earlier effort, but something about them broke Phpstan. I removed them until I could determine the actual cause, which is ...

The array `$phpSpreadsheetFunctions` is a very large and very complicated array, typehinted as `array`. It is declared as private static; however, its content never changes (at least not now - there are some outstanding proposals that might change that). I have had some success with changing unmodifiable private static to private const. However, such a change here causes Phpstan to perform a lot more processing and eventually time out. So, leave it as static.

Having identified the cause of the problem, none of the other changes were problematic, so this PR applies the rest of them.

* Scrutinizer

One problem.

* Scrutinizer False Positives Without Suggested Annotation

See if minor code changes can make these go away.

* Scrutinizer Still Experimenting

Trying again.
This commit is contained in:
oleibman 2022-10-12 23:28:08 -07:00 committed by GitHub
parent de975e650f
commit befbc564f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 652 deletions

File diff suppressed because it is too large Load Diff

View File

@ -64,14 +64,14 @@ class Calculation
/**
* Instance of this class.
*
* @var Calculation
* @var ?Calculation
*/
private static $instance;
/**
* Instance of the spreadsheet this Calculation Engine is using.
*
* @var Spreadsheet
* @var ?Spreadsheet
*/
private $spreadsheet;
@ -102,10 +102,8 @@ class Calculation
/**
* List of operators that can be used within formulae
* The true/false value indicates whether it is a binary operator or a unary operator.
*
* @var array
*/
private static $operators = [
private const CALCULATION_OPERATORS = [
'+' => true, '-' => true, '*' => true, '/' => true,
'^' => true, '&' => true, '%' => false, '~' => false,
'>' => true, '<' => true, '=' => true, '>=' => true,
@ -115,10 +113,8 @@ class Calculation
/**
* List of binary operators (those that expect two operands).
*
* @var array
*/
private static $binaryOperators = [
private const BINARY_OPERATORS = [
'+' => true, '-' => true, '*' => true, '/' => true,
'^' => true, '&' => true, '>' => true, '<' => true,
'=' => true, '>=' => true, '<=' => true, '<>' => true,
@ -221,25 +217,47 @@ class Calculation
*
* @var array<string, string>
*/
public static $localeBoolean = [
private static $localeBoolean = [
'TRUE' => 'TRUE',
'FALSE' => 'FALSE',
'NULL' => 'NULL',
];
public static function getLocaleBoolean(string $index): string
{
return self::$localeBoolean[$index];
}
/**
* Excel constant string translations to their PHP equivalents
* Constant conversion from text name/value to actual (datatyped) value.
*
* @var array<string, mixed>
*/
public static $excelConstants = [
private static $excelConstants = [
'TRUE' => true,
'FALSE' => false,
'NULL' => null,
];
/** @var array */
public static function keyInExcelConstants(string $key): bool
{
return array_key_exists($key, self::$excelConstants);
}
/** @return mixed */
public static function getExcelConstants(string $key)
{
return self::$excelConstants[$key];
}
/**
* Array of functions usable on Spreadsheet.
* In theory, this could be const rather than static;
* however, Phpstan breaks trying to analyze it when attempted.
*
*@var array
*/
private static $phpSpreadsheetFunctions = [
'ABS' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
@ -2855,7 +2873,8 @@ class Calculation
private static function loadLocales(): void
{
$localeFileDirectory = __DIR__ . '/locale/';
foreach (glob($localeFileDirectory . '*', GLOB_ONLYDIR) as $filename) {
$localeFileNames = glob($localeFileDirectory . '*', GLOB_ONLYDIR) ?: [];
foreach ($localeFileNames as $filename) {
$filename = substr($filename, strlen($localeFileDirectory));
if ($filename != 'en') {
self::$validLocaleLanguages[] = $filename;
@ -3118,7 +3137,7 @@ class Calculation
}
// Retrieve the list of locale or language specific function names
$localeFunctions = file($functionNamesFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$localeFunctions = file($functionNamesFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [];
foreach ($localeFunctions as $localeFunction) {
[$localeFunction] = explode('##', $localeFunction); // Strip out comments
if (strpos($localeFunction, '=') !== false) {
@ -3142,7 +3161,7 @@ class Calculation
return false;
}
$localeSettings = file($configFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$localeSettings = file($configFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [];
foreach ($localeSettings as $localeSetting) {
[$localeSetting] = explode('##', $localeSetting); // Strip out comments
if (strpos($localeSetting, '=') !== false) {
@ -3239,7 +3258,7 @@ class Calculation
$notWithinQuotes = false;
foreach ($temp as &$value) {
// Only adjust in alternating array entries
$notWithinQuotes = !$notWithinQuotes;
$notWithinQuotes = self::logicalNot($notWithinQuotes);
if ($notWithinQuotes === true) {
$value = self::translateFormulaBlock($from, $to, $value, $inFunctionBracesLevel, $inMatrixBracesLevel, $fromSeparator, $toSeparator);
}
@ -3453,12 +3472,19 @@ class Calculation
try {
$result = self::unwrapResult($this->_calculateFormulaValue($cell->getValue(), $cell->getCoordinate(), $cell));
if ($this->spreadsheet === null) {
throw new Exception('null spreadsheet in calculateCellValue');
}
$cellAddress = array_pop($this->cellStack);
$this->spreadsheet->getSheetByName($cellAddress['sheet'])->getCell($cellAddress['cell']);
if ($cellAddress === null) {
throw new Exception('null cellAddress in calculateCellValue');
}
$testSheet = $this->spreadsheet->getSheetByName($cellAddress['sheet']);
if ($testSheet === null) {
throw new Exception('worksheet not found in calculateCellValue');
}
$testSheet->getCell($cellAddress['cell']);
} catch (\Exception $e) {
$cellAddress = array_pop($this->cellStack);
$this->spreadsheet->getSheetByName($cellAddress['sheet'])->getCell($cellAddress['cell']);
throw new Exception($e->getMessage());
}
@ -3933,7 +3959,7 @@ class Calculation
$notWithinQuotes = false;
foreach ($temp as &$value) {
// Only count/replace in alternating array entries
$notWithinQuotes = !$notWithinQuotes;
$notWithinQuotes = self::logicalNot($notWithinQuotes);
if ($notWithinQuotes === true) {
$openCount += substr_count($value, self::FORMULA_OPEN_MATRIX_BRACE);
$closeCount += substr_count($value, self::FORMULA_CLOSE_MATRIX_BRACE);
@ -4077,11 +4103,11 @@ class Calculation
++$index; // Drop the redundant plus symbol
} elseif ((($opCharacter == '~') || ($opCharacter == '∩') || ($opCharacter == '')) && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde, union or intersect because they are legal
return $this->raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression
} elseif ((isset(self::$operators[$opCharacter]) || $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack?
} elseif ((isset(self::CALCULATION_OPERATORS[$opCharacter]) || $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack?
while (
$stack->count() > 0 &&
($o2 = $stack->last()) &&
isset(self::$operators[$o2['value']]) &&
isset(self::CALCULATION_OPERATORS[$o2['value']]) &&
@(self::$operatorAssociativity[$opCharacter] ? self::$operatorPrecedence[$opCharacter] < self::$operatorPrecedence[$o2['value']] : self::$operatorPrecedence[$opCharacter] <= self::$operatorPrecedence[$o2['value']])
) {
$output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output
@ -4095,9 +4121,6 @@ class Calculation
} elseif ($opCharacter == ')' && $expectingOperator) { // Are we expecting to close a parenthesis?
$expectingOperand = false;
while (($o2 = $stack->pop()) && $o2['value'] !== '(') { // Pop off the stack back to the last (
if ($o2 === null) {
return $this->raiseFormulaError('Formula Error: Unexpected closing brace ")"');
}
$output[] = $o2;
}
$d = $stack->last(2);
@ -4121,10 +4144,14 @@ class Calculation
$output[] = $stack->pop(); // Pop the function and push onto the output
if (isset(self::$controlFunctions[$functionName])) {
$expectedArgumentCount = self::$controlFunctions[$functionName]['argumentCount'];
// Scrutinizer says functionCall is unused after this assignment.
// It might be right, but I'm too lazy to confirm.
$functionCall = self::$controlFunctions[$functionName]['functionCall'];
self::doNothing($functionCall);
} elseif (isset(self::$phpSpreadsheetFunctions[$functionName])) {
$expectedArgumentCount = self::$phpSpreadsheetFunctions[$functionName]['argumentCount'];
$functionCall = self::$phpSpreadsheetFunctions[$functionName]['functionCall'];
self::doNothing($functionCall);
} else { // did we somehow push a non-function on the stack? this should never happen
return $this->raiseFormulaError('Formula Error: Internal error, non-function on stack');
}
@ -4145,6 +4172,7 @@ class Calculation
}
} elseif ($expectedArgumentCount != '*') {
$isOperandOrFunction = preg_match('/(\d*)([-+,])(\d*)/', $expectedArgumentCount, $argMatch);
self::doNothing($isOperandOrFunction);
switch ($argMatch[2]) {
case '+':
if ($argumentCount < $argMatch[1]) {
@ -4182,9 +4210,6 @@ class Calculation
}
while (($o2 = $stack->pop()) && $o2['value'] !== '(') { // Pop off the stack back to the last (
if ($o2 === null) {
return $this->raiseFormulaError('Formula Error: Unexpected ,');
}
$output[] = $o2; // pop the argument expression stuff and push onto the output
}
// If we've a comma when we're expecting an operand, then what we actually have is a null operand;
@ -4256,20 +4281,20 @@ class Calculation
if ($matches[2] === '') {
// Otherwise, we 'inherit' the worksheet reference from the start cell reference
// The start of the cell range reference should be the last entry in $output
$rangeStartCellRef = $output[count($output) - 1]['value'];
$rangeStartCellRef = $output[count($output) - 1]['value'] ?? '';
if ($rangeStartCellRef === ':') {
// Do we have chained range operators?
$rangeStartCellRef = $output[count($output) - 2]['value'];
$rangeStartCellRef = $output[count($output) - 2]['value'] ?? '';
}
preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/miu', $rangeStartCellRef, $rangeStartMatches);
if ($rangeStartMatches[2] > '') {
$val = $rangeStartMatches[2] . '!' . $val;
}
} else {
$rangeStartCellRef = $output[count($output) - 1]['value'];
$rangeStartCellRef = $output[count($output) - 1]['value'] ?? '';
if ($rangeStartCellRef === ':') {
// Do we have chained range operators?
$rangeStartCellRef = $output[count($output) - 2]['value'];
$rangeStartCellRef = $output[count($output) - 2]['value'] ?? '';
}
preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/miu', $rangeStartCellRef, $rangeStartMatches);
if ($rangeStartMatches[2] !== $matches[2]) {
@ -4299,9 +4324,9 @@ class Calculation
!is_numeric($val) &&
((ctype_alpha($val) === false || strlen($val) > 3)) &&
(preg_match('/^' . self::CALCULATION_REGEXP_DEFINEDNAME . '$/mui', $val) !== false) &&
($this->spreadsheet->getNamedRange($val) !== null)
($this->spreadsheet === null || $this->spreadsheet->getNamedRange($val) !== null)
) {
$namedRange = $this->spreadsheet->getNamedRange($val);
$namedRange = ($this->spreadsheet === null) ? null : $this->spreadsheet->getNamedRange($val);
if ($namedRange !== null) {
$stackItemType = 'Defined Name';
$address = str_replace('$', '', $namedRange->getValue());
@ -4319,7 +4344,7 @@ class Calculation
$val = $address;
}
} else {
$startRowColRef = $output[count($output) - 1]['value'];
$startRowColRef = $output[count($output) - 1]['value'] ?? '';
[$rangeWS1, $startRowColRef] = Worksheet::extractSheetTitle($startRowColRef, true);
$rangeSheetRef = $rangeWS1;
if ($rangeWS1 !== '') {
@ -4395,7 +4420,7 @@ class Calculation
$stackItemType = 'Defined Name';
$stackItemReference = $val;
} elseif (is_numeric($val)) {
if ((strpos($val, '.') !== false) || (stripos($val, 'e') !== false) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) {
if ((strpos((string) $val, '.') !== false) || (stripos((string) $val, 'e') !== false) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) {
$val = (float) $val;
} else {
$val = (int) $val;
@ -4419,7 +4444,7 @@ class Calculation
} else {
return $this->raiseFormulaError("Formula Error: Unexpected ')'");
}
} elseif (isset(self::$operators[$opCharacter]) && !$expectingOperator) {
} elseif (isset(self::CALCULATION_OPERATORS[$opCharacter]) && !$expectingOperator) {
return $this->raiseFormulaError("Formula Error: Unexpected operator '$opCharacter'");
} else { // I don't even want to know what you did to get here
return $this->raiseFormulaError('Formula Error: An unexpected error occurred');
@ -4428,7 +4453,7 @@ class Calculation
if ($index == strlen($formula)) {
// Did we end with an operator?.
// Only valid for the % unary operator
if ((isset(self::$operators[$opCharacter])) && ($opCharacter != '%')) {
if ((isset(self::CALCULATION_OPERATORS[$opCharacter])) && ($opCharacter != '%')) {
return $this->raiseFormulaError("Formula Error: Operator '$opCharacter' has no operands");
}
@ -4462,7 +4487,7 @@ class Calculation
while (
$stack->count() > 0 &&
($o2 = $stack->last()) &&
isset(self::$operators[$o2['value']]) &&
isset(self::CALCULATION_OPERATORS[$o2['value']]) &&
@(self::$operatorAssociativity[$opCharacter] ? self::$operatorPrecedence[$opCharacter] < self::$operatorPrecedence[$o2['value']] : self::$operatorPrecedence[$opCharacter] <= self::$operatorPrecedence[$o2['value']])
) {
$output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output
@ -4475,7 +4500,7 @@ class Calculation
while (($op = $stack->pop()) !== null) {
// pop everything off the stack and push onto output
if ((is_array($op) && $op['value'] == '(') || ($op === '(')) {
if ((is_array($op) && $op['value'] == '(')) {
return $this->raiseFormulaError("Formula Error: Expecting ')'"); // if there are any opening braces on the stack, then braces were unbalanced
}
$output[] = $op;
@ -4605,7 +4630,7 @@ class Calculation
}
// if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack
if (!is_numeric($token) && isset(self::$binaryOperators[$token])) {
if (!is_numeric($token) && isset(self::BINARY_OPERATORS[$token])) {
// We must have two operands, error if we don't
if (($operand2Data = $stack->pop()) === null) {
return $this->raiseFormulaError('Internal error - Operand value missing from stack');
@ -4642,7 +4667,7 @@ class Calculation
// Binary Operators
case ':': // Range
if ($operand1Data['type'] === 'Defined Name') {
if (preg_match('/$' . self::CALCULATION_REGEXP_DEFINEDNAME . '^/mui', $operand1Data['reference']) !== false) {
if (preg_match('/$' . self::CALCULATION_REGEXP_DEFINEDNAME . '^/mui', $operand1Data['reference']) !== false && $this->spreadsheet !== null) {
$definedName = $this->spreadsheet->getNamedRange($operand1Data['reference']);
if ($definedName !== null) {
$operand1Data['reference'] = $operand1Data['value'] = str_replace('$', '', $definedName->getValue());
@ -4692,7 +4717,7 @@ class Calculation
$oRow[] = $oCR[1];
}
$cellRef = Coordinate::stringFromColumnIndex(min($oCol) + 1) . min($oRow) . ':' . Coordinate::stringFromColumnIndex(max($oCol) + 1) . max($oRow);
if ($pCellParent !== null) {
if ($pCellParent !== null && $this->spreadsheet !== null) {
$cellValue = $this->extractCellRange($cellRef, $this->spreadsheet->getSheetByName($sheet1), false);
} else {
return $this->raiseFormulaError('Unable to access Cell Reference');
@ -4853,7 +4878,7 @@ class Calculation
}
$matches[2] = trim($matches[2], "\"'");
$this->debugLog->writeDebugLog('Evaluating Cell Range %s in worksheet %s', $cellRef, $matches[2]);
if ($pCellParent !== null) {
if ($pCellParent !== null && $this->spreadsheet !== null) {
$cellValue = $this->extractCellRange($cellRef, $this->spreadsheet->getSheetByName($matches[2]), false);
} else {
return $this->raiseFormulaError('Unable to access Cell Reference');
@ -4882,7 +4907,7 @@ class Calculation
return $this->raiseFormulaError('Unable to access External Workbook');
}
$this->debugLog->writeDebugLog('Evaluating Cell %s in worksheet %s', $cellRef, $matches[2]);
if ($pCellParent !== null) {
if ($pCellParent !== null && $this->spreadsheet !== null) {
$cellSheet = $this->spreadsheet->getSheetByName($matches[2]);
if ($cellSheet && $cellSheet->cellExists($cellRef)) {
$cellValue = $this->extractCellRange($cellRef, $this->spreadsheet->getSheetByName($matches[2]), false);
@ -5272,7 +5297,7 @@ class Calculation
{
$this->formulaError = $errorMessage;
$this->cyclicReferenceStack->clear();
$suppress = $this->suppressFormulaErrors ?? $this->suppressFormulaErrorsNew;
$suppress = /** @scrutinizer ignore-deprecated */ $this->suppressFormulaErrors ?? $this->suppressFormulaErrorsNew;
if (!$suppress) {
throw new Exception($errorMessage);
}
@ -5299,16 +5324,18 @@ class Calculation
if (strpos($range, '!') !== false) {
[$worksheetName, $range] = Worksheet::extractSheetTitle($range, true);
$worksheet = $this->spreadsheet->getSheetByName($worksheetName);
$worksheet = ($this->spreadsheet === null) ? null : $this->spreadsheet->getSheetByName($worksheetName);
}
// Extract range
$aReferences = Coordinate::extractAllCellReferencesInRange($range);
$range = "'" . $worksheetName . "'" . '!' . $range;
$currentCol = '';
$currentRow = 0;
if (!isset($aReferences[1])) {
// Single cell in range
sscanf($aReferences[0], '%[A-Z]%d', $currentCol, $currentRow);
if ($worksheet->cellExists($aReferences[0])) {
if ($worksheet !== null && $worksheet->cellExists($aReferences[0])) {
$returnValue[$currentRow][$currentCol] = $worksheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
} else {
$returnValue[$currentRow][$currentCol] = null;
@ -5318,7 +5345,7 @@ class Calculation
foreach ($aReferences as $reference) {
// Extract range
sscanf($reference, '%[A-Z]%d', $currentCol, $currentRow);
if ($worksheet->cellExists($reference)) {
if ($worksheet !== null && $worksheet->cellExists($reference)) {
$returnValue[$currentRow][$currentCol] = $worksheet->getCell($reference)->getCalculatedValue($resetLog);
} else {
$returnValue[$currentRow][$currentCol] = null;
@ -5347,11 +5374,11 @@ class Calculation
if ($worksheet !== null) {
if (strpos($range, '!') !== false) {
[$worksheetName, $range] = Worksheet::extractSheetTitle($range, true);
$worksheet = $this->spreadsheet->getSheetByName($worksheetName);
$worksheet = ($this->spreadsheet === null) ? null : $this->spreadsheet->getSheetByName($worksheetName);
}
// Named range?
$namedRange = DefinedName::resolveName($range, /** @scrutinizer ignore-type */ $worksheet);
$namedRange = ($worksheet === null) ? null : DefinedName::resolveName($range, $worksheet);
if ($namedRange === null) {
return Information\ExcelError::REF();
}
@ -5360,10 +5387,10 @@ class Calculation
$range = $namedRange->getValue();
$splitRange = Coordinate::splitRange($range);
// Convert row and column references
if (ctype_alpha($splitRange[0][0])) {
$range = $splitRange[0][0] . '1:' . $splitRange[0][1] . $namedRange->getWorksheet()->getHighestRow();
} elseif (ctype_digit($splitRange[0][0])) {
$range = 'A' . $splitRange[0][0] . ':' . $namedRange->getWorksheet()->getHighestColumn() . $splitRange[0][1];
if ($worksheet !== null && ctype_alpha($splitRange[0][0])) {
$range = $splitRange[0][0] . '1:' . $splitRange[0][1] . $worksheet->getHighestRow();
} elseif ($worksheet !== null && ctype_digit($splitRange[0][0])) {
$range = 'A' . $splitRange[0][0] . ':' . $worksheet->getHighestColumn() . $splitRange[0][1];
}
// Extract range
@ -5371,7 +5398,7 @@ class Calculation
if (!isset($aReferences[1])) {
// Single cell (or single column or row) in range
[$currentCol, $currentRow] = Coordinate::coordinateFromString($aReferences[0]);
if ($worksheet->cellExists($aReferences[0])) {
if ($worksheet !== null && $worksheet->cellExists($aReferences[0])) {
$returnValue[$currentRow][$currentCol] = $worksheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
} else {
$returnValue[$currentRow][$currentCol] = null;
@ -5381,7 +5408,7 @@ class Calculation
foreach ($aReferences as $reference) {
// Extract range
[$currentCol, $currentRow] = Coordinate::coordinateFromString($reference);
if ($worksheet->cellExists($reference)) {
if ($worksheet !== null && $worksheet->cellExists($reference)) {
$returnValue[$currentRow][$currentCol] = $worksheet->getCell($reference)->getCalculatedValue($resetLog);
} else {
$returnValue[$currentRow][$currentCol] = null;
@ -5593,4 +5620,15 @@ class Calculation
{
return $this->suppressFormulaErrorsNew;
}
private static function logicalNot(bool $arg): bool
{
return $arg === false;
}
/** @param mixed $arg */
private static function doNothing($arg): bool
{
return (bool) $arg;
}
}

View File

@ -236,7 +236,7 @@ class Format
$value = ($format === true) ? Calculation::wrapResult($value) : $value;
$value = str_replace("\n", '', $value);
} elseif (is_bool($value)) {
$value = Calculation::$localeBoolean[$value === true ? 'TRUE' : 'FALSE'];
$value = Calculation::getLocaleBoolean($value ? 'TRUE' : 'FALSE');
}
return (string) $value;

View File

@ -232,7 +232,7 @@ class Text
private static function formatValueMode0($cellValue): string
{
if (is_bool($cellValue)) {
return ($cellValue) ? Calculation::$localeBoolean['TRUE'] : Calculation::$localeBoolean['FALSE'];
return Calculation::getLocaleBoolean($cellValue ? 'TRUE' : 'FALSE');
}
return (string) $cellValue;
@ -246,7 +246,7 @@ class Text
if (is_string($cellValue) && Functions::isError($cellValue) === false) {
return Calculation::FORMULA_STRING_QUOTE . $cellValue . Calculation::FORMULA_STRING_QUOTE;
} elseif (is_bool($cellValue)) {
return ($cellValue) ? Calculation::$localeBoolean['TRUE'] : Calculation::$localeBoolean['FALSE'];
return Calculation::getLocaleBoolean($cellValue ? 'TRUE' : 'FALSE');
}
return (string) $cellValue;

View File

@ -140,8 +140,8 @@ class CellValue extends WizardAbstract implements WizardInterface
// Best-guess to try and identify if the text is a string literal, a cell reference or a formula?
$operandValueType = Wizard::VALUE_TYPE_LITERAL;
if (is_string($condition)) {
if (array_key_exists($condition, Calculation::$excelConstants)) {
$condition = Calculation::$excelConstants[$condition];
if (Calculation::keyInExcelConstants($condition)) {
$condition = Calculation::getExcelConstants($condition);
} elseif (preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '$/i', $condition)) {
$operandValueType = Wizard::VALUE_TYPE_CELL;
$condition = self::reverseAdjustCellRef($condition, $cellRange);

View File

@ -129,9 +129,7 @@ class TextValue extends WizardAbstract implements WizardInterface
// Best-guess to try and identify if the text is a string literal, a cell reference or a formula?
$wizard->operandValueType = Wizard::VALUE_TYPE_LITERAL;
$condition = $conditional->getText();
if (is_string($condition) && array_key_exists($condition, Calculation::$excelConstants)) {
$condition = Calculation::$excelConstants[$condition];
} elseif (preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '$/i', $condition)) {
if (preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '$/i', $condition)) {
$wizard->operandValueType = Wizard::VALUE_TYPE_CELL;
$condition = self::reverseAdjustCellRef($condition, $cellRange);
} elseif (