Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
13532 anikendra 1
<?php
2
/**
3
 * A factory class to manage the life cycle of test fixtures
4
 *
5
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
6
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
7
 *
8
 * Licensed under The MIT License
9
 * For full copyright and license information, please see the LICENSE.txt
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
13
 * @link          http://cakephp.org CakePHP(tm) Project
14
 * @package       Cake.TestSuite.Fixture
15
 * @since         CakePHP(tm) v 2.0
16
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
17
 */
18
 
19
App::uses('ConnectionManager', 'Model');
20
App::uses('ClassRegistry', 'Utility');
21
 
22
/**
23
 * A factory class to manage the life cycle of test fixtures
24
 *
25
 * @package       Cake.TestSuite.Fixture
26
 */
27
class CakeFixtureManager {
28
 
29
/**
30
 * Was this class already initialized?
31
 *
32
 * @var boolean
33
 */
34
	protected $_initialized = false;
35
 
36
/**
37
 * Default datasource to use
38
 *
39
 * @var DataSource
40
 */
41
	protected $_db = null;
42
 
43
/**
44
 * Holds the fixture classes that where instantiated
45
 *
46
 * @var array
47
 */
48
	protected $_loaded = array();
49
 
50
/**
51
 * Holds the fixture classes that where instantiated indexed by class name
52
 *
53
 * @var array
54
 */
55
	protected $_fixtureMap = array();
56
 
57
/**
58
 * Inspects the test to look for unloaded fixtures and loads them
59
 *
60
 * @param CakeTestCase $test the test case to inspect
61
 * @return void
62
 */
63
	public function fixturize($test) {
64
		if (!$this->_initialized) {
65
			ClassRegistry::config(array('ds' => 'test', 'testing' => true));
66
		}
67
		if (empty($test->fixtures) || !empty($this->_processed[get_class($test)])) {
68
			$test->db = $this->_db;
69
			return;
70
		}
71
		$this->_initDb();
72
		$test->db = $this->_db;
73
		if (!is_array($test->fixtures)) {
74
			$test->fixtures = array_map('trim', explode(',', $test->fixtures));
75
		}
76
		if (isset($test->fixtures)) {
77
			$this->_loadFixtures($test->fixtures);
78
		}
79
 
80
		$this->_processed[get_class($test)] = true;
81
	}
82
 
83
/**
84
 * Initializes this class with a DataSource object to use as default for all fixtures
85
 *
86
 * @return void
87
 */
88
	protected function _initDb() {
89
		if ($this->_initialized) {
90
			return;
91
		}
92
		$db = ConnectionManager::getDataSource('test');
93
		$db->cacheSources = false;
94
		$this->_db = $db;
95
		$this->_initialized = true;
96
	}
97
 
98
/**
99
 * Looks for fixture files and instantiates the classes accordingly
100
 *
101
 * @param array $fixtures the fixture names to load using the notation {type}.{name}
102
 * @return void
103
 * @throws UnexpectedValueException when a referenced fixture does not exist.
104
 */
105
	protected function _loadFixtures($fixtures) {
106
		foreach ($fixtures as $fixture) {
107
			$fixtureFile = null;
108
			$fixtureIndex = $fixture;
109
			if (isset($this->_loaded[$fixture])) {
110
				continue;
111
			}
112
 
113
			if (strpos($fixture, 'core.') === 0) {
114
				$fixture = substr($fixture, strlen('core.'));
115
				$fixturePaths[] = CAKE . 'Test' . DS . 'Fixture';
116
			} elseif (strpos($fixture, 'app.') === 0) {
117
				$fixture = substr($fixture, strlen('app.'));
118
				$fixturePaths = array(
119
					TESTS . 'Fixture'
120
				);
121
			} elseif (strpos($fixture, 'plugin.') === 0) {
122
				$parts = explode('.', $fixture, 3);
123
				$pluginName = $parts[1];
124
				$fixture = $parts[2];
125
				$fixturePaths = array(
126
					CakePlugin::path(Inflector::camelize($pluginName)) . 'Test' . DS . 'Fixture',
127
					TESTS . 'Fixture'
128
				);
129
			} else {
130
				$fixturePaths = array(
131
					TESTS . 'Fixture',
132
					CAKE . 'Test' . DS . 'Fixture'
133
				);
134
			}
135
 
136
			$loaded = false;
137
			foreach ($fixturePaths as $path) {
138
				$className = Inflector::camelize($fixture);
139
				if (is_readable($path . DS . $className . 'Fixture.php')) {
140
					$fixtureFile = $path . DS . $className . 'Fixture.php';
141
					require_once $fixtureFile;
142
					$fixtureClass = $className . 'Fixture';
143
					$this->_loaded[$fixtureIndex] = new $fixtureClass();
144
					$this->_fixtureMap[$fixtureClass] = $this->_loaded[$fixtureIndex];
145
					$loaded = true;
146
					break;
147
				}
148
			}
149
 
150
			if (!$loaded) {
151
				$firstPath = str_replace(array(APP, CAKE_CORE_INCLUDE_PATH, ROOT), '', $fixturePaths[0] . DS . $className . 'Fixture.php');
152
				throw new UnexpectedValueException(__d('cake_dev', 'Referenced fixture class %s (%s) not found', $className, $firstPath));
153
			}
154
		}
155
	}
156
 
157
/**
158
 * Runs the drop and create commands on the fixtures if necessary.
159
 *
160
 * @param CakeTestFixture $fixture the fixture object to create
161
 * @param DataSource $db the datasource instance to use
162
 * @param boolean $drop whether drop the fixture if it is already created or not
163
 * @return void
164
 */
165
	protected function _setupTable($fixture, $db = null, $drop = true) {
166
		if (!$db) {
167
			if (!empty($fixture->useDbConfig)) {
168
				$db = ConnectionManager::getDataSource($fixture->useDbConfig);
169
			} else {
170
				$db = $this->_db;
171
			}
172
		}
173
		if (!empty($fixture->created) && in_array($db->configKeyName, $fixture->created)) {
174
			return;
175
		}
176
 
177
		$sources = (array)$db->listSources();
178
		$table = $db->config['prefix'] . $fixture->table;
179
		$exists = in_array($table, $sources);
180
 
181
		if ($drop && $exists) {
182
			$fixture->drop($db);
183
			$fixture->create($db);
184
		} elseif (!$exists) {
185
			$fixture->create($db);
186
		} else {
187
			$fixture->created[] = $db->configKeyName;
188
		}
189
	}
190
 
191
/**
192
 * Creates the fixtures tables and inserts data on them.
193
 *
194
 * @param CakeTestCase $test the test to inspect for fixture loading
195
 * @return void
196
 */
197
	public function load(CakeTestCase $test) {
198
		if (empty($test->fixtures)) {
199
			return;
200
		}
201
		$fixtures = $test->fixtures;
202
		if (empty($fixtures) || !$test->autoFixtures) {
203
			return;
204
		}
205
 
206
		foreach ($fixtures as $f) {
207
			if (!empty($this->_loaded[$f])) {
208
				$fixture = $this->_loaded[$f];
209
				$db = ConnectionManager::getDataSource($fixture->useDbConfig);
210
				$db->begin();
211
				$this->_setupTable($fixture, $db, $test->dropTables);
212
				$fixture->insert($db);
213
				$db->commit();
214
			}
215
		}
216
	}
217
 
218
/**
219
 * Truncates the fixtures tables
220
 *
221
 * @param CakeTestCase $test the test to inspect for fixture unloading
222
 * @return void
223
 */
224
	public function unload(CakeTestCase $test) {
225
		$fixtures = !empty($test->fixtures) ? $test->fixtures : array();
226
		foreach (array_reverse($fixtures) as $f) {
227
			if (isset($this->_loaded[$f])) {
228
				$fixture = $this->_loaded[$f];
229
				if (!empty($fixture->created)) {
230
					foreach ($fixture->created as $ds) {
231
						$db = ConnectionManager::getDataSource($ds);
232
						$fixture->truncate($db);
233
					}
234
				}
235
			}
236
		}
237
	}
238
 
239
/**
240
 * Creates a single fixture table and loads data into it.
241
 *
242
 * @param string $name of the fixture
243
 * @param DataSource $db DataSource instance or leave null to get DataSource from the fixture
244
 * @param boolean $dropTables Whether or not tables should be dropped and re-created.
245
 * @return void
246
 * @throws UnexpectedValueException if $name is not a previously loaded class
247
 */
248
	public function loadSingle($name, $db = null, $dropTables = true) {
249
		$name .= 'Fixture';
250
		if (isset($this->_fixtureMap[$name])) {
251
			$fixture = $this->_fixtureMap[$name];
252
			if (!$db) {
253
				$db = ConnectionManager::getDataSource($fixture->useDbConfig);
254
			}
255
			$this->_setupTable($fixture, $db, $dropTables);
256
			$fixture->truncate($db);
257
			$fixture->insert($db);
258
		} else {
259
			throw new UnexpectedValueException(__d('cake_dev', 'Referenced fixture class %s not found', $name));
260
		}
261
	}
262
 
263
/**
264
 * Drop all fixture tables loaded by this class
265
 *
266
 * This will also close the session, as failing to do so will cause
267
 * fatal errors with database sessions.
268
 *
269
 * @return void
270
 */
271
	public function shutDown() {
272
		if (session_id()) {
273
			session_write_close();
274
		}
275
		foreach ($this->_loaded as $fixture) {
276
			if (!empty($fixture->created)) {
277
				foreach ($fixture->created as $ds) {
278
					$db = ConnectionManager::getDataSource($ds);
279
					$fixture->drop($db);
280
				}
281
			}
282
		}
283
	}
284
 
285
}