Completed
Push — master ( 43dd7f...66a30f )
by Andrii
03:54
created

Helper::dumpClosure()   C

Complexity

Conditions 7
Paths 26

Size

Total Lines 29
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 29
ccs 0
cts 22
cp 0
rs 6.7272
cc 7
eloc 22
nc 26
nop 1
crap 56
1
<?php
2
3
namespace hiqdev\composerextensionplugin;
4
5
use Closure;
6
use ReflectionFunction;
7
8
/**
9
 * Helper class.
10
 *
11
 * @author Andrii Vasyliev <[email protected]>
12
 */
13
class Helper
14
{
15
    /**
16
     * Merges two or more arrays into one recursively.
17
     * Based on Yii2 yii\helpers\BaseArrayHelper::merge.
18
     * @param array $a array to be merged to
19
     * @param array $b array to be merged from
20
     * @return array the merged array
21
     */
22 View Code Duplication
    public static function mergeConfig($a, $b)
0 ignored issues
show
Unused Code introduced by
The parameter $a 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...
Unused Code introduced by
The parameter $b 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...
Duplication introduced by
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...
23
    {
24
        $args = func_get_args();
25
        $res = array_shift($args);
26
        foreach ($args as $items) {
27
            if (!is_array($items)) {
28
                continue;
29
            }
30
            foreach ($items as $k => $v) {
31
                if (is_int($k)) {
32
                    if (isset($res[$k])) {
33
                        $res[] = $v;
34
                    } else {
35
                        $res[$k] = $v;
36
                    }
37
                } elseif (is_array($v) && isset($res[$k]) && is_array($res[$k])) {
38
                    $res[$k] = self::mergeConfig($res[$k], $v);
39
                } else {
40
                    $res[$k] = $v;
41
                }
42
            }
43
        }
44
45
        return $res;
46
    }
47
48
    /**
49
     * Dumps closure object to string.
50
     * Based on http://www.metashock.de/2013/05/dump-source-code-of-closure-in-php/
51
     * @param Closure $c 
52
     * @return string
53
     */
54
    public static function dumpClosure(Closure $c) {
55
        $res = 'function (';
56
        $fun = new ReflectionFunction($c);
57
        $args = [];
58
        foreach($fun->getParameters() as $arg) {
59
            $str = '';
60
            if($arg->isArray()) {
61
                $str .= 'array ';
62
            } else if($arg->getClass()) {
63
                $str .= $arg->getClass()->name . ' ';
64
            }
65
            if($arg->isPassedByReference()){
66
                $str .= '&';
67
            }
68
            $str .= '$' . $arg->name;
69
            if ($arg->isOptional()) {
70
                $str .= ' = ' . var_export($arg->getDefaultValue(), true);
71
            }
72
            $args[] = $str;
73
        }
74
        $res .= implode(', ', $args);
75
        $res .= ') {' . PHP_EOL;
76
        $lines = file($fun->getFileName());
77
        for ($i = $fun->getStartLine(); $i < $fun->getEndLine(); $i++) {
78
            $res .= $lines[$i];
79
        }
80
81
        return rtrim($res, "\n ,");
82
    }
83
84
    /**
85
     * Returns a parsable string representation of given value.
86
     * In contrast to var_dump outputs Closures as PHP code.
87
     * @param mixed $value
88
     * @return string
89
     */
90
    public static function exportVar($value)
91
    {
92
        $closures = self::collectClosures($value);
93
        $res = var_export($value, true);
94
        if (!empty($closures)) {
95
            $subs = [];
96
            foreach ($closures as $key => $closure) {
97
                $subs["'" . $key . "'"] = self::dumpClosure($closure);
98
            }
99
            $res = strtr($res, $subs);
100
        }
101
102
        return $res;
103
    }
104
105
    /**
106
     * Collects closures from given input.
107
     * Substitutes closures with a tag.
108
     * @param mixed $input will be changed
109
     * @return array array of found closures
110
     */
111
    private static function collectClosures(&$input) {
112
        static $closureNo = 1;
113
        $closures = [];
114
        if (is_array($input)) {
115
            foreach ($input as &$value) {
116
                if (is_array($value) || $value instanceof Closure) {
117
                    $closures = array_merge($closures, self::collectClosures($value));
118
                }
119
            }
120
        } elseif ($input instanceof Closure) {
121
            $closureNo++;
122
            $key = "--==<<[[((Closure#$closureNo))]]>>==--";
123
            $closures[$key] = $input;
124
            $input = $key;
125
        }
126
127
        return $closures;
128
    }
129
}
130