* @since 2.0 */ abstract class Generator extends Model { public $templates = array(); /** * @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; /** * @return string name of the code generator */ abstract public function getName(); public function init() { parent::init(); if (!isset($this->templates['default'])) { $this->templates['default'] = $this->getDefaultTemplate(); } } /** * 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 array(); } /** * 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(); } public function getViewFile() { $class = new ReflectionClass($this); return dirname($class->getFileName()) . '/views/form.php'; } public function getDefaultTemplate() { $class = new ReflectionClass($this); return dirname($class->getFileName()) . '/templates'; } public function getDescription() { return ''; } /** * Declares the model validation rules. * Child classes must override this method in the following format: *
* return array_merge(parent::rules(), array( * ...rules for the child class... * )); ** @return array validation rules */ public function rules() { return array( array('template', 'required', 'message' => 'A code template must be selected.'), array('template', 'validateTemplate', 'skipOnError' => true), ); } /** * 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()); } /** * Saves the generated code into files. */ public function save($files, $answers = array()) { $result = true; foreach ($files as $file) { if ($this->confirmed($file)) { $result = $file->save() && $result; } } return $result; } /** * @return string the directory that contains the template files. * @throws InvalidConfigException if {@link templates} is empty or template selection is invalid */ public function getTemplatePath() { if (isset($this->templates[$this->template])) { return $this->templates[$this->template]; } else { throw new InvalidConfigException("Unknown template: {$this->template}"); } } /** * @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 === CodeFile::OP_NEW || is_array($this->answers) && isset($this->answers[md5($file->path)]); } /** * Generates the code using the specified code template file. * 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 * @return string the generated code */ public function render($templateFile, $params = array()) { $view = new View; return $view->renderFile($templateFile, $params, $this); } /** * @return string the code generation result log. */ public function renderResults() { $output = 'Generating code using template "' . $this->templatePath . "\"...\n"; foreach ($this->files as $file) { if ($file->error !== null) { $output .= "generating {$file->relativePath}