getCleanTitle(); $searchResult = $this->search($movie); if ($searchResult === false) { $this->outputNotFound(); return AdultProcessingResult::notFound($this->getName()); } $this->title = $searchResult['title']; $this->directUrl = $searchResult['url']; // Fetch the movie details page $this->response = $this->fetchHtml($this->directUrl, $this->cookie); if ($this->response === false) { // @phpstan-ignore identical.alwaysFalse return AdultProcessingResult::failed('Failed to fetch movie details page', $this->getName()); } $this->getHtmlParser()->loadHtml($this->response); $movieInfo = $this->getMovieInfo(); if ($movieInfo === false) { return AdultProcessingResult::notFound($this->getName()); } $this->outputMatch($this->title); return AdultProcessingResult::matched( $this->title, $this->getName(), $movieInfo ); } protected function search(string $movie): array|false { if (empty($movie)) { return false; } $searchUrl = self::BASE_URL.self::SEARCH_URL.urlencode($movie); $response = $this->fetchHtml($searchUrl, $this->cookie); if ($response === false) { return false; } $this->getHtmlParser()->loadHtml($response); $check = $this->getHtmlParser()->find('img[rel=license]'); if (empty($check)) { return false; } $bestMatch = null; $highestSimilarity = 0; foreach ($check as $ret) { if (! isset($ret->alt) || ! isset($ret->src)) { continue; } $title = trim($ret->alt, '"'); $title = str_replace('/XXX/', '', $title); $similarity = $this->calculateSimilarity($movie, $title); if ($similarity > $highestSimilarity && preg_match('/\/(?\d+)\.jpg$/i', $ret->src, $hits)) { $highestSimilarity = $similarity; $bestMatch = [ 'title' => trim($title), 'sku' => $hits['sku'], ]; } } if ($bestMatch !== null && $highestSimilarity >= $this->minimumSimilarity) { return [ 'title' => $bestMatch['title'], 'url' => self::BASE_URL.'/dvd_view_'.$bestMatch['sku'].'.html', ]; } return false; } protected function getMovieInfo(): array|false { $results = []; if (! empty($this->directUrl)) { if (! empty($this->title)) { $results['title'] = $this->title; } $results['directurl'] = $this->directUrl; } // Get all the movie data $results = array_merge($results, $this->extractSynopsis()); $results = array_merge($results, $this->extractProductInfo(true)); $results = array_merge($results, $this->extractCast()); $results = array_merge($results, $this->extractGenres()); $results = array_merge($results, $this->extractCovers()); if (empty($results)) { return false; } return $results; } protected function extractCovers(): array { $res = []; $baseUrl = 'https://www.adultdvdmarketplace.com/'; // Try fancybox link first if ($ret = $this->getHtmlParser()->findOne('a[rel=fancybox-button]')) { // @phpstan-ignore if.alwaysTrue if (isset($ret->href) && preg_match('/images\/.*[\d]+\.jpg$/i', $ret->href, $hits)) { $res['boxcover'] = str_starts_with($hits[0], 'http') ? $hits[0] : $baseUrl.$hits[0]; $res['backcover'] = str_ireplace('/front/', '/back/', $res['boxcover']); return $res; } } // Try license image if ($ret = $this->getHtmlParser()->findOne('img[rel=license]')) { // @phpstan-ignore if.alwaysTrue if (isset($ret->src) && preg_match('/images\/.*[\d]+\.jpg$/i', $ret->src, $hits)) { $res['boxcover'] = str_starts_with($hits[0], 'http') ? $hits[0] : $baseUrl.$hits[0]; return $res; } } return $res; } protected function extractSynopsis(): array { $res = []; $res['synopsis'] = 'N/A'; // Try to find Description heading foreach ($this->getHtmlParser()->find('h3') as $heading) { if (trim($heading->plaintext) === 'Description') { $nextElement = $heading->next_sibling(); if ($nextElement && ! empty(trim($nextElement->plaintext))) { $res['synopsis'] = trim($nextElement->plaintext); return $res; } } } // Fallback: Try meta description $meta = $this->getHtmlParser()->findOne('meta[name="description"]'); if ($meta && isset($meta->content) && ! empty(trim($meta->content))) { // @phpstan-ignore booleanAnd.leftAlwaysTrue $res['synopsis'] = trim($meta->content); } return $res; } protected function extractProductInfo(bool $extras = false): array { $res = []; foreach ($this->getHtmlParser()->find('ul.list-unstyled li') as $li) { $category = explode(':', $li->plaintext); switch (trim($category[0])) { case 'Director': $res['director'] = trim($category[1]); break; case 'Format': case 'Studio': case 'Released': case 'SKU': $res['productinfo'][trim($category[0])] = trim($category[1]); } } return $res; } protected function extractCast(): array { $res = []; $cast = []; foreach ($this->getHtmlParser()->find('h3') as $heading) { if (trim($heading->plaintext) === 'Cast') { $next = $heading->nextSibling(); while ($next) { if ($next->nodeName === 'h3') { // @phpstan-ignore property.notFound break; } if (isset($next->href) && preg_match('/search_performerid/', $next->href)) { $cast[] = trim($next->plaintext); } $next = $next->nextSibling(); } } } $res['cast'] = array_unique($cast); return $res; } protected function extractGenres(): array { $res = []; $genres = []; foreach ($this->getHtmlParser()->find('ul.list-unstyled') as $li) { $category = explode(':', $li->plaintext); if (trim($category[0]) === 'Category') { foreach (explode(',', $category[1]) as $genre) { $genres[] = trim($genre); } $res['genres'] = $genres; } } return $res; } }