Completed
Push — master ( 15fb6c...64be1d )
by Jáchym
01:33
created

TranslationExtension   C

Complexity

Total Complexity 69

Size/Duplication

Total Lines 441
Duplicated Lines 10.43 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 69
lcom 1
cbo 5
dl 46
loc 441
rs 5.6445
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A isRegisteredConsoleExtension() 0 10 3
A __construct() 0 4 1
B loadConfiguration() 0 66 5
B loadLocaleResolver() 12 39 6
A loadConsole() 0 10 1
A loadDumpers() 10 10 2
A loadLoaders() 0 13 3
A loadExtractors() 10 10 2
F beforeCompile() 14 92 19
A beforeCompileLogging() 0 20 4
B loadResourcesFromDirs() 0 27 6
C validateResource() 0 32 8
A afterCompile() 0 7 2
A getConfig() 0 4 1
A register() 0 6 1
A filterArgs() 0 4 2
A isOfType() 0 4 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like TranslationExtension often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TranslationExtension, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * This file is part of the Kdyby (http://www.kdyby.org)
5
 *
6
 * Copyright (c) 2008 Filip Procházka ([email protected])
7
 *
8
 * For the full copyright and license information, please view the file license.txt that was distributed with this source code.
9
 */
10
11
namespace Kdyby\Translation\DI;
12
13
use Kdyby\Console\DI\ConsoleExtension;
14
use Kdyby\Monolog\Logger as KdybyLogger;
15
use Kdyby\Translation\Caching\PhpFileStorage;
16
use Kdyby\Translation\CatalogueCompiler;
17
use Kdyby\Translation\CatalogueFactory;
18
use Kdyby\Translation\Console\ExtractCommand;
19
use Kdyby\Translation\Diagnostics\Panel;
20
use Kdyby\Translation\FallbackResolver;
21
use Kdyby\Translation\IUserLocaleResolver;
22
use Kdyby\Translation\Latte\TranslateMacros;
23
use Kdyby\Translation\LocaleResolver\AcceptHeaderResolver;
24
use Kdyby\Translation\LocaleResolver\ChainResolver;
25
use Kdyby\Translation\LocaleResolver\LocaleParamResolver;
26
use Kdyby\Translation\LocaleResolver\SessionResolver;
27
use Kdyby\Translation\TemplateHelpers;
28
use Kdyby\Translation\TranslationLoader;
29
use Kdyby\Translation\Translator as KdybyTranslator;
30
use Latte\Engine as LatteEngine;
31
use Nette\Application\Application;
32
use Nette\Bridges\ApplicationLatte\ILatteFactory;
33
use Nette\Configurator;
34
use Nette\DI\Compiler;
35
use Nette\DI\Helpers;
36
use Nette\DI\ServiceDefinition;
37
use Nette\DI\Statement;
38
use Nette\PhpGenerator\ClassType as ClassTypeGenerator;
39
use Nette\PhpGenerator\PhpLiteral;
40
use Nette\Reflection\ClassType as ReflectionClassType;
41
use Nette\Utils\Callback;
42
use Nette\Utils\Finder;
43
use Nette\Utils\Validators;
44
use Symfony\Component\Translation\Extractor\ChainExtractor;
45
use Symfony\Component\Translation\Formatter\MessageFormatter;
46
use Symfony\Component\Translation\Loader\LoaderInterface;
47
use Symfony\Component\Translation\MessageSelector;
48
use Symfony\Component\Translation\Writer\TranslationWriter;
49
use Tracy\Debugger;
50
use Tracy\IBarPanel;
51
52
class TranslationExtension extends \Nette\DI\CompilerExtension
53
{
54
55
	use \Kdyby\StrictObjects\Scream;
56
57
	/** @deprecated */
58
	const LOADER_TAG = self::TAG_LOADER;
59
	/** @deprecated */
60
	const DUMPER_TAG = self::TAG_DUMPER;
61
	/** @deprecated */
62
	const EXTRACTOR_TAG = self::TAG_EXTRACTOR;
63
64
	const TAG_LOADER = 'translation.loader';
65
	const TAG_DUMPER = 'translation.dumper';
66
	const TAG_EXTRACTOR = 'translation.extractor';
67
68
	const RESOLVER_REQUEST = 'request';
69
	const RESOLVER_HEADER = 'header';
70
	const RESOLVER_SESSION = 'session';
71
72
	/**
73
	 * @var mixed[]
74
	 */
75
	public $defaults = [
76
		'whitelist' => NULL, // array('cs', 'en'),
0 ignored issues
show
Unused Code Comprehensibility introduced by
78% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
77
		'default' => 'en',
78
		'logging' => NULL, //  TRUE for psr/log, or string for kdyby/monolog channel
79
		// 'fallback' => array('en_US', 'en'), // using custom merge strategy becase Nette's config merger appends lists of values
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
80
		'dirs' => ['%appDir%/lang', '%appDir%/locale'],
81
		'cache' => PhpFileStorage::class,
82
		'debugger' => '%debugMode%',
83
		'resolvers' => [
84
			self::RESOLVER_SESSION => FALSE,
85
			self::RESOLVER_REQUEST => TRUE,
86
			self::RESOLVER_HEADER => TRUE,
87
		],
88
		'loaders' => [],
89
	];
90
91
	/**
92
	 * @var array
93
	 */
94
	private $loaders;
95
96
	public function __construct()
97
	{
98
		$this->defaults['cache'] = new Statement($this->defaults['cache'], ['%tempDir%/cache']);
99
	}
100
101
	public function loadConfiguration()
102
	{
103
		$this->loaders = [];
104
105
		$builder = $this->getContainerBuilder();
106
		$config = $this->getConfig();
107
108
		$translator = $builder->addDefinition($this->prefix('default'))
109
			->setClass(KdybyTranslator::class, [$this->prefix('@userLocaleResolver')])
110
			->addSetup('?->setTranslator(?)', [$this->prefix('@userLocaleResolver.param'), '@self'])
111
			->addSetup('setDefaultLocale', [$config['default']])
112
			->addSetup('setLocaleWhitelist', [$config['whitelist']]);
113
114
		Validators::assertField($config, 'fallback', 'list');
115
		$translator->addSetup('setFallbackLocales', [$config['fallback']]);
116
117
		$catalogueCompiler = $builder->addDefinition($this->prefix('catalogueCompiler'))
118
			->setClass(CatalogueCompiler::class, self::filterArgs($config['cache']));
119
120
		if ($config['debugger'] && interface_exists(IBarPanel::class)) {
121
			$builder->addDefinition($this->prefix('panel'))
122
				->setClass(Panel::class, [dirname($builder->expand('%appDir%'))])
123
				->addSetup('setLocaleWhitelist', [$config['whitelist']]);
124
125
			$translator->addSetup('?->register(?)', [$this->prefix('@panel'), '@self']);
126
			$catalogueCompiler->addSetup('enableDebugMode');
127
		}
128
129
		$this->loadLocaleResolver($config);
130
131
		$builder->addDefinition($this->prefix('helpers'))
132
			->setClass(TemplateHelpers::class)
133
			->setFactory($this->prefix('@default') . '::createTemplateHelpers');
134
135
		$builder->addDefinition($this->prefix('fallbackResolver'))
136
			->setClass(FallbackResolver::class);
137
138
		$builder->addDefinition($this->prefix('catalogueFactory'))
139
			->setClass(CatalogueFactory::class);
140
141
		$builder->addDefinition($this->prefix('selector'))
142
			->setClass(MessageSelector::class);
143
144
		$builder->addDefinition($this->prefix('formatter'))
145
			->setClass(MessageFormatter::class);
146
147
		$builder->addDefinition($this->prefix('extractor'))
148
			->setClass(ChainExtractor::class);
149
150
		$this->loadExtractors();
151
152
		$builder->addDefinition($this->prefix('writer'))
153
			->setClass(TranslationWriter::class);
154
155
		$this->loadDumpers();
156
157
		$builder->addDefinition($this->prefix('loader'))
158
			->setClass(TranslationLoader::class);
159
160
		$loaders = $this->loadFromFile(__DIR__ . '/config/loaders.neon');
161
		$this->loadLoaders($loaders, $config['loaders'] ?: array_keys($loaders));
162
163
		if ($this->isRegisteredConsoleExtension()) {
164
			$this->loadConsole($config);
165
		}
166
	}
167
168
	protected function loadLocaleResolver(array $config)
169
	{
170
		$builder = $this->getContainerBuilder();
171
172
		$builder->addDefinition($this->prefix('userLocaleResolver.param'))
173
			->setClass(LocaleParamResolver::class)
174
			->setAutowired(FALSE);
175
176
		$builder->addDefinition($this->prefix('userLocaleResolver.acceptHeader'))
177
			->setClass(AcceptHeaderResolver::class);
178
179
		$builder->addDefinition($this->prefix('userLocaleResolver.session'))
180
			->setClass(SessionResolver::class);
181
182
		$chain = $builder->addDefinition($this->prefix('userLocaleResolver'))
183
			->setClass(IUserLocaleResolver::class)
184
			->setFactory(ChainResolver::class);
185
186
		$resolvers = [];
187 View Code Duplication
		if ($config['resolvers'][self::RESOLVER_HEADER]) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
188
			$resolvers[] = $this->prefix('@userLocaleResolver.acceptHeader');
189
			$chain->addSetup('addResolver', [$this->prefix('@userLocaleResolver.acceptHeader')]);
190
		}
191
192 View Code Duplication
		if ($config['resolvers'][self::RESOLVER_REQUEST]) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
193
			$resolvers[] = $this->prefix('@userLocaleResolver.param');
194
			$chain->addSetup('addResolver', [$this->prefix('@userLocaleResolver.param')]);
195
		}
196
197 View Code Duplication
		if ($config['resolvers'][self::RESOLVER_SESSION]) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
198
			$resolvers[] = $this->prefix('@userLocaleResolver.session');
199
			$chain->addSetup('addResolver', [$this->prefix('@userLocaleResolver.session')]);
200
		}
201
202
		if ($config['debugger'] && interface_exists(IBarPanel::class)) {
203
			$builder->getDefinition($this->prefix('panel'))
204
				->addSetup('setLocaleResolvers', [array_reverse($resolvers)]);
205
		}
206
	}
207
208
	protected function loadConsole(array $config)
209
	{
210
		$builder = $this->getContainerBuilder();
211
212
		Validators::assertField($config, 'dirs', 'list');
213
		$builder->addDefinition($this->prefix('console.extract'))
214
			->setClass(ExtractCommand::class)
215
			->addSetup('$defaultOutputDir', [reset($config['dirs'])])
216
			->addTag(ConsoleExtension::TAG_COMMAND, 'latte');
217
	}
218
219 View Code Duplication
	protected function loadDumpers()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
220
	{
221
		$builder = $this->getContainerBuilder();
222
223
		foreach ($this->loadFromFile(__DIR__ . '/config/dumpers.neon') as $format => $class) {
224
			$builder->addDefinition($this->prefix('dumper.' . $format))
225
				->setClass($class)
226
				->addTag(self::TAG_DUMPER, $format);
227
		}
228
	}
229
230
	protected function loadLoaders(array $loaders, array $allowed)
231
	{
232
		$builder = $this->getContainerBuilder();
233
234
		foreach ($loaders as $format => $class) {
235
			if (array_search($format, $allowed) === FALSE) {
236
				continue;
237
			}
238
			$builder->addDefinition($this->prefix('loader.' . $format))
239
				->setClass($class)
240
				->addTag(self::TAG_LOADER, $format);
241
		}
242
	}
243
244 View Code Duplication
	protected function loadExtractors()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
	{
246
		$builder = $this->getContainerBuilder();
247
248
		foreach ($this->loadFromFile(__DIR__ . '/config/extractors.neon') as $format => $class) {
249
			$builder->addDefinition($this->prefix('extractor.' . $format))
250
				->setClass($class)
251
				->addTag(self::TAG_EXTRACTOR, $format);
252
		}
253
	}
254
255
	public function beforeCompile()
256
	{
257
		$builder = $this->getContainerBuilder();
258
		$config = $this->getConfig();
259
260
		$this->beforeCompileLogging($config);
261
262
		$registerToLatte = function (ServiceDefinition $def) {
263
			$def->addSetup('?->onCompile[] = function($engine) { ?::install($engine->getCompiler()); }', ['@self', new PhpLiteral(TranslateMacros::class)]);
264
265
			$def->addSetup('addProvider', ['translator', $this->prefix('@default')])
266
				->addSetup('addFilter', ['translate', [$this->prefix('@helpers'), 'translateFilterAware']]);
267
		};
268
269
		$latteFactoryService = $builder->getByType(ILatteFactory::class);
270
		if (!$latteFactoryService || !self::isOfType($builder->getDefinition($latteFactoryService)->getClass(), LatteEngine::class)) {
271
			$latteFactoryService = 'nette.latteFactory';
272
		}
273
274
		if ($builder->hasDefinition($latteFactoryService) && self::isOfType($builder->getDefinition($latteFactoryService)->getClass(), LatteEngine::class)) {
275
			$registerToLatte($builder->getDefinition($latteFactoryService));
276
		}
277
278
		if ($builder->hasDefinition('nette.latte')) {
279
			$registerToLatte($builder->getDefinition('nette.latte'));
280
		}
281
282
		$applicationService = $builder->getByType(Application::class) ?: 'application';
283
		if ($builder->hasDefinition($applicationService)) {
284
			$builder->getDefinition($applicationService)
285
				->addSetup('$service->onRequest[] = ?', [[$this->prefix('@userLocaleResolver.param'), 'onRequest']]);
286
287
			if ($config['debugger'] && interface_exists(IBarPanel::class)) {
288
				$builder->getDefinition($applicationService)
289
					->addSetup('$self = $this; $service->onStartup[] = function () use ($self) { $self->getService(?); }', [$this->prefix('default')])
290
					->addSetup('$service->onRequest[] = ?', [[$this->prefix('@panel'), 'onRequest']]);
291
			}
292
		}
293
294
		if (class_exists(Debugger::class)) {
295
			Panel::registerBluescreen();
296
		}
297
298
		$extractor = $builder->getDefinition($this->prefix('extractor'));
299 View Code Duplication
		foreach ($builder->findByTag(self::TAG_EXTRACTOR) as $extractorId => $meta) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
300
			Validators::assert($meta, 'string:2..');
301
302
			$extractor->addSetup('addExtractor', [$meta, '@' . $extractorId]);
303
304
			$builder->getDefinition($extractorId)->setAutowired(FALSE);
305
		}
306
307
		$writer = $builder->getDefinition($this->prefix('writer'));
308 View Code Duplication
		foreach ($builder->findByTag(self::TAG_DUMPER) as $dumperId => $meta) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
309
			Validators::assert($meta, 'string:2..');
310
311
			$writer->addSetup('addDumper', [$meta, '@' . $dumperId]);
312
313
			$builder->getDefinition($dumperId)->setAutowired(FALSE);
314
		}
315
316
		$this->loaders = [];
317
		foreach ($builder->findByTag(self::TAG_LOADER) as $loaderId => $meta) {
318
			Validators::assert($meta, 'string:2..');
319
			$builder->getDefinition($loaderId)->setAutowired(FALSE);
320
			$this->loaders[$meta] = $loaderId;
321
		}
322
323
		$builder->getDefinition($this->prefix('loader'))
324
			->addSetup('injectServiceIds', [$this->loaders]);
325
326
		foreach ($this->compiler->getExtensions() as $extension) {
327
			if (!$extension instanceof ITranslationProvider) {
328
				continue;
329
			}
330
331
			$config['dirs'] = array_merge($config['dirs'], array_values($extension->getTranslationResources()));
332
		}
333
334
		$config['dirs'] = array_map(function ($dir) {
335
			return str_replace((DIRECTORY_SEPARATOR === '/') ? '\\' : '/', DIRECTORY_SEPARATOR, $dir);
336
		}, $config['dirs']);
337
338
		$dirs = array_values(array_filter($config['dirs'], Callback::closure('is_dir')));
339
		if (count($dirs) > 0) {
340
			foreach ($dirs as $dir) {
341
				$builder->addDependency($dir);
342
			}
343
344
			$this->loadResourcesFromDirs($dirs);
345
		}
346
	}
347
348
	protected function beforeCompileLogging(array $config)
349
	{
350
		$builder = $this->getContainerBuilder();
351
		$translator = $builder->getDefinition($this->prefix('default'));
352
353
		if ($config['logging'] === TRUE) {
354
			$translator->addSetup('injectPsrLogger');
355
356
		} elseif (is_string($config['logging'])) { // channel for kdyby/monolog
357
			$translator->addSetup('injectPsrLogger', [
358
				new Statement(sprintf('@%s::channel', KdybyLogger::class), [$config['logging']]),
359
			]);
360
361
		} elseif ($config['logging'] !== NULL) {
362
			throw new \Kdyby\Translation\InvalidArgumentException(sprintf(
363
				'Invalid config option for logger. Valid are TRUE for general psr/log or string for kdyby/monolog channel, but %s was given',
364
				$config['logging']
365
			));
366
		}
367
	}
368
369
	protected function loadResourcesFromDirs($dirs)
370
	{
371
		$builder = $this->getContainerBuilder();
372
		$config = $this->getConfig();
373
374
		$whitelistRegexp = KdybyTranslator::buildWhitelistRegexp($config['whitelist']);
375
		$translator = $builder->getDefinition($this->prefix('default'));
376
377
		$mask = array_map(function ($value) {
378
			return '*.*.' . $value;
379
		}, array_keys($this->loaders));
380
381
		foreach (Finder::findFiles($mask)->from($dirs) as $file) {
382
			/** @var \SplFileInfo $file */
383
			if (!preg_match('~^(?P<domain>.*?)\.(?P<locale>[^\.]+)\.(?P<format>[^\.]+)$~', $file->getFilename(), $m)) {
384
				continue;
385
			}
386
387
			if ($whitelistRegexp && !preg_match($whitelistRegexp, $m['locale']) && $builder->parameters['productionMode']) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $whitelistRegexp of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
388
				continue; // ignore in production mode, there is no need to pass the ignored resources
389
			}
390
391
			$this->validateResource($m['format'], $file->getPathname(), $m['locale'], $m['domain']);
392
			$translator->addSetup('addResource', [$m['format'], $file->getPathname(), $m['locale'], $m['domain']]);
393
			$builder->addDependency($file->getPathname());
394
		}
395
	}
396
397
	/**
398
	 * @param string $format
399
	 * @param string $file
400
	 * @param string $locale
401
	 * @param string $domain
402
	 */
403
	protected function validateResource($format, $file, $locale, $domain)
404
	{
405
		$builder = $this->getContainerBuilder();
406
407
		if (!isset($this->loaders[$format])) {
408
			return;
409
		}
410
411
		try {
412
			$def = $builder->getDefinition($this->loaders[$format]);
413
			$refl = ReflectionClassType::from($def->getEntity() ?: $def->getClass());
414
			$method = $refl->getConstructor();
415
			if ($method !== NULL && $method->getNumberOfRequiredParameters() > 1) {
416
				return;
417
			}
418
419
			$loader = $refl->newInstance();
420
			if (!$loader instanceof LoaderInterface) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\Transl...\Loader\LoaderInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
421
				return;
422
			}
423
424
		} catch (\ReflectionException $e) {
425
			return;
426
		}
427
428
		try {
429
			$loader->load($file, $locale, $domain);
430
431
		} catch (\Exception $e) {
432
			throw new \Kdyby\Translation\InvalidResourceException(sprintf('Resource %s is not valid and cannot be loaded.', $file), 0, $e);
433
		}
434
	}
435
436
	public function afterCompile(ClassTypeGenerator $class)
437
	{
438
		$initialize = $class->getMethod('initialize');
439
		if (class_exists(Debugger::class)) {
440
			$initialize->addBody('?::registerBluescreen();', [new PhpLiteral(Panel::class)]);
441
		}
442
	}
443
444
	/**
445
	 * {@inheritdoc}
446
	 */
447
	public function getConfig(array $defaults = NULL, $expand = TRUE)
448
	{
449
		return parent::getConfig($this->defaults) + ['fallback' => ['en_US']];
450
	}
451
452
	private function isRegisteredConsoleExtension()
453
	{
454
		foreach ($this->compiler->getExtensions() as $extension) {
455
			if ($extension instanceof ConsoleExtension) {
0 ignored issues
show
Bug introduced by
The class Kdyby\Console\DI\ConsoleExtension does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
456
				return TRUE;
457
			}
458
		}
459
460
		return FALSE;
461
	}
462
463
	/**
464
	 * @param \Nette\Configurator $configurator
465
	 */
466
	public static function register(Configurator $configurator)
467
	{
468
		$configurator->onCompile[] = function ($config, Compiler $compiler) {
469
			$compiler->addExtension('translation', new TranslationExtension());
470
		};
471
	}
472
473
	/**
474
	 * @param string|\stdClass $statement
475
	 * @return \Nette\DI\Statement[]
476
	 */
477
	protected static function filterArgs($statement)
478
	{
479
		return Helpers::filterArguments([is_string($statement) ? new Statement($statement) : $statement]);
480
	}
481
482
	/**
483
	 * @param string|NULL $class
484
	 * @param string $type
485
	 * @return bool
486
	 */
487
	private static function isOfType($class, $type)
488
	{
489
		return $class !== NULL && ($class === $type || is_subclass_of($class, $type));
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if $type can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
490
	}
491
492
}
493