value = $normalized; } public static function castUsing(array $arguments): string { return CnpjCast::class; } public static function rule(): Closure { return static function (string $attribute, mixed $value, Closure $fail): void { if (! is_string($value)) { $fail(__('validation.cnpj')); return; } try { new self($value); } catch (InvalidArgumentException) { $fail(__('validation.cnpj')); } }; } public function value(): string { return $this->value; } public function formatted(): string { return preg_replace( '/^(.{2})(.{3})(.{3})(.{4})(\d{2})$/', '$1.$2.$3/$4-$5', $this->value, ); } public function __toString(): string { return $this->value; } public function jsonSerialize(): string { return $this->value; } private static function isValid(string $value): bool { if (! preg_match('/^[A-Z0-9]{12}\d{2}$/', $value) || preg_match('/^([A-Z0-9])\1{13}$/', $value)) { return false; } $base = substr($value, 0, 12); $firstDigit = self::checkDigit($base); $secondDigit = self::checkDigit($base.$firstDigit); return hash_equals($base.$firstDigit.$secondDigit, $value); } private static function checkDigit(string $value): int { $sum = 0; $weight = 2; for ($index = strlen($value) - 1; $index >= 0; $index--) { $sum += (ord($value[$index]) - 48) * $weight; $weight = $weight === 9 ? 2 : $weight + 1; } $remainder = $sum % 11; return $remainder < 2 ? 0 : 11 - $remainder; } }