Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Adding ability to generate fixtures from data in app tables, with cus…
…tom conditions. Test cases added.
  • Loading branch information
markstory committed Jul 21, 2009
1 parent 10f5ae2 commit 19eca90
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 17 deletions.
94 changes: 77 additions & 17 deletions cake/console/libs/tasks/fixture.php
Expand Up @@ -144,8 +144,8 @@ function importOptions($modelName) {
}
if ($doRecords == 'n') {
$prompt = sprintf(__("Would you like to build this fixture with data from %s's table?", true), $modelName);
$fromDb = $this->in($prompt, array('y', 'n'), 'n');
if (strtolower($fromDb) == 'y') {
$fromTable = $this->in($prompt, array('y', 'n'), 'n');
if (strtolower($fromTable) == 'y') {
$options['fromTable'] = true;
}
}
Expand All @@ -161,14 +161,13 @@ function importOptions($modelName) {
* @access private
*/
function bake($model, $useTable = false, $importOptions = array()) {
$table = $schema = $records = $import = null;
$table = $schema = $records = $import = $modelImport = $recordImport = null;
if (!$useTable) {
$useTable = Inflector::tableize($model);
} elseif ($useTable != Inflector::tableize($model)) {
$table = $useTable;
}

$modelImport = $import = $recordImport = null;
if (!empty($importOptions)) {
if (isset($importOptions['schema'])) {
$modelImport = "'model' => '{$importOptions['schema']}'";
Expand All @@ -179,7 +178,9 @@ function bake($model, $useTable = false, $importOptions = array()) {
if ($modelImport && $recordImport) {
$modelImport .= ', ';
}
$import = sprintf("array(%s%s)", $modelImport, $recordImport);
if (!empty($modelImport) || !empty($recordImport)) {
$import = sprintf("array(%s%s)", $modelImport, $recordImport);
}
}

$this->_Schema = new CakeSchema();
Expand All @@ -195,12 +196,15 @@ function bake($model, $useTable = false, $importOptions = array()) {
$schema = $this->_generateSchema($tableInfo);
}

if (is_null($recordImport)) {
if (!isset($importOptions['records']) && !isset($importOptions['fromTable'])) {
$recordCount = 1;
if (isset($this->params['count'])) {
$recordCount = $this->params['count'];
}
$records = $this->_generateRecords($tableInfo, $recordCount);
$records = $this->_makeRecordString($this->_generateRecords($tableInfo, $recordCount));
}
if (isset($importOptions['fromTable'])) {
$records = $this->_makeRecordString($this->_getRecordsFromTable($model, $useTable));
}
$out = $this->generateFixtureFile($model, compact('records', 'table', 'schema', 'import', 'fields'));
return $out;
Expand Down Expand Up @@ -265,13 +269,12 @@ function _generateSchema($tableInfo) {
* Generate String representation of Records
*
* @param array $table Table schema array
* @return string
* @return array Array of records to use in the fixture.
**/
function _generateRecords($tableInfo, $recordCount = 1) {
$out = "array(\n";

$records = array();
for ($i = 0; $i < $recordCount; $i++) {
$records = array();
$record = array();
foreach ($tableInfo as $field => $fieldInfo) {
if (empty($fieldInfo['type'])) {
continue;
Expand All @@ -281,9 +284,17 @@ function _generateRecords($tableInfo, $recordCount = 1) {
$insert = $i + 1;
break;
case 'string';
$insert = "Lorem ipsum dolor sit amet";
if (!empty($fieldInfo['length'])) {
$insert = substr($insert, 0, (int)$fieldInfo['length'] - 2);
$isPrimaryUuid = (
isset($fieldInfo['key']) && strtolower($fieldInfo['key']) == 'primary' &&
isset($fieldInfo['length']) && $fieldInfo['length'] == 36
);
if ($isPrimaryUuid) {
$insert = String::uuid();
} else {
$insert = "Lorem ipsum dolor sit amet";
if (!empty($fieldInfo['length'])) {
$insert = substr($insert, 0, (int)$fieldInfo['length'] - 2);
}
}
$insert = "'$insert'";
break;
Expand Down Expand Up @@ -316,15 +327,64 @@ function _generateRecords($tableInfo, $recordCount = 1) {
$insert .= " duis vestibulum nunc mattis convallis.'";
break;
}
$records[] = "\t\t\t'$field' => $insert";
$record[$field] = $insert;
}
$records[] = $record;
}
return $records;
}
/**
* Convert a $records array into a a string.
*
* @param array $records Array of records to be converted to string
* @return string A string value of the $records array.
**/
function _makeRecordString($records) {
$out = "array(\n";
foreach ($records as $record) {
$values = array();
foreach ($record as $field => $value) {
$values[] = "\t\t\t'$field' => $value";
}
$out .= "\t\tarray(\n";
$out .= implode(",\n", $records);
$out .= implode(",\n", $values);
$out .= "\n\t\t),\n";
}
$out .= "\t)";
return $out;
}
/**
* Interact with the user to get a custom SQL condition and use that to extract data
* to build a fixture.
*
* @param string $modelName name of the model to take records from.
* @param string $useTable Name of table to use.
* @return array Array of records.
**/
function _getRecordsFromTable($modelName, $useTable = null) {
$condition = null;
$prompt = __("Please provide a SQL fragment to use as conditions\nExample: WHERE 1=1 LIMIT 10", true);
while (!$condition) {
$condition = $this->in($prompt, null, 'WHERE 1=1 LIMIT 10');
}
App::import('Core', 'Model');
$modelObject =& new Model(array('name' => $modelName, 'table' => $useTable, 'ds' => $this->connection));
$records = $modelObject->find('all', array(
'conditions' => $condition,
'recursive' => -1
));
$db =& $modelObject->getDataSource();
$schema = $modelObject->schema();
$out = array();
foreach ($records as $record) {
$row = array();
foreach ($record[$modelObject->alias] as $field => $value) {
$row[$field] = $db->value($value, $schema[$field]['type']);
}
$out[] = $row;
}
return $out;
}
/**
* Displays help contents
*
Expand All @@ -339,7 +399,7 @@ function help() {
$this->out("\nfixture all\n\tbakes all fixtures.");
$this->out("");
$this->out('Parameters:');
$this->out("\t-count The number of records to include in the fixture(s).");
$this->out("\t-count When using generated data, the number of records to include in the fixture(s).");
$this->out("\t-connection Which database configuration to use for baking.");
$this->out("\t-plugin lowercased_underscored name of plugin to bake fixtures for.");
$this->out("");
Expand Down
18 changes: 18 additions & 0 deletions cake/tests/cases/console/libs/tasks/fixture.test.php
Expand Up @@ -125,6 +125,24 @@ function testImportOptions() {
$expected = array('fromTable' => true);
$this->assertEqual($result, $expected);
}
/**
* test generating a fixture with database conditions.
*
* @return void
**/
function testImportRecordsFromDatabaseWithConditions() {
$this->Task->setReturnValueAt(0, 'in', 'WHERE 1=1 LIMIT 10');
$this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/';
$result = $this->Task->bake('Article', false, array('fromTable' => true, 'schema' => 'Article', 'records' => false));
debug($result, true);
$this->assertPattern('/class ArticleFixture extends CakeTestFixture/', $result);
$this->assertPattern('/var \$records/', $result);
$this->assertPattern('/var \$import/', $result);
$this->assertPattern("/'title' => 'First Article'/", $result, 'Missing import data %s');
$this->assertPattern('/Second Article/', $result, 'Missing import data %s');
$this->assertPattern('/Third Article/', $result, 'Missing import data %s');
}
/**
* test that execute passes runs bake depending with named model.
*
Expand Down

0 comments on commit 19eca90

Please sign in to comment.