Completed
Push — master ( 8a0039...4684b6 )
by Maik
03:19
created

Orm::find()   C

Complexity

Conditions 7
Paths 81

Size

Total Lines 51
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 7

Importance

Changes 18
Bugs 3 Features 3
Metric Value
c 18
b 3
f 3
dl 0
loc 51
ccs 33
cts 33
cp 1
rs 6.9744
cc 7
eloc 30
nc 81
nop 5
crap 7

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace Nkey\Caribu\Orm;
3
4
use \Nkey\Caribu\Model\AbstractModel;
5
use \Nkey\Caribu\Type\IType;
6
7
/**
8
 * The main object relational mapper class
9
 *
10
 * This class is part of Caribu package
11
 *
12
 * @author Maik Greubel <[email protected]>
13
 */
14
class Orm
15
{
16
    /**
17
     * Include the transaction related functionality
18
     */
19
    use OrmTransaction;
20
    
21
    /**
22
     * Include persisting related functionality
23
     */
24
    use OrmPersister;
25
    
26
    /**
27
     * Include the generics interpolation functionality
28
     */
29
    use \Generics\Util\Interpolator;
30
31
    /**
32
     * Singleton pattern
33
     *
34
     * @var Orm
35
     */
36
    private static $instance = null;
37
38
    /**
39
     * Singleton pattern
40
     *
41
     * @return Orm The current instance
42
     */
43 34
    public static function getInstance()
44
    {
45 34
        if (null === self::$instance) {
46 34
            self::$instance = new self();
47 34
        }
48
        
49 34
        return self::$instance;
50
    }
51
52
    /**
53
     * Singleton pattern
54
     */
55 34
    private function __construct()
56
    {
57
        // TODO:Implement console logging of sql for debugging purposes
58 34
    }
59
60
    /**
61
     * Disable cloning
62
     */
63
    private function __clone()
64
    {
65
        //
66
    }
67
68
    /**
69
     * Retrieve particular dataset by given id
70
     *
71
     * @param mixed $id
72
     *            The primary key value of dataset row to retrieve
73
     *            
74
     * @return \Nkey\Caribu\Model\AbstractModel
75
     *
76
     * @throws OrmException
77
     */
78 11
    public static function get($id)
79
    {
80 11
        $className = get_called_class();
81
        
82 11
        $pkColumn = self::getPrimaryKeyCol($className);
83
        
84 11
        $result = self::find(array(
85
            $pkColumn => $id
86 11
        ));
87
        
88 11
        if (! $result || is_array($result)) {
89 1
            throw new OrmException("More than one entity found (expected exactly one)");
90
        }
91
        
92 10
        return $result;
93
    }
94
95
    /**
96
     * Find data sets by given criteria
97
     *
98
     * @param array $criteria
99
     *            Array of criterias in form of "property" => "value"
100
     * @param string $orderBy
101
     *            An order-by statement in form of "property ASC|DESC"
102
     * @param int $limit
103
     *            The maximum amount of results
104
     * @param int $startOffset
105
     *            The offset where to get results of
106
     * @param boolean $asList
107
     *            Fetch results as list, also if number of results is one
108
     *            
109
     * @return Nkey\Caribu\Orm\AbstractModel|array|null Either an array of entities, a single entity (if only one was found) or null
110
     *        
111
     * @throws OrmException
112
     */
113 29
    public static function find(array $criteria, $orderBy = "", $limit = 0, $startOffset = 0, $asList = false)
114
    {
115 29
        $results = null;
116
        
117 29
        $instance = self::getInstance();
118
        
119 29
        $class = get_called_class();
120
        
121 29
        $table = self::getTableName($class);
122
        
123 29
        $escapeSign = $instance->getDbType()->getEscapeSign();
124
        
125 28
        $query = self::createQuery($class, $table, $criteria, array(
126 28
            sprintf("%s%s%s.*", $escapeSign, $table, $escapeSign)
127 28
        ), $orderBy, $limit, $startOffset, $escapeSign);
128 27
        $statement = null;
129
        
130
        try {
131 27
            $statement = $instance->startTX()->prepare($query);
132
            
133 27
            foreach ($criteria as $criterion => $value) {
134 24
                $placeHolder = str_replace('.', '_', $criterion);
135 24
                $placeHolder = str_replace('OR ', 'OR_', $placeHolder);
136 24
                $value = str_ireplace('LIKE ', '', $value);
137 24
                $statement->bindValue(":" . $placeHolder, $value);
138 27
            }
139
            
140 27
            $statement->execute();
141
            
142 27
            $unmapped = array();
143 27
            while ($result = $statement->fetch(\PDO::FETCH_OBJ)) {
144 26
                $unmapped[] = $result;
145 26
            }
146
            
147 27
            $statement->closeCursor();
148
            
149 27
            foreach ($unmapped as $result) {
150 26
                $results[] = self::map($result, $class, $instance);
151 26
            }
152
            
153 26
            if (! $asList && count($results) == 1) {
154 21
                $results = $results[0];
155 21
            }
156
            
157 26
            $instance->commitTX();
158 27
        } catch (\Exception $exception) {
159 1
            throw self::handleException($instance, $statement, $exception, "Finding data set failed", - 100);
160
        }
161
        
162 26
        return $results;
163
    }
164
165
    /**
166
     * Find data sets by given criteria
167
     *
168
     * @param array $criteria
169
     *            Array of criterias in form of "property" => "value"
170
     * @param string $orderBy
171
     *            An order-by statement in form of "property ASC|DESC"
172
     * @param int $limit
173
     *            The maximum amount of results
174
     * @param int $startOffset
175
     *            The offset where to get results of
176
     *            
177
     * @return mixed Either an array of object, a single object (if only one was found) or null
178
     *        
179
     * @throws OrmException
180
     */
181 1
    public static function findAll(array $criteria = array(), $orderBy = "", $limit = 0, $startOffset = 0)
182
    {
183 1
        return self::find($criteria, $orderBy, $limit, $startOffset, true);
184
    }
185
186
    /**
187
     * Persist the object into database
188
     *
189
     * @throws OrmException
190
     */
191 13
    public function persist()
192
    {
193 13
        $instance = self::getInstance();
194
        
195 13
        $escapeSign = $instance->getDbType()->getEscapeSign();
196
        
197 13
        $entity = $this;
198 13
        assert($entity instanceof \Nkey\Caribu\Model\AbstractModel);
199 13
        $class = get_class($entity);
200
        
201 13
        $tableName = self::getTableName($class);
202
        
203 13
        self::persistAnnotated($class, $entity);
204
        
205 13
        $pk = self::getPrimaryKey($class, $entity);
206 12
        if (is_null($pk)) {
207
            throw new OrmException("No primary key column found!");
208
        }
209 12
        $primaryKeyCol = array_keys($pk)[0];
210 12
        $primaryKeyValue = array_values($pk)[0];
211
        
212 12
        $pairs = self::getAnnotatedColumnValuePairs($class, $entity);
213
        
214 12
        $query = self::createUpdateStatement($class, $pairs, $primaryKeyCol, $primaryKeyValue, $escapeSign);
215
        
216 12
        $connection = $instance->startTX();
217 12
        $statement = null;
218
        
219
        try {
220 12
            $statement = $connection->prepare($query);
221
            
222 11
            foreach ($pairs as $column => $value) {
223 11
                if ($value instanceof \Nkey\Caribu\Model\AbstractModel) {
224 4
                    $value = self::getPrimaryKey(get_class($value), $value, true);
225 4
                }
226 11
                $statement->bindValue(":{$column}", self::convertToDatabaseType(self::getColumnType($instance, $tableName, $column), $value));
227 11
            }
228 11
            if ($primaryKeyValue) {
229 6
                $statement->bindValue(":{$primaryKeyCol}", $primaryKeyValue);
230 6
            }
231
            
232 11
            $instance->getDbType()->lock($tableName, IType::LOCK_TYPE_WRITE, $instance);
233 11
            $statement->execute();
234 11
            if (! $primaryKeyValue) {
235 10
                $pk = $connection->lastInsertId($instance->getDbType()
236 10
                    ->getSequenceNameForColumn($tableName, $primaryKeyCol, $instance));
237 10
            }
238 11
            $instance->getDbType()->unlock($tableName, $instance);
239
            
240 11
            unset($statement);
241
            
242 11
            if (! $primaryKeyValue) {
243 10
                $this->setPrimaryKey($class, $entity, $pk);
244 10
            }
245
            
246 11
            $this->persistMappedBy($class, $entity);
247
            
248 11
            $instance->commitTX();
249 12
        } catch (\PDOException $exception) {
250 1
            $instance->getDbType()->unlock($tableName, $instance);
251 1
            throw self::handleException($instance, $statement, $exception, "Persisting data set failed", - 1000);
252
        }
253 11
    }
254
255
    /**
256
     * Removes the current persisted entity
257
     *
258
     * @throws OrmException
259
     */
260 3
    public function delete()
261
    {
262 3
        $instance = self::getInstance();
263
        
264 3
        $class = get_class($this);
265
        
266 3
        $tableName = $this->getTableName($class);
267
        
268 3
        $escapeSign = $this->getDbType()->getEscapeSign();
269
        
270 3
        $pk = self::getPrimaryKey($class, $this);
271 3
        $primaryKeyCol = array_keys($pk)[0];
272 3
        $primaryKeyValue = array_values($pk)[0];
273
        
274 3
        if (is_null($primaryKeyValue)) {
275
            throw new OrmException("Entity is not persisted or detached. Can not delete.");
276
        }
277
        
278 3
        $query = sprintf("DELETE FROM %s%s%s WHERE %s%s%s = :%s", $escapeSign, $tableName, $escapeSign, $escapeSign, $primaryKeyCol, $escapeSign, $primaryKeyCol);
279
        
280 3
        $statement = null;
281
        
282
        try {
283 3
            $statement = $instance->startTX()->prepare($query);
284 3
            $statement->bindValue(":{$primaryKeyCol}", $primaryKeyValue);
285
            
286 3
            $instance->getDbType()->lock($tableName, IType::LOCK_TYPE_WRITE, $instance);
287 3
            $statement->execute();
288 3
            $instance->getDbType()->unlock($tableName, $instance);
289 3
            unset($statement);
290 3
            $instance->commitTX();
291 3
        } catch (\PDOException $exception) {
292
            $instance->getDbType()->unlock($tableName, $instance);
293
            throw self::handleException($instance, $statement, $exception, "Persisting data set failed", - 1000);
294
        }
295 3
    }
296
297
    /**
298
     * Destroy the orm instance
299
     */
300 34
    public static function passivate()
301
    {
302 34
        if (self::$instance) {
303 33
            self::$instance->passivateConnection();
304 33
            self::$instance = null;
305 33
        }
306 34
    }
307
}
308