Completed
Pull Request — master (#9)
by Arnold
10:19
created

functions.php ➔ _merge_args()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 3
dl 0
loc 13
ccs 1
cts 1
cp 1
crap 4
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
namespace Cypress\Curry;
4
5
use Cypress\Curry\Placeholder;
6
7
/**
8
 * @param callable $callable
9
 * @return callable
10
 */
11
function curry($callable)
12
{
13 9
    if (_number_of_required_params($callable) === 0) {
14 9
        return _make_function($callable);
15 7
    }
16
    if (_number_of_required_params($callable) === 1) {
17
        return _curry_array_args($callable, _rest(func_get_args()));
18
    }
19
20
    return _curry_array_args($callable, _rest(func_get_args()));
21
}
22
23
/**
24
 * @param $callable
25
 * @param array $args pass the arguments to be curried as an array
26 2
 *
27
 * @return callable
28
 */
29
function curry_args($callable, array $args)
30
{
31
    return _curry_array_args($callable, $args);
32
}
33
34
/**
35 4
 * @param callable $callable
36 4
 * @return callable
37 4
 */
38
function curry_right($callable)
39
{
40
    if (_number_of_required_params($callable) < 2)
41
        return _make_function($callable);
42
    return _curry_array_args($callable, _rest(func_get_args()), false);
43
}
44
45
/**
46
 * @param callable $callable
47
 * @param array $args pass the arguments to be curried as an array
48 3
 *
49
 * @return callable
50
 */
51
function curry_right_args($callable, array $args)
52
{
53
    return _curry_array_args($callable, $args, false);
54
}
55
56
/**
57
 * @param callable $callable
58
 * @param $args
59
 * @param bool $left
60 15
 * @return callable
61 4
 */
62
function _curry_array_args($callable, $args, $left = true)
63 11
{
64 11
    return function () use ($callable, $args, $left) {
65 11
        $newArgs = _merge_args($args, func_get_args(), $left);
66
67 6
        if (_is_fullfilled($callable, $newArgs)) {
68 15
            return _execute($callable, $newArgs, $left);
69
        }
70
        return _curry_array_args($callable, $newArgs, $left);
71
    };
72
}
73
74
/**
75
 * @internal
76
 * @param $callable
77
 * @param $args
78
 * @param $left
79
 * @return mixed
80 15
 */
81 7
function _execute($callable, $args, $left)
82 7
{
83
    if (! $left) {
84 15
        $args = array_reverse($args);
85 15
    }
86 1
87 1
    $n = _number_of_required_params($callable);
88
89
    if (count($args) > $n) {
90
        $extra = array_splice($args, $left ? $n : 0, count($args) - $n);
91
        $args = array_merge($args, $left ? $extra : array_reverse($extra));
92
    }
93 1
94 1
    return call_user_func_array($callable, $args);
95 1
}
96 1
97 1
/**
98
 * @internal
99 15
 * @param array $args
100
 * @return array
101
 */
102
function _rest(array $args)
103
{
104
    return array_slice($args, 1);
105
}
106
107
/**
108
 * @internal
109 11
 * @param callable $callable
110
 * @param $args
111
 * @return bool
112
 */
113
function _is_fullfilled($callable, $args)
114
{
115
    return count($args) >= _number_of_required_params($callable) &&
116
        !in_array(Placeholder::get(), $args, true);
117
}
118
119
/**
120
 * @internal
121 20
 * @param $callable
122 22
 * @return int
123 22
 */
124
function _number_of_required_params($callable)
125
{
126
    if (is_array($callable)) {
127
        $refl = new \ReflectionClass($callable[0]);
128
        $method = $refl->getMethod($callable[1]);
129
        return $method->getNumberOfRequiredParameters();
130
    }
131
    $refl = new \ReflectionFunction($callable);
132
    return $refl->getNumberOfRequiredParameters();
133 24
}
134 16
135 16
/**
136 16
 * if the callback is an array(instance, method), 
137
 * it returns an equivalent function for PHP 5.3 compatibility.
138 8
 *
139 8
 * @internal 
140
 * @param  callable $callable
141
 * @return callable
142
 */
143
function _make_function($callable)
144
{
145
    if (is_array($callable))
146
        return function() use($callable) {
147
            return call_user_func_array($callable, func_get_args());
148
        };
149
    return $callable;
150
}
151
152 3
/**
153
 * Checks if an argument is a placeholder.
154 1
 *
155 1
 * @internal
156 2
 * @param  mixed  $arg
157
 * @return boolean
158
 */
159
function _is_placeholder($arg)
160
{
161
    return $arg instanceof Placeholder;
162
}
163
164
/**
165
 * Merge arguments, replacing placeholders
166
 */
167
function _merge_args($args, $newArgs, $left = true)
0 ignored issues
show
Unused Code introduced by
The parameter $left 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...
168 20
{
169
    foreach ($args as &$arg) {
170
        if (!_is_placeholder($arg))
171
            continue;
172
173
        $arg = array_shift($newArgs);
174
        if (empty($newArgs))
175
            break;
176
    }
177
178
    return array_merge($args, $newArgs);
179
}
180 15
181
/**
182
 * Gets a special placeholder value used to specify "gaps" within curried 
183
 * functions, allowing partial application of any combination of arguments, 
184
 * regardless of their positions. Should be used only for required arguments.
185
 * When used, optional arguments must be at the end of the arguments list.
186
 *
187
 * @return Cypress\Curry\Placeholder
188
 */
189
function __()
190
{
191
    return Placeholder::get();
192
}
193