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

UniqueWord::loadFullDictionary()   B

Complexity

Conditions 8
Paths 9

Size

Total Lines 36
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
eloc 24
dl 0
loc 36
ccs 0
cts 33
cp 0
rs 8.4444
c 0
b 0
f 0
cc 8
nc 9
nop 0
crap 72
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
     * Get a random element from the loaded dictionary.
38
     *
39
     * @return string
40
     */
41
    public function uniqueWord()
42
    {
43
        $this->loadFullDictionary();
44
45
        return static::randomElement(static::$wordList);
46
    }
47
48
    /**
49
     *  Load the current language dictionary with a lot of words to always be able to get a unique value.
50
     */
51
    public function loadFullDictionary()
52
    {
53
        static $loaded = false;
54
        if ($loaded === true) {
55
            return;
56
        }
57
        $numberOfWordsRequired = $this->nrOfWordsRequired * 2; // to cater for multiple loops to ensure uniqueness
58
        if (\count(static::$wordList) >= $numberOfWordsRequired) {
59
            return;
60
        }
61
62
        $file = __DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'Dictionary'.DIRECTORY_SEPARATOR.$this->language;
63
        if (!file_exists($file)) {
64
            $loaded = true;
65
66
            return;
67
        }
68
        $fp = fopen($file, 'rb');
69
        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

69
        while (($line = fgets(/** @scrutinizer ignore-type */ $fp, 4096)) !== false) {
Loading history...
70
            if (strpos($line, '%') !== false) {
71
                continue;
72
            }
73
            $word = trim($line);
74
            if (!\in_array($word, static::$wordList, false)) {
75
                static::$wordList[] = $word;
76
            }
77
            if (\count(static::$wordList) >= $numberOfWordsRequired) {
78
                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

78
                fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
79
                $loaded = true;
80
81
                return;
82
            }
83
        }
84
        fclose($fp);
85
        $loaded = true;
86
        echo 'Dictionary loaded'.PHP_EOL;
87
    }
88
}
89