Issues (6)

src/Vocabulary/Loader.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ReliqArts\DirectTranslator\Vocabulary;
6
7
use DomainException;
8
use Exception;
0 ignored issues
show
This use statement conflicts with another class in this namespace, ReliqArts\DirectTranslator\Vocabulary\Exception. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
9
use ReliqArts\DirectTranslator\ConfigProvider;
10
use ReliqArts\DirectTranslator\Utility\RemoteFileAssistant;
11
use ReliqArts\DirectTranslator\Vocabulary as VocabularyContract;
12
use ReliqArts\DirectTranslator\Vocabulary\Exception\LoadingFailed;
13
use ReliqArts\DirectTranslator\VocabularyLoader;
14
15
final class Loader implements VocabularyLoader
16
{
17
    private const VOCAB_FILE_EXTENSION = 'json';
18
19
    /**
20
     * @var ConfigProvider
21
     */
22
    private $configProvider;
23
24
    /**
25
     * @var RemoteFileAssistant
26
     */
27
    private $remoteFileAssistant;
28
29
    /**
30
     * @var Reader
31
     */
32
    private $reader;
33
34
    /**
35
     * @var Builder
36
     */
37
    private $builder;
38
39
    /**
40
     * VocabularyLoader constructor.
41
     *
42
     * @param ConfigProvider      $configProvider
43
     * @param RemoteFileAssistant $remoteFileAssistant
44
     * @param Reader              $reader
45
     * @param Builder             $builder
46
     */
47
    public function __construct(
48
        ConfigProvider $configProvider,
49
        RemoteFileAssistant $remoteFileAssistant,
50
        Reader $reader,
51
        Builder $builder
52
    ) {
53
        $this->configProvider = $configProvider;
54
        $this->remoteFileAssistant = $remoteFileAssistant;
55
        $this->reader = $reader;
56
        $this->builder = $builder;
57
    }
58
59
    /**
60
     * @param string $key
61
     *
62
     * @throws LoadingFailed
63
     *
64
     * @return VocabularyContract
65
     */
66
    public function load(string $key): VocabularyContract
67
    {
68
        try {
69
            $filePath = $this->getVocabularyFilePath($key);
70
71
            return $this->builder->create($this->reader->read($filePath));
72
        } catch (Exception $exception) {
73
            throw new LoadingFailed(
74
                sprintf('Could not load vocabulary by key: `%s`', $key),
75
                $exception->getCode(),
76
                $exception
77
            );
78
        }
79
    }
80
81
    /**
82
     * @param string $key
83
     *
84
     * @throws DomainException
85
     *
86
     * @return null|string
87
     */
88
    private function getVocabularyFilePath(string $key): ?string
89
    {
90
        $vocabularyDirectories = $this->configProvider->getVocabularyDirectories();
91
92
        foreach ($vocabularyDirectories as $directory) {
93
            $path = sprintf('%s/%s.%s', $directory, $key, self::VOCAB_FILE_EXTENSION);
94
            $vocabularyPath = realpath($path);
95
96
            if (!empty($vocabularyPath)) {
97
                return $vocabularyPath;
98
            }
99
100
            if ($this->pathIsUrl($path) && $this->remoteFileAssistant->fileExists($path)) {
101
                return $path;
102
            }
103
        }
104
105
        throw new DomainException(
106
            sprintf('Vocabulary file not found for key: `%s`.', $key)
107
        );
108
    }
109
110
    /**
111
     * @param string $path
112
     *
113
     * @return bool
114
     */
115
    private function pathIsUrl(string $path): bool
116
    {
117
        return !empty(filter_var($path, FILTER_VALIDATE_URL));
118
    }
119
}
120