Completed
Push — master ( 343d0a...c5b636 )
by James Ekow Abaka
02:58
created

QueryOperations::resetQueryParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 3
rs 10
ccs 3
cts 3
cp 1
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * The MIT License
5
 *
6
 * Copyright 2015 ekow.
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated documentation files (the "Software"), to deal
10
 * in the Software without restriction, including without limitation the rights
11
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
 * copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
 * THE SOFTWARE.
25
 */
26
27
namespace ntentan\nibii;
28
29
use ntentan\utils\Text;
30
31
class QueryOperations {
32
33
    /**
34
     *
35
     * @var RecordWrapper
36
     */
37
    private $wrapper;
38
    private $adapter;
39
    private $queryParameters;
40
    private $pendingMethod;
41
    private $dynamicMethods = [
42
        "/(?<method>filterBy)(?<variable>[A-Z][A-Za-z]+){1}/",
43
        "/(?<method>sort)(?<direction>Asc|Desc)?(By)(?<variable>[A-Z][A-Za-z]+){1}/",
44
        "/(?<method>fetch)(?<first>First)?(With)(?<variable>[A-Za-z]+)/"
45
    ];
46
    private $dataOperations;
47
    private $driver;
48
49
    /**
50
     * 
51
     * @param RecordWrapper $wrapper
52
     * @param DriverAdapter $adapter
53
     * @param DataOperations $dataOperations
54
     */
55 35 View Code Duplication
    public function __construct(ORMContext $context, RecordWrapper $wrapper, DriverAdapter $adapter, $dataOperations) {
56 35
        $this->wrapper = $wrapper;
57 35
        $this->adapter = $adapter;
58 35
        $this->dataOperations = $dataOperations;
59 35
        $this->driver = $context->getDbContext()->getDriver();
60 35
    }
61
62 25
    public function doFetch($id = null) {
63 25
        $parameters = $this->getFetchQueryParameters($id);
64 25
        $data = $this->adapter->select($parameters);
65 25
        $this->wrapper->setData($data);
66 25
        $this->resetQueryParameters();
67 25
        return $this->wrapper;
68
    }
69
70 25
    private function getFetchQueryParameters($arg, $instantiate = true) {
71 25
        if ($arg instanceof \ntentan\nibii\QueryParameters) {
72 12
            return $arg;
73
        }        
74
        
75 25
        $parameters = $this->getQueryParameters($instantiate);
76
        
77 25
        if (is_numeric($arg)) {
78 6
            $description = $this->wrapper->getDescription();
79 6
            $parameters->addFilter($description->getPrimaryKey()[0], $arg);
80 6
            $parameters->setFirstOnly(true);
81 21
        } else if (is_array($arg)) {
82 6
            foreach ($arg as $field => $value) {
83 6
                $parameters->addFilter($field, $value);
84
            }
85
        }
86
        
87 25
        return $parameters;
88
    }
89
90
    /**
91
     *
92
     * @return \ntentan\nibii\QueryParameters
93
     */
94 33
    private function getQueryParameters($instantiate = true) {
95 33
        if ($this->queryParameters === null && $instantiate) {
96 33
            $this->queryParameters = new QueryParameters($this->wrapper->getDBStoreInformation()['quoted_table']);
97
        }
98 33
        return $this->queryParameters;
99
    }
100
101 31
    private function resetQueryParameters() {
102 31
        $this->queryParameters = null;
103 31
    }
104
105 10
    public function doFetchFirst($id = null) {
106 10
        $this->getQueryParameters()->setFirstOnly(true);
107 10
        return $this->doFetch($id);
108
    }
109
110 12
    public function doFields() {
111 12
        $fields = [];
112 12
        $arguments = func_get_args();
113 12
        foreach ($arguments as $argument) {
114 12
            if (is_array($argument)) {
115 6
                $fields = array_merge($fields, $argument);
116
            } else {
117 12
                $fields[] = $argument;
118
            }
119
        }
120 12
        $this->getQueryParameters()->setFields($fields);
121 12
        return $this->wrapper;
122
    }
123
124 10
    private function getFilter($arguments) {
125 10
        if (count($arguments) == 2 && is_array($arguments[1])) {
126 2
            $filter = $arguments[0];
127 2
            $data = $arguments[1];
128
        } else {
129 10
            $filter = array_shift($arguments);
130 10
            $data = $arguments;
131
        }
132 10
        return ['filter' => $filter, 'data' => $data];
133
    }
134
135 6
    public function doFilter() {
136 6
        $arguments = func_get_args();
137 6
        $details = $this->getFilter($arguments);
138 6
        $filterCompiler = new FilterCompiler();
139 6
        $this->getQueryParameters()->setRawFilter(
140 6
            $filterCompiler->compile($details['filter']), $filterCompiler->rewriteBoundData($details['data'])
141
        );
142 6
        return $this->wrapper;
143
    }
144
145 4
    public function doFilterBy() {
146 4
        $arguments = func_get_args();
147 4
        $details = $this->getFilter($arguments);
148 4
        $this->getQueryParameters()->addFilter($details['filter'], $details['data']);
149 4
        return $this->wrapper;
150
    }
151
152 6
    public function doUpdate($data) {
153 6
        $this->driver->beginTransaction();
154 6
        $parameters = $this->getQueryParameters();
155 6
        $this->adapter->bulkUpdate($data, $parameters);
156 6
        $this->driver->commit();
157 6
        $this->resetQueryParameters();
158 6
    }
159
160
    public function doDelete($args) {
161
        $this->driver->beginTransaction();
162
        $parameters = $this->getFetchQueryParameters($args);
163
164
        if ($parameters === null) {
165
            $primaryKey = $this->wrapper->getDescription()->getPrimaryKey();
166
            $parameters = $this->getQueryParameters();
167
            $data = $this->wrapper->getData();
168
            $keys = [];
169
170
            foreach ($data as $datum) {
171
                if ($this->dataOperations->isItemDeletable($primaryKey, $datum)) {
172
                    $keys[] = $datum[$primaryKey[0]];
173
                }
174
            }
175
176
            $parameters->addFilter($primaryKey[0], $keys);
177
            $this->adapter->delete($parameters);
178
        } else {
179
            $this->adapter->delete($parameters);
180
        }
181
182
        $this->driver->commit();
183
        $this->resetQueryParameters();
184
    }
185
186 10
    public function runDynamicMethod($arguments) {
187 10
        $arguments = count($arguments) > 1 ? $arguments : $arguments[0];
188 10
        switch ($this->pendingMethod['method']) {
189 10
            case 'filterBy':
190 4
                $this->getQueryParameters()->addFilter(Text::deCamelize($this->pendingMethod['variable']), $arguments);
191 4
                return $this->wrapper;
192 8
            case 'sort':
193
                $this->getQueryParameters()->addSort(Text::deCamelize($this->pendingMethod['variable']), $this->pendingMethod['direction']);
194
                return $this->wrapper;
195 8
            case 'fetch':
196 8
                $parameters = $this->getQueryParameters();
197 8
                $parameters->addFilter(Text::deCamelize($this->pendingMethod['variable']), $arguments);
198 8
                if ($this->pendingMethod['first'] === 'First') {
199 8
                    $parameters->setFirstOnly(true);
200
                }
201 8
                return $this->doFetch();
202
        }
203
    }
204
205 10
    public function initDynamicMethod($method) {
206 10
        $return = false;
207
208 10
        foreach ($this->dynamicMethods as $regexp) {
209 10
            if (preg_match($regexp, $method, $matches)) {
210 10
                $return = true;
211 10
                $this->pendingMethod = $matches;
212 10
                break;
213
            }
214
        }
215
216 10
        return $return;
217
    }
218
219
    public function doCount() {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
220
        return $this->adapter->count($this->getQueryParameters());
221
    }
222
223
    public function doLimit($numItems) {
224
        $this->getQueryParameters()->setLimit($numItems);
225
        return $this->wrapper;
226
    }
227
228
    public function doOffset($offset) {
229
        $this->getQueryParameters()->setOffset($offset);
230
        return $this->wrapper;
231
    }
232
    
233
    public function doWith($model) {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
234
        $relationship = $this->wrapper->getDescription()->getRelationships()[$model];
235
        return $relationship->getQuery();
236
    }
237
238
}
239