http://phing.info/

Source Code Coverage

Designed for use with PHPUnit2, Xdebug and Phing.

Methods: 21 LOC: 362 Statements: 86

Source file Statements Methods Total coverage
Repository.php 100.0% 100.0% 100.0%
 
1
<?php
2
/**
3
 * Xyster Framework
4
 *
5
 * This source file is subject to the new BSD license that is bundled
6
 * with this package in the file LICENSE.txt.
7
 * It is also available through the world-wide-web at this URL:
8
 * http://www.opensource.org/licenses/bsd-license.php
9
 *
10
 * @category  Xyster
11
 * @package   Xyster_Orm
12
 * @copyright Copyright (c) 2007-2008 Irrational Logic (http://irrationallogic.net)
13
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
14
 * @version   $Id: Repository.php 199 2008-01-19 21:54:40Z doublecompile $
15
 */
16
/**
17
 * @see Xyster_Orm_Loader
18
 */
19 1
require_once 'Xyster/Orm/Loader.php';
20
/**
21
 * @see Xyster_Collection_Map_String
22
 */
23 1
require_once 'Xyster/Collection/Map/String.php';
24
/**
25
 * The "identity map" of persisted entities
26
 *
27
 * @category  Xyster
28
 * @package   Xyster_Orm
29
 * @copyright Copyright (c) 2007-2008 Irrational Logic (http://irrationallogic.net)
30
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
31
 */
32
class Xyster_Orm_Repository
33
{
34
    /**
35
     * A container for the entity objects
36
     *
37
     * The array is structured using class names as keys, then another array
38
	 * with the keys 'byKey', 'byIndex', and 'hasAll'.  hasAll is a boolean, the
39
	 * other two are {@link Xyster_Collection_Map_String} objects.
40
	 *
41
	 * <code>array(
42
	 * 		'entityName1' => array(
43
	 * 			'byKey' => Xyster_Collection_Map_String,
44
	 * 			'byIndex => Xyster_Collection_Map_String,
45
	 * 			'hasAll' => false
46
	 * 		),
47
	 * 		'entityName2' => array(
48
	 * 			'byKey' => Xyster_Collection_Map_String,
49
	 * 			'byIndex => Xyster_Collection_Map_String,
50
	 * 			'hasAll' => false
51
	 * 		)
52
	 * );</code>
53
     *
54
     * @var array
55
     */
56
    protected $_items = array();
57
58
    /**
59
     * The mapper factory
60
     *
61
     * @var Xyster_Orm_Mapper_Factory_Interface
62
     */
63
    protected $_mapFactory;
64
65
    /**
66
     * Creates a new entity repository
67
     *
68
     * @param Xyster_Orm_Mapper_Factory_Interface $mapFactory
69
     */
70
    public function __construct( Xyster_Orm_Mapper_Factory_Interface $mapFactory )
71
    {
72 67
        $this->_mapFactory = $mapFactory;
73
    }
74
75
    /**
76
     * Adds an entity to the repository
77
     *
78
     * @param Xyster_Orm_Entity $entity
79
     */
80
    public function add( Xyster_Orm_Entity $entity )
81
    {
82 49
        $this->_getByKeyMap($entity)->set($this->_stringifyPrimaryKey($entity), $entity);
83
84
        /*
85
         * Add the entity to its appropriate index(es)
86
         */
87 49
        $indexMap = $this->_getByIndexMap($entity);
88 49
        foreach( $this->_getMapper($entity)->getIndex() as $index ) {
89 8
	        if ( is_array($index) && count($index) ) {
90 8
				$hash = array();
91 8
				foreach( $index as $name ) {
92 8
					$hash[] = $name . '=' . $entity->$name;
93 8
				}
94 8
				$hash = implode(',', $hash);
95 8
				$indexMap->set($hash, $entity);
96 8
			}
97 8
        }
98
    }
99
100
    /**
101
     * Adds a set to the repository
102
     *
103
     * @param Xyster_Orm_Set $set
104
     */
105
    public function addAll( Xyster_Orm_Set $set )
106
    {
107 30
        foreach( $set as $entity ) {
108 26
            $this->add($entity);
109 26
        }
110
    }
111
112
    /**
113
     * Gets whether the repository contains the entity supplied
114
     *
115
     * @param Xyster_Orm_Entity $entity
116
     * @return boolean
117
     */
118
    public function contains( Xyster_Orm_Entity $entity )
119
    {
120 8
        return $this->_getByKeyMap($entity)->containsValue($entity);
121
    }
122
123
    /**
124
     * Finds an entity by indexed value
125
     *
126
     * @param string $class
127
     * @param array $values
128
     * @return Xyster_Orm_Entity The entity found or null if none
129
     */
130
    public function find( $class, array $values )
131
    {
132 5
        Xyster_Orm_Loader::loadEntityClass($class);
133
134 5
        $hash = array();
135 5
		foreach( $values as $name => $value ) {
136 5
			$hash[] = $name . "=" . $value;
137 5
		}
138 5
		$hash = implode(',', $hash);
139
140 5
		return $this->_getByIndexMap($class)->get($hash);
141
    }
142
143
    /**
144
     * Gets an item from the repository
145
     *
146
     * @param string $class
147
     * @param mixed $primaryKey
148
     * @return Xyster_Orm_Entity The entity found or null if none
149
     */
150
    public function get( $class, $primaryKey )
151
    {
152 63
        Xyster_Orm_Loader::loadEntityClass($class);
153 63
        return $this->_getByKeyMap($class)
154 63
            ->get($this->_stringifyPrimaryKey($primaryKey));
155
    }
156
157
    /**
158
     * Gets the names of classes that are currently stored in this map
159
     *
160
     * @return array The names of the classes stored
161
     */
162
    public function getClasses()
163
    {
164 2
        return array_keys($this->_items);
165
    }
166
167
    /**
168
     * Gets all entities of a particular type
169
     *
170
     * @return Xyster_Collection_Interface
171
     */
172
    public function getAll( $class )
173
    {
174 5
        Xyster_Orm_Loader::loadEntityClass($class);
175 5
        return $this->_getByKeyMap($class)
176 5
            ->values();
177
    }
178
179
    /**
180
     * Gets whether a given class has all of its entities loaded
181
     *
182
     * @param string $class The entity class
183
     * @return boolean Whether all entities have been loaded
184
     */
185
    public function hasAll( $class )
186
    {
187 9
        return array_key_exists($class, $this->_items) &&
188 8
            array_key_exists('hasAll', $this->_items[$class]) &&
189 9
            $this->_items[$class]['hasAll'];
190
    }
191
192
    /**
193
     * Removes an entity from the repository
194
     *
195
     * @param Xyster_Orm_Entity $entity The entity to remove
196
     */
197
    public function remove( Xyster_Orm_Entity $entity )
198
    {
199 4
        $this->_removeEntity($entity);
200 4
        $this->setHasAll(get_class($entity), false);
201
    }
202
203
    /**
204
     * Removes an entity by class and primary key
205
     *
206
     * @param string $class
207
     * @param mixed $key
208
     */
209
    public function removeByKey( $class, $key )
210
    {
211 1
        Xyster_Orm_Loader::loadEntityClass($class);
212 1
        $this->_removeByClassAndKey($class, $key);
213 1
        $this->setHasAll($class, false);
214
    }
215
216
    /**
217
     * Removes all entities supplied from the repository
218
     *
219
     * @param Xyster_Orm_Set $set The entities to remove
220
     */
221
    public function removeAll( Xyster_Orm_Set $set )
222
    {
223 2
        foreach( $set as $entity ) {
224 2
            $this->_removeEntity($entity);
225 2
        }
226 2
        $this->setHasAll($set->getEntityName(), false);
227
    }
228
229
    /**
230
     * Removes all entities by class and primary keys
231
     *
232
     * @param string $class
233
     * @param array $ids
234
     */
235
    public function removeAllByKey( $class, array $ids )
236
    {
237 1
        Xyster_Orm_Loader::loadEntityClass($class);
238 1
        foreach( $ids as $key ) {
239 1
            $this->_removeByClassAndKey($class, $key);
240 1
        }
241 1
        $this->setHasAll($class, false);
242
    }
243
244
    /**
245
     * Sets whether a given class has all of its entities loaded
246
     *
247
     * @param string $class The entity class
248
     * @param boolean $hasAll Whether all entities have been loaded
249
     */
250
    public function setHasAll( $class, $hasAll = true )
251
    {
252 12
        $this->_items[$class]['hasAll'] = $hasAll;
253
    }
254
255
    /**
256
     * Convenience method to get the map (and create it if necessary)
257
     *
258
     * @param string $class The entity
259
     * @return Xyster_Collection_Map_String
260
     */
261
    protected function _getByKeyMap( $class )
262
    {
263 71
        return $this->_getByHelper($class, 'byKey');
264
    }
265
266
    /**
267
     * Convenience method to get the map (and create it if necessary)
268
     *
269
     * @param string $class The entity
270
     * @return Xyster_Collection_Map_String
271
     */
272
    protected function _getByIndexMap( $class )
273
    {
274 49
        return $this->_getByHelper($class, 'byIndex');
275
    }
276
277
    /**
278
     * Sets up the array and class name
279
     *
280
     * @param mixed $class
281
     * @param string $key
282
     * @return string
283
     */
284
    protected function _getByHelper( $class, $key )
285
    {
286 71
        if ( is_object($class) ) {
287 49
            $class = get_class($class);
288 49
        }
289 71
        if ( !array_key_exists($class, $this->_items) ) {
290 64
            $this->_items[$class] = array();
291 64
        }
292 71
        if ( !array_key_exists($key, $this->_items[$class]) ) {
293 64
            $this->_items[$class][$key] = new Xyster_Collection_Map_String();
294 64
        }
295 71
        return $this->_items[$class][$key];
296
    }
297
298
    /**
299
     * Convenience method to get the entity's mapper
300
     *
301
     * @return Xyster_Orm_Mapper
302
     */
303
    protected function _getMapper( Xyster_Orm_Entity $entity )
304
    {
305 49
        return $this->_mapFactory->get(get_class($entity));
306
    }
307
308
    /**
309
     * Convenience method to remove an entity
310
     *
311
     * @param string $class
312
     * @param mixed $key
313
     */
314
    protected function _removeByClassAndKey( $class, $key )
315
    {
316 2
        $map = $this->_getByKeyMap($class);
317 2
        $entity = $map->get($this->_stringifyPrimaryKey($key));
318 2
        if ( $entity ) {
319 2
            $this->_removeEntity($entity);
320 2
        }
321
    }
322
323
    /**
324
     * Removes an entity from both maps
325
     *
326
     * @param Xyster_Orm_Entity $entity
327
     */
328
    protected function _removeEntity( Xyster_Orm_Entity $entity )
329
    {
330
        // remove the entity from the index map
331 8
        $indexMap = $this->_getByIndexMap($entity);
332 8
        foreach( $indexMap->keysFor($entity) as $key ) {
333 1
            $indexMap->remove($key);
334 1
        }
335
336
        // remove the entity from the key map
337 8
        $keyMap = $this->_getByKeyMap($entity);
338 8
        $keyMap->remove($this->_stringifyPrimaryKey($entity));
339
    }
340
341
    /**
342
     * Convenience method to stringify the primary key
343
     *
344
     * @param mixed $key A primary key or an entity whose primary key is used
345
     * @return string The primary key as a string
346
     */
347
    protected function _stringifyPrimaryKey( $key )
348
    {
349 71
        if ( $key instanceof Xyster_Orm_Entity ) {
350
        	/* @var $key Xyster_Orm_Entity */
351 49
            $key = $key->getPrimaryKey();
352 49
        }
353 71
        if ( is_array($key) ) {
354 71
            $string = array();
355 71
            foreach( $key as $k => $value ) {
356 71
                $string[] = $k . '=' . $value;
357 71
            }
358 71
            $key = implode(',', $string);
359 71
        }
360 71
        return (string) $key;
361
    }
362
}


Report generated at 2008-01-20T12:13:38-05:00