FileLoader   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 182
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 12
Bugs 3 Features 1
Metric Value
wmc 29
eloc 84
c 12
b 3
f 1
dl 0
loc 182
ccs 78
cts 78
cp 1
rs 10

15 Methods

Rating   Name   Duplication   Size   Complexity  
A getLang() 0 2 1
A setFolders() 0 8 3
A setDefaultLang() 0 2 1
A getLanguageFilenameMask() 0 2 1
A loadTexts() 0 21 4
A getFolders() 0 2 1
A getResources() 0 2 1
A getAvailableLanguages() 0 19 4
A getDefaultLang() 0 2 1
A setLang() 0 5 2
A getTexts() 0 3 1
A getResolverName() 0 3 1
A __construct() 0 3 1
A loadDomain() 0 21 4
A addResource() 0 3 3
1
<?php
2
declare(strict_types=1);
3
4
namespace Nexendrie\Translation\Loaders;
5
6
use Nette\Utils\Finder;
7
use Nette\Utils\Strings;
8
use Nexendrie\Translation\ILocaleResolver;
9
use Nexendrie\Translation\Resolvers\ManualLocaleResolver;
10
use Nexendrie\Translation\ISettableLocaleResolver;
11
use Nexendrie\Translation\InvalidFolderException;
12
use Nexendrie\Translation\FolderNotSetException;
13
use Nette\Utils\Arrays;
14
use Nexendrie\Translation\IFileLoader;
15
16
/**
17
 * Generic file translations loader
18
 * Loads texts from {$this->extension} files
19
 * You need to define method parseFile() which processes individual file
20
 *
21
 * @author Jakub Konečný
22
 * @property string $defaultLang
23
 * @property string $lang
24
 * @property array $texts
25
 * @property string[] $folders
26
 * @property-read array $resources
27
 * @method void onLanguageChange(FileLoader $loader, string $oldLang, string $newLang)
28
 * @method void onFoldersChange(FileLoader $loader, string[] $folders)
29
 * @method void onLoad(FileLoader $loader, string $lang)
30
 */
31 1
abstract class FileLoader implements IFileLoader {
32 1
  use \Nette\SmartObject;
33
34
  protected const DOMAIN_MASK = "%domain%";
35
  protected const LANGUAGE_MASK = "%language%";
36
  
37
  /** @var string */
38
  protected $defaultLang = "en";
39
  /** @var string|null */
40
  protected $loadedLang = null;
41
  /** @var array */
42
  protected $texts = [];
43
  /** @var string[] */
44
  protected $folders = [];
45
  /** @var ILocaleResolver */
46
  protected $resolver;
47
  /** @var array */
48
  protected $resources = [];
49
  /** @var string */
50
  protected $extension;
51
  /** @var callable[] */
52
  public $onLanguageChange = [];
53
  /** @var callable[] */
54
  public $onFoldersChange = [];
55
  /** @var callable[] */
56
  public $onLoad = [];
57
  
58
  /**
59
   * @param string[] $folders
60
   */
61
  public function __construct(ILocaleResolver $resolver = null, array $folders = []) {
62 1
    $this->setFolders($folders);
63 1
    $this->resolver = $resolver ?? new ManualLocaleResolver();
64 1
  }
65
  
66
  public function getLang(): string {
67 1
    return $this->resolver->resolve() ?? $this->defaultLang;
68
  }
69
  
70
  public function setLang(string $lang): void {
71 1
    if(is_a($this->resolver, ISettableLocaleResolver::class)) {
72 1
      $oldLang = $this->lang;
73 1
      $this->resolver->setLang($lang);
74 1
      $this->onLanguageChange($this, $oldLang, $lang);
75
    }
76 1
  }
77
  
78
  public function getDefaultLang(): string {
79 1
    return $this->defaultLang;
80
  }
81
  
82
  public function setDefaultLang(string $defaultLang): void {
83 1
    $this->defaultLang = $defaultLang;
84 1
  }
85
  
86
  /**
87
   * @return string[]
88
   */
89
  public function getFolders(): array {
90 1
    return $this->folders;
91
  }
92
  
93
  /**
94
   * @param string[] $folders
95
   * @throws InvalidFolderException
96
   */
97
  public function setFolders(array $folders): void {
98 1
    foreach($folders as $folder) {
99 1
      if(!is_dir($folder)) {
100 1
        throw new InvalidFolderException("Folder $folder does not exist.");
101
      }
102 1
      $this->folders[] = $folder;
103
    }
104 1
    $this->onFoldersChange($this, $folders);
105 1
  }
106
  
107
  protected function addResource(string $filename, string $domain): void {
108 1
    if(!isset($this->resources[$domain]) || !in_array($filename, $this->resources[$domain], true)) {
109 1
      $this->resources[$domain][] = $filename;
110
    }
111 1
  }
112
  
113
  public function getResources(): array {
114 1
    return $this->resources;
115
  }
116
  
117
  /**
118
   * Parse individual file
119
   */
120
  abstract protected function parseFile(string $filename): array;
121
  
122
  /**
123
   * Load texts from one text domain
124
   */
125
  protected function loadDomain(string $name): array {
126 1
    $return = [];
127 1
    $defaultLang = $this->defaultLang;
128 1
    $defaultFilename = $this->getLanguageFilenameMask();
129 1
    $defaultFilename = str_replace([static::DOMAIN_MASK, static::LANGUAGE_MASK, ], [$name, $defaultLang, ], $defaultFilename);
0 ignored issues
show
introduced by Jakub Konečný
Line exceeds 120 characters; contains 126 characters
Loading history...
130 1
    $files = Finder::findFiles($defaultFilename)
131 1
      ->from($this->folders);
132
    /** @var \SplFileInfo $file */
133 1
    foreach($files as $file) {
134 1
      $default = $this->parseFile($file->getPathname());
135 1
      $this->addResource($file->getPathname(), $name);
136 1
      $lang = [];
137 1
      $filename = str_replace($defaultLang, $this->lang, $defaultFilename);
138 1
      $filename = str_replace($defaultFilename, $filename, $file->getPathname());
139 1
      if($this->lang != $defaultLang && is_file($filename)) {
140 1
        $lang = $this->parseFile($filename);
141 1
        $this->addResource($filename, $name);
142
      }
143 1
      $return = Arrays::mergeTree($return, Arrays::mergeTree($lang, $default));
144
    }
145 1
    return $return;
146
  }
147
  
148
  /**
149
   * Load all texts
150
   *
151
   * @throws FolderNotSetException
152
   */
153
  protected function loadTexts(): void {
154 1
    if($this->lang === $this->loadedLang) {
155 1
      return;
156
    }
157 1
    if(count($this->folders) === 0) {
158 1
      throw new FolderNotSetException("Folder for translations was not set.");
159
    }
160 1
    $default = $this->defaultLang;
161 1
    $this->resources = $texts = [];
162 1
    $mask = $this->getLanguageFilenameMask();
163 1
    $mask = str_replace([static::DOMAIN_MASK, static::LANGUAGE_MASK, ], ["*", $default, ], $mask);
164 1
    $files = Finder::findFiles($mask)
165 1
      ->from($this->folders);
166
    /** @var \SplFileInfo $file */
167 1
    foreach($files as $file) {
168 1
      $domain = $file->getBasename((string) Strings::after($mask, "*"));
169 1
      $texts[$domain] = $this->loadDomain($domain);
170
    }
171 1
    $this->texts = $texts;
172 1
    $this->loadedLang = $this->lang;
173 1
    $this->onLoad($this, $this->lang);
174 1
  }
175
  
176
  public function getTexts(): array {
177 1
    $this->loadTexts();
178 1
    return $this->texts;
179
  }
180
  
181
  public function getResolverName(): string {
182 1
    $class = get_class($this->resolver);
183 1
    return (string) Strings::after($class, '\\', -1);
184
  }
185
186
  protected function getLanguageFilenameMask(): string {
187 1
    return static::DOMAIN_MASK . "." . static::LANGUAGE_MASK . "." . $this->extension;
188
  }
189
  
190
  /**
191
   * @return string[]
192
   * @throws FolderNotSetException
193
   */
194
  public function getAvailableLanguages(): array {
195 1
    if(count($this->folders) === 0) {
196 1
      throw new FolderNotSetException("Folder for translations was not set.");
197
    }
198 1
    $languages = [];
199 1
    $extension = $this->extension;
200 1
    $mask = $this->getLanguageFilenameMask();
201 1
    $mask = str_replace([static::DOMAIN_MASK, static::LANGUAGE_MASK, ], "*", $mask);
202 1
    $files = Finder::findFiles($mask)
203 1
      ->from($this->folders);
204
    /** @var \SplFileInfo $file */
205 1
    foreach($files as $file) {
206 1
      $filename = $file->getBasename(".$extension");
207 1
      $lang = (string) Strings::after($filename, ".");
208 1
      if(!in_array($lang, $languages, true)) {
209 1
        $languages[] = $lang;
210
      }
211
    }
212 1
    return $languages;
213
  }
214
}
215
?>