Passed
Push — master ( 9280cd...76fe10 )
by Simon
02:08
created

Query::run()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 0
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
    protected $numberDataSets = 1;
26
    protected $currentDataSet = 0;
27
    protected $modifiers = [];
28
    protected $queryBase;
29
    
30
    /**
31
     * Stringify the current data set
32
     * 
33
     * @return string
34
     */
35
    public function __toString()
36
    {
37
        return $this->getTitle();
38
    }
39
            
40
    /**
41
     * Set the tracking parameters back to their base value
42
     * @return $this
43
     */
44
    public function reset()
45
    {
46
        $this->numberDataSets = 1;
47
        $this->currentDataset = 0;
0 ignored issues
show
Bug introduced by
The property currentDataset does not seem to exist. Did you mean currentDataSet?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
48
        
49
        return $this;
50
    }
51
52
    /**
53
     * Inform the service how many rounds the report will go through
54
     *
55
     * @param integer $count
56
     * @return $this
57
     * @throws \InvalidArgumentException if count not an integer, zero or less
58
     */
59
    public function setNumberDataSets($count)
60
    {
61
        if (!is_int($count)) {
62
            throw new \InvalidArgumentException('Must be an integer');
63
        }
64
        if ($count < 1) {
65
            throw new \InvalidArgumentException('Cannot have a negative number of sets');
66
        }
67
        $this->numberDataSets = $count;
68
        
69
        return $this;
70
    }
71
72
    /**
73
     * Attempt to move the query counter forward and halt operations if at end
74
     *
75
     * @return boolean True if can continue
76
     */
77
    public function tick()
78
    {
79
        ++$this->currentDataSet;
80
        if ($this->currentDataSet <= $this->numberDataSets) {
81
            return true;
82
        }
83
84
        // TODO shutdown procedure on query interface?
85
        return false;
86
    }
87
88
    /**
89
     * Set the Doctrine query repository to be used
90
     *
91
     * @param ObjectRepository $repository
92
     * @return $this
93
     */
94
    public function setRepository(ObjectRepository $repository)
95
    {
96
        $this->repository = $repository;
0 ignored issues
show
Bug introduced by
The property repository does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
97
98
        return $this;
99
    }
100
101
    /**
102
     * Set the Query Builder object which will form the basis of all information
103
     * gathering
104
     *
105
     * @param object $query
106
     * @return $this
107
     */
108
    public function setQueryBase($query)
109
    {
110
        // TODO Check if it is really a querybuilder once storage agnostic
111
        $this->queryBase = $query;
112
113
        return $this;
114
    }
115
116
    /**
117
     * Influence the current query that will be run by adding modifier conditions
118
     *
119
     * @param string $field   The database field
120
     * @param array  $options Options associated with the modifier
121
     * @return $this
122
     * @throws \InvalidArgumentException   If minimum options are not set
123
     */
124
    public function addModifier($field, $options = [])
125
    {
126
127
        if (!isset($options['type']) || !isset($options['value'])) {
128
            throw new \InvalidArgumentException('Modifier must have at least type and value present');
129
        }
130
131
        $this->modifiers[$field] = $options;
132
133
        return $this;
134
    }
135
136
    /**
137
     * Using the query base and available modifiers, create the base part of the
138
     * database query to be run in the current data set
139
     *
140
     * @return object QueryBuilder
141
     * @throws \Exception If an unrecognized query modifier is being used
142
     */
143
    public function prepareQuery()
144
    {
145
146
        $query = clone $this->queryBase;
147
        foreach ($this->getModifiers() as $key => $options) {
148
            switch (strtoupper($options['type'])) {
149
                case 'EQUALS':
150
                    $query->addAnd(
151
                        $query->expr()
152
                        ->field($key)
153
                        ->equals($options['value'])
154
                    );
155
                    break;
156
157
                case 'REFERENCES':
158
                    $query->addAnd(
159
                        $query->expr()
160
                        ->field($key)
161
                        ->references($options['value'])
162
                    );
163
                    break;
164
165
                default:
166
                    throw new \Exception('Query modifier for: ' . $key . ' not recognised:' . $options['type']);
167
            }
168
        }
169
170
        return $query;
171
    }
172
173
    /**
174
     * Attempt to build the actual database operation and return the result
175
     * @return type
176
     * @throws \Exception
177
     */
178
    public function run()
179
    {
180
181
        if (!$this->repository) {
182
            throw new \Exception('Set a repository before trying to run query');
183
        }
184
185
        // If no base query has been set, create a default one
186
        if (!$this->queryBase) {
187
            $this->queryBase = $this->repository->createQueryBuilder();
188
        }
189
190
        $query = $this->prepareQuery();
191
192
        // Empty the modifiers after the query has been run
193
        $this->modifiers = [];
194
195
        return $query->getQuery()->execute();
196
    }
197
198
    /**
199
     * Return the Doctrine repository object
200
     * @return object
201
     */
202
    public function getRepository()
203
    {
204
        return $this->repository;
205
    }
206
207
    /**
208
     * Return the current set counter
209
     *
210
     * @return integer
211
     */
212
    public function getNumberDataSetCurrent()
213
    {
214
        return $this->currentDataSet;
215
    }
216
217
    /**
218
     * Return the total number of data sets to be run
219
     *
220
     * @return integer
221
     */
222
    public function getNumberDataSetCount()
223
    {
224
        return $this->numberDataSets;
225
    }
226
       
227
    /**
228
     * Return the current modifiers in their array definition format
229
     *
230
     * @return array
231
     */
232
    public function getModifiers()
233
    {
234
        return $this->modifiers;
235
    }
236
    /**
237
     * Display the set heading
238
     * 
239
     * @return string
240
     */
241
    public function getTitle()
242
    {
243
        return '';
244
    }
245
}
246