123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- <?php
- /**
- * CrudCommand class file.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.yiiframework.com/
- * @copyright 2008-2013 Yii Software LLC
- * @license http://www.yiiframework.com/license/
- */
- /**
- * CrudCommand generates code implementing CRUD operations.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @package system.cli.commands.shell
- * @since 1.0
- */
- class CrudCommand extends CConsoleCommand
- {
- /**
- * @var string the directory that contains templates for crud commands.
- * Defaults to null, meaning using 'framework/cli/views/shell/crud'.
- * If you set this path and some views are missing in the directory,
- * the default views will be used.
- */
- public $templatePath;
- /**
- * @var string the directory that contains functional test classes.
- * Defaults to null, meaning using 'protected/tests/functional'.
- * If this is false, it means functional test file should NOT be generated.
- */
- public $functionalTestPath;
- /**
- * @var array list of actions to be created. Each action must be associated with a template file with the same name.
- */
- public $actions=array('create','update','index','view','admin','_form','_view','_search');
- public function getHelp()
- {
- return <<<EOD
- USAGE
- crud <model-class> [controller-ID] ...
- DESCRIPTION
- This command generates a controller and views that accomplish
- CRUD operations for the specified data model.
- PARAMETERS
- * model-class: required, the name of the data model class. This can
- also be specified as a path alias (e.g. application.models.Post).
- If the model class belongs to a module, it should be specified
- as 'ModuleID.models.ClassName'.
- * controller-ID: optional, the controller ID (e.g. 'post').
- If this is not specified, the model class name will be used
- as the controller ID. In this case, if the model belongs to
- a module, the controller will also be created under the same
- module.
- If the controller should be located under a subdirectory,
- please specify the controller ID as 'path/to/ControllerID'
- (e.g. 'admin/user').
- If the controller belongs to a module (different from the module
- that the model belongs to), please specify the controller ID
- as 'ModuleID/ControllerID' or 'ModuleID/path/to/Controller'.
- EXAMPLES
- * Generates CRUD for the Post model:
- crud Post
- * Generates CRUD for the Post model which belongs to module 'admin':
- crud admin.models.Post
- * Generates CRUD for the Post model. The generated controller should
- belong to module 'admin', but not the model class:
- crud Post admin/post
- EOD;
- }
- /**
- * Execute the action.
- * @param array $args command line parameters specific for this command
- * @return integer|null non zero application exit code for help or null on success
- */
- public function run($args)
- {
- if(!isset($args[0]))
- {
- echo "Error: data model class is required.\n";
- echo $this->getHelp();
- return 1;
- }
- $module=Yii::app();
- $modelClass=$args[0];
- if(($pos=strpos($modelClass,'.'))===false)
- $modelClass='application.models.'.$modelClass;
- else
- {
- $id=substr($modelClass,0,$pos);
- if(($m=Yii::app()->getModule($id))!==null)
- $module=$m;
- }
- $modelClass=Yii::import($modelClass);
- if(isset($args[1]))
- {
- $controllerID=$args[1];
- if(($pos=strrpos($controllerID,'/'))===false)
- {
- $controllerClass=ucfirst($controllerID).'Controller';
- $controllerFile=$module->controllerPath.DIRECTORY_SEPARATOR.$controllerClass.'.php';
- $controllerID[0]=strtolower($controllerID[0]);
- }
- else
- {
- $last=substr($controllerID,$pos+1);
- $last[0]=strtolower($last);
- $pos2=strpos($controllerID,'/');
- $first=substr($controllerID,0,$pos2);
- $middle=$pos===$pos2?'':substr($controllerID,$pos2+1,$pos-$pos2);
- $controllerClass=ucfirst($last).'Controller';
- $controllerFile=($middle===''?'':$middle.'/').$controllerClass.'.php';
- $controllerID=$middle===''?$last:$middle.'/'.$last;
- if(($m=Yii::app()->getModule($first))!==null)
- $module=$m;
- else
- {
- $controllerFile=$first.'/'.$controllerFile;
- $controllerID=$first.'/'.$controllerID;
- }
- $controllerFile=$module->controllerPath.DIRECTORY_SEPARATOR.str_replace('/',DIRECTORY_SEPARATOR,$controllerFile);
- }
- }
- else
- {
- $controllerID=$modelClass;
- $controllerClass=ucfirst($controllerID).'Controller';
- $controllerFile=$module->controllerPath.DIRECTORY_SEPARATOR.$controllerClass.'.php';
- $controllerID[0]=strtolower($controllerID[0]);
- }
- $templatePath=$this->templatePath===null?YII_PATH.'/cli/views/shell/crud':$this->templatePath;
- $functionalTestPath=$this->functionalTestPath===null?Yii::getPathOfAlias('application.tests.functional'):$this->functionalTestPath;
- $viewPath=$module->viewPath.DIRECTORY_SEPARATOR.str_replace('.',DIRECTORY_SEPARATOR,$controllerID);
- $fixtureName=$this->pluralize($modelClass);
- $fixtureName[0]=strtolower($fixtureName);
- $list=array(
- basename($controllerFile)=>array(
- 'source'=>$templatePath.'/controller.php',
- 'target'=>$controllerFile,
- 'callback'=>array($this,'generateController'),
- 'params'=>array($controllerClass,$modelClass),
- ),
- );
- if($functionalTestPath!==false)
- {
- $list[$modelClass.'Test.php']=array(
- 'source'=>$templatePath.'/test.php',
- 'target'=>$functionalTestPath.DIRECTORY_SEPARATOR.$modelClass.'Test.php',
- 'callback'=>array($this,'generateTest'),
- 'params'=>array($controllerID,$fixtureName,$modelClass),
- );
- }
- foreach($this->actions as $action)
- {
- $list[$action.'.php']=array(
- 'source'=>$templatePath.'/'.$action.'.php',
- 'target'=>$viewPath.'/'.$action.'.php',
- 'callback'=>array($this,'generateView'),
- 'params'=>$modelClass,
- );
- }
- $this->copyFiles($list);
- if($module instanceof CWebModule)
- $moduleID=$module->id.'/';
- else
- $moduleID='';
- echo "\nCrud '{$controllerID}' has been successfully created. You may access it via:\n";
- echo "http://hostname/path/to/index.php?r={$moduleID}{$controllerID}\n";
- }
- public function generateController($source,$params)
- {
- list($controllerClass,$modelClass)=$params;
- $model=CActiveRecord::model($modelClass);
- $id=$model->tableSchema->primaryKey;
- if($id===null)
- throw new ShellException(Yii::t('yii','Error: Table "{table}" does not have a primary key.',array('{table}'=>$model->tableName())));
- elseif(is_array($id))
- throw new ShellException(Yii::t('yii','Error: Table "{table}" has a composite primary key which is not supported by crud command.',array('{table}'=>$model->tableName())));
- if(!is_file($source)) // fall back to default ones
- $source=YII_PATH.'/cli/views/shell/crud/'.basename($source);
- return $this->renderFile($source,array(
- 'ID'=>$id,
- 'controllerClass'=>$controllerClass,
- 'modelClass'=>$modelClass,
- ),true);
- }
- public function generateView($source,$modelClass)
- {
- $model=CActiveRecord::model($modelClass);
- $table=$model->getTableSchema();
- $columns=$table->columns;
- if(!is_file($source)) // fall back to default ones
- $source=YII_PATH.'/cli/views/shell/crud/'.basename($source);
- return $this->renderFile($source,array(
- 'ID'=>$table->primaryKey,
- 'modelClass'=>$modelClass,
- 'columns'=>$columns),true);
- }
- public function generateTest($source,$params)
- {
- list($controllerID,$fixtureName,$modelClass)=$params;
- if(!is_file($source)) // fall back to default ones
- $source=YII_PATH.'/cli/views/shell/crud/'.basename($source);
- return $this->renderFile($source, array(
- 'controllerID'=>$controllerID,
- 'fixtureName'=>$fixtureName,
- 'modelClass'=>$modelClass,
- ),true);
- }
- public function generateInputLabel($modelClass,$column)
- {
- return "CHtml::activeLabelEx(\$model,'{$column->name}')";
- }
- public function generateInputField($modelClass,$column)
- {
- if($column->type==='boolean')
- return "CHtml::activeCheckBox(\$model,'{$column->name}')";
- elseif(stripos($column->dbType,'text')!==false)
- return "CHtml::activeTextArea(\$model,'{$column->name}',array('rows'=>6, 'cols'=>50))";
- else
- {
- if(preg_match('/^(password|pass|passwd|passcode)$/i',$column->name))
- $inputField='activePasswordField';
- else
- $inputField='activeTextField';
- if($column->type!=='string' || $column->size===null)
- return "CHtml::{$inputField}(\$model,'{$column->name}')";
- else
- {
- if(($size=$maxLength=$column->size)>60)
- $size=60;
- return "CHtml::{$inputField}(\$model,'{$column->name}',array('size'=>$size,'maxlength'=>$maxLength))";
- }
- }
- }
- public function generateActiveLabel($modelClass,$column)
- {
- return "\$form->labelEx(\$model,'{$column->name}')";
- }
- public function generateActiveField($modelClass,$column)
- {
- if($column->type==='boolean')
- return "\$form->checkBox(\$model,'{$column->name}')";
- elseif(stripos($column->dbType,'text')!==false)
- return "\$form->textArea(\$model,'{$column->name}',array('rows'=>6, 'cols'=>50))";
- else
- {
- if(preg_match('/^(password|pass|passwd|passcode)$/i',$column->name))
- $inputField='passwordField';
- else
- $inputField='textField';
- if($column->type!=='string' || $column->size===null)
- return "\$form->{$inputField}(\$model,'{$column->name}')";
- else
- {
- if(($size=$maxLength=$column->size)>60)
- $size=60;
- return "\$form->{$inputField}(\$model,'{$column->name}',array('size'=>$size,'maxlength'=>$maxLength))";
- }
- }
- }
- public function guessNameColumn($columns)
- {
- foreach($columns as $column)
- {
- if(!strcasecmp($column->name,'name'))
- return $column->name;
- }
- foreach($columns as $column)
- {
- if(!strcasecmp($column->name,'title'))
- return $column->name;
- }
- foreach($columns as $column)
- {
- if($column->isPrimaryKey)
- return $column->name;
- }
- return 'id';
- }
- public function class2id($className)
- {
- return trim(strtolower(str_replace('_','-',preg_replace('/(?<![A-Z])[A-Z]/', '-\0', $className))),'-');
- }
- public function class2name($className,$pluralize=false)
- {
- if($pluralize)
- $className=$this->pluralize($className);
- return ucwords(trim(strtolower(str_replace(array('-','_'),' ',preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $className)))));
- }
- }
|