http://phing.info/

Source Code Coverage

Designed for use with PHPUnit2, Xdebug and Phing.

Methods: 20 LOC: 440 Statements: 147

Source file Statements Methods Total coverage
Manager.php 95.2% 100.0% 95.8%
   
1
<?php
2
/**
3
 * Xyster Framework
4
 *
5
 * LICENSE
6
 *
7
 * This source file is subject to the new BSD license that is bundled
8
 * with this package in the file LICENSE.txt.
9
 * It is also available through the world-wide-web at this URL:
10
 * http://www.opensource.org/licenses/bsd-license.php
11
 * If you did not receive a copy of the license and are unable to
12
 * obtain it through the world-wide-web, please send an email
13
 * to xyster@devweblog.org so we can send you a copy immediately.
14
 *
15
 * @category  Xyster
16
 * @package   Xyster_Orm
17
 * @copyright Copyright (c) 2007 Irrational Logic (http://devweblog.org)
18
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
19
 * @version   $Id: Manager.php 116 2007-10-07 17:03:52Z doublecompile $
20
 */
21
/**
22
 * @see Xyster_Orm_Repository
23
 */
24 1
require_once 'Xyster/Orm/Repository.php';
25
/**
26
 * @see Xyster_Orm_Plugin_Broker
27
 */
28 1
require_once 'Xyster/Orm/Plugin/Broker.php';
29
/**
30
 * The main backend of the orm package
31
 *
32
 * @category  Xyster
33
 * @package   Xyster_Orm
34
 * @copyright Copyright (c) 2007 Irrational Logic (http://devweblog.org)
35
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
36
 */
37
class Xyster_Orm_Manager
38
{
39
    /**
40
     * The mapper factory
41
     *
42
     * @var Xyster_Orm_Mapper_Factory_Interface
43
     */
44
    protected $_mapFactory;
45
46
    /**
47
     * The repository for storing entities
48
     *
49
     * @var Xyster_Orm_Repository
50
     */
51
    protected $_repository;
52
53
    /**
54
     * The secondary cache
55
     *
56
     * @var Zend_Cache_Core
57
     */
58
    protected $_secondaryCache;
59
60
    /**
61
     * The plugin broker
62
     *
63
     * @var Xyster_Orm_Plugin_Broker
64
     */
65
    protected $_plugins;
66
67
    /**
68
     * Creates a new Orm_Manager
69
     *
70
     */
71
    public function __construct()
72
    {
73 212
        $this->_plugins = new Xyster_Orm_Plugin_Broker();
74
    }
75
76
    /**
77
     * Clears out the repository
78
     *
79
     */
80
    public function clear()
81
    {
82 2
        $this->_repository = null;
83
    }
84
85
    /**
86
     * Executes a query or report query
87
     *
88
     * @param Xyster_Orm_Query $query
89
     * @return Xyster_Data_Set
90
     */
91
    public function executeQuery( Xyster_Orm_Query $query )
92
    {
93 11
        $set = $this->_mapFactory->get($query->getFrom())->query($query);
94
95 11
        if ( $set instanceof Xyster_Orm_Set ) {
96
        	// add returned entities to the cache
97 7
        	$this->getRepository()->addAll($set);
98 7
        	$this->putAllInSecondaryCache($set);
99 7
        }
100
101 11
        return $set;
102
    }
103
104
    /**
105
     * Gets the first entity found matching a set of criteria
106
     *
107
     * @param string $className
108
     * @param array $criteria
109
     * @return Xyster_Orm_Entity The entity found or null if none
110
     */
111
    public function find( $className, array $criteria )
112
    {
113 3
        if ( $entity = $this->getRepository()->find($className, $criteria) ) {
114
115 1
            return $entity;
116
117 0
        } else {
118
119 2
            $map = $this->getMapperFactory()->get($className);
120 2
            $entity = $map->find($criteria);
121 2
            if ( $entity ) {
122 2
                $this->getRepository()->add($entity);
123 2
                $this->putInSecondaryCache($entity);
124 2
            }
125 2
            return $entity;
126
        }
127
    }
128
129
    /**
130
     * Finds all entities matching a given criteria
131
     *
132
     * @param string $className
133
     * @param mixed $criteria {@link Xyster_Data_Criterion} or associative array
134
     * @param mixed $sorts Array of {@link Xyster_Data_Sort} objects
135
     */
136
    public function findAll( $className, $criteria, $sorts = null )
137
    {
138 6
        $map = $this->getMapperFactory()->get($className);
139 6
        $all = $map->findAll($criteria, $sorts);
140 5
        $this->getRepository()->addAll($all);
141 5
        $this->putAllInSecondaryCache($all);
142 5
        return $all;
143
    }
144
145
    /**
146
     * Gets an entity by class and primary key
147
     *
148
     * @param string $className
149
     * @param mixed $id
150
     * @return Xyster_Orm_Entity
151
     */
152
    public function get( $className, $id )
153
    {
154 23
        $map = $this->getMapperFactory()->get($className);
155
156 23
        if ( is_scalar($id) || is_null($id) ) {
157 16
            $keyNames = $map->getEntityMeta()->getPrimary();
158 16
            $id = array( $keyNames[0] => $id );
159 16
        }
160
161 23
        $entity = $this->getFromCache($className, $id, true);
162 23
        if ( $entity instanceof Xyster_Orm_Entity ) {
163 9
            return $entity;
164 0
        }
165
166 16
        $entity = $map->get($id);
167 16
        if ( $entity instanceof Xyster_Orm_Entity ) {
168 12
            $this->getRepository()->add($entity);
169 12
            $this->putInSecondaryCache($entity);
170 12
            return $entity;
171 0
        }
172 4
        return null;
173
    }
174
175
    /**
176
     * Gets all entities from the data source or a subset if given the keys
177
     *
178
     * @param string $className
179
     * @param array $ids
180
     * @return Xyster_Orm_Set
181
     */
182
    public function getAll( $className, array $ids = null )
183
    {
184 3
        $all = null;
185 3
        $map = $this->getMapperFactory()->get($className);
186
187 3
        if ( is_array($ids) && count($ids) ) {
188
            // we're getting a few entities by primary key
189
190 3
            if ( $this->getRepository()->hasAll($className) ) {
191 1
                $keyNames = $map->getEntityMeta()->getPrimary();
192 1
                $all = $map->getSet();
193 1
                foreach( $ids as $id ) {
194 1
                    if ( is_scalar($id) ) {
195 1
                        $id = array( $keyNames[0] => $id );
196 1
                    }
197 1
                    $entity = $this->getRepository()->get($className, $id);
198 1
                    if ( $entity ) {
199 1
                        $all->add( $entity );
200 1
                    }
201 1
                }
202 1
            } else {
203 2
                $all = $map->getAll($ids);
204 2
                $this->getRepository()->addAll($all);
205 2
                $this->putAllInSecondaryCache($all);
206
            }
207
208 3
        } else {
209
            // we're getting ALL entities from the source
210
211 1
            if ( $this->getRepository()->hasAll($className) ) {
212 1
                $all = $this->getRepository()->getAll($className);
213 1
                if (! $all instanceof Xyster_Orm_Set ) {
214 1
                    $all = $map->getSet($all);
215 1
                }
216 1
            } else {
217 1
                $all = $map->getAll();
218 1
                $this->getRepository()->addAll($all);
219 1
                $this->putAllInSecondaryCache($all);
220 1
                $this->getRepository()->setHasAll($className);
221
            }
222
223
        }
224
225 3
        return $all;
226
    }
227
228
    /**
229
     * Tries to load an entity from the cache
230
     *
231
     * This method will return null if the entity isn't in either cache
232
     *
233
     * @param string $className
234
     * @param mixed $id
235
     * @param boolean $checkSecondary Whether to also check the secondary cache
236
     * @return Xyster_Orm_Entity
237
     */
238
    public function getFromCache( $className, $id, $checkSecondary = false )
239
    {
240 57
        $map = $this->getMapperFactory()->get($className);
241
242 57
        if ( is_scalar($id) || is_null($id) ) {
243 1
            $keyNames = $map->getEntityMeta()->getPrimary();
244 1
            $id = array( $keyNames[0] => $id );
245 1
        }
246
247 57
        $entity = $this->getRepository()->get($className, $id);
248 57
        if ( $entity instanceof Xyster_Orm_Entity ) {
249 21
            return $entity;
250 0
        }
251
252 55
        if ( $checkSecondary ) {
253 17
            $entity = $this->_getFromSecondaryCache($className, $id);
254 17
            if ( $entity instanceof Xyster_Orm_Entity ) {
255 1
                $this->getRepository()->add($entity);
256 1
                return $entity;
257 0
            }
258 16
        }
259
    }
260
261
    /**
262
     * Gets entities via a many-to-many table
263
     *
264
     * @param string $className
265
     * @param Xyster_Orm_Entity $entity
266
     * @param Xyster_Orm_Relation $relation
267
     * @return Xyster_Orm_Set
268
     */
269
    public function getJoined( Xyster_Orm_Entity $entity, Xyster_Orm_Relation $relation )
270
    {
271 5
        $className = get_class($entity);
272 5
        $joined = $this->_mapFactory->get($className)->getJoined($entity, $relation);
273 5
        $this->getRepository()->addAll($joined);
274 5
        return $joined;
275
    }
276
277
    /**
278
     * Gets the factory for entity mappers
279
     *
280
     * @return Xyster_Orm_Mapper_Factory_Interface
281
     */
282
    public function getMapperFactory()
283
    {
284 94
        if ( !$this->_mapFactory ) {
285 1
            require_once 'Xyster/Orm/Mapper/Factory.php';
286 1
            $this->setMapperFactory(new Xyster_Orm_Mapper_Factory());
287 1
        }
288 94
        return $this->_mapFactory;
289
    }
290
291
    /**
292
     * Gets the plugin broker
293
     *
294
     * @return Xyster_Orm_Plugin_Broker
295
     */
296
    public function getPluginBroker()
297
    {
298 56
        return $this->_plugins;
299
    }
300
301
    /**
302
     * Gets the entity repository
303
     *
304
     * @return Xyster_Orm_Repository
305
     */
306
    public function getRepository()
307
    {
308 60
        if ( !$this->_repository ) {
309 53
            $this->_repository = new Xyster_Orm_Repository($this->getMapperFactory());
310 53
        }
311 60
        return $this->_repository;
312
    }
313
314
    /**
315
     * Gets the secondary repository for storing entities
316
     *
317
     * @return Zend_Cache_Core
318
     */
319
    public function getSecondaryCache()
320
    {
321 37
        return $this->_secondaryCache;
322
    }
323
324
    /**
325
     * Refreshes the values of an entity
326
     */
327
    public function refresh( Xyster_Orm_Entity $entity )
328
    {
329 2
        $this->getMapperFactory()->get(get_class($entity))->refresh($entity);
330
    }
331
332
    /**
333
     * Sets the factory for entity mappers
334
     *
335
     * This method also calls the
336
     * {@link Xyster_Orm_Mapper_Factory_Interface::setManager} method.
337
     *
338
     * @param Xyster_Orm_Mapper_Factory_Interface $mapFactory
339
     */
340
    public function setMapperFactory( Xyster_Orm_Mapper_Factory_Interface $mapFactory )
341
    {
342 212
        $this->_mapFactory = $mapFactory;
343 212
        $mapFactory->setManager($this);
344
    }
345
346
    /**
347
     * Sets the secondary repository for storing entities
348
     *
349
     * If $repository is null, then no secondary repository is used.
350
     *
351
     * @param mixed $repository Either a Cache object, or a string naming a Registry key
352
     */
353
    public function setSecondaryCache($repository = null)
354
    {
355 36
        $this->_secondaryCache = $this->_setupSecondaryCache($repository);
356
    }
357
358
    /**
359
     * Gets an entity from the secondary repository
360
     *
361
     * @param string $className
362
     * @param array $id
363
     * @return Xyster_Orm_Entity the entity found or null if none
364
     */
365
    protected function _getFromSecondaryCache( $className, $id )
366
    {
367 17
        $repo = $this->getSecondaryCache();
368 17
        $entity = null;
369 17
        if ( $repo ) {
370 10
            $repoId = array( 'Xyster_Orm',
371 10
                $this->getMapperFactory()->get($className)->getDomain(),
372 10
                $className );
373 10
            foreach( $id as $key => $value ) {
374 10
                $repoId[] = $key . '=' . $value;
375 10
            }
376 10
            $repoId = md5(implode("/",$repoId));
377
378 10
            $entity = $repo->load($repoId);
379 10
        }
380 17
        return $entity;
381
    }
382
383
    /**
384
     * Puts the entity in the secondary repository
385
     *
386
     * @param Xyster_Orm_Entity $entity
387
     */
388
    public function putInSecondaryCache( Xyster_Orm_Entity $entity )
389
    {
390 28
        $repo = $this->getSecondaryCache();
391 28
        $className = get_class($entity);
392 28
        $map = $this->getMapperFactory()->get($className);
393 28
        $cacheLifetime = $map->getLifetime();
394
395
        // only store the entity if it should be cached longer than the request
396
        // that's why we have the primary repository
397 28
        if ( $repo && $cacheLifetime > -1 ) {
398
399 13
            $repoId = array('Xyster_Orm', $map->getDomain(), $className);
400 13
            foreach( $entity->getPrimaryKey() as $key => $value ) {
401 13
                $repoId[] = $key . '=' . $value;
402 13
            }
403 13
            $repoId = md5(implode("/", $repoId));
404 13
            $repo->save($entity, $repoId, array(), $cacheLifetime);
405 13
        }
406
    }
407
408
    /**
409
     * Convenience method to put all entities in a set in the cache
410
     *
411
     * @param Xyster_Orm_Set $set
412
     */
413
    public function putAllInSecondaryCache( Xyster_Orm_Set $set )
414
    {
415 15
        foreach( $set as $entity ) {
416 14
            $this->putInSecondaryCache($entity);
417 14
        }
418
    }
419
420
    /**
421
     * @param mixed $repository Either a Cache object, or a string naming a Registry key
422
     * @return Zend_Cache_Core
423
     * @throws Xyster_Orm_Exception
424
     */
425
    final protected function _setupSecondaryCache($repository)
426
    {
427 36
        if ($repository === null) {
428 1
            return null;
429 0
        }
430 36
        if (is_string($repository)) {
431 2
            require_once 'Zend/Registry.php';
432 2
            $repository = Zend_Registry::get($repository);
433 1
        }
434 36
        if (!$repository instanceof Zend_Cache_Core) {
435 1
            require_once 'Xyster/Orm/Exception.php';
436 1
            throw new Xyster_Orm_Exception('Argument must be of type Zend_Cache_Core, or a Registry key where a Zend_Cache_Core object is stored');
437 0
        }
438 36
        return $repository;
439
    }
440
}


Report generated at 2007-10-08T19:32:23-05:00