diff --git a/src/Cache/Storage.php b/src/Cache/Storage.php index 6c41144..c244b08 100644 --- a/src/Cache/Storage.php +++ b/src/Cache/Storage.php @@ -17,7 +17,7 @@ */ namespace Ytake\LaravelSmarty\Cache; -use Smarty; +use Ytake\LaravelSmarty\Smarty; use Illuminate\Contracts\Config\Repository as ConfigContract; /** diff --git a/src/Compilers/Compilable.php b/src/Compilers/Compilable.php new file mode 100644 index 0000000..e6f7e36 --- /dev/null +++ b/src/Compilers/Compilable.php @@ -0,0 +1,39 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ +interface Compilable +{ + /** + * @param Factory $factory + */ + public function setViewFactory(Factory $factory); + + /** + * @param array $data + */ + public function setLaravelViewData(array $data); +} diff --git a/src/Compilers/CompileInclude.php b/src/Compilers/CompileInclude.php new file mode 100644 index 0000000..a8b6905 --- /dev/null +++ b/src/Compilers/CompileInclude.php @@ -0,0 +1,97 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ +class CompileInclude extends \Smarty_Internal_Compile_Include implements Compilable +{ + /** @var Factory|\Ytake\LaravelSmarty\SmartyFactory */ + protected $viewFactory; + + /** @var array */ + protected $laravelViewData; + + /** + * {@inheritdoc} + */ + public function compile($args, \Smarty_Internal_SmartyTemplateCompiler $compiler, $parameter) + { + foreach ($args as $arg) { + if (isset($arg['file'])) { + $viewName = $this->normalizeTemplateName($arg['file']); + $this->dispatch($viewName); + } + } + + return parent::compile($args, $compiler, $parameter); + } + + /** + * @param Factory $factory + */ + public function setViewFactory(Factory $factory) + { + $this->viewFactory = $factory; + } + + /** + * @param array $data + */ + public function setLaravelViewData(array $data) + { + $this->laravelViewData = $data; + } + + /** + * @param string $name + * + * @return string + */ + protected function normalizeTemplateName($name) + { + $fileInfo = new \SplFileInfo($name); + $path = ($fileInfo->getPath() === '') ? null : $fileInfo->getPath() . '/'; + $viewPathInfo = $path . $fileInfo->getBasename('.' . $fileInfo->getExtension()); + + return trim(str_replace('/', '.', $viewPathInfo), '"'); + } + + /** + * @param $name + */ + protected function dispatch($name) + { + $view = new View( + $this->viewFactory, + $this->viewFactory->getEngineResolver()->resolve('smarty'), + $name, + null, + [] + ); + $this->viewFactory->callCreator($view); + $this->viewFactory->callComposer($view); + } +} diff --git a/src/Compilers/TemplateCompiler.php b/src/Compilers/TemplateCompiler.php new file mode 100644 index 0000000..381a3f6 --- /dev/null +++ b/src/Compilers/TemplateCompiler.php @@ -0,0 +1,84 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ +class TemplateCompiler extends \Smarty_Internal_SmartyTemplateCompiler +{ + /** + * {@inheritdoc} + */ + public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null) + { + $this->smarty->tpl_vars['userCount'] = new \Smarty_Variable(9999); + if (!isset(self::$_tag_objects[$tag])) { + // lazy load internal compiler plugin + $_tag = explode('_', $tag); + $_tag = array_map('ucfirst', $_tag); + $class_name = $this->detectSmartyInternalCompiler('Smarty_Internal_Compile_' . implode('_', $_tag)); + if (class_exists($class_name) && + (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) + ) { + self::$_tag_objects[$tag] = $this->appendViewFactoryInstance(new $class_name);; + } else { + self::$_tag_objects[$tag] = false; + + return false; + } + } + + // compile this tag + return self::$_tag_objects[$tag] === false ? false : + self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3); + } + + /** + * @param string $className + * + * @return string + */ + protected function detectSmartyInternalCompiler($className) + { + if ($className === \Smarty_Internal_Compile_Include::class) { + $className = CompileInclude::class; + } + + return $className; + } + + /** + * @param \Smarty_Internal_CompileBase|Compilable $instance + * + * @return \Smarty_Internal_CompileBase|Compilable + */ + protected function appendViewFactoryInstance($instance) + { + if ($instance instanceof Compilable) { + if (!is_null($this->smarty->getViewFactory())) { + $instance->setViewFactory($this->smarty->getViewFactory()); + } + } + + return $instance; + } +} diff --git a/src/Console/CacheClearCommand.php b/src/Console/CacheClearCommand.php index a7774f7..0eda97c 100644 --- a/src/Console/CacheClearCommand.php +++ b/src/Console/CacheClearCommand.php @@ -17,7 +17,7 @@ */ namespace Ytake\LaravelSmarty\Console; -use Smarty; +use Ytake\LaravelSmarty\Smarty; use Illuminate\Console\Command; use Symfony\Component\Console\Input\InputOption; diff --git a/src/Console/OptimizeCommand.php b/src/Console/OptimizeCommand.php index b9a6bae..ae77db5 100644 --- a/src/Console/OptimizeCommand.php +++ b/src/Console/OptimizeCommand.php @@ -17,7 +17,7 @@ */ namespace Ytake\LaravelSmarty\Console; -use Smarty; +use Ytake\LaravelSmarty\Smarty; use Illuminate\Console\Command; use Symfony\Component\Console\Input\InputOption; use Illuminate\Contracts\Config\Repository as ConfigContract; diff --git a/src/Console/PackageInfoCommand.php b/src/Console/PackageInfoCommand.php index c6d2af8..1a7d6b9 100644 --- a/src/Console/PackageInfoCommand.php +++ b/src/Console/PackageInfoCommand.php @@ -17,7 +17,7 @@ */ namespace Ytake\LaravelSmarty\Console; -use Smarty; +use Ytake\LaravelSmarty\Smarty; use Illuminate\Console\Command; use Ytake\LaravelSmarty\SmartyFactory; diff --git a/src/Engines/SmartyEngine.php b/src/Engines/SmartyEngine.php index 4c05a54..4a37c36 100644 --- a/src/Engines/SmartyEngine.php +++ b/src/Engines/SmartyEngine.php @@ -17,8 +17,9 @@ */ namespace Ytake\LaravelSmarty\Engines; -use Smarty; +use Illuminate\Events\Dispatcher; use Throwable; +use Ytake\LaravelSmarty\Smarty; use Illuminate\View\Engines\EngineInterface; use Symfony\Component\Debug\Exception\FatalThrowableError; @@ -83,6 +84,7 @@ protected function evaluatePath($path, array $data = []) /** * @codeCoverageIgnore + * * @param \Exception $e * * @throws \Exception diff --git a/src/Engines/SmartyTemplate.php b/src/Engines/SmartyTemplate.php new file mode 100644 index 0000000..345c3ec --- /dev/null +++ b/src/Engines/SmartyTemplate.php @@ -0,0 +1,64 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ +class SmartyTemplate extends \Smarty_Internal_Template +{ + /** + * {@inheritdoc} + */ + public function __construct( + $template_resource, + Smarty $smarty, + Smarty_Internal_Data $_parent = null, + $_cache_id = null, + $_compile_id = null, + $_caching = null, + $_cache_lifetime = null + ) { + $this->smarty = $smarty; + $this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id; + $this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id; + $this->caching = $_caching === null ? $this->smarty->caching : $_caching; + if ($this->caching === true) { + $this->caching = Smarty::CACHING_LIFETIME_CURRENT; + } + $this->cache_lifetime = $_cache_lifetime === null ? $this->smarty->cache_lifetime : $_cache_lifetime; + $this->parent = $_parent; + // Template resource + $this->template_resource = $template_resource; + $this->source = Smarty_Template_Source::load($this); + $this->source->compiler_class = TemplateCompiler::class; + + Smarty_Internal_Data::__construct(); + if ($smarty->security_policy && method_exists($smarty->security_policy, 'registerCallBacks')) { + $smarty->security_policy->registerCallBacks($this); + } + } +} diff --git a/src/Smarty.php b/src/Smarty.php new file mode 100644 index 0000000..8f9134d --- /dev/null +++ b/src/Smarty.php @@ -0,0 +1,67 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ +final class Smarty extends \Smarty +{ + /** @var Factory */ + protected $viewFactory; + + /** @var array */ + protected $laravelViewData = []; + + /** + * @param Factory $factory + */ + public function setViewFactory(Factory $factory) + { + $this->viewFactory = $factory; + } + + /** + * @return Factory + */ + public function getViewFactory() + { + return $this->viewFactory; + } + + /** + * @param array $data + */ + public function setLaravelViewData(array $data) + { + $this->laravelViewData = $data; + } + + /** + * @return array + */ + public function getLaravelViewData() + { + return $this->laravelViewData; + } +} diff --git a/src/SmartyFactory.php b/src/SmartyFactory.php index ca5424a..825a7dd 100644 --- a/src/SmartyFactory.php +++ b/src/SmartyFactory.php @@ -17,12 +17,13 @@ */ namespace Ytake\LaravelSmarty; -use Smarty; +use Ytake\LaravelSmarty\Smarty; use ReflectionClass; use Illuminate\View\Factory; use Illuminate\View\ViewFinderInterface; use Illuminate\View\Engines\EngineResolver; use Ytake\LaravelSmarty\Cache\Storage; +use Ytake\LaravelSmarty\Engines\SmartyTemplate; use Ytake\LaravelSmarty\Exception\MethodNotFoundException; use Illuminate\Contracts\Config\Repository as ConfigContract; use Illuminate\Contracts\Events\Dispatcher as DispatcherContract; @@ -38,7 +39,7 @@ class SmartyFactory extends Factory /** * @var string version */ - const VERSION = '2.1.7'; + const VERSION = '2.1.11'; /** @var Smarty $smarty */ protected $smarty; @@ -116,7 +117,7 @@ class SmartyFactory extends Factory 'template_class', 'tpl_vars', 'parent', - 'config_vars' + 'config_vars', ]; /** @var array valid security policy config keys */ @@ -162,7 +163,7 @@ public function __construct( } /** - * @return \Smarty + * @return Smarty */ public function getSmarty() { @@ -208,7 +209,8 @@ public function setSmartyConfigure() } $smarty->error_reporting = array_get($config, 'error_reporting', E_ALL & ~E_NOTICE); - + // SmartyTemplate class for laravel + $smarty->template_class = SmartyTemplate::class; foreach ($config as $key => $value) { if (in_array($key, $this->configKeys)) { $this->smarty->{$key} = $value; @@ -217,7 +219,6 @@ public function setSmartyConfigure() if (array_get($config, 'enable_security')) { $smarty->enableSecurity(); - $securityPolicy = $smarty->security_policy; $securityConfig = array_get($config, 'security_policy', []); foreach ($securityConfig as $key => $value) { @@ -241,6 +242,7 @@ public function __call($name, $arguments) if (!$reflectionClass->hasMethod($name)) { throw new MethodNotFoundException("{$name} : Method Not Found"); } + return call_user_func_array([$this->smarty, $name], $arguments); } } diff --git a/src/SmartyServiceProvider.php b/src/SmartyServiceProvider.php index 8e3b45a..c5b38a5 100644 --- a/src/SmartyServiceProvider.php +++ b/src/SmartyServiceProvider.php @@ -17,7 +17,7 @@ */ namespace Ytake\LaravelSmarty; -use Smarty; +use Ytake\LaravelSmarty\Smarty; use Illuminate\Support\ServiceProvider; /** @@ -56,22 +56,22 @@ public function register() ]); $this->app->singleton('smarty.view', function ($app) { + $smartyTemplate = new Smarty; $factory = new SmartyFactory( $app['view.engine.resolver'], $app['view.finder'], $app['events'], - new Smarty, + $smartyTemplate, $this->app['config'] ); - // Pass the container to the factory so it can be used to resolve view composers. $factory->setContainer($app); - $factory->share('app', $app); // resolve cache storage $factory->resolveSmartyCache(); // smarty configure(use ytake-laravel-smarty.php) $factory->setSmartyConfigure(); + $smartyTemplate->setViewFactory($factory); return $factory; });