', '|', "\0"]; /** * Sanitize a value for use in a single-line text description. * * Transformations (in order): * 1. Replaces "/" with "-" (the reported 400 trigger) * 2. Strips control characters (\x00-\x1F) except \t and \n * 3. Replaces tab with single space * 4. Collapses newlines into spaces (text lines are single-line) * 5. Collapses runs of spaces to a single space * 6. Trims leading/trailing whitespace * 7. Truncates to $maxLength with "..." suffix if needed */ public static function sanitizeTextLine(mixed $value, int $maxLength = self::TEXT_LINE_MAX_LENGTH): string { if ($value === null) { return ''; } $text = (string)$value; if ($text === '') { return ''; } // 1. Strip control characters except \t and \n $text = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $text); // 2. Replace tab with single space $text = str_replace("\t", ' ', $text); // 3. Collapse newlines to single space (text lines are single-line) $text = preg_replace('/[\r\n]+/u', ' ', $text); // 4. Replace forward slashes (the reported 400 trigger) $text = str_replace('/', '-', $text); // 5. Collapse runs of spaces $text = preg_replace('/\s+/u', ' ', $text); // 6. Trim $text = trim($text); // 7. Truncate with ellipsis if too long if ($maxLength > 3 && mb_strlen($text) > $maxLength) { $text = mb_substr($text, 0, $maxLength - 3) . '...'; } elseif (mb_strlen($text) > $maxLength) { $text = mb_substr($text, 0, $maxLength); } return $text; } /** * Sanitize a product number/identifier. * * Removes characters that are illegal in product numbers on most * e-conomic setups (filesystem-unsafe + path separators). */ public static function sanitizeProductNumber(mixed $value): string { if ($value === null) { return ''; } $text = (string)$value; if ($text === '') { return ''; } $text = str_replace(self::PRODUCT_NUMBER_FORBIDDEN, '', $text); $text = preg_replace('/[\x00-\x1F\x7F]/u', '', $text); $text = trim($text); if (mb_strlen($text) > self::PRODUCT_NUMBER_MAX_LENGTH) { $text = mb_substr($text, 0, self::PRODUCT_NUMBER_MAX_LENGTH); } return $text; } /** * Sanitize a longer product description. */ public static function sanitizeProductDescription(mixed $value): string { return self::sanitizeTextLine($value, self::PRODUCT_DESCRIPTION_MAX_LENGTH); } /** * Catch-all sanitizer for any user-input value going to e-conomic. * Defaults to text-line rules. */ public static function sanitizeForEconApi(mixed $value): string { return self::sanitizeTextLine($value); } }