Words::getScore()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace detox\core;
4
5
6
use detox\dataset\SetContract;
7
use detox\source\Text;
8
9
/**
10
 * Class Words
11
 * @package detox\core
12
 *
13
 * @property Text text
14
 */
15
class Words
16
{
17
18
    public const MAX_SCORE        = 1;
19
    public const ASTERISKS_MIDDLE = 0.8;
20
    public const ASTERISKS_LEFT   = 0.5;
21
    public const ASTERISKS_RIGHT  = 0.6;
22
23
    protected $dataSet;
24
    protected $score = 0;
25
    protected $text;
26
27
    /**
28
     * Words constructor.
29
     *
30
     * @param SetContract $set
31
     * @param Text $text
32
     */
33
    public function __construct(SetContract $set, Text $text)
34
    {
35
        $this->dataSet = $set;
36
        $this->text    = $text;
37
    }
38
39
    /**
40
     * Finds bad words from *Set and setting score/replace
41
     */
42
    public function processWords() : void
43
    {
44
        // to match lower case letters in words set array
45
        $lowerSource = $this->addLowSpaces($this->text->getString());
46
        /**
47
         * 1st level checking discrete words with spaces
48
         * @var string $points
49
         * @var array $words
50
         */
51
        foreach ($this->dataSet->getWords() as $points => $words) {
52
            foreach ($words as $word) {
53
                if (mb_strpos($lowerSource, ' ' . $word . ' ') !== false) {
54
                    $this->score += (float)$points;
55
                    if ($this->text->isReplaceable()) {
56
                        $this->replace($word);
57
                    }
58
                }
59
            }
60
        }
61
        if ($this->score < self::ASTERISKS_MIDDLE) {
62
            // 2nd level checking the worst (3 highest levels) words with probability to be mutated ex.: shittyass, crappish, unfuckkish etc
63
            $slice = array_slice($this->dataSet->getWords(), 0, 3);
64
            foreach ($slice as $points => $words) {
65
                foreach ($words as $word) {
66
                    if (mb_strpos($lowerSource, $word) !== false) {
67
                        $this->score += (float)$points;
68
                        if ($this->text->isReplaceable()) {
69
                            $this->replace($word);
70
                        }
71
                    }
72
                }
73
            }
74
        }
75
        if ($this->score >= self::MAX_SCORE) {
76
            $this->score = self::MAX_SCORE;
77
        }
78
    }
79
80
    /**
81
     * Finds bad words with asterisks and setting score/replace
82
     */
83
    public function processPatterns() : void
84
    {
85
        $lowerSource = $this->addLowSpaces($this->text->getString());
86
        if (preg_match_all('/\s(([\w]+)[\*]+([\w]+))\s/', $lowerSource, $matches) > 0) {
87
            $this->score += (self::ASTERISKS_MIDDLE * count($matches[0]));
88
            if ($this->text->isReplaceable()) {
89
                $this->replaceMatches($matches);
90
            }
91
        }
92
        $lowerSource = $this->addLowSpaces($this->text->getString());
93
        if (preg_match_all('/\s(([\w]+)[\*]+)\s/', $lowerSource, $matches) > 0) {
94
            $this->score += (self::ASTERISKS_RIGHT * count($matches[0]));
95
            if ($this->text->isReplaceable()) {
96
                $this->replaceMatches($matches);
97
            }
98
        }
99
        $lowerSource = $this->addLowSpaces($this->text->getString());
100
        if (preg_match_all('/\s([\*]+([\w]+))\s/', $lowerSource, $matches) > 0) {
101
            $this->score += (self::ASTERISKS_LEFT * count($matches[0]));
102
            if ($this->text->isReplaceable()) {
103
                $this->replaceMatches($matches);
104
            }
105
        }
106
    }
107
108
    /**
109
     * @param SetContract $set
110
     */
111
    public function setData(SetContract $set) : void
112
    {
113
        $this->dataSet = $set;
114
    }
115
116
    /**
117
     * @return float
118
     */
119
    public function getScore() : float
120
    {
121
        return $this->score;
122
    }
123
124
    /**
125
     * @param float $score
126
     */
127
    public function setScore(float $score) : void
128
    {
129
        $this->score = $score;
130
    }
131
132
    /**
133
     * @param string $str
134
     * @return string
135
     */
136
    protected function addLowSpaces(string $str) : string
137
    {
138
        return ' ' . mb_strtolower($str) . ' ';
139
    }
140
141
    /**
142
     * @param string $phrase word or phrase to replace
143
     */
144
    protected function replace(string $phrase) : void
145
    {
146
        // todo: slice the word with replacement to prevent WoRd -> word transformations
147
        $this->text->setString(str_replace($phrase, $this->text->getPrefix() . $this->text->getReplaceChars() . $this->text->getPostfix(),
148
            mb_strtolower($this->text->getString())));
149
    }
150
151
    private function replaceMatches(array $matches) : void
152
    {
153
        /** @var array $matches */
154
        foreach ($matches[0] as $word) {
155
            $this->replace($word);
156
        }
157
    }
158
159
    /**
160
     * Setter for convenient DI with Text object and it's properties
161
     * @param Text $text
162
     */
163
    public function setText(Text $text) : void
164
    {
165
        $this->text = $text;
166
    }
167
168
    /**
169
     * @return Text
170
     */
171
    public function getText() : Text
172
    {
173
        return $this->text;
174
    }
175
176
    /**
177
     * @return SetContract
178
     */
179
    public function getDataSet() : SetContract
180
    {
181
        return $this->dataSet;
182
    }
183
184
    /**
185
     * @param SetContract $dataSet
186
     */
187
    public function setDataSet(SetContract $dataSet) : void
188
    {
189
        $this->dataSet = $dataSet;
190
    }
191
}