1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
18:
19: App::uses('ConnectionManager', 'Model');
20: App::uses('ClassRegistry', 'Utility');
21:
22: 23: 24: 25: 26:
27: class CakeFixtureManager {
28:
29: 30: 31: 32: 33:
34: protected $_initialized = false;
35:
36: 37: 38: 39: 40:
41: protected $_db = null;
42:
43: 44: 45: 46: 47:
48: protected $_loaded = array();
49:
50: 51: 52: 53: 54:
55: protected $_fixtureMap = array();
56:
57: 58: 59: 60: 61: 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: 85: 86: 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: 100: 101: 102: 103: 104:
105: protected function _parseFixturePath($fixturePath) {
106: $pathTokenArray = explode('/', $fixturePath);
107: $fixture = array_pop($pathTokenArray);
108: $additionalPath = '';
109: foreach ($pathTokenArray as $pathToken) {
110: $additionalPath .= DS . $pathToken;
111: }
112: return array('fixture' => $fixture, 'additionalPath' => $additionalPath);
113: }
114:
115: 116: 117: 118: 119: 120: 121:
122: protected function _loadFixtures($fixtures) {
123: foreach ($fixtures as $fixture) {
124: $fixtureFile = null;
125: $fixtureIndex = $fixture;
126: if (isset($this->_loaded[$fixture])) {
127: continue;
128: }
129:
130: if (strpos($fixture, 'core.') === 0) {
131: $fixture = substr($fixture, strlen('core.'));
132: $fixturePaths[] = CAKE . 'Test' . DS . 'Fixture';
133: } elseif (strpos($fixture, 'app.') === 0) {
134: $fixturePrefixLess = substr($fixture, strlen('app.'));
135: $fixtureParsedPath = $this->_parseFixturePath($fixturePrefixLess);
136: $fixture = $fixtureParsedPath['fixture'];
137: $fixturePaths = array(
138: TESTS . 'Fixture' . $fixtureParsedPath['additionalPath']
139: );
140: } elseif (strpos($fixture, 'plugin.') === 0) {
141: $explodedFixture = explode('.', $fixture, 3);
142: $pluginName = $explodedFixture[1];
143: $fixtureParsedPath = $this->_parseFixturePath($explodedFixture[2]);
144: $fixture = $fixtureParsedPath['fixture'];
145: $fixturePaths = array(
146: CakePlugin::path(Inflector::camelize($pluginName)) . 'Test' . DS . 'Fixture' . $fixtureParsedPath['additionalPath'],
147: TESTS . 'Fixture' . $fixtureParsedPath['additionalPath']
148: );
149: } else {
150: $fixturePaths = array(
151: TESTS . 'Fixture',
152: CAKE . 'Test' . DS . 'Fixture'
153: );
154: }
155:
156: $loaded = false;
157: foreach ($fixturePaths as $path) {
158: $className = Inflector::camelize($fixture);
159: if (is_readable($path . DS . $className . 'Fixture.php')) {
160: $fixtureFile = $path . DS . $className . 'Fixture.php';
161: require_once $fixtureFile;
162: $fixtureClass = $className . 'Fixture';
163: $this->_loaded[$fixtureIndex] = new $fixtureClass();
164: $this->_fixtureMap[$fixtureClass] = $this->_loaded[$fixtureIndex];
165: $loaded = true;
166: break;
167: }
168: }
169:
170: if (!$loaded) {
171: $firstPath = str_replace(array(APP, CAKE_CORE_INCLUDE_PATH, ROOT), '', $fixturePaths[0] . DS . $className . 'Fixture.php');
172: throw new UnexpectedValueException(__d('cake_dev', 'Referenced fixture class %s (%s) not found', $className, $firstPath));
173: }
174: }
175: }
176:
177: 178: 179: 180: 181: 182: 183: 184:
185: protected function _setupTable($fixture, $db = null, $drop = true) {
186: if (!$db) {
187: if (!empty($fixture->useDbConfig)) {
188: $db = ConnectionManager::getDataSource($fixture->useDbConfig);
189: } else {
190: $db = $this->_db;
191: }
192: }
193: if (!empty($fixture->created) && in_array($db->configKeyName, $fixture->created)) {
194: return;
195: }
196:
197: $sources = (array)$db->listSources();
198: $table = $db->config['prefix'] . $fixture->table;
199: $exists = in_array($table, $sources);
200:
201: if ($drop && $exists) {
202: $fixture->drop($db);
203: $fixture->create($db);
204: } elseif (!$exists) {
205: $fixture->create($db);
206: } else {
207: $fixture->created[] = $db->configKeyName;
208: }
209: }
210:
211: 212: 213: 214: 215: 216:
217: public function load(CakeTestCase $test) {
218: if (empty($test->fixtures)) {
219: return;
220: }
221: $fixtures = $test->fixtures;
222: if (empty($fixtures) || !$test->autoFixtures) {
223: return;
224: }
225:
226: foreach ($fixtures as $f) {
227: if (!empty($this->_loaded[$f])) {
228: $fixture = $this->_loaded[$f];
229: $db = ConnectionManager::getDataSource($fixture->useDbConfig);
230: $db->begin();
231: $this->_setupTable($fixture, $db, $test->dropTables);
232: $fixture->truncate($db);
233: $fixture->insert($db);
234: $db->commit();
235: }
236: }
237: }
238:
239: 240: 241: 242: 243: 244:
245: public function unload(CakeTestCase $test) {
246: $fixtures = !empty($test->fixtures) ? $test->fixtures : array();
247: foreach (array_reverse($fixtures) as $f) {
248: if (isset($this->_loaded[$f])) {
249: $fixture = $this->_loaded[$f];
250: if (!empty($fixture->created)) {
251: foreach ($fixture->created as $ds) {
252: $db = ConnectionManager::getDataSource($ds);
253: $fixture->truncate($db);
254: }
255: }
256: }
257: }
258: }
259:
260: 261: 262: 263: 264: 265: 266: 267: 268:
269: public function loadSingle($name, $db = null, $dropTables = true) {
270: $name .= 'Fixture';
271: if (isset($this->_fixtureMap[$name])) {
272: $fixture = $this->_fixtureMap[$name];
273: if (!$db) {
274: $db = ConnectionManager::getDataSource($fixture->useDbConfig);
275: }
276: $this->_setupTable($fixture, $db, $dropTables);
277: $fixture->truncate($db);
278: $fixture->insert($db);
279: } else {
280: throw new UnexpectedValueException(__d('cake_dev', 'Referenced fixture class %s not found', $name));
281: }
282: }
283:
284: 285: 286: 287: 288: 289: 290: 291:
292: public function shutDown() {
293: if (session_id()) {
294: session_write_close();
295: }
296: foreach ($this->_loaded as $fixture) {
297: if (!empty($fixture->created)) {
298: foreach ($fixture->created as $ds) {
299: $db = ConnectionManager::getDataSource($ds);
300: $fixture->drop($db);
301: }
302: }
303: }
304: }
305:
306: }
307: