Files
UNIT3D-Community-Edition/app/Helpers/LanguageCensor.php
HDVinnie 8a9d94e07a update: preslash simple functions
- performance
2020-12-31 12:41:46 -05:00

89 lines
2.5 KiB
PHP

<?php
/**
* NOTICE OF LICENSE.
*
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
* The details is bundled with this project in the file LICENSE.txt.
*
* @project UNIT3D Community Edition
*
* @author HDVinnie <hdinnovations@protonmail.com>
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
*/
namespace App\Helpers;
/**
* Class LanguageCensor.
*
* A class that can redact/replace words.
*/
class LanguageCensor
{
/**
* @var string
*/
private const SPECIAL_CHARS = "<>\n [].;,";
protected static function isSpecial($c)
{
return \str_contains(self::SPECIAL_CHARS, $c);
}
protected static function matchWordIndexes($string, $word)
{
$result = [];
$length = \strlen($word);
$stringLength = \strlen($string);
$pos = \stripos($string, $word, 0);
while ($pos !== false) {
$prev = ($pos === 0) ? ' ' : $string[$pos - 1];
$last = ($pos + $length) < $stringLength ? $string[$pos + $length] : ' ';
if (self::isSpecial($prev) && self::isSpecial($last)) {
$result[] = $pos;
}
$pos = \stripos($string, $word, $pos + $length);
}
return $result;
}
/**
* Censor a text.
*
* @param $source
*
* @return mixed
*/
public static function censor($source)
{
foreach (\config('censor.redact', []) as $word) {
$result = '';
$length = \strlen($source);
$wordLength = \strlen($word);
\assert($wordLength > 0);
$indexes = self::matchWordIndexes($source, $word);
$ignore = 0;
for ($i = 0; $i < $length; $i++) {
if ((\is_countable($indexes) ? \count($indexes) : 0) > 0 && $indexes[0] == $i) {
$match = \substr($source, $indexes[0], $wordLength);
$result .= \sprintf("<span class='censor'>%s</span>", $match);
$ignore = $wordLength - 1;
} elseif ($ignore > 0) {
$ignore--;
} else {
$result .= $source[$i];
}
}
$source = $result;
}
$replaceDict = \config('censor.replace', []);
foreach ($replaceDict as $word => $replacement) {
$source = \str_ireplace($word, $replacement, $source);
}
return $source;
}
}