EnvironmentExtension   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 1
dl 0
loc 145
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
B loadConfiguration() 0 72 9
B beforeCompile() 0 22 7
A afterCompile() 0 12 2
A useDebugger() 0 7 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SixtyEightPublishers\Application\Environment\DI;
6
7
use Nette\DI\CompilerExtension;
8
use Nette\PhpGenerator\ClassType;
9
use Nette\Utils\AssertionException;
10
use SixtyEightPublishers\Application\Environment\ConfigurationException;
11
use SixtyEightPublishers\Application\Environment\Environment;
12
use SixtyEightPublishers\Application\Environment\ProfileContainer;
13
use SixtyEightPublishers\Application\Environment\IEnvironmentDetector;
14
use SixtyEightPublishers\Application\Environment\Detector\NetteRequestDetector;
15
use SixtyEightPublishers\Application\Environment\Diagnostics\Panel;
16
use SixtyEightPublishers\Application\Environment\IProfileStorage;
17
use SixtyEightPublishers\Application\Environment\Storage\SessionProfileStorage;
18
use SixtyEightPublishers\Application\Environment\Translation\ChangeTranslatorLocaleHandler;
19
use SixtyEightPublishers\Application\Environment\Translation\ProfileStorageResolver;
20
21
class EnvironmentExtension extends CompilerExtension
22
{
23
	/**
24
	 * @var array
25
	 */
26
	private $defaults = [
27
		'debugger' => FALSE,
28
		'localeDomain' => FALSE,
29
		'translations' => [
30
			'enable' => FALSE,
31
			'useDefault' => FALSE,
32
		],
33
		'mode' => 'tolerant',
34
		'profile' => [],
35
	];
36
37
	/**
38
	 * {@inheritdoc}
39
	 */
40
	public function loadConfiguration()
41
	{
42
		$builder = $this->getContainerBuilder();
43
		$config = $this->getConfig($this->defaults);
44
45
		$builder->addDefinition($this->prefix('environment'))
46
			->setType(Environment::class);
47
48
		$builder->addDefinition($this->prefix('detector'))
49
			->setType(NetteRequestDetector::class);
50
51
		$builder->addDefinition($this->prefix('profileStorage'))
52
			->setType(SessionProfileStorage::class);
53
54
		$profileContainer = $builder->addDefinition($this->prefix('profileContainer'))
55
			->setType(ProfileContainer::class);
56
57
		if (empty($config['profile'])) {
58
			throw new ConfigurationException("You must define some profile combination in your configuration.");
59
		}
60
61
		$requiredProfileParams = ['country', 'language', 'currency'];
62
		foreach ($config['profile'] as $profileName => $profile) {
63
			if (!empty(array_diff($requiredProfileParams, array_keys($profile)))) {
64
				throw new ConfigurationException("Problem with \"{$profileName}\" profile configuration. There are missing some of the required parameters (country, language, currency).");
65
			}
66
67
			$profileContainer->addSetup('addProfile', [
68
				$profileName,
69
				(array) $profile['country'],
70
				(array) $profile['language'],
71
				(array) $profile['currency'],
72
				array_key_exists('domain', $profile) ? (array) $profile['domain'] : [],
73
				!(array_key_exists('disable', $profile) && $profile['disable'] === TRUE),
74
			]);
75
		}
76
77
		if ($config['translations']['enable']) {
78
			$extensions = $this->compiler->getExtensions($extensionClass = '\Kdyby\Translation\DI\TranslationExtension');
79
			if (empty($extensions)) {
80
				throw new AssertionException('You should register \'' . $extensionClass . '\' before \'' . get_class($this) . '\'.', E_USER_NOTICE);
81
			}
82
			/** @var \Nette\DI\CompilerExtension $extension */
83
			$extension = $extensions[array_keys($extensions)[0]];
84
85
			$builder->addDefinition($this->prefix('translationResolver'))
86
				->setType(ProfileStorageResolver::class)
87
				->setArguments([
88
					'useDefault' => (bool) $config['translations']['useDefault'],
89
				]);
90
91
			$chain = $builder->getDefinition($extension->name . '.userLocaleResolver');
92
			$chain->addSetup('addResolver', [
93
				$this->prefix('@translationResolver')
94
			]);
95
96
			$builder->addDefinition($this->prefix('changeTranslatorLocaleHandler'))
97
				->setType(ChangeTranslatorLocaleHandler::class)
98
				->setTags([
99
					'run' => TRUE
100
				]);
101
102
			# @todo: Add resolver to Tracy Bar
103
		}
104
105
		if ($this->useDebugger()) {
106
			$builder->addDefinition($this->prefix('panel'))
107
				->setType(Panel::class)
108
				->setInject(FALSE)
109
				->setAutowired(FALSE);
110
		}
111
	}
112
113
	/**
114
	 * {@inheritdoc}
115
	 */
116
	public function beforeCompile()
117
	{
118
		$builder = $this->getContainerBuilder();
119
		$detectors = $builder->findByType(IEnvironmentDetector::class);
120
		$storage = $builder->findByType(IProfileStorage::class);
121
122
		if (count($detectors) > 1) {
123
			foreach ($detectors as $name => $definition) {
124
				if ($definition->getType() === NetteRequestDetector::class) {
125
					$builder->removeDefinition($name);
126
				}
127
			}
128
		}
129
130
		if (count($storage) > 1) {
131
			foreach ($storage as $name => $definition) {
132
				if ($definition->getType() === SessionProfileStorage::class) {
133
					$builder->removeDefinition($name);
134
				}
135
			}
136
		}
137
	}
138
139
	/**
140
	 * {@inheritdoc}
141
	 */
142
	public function afterCompile(ClassType $class)
143
	{
144
		$initialize = $class->methods['initialize'];
145
146
		if ($this->useDebugger()) {
147
			$bar = $this->getContainerBuilder()->getByType('Tracy\Bar');
148
			$initialize->addBody('$this->getService(?)->addPanel($this->getService(?));', [
149
				$bar,
150
				$this->prefix('panel'),
151
			]);
152
		}
153
	}
154
155
	/**
156
	 * @return bool
157
	 */
158
	private function useDebugger()
159
	{
160
		$config = $this->getConfig($this->defaults);
161
		$bar = $this->getContainerBuilder()->getByType('Tracy\Bar');
162
163
		return ($config['debugger'] && $bar && interface_exists('Tracy\IBarPanel'));
164
	}
165
}
166