Completed
Push — 4.0 ( 14a1f2...cbd7ec )
by David
02:31
created

InnerResultIterator   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 245
Duplicated Lines 5.31 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 20
c 3
b 0
f 0
lcom 1
cbo 6
dl 13
loc 245
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 13 13 1
A executeQuery() 0 9 1
A count() 0 8 2
A current() 0 4 1
A key() 0 4 1
B next() 0 59 8
A rewind() 0 6 1
A valid() 0 4 1
A offsetExists() 0 4 1
A offsetGet() 0 4 1
A offsetSet() 0 4 1
A offsetUnset() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Mouf\Database\TDBM;
4
5
use Doctrine\DBAL\Statement;
6
use Mouf\Database\MagicQuery;
7
8
/*
9
 Copyright (C) 2006-2016 David Négrier - THE CODING MACHINE
10
11
 This program is free software; you can redistribute it and/or modify
12
 it under the terms of the GNU General Public License as published by
13
 the Free Software Foundation; either version 2 of the License, or
14
 (at your option) any later version.
15
16
 This program is distributed in the hope that it will be useful,
17
 but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 GNU General Public License for more details.
20
21
 You should have received a copy of the GNU General Public License
22
 along with this program; if not, write to the Free Software
23
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24
 */
25
26
/**
27
 * Iterator used to retrieve results.
28
 */
29
class InnerResultIterator implements \Iterator, \Countable, \ArrayAccess
30
{
31
    /**
32
     * @var Statement
33
     */
34
    protected $statement;
35
36
    protected $fetchStarted = false;
37
    private $objectStorage;
38
    private $className;
39
40
    private $tdbmService;
41
    private $magicSql;
42
    private $parameters;
43
    private $limit;
44
    private $offset;
45
    private $columnDescriptors;
46
    private $magicQuery;
47
48
    /**
49
     * The key of the current retrieved object.
50
     *
51
     * @var int
52
     */
53
    protected $key = -1;
54
55
    protected $current = null;
56
57
    private $databasePlatform;
58
59 View Code Duplication
    public function __construct($magicSql, array $parameters, $limit, $offset, array $columnDescriptors, $objectStorage, $className, TDBMService $tdbmService, MagicQuery $magicQuery)
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...
60
    {
61
        $this->magicSql = $magicSql;
62
        $this->objectStorage = $objectStorage;
63
        $this->className = $className;
64
        $this->tdbmService = $tdbmService;
65
        $this->parameters = $parameters;
66
        $this->limit = $limit;
67
        $this->offset = $offset;
68
        $this->columnDescriptors = $columnDescriptors;
69
        $this->magicQuery = $magicQuery;
70
        $this->databasePlatform = $this->tdbmService->getConnection()->getDatabasePlatform();
71
    }
72
73
    protected function executeQuery()
74
    {
75
        $sql = $this->magicQuery->build($this->magicSql, $this->parameters);
76
        $sql = $this->tdbmService->getConnection()->getDatabasePlatform()->modifyLimitQuery($sql, $this->limit, $this->offset);
77
78
        $this->statement = $this->tdbmService->getConnection()->executeQuery($sql, $this->parameters);
79
80
        $this->fetchStarted = true;
81
    }
82
83
    /**
84
     * Counts found records (this is the number of records fetched, taking into account the LIMIT and OFFSET settings).
85
     *
86
     * @return int
87
     */
88
    public function count()
89
    {
90
        if (!$this->fetchStarted) {
91
            $this->executeQuery();
92
        }
93
94
        return $this->statement->rowCount();
95
    }
96
97
    /**
98
     * Fetches record at current cursor.
99
     *
100
     * @return AbstractTDBMObject|null
101
     */
102
    public function current()
103
    {
104
        return $this->current;
105
    }
106
107
    /**
108
     * Returns the current result's key.
109
     *
110
     * @return int
111
     */
112
    public function key()
113
    {
114
        return $this->key;
115
    }
116
117
    /**
118
     * Advances the cursor to the next result.
119
     * Casts the database result into one (or several) beans.
120
     */
121
    public function next()
122
    {
123
        $row = $this->statement->fetch(\PDO::FETCH_NUM);
124
        if ($row) {
125
126
            // array<tablegroup, array<table, array<column, value>>>
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
127
            $beansData = [];
128
            foreach ($row as $i => $value) {
129
                $columnDescriptor = $this->columnDescriptors[$i];
130
                // Let's cast the value according to its type
131
                $value = $columnDescriptor['type']->convertToPHPValue($value, $this->databasePlatform);
132
133
                $beansData[$columnDescriptor['tableGroup']][$columnDescriptor['table']][$columnDescriptor['column']] = $value;
134
            }
135
136
            $reflectionClassCache = [];
137
            $firstBean = true;
138
            foreach ($beansData as $beanData) {
139
140
                // Let's find the bean class name associated to the bean.
141
142
                list($actualClassName, $mainBeanTableName) = $this->tdbmService->_getClassNameFromBeanData($beanData);
143
144
                if ($this->className !== null) {
145
                    $actualClassName = $this->className;
146
                }
147
148
                // Must we create the bean? Let's see in the cache if we have a mapping DbRow?
149
                // Let's get the first object mapping a row:
150
                // We do this loop only for the first table
151
152
                $primaryKeys = $this->tdbmService->_getPrimaryKeysFromObjectData($mainBeanTableName, $beanData[$mainBeanTableName]);
153
                $hash = $this->tdbmService->getObjectHash($primaryKeys);
154
155
                if ($this->objectStorage->has($mainBeanTableName, $hash)) {
156
                    $dbRow = $this->objectStorage->get($mainBeanTableName, $hash);
157
                    $bean = $dbRow->getTDBMObject();
158
                } else {
159
                    // Let's construct the bean
160
                    if (!isset($reflectionClassCache[$actualClassName])) {
161
                        $reflectionClassCache[$actualClassName] = new \ReflectionClass($actualClassName);
162
                    }
163
                    // Let's bypass the constructor when creating the bean!
164
                    $bean = $reflectionClassCache[$actualClassName]->newInstanceWithoutConstructor();
165
                    $bean->_constructFromData($beanData, $this->tdbmService);
166
                }
167
168
                // The first bean is the one containing the main table.
169
                if ($firstBean) {
170
                    $firstBean = false;
171
                    $this->current = $bean;
172
                }
173
            }
174
175
            ++$this->key;
176
        } else {
177
            $this->current = null;
178
        }
179
    }
180
181
    /**
182
     * Moves the cursor to the beginning of the result set.
183
     */
184
    public function rewind()
185
    {
186
        $this->executeQuery();
187
        $this->key = -1;
188
        $this->next();
189
    }
190
    /**
191
     * Checks if the cursor is reading a valid result.
192
     *
193
     * @return bool
194
     */
195
    public function valid()
196
    {
197
        return $this->current !== null;
198
    }
199
200
    /**
201
     * Whether a offset exists.
202
     *
203
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
204
     *
205
     * @param mixed $offset <p>
206
     *                      An offset to check for.
207
     *                      </p>
208
     *
209
     * @return bool true on success or false on failure.
210
     *              </p>
211
     *              <p>
212
     *              The return value will be casted to boolean if non-boolean was returned.
213
     *
214
     * @since 5.0.0
215
     */
216
    public function offsetExists($offset)
217
    {
218
        throw new TDBMInvalidOperationException('You cannot access this result set via index because it was fetched in CURSOR mode. Use ARRAY_MODE instead.');
219
    }
220
221
    /**
222
     * Offset to retrieve.
223
     *
224
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
225
     *
226
     * @param mixed $offset <p>
227
     *                      The offset to retrieve.
228
     *                      </p>
229
     *
230
     * @return mixed Can return all value types.
231
     *
232
     * @since 5.0.0
233
     */
234
    public function offsetGet($offset)
235
    {
236
        throw new TDBMInvalidOperationException('You cannot access this result set via index because it was fetched in CURSOR mode. Use ARRAY_MODE instead.');
237
    }
238
239
    /**
240
     * Offset to set.
241
     *
242
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
243
     *
244
     * @param mixed $offset <p>
245
     *                      The offset to assign the value to.
246
     *                      </p>
247
     * @param mixed $value  <p>
248
     *                      The value to set.
249
     *                      </p>
250
     *
251
     * @since 5.0.0
252
     */
253
    public function offsetSet($offset, $value)
254
    {
255
        throw new TDBMInvalidOperationException('You can set values in a TDBM result set.');
256
    }
257
258
    /**
259
     * Offset to unset.
260
     *
261
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
262
     *
263
     * @param mixed $offset <p>
264
     *                      The offset to unset.
265
     *                      </p>
266
     *
267
     * @since 5.0.0
268
     */
269
    public function offsetUnset($offset)
270
    {
271
        throw new TDBMInvalidOperationException('You can unset values in a TDBM result set.');
272
    }
273
}
274