Initial xentral_oss_20.3.c9ffacf
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Template;
|
||||
|
||||
use Config;
|
||||
use Smarty;
|
||||
use SmartyException;
|
||||
use Xentral\Components\Template\SmartyPlugin\EscapePlugin;
|
||||
use Xentral\Components\Template\SmartyPlugin\TranslationPlugin;
|
||||
use Xentral\Core\DependencyInjection\ContainerInterface;
|
||||
|
||||
final class Bootstrap
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function registerServices()
|
||||
{
|
||||
return [
|
||||
'Template' => 'onInitTemplate',
|
||||
'SmartyFacade' => 'onInitSmartyFacade',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return Template
|
||||
*/
|
||||
public static function onInitTemplate(ContainerInterface $container)
|
||||
{
|
||||
return new Template($container->get('SmartyFacade'), $container->get('LegacyApplication')->Tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Template-Konfiguration einstellbar machen
|
||||
* @todo Code eventuell in Factory auslagern
|
||||
*
|
||||
* @throws SmartyException
|
||||
*
|
||||
* @return SmartyFacade
|
||||
*/
|
||||
public static function onInitSmartyFacade()
|
||||
{
|
||||
$config = new Config();
|
||||
$userdataDir = $config->WFuserdata !== null
|
||||
? $config->WFuserdata
|
||||
: dirname(dirname(dirname(__DIR__))) . '/userdata';
|
||||
|
||||
$smarty = new Smarty();
|
||||
$smarty->setCompileDir(realpath($userdataDir) . '/tmp/templates_c');
|
||||
$smarty->setCaching(false);
|
||||
$smarty->setDebugging(true);
|
||||
$smarty->setEscapeHtml(false);
|
||||
$smarty->setCompileCheck(true); // @todo Kann deaktiviert werden auf Produktivsystemen
|
||||
$smarty->setDebugTemplate(__DIR__ . '/templates/debug.tpl');
|
||||
$smarty->setTemplateDir(__DIR__ . '/templates');
|
||||
$smarty->addTemplateDir(dirname(dirname(__DIR__)), 'classes');
|
||||
|
||||
/** @see https://www.smarty.net/docs/en/advanced.features.tpl#advanced.features.security */
|
||||
$smarty->enableSecurity(); // @todo Eigene Security-Klasse definieren
|
||||
|
||||
$translationPlugin = new TranslationPlugin();
|
||||
$smarty->registerPlugin('function', 'namespace', [$translationPlugin, 'compileNamespaceFunction']);
|
||||
$smarty->registerPlugin('block', 'translate', [$translationPlugin, 'compileTranslateBlock']);
|
||||
|
||||
$escapePlugin = new EscapePlugin(); // @todo Escape Json, Javascript, Mail, Unescape
|
||||
$smarty->registerPlugin('block', 'escape', [$escapePlugin, 'compileEscapeBlock']);
|
||||
$smarty->registerPlugin('block', 'escapeHtml', [$escapePlugin, 'compileEscapeHtmlBlock']);
|
||||
$smarty->registerPlugin('modifier', 'escape', [$escapePlugin, 'compileEscapeModifier']);
|
||||
$smarty->registerPlugin('modifier', 'escapeEntities', [$escapePlugin, 'compileEscapeEntitiesModifier']);
|
||||
$smarty->registerPlugin('modifier', 'escapeQuotes', [$escapePlugin, 'compileEscapeQuotesModifier']);
|
||||
$smarty->registerPlugin('modifier', 'escapeHtml', [$escapePlugin, 'compileEscapeHtmlModifier']);
|
||||
$smarty->registerPlugin('modifier', 'escapeUrl', [$escapePlugin, 'compileEscapeUrlModifier']);
|
||||
|
||||
//$smartyDebug = new Smarty_Internal_Debug();
|
||||
//$smartyDebug->display_debug($smarty, true);
|
||||
|
||||
return new SmartyFacade($smarty);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Template\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class DirectoryNotFoundException extends RuntimeException implements TemplateExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Template\Exception;
|
||||
|
||||
use InvalidArgumentException as SplInvalidArgumentException;
|
||||
|
||||
class InvalidArgumentException extends SplInvalidArgumentException implements TemplateExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Template\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class TemplateException extends RuntimeException implements TemplateExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Template\Exception;
|
||||
|
||||
use Xentral\Core\Exception\ComponentExceptionInterface;
|
||||
|
||||
interface TemplateExceptionInterface extends ComponentExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Template;
|
||||
|
||||
use Exception;
|
||||
use Smarty;
|
||||
use Xentral\Components\Template\Exception\TemplateException;
|
||||
|
||||
final class SmartyFacade
|
||||
{
|
||||
/** @var Smarty $smarty */
|
||||
private $smarty;
|
||||
|
||||
/**
|
||||
* @param Smarty $smarty
|
||||
*/
|
||||
public function __construct(Smarty $smarty)
|
||||
{
|
||||
$this->smarty = $smarty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Smarty_Internal_Template::fetch()
|
||||
*
|
||||
* @param string $template
|
||||
*
|
||||
* @throws TemplateException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fetch($template = null)
|
||||
{
|
||||
try {
|
||||
return $this->smarty->fetch($template);
|
||||
} catch (Exception $e) {
|
||||
throw new TemplateException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Smarty_Internal_Template::display()
|
||||
*
|
||||
* @param string $template
|
||||
*
|
||||
* @throws TemplateException
|
||||
*/
|
||||
public function display($template = null)
|
||||
{
|
||||
try {
|
||||
$this->smarty->display($template);
|
||||
} catch (Exception $e) {
|
||||
throw new TemplateException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Smarty_Internal_Data::assign()
|
||||
*
|
||||
* @param array|string $tplVar
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return SmartyFacade
|
||||
*/
|
||||
public function assign($tplVar, $value = null)
|
||||
{
|
||||
$this->smarty->assign($tplVar, $value, false);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Smarty_Internal_Data::append()
|
||||
*
|
||||
* @param array|string $tplVar
|
||||
* @param mixed $value
|
||||
* @param bool $merge
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function append($tplVar, $value = null, $merge = false)
|
||||
{
|
||||
$this->smarty->append($tplVar, $value, $merge, false);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $tplVar
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function clearAssign($tplVar)
|
||||
{
|
||||
$this->smarty->clearAssign($tplVar);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $varName
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTemplateVars($varName = null)
|
||||
{
|
||||
return $this->smarty->getTemplateVars($varName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $templateDir
|
||||
* @param null $key
|
||||
* @param bool $isConfig
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addTemplateDir($templateDir, $key = null, $isConfig = false)
|
||||
{
|
||||
$this->smarty->addTemplateDir($templateDir, $key, $isConfig);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $template
|
||||
*
|
||||
* @throws TemplateException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function templateExists($template)
|
||||
{
|
||||
try {
|
||||
return $this->smarty->templateExists($template);
|
||||
} catch (Exception $e) {
|
||||
throw new TemplateException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Smarty
|
||||
*/
|
||||
public function getSmarty()
|
||||
{
|
||||
return $this->smarty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws TemplateException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function displayDebugConsole()
|
||||
{
|
||||
try {
|
||||
$this->smarty->_debug->display_debug($this->smarty);
|
||||
} catch (Exception $e) {
|
||||
throw new TemplateException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Template\SmartyPlugin;
|
||||
|
||||
use Smarty_Internal_Template;
|
||||
use Xentral\Components\Template\Exception\TemplateException;
|
||||
|
||||
final class EscapePlugin
|
||||
{
|
||||
/** @var string $charset */
|
||||
private $charset = 'UTF-8';
|
||||
|
||||
/**
|
||||
* @example {escape format='html'}{$evilString}{/escape}
|
||||
*
|
||||
* Default format is 'html'
|
||||
*
|
||||
* @param array $params
|
||||
* @param mixed $content
|
||||
* @param Smarty_Internal_Template $template
|
||||
* @param bool $repeat
|
||||
*
|
||||
* @throws TemplateException On missing params
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function compileEscapeBlock($params, $content, $template, &$repeat)
|
||||
{
|
||||
// Only output on closing tag @see https://www.smarty.net/docs/en/plugins.block.functions.tpl
|
||||
if ($repeat === true) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$format = isset($params['format']) ? $params['format'] : 'html';
|
||||
|
||||
switch ($format) {
|
||||
case 'none':
|
||||
case 'null':
|
||||
return $content;
|
||||
break;
|
||||
|
||||
case 'entitites':
|
||||
return $this->escapeHtmlEntities($content);
|
||||
break;
|
||||
|
||||
case 'quotes':
|
||||
return $this->escapeQuotes($content);
|
||||
break;
|
||||
|
||||
case 'url':
|
||||
return $this->escapeUrl($content);
|
||||
break;
|
||||
|
||||
case 'html':
|
||||
default:
|
||||
return $this->escapeHtml($content);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @example {escapeHtml}{$evilString}{/escapeHtml}
|
||||
*
|
||||
* @param array $params
|
||||
* @param mixed $content
|
||||
* @param Smarty_Internal_Template $template
|
||||
* @param bool $repeat
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function compileEscapeHtmlBlock($params, $content, $template, &$repeat)
|
||||
{
|
||||
// Only output on closing tag @see https://www.smarty.net/docs/en/plugins.block.functions.tpl
|
||||
if ($repeat === true) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->escapeHtml($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @example {$evilString|escape:'html'}
|
||||
*
|
||||
* @param string $content
|
||||
* @param string $format
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function compileEscapeModifier($content, $format = 'html')
|
||||
{
|
||||
switch ($format) {
|
||||
case 'none':
|
||||
case 'null':
|
||||
return $content;
|
||||
break;
|
||||
|
||||
case 'entitites':
|
||||
return $this->escapeHtmlEntities($content);
|
||||
break;
|
||||
|
||||
case 'quotes':
|
||||
return $this->escapeQuotes($content);
|
||||
break;
|
||||
|
||||
case 'url':
|
||||
return $this->escapeUrl($content);
|
||||
break;
|
||||
|
||||
case 'html':
|
||||
default:
|
||||
return $this->escapeHtml($content);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @example {$string|escapeEntities}
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function compileEscapeEntitiesModifier($content)
|
||||
{
|
||||
return $this->escapeHtmlEntities($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes unescaped single quotes
|
||||
*
|
||||
* @example {$quotedString|escapeQuotes}
|
||||
*
|
||||
* @param mixed $content
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function compileEscapeQuotesModifier($content)
|
||||
{
|
||||
return $this->escapeQuotes($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @example {$evilString|escapeHtml}
|
||||
*
|
||||
* @param mixed $content
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function compileEscapeHtmlModifier($content)
|
||||
{
|
||||
return $this->escapeHtml($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @example {$url|escapeUrl}
|
||||
*
|
||||
* @param mixed $content
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function compileEscapeUrlModifier($content)
|
||||
{
|
||||
return $this->escapeUrl($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function escapeHtml($string)
|
||||
{
|
||||
return htmlspecialchars($string, ENT_QUOTES, $this->charset, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function escapeHtmlEntities($string)
|
||||
{
|
||||
return htmlentities($string, ENT_QUOTES, $this->charset, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function escapeQuotes($string)
|
||||
{
|
||||
return preg_replace("%(?<!\\\\)'%", "\\'", $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function escapeUrl($string)
|
||||
{
|
||||
return rawurlencode($string);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Template\SmartyPlugin;
|
||||
|
||||
use Smarty_Internal_Template;
|
||||
use Smarty_Template_Source;
|
||||
use Xentral\Components\Template\Exception\TemplateException;
|
||||
|
||||
final class TranslationPlugin
|
||||
{
|
||||
/**
|
||||
* @todo Add TranslationService
|
||||
* @var null $translator
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
/** @var array $resourceNamespaces */
|
||||
private $resourceNamespaces = [];
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
* @param Smarty_Internal_Template $template
|
||||
*
|
||||
* @throws TemplateException If 'key' param is not set
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function compileNamespaceFunction($params, $template)
|
||||
{
|
||||
if (empty($params['key'])) {
|
||||
$sourceName = $this->getResourceSourceName($template);
|
||||
throw new TemplateException(sprintf(
|
||||
'Template error: Required parameter "key" is missing in {namespace} function. Source: %s', $sourceName
|
||||
));
|
||||
}
|
||||
|
||||
// Store which namespace is used in which template
|
||||
$resource = $template->source->resource;
|
||||
$this->addResourceNamespace($resource, $params['key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
* @param mixed $content
|
||||
* @param Smarty_Internal_Template $template
|
||||
* @param bool $repeat
|
||||
*
|
||||
* @throws TemplateException On missing params
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function compileTranslateBlock($params, $content, $template, &$repeat)
|
||||
{
|
||||
// Only output on closing tag @see https://www.smarty.net/docs/en/plugins.block.functions.tpl
|
||||
if ($repeat === true) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (empty($params['key'])) {
|
||||
throw new TemplateException(sprintf(
|
||||
'Template error: Required parameter "key" is missing in {translate} block. Source: %s',
|
||||
$template->source->resource
|
||||
));
|
||||
}
|
||||
|
||||
if (!empty($params['namespace'])) {
|
||||
$namespace = $params['namespace'];
|
||||
} else {
|
||||
$namespace = $this->determineResourceNamespace($template);
|
||||
}
|
||||
|
||||
if (empty($namespace)) {
|
||||
$sourceName = $this->getResourceSourceName($template);
|
||||
throw new TemplateException(sprintf(
|
||||
'Template error: Namespace for translation could not be determined. Source: %s', $sourceName
|
||||
));
|
||||
}
|
||||
|
||||
// @todo Use TranslationService
|
||||
return (string)$content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Smarty_Internal_Template $template
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getResourceSourceName($template)
|
||||
{
|
||||
$source = $template->source;
|
||||
if ($source->type === 'file') {
|
||||
return 'File ' . $source->filepath;
|
||||
}
|
||||
|
||||
return sprintf('Resource %s:%s', $source->type, $source->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $resource
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isResourceNamespaceDefined($resource)
|
||||
{
|
||||
return isset($this->resourceNamespaces[$resource]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $resource
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getResourceNamespace($resource)
|
||||
{
|
||||
return $this->resourceNamespaces[$resource];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Smarty_Internal_Template $template
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function determineResourceNamespace($template)
|
||||
{
|
||||
$resource = $template->source->resource;
|
||||
if ($this->isResourceNamespaceDefined($resource)) {
|
||||
return $this->getResourceNamespace($resource);
|
||||
}
|
||||
|
||||
$namespace = $this->findResourceNamespaceFromParents($template->inheritance->sources);
|
||||
$this->addResourceNamespace($resource, $namespace);
|
||||
|
||||
return $namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|Smarty_Template_Source[] $parents
|
||||
*
|
||||
* @return string|null Namespace
|
||||
*/
|
||||
private function findResourceNamespaceFromParents($parents)
|
||||
{
|
||||
foreach ($parents as $source) {
|
||||
$resource = $source->resource;
|
||||
if ($this->isResourceNamespaceDefined($resource)) {
|
||||
return $this->resourceNamespaces[$resource];
|
||||
}
|
||||
}
|
||||
|
||||
return 'default';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $resource
|
||||
* @param string $namespace
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addResourceNamespace($resource, $namespace)
|
||||
{
|
||||
if ($this->isResourceNamespaceDefined($resource)) {
|
||||
throw new TemplateException(sprintf(
|
||||
'Template resource namespace for resource "%s" is already defined', $resource
|
||||
));
|
||||
}
|
||||
|
||||
$this->resourceNamespaces[$resource] = $namespace;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Template;
|
||||
|
||||
use Smarty;
|
||||
use TemplateParser;
|
||||
use Xentral\Components\Template\Exception\DirectoryNotFoundException;
|
||||
use Xentral\Components\Template\Exception\InvalidArgumentException;
|
||||
|
||||
final class Template implements TemplateInterface
|
||||
{
|
||||
/** @var SmartyFacade $smartyFacade */
|
||||
private $smartyFacade;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @var TemplateParser $legacyTemplate
|
||||
*/
|
||||
private $legacyTemplate;
|
||||
|
||||
/** @var string $defaultNamespace */
|
||||
private $defaultNamespace;
|
||||
|
||||
/**
|
||||
* @param SmartyFacade $smarty
|
||||
* @param TemplateParser $legacyTemplate
|
||||
*/
|
||||
public function __construct(SmartyFacade $smarty, TemplateParser $legacyTemplate)
|
||||
{
|
||||
$this->smartyFacade = $smarty;
|
||||
$this->legacyTemplate = $legacyTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getVar($tplVar)
|
||||
{
|
||||
$this->ensureTemplateVarIsString($tplVar);
|
||||
|
||||
return $this->smartyFacade->getTemplateVars($tplVar);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getVars()
|
||||
{
|
||||
return $this->smartyFacade->getTemplateVars(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function assign($tplVar, $value)
|
||||
{
|
||||
$this->ensureTemplateVarIsString($tplVar);
|
||||
$this->smartyFacade->assign((string)$tplVar, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function assignAssoc(array $assocTplVars)
|
||||
{
|
||||
foreach ($assocTplVars as $tplVar => $value) {
|
||||
$this->assign($tplVar, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function append($tplVar, $value)
|
||||
{
|
||||
$this->ensureTemplateVarIsString($tplVar);
|
||||
$this->smartyFacade->append($tplVar, $value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function appendString($tplVar, $value)
|
||||
{
|
||||
$this->ensureTemplateVarIsString($tplVar);
|
||||
$assigned = (string)$this->getVar($tplVar);
|
||||
|
||||
$this->smartyFacade->assign($tplVar, $assigned . $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function appendAssoc(array $assocTplVar)
|
||||
{
|
||||
foreach ($assocTplVar as $tplVar => $value) {
|
||||
$this->append((string)$tplVar, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function clearAssign($tplVar)
|
||||
{
|
||||
$this->ensureTemplateVarIsString($tplVar);
|
||||
$this->smartyFacade->clearAssign((string)$tplVar);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function clearAssoc(array $tplVars)
|
||||
{
|
||||
foreach ($tplVars as $tplVar) {
|
||||
$this->clearAssign($tplVar);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function fetch($template, $namespace = null)
|
||||
{
|
||||
$templatePath = $this->discoverTemplatePath($template, $namespace);
|
||||
|
||||
return $this->smartyFacade->fetch($templatePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function display($template, $namespace = null)
|
||||
{
|
||||
$html = $this->fetch($template, $namespace);
|
||||
|
||||
$this->legacyTemplate->Set('PAGE', $html);
|
||||
$this->legacyTemplate->Parse('PAGE', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function addTemplateDir($directory)
|
||||
{
|
||||
$realPath = realpath($directory);
|
||||
if ($realPath === false || !is_dir($realPath)) {
|
||||
throw new DirectoryNotFoundException(sprintf(
|
||||
'Directory "%s" does not exist.', $directory
|
||||
));
|
||||
}
|
||||
|
||||
$this->smartyFacade->addTemplateDir($directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDefaultNamespace()
|
||||
{
|
||||
return $this->defaultNamespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function setDefaultNamespace($namespace)
|
||||
{
|
||||
if (empty($namespace)) {
|
||||
throw new InvalidArgumentException('Namespace can not be empty.');
|
||||
}
|
||||
|
||||
$this->defaultNamespace = $namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @return Smarty
|
||||
*/
|
||||
public function getSmarty()
|
||||
{
|
||||
return $this->smartyFacade->getSmarty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens Smarty Debugging Console window
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function displayDebugWindow()
|
||||
{
|
||||
$this->smartyFacade->displayDebugConsole();
|
||||
}
|
||||
|
||||
/**
|
||||
* @example 'list.tpl', 'Modules/Chat' => 'Modules/Chat/templates/list.tpl'
|
||||
*
|
||||
* @param string $template
|
||||
* @param string|null $namespace
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function discoverTemplatePath($template, $namespace = null)
|
||||
{
|
||||
if (empty($template)) {
|
||||
throw new InvalidArgumentException('Required parameter "$template" is empty.');
|
||||
}
|
||||
|
||||
// System templates don't have namespaces
|
||||
if ($namespace === null && $this->smartyFacade->templateExists($template)) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
return $this->discoverNamespacedTemplatePath($template, $namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $template
|
||||
* @param string|null $namespace
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function discoverNamespacedTemplatePath($template, $namespace = null)
|
||||
{
|
||||
if ($namespace === null && $this->defaultNamespace === null) {
|
||||
throw new InvalidArgumentException('Default namespace is not set.');
|
||||
}
|
||||
if ($namespace === null) {
|
||||
$namespace = $this->defaultNamespace;
|
||||
}
|
||||
|
||||
$template = ltrim($template, '/');
|
||||
$namespace = trim($namespace, '/');
|
||||
|
||||
return $namespace . '/templates/' . $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $tplVar
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function ensureTemplateVarIsString($tplVar)
|
||||
{
|
||||
if (!is_string($tplVar)) {
|
||||
throw new InvalidArgumentException('Template variable is not a string.');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Template;
|
||||
|
||||
use Xentral\Components\Template\Exception\DirectoryNotFoundException;
|
||||
|
||||
interface TemplateInterface
|
||||
{
|
||||
/**
|
||||
* Gets the value of one assigned template variable.
|
||||
*
|
||||
* @param string $tplVar
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getVar($tplVar);
|
||||
|
||||
/**
|
||||
* Gets all assigned template variables and values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getVars();
|
||||
|
||||
/**
|
||||
* Assigns a value to a template variable.
|
||||
*
|
||||
* If variable is already assigned, than the value will be overwritten.
|
||||
*
|
||||
* @param string $tplVar
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assign($tplVar, $value);
|
||||
|
||||
/**
|
||||
* Assigns multiple template variables.
|
||||
*
|
||||
* Array keys will be used as template variable and array values as value.
|
||||
*
|
||||
* @example assignAssoc(['foo' => 'zof', 'bar' => 'baz']); In Tempalte: {$foo} {$bar}
|
||||
*
|
||||
* @param array $assocTplVar
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assignAssoc(array $assocTplVar);
|
||||
|
||||
/**
|
||||
* Appends a value to a previously assigned variable.
|
||||
*
|
||||
* * The previously assigned value will be transformed to an array.
|
||||
* * The passed value will be pushed to that array.
|
||||
*
|
||||
* @param string $tplVar
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function append($tplVar, $value);
|
||||
|
||||
/**
|
||||
* Appends a value as string
|
||||
*
|
||||
* Previously assigned values will be transformed to string. Values will be concatenated.
|
||||
*
|
||||
* @param string $tplVar
|
||||
* @param string $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function appendString($tplVar, $value);
|
||||
|
||||
/**
|
||||
* Appends multiple template variables.
|
||||
*
|
||||
* Array keys will be used as template variable and array values as value.
|
||||
*
|
||||
* For each row:
|
||||
* * The previously assigned value will be transformed to an array.
|
||||
* * The passed value will be pushed to that array.
|
||||
*
|
||||
* @param array $assocTplVar
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function appendAssoc(array $assocTplVar);
|
||||
|
||||
/**
|
||||
* Deletes a template variable
|
||||
*
|
||||
* @param string $tplVar
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clearAssign($tplVar);
|
||||
|
||||
/**
|
||||
* Deletes multiple template variables.
|
||||
*
|
||||
* @param array|string[] $tplVars
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clearAssoc(array $tplVars);
|
||||
|
||||
/**
|
||||
* Parses the template an returns the output.
|
||||
*
|
||||
* @param string $template
|
||||
* @param string|null $namespace
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fetch($template, $namespace = null);
|
||||
|
||||
/**
|
||||
* Parses the template an display the output.
|
||||
*
|
||||
* @param string $template
|
||||
* @param string|null $namespace
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display($template, $namespace = null);
|
||||
|
||||
/**
|
||||
* @param string $directory Absolute path to template directory
|
||||
*
|
||||
* @throws DirectoryNotFoundException If the directory does not exist
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addTemplateDir($directory);
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDefaultNamespace();
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultNamespace($namespace);
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
{capture name='_smarty_debug' assign=debug_output}
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
<head>
|
||||
<title>Smarty Debug Console</title>
|
||||
<style type="text/css">
|
||||
{literal}
|
||||
body, h1, h2, h3, td, th, p {
|
||||
font-family: sans-serif;
|
||||
font-weight: normal;
|
||||
font-size: 0.9em;
|
||||
margin: 1px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
padding: 2px;
|
||||
background-color: #f0c040;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
background-color: #9B410E;
|
||||
color: white;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
padding: 2px;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
h3 {
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
font-size: 0.7em;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
body {
|
||||
background: black;
|
||||
}
|
||||
|
||||
p, table, div {
|
||||
background: #f0ead8;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
th, td {
|
||||
font-family: monospace;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.odd {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
.even {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.exectime {
|
||||
font-size: 0.8em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#bold div {
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
#blue h3 {
|
||||
color: blue;
|
||||
}
|
||||
#normal div {
|
||||
color: black;
|
||||
font-weight: normal;
|
||||
}
|
||||
#table_assigned_vars th {
|
||||
color: blue;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#table_config_vars th {
|
||||
color: maroon;
|
||||
}
|
||||
|
||||
{/literal}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Smarty {Smarty::SMARTY_VERSION} Debug Console
|
||||
- {if isset($template_name)}{$template_name|debug_print_var nofilter} {/if}{if !empty($template_data)}Total Time {$execution_time|string_format:"%.5f"}{/if}</h1>
|
||||
|
||||
{if !empty($template_data)}
|
||||
<h2>included templates & config files (load time in seconds)</h2>
|
||||
<div>
|
||||
{foreach $template_data as $template}
|
||||
<font color=brown>{$template.name}</font>
|
||||
<br /> <span class="exectime">
|
||||
(compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"})
|
||||
</span>
|
||||
<br />
|
||||
{/foreach}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<h2>assigned template variables</h2>
|
||||
|
||||
<table id="table_assigned_vars">
|
||||
{foreach $assigned_vars as $vars}
|
||||
<tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
|
||||
<td><h3><font color=blue>${$vars@key}</font></h3>
|
||||
{if isset($vars['nocache'])}<b>Nocache</b><br />{/if}
|
||||
{if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var nofilter}{/if}
|
||||
</td>
|
||||
<td><h3>Value</h3>{$vars['value']|debug_print_var:10:80 nofilter}</td>
|
||||
<td>{if isset($vars['attributes'])}<h3>Attributes</h3>{$vars['attributes']|debug_print_var nofilter} {/if}</td>
|
||||
{/foreach}
|
||||
</table>
|
||||
|
||||
<h2>assigned config file variables</h2>
|
||||
|
||||
<table id="table_config_vars">
|
||||
{foreach $config_vars as $vars}
|
||||
<tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
|
||||
<td><h3><font color=blue>#{$vars@key}#</font></h3>
|
||||
{if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var nofilter}{/if}
|
||||
</td>
|
||||
<td>{$vars['value']|debug_print_var:10:80 nofilter}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
{/capture}
|
||||
<script type="text/javascript">
|
||||
{$id = '__Smarty__'}
|
||||
{if $display_mode}{$id = "$offset$template_name"|md5}{/if}
|
||||
_smarty_console = window.open("", "console{$id}", "width=1024,height=600,left={$offset},top={$offset},resizable,scrollbars=yes");
|
||||
_smarty_console.document.write("{$debug_output|escape:'javascript' nofilter}");
|
||||
_smarty_console.document.close();
|
||||
</script>
|
||||
@@ -0,0 +1,4 @@
|
||||
{* Hier sollte das HTML-Grundgerüst sein; momentan wird das Grundgerüst über den Legacy-TemplateParser gerendert. *}
|
||||
{namespace key='default'}
|
||||
|
||||
{block name="page"}{/block}
|
||||
Reference in New Issue
Block a user