123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- <?php
- /**
- * @link http://www.yiiframework.com/
- * @copyright Copyright (c) 2008 Yii Software LLC
- * @license http://www.yiiframework.com/license/
- */
- namespace yii\twig;
- use yii\base\InvalidCallException;
- use yii\helpers\Inflector;
- use yii\helpers\StringHelper;
- use yii\helpers\Url;
- use yii\web\AssetBundle;
- /**
- * Extension provides Yii-specific syntax for Twig templates.
- *
- * @author Andrey Grachov <andrey.grachov@gmail.com>
- * @author Alexander Makarov <sam@rmcreative.ru>
- */
- class Extension extends \Twig_Extension
- {
- /**
- * @var array used namespaces
- */
- protected $namespaces = [];
- /**
- * @var array used class aliases
- */
- protected $aliases = [];
- /**
- * @var array used widgets
- */
- protected $widgets = [];
- /**
- * Creates new instance
- *
- * @param array $uses namespaces and classes to use in the template
- */
- public function __construct(array $uses = [])
- {
- $this->addUses($uses);
- }
- /**
- * @inheritdoc
- */
- public function getNodeVisitors()
- {
- return [
- new Optimizer(),
- new GetAttrAdjuster(),
- ];
- }
- /**
- * @inheritdoc
- */
- public function getFunctions()
- {
- $options = [
- 'is_safe' => ['html'],
- ];
- $functions = [
- new \Twig_SimpleFunction('use', [$this, 'addUses'], $options),
- new \Twig_SimpleFunction('*_begin', [$this, 'beginWidget'], $options),
- new \Twig_SimpleFunction('*_end', [$this, 'endWidget'], $options),
- new \Twig_SimpleFunction('widget_end', [$this, 'endWidget'], $options),
- new \Twig_SimpleFunction('*_widget', [$this, 'widget'], $options),
- new \Twig_SimpleFunction('path', [$this, 'path']),
- new \Twig_SimpleFunction('url', [$this, 'url']),
- new \Twig_SimpleFunction('void', function(){}),
- new \Twig_SimpleFunction('set', [$this, 'setProperty']),
- ];
- $options = array_merge($options, [
- 'needs_context' => true,
- ]);
- $functions[] = new \Twig_SimpleFunction('register_*', [$this, 'registerAsset'], $options);
- $functions[] = new \Twig_SimpleFunction('register_asset_bundle', [$this, 'registerAssetBundle'], $options);
- foreach (['begin_page', 'end_page', 'begin_body', 'end_body', 'head'] as $helper) {
- $functions[] = new \Twig_SimpleFunction($helper, [$this, 'viewHelper'], $options);
- }
- return $functions;
- }
- /**
- * Function for registering an asset
- *
- * ```
- * {{ use('yii/web/JqueryAsset') }}
- * {{ register_jquery_asset() }}
- * ```
- *
- * @param array $context context information
- * @param string $asset asset name
- * @return mixed
- */
- public function registerAsset($context, $asset)
- {
- return $this->resolveAndCall($asset, 'register', [
- isset($context['this']) ? $context['this'] : null,
- ]);
- }
- /**
- * Function for additional syntax of registering asset bundles
- *
- * ```
- * {{ register_asset_bundle('yii/web/JqueryAsset') }}
- * ```
- *
- * @param array $context context information
- * @param string $bundle asset bundle class fully qualified name
- * @param bool $return indicates if AssetBundle should be returned
- *
- * @return void|AssetBundle
- * @since 2.0.4
- */
- public function registerAssetBundle($context, $bundle, $return = false)
- {
- $bundle = str_replace('/', '\\', $bundle);
- $bundle = $this->call($bundle, 'register', [
- isset($context['this']) ? $context['this'] : null,
- ]);
- if ($return) {
- return $bundle;
- }
- }
- /**
- * Function for *_begin syntax support
- *
- * @param string $widget widget name
- * @param array $config widget config
- * @return mixed
- */
- public function beginWidget($widget, $config = [])
- {
- $widget = $this->resolveClassName($widget);
- $this->widgets[] = $widget;
- return $this->call($widget, 'begin', [
- $config,
- ]);
- }
- /**
- * Function for *_end syntax support
- *
- * @param string $widget widget name
- */
- public function endWidget($widget = null)
- {
- if ($widget === null) {
- if (empty($this->widgets)) {
- throw new InvalidCallException('Unexpected end_widget() call. A matching begin_widget() is not found.');
- }
- $this->call(array_pop($this->widgets), 'end');
- } else {
- array_pop($this->widgets);
- $this->resolveAndCall($widget, 'end');
- }
- }
- /**
- * Function for *_widget syntax support
- *
- * @param string $widget widget name
- * @param array $config widget config
- * @return mixed
- */
- public function widget($widget, $config = [])
- {
- return $this->resolveAndCall($widget, 'widget', [
- $config,
- ]);
- }
- /**
- * Used for 'begin_page', 'end_page', 'begin_body', 'end_body', 'head'
- *
- * @param array $context context information
- * @param string $name
- */
- public function viewHelper($context, $name = null)
- {
- if ($name !== null && isset($context['this'])) {
- $this->call($context['this'], Inflector::variablize($name));
- }
- }
- /**
- * Resolves a method from widget and asset syntax and calls it
- *
- * @param string $className class name
- * @param string $method method name
- * @param array $arguments
- * @return mixed
- */
- public function resolveAndCall($className, $method, $arguments = null)
- {
- return $this->call($this->resolveClassName($className), $method, $arguments);
- }
- /**
- * Calls a method
- *
- * @param string $className class name
- * @param string $method method name
- * @param array $arguments
- * @return mixed
- */
- public function call($className, $method, $arguments = null)
- {
- $callable = [$className, $method];
- if ($arguments === null) {
- return call_user_func($callable);
- } else {
- return call_user_func_array($callable, $arguments);
- }
- }
- /**
- * Resolves class name from widget and asset syntax
- *
- * @param string $className class name
- * @return string
- */
- public function resolveClassName($className)
- {
- $className = Inflector::id2camel($className, '_');
- if (isset($this->aliases[$className])) {
- return $this->aliases[$className];
- }
- foreach ($this->namespaces as $namespace) {
- $resolvedClassName = $namespace . '\\' . $className;
- if (class_exists($resolvedClassName)) {
- return $this->aliases[$className] = $resolvedClassName;
- }
- }
- return $className;
- }
- /**
- * Adds namespaces and aliases from constructor
- *
- * @param array $args namespaces and classes to use in the template
- */
- public function addUses($args)
- {
- foreach ((array)$args as $key => $value) {
- $value = str_replace('/', '\\', $value);
- if (is_int($key)) {
- // namespace or class import
- if (class_exists($value)) {
- // class import
- $this->aliases[StringHelper::basename($value)] = $value;
- } else {
- // namespace
- $this->namespaces[] = $value;
- }
- } else {
- // aliased class import
- $this->aliases[$key] = $value;
- }
- }
- }
- /**
- * Generates relative URL
- *
- * @param string $path the parameter to be used to generate a valid URL
- * @param array $args arguments
- * @return string the generated relative URL
- */
- public function path($path, $args = [])
- {
- if (is_array($path)) {
- $path = array_merge($path, $args);
- } elseif ($args !== []) {
- $path = array_merge([$path], $args);
- }
- return Url::to($path);
- }
- /**
- * Generates absolute URL
- *
- * @param string $path the parameter to be used to generate a valid URL
- * @param array $args arguments
- * @return string the generated absolute URL
- */
- public function url($path, $args = [])
- {
- if (is_array($path)) {
- $path = array_merge($path, $args);
- } elseif ($args !== []) {
- $path = array_merge([$path], $args);
- }
- return Url::to($path, true);
- }
- /**
- * Sets object property
- *
- * @param \stdClass $object
- * @param string $property
- * @param mixed $value
- */
- public function setProperty($object, $property, $value)
- {
- $object->$property = $value;
- }
- /**
- * @inheritdoc
- */
- public function getName()
- {
- return 'yii2-twig';
- }
- }
|