Skip to content

Commit 0d30cda

Browse files
committed
Init Twig Extra component
1 parent 39a6c2d commit 0d30cda

17 files changed

+578
-2
lines changed

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
},
4747
"autoload": {
4848
"psr-4": {
49+
"Sylius\\TwigExtra\\": "src/TwigExtra/src/",
4950
"Sylius\\TwigHooks\\": "src/TwigHooks/src/"
5051
}
5152
},

config/bundles.php

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
66
Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true],
77
Sylius\TwigHooks\TwigHooksBundle::class => ['all' => true],
8+
Sylius\TwigExtra\Symfony\TwigExtraBundle::class => ['all' => true],
89
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
910
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
1011
Symfony\UX\LiveComponent\LiveComponentBundle::class => ['all' => true],

phpunit.xml.dist

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818
</php>
1919

2020
<testsuites>
21+
<testsuite name="TwigExtra Test Suite">
22+
<directory>src/TwigExtra/tests</directory>
23+
</testsuite>
24+
2125
<testsuite name="TwigHooks Test Suite">
2226
<directory>src/TwigHooks/tests</directory>
23-
2427
</testsuite>
2528
</testsuites>
2629

src/TwigExtra/composer.json

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "sylius/twig-extra",
3+
"type": "library",
4+
"license": "MIT",
5+
"authors": [
6+
{
7+
"name": "Sylius project",
8+
"homepage": "https://sylius.com"
9+
},
10+
{
11+
"name": "Community contributions",
12+
"homepage": "https://github.com/Sylius/Stack/contributors"
13+
}
14+
],
15+
"require": {
16+
"php": "^8.1",
17+
"symfony/http-kernel": "^6.4",
18+
"symfony/twig-bundle": "^6.4"
19+
},
20+
"conflict": {
21+
"sylius/ui-bundle": "<2.0"
22+
},
23+
"autoload": {
24+
"psr-4": {
25+
"Sylius\\TwigExtra\\": "src/"
26+
}
27+
},
28+
"autoload-dev": {
29+
"psr-4": {
30+
"Tests\\Sylius\\TwigExtra\\": "tests/"
31+
}
32+
}
33+
}

src/TwigExtra/config/services.php

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
6+
7+
use Sylius\TwigExtra\Twig\SortByExtension;
8+
use Sylius\TwigExtra\Twig\TestFormAttributeExtension;
9+
use Sylius\TwigExtra\Twig\TestHtmlAttributeExtension;
10+
11+
return function (ContainerConfigurator $configurator): void {
12+
$services = $configurator->services();
13+
14+
$services->set('twig_extra.twig.extension.test_form_attribute', TestFormAttributeExtension::class)
15+
->args([
16+
param('kernel.environment'),
17+
param('kernel.debug'),
18+
])
19+
->tag(name: 'twig.extension')
20+
;
21+
22+
$services->set('twig_extra.twig.extension.test_html_attribute', TestHtmlAttributeExtension::class)
23+
->args([
24+
param('kernel.environment'),
25+
param('kernel.debug'),
26+
])
27+
->tag(name: 'twig.extension')
28+
;
29+
30+
$services->set('twig_extra.twig.extension.sort_by', SortByExtension::class)
31+
->tag(name: 'twig.extension')
32+
;
33+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sylius\TwigExtra\Symfony\DependencyInjection;
6+
7+
use Symfony\Component\Config\FileLocator;
8+
use Symfony\Component\DependencyInjection\ContainerBuilder;
9+
use Symfony\Component\DependencyInjection\Extension\Extension;
10+
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
11+
12+
final class TwigExtraExtension extends Extension
13+
{
14+
public function load(array $configs, ContainerBuilder $container): void
15+
{
16+
$loader = new PhpFileLoader(
17+
$container,
18+
new FileLocator(dirname(__DIR__, 3) . '/config'),
19+
);
20+
21+
$loader->load('services.php');
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sylius\TwigExtra\Symfony;
6+
7+
use Symfony\Component\HttpKernel\Bundle\Bundle;
8+
9+
final class TwigExtraBundle extends Bundle
10+
{
11+
}
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sylius\TwigExtra\Twig;
6+
7+
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
8+
use Symfony\Component\PropertyAccess\PropertyAccess;
9+
use Twig\Extension\AbstractExtension;
10+
use Twig\TwigFilter;
11+
12+
class SortByExtension extends AbstractExtension
13+
{
14+
public function getFilters(): array
15+
{
16+
return [
17+
new TwigFilter('sort_by', [$this, 'sortBy']),
18+
];
19+
}
20+
21+
/**
22+
* @throws NoSuchPropertyException
23+
*/
24+
public function sortBy(iterable $iterable, string $field, string $order = 'ASC'): array
25+
{
26+
$array = $this->transformIterableToArray($iterable);
27+
28+
usort(
29+
$array,
30+
function (array|object $firstElement, array|object $secondElement) use ($field, $order) {
31+
$accessor = PropertyAccess::createPropertyAccessor();
32+
33+
$firstProperty = (string) $accessor->getValue($firstElement, $field);
34+
$secondProperty = (string) $accessor->getValue($secondElement, $field);
35+
36+
$result = strnatcasecmp($firstProperty, $secondProperty);
37+
if ('DESC' === $order) {
38+
$result *= -1;
39+
}
40+
41+
return $result;
42+
},
43+
);
44+
45+
return $array;
46+
}
47+
48+
private function transformIterableToArray(iterable $iterable): array
49+
{
50+
if (is_array($iterable)) {
51+
return $iterable;
52+
}
53+
54+
return iterator_to_array($iterable);
55+
}
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sylius\TwigExtra\Twig;
6+
7+
use Twig\Extension\AbstractExtension;
8+
use Twig\TwigFunction;
9+
10+
final class TestFormAttributeExtension extends AbstractExtension
11+
{
12+
public function __construct(private string $environment)
13+
{
14+
}
15+
16+
/**
17+
* @return TwigFunction[]
18+
*/
19+
public function getFunctions(): array
20+
{
21+
return [
22+
new TwigFunction(
23+
'sylius_test_form_attribute',
24+
function (string $name, ?string $value = null): array {
25+
if (str_starts_with($this->environment, 'test')) {
26+
return ['attr' => ['data-test-' . $name => (string) $value]];
27+
}
28+
29+
return [];
30+
},
31+
['is_safe' => ['html']],
32+
),
33+
];
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sylius\TwigExtra\Twig;
6+
7+
use Twig\Extension\AbstractExtension;
8+
use Twig\TwigFunction;
9+
10+
final class TestHtmlAttributeExtension extends AbstractExtension
11+
{
12+
public function __construct(private readonly string $environment, private readonly bool $isDebugEnabled)
13+
{
14+
}
15+
16+
/**
17+
* @return TwigFunction[]
18+
*/
19+
public function getFunctions(): array
20+
{
21+
return [
22+
new TwigFunction(
23+
'sylius_test_html_attribute',
24+
function (string $name, ?string $value = null): string {
25+
if (str_starts_with($this->environment, 'test') || $this->isDebugEnabled) {
26+
return sprintf('data-test-%s="%s"', $name, (string) $value);
27+
}
28+
29+
return '';
30+
},
31+
['is_safe' => ['html']],
32+
),
33+
];
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Sylius\TwigExtra\Functional\Twig\Extension;
6+
7+
use Sylius\TwigExtra\Twig\SortByExtension;
8+
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
9+
10+
final class SortByExtensionTest extends KernelTestCase
11+
{
12+
public function testTheContainerContainsTheService(): void
13+
{
14+
$this->bootKernel();
15+
16+
$container = $this->getContainer();
17+
18+
$this->assertTrue($container->has('twig_extra.twig.extension.sort_by'));
19+
$this->assertInstanceOf(SortByExtension::class, $container->get('twig_extra.twig.extension.sort_by'));
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Sylius\TwigExtra\Functional\Twig\Extension;
6+
7+
use Sylius\TwigExtra\Twig\TestFormAttributeExtension;
8+
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
9+
10+
final class TestFormAttributeExtensionTest extends KernelTestCase
11+
{
12+
public function testTheContainerContainsTheService(): void
13+
{
14+
$this->bootKernel();
15+
16+
$container = $this->getContainer();
17+
18+
$this->assertTrue($container->has('twig_extra.twig.extension.test_form_attribute'));
19+
$this->assertInstanceOf(TestFormAttributeExtension::class, $container->get('twig_extra.twig.extension.test_form_attribute'));
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Sylius\TwigExtra\Functional\Twig\Extension;
6+
7+
use Sylius\TwigExtra\Twig\TestHtmlAttributeExtension;
8+
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
9+
10+
final class TestHtmlAttributeExtensionTest extends KernelTestCase
11+
{
12+
public function testTheContainerContainsTheService(): void
13+
{
14+
$this->bootKernel();
15+
16+
$container = $this->getContainer();
17+
18+
$this->assertTrue($container->has('twig_extra.twig.extension.test_html_attribute'));
19+
$this->assertInstanceOf(TestHtmlAttributeExtension::class, $container->get('twig_extra.twig.extension.test_html_attribute'));
20+
}
21+
}

0 commit comments

Comments
 (0)