PageRenderTime 27ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Cake/TestSuite/Fixture/CakeFixtureManager.php

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