decodeBinaryValue($value); } public function setBinLetterAttribute($value) { $this->attributes['binLetter'] = $this->encodeBinaryValue($value); } public function getBinTitleAttribute($value) { return $this->decodeBinaryValue($value); } public function setBinTitleAttribute($value) { $this->attributes['binTitle'] = $this->encodeBinaryValue($value); } private function decodeBinaryValue(?string $value): ?string { $value = $this->stripNulls($value); if ($value === null || $value === '') { return $value; } $decoded = $this->decodeBase64($this->decodeBase64($value)); $decoded = $this->stripNulls($decoded); return $decoded === null ? null : $this->ensureUtf8($decoded); } private function encodeBinaryValue(?string $value): ?string { $value = $this->stripNulls($value); if ($value === null || $value === '') { return $value; } $prepared = @iconv('UTF-8', 'CP1251//IGNORE', $value); if ($prepared === false) { $prepared = $value; } return base64_encode(base64_encode($prepared)); } private function stripNulls(?string $value): ?string { return $value === null ? null : rtrim($value, "\0"); } private function decodeBase64(string $value): string { $decoded = base64_decode($value, true); return $decoded === false ? $value : $decoded; } private function ensureUtf8(string $value): string { if ($value === '') { return ''; } if (mb_check_encoding($value, 'UTF-8')) { return $this->removeControlChars($value); } $candidates = []; if (function_exists('iconv')) { $candidates[] = fn () => @iconv('CP1251', 'UTF-8//IGNORE', $value); } if (function_exists('mb_convert_encoding')) { $candidates[] = fn () => @mb_convert_encoding($value, 'UTF-8', 'CP1251'); $candidates[] = fn () => @mb_convert_encoding($value, 'UTF-8', 'ISO-8859-1'); } $candidates[] = fn () => utf8_encode($value); foreach ($candidates as $candidate) { $converted = $candidate(); if (is_string($converted) && mb_check_encoding($converted, 'UTF-8')) { return $this->removeControlChars($converted); } } if (function_exists('iconv')) { $sanitized = @iconv('UTF-8', 'UTF-8//IGNORE', $value); if (is_string($sanitized) && mb_check_encoding($sanitized, 'UTF-8')) { return $this->removeControlChars($sanitized); } } return ''; } private function removeControlChars(string $value): string { $clean = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $value); return is_string($clean) ? $clean : ''; } public function toArray() { $array = parent::toArray(); array_walk_recursive($array, function (&$v) { if (is_string($v)) { $v = $this->ensureUtf8($v); } }); return $array; } }