Completed
Pull Request — master (#3)
by
unknown
08:38
created

WebpackEncoreBundleExtension::getConfigSchema()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 16
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 25
ccs 3
cts 3
cp 1
crap 3
rs 9.7333
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 SixtyEightPublishers;
11
12
final class WebpackEncoreBundleExtension extends Nette\DI\CompilerExtension
13
{
14
	private const ENTRYPOINTS_FILE_NAME = 'entrypoints.json';
15
16
	private const ENTRYPOINT_DEFAULT_NAME = '_default';
17
18
	private const CROSSORIGIN_ALLOWED_VALUES = [NULL, 'anonymous', 'use-credentials'];
19
20
	public function getConfigSchema(): Nette\Schema\Schema
21
	{
22
		return Nette\Schema\Expect::structure([
23
			'output_path' => Nette\Schema\Expect::string()->nullable(), # The path where Encore is building the assets - i.e. Encore.setOutputPath()
24
			'builds' => Nette\Schema\Expect::array()->items('string')->assert(function (array $value): bool {
25
				if (isset($value[self::ENTRYPOINT_DEFAULT_NAME])) {
26
					throw new Nette\Utils\AssertionException(sprintf('Key "%s" can\'t be used as build name.', self::ENTRYPOINT_DEFAULT_NAME));
27
				}
28
29
				return TRUE;
30
			}),
31
			'crossorigin' => Nette\Schema\Expect::string()->nullable()->assert(function (?string $value): bool {
32
				if (!in_array($value, self::CROSSORIGIN_ALLOWED_VALUES, TRUE)) {
33
					throw new Nette\Utils\AssertionException(sprintf('Value "%s" for setting "crossorigin" is not allowed', $value));
34
				}
35
36
				return TRUE;
37
			}), # crossorigin value when Encore.enableIntegrityHashes() is used, can be NULL (default), anonymous or use-credentials
38
			'cache' => Nette\Schema\Expect::structure([
39
				'enabled' => Nette\Schema\Expect::bool(FALSE),
40
				'storage' => Nette\Schema\Expect::string('@' . Nette\Caching\IStorage::class)->dynamic(),
41
			]),
42 1
			'latte' => Nette\Schema\Expect::structure([
43 1
				'js_assets_macro_name' => Nette\Schema\Expect::string('encore_js'),
44 1
				'css_assets_macro_name' => Nette\Schema\Expect::string('encore_css'),
45 1
			]),
46
		]);
47 1
	}
48 1
49
	/**
50
	 * {@inheritdoc}
51 1
	 *
52 1
	 * @throws \Nette\Utils\AssertionException
53
	 */
54
	public function loadConfiguration(): void
55 1
	{
56 1
		$builder = $this->getContainerBuilder();
57 1
		$cache = $this->registerCache($this->config->cache->enabled, $this->config->cache->storage);
58 1
		$lookups = [];
59 1
60
		if (NULL !== $this->config->output_path) {
61
			$lookups[] = $this->createEntryPointLookupStatement(self::ENTRYPOINT_DEFAULT_NAME, $this->config->output_path, $cache);
62 1
		}
63
64 1
		foreach ($this->config->builds as $name => $path) {
65
			$lookups[] = $this->createEntryPointLookupStatement($name, $path, $cache);
66
		}
67
68 1
		$builder->addDefinition($this->prefix('entryPointLookupProvider'))
69 1
			->setType(SixtyEightPublishers\WebpackEncoreBundle\EntryPoint\IEntryPointLookupProvider::class)
70 1
			->setFactory(SixtyEightPublishers\WebpackEncoreBundle\EntryPoint\EntryPointLookupProvider::class, [
71 1
				'lookups' => $lookups,
72 1
				'defaultName' => NULL !== $this->config->output_path ? self::ENTRYPOINT_DEFAULT_NAME : NULL,
73
			]);
74 1
75
		$defaultAttributes = [];
76
77
		if (NULL !== $this->config->crossorigin) {
78
			$defaultAttributes['crossorigin'] = $this->config->crossorigin;
79
		}
80
81
		$builder->addDefinition($this->prefix('tagRenderer'))
82
			->setType(SixtyEightPublishers\WebpackEncoreBundle\Latte\TagRenderer::class)
83 1
			->setAutowired(FALSE)
84 1
			->setArguments([
85
				'defaultAttributes' => $defaultAttributes,
86 1
			]);
87
	}
88
89
	/**
90 1
	 * {@inheritdoc}
91
	 *
92 1
	 * @throws \Nette\Utils\AssertionException
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', [
0 ignored issues
show
Bug introduced by
Are you sure the usage of $latteFactory->getResultDefinition() targeting Nette\DI\Definitions\Definition::__call() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

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.

Loading history...
105
			'name' => 'webpackEncoreTagRenderer',
106
			'value' => $this->prefix('@tagRenderer'),
107
		]);
108
109
		$latteFactory->getResultDefinition()->addSetup('?->onCompile[] = function ($engine) { ?::install(?, ?, $engine->getCompiler()); }', [
0 ignored issues
show
Bug introduced by
Are you sure the usage of $latteFactory->getResultDefinition() targeting Nette\DI\Definitions\Definition::__call() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

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.

Loading history...
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\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