Skip to content

Commit

Permalink
Accept a class name to leverage runtime lazy-loading
Browse files Browse the repository at this point in the history
  • Loading branch information
GromNaN committed Nov 26, 2023
1 parent 50f7c1f commit d4a3560
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 13 deletions.
20 changes: 12 additions & 8 deletions src/Extension/AttributeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ final class AttributeExtension extends AbstractExtension

public function __construct(
/**
* @var iterable<object>
* A list of objects or class names defining filters, functions, and tests using the new PHP attributes.
* When passing a class name, it must be available as runtime extension.
*
* @var iterable<object|class-string>
*/
private iterable $objects,
) {
Expand Down Expand Up @@ -69,11 +72,12 @@ private function initFromAttributes()
{
$filters = $functions = $tests = [];

foreach ($this->objects as $object) {
if (!\is_object($object)) {
throw new \LogicException(sprintf('"%s" class requires a list of objects, "%s" given.', __CLASS__, get_debug_type($object)));
foreach ($this->objects as $objectOrClass) {
try {
$reflectionClass = new \ReflectionClass($objectOrClass);
} catch (\ReflectionException $e) {
throw new \LogicException(sprintf('"%s" class requires a list of objects or class name, "%s" given.', __CLASS__, get_debug_type($objectOrClass)), 0, $e);
}
$reflectionClass = new \ReflectionClass($object);

foreach ($reflectionClass->getMethods() as $method) {
// Filters
Expand All @@ -92,7 +96,7 @@ private function initFromAttributes()
$firstParam += $needsContext ? 1 : 0;
$isVariadic = isset($parameters[$firstParam]) && $parameters[$firstParam]->isVariadic();

$filters[$name] = new TwigFilter($name, [$object, $method->getName()], [
$filters[$name] = new TwigFilter($name, [$objectOrClass, $method->getName()], [
'needs_environment' => $needsEnvironment,
'needs_context' => $needsContext,
'is_variadic' => $isVariadic,
Expand Down Expand Up @@ -121,7 +125,7 @@ private function initFromAttributes()
$firstParam += $needsContext ? 1 : 0;
$isVariadic = isset($parameters[$firstParam]) && $parameters[$firstParam]->isVariadic();

$functions[$name] = new TwigFunction($name, [$object, $method->getName()], [
$functions[$name] = new TwigFunction($name, [$objectOrClass, $method->getName()], [
'needs_environment' => $needsEnvironment,
'needs_context' => $needsContext,
'is_variadic' => $isVariadic,
Expand All @@ -144,7 +148,7 @@ private function initFromAttributes()
$parameters = $method->getParameters();
$isVariadic = isset($parameters[0]) && $parameters[0]->isVariadic();

$tests[$name] = new TwigTest($name, [$object, $method->getName()], [
$tests[$name] = new TwigTest($name, [$objectOrClass, $method->getName()], [
'is_variadic' => $isVariadic,
'deprecated' => $attribute->deprecated,
'alternative' => $attribute->alternative,
Expand Down
18 changes: 14 additions & 4 deletions tests/Extension/AttributeExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use PHPUnit\Framework\TestCase;
use Twig\Extension\AttributeExtension;
use Twig\Tests\Extension\Fixtures\ObjectWithAttributes;
use Twig\Tests\Extension\Fixtures\ExtensionWithAttributes;
use Twig\TwigFilter;
use Twig\TwigFunction;
use Twig\TwigTest;
Expand All @@ -19,7 +19,7 @@ class AttributeExtensionTest extends TestCase
*/
public function testFilter(string $name, string $method, array $options)
{
$object = new ObjectWithAttributes();
$object = new ExtensionWithAttributes();
$extension = new AttributeExtension([$object]);
foreach ($extension->getFilters() as $filter) {
if ($filter->getName() === $name) {
Expand Down Expand Up @@ -48,7 +48,7 @@ public static function provideFilters()
*/
public function testFunction(string $name, string $method, array $options)
{
$object = new ObjectWithAttributes();
$object = new ExtensionWithAttributes();
$extension = new AttributeExtension([$object]);
foreach ($extension->getFunctions() as $function) {
if ($function->getName() === $name) {
Expand Down Expand Up @@ -77,7 +77,7 @@ public static function provideFunctions()
*/
public function testTest(string $name, string $method, array $options)
{
$object = new ObjectWithAttributes();
$object = new ExtensionWithAttributes();
$extension = new AttributeExtension([$object]);
foreach ($extension->getTests() as $test) {
if ($test->getName() === $name) {
Expand All @@ -97,4 +97,14 @@ public static function provideTests()
yield 'variadic' => ['variadicTest', 'variadicTest', ['is_variadic' => true]];
yield 'deprecated' => ['deprecatedTest', 'deprecatedTest', ['deprecated' => true, 'alternative' => 'bar']];
}

public function testRuntimeExtension()
{
$class = ExtensionWithAttributes::class;
$extension = new AttributeExtension([$class]);

$this->assertSame([$class, 'fooFilter'], $extension->getFilters()['foo']->getCallable());
$this->assertSame([$class, 'fooFunction'], $extension->getFunctions()['foo']->getCallable());
$this->assertSame([$class, 'fooTest'], $extension->getTests()['foo']->getCallable());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
use Twig\Extension\Attribute\AsTwigFilter;
use Twig\Extension\Attribute\AsTwigFunction;
use Twig\Extension\Attribute\AsTwigTest;
use Twig\Extension\RuntimeExtensionInterface;

class ObjectWithAttributes
class ExtensionWithAttributes implements RuntimeExtensionInterface
{
#[AsTwigFilter]
#[AsTwigFilter(name: 'foo')]
Expand Down
2 changes: 2 additions & 0 deletions tests/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

use Twig\Extension\AbstractExtension;
use Twig\Extension\AttributeExtension;
use Twig\Extension\DebugExtension;
use Twig\Extension\SandboxExtension;
use Twig\Extension\StringLoaderExtension;
Expand Down Expand Up @@ -44,6 +45,7 @@ public function getExtensions()
new SandboxExtension($policy, false),
new StringLoaderExtension(),
new TwigTestExtension(),
new AttributeExtension(new \ArrayIterator(['']))
];
}

Expand Down

0 comments on commit d4a3560

Please sign in to comment.