http://phing.info/

Source Code Coverage

Designed for use with PHPUnit2, Xdebug and Phing.

Methods: 21 LOC: 366 Statements: 83

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


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