Completed
Push — master ( 3a5af3...5969bf )
by Dmitriy
05:50
created

CriteriaFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace T4webInfrastructure;
4
5
use T4webDomainInterface\Infrastructure\CriteriaInterface;
6
use RuntimeException;
7
8
class CriteriaFactory
9
{
10
    /**
11
     * @var Config
12
     */
13
    protected $config;
14
15
    /**
16
     * CriteriaFactory constructor.
17
     * @param Config $config
18
     */
19
    public function __construct(Config $config)
20
    {
21
        $this->config = $config;
22
    }
23
24
    /**
25
     * @param string $entityName
26
     * @param array $filter
27
     * @return CriteriaInterface
28
     */
29
    public function build($entityName, array $filter = [])
30
    {
31
        if (!is_string($entityName)) {
32
            throw new RuntimeException(sprintf('Entity mame must be string, %s given', gettype($entityName)));
33
        }
34
35
        $criteria = new Criteria($entityName, $this->config);
36
37
        if (empty($filter)) {
38
            return $criteria;
39
        }
40
41
        $relations = [];
42
        if (isset($filter['relations'])) {
43
            $relations = $filter['relations'];
44
            unset($filter['relations']);
45
        }
46
47
        $this->applyFilter($criteria, $filter);
48
49
        foreach ($relations as $relationEntity => $relationFilter) {
50
            $relation = $criteria->relation($relationEntity);
51
            $this->applyFilter($relation, $relationFilter);
52
        }
53
54
55
        return $criteria;
56
    }
57
58
    /**
59
     * @param CriteriaInterface $criteria
60
     * @param array $filter
61
     * @return CriteriaInterface
62
     */
63
    private function applyFilter(CriteriaInterface $criteria, array $filter)
64
    {
65
        foreach ($filter as $expressionString => $value) {
66
67
            if (in_array($expressionString, ['limit', 'offset'])) {
68
                $value = (int)$value;
69
                if ($value < 0) {
70
                    throw new RuntimeException(sprintf('Predicate %s must unsigned int, %s given', $expressionString, $value));
71
                }
72
73
                $criteria->{$expressionString}($value);
74
                continue;
75
            }
76
77
            if ($expressionString == 'page') {
78
                if (!isset($filter['limit'])) {
79
                    throw new RuntimeException(sprintf('Predicate %s require limit', $expressionString));
80
                }
81
                $criteria->offset($filter['limit'] * ($value - 1));
82
                continue;
83
            }
84
85
            if ($expressionString == 'order') {
86
                $criteria->order($value);
87
                continue;
88
            }
89
90
            if (strpos($expressionString, '.') !== false) {
91
                $expressionArray = explode('.', $expressionString);
92
            } else {
93
                $expressionArray = explode('_', $expressionString);
94
            }
95
96
            if (count($expressionArray) > 2) {
97
                continue;
98
            }
99
100
            if (count($expressionArray) == 2) {
101
                list($attribute, $method) = $expressionArray;
102
103
                if (in_array($method, ['isNull', 'isNotNull']) && $value) {
104
                    $criteria->{$method}($attribute);
105
                    continue;
106
                }
107
108
                if ($method == 'between') {
109
                    if (!is_array($value) || !isset($value[0]) || !isset($value[1])) {
110
                        throw new RuntimeException(sprintf('Predicate %s must contain array [MIN_VALUE, MAX_VALUE], ', $method));
111
                    }
112
113
                    $criteria->between($attribute, $value[0], $value[1]);
114
                    continue;
115
                }
116
117
                if (!method_exists($criteria, $method)) {
118
                    throw new RuntimeException(sprintf('Predicate %s does not exists', $method));
119
                }
120
121
                call_user_func([$criteria, $method], $attribute, $value);
122
            }
123
124
            if (count($expressionArray) == 1) {
125
                $customCriteria = ucfirst($expressionArray[0]);
126
                $entityNamespace = $this->config->getNamespace($criteria->getEntityName());
127
                $customCriteriaClass = "$entityNamespace\\Infrastructure\\Criteria\\$customCriteria";
128
129
                if (!class_exists($customCriteriaClass)) {
130
                    throw new RuntimeException(sprintf('Wrong criteria %s. Class %s does not exists.', $customCriteria, $customCriteriaClass));
131
                }
132
133
                $customCriteriaInstance = new $customCriteriaClass();
134
135
                if (!is_callable($customCriteriaInstance)) {
136
                    throw new RuntimeException(sprintf('Wrong criteria %s. Object of type %s is not callable.', $customCriteria, $customCriteriaClass));
137
                }
138
139
                $customCriteriaInstance($criteria, $value);
140
            }
141
        }
142
143
        return $criteria;
144
    }
145
146
}
147