Issues (19)

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/tree.php (8 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 Ariadne Component Library.
5
 *
6
 * (c) Muze <[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 arc;
13
14
/**
15
 *	Utility methods to handle common path related tasks, cleaning, changing relative to absolute, etc.
16
 */
17
class tree
18
{
19
    /**
20
     * Create a simple array from a tree. Each non-null nodeValue will be added with the path to its node as the key
21
     * @param  \arc\tree\Node $node
22
     * @param  string         $root
23
     * @param  string         $nodeName
24
     * @return array          [ $path => $data, ... ]
25
     */
26 10
    public static function collapse($node, $root = '', $nodeName = 'nodeName')
27
    {
28 10
        return \arc\tree::map(
29 10
            $node,
30 10
            function ($child) {
31 10
                return $child->nodeValue;
32 10
            },
33
            $root,
34
            $nodeName
35
        );
36
    }
37
38
    /**
39
     * Creates a NamedNode tree from an array with path => nodeValue entries.
40
     * @param  array               $tree The collapsed tree: [ $path => $data, ... ]
41
     * @return \arc\tree\NamedNode an object tree with parent/children relations
42
     */
43 16
    public static function expand($tree = null)
44
    {
45 16
        if (is_object( $tree ) && isset( $tree->childNodes )) {
46
            return $tree; //FIXME: should we clone the tree to avoid shared state?
47
        }
48 16
        $root = new \arc\tree\NamedNode();
49 16
        if (!is_array($tree)) {
50 12
            return $root; // empty tree
51
        }
52 4
        $previousParent = $root;
53 4
        foreach ($tree as $path => $data) {
54 4
            $previousPath = $previousParent->getPath();
55 4
            $subPath = \arc\path::diff( $previousPath, $path );
56 4
            if ($subPath) {
57
                // create missing parent nodes, input tree may be sparsely filled
58 4
                $node = \arc\path::reduce(
59 4
                    $subPath,
60 4
                    function ($previous, $name) {
61 4
                        if ($name == '..') {
62 4
                            return $previous->parentNode;
63
                        }
64
65 4
                        return $previous->appendChild( $name );
66 4
                    },
67 4
                    $previousParent
68
                );
69
            } else {
70
                // means the previousParent is equal to the current path, e.g. the root
71
                $node = $previousParent;
72
            }
73 4
            $node->nodeValue = $data;
74 4
            $previousParent = $node;
75
        }
76
77 4
        return $root;
78
    }
79
80
    /**
81
     * Calls the first callback method on each successive parent until a non-null value is returned. Then
82
     * calls all the parents from that point back to this node with the second callback in reverse order.
83
     * The first callback (dive) must accept one parameter, the node.
84
     * The second callback (rise) must accept two parameters, the nde and the result up to that point.
85
     * @param  \arc\tree\Node $node         A tree node, must have traversable childNodes property and a parentNode property
86
     * @param  callable       $diveCallback The callback for the dive phase.
87
     * @param  callable       $riseCallback The callback for the rise phase.
88
     * @return mixed
89
     */
90 8
    public static function dive($node, $diveCallback = null, $riseCallback = null)
91
    {
92 8
        $result = null;
93 8
        if (is_callable( $diveCallback )) {
94 6
            $result = call_user_func( $diveCallback, $node );
95
        }
96 8
        if (!isset( $result ) && $node->parentNode) {
97 4
            $result = \arc\tree::dive( $node->parentNode, $diveCallback, $riseCallback );
0 ignored issues
show
The property parentNode does not seem to exist in arc\tree\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
98
        }
99 8
        if (is_callable( $riseCallback )) {
100 4
            return call_user_func( $riseCallback, $node, $result );
101
        } else {
102 6
            return $result;
103
        }
104
    }
105
106
    /**
107
     * Calls the callback method on each parent of the given node, starting at the root.
108
     * @param  \arc\tree\Node $node     A tree node, must have traversable childNodes property and a parentNode property
109
     * @param  callable       $callback The callback function applied to each parent.
110
     * @return mixed
111
     */
112 4
    public static function parents($node, $callback = null)
113
    {
114 4
        if (!isset( $callback )) {
115
            $callback = function ($node, $result) {
116
                return ( (array) $result ) + array( $node );
117
            };
118
        }
119
120 4
        return self::dive( $node, null, $callback );
121
    }
122
123
    /**
124
     * Calls the callback method on each of the direct child nodes of the given node.
125
     * @param  \arc\tree\Node $node
126
     * @param  callable       $callback The callback function applied to each child node
127
     * @param  mixed          $nodeName The name of the 'name' property or a function that returns the name of a node.
128
     * @return array
129
     */
130 View Code Duplication
    public static function ls($node, $callback, $nodeName = 'nodeName')
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...
131
    {
132
        $result = [];
133
        foreach ($node->childNodes as $child) {
0 ignored issues
show
The property childNodes does not seem to exist in arc\tree\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
134
            $name = self::getNodeName( $child, $nodeName );
135
            $result[ $name ] = call_user_func( $callback, $child );
136
        }
137
138
        return $result;
139
    }
140
141
    /**
142
     * Calls the callback method on each child of the current node, including the node itself, until a non-null
143
     * result is returned. Returns that result. The tree is searched depth first.
144
     * @param  \arc\tree\Node $node
145
     * @param  callable       $callback The callback function applied to each child node
146
     * @return mixed
147
     */
148
    public static function search($node, $callback)
149
    {
150
        $result = call_user_func( $callback, $node );
151
        if (isset( $result )) {
152
            return $result;
153
        }
154
        foreach ($node->childNodes as $child) {
0 ignored issues
show
The property childNodes does not seem to exist in arc\tree\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
155
            $result = self::search( $child, $callback );
156
            if (isset( $result )) {
157
                return $result;
158
            }
159
        }
160
161
        return null;
162
    }
163
164
    /**
165
     * Calls the callback method on each child of the current node, including the node itself. Any non-null result
166
     * is added to the result array, with the path to the node as the key.
167
     * @param  \arc\tree\Node $node
168
     * @param  callable       $callback The callback function applied to each child node
169
     * @param  string         $root
170
     * @param  mixed          $nodeName The name of the 'name' property or a function that returns the name of a node.
171
     * @return array
172
     */
173 10
    public static function map($node, $callback, $root = '', $nodeName = 'nodeName')
174
    {
175 10
        $result = [];
176 10
        $name = self::getNodeName( $node, $nodeName );
177 10
        $path = $root . $name . '/';
178 10
        $callbackResult = call_user_func( $callback, $node );
179 10
        if (isset($callbackResult)) {
180 10
            $result[ $path ] = $callbackResult;
181
        }
182 10
        foreach ($node->childNodes as $child) {
0 ignored issues
show
The property childNodes does not seem to exist in arc\tree\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
183 10
            $result += self::map( $child, $callback, $path, $nodeName );
184
        }
185
186 10
        return $result;
187
    }
188
189
    /**
190
     * Calls the callback method on all child nodes of the given node, including the node itself. The result of each
191
     * call is passed on as the first argument to each succesive call.
192
     * @param  \arc\tree\Node $node
193
     * @param  callable       $callback
194
     * @param  mixed          $initial  The value to pass to the first callback call.
195
     * @return mixed
196
     */
197 View Code Duplication
    public static function reduce($node, $callback, $initial = null)
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...
198
    {
199
        $result = call_user_func( $callback, $initial, $node );
200
        foreach ($node->childNodes as $child) {
0 ignored issues
show
The property childNodes does not seem to exist in arc\tree\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
201
            $result = self::reduce( $child, $callback, $result );
202
        }
203
204
        return $result;
205
    }
206
207
    /**
208
     * Filters the tree using a callback method. If the callback method returns true, the node's value is included
209
     * in the result, otherwise it is skipped. Filter returns a collapsed tree: [ path => nodeValue ]
210
     * The callback method must take one argument: the current node.
211
     * @param  \arc\tree\Node $node
212
     * @param  callable       $callback
213
     * @return array
214
     */
215
    public static function filter($node, $callback, $root = '', $nodeName = 'nodeName')
216
    {
217
        return self::map( $node, function ($node) use ($callback) {
218
            if (call_user_func( $callback, $node )) {
219
                return $node->nodeValue;
220
            }
221
        }, $root, $nodeName );
222
    }
223
224
    /**
225
     * Sorts the childNodes list of the node, recursively.
226
     * @param  \arc\tree\Node   $node
227
     * @param  callable         $callback
228
     * @param  mixed            $nodeName
229
     * @throws UnknownError
230
     */
231
    public static function sort($node, $callback, $nodeName = 'nodeName')
232
    {
233
        if (is_array($node->childNodes)) {
234
            $sort = function ($node) use ($callback) {
235
                uasort( $node->childNodes, $callback );
236
            };
237
        } elseif ($node->childNodes instanceof \ArrayObject) {
0 ignored issues
show
The property childNodes does not seem to exist in arc\tree\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
238
            $sort = function ($node) use ($callback) {
239
                $node->childNodes->uasort( $callback );
240
            };
241
        } else {
242
            throw new \arc\UnknownError( 'Cannot sort this tree - no suitable sort method found',
243
                \arc\exceptions::OBJECT_NOT_FOUND);
244
        }
245
        self::map( $node, $sort, '', $nodeName );
246
    }
247
248 10
    private static function getNodeName($node, $nodeName)
249
    {
250 10
        if (is_callable($nodeName)) {
251
            $name = call_user_func( $nodeName, $node );
252
        } else {
253 10
            $name = $node->{$nodeName};
254
        }
255
256 10
        return $name;
257
    }
258
}
259