tissue/app/MetadataResolver/OGPResolver.php

54 lines
1.7 KiB
PHP

<?php
namespace App\MetadataResolver;
class OGPResolver implements Resolver, Parser
{
public function resolve(string $url): Metadata
{
$client = new \GuzzleHttp\Client();
$res = $client->get($url);
if ($res->getStatusCode() === 200) {
return $this->parse($res->getBody());
} else {
throw new \RuntimeException("{$res->getStatusCode()}: $url");
}
}
public function parse(string $html): Metadata
{
$dom = new \DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'ASCII,JIS,UTF-8,eucJP-win,SJIS-win'));
$xpath = new \DOMXPath($dom);
$metadata = new Metadata();
$metadata->title = $this->findContent($xpath, '//meta[@*="og:title"]', '//meta[@*="twitter:title"]');
if (empty($metadata->title)) {
$nodes = $xpath->query('//title');
if ($nodes->length !== 0) {
$metadata->title = $nodes->item(0)->textContent;
}
}
$metadata->description = $this->findContent($xpath, '//meta[@*="og:description"]', '//meta[@*="twitter:description"]', '//meta[@name="description"]');
$metadata->image = $this->findContent($xpath, '//meta[@*="og:image"]', '//meta[@*="twitter:image"]');
return $metadata;
}
private function findContent(\DOMXPath $xpath, string ...$expressions)
{
foreach ($expressions as $expression) {
$nodes = $xpath->query($expression);
foreach ($nodes as $node) {
$content = $node->getAttribute('content');
if (!empty($content)) {
return $content;
}
}
}
return '';
}
}