Commit 1896dd17 by Qiang Xue

gii WIP

parent 94e4c076
......@@ -21,7 +21,7 @@ $this->params['breadcrumbs'][] = $this->title;
<?php echo $form->field($model, 'username'); ?>
<?php echo $form->field($model, 'password')->passwordInput(); ?>
<?php echo $form->field($model, 'rememberMe')->checkbox(); ?>
<div class="form-actions">
<div class="form-group">
<?php echo Html::submitButton('Login', array('class' => 'btn btn-primary')); ?>
</div>
<?php ActiveForm::end(); ?>
......
......@@ -29,7 +29,7 @@ $this->params['breadcrumbs'][] = $this->title;
'options' => array('class' => 'form-control'),
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
)); ?>
<div class="form-actions">
<div class="form-group">
<?php echo Html::submitButton('Submit', array('class' => 'btn btn-primary')); ?>
</div>
<?php ActiveForm::end(); ?>
......
......@@ -24,7 +24,7 @@ $this->params['breadcrumbs'][] = $this->title;
<div style="color:#999;margin:1em 0">
If you forgot your password you can <?php echo Html::a('reset it', array('site/request-password-reset'))?>.
</div>
<div class="form-actions">
<div class="form-group">
<?php echo Html::submitButton('Login', array('class' => 'btn btn-primary')); ?>
</div>
<?php ActiveForm::end(); ?>
......
......@@ -19,7 +19,7 @@ $this->params['breadcrumbs'][] = $this->title;
<div class="col-lg-5">
<?php $form = ActiveForm::begin(array('id' => 'request-password-reset-form')); ?>
<?php echo $form->field($model, 'email'); ?>
<div class="form-actions">
<div class="form-group">
<?php echo Html::submitButton('Send', array('class' => 'btn btn-primary')); ?>
</div>
<?php ActiveForm::end(); ?>
......
......@@ -19,10 +19,10 @@ $this->params['breadcrumbs'][] = $this->title;
<div class="col-lg-5">
<?php $form = ActiveForm::begin(array('id' => 'reset-password-form')); ?>
<?php echo $form->field($model, 'password')->passwordInput(); ?>
<div class="form-actions">
<div class="form-group">
<?php echo Html::submitButton('Save', array('class' => 'btn btn-primary')); ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>
\ No newline at end of file
</div>
......@@ -21,7 +21,7 @@ $this->params['breadcrumbs'][] = $this->title;
<?php echo $form->field($model, 'username'); ?>
<?php echo $form->field($model, 'email'); ?>
<?php echo $form->field($model, 'password')->passwordInput(); ?>
<div class="form-actions">
<div class="form-group">
<?php echo Html::submitButton('Signup', array('class' => 'btn btn-primary')); ?>
</div>
<?php ActiveForm::end(); ?>
......
......@@ -37,7 +37,7 @@ $this->params['breadcrumbs'][] = $this->title;
'options' => array('class' => 'form-control'),
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
)); ?>
<div class="form-actions">
<div class="form-group">
<?php echo Html::submitButton('Submit', array('class' => 'btn btn-primary')); ?>
</div>
<?php ActiveForm::end(); ?>
......
......@@ -21,7 +21,7 @@ $this->params['breadcrumbs'][] = $this->title;
<?php echo $form->field($model, 'username'); ?>
<?php echo $form->field($model, 'password')->passwordInput(); ?>
<?php echo $form->field($model, 'rememberMe')->checkbox(); ?>
<div class="form-actions">
<div class="form-group">
<?php echo Html::submitButton('Login', array('class' => 'btn btn-primary')); ?>
</div>
<?php ActiveForm::end(); ?>
......
......@@ -338,7 +338,7 @@ It is represented as an `ActiveField` object. Using fields, you can build a form
<?php $form = yii\widgets\ActiveForm::begin(); ?>
<?php echo $form->field($model, 'username'); ?>
<?php echo $form->field($model, 'password')->passwordInput(); ?>
<div class="form-actions">
<div class="form-group">
<?php echo Html::submitButton('Login'); ?>
</div>
<?php yii\widgets\ActiveForm::end(); ?>
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\gii;
use Yii;
use yii\base\Object;
/**
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class CodeFile extends Object
{
const OP_NEW = 'new';
const OP_OVERWRITE = 'overwrite';
const OP_SKIP = 'skip';
/**
* @var string the file path that the new code should be saved to.
*/
public $path;
/**
* @var mixed the newly generated code. If this is null, it means {@link path}
* should be treated as a directory.
*/
public $content;
/**
* @var string the operation to be performed
*/
public $operation;
/**
* @var string the error occurred when saving the code into a file
*/
public $error;
/**
* Constructor.
* @param string $path the file path that the new code should be saved to.
* @param string $content the newly generated code
*/
public function __construct($path, $content)
{
$this->path = strtr($path, array('/' => DIRECTORY_SEPARATOR, '\\' => DIRECTORY_SEPARATOR));
$this->content = $content;
if (is_file($path)) {
$this->operation = file_get_contents($path) === $content ? self::OP_SKIP : self::OP_OVERWRITE;
} elseif ($content === null) // is dir
{
$this->operation = is_dir($path) ? self::OP_SKIP : self::OP_NEW;
} else {
$this->operation = self::OP_NEW;
}
}
/**
* Saves the code into the file {@link path}.
*/
public function save()
{
$module = Yii::$app->controller->module;
if ($this->content === null) // a directory
{
if (!is_dir($this->path)) {
$oldmask = @umask(0);
$result = @mkdir($this->path, $module->newDirMode, true);
@umask($oldmask);
if (!$result) {
$this->error = "Unable to create the directory '{$this->path}'.";
return false;
}
}
return true;
}
if ($this->operation === self::OP_NEW) {
$dir = dirname($this->path);
if (!is_dir($dir)) {
$oldmask = @umask(0);
$result = @mkdir($dir, $module->newDirMode, true);
@umask($oldmask);
if (!$result) {
$this->error = "Unable to create the directory '$dir'.";
return false;
}
}
}
if (@file_put_contents($this->path, $this->content) === false) {
$this->error = "Unable to write the file '{$this->path}'.";
return false;
} else {
$oldmask = @umask(0);
@chmod($this->path, $module->newFileMode);
@umask($oldmask);
}
return true;
}
/**
* @return string the code file path relative to the application base path.
*/
public function getRelativePath()
{
if (strpos($this->path, Yii::$app->basePath) === 0) {
return substr($this->path, strlen(Yii::$app->basePath) + 1);
} else {
return $this->path;
}
}
/**
* @return string the code file extension (e.g. php, txt)
*/
public function getType()
{
if (($pos = strrpos($this->path, '.')) !== false) {
return substr($this->path, $pos + 1);
} else {
return 'unknown';
}
}
}
......@@ -8,161 +8,73 @@
namespace yii\gii;
use Yii;
use ReflectionClass;
use yii\base\InvalidConfigException;
use yii\base\Model;
use yii\base\View;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Generator extends Model
abstract class Generator extends Model
{
public $templates = array();
/**
* @var string
* @var string the name of the code template that the user has selected.
* The value of this property is internally managed by this class and {@link CCodeGenerator}.
*/
public $id;
public $template;
/**
* @return string name of the code generator
*/
public function getName()
abstract public function getName();
public function init()
{
return 'unknown';
parent::init();
if (!isset($this->templates['default'])) {
$this->templates['default'] = $this->getDefaultTemplate();
}
}
public function getDescription()
/**
* Prepares the code files to be generated.
* This is the main method that child classes should implement. It should contain the logic
* that populates the {@link files} property with a list of code files to be generated.
*/
public function prepare()
{
return '';
return array();
}
public function getUrl()
/**
* Returns a list of code templates that are required.
* Derived classes usually should override this method.
* @return array list of code templates that are required. They should be file paths
* relative to {@link templatePath}.
*/
public function requiredTemplates()
{
return Yii::$app->controller->createUrl('default/view', array('id' => $this->id));
return array();
}
public function renderForm()
public function getViewFile()
{
return '';
$class = new ReflectionClass($this);
return dirname($class->getFileName()) . '/views/form.php';
}
public function renderFileList()
public function getDefaultTemplate()
{
return '';
$class = new ReflectionClass($this);
return dirname($class->getFileName()) . '/templates';
}
const STATUS_NEW = 1;
const STATUS_PREVIEW = 2;
const STATUS_SUCCESS = 3;
const STATUS_ERROR = 4;
static $keywords = array(
'__class__',
'__dir__',
'__file__',
'__function__',
'__line__',
'__method__',
'__namespace__',
'abstract',
'and',
'array',
'as',
'break',
'case',
'catch',
'cfunction',
'class',
'clone',
'const',
'continue',
'declare',
'default',
'die',
'do',
'echo',
'else',
'elseif',
'empty',
'enddeclare',
'endfor',
'endforeach',
'endif',
'endswitch',
'endwhile',
'eval',
'exception',
'exit',
'extends',
'final',
'final',
'for',
'foreach',
'function',
'global',
'goto',
'if',
'implements',
'include',
'include_once',
'instanceof',
'interface',
'isset',
'list',
'namespace',
'new',
'old_function',
'or',
'parent',
'php_user_filter',
'print',
'private',
'protected',
'public',
'require',
'require_once',
'return',
'static',
'switch',
'this',
'throw',
'try',
'unset',
'use',
'var',
'while',
'xor',
);
/**
* @var array user confirmations on whether to overwrite existing code files with the newly generated ones.
* The value of this property is internally managed by this class and {@link CCodeGenerator}.
*/
public $answers;
/**
* @var string the name of the code template that the user has selected.
* The value of this property is internally managed by this class and {@link CCodeGenerator}.
*/
public $template;
/**
* @var array a list of {@link CCodeFile} objects that represent the code files to be generated.
* The {@link prepare()} method is responsible to populate this property.
*/
public $files = array();
/**
* @var integer the status of this model. T
* The value of this property is internally managed by {@link CCodeGenerator}.
*/
public $status = self::STATUS_NEW;
private $_stickyAttributes = array();
/**
* Prepares the code files to be generated.
* This is the main method that child classes should implement. It should contain the logic
* that populates the {@link files} property with a list of code files to be generated.
*/
public function prepare()
public function getDescription()
{
return '';
}
/**
......@@ -178,35 +90,12 @@ class Generator extends Model
public function rules()
{
return array(
array('template', 'required'),
array('template', 'required', 'message' => 'A code template must be selected.'),
array('template', 'validateTemplate', 'skipOnError' => true),
array('template', 'sticky'),
);
}
/**
* Validates the template selection.
* This method validates whether the user selects an existing template
* and the template contains all required template files as specified in {@link requiredTemplates}.
* @param string $attribute the attribute to be validated
* @param array $params validation parameters
*/
public function validateTemplate($attribute, $params)
{
$templates = $this->templates;
if (!isset($templates[$this->template])) {
$this->addError('template', 'Invalid template selection.');
} else {
$templatePath = $this->templatePath;
foreach ($this->requiredTemplates() as $template) {
if (!is_file($templatePath . '/' . $template)) {
$this->addError('template', "Unable to find the required code template file '$template'.");
}
}
}
}
/**
* Checks if the named class exists (in a case sensitive manner).
* @param string $name class name to be checked
* @return boolean whether the class exists
......@@ -217,40 +106,12 @@ class Generator extends Model
}
/**
* Declares the model attribute labels.
* Child classes must override this method in the following format:
* <pre>
* return array_merge(parent::attributeLabels(), array(
* ...labels for the child class attributes...
* ));
* </pre>
* @return array the attribute labels
*/
public function attributeLabels()
{
return array(
'template' => 'Code Template',
);
}
/**
* Returns a list of code templates that are required.
* Derived classes usually should override this method.
* @return array list of code templates that are required. They should be file paths
* relative to {@link templatePath}.
*/
public function requiredTemplates()
{
return array();
}
/**
* Saves the generated code into files.
*/
public function save()
public function save($files, $answers = array())
{
$result = true;
foreach ($this->files as $file) {
foreach ($files as $file) {
if ($this->confirmed($file)) {
$result = $file->save() && $result;
}
......@@ -259,59 +120,25 @@ class Generator extends Model
}
/**
* Returns the message to be displayed when the newly generated code is saved successfully.
* Child classes should override this method if the message needs to be customized.
* @return string the message to be displayed when the newly generated code is saved successfully.
*/
public function successMessage()
{
return 'The code has been generated successfully.';
}
/**
* Returns the message to be displayed when some error occurred during code file saving.
* Child classes should override this method if the message needs to be customized.
* @return string the message to be displayed when some error occurred during code file saving.
*/
public function errorMessage()
{
return 'There was some error when generating the code. Please check the following messages.';
}
/**
* Returns a list of available code templates (name=>directory).
* This method simply returns the {@link CCodeGenerator::templates} property value.
* @return array a list of available code templates (name=>directory).
*/
public function getTemplates()
{
return Yii::app()->controller->templates;
}
/**
* @return string the directory that contains the template files.
* @throws CHttpException if {@link templates} is empty or template selection is invalid
* @throws InvalidConfigException if {@link templates} is empty or template selection is invalid
*/
public function getTemplatePath()
{
$templates = $this->getTemplates();
if (isset($templates[$this->template])) {
return $templates[$this->template];
} elseif (empty($templates)) {
throw new CHttpException(500, 'No templates are available.');
if (isset($this->templates[$this->template])) {
return $this->templates[$this->template];
} else {
throw new CHttpException(500, 'Invalid template selection.');
throw new InvalidConfigException("Unknown template: {$this->template}");
}
}
/**
* @param CCodeFile $file whether the code file should be saved
* @param CodeFile $file whether the code file should be saved
* @return bool whether the confirmation is found in {@link answers} with appropriate {@link operation}
*/
public function confirmed($file)
{
return $this->answers === null && $file->operation === CCodeFile::OP_NEW
return $this->answers === null && $file->operation === CodeFile::OP_NEW
|| is_array($this->answers) && isset($this->answers[md5($file->path)]);
}
......@@ -320,24 +147,12 @@ class Generator extends Model
* This method is manly used in {@link generate} to generate code.
* @param string $templateFile the code template file path
* @param array $_params_ a set of parameters to be extracted and made available in the code template
* @throws CException is template file does not exist
* @return string the generated code
*/
public function render($templateFile, $_params_ = null)
public function render($templateFile, $params = array())
{
if (!is_file($templateFile)) {
throw new CException("The template file '$templateFile' does not exist.");
}
if (is_array($_params_)) {
extract($_params_, EXTR_PREFIX_SAME, 'params');
} else {
$params = $_params_;
}
ob_start();
ob_implicit_flush(false);
require($templateFile);
return ob_get_clean();
$view = new View;
return $view->renderFile($templateFile, $params, $this);
}
/**
......@@ -349,9 +164,9 @@ class Generator extends Model
foreach ($this->files as $file) {
if ($file->error !== null) {
$output .= "<span class=\"error\">generating {$file->relativePath}<br/> {$file->error}</span>\n";
} elseif ($file->operation === CCodeFile::OP_NEW && $this->confirmed($file)) {
} elseif ($file->operation === CodeFile::OP_NEW && $this->confirmed($file)) {
$output .= ' generated ' . $file->relativePath . "\n";
} elseif ($file->operation === CCodeFile::OP_OVERWRITE && $this->confirmed($file)) {
} elseif ($file->operation === CodeFile::OP_OVERWRITE && $this->confirmed($file)) {
$output .= ' overwrote ' . $file->relativePath . "\n";
} else {
$output .= ' skipped ' . $file->relativePath . "\n";
......@@ -362,66 +177,111 @@ class Generator extends Model
}
/**
* The "sticky" validator.
* This validator does not really validate the attributes.
* It actually saves the attribute value in a file to make it sticky.
* @param string $attribute the attribute to be validated
* @param array $params the validation parameters
*/
public function sticky($attribute, $params)
{
if (!$this->hasErrors()) {
$this->_stickyAttributes[$attribute] = $this->$attribute;
}
}
/**
* Loads sticky attributes from a file and populates them into the model.
* Validates the template selection.
* This method validates whether the user selects an existing template
* and the template contains all required template files as specified in {@link requiredTemplates}.
*/
public function loadStickyAttributes()
public function validateTemplate()
{
$this->_stickyAttributes = array();
$path = $this->getStickyFile();
if (is_file($path)) {
$result = @include($path);
if (is_array($result)) {
$this->_stickyAttributes = $result;
foreach ($this->_stickyAttributes as $name => $value) {
if (property_exists($this, $name) || $this->canSetProperty($name)) {
$this->$name = $value;
}
$templates = $this->templates;
if (!isset($templates[$this->template])) {
$this->addError('template', 'Invalid template selection.');
} else {
$templatePath = $this->templates[$this->template];
foreach ($this->requiredTemplates() as $template) {
if (!is_file($templatePath . '/' . $template)) {
$this->addError('template', "Unable to find the required code template file '$template'.");
}
}
}
}
/**
* Saves sticky attributes into a file.
*/
public function saveStickyAttributes()
{
$path = $this->getStickyFile();
@mkdir(dirname($path), 0755, true);
file_put_contents($path, "<?php\nreturn " . var_export($this->_stickyAttributes, true) . ";\n");
}
/**
* @return string the file path that stores the sticky attribute values.
*/
public function getStickyFile()
{
return Yii::app()->runtimePath . '/gii-' . Yii::getVersion() . '/' . get_class($this) . '.php';
}
/**
* Validates an attribute to make sure it is not taking a PHP reserved keyword.
* @param string $attribute the attribute to be validated
* @param array $params validation parameters
*/
public function validateReservedWord($attribute, $params)
{
static $keywords = array(
'__class__',
'__dir__',
'__file__',
'__function__',
'__line__',
'__method__',
'__namespace__',
'abstract',
'and',
'array',
'as',
'break',
'case',
'catch',
'cfunction',
'class',
'clone',
'const',
'continue',
'declare',
'default',
'die',
'do',
'echo',
'else',
'elseif',
'empty',
'enddeclare',
'endfor',
'endforeach',
'endif',
'endswitch',
'endwhile',
'eval',
'exception',
'exit',
'extends',
'final',
'final',
'for',
'foreach',
'function',
'global',
'goto',
'if',
'implements',
'include',
'include_once',
'instanceof',
'interface',
'isset',
'list',
'namespace',
'new',
'old_function',
'or',
'parent',
'php_user_filter',
'print',
'private',
'protected',
'public',
'require',
'require_once',
'return',
'static',
'switch',
'this',
'throw',
'try',
'unset',
'use',
'var',
'while',
'xor',
);
$value = $this->$attribute;
if (in_array(strtolower($value), self::$keywords)) {
if (in_array(strtolower($value), $keywords)) {
$this->addError($attribute, $this->getAttributeLabel($attribute) . ' cannot take a reserved PHP keyword.');
}
}
......
......@@ -53,7 +53,6 @@ class Module extends \yii\base\Module
{
parent::init();
foreach (array_merge($this->coreGenerators(), $this->generators) as $id => $config) {
$config['id'] = $id;
$this->generators[$id] = Yii::createObject($config);
}
}
......
......@@ -41,3 +41,16 @@ body {
.hint-block {
display: none;
}
table.code-files .file {
}
table.code-files .action {
width: 100px;
}
table.code-files .check {
width: 25px;
text-align: center;
}
......@@ -17,6 +17,13 @@ use yii\web\HttpException;
class DefaultController extends Controller
{
public $layout = 'generator';
/**
* @var \yii\gii\Module
*/
public $module;
/**
* @var \yii\gii\Generator
*/
public $generator;
public function actionIndex()
......@@ -28,9 +35,19 @@ class DefaultController extends Controller
public function actionView($id)
{
$generator = $this->loadGenerator($id);
return $this->render('view', array(
'generator' => $generator
));
$params = array('generator' => $generator);
if (isset($_POST['preview']) || isset($_POST['generate'])) {
if ($generator->validate()) {
$files = $generator->prepare();
if (isset($_POST['generate'], $_POST['answers'])) {
$params['result'] = $generator->save($files, $_POST['answers']);
} else {
$params['files'] = $files;
}
}
}
return $this->render('view', $params);
}
public function actionCode($file)
......@@ -43,10 +60,18 @@ class DefaultController extends Controller
}
/**
* Loads the generator with the specified ID.
* @param string $id the ID of the generator to be loaded.
* @return \yii\gii\Generator the loaded generator
* @throws \yii\web\HttpException
*/
protected function loadGenerator($id)
{
if (isset($this->module->generators[$id])) {
return $this->generator = $this->module->generators[$id];
$this->generator = $this->module->generators[$id];
$this->generator->load($_POST);
return $this->generator;
} else {
throw new HttpException(404, "Code generator not found: $id");
}
......
......@@ -8,6 +8,8 @@
namespace yii\gii\generators\controller;
use Yii;
use yii\gii\CodeFile;
use yii\helpers\Html;
/**
*
......@@ -31,33 +33,25 @@ class Generator extends \yii\gii\Generator
one or several controller actions and their corresponding views.';
}
public function renderForm()
{
return Yii::$app->getView()->renderFile(__DIR__ . '/views/form.php', array(
'model' => $this,
));
}
public function rules()
{
return array_merge(parent::rules(), array(
array('controller, actions, baseClass', 'filter', 'filter' => 'trim'),
array('controller, baseClass', 'required'),
array('controller', 'match', 'pattern' => '/^[\w+\\/]*$/', 'message' => '{attribute} should only contain word characters and slashes.'),
array('actions', 'match', 'pattern' => '/^\w+[\w\s,]*$/', 'message' => '{attribute} should only contain word characters, spaces and commas.'),
array('baseClass', 'match', 'pattern' => '/^[a-zA-Z_][\w\\\\]*$/', 'message' => '{attribute} should only contain word characters and backslashes.'),
array('controller', 'match', 'pattern' => '/^[\w+\\/]*$/', 'message' => 'Only word characters and slashes are allowed.'),
array('actions', 'match', 'pattern' => '/^\w+[\w\s,]*$/', 'message' => 'Only word characters, spaces and commas are allowed.'),
array('baseClass', 'match', 'pattern' => '/^[a-zA-Z_][\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'),
array('baseClass', 'validateReservedWord', 'skipOnError' => true),
array('baseClass, actions', 'sticky'),
));
}
public function attributeLabels()
{
return array_merge(parent::attributeLabels(), array(
return array(
'baseClass' => 'Base Class',
'controller' => 'Controller ID',
'actions' => 'Action IDs',
));
);
}
public function requiredTemplates()
......@@ -70,32 +64,34 @@ class Generator extends \yii\gii\Generator
public function successMessage()
{
$link = CHtml::link('try it now', Yii::app()->createUrl($this->controller), array('target' => '_blank'));
$link = Html::a('try it now', Yii::$app->getUrlManager()->createUrl($this->controller), array('target' => '_blank'));
return "The controller has been generated successfully. You may $link.";
}
public function prepare()
{
$this->files = array();
$templatePath = $this->templatePath;
$files = array();
$this->files[] = new CCodeFile(
$this->controllerFile,
$templatePath = $this->getTemplatePath();
$files[] = new CodeFile(
$this->getControllerFile(),
$this->render($templatePath . '/controller.php')
);
foreach ($this->getActionIDs() as $action) {
$this->files[] = new CCodeFile(
$files[] = new CodeFile(
$this->getViewFile($action),
$this->render($templatePath . '/view.php', array('action' => $action))
);
}
return $files;
}
public function getActionIDs()
{
$actions = preg_split('/[\s,]+/', $this->actions, -1, PREG_SPLIT_NO_EMPTY);
$actions = array_unique($actions);
$actions = array_unique(preg_split('/[\s,]+/', $this->actions, -1, PREG_SPLIT_NO_EMPTY));
sort($actions);
return $actions;
}
......@@ -113,16 +109,16 @@ class Generator extends \yii\gii\Generator
{
if (($pos = strpos($this->controller, '/')) !== false) {
$id = substr($this->controller, 0, $pos);
if (($module = Yii::app()->getModule($id)) !== null) {
if (($module = Yii::$app->getModule($id)) !== null) {
return $module;
}
}
return Yii::app();
return Yii::$app;
}
public function getControllerID()
{
if ($this->getModule() !== Yii::app()) {
if ($this->getModule() !== Yii::$app) {
$id = substr($this->controller, strpos($this->controller, '/') + 1);
} else {
$id = $this->controller;
......@@ -157,10 +153,4 @@ class Generator extends \yii\gii\Generator
}
return $module->getControllerPath() . '/' . $id . 'Controller.php';
}
public function getViewFile($action)
{
$module = $this->getModule();
return $module->getViewPath() . '/' . $this->getControllerID() . '/' . $action . '.php';
}
}
<?php
/**
* Created by JetBrains PhpStorm.
* User: qiang
* Date: 8/15/13
* Time: 4:45 PM
* To change this template use File | Settings | File Templates.
*/
<?php
/**
* Created by JetBrains PhpStorm.
* User: qiang
* Date: 8/15/13
* Time: 4:46 PM
* To change this template use File | Settings | File Templates.
*/
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/**
* @var yii\base\View $this
* @var yii\widgets\ActiveForm $form
* @var yii\gii\generators\controller\Generator $generator
*/
?>
<div class="controller-form">
<div class="row">
<div class="col-lg-6">
<?php $form = ActiveForm::begin(array('id' => 'login-form')); ?>
<?php echo $form->field($model, 'controller')->hint('
Controller ID is case-sensitive and can contain module ID(s). For example:
<ul>
<li><code>order</code> generates <code>OrderController.php</code></li>
<li><code>order-item</code> generates <code>OrderItemController.php</code></li>
<li><code>admin/user</code> generates <code>UserController.php</code> within the <code>admin</code> module.</li>
</ul>
'); ?>
<?php echo $form->field($model, 'baseClass')->hint('
This is the class that the new controller class will extend from.
Please make sure the class exists and can be autoloaded.
'); ?>
<?php echo $form->field($model, 'actions')->hint('
Provide one or multiple action IDs to generate empty action method(s) in the controller.
Separate multiple action IDs with commas or spaces.
'); ?>
<div class="form-actions">
<?php echo Html::submitButton('Preview', array('class' => 'btn btn-primary')); ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>
<?php echo $form->field($generator, 'controller')->hint('
Controller ID is case-sensitive and can contain module ID(s). For example:
<ul>
<li><code>order</code> generates <code>OrderController.php</code></li>
<li><code>order-item</code> generates <code>OrderItemController.php</code></li>
<li><code>admin/user</code> generates <code>UserController.php</code> within the <code>admin</code> module.</li>
</ul>
'); ?>
<?php echo $form->field($generator, 'baseClass')->hint('
This is the class that the new controller class will extend from.
Please make sure the class exists and can be autoloaded.
'); ?>
<?php echo $form->field($generator, 'actions')->hint('
Provide one or multiple action IDs to generate empty action method(s) in the controller.
Separate multiple action IDs with commas or spaces.
'); ?>
......@@ -24,4 +24,9 @@ class Generator extends \yii\gii\Generator
return 'This generator generates a controller and views that implement CRUD (Create, Read, Update, Delete)
operations for the specified data model.';
}
public function getViewFile()
{
return __DIR__ . '/views/form.php';
}
}
......@@ -23,4 +23,10 @@ class Generator extends \yii\gii\Generator
{
return 'This generator generates a view script file that displays a form to collect input for the specified model class.';
}
public function getViewFile()
{
return __DIR__ . '/views/form.php';
}
}
......@@ -23,4 +23,9 @@ class Generator extends \yii\gii\Generator
{
return 'This generator generates a model class for the specified database table.';
}
public function getViewFile()
{
return __DIR__ . '/views/form.php';
}
}
......@@ -23,4 +23,10 @@ class Generator extends \yii\gii\Generator
{
return 'This generator helps you to generate the skeleton code needed by a Yii module.';
}
public function getViewFile()
{
return __DIR__ . '/views/form.php';
}
}
<?php
use yii\gii\Generator;
use yii\helpers\Html;
use yii\gii\CodeFile;
/**
* @var $this \yii\base\View
* @var $generator \yii\gii\Generator
* @var CodeFile[] $files
*/
?>
<table class="table table-bordered table-striped table-condensed code-files">
<thead>
<tr>
<th class="file">Code File</th>
<th class="action">Action</th>
<th class="check">
<?php
$count = 0;
foreach ($files as $file) {
if ($file->operation !== CodeFile::OP_SKIP) {
$count++;
}
}
if ($count > 1) {
echo '<input type="checkbox" name="checkAll" id="check-all" />';
}
?>
</th>
</tr>
</thead>
<tbody>
<?php foreach ($files as $i => $file): ?>
<tr class="<?php echo $file->operation; ?>">
<td class="file">
<?php echo Html::a(Html::encode($file->getRelativePath()), array('code', 'file' => $i), array('class' => 'view-code', 'rel' => $file->path)); ?>
<?php if ($file->operation === CodeFile::OP_OVERWRITE): ?>
(<?php echo Html::a('diff', array('diff', 'file' => $i), array('class' => 'view-code', 'rel' => $file->path)); ?>)
<?php endif; ?>
</td>
<td class="action">
<?php
if ($file->operation === CodeFile::OP_SKIP) {
echo 'unchanged';
} else {
echo $file->operation;
}
?>
</td>
<td class="check">
<?php
if ($file->operation === CodeFile::OP_SKIP) {
echo '&nbsp;';
} else {
$key = md5($file->path);
echo Html::checkBox("answers[$key]");
}
?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
......@@ -19,16 +19,15 @@ $this->title = 'Welcome to Gii';
<p class="lead">Start the fun with the following code generators:</p>
<div class="row">
<?php foreach (array_values($generators) as $i => $generator): ?>
<?php foreach ($generators as $id => $generator): ?>
<div class="generator col-lg-4">
<h3><?php echo Html::encode($generator->getName()); ?></h3>
<p><?php echo $generator->getDescription(); ?></p>
<p><?php echo Html::a('Start »', $generator->getUrl(), array('class' => 'btn btn-default')); ?></p>
<p><?php echo Html::a('Start »', array('default/view', 'id' => $id), array('class' => 'btn btn-default')); ?></p>
</div>
<?php endforeach; ?>
</div>
<p><a class="btn btn-success" href="http://www.yiiframework.com/extensions/?tag=gii">Get More Generators</a></p>
</div>
<?php
use yii\gii\Generator;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\gii\CodeFile;
/**
* @var $this \yii\base\View
* @var $generator \yii\gii\Generator
* @var yii\base\View $this
* @var yii\gii\Generator $generator
* @var yii\widgets\ActiveForm $form
* @var string $result
* @var CodeFile[] $files
*/
$this->title = $generator->getName();
$templates = array();
foreach ($generator->templates as $name => $path) {
$templates[$name] = "$name ($path)";
}
?>
<div class="default-view">
<h1><?php echo Html::encode($generator->getName()); ?></h1>
<h1><?php echo Html::encode($this->title); ?></h1>
<p><?php echo $generator->getDescription(); ?></p>
<?php echo $generator->renderForm(); ?>
<?php $form = ActiveForm::begin(); ?>
<div class="row">
<div class="col-lg-6">
<?php echo $this->renderFile($generator->getViewFile(), array(
'generator' => $generator,
'form' => $form,
)); ?>
<?php echo $form->field($generator, 'template')->label(array('label' => 'Code Template'))->dropDownList($templates)->hint('
Please select which set of the templates should be used to generated the code.
'); ?>
<div class="form-group">
<?php echo Html::submitButton('Preview', array('name' => 'preview', 'class' => 'btn btn-primary')); ?>
<?php if(isset($files)): ?>
<?php echo Html::submitButton('Generate', array('name' => 'generate', 'class' => 'btn btn-danger')); ?>
<?php endif; ?>
</div>
</div>
</div>
<?php
if (isset($result)) {
echo '<div class="result">' . $result . '</div>';
} elseif (isset($files)) {
echo $this->render('_files', array(
'generator' => $generator,
'files' => $files,
));
}
?>
<?php echo $generator->renderFileList(); ?>
<?php ActiveForm::end(); ?>
</div>
......@@ -1627,7 +1627,7 @@ select:focus:invalid:focus {
box-shadow: 0 0 6px #f8b9b7;
}
.form-actions {
.form-group {
padding: 19px 20px 20px;
margin-top: 20px;
margin-bottom: 20px;
......@@ -1636,14 +1636,14 @@ select:focus:invalid:focus {
*zoom: 1;
}
.form-actions:before,
.form-actions:after {
.form-group:before,
.form-group:after {
display: table;
line-height: 0;
content: "";
}
.form-actions:after {
.form-group:after {
clear: both;
}
......@@ -1991,7 +1991,7 @@ legend + .control-group {
margin-top: 10px;
}
.form-horizontal .form-actions {
.form-horizontal .form-group {
padding-left: 180px;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment