Pspell   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 89
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 32
c 3
b 0
f 0
dl 0
loc 89
ccs 34
cts 34
cp 1
rs 10
wmc 9

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A errorHandler() 0 3 1
A fromLocale() 0 22 3
A contains() 0 22 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stadly\PasswordPolice\WordList;
6
7
use ErrorException;
8
use InvalidArgumentException;
9
use RuntimeException;
10
use Stadly\PasswordPolice\CharTree;
11
use Stadly\PasswordPolice\Formatter;
12
use Stadly\PasswordPolice\Formatter\Combiner;
13
use Stadly\PasswordPolice\WordList;
14
15
final class Pspell implements WordList
16
{
17
    /**
18
     * @var int Pspell dictionary.
19
     */
20
    private $pspell;
21
22
    /**
23
     * @var Formatter Formatter.
24
     */
25
    private $formatter;
26
27
    /**
28
     * Pspell dictionaries are case-sensitive.
29
     * Specify case formatters if tests should also be performed for the word formatted to other cases.
30
     *
31
     * @param int $pspell Pspell dictionary link, as generated by `pspell_new` and friends.
32
     * @param array<Formatter> $formatters Formatters.
33
     */
34 9
    public function __construct(int $pspell, array $formatters = [])
35
    {
36 9
        $this->pspell = $pspell;
37 9
        $this->formatter = new Combiner($formatters);
38 9
    }
39
40
    /**
41
     * Pspell dictionaries are case-sensitive.
42
     * Specify case formatters if tests should also be performed for the word formatted to other cases.
43
     *
44
     * @param string $locale Locale of the pspell dictionary to load. For example `en-US` or `de`.
45
     * @param array<Formatter> $formatters Formatters.
46
     * @throws RuntimeException If the pspell dictionary could not be loaded.
47
     * @return self Pspell word list.
48
     */
49 11
    public static function fromLocale(string $locale, array $formatters = []): self
50
    {
51 11
        if (preg_match('{^[a-z]{2}(?:[-_][A-Z]{2})?$}', $locale) !== 1) {
52 2
            throw new InvalidArgumentException(sprintf('%s is not a valid locale.', $locale));
53
        }
54
55 9
        set_error_handler([self::class, 'errorHandler']);
56
        try {
57 9
            $pspell = pspell_new($locale);
58 2
        } catch (ErrorException $exception) {
59 2
            throw new RuntimeException(
60 2
                'An error occurred while loading the word list: ' . $exception->getMessage(),
61 2
                /*code*/0,
62 2
                $exception
63
            );
64 7
        } finally {
65 9
            restore_error_handler();
66
        }
67
68 7
        assert($pspell !== false);
69
70 7
        return new self($pspell, $formatters);
71
    }
72
73 8
    public function contains(string $word): bool
74
    {
75 8
        foreach ($this->formatter->apply(CharTree::fromString($word)) as $formattedWord) {
76 8
            set_error_handler([self::class, 'errorHandler']);
77
            try {
78 8
                $check = pspell_check($this->pspell, $formattedWord);
79 2
            } catch (ErrorException $exception) {
80 2
                throw new RuntimeException(
81 2
                    'An error occurred while using the word list: ' . $exception->getMessage(),
82 2
                    /*code*/0,
83 2
                    $exception
84
                );
85 6
            } finally {
86 8
                restore_error_handler();
87
            }
88
89 6
            if ($check) {
90 6
                return true;
91
            }
92
        }
93
94 4
        return false;
95
    }
96
97
    // phpcs:disable SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod
98
    /**
99
     * @throws ErrorException Error converted to an exception.
100
     */
101 4
    private static function errorHandler(int $severity, string $message, string $filename, int $line): bool
102
    {
103 4
        throw new ErrorException($message, /*code*/0, $severity, $filename, $line);
104
    }
105
    // phpcs:enable
106
}
107