Subversion-Projekte lars-tiefland.cakephp

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* SVN FILE: $Id: view.php 7945 2008-12-19 02:16:01Z gwoo $ */
3
/**
4
 * The View Tasks handles creating and updating view files.
5
 *
6
 * Long description for file
7
 *
8
 * PHP versions 4 and 5
9
 *
10
 * CakePHP(tm) :  Rapid Development Framework (http://www.cakephp.org)
11
 * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
12
 *
13
 * Licensed under The MIT License
14
 * Redistributions of files must retain the above copyright notice.
15
 *
16
 * @filesource
17
 * @copyright     Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
18
 * @link          http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
19
 * @package       cake
20
 * @subpackage    cake.cake.console.libs.tasks
21
 * @since         CakePHP(tm) v 1.2
22
 * @version       $Revision: 7945 $
23
 * @modifiedby    $LastChangedBy: gwoo $
24
 * @lastmodified  $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
25
 * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
26
 */
27
App::import('Core', 'Controller');
28
/**
29
 * Task class for creating and updating view files.
30
 *
31
 * @package       cake
32
 * @subpackage    cake.cake.console.libs.tasks
33
 */
34
class ViewTask extends Shell {
35
/**
36
 * Name of plugin
37
 *
38
 * @var string
39
 * @access public
40
 */
41
	var $plugin = null;
42
/**
43
 * Tasks to be loaded by this Task
44
 *
45
 * @var array
46
 * @access public
47
 */
48
	var $tasks = array('Project', 'Controller');
49
/**
50
 * path to VIEWS directory
51
 *
52
 * @var array
53
 * @access public
54
 */
55
	var $path = VIEWS;
56
/**
57
 * Name of the controller being used
58
 *
59
 * @var string
60
 * @access public
61
 */
62
	var $controllerName = null;
63
/**
64
 * Path to controller to put views
65
 *
66
 * @var string
67
 * @access public
68
 */
69
	var $controllerPath = null;
70
/**
71
 * The template file to use
72
 *
73
 * @var string
74
 * @access public
75
 */
76
	var $template = null;
77
/**
78
 * Actions to use for scaffolding
79
 *
80
 * @var array
81
 * @access public
82
 */
83
	var $scaffoldActions = array('index', 'view', 'add', 'edit');
84
/**
85
 * Override initialize
86
 *
87
 * @access public
88
 */
89
	function initialize() {
90
	}
91
/**
92
 * Execution method always used for tasks
93
 *
94
 * @access public
95
 */
96
	function execute() {
97
		if (empty($this->args)) {
98
			$this->__interactive();
99
		}
100
 
101
		if (isset($this->args[0])) {
102
			$controller = $action = $alias = null;
103
			$this->controllerName = Inflector::camelize($this->args[0]);
104
			$this->controllerPath = Inflector::underscore($this->controllerName);
105
 
106
			if (isset($this->args[1])) {
107
				$this->template = $this->args[1];
108
			}
109
 
110
			if (isset($this->args[2])) {
111
				$action = $this->args[2];
112
			}
113
 
114
			if (!$action) {
115
				$action = $this->template;
116
			}
117
 
118
			if (in_array($action, $this->scaffoldActions)) {
119
				$this->bake($action, true);
120
			} elseif ($action) {
121
				$this->bake($action, true);
122
			} else {
123
				$vars = $this->__loadController();
124
				if ($vars) {
125
 
126
					$methods =  array_diff(
127
						array_map('strtolower', get_class_methods($this->controllerName . 'Controller')),
128
						array_map('strtolower', get_class_methods('appcontroller'))
129
					);
130
					if (empty($methods)) {
131
						$methods = $this->scaffoldActions;
132
					}
133
					$adminDelete = null;
134
 
135
					$adminRoute = Configure::read('Routing.admin');
136
					if (!empty($adminRoute)) {
137
						$adminDelete = $adminRoute.'_delete';
138
					}
139
					foreach ($methods as $method) {
140
						if ($method{0} != '_' && !in_array($method, array('delete', $adminDelete))) {
141
							$content = $this->getContent($method, $vars);
142
							$this->bake($method, $content);
143
						}
144
					}
145
				}
146
			}
147
		}
148
	}
149
/**
150
 * Handles interactive baking
151
 *
152
 * @access private
153
 */
154
	function __interactive() {
155
		$this->hr();
156
		$this->out(sprintf("Bake View\nPath: %s", $this->path));
157
		$this->hr();
158
		$wannaDoAdmin = 'n';
159
		$wannaDoScaffold = 'y';
160
		$this->interactive = false;
161
 
162
		$this->controllerName = $this->Controller->getName();
163
 
164
		$this->controllerPath = low(Inflector::underscore($this->controllerName));
165
 
166
		$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');
167
 
168
		if (low($interactive) == 'y' || low($interactive) == 'yes') {
169
			$this->interactive = true;
170
			$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');
171
		}
172
 
173
		if (low($wannaDoScaffold) == 'y' || low($wannaDoScaffold) == 'yes') {
174
			$wannaDoAdmin = $this->in("Would you like to create the views for admin routing?", array('y','n'), 'y');
175
		}
176
		$admin = false;
177
 
178
		if ((low($wannaDoAdmin) == 'y' || low($wannaDoAdmin) == 'yes')) {
179
			$admin = $this->getAdmin();
180
		}
181
 
182
		if (low($wannaDoScaffold) == 'y' || low($wannaDoScaffold) == 'yes') {
183
			$actions = $this->scaffoldActions;
184
			if ($admin) {
185
				foreach ($actions as $action) {
186
					$actions[] = $admin . $action;
187
				}
188
			}
189
			$vars = $this->__loadController();
190
			if ($vars) {
191
				foreach ($actions as $action) {
192
					$content = $this->getContent($action, $vars);
193
					$this->bake($action, $content);
194
				}
195
			}
196
			$this->hr();
197
			$this->out('');
198
			$this->out('View Scaffolding Complete.'."\n");
199
		} else {
200
			$action = '';
201
			while ($action == '') {
202
				$action = $this->in('Action Name? (use camelCased function name)');
203
				if ($action == '') {
204
					$this->out('The action name you supplied was empty. Please try again.');
205
				}
206
			}
207
			$this->out('');
208
			$this->hr();
209
			$this->out('The following view will be created:');
210
			$this->hr();
211
			$this->out("Controller Name: {$this->controllerName}");
212
			$this->out("Action Name:	 {$action}");
213
			$this->out("Path:			 ".$this->params['app'] . DS . $this->controllerPath . DS . Inflector::underscore($action) . ".ctp");
214
			$this->hr();
215
			$looksGood = $this->in('Look okay?', array('y','n'), 'y');
216
			if (low($looksGood) == 'y' || low($looksGood) == 'yes') {
217
				$this->bake($action);
218
				$this->_stop();
219
			} else {
220
				$this->out('Bake Aborted.');
221
			}
222
		}
223
	}
224
/**
225
 * Loads Controller and sets variables for the template
226
 * Available template variables
227
 *	'modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar',
228
 *	'singularHumanName', 'pluralHumanName', 'fields', 'foreignKeys',
229
 *	'belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'
230
 *
231
 * @return array Returns an variables to be made available to a view template
232
 * @access private
233
 */
234
	function __loadController() {
235
		if (!$this->controllerName) {
236
			$this->err(__('Controller not found', true));
237
		}
238
 
239
		$import = $this->controllerName;
240
		if ($this->plugin) {
241
			$import = $this->plugin . '.' . $this->controllerName;
242
		}
243
 
244
		if (!App::import('Controller', $import)) {
245
			$file = $this->controllerPath . '_controller.php';
246
			$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));
247
			$this->_stop();
248
		}
249
		$controllerClassName = $this->controllerName . 'Controller';
250
		$controllerObj = & new $controllerClassName();
251
		$controllerObj->constructClasses();
252
		$modelClass = $controllerObj->modelClass;
253
		$modelObj =& ClassRegistry::getObject($controllerObj->modelKey);
254
 
255
		if ($modelObj) {
256
			$primaryKey = $modelObj->primaryKey;
257
			$displayField = $modelObj->displayField;
258
			$singularVar = Inflector::variable($modelClass);
259
			$pluralVar = Inflector::variable($this->controllerName);
260
			$singularHumanName = Inflector::humanize($modelClass);
261
			$pluralHumanName = Inflector::humanize($this->controllerName);
262
			$schema = $modelObj->schema();
263
			$fields = array_keys($schema);
264
			$associations = $this->__associations($modelObj);
265
		} else {
266
			$primaryKey = null;
267
			$displayField = null;
268
			$singularVar = Inflector::variable(Inflector::singularize($this->controllerName));
269
			$pluralVar = Inflector::variable($this->controllerName);
270
			$singularHumanName = Inflector::humanize(Inflector::singularize($this->controllerName));
271
			$pluralHumanName = Inflector::humanize($this->controllerName);
272
			$fields = array();
273
			$schema = array();
274
			$associations = array();
275
		}
276
 
277
		return compact('modelClass', 'schema', 'primaryKey', 'displayField', 'singularVar', 'pluralVar',
278
				'singularHumanName', 'pluralHumanName', 'fields','associations');
279
	}
280
/**
281
 * Assembles and writes bakes the view file.
282
 *
283
 * @param string $action Action to bake
284
 * @param string $content Content to write
285
 * @return boolean Success
286
 * @access public
287
 */
288
	function bake($action, $content = '') {
289
		if ($content === true) {
290
			$content = $this->getContent();
291
		}
292
		$filename = $this->path . $this->controllerPath . DS . Inflector::underscore($action) . '.ctp';
293
		$Folder =& new Folder($this->path . $this->controllerPath, true);
294
		$errors = $Folder->errors();
295
		if (empty($errors)) {
296
			$path = $Folder->slashTerm($Folder->pwd());
297
			return $this->createFile($filename, $content);
298
		} else {
299
			foreach ($errors as $error) {
300
				$this->err($error);
301
			}
302
		}
303
		return false;
304
	}
305
/**
306
 * Builds content from template and variables
307
 *
308
 * @param string $template file to use
309
 * @param array $vars passed for use in templates
310
 * @return string content from template
311
 * @access public
312
 */
313
	function getContent($template = null, $vars = null) {
314
		if (!$template) {
315
			$template = $this->template;
316
		}
317
		$action = $template;
318
 
319
		$adminRoute = Configure::read('Routing.admin');
320
		if (!empty($adminRoute) && strpos($template, $adminRoute) !== false) {
321
			$template = str_replace($adminRoute.'_', '', $template);
322
		}
323
		if (in_array($template, array('add', 'edit'))) {
324
			$action = $template;
325
			$template = 'form';
326
		}
327
		$loaded = false;
328
		foreach ($this->Dispatch->shellPaths as $path) {
329
			$templatePath = $path . 'templates' . DS . 'views' . DS .Inflector::underscore($template).'.ctp';
330
			if (file_exists($templatePath) && is_file($templatePath)) {
331
				$loaded = true;
332
				break;
333
			}
334
		}
335
		if (!$vars) {
336
			$vars = $this->__loadController();
337
		}
338
		if ($loaded) {
339
			extract($vars);
340
			ob_start();
341
			ob_implicit_flush(0);
342
			include($templatePath);
343
			$content = ob_get_clean();
344
			return $content;
345
		}
346
		$this->hr();
347
		$this->err(sprintf(__('Template for %s could not be found', true), $template));
348
		return false;
349
	}
350
/**
351
 * Displays help contents
352
 *
353
 * @access public
354
 */
355
	function help() {
356
		$this->hr();
357
		$this->out("Usage: cake bake view <arg1> <arg2>...");
358
		$this->hr();
359
		$this->out('Commands:');
360
		$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)");
361
		$this->out("\n\tview <controller> <action>\n\t\twill bake a template. core templates: (index, add, edit, view)");
362
		$this->out("\n\tview <controller> <template> <alias>\n\t\twill use the template specified but name the file based on the alias");
363
		$this->out("");
364
		$this->_stop();
365
	}
366
/**
367
 * Returns associations for controllers models.
368
 *
369
 * @return  array $associations
370
 * @access private
371
 */
372
	function __associations($model) {
373
		$keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
374
		$associations = array();
375
 
376
		foreach ($keys as $key => $type) {
377
			foreach ($model->{$type} as $assocKey => $assocData) {
378
				$associations[$type][$assocKey]['primaryKey'] = $model->{$assocKey}->primaryKey;
379
				$associations[$type][$assocKey]['displayField'] = $model->{$assocKey}->displayField;
380
				$associations[$type][$assocKey]['foreignKey'] = $assocData['foreignKey'];
381
				$associations[$type][$assocKey]['controller'] = Inflector::pluralize(Inflector::underscore($assocData['className']));
382
				$associations[$type][$assocKey]['fields'] =  array_keys($model->{$assocKey}->schema());
383
			}
384
		}
385
		return $associations;
386
	}
387
}
388
 
389
?>