You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

336 lines
7.7 KiB

12 years ago
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\gii;
use Yii;
12 years ago
use ReflectionClass;
use yii\base\InvalidConfigException;
12 years ago
use yii\base\Model;
12 years ago
use yii\base\View;
12 years ago
12 years ago
12 years ago
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
12 years ago
abstract class Generator extends Model
12 years ago
{
12 years ago
public $templates = array();
12 years ago
/**
12 years ago
* @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}.
12 years ago
*/
12 years ago
public $template;
12 years ago
/**
* @return string name of the code generator
*/
12 years ago
abstract public function getName();
public function init()
12 years ago
{
12 years ago
parent::init();
if (!isset($this->templates['default'])) {
12 years ago
$this->templates['default'] = $this->defaultTemplate();
12 years ago
}
12 years ago
}
12 years ago
/**
* 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()
12 years ago
{
12 years ago
return array();
12 years ago
}
12 years ago
/**
* 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()
12 years ago
{
12 years ago
return array();
12 years ago
}
12 years ago
public function stickyAttributes()
{
return array('template');
}
public function hints()
{
return array();
}
/**
* 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.';
}
12 years ago
public function formView()
12 years ago
{
12 years ago
$class = new ReflectionClass($this);
return dirname($class->getFileName()) . '/views/form.php';
12 years ago
}
12 years ago
public function defaultTemplate()
12 years ago
{
12 years ago
$class = new ReflectionClass($this);
return dirname($class->getFileName()) . '/templates';
12 years ago
}
12 years ago
public function getDescription()
12 years ago
{
12 years ago
return '';
12 years ago
}
/**
* Declares the model validation rules.
* Child classes must override this method in the following format:
* <pre>
* return array_merge(parent::rules(), array(
* ...rules for the child class...
* ));
* </pre>
* @return array validation rules
*/
public function rules()
{
return array(
12 years ago
array('template', 'required', 'message' => 'A code template must be selected.'),
12 years ago
array('template', 'validateTemplate'),
12 years ago
);
}
/**
* 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
*/
public function classExists($name)
{
return class_exists($name, false) && in_array($name, get_declared_classes());
}
/**
12 years ago
* Loads sticky attributes from a file and populates them into the model.
12 years ago
*/
12 years ago
public function loadStickyAttributes()
12 years ago
{
12 years ago
$stickyAttributes = $this->stickyAttributes();
$attributes[] = 'template';
$path = $this->getStickyDataFile();
if (is_file($path)) {
$result = @include($path);
if (is_array($result)) {
foreach ($stickyAttributes as $name) {
if (isset($result[$name])) {
$this->$name = $result[$name];
}
}
12 years ago
}
}
}
/**
12 years ago
* Saves sticky attributes into a file.
12 years ago
*/
12 years ago
public function saveStickyAttributes()
12 years ago
{
12 years ago
$stickyAttributes = $this->stickyAttributes();
$stickyAttributes[] = 'template';
$values = array();
foreach ($stickyAttributes as $name) {
$values[$name] = $this->$name;
12 years ago
}
12 years ago
$path = $this->getStickyDataFile();
@mkdir(dirname($path), 0755, true);
file_put_contents($path, "<?php\nreturn " . var_export($values, true) . ";\n");
12 years ago
}
/**
12 years ago
* @return string the file path that stores the sticky attribute values.
12 years ago
*/
12 years ago
public function getStickyDataFile()
12 years ago
{
12 years ago
return Yii::$app->getRuntimePath() . '/gii-' . Yii::getVersion() . '/' . str_replace('\\', '-',get_class($this)) . '.php';
12 years ago
}
/**
12 years ago
* Saves the generated code into files.
* @param CodeFile[] $files
* @param array $answers
* @param boolean $hasError
* @return string
12 years ago
*/
12 years ago
public function save($files, $answers, &$hasError)
12 years ago
{
12 years ago
$lines = array('Generating code using template "' . $this->templatePath . '"...');
foreach ($files as $file) {;
$relativePath = $file->getRelativePath();
if (isset($answers[$file->id]) && $file->operation !== CodeFile::OP_SKIP) {
$error = $file->save();
if (is_string($error)) {
$lines[] = "<span class=\"error\">generating $relativePath<br> $error</span>";
} elseif ($file->operation === CodeFile::OP_NEW) {
$lines[] = " generated $relativePath";
} else {
$lines[] = " overwrote $relativePath";
}
} else {
$lines[] = " skipped $relativePath";
}
}
$lines[] = "done!\n";
return implode("\n", $lines);
12 years ago
}
/**
12 years ago
* @return string the directory that contains the template files.
* @throws InvalidConfigException if {@link templates} is empty or template selection is invalid
12 years ago
*/
12 years ago
public function getTemplatePath()
12 years ago
{
12 years ago
if (isset($this->templates[$this->template])) {
return $this->templates[$this->template];
} else {
throw new InvalidConfigException("Unknown template: {$this->template}");
12 years ago
}
12 years ago
}
public function generateCode($template, $params = array())
{
$view = new View;
$params['generator'] = $this;
return $view->renderFile($template, $params, $this);
12 years ago
}
/**
12 years ago
* 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}.
12 years ago
*/
12 years ago
public function validateTemplate()
12 years ago
{
12 years ago
$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'.");
12 years ago
}
}
}
}
/**
* 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)
{
12 years ago
static $keywords = array(
'__class__',
'__dir__',
'__file__',
'__function__',
'__line__',
'__method__',
'__namespace__',
12 years ago
'__trait__',
12 years ago
'abstract',
'and',
'array',
'as',
'break',
'case',
'catch',
'callable',
12 years ago
'cfunction',
'class',
'clone',
'const',
'continue',
'declare',
'default',
'die',
'do',
'echo',
'else',
'elseif',
'empty',
'enddeclare',
'endfor',
'endforeach',
'endif',
'endswitch',
'endwhile',
'eval',
'exception',
'exit',
'extends',
'final',
12 years ago
'finally',
12 years ago
'for',
'foreach',
'function',
'global',
'goto',
'if',
'implements',
'include',
'include_once',
'instanceof',
'insteadof',
12 years ago
'interface',
'isset',
'list',
'namespace',
'new',
'old_function',
'or',
'parent',
'php_user_filter',
'print',
'private',
'protected',
'public',
'require',
'require_once',
'return',
'static',
'switch',
'this',
'throw',
12 years ago
'trait',
12 years ago
'try',
'unset',
'use',
'var',
'while',
'xor',
);
12 years ago
$value = $this->$attribute;
12 years ago
if (in_array(strtolower($value), $keywords)) {
12 years ago
$this->addError($attribute, $this->getAttributeLabel($attribute) . ' cannot take a reserved PHP keyword.');
}
}
}