Completed
Pull Request — master (#90)
by Jonathan
02:06
created

Converse::addRules()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 16
nc 8
nop 2
dl 0
loc 28
ccs 16
cts 16
cp 1
crap 6
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Inflector;
6
7
use Doctrine\Inflector\Rules\Ruleset;
8
use Doctrine\Inflector\Rules\Uninflected;
9
use function array_keys;
10
use function array_merge;
11
use function implode;
12
use function is_array;
13
use function preg_match;
14
use function preg_replace;
15
use function strtolower;
16
use function substr;
17
use function ucfirst;
18
19
abstract class Converse
20
{
21
    /** @var Uninflected */
22
    protected $uninflected;
23
24
    /** @var mixed[] */
25
    protected $rules = [];
26
27
    /** @var string[] */
28
    protected $cache = [];
29
30 526
    public function __construct(Uninflected $uninflected)
31
    {
32 526
        $this->uninflected = $uninflected;
33 526
        $this->rules       = $this->getRuleset()->toArray();
34
35 526
        $this->initializeRules();
36 526
    }
37
38
    abstract public function getRuleset() : Ruleset;
39
40
    /**
41
     * Adds custom inflection rules.
42
     *
43
     * $singularizer->addRules(['/^(inflect)or$/i' => '\1ables']);
44
     * $pluralizer->addRules([
45
     *     'rules' => ['/^(inflect)ors$/i' => '\1ables'],
46
     *     'uninflected' => ['dontinflectme'],
47
     *     'irregular' => ['red' => 'redlings']
48
     * ]);
49
     *
50
     * @param mixed[] $rules An array of rules to be added.
51
     *                                new rules that are being defined in $rules.
52
     * @param bool    $reset If true, will unset default inflections for all
53
     *                       new rules that are being defined in $rules.
54
     */
55 4
    public function addRules(array $rules, bool $reset = false) : void
56
    {
57 4
        foreach ($rules as $rule => $pattern) {
58 4
            if (! is_array($pattern)) {
59 2
                continue;
60
            }
61
62 4
            if ($reset) {
63 1
                $this->rules[$rule] = $pattern;
64
            } else {
65 3
                $this->rules[$rule] = ($rule === 'uninflected')
66 2
                    ? array_merge($pattern, $this->rules[$rule])
67 3
                    : $pattern + $this->rules[$rule];
68
            }
69
70 4
            unset($rules[$rule], $this->rules['cache' . ucfirst($rule)]);
71
72 4
            if (! isset($this->rules['merged'][$rule])) {
73 4
                continue;
74
            }
75
76 4
            unset($this->rules['merged'][$rule]);
77
        }
78
79 4
        $this->cache          = [];
80 4
        $this->rules['rules'] = $rules + $this->rules['rules'];
81
82 4
        $this->initializeRules();
83 4
    }
84
85 510
    public function inflect(string $word) : string
86
    {
87 510
        if (isset($this->cache[$word])) {
88
            return $this->cache[$word];
89
        }
90
91 510
        if (preg_match('/(.*)\\b(' . $this->rules['cacheIrregular'] . ')$/i', $word, $regs)) {
92 93
            $this->cache[$word] = $regs[1] . $word[0] . substr($this->rules['merged']['irregular'][strtolower($regs[2])], 1);
93
94 93
            return $this->cache[$word];
95
        }
96
97 420
        if (preg_match('/^(' . $this->rules['cacheUninflected'] . ')$/i', $word, $regs)) {
98 244
            $this->cache[$word] = $word;
99
100 244
            return $word;
101
        }
102
103 179
        foreach ($this->rules['rules'] as $rule => $replacement) {
104 179
            if (preg_match($rule, $word)) {
105 177
                $this->cache[$word] = preg_replace($rule, $replacement, $word);
106
107 179
                return $this->cache[$word];
108
            }
109
        }
110
111 2
        $this->cache[$word] = $word;
112
113 2
        return $word;
114
    }
115
116 526
    protected function initializeRules() : void
117
    {
118 526
        if (! isset($this->rules['merged']['uninflected'])) {
119 526
            $this->rules['merged']['uninflected'] = array_merge(
120 526
                $this->rules['uninflected'],
121 526
                $this->uninflected->getUninflected()
122
            );
123
        }
124
125 526
        $this->initializeIrregular();
126
127 526
        if (isset($this->rules['cacheUninflected']) && isset($this->rules['cacheIrregular'])) {
128 3
            return;
129
        }
130
131 526
        $this->rules['cacheUninflected'] = '(?:' . implode('|', $this->rules['merged']['uninflected']) . ')';
132 526
        $this->rules['cacheIrregular']   = '(?:' . implode('|', array_keys($this->rules['merged']['irregular'])) . ')';
133 526
    }
134
135
    abstract protected function initializeIrregular() : void;
136
}
137