Base::setRepository()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the ReportBundle package
5
 *
6
 * (c) symball <http://simonball.me>
7
 *
8
 * For the full copyright and license information, please view the LICENSE file
9
 * that was distributed with this source code.
10
 */
11
12
namespace Symball\ReportBundle\Query;
13
14
use Doctrine\Common\Persistence\ObjectRepository;
15
use Symball\ReportBundle\Interfaces\QueryInterface;
16
17
/**
18
 * The query class is responsible for performing information gathering operations
19
 * and typically involves a database query
20
 *
21
 * @author Simon Ball <simonball at simonball dot me>
22
 */
23
class Base implements QueryInterface
24
{
25
26
    /**
27
     * A limit to the number of rounds that the report builder will run
28
     * @var integer
29
     */
30
    protected $numberDataSets = 1;
31
32
    /**
33
     * pointer tracking
34
     * @var integer
35
     */
36
    protected $currentDataSet = 0;
37
38
    /**
39
     * For any query modifiers that will be used when the data query is run.
40
     * This gets reset every record set
41
     *
42
     * @var array
43
     */
44
    protected $modifiers = [];
45
46
    /**
47
     * A Doctrine query object that is used for pulling data in to the builder
48
     * @var object
49
     */
50
    protected $queryBase;
51
52
    /**
53
     * The Doctrine repository class used in the query
54
     * @var object
55
     */
56
    protected $repository;
57
58
    /**
59
     * Stringify the current data set
60
     *
61
     * @return string
62
     */
63
    public function __toString()
64
    {
65
        return $this->getTitle();
66
    }
67
68
    /**
69
     * Set the tracking parameters back to their base value
70
     * @return $this
71
     */
72
    public function reset()
73
    {
74
        $this->numberDataSets = 1;
75
        $this->currentDataSet = 0;
76
77
        return $this;
78
    }
79
80
    /**
81
     * Inform the service how many rounds the report will go through
82
     *
83
     * @param integer $count
84
     * @return $this
85
     * @throws \InvalidArgumentException if count not an integer, zero or less
86
     */
87
    public function setNumberDataSets($count)
88
    {
89
        if (!is_int($count)) {
90
            throw new \InvalidArgumentException('Must be an integer');
91
        }
92
        if ($count < 1) {
93
            throw new \InvalidArgumentException('Cannot have a negative number of sets');
94
        }
95
        $this->numberDataSets = $count;
96
97
        return $this;
98
    }
99
100
    /**
101
     * Attempt to move the query counter forward and halt operations if at end
102
     *
103
     * @return boolean True if can continue
104
     */
105
    public function tick()
106
    {
107
        ++$this->currentDataSet;
108
        if ($this->currentDataSet <= $this->numberDataSets) {
109
            return true;
110
        }
111
112
        // TODO shutdown procedure on query interface?
113
        return false;
114
    }
115
116
    /**
117
     * Set the Doctrine query repository to be used
118
     *
119
     * @param ObjectRepository $repository
120
     * @return $this
121
     */
122
    public function setRepository(ObjectRepository $repository)
123
    {
124
        $this->repository = $repository;
125
126
        return $this;
127
    }
128
129
    /**
130
     * Set the Query Builder object which will form the basis of all information
131
     * gathering
132
     *
133
     * @param object $query
134
     * @return $this
135
     */
136
    public function setQueryBase($query)
137
    {
138
        // TODO Check if it is really a querybuilder once storage agnostic
139
        $this->queryBase = $query;
140
141
        return $this;
142
    }
143
144
    /**
145
     * Influence the current query that will be run by adding modifier conditions
146
     *
147
     * @param string $field   The database field
148
     * @param array  $options Options associated with the modifier
149
     * @return $this
150
     * @throws \InvalidArgumentException   If minimum options are not set
151
     */
152
    public function addModifier($field, $options = [])
153
    {
154
155
        if (!isset($options['type']) || !isset($options['value'])) {
156
            throw new \InvalidArgumentException('Modifier must have at least type and value present');
157
        }
158
159
        $this->modifiers[$field] = $options;
160
161
        return $this;
162
    }
163
164
    /**
165
     * Using the query base and available modifiers, create the base part of the
166
     * database query to be run in the current data set
167
     *
168
     * @return object QueryBuilder
169
     * @throws \Exception If an unrecognized query modifier is being used
170
     */
171
    public function prepareQuery()
172
    {
173
174
        $query = clone $this->queryBase;
175
        foreach ($this->getModifiers() as $key => $options) {
176
            switch (strtoupper($options['type'])) {
177
                case 'EQUALS':
178
                    $query->addAnd(
179
                        $query->expr()
180
                        ->field($key)
181
                        ->equals($options['value'])
182
                    );
183
                    break;
184
185
                case 'REFERENCES':
186
                    $query->addAnd(
187
                        $query->expr()
188
                        ->field($key)
189
                        ->references($options['value'])
190
                    );
191
                    break;
192
193
                default:
194
                    throw new \Exception('Query modifier for: ' . $key . ' not recognised:' . $options['type']);
195
            }
196
        }
197
198
        return $query;
199
    }
200
201
    /**
202
     * Attempt to build the actual database operation and return the result
203
     * @return type
204
     * @throws \Exception
205
     */
206
    public function run()
207
    {
208
209
        if (!$this->repository) {
210
            throw new \Exception('Set a repository before trying to run query');
211
        }
212
213
        // If no base query has been set, create a default one
214
        if (!$this->queryBase) {
215
            $this->queryBase = $this->repository->createQueryBuilder();
216
        }
217
218
        $query = $this->prepareQuery();
219
220
        // Empty the modifiers after the query has been run
221
        $this->modifiers = [];
222
223
        return $query->getQuery()->execute();
224
    }
225
226
    /**
227
     * Return the Doctrine repository object
228
     * @return object
229
     */
230
    public function getRepository()
231
    {
232
        return $this->repository;
233
    }
234
235
    /**
236
     * Return the current set counter
237
     *
238
     * @return integer
239
     */
240
    public function getNumberDataSetCurrent()
241
    {
242
        return $this->currentDataSet;
243
    }
244
245
    /**
246
     * Return the total number of data sets to be run
247
     *
248
     * @return integer
249
     */
250
    public function getNumberDataSetCount()
251
    {
252
        return $this->numberDataSets;
253
    }
254
255
    /**
256
     * Return the current modifiers in their array definition format
257
     *
258
     * @return array
259
     */
260
    public function getModifiers()
261
    {
262
        return $this->modifiers;
263
    }
264
    /**
265
     * Display the set heading
266
     *
267
     * @return string
268
     */
269
    public function getTitle()
270
    {
271
        return '';
272
    }
273
}
274