Issues (201)

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/Util/TwoDimensionalHashMap.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
/*
4
 * This file is part of the puli/manager package.
5
 *
6
 * (c) Bernhard Schussek <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Puli\Manager\Util;
13
14
use OutOfBoundsException;
15
16
/**
17
 * An hash-map for values identified by a two-dimensional key.
18
 *
19
 * Every value in the store has a primary key and a secondary key. When adding
20
 * values to the store, both keys need to be defined. When retrieving values
21
 * from the store, you can either get the value for a composite key or all
22
 * values for the primary key indexed by their secondary keys.
23
 *
24
 * @since  1.0
25
 *
26
 * @author Bernhard Schussek <[email protected]>
27
 */
28
class TwoDimensionalHashMap
29
{
30
    /**
31
     * @var array[]
32
     */
33
    private $values = array();
34
35
    /**
36
     * Sets a value in the store.
37
     *
38
     * @param int|string $primaryKey   The primary key.
39
     * @param int|string $secondaryKey The secondary key.
40
     * @param mixed      $value        The value.
41
     */
42 146
    public function set($primaryKey, $secondaryKey, $value)
43
    {
44 146
        if (!isset($this->values[$primaryKey])) {
45 146
            $this->values[$primaryKey] = array();
46
        }
47
48 146
        $this->values[$primaryKey][$secondaryKey] = $value;
49 146
    }
50
51
    /**
52
     * Removes a value from the store.
53
     *
54
     * This method ignores non-existing keys.
55
     *
56
     * @param int|string $primaryKey   The primary key.
57
     * @param int|string $secondaryKey The secondary key.
58
     */
59 31
    public function remove($primaryKey, $secondaryKey)
60
    {
61 31
        unset($this->values[$primaryKey][$secondaryKey]);
62
63 31
        if (isset($this->values[$primaryKey]) && 0 === count($this->values[$primaryKey])) {
64 24
            unset($this->values[$primaryKey]);
65
        }
66 31
    }
67
68
    /**
69
     * Removes all values for the given primary key.
70
     *
71
     * This method ignores non-existing keys.
72
     *
73
     * @param int|string $primaryKey The primary key.
74
     */
75 1
    public function removeAll($primaryKey)
76
    {
77 1
        unset($this->values[$primaryKey]);
78 1
    }
79
80
    /**
81
     * Returns a value from the store.
82
     *
83
     * @param int|string $primaryKey   The primary key.
84
     * @param int|string $secondaryKey The secondary key.
85
     *
86
     * @return mixed The value.
87
     *
88
     * @throws OutOfBoundsException If no value is set for the given keys.
89
     */
90 44
    public function get($primaryKey, $secondaryKey)
91
    {
92 44 View Code Duplication
        if (!isset($this->values[$primaryKey][$secondaryKey])) {
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...
93 1
            throw new OutOfBoundsException(sprintf(
94 1
                'The key ("%s","%s") does not exist.',
95
                $primaryKey,
96
                $secondaryKey
97
            ));
98
        }
99
100 43
        return $this->values[$primaryKey][$secondaryKey];
101
    }
102
103
    /**
104
     * Returns whether the store contains the given key(s).
105
     *
106
     * The secondary key is optional. If you don't pass it, this method returns
107
     * `true` if the store contains the given primary key with any secondary
108
     * key.
109
     *
110
     * @param int|string      $primaryKey   The primary key.
111
     * @param int|string|null $secondaryKey The secondary key.
112
     *
113
     * @return bool Returns `true` if the store contains the given key(s).
114
     */
115 107
    public function contains($primaryKey, $secondaryKey = null)
116
    {
117 107
        if (null !== $secondaryKey) {
118 99
            return isset($this->values[$primaryKey][$secondaryKey]);
119
        }
120
121 86
        return isset($this->values[$primaryKey]);
122
    }
123
124
    /**
125
     * Returns the first value set for the given primary key.
126
     *
127
     * @param int|string $primaryKey The primary key.
128
     *
129
     * @return mixed The value.
130
     *
131
     * @throws OutOfBoundsException If the primary key does not exist.
132
     */
133 49 View Code Duplication
    public function getFirst($primaryKey)
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...
134
    {
135 49
        if (!isset($this->values[$primaryKey])) {
136 1
            throw new OutOfBoundsException(sprintf(
137 1
                'The key "%s" does not exist.',
138
                $primaryKey
139
            ));
140
        }
141
142 48
        return reset($this->values[$primaryKey]);
143
    }
144
145
    /**
146
     * Returns the last value set for the given primary key.
147
     *
148
     * @param int|string $primaryKey The primary key.
149
     *
150
     * @return mixed The value.
151
     *
152
     * @throws OutOfBoundsException If the primary key does not exist.
153
     */
154 2 View Code Duplication
    public function getLast($primaryKey)
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...
155
    {
156 2
        if (!isset($this->values[$primaryKey])) {
157 1
            throw new OutOfBoundsException(sprintf(
158 1
                'The key "%s" does not exist.',
159
                $primaryKey
160
            ));
161
        }
162
163 1
        return end($this->values[$primaryKey]);
164
    }
165
166
    /**
167
     * Returns the number of secondary keys set for the given primary key.
168
     *
169
     * @param int|string $primaryKey The primary key.
170
     *
171
     * @return int The number of secondary keys set for the primary key.
172
     *
173
     * @throws OutOfBoundsException If the primary key does not exist.
174
     */
175 3 View Code Duplication
    public function getCount($primaryKey)
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...
176
    {
177 3
        if (!isset($this->values[$primaryKey])) {
178 1
            throw new OutOfBoundsException(sprintf(
179 1
                'The key "%s" does not exist.',
180
                $primaryKey
181
            ));
182
        }
183
184 2
        return count($this->values[$primaryKey]);
185
    }
186
187
    /**
188
     * Returns all values set for the given primary key.
189
     *
190
     * @param int|string $primaryKey The primary key.
191
     *
192
     * @return array The values indexed by their secondary keys.
193
     *
194
     * @throws OutOfBoundsException If the primary key does not exist.
195
     */
196 78 View Code Duplication
    public function listByPrimaryKey($primaryKey)
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...
197
    {
198 78
        if (!isset($this->values[$primaryKey])) {
199 3
            throw new OutOfBoundsException(sprintf(
200 3
                'The key "%s" does not exist.',
201
                $primaryKey
202
            ));
203
        }
204
205 75
        return $this->values[$primaryKey];
206
    }
207
208
    /**
209
     * Returns all values set for the given secondary key.
210
     *
211
     * @param int|string $secondaryKey The secondary key.
212
     *
213
     * @return array The values indexed by their primary keys.
214
     *
215
     * @throws OutOfBoundsException If the secondary key does not exist.
216
     */
217 13
    public function listBySecondaryKey($secondaryKey)
218
    {
219 13
        $list = array();
220
221 13
        foreach ($this->values as $primaryKey => $valuesBySecondaryKey) {
222 13
            if (isset($valuesBySecondaryKey[$secondaryKey])) {
223 13
                $list[$primaryKey] = $valuesBySecondaryKey[$secondaryKey];
224
            }
225
        }
226
227 13
        if (!$list) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $list of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
228
            throw new OutOfBoundsException(sprintf(
229
                'The key "%s" does not exist.',
230
                $secondaryKey
231
            ));
232
        }
233
234 13
        return $list;
235
    }
236
237
    /**
238
     * Returns the secondary keys for the given primary key.
239
     *
240
     * The primary key is optional. If this argument is not provided, all secondary keys will be returned.
241
     *
242
     * @param int|string|null $primaryKey The primary key.
243
     *
244
     * @return int[]|string[] The secondary keys.
245
     *
246
     * @throws OutOfBoundsException If the primary key does not exist.
247
     */
248 31
    public function getSecondaryKeys($primaryKey = null)
249
    {
250 31 View Code Duplication
        if ($primaryKey) {
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...
251 17
            if (!isset($this->values[$primaryKey])) {
252 1
                throw new OutOfBoundsException(sprintf(
253 1
                    'The key "%s" does not exist.',
254
                    $primaryKey
255
                ));
256
            }
257
258 16
            return array_keys($this->values[$primaryKey]);
259
        }
260
261 14
        $allSecondaryKeys = array();
262
263 14
        foreach ($this->values as $primaryKey => $valuesBySecondaryKey) {
264 13
            foreach ($valuesBySecondaryKey as $secondaryKey => $values) {
265 13
                $allSecondaryKeys[$secondaryKey] = true;
266
            }
267
        }
268
269 14
        return array_keys($allSecondaryKeys);
270
    }
271
272
    /**
273
     * Returns all primary keys.
274
     *
275
     * @return int[]|string[] The primary keys.
0 ignored issues
show
Consider making the return type a bit more specific; maybe use integer[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
276
     */
277 88
    public function getPrimaryKeys()
278
    {
279 88
        return array_keys($this->values);
280
    }
281
282
    /**
283
     * Returns the contents of the store as array.
284
     *
285
     * @return array[] A multi-dimensional array containing all values by
286
     *                 their primary and secondary keys.
287
     */
288 54
    public function toArray()
289
    {
290 54
        return $this->values;
291
    }
292
293
    /**
294
     * Returns whether the map is empty.
295
     *
296
     * @return bool Returns `true` if the map is empty and `false` otherwise.
297
     */
298 4
    public function isEmpty()
299
    {
300 4
        return 0 === count($this->values);
301
    }
302
303
    /**
304
     * Sorts the primary keys of the map.
305
     *
306
     * @param int[]|string[]|null $order The keys in the desired order.
0 ignored issues
show
Consider making the type for parameter $order a bit more specific; maybe use null|integer[].
Loading history...
307
     */
308 2
    public function sortPrimaryKeys(array $order = null)
309
    {
310 2
        if (!$order) {
311 1
            ksort($this->values);
312
313 1
            return;
314
        }
315
316 1
        $orderedKeys = array_intersect_key(array_flip($order), $this->values);
317
318 1
        $this->values = array_replace($orderedKeys, $this->values);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_replace($orderedKeys, $this->values) of type array is incompatible with the declared type array<integer,array> of property $values.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
319 1
    }
320
321
    /**
322
     * Sorts the secondary keys of a map entry.
323
     *
324
     * @param int|string          $primaryKey The primary key.
325
     * @param int[]|string[]|null $order      The keys in the desired order.
0 ignored issues
show
Consider making the type for parameter $order a bit more specific; maybe use null|integer[].
Loading history...
326
     */
327 3
    public function sortSecondaryKeys($primaryKey, array $order = null)
328
    {
329 3
        if (!isset($this->values[$primaryKey])) {
330 1
            throw new OutOfBoundsException(sprintf(
331 1
                'The key "%s" does not exist.',
332
                $primaryKey
333
            ));
334
        }
335
336 2
        if (!$order) {
337 1
            ksort($this->values[$primaryKey]);
338
339 1
            return;
340
        }
341
342 1
        $orderedKeys = array_intersect_key(array_flip($order), $this->values[$primaryKey]);
343
344 1
        $this->values[$primaryKey] = array_replace($orderedKeys, $this->values[$primaryKey]);
345 1
    }
346
}
347