Completed
Pull Request — master (#9)
by Sander
04:39
created

UniqueWord::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 5
ccs 0
cts 5
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 2
1
<?php
2
3
namespace Edyan\Neuralyzer\Faker\Provider;
4
5
use Faker\Generator;
6
use Faker\Provider\Base;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Edyan\Neuralyzer\Faker\Provider\Base. 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...
7
8
/**
9
 * Class UniqueWord
10
 */
11
class UniqueWord extends Base
12
{
13
    /** @var int */
14
    private $nrOfWordsRequired;
15
16
    /** @var string */
17
    private $language;
18
19
    /** @var array */
20
    protected static $wordList = [];
21
22
    /**
23
     * UniqueWord constructor.
24
     *
25
     * @param Generator $generator
26
     * @param int       $nrOfWordsRequired
27
     * @param string    $language
28
     */
29
    public function __construct(Generator $generator, int $nrOfWordsRequired = 150, string $language = 'en_US')
30
    {
31
        parent::__construct($generator);
32
        $this->nrOfWordsRequired = $nrOfWordsRequired;
33
        $this->language = $language;
34
    }
35
36
    /**
37
     * @return string
38
     */
39
    public function uniqueWord()
40
    {
41
        $this->loadFullDictionary();
42
43
        return static::randomElement(static::$wordList);
44
    }
45
46
    public function loadFullDictionary()
47
    {
48
        static $loaded = false;
49
        if ($loaded === true) {
50
            return;
51
        }
52
        $numberOfWordsRequired = $this->nrOfWordsRequired * 2; // to cater for multiple loops to ensure uniqueness
53
        if (\count(static::$wordList) >= $numberOfWordsRequired) {
54
            return;
55
        }
56
57
        $file = __DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'Dictionary'.DIRECTORY_SEPARATOR.$this->language;
58
        if (!file_exists($file)) {
59
            $loaded = true;
60
61
            return;
62
        }
63
        $fp = fopen($file, 'rb');
64
        while (($line = fgets($fp, 4096)) !== false) {
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fgets() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

64
        while (($line = fgets(/** @scrutinizer ignore-type */ $fp, 4096)) !== false) {
Loading history...
65
            if (strpos($line, '%') !== false) {
66
                continue;
67
            }
68
            $word = trim($line);
69
            if (!\in_array($word, static::$wordList, false)) {
70
                static::$wordList[] = $word;
71
            }
72
            if (\count(static::$wordList) >= $numberOfWordsRequired) {
73
                fclose($fp);
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
                fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
74
                $loaded = true;
75
76
                return;
77
            }
78
        }
79
        fclose($fp);
80
        $loaded = true;
81
        echo 'Dictionary loaded'.PHP_EOL;
82
    }
83
}
84