view.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: console_2libs_2tasks_2view_8php-source.html 580 2008-07-01 14:45:49Z gwoo $ */
00003 /**
00004  * The View Tasks handles creating and updating view files.
00005  *
00006  * Long description for file
00007  *
00008  * PHP versions 4 and 5
00009  *
00010  * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
00011  * Copyright 2005-2008, Cake Software Foundation, Inc.
00012  *                              1785 E. Sahara Avenue, Suite 490-204
00013  *                              Las Vegas, Nevada 89104
00014  *
00015  * Licensed under The MIT License
00016  * Redistributions of files must retain the above copyright notice.
00017  *
00018  * @filesource
00019  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00020  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00021  * @package         cake
00022  * @subpackage      cake.cake.console.libs.tasks
00023  * @since           CakePHP(tm) v 1.2
00024  * @version         $Revision: 580 $
00025  * @modifiedby      $LastChangedBy: gwoo $
00026  * @lastmodified    $Date: 2008-07-01 09:45:49 -0500 (Tue, 01 Jul 2008) $
00027  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00028  */
00029 App::import('Core', 'Controller');
00030 /**
00031  * Task class for creating and updating view files.
00032  *
00033  * @package     cake
00034  * @subpackage  cake.cake.console.libs.tasks
00035  */
00036 class ViewTask extends Shell {
00037 /**
00038  * Name of plugin
00039  *
00040  * @var string
00041  * @access public
00042  */
00043     var $plugin = null;
00044 /**
00045  * Tasks to be loaded by this Task
00046  *
00047  * @var array
00048  * @access public
00049  */
00050     var $tasks = array('Project', 'Controller');
00051 /**
00052  * path to VIEWS directory
00053  *
00054  * @var array
00055  * @access public
00056  */
00057     var $path = VIEWS;
00058 /**
00059  * Name of the controller being used
00060  *
00061  * @var string
00062  * @access public
00063  */
00064     var $controllerName = null;
00065 /**
00066  * Path to controller to put views
00067  *
00068  * @var string
00069  * @access public
00070  */
00071     var $controllerPath = null;
00072 /**
00073  * The template file to use
00074  *
00075  * @var string
00076  * @access public
00077  */
00078     var $template = null;
00079 /**
00080  * Actions to use for scaffolding
00081  *
00082  * @var array
00083  * @access public
00084  */
00085     var $scaffoldActions = array('index', 'view', 'add', 'edit');
00086 /**
00087  * Override initialize
00088  *
00089  * @access public
00090  */
00091     function initialize() {
00092     }
00093 /**
00094  * Execution method always used for tasks
00095  *
00096  * @access public
00097  */
00098     function execute() {
00099         if (empty($this->args)) {
00100             $this->__interactive();
00101         }
00102 
00103         if (isset($this->args[0])) {
00104             $controller = $action = $alias = null;
00105             $this->controllerName = Inflector::camelize($this->args[0]);
00106             $this->controllerPath = Inflector::underscore($this->controllerName);
00107 
00108             if (isset($this->args[1])) {
00109                 $this->template = $this->args[1];
00110             }
00111 
00112             if (isset($this->args[2])) {
00113                 $action = $this->args[2];
00114             }
00115 
00116             if (!$action) {
00117                 $action = $this->template;
00118             }
00119 
00120             if (in_array($action, $this->scaffoldActions)) {
00121                 $this->bake($action, true);
00122             } elseif ($action) {
00123                 $this->bake($action, true);
00124             } else {
00125                 $vars = $this->__loadController();
00126                 if ($vars) {
00127                     $protected = array_map('strtolower', get_class_methods('appcontroller'));
00128                     $classVars = get_class_vars($this->controllerName . 'Controller');
00129                     if (array_key_exists('scaffold', $classVars)) {
00130                         $methods = $this->scaffoldActions;
00131                     } else {
00132                         $methods = get_class_methods($this->controllerName . 'Controller');
00133                     }
00134                     $adminDelete = null;
00135 
00136                     $adminRoute = Configure::read('Routing.admin');
00137                     if (!empty($adminRoute)) {
00138                         $adminDelete = $adminRoute.'_delete';
00139                     }
00140                     foreach ($methods as $method) {
00141                         if ($method{0} != '_' && !in_array(low($method), array_merge($protected, array('delete', $adminDelete)))) {
00142                             $content = $this->getContent($method, $vars);
00143                             $this->bake($method, $content);
00144                         }
00145                     }
00146                 }
00147             }
00148         }
00149     }
00150 /**
00151  * Handles interactive baking
00152  *
00153  * @access private
00154  */
00155     function __interactive() {
00156         $this->hr();
00157         $this->out(sprintf("Bake View\nPath: %s", $this->path));
00158         $this->hr();
00159         $wannaDoAdmin = 'n';
00160         $wannaDoScaffold = 'y';
00161         $this->interactive = false;
00162 
00163         $this->controllerName = $this->Controller->getName();
00164 
00165         $this->controllerPath = low(Inflector::underscore($this->controllerName));
00166 
00167         $interactive = $this->in("Would you like bake to build your views interactively?\nWarning: Choosing no will overwrite {$this->controllerName} views if it exist.", array('y','n'), 'y');
00168 
00169         if (low($interactive) == 'y' || low($interactive) == 'yes') {
00170             $this->interactive = true;
00171             $wannaDoScaffold = $this->in("Would you like to create some scaffolded views (index, add, view, edit) for this controller?\nNOTE: Before doing so, you'll need to create your controller and model classes (including associated models).", array('y','n'), 'n');
00172         }
00173 
00174         if (low($wannaDoScaffold) == 'y' || low($wannaDoScaffold) == 'yes') {
00175             $wannaDoAdmin = $this->in("Would you like to create the views for admin routing?", array('y','n'), 'y');
00176         }
00177         $admin = false;
00178 
00179         if ((low($wannaDoAdmin) == 'y' || low($wannaDoAdmin) == 'yes')) {
00180             $admin = $this->getAdmin();
00181         }
00182 
00183         if (low($wannaDoScaffold) == 'y' || low($wannaDoScaffold) == 'yes') {
00184             $actions = $this->scaffoldActions;
00185             if ($admin) {
00186                 foreach ($actions as $action) {
00187                     $actions[] = $admin . $action;
00188                 }
00189             }
00190             $vars = $this->__loadController();
00191             if ($vars) {
00192                 foreach ($actions as $action) {
00193                     $content = $this->getContent($action, $vars);
00194                     $this->bake($action, $content);
00195                 }
00196             }
00197             $this->hr();
00198             $this->out('');
00199             $this->out('View Scaffolding Complete.'."\n");
00200         } else {
00201             $action = '';
00202             while ($action == '') {
00203                 $action = $this->in('Action Name? (use camelCased function name)');
00204                 if ($action == '') {
00205                     $this->out('The action name you supplied was empty. Please try again.');
00206                 }
00207             }
00208             $this->out('');
00209             $this->hr();
00210             $this->out('The following view will be created:');
00211             $this->hr();
00212             $this->out("Controller Name: {$this->controllerName}");
00213             $this->out("Action Name:     {$action}");
00214             $this->out("Path:            ".$this->params['app'] . DS . $this->controllerPath . DS . Inflector::underscore($action) . ".ctp");
00215             $this->hr();
00216             $looksGood = $this->in('Look okay?', array('y','n'), 'y');
00217             if (low($looksGood) == 'y' || low($looksGood) == 'yes') {
00218                 $this->bake($action);
00219                 $this->_stop();
00220             } else {
00221                 $this->out('Bake Aborted.');
00222             }
00223         }
00224     }
00225 /**
00226  * Loads Controller and sets variables for the template
00227  * Available template variables
00228  *  'modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar',
00229  *  'singularHumanName', 'pluralHumanName', 'fields', 'foreignKeys',
00230  *  'belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'
00231  *
00232  * @return array Returns an variables to be made available to a view template
00233  * @access private
00234  */
00235     function __loadController() {
00236         if (!$this->controllerName) {
00237             $this->err(__('Controller not found', true));
00238         }
00239 
00240         $import = $this->controllerName;
00241         if ($this->plugin) {
00242             $import = $this->plugin . '.' . $this->controllerName;
00243         }
00244 
00245         if (!App::import('Controller', $import)) {
00246             $file = $this->controllerPath . '_controller.php';
00247             $this->err(sprintf(__("The file '%s' could not be found.\nIn order to bake a view, you'll need to first create the controller.", true), $file));
00248             $this->_stop();
00249         }
00250         $controllerClassName = $this->controllerName . 'Controller';
00251         $controllerObj = & new $controllerClassName();
00252         $controllerObj->constructClasses();
00253         $modelClass = $controllerObj->modelClass;
00254         $modelObj =& ClassRegistry::getObject($controllerObj->modelKey);
00255 
00256         if ($modelObj) {
00257             $primaryKey = $modelObj->primaryKey;
00258             $displayField = $modelObj->displayField;
00259             $singularVar = Inflector::variable($modelClass);
00260             $pluralVar = Inflector::variable($this->controllerName);
00261             $singularHumanName = Inflector::humanize($modelClass);
00262             $pluralHumanName = Inflector::humanize($this->controllerName);
00263             $schema = $modelObj->schema();
00264             $fields = array_keys($schema);
00265             $associations = $this->__associations($modelObj);
00266         } else {
00267             $primaryKey = null;
00268             $displayField = null;
00269             $singularVar = Inflector::variable(Inflector::singularize($this->controllerName));
00270             $pluralVar = Inflector::variable($this->controllerName);
00271             $singularHumanName = Inflector::humanize(Inflector::singularize($this->controllerName));
00272             $pluralHumanName = Inflector::humanize($this->controllerName);
00273             $fields = array();
00274             $schema = array();
00275             $associations = array();
00276         }
00277 
00278         return compact('modelClass', 'schema', 'primaryKey', 'displayField', 'singularVar', 'pluralVar',
00279                 'singularHumanName', 'pluralHumanName', 'fields','associations');
00280     }
00281 /**
00282  * Assembles and writes bakes the view file.
00283  *
00284  * @param string $action Action to bake
00285  * @param string $content Content to write
00286  * @return boolean Success
00287  * @access public
00288  */
00289     function bake($action, $content = '') {
00290         if ($content === true) {
00291             $content = $this->getContent();
00292         }
00293         $filename = $this->path . $this->controllerPath . DS . Inflector::underscore($action) . '.ctp';
00294         $Folder =& new Folder($this->path . $this->controllerPath, true);
00295         $errors = $Folder->errors();
00296         if (empty($errors)) {
00297             $path = $Folder->slashTerm($Folder->pwd());
00298             return $this->createFile($filename, $content);
00299         } else {
00300             foreach ($errors as $error) {
00301                 $this->err($error);
00302             }
00303         }
00304         return false;
00305     }
00306 /**
00307  * Builds content from template and variables
00308  *
00309  * @param string $template file to use
00310  * @param array $vars passed for use in templates
00311  * @return string content from template
00312  * @access public
00313  */
00314     function getContent($template = null, $vars = null) {
00315         if (!$template) {
00316             $template = $this->template;
00317         }
00318         $action = $template;
00319 
00320         $adminRoute = Configure::read('Routing.admin');
00321         if (!empty($adminRoute) && strpos($template, $adminRoute) !== false) {
00322             $template = str_replace($adminRoute.'_', '', $template);
00323         }
00324         if (in_array($template, array('add', 'edit'))) {
00325             $action = $template;
00326             $template = 'form';
00327         }
00328         $loaded = false;
00329         foreach ($this->Dispatch->shellPaths as $path) {
00330             $templatePath = $path . 'templates' . DS . 'views' . DS .Inflector::underscore($template).'.ctp';
00331             if (file_exists($templatePath) && is_file($templatePath)) {
00332                 $loaded = true;
00333                 break;
00334             }
00335         }
00336         if (!$vars) {
00337             $vars = $this->__loadController();
00338         }
00339         if ($loaded) {
00340             extract($vars);
00341             ob_start();
00342             ob_implicit_flush(0);
00343             include($templatePath);
00344             $content = ob_get_clean();
00345             return $content;
00346         }
00347         $this->hr();
00348         $this->err(sprintf(__('Template for %s could not be found', true), $template));
00349         return false;
00350     }
00351 /**
00352  * Displays help contents
00353  *
00354  * @access public
00355  */
00356     function help() {
00357         $this->hr();
00358         $this->out("Usage: cake bake view <arg1> <arg2>...");
00359         $this->hr();
00360         $this->out('Commands:');
00361         $this->out("\n\tview <controller>\n\t\twill read the given controller for methods\n\t\tand bake corresponding views.\n\t\tIf var scaffold is found it will bake the scaffolded actions\n\t\t(index,view,add,edit)");
00362         $this->out("\n\tview <controller> <action>\n\t\twill bake a template. core templates: (index, add, edit, view)");
00363         $this->out("\n\tview <controller> <template> <alias>\n\t\twill use the template specified but name the file based on the alias");
00364         $this->out("");
00365         $this->_stop();
00366     }
00367 /**
00368  * Returns associations for controllers models.
00369  *
00370  * @return  array $associations
00371  * @access private
00372  */
00373     function __associations($model) {
00374         $keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
00375         $associations = array();
00376 
00377         foreach ($keys as $key => $type){
00378             foreach ($model->{$type} as $assocKey => $assocData) {
00379                 $associations[$type][$assocKey]['primaryKey'] = $model->{$assocKey}->primaryKey;
00380                 $associations[$type][$assocKey]['displayField'] = $model->{$assocKey}->displayField;
00381                 $associations[$type][$assocKey]['foreignKey'] = $assocData['foreignKey'];
00382                 $associations[$type][$assocKey]['controller'] = Inflector::pluralize(Inflector::underscore($assocData['className']));
00383                 $associations[$type][$assocKey]['fields'] =  array_keys($model->{$assocKey}->schema());
00384             }
00385         }
00386         return $associations;
00387     }
00388 }
00389 
00390 ?>