dakata__92
Super Moderator
Необходимо ми е да оптимизирам клас, който да скрива чувствително съдържание в различен набор от текстове. Идеята е да се крият пароли, банкови сметки и прочие в текст, преди и след ключова дума. Маскира се при визуализиране на съдържанието. Сегашният код е дървен, неефективен и бавен. Търся дългосрочно и по-добро решение на проблема. Ако някой използва подобен код, ще се радвам да видя как е решил проблема.
PHP:
<?php
class Gdpr extends Model
{
private array $patterns = [
'pass',
'password',
'parola',
'парола',
'code',
'kod',
'код',
'iban',
'card',
'karta',
'карта',
'pin',
'пин',
'smetka',
'сметка',
];
public function __construct()
{
$this->isActiveForUser = auth()->user()->gdpr == 1;
}
/**
* Masking content when previewing.
*
* @param string $string
* @param string $character
* @param string $encoding
* @return string
*/
public function mask(
string $string,
string $character = '*',
string $encoding = 'UTF-8'
): string
{
if (empty($string) || !$this->isActiveForUser) {
return $string;
}
return $this->maskPatterns($string, $character, $encoding);
}
/**
* @param string $string
* @param string $character
* @param string $encoding
* @return string
*/
public function maskPatterns(
string $string,
string $character = '*',
string $encoding = 'UTF-8'
): string
{
$mask = $string;
if (empty($string) || !$this->isActiveForUser) {
return $mask;
}
$positions = [];
foreach ($this->getPatterns() ?? [] as $pattern) {
if (($firstPatternPosition = mb_stripos($string, $pattern, 0, $encoding)) !== false) {
$positions[$firstPatternPosition] = $pattern;
}
if (($lastPatternPosition = mb_strripos($string, $pattern, 0, $encoding)) !== false) {
$positions[$lastPatternPosition] = $pattern;
}
}
if (count($positions) == 0) {
return $mask;
}
ksort($positions);
$mask = preg_replace('/\d/ui', $character, $mask); // Hide all digits.
$space = ' ';
$stringLength = mb_strlen($string, $encoding);
foreach ($positions as $position => $pattern) {
//Right
$patternLength = mb_strlen($pattern, $encoding);
$index = $position + $patternLength; //Adjust start index to not hide pattern
$length = (int)round($stringLength / 10); //Default length after start index
$nextPattern = next($positions);
$nextPosition = key($positions);
if ($nextPosition && $nextPattern) {
//Correction with next pattern
$length = ($index + $length) >= $nextPosition ? $nextPosition - $index : $length;
}
if ($space == mb_substr($string, ($index + $length) - 1, 1, $encoding)) {
$length -= 1; //Correction for space to sow and break
}
$mask = Str::mask($mask, $character, $index, $length, $encoding);
}
return $mask;
}
/**
* @return array
*/
public function getPatterns(): array
{
return $this->patterns;
}
/**
* @param array $patterns
*/
public function setPatterns(array $patterns): void
{
$this->patterns = $patterns;
}
}