identifier($isbn10); if ($isbn10 === null || strlen($isbn10) !== 10) { return null; } $base = '978' . substr($isbn10, 0, 9); $sum = 0; for ($index = 0; $index < 12; $index++) { $sum += (int) $base[$index] * ($index % 2 === 0 ? 1 : 3); } return $base . ((10 - ($sum % 10)) % 10); } public function isbn10FromIsbn13(?string $isbn13): ?string { $isbn13 = $this->identifier($isbn13); if ($isbn13 === null || strlen($isbn13) !== 13 || ! str_starts_with($isbn13, '978')) { return null; } $base = substr($isbn13, 3, 9); $sum = 0; for ($index = 0; $index < 9; $index++) { $sum += (10 - $index) * (int) $base[$index]; } $check = (11 - ($sum % 11)) % 11; return $base . ($check === 10 ? 'X' : (string) $check); } public function language(?string $value): ?string { $value = $this->text($value); if ($value === null) { return null; } $languages = [ 'english' => 'en', 'eng' => 'en', 'italian' => 'it', 'italiano' => 'it', 'ita' => 'it', 'french' => 'fr', 'français' => 'fr', 'fre' => 'fr', 'fra' => 'fr', 'german' => 'de', 'deutsch' => 'de', 'ger' => 'de', 'deu' => 'de', 'spanish' => 'es', 'español' => 'es', 'spa' => 'es', ]; $key = strtolower($value); return $languages[$key] ?? strtolower(substr($value, 0, 2)); } public function publicationDate(?string $value): ?string { $value = $this->text($value); if ($value === null) { return null; } if (preg_match('/^(\d{4})(?:[-\/.](\d{1,2}))?(?:[-\/.](\d{1,2}))?/', $value, $matches) === 1) { $year = $matches[1]; if (! isset($matches[2]) || $matches[2] === '') { return $year; } $month = str_pad($matches[2], 2, '0', STR_PAD_LEFT); if (! isset($matches[3]) || $matches[3] === '') { return $year . '-' . $month; } return $year . '-' . $month . '-' . str_pad($matches[3], 2, '0', STR_PAD_LEFT); } $timestamp = strtotime($value); return $timestamp !== false ? gmdate('Y-m-d', $timestamp) : $value; } public function name(?string $value): ?string { $value = $this->text($value); return $value !== null ? preg_replace('/\s*,\s*/u', ', ', $value) : null; } public function list(string|array|null $value): array { $inputs = is_array($value) ? $value : [$value]; $normalized = []; foreach ($inputs as $input) { foreach (preg_split('/[,;|]+/u', is_scalar($input) ? (string) $input : '') ?: [] as $item) { $text = $this->name($item); if ($text === null) { continue; } $key = strtolower($text); if (! isset($normalized[$key])) { $normalized[$key] = $text; } } } return array_values($normalized); } public function imageUrl(?string $value): ?string { $value = $this->text($value); if ($value === null || filter_var($value, FILTER_VALIDATE_URL) === false || preg_match('/(?:placeholder|no[-_]?image|spacer|transparent)[^\/]*\.(?:gif|png|jpe?g|webp)(?:\?|$)/i', $value) === 1) { return null; } return str_starts_with($value, 'http://') ? 'https://' . substr($value, 7) : $value; } }