url = $url; return $p->update() ? $p : null; } /** * Updates the information for this link preview. * @return bool true if successful */ public function update(): bool { if (!(str_starts_with($this->url, "https://") || str_starts_with($this->url, "http://"))) { return false; } // TODO: Respect Content-Type header from response, maybe set an Accept header in the request? // I was able to find a URL serving SHIFT-JIS, but they do not specify a charset in the Content-Type header. // https://www2d.biglobe.ne.jp/~msyk/charcode/cp932/Windows-31J-charset.html $max_length = 256 * 1024; // 256KiB should be enough for the document head $c = @file_get_contents($this->url, false, null, 0, $max_length); if (!$c) return false; $d = \Dom\HTMLDocument::createFromString($c, LIBXML_NOERROR); $url = $this->url; $siteName = hostname_from_uri($this->url); $style = 'text'; // opengraph $title = $d->querySelector("meta[property='og:title']")?->getAttribute('content'); $description = $d->querySelector("meta[property='og:description']")?->getAttribute('content'); $url = $d->querySelector("meta[property='og:url']")?->getAttribute('content'); $siteName = $d->querySelector("meta[property='og:site_name']")?->getAttribute('content'); $imageUrl = $d->querySelector("meta[property='og:image']")?->getAttribute('content'); // fallbacks $title = $title ?? $d->querySelector('title')?->textContent; $description = $description ?? $d->querySelector('meta[name=description]')?->getAttribute('content'); if ($d->querySelector("meta[name='twitter:card'][content=summary_large_image]") != null) { $style = 'largeImage'; } // turn text into smallImage if an image is present $style = ($style == 'text' && isset($imageUrl)) ? 'smallImage' : $style; if (!isset($title, $description)) return false; $this->url = $url; $this->siteName = $siteName; $this->title = $title; $this->description = $description; $this->style = $style; $this->imageUrl = $imageUrl ?? null; return true; } public function jsonSerialize(): array { return [ 'url' => $this->url, 'siteName' => $this->siteName, 'title' => $this->title, 'description' => $this->description, 'style' => $this->style, 'imageUrl' => $this->imageUrl ]; } }