FileLoader   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 169
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 169
ccs 71
cts 71
cp 1
c 0
b 0
f 0
wmc 29
lcom 1
cbo 7
rs 10

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getLang() 0 3 1
A setLang() 0 5 2
A getDefaultLang() 0 3 1
A setDefaultLang() 0 3 1
A getFolders() 0 3 1
A setFolders() 0 8 3
A addResource() 0 5 3
A getResources() 0 3 1
parseFile() 0 1 ?
B loadDomain() 0 22 4
A loadTexts() 0 20 4
A getTexts() 0 4 1
A getResolverName() 0 4 1
A getLanguageFilenameMask() 0 3 1
A getAvailableLanguages() 0 18 4
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 {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
FileLoader does not seem to conform to the naming convention (^Abstract|Factory$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
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
0 ignored issues
show
Documentation introduced by Jakub Konečný
Should the type for parameter $resolver not be null|ILocaleResolver?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
45
   * @param string[] $folders
46
   */
47
  public function __construct(ILocaleResolver $resolver = NULL, array $folders = []) {
48 1
    $this->setFolders($folders);
49 1
    $this->resolver = $resolver ?? new ManualLocaleResolver;
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Inline shorthand IF statement must be declared on a single line
Loading history...
50 1
  }
51
  
52
  public function getLang(): string {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Expected 1 space after closing parenthesis; found 0
Loading history...
53 1
    return $this->resolver->resolve() ?? $this->defaultLang;
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Inline shorthand IF statement must be declared on a single line
Loading history...
54
  }
55
  
56
  public function setLang(string $lang) {
57 1
    if(method_exists($this->resolver, "setLang")) {
58 1
      $this->resolver->setLang($lang);
0 ignored issues
show
Bug introduced by Jakub Konečný
It seems like you code against a concrete implementation and not the interface Nexendrie\Translation\Resolvers\ILocaleResolver as the method setLang() does only exist in the following implementations of said interface: Nexendrie\Translation\Re...vironmentLocaleResolver, Nexendrie\Translation\Re...rs\ManualLocaleResolver, Nexendrie\Translation\Re...s\SessionLocaleResolver.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
59
    }
60 1
  }
61
  
62
  public function getDefaultLang(): string {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Expected 1 space after closing parenthesis; found 0
Loading history...
63 1
    return $this->defaultLang;
64
  }
65
  
66
  public function setDefaultLang(string $defaultLang) {
67 1
    $this->defaultLang = $defaultLang;
68 1
  }
69
  
70
  /**
71
   * @return string[]
72
   */
73
  public function getFolders(): array {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Expected 1 space after closing parenthesis; found 0
Loading history...
74 1
    return $this->folders;
75
  }
76
  
77
  /**
78
   * @param string[] $folders
79
   * @throws InvalidFolderException
80
   */
81
  public function setFolders(array $folders) {
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 {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Expected 1 space after closing parenthesis; found 0
Loading history...
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
  public function getResources(): array {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Expected 1 space after closing parenthesis; found 0
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 {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Expected 1 space after closing parenthesis; found 0
Loading history...
109 1
    $return = [];
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 10 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
110 1
    $defaultLang = $this->defaultLang;
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
111 1
    $extension = $this->extension;
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 7 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
112 1
    $defaultFilename = "$name.$defaultLang.$extension";
113 1
    $files = Finder::findFiles($defaultFilename)
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 11 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
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 = [];
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
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 {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Expected 1 space after closing parenthesis; found 0
Loading history...
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;
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 9 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
144 1
    $this->resources = $texts = [];
145 1
    $extension = $this->extension;
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 7 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
146 1
    $files = Finder::findFiles("*.$default.$extension")
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 11 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
147 1
      ->from($this->folders);
148
    /** @var \SplFileInfo $file */
149 1
    foreach($files as $file) {
150 1
      $domain = $file->getBasename(".$default.$extension");
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 9 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
151 1
      $texts[$domain] = $this->loadDomain($domain);
152
    }
153 1
    $this->texts = $texts;
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
154 1
    $this->loadedLang = $this->lang;
155 1
  }
156
  
157
  public function getTexts(): array {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Expected 1 space after closing parenthesis; found 0
Loading history...
158 1
    $this->loadTexts();
159 1
    return $this->texts;
160
  }
161
  
162
  public function getResolverName(): string {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Expected 1 space after closing parenthesis; found 0
Loading history...
163 1
    $class = get_class($this->resolver);
164 1
    return (string) Strings::after($class, '\\', -1);
165
  }
166
  
167
  protected function getLanguageFilenameMask(): string {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Expected 1 space after closing parenthesis; found 0
Loading history...
168 1
    return "*.$this->extension";
169
  }
170
  
171
  /**
172
   * @return string[]
173
   * @throws FolderNotSetException
174
   */
175
  public function getAvailableLanguages(): array {
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Expected 1 space after closing parenthesis; found 0
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())
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
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, ".");
0 ignored issues
show
Coding Style introduced by Jakub Konečný
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
187 1
      if(!in_array($lang, $languages)) {
188 1
        $languages[] = $lang;
189
      }
190
    }
191 1
    return $languages;
192
  }
193
}
194
?>