TYPO3 API  SVNRelease
AbstractTemplateView.php
Go to the documentation of this file.
00001 <?php
00002 
00003 /*                                                                        *
00004  * This script belongs to the FLOW3 package "Fluid".                      *
00005  *                                                                        *
00006  * It is free software; you can redistribute it and/or modify it under    *
00007  * the terms of the GNU Lesser General Public License as published by the *
00008  * Free Software Foundation, either version 3 of the License, or (at your *
00009  * option) any later version.                                             *
00010  *                                                                        *
00011  * This script is distributed in the hope that it will be useful, but     *
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
00013  * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
00014  * General Public License for more details.                               *
00015  *                                                                        *
00016  * You should have received a copy of the GNU Lesser General Public       *
00017  * License along with the script.                                         *
00018  * If not, see http://www.gnu.org/licenses/lgpl.html                      *
00019  *                                                                        *
00020  * The TYPO3 project - inspiring people to share!                         *
00021  *                                                                        */
00022 
00023 /**
00024  * Abstract Fluid Template View.
00025  *
00026  * Contains the fundamental methods which any Fluid based template view needs.
00027  *
00028  * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
00029  */
00030 abstract class Tx_Fluid_View_AbstractTemplateView implements Tx_Extbase_MVC_View_ViewInterface {
00031 
00032     /**
00033      * Constants defining possible rendering types
00034      */
00035     const RENDERING_TEMPLATE = 1;
00036     const RENDERING_PARTIAL = 2;
00037     const RENDERING_LAYOUT = 3;
00038 
00039     /**
00040      * @var Tx_Extbase_MVC_Controller_ControllerContext
00041      */
00042     protected $controllerContext;
00043 
00044     /**
00045      * @var Tx_Extbase_Object_ObjectManagerInterface
00046      */
00047     protected $objectManager;
00048 
00049     /**
00050      * @var Tx_Fluid_Core_Parser_TemplateParser
00051      */
00052     protected $templateParser;
00053 
00054     /**
00055      * The initial rendering context for this template view.
00056      * Due to the rendering stack, another rendering context might be active
00057      * at certain points while rendering the template.
00058      *
00059      * @var Tx_Fluid_Core_Rendering_RenderingContextInterface
00060      */
00061     protected $baseRenderingContext;
00062 
00063     /**
00064      * Stack containing the current rendering type, the current rendering context, and the current parsed template
00065      * Do not manipulate directly, instead use the methods"getCurrent*()", "startRendering(...)" and "stopRendering()"
00066      * @var array
00067      */
00068     protected $renderingStack = array();
00069 
00070     /**
00071      * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager
00072      * @return void
00073      * @author Robert Lemke <robert@typo3.org>
00074      */
00075     public function injectObjectManager(Tx_Extbase_Object_ObjectManagerInterface $objectManager) {
00076         $this->objectManager = $objectManager;
00077     }
00078 
00079     /**
00080      * Inject the Template Parser
00081      *
00082      * @param Tx_Fluid_Core_Parser_TemplateParser $templateParser The template parser
00083      * @return void
00084      * @author Sebastian Kurfürst <sebastian@typo3.org>
00085      */
00086     public function injectTemplateParser(Tx_Fluid_Core_Parser_TemplateParser $templateParser) {
00087         $this->templateParser = $templateParser;
00088     }
00089 
00090     /**
00091      * Injects a fresh rendering context
00092      *
00093      * @param Tx_Fluid_Core_Rendering_RenderingContextInterface $renderingContext
00094      * @return void
00095      * @author Robert Lemke <robert@typo3.org>
00096      */
00097     public function setRenderingContext(Tx_Fluid_Core_Rendering_RenderingContextInterface $renderingContext) {
00098         $this->baseRenderingContext = $renderingContext;
00099         $this->baseRenderingContext->getViewHelperVariableContainer()->setView($this);
00100         $this->controllerContext = $renderingContext->getControllerContext();
00101     }
00102 
00103     /**
00104      * Sets the current controller context
00105      *
00106      * @param Tx_Extbase_MVC_Controller_ControllerContext $controllerContext
00107      * @return void
00108      * @author Robert Lemke <robert@typo3.org>
00109      * @api
00110      */
00111     public function setControllerContext(Tx_Extbase_MVC_Controller_ControllerContext $controllerContext) {
00112         $this->controllerContext = $controllerContext;
00113     }
00114 
00115     public function initializeView() {
00116     }
00117     // Here, the backporter can insert the initializeView method, which is needed for Fluid v4.
00118 
00119     /**
00120      * Assign a value to the variable container.
00121      *
00122      * @param string $key The key of a view variable to set
00123      * @param mixed $value The value of the view variable
00124      * @return Tx_Fluid_View_AbstractTemplateView the instance of this view to allow chaining
00125      * @author Robert Lemke <robert@typo3.org>
00126      * @api
00127      */
00128     public function assign($key, $value) {
00129         $templateVariableContainer = $this->baseRenderingContext->getTemplateVariableContainer();
00130         if ($templateVariableContainer->exists($key)) {
00131             $templateVariableContainer->remove($key);
00132         }
00133         $templateVariableContainer->add($key, $value);
00134         return $this;
00135     }
00136 
00137     /**
00138      * Assigns multiple values to the JSON output.
00139      * However, only the key "value" is accepted.
00140      *
00141      * @param array $values Keys and values - only a value with key "value" is considered
00142      * @return Tx_Fluid_View_AbstractTemplateView the instance of this view to allow chaining
00143      * @author Robert Lemke <robert@typo3.org>
00144      * @api
00145      */
00146     public function assignMultiple(array $values) {
00147         $templateVariableContainer = $this->baseRenderingContext->getTemplateVariableContainer();
00148         foreach ($values as $key => $value) {
00149             if ($templateVariableContainer->exists($key)) {
00150                 $templateVariableContainer->remove($key);
00151             }
00152             $templateVariableContainer->add($key, $value);
00153         }
00154         return $this;
00155     }
00156 
00157     /**
00158      * Loads the template source and render the template.
00159      * If "layoutName" is set in a PostParseFacet callback, it will render the file with the given layout.
00160      *
00161      * @param string $actionName If set, the view of the specified action will be rendered instead. Default is the action specified in the Request object
00162      * @return string Rendered Template
00163      * @author Sebastian Kurfürst <sebastian@typo3.org>
00164      * @author Robert Lemke <robert@typo3.org>
00165      * @api
00166      */
00167     public function render($actionName = NULL) {
00168         $this->baseRenderingContext->setControllerContext($this->controllerContext);
00169         $this->templateParser->setConfiguration($this->buildParserConfiguration());
00170         $parsedTemplate = $this->templateParser->parse($this->getTemplateSource($actionName));
00171 
00172         if ($this->isLayoutDefinedInTemplate($parsedTemplate)) {
00173             $this->startRendering(self::RENDERING_LAYOUT, $parsedTemplate, $this->baseRenderingContext);
00174             $parsedLayout = $this->templateParser->parse($this->getLayoutSource($this->getLayoutNameInTemplate($parsedTemplate)));
00175             $output = $parsedLayout->render($this->baseRenderingContext);
00176             $this->stopRendering();
00177         } else {
00178             $this->startRendering(self::RENDERING_TEMPLATE, $parsedTemplate, $this->baseRenderingContext);
00179             $output = $parsedTemplate->render($this->baseRenderingContext);
00180             $this->stopRendering();
00181         }
00182 
00183         return $output;
00184     }
00185 
00186     /**
00187      * Renders a given section.
00188      *
00189      * @param string $sectionName Name of section to render
00190      * @param array $variables the variables to use.
00191      * @return string rendered template for the section
00192      * @throws Tx_Fluid_View_Exception_InvalidSectionException
00193      * @author Sebastian Kurfürst <sebastian@typo3.org>
00194      * @author Bastian Waidelich <bastian@typo3.org>
00195      */
00196     public function renderSection($sectionName, array $variables) {
00197         $parsedTemplate = $this->getCurrentParsedTemplate();
00198 
00199         $sections = $parsedTemplate->getVariableContainer()->get('sections');
00200         if(!array_key_exists($sectionName, $sections)) {
00201             throw new Tx_Fluid_View_Exception_InvalidSectionException('The given section does not exist!', 1227108982);
00202         }
00203         $section = $sections[$sectionName];
00204 
00205         $renderingContext = $this->getCurrentRenderingContext();
00206         if ($this->getCurrentRenderingType() === self::RENDERING_LAYOUT) {
00207             // in case we render a layout right now, we will render a section inside a TEMPLATE.
00208             $renderingTypeOnNextLevel = self::RENDERING_TEMPLATE;
00209         } else {
00210             $variableContainer = $this->objectManager->create('Tx_Fluid_Core_ViewHelper_TemplateVariableContainer', $variables);
00211             $renderingContext = clone $renderingContext;
00212             $renderingContext->setTemplateVariableContainer($variableContainer);
00213             $renderingTypeOnNextLevel = $this->getCurrentRenderingType();
00214         }
00215 
00216         $renderingContext->getViewHelperVariableContainer()->add('Tx_Fluid_ViewHelpers_SectionViewHelper', 'isCurrentlyRenderingSection', 'TRUE');
00217 
00218         $this->startRendering($renderingTypeOnNextLevel, $parsedTemplate, $renderingContext);
00219         $output = $section->evaluate($renderingContext);
00220         $this->stopRendering();
00221 
00222         return $output;
00223     }
00224 
00225     /**
00226      * Renders a partial.
00227      *
00228      * @param string $partialName
00229      * @param string $sectionName
00230      * @param array $variables
00231      * @param Tx_Fluid_Core_ViewHelper_ViewHelperVariableContainer $viewHelperVariableContainer the View Helper Variable container to use.
00232      * @return string
00233      * @author Sebastian Kurfürst <sebastian@typo3.org>
00234      * @author Bastian Waidelich <bastian@typo3.org>
00235      * @author Robert Lemke <robert@typo3.org>
00236      */
00237     public function renderPartial($partialName, $sectionName, array $variables) {
00238         $partial = $this->templateParser->parse($this->getPartialSource($partialName));
00239         $variableContainer = $this->objectManager->create('Tx_Fluid_Core_ViewHelper_TemplateVariableContainer', $variables);
00240         $renderingContext = clone $this->getCurrentRenderingContext();
00241         $renderingContext->setTemplateVariableContainer($variableContainer);
00242 
00243         $this->startRendering(self::RENDERING_PARTIAL, $partial, $renderingContext);
00244         if ($sectionName !== NULL) {
00245             $output = $this->renderSection($sectionName, $variables);
00246         } else {
00247             $output = $partial->render($renderingContext);
00248         }
00249         $this->stopRendering();
00250 
00251         return $output;
00252     }
00253 
00254     /**
00255      * Resolve the template path and filename for the given action. If $actionName
00256      * is NULL, looks into the current request.
00257      *
00258      * @param string $actionName Name of the action. If NULL, will be taken from request.
00259      * @return string Full path to template
00260      * @throws Tx_Fluid_View_Exception_InvalidTemplateResourceException in case the template was not found
00261      */
00262     abstract protected function getTemplateSource($actionName = NULL);
00263 
00264     /**
00265      * Resolve the path and file name of the layout file, based on
00266      * $this->layoutPathAndFilename and $this->layoutPathAndFilenamePattern.
00267      *
00268      * In case a layout has already been set with setLayoutPathAndFilename(),
00269      * this method returns that path, otherwise a path and filename will be
00270      * resolved using the layoutPathAndFilenamePattern.
00271      *
00272      * @param string $layoutName Name of the layout to use. If none given, use "default"
00273      * @return string Path and filename of layout file
00274      * @throws Tx_Fluid_View_Exception_InvalidTemplateResourceException
00275      */
00276     abstract protected function getLayoutSource($layoutName = 'default');
00277 
00278     /**
00279      * Figures out which partial to use.
00280      *
00281      * @param string $partialName The name of the partial
00282      * @return string the full path which should be used. The path definitely exists.
00283      * @throws Tx_Fluid_View_Exception_InvalidTemplateResourceException
00284      */
00285     abstract protected function getPartialSource($partialName);
00286 
00287     /**
00288      * Build parser configuration
00289      *
00290      * @return Tx_Fluid_Core_Parser_Configuration
00291      * @author Karsten Dambekalns <karsten@typo3.org>
00292      */
00293     protected function buildParserConfiguration() {
00294         $parserConfiguration = $this->objectManager->create('Tx_Fluid_Core_Parser_Configuration');
00295         if ($this->controllerContext->getRequest()->getFormat() === 'html') {
00296             $parserConfiguration->addInterceptor($this->objectManager->get('Tx_Fluid_Core_Parser_Interceptor_Escape'));
00297 
00298         }
00299         return $parserConfiguration;
00300     }
00301 
00302     /**
00303      * Returns TRUE if there is a layout defined in the given template via a <f:layout name="..." /> tag.
00304      *
00305      * @param Tx_Fluid_Core_Parser_ParsedTemplateInterface $parsedTemplate
00306      * @return boolean TRUE if a layout has been defined, FALSE otherwise.
00307      * @author Sebastian Kurfürst <sebastian@typo3.org>
00308      */
00309     protected function isLayoutDefinedInTemplate(Tx_Fluid_Core_Parser_ParsedTemplateInterface $parsedTemplate) {
00310         $variableContainer = $parsedTemplate->getVariableContainer();
00311         return ($variableContainer !== NULL && $variableContainer->exists('layoutName'));
00312     }
00313 
00314     /**
00315      * Returns the name of the layout defined in the template, if one exists.
00316      *
00317      * @param Tx_Fluid_Core_Parser_ParsedTemplateInterface $parsedTemplate
00318      * @return string the Layout name
00319      * @author Sebastian Kurfürst <sebastian@typo3.org>
00320      */
00321     protected function getLayoutNameInTemplate(Tx_Fluid_Core_Parser_ParsedTemplateInterface $parsedTemplate) {
00322         if ($this->isLayoutDefinedInTemplate($parsedTemplate)) {
00323             return $parsedTemplate->getVariableContainer()->get('layoutName');
00324         }
00325         return NULL;
00326     }
00327 
00328     /**
00329      * Start a new nested rendering. Pushes the given information onto the $renderingStack.
00330      *
00331      * @param int $type one of the RENDERING_* constants
00332      * @param Tx_Fluid_Core_Parser_ParsedTemplateInterface $parsedTemplate
00333      * @param Tx_Fluid_Core_Rendering_RenderingContextInterface $renderingContext
00334      * @return void
00335      * @author Sebastian Kurfürst <sebastian@typo3.org>
00336      */
00337     protected function startRendering($type, Tx_Fluid_Core_Parser_ParsedTemplateInterface $parsedTemplate, Tx_Fluid_Core_Rendering_RenderingContextInterface $renderingContext) {
00338         array_push($this->renderingStack, array('type' => $type, 'parsedTemplate' => $parsedTemplate, 'renderingContext' => $renderingContext));
00339     }
00340 
00341     /**
00342      * Stops the current rendering. Removes one element from the $renderingStack. Make sure to always call this
00343      * method pair-wise with startRendering().
00344      *
00345      * @return void
00346      * @author Sebastian Kurfürst <sebastian@typo3.org>
00347      */
00348     protected function stopRendering() {
00349         array_pop($this->renderingStack);
00350     }
00351 
00352     /**
00353      * Get the current rendering type.
00354      *
00355      * @return one of RENDERING_* constants
00356      * @author Sebastian Kurfürst <sebastian@typo3.org>
00357      */
00358     protected function getCurrentRenderingType() {
00359         $currentRendering = end($this->renderingStack);
00360         return $currentRendering['type'];
00361     }
00362 
00363     /**
00364      * Get the parsed template which is currently being rendered.
00365      *
00366      * @return Tx_Fluid_Core_Parser_ParsedTemplateInterface
00367      * @author Sebastian Kurfürst <sebastian@typo3.org>
00368      */
00369     protected function getCurrentParsedTemplate() {
00370         $currentRendering = end($this->renderingStack);
00371         return $currentRendering['parsedTemplate'];
00372     }
00373 
00374     /**
00375      * Get the rendering context which is currently used.
00376      *
00377      * @return Tx_Fluid_Core_Rendering_RenderingContextInterface
00378      * @author Sebastian Kurfürst <sebastian@typo3.org>
00379      */
00380     protected function getCurrentRenderingContext() {
00381         $currentRendering = end($this->renderingStack);
00382         return $currentRendering['renderingContext'];
00383     }
00384 
00385     /**
00386      * Tells if the view implementation can render the view for the given context.
00387      *
00388      * By default we assume that the view implementation can handle all kinds of
00389      * contexts. Override this method if that is not the case.
00390      *
00391      * @param Tx_Extbase_MVC_Controller_ControllerContext $controllerContext
00392      * @return boolean TRUE if the view has something useful to display, otherwise FALSE
00393      * @api
00394      */
00395     public function canRender(Tx_Extbase_MVC_Controller_ControllerContext $controllerContext) {
00396         return TRUE;
00397     }
00398 
00399 }
00400 
00401 ?>