Completed
Push — master ( 1ee05e...99144a )
by Gaetano
05:13
created

AbstractMatcher::validateConditions()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
dl 0
loc 17
c 0
b 0
f 0
ccs 0
cts 10
cp 0
rs 8.8333
cc 7
nc 5
nop 1
crap 56
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Matcher;
4
5
use Kaliop\eZMigrationBundle\API\MatcherInterface;
6
7
abstract class AbstractMatcher implements MatcherInterface
8
{
9
    /** @var string[] $allowedConditions the keywords we allow to be used for matching on*/
10
    protected $allowedConditions = array();
11
    /** @var  string $returns user-readable name of the type of object returned */
12
    protected $returns;
13
    /** @var int $maxConditions the maximum number of conditions we allow to match on for a single match request */
14
    protected $maxConditions = 1;
15
    /** @var int $minConditions the minimum number of conditions we allow to match on for a single match request. It could be replaced with an array of mandatory conditions, really... */
16
    protected $minConditions = 1;
17
18
    protected function validateConditions(array $conditions)
19
    {
20
        if ($this->minConditions > 0 && count($conditions) < $this->minConditions) {
21
            throw new \Exception($this->returns . ' can not be matched because the matching conditions are empty');
22
        }
23
24
        if ($this->maxConditions > 0 && count($conditions) > $this->maxConditions) {
25
            throw new \Exception($this->returns . " can not be matched because multiple matching conditions are specified. Only {$this->maxConditions} condition(s) are supported");
26
        }
27
28
        foreach ($conditions as $key => $value) {
29
            if (!in_array((string)$key, $this->allowedConditions)) {
30
                throw new \Exception($this->returns . " can not be matched because matching condition '$key' is not supported. Supported conditions are: " .
31
                    implode(', ', $this->allowedConditions));
32
            }
33
        }
34
    }
35
36 View Code Duplication
    protected function matchAnd($conditionsArray)
0 ignored issues
show
Duplication introduced by
This method 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...
37
    {
38
        /// @todo introduce proper re-validation of all child conditions
39
        if (!is_array($conditionsArray) || !count($conditionsArray)) {
40
            throw new \Exception($this->returns . " can not be matched because no matching conditions found for 'and' clause.");
41
        }
42
43
        $class = null;
44
        foreach ($conditionsArray as $conditions) {
45
            $out = $this->match($conditions);
46
            if ($out instanceof \ArrayObject) {
47
                $class = get_class($out);
48
                $out = $out->getArrayCopy();
49
            }
50
            if (!isset($results)) {
51
                $results = $out;
52
            } else {
53
                $results = array_intersect_key($results, $out);
54
            }
55
        }
56
57
        if ($class) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $class of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
58
            $results = new $class($results);
0 ignored issues
show
Bug introduced by
The variable $results does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
59
        }
60
61
        return $results;
62
    }
63
64 View Code Duplication
    protected function matchOr(array $conditionsArray)
0 ignored issues
show
Duplication introduced by
This method 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...
65
    {
66
        /// @todo introduce proper re-validation of all child conditions
67
        if (!is_array($conditionsArray) || !count($conditionsArray)) {
68
            throw new \Exception($this->returns . " can not be matched because no matching conditions found for 'or' clause.");
69
        }
70
71
        $class = null;
72
        $results = array();
73
        foreach ($conditionsArray as $conditions) {
74
            $out = $this->match($conditions);
75
            if ($out instanceof \ArrayObject) {
76
                $class = get_class($out);
77
                $out = $out->getArrayCopy();
78
            }
79
            $results = array_replace($results, $out);
80
        }
81
82
        if ($class) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $class of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
83
            $results = new $class($results);
84
        }
85
86
        return $results;
87
    }
88
89
    public function matchOne(array $conditions)
90
    {
91
        $results = $this->match($conditions);
92
        $count = count($results);
93
        if ($count !== 1) {
94
            throw new \Exception("Found $count " . $this->returns . " when expected exactly only one to match the conditions");
95
        }
96
        return reset($results);
97
    }
98
99
    /**
100
     * @param array $conditions
101
     * @return array|\ArrayObject the keys must be a unique identifier of the matched entities
102
     */
103
    abstract public function match(array $conditions);
104
}
105