private function checkForTypeFunctionCall(\PHPParser_Node $node, LinkedFlowScope $blindScope, $outcome) { if ($node instanceof \PHPParser_Node_Stmt_Case) { $left = $node->getAttribute('parent')->cond; $right = $node->cond; } else { $left = $node->left; $right = $node->right; } // Handle gettype() function calls. $gettypeNode = $stringNode = null; if (NodeUtil::isGetTypeFunctionCall($left) && $right instanceof \PHPParser_Node_Scalar_String) { $gettypeNode = $left; $stringNode = $right; } else { if (NodeUtil::isGetTypeFunctionCall($right) && $left instanceof \PHPParser_Node_Scalar_String) { $gettypeNode = $right; $stringNode = $left; } } if (null !== $gettypeNode && null !== $stringNode && isset($gettypeNode->args[0])) { $operandNode = $gettypeNode->args[0]->value; $operandType = $this->getTypeIfRefinable($operandNode, $blindScope); if (null !== $operandType) { $resultEqualsValue = $node instanceof \PHPParser_Node_Expr_Equal || $node instanceof \PHPParser_Node_Expr_Identical || $node instanceof \PHPParser_Node_Stmt_Case; if (!$outcome) { $resultEqualsValue = !$resultEqualsValue; } return $this->caseGettypeFunctionCall($operandNode, $operandType, $stringNode->value, $resultEqualsValue, $blindScope); } } // Handle get_class() function calls. $getClassNode = $stringNode = null; if ('get_class' === NodeUtil::getFunctionName($left) && $right instanceof \PHPParser_Node_Scalar_String) { $getClassNode = $left; $stringNode = $right; } else { if ('get_class' === NodeUtil::getFunctionName($right) && $left instanceof \PHPParser_Node_Scalar_String) { $getClassNode = $right; $stringNode = $left; } } if (null !== $getClassNode && null !== $stringNode && isset($getClassNode->args[0])) { $operandNode = $getClassNode->args[0]->value; $operandType = $this->getTypeIfRefinable($operandNode, $blindScope); if (null !== $operandType) { $resultEqualsValue = $node instanceof \PHPParser_Node_Expr_Equal || $node instanceof \PHPParser_Node_Expr_Identical || $node instanceof \PHPParser_Node_Stmt_Case; if (!$outcome) { $resultEqualsValue = !$resultEqualsValue; } return $this->caseGetClassFunctionCall($operandNode, $operandType, $stringNode->value, $resultEqualsValue, $blindScope); } } // Handle is_??? and assert function calls as well as instanceof checks. $typeFunctionNode = $booleanNode = null; if ((NodeUtil::isTypeFunctionCall($left) || NodeUtil::isMaybeFunctionCall($left, 'assert') || $left instanceof \PHPParser_Node_Expr_Instanceof) && NodeUtil::isBoolean($right)) { $typeFunctionNode = $left; $booleanNode = $right; } else { if ((NodeUtil::isTypeFunctionCall($right) || NodeUtil::isMaybeFunctionCall($right, 'assert') || $right instanceof \PHPParser_Node_Expr_Instanceof) && NodeUtil::isBoolean($left)) { $typeFunctionNode = $right; $booleanNode = $left; } } if (null !== $booleanNode && null !== $typeFunctionNode) { $expectedOutcome = NodeUtil::getBooleanValue($booleanNode) ? $outcome : !$outcome; if ($typeFunctionNode instanceof \PHPParser_Node_Expr_Instanceof) { return $this->firstPreciserScopeKnowingConditionOutcome($typeFunctionNode, $blindScope, $expectedOutcome); } if (isset($typeFunctionNode->args[0])) { if (NodeUtil::isMaybeFunctionCall($typeFunctionNode, 'assert')) { return $this->firstPreciserScopeKnowingConditionOutcome($typeFunctionNode->args[0]->value, $blindScope, $expectedOutcome); } return $this->caseTypeFunctionCall($typeFunctionNode->name, $typeFunctionNode->args[0], $blindScope, $expectedOutcome); } } return null; }