Completed
Push — master ( 0e2954...632183 )
by Ítalo
04:23
created

ExtractTrait::extractData()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.3074

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 20
ccs 10
cts 13
cp 0.7692
rs 8.8571
cc 5
eloc 12
nc 4
nop 2
crap 5.3074
1
<?php
2
3
// Copyright (c) Lellys Informática. All rights reserved. See License.txt in the project root for license information.
4
namespace Collections\Traits;
5
6
use Symfony\Component\PropertyAccess\PropertyAccess;
7
8
/**
9
 * Provides utility protected methods for extracting a property or column
10
 * from an array or object.
11
 */
12
trait ExtractTrait
13
{
14
    /**
15
     * Returns a callable that can be used to extract a property or column from
16
     * an array or object based on a dot separated path.
17
     *
18
     * @param string|callable $callback A dot separated path of column to follow
19
     * so that the final one can be returned or a callable that will take care
20
     * of doing that.
21
     * @return callable
22
     */
23 4
    public function propertyExtractor($callback)
24
    {
25 4
        if (is_string($callback)) {
26 4
            $path = explode('.', $callback);
27
            $callback = function ($element) use ($path) {
28 4
                return $this->extractData($element, $path);
29 4
            };
30 4
        }
31
32 4
        return $callback;
33
    }
34
35
    /**
36
     * Returns a column from $data that can be extracted
37
     * by iterating over the column names contained in $path
38
     *
39
     * @param array|\ArrayAccess $data Data.
40
     * @param array $path Path to extract from.
41
     * @return mixed
42
     */
43 4
    protected function extractData($data, $path)
44
    {
45 4
        $accessor = PropertyAccess::createPropertyAccessor();
46 4
        $value = null;
47 4
        foreach ($path as $column) {
48 4
            if (is_array($data) || $data instanceof \ArrayAccess) {
49 4
                $value = $accessor->getValue($data, "[$column]");
50 4
            } else {
51
52
                if (!$accessor->isReadable($data, $column)) {
53
                    return null;
54
                }
55
56
                $value = $accessor->getValue($data, $column);
57
            }
58 4
            $data = $value;
59 4
        }
60
61 4
        return $value;
62
    }
63
64
    /**
65
     * Returns a callable that receives a value and will return whether or not
66
     * it matches certain condition.
67
     *
68
     * @param array $conditions A key-value list of conditions to match where the
69
     * key is the property path to get from the current item and the value is the
70
     * value to be compared the item with.
71
     * @return callable
72
     */
73
    protected function createMatcherFilter(array $conditions)
74
    {
75
        $matchers = [];
76
        foreach ($conditions as $property => $value) {
77
            $extractor = $this->propertyExtractor($property);
0 ignored issues
show
Bug introduced by
It seems like $property can also be of type integer; however, Collections\Traits\Extra...it::propertyExtractor() does only seem to accept callable, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
78
            $matchers[] = function ($v) use ($extractor, $value) {
79
                return $extractor($v) == $value;
80
            };
81
        }
82
83
        return function ($value) use ($matchers) {
84
            foreach ($matchers as $match) {
85
                if (!$match($value)) {
86
                    return false;
87
                }
88
            }
89
90
            return true;
91
        };
92
    }
93
}
94