Completed
Push — master ( 864f8b...c13991 )
by Andrii
06:22
created

Helper::exportDefines()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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