1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace SixtyEightPublishers\WebpackEncoreBundle\DI; |
6
|
|
|
|
7
|
|
|
use Latte; |
8
|
|
|
use Nette; |
9
|
|
|
use Symfony; |
10
|
|
|
use RuntimeException; |
11
|
|
|
use SixtyEightPublishers; |
12
|
|
|
|
13
|
|
|
final class WebpackEncoreBundleExtension extends Nette\DI\CompilerExtension |
14
|
|
|
{ |
15
|
|
|
private const ENTRYPOINTS_FILE_NAME = 'entrypoints.json'; |
16
|
|
|
|
17
|
|
|
private const ENTRYPOINT_DEFAULT_NAME = '_default'; |
18
|
|
|
|
19
|
|
|
private const CROSSORIGIN_ALLOWED_VALUES = [NULL, 'anonymous', 'use-credentials']; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* {@inheritdoc} |
23
|
|
|
*/ |
24
|
|
|
public function getConfigSchema(): Nette\Schema\Schema |
25
|
|
|
{ |
26
|
|
|
return Nette\Schema\Expect::structure([ |
27
|
|
|
'output_path' => Nette\Schema\Expect::string()->nullable(), # The path where Encore is building the assets - i.e. Encore.setOutputPath() |
28
|
|
|
'builds' => Nette\Schema\Expect::array()->items('string')->assert(function (array $value): bool { |
29
|
|
|
if (isset($value[self::ENTRYPOINT_DEFAULT_NAME])) { |
30
|
|
|
throw new Nette\Utils\AssertionException(sprintf('Key "%s" can\'t be used as build name.', self::ENTRYPOINT_DEFAULT_NAME)); |
31
|
|
|
} |
32
|
|
|
|
33
|
|
|
return TRUE; |
34
|
|
|
}), |
35
|
|
|
'crossorigin' => Nette\Schema\Expect::string()->nullable()->assert(function (?string $value): bool { |
36
|
|
|
if (!in_array($value, self::CROSSORIGIN_ALLOWED_VALUES, TRUE)) { |
37
|
|
|
throw new Nette\Utils\AssertionException(sprintf('Value "%s" for setting "crossorigin" is not allowed', $value)); |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
return TRUE; |
41
|
|
|
}), # crossorigin value when Encore.enableIntegrityHashes() is used, can be NULL (default), anonymous or use-credentials |
42
|
1 |
|
'cache' => Nette\Schema\Expect::structure([ |
43
|
1 |
|
'enabled' => Nette\Schema\Expect::bool(FALSE), |
44
|
1 |
|
'storage' => Nette\Schema\Expect::string('@' . Nette\Caching\IStorage::class)->dynamic(), |
45
|
1 |
|
]), |
46
|
|
|
'latte' => Nette\Schema\Expect::structure([ |
47
|
1 |
|
'js_assets_macro_name' => Nette\Schema\Expect::string('encore_js'), |
48
|
1 |
|
'css_assets_macro_name' => Nette\Schema\Expect::string('encore_css'), |
49
|
|
|
]), |
50
|
|
|
]); |
51
|
1 |
|
} |
52
|
1 |
|
|
53
|
|
|
/** |
54
|
|
|
* {@inheritdoc} |
55
|
1 |
|
*/ |
56
|
1 |
|
public function loadConfiguration(): void |
57
|
1 |
|
{ |
58
|
1 |
|
$builder = $this->getContainerBuilder(); |
59
|
1 |
|
$cache = $this->registerCache($this->getConfig()->cache->enabled, $this->getConfig()->cache->storage); |
60
|
|
|
$lookups = []; |
61
|
|
|
|
62
|
1 |
|
if (NULL !== $this->getConfig()->output_path) { |
63
|
|
|
$lookups[] = $this->createEntryPointLookupStatement(self::ENTRYPOINT_DEFAULT_NAME, $this->getConfig()->output_path, $cache); |
64
|
1 |
|
} |
65
|
|
|
|
66
|
|
|
foreach ($this->getConfig()->builds as $name => $path) { |
67
|
|
|
$lookups[] = $this->createEntryPointLookupStatement($name, $path, $cache); |
68
|
1 |
|
} |
69
|
1 |
|
|
70
|
1 |
|
$builder->addDefinition($this->prefix('entryPointLookupProvider')) |
71
|
1 |
|
->setType(SixtyEightPublishers\WebpackEncoreBundle\EntryPoint\IEntryPointLookupProvider::class) |
72
|
1 |
|
->setFactory(SixtyEightPublishers\WebpackEncoreBundle\EntryPoint\EntryPointLookupProvider::class, [ |
73
|
|
|
'lookups' => $lookups, |
74
|
1 |
|
'defaultName' => NULL !== $this->getConfig()->output_path ? self::ENTRYPOINT_DEFAULT_NAME : NULL, |
75
|
|
|
]); |
76
|
|
|
|
77
|
|
|
$defaultAttributes = []; |
78
|
|
|
|
79
|
|
|
if (NULL !== $this->getConfig()->crossorigin) { |
80
|
|
|
$defaultAttributes['crossorigin'] = $this->getConfig()->crossorigin; |
81
|
|
|
} |
82
|
|
|
|
83
|
1 |
|
$builder->addDefinition($this->prefix('tagRenderer')) |
84
|
1 |
|
->setType(SixtyEightPublishers\WebpackEncoreBundle\Latte\TagRenderer::class) |
85
|
|
|
->setAutowired(FALSE) |
86
|
1 |
|
->setArguments([ |
87
|
|
|
'defaultAttributes' => $defaultAttributes, |
88
|
|
|
]); |
89
|
|
|
} |
90
|
1 |
|
|
91
|
|
|
/** |
92
|
1 |
|
* {@inheritdoc} |
93
|
1 |
|
*/ |
94
|
1 |
|
public function beforeCompile(): void |
95
|
|
|
{ |
96
|
|
|
$builder = $this->getContainerBuilder(); |
97
|
1 |
|
|
98
|
1 |
|
if (NULL === $builder->getByType(Symfony\Component\Asset\Packages::class, FALSE)) { |
99
|
1 |
|
throw new RuntimeException('Missing service of type Symfony\Component\Asset\Packages that is required by this package. You can configure and register it manually or you can use package 68publishers/asset (recommended way).'); |
100
|
1 |
|
} |
101
|
1 |
|
|
102
|
|
|
$latteFactory = $builder->getDefinition($builder->getByType(Latte\Engine::class) ?? 'nette.latteFactory'); |
103
|
1 |
|
|
104
|
|
|
$latteFactory->getResultDefinition()->addSetup('addProvider', [ |
|
|
|
|
105
|
|
|
'name' => 'webpackEncoreTagRenderer', |
106
|
|
|
'value' => $this->prefix('@tagRenderer'), |
107
|
|
|
]); |
108
|
|
|
|
109
|
|
|
$latteFactory->getResultDefinition()->addSetup('?->onCompile[] = function ($engine) { ?::install(?, ?, $engine->getCompiler()); }', [ |
|
|
|
|
110
|
|
|
'@self', |
111
|
|
|
new Nette\PhpGenerator\PhpLiteral(SixtyEightPublishers\WebpackEncoreBundle\Latte\WebpackEncoreMacros::class), |
112
|
1 |
|
$this->getConfig()->latte->js_assets_macro_name, |
113
|
|
|
$this->getConfig()->latte->css_assets_macro_name, |
114
|
1 |
|
]); |
115
|
1 |
|
} |
116
|
1 |
|
|
117
|
1 |
|
/** |
118
|
|
|
* @param string $name |
119
|
|
|
* @param string $path |
120
|
|
|
* @param Nette\DI\Definitions\ServiceDefinition|NULL $cache |
121
|
|
|
* |
122
|
|
|
* @return Nette\DI\Definitions\Statement |
123
|
|
|
*/ |
124
|
|
|
private function createEntryPointLookupStatement(string $name, string $path, ?Nette\DI\Definitions\ServiceDefinition $cache): Nette\DI\Definitions\Statement |
125
|
|
|
{ |
126
|
|
|
return new Nette\DI\Definitions\Statement(SixtyEightPublishers\WebpackEncoreBundle\EntryPoint\EntryPointLookup::class, [ |
127
|
1 |
|
'buildName' => $name, |
128
|
|
|
'entryPointJsonPath' => $path . '/' . self::ENTRYPOINTS_FILE_NAME, |
129
|
1 |
|
'cache' => $cache, |
130
|
1 |
|
]); |
131
|
|
|
} |
132
|
|
|
|
133
|
1 |
|
/** |
134
|
|
|
* @param bool $enabled |
135
|
1 |
|
* @param mixed $storage |
136
|
1 |
|
* |
137
|
1 |
|
* @return Nette\DI\Definitions\ServiceDefinition|NULL |
138
|
1 |
|
*/ |
139
|
1 |
|
private function registerCache(bool $enabled, $storage): ?Nette\DI\Definitions\ServiceDefinition |
140
|
|
|
{ |
141
|
|
|
if (FALSE === $enabled) { |
142
|
1 |
|
return NULL; |
143
|
1 |
|
} |
144
|
1 |
|
|
145
|
1 |
|
$builder = $this->getContainerBuilder(); |
146
|
1 |
|
|
147
|
|
|
if (!is_string($storage) || !Nette\Utils\Strings::startsWith($storage, '@')) { |
148
|
1 |
|
$storage = $builder->addDefinition($this->prefix('cache.storage')) |
149
|
|
|
->setType(Nette\Caching\IStorage::class) |
150
|
|
|
->setFactory($storage) |
151
|
|
|
->addTag(Nette\DI\Extensions\InjectExtension::TAG_INJECT); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
return $builder->addDefinition($this->prefix('cache.cache')) |
155
|
|
|
->setType(Nette\Caching\Cache::class) |
156
|
|
|
->setArguments([ |
157
|
|
|
'storage' => $storage, |
158
|
1 |
|
'namespace' => str_replace('\\', '.', SixtyEightPublishers\WebpackEncoreBundle\EntryPoint\IEntryPointLookup::class), |
159
|
|
|
]) |
160
|
1 |
|
->addTag(Nette\DI\Extensions\InjectExtension::TAG_INJECT); |
161
|
1 |
|
} |
162
|
|
|
} |
163
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.