Issues (55)

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/Collection.php (2 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
namespace Spindle\Collection;
3
4
class Collection implements \IteratorAggregate
5
{
6
    use Traits\SortTrait;
7
    use Traits\SetsTrait;
8
    use Traits\TerminateTrait;
9
    use Traits\LimitTrait;
10
    use Traits\TransformTrait;
11
12
    const TYPE_FOR = 'for';
13
    const TYPE_FOREACH = 'foreach';
14
15
    private $type = self::TYPE_FOREACH;
16
    private $debug = false;
17
18
    private $ops = [];
19
    private $seed;
20
    private $is_array;
21
    private $vars = [];
22
    private $fn_cnt = 0;
23
24
    /**
25
     * @return \Spindle\Collection
26
     */
27 10
    public static function from($iterable, $debug = null)
28
    {
29 10
        return new static($iterable, $debug);
30
    }
31
32
    /**
33
     * Generator-based range()
34
     * @param int|string $start
35
     * @param int|string $end
36
     * @param int $step
37
     * @param bool $debug
38
     * @return \Spindle\Collection
39
     */
40 23
    public static function range($start, $end, $step = 1, $debug = null)
41
    {
42 23
        if (!is_int($step) || $step < 1) {
43 1
            throw new \InvalidArgumentException('$step must be natural number: ' . $step);
44
        }
45 22
        if (is_numeric($start) && is_numeric($end)) {
46
            $seed = [
47 22
                '$_current = ' . $start,
48 22
                '$_current <= ' . $end,
49 22
                $step === 1 ? '++$_current' : '$_current += ' . $step,
50 22
            ];
51 22
        } else {
52
            $seed = [
53 1
                '$_current = ' . var_export($start, 1),
54 1
                '$_current <= ' . var_export($end, 1),
55 1
                implode(',', array_fill(0, $step, '++$_current')),
56 1
            ];
57
        }
58 22
        return new static($seed, $debug, self::TYPE_FOR);
59
    }
60
61
    /**
62
     * Generator-based repeat()
63
     * @param mixed $elem
64
     * @param int $count
65
     * @param bool $debug
66
     */
67 2
    public static function repeat($elem, $count, $debug = null)
68
    {
69 2
        if (!is_int($count) || $count < 0) {
70 1
            throw new \InvalidArgumentException('$count must be int >= 0. given: ' . gettype($count));
71
        }
72
        $seed = [
73 1
            '$_current = $_elem, $_count = ' . var_export($count, 1),
74 1
            '$_count > 0',
75
            '--$_count'
76 1
        ];
77 1
        $collection = new static($seed, $debug, self::TYPE_FOR);
78 1
        $collection->vars['_elem'] = $elem;
79 1
        return $collection;
80
    }
81
82
    /**
83
     * @param iterable $seed
84
     */
85 32
    public function __construct($seed, $debug = null, $type = null)
86
    {
87 32
        if (!is_array($seed) && !is_object($seed)) {
88 1
            throw new \InvalidArgumentException('$seed should be iterable, given ' . gettype($seed));
89
        }
90 31
        $this->seed = $seed;
91 31
        if ($debug) {
92 1
            $this->debug = true;
93 1
        }
94 31
        if ($type === self::TYPE_FOR) {
95 23
            $this->type = $type;
96 23
            $this->is_array = false;
97 23
            return;
98
        }
99 16
        $this->is_array = is_array($seed);
100 16
    }
101
102 17
    private function step()
0 ignored issues
show
This method is not used, and could be removed.
Loading history...
103
    {
104 17
        if ($this->debug) {
105 1
            $this->toArray();
106 1
            return $this;
107
        }
108 16
        return $this;
109
    }
110
111
    /**
112
     * @return \Generator|\ArrayIterator
113
     */
114 1
    public function getIterator()
115
    {
116 1
        if ($this->is_array) {
117 1
            return new \ArrayIterator($this->seed);
118
        }
119 1
        $ops = $this->ops;
120 1
        $ops[] = 'yield $_key => $_;';
121 1
        $gen = self::evaluate(
122 1
            $this->seed,
123 1
            $this->vars,
124 1
            $this->compile($ops),
125 1
            '$_result = static function() use($_seed){',
126
            '};'
127 1
        );
128 1
        return $gen();
129
    }
130
131
    /**
132
     * @return array
133
     */
134 19
    public function toArray()
135
    {
136 19
        if ($this->is_array) {
137 10
            return $this->seed;
138
        }
139 15
        $ops = $this->ops;
140 15
        $ops[] = '    $_result[$_key] = $_;';
141 15
        $array = self::evaluate(
142 15
            $this->seed,
143 15
            $this->vars,
144 15
            $this->compile($ops),
145 15
            '$_result = [];',
146
            ''
147 15
        );
148 15
        $this->type = self::TYPE_FOREACH;
149 15
        $this->is_array = true;
150 15
        $this->ops = [];
151 15
        $this->seed = $array;
152 15
        $this->vars = [];
153 15
        $this->fn_cnt = 0;
154 15
        return $array;
155
    }
156
157
    /**
158
     * @return $this
159
     */
160 1
    public function dump()
161
    {
162 1
        var_dump($this);
163 1
        return $this;
164
    }
165
166
    /**
167
     * @return $this
168
     */
169 1
    public function assignTo(&$var = null)
170
    {
171 1
        $var = $this;
172 1
        return $this;
173
    }
174
175
    /**
176
     * @return $this
177
     */
178 4
    public function assignArrayTo(&$var = null)
179
    {
180 4
        $var = $this->toArray();
181 4
        return $this;
182
    }
183
184
    /**
185
     * @return string
186
     */
187 1
    public function __toString()
188
    {
189 1
        return implode("\n", [
190 1
            static::class,
191 1
            ' array-mode:' . (int)$this->is_array,
192 1
            " codes:\n  " . implode("\n  ", $this->ops)
193 1
        ]);
194
    }
195
196
    /**
197
     * @return array
198
     */
199 1
    public function __debugInfo()
200
    {
201 1
        if (is_array($this->seed)) {
202 1
            $cnt = count($this->seed);
203 1
            if ($cnt === 0) {
204 1
                $seed = "empty array()";
205 1
            } else {
206 1
                $first = gettype(current($this->seed));
207 1
                $seed = "array($first, ...($cnt items))";
208
            }
209 1
        } else {
210 1
            $seed = get_class($this->seed);
211
        }
212
        return [
213 1
            'seed' => $seed,
214 1
            'code' => $this->compile($this->ops),
215 1
        ];
216
    }
217
218
    private static function evaluate($_seed, $_vars, $_code, $_before, $_after)
0 ignored issues
show
The parameter $_seed is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
219
    {
220 24
        set_error_handler(function($severity, $message, $file, $line){
221 1
            throw new \ErrorException($message, 0, $severity, $file, $line);
222 24
        }, E_ALL ^ E_DEPRECATED ^ E_USER_DEPRECATED);
223
        try {
224 24
            $_result = null;
225 24
            extract($_vars);
226 24
            eval("$_before \n $_code \n $_after");
227 24
        } catch (\ParseError $e) {
228
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
229 24
        } finally {
230 24
            restore_error_handler();
231
        }
232 24
        return $_result;
233
    }
234
235 25
    private function compile($ops)
236
    {
237 25
        if ($this->type === self::TYPE_FOR) {
238 20
            return $this->compileFor($ops, $this->seed);
239
        }
240
241 10
        return $this->compileForeach($ops);
242
    }
243
244 20
    private static function compileFor($ops, $seed)
245
    {
246 20
        array_unshift(
247 20
            $ops,
248 20
            '$_i = 0;',
249 20
            'for (' . implode('; ', $seed). ') {',
250 20
            '    $_key = $_i;',
251 20
            '    $_ = $_current;',
252
            '    ++$_i;'
253 20
        );
254 20
        $ops[] = '}';
255
256 20
        return implode("\n", $ops);
257
    }
258
259 10
    private static function compileForeach($ops)
260
    {
261 10
        array_unshift(
262 10
            $ops,
263 10
            '$_i = 0;',
264 10
            'foreach ($_seed as $_key => $_) {',
265
            '    ++$_i;'
266 10
        );
267 10
        $ops[] = '}';
268
269 10
        return implode("\n", $ops);
270
    }
271
}
272