Development

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

You must first sign up to be able to contribute.

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

Revision 24208, 14.8 kB (checked in by fabien, 4 years ago)

[1.2] reverting r23917 as it breaks BC (closes #7560)

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Rev Date
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', '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     if (!is_null($format = $request->getRequestFormat()))
124     {
125       if ('html' != $format)
126       {
127         $this->setExtension('.'.$format.$this->getExtension());
128       }
129       
130       if ($mimeType = $request->getMimeType($format))
131       {
132         $this->context->getResponse()->setContentType($mimeType);
133         
134         if ('html' != $format)
135         {
136           $this->setDecorator(false);
137         }
138       }
139
140       $this->dispatcher->notify(new sfEvent($this, 'view.configure_format', array('format' => $format, 'response' => $context->getResponse(), 'request' => $context->getRequest())));
141     }
142
143     // include view configuration
144     $this->configure();
145
146     return true;
147   }
148
149   protected function initializeAttributeHolder($attributes = array())
150   {
151     if ('both' === sfConfig::get('sf_escaping_strategy'))
152     {
153       $this->dispatcher->notify(new sfEvent($this, 'application.log', array('Escaping strategy "both" is deprecated, please use "on".', 'priority' => sfLogger::ERR)));
154       sfConfig::set('sf_escaping_strategy', 'on');
155     }
156     else if ('bc' === sfConfig::get('sf_escaping_strategy'))
157     {
158       $this->dispatcher->notify(new sfEvent($this, 'application.log', array('Escaping strategy "bc" is deprecated, please use "off".', 'priority' => sfLogger::ERR)));
159       sfConfig::set('sf_escaping_strategy', 'off');
160     }
161
162     $attributeHolder = new sfViewParameterHolder($this->dispatcher, $attributes, array(
163       'escaping_method'   => sfConfig::get('sf_escaping_method'),
164       'escaping_strategy' => sfConfig::get('sf_escaping_strategy'),
165     ));
166
167     return $attributeHolder;
168   }
169
170   /**
171    * Executes any presentation logic and set template attributes.
172    */
173   abstract function execute();
174
175   /**
176    * Configures template.
177    */
178   abstract function configure();
179
180   /**
181    * Retrieves this views decorator template directory.
182    *
183    * @return string An absolute filesystem path to this views decorator template directory
184    */
185   public function getDecoratorDirectory()
186   {
187     return $this->decoratorDirectory;
188   }
189
190   /**
191    * Retrieves this views decorator template.
192    *
193    * @return string A template filename, if a template has been set, otherwise null
194    */
195   public function getDecoratorTemplate()
196   {
197     return $this->decoratorTemplate;
198   }
199
200   /**
201    * Retrieves this view template directory.
202    *
203    * @return string An absolute filesystem path to this views template directory
204    */
205   public function getDirectory()
206   {
207     return $this->directory;
208   }
209
210   /**
211    * Retrieves the template engine associated with this view.
212    *
213    * Note: This will return null for PHPView instances.
214    *
215    * @return mixed A template engine instance
216    */
217   abstract function getEngine();
218
219   /**
220    * Retrieves this views template.
221    *
222    * @return string A template filename, if a template has been set, otherwise null
223    */
224   public function getTemplate()
225   {
226     return $this->template;
227   }
228
229   /**
230    * Retrieves attributes for the current view.
231    *
232    * @return sfParameterHolder The attribute parameter holder
233    */
234   public function getAttributeHolder()
235   {
236     return $this->attributeHolder;
237   }
238
239   /**
240    * Retrieves an attribute for the current view.
241    *
242    * @param  string $name     Name of the attribute
243    * @param  string $default  Value of the attribute
244    *
245    * @return mixed Attribute
246    */
247   public function getAttribute($name, $default = null)
248   {
249     return $this->attributeHolder->get($name, $default);
250   }
251
252   /**
253    * Returns true if the view have attributes.
254    *
255    * @param  string $name  Name of the attribute
256    *
257    * @return mixed Attribute of the view
258    */
259   public function hasAttribute($name)
260   {
261     return $this->attributeHolder->has($name);
262   }
263
264   /**
265    * Sets an attribute of the view.
266    *
267    * @param string $name   Attribute name
268    * @param string $value  Value for the attribute
269    */
270   public function setAttribute($name, $value)
271   {
272     $this->attributeHolder->set($name, $value);
273   }
274
275   /**
276    * Retrieves the parameters for the current view.
277    *
278    * @return sfParameterHolder The parameter holder
279    */
280   public function getParameterHolder()
281   {
282     return $this->parameterHolder;
283   }
284
285   /**
286    * Retrieves a parameter from the current view.
287    *
288    * @param  string $name     Parameter name
289    * @param  string $default  Default parameter value
290    *
291    * @return mixed A parameter value
292    */
293   public function getParameter($name, $default = null)
294   {
295     return $this->parameterHolder->get($name, $default);
296   }
297
298   /**
299    * Indicates whether or not a parameter exist for the current view.
300    *
301    * @param  string $name  Name of the paramater
302    *
303    * @return bool true, if the parameter exists otherwise false
304    */
305   public function hasParameter($name)
306   {
307     return $this->parameterHolder->has($name);
308   }
309
310   /**
311    * Sets a parameter for the view.
312    *
313    * @param string $name   Name of the parameter
314    * @param string $value  The parameter value
315    */
316   public function setParameter($name, $value)
317   {
318     $this->parameterHolder->set($name, $value);
319   }
320
321   /**
322    * Indicates that this view is a decorating view.
323    *
324    * @return bool true, if this view is a decorating view, otherwise false
325    */
326   public function isDecorator()
327   {
328     return $this->decorator;
329   }
330
331   /**
332    * Sets the decorating mode for the current view.
333    *
334    * @param bool $boolean  Set the decorating mode for the view
335    */
336   public function setDecorator($boolean)
337   {
338     $this->decorator = (boolean) $boolean;
339
340     if (false === $boolean)
341     {
342       $this->decoratorTemplate = false;
343     }
344   }
345
346   /**
347    * Executes a basic pre-render check to verify all required variables exist
348    * and that the template is readable.
349    *
350    * @throws sfRenderException If the pre-render check fails
351    */
352   protected function preRenderCheck()
353   {
354     if (is_null($this->template))
355     {
356       // a template has not been set
357       throw new sfRenderException('A template has not been set.');
358     }
359
360     if (!is_readable($this->directory.'/'.$this->template))
361     {
362       // 404?
363       if ('404' == $this->context->getResponse()->getStatusCode())
364       {
365         // use default exception templates
366         $this->template = sfException::getTemplatePathForError($this->context->getRequest()->getRequestFormat(), false);
367         $this->directory = dirname($this->template);
368         $this->template = basename($this->template);
369         $this->setAttribute('code', '404');
370         $this->setAttribute('text', 'Not Found');
371       }
372       else
373       {
374         throw new sfRenderException(sprintf('The template "%s" does not exist or is unreadable in "%s".', $this->template, $this->directory));
375       }
376     }
377
378     // check to see if this is a decorator template
379     if ($this->decorator && !is_readable($this->decoratorDirectory.'/'.$this->decoratorTemplate))
380     {
381       throw new sfRenderException(sprintf('The decorator template "%s" does not exist or is unreadable in "%s".', $this->decoratorTemplate, $this->decoratorDirectory));
382     }
383   }
384
385   /**
386    * Renders the presentation.
387    *
388    * @return string A string representing the rendered presentation
389    */
390   abstract function render();
391
392   /**
393    * Sets the decorator template directory for this view.
394    *
395    * @param string $directory  An absolute filesystem path to a template directory
396    */
397   public function setDecoratorDirectory($directory)
398   {
399     $this->decoratorDirectory = $directory;
400   }
401
402   /**
403    * Sets the decorator template for this view.
404    *
405    * If the template path is relative, it will be based on the currently
406    * executing module's template sub-directory.
407    *
408    * @param string $template  An absolute or relative filesystem path to a template
409    */
410   public function setDecoratorTemplate($template)
411   {
412     if (false === $template)
413     {
414       $this->setDecorator(false);
415
416       return;
417     }
418     else if (is_null($template))
419     {
420       return;
421     }
422
423     if (!strpos($template, '.'))
424     {
425       $template .= $this->getExtension();
426     }
427
428     if (sfToolkit::isPathAbsolute($template))
429     {
430       $this->decoratorDirectory = dirname($template);
431       $this->decoratorTemplate  = basename($template);
432     }
433     else
434     {
435       $this->decoratorDirectory = $this->context->getConfiguration()->getDecoratorDir($template);
436       $this->decoratorTemplate = $template;
437     }
438
439     // set decorator status
440     $this->decorator = true;
441   }
442
443   /**
444    * Sets the template directory for this view.
445    *
446    * @param string $directory  An absolute filesystem path to a template directory
447    */
448   public function setDirectory($directory)
449   {
450     $this->directory = $directory;
451   }
452
453   /**
454    * Sets the module and action to be executed in place of a particular template attribute.
455    *
456    * @param string $attributeName  A template attribute name
457    * @param string $moduleName     A module name
458    * @param string $componentName  A component name
459    */
460   public function setComponentSlot($attributeName, $moduleName, $componentName)
461   {
462     $this->componentSlots[$attributeName]                   = array();
463     $this->componentSlots[$attributeName]['module_name']    = $moduleName;
464     $this->componentSlots[$attributeName]['component_name'] = $componentName;
465   }
466
467   /**
468    * Indicates whether or not a component slot exists.
469    *
470    * @param  string $name  The component slot name
471    *
472    * @return bool true, if the component slot exists, otherwise false
473    */
474   public function hasComponentSlot($name)
475   {
476     return isset($this->componentSlots[$name]);
477   }
478
479   /**
480    * Gets a component slot
481    *
482    * @param  string $name  The component slot name
483    *
484    * @return array The component slot
485    */
486   public function getComponentSlot($name)
487   {
488     if (isset($this->componentSlots[$name]) && $this->componentSlots[$name]['module_name'] && $this->componentSlots[$name]['component_name'])
489     {
490       return array($this->componentSlots[$name]['module_name'], $this->componentSlots[$name]['component_name']);
491     }
492
493     return null;
494   }
495
496   /**
497    * Sets the template for this view.
498    *
499    * If the template path is relative, it will be based on the currently
500    * executing module's template sub-directory.
501    *
502    * @param string $template  An absolute or relative filesystem path to a template
503    */
504   public function setTemplate($template)
505   {
506     if (sfToolkit::isPathAbsolute($template))
507     {
508       $this->directory = dirname($template);
509       $this->template  = basename($template);
510     }
511     else
512     {
513       $this->directory = $this->context->getConfiguration()->getTemplateDir($this->moduleName, $template);
514       $this->template = $template;
515     }
516   }
517
518   /**
519    * Retrieves the current view extension.
520    *
521    * @return string The extension for current view.
522    */
523   public function getExtension()
524   {
525     return $this->extension;
526   }
527
528   /**
529    * Sets an extension for the current view.
530    *
531    * @param string $extension  The extension name.
532    */
533   public function setExtension($extension)
534   {
535     $this->extension = $extension;
536   }
537
538   /**
539    * Gets the module name associated with this view.
540    *
541    * @return string A module name
542    */
543   public function getModuleName()
544   {
545     return $this->moduleName;
546   }
547
548   /**
549    * Gets the action name associated with this view.
550    *
551    * @return string An action name
552    */
553   public function getActionName()
554   {
555     return $this->actionName;
556   }
557
558   /**
559    * Gets the view name associated with this view.
560    *
561    * @return string An action name
562    */
563   public function getViewName()
564   {
565     return $this->viewName;
566   }
567
568   /**
569    * Calls methods defined via sfEventDispatcher.
570    *
571    * @param  string $method     The method name
572    * @param  array  $arguments  The method arguments
573    *
574    * @return mixed The returned value of the called method
575    *
576    * @throws sfException< If the calls fails
577    */
578   public function __call($method, $arguments)
579   {
580     $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'view.method_not_found', array('method' => $method, 'arguments' => $arguments)));
581     if (!$event->isProcessed())
582     {
583       throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
584     }
585
586     return $event->getReturnValue();
587   }
588 }
589
Note: See TracBrowser for help on using the browser.