Completed
Push — master ( 8216e2...4b2f01 )
by Vladimir
02:34
created

WhereFilter::compare()   D

Complexity

Conditions 18
Paths 35

Size

Total Lines 38
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 18

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 18
eloc 22
nc 35
nop 4
dl 0
loc 38
ccs 27
cts 27
cp 1
crap 18
rs 4.947
c 2
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
/**
4
 * @copyright 2017 Vladimir Jimenez
5
 * @license   https://github.com/allejo/stakx/blob/master/LICENSE.md MIT
6
 */
7
8
namespace allejo\stakx\Twig;
9
10
use allejo\stakx\Object\FrontMatterObject;
11
use allejo\stakx\Object\JailObject;
12
use Twig_Error_Syntax;
13
14
/**
15
 * Where Twig Filter
16
 *
17
 * This Twig filter introduces the `where` filter
18
 *
19
 * Usage:
20
 *   <array> | where(<key>, <comparison>, <value>)
21
 *
22
 * Available comparisons:
23
 *   - ==  Ensure the values are equal and are the same data type
24
 *   - !=  Ensure the values are not equal; returns false if the values are the same but different data types
25
 *   - >   Greater than
26
 *   - >=  Greater than or equal to
27
 *   - <   Less than
28
 *   - <=  Less than or equal to
29
 *   - ~=  Check if a string or array contains the <value>; case-sensitive
30
 *   - _=  Check if a string or array contains the <value>; case-insensitive
31
 *   - /=  Compare the <value> with a regular expression
32
 *
33
 * @package allejo\stakx\Twig
34
 */
35
class WhereFilter
36
{
37
    /**
38
     * @param  array|\ArrayAccess[] $array      The elements to filter through
39
     * @param  string               $key        The key value in an associative array or FrontMatter
40
     * @param  string               $comparison The actual comparison symbols being used
41
     * @param  mixed                $value      The value we're searching for
42
     *
43
     * @return array
44
     */
45 38
    public function __invoke ($array, $key, $comparison, $value)
46
    {
47 38
        $results = array();
48 38
        $this->search_r($array, $key, $comparison, $value, $results);
49
50 37
        return $results;
51
    }
52
53
    /**
54
     * @return \Twig_SimpleFilter
55
     */
56 2
    public static function get ()
57
    {
58 2
        return new \Twig_SimpleFilter('where', new self());
59
    }
60
61
    /**
62
     * Recursive searching calling our comparison
63
     *
64
     * @param array|\ArrayAccess[] $array      The elements to filter through
65
     * @param string               $key        The key value in an associative array or FrontMatter
66
     * @param string               $comparison The actual comparison symbols being used
67
     * @param string               $value      The value we're searching for
68
     * @param array                $results    The reference to where to keep the filtered elements
69
     */
70 38
    private function search_r ($array, $key, $comparison, $value, &$results)
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
71
    {
72 38
        if (!is_array($array) && !($array instanceof \ArrayAccess))
73 38
        {
74 19
            return;
75
        }
76
77 38
        if ($this->compare($array, $key, $comparison, $value))
78 38
        {
79 29
            $results[] = $array;
80 29
        }
81
82 38
        foreach ($array as $subarray)
83
        {
84 38
            $this->search_r($subarray, $key, $comparison, $value, $results);
85 37
        }
86 37
    }
87
88
    /**
89
     * The logic for determining if an element matches the filter
90
     *
91
     * @param  array|\ArrayAccess[] $array      The elements to filter through
92
     * @param  string               $key        The key value in an associative array or FrontMatter
93
     * @param  string               $comparison The actual comparison symbols being used
94
     * @param  mixed                $value      The value we're searching for
95
     *
96
     * @return bool
97
     *
98
     * @throws Twig_Error_Syntax
99
     */
100 38
    private function compare ($array, $key, $comparison, $value)
101
    {
102 38
        if ($array instanceof JailObject && $array->coreInstanceOf(FrontMatterObject::class))
103 38
        {
104 17
            if (!isset($array[$key]))
105 17
            {
106 5
                if ($comparison == '==' && is_null($value)) { return true; }
107 4
                if ($comparison == '!=' && !is_null($value)) { return true; }
108 3
            }
109 17
        }
110
111 38
        if (!isset($array[$key]))
112 38
        {
113 38
            return false;
114
        }
115
116
        switch ($comparison)
117
        {
118 37
            case "==": return ($array[$key] === $value);
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
119 28
            case "!=": return ($array[$key] !== $value);
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
120 24
            case ">" : return ($array[$key] > $value);
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
121 21
            case ">=": return ($array[$key] >= $value);
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
122 17
            case "<" : return ($array[$key] < $value);
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
123 14
            case "<=": return ($array[$key] <= $value);
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
124
125 11
            case "~=":
126 7
                return $this->contains($array[$key], $value);
127
128 4
            case "_=":
129 2
                return $this->containsCaseInsensitive($array[$key], $value);
130
131 2
            case "/=":
132 1
                return $this->regexMatches($array[$key], $value);
133
134 1
            default:
135 1
                throw new Twig_Error_Syntax("Invalid where comparison ({$comparison})");
136 1
        }
137
    }
138
139 7
    private function contains ($haystack, $needle)
140
    {
141
        return (
142 7
            (is_array($haystack) && in_array($needle, $haystack)) ||
143 7
            (is_string($haystack) && strpos($haystack, $needle) !== false)
144 7
        );
145
    }
146
147 2
    private function containsCaseInsensitive ($haystack, $needle)
148
    {
149 2
        if (is_array($haystack))
150 2
        {
151
            $downCase = array_combine(array_map('strtolower', $haystack), $haystack);
152
153
            return (isset($downCase[strtolower($needle)]));
154
        }
155
156 2
        return (is_string($haystack) && strpos(strtolower($haystack), strtolower($needle)) !== false);
157
    }
158
159 1
    private function regexMatches ($haystack, $regex)
160
    {
161 1
        return (preg_match($regex, $haystack) === 1);
162
    }
163
}