1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Twig;
13
14use Twig\Node\Expression\FunctionExpression;
15use Twig\Node\Node;
16
17/**
18 * Represents a template function.
19 *
20 * @final
21 *
22 * @author Fabien Potencier <fabien@symfony.com>
23 *
24 * @see https://twig.symfony.com/doc/templates.html#functions
25 */
26class TwigFunction
27{
28    private $name;
29    private $callable;
30    private $options;
31    private $arguments = [];
32
33    /**
34     * Creates a template function.
35     *
36     * @param string        $name     Name of this function
37     * @param callable|null $callable A callable implementing the function. If null, you need to overwrite the "node_class" option to customize compilation.
38     * @param array         $options  Options array
39     */
40    public function __construct(string $name, $callable = null, array $options = [])
41    {
42        if (__CLASS__ !== static::class) {
43            @trigger_error('Overriding '.__CLASS__.' is deprecated since Twig 2.4.0 and the class will be final in 3.0.', \E_USER_DEPRECATED);
44        }
45
46        $this->name = $name;
47        $this->callable = $callable;
48        $this->options = array_merge([
49            'needs_environment' => false,
50            'needs_context' => false,
51            'is_variadic' => false,
52            'is_safe' => null,
53            'is_safe_callback' => null,
54            'node_class' => FunctionExpression::class,
55            'deprecated' => false,
56            'alternative' => null,
57        ], $options);
58    }
59
60    public function getName()
61    {
62        return $this->name;
63    }
64
65    /**
66     * Returns the callable to execute for this function.
67     *
68     * @return callable|null
69     */
70    public function getCallable()
71    {
72        return $this->callable;
73    }
74
75    public function getNodeClass()
76    {
77        return $this->options['node_class'];
78    }
79
80    public function setArguments($arguments)
81    {
82        $this->arguments = $arguments;
83    }
84
85    public function getArguments()
86    {
87        return $this->arguments;
88    }
89
90    public function needsEnvironment()
91    {
92        return $this->options['needs_environment'];
93    }
94
95    public function needsContext()
96    {
97        return $this->options['needs_context'];
98    }
99
100    public function getSafe(Node $functionArgs)
101    {
102        if (null !== $this->options['is_safe']) {
103            return $this->options['is_safe'];
104        }
105
106        if (null !== $this->options['is_safe_callback']) {
107            return $this->options['is_safe_callback']($functionArgs);
108        }
109
110        return [];
111    }
112
113    public function isVariadic()
114    {
115        return $this->options['is_variadic'];
116    }
117
118    public function isDeprecated()
119    {
120        return (bool) $this->options['deprecated'];
121    }
122
123    public function getDeprecatedVersion()
124    {
125        return $this->options['deprecated'];
126    }
127
128    public function getAlternative()
129    {
130        return $this->options['alternative'];
131    }
132}
133
134// For Twig 1.x compatibility
135class_alias('Twig\TwigFunction', 'Twig_SimpleFunction', false);
136
137class_alias('Twig\TwigFunction', 'Twig_Function');
138
139// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name.
140class_exists('Twig\Node\Node');
141