Skip to content

Commit ec0b763

Browse files
committed
Latte 3 support
- added support for both Latte versions - `^2.5` and `^3.0` - added Latte extension `Latte\AssetExtension` - added tests for latte filters - updated PHPStan configuration - updated README
1 parent 1e273bd commit ec0b763

File tree

6 files changed

+180
-33
lines changed

6 files changed

+180
-33
lines changed

README.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,13 @@ Configuration options are described in official [Symfony documentation](https://
4848
You can also use Filter/Helper equivalent. For example if you want to store result in variable:
4949

5050
```latte
51-
{var img = ('my/awesome/image.png')|asset}
52-
{var imgFoo = ('my/awesome/image.png', 'foo')|asset}
51+
{var $filename = 'my/awesome/image.png'}
5352
54-
{var version = ('my/awesome/image.png')|asset_version}
55-
{var versionFoo = ('my/awesome/image.png', 'foo')|asset_version}
53+
{$filename|asset}
54+
{$filename|asset: foo}
55+
56+
{$filename|asset_version}
57+
{$filename|asset_version: foo}
5658
```
5759

5860
## Contributing

composer.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
}
1111
],
1212
"require": {
13-
"php": "^7.4 | ^8.0",
14-
"latte/latte": "^2.5",
13+
"php": "^7.4 || ^8.0",
14+
"latte/latte": "^2.5 || ^3.0",
1515
"nette/di": "^3.0.10",
1616
"nette/utils": "^3.2.5",
17-
"symfony/asset": "^4.2 | ^5.0 | ^6.0"
17+
"symfony/asset": "^4.2 || ^5.0 || ^6.0"
1818
},
1919
"require-dev": {
2020
"friendsofphp/php-cs-fixer": "^3.13",

phpstan.neon

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
11
includes:
22
- vendor/phpstan/phpstan-nette/extension.neon
33
- vendor/phpstan/phpstan-nette/rules.neon
4+
5+
parameters:
6+
ignoreErrors:
7+
-
8+
message: '~If condition is always false\.~'
9+
path: src/DI/AssetExtension.php
10+
11+
excludePaths:
12+
analyse:
13+
- src/Latte/AssetMacroSet.php

src/DI/AssetExtension.php

+28-21
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy;
2222
use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface;
2323
use Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy;
24+
use SixtyEightPublishers\Asset\Latte\AssetExtension as AssetLatteExtension;
2425
use function assert;
2526
use function is_array;
2627
use function is_string;
@@ -109,27 +110,33 @@ public function beforeCompile(): void
109110
assert($latteFactory instanceof FactoryDefinition);
110111
$resultDefinition = $latteFactory->getResultDefinition();
111112

112-
# asset filters
113-
$resultDefinition->addSetup('addFilter', [
114-
'name' => 'asset',
115-
'callback' => [$this->prefix('@packages'), 'getUrl'],
116-
]);
117-
118-
$resultDefinition->addSetup('addFilter', [
119-
'name' => 'asset_version',
120-
'callback' => [$this->prefix('@packages'), 'getVersion'],
121-
]);
122-
123-
# asset macros
124-
$resultDefinition->addSetup('addProvider', [
125-
'name' => 'symfonyPackages',
126-
'value' => $this->prefix('@packages'),
127-
]);
128-
129-
$resultDefinition->addSetup('?->onCompile[] = function ($engine) { ?::install($engine->getCompiler()); }', [
130-
'@self',
131-
new PhpLiteral(AssetMacroSet::class),
132-
]);
113+
if (version_compare(Engine::VERSION, '3', '<')) {
114+
# asset filters
115+
$resultDefinition->addSetup('addFilter', [
116+
'name' => 'asset',
117+
'callback' => [$this->prefix('@packages'), 'getUrl'],
118+
]);
119+
120+
$resultDefinition->addSetup('addFilter', [
121+
'name' => 'asset_version',
122+
'callback' => [$this->prefix('@packages'), 'getVersion'],
123+
]);
124+
125+
# asset macros
126+
$resultDefinition->addSetup('addProvider', [
127+
'name' => 'symfonyPackages',
128+
'value' => $this->prefix('@packages'),
129+
]);
130+
131+
$resultDefinition->addSetup('?->onCompile[] = function ($engine) { ?::install($engine->getCompiler()); }', [
132+
'@self',
133+
new PhpLiteral(AssetMacroSet::class),
134+
]);
135+
} else {
136+
$resultDefinition->addSetup('addExtension', [
137+
new Statement(AssetLatteExtension::class),
138+
]);
139+
}
133140
}
134141

135142
private function createVersionStrategy(string $packageName, PackageConfig $config, ?ServiceDefinition $default = NULL): ServiceDefinition

src/Latte/AssetExtension.php

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SixtyEightPublishers\Asset\Latte;
6+
7+
use Latte\Extension;
8+
use Latte\Compiler\Tag;
9+
use Latte\Compiler\Node;
10+
use Latte\Compiler\PrintContext;
11+
use Symfony\Component\Asset\Packages;
12+
use Latte\Compiler\Nodes\AuxiliaryNode;
13+
14+
final class AssetExtension extends Extension
15+
{
16+
private Packages $packages;
17+
18+
public function __construct(Packages $packages)
19+
{
20+
$this->packages = $packages;
21+
}
22+
23+
/**
24+
* @return array{asset: callable, asset_version: callable}
25+
*/
26+
public function getTags(): array
27+
{
28+
return [
29+
'asset' => [$this, 'createAsset'],
30+
'asset_version' => [$this, 'createAssetVersion'],
31+
];
32+
}
33+
34+
/**
35+
* @return array{asset: callable, asset_version: callable}
36+
*/
37+
public function getFilters(): array
38+
{
39+
return [
40+
'asset' => [$this->packages, 'getUrl'],
41+
'asset_version' => [$this->packages, 'getVersion'],
42+
];
43+
}
44+
45+
/**
46+
* @return array{symfonyPackages: Packages}
47+
*/
48+
public function getProviders(): array
49+
{
50+
return [
51+
'symfonyPackages' => $this->packages,
52+
];
53+
}
54+
55+
public function createAsset(Tag $tag): Node
56+
{
57+
$args = [];
58+
$path = $tag->parser->parseUnquotedStringOrExpression();
59+
60+
if (!$tag->parser->isEnd()) {
61+
$tag->parser->stream->tryConsume(',');
62+
$args = [$tag->parser->parseExpression()];
63+
}
64+
65+
return new AuxiliaryNode(
66+
fn (PrintContext $context) => $context->format(
67+
'echo %escape($this->global->symfonyPackages->getUrl(%node, %args));',
68+
$path,
69+
$args
70+
)
71+
);
72+
}
73+
74+
public function createAssetVersion(Tag $tag): Node
75+
{
76+
$args = [];
77+
$path = $tag->parser->parseUnquotedStringOrExpression();
78+
79+
if (!$tag->parser->isEnd()) {
80+
$tag->parser->stream->tryConsume(',');
81+
$args = [$tag->parser->parseExpression()];
82+
}
83+
84+
return new AuxiliaryNode(
85+
fn (PrintContext $context) => $context->format(
86+
'echo %escape($this->global->symfonyPackages->getVersion(%node, %args));',
87+
$path,
88+
$args
89+
)
90+
);
91+
}
92+
}

tests/Latte/AssetMacroSetTest.phpt renamed to tests/Latte/AssetMacrosAndFiltersTest.phpt

+41-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use function assert;
1414

1515
require __DIR__ . '/../bootstrap.php';
1616

17-
final class AssetMacroSetTest extends TestCase
17+
final class AssetMacrosAndFiltersTest extends TestCase
1818
{
1919
private Engine $engine;
2020

@@ -32,21 +32,57 @@ final class AssetMacroSetTest extends TestCase
3232

3333
public function testAssetMacro(): void
3434
{
35-
$this->assertMacros([
35+
$this->assertLatte([
3636
['{asset "my/file.json"}', 'https://cdn.example.com/my/file.json?version=2.1'],
3737
['{asset "my/nested/file.json", "json_manifest_strategy"}', '/my/nested/file.abc123.json'],
3838
]);
3939
}
4040

4141
public function testAssetVersionMacro(): void
4242
{
43-
$this->assertMacros([
43+
$this->assertLatte([
4444
['{asset_version "my/file.json"}', '2.1'],
4545
['{asset_version "my/nested/file.json", "json_manifest_strategy"}', '/my/nested/file.abc123.json'],
4646
]);
4747
}
4848

49-
private function assertMacros(array $data): void
49+
public function testAssetFilter(): void
50+
{
51+
$defaultPackage = <<< LATTE
52+
{var \$file = "my/file.json"}
53+
{\$file|asset}
54+
LATTE;
55+
56+
$nestedPackage = <<< LATTE
57+
{var \$file = "my/nested/file.json"}
58+
{\$file|asset: json_manifest_strategy}
59+
LATTE;
60+
61+
$this->assertLatte([
62+
[$defaultPackage, 'https://cdn.example.com/my/file.json?version=2.1'],
63+
[$nestedPackage, '/my/nested/file.abc123.json'],
64+
]);
65+
}
66+
67+
public function testAssetVersionFilter(): void
68+
{
69+
$defaultPackage = <<< LATTE
70+
{var \$file = "my/file.json"}
71+
{\$file|asset_version}
72+
LATTE;
73+
74+
$nestedPackage = <<< LATTE
75+
{var \$file = "my/nested/file.json"}
76+
{\$file|asset_version: json_manifest_strategy}
77+
LATTE;
78+
79+
$this->assertLatte([
80+
[$defaultPackage, '2.1'],
81+
[$nestedPackage, '/my/nested/file.abc123.json'],
82+
]);
83+
}
84+
85+
private function assertLatte(array $data): void
5086
{
5187
foreach ($data as [$latteCode, $expectedOutput]) {
5288
$output = $this->engine->renderToString($latteCode);
@@ -56,4 +92,4 @@ final class AssetMacroSetTest extends TestCase
5692
}
5793
}
5894

59-
(new AssetMacroSetTest())->run();
95+
(new AssetMacrosAndFiltersTest())->run();

0 commit comments

Comments
 (0)