TYPO3 CMS  TYPO3_7-6
TemplateView.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Fluid\View;
3 
4 /* *
5  * This script is backported from the TYPO3 Flow package "TYPO3.Fluid". *
6  * *
7  * It is free software; you can redistribute it and/or modify it under *
8  * the terms of the GNU Lesser General Public License, either version 3 *
9  * of the License, or (at your option) any later version. *
10  * *
11  * The TYPO3 project - inspiring people to share! *
12  * */
13 
21 
28 {
36  protected $templateRootPathPattern = '@packageResourcesPath/Private/Templates';
37 
45  protected $partialRootPathPattern = '@packageResourcesPath/Private/Partials';
46 
54  protected $layoutRootPathPattern = '@packageResourcesPath/Private/Layouts';
55 
61  protected $templateRootPaths = null;
62 
68  protected $partialRootPaths = null;
69 
75  protected $layoutRootPaths = null;
76 
89  protected $templatePathAndFilenamePattern = '@templateRoot/@subpackage/@controller/@action.@format';
90 
103  private $partialPathAndFilenamePattern = '@partialRoot/@subpackage/@partial.@format';
104 
117  protected $layoutPathAndFilenamePattern = '@layoutRoot/@layout.@format';
118 
124  protected $templatePathAndFilename = null;
125 
131  protected $layoutPathAndFilename = null;
132 
136  public function __construct()
137  {
138  $this->templateParser = TemplateParserBuilder::build();
139  $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
140  $this->setRenderingContext($this->objectManager->get(RenderingContextInterface::class));
141  }
142 
146  public function initializeView()
147  {
148  }
149  // Here, the backporter can insert a constructor method, which is needed for the TYPO3 CMS extension
150 
160  {
161  $this->templatePathAndFilename = $templatePathAndFilename;
162  }
163 
172  {
173  $this->layoutPathAndFilename = $layoutPathAndFilename;
174  }
175 
185  public function setTemplateRootPath($templateRootPath)
186  {
187  $this->setTemplateRootPaths([$templateRootPath]);
188  }
189 
195  public function getTemplateRootPaths()
196  {
197  if ($this->templateRootPaths !== null) {
199  }
201  $actionRequest = $this->controllerContext->getRequest();
202  return [str_replace('@packageResourcesPath', ExtensionManagementUtility::extPath($actionRequest->getControllerExtensionKey()) . 'Resources/', $this->templateRootPathPattern)];
203  }
204 
214  {
215  $this->templateRootPaths = $templateRootPaths;
216  }
217 
227  public function setPartialRootPath($partialRootPath)
228  {
229  $this->setPartialRootPaths([$partialRootPath]);
230  }
231 
240  public function setPartialRootPaths(array $partialRootPaths)
241  {
242  $this->partialRootPaths = $partialRootPaths;
243  }
244 
250  protected function getPartialRootPaths()
251  {
252  if ($this->partialRootPaths !== null) {
254  }
256  $actionRequest = $this->controllerContext->getRequest();
257  return [str_replace('@packageResourcesPath', ExtensionManagementUtility::extPath($actionRequest->getControllerExtensionKey()) . 'Resources/', $this->partialRootPathPattern)];
258  }
259 
269  public function setLayoutRootPath($layoutRootPath)
270  {
271  $this->setLayoutRootPaths([$layoutRootPath]);
272  }
273 
282  public function setLayoutRootPaths(array $layoutRootPaths)
283  {
284  $this->layoutRootPaths = $layoutRootPaths;
285  }
286 
292  protected function getLayoutRootPaths()
293  {
294  if ($this->layoutRootPaths !== null) {
295  return $this->layoutRootPaths;
296  }
298  $actionRequest = $this->controllerContext->getRequest();
299  return [str_replace('@packageResourcesPath', ExtensionManagementUtility::extPath($actionRequest->getControllerExtensionKey()) . 'Resources/', $this->layoutRootPathPattern)];
300  }
301 
309  protected function getTemplateIdentifier($actionName = null)
310  {
311  $templatePathAndFilename = $this->getTemplatePathAndFilename($actionName);
312  if ($actionName === null) {
314  $actionRequest = $this->controllerContext->getRequest();
315  $actionName = $actionRequest->getControllerActionName();
316  }
317  $prefix = 'action_' . $actionName;
318  return $this->createIdentifierForFile($templatePathAndFilename, $prefix);
319  }
320 
329  protected function getTemplateSource($actionName = null)
330  {
331  $templatePathAndFilename = $this->getTemplatePathAndFilename($actionName);
332  $templateSource = file_get_contents($templatePathAndFilename);
333  if ($templateSource === false) {
334  throw new Exception\InvalidTemplateResourceException('"' . $templatePathAndFilename . '" is not a valid template resource URI.', 1257246929);
335  }
336  return $templateSource;
337  }
338 
347  protected function getTemplatePathAndFilename($actionName = null)
348  {
349  if ($this->templatePathAndFilename !== null) {
350  return $this->resolveFileNamePath($this->templatePathAndFilename);
351  }
352  if ($actionName === null) {
354  $actionRequest = $this->controllerContext->getRequest();
355  $actionName = $actionRequest->getControllerActionName();
356  }
357 
358  $paths = $this->expandGenericPathPattern($this->templatePathAndFilenamePattern, false, false);
359  $possibleFileNames = $this->buildListOfTemplateCandidates($actionName, $paths, '@action');
360  foreach ($possibleFileNames as $templatePathAndFilename) {
361  if ($this->testFileExistence($templatePathAndFilename)) {
363  }
364  }
365  throw new Exception\InvalidTemplateResourceException('Template could not be loaded. I tried "' . implode('", "', $possibleFileNames) . '"', 1225709595);
366  }
367 
375  protected function getLayoutIdentifier($layoutName = 'Default')
376  {
377  $layoutPathAndFilename = $this->getLayoutPathAndFilename($layoutName);
378  $prefix = 'layout_' . $layoutName;
379  return $this->createIdentifierForFile($layoutPathAndFilename, $prefix);
380  }
381 
394  protected function getLayoutSource($layoutName = 'Default')
395  {
396  $layoutPathAndFilename = $this->getLayoutPathAndFilename($layoutName);
397  $layoutSource = file_get_contents($layoutPathAndFilename);
398  if ($layoutSource === false) {
399  throw new Exception\InvalidTemplateResourceException('"' . $layoutPathAndFilename . '" is not a valid template resource URI.', 1257246930);
400  }
401  return $layoutSource;
402  }
403 
416  protected function getLayoutPathAndFilename($layoutName = 'Default')
417  {
418  if ($this->layoutPathAndFilename !== null) {
419  return $this->resolveFileNamePath($this->layoutPathAndFilename);
420  }
421  $paths = $this->expandGenericPathPattern($this->layoutPathAndFilenamePattern, true, true);
422  $possibleFileNames = $this->buildListOfTemplateCandidates($layoutName, $paths, '@layout');
423  foreach ($possibleFileNames as $layoutPathAndFilename) {
424  if ($this->testFileExistence($layoutPathAndFilename)) {
425  return $layoutPathAndFilename;
426  }
427  }
428  throw new Exception\InvalidTemplateResourceException('The layout files "' . implode('", "', $possibleFileNames) . '" could not be loaded.', 1225709596);
429  }
430 
438  protected function getPartialIdentifier($partialName)
439  {
440  $partialPathAndFilename = $this->getPartialPathAndFilename($partialName);
441  $prefix = 'partial_' . $partialName;
442  return $this->createIdentifierForFile($partialPathAndFilename, $prefix);
443  }
444 
452  protected function getPartialSource($partialName)
453  {
454  $partialPathAndFilename = $this->getPartialPathAndFilename($partialName);
455  $partialSource = file_get_contents($partialPathAndFilename);
456  if ($partialSource === false) {
457  throw new Exception\InvalidTemplateResourceException('"' . $partialPathAndFilename . '" is not a valid template resource URI.', 1257246931);
458  }
459  return $partialSource;
460  }
461 
469  protected function getPartialPathAndFilename($partialName)
470  {
471  $paths = $this->expandGenericPathPattern($this->partialPathAndFilenamePattern, true, true);
472  $possibleFileNames = $this->buildListOfTemplateCandidates($partialName, $paths, '@partial');
473  foreach ($possibleFileNames as $partialPathAndFilename) {
474  if ($this->testFileExistence($partialPathAndFilename)) {
475  return $partialPathAndFilename;
476  }
477  }
478  throw new Exception\InvalidTemplateResourceException('The partial files "' . implode('", "', $possibleFileNames) . '" could not be loaded.', 1225709597);
479  }
480 
489  protected function buildListOfTemplateCandidates($templateName, $paths, $marker)
490  {
491  $upperCasedTemplateName = $this->ucFileNameInPath($templateName);
492  $possibleFileNames = [];
493  foreach ($paths as $partialPathAndFilename) {
494  $possibleFileNames[] = $this->resolveFileNamePath(str_replace($marker, $upperCasedTemplateName, $partialPathAndFilename));
495  if ($templateName !== $upperCasedTemplateName) {
496  $possibleFileNames[] = $this->resolveFileNamePath(str_replace($marker, $templateName, $partialPathAndFilename));
497  }
498  }
499  return $possibleFileNames;
500  }
501 
510  {
511  $this->setControllerContext($controllerContext);
512  try {
513  $this->getTemplateSource();
514  return true;
516  return false;
517  }
518  }
519 
555  protected function expandGenericPathPattern($pattern, $bubbleControllerAndSubpackage, $formatIsOptional)
556  {
557  $paths = [$pattern];
558  $this->expandPatterns($paths, '@templateRoot', $this->getTemplateRootPaths());
559  $this->expandPatterns($paths, '@partialRoot', $this->getPartialRootPaths());
560  $this->expandPatterns($paths, '@layoutRoot', $this->getLayoutRootPaths());
561 
563  $actionRequest = $this->controllerContext->getRequest();
564  $subpackageKey = $actionRequest->getControllerSubpackageKey();
565  $controllerName = $actionRequest->getControllerName();
566  if ($subpackageKey !== null) {
567  if (strpos($subpackageKey, Fluid::NAMESPACE_SEPARATOR) !== false) {
568  $namespaceSeparator = Fluid::NAMESPACE_SEPARATOR;
569  } else {
570  $namespaceSeparator = Fluid::LEGACY_NAMESPACE_SEPARATOR;
571  }
572  $subpackageKeyParts = explode($namespaceSeparator, $subpackageKey);
573  } else {
574  $subpackageKeyParts = [];
575  }
576  if ($bubbleControllerAndSubpackage) {
577  $numberOfPathsBeforeSubpackageExpansion = count($paths);
578  $numberOfSubpackageParts = count($subpackageKeyParts);
579  $subpackageReplacements = [];
580  for ($i = 0; $i <= $numberOfSubpackageParts; $i++) {
581  $subpackageReplacements[] = implode('/', ($i < 0 ? $subpackageKeyParts : array_slice($subpackageKeyParts, $i)));
582  }
583  $this->expandPatterns($paths, '@subpackage', $subpackageReplacements);
584 
585  for ($i = ($numberOfPathsBeforeSubpackageExpansion - 1) * ($numberOfSubpackageParts + 1); $i >= 0; $i -= ($numberOfSubpackageParts + 1)) {
586  array_splice($paths, $i, 0, str_replace('@controller', $controllerName, $paths[$i]));
587  }
588  $this->expandPatterns($paths, '@controller', ['']);
589  } else {
590  $i = $controllerName === null ? 0 : -1;
591  $this->expandPatterns($paths, '@subpackage', [implode('/', $i < 0 ? $subpackageKeyParts :
592  array_slice($subpackageKeyParts, $i))]);
593  $this->expandPatterns($paths, '@controller', [$controllerName]);
594  }
595 
596  if ($formatIsOptional) {
597  $this->expandPatterns($paths, '.@format', ['.' . $actionRequest->getFormat(), '']);
598  $this->expandPatterns($paths, '@format', [$actionRequest->getFormat(), '']);
599  } else {
600  $this->expandPatterns($paths, '.@format', ['.' . $actionRequest->getFormat()]);
601  $this->expandPatterns($paths, '@format', [$actionRequest->getFormat()]);
602  }
603  return array_values(array_unique($paths));
604  }
605 
615  protected function expandPatterns(array &$patterns, $search, array $replacements)
616  {
617  $patternsWithReplacements = [];
618  foreach ($patterns as $pattern) {
619  foreach ($replacements as $replacement) {
620  $patternsWithReplacements[] = GeneralUtility::fixWindowsFilePath(str_replace($search, $replacement, $pattern));
621  }
622  }
623  $patterns = $patternsWithReplacements;
624  }
625 
635  protected function createIdentifierForFile($pathAndFilename, $prefix)
636  {
638  $actionRequest = $this->controllerContext->getRequest();
639  $extensionName = $actionRequest->getControllerExtensionName();
640  $subPackageKey = $actionRequest->getControllerSubpackageKey();
641  if ($subPackageKey !== null) {
642  $extensionName .= '_' . $subPackageKey;
643  }
644  $controllerName = $actionRequest->getControllerName();
645  $templateModifiedTimestamp = filemtime($pathAndFilename);
646  $templateIdentifier = sprintf('%s_%s_%s_%s', $extensionName, $controllerName, $prefix, sha1($pathAndFilename . '|' . $templateModifiedTimestamp));
647  return $templateIdentifier;
648  }
649 
657  protected function resolveFileNamePath($pathAndFilename)
658  {
660  }
661 }
setTemplatePathAndFilename($templatePathAndFilename)
setTemplateRootPath($templateRootPath)
setPartialRootPath($partialRootPath)
canRender(ControllerContext $controllerContext)
setRenderingContext(\TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface $renderingContext)
const NAMESPACE_SEPARATOR
Definition: Fluid.php:19
buildListOfTemplateCandidates($templateName, $paths, $marker)
resolveFileNamePath($pathAndFilename)
getLayoutPathAndFilename($layoutName='Default')
getLayoutIdentifier($layoutName='Default')
setPartialRootPaths(array $partialRootPaths)
getLayoutSource($layoutName='Default')
setControllerContext(\TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext)
expandPatterns(array &$patterns, $search, array $replacements)
const LEGACY_NAMESPACE_SEPARATOR
Definition: Fluid.php:18
setLayoutPathAndFilename($layoutPathAndFilename)
static getFileAbsFileName($filename, $onlyRelative=true, $relToTYPO3_mainDir=false)
setTemplateRootPaths(array $templateRootPaths)
setLayoutRootPaths(array $layoutRootPaths)