/** * Pre-process the template source before it is * returned to the TemplateParser or passed to * the next TemplateProcessorInterface instance. * * @param string $templateSource * @return string */ public function preProcessSource($templateSource) { $matches = []; preg_match_all(self::$SCAN_PATTERN_ESCAPINGMODIFIER, $templateSource, $matches, PREG_SET_ORDER); if ($matches === []) { return $templateSource; } if (count($matches) > 1) { throw new Exception('There is more than one escaping modifier defined. There can only be one {escapingEnabled=...} per template.', 1407331080); } if (strtolower($matches[0]['enabled']) === 'false') { $this->renderingContext->getTemplateParser()->setEscapingEnabled(false); } $templateSource = preg_replace(self::$SCAN_PATTERN_ESCAPINGMODIFIER, '', $templateSource); return $templateSource; }
/** * Renders a partial. * * @param string $partialName * @param string $sectionName * @param array $variables * @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string * @return string */ public function renderPartial($partialName, $sectionName, array $variables, $ignoreUnknown = FALSE) { if (!isset($this->partialIdentifierCache[$partialName])) { $this->partialIdentifierCache[$partialName] = $this->baseRenderingContext->getTemplatePaths()->getPartialIdentifier($partialName); } $partialIdentifier = $this->partialIdentifierCache[$partialName]; $parsedPartial = $this->baseRenderingContext->getTemplateParser()->getOrParseAndStoreTemplate($partialIdentifier, function ($parent, TemplatePaths $paths) use($partialName) { return $paths->getPartialSource($partialName); }); $renderingContext = clone $this->getCurrentRenderingContext(); $renderingContext->setVariableProvider($renderingContext->getVariableProvider()->getScopeCopy($variables)); $this->startRendering(self::RENDERING_PARTIAL, $parsedPartial, $renderingContext); if ($sectionName !== NULL) { $output = $this->renderSection($sectionName, $variables, $ignoreUnknown); } else { $output = $parsedPartial->render($renderingContext); } $this->stopRendering(); return $output; }
/** * Register all namespaces that are declared inside the template string * * @param string $templateSource * @return void */ public function registerNamespacesFromTemplateSource($templateSource) { $viewHelperResolver = $this->renderingContext->getViewHelperResolver(); if (preg_match_all(static::SPLIT_PATTERN_TEMPLATE_OPEN_NAMESPACETAG, $templateSource, $matchedVariables, PREG_SET_ORDER) > 0) { foreach ($matchedVariables as $namespaceMatch) { $viewHelperNamespace = $this->renderingContext->getTemplateParser()->unquoteString($namespaceMatch[2]); $phpNamespace = $viewHelperResolver->resolvePhpNamespaceFromFluidNamespace($viewHelperNamespace); if (strpos($phpNamespace, '/') === false) { $viewHelperResolver->addNamespace($namespaceMatch[1], $phpNamespace); } } } preg_match_all(static::NAMESPACE_DECLARATION, $templateSource, $namespaces); foreach ($namespaces['identifier'] as $key => $identifier) { $namespace = $namespaces['phpNamespace'][$key]; if (strlen($namespace) === 0) { $namespace = null; } $viewHelperResolver->addNamespace($identifier, $namespace); } }
/** * Renders a partial. * * @param string $partialName * @param string $sectionName * @param array $variables * @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string * @return string */ public function renderPartial($partialName, $sectionName, array $variables, $ignoreUnknown = false) { $templatePaths = $this->baseRenderingContext->getTemplatePaths(); try { $parsedPartial = $this->baseRenderingContext->getTemplateParser()->getOrParseAndStoreTemplate($templatePaths->getPartialIdentifier($partialName), function ($parent, TemplatePaths $paths) use($partialName) { return $paths->getPartialSource($partialName); }); } catch (PassthroughSourceException $error) { return $error->getSource(); } $renderingContext = clone $this->getCurrentRenderingContext(); $renderingContext->setVariableProvider($renderingContext->getVariableProvider()->getScopeCopy($variables)); $this->startRendering(self::RENDERING_PARTIAL, $parsedPartial, $renderingContext); if ($sectionName !== null) { $output = $this->renderSection($sectionName, $variables, $ignoreUnknown); } else { $output = $parsedPartial->render($renderingContext); } $this->stopRendering(); return $output; }
/** * Convert argument strings to their equivalents. Needed to handle strings with a boolean meaning. * * Must be public and static as it is used from inside cached templates. * * @param boolean $value Value to be converted to boolean * @param RenderingContextInterface $renderingContext * @return boolean */ public static function convertToBoolean($value, $renderingContext) { if (is_bool($value)) { return $value; } if (is_numeric($value)) { return (bool) ((double) $value > 0); } if (is_string($value)) { if (strlen($value) === 0) { return false; } $value = $renderingContext->getTemplateParser()->unquoteString($value); return strtolower($value) !== 'false' && !empty($value); } if (is_array($value) || is_object($value) && $value instanceof \Countable) { return count($value) > 0; } if (is_object($value)) { return true; } return false; }
/** * Warm up a single template file. * * Performs reading, parsing and attempts compiling of a single * template file. Catches errors that may occur and reports them * in a FailedCompilingState (which can then be `add()`'ed to * the FluidCacheWarmupResult to assimilate the information within. * * Adds basic mitigation suggestions for each specific type of error, * giving hints to developers if a certain template fails to compile. * * @param string $templatePathAndFilename * @param string $identifier * @param RenderingContextInterface $renderingContext * @return ParsedTemplateInterface */ protected function warmSingleFile($templatePathAndFilename, $identifier, RenderingContextInterface $renderingContext) { $parsedTemplate = new FailedCompilingState(); $parsedTemplate->setVariableProvider($renderingContext->getVariableProvider()); $parsedTemplate->setCompilable(false); $parsedTemplate->setIdentifier($identifier); try { $parsedTemplate = $renderingContext->getTemplateParser()->getOrParseAndStoreTemplate($identifier, function (TemplateParser $parser, TemplatePaths $templatePaths) use($templatePathAndFilename) { return file_get_contents($templatePathAndFilename, FILE_TEXT); }); } catch (StopCompilingException $error) { $parsedTemplate->setFailureReason(sprintf('Compiling is intentionally disabled. Specific reason unknown. Message: "%s"', $error->getMessage())); $parsedTemplate->setMitigations(['Can be caused by specific ViewHelpers. If this is is not intentional: avoid ViewHelpers which disable caches.', 'If cache is intentionally disabled: consider using `f:cache.static` to cause otherwise uncompilable ViewHelpers\' output to be replaced with a static string in compiled templates.']); } catch (ExpressionException $error) { $parsedTemplate->setFailureReason(sprintf('ExpressionNode evaluation error: %s', $error->getMessage())); $parsedTemplate->setMitigations(['Emulate variables used in ExpressionNode using `f:cache.warmup` or assign in warming RenderingContext']); } catch (\TYPO3Fluid\Fluid\Core\Parser\Exception $error) { $parsedTemplate->setFailureReason($error->getMessage()); $parsedTemplate->setMitigations(['Fix possible syntax errors.', 'Check that all ViewHelpers are correctly referenced and namespaces loaded (note: namespaces may be added externally!)', 'Check that all ExpressionNode types used by the template are loaded (note: may depend on RenderingContext implementation!)', 'Emulate missing variables used in expressions by using `f:cache.warmup` around your template code.']); } catch (\TYPO3Fluid\Fluid\Core\ViewHelper\Exception $error) { $parsedTemplate->setFailureReason(sprintf('ViewHelper threw Exception: %s', $error->getMessage())); $parsedTemplate->setMitigations(['Emulate missing variables using `f:cache.warmup` around failing ViewHelper.', 'Emulate globals / context required by ViewHelper.', 'Disable caching for template if ViewHelper depends on globals / context that cannot be emulated.']); } catch (\TYPO3Fluid\Fluid\Core\Exception $error) { $parsedTemplate->setFailureReason(sprintf('Fluid engine error: %s', $error->getMessage())); $parsedTemplate->setMitigations(['Search online for additional information about specific error.']); } catch (Exception $error) { $parsedTemplate->setFailureReason(sprintf('Fluid view error: %s', $error->getMessage())); $parsedTemplate->setMitigations(['Investigate reported error in View class for missing variable checks, missing configuration etc.', 'Consider using a different View class for rendering in warmup mode (a custom rendering context can provide it)']); } catch (\RuntimeException $error) { $parsedTemplate->setFailureReason(sprintf('General error: %s line %s threw %s (code: %d)', get_class($error), $error->getFile(), $error->getLine(), $error->getMessage(), $error->getCode())); $parsedTemplate->setMitigations(['There are no automated suggestions for mitigating this issue. An online search may yield more information.']); } return $parsedTemplate; }