Issues (22)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/NodeGenerator.php (11 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Saxulum\ElasticSearchQueryBuilder\Generator;
6
7
use PhpParser\Node\Arg;
8
use PhpParser\Node\Expr;
9
use PhpParser\Node\Expr\Assign;
10
use PhpParser\Node\Expr\ConstFetch;
11
use PhpParser\Node\Expr\MethodCall;
12
use PhpParser\Node\Expr\StaticCall;
13
use PhpParser\Node\Expr\Variable;
14
use PhpParser\Node\Name;
15
use PhpParser\Node\Scalar\DNumber;
16
use PhpParser\Node\Scalar\LNumber;
17
use PhpParser\Node\Scalar\String_;
18
use PhpParser\PrettyPrinter\Standard as PhpGenerator;
19
20
final class NodeGenerator
21
{
22
    /**
23
     * @var PhpGenerator
24
     */
25
    private $phpGenerator;
26
27
    /**
28
     * @var bool
29
     */
30
    private $useQueryBuilderFactory;
31
32
    /**
33
     * @param PhpGenerator $phpGenerator
34
     * @param bool         $useQueryBuilderFactory
35
     */
36 15
    public function __construct(PhpGenerator $phpGenerator, bool $useQueryBuilderFactory = false)
37
    {
38 15
        $this->phpGenerator = $phpGenerator;
39 15
        $this->useQueryBuilderFactory = $useQueryBuilderFactory;
40
41 15
        if ($useQueryBuilderFactory) {
42 1
            @trigger_error('Argument $useQueryBuilderFactory will be removed', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
43
        }
44 15
    }
45
46
    /**
47
     * @param $query
48
     *
49
     * @return string
50
     */
51 15
    public function generateByJson($query): string
52
    {
53 15
        $data = json_decode($query, false);
54 15
        if (JSON_ERROR_NONE !== json_last_error()) {
55 1
            throw new \InvalidArgumentException(sprintf('Message: %s, query: %s', json_last_error_msg(), $query));
56
        }
57
58 14
        if ($data instanceof \stdClass) {
59 13
            $expr = $this->appendChildrenToObjectNode($data);
60
        } else {
61 1
            $expr = $this->appendChildrenToArrayNode($data);
62
        }
63
64 14
        $code = $this->phpGenerator->prettyPrint([new Assign(new Variable('node'), $expr)]);
65
66 14
        return $this->structureCode($code);
67
    }
68
69
    /**
70
     * @return Expr
71
     */
72 13 View Code Duplication
    private function createObjectNode(): Expr
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
73
    {
74 13
        if (!$this->useQueryBuilderFactory) {
75 12
            return new StaticCall(new Name('ObjectNode'), 'create');
76
        }
77
78 1
        return new MethodCall(new Variable('qb'), 'objectNode');
79
    }
80
81
    /**
82
     * @return Expr
83
     */
84 4 View Code Duplication
    private function createArrayNode(): Expr
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
85
    {
86 4
        if (!$this->useQueryBuilderFactory) {
87 3
            return new StaticCall(new Name('ArrayNode'), 'create');
88
        }
89
90 1
        return new MethodCall(new Variable('qb'), 'arrayNode');
91
    }
92
93
    /**
94
     * @param string|float|int|bool|null $value
95
     *
96
     * @return Expr
97
     */
98 13
    private function createScalarNode($value): Expr
99
    {
100 13
        if (!$this->useQueryBuilderFactory) {
101 12
            return $this->createScalarNodeDefault($value);
102
        }
103
104 1
        return $this->createScalarNodeQueryBuilderFactory($value);
105
    }
106
107
    /**
108
     * @param string|float|int|bool|null $value
109
     *
110
     * @return Expr
111
     */
112 12 View Code Duplication
    private function createScalarNodeDefault($value): Expr
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
113
    {
114 12
        if (is_int($value)) {
115 5
            return new StaticCall(new Name('IntNode'), 'create', [new Arg(new LNumber($value))]);
116 10
        } elseif (is_float($value)) {
117 1
            return new StaticCall(new Name('FloatNode'), 'create', [new Arg(new DNumber($value))]);
118 10
        } elseif (is_bool($value)) {
119 1
            return new StaticCall(new Name('BoolNode'), 'create', [new Arg(new ConstFetch(new Name($value ? 'true' : 'false')))]);
120 10
        } elseif (null === $value) {
121 1
            return new StaticCall(new Name('NullNode'), 'create');
122
        }
123
124 10
        return new StaticCall(new Name('StringNode'), 'create', [new Arg(new String_($value))]);
125
    }
126
127
    /**
128
     * @param string|float|int|bool|null $value
129
     *
130
     * @return Expr
131
     */
132 1 View Code Duplication
    private function createScalarNodeQueryBuilderFactory($value): Expr
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
133
    {
134 1
        if (is_int($value)) {
135 1
            return new MethodCall(new Variable('qb'), 'intNode', [new Arg(new LNumber($value))]);
136 1
        } elseif (is_float($value)) {
137 1
            return new MethodCall(new Variable('qb'), 'floatNode', [new Arg(new DNumber($value))]);
138 1
        } elseif (is_bool($value)) {
139 1
            return new MethodCall(new Variable('qb'), 'boolNode', [new Arg(new ConstFetch(new Name($value ? 'true' : 'false')))]);
140 1
        } elseif (null === $value) {
141 1
            return new MethodCall(new Variable('qb'), 'nullNode');
142
        }
143
144 1
        return new MethodCall(new Variable('qb'), 'stringNode', [new Arg(new String_($value))]);
145
    }
146
147
    /**
148
     * @param array $data
149
     *
150
     * @return Expr
151
     */
152 4
    private function appendChildrenToArrayNode(array $data)
153
    {
154 4
        $expr = $this->createArrayNode();
155
156 4
        foreach ($data as $key => $value) {
157 4 View Code Duplication
            if ($value instanceof \stdClass) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
158 2
                $nodeExpr = $this->createObjectNode();
159 4
            } elseif (is_array($value)) {
160 2
                $nodeExpr = $this->createArrayNode();
161
            } else {
162 2
                $nodeExpr = $this->createScalarNode($value);
163
            }
164
165 4 View Code Duplication
            if ($value instanceof \stdClass) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
166 2
                $nodeExpr = $this->appendChildrenToObjectNode($value);
167 4
            } elseif (is_array($value)) {
168 2
                $nodeExpr = $this->appendChildrenToArrayNode($value);
169
            }
170
171 4
            $expr = new MethodCall($expr, 'add', [new Arg($nodeExpr)]);
172
        }
173
174 4
        return $expr;
175
    }
176
177
    /**
178
     * @param \stdClass $data
179
     *
180
     * @return Expr
181
     */
182 13
    private function appendChildrenToObjectNode(\stdClass $data)
183
    {
184 13
        $expr = $this->createObjectNode();
185
186 13
        foreach ($data as $key => $value) {
0 ignored issues
show
The expression $data of type object<stdClass> is not traversable.
Loading history...
187 13 View Code Duplication
            if ($value instanceof \stdClass) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
188 13
                $nodeExpr = $this->createObjectNode();
189 12
            } elseif (is_array($value)) {
190 3
                $nodeExpr = $this->createArrayNode();
191
            } else {
192 12
                $nodeExpr = $this->createScalarNode($value);
193
            }
194
195 13 View Code Duplication
            if ($value instanceof \stdClass) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
196 13
                $nodeExpr = $this->appendChildrenToObjectNode($value);
197 12
            } elseif (is_array($value)) {
198 3
                $nodeExpr = $this->appendChildrenToArrayNode($value);
199
            }
200
201 13
            $expr = new MethodCall($expr, 'add', [new Arg(new String_($key)), new Arg($nodeExpr)]);
202
        }
203
204 13
        return $expr;
205
    }
206
207
    /**
208
     * @param string $code
209
     *
210
     * @return string
211
     */
212 14
    private function structureCode(string $code): string
213
    {
214 14
        $lines = $this->getLinesByCode($code);
215
216 14
        $position = 0;
217
218 14
        $structuredLines = [];
219
220 14 View Code Duplication
        foreach ($lines as $i => $line) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221 14
            $lastStructuredLine = $structuredLines[count($structuredLines) - 1] ?? '';
222 14
            $this->structuredLine($line, $lastStructuredLine, $position, $structuredLines);
223
        }
224
225 14
        $structuredLines[count($structuredLines) - 1] .= ';';
226
227 14
        return implode("\n", $structuredLines);
228
    }
229
230
    /**
231
     * @param string $code
232
     *
233
     * @return array
234
     */
235 14
    private function getLinesByCode(string $code): array
236
    {
237 14
        $codeWithLinebreaks = str_replace('->add', "\n->add", substr($code, 0, -1));
238
239 14
        return explode("\n", $codeWithLinebreaks);
240
    }
241
242
    /**
243
     * @param string $line
244
     * @param string $lastStructuredLine
245
     * @param int    $position
246
     * @param array  $structuredLines
247
     */
248 14
    private function structuredLine(string $line, string $lastStructuredLine, int &$position, array &$structuredLines)
249
    {
250 14
        if (0 === strpos($line, '->add') &&
251 14
            false === strpos($lastStructuredLine, ' )') &&
252 14
            false === strpos($lastStructuredLine, 'oolNode') &&
253 14
            false === strpos($lastStructuredLine, 'loatNode') &&
254 14
            false === strpos($lastStructuredLine, 'ntNode') &&
255 14
            false === strpos($lastStructuredLine, 'ullNode') &&
256 14
            false === strpos($lastStructuredLine, 'tringNode')) {
257 14
            ++$position;
258
        }
259
260 14
        $lineLength = strlen($line);
261 14
        $braceCount = 0;
262
263 14
        while (')' === $line[--$lineLength]) {
264 14
            ++$braceCount;
265
        }
266
267 14
        $prefix = str_pad('', $position * 4);
268
269 14
        if ($braceCount > 2) {
270 13
            $structuredLines[] = $prefix.substr($line, 0, -($braceCount - 2));
271
        } else {
272 14
            $structuredLines[] = $prefix.$line;
273
        }
274
275 14
        while ($braceCount-- > 2) {
276 13
            --$position;
277 13
            $structuredLines[] = str_pad('', $position * 4).')';
278
        }
279 14
    }
280
}
281