Passed
Push — master ( da3383...67a80d )
by Jianhua
03:27
created

initTireSingle()   B

Complexity

Conditions 9
Paths 1

Size

Total Lines 31
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 9
eloc 21
c 1
b 0
f 1
nc 1
nop 0
dl 0
loc 31
rs 8.0555
1
<?php
2
3
use Illuminate\Database\Eloquent\Model;
4
use App\Foundation\Tire;
5
use Illuminate\Support\Facades\Cache;
6
use App\Model\Admin\SensitiveWord;
7
8
function parseEntityFieldParams($params)
9
{
10
    $items = explode("\n", $params);
11
    return array_map(function ($item) {
12
        return explode("=", $item);
13
    }, $items);
14
}
15
16
function isChecked($value, $options)
17
{
18
    return in_array($value, explode(',', $options), true);
19
}
20
21
function xssFilter(Model $data)
22
{
23
    $attributes = $data->getAttributes();
24
    foreach ($attributes as &$v) {
25
        if (is_string($v)) {
26
            $v = htmlspecialchars($v, ENT_QUOTES | ENT_SUBSTITUTE, 'utf-8');
27
        }
28
    }
29
    $data->setRawAttributes($attributes);
30
}
31
32
function initTire()
33
{
34
    return Cache::rememberForever('sensitive_words_tire', function () {
35
        $tires = [];
36
37
        foreach (['noun', 'verb', 'exclusive'] as $v) {
38
            $words = SensitiveWord::query()->select($v)->where($v, '<>', '')->get();
39
40
            $tire = new Tire();
41
            foreach ($words as $k) {
42
                $tire->add($k->$v);
43
            }
44
            $tires[$v] = $tire;
45
        }
46
47
        return $tires;
48
    });
49
}
50
51
function initTireSingle()
52
{
53
    return Cache::rememberForever('sensitive_words_tire_single', function () {
54
        $types = SensitiveWord::query()->select('type')->groupBy('type')->get();
55
        $tire = new Tire();
56
        foreach ($types as $type) {
57
            $words = SensitiveWord::query()->where('type', $type->type)->get();
58
            $nouns = [];
59
            $verbs = [];
60
            $exclusives = [];
61
            foreach ($words as $word) {
62
                if ($word->noun !== '') {
0 ignored issues
show
Bug Best Practice introduced by
The property noun does not exist on App\Model\Admin\SensitiveWord. Since you implemented __get, consider adding a @property annotation.
Loading history...
63
                    $nouns[] = $word->noun;
64
                } elseif ($word->verb !== '') {
0 ignored issues
show
Bug Best Practice introduced by
The property verb does not exist on App\Model\Admin\SensitiveWord. Since you implemented __get, consider adding a @property annotation.
Loading history...
65
                    $verbs[] = $word->verb;
66
                } elseif ($word->exclusive !== '') {
0 ignored issues
show
Bug Best Practice introduced by
The property exclusive does not exist on App\Model\Admin\SensitiveWord. Since you implemented __get, consider adding a @property annotation.
Loading history...
67
                    $exclusives[] = $word->exclusive;
68
                }
69
            }
70
71
            foreach ($exclusives as $k) {
72
                $tire->add($k);
73
            }
74
            foreach ($verbs as $vk) {
75
                foreach ($nouns as $nk) {
76
                    $tire->add($vk . $nk);
77
                }
78
            }
79
        }
80
81
        return $tire;
82
    });
83
}
84
85
function mapTypeToVerbOfSensitiveWords()
86
{
87
    return Cache::rememberForever('sensitive_verb_words', function () {
88
        $words = SensitiveWord::query()->select('verb', 'type')->where('verb', '<>', '')->get();
89
90
        $data = [];
91
        foreach ($words as $word) {
92
            $data[$word->type <> '' ? $word->type : 'others'][] = $word->verb;
93
        }
94
95
        return $data;
96
    });
97
}
98
99
/**
100
 * 敏感词检查
101
 *
102
 * @param string $text 待检查文本
103
 * @param string $type 名词、动词的检测方法。默认为 join 。join:名词和动词相连组合在一起视为违规 all:名词和动词只要同时出现即为违规
104
 * @param null $mode 检查模式。仅 $type 为 all 时有效。默认名词、动词、专用词都检查,显示可指定为 noun verb exclusive
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $mode is correct as it would always require null to be passed?
Loading history...
105
 * @return array
106
 */
107
function checkSensitiveWords(string $text, $type = 'join', $mode = null)
108
{
109
    if (!is_null($mode) && !in_array($mode, ['noun', 'verb', 'exclusive'])) {
0 ignored issues
show
introduced by
The condition is_null($mode) is always true.
Loading history...
110
        throw new \InvalidArgumentException('mode参数无效,只能为null值、noun、exclusive');
111
    }
112
113
    if ($type === 'join') {
114
        $tire = initTireSingle();
115
        $result = $tire->seek($text);
116
        return $result;
117
    }
118
119
    $tires = initTire();
120
    if (!is_null($mode)) {
121
        return $tires[$mode]->seek($text);
122
    }
123
124
    $result = [];
125
    $return = [];
126
    foreach ($tires as $k => $tire) {
127
        $result[$k] = $tire->seek($text);
128
    }
129
    if (!empty($result['noun']) && !empty($result['verb'])) {
130
        $data = mapTypeToVerbOfSensitiveWords();
131
        foreach ($result['noun'] as $noun) {
132
            $type = Cache::rememberForever('sensitive_words_noun_type:' . $noun, function () use ($noun) {
133
                return SensitiveWord::query()->where('noun', $noun)->value('type');
134
            });
135
            $type = $type ? $type : 'others';
136
            $verbs = array_intersect($data[$type], $result['verb']);
137
            if (!empty($verbs)) {
138
                array_push($verbs, $noun);
139
                $return[] = implode(' ', $verbs);
140
            }
141
        }
142
    }
143
    return array_merge($return, $result['exclusive']);
144
}
145