Completed
Pull Request — master (#49)
by Luke
02:03
created

functions.php ➔ is_arrayable()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 4
nop 1
dl 0
loc 13
ccs 0
cts 0
cp 0
crap 20
rs 9.2
c 0
b 0
f 0
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 InvalidArgumentException;
13
use Iterator;
14
use Noz\Collection\Collection;
15
use Noz\Contracts\CollectionInterface;
16
use Traversable;
17
18
/**
19
 * Collection factory.
20
 *
21
 * Simply an alias to (new Collection($in)). Allows for a little more concise and
22
 * simpler instantiation of a collection. Also I plan to eventually support
23
 * additional input types that will make this function more flexible and forgiving
24
 * than simply instantiating a Collection object, but for now the two are identical.
25
 *
26
 * @param array|Iterator $data Either an array or an iterator of data
27
 *
28
 * @return CollectionInterface
29
 */
30
function collect($data = null)
31
{
32
    return Collection::factory($data);
33 2
}
34
35
/**
36
 * Invoke a callable and return result.
37
 *
38
 * Pass in a callable followed by whatever arguments you want passed to
39
 * it and this function will invoke it with your arguments and return
40
 * the result.
41
 *
42
 * @param callable $callback The callback function to invoke
43
 * @param array ...$args     The args to pass to your callable
44
 *
45
 * @return mixed The result of your invoked callable
46
 */
47
function invoke(callable $callback, ...$args)
48
{
49
    return $callback(...$args);
50 1
}
51
52
/**
53
 * Determine if data is traversable.
54
 *
55
 * Pass in any variable and this function will tell you whether or not it
56
 * is traversable. Basically this just means that it is either an array or an iterator.
57
 * This function was written simply because I was tired of if statements that checked
58
 * whether a variable was an array or a descendant of \Iterator. So I wrote this guy.
59
 *
60
 * @param mixed $data The variable to determine traversability
61
 *
62
 * @return bool True if $input is an array or an Iterator
63
 */
64
function is_traversable($data)
65
{
66
    return is_array($data) || $data instanceof Traversable;
67 100
}
68
69
/**
70
 * Can data be converted to an array?
71
 *
72
 * @param mixed $data The data to check
73
 *
74
 * @return bool
75
 */
76
function is_arrayable($data)
77
{
78
    if (!is_array($data)) {
79
        if (is_object($data)) {
80
            return (
81
                method_exists($data, 'toArray') ||
82
                $data instanceof Traversable
83
            );
84
        }
85
        return false;
86
    }
87
    return true;
88
}
89
90
/**
91
 * Convert any traversable to an array.
92
 *
93
 * @todo I'm not sure if this function is necessary or not. Does iterator_to_array do everything this can do?
94
 *
95
 * @param Traversable $data Traversable data
96
 *
97
 * @return array
98
 */
99
function traversable_to_array(Traversable $data)
100
{
101
    $arr = [];
102
    foreach ($data as $key => $val) {
103
        $arr[$key] = $val;
104
    }
105
    return $arr;
106
}
107
108
/**
109
 * Convert data to an array.
110
 *
111
 * Accepts any kind of data and converts it to an array. If strict mode is on, only data that returns true from
112
 * is_arrayable() will be converted to an array. Anything else will cause an InvalidArgumentException to be thrown.
113
114
 * @param mixed $data   Data to convert to array
115
 * @param bool  $strict Whether to use strict mode
116
117
 * @return array
118
 *
119
 * @throws InvalidArgumentException
120
 */
121
function to_array($data, $strict = true)
122
{
123
    if (is_arrayable($data)) {
124
        if (is_array($data)) {
125
            return $data;
126
        }
127
        // this is what makes toArray() work recursively
128
        // it must stay right where it is do not move it
129
        if (method_exists($data, 'toArray')) {
130
            return $data->toArray();
131
        }
132
        if ($data instanceof Iterator) {
133
            return iterator_to_array($data);
134
        }
135
        if ($data instanceof Traversable) {
136
            return traversable_to_array($data);
137
        }
138
    }
139
    if ($strict) {
140
        throw new InvalidArgumentException(sprintf(
141
            'Invalid argument for "%s". Cannot convert "%s" to an array.',
142
            __FUNCTION__,
143
            typeof($data)
144
        ));
145
    }
146
    if (is_object($data)) {
147
        $values = [];
148
        foreach ($data as $key => $val) {
149
            $values[$key] = $val;
150
        }
151
        return $values;
152
    }
153
    if (is_null($data)) {
154
        return [];
155
    }
156
    return [$data];
157
}
158
159
/**
160
 * Get data type.
161
 *
162
 * Inspects data to determine its type.
163
 *
164
 * @param mixed  $data       The data to check
165
 * @param bool   $meta       Whether to include meta data such as length/size
166
// * @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...
167
 *
168
 * @return string
169
 */
170
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...
171
{
172
    $type = gettype($data);
173
    if ($meta) {
174
        switch($type) {
175
            case 'object':
176
                $class = get_class($data);
177
                return "{$type} <{$class}>";
178
            case 'resource':
179
                $restype = get_resource_type($data);
180
                return "{$type} <{$restype}>";
181
        }
182
    } else {
183
        switch($type) {
184
            case 'object':
185
                return get_class($data);
186
            case 'resource':
187
                return get_resource_type($data);
188
        }
189
    }
190
    return $type;
191
//    $params = [
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% 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...
192
//        'type' => strtolower(gettype($data)),
193
//        'class' => null,
194
//        'size' => null,
195
//        'value' => null
196
//    ];
197
//    switch($params['type']) {
198
//        case 'object':
199
//            $params['class'] = get_class($data);
200
//            break;
201
//        case 'resource':
202
//            $params['class'] = get_resource_type($data);
203
//            break;
204
//        case 'array':
205
//            $params['size'] = count($data);
206
//            break;
207
//        case 'boolean':
208
//            $params['value'] = $data ? 'true' : 'false';
209
//            break;
210
//        case 'string':
211
//            $params['size'] = strlen($data);
212
//            $params['value'] = $data;
213
//            break;
214
//        case 'integer':
215
//            $params['size'] = strlen($data);
216
//            $params['value'] = $data;
217
//            break;
218
//        case 'double':
219
//            list($real, $decimal) = explode('.', $data, 2);
220
//            $params['size'] = strlen($real) . ',' . strlen($decimal);
221
//            $params['value'] = $data;
222
//            break;
223
//        case 'null':
224
//            break;
225
//        case 'unknown type':
226
//        default:
227
//            $params['type'] = 'undefined';
228
//            break;
229
//    }
230
//    if ($returnType == 'array') {
231
//        if (!$meta) {
232
//            return ['type' => $params['type']];
233
//        }
234
//        return collect($params)->filter(function($val) {
235
//            return !is_null($val);
236
//        })->toArray();
237
//    }
238
//    if (!$meta) {
239
//        return $params['type'];
240
//    }
241
//    $return = $params['type'];
242
//    if (!is_null($params['class'])) {
243
//        $return .= " <{$params['class']}>";
244
//    }
245
//    if (!is_null($params['size'])) {
246
//        $return .= " <{$params['size']}>";
247
//    }
248
//    if (!is_null($params['value'])) {
249
//        $return .= " ({$params['value']})";
250
//    }
251
//    return $return;
252
}
253
254
// BEGIN debug/testing functions
255
256
/**
257
 * Dump and die.
258
 *
259
 * @param mixed $input Data to dump
260
 * @param bool  $exit  Should we exit after dump?
261
 * @param bool  $label Should we print a label?
262
 * @codeCoverageIgnore
263
 */
264
function dd($input, $exit = true, $label = null)
265
{
266
    if (is_null($label)) {
267
        $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 1);
268
        $label = 'File: ';
269
        $label .= pathinfo($trace[0]['file'], PATHINFO_FILENAME);
270
        $label .= ':' . $trace[0]['line'];
271
        echo $label . "\n";
272
    } else {
273
        echo $label . "\n" . implode(
274
                array_map(
275
                    function () {
276
                        return '-';
277
                    },
278
                    str_split($label)
279
                )
280
            ) . "\n";
281
    }
282
    var_dump($input);
283
    echo "\n";
284
    if ($exit) {
285
        exit;
286
    }
287
}
288
289
/**
290
 * Exactly the same as var_dump, except that it returns its output rather than dumping it.
291
 */
292
function sdump($var)
293
{
294
    ob_start();
295
    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...
296
    return ob_get_clean();
297
}
298
299
/**
300
 * Get object hash/checksum.
301
 * Using a var_dump of an object, this will return a hash that tells you if anything in your object has changed. Just
302
 * create a hash of an object, do some stuff with it, then create another hash of it and compare the two. If they are
303
 * different, teh object has changed in some way.
304
 *
305
 * @param object $obj The object to hash
306
 * @param string $alg The hash algorithm (supports md5 or sha1)
307
 *
308
 * @return string
309
 *
310
 * @throws InvalidArgumentException
311
 */
312
function object_hash($obj, $alg = 'md5')
313
{
314
    $algorithms = ['md5', 'sha1'];
315
    if (!in_array($alg, $algorithms)) {
316
        throw new InvalidArgumentException(sprintf(
317
            '"%s" is not a valid hash algorithm (%s).',
318
            $alg,
319
            implode(', ', $algorithms)
320
        ));
321
    }
322
    return call_user_func($alg, sdump($obj));
323
}
324