Completed
Pull Request — master (#49)
by Luke
04:47 queued 02:21
created

functions.php ➔ to_array()   D

Complexity

Conditions 10
Paths 14

Size

Total Lines 38
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 13.2767

Importance

Changes 0
Metric Value
cc 10
eloc 23
nc 14
nop 2
dl 0
loc 38
ccs 17
cts 25
cp 0.68
crap 13.2767
rs 4.8196
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * Nozavroni/Collections
4
 * Just another collections library for PHP5.6+.
5
 *
6
 * @copyright Copyright (c) 2016 Luke Visinoni <[email protected]>
7
 * @author    Luke Visinoni <[email protected]>
8
 * @license   https://github.com/nozavroni/collections/blob/master/LICENSE The MIT License (MIT)
9
 */
10
namespace Noz;
11
12
use Closure;
13
use InvalidArgumentException;
14
use Iterator;
15
use Noz\Collection\Collection;
16
use Noz\Contracts\CollectionInterface;
17
use Traversable;
18
19
/**
20
 * Collection factory.
21
 *
22
 * Simply an alias to (new Collection($in)). Allows for a little more concise and
23
 * simpler instantiation of a collection. Also I plan to eventually support
24
 * additional input types that will make this function more flexible and forgiving
25
 * than simply instantiating a Collection object, but for now the two are identical.
26
 *
27
 * @param array|Iterator $data Either an array or an iterator of data
28
 *
29
 * @return CollectionInterface
0 ignored issues
show
Documentation introduced by
Should the return type not be Illuminate\Support\Collection?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
30
 */
31
function collect($data = null)
32
{
33 42
    return Collection::factory($data);
34
}
35
36
/**
37
 * Invoke a callable and return result.
38
 *
39
 * Pass in a callable followed by whatever arguments you want passed to
40
 * it and this function will invoke it with your arguments and return
41
 * the result.
42
 *
43
 * @param callable $callback The callback function to invoke
44
 * @param array ...$args     The args to pass to your callable
45
 *
46
 * @return mixed The result of your invoked callable
47
 */
48
function invoke(callable $callback, ...$args)
49
{
50 7
    return call_user_func($callback, ...$args);
51
}
52
53
/**
54
 * Underscore function.
55
56
 * This function is meant to work sort of like jQuery's "$()". It is a contextual catch-all type function. It works
57
 * as a short-hand alias for invoke, collect, and with.
58
59
 * @param callable|mixed    $in
60
 * @param mixed ...         $_
61
 *
62
 * @return mixed|CollectionInterface
63
 */
64
function _($in, ...$args)
65
{
66 3
    if (is_callable($in)) {
67 3
        return invoke($in, ...$args);
68
    }
69
    if (is_traversable($in)) {
70
        return collect($in);
71
    }
72
    return $in;
73
}
74
75
/**
76
 * Determine if data is traversable.
77
 *
78
 * Pass in any variable and this function will tell you whether or not it
79
 * is traversable. Basically this just means that it is either an array or an iterator.
80
 * This function was written simply because I was tired of if statements that checked
81
 * whether a variable was an array or a descendant of \Iterator. So I wrote this guy.
82
 *
83
 * @param mixed $data The variable to determine traversability
84
 *
85
 * @return bool True if $input is an array or an Iterator
86
 */
87
function is_traversable($data)
88
{
89 62
    return is_array($data) || $data instanceof Traversable;
90
}
91
92
/**
93
 * Can data be converted to an array?
94
 *
95
 * @param mixed $data The data to check
96
 *
97
 * @return bool
98
 */
99
function is_arrayable($data)
100
{
101 38
    if (!is_array($data)) {
102 35
        if (is_object($data)) {
103
            return (
104 3
                method_exists($data, 'toArray') ||
105
                $data instanceof Traversable
106 3
            );
107
        }
108 35
        return false;
109
    }
110 8
    return true;
111
}
112
113
/**
114
 * Convert any traversable to an array.
115
 *
116
 * @todo I'm not sure if this function is necessary or not. Does iterator_to_array do everything this can do?
117
 *
118
 * @param Traversable $data Traversable data
119
 *
120
 * @return array
121
 */
122
function traversable_to_array(Traversable $data)
123
{
124
    $arr = [];
125
    foreach ($data as $key => $val) {
126
        $arr[$key] = $val;
127
    }
128
    return $arr;
129
}
130
131
/**
132
 * Convert data to an array.
133
 *
134
 * Accepts any kind of data and converts it to an array. If strict mode is on, only data that returns true from
135
 * is_arrayable() will be converted to an array. Anything else will cause an InvalidArgumentException to be thrown.
136
137
 * @param mixed $data   Data to convert to array
138
 * @param bool  $strict Whether to use strict mode
139
140
 * @return array
141
 *
142
 * @throws InvalidArgumentException
143
 */
144
function to_array($data, $strict = true)
145
{
146 8
    if (is_arrayable($data)) {
147 8
        if (is_array($data)) {
148 7
            return $data;
149
        }
150
        // this is what makes toArray() work recursively
151
        // it must stay right where it is do not move it
152 2
        if (method_exists($data, 'toArray')) {
153 2
            return $data->toArray();
154
        }
155 1
        if ($data instanceof Iterator) {
156 1
            return iterator_to_array($data);
157
        }
158
        // @todo I don't think this will EVER be called...
159
        if ($data instanceof Traversable) {
160
            return traversable_to_array($data);
161
        }
162
    }
163 1
    if ($strict) {
164
        throw new InvalidArgumentException(sprintf(
165
            'Invalid argument for "%s". Cannot convert "%s" to an array.',
166
            __FUNCTION__,
167
            typeof($data)
168
        ));
169
    }
170 1
    if (is_object($data)) {
171 1
        $values = [];
172 1
        foreach ($data as $key => $val) {
173 1
            $values[$key] = $val;
174 1
        }
175 1
        return $values;
176
    }
177 1
    if (is_null($data)) {
178 1
        return [];
179
    }
180 1
    return [$data];
181
}
182
183
/**
184
 * Get data type.
185
 *
186
 * Inspects data to determine its type.
187
 *
188
 * @param mixed  $data       The data to check
189
 * @param bool   $meta       Whether to include meta data such as length/size
190
// * @param string $returnType What type of value to return (array or string)
0 ignored issues
show
Bug introduced by
There is no parameter named $returnType. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
191
 *
192
 * @return string
193
 */
194
function typeof($data, $meta = true/*, $returnType = 'string'*/)
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
195
{
196 3
    $type = gettype($data);
197 3
    if ($meta) {
198
        switch($type) {
199 3
            case 'object':
200 1
                $class = get_class($data);
201 1
                return "{$type} <{$class}>";
202 3
            case 'resource':
203 1
                $restype = get_resource_type($data);
204 1
                return "{$type} <{$restype}>";
205
        }
206 3
    } else {
207
        switch($type) {
208 1
            case 'object':
209 1
                return get_class($data);
210 1
            case 'resource':
211 1
                return get_resource_type($data);
212
        }
213
    }
214 3
    return $type;
215
}
216
217
218
219
// BEGIN debug/testing functions
220
221
/**
222
 * Dump and die.
223
 *
224
 * @param mixed $input Data to dump
225
 * @param bool  $exit  Should we exit after dump?
226
 * @param bool  $label Should we print a label?
227
 * @codeCoverageIgnore
228
 */
229
function dd($input, $exit = true, $label = null)
230
{
231
    if (is_null($label)) {
232
        $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 1);
233
        $label = 'File: ';
234
        $label .= pathinfo($trace[0]['file'], PATHINFO_FILENAME);
235
        $label .= ':' . $trace[0]['line'];
236
        echo $label . "\n";
237
    } else {
238
        echo $label . "\n" . implode(
239
                array_map(
240
                    function () {
241
                        return '-';
242
                    },
243
                    str_split($label)
244
                )
245
            ) . "\n";
246
    }
247
    var_dump($input);
248
    echo "\n";
249
    if ($exit) {
250
        exit;
251
    }
252
}
253
254
/**
255
 * Exactly the same as var_dump, except that it returns its output rather than dumping it.
256
 */
257
function sdump($var)
258
{
259 22
    ob_start();
260 22
    var_dump($var);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($var); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
261 22
    return ob_get_clean();
262
}
263
264
/**
265
 * Get object hash/checksum.
266
 * Using a var_dump of an object, this will return a hash that tells you if anything in your object has changed. Just
267
 * create a hash of an object, do some stuff with it, then create another hash of it and compare the two. If they are
268
 * different, teh object has changed in some way.
269
 *
270
 * @param object $obj The object to hash
271
 * @param string $alg The hash algorithm (supports md5 or sha1)
272
 *
273
 * @return string
274
 *
275
 * @throws InvalidArgumentException
276
 */
277
function object_hash($obj, $alg = 'md5')
278
{
279 22
    $algorithms = ['md5', 'sha1'];
280 22
    if (!in_array($alg, $algorithms)) {
281
        throw new InvalidArgumentException(sprintf(
282
            '"%s" is not a valid hash algorithm (%s).',
283
            $alg,
284
            implode(', ', $algorithms)
285
        ));
286
    }
287 22
    return call_user_func($alg, sdump($obj));
288
}
289