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; } }