2009-04-29 00:32:15 +00:00
< ? php
/**
2009-07-17 03:55:41 +00:00
* The FixtureTask handles creating and updating fixture files .
2009-04-29 00:32:15 +00:00
*
2010-10-03 16:38:58 +00:00
* PHP 5
2009-04-29 00:32:15 +00:00
*
2009-11-06 06:46:59 +00:00
* CakePHP ( tm ) : Rapid Development Framework ( http :// cakephp . org )
2010-10-24 20:58:22 +00:00
* Copyright 2005 - 2010 , Cake Software Foundation , Inc .
2009-04-29 00:32:15 +00:00
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice .
*
2010-10-24 20:58:22 +00:00
* @ copyright Copyright 2005 - 2010 , Cake Software Foundation , Inc . ( http :// cakefoundation . org )
2009-11-06 06:00:11 +00:00
* @ link http :// cakephp . org CakePHP ( tm ) Project
2010-12-24 19:26:26 +00:00
* @ package cake . console . shells . tasks
2009-04-29 00:32:15 +00:00
* @ since CakePHP ( tm ) v 1.3
2009-11-06 06:51:51 +00:00
* @ license MIT License ( http :// www . opensource . org / licenses / mit - license . php )
2009-04-29 00:32:15 +00:00
*/
2010-12-08 00:20:56 +00:00
App :: uses ( 'BakeTask' , 'Console/Command/Task' );
2010-12-09 03:45:18 +00:00
App :: uses ( 'Model' , 'Model' );
2010-12-08 00:20:56 +00:00
2009-04-29 00:32:15 +00:00
/**
* Task class for creating and updating fixtures files .
*
2010-12-24 19:26:26 +00:00
* @ package cake . console . shells . tasks
2009-04-29 00:32:15 +00:00
*/
2010-03-05 02:30:26 +00:00
class FixtureTask extends BakeTask {
2009-07-24 19:18:37 +00:00
2009-04-29 00:32:15 +00:00
/**
* Tasks to be loaded by this Task
*
* @ var array
* @ access public
*/
2010-04-04 07:14:00 +00:00
public $tasks = array ( 'DbConfig' , 'Model' , 'Template' );
2009-07-24 19:18:37 +00:00
2009-04-29 00:32:15 +00:00
/**
* path to fixtures directory
*
* @ var string
* @ access public
*/
2010-04-04 07:14:00 +00:00
public $path = null ;
2009-07-24 19:18:37 +00:00
2009-07-20 04:59:18 +00:00
/**
* Schema instance
*
* @ var object
2009-12-30 03:50:43 +00:00
* @ access protected
2009-11-14 12:19:25 +00:00
*/
2010-04-04 06:36:12 +00:00
protected $_Schema = null ;
2009-07-24 19:18:37 +00:00
2009-04-29 00:32:15 +00:00
/**
* Override initialize
*
*/
2010-10-24 19:27:44 +00:00
public function __construct ( $stdout = null , $stderr = null , $stdin = null ) {
parent :: __construct ( $stdout , $stderr , $stdin );
2011-04-11 01:26:06 +00:00
$this -> path = APP . 'tests' . DS . 'Fixture' . DS ;
2009-04-29 00:32:15 +00:00
}
2009-07-24 19:18:37 +00:00
2010-10-12 04:04:10 +00:00
/**
* get the option parser .
*
* @ return void
*/
public function getOptionParser () {
$parser = parent :: getOptionParser ();
return $parser -> description (
2011-03-19 17:32:35 +00:00
__d ( 'cake_console' , 'Generate fixtures for use with the test suite. You can use `bake fixture all` to bake all fixtures.' )
2010-10-12 04:04:10 +00:00
) -> addArgument ( 'name' , array (
2011-03-19 17:32:35 +00:00
'help' => __d ( 'cake_console' , 'Name of the fixture to bake. Can use Plugin.name to bake plugin fixtures.' )
2010-10-12 04:04:10 +00:00
)) -> addOption ( 'count' , array (
2011-03-19 17:32:35 +00:00
'help' => __d ( 'cake_console' , 'When using generated data, the number of records to include in the fixture(s).' ),
2010-10-12 04:04:10 +00:00
'short' => 'n' ,
'default' => 10
)) -> addOption ( 'connection' , array (
2011-03-19 17:32:35 +00:00
'help' => __d ( 'cake_console' , 'Which database configuration to use for baking.' ),
2010-10-12 04:04:10 +00:00
'short' => 'c' ,
'default' => 'default'
)) -> addOption ( 'plugin' , array (
2011-03-19 17:32:35 +00:00
'help' => __d ( 'cake_console' , 'CamelCased name of the plugin to bake fixtures for.' ),
2010-10-12 04:04:10 +00:00
'short' => 'p' ,
)) -> addOption ( 'records' , array (
2011-04-25 19:17:59 +00:00
'help' => __d ( 'cake_console' , 'Used with --count and <name>/all commands to pull [n] records from the live tables, where [n] is either --count or the default of 10' ),
2010-10-12 04:04:10 +00:00
'short' => 'r' ,
'boolean' => true
2011-03-19 17:32:35 +00:00
)) -> epilog ( __d ( 'cake_console' , 'Omitting all arguments and options will enter into an interactive mode.' ));;
2009-04-29 00:32:15 +00:00
}
2009-07-24 19:18:37 +00:00
2009-04-29 00:32:15 +00:00
/**
* Execution method always used for tasks
2011-04-25 19:17:59 +00:00
* Handles dispatching to interactive , named , or all processeses .
2009-04-29 00:32:15 +00:00
*
2010-04-24 01:57:59 +00:00
* @ return void
2009-04-29 00:32:15 +00:00
*/
2010-04-05 03:19:38 +00:00
public function execute () {
2010-10-19 03:09:23 +00:00
parent :: execute ();
2009-04-29 00:32:15 +00:00
if ( empty ( $this -> args )) {
2010-04-24 01:57:59 +00:00
$this -> _interactive ();
2009-04-29 00:32:15 +00:00
}
if ( isset ( $this -> args [ 0 ])) {
2009-10-24 18:32:56 +00:00
$this -> interactive = false ;
2009-05-08 03:59:43 +00:00
if ( ! isset ( $this -> connection )) {
$this -> connection = 'default' ;
}
2009-04-29 00:32:15 +00:00
if ( strtolower ( $this -> args [ 0 ]) == 'all' ) {
return $this -> all ();
}
2010-03-06 02:30:58 +00:00
$model = $this -> _modelName ( $this -> args [ 0 ]);
2009-05-08 03:59:43 +00:00
$this -> bake ( $model );
2009-04-29 00:32:15 +00:00
}
}
2009-07-24 19:18:37 +00:00
2009-04-29 00:32:15 +00:00
/**
* Bake All the Fixtures at once . Will only bake fixtures for models that exist .
*
* @ return void
2009-11-14 12:19:25 +00:00
*/
2010-04-24 01:57:59 +00:00
public function all () {
2009-04-30 02:50:43 +00:00
$this -> interactive = false ;
2009-10-24 18:32:56 +00:00
$this -> Model -> interactive = false ;
2009-05-04 01:43:22 +00:00
$tables = $this -> Model -> listAll ( $this -> connection , false );
2009-04-30 02:50:43 +00:00
foreach ( $tables as $table ) {
$model = $this -> _modelName ( $table );
$this -> bake ( $model );
}
2009-04-29 00:32:15 +00:00
}
2009-07-24 19:18:37 +00:00
2009-04-29 00:32:15 +00:00
/**
* Interactive baking function
*
2010-04-24 01:57:59 +00:00
* @ return void
2009-04-29 00:32:15 +00:00
*/
2010-04-24 01:57:59 +00:00
protected function _interactive () {
2010-03-09 02:18:53 +00:00
$this -> DbConfig -> interactive = $this -> Model -> interactive = $this -> interactive = true ;
2009-04-29 00:45:07 +00:00
$this -> hr ();
2011-04-25 19:17:59 +00:00
$this -> out ( __d ( 'cake_console' , " Bake Fixture \n Path: %s " , $this -> path ));
2009-04-29 00:45:07 +00:00
$this -> hr ();
2009-05-04 01:43:22 +00:00
if ( ! isset ( $this -> connection )) {
$this -> connection = $this -> DbConfig -> getConfig ();
}
$modelName = $this -> Model -> getName ( $this -> connection );
$useTable = $this -> Model -> getTable ( $modelName , $this -> connection );
2009-04-30 00:52:12 +00:00
$importOptions = $this -> importOptions ( $modelName );
$this -> bake ( $modelName , $useTable , $importOptions );
}
2009-07-24 19:18:37 +00:00
2009-04-30 00:52:12 +00:00
/**
* Interacts with the User to setup an array of import options . For a fixture .
*
* @ param string $modelName Name of model you are dealing with .
* @ return array Array of import options .
2009-11-14 12:19:25 +00:00
*/
2010-04-05 03:19:38 +00:00
public function importOptions ( $modelName ) {
2009-04-30 00:52:12 +00:00
$options = array ();
2011-03-19 17:32:35 +00:00
$doSchema = $this -> in ( __d ( 'cake_console' , 'Would you like to import schema for this fixture?' ), array ( 'y' , 'n' ), 'n' );
2009-04-30 00:52:12 +00:00
if ( $doSchema == 'y' ) {
$options [ 'schema' ] = $modelName ;
}
2011-03-19 17:32:35 +00:00
$doRecords = $this -> in ( __d ( 'cake_console' , 'Would you like to use record importing for this fixture?' ), array ( 'y' , 'n' ), 'n' );
2009-04-30 00:52:12 +00:00
if ( $doRecords == 'y' ) {
$options [ 'records' ] = true ;
}
2009-07-20 04:59:18 +00:00
if ( $doRecords == 'n' ) {
2011-03-19 17:32:35 +00:00
$prompt = __d ( 'cake_console' , " Would you like to build this fixture with data from %s's table? " , $modelName );
2009-07-21 04:00:39 +00:00
$fromTable = $this -> in ( $prompt , array ( 'y' , 'n' ), 'n' );
if ( strtolower ( $fromTable ) == 'y' ) {
2009-07-20 04:59:18 +00:00
$options [ 'fromTable' ] = true ;
}
}
2009-04-30 00:52:12 +00:00
return $options ;
2009-04-29 00:32:15 +00:00
}
2009-07-24 19:18:37 +00:00
2009-04-29 00:32:15 +00:00
/**
* Assembles and writes a Fixture file
*
2009-04-30 00:52:12 +00:00
* @ param string $model Name of model to bake .
* @ param string $useTable Name of table to use .
2010-04-04 07:14:00 +00:00
* @ param array $importOptions Options for public $import
2009-12-30 03:50:43 +00:00
* @ return string Baked fixture content
2009-04-29 00:32:15 +00:00
*/
2010-04-05 03:19:38 +00:00
public function bake ( $model , $useTable = false , $importOptions = array ()) {
2010-12-09 03:45:18 +00:00
App :: uses ( 'CakeSchema' , 'Model' );
2010-12-31 18:05:04 +00:00
$table = $schema = $records = $import = $modelImport = null ;
$importBits = array ();
2009-04-30 00:52:12 +00:00
if ( ! $useTable ) {
$useTable = Inflector :: tableize ( $model );
} elseif ( $useTable != Inflector :: tableize ( $model )) {
2009-05-11 02:16:38 +00:00
$table = $useTable ;
2009-04-30 00:52:12 +00:00
}
if ( ! empty ( $importOptions )) {
if ( isset ( $importOptions [ 'schema' ])) {
2010-12-31 18:05:04 +00:00
$modelImport = true ;
$importBits [] = " 'model' => ' { $importOptions [ 'schema' ] } ' " ;
2009-04-30 00:52:12 +00:00
}
if ( isset ( $importOptions [ 'records' ])) {
2010-12-31 18:05:04 +00:00
$importBits [] = " 'records' => true " ;
2009-05-04 01:43:22 +00:00
}
2010-12-31 18:05:04 +00:00
if ( $this -> connection != 'default' ) {
$importBits [] .= " 'connection' => ' { $this -> connection } ' " ;
2009-04-30 00:52:12 +00:00
}
2010-12-31 18:05:04 +00:00
if ( ! empty ( $importBits )) {
$import = sprintf ( " array(%s) " , implode ( ', ' , $importBits ));
2009-07-21 04:00:39 +00:00
}
2009-04-30 00:52:12 +00:00
}
$this -> _Schema = new CakeSchema ();
2009-05-04 01:43:22 +00:00
$data = $this -> _Schema -> read ( array ( 'models' => false , 'connection' => $this -> connection ));
2009-04-30 00:52:12 +00:00
if ( ! isset ( $data [ 'tables' ][ $useTable ])) {
$this -> err ( 'Could not find your selected table ' . $useTable );
return false ;
}
$tableInfo = $data [ 'tables' ][ $useTable ];
if ( is_null ( $modelImport )) {
2009-05-11 02:16:38 +00:00
$schema = $this -> _generateSchema ( $tableInfo );
2009-04-30 00:52:12 +00:00
}
2009-07-21 04:00:39 +00:00
if ( ! isset ( $importOptions [ 'records' ]) && ! isset ( $importOptions [ 'fromTable' ])) {
2009-04-30 00:52:12 +00:00
$recordCount = 1 ;
if ( isset ( $this -> params [ 'count' ])) {
$recordCount = $this -> params [ 'count' ];
}
2009-07-21 04:00:39 +00:00
$records = $this -> _makeRecordString ( $this -> _generateRecords ( $tableInfo , $recordCount ));
}
2009-10-24 18:32:56 +00:00
if ( isset ( $this -> params [ 'records' ]) || isset ( $importOptions [ 'fromTable' ])) {
2009-07-21 04:00:39 +00:00
$records = $this -> _makeRecordString ( $this -> _getRecordsFromTable ( $model , $useTable ));
2009-04-30 00:52:12 +00:00
}
2009-05-11 02:16:38 +00:00
$out = $this -> generateFixtureFile ( $model , compact ( 'records' , 'table' , 'schema' , 'import' , 'fields' ));
2009-05-04 01:43:22 +00:00
return $out ;
}
2009-07-24 19:18:37 +00:00
2009-05-04 01:43:22 +00:00
/**
* Generate the fixture file , and write to disk
*
* @ param string $model name of the model being generated
* @ param string $fixture Contents of the fixture file .
2009-12-30 03:50:43 +00:00
* @ return string Content saved into fixture file .
2009-11-14 12:19:25 +00:00
*/
2010-04-05 03:19:38 +00:00
public function generateFixtureFile ( $model , $otherVars ) {
2009-05-11 02:16:38 +00:00
$defaults = array ( 'table' => null , 'schema' => null , 'records' => null , 'import' => null , 'fields' => null );
$vars = array_merge ( $defaults , $otherVars );
2009-06-07 00:03:04 +00:00
2010-03-05 02:57:48 +00:00
$path = $this -> getPath ();
2011-04-11 01:26:06 +00:00
$filename = Inflector :: camelize ( $model ) . 'Fixture.php' ;
2009-05-11 02:16:38 +00:00
2009-05-13 01:26:37 +00:00
$this -> Template -> set ( 'model' , $model );
$this -> Template -> set ( $vars );
2009-07-01 04:50:38 +00:00
$content = $this -> Template -> generate ( 'classes' , 'fixture' );
2009-05-11 02:16:38 +00:00
2011-04-25 19:17:59 +00:00
$this -> out ( " \n " . __d ( 'cake_console' , 'Baking test fixture for %s...' , $model ), 1 , Shell :: QUIET );
2009-04-30 00:52:12 +00:00
$this -> createFile ( $path . $filename , $content );
2009-05-11 02:16:38 +00:00
return $content ;
2009-04-30 00:52:12 +00:00
}
2009-07-24 19:18:37 +00:00
2010-03-05 02:57:48 +00:00
/**
* Get the path to the fixtures .
*
2010-04-24 01:57:59 +00:00
* @ return string Path for the fixtures
2010-03-05 02:57:48 +00:00
*/
2010-04-24 01:57:59 +00:00
public function getPath () {
2010-03-05 02:57:48 +00:00
$path = $this -> path ;
if ( isset ( $this -> plugin )) {
2011-04-11 01:26:06 +00:00
$path = $this -> _pluginPath ( $this -> plugin ) . 'tests' . DS . 'Fixture' . DS ;
2010-03-05 02:57:48 +00:00
}
return $path ;
}
2009-04-30 00:52:12 +00:00
/**
* Generates a string representation of a schema .
*
* @ param array $table Table schema array
* @ return string fields definitions
2009-11-14 12:19:25 +00:00
*/
2010-04-05 03:21:28 +00:00
protected function _generateSchema ( $tableInfo ) {
2009-10-22 17:11:30 +00:00
$schema = $this -> _Schema -> generateTable ( 'f' , $tableInfo );
return substr ( $schema , 10 , - 2 );
2009-04-30 00:52:12 +00:00
}
2009-07-24 19:18:37 +00:00
2009-04-30 00:52:12 +00:00
/**
* Generate String representation of Records
*
* @ param array $table Table schema array
2009-07-21 04:00:39 +00:00
* @ return array Array of records to use in the fixture .
2009-11-14 12:19:25 +00:00
*/
2010-04-05 03:21:28 +00:00
protected function _generateRecords ( $tableInfo , $recordCount = 1 ) {
2009-07-21 04:00:39 +00:00
$records = array ();
2009-04-30 00:52:12 +00:00
for ( $i = 0 ; $i < $recordCount ; $i ++ ) {
2009-07-21 04:00:39 +00:00
$record = array ();
2009-04-30 00:52:12 +00:00
foreach ( $tableInfo as $field => $fieldInfo ) {
if ( empty ( $fieldInfo [ 'type' ])) {
continue ;
}
switch ( $fieldInfo [ 'type' ]) {
case 'integer' :
2009-11-09 03:22:08 +00:00
case 'float' :
2009-04-30 00:52:12 +00:00
$insert = $i + 1 ;
break ;
2009-11-09 03:22:08 +00:00
case 'string' :
case 'binary' :
2009-07-21 04:00:39 +00:00
$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 );
}
2009-04-30 00:52:12 +00:00
}
$insert = " ' $insert ' " ;
break ;
2009-04-30 02:50:43 +00:00
case 'timestamp' :
$ts = time ();
$insert = " ' $ts ' " ;
break ;
2009-04-30 00:52:12 +00:00
case 'datetime' :
$ts = date ( 'Y-m-d H:i:s' );
$insert = " ' $ts ' " ;
break ;
case 'date' :
$ts = date ( 'Y-m-d' );
$insert = " ' $ts ' " ;
break ;
case 'time' :
$ts = date ( 'H:i:s' );
$insert = " ' $ts ' " ;
break ;
case 'boolean' :
$insert = 1 ;
break ;
case 'text' :
$insert = " 'Lorem ipsum dolor sit amet, aliquet feugiat. " ;
$insert .= " Convallis morbi fringilla gravida, " ;
$insert .= " phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin " ;
$insert .= " venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla " ;
$insert .= " vestibulum massa neque ut et, id hendrerit sit, " ;
$insert .= " feugiat in taciti enim proin nibh, tempor dignissim, rhoncus " ;
$insert .= " duis vestibulum nunc mattis convallis.' " ;
break ;
}
2009-07-21 04:00:39 +00:00
$record [ $field ] = $insert ;
}
$records [] = $record ;
}
return $records ;
}
2009-07-24 19:18:37 +00:00
2009-07-21 04:00:39 +00:00
/**
* 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 .
2009-11-14 12:19:25 +00:00
*/
2010-04-05 03:21:28 +00:00
protected function _makeRecordString ( $records ) {
2009-07-21 04:00:39 +00:00
$out = " array( \n " ;
foreach ( $records as $record ) {
$values = array ();
foreach ( $record as $field => $value ) {
$values [] = " \t \t \t ' $field ' => $value " ;
2009-04-30 00:52:12 +00:00
}
$out .= " \t \t array( \n " ;
2009-07-21 04:00:39 +00:00
$out .= implode ( " , \n " , $values );
2009-04-30 00:52:12 +00:00
$out .= " \n \t \t ), \n " ;
}
2009-05-11 02:16:38 +00:00
$out .= " \t ) " ;
2009-04-30 00:52:12 +00:00
return $out ;
2009-04-29 00:32:15 +00:00
}
2009-07-24 19:18:37 +00:00
2009-07-21 04:00:39 +00:00
/**
* Interact with the user to get a custom SQL condition and use that to extract data
* to build a fixture .
2009-07-24 19:18:37 +00:00
*
2009-07-21 04:00:39 +00:00
* @ param string $modelName name of the model to take records from .
* @ param string $useTable Name of table to use .
* @ return array Array of records .
2009-11-14 12:19:25 +00:00
*/
2010-04-05 03:21:28 +00:00
protected function _getRecordsFromTable ( $modelName , $useTable = null ) {
2009-10-24 18:32:56 +00:00
if ( $this -> interactive ) {
$condition = null ;
2011-03-19 17:32:35 +00:00
$prompt = __d ( 'cake_console' , " Please provide a SQL fragment to use as conditions \n Example: WHERE 1=1 LIMIT 10 " );
2009-10-24 18:32:56 +00:00
while ( ! $condition ) {
$condition = $this -> in ( $prompt , null , 'WHERE 1=1 LIMIT 10' );
}
} else {
2010-03-23 02:26:32 +00:00
$condition = 'WHERE 1=1 LIMIT ' . ( isset ( $this -> params [ 'count' ]) ? $this -> params [ 'count' ] : 10 );
2009-07-21 04:00:39 +00:00
}
2010-11-13 04:05:44 +00:00
$modelObject = new Model ( array ( 'name' => $modelName , 'table' => $useTable , 'ds' => $this -> connection ));
2009-07-21 04:00:39 +00:00
$records = $modelObject -> find ( 'all' , array (
'conditions' => $condition ,
'recursive' => - 1
));
2010-11-13 04:05:44 +00:00
$db = ConnectionManager :: getDataSource ( $modelObject -> useDbConfig );
2009-12-30 03:39:49 +00:00
$schema = $modelObject -> schema ( true );
2009-07-21 04:00:39 +00:00
$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 ;
}
2009-07-24 19:18:37 +00:00
2009-04-29 00:32:15 +00:00
}