Completed
Pull Request — master (#98)
by
unknown
09:46
created

TranslationExtension::loadResourcesFromDirs()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 25
rs 6.7272
cc 7
eloc 14
nc 5
nop 1
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;
14
use Kdyby\Translation\InvalidResourceException;
15
use Nette;
16
use Nette\DI\Statement;
17
use Nette\PhpGenerator as Code;
18
use Nette\Reflection;
19
use Nette\Utils\Callback;
20
use Nette\Utils\Finder;
21
use Nette\Utils\Strings;
22
use Nette\Utils\Validators;
23
use Symfony\Component\Translation\Loader\LoaderInterface;
24
use Tracy;
25
26
27
28
/**
29
 * @author Filip Procházka <[email protected]>
30
 */
31
class TranslationExtension extends Nette\DI\CompilerExtension
32
{
33
34
	/** @deprecated */
35
	const LOADER_TAG = self::TAG_LOADER;
36
	/** @deprecated */
37
	const DUMPER_TAG = self::TAG_DUMPER;
38
	/** @deprecated */
39
	const EXTRACTOR_TAG = self::TAG_EXTRACTOR;
40
41
	const TAG_LOADER = 'translation.loader';
42
	const TAG_DUMPER = 'translation.dumper';
43
	const TAG_EXTRACTOR = 'translation.extractor';
44
45
	const RESOLVER_REQUEST = 'request';
46
	const RESOLVER_HEADER = 'header';
47
	const RESOLVER_SESSION = 'session';
48
49
	/**
50
	 * @var array
51
	 */
52
	public $defaults = array(
53
		'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...
54
		'default' => 'en',
55
		'logging' => NULL, //  TRUE for psr/log, or string for kdyby/monolog channel
56
		// '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
65% 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...
57
		'dirs' => array('%appDir%/lang', '%appDir%/locale'),
58
		'cache' => 'Kdyby\Translation\Caching\PhpFileStorage',
59
		'debugger' => '%debugMode%',
60
		'resolvers' => array(
61
			self::RESOLVER_SESSION => FALSE,
62
			self::RESOLVER_REQUEST => TRUE,
63
			self::RESOLVER_HEADER => TRUE,
64
		),
65
	);
66
67
	/**
68
	 * @var array
69
	 */
70
	private $loaders;
71
72
73
74
	public function __construct()
75
	{
76
		$this->defaults['cache'] = new Statement($this->defaults['cache'], array('%tempDir%/cache'));
77
	}
78
79
80
81
	public function loadConfiguration()
82
	{
83
		$this->loaders = array();
84
85
		$builder = $this->getContainerBuilder();
86
		$config = $this->getConfig();
87
88
		$translator = $builder->addDefinition($this->prefix('default'))
89
			->setClass('Kdyby\Translation\Translator', array($this->prefix('@userLocaleResolver')))
90
			->addSetup('?->setTranslator(?)', array($this->prefix('@userLocaleResolver.param'), '@self'))
91
			->addSetup('setDefaultLocale', array($config['default']))
92
			->addSetup('setLocaleWhitelist', array($config['whitelist']))
93
			->setInject(FALSE);
94
95
		Validators::assertField($config, 'fallback', 'list');
96
		$translator->addSetup('setFallbackLocales', array($config['fallback']));
97
98
		$catalogueCompiler = $builder->addDefinition($this->prefix('catalogueCompiler'))
99
			->setClass('Kdyby\Translation\CatalogueCompiler', self::filterArgs($config['cache']))
100
			->setInject(FALSE);
101
102
		if ($config['debugger'] && interface_exists('Tracy\IBarPanel')) {
103
			$builder->addDefinition($this->prefix('panel'))
104
				->setClass('Kdyby\Translation\Diagnostics\Panel', array(dirname($builder->expand('%appDir%'))))
0 ignored issues
show
Deprecated Code introduced by
The method Nette\DI\ContainerBuilder::expand() has been deprecated.

This method has been deprecated.

Loading history...
105
				->addSetup('setLocaleWhitelist', array($config['whitelist']));
106
107
			$translator->addSetup('?->register(?)', array($this->prefix('@panel'), '@self'));
108
			$catalogueCompiler->addSetup('enableDebugMode');
109
		}
110
111
		$this->loadLocaleResolver($config);
112
113
		$builder->addDefinition($this->prefix('helpers'))
114
			->setClass('Kdyby\Translation\TemplateHelpers')
115
			->setFactory($this->prefix('@default') . '::createTemplateHelpers')
116
			->setInject(FALSE);
117
118
		$builder->addDefinition($this->prefix('fallbackResolver'))
119
			->setClass('Kdyby\Translation\FallbackResolver')
120
			->setInject(FALSE);
121
122
		$builder->addDefinition($this->prefix('catalogueFactory'))
123
			->setClass('Kdyby\Translation\CatalogueFactory')
124
			->setInject(FALSE);
125
126
		$builder->addDefinition($this->prefix('selector'))
127
			->setClass('Symfony\Component\Translation\MessageSelector')
128
			->setInject(FALSE);
129
130
		$builder->addDefinition($this->prefix('extractor'))
131
			->setClass('Symfony\Component\Translation\Extractor\ChainExtractor')
132
			->setInject(FALSE);
133
134
		$this->loadExtractors();
135
136
		$builder->addDefinition($this->prefix('writer'))
137
			->setClass('Symfony\Component\Translation\Writer\TranslationWriter')
138
			->setInject(FALSE);
139
140
		$this->loadDumpers();
141
142
		$builder->addDefinition($this->prefix('loader'))
143
			->setClass('Kdyby\Translation\TranslationLoader')
144
			->setInject(FALSE);
145
146
		$this->loadLoaders();
147
148
		if ($this->isRegisteredConsoleExtension()) {
149
			$this->loadConsole($config);
150
		}
151
	}
152
153
154
155
	protected function loadLocaleResolver(array $config)
156
	{
157
		$builder = $this->getContainerBuilder();
158
159
		$builder->addDefinition($this->prefix('userLocaleResolver.param'))
160
			->setClass('Kdyby\Translation\LocaleResolver\LocaleParamResolver')
161
			->setAutowired(FALSE)
162
			->setInject(FALSE);
163
164
		$builder->addDefinition($this->prefix('userLocaleResolver.acceptHeader'))
165
			->setClass('Kdyby\Translation\LocaleResolver\AcceptHeaderResolver')
166
			->setInject(FALSE);
167
168
		$builder->addDefinition($this->prefix('userLocaleResolver.session'))
169
			->setClass('Kdyby\Translation\LocaleResolver\SessionResolver')
170
			->setInject(FALSE);
171
172
		$chain = $builder->addDefinition($this->prefix('userLocaleResolver'))
173
			->setClass('Kdyby\Translation\IUserLocaleResolver')
174
			->setFactory('Kdyby\Translation\LocaleResolver\ChainResolver')
175
			->setInject(FALSE);
176
177
		$resolvers = array();
178 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...
179
			$resolvers[] = $this->prefix('@userLocaleResolver.acceptHeader');
180
			$chain->addSetup('addResolver', array($this->prefix('@userLocaleResolver.acceptHeader')));
181
		}
182
183 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...
184
			$resolvers[] = $this->prefix('@userLocaleResolver.param');
185
			$chain->addSetup('addResolver', array($this->prefix('@userLocaleResolver.param')));
186
		}
187
188 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...
189
			$resolvers[] = $this->prefix('@userLocaleResolver.session');
190
			$chain->addSetup('addResolver', array($this->prefix('@userLocaleResolver.session')));
191
		}
192
193
		if ($config['debugger'] && interface_exists('Tracy\IBarPanel')) {
194
			$builder->getDefinition($this->prefix('panel'))
195
				->addSetup('setLocaleResolvers', array(array_reverse($resolvers)));
196
		}
197
	}
198
199
200
201
	protected function loadConsole(array $config)
202
	{
203
		$builder = $this->getContainerBuilder();
204
205
		Validators::assertField($config, 'dirs', 'list');
206
		$builder->addDefinition($this->prefix('console.extract'))
207
			->setClass('Kdyby\Translation\Console\ExtractCommand')
208
			->addSetup('$defaultOutputDir', array(reset($config['dirs'])))
209
			->setInject(FALSE)
210
			->addTag('kdyby.console.command', 'latte');
0 ignored issues
show
Documentation introduced by
'latte' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
211
	}
212
213
214
215 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...
216
	{
217
		$builder = $this->getContainerBuilder();
218
219
		foreach ($this->loadFromFile(__DIR__ . '/config/dumpers.neon') as $format => $class) {
0 ignored issues
show
Bug introduced by
The expression $this->loadFromFile(__DI...'/config/dumpers.neon') of type array|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
220
			$builder->addDefinition($this->prefix('dumper.' . $format))
221
				->setClass($class)
222
				->addTag(self::TAG_DUMPER, $format);
0 ignored issues
show
Documentation introduced by
$format is of type integer|string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
223
		}
224
	}
225
226
227
228 View Code Duplication
	protected function loadLoaders()
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...
229
	{
230
		$builder = $this->getContainerBuilder();
231
232
		foreach ($this->loadFromFile(__DIR__ . '/config/loaders.neon') as $format => $class) {
0 ignored issues
show
Bug introduced by
The expression $this->loadFromFile(__DI...'/config/loaders.neon') of type array|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
233
			$builder->addDefinition($this->prefix('loader.' . $format))
234
				->setClass($class)
235
				->addTag(self::TAG_LOADER, $format);
0 ignored issues
show
Documentation introduced by
$format is of type integer|string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
236
		}
237
	}
238
239
240
241 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...
242
	{
243
		$builder = $this->getContainerBuilder();
244
245
		foreach ($this->loadFromFile(__DIR__ . '/config/extractors.neon') as $format => $class) {
0 ignored issues
show
Bug introduced by
The expression $this->loadFromFile(__DI...onfig/extractors.neon') of type array|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
246
			$builder->addDefinition($this->prefix('extractor.' . $format))
247
				->setClass($class)
248
				->addTag(self::TAG_EXTRACTOR, $format);
0 ignored issues
show
Documentation introduced by
$format is of type integer|string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
249
		}
250
	}
251
252
253
254
	public function beforeCompile()
255
	{
256
		$builder = $this->getContainerBuilder();
257
		$config = $this->getConfig();
258
259
		$this->beforeCompileLogging($config);
260
261
		$registerToLatte = function (Nette\DI\ServiceDefinition $def) {
262
			$def
263
				->addSetup('?->onCompile[] = function($engine) { Kdyby\Translation\Latte\TranslateMacros::install($engine->getCompiler()); }', array('@self'))
264
				->addSetup('addFilter', array('translate', array($this->prefix('@helpers'), 'translate')))
265
				->addSetup('addFilter', array('getTranslator', array($this->prefix('@helpers'), 'getTranslator')));
266
		};
267
268
		$latteFactoryService = $builder->getByType('Nette\Bridges\ApplicationLatte\ILatteFactory') ?: 'nette.latteFactory';
269
		if ($builder->hasDefinition($latteFactoryService)) {
270
			$registerToLatte($builder->getDefinition($latteFactoryService));
271
		}
272
273
		if ($builder->hasDefinition('nette.latte')) {
274
			$registerToLatte($builder->getDefinition('nette.latte'));
275
		}
276
277
		$applicationService = $builder->getByType('Nette\Application\Application') ?: 'application';
278
		if ($builder->hasDefinition($applicationService)) {
279
			$builder->getDefinition($applicationService)
280
				->addSetup('$service->onRequest[] = ?', array(array($this->prefix('@userLocaleResolver.param'), 'onRequest')));
281
282
			if ($config['debugger'] && interface_exists('Tracy\IBarPanel')) {
283
				$builder->getDefinition($applicationService)
284
					->addSetup('$self = $this; $service->onStartup[] = function () use ($self) { $self->getService(?); }', array($this->prefix('default')))
285
					->addSetup('$service->onRequest[] = ?', array(array($this->prefix('@panel'), 'onRequest')));
286
			}
287
		}
288
289
		if (class_exists('Tracy\Debugger')) {
290
			Kdyby\Translation\Diagnostics\Panel::registerBluescreen();
291
		}
292
293
		$extractor = $builder->getDefinition($this->prefix('extractor'));
294 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...
295
			Validators::assert($meta, 'string:2..');
296
297
			$extractor->addSetup('addExtractor', array($meta, '@' . $extractorId));
298
299
			$builder->getDefinition($extractorId)->setAutowired(FALSE)->setInject(FALSE);
300
		}
301
302
		$writer = $builder->getDefinition($this->prefix('writer'));
303 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...
304
			Validators::assert($meta, 'string:2..');
305
306
			$writer->addSetup('addDumper', array($meta, '@' . $dumperId));
307
308
			$builder->getDefinition($dumperId)->setAutowired(FALSE)->setInject(FALSE);
309
		}
310
311
		$this->loaders = array();
312
		foreach ($builder->findByTag(self::TAG_LOADER) as $loaderId => $meta) {
313
			Validators::assert($meta, 'string:2..');
314
			$builder->getDefinition($loaderId)->setAutowired(FALSE)->setInject(FALSE);
315
			$this->loaders[$meta] = $loaderId;
316
		}
317
318
		$builder->getDefinition($this->prefix('loader'))
319
			->addSetup('injectServiceIds', array($this->loaders))
320
			->setInject(FALSE);
321
322
		foreach ($this->compiler->getExtensions() as $extension) {
323
			if (!$extension instanceof ITranslationProvider) {
324
				continue;
325
			}
326
327
			$config['dirs'] = array_merge($config['dirs'], array_values($extension->getTranslationResources()));
328
		}
329
330
		if ($dirs = array_values(array_filter($config['dirs'], Callback::closure('is_dir')))) {
331
			foreach ($dirs as $dir) {
332
				$builder->addDependency($dir);
333
			}
334
335
			$this->loadResourcesFromDirs($dirs);
336
		}
337
	}
338
339
340
341
	protected function beforeCompileLogging(array $config)
342
	{
343
		$builder = $this->getContainerBuilder();
344
		$translator = $builder->getDefinition($this->prefix('default'));
345
346
		if ($config['logging'] === TRUE) {
347
			$translator->addSetup('injectPsrLogger');
348
349
		} elseif (is_string($config['logging'])) { // channel for kdyby/monolog
350
			$translator->addSetup('injectPsrLogger', [
351
				new Statement('@Kdyby\Monolog\Logger::channel', [$config['logging']]),
352
			]);
353
354
		} elseif ($config['logging'] !== NULL) {
355
			throw new Kdyby\Translation\InvalidArgumentException(sprintf(
356
				"Invalid config option for logger. Valid are TRUE for general psr/log or string for kdyby/monolog channel, but %s was given",
357
				$config['logging']
358
			));
359
		}
360
	}
361
362
363
364
	protected function loadResourcesFromDirs($dirs)
365
	{
366
		$builder = $this->getContainerBuilder();
367
		$config = $this->getConfig();
368
369
		$whitelistRegexp = Kdyby\Translation\Translator::buildWhitelistRegexp($config['whitelist']);
370
		$translator = $builder->getDefinition($this->prefix('default'));
371
372
		foreach ($this->loaders as $format => $_) {
373
			foreach (Finder::findFiles('*.*.' . $format)->from($dirs) as $file) {
374
				/** @var \SplFileInfo $file */
375
				if (!$m = Strings::match($file->getFilename(), '~^(?P<domain>.*?)\.(?P<locale>[^\.]+)\.' . preg_quote($format) . '$~')) {
376
					continue;
377
				}
378
379
				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...
380
					continue; // ignore in production mode, there is no need to pass the ignored resources
381
				}
382
383
				$this->validateResource($format, $file->getPathname(), $m['locale'], $m['domain']);
384
				$translator->addSetup('addResource', array($format, $file->getPathname(), $m['locale'], $m['domain']));
385
				$builder->addDependency($file->getPathname());
386
			}
387
		}
388
	}
389
390
391
392
	protected function validateResource($format, $file, $locale, $domain)
393
	{
394
		$builder = $this->getContainerBuilder();
395
396
		if (!isset($this->loaders[$format])) {
397
			return;
398
		}
399
400
		try {
401
			$def = $builder->getDefinition($this->loaders[$format]);
402
			$refl = Reflection\ClassType::from($def->factory ? $def->factory->entity : $def->class);
403
			if (($method = $refl->getConstructor()) && $method->getNumberOfRequiredParameters() > 1) {
404
				return;
405
			}
406
407
			$loader = $refl->newInstance();
408
			if (!$loader instanceof LoaderInterface) {
409
				return;
410
			}
411
412
		} catch (\ReflectionException $e) {
413
			return;
414
		}
415
416
		try {
417
			$loader->load($file, $locale, $domain);
418
419
		} catch (\Exception $e) {
420
			throw new InvalidResourceException("Resource $file is not valid and cannot be loaded.", 0, $e);
421
		}
422
	}
423
424
425
426
	public function afterCompile(Code\ClassType $class)
427
	{
428
		$initialize = $class->methods['initialize'];
429
		if (class_exists('Tracy\Debugger')) {
430
			$initialize->addBody('Kdyby\Translation\Diagnostics\Panel::registerBluescreen();');
431
		}
432
	}
433
434
435
436
	private function isRegisteredConsoleExtension()
437
	{
438
		foreach ($this->compiler->getExtensions() as $extension) {
439
			if ($extension instanceof Kdyby\Console\DI\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...
440
				return TRUE;
441
			}
442
		}
443
444
		return FALSE;
445
	}
446
447
448
449
	/**
450
	 * {@inheritdoc}
451
	 */
452
	public function getConfig(array $defaults = NULL, $expand = TRUE)
0 ignored issues
show
Unused Code introduced by
The parameter $defaults is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $expand is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
453
	{
454
		return parent::getConfig($this->defaults) + array('fallback' => array('en_US'));
455
	}
456
457
458
459
	/**
460
	 * @param string|\stdClass $statement
461
	 * @return Nette\DI\Statement[]
462
	 */
463
	public static function filterArgs($statement)
464
	{
465
		return Nette\DI\Compiler::filterArguments(array(is_string($statement) ? new Nette\DI\Statement($statement) : $statement));
466
	}
467
468
469
470
	/**
471
	 * @param \Nette\Configurator $configurator
472
	 */
473
	public static function register(Nette\Configurator $configurator)
474
	{
475
		$configurator->onCompile[] = function ($config, Nette\DI\Compiler $compiler) {
476
			$compiler->addExtension('translation', new TranslationExtension());
477
		};
478
	}
479
480
}
481