1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16:
17: App::uses('CakeSchema', 'Model');
18:
19: 20: 21: 22: 23: 24:
25: class CakeTestFixture {
26:
27: 28: 29: 30: 31:
32: public $name = null;
33:
34: 35: 36: 37: 38:
39: public $db = null;
40:
41: 42: 43: 44: 45:
46: public $useDbConfig = 'test';
47:
48: 49: 50: 51: 52:
53: public $table = null;
54:
55: 56: 57: 58: 59:
60: public $created = array();
61:
62: 63: 64: 65: 66: 67:
68: public $fields = array();
69:
70: 71: 72: 73: 74:
75: public $records = array();
76:
77: 78: 79: 80: 81:
82: public $primaryKey = null;
83:
84: 85: 86: 87: 88: 89: 90:
91: public $canUseMemory = true;
92:
93: 94: 95: 96: 97:
98: public function __construct() {
99: if ($this->name === null) {
100: if (preg_match('/^(.*)Fixture$/', get_class($this), $matches)) {
101: $this->name = $matches[1];
102: } else {
103: $this->name = get_class($this);
104: }
105: }
106: $connection = 'test';
107: if (!empty($this->useDbConfig)) {
108: $connection = $this->useDbConfig;
109: if (strpos($connection, 'test') !== 0) {
110: $message = __d(
111: 'cake_dev',
112: 'Invalid datasource name "%s" for "%s" fixture. Fixture datasource names must begin with "test".',
113: $connection,
114: $this->name
115: );
116: throw new CakeException($message);
117: }
118: }
119: $this->Schema = new CakeSchema(array('name' => 'TestSuite', 'connection' => $connection));
120: $this->init();
121: }
122:
123: 124: 125: 126: 127: 128:
129: public function init() {
130: if (isset($this->import) && (is_string($this->import) || is_array($this->import))) {
131: $import = array_merge(
132: array('connection' => 'default', 'records' => false),
133: is_array($this->import) ? $this->import : array('model' => $this->import)
134: );
135:
136: $this->Schema->connection = $import['connection'];
137: if (isset($import['model'])) {
138: list($plugin, $modelClass) = pluginSplit($import['model'], true);
139: App::uses($modelClass, $plugin . 'Model');
140: if (!class_exists($modelClass)) {
141: throw new MissingModelException(array('class' => $modelClass));
142: }
143: $model = new $modelClass(null, null, $import['connection']);
144: $db = $model->getDataSource();
145: if (empty($model->tablePrefix)) {
146: $model->tablePrefix = $db->config['prefix'];
147: }
148: $this->fields = $model->schema(true);
149: $this->fields[$model->primaryKey]['key'] = 'primary';
150: $this->table = $db->fullTableName($model, false, false);
151: $this->primaryKey = $model->primaryKey;
152: ClassRegistry::config(array('ds' => 'test'));
153: ClassRegistry::flush();
154: } elseif (isset($import['table'])) {
155: $model = new Model(null, $import['table'], $import['connection']);
156: $db = ConnectionManager::getDataSource($import['connection']);
157: $db->cacheSources = false;
158: $model->useDbConfig = $import['connection'];
159: $model->name = Inflector::camelize(Inflector::singularize($import['table']));
160: $model->table = $import['table'];
161: $model->tablePrefix = $db->config['prefix'];
162: $this->fields = $model->schema(true);
163: $this->primaryKey = $model->primaryKey;
164: ClassRegistry::flush();
165: }
166:
167: if (!empty($db->config['prefix']) && strpos($this->table, $db->config['prefix']) === 0) {
168: $this->table = str_replace($db->config['prefix'], '', $this->table);
169: }
170:
171: if (isset($import['records']) && $import['records'] !== false && isset($model) && isset($db)) {
172: $this->records = array();
173: $query = array(
174: 'fields' => $db->fields($model, null, array_keys($this->fields)),
175: 'table' => $db->fullTableName($model),
176: 'alias' => $model->alias,
177: 'conditions' => array(),
178: 'order' => null,
179: 'limit' => null,
180: 'group' => null
181: );
182: $records = $db->fetchAll($db->buildStatement($query, $model), false, $model->alias);
183:
184: if ($records !== false && !empty($records)) {
185: $this->records = Hash::extract($records, '{n}.' . $model->alias);
186: }
187: }
188: }
189:
190: if (!isset($this->table)) {
191: $this->table = Inflector::underscore(Inflector::pluralize($this->name));
192: }
193:
194: if (!isset($this->primaryKey) && isset($this->fields['id'])) {
195: $this->primaryKey = 'id';
196: }
197: }
198:
199: 200: 201: 202: 203: 204:
205: public function create($db) {
206: if (!isset($this->fields) || empty($this->fields)) {
207: return false;
208: }
209:
210: if (empty($this->fields['tableParameters']['engine'])) {
211: $canUseMemory = $this->canUseMemory;
212: foreach ($this->fields as $args) {
213:
214: if (is_string($args)) {
215: $type = $args;
216: } elseif (!empty($args['type'])) {
217: $type = $args['type'];
218: } else {
219: continue;
220: }
221:
222: if (in_array($type, array('blob', 'text', 'binary'))) {
223: $canUseMemory = false;
224: break;
225: }
226: }
227:
228: if ($canUseMemory) {
229: $this->fields['tableParameters']['engine'] = 'MEMORY';
230: }
231: }
232: $this->Schema->build(array($this->table => $this->fields));
233: try {
234: $db->execute($db->createSchema($this->Schema), array('log' => false));
235: $this->created[] = $db->configKeyName;
236: } catch (Exception $e) {
237: $msg = __d(
238: 'cake_dev',
239: 'Fixture creation for "%s" failed "%s"',
240: $this->table,
241: $e->getMessage()
242: );
243: CakeLog::error($msg);
244: trigger_error($msg, E_USER_WARNING);
245: return false;
246: }
247: return true;
248: }
249:
250: 251: 252: 253: 254: 255:
256: public function drop($db) {
257: if (empty($this->fields)) {
258: return false;
259: }
260: $this->Schema->build(array($this->table => $this->fields));
261: try {
262:
263: $db->execute($db->dropSchema($this->Schema), array('log' => false));
264: $this->created = array_diff($this->created, array($db->configKeyName));
265: } catch (Exception $e) {
266: return false;
267: }
268: return true;
269: }
270:
271: 272: 273: 274: 275: 276: 277: 278:
279: public function insert($db) {
280: if (!isset($this->_insert)) {
281: $values = array();
282: if (isset($this->records) && !empty($this->records)) {
283: $fields = array();
284: foreach ($this->records as $record) {
285: $fields = array_merge($fields, array_keys(array_intersect_key($record, $this->fields)));
286: }
287: $fields = array_unique($fields);
288: $default = array_fill_keys($fields, null);
289: foreach ($this->records as $record) {
290: $mergeData = array_merge($default, $record);
291: $merge = array_values($mergeData);
292: if (count($fields) !== count($merge)) {
293:
294: $mergeFields = array_diff_key(array_keys($mergeData), $fields);
295:
296: $message = 'Fixture invalid: Count of fields does not match count of values in ' . get_class($this) . "\n";
297: foreach ($mergeFields as $field) {
298: $message .= "The field '" . $field . "' is in the data fixture but not in the schema." . "\n";
299: }
300:
301: throw new CakeException($message);
302: }
303: $values[] = $merge;
304: }
305: $nested = $db->useNestedTransactions;
306: $db->useNestedTransactions = false;
307: $result = $db->insertMulti($this->table, $fields, $values);
308: if ($this->primaryKey &&
309: isset($this->fields[$this->primaryKey]['type']) &&
310: in_array($this->fields[$this->primaryKey]['type'], array('integer', 'biginteger'))
311: ) {
312: $db->resetSequence($this->table, $this->primaryKey);
313: }
314: $db->useNestedTransactions = $nested;
315: return $result;
316: }
317: return true;
318: }
319: }
320:
321: 322: 323: 324: 325: 326: 327:
328: public function truncate($db) {
329: $fullDebug = $db->fullDebug;
330: $db->fullDebug = false;
331: $return = $db->truncate($this->table);
332: $db->fullDebug = $fullDebug;
333: return $return;
334: }
335:
336: }
337: