Passed
Push — master ( bb74df...01777c )
by Jakub
02:24
created

src/Loaders/FileLoader.php (11 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
declare(strict_types=1);
3
4
namespace Nexendrie\Translation\Loaders;
5
6
use Nette\Utils\Finder,
7
    Nette\Utils\Strings,
8
    Nexendrie\Translation\Resolvers\ILocaleResolver,
9
    Nexendrie\Translation\Resolvers\ManualLocaleResolver,
10
    Nexendrie\Translation\InvalidFolderException,
11
    Nexendrie\Translation\FolderNotSetException;
12
13
/**
14
 * Generic file translations loader
15
 * Loads texts from {$this->extension} files
16
 * You need to define method parseFile() which processes individual file
17
 *
18
 * @author Jakub Konečný
19
 * @property string $defaultLang
20
 * @property string $lang
21
 * @property array $texts
22
 * @property string[] $folders
23
 * @property-read array $resources
24
 */
25 1
abstract class FileLoader implements ILoader {
26 1
  use \Nette\SmartObject;
27
  
28
  /** @var string */
29
  protected $defaultLang = "en";
30
  /** @var string|NULL */
31
  protected $loadedLang = NULL;
32
  /** @var array */
33
  protected $texts = [];
34
  /** @var string[] */
35
  protected $folders = [];
36
  /** @var ILocaleResolver */
37
  protected $resolver;
38
  /** @var array */
39
  protected $resources = [];
40
  /** @var string */
41
  protected $extension;
42
  
43
  /**
44
   * @param ILocaleResolver $resolver
45
   * @param string[] $folders
46
   */
47
  function __construct(ILocaleResolver $resolver = NULL, array $folders = []) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
48 1
    $this->setFolders($folders);
49 1
    $this->resolver = $resolver ?? new ManualLocaleResolver;
50 1
  }
51
  
52
  function getLang(): string {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
53 1
    return $this->resolver->resolve() ?? $this->defaultLang;
54
  }
55
  
56
  function setLang(string $lang) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
57 1
    if(method_exists($this->resolver, "setLang")) {
58 1
      $this->resolver->setLang($lang);
59
    }
60 1
  }
61
  
62
  function getDefaultLang(): string {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
63 1
    return $this->defaultLang;
64
  }
65
  
66
  function setDefaultLang(string $defaultLang) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
67 1
    $this->defaultLang = $defaultLang;
68 1
  }
69
  
70
  /**
71
   * @return string[]
72
   */
73
  function getFolders(): array {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
74 1
    return $this->folders;
75
  }
76
  
77
  /**
78
   * @param string[] $folders
79
   * @throws InvalidFolderException
80
   */
81
  function setFolders(array $folders) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
82 1
    foreach($folders as $folder) {
83 1
      if(!is_dir($folder)) {
84 1
        throw new InvalidFolderException("Folder $folder does not exist.");
85
      }
86 1
      $this->folders[] = $folder;
87
    }
88 1
  }
89
  
90
  protected function addResource(string $filename, string $domain): void {
91 1
    if(!isset($this->resources[$domain]) OR !in_array($filename, $this->resources[$domain])) {
92 1
      $this->resources[$domain][] = $filename;
93
    }
94 1
  }
95
  
96
  function getResources(): array {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
97 1
    return $this->resources;
98
  }
99
  
100
  /**
101
   * Parse individual file
102
   */
103
  abstract protected function parseFile(string $filename): array;
104
  
105
  /**
106
   * Load texts from one text domain
107
   */
108
  protected function loadDomain(string $name): array {
109 1
    $return = [];
110 1
    $defaultLang = $this->defaultLang;
111 1
    $extension = $this->extension;
112 1
    $defaultFilename = "$name.$defaultLang.$extension";
113 1
    $files = Finder::findFiles($defaultFilename)
114 1
      ->from($this->folders);
115
    /** @var \SplFileInfo $file */
116 1
    foreach($files as $file) {
117 1
      $default = $this->parseFile($file->getPathname());
118 1
      $this->addResource($file->getPathname(), $name);
119 1
      $lang = [];
120 1
      $filename = "$name.$this->lang.$extension";
121 1
      $filename = str_replace($defaultFilename, $filename, $file->getPathname());
122 1
      if($this->lang != $defaultLang AND is_file($filename)) {
123 1
        $lang = $this->parseFile($filename);
124 1
        $this->addResource($filename, $name);
125
      }
126 1
      $return = array_merge($return, $default, $lang);
127
    }
128 1
    return $return;
129
  }
130
  
131
  /**
132
   * Load all texts
133
   *
134
   * @throws FolderNotSetException
135
   */
136
  protected function loadTexts(): void {
137 1
    if($this->lang === $this->loadedLang) {
138 1
      return;
139
    }
140 1
    if(!count($this->folders)) {
141 1
      throw new FolderNotSetException("Folder for translations was not set.");
142
    }
143 1
    $default = $this->defaultLang;
144 1
    $this->resources = $texts = [];
145 1
    $extension = $this->extension;
146 1
    $files = Finder::findFiles("*.$default.$extension")
147 1
      ->from($this->folders);
148
    /** @var \SplFileInfo $file */
149 1
    foreach($files as $file) {
150 1
      $domain = $file->getBasename(".$default.$extension");
151 1
      $texts[$domain] = $this->loadDomain($domain);
152
    }
153 1
    $this->texts = $texts;
154 1
    $this->loadedLang = $this->lang;
155 1
  }
156
  
157
  function getTexts(): array {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
158 1
    $this->loadTexts();
159 1
    return $this->texts;
160
  }
161
  
162
  function getResolverName(): string {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
163 1
    $class = get_class($this->resolver);
164 1
    return (string) Strings::after($class, '\\', -1);
165
  }
166
  
167
  protected function getLanguageFilenameMask(): string {
168 1
    return "*.$this->extension";
169
  }
170
  
171
  /**
172
   * @return string[]
173
   * @throws FolderNotSetException
174
   */
175
  function getAvailableLanguages(): array {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
176 1
    if(!count($this->folders)) {
177 1
      throw new FolderNotSetException("Folder for translations was not set.");
178
    }
179 1
    $languages = [];
180 1
    $extension = $this->extension;
181 1
    $files = Finder::findFiles($this->getLanguageFilenameMask())
182 1
      ->from($this->folders);
183
    /** @var \SplFileInfo $file */
184 1
    foreach($files as $file) {
185 1
      $filename = $file->getBasename(".$extension");
186 1
      $lang = Strings::after($filename, ".");
187 1
      if(!in_array($lang, $languages)) {
188 1
        $languages[] = $lang;
189
      }
190
    }
191 1
    return $languages;
192
  }
193
}
194
?>