TYPO3 API  SVNRelease
TemplateView.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  * The main template view. Should be used as view if you want Fluid Templating
00025  *
00026  * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
00027  * @api
00028  */
00029 class Tx_Fluid_View_TemplateView extends Tx_Fluid_View_AbstractTemplateView {
00030 
00031     /**
00032      * Pattern to be resolved for @templateRoot in the other patterns.
00033      * @var string
00034      */
00035     protected $templateRootPathPattern = '@packageResourcesPath/Private/Templates';
00036 
00037     /**
00038      * Pattern to be resolved for @partialRoot in the other patterns.
00039      * @var string
00040      */
00041     protected $partialRootPathPattern = '@packageResourcesPath/Private/Partials';
00042 
00043     /**
00044      * Pattern to be resolved for @layoutRoot in the other patterns.
00045      * @var string
00046      */
00047     protected $layoutRootPathPattern = '@packageResourcesPath/Private/Layouts';
00048 
00049     /**
00050      * Path to the template root. If NULL, then $this->templateRootPathPattern will be used.
00051      * @var string
00052      */
00053     protected $templateRootPath = NULL;
00054 
00055     /**
00056      * Path to the partial root. If NULL, then $this->partialRootPathPattern will be used.
00057      * @var string
00058      */
00059     protected $partialRootPath = NULL;
00060 
00061     /**
00062      * Path to the layout root. If NULL, then $this->layoutRootPathPattern will be used.
00063      * @var string
00064      */
00065     protected $layoutRootPath = NULL;
00066 
00067     /**
00068      * File pattern for resolving the template file
00069      * @var string
00070      */
00071     protected $templatePathAndFilenamePattern = '@templateRoot/@subpackage/@controller/@action.@format';
00072 
00073     /**
00074      * Directory pattern for global partials. Not part of the public API, should not be changed for now.
00075      * @var string
00076      */
00077     private $partialPathAndFilenamePattern = '@partialRoot/@subpackage/@partial.@format';
00078 
00079     /**
00080      * File pattern for resolving the layout
00081      * @var string
00082      */
00083     protected $layoutPathAndFilenamePattern = '@layoutRoot/@layout.@format';
00084 
00085     /**
00086      * Path and filename of the template file. If set,  overrides the templatePathAndFilenamePattern
00087      * @var string
00088      */
00089     protected $templatePathAndFilename = NULL;
00090 
00091     /**
00092      * Path and filename of the layout file. If set, overrides the layoutPathAndFilenamePattern
00093      * @var string
00094      */
00095     protected $layoutPathAndFilename = NULL;
00096 
00097     public function __construct() {
00098             $this->injectTemplateParser(Tx_Fluid_Compatibility_TemplateParserBuilder::build());
00099             $this->injectObjectManager(t3lib_div::makeInstance('Tx_Extbase_Object_ObjectManager'));
00100             $this->setRenderingContext($this->objectManager->create('Tx_Fluid_Core_Rendering_RenderingContext'));
00101         }
00102 
00103         public function initializeView() {
00104         }
00105 
00106     // Here, the backporter can insert a constructor method, which is needed for Fluid v4.
00107 
00108     /**
00109      * Sets the path and name of of the template file. Effectively overrides the
00110      * dynamic resolving of a template file.
00111      *
00112      * @param string $templatePathAndFilename Template file path
00113      * @return void
00114      * @author Sebastian Kurfürst <sebastian@typo3.org>
00115      * @api
00116      */
00117     public function setTemplatePathAndFilename($templatePathAndFilename) {
00118         $this->templatePathAndFilename = $templatePathAndFilename;
00119     }
00120 
00121     /**
00122      * Sets the path and name of the layout file. Overrides the dynamic resolving of the layout file.
00123      *
00124      * @param string $layoutPathAndFilename Path and filename of the layout file
00125      * @return void
00126      * @author Sebastian Kurfürst <sebastian@typo3.org>
00127      * @api
00128      */
00129     public function setLayoutPathAndFilename($layoutPathAndFilename) {
00130         $this->layoutPathAndFilename = $layoutPathAndFilename;
00131     }
00132 
00133     /**
00134      * Checks whether a template can be resolved for the current request context.
00135      *
00136      * @return boolean
00137      * @author Karsten Dambekalns <karsten@typo3.org>
00138      * @author Sebastian Kurfürst <sebastian@typo3.org>
00139      * @api
00140      */
00141     public function canRender(Tx_Extbase_MVC_Controller_ControllerContext $controllerContext) {
00142         $this->setControllerContext($controllerContext);
00143         try {
00144             $this->getTemplateSource();
00145             return TRUE;
00146         } catch (Tx_Fluid_View_Exception_InvalidTemplateResourceException $e) {
00147             return FALSE;
00148         }
00149     }
00150 
00151         /**
00152      * Set the root path to the templates.
00153      * If set, overrides the one determined from $this->templateRootPathPattern
00154      *
00155      * @param string $templateRootPath Root path to the templates. If set, overrides the one determined from $this->templateRootPathPattern
00156      * @return void
00157      * @author Sebastian Kurfürst <sebastian@typo3.org>
00158      * @api
00159      */
00160     public function setTemplateRootPath($templateRootPath) {
00161         $this->templateRootPath = $templateRootPath;
00162     }
00163 
00164     /**
00165      * Resolve the template path and filename for the given action. If $actionName
00166      * is NULL, looks into the current request.
00167      *
00168      * @param string $actionName Name of the action. If NULL, will be taken from request.
00169      * @return string Full path to template
00170      * @throws Tx_Fluid_View_Exception_InvalidTemplateResourceException
00171      * @author Sebastian Kurfürst <sebastian@typo3.org>
00172      */
00173     protected function getTemplateSource($actionName = NULL) {
00174         if ($this->templatePathAndFilename !== NULL) {
00175             $templatePathAndFilename = $this->templatePathAndFilename;
00176         } else {
00177             $actionName = ($actionName !== NULL ? $actionName : $this->controllerContext->getRequest()->getControllerActionName());
00178 
00179             $paths = $this->expandGenericPathPattern($this->templatePathAndFilenamePattern, FALSE, FALSE);
00180             $found = FALSE;
00181             foreach ($paths as &$templatePathAndFilename) {
00182                 // These tokens are replaced by the Backporter for the graceful fallback in version 4.
00183                 $fallbackPath = str_replace('@action', $actionName, $templatePathAndFilename);
00184                 $templatePathAndFilename = str_replace('@action', ucfirst($actionName), $templatePathAndFilename);
00185                 if (file_exists($templatePathAndFilename)) {
00186                     $found = TRUE;
00187                     // additional check for deprecated template filename for case insensitive file systems (Windows)
00188                     $realFileName = basename(realpath($templatePathAndFilename));
00189                     if ($realFileName !== ucfirst($realFileName)) {
00190                         t3lib_div::deprecationLog('the template filename "' . t3lib_div::fixWindowsFilePath(realpath($templatePathAndFilename)) . '" is lowercase. This is deprecated since TYPO3 4.4. Please rename the template to "' . basename($templatePathAndFilename) . '"');
00191                     }
00192                     break;
00193                 } elseif (file_exists($fallbackPath)) {
00194                     t3lib_div::deprecationLog('the template filename "' . $fallbackPath . '" is lowercase. This is deprecated since TYPO3 4.4. Please rename the template to "' . basename($templatePathAndFilename) . '"');
00195                     $found = TRUE;
00196                     $templatePathAndFilename = $fallbackPath;
00197                     break;
00198                 }
00199             }
00200             if (!$found) {
00201                 throw new Tx_Fluid_View_Exception_InvalidTemplateResourceException('Template could not be loaded. I tried "' . implode('", "', $paths) . '"', 1225709595);
00202             }
00203         }
00204 
00205         $templateSource = file_get_contents($templatePathAndFilename);
00206         if ($templateSource === FALSE) {
00207             throw new Tx_Fluid_View_Exception_InvalidTemplateResourceException('"' . $templatePathAndFilename . '" is not a valid template resource URI.', 1257246929);
00208         }
00209         return $templateSource;
00210     }
00211 
00212     /**
00213      * Resolve the path and file name of the layout file, based on
00214      * $this->layoutPathAndFilename and $this->layoutPathAndFilenamePattern.
00215      *
00216      * In case a layout has already been set with setLayoutPathAndFilename(),
00217      * this method returns that path, otherwise a path and filename will be
00218      * resolved using the layoutPathAndFilenamePattern.
00219      *
00220      * @param string $layoutName Name of the layout to use. If none given, use "default"
00221      * @return string Path and filename of layout file
00222      * @throws Tx_Fluid_View_Exception_InvalidTemplateResourceException
00223      * @author Sebastian Kurfürst <sebastian@typo3.org>
00224      */
00225     protected function getLayoutSource($layoutName = 'default') {
00226         if ($this->layoutPathAndFilename !== NULL) {
00227              $layoutPathAndFilename = $this->layoutPathAndFilename;
00228         } else {
00229             $paths = $this->expandGenericPathPattern($this->layoutPathAndFilenamePattern, TRUE, TRUE);
00230             $found = FALSE;
00231             foreach ($paths as &$layoutPathAndFilename) {
00232                 $layoutPathAndFilename = str_replace('@layout', $layoutName, $layoutPathAndFilename);
00233                 if (file_exists($layoutPathAndFilename)) {
00234                     $found = TRUE;
00235                     break;
00236                 }
00237             }
00238 
00239             if (!$found) {
00240                 throw new Tx_Fluid_View_Exception_InvalidTemplateResourceException('The template files "' . implode('", "', $paths) . '" could not be loaded.', 1225709595);
00241             }
00242         }
00243 
00244         $layoutSource = file_get_contents($layoutPathAndFilename);
00245         if ($layoutSource === FALSE) {
00246             throw new Tx_Fluid_View_Exception_InvalidTemplateResourceException('"' . $layoutPathAndFilename . '" is not a valid template resource URI.', 1257246929);
00247         }
00248         return $layoutSource;
00249     }
00250 
00251     /**
00252      * Figures out which partial to use.
00253      *
00254      * @param string $partialName The name of the partial
00255      * @return string the full path which should be used. The path definitely exists.
00256      * @throws Tx_Fluid_View_Exception_InvalidTemplateResourceException
00257      * @author Sebastian Kurfürst <sebastian@typo3.org>
00258      */
00259     protected function getPartialSource($partialName) {
00260         $paths = $this->expandGenericPathPattern($this->partialPathAndFilenamePattern, TRUE, TRUE);
00261         $found = FALSE;
00262         foreach ($paths as &$partialPathAndFilename) {
00263             $partialPathAndFilename = str_replace('@partial', $partialName, $partialPathAndFilename);
00264             if (file_exists($partialPathAndFilename)) {
00265                 $found = TRUE;
00266                 break;
00267             }
00268         }
00269         if (!$found) {
00270             throw new Tx_Fluid_View_Exception_InvalidTemplateResourceException('The template files "' . implode('", "', $paths) . '" could not be loaded.', 1225709595);
00271         }
00272         $partialSource = file_get_contents($partialPathAndFilename);
00273         if ($partialSource === FALSE) {
00274             throw new Tx_Fluid_View_Exception_InvalidTemplateResourceException('"' . $partialPathAndFilename . '" is not a valid template resource URI.', 1257246929);
00275         }
00276         return $partialSource;
00277     }
00278 
00279     /**
00280      * Resolves the template root to be used inside other paths.
00281      *
00282      * @return string Path to template root directory
00283      * @author Sebastian Kurfürst <sebastian@typo3.org>
00284      */
00285     protected function getTemplateRootPath() {
00286         if ($this->templateRootPath !== NULL) {
00287             return $this->templateRootPath;
00288         } else {
00289             return str_replace('@packageResourcesPath', t3lib_extMgm::extPath($this->controllerContext->getRequest()->getControllerExtensionKey()) . 'Resources/', $this->templateRootPathPattern);
00290         }
00291     }
00292 
00293     /**
00294      * Set the root path to the partials.
00295      * If set, overrides the one determined from $this->partialRootPathPattern
00296      *
00297      * @param string $partialRootPath Root path to the partials. If set, overrides the one determined from $this->partialRootPathPattern
00298      * @return void
00299      * @author Bastian Waidelich <bastian@typo3.org>
00300      * @api
00301      */
00302     public function setPartialRootPath($partialRootPath) {
00303         $this->partialRootPath = $partialRootPath;
00304     }
00305 
00306     /**
00307      * Resolves the partial root to be used inside other paths.
00308      *
00309      * @return string Path to partial root directory
00310      * @author Bastian Waidelich <bastian@typo3.org>
00311      */
00312     protected function getPartialRootPath() {
00313         if ($this->partialRootPath !== NULL) {
00314             return $this->partialRootPath;
00315         } else {
00316             return str_replace('@packageResourcesPath', t3lib_extMgm::extPath($this->controllerContext->getRequest()->getControllerExtensionKey()) . 'Resources/', $this->partialRootPathPattern);
00317         }
00318     }
00319 
00320     /**
00321      * Set the root path to the layouts.
00322      * If set, overrides the one determined from $this->layoutRootPathPattern
00323      *
00324      * @param string $layoutRootPath Root path to the layouts. If set, overrides the one determined from $this->layoutRootPathPattern
00325      * @return void
00326      * @author Bastian Waidelich <bastian@typo3.org>
00327      * @api
00328      */
00329     public function setLayoutRootPath($layoutRootPath) {
00330         $this->layoutRootPath = $layoutRootPath;
00331     }
00332 
00333     /**
00334      * Resolves the layout root to be used inside other paths.
00335      *
00336      * @return string Path to layout root directory
00337      * @author Bastian Waidelich <bastian@typo3.org>
00338      */
00339     protected function getLayoutRootPath() {
00340         if ($this->layoutRootPath !== NULL) {
00341             return $this->layoutRootPath;
00342         } else {
00343             return str_replace('@packageResourcesPath', t3lib_extMgm::extPath($this->controllerContext->getRequest()->getControllerExtensionKey()) . 'Resources/', $this->layoutRootPathPattern);
00344         }
00345     }
00346 
00347     /**
00348      * Processes @templateRoot, @subpackage, @controller, and @format placeholders inside $pattern.
00349      * This method is used to generate "fallback chains" for file system locations where a certain Partial can reside.
00350      *
00351      * If $bubbleControllerAndSubpackage is FALSE and $formatIsOptional is FALSE, then the resulting array will only have one element
00352      * with all the above placeholders replaced.
00353      *
00354      * If you set $bubbleControllerAndSubpackage to TRUE, then you will get an array with potentially many elements:
00355      * The first element of the array is like above. The second element has the @controller part set to "" (the empty string)
00356      * The third element now has the @controller part again stripped off, and has the last subpackage part stripped off as well.
00357      * This continues until both @subpackage and @controller are empty.
00358      *
00359      * Example for $bubbleControllerAndSubpackage is TRUE, we have the Tx_Fluid_MySubPackage_Controller_MyController as Controller Object Name and the current format is "html"
00360      * If pattern is @templateRoot/@controller/@action.@format, then the resulting array is:
00361      *  - Resources/Private/Templates/MySubPackage/My/@action.html
00362      *  - Resources/Private/Templates/MySubPackage/@action.html
00363      *  - Resources/Private/Templates/@action.html
00364      *
00365      * If you set $formatIsOptional to TRUE, then for any of the above arrays, every element will be duplicated  - once with @format
00366      * replaced by the current request format, and once with .@format stripped off.
00367      *
00368      * @param string $pattern Pattern to be resolved
00369      * @param boolean $bubbleControllerAndSubpackage if TRUE, then we successively split off parts from @controller and @subpackage until both are empty.
00370      * @param boolean $formatIsOptional if TRUE, then half of the resulting strings will have .@format stripped off, and the other half will have it.
00371      * @return array unix style path
00372      * @author Sebastian Kurfürst <sebastian@typo3.org>
00373      * @author Robert Lemke <robert@typo3.org>
00374      */
00375     protected function expandGenericPathPattern($pattern, $bubbleControllerAndSubpackage, $formatIsOptional) {
00376         $pattern = str_replace('@templateRoot', $this->getTemplateRootPath(), $pattern);
00377         $pattern = str_replace('@partialRoot', $this->getPartialRootPath(), $pattern);
00378         $pattern = str_replace('@layoutRoot', $this->getLayoutRootPath(), $pattern);
00379 
00380         $subpackageKey = $this->controllerContext->getRequest()->getControllerSubpackageKey();
00381         $controllerName = $this->controllerContext->getRequest()->getControllerName();
00382 
00383         $subpackageParts = ($subpackageKey !== NULL) ? explode(Tx_Fluid_Fluid::NAMESPACE_SEPARATOR, $subpackageKey) : array();
00384 
00385         $results = array();
00386 
00387         $i = ($controllerName === NULL) ? 0 : -1;
00388         do {
00389             $temporaryPattern = $pattern;
00390             if ($i < 0) {
00391                 $temporaryPattern = str_replace('@controller', $controllerName, $temporaryPattern);
00392             } else {
00393                 $temporaryPattern = str_replace('//', '/', str_replace('@controller', '', $temporaryPattern));
00394             }
00395             $temporaryPattern = str_replace('@subpackage', implode('/', ($i<0 ? $subpackageParts : array_slice($subpackageParts, $i))), $temporaryPattern);
00396 
00397             $results[] = t3lib_div::fixWindowsFilePath(str_replace('@format', $this->controllerContext->getRequest()->getFormat(), $temporaryPattern));
00398             if ($formatIsOptional) {
00399                 $results[] =  t3lib_div::fixWindowsFilePath(str_replace('.@format', '', $temporaryPattern));
00400             }
00401 
00402         } while($i++ < count($subpackageParts) && $bubbleControllerAndSubpackage);
00403         return $results;
00404     }
00405 
00406 }
00407 
00408 ?>