diff --git a/src/View/AbstractTemplateView.php b/src/View/AbstractTemplateView.php index 75efac85d..35f213d2c 100644 --- a/src/View/AbstractTemplateView.php +++ b/src/View/AbstractTemplateView.php @@ -146,7 +146,7 @@ public function render($actionName = null) $output = $parsedTemplate->render($this->baseRenderingContext); $this->stopRendering(); } else { - $layoutName = $parsedTemplate->getLayoutName($this->baseRenderingContext); + $layoutName = (string)$parsedTemplate->getLayoutName($this->baseRenderingContext); try { $parsedLayout = $templateParser->getOrParseAndStoreTemplate( $templatePaths->getLayoutIdentifier($layoutName), diff --git a/src/View/TemplatePaths.php b/src/View/TemplatePaths.php index 71af7f4eb..e0a377558 100644 --- a/src/View/TemplatePaths.php +++ b/src/View/TemplatePaths.php @@ -1,5 +1,7 @@ */ - protected $resolvedIdentifiers = [ + protected array $resolvedIdentifiers = [ self::NAME_TEMPLATES => [], self::NAME_LAYOUTS => [], self::NAME_PARTIALS => [], @@ -65,53 +67,43 @@ class TemplatePaths /** * Holds already resolved identifiers for template files * - * @var array + * @var array */ - protected $resolvedFiles = [ + protected array $resolvedFiles = [ self::NAME_TEMPLATES => [], self::NAME_LAYOUTS => [], self::NAME_PARTIALS => [], ]; /** - * @var array + * @var string[] */ - protected $templateRootPaths = []; + protected array $templateRootPaths = []; /** - * @var array + * @var string[] */ - protected $layoutRootPaths = []; + protected array $layoutRootPaths = []; /** - * @var array + * @var string[] */ - protected $partialRootPaths = []; + protected array $partialRootPaths = []; - /** - * @var string - */ - protected $templatePathAndFilename; + protected ?string $templatePathAndFilename = null; - /** - * @var string - */ - protected $layoutPathAndFilename; + protected ?string $layoutPathAndFilename = null; /** - * @var string|null + * @todo this can also contain resources, see getTemplateSource(). We should check if this is necessary. + * + * @var string|resource|null */ - protected $templateSource; + protected mixed $templateSource = null; - /** - * @var string - */ - protected $format = self::DEFAULT_FORMAT; + protected string $format = self::DEFAULT_FORMAT; - /** - * @param array|string|null $packageNameOrArray - */ - public function __construct($packageNameOrArray = null) + public function __construct(array|string|null $packageNameOrArray = null) { if (is_array($packageNameOrArray)) { $this->fillFromConfigurationArray($packageNameOrArray); @@ -120,10 +112,7 @@ public function __construct($packageNameOrArray = null) } } - /** - * @return array - */ - public function toArray() + public function toArray(): array { return [ self::CONFIG_TEMPLATEROOTPATHS => $this->sanitizePaths($this->getTemplateRootPaths()), @@ -132,85 +121,70 @@ public function toArray() ]; } - /** - * @param string $templatePathAndFilename - */ - public function setTemplatePathAndFilename($templatePathAndFilename) + public function setTemplatePathAndFilename(string $templatePathAndFilename): void { - $this->templatePathAndFilename = (string)$this->sanitizePath($templatePathAndFilename); + $this->templatePathAndFilename = $this->sanitizePath($templatePathAndFilename); } - /** - * @param string $layoutPathAndFilename - */ - public function setLayoutPathAndFilename($layoutPathAndFilename) + public function setLayoutPathAndFilename(string $layoutPathAndFilename): void { - $this->layoutPathAndFilename = (string)$this->sanitizePath($layoutPathAndFilename); + $this->layoutPathAndFilename = $this->sanitizePath($layoutPathAndFilename); } /** - * @return array + * @return string[] */ - public function getTemplateRootPaths() + public function getTemplateRootPaths(): array { return $this->templateRootPaths; } /** - * @param array $templateRootPaths + * @param string[] $templateRootPaths */ - public function setTemplateRootPaths(array $templateRootPaths) + public function setTemplateRootPaths(array $templateRootPaths): void { - $this->templateRootPaths = (array)$this->sanitizePaths($templateRootPaths); + $this->templateRootPaths = $this->sanitizePaths($templateRootPaths); $this->clearResolvedIdentifiersAndTemplates(self::NAME_TEMPLATES); } - /** - * @return array - */ - public function getLayoutRootPaths() + public function getLayoutRootPaths(): array { return $this->layoutRootPaths; } /** - * @param array $layoutRootPaths + * @param string[] $layoutRootPaths */ - public function setLayoutRootPaths(array $layoutRootPaths) + public function setLayoutRootPaths(array $layoutRootPaths): void { - $this->layoutRootPaths = (array)$this->sanitizePaths($layoutRootPaths); + $this->layoutRootPaths = $this->sanitizePaths($layoutRootPaths); $this->clearResolvedIdentifiersAndTemplates(self::NAME_LAYOUTS); } /** - * @return array + * @return string[] */ - public function getPartialRootPaths() + public function getPartialRootPaths(): array { return $this->partialRootPaths; } /** - * @param array $partialRootPaths + * @param string[] $partialRootPaths */ - public function setPartialRootPaths(array $partialRootPaths) + public function setPartialRootPaths(array $partialRootPaths): void { - $this->partialRootPaths = (array)$this->sanitizePaths($partialRootPaths); + $this->partialRootPaths = $this->sanitizePaths($partialRootPaths); $this->clearResolvedIdentifiersAndTemplates(self::NAME_PARTIALS); } - /** - * @return string - */ - public function getFormat() + public function getFormat(): string { return $this->format; } - /** - * @param string $format - */ - public function setFormat($format) + public function setFormat(string $format): void { $this->format = $format; } @@ -237,14 +211,9 @@ public function setFormat($format) * this reverse behavior (which you should * already be, given that it is the same way * TypoScript path configurations work). - * - * @param string $controller - * @param string $action - * @param string $format - * @return string|null * @api */ - public function resolveTemplateFileForControllerAndActionAndFormat($controller, $action, $format = null) + public function resolveTemplateFileForControllerAndActionAndFormat(string $controller, string $action, ?string $format = null): ?string { if ($this->templatePathAndFilename !== null) { return $this->templatePathAndFilename; @@ -268,43 +237,38 @@ public function resolveTemplateFileForControllerAndActionAndFormat($controller, } /** - * @param string|null $controllerName - * @param string $format - * @return array + * @return string[] */ - public function resolveAvailableTemplateFiles($controllerName, $format = null) + public function resolveAvailableTemplateFiles(?string $controllerName, ?string $format = null): array { $paths = $this->getTemplateRootPaths(); foreach ($paths as $index => $path) { - $paths[$index] = rtrim($path . $controllerName, '/') . '/'; + $paths[$index] = rtrim($path . ($controllerName ?? ''), '/') . '/'; } return $this->resolveFilesInFolders($paths, $format ?: $this->getFormat()); } /** - * @param string $format - * @return array + * @return string[] */ - public function resolveAvailablePartialFiles($format = null) + public function resolveAvailablePartialFiles(?string $format = null): array { return $this->resolveFilesInFolders($this->getPartialRootPaths(), $format ?: $this->getFormat()); } /** - * @param string $format - * @return array + * @return string[] */ - public function resolveAvailableLayoutFiles($format = null) + public function resolveAvailableLayoutFiles(?string $format = null): array { return $this->resolveFilesInFolders($this->getLayoutRootPaths(), $format ?: $this->getFormat()); } /** - * @param array $folders - * @param string $format - * @return array + * @param string[] $folders + * @return string[] */ - protected function resolveFilesInFolders(array $folders, $format) + protected function resolveFilesInFolders(array $folders, string $format): array { $files = []; foreach ($folders as $folder) { @@ -314,11 +278,9 @@ protected function resolveFilesInFolders(array $folders, $format) } /** - * @param string $folder - * @param string $format - * @return array + * @return string[] */ - protected function resolveFilesInFolder($folder, $format) + protected function resolveFilesInFolder(string $folder, string $format): array { if (!is_dir($folder)) { return []; @@ -364,10 +326,9 @@ protected function resolveFilesInFolder($folder, $format) * * Will replace any currently configured paths. * - * @param array $paths * @api */ - public function fillFromConfigurationArray(array $paths) + public function fillFromConfigurationArray(array $paths): void { list($templateRootPaths, $layoutRootPaths, $partialRootPaths, $format) = $this->extractPathArrays($paths); $this->setTemplateRootPaths($templateRootPaths); @@ -383,10 +344,9 @@ public function fillFromConfigurationArray(array $paths) * * Will replace any currently configured paths. * - * @param string $packageName * @api */ - public function fillDefaultsByPackageName($packageName) + public function fillDefaultsByPackageName(string $packageName): void { $path = $this->getPackagePath($packageName); $this->setTemplateRootPaths([$path . self::DEFAULT_TEMPLATES_DIRECTORY]); @@ -398,35 +358,38 @@ public function fillDefaultsByPackageName($packageName) * Sanitize a path, ensuring it is absolute and * if a directory, suffixed by a trailing slash. * - * @param string|array $path - * @return string|array + * @todo $path should really be string. Array handling should not be part of this method, and other types + * (such as bool) should really not be passed to this method in the first place. Further refactoring + * is necessary to guarantee this. + * @param mixed $path + * @return string|string[] */ - protected function sanitizePath($path) + protected function sanitizePath(mixed $path): string|array { if (is_array($path)) { $paths = array_map([$this, 'sanitizePath'], $path); return array_unique($paths); } - if (($wrapper = parse_url($path, PHP_URL_SCHEME)) && in_array($wrapper, stream_get_wrappers())) { + if (($wrapper = parse_url((string)$path, PHP_URL_SCHEME)) && in_array($wrapper, stream_get_wrappers())) { return $path; } if (!empty($path)) { $path = str_replace(['\\', '//'], '/', (string)$path); - $path = (string)$this->ensureAbsolutePath($path); + $path = $this->ensureAbsolutePath($path); if (is_dir($path)) { $path = $this->ensureSuffixedPath($path); } } - return $path; + return (string)$path; } /** * Sanitize paths passing each through sanitizePath(). * - * @param array $paths - * @return array + * @param string[] $paths + * @return string[] */ - protected function sanitizePaths(array $paths) + protected function sanitizePaths(array $paths): array { return array_unique(array_map([$this, 'sanitizePath'], $paths)); } @@ -434,11 +397,8 @@ protected function sanitizePaths(array $paths) /** * Guarantees that $reference is turned into a * correct, absolute path. - * - * @param string $path - * @return string */ - protected function ensureAbsolutePath($path) + protected function ensureAbsolutePath(string $path): string { return (!empty($path) && $path[0] !== '/' && $path[1] !== ':') ? $this->sanitizePath(realpath($path)) : $path; } @@ -447,19 +407,15 @@ protected function ensureAbsolutePath($path) * Guarantees that array $reference with paths * are turned into correct, absolute paths * - * @param array $reference - * @return array + * @param string[] $reference + * @return string[] */ - protected function ensureAbsolutePaths(array $reference) + protected function ensureAbsolutePaths(array $reference): array { return array_map([$this, 'ensureAbsolutePath'], $reference); } - /** - * @param string $path - * @return string - */ - protected function ensureSuffixedPath($path) + protected function ensureSuffixedPath(string $path): string { return $path !== '' ? rtrim($path, '/') . '/' : ''; } @@ -474,11 +430,8 @@ protected function ensureSuffixedPath($path) * entries being recorded first and plurals second. * * Adds legacy singular name as last option, if set. - * - * @param array $paths - * @return array */ - protected function extractPathArrays(array $paths) + protected function extractPathArrays(array $paths): array { $format = $this->getFormat(); // pre-processing: if special parameters exist, extract them: @@ -503,11 +456,7 @@ protected function extractPathArrays(array $paths) return $pathCollections; } - /** - * @param string $packageName - * @return string - */ - protected function getPackagePath($packageName) + protected function getPackagePath(string $packageName): string { return ''; } @@ -519,7 +468,7 @@ protected function getPackagePath($packageName) * @param string $layoutName The name of the layout * @return string layout identifier */ - public function getLayoutIdentifier($layoutName = 'Default') + public function getLayoutIdentifier(string $layoutName = 'Default'): string { $filePathAndFilename = $this->getLayoutPathAndFilename($layoutName); $layoutName = str_replace('.', '_', $layoutName); @@ -539,7 +488,7 @@ public function getLayoutIdentifier($layoutName = 'Default') * @return string Path and filename of layout file * @throws InvalidTemplateResourceException */ - public function getLayoutSource($layoutName = 'Default') + public function getLayoutSource(string $layoutName = 'Default'): string { $layoutPathAndFilename = $this->getLayoutPathAndFilename($layoutName); return file_get_contents($layoutPathAndFilename); @@ -553,8 +502,10 @@ public function getLayoutSource($layoutName = 'Default') * @param string $action Name of the action. If null, will be taken from request. * @return string template identifier */ - public function getTemplateIdentifier($controller = 'Default', $action = 'Default') + public function getTemplateIdentifier(?string $controller = 'Default', ?string $action = 'Default'): string { + $controller ??= ''; + $action ??= ''; if ($this->templateSource !== null) { return 'source_' . hash('xxh3', (string)$this->templateSource) . '_' . $controller . '_' . $action . '_' . $this->getFormat(); } @@ -566,7 +517,7 @@ public function getTemplateIdentifier($controller = 'Default', $action = 'Defaul /** * @param mixed $source */ - public function setTemplateSource($source) + public function setTemplateSource(mixed $source): void { $this->templateSource = $source; } @@ -612,14 +563,9 @@ public function getTemplateSource($controller = 'Default', $action = 'Default') * Returns a unique identifier for the given file in the format * ____ * The SH1 hash is a checksum that is based on the file path and last modification date - * - * @param string|null $pathAndFilename - * @param string $prefix - * @return string */ - protected function createIdentifierForFile($pathAndFilename, $prefix) + protected function createIdentifierForFile(string $pathAndFilename, string $prefix): string { - $pathAndFilename = (string)$pathAndFilename; $templateModifiedTimestamp = $pathAndFilename !== 'php://stdin' && file_exists($pathAndFilename) ? filemtime($pathAndFilename) : 0; return sprintf('%s_%s', $prefix, hash('xxh3', $pathAndFilename . '|' . $templateModifiedTimestamp)); } @@ -636,7 +582,7 @@ protected function createIdentifierForFile($pathAndFilename, $prefix) * @return string Path and filename of layout files * @throws Exception\InvalidTemplateResourceException */ - public function getLayoutPathAndFilename($layoutName = 'Default') + public function getLayoutPathAndFilename(string $layoutName = 'Default'): string { if ($this->layoutPathAndFilename !== null) { return $this->layoutPathAndFilename; @@ -657,7 +603,7 @@ public function getLayoutPathAndFilename($layoutName = 'Default') * @param string $partialName The name of the partial * @return string partial identifier */ - public function getPartialIdentifier($partialName) + public function getPartialIdentifier(string $partialName): string { $partialKey = $partialName . '.' . $this->getFormat(); if (!array_key_exists($partialKey, $this->resolvedIdentifiers[self::NAME_PARTIALS])) { @@ -675,7 +621,7 @@ public function getPartialIdentifier($partialName) * @return string contents of the partial template * @throws InvalidTemplateResourceException */ - public function getPartialSource($partialName) + public function getPartialSource(string $partialName): string { $partialPathAndFilename = $this->getPartialPathAndFilename($partialName); return file_get_contents($partialPathAndFilename); @@ -688,7 +634,7 @@ public function getPartialSource($partialName) * @return string the full path which should be used. The path definitely exists. * @throws InvalidTemplateResourceException */ - public function getPartialPathAndFilename($partialName) + public function getPartialPathAndFilename(string $partialName): string { $partialKey = $partialName . '.' . $this->getFormat(); if (!array_key_exists($partialKey, $this->resolvedFiles[self::NAME_PARTIALS])) { @@ -700,13 +646,10 @@ public function getPartialPathAndFilename($partialName) } /** - * @param array $paths - * @param string $relativePathAndFilename - * @param string $format Optional format to resolve. - * @return string + * @param string[] $paths * @throws \TYPO3Fluid\Fluid\View\Exception\InvalidTemplateResourceException */ - protected function resolveFileInPaths(array $paths, $relativePathAndFilename, $format = null) + protected function resolveFileInPaths(array $paths, string $relativePathAndFilename, ?string $format = null): string { $format = $format ?: $this->getFormat(); $tried = []; @@ -731,10 +674,7 @@ protected function resolveFileInPaths(array $paths, $relativePathAndFilename, $f ); } - /** - * @param string|null $type - */ - protected function clearResolvedIdentifiersAndTemplates($type = null) + protected function clearResolvedIdentifiersAndTemplates(?string $type = null): void { if ($type !== null) { $this->resolvedIdentifiers[$type] = $this->resolvedFiles[$type] = [];