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