binaryOpManipulator = $binaryOpManipulator; } /** * getRuleDefinition * * @return RuleDefinition * @throws PoorDocumentationException */ public function getRuleDefinition(): RuleDefinition { return new RuleDefinition( 'Change $conf->global to getDolGlobal in context (1) conf->global Operator Value or (2) function(conf->global...)', [new CodeSample( '$conf->global->CONSTANT', 'getDolGlobalString|Int(\'CONSTANT\')' )] ); } /** * Return a node type from https://github.com/rectorphp/php-parser-nodes-docs/ * * @return string[] */ public function getNodeTypes(): array { return [Assign::class, FuncCall::class, MethodCall::class, Equal::class, NotEqual::class, Greater::class, GreaterOrEqual::class, Smaller::class, SmallerOrEqual::class, NotIdentical::class, BooleanAnd::class, Concat::class, ArrayItem::class, ArrayDimFetch::class]; } /** * refactor * * @param Node $node A node * @return FuncCall|Equal|Concat|ArrayDimFetch|void * return $node unchanged or void to do nothing */ public function refactor(Node $node) { if ($node instanceof Node\Expr\Assign) { // var is left of = and expr is right if (!isset($node->var)) { return; } if ($this->isGlobalVar($node->expr)) { $constName = $this->getConstName($node->expr); if (empty($constName)) { return; } $node->expr = new FuncCall( new Name('getDolGlobalString'), [new Arg($constName)] ); } return $node; } if ($node instanceof Node\Expr\ArrayItem) { if (!isset($node->key)) { return; } if ($this->isGlobalVar($node->value)) { $constName = $this->getConstName($node->value); if (empty($constName)) { return; } $node->value = new FuncCall( new Name('getDolGlobalString'), [new Arg($constName)] ); } return $node; } if ($node instanceof Node\Expr\ArrayDimFetch) { if (!isset($node->dim)) { return; } if ($this->isGlobalVar($node->dim)) { $constName = $this->getConstName($node->dim); if (empty($constName)) { return; } $node->dim = new FuncCall( new Name('getDolGlobalString'), [new Arg($constName)] ); } return $node; } if ($node instanceof FuncCall) { $tmpfunctionname = $this->getName($node); // If function is ok. We must avoid a lot of cases like isset(), empty() if (in_array($tmpfunctionname, array('dol_escape_htmltag', 'dol_hash', 'explode', 'is_numeric', 'length_accountg', 'length_accounta', 'make_substitutions', 'min', 'max', 'trunc', 'urlencode', 'yn'))) { //print "tmpfunctionname=".$tmpfunctionname."\n"; $args = $node->getArgs(); $nbofparam = count($args); if ($nbofparam >= 1) { $tmpargs = $args; foreach ($args as $key => $arg) { // only 1 element in this array //var_dump($key); //var_dump($arg->value);exit; if ($this->isGlobalVar($arg->value)) { $constName = $this->getConstName($arg->value); if (empty($constName)) { return; } $a = new FuncCall(new Name('getDolGlobalString'), [new Arg($constName)]); $tmpargs[$key] = new Arg($a); $r = new FuncCall(new Name($tmpfunctionname), $tmpargs); return $r; } } } } return $node; } if ($node instanceof MethodCall) { $tmpmethodname = $this->getName($node->name); // If function is ok. We must avoid a lot of cases if (in_array($tmpmethodname, array('fetch', 'idate', 'sanitize', 'select_language', 'trans'))) { //print "tmpmethodname=".$tmpmethodname."\n"; $expr = $node->var; $args = $node->getArgs(); $nbofparam = count($args); if ($nbofparam >= 1) { $tmpargs = $args; foreach ($args as $key => $arg) { // only 1 element in this array //var_dump($key); //var_dump($arg->value);exit; if ($this->isGlobalVar($arg->value)) { $constName = $this->getConstName($arg->value); if (empty($constName)) { return; } $a = new FuncCall(new Name('getDolGlobalString'), [new Arg($constName)]); $tmpargs[$key] = new Arg($a); $r = new MethodCall($expr, $tmpmethodname, $tmpargs); return $r; } } } } return $node; } if ($node instanceof Concat) { if ($this->isGlobalVar($node->left)) { $constName = $this->getConstName($node->left); if (empty($constName)) { return; } $leftConcat = new FuncCall( new Name('getDolGlobalString'), [new Arg($constName)] ); $rightConcat = $node->right; } if ($this->isGlobalVar($node->right)) { $constName = $this->getConstName($node->right); if (empty($constName)) { return; } $rightConcat = new FuncCall( new Name('getDolGlobalString'), [new Arg($constName)] ); $leftConcat = $node->left; } if (!isset($leftConcat, $rightConcat)) { return; } return new Concat($leftConcat, $rightConcat); } // If a && b and a or b is conf->global, we replace a or/and b if ($node instanceof BooleanAnd) { // Transformation sur le nœud gauche $changedone = 0; if ($this->isGlobalVar($node->left)) { $constName = $this->getConstName($node->left); if (empty($constName)) { return; } $node->left = new FuncCall( new Name('getDolGlobalString'), [new Arg($constName)] ); $changedone++; } if ($this->isGlobalVar($node->right)) { $constName = $this->getConstName($node->right); if (empty($constName)) { return; } $node->right = new FuncCall( new Name('getDolGlobalString'), [new Arg($constName)] ); $changedone++; } if ($changedone) { return $node; } } // Now process all comparison like: // $conf->global->... Operator Value $typeofcomparison = ''; if ($node instanceof Equal) { $typeofcomparison = 'Equal'; } if ($node instanceof NotEqual) { $typeofcomparison = 'NotEqual'; } if ($node instanceof Greater) { $typeofcomparison = 'Greater'; } if ($node instanceof GreaterOrEqual) { $typeofcomparison = 'GreaterOrEqual'; } if ($node instanceof Smaller) { $typeofcomparison = 'Smaller'; } if ($node instanceof SmallerOrEqual) { $typeofcomparison = 'SmallerOrEqual'; } if ($node instanceof NotIdentical) { $typeofcomparison = 'NotIdentical'; //var_dump($node->left); } if (empty($typeofcomparison)) { return; } // Now we process a comparison $isconfglobal = $this->isGlobalVar($node->left); if (!$isconfglobal) { $isconfglobal = $this->isGlobalVar($node->right); if (!$isconfglobal) { // The left side and right side is not conf->global->xxx, so we leave return; } // Right side is conf->global->xxx, but we can't know if we must use getDolGlobalInt or String, // so we use getDolGlobalString if comparison is == if ($typeofcomparison == 'Equal') { $constName = $this->getConstName($node->right); if (empty($constName)) { return; } // Test the type after the comparison conf->global->xxx to know the name of function $typeleft = $node->left->getType(); switch ($typeleft) { case 'Scalar_LNumber': $funcName = 'getDolGlobalInt'; break; case 'Scalar_String': $funcName = 'getDolGlobalString'; break; default: // Can be Expr_FuncCall $funcName = 'getDolGlobalString'; break; } $node->right = new FuncCall( new Name($funcName), [new Arg($constName)] ); return $node; } return; } // Test the type after the comparison conf->global->xxx to know the name of function $typeright = $node->right->getType(); switch ($typeright) { case 'Scalar_LNumber': $funcName = 'getDolGlobalInt'; break; case 'Scalar_String': $funcName = 'getDolGlobalString'; break; default: $funcName = 'getDolGlobalString'; break; } $constName = $this->getConstName($node->left); if (empty($constName)) { return; } if ($typeofcomparison == 'Equal') { return new Equal( new FuncCall( new Name($funcName), [new Arg($constName)] ), $node->right ); } if ($typeofcomparison == 'NotEqual') { return new NotEqual( new FuncCall( new Name($funcName), [new Arg($constName)] ), $node->right ); } if ($typeofcomparison == 'Greater') { return new Greater( new FuncCall( new Name($funcName), [new Arg($constName)] ), $node->right ); } if ($typeofcomparison == 'GreaterOrEqual') { return new GreaterOrEqual( new FuncCall( new Name($funcName), [new Arg($constName)] ), $node->right ); } if ($typeofcomparison == 'Smaller') { return new Smaller( new FuncCall( new Name($funcName), [new Arg($constName)] ), $node->right ); } if ($typeofcomparison == 'SmallerOrEqual') { return new SmallerOrEqual( new FuncCall( new Name($funcName), [new Arg($constName)] ), $node->right ); } if ($typeofcomparison == 'NotIdentical') { return new NotIdentical( new FuncCall( new Name($funcName), [new Arg($constName)] ), $node->right ); } } /** * Check if node is a global access with format conf->global->XXX * * @param Node $node A node * @return bool Return true if node is conf->global->XXX */ private function isGlobalVar($node) { if (!$node instanceof PropertyFetch) { return false; } if (!$this->isName($node->var, 'global')) { return false; } $global = $node->var; if (!$global instanceof PropertyFetch) { return false; } if (!$this->isName($global->var, 'conf')) { return false; } return true; } /** * @param Node $node Node to be parsed * @return Node|void Return the name of the constant */ private function getConstName($node) { if ($node instanceof PropertyFetch && $node->name instanceof Node\Expr) { return $node->name; } $name = $this->getName($node); if (empty($name)) { return; } return new String_($name); } }