Files
SkinbaseNova/app/Services/Moderation/Rules/ExcessivePunctuationRule.php

54 lines
1.8 KiB
PHP

<?php
namespace App\Services\Moderation\Rules;
use App\Contracts\Moderation\ModerationRuleInterface;
class ExcessivePunctuationRule implements ModerationRuleInterface
{
public function analyze(string $content, string $normalized, array $context = []): array
{
$config = app('config')->get('content_moderation.excessive_punctuation', []);
$length = mb_strlen($content);
if ($length < (int) ($config['min_length'] ?? 20)) {
return [];
}
$exclamationRatio = substr_count($content, '!') / max($length, 1);
$questionRatio = substr_count($content, '?') / max($length, 1);
$capsRatio = $this->capsRatio($content);
$symbolBurst = preg_match('/[!?$%*@#._\-]{6,}/', $content) === 1;
if (
$exclamationRatio <= (float) ($config['max_exclamation_ratio'] ?? 0.1)
&& $questionRatio <= (float) ($config['max_question_ratio'] ?? 0.1)
&& $capsRatio <= (float) ($config['max_caps_ratio'] ?? 0.7)
&& ! $symbolBurst
) {
return [];
}
return [[
'rule' => 'excessive_punctuation',
'score' => app('config')->get('content_moderation.weights.excessive_punctuation', 15),
'reason' => 'Contains excessive punctuation, all-caps patterns, or symbol spam',
'links' => [],
'domains' => [],
'keywords' => [],
]];
}
private function capsRatio(string $content): float
{
preg_match_all('/\p{Lu}/u', $content, $upperMatches);
preg_match_all('/\p{L}/u', $content, $letterMatches);
$letters = count($letterMatches[0] ?? []);
if ($letters === 0) {
return 0.0;
}
return count($upperMatches[0] ?? []) / $letters;
}
}