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 14/** 15 * @author Fabien Potencier <fabien@symfony.com> 16 */ 17abstract class AbstractTwigCallable implements TwigCallableInterface 18{ 19 protected $options; 20 21 private $name; 22 private $dynamicName; 23 private $callable; 24 private $arguments; 25 26 public function __construct(string $name, $callable = null, array $options = []) 27 { 28 $this->name = $this->dynamicName = $name; 29 $this->callable = $callable; 30 $this->arguments = []; 31 $this->options = array_merge([ 32 'needs_environment' => false, 33 'needs_context' => false, 34 'needs_charset' => false, 35 'needs_is_sandboxed' => false, 36 'is_variadic' => false, 37 'deprecation_info' => null, 38 'deprecated' => false, 39 'deprecating_package' => '', 40 'alternative' => null, 41 ], $options); 42 43 if ($this->options['deprecation_info'] && !$this->options['deprecation_info'] instanceof DeprecatedCallableInfo) { 44 throw new \LogicException(\sprintf('The "deprecation_info" option must be an instance of "%s".', DeprecatedCallableInfo::class)); 45 } 46 47 if ($this->options['deprecated']) { 48 if ($this->options['deprecation_info']) { 49 throw new \LogicException('When setting the "deprecation_info" option, you need to remove the obsolete deprecated options.'); 50 } 51 52 trigger_deprecation('twig/twig', '3.15', 'Using the "deprecated", "deprecating_package", and "alternative" options is deprecated, pass a "deprecation_info" one instead.'); 53 54 $this->options['deprecation_info'] = new DeprecatedCallableInfo( 55 $this->options['deprecating_package'], 56 $this->options['deprecated'], 57 null, 58 $this->options['alternative'], 59 ); 60 } 61 62 if ($this->options['deprecation_info']) { 63 $this->options['deprecation_info']->setName($name); 64 $this->options['deprecation_info']->setType($this->getType()); 65 } 66 } 67 68 public function __toString(): string 69 { 70 return \sprintf('%s(%s)', static::class, $this->name); 71 } 72 73 public function getName(): string 74 { 75 return $this->name; 76 } 77 78 public function getDynamicName(): string 79 { 80 return $this->dynamicName; 81 } 82 83 /** 84 * @return callable|array{class-string, string}|null 85 */ 86 public function getCallable() 87 { 88 return $this->callable; 89 } 90 91 public function getNodeClass(): string 92 { 93 return $this->options['node_class']; 94 } 95 96 public function needsCharset(): bool 97 { 98 return $this->options['needs_charset']; 99 } 100 101 public function needsEnvironment(): bool 102 { 103 return $this->options['needs_environment']; 104 } 105 106 public function needsContext(): bool 107 { 108 return $this->options['needs_context']; 109 } 110 111 public function needsIsSandboxed(): bool 112 { 113 return $this->options['needs_is_sandboxed']; 114 } 115 116 /** 117 * @return static 118 */ 119 public function withDynamicArguments(string $name, string $dynamicName, array $arguments): self 120 { 121 $new = clone $this; 122 $new->name = $name; 123 $new->dynamicName = $dynamicName; 124 $new->arguments = $arguments; 125 126 return $new; 127 } 128 129 /** 130 * @deprecated since Twig 3.12, use withDynamicArguments() instead 131 */ 132 public function setArguments(array $arguments): void 133 { 134 trigger_deprecation('twig/twig', '3.12', 'The "%s::setArguments()" method is deprecated, use "%s::withDynamicArguments()" instead.', static::class, static::class); 135 136 $this->arguments = $arguments; 137 } 138 139 public function getArguments(): array 140 { 141 return $this->arguments; 142 } 143 144 public function isVariadic(): bool 145 { 146 return $this->options['is_variadic']; 147 } 148 149 public function isDeprecated(): bool 150 { 151 return (bool) $this->options['deprecation_info']; 152 } 153 154 public function triggerDeprecation(?string $file = null, ?int $line = null): void 155 { 156 $this->options['deprecation_info']->triggerDeprecation($file, $line); 157 } 158 159 /** 160 * @deprecated since Twig 3.15 161 */ 162 public function getDeprecatingPackage(): string 163 { 164 trigger_deprecation('twig/twig', '3.15', 'The "%s" method is deprecated, use "%s::triggerDeprecation()" instead.', __METHOD__, static::class); 165 166 return $this->options['deprecating_package']; 167 } 168 169 /** 170 * @deprecated since Twig 3.15 171 */ 172 public function getDeprecatedVersion(): string 173 { 174 trigger_deprecation('twig/twig', '3.15', 'The "%s" method is deprecated, use "%s::triggerDeprecation()" instead.', __METHOD__, static::class); 175 176 return \is_bool($this->options['deprecated']) ? '' : $this->options['deprecated']; 177 } 178 179 /** 180 * @deprecated since Twig 3.15 181 */ 182 public function getAlternative(): ?string 183 { 184 trigger_deprecation('twig/twig', '3.15', 'The "%s" method is deprecated, use "%s::triggerDeprecation()" instead.', __METHOD__, static::class); 185 186 return $this->options['alternative']; 187 } 188 189 public function getMinimalNumberOfRequiredArguments(): int 190 { 191 return ($this->options['needs_charset'] ? 1 : 0) + ($this->options['needs_environment'] ? 1 : 0) + ($this->options['needs_context'] ? 1 : 0) + ($this->options['needs_is_sandboxed'] ? 1 : 0) + \count($this->arguments); 192 } 193} 194