Development

/branches/1.3/lib/view/sfView.class.php

You must first sign up to be able to contribute.

root/branches/1.3/lib/view/sfView.class.php

Revision 28713, 14.5 kB (checked in by fabien, 4 years ago)

[1.3, 1.4] fixed layout.php is required even if you use decorate_with() to use another layout (closes #8441)

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1 <?php
2
3 /*
4  * This file is part of the symfony package.
5  * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
6  * (c) 2004-2006 Sean Kerr <sean@code-box.org>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 /**
13  * A view represents the presentation layer of an action. Output can be
14  * customized by supplying attributes, which a template can manipulate and
15  * display.
16  *
17  * @package    symfony
18  * @subpackage view
19  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
20  * @author     Sean Kerr <sean@code-box.org>
21  * @version    SVN: $Id$
22  */
23 abstract class sfView
24 {
25   /**
26    * Show an alert view.
27    */
28   const ALERT = 'Alert';
29
30   /**
31    * Show an error view.
32    */
33   const ERROR = 'Error';
34
35   /**
36    * Show a form input view.
37    */
38   const INPUT = 'Input';
39
40   /**
41    * Skip view execution.
42    */
43   const NONE = 'None';
44
45   /**
46    * Show a success view.
47    */
48   const SUCCESS = 'Success';
49
50   /**
51    * Do not render the presentation.
52    */
53   const RENDER_NONE = 1;
54
55   /**
56    * Render the presentation to the client.
57    */
58   const RENDER_CLIENT = 2;
59
60   /**
61    * Render the presentation to a variable.
62    */
63   const RENDER_VAR = 4;
64
65   /**
66    * Skip view rendering but output http headers
67    */
68   const HEADER_ONLY = 8;
69
70   protected
71     $context            = null,
72     $dispatcher         = null,
73     $decorator          = false,
74     $decoratorDirectory = null,
75     $decoratorTemplate  = null,
76     $directory          = null,
77     $componentSlots     = array(),
78     $template           = null,
79     $attributeHolder    = null,
80     $parameterHolder    = null,
81     $moduleName         = '',
82     $actionName         = '',
83     $viewName           = '',
84     $extension          = '.php';
85
86   /**
87    * Class constructor.
88    *
89    * @see initialize()
90    */
91   public function __construct($context, $moduleName, $actionName, $viewName)
92   {
93     $this->initialize($context, $moduleName, $actionName, $viewName);
94   }
95
96   /**
97    * Initializes this view.
98    *
99    * @param  sfContext $context     The current application context
100    * @param  string    $moduleName  The module name for this view
101    * @param  string    $actionName  The action name for this view
102    * @param  string    $viewName    The view name
103    *
104    * @return bool  true, if initialization completes successfully, otherwise false
105    */
106   public function initialize($context, $moduleName, $actionName, $viewName)
107   {
108     $this->moduleName = $moduleName;
109     $this->actionName = $actionName;
110     $this->viewName   = $viewName;
111
112     $this->context    = $context;
113     $this->dispatcher = $context->getEventDispatcher();
114
115     sfOutputEscaper::markClassesAsSafe(array('sfForm', 'sfFormField', 'sfFormFieldSchema', 'sfModelGeneratorHelper'));
116
117     $this->attributeHolder = $this->initializeAttributeHolder();
118
119     $this->parameterHolder = new sfParameterHolder();
120     $this->parameterHolder->add(sfConfig::get('mod_'.strtolower($moduleName).'_view_param', array()));
121
122     $request = $context->getRequest();
123
124     $format = $request->getRequestFormat();
125     if (null !== $format)
126     {
127       if ('html' != $format)
128       {
129         $this->setExtension('.'.$format.$this->getExtension());
130       }
131
132       if ($mimeType = $request->getMimeType($format))
133       {
134         $this->context->getResponse()->setContentType($mimeType);
135
136         if ('html' != $format)
137         {
138           $this->setDecorator(false);
139         }
140       }
141     }
142     $this->dispatcher->notify(new sfEvent($this, 'view.configure_format', array('format' => $format, 'response' => $context->getResponse(), 'request' => $context->getRequest())));
143
144     // include view configuration
145     $this->configure();
146
147     return true;
148   }
149
150   protected function initializeAttributeHolder($attributes = array())
151   {
152     if ('both' === sfConfig::get('sf_escaping_strategy'))
153     {
154       $this->dispatcher->notify(new sfEvent($this, 'application.log', array('Escaping strategy "both" is deprecated, please use "on".', 'priority' => sfLogger::ERR)));
155       sfConfig::set('sf_escaping_strategy', 'on');
156     }
157     else if ('bc' === sfConfig::get('sf_escaping_strategy'))
158     {
159       $this->dispatcher->notify(new sfEvent($this, 'application.log', array('Escaping strategy "bc" is deprecated, please use "off".', 'priority' => sfLogger::ERR)));
160       sfConfig::set('sf_escaping_strategy', 'off');
161     }
162
163     $attributeHolder = new sfViewParameterHolder($this->dispatcher, $attributes, array(
164       'escaping_method'   => sfConfig::get('sf_escaping_method'),
165       'escaping_strategy' => sfConfig::get('sf_escaping_strategy'),
166     ));
167
168     return $attributeHolder;
169   }
170
171   /**
172    * Executes any presentation logic and set template attributes.
173    */
174   abstract function execute();
175
176   /**
177    * Configures template.
178    */
179   abstract function configure();
180
181   /**
182    * Retrieves this views decorator template directory.
183    *
184    * @return string An absolute filesystem path to this views decorator template directory
185    */
186   public function getDecoratorDirectory()
187   {
188     return $this->decoratorDirectory;
189   }
190
191   /**
192    * Retrieves this views decorator template.
193    *
194    * @return string A template filename, if a template has been set, otherwise null
195    */
196   public function getDecoratorTemplate()
197   {
198     return $this->decoratorTemplate;
199   }
200
201   /**
202    * Retrieves this view template directory.
203    *
204    * @return string An absolute filesystem path to this views template directory
205    */
206   public function getDirectory()
207   {
208     return $this->directory;
209   }
210
211   /**
212    * Retrieves the template engine associated with this view.
213    *
214    * Note: This will return null for PHPView instances.
215    *
216    * @return mixed A template engine instance
217    */
218   abstract function getEngine();
219
220   /**
221    * Retrieves this views template.
222    *
223    * @return string A template filename, if a template has been set, otherwise null
224    */
225   public function getTemplate()
226   {
227     return $this->template;
228   }
229
230   /**
231    * Retrieves attributes for the current view.
232    *
233    * @return sfParameterHolder The attribute parameter holder
234    */
235   public function getAttributeHolder()
236   {
237     return $this->attributeHolder;
238   }
239
240   /**
241    * Retrieves an attribute for the current view.
242    *
243    * @param  string $name     Name of the attribute
244    * @param  string $default  Value of the attribute
245    *
246    * @return mixed Attribute
247    */
248   public function getAttribute($name, $default = null)
249   {
250     return $this->attributeHolder->get($name, $default);
251   }
252
253   /**
254    * Returns true if the view have attributes.
255    *
256    * @param  string $name  Name of the attribute
257    *
258    * @return mixed Attribute of the view
259    */
260   public function hasAttribute($name)
261   {
262     return $this->attributeHolder->has($name);
263   }
264
265   /**
266    * Sets an attribute of the view.
267    *
268    * @param string $name   Attribute name
269    * @param string $value  Value for the attribute
270    */
271   public function setAttribute($name, $value)
272   {
273     $this->attributeHolder->set($name, $value);
274   }
275
276   /**
277    * Retrieves the parameters for the current view.
278    *
279    * @return sfParameterHolder The parameter holder
280    */
281   public function getParameterHolder()
282   {
283     return $this->parameterHolder;
284   }
285
286   /**
287    * Retrieves a parameter from the current view.
288    *
289    * @param  string $name     Parameter name
290    * @param  string $default  Default parameter value
291    *
292    * @return mixed A parameter value
293    */
294   public function getParameter($name, $default = null)
295   {
296     return $this->parameterHolder->get($name, $default);
297   }
298
299   /**
300    * Indicates whether or not a parameter exist for the current view.
301    *
302    * @param  string $name  Name of the parameter
303    *
304    * @return bool true, if the parameter exists otherwise false
305    */
306   public function hasParameter($name)
307   {
308     return $this->parameterHolder->has($name);
309   }
310
311   /**
312    * Sets a parameter for the view.
313    *
314    * @param string $name   Name of the parameter
315    * @param string $value  The parameter value
316    */
317   public function setParameter($name, $value)
318   {
319     $this->parameterHolder->set($name, $value);
320   }
321
322   /**
323    * Indicates that this view is a decorating view.
324    *
325    * @return bool true, if this view is a decorating view, otherwise false
326    */
327   public function isDecorator()
328   {
329     return $this->decorator;
330   }
331
332   /**
333    * Sets the decorating mode for the current view.
334    *
335    * @param bool $boolean  Set the decorating mode for the view
336    */
337   public function setDecorator($boolean)
338   {
339     $this->decorator = (boolean) $boolean;
340
341     if (false === $boolean)
342     {
343       $this->decoratorTemplate = false;
344     }
345   }
346
347   /**
348    * Executes a basic pre-render check to verify all required variables exist
349    * and that the template is readable.
350    *
351    * @throws sfRenderException If the pre-render check fails
352    */
353   protected function preRenderCheck()
354   {
355     if (null === $this->template)
356     {
357       // a template has not been set
358       throw new sfRenderException('A template has not been set.');
359     }
360
361     if (!is_readable($this->directory.'/'.$this->template))
362     {
363       // 404?
364       if ('404' == $this->context->getResponse()->getStatusCode())
365       {
366         // use default exception templates
367         $this->template = sfException::getTemplatePathForError($this->context->getRequest()->getRequestFormat(), false);
368         $this->directory = dirname($this->template);
369         $this->template = basename($this->template);
370         $this->setAttribute('code', '404');
371         $this->setAttribute('text', 'Not Found');
372       }
373       else
374       {
375         throw new sfRenderException(sprintf('The template "%s" does not exist or is unreadable in "%s".', $this->template, $this->directory));
376       }
377     }
378   }
379
380   /**
381    * Renders the presentation.
382    *
383    * @return string A string representing the rendered presentation
384    */
385   abstract function render();
386
387   /**
388    * Sets the decorator template directory for this view.
389    *
390    * @param string $directory  An absolute filesystem path to a template directory
391    */
392   public function setDecoratorDirectory($directory)
393   {
394     $this->decoratorDirectory = $directory;
395   }
396
397   /**
398    * Sets the decorator template for this view.
399    *
400    * If the template path is relative, it will be based on the currently
401    * executing module's template sub-directory.
402    *
403    * @param string $template  An absolute or relative filesystem path to a template
404    */
405   public function setDecoratorTemplate($template)
406   {
407     if (false === $template)
408     {
409       $this->setDecorator(false);
410
411       return;
412     }
413     else if (null === $template)
414     {
415       return;
416     }
417
418     if (!strpos($template, '.'))
419     {
420       $template .= $this->getExtension();
421     }
422
423     if (sfToolkit::isPathAbsolute($template))
424     {
425       $this->decoratorDirectory = dirname($template);
426       $this->decoratorTemplate  = basename($template);
427     }
428     else
429     {
430       $this->decoratorDirectory = $this->context->getConfiguration()->getDecoratorDir($template);
431       $this->decoratorTemplate = $template;
432     }
433
434     // set decorator status
435     $this->decorator = true;
436   }
437
438   /**
439    * Sets the template directory for this view.
440    *
441    * @param string $directory  An absolute filesystem path to a template directory
442    */
443   public function setDirectory($directory)
444   {
445     $this->directory = $directory;
446   }
447
448   /**
449    * Sets the module and action to be executed in place of a particular template attribute.
450    *
451    * @param string $attributeName  A template attribute name
452    * @param string $moduleName     A module name
453    * @param string $componentName  A component name
454    */
455   public function setComponentSlot($attributeName, $moduleName, $componentName)
456   {
457     $this->componentSlots[$attributeName]                   = array();
458     $this->componentSlots[$attributeName]['module_name']    = $moduleName;
459     $this->componentSlots[$attributeName]['component_name'] = $componentName;
460   }
461
462   /**
463    * Indicates whether or not a component slot exists.
464    *
465    * @param  string $name  The component slot name
466    *
467    * @return bool true, if the component slot exists, otherwise false
468    */
469   public function hasComponentSlot($name)
470   {
471     return isset($this->componentSlots[$name]);
472   }
473
474   /**
475    * Gets a component slot
476    *
477    * @param  string $name  The component slot name
478    *
479    * @return array The component slot
480    */
481   public function getComponentSlot($name)
482   {
483     if (isset($this->componentSlots[$name]) && $this->componentSlots[$name]['module_name'] && $this->componentSlots[$name]['component_name'])
484     {
485       return array($this->componentSlots[$name]['module_name'], $this->componentSlots[$name]['component_name']);
486     }
487
488     return null;
489   }
490
491   /**
492    * Sets the template for this view.
493    *
494    * If the template path is relative, it will be based on the currently
495    * executing module's template sub-directory.
496    *
497    * @param string $template  An absolute or relative filesystem path to a template
498    */
499   public function setTemplate($template)
500   {
501     if (sfToolkit::isPathAbsolute($template))
502     {
503       $this->directory = dirname($template);
504       $this->template  = basename($template);
505     }
506     else
507     {
508       $this->directory = $this->context->getConfiguration()->getTemplateDir($this->moduleName, $template);
509       $this->template = $template;
510     }
511   }
512
513   /**
514    * Retrieves the current view extension.
515    *
516    * @return string The extension for current view.
517    */
518   public function getExtension()
519   {
520     return $this->extension;
521   }
522
523   /**
524    * Sets an extension for the current view.
525    *
526    * @param string $extension  The extension name.
527    */
528   public function setExtension($extension)
529   {
530     $this->extension = $extension;
531   }
532
533   /**
534    * Gets the module name associated with this view.
535    *
536    * @return string A module name
537    */
538   public function getModuleName()
539   {
540     return $this->moduleName;
541   }
542
543   /**
544    * Gets the action name associated with this view.
545    *
546    * @return string An action name
547    */
548   public function getActionName()
549   {
550     return $this->actionName;
551   }
552
553   /**
554    * Gets the view name associated with this view.
555    *
556    * @return string An action name
557    */
558   public function getViewName()
559   {
560     return $this->viewName;
561   }
562
563   /**
564    * Calls methods defined via sfEventDispatcher.
565    *
566    * @param  string $method     The method name
567    * @param  array  $arguments  The method arguments
568    *
569    * @return mixed The returned value of the called method
570    *
571    * @throws sfException< If the calls fails
572    */
573   public function __call($method, $arguments)
574   {
575     $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'view.method_not_found', array('method' => $method, 'arguments' => $arguments)));
576     if (!$event->isProcessed())
577     {
578       throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
579     }
580
581     return $event->getReturnValue();
582   }
583 }
584
Note: See TracBrowser for help on using the browser.