83 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php declare(strict_types=1);
 | 
						|
 | 
						|
namespace Lewisdale\Webmentions;
 | 
						|
 | 
						|
use League\Uri\Exceptions\SyntaxError;
 | 
						|
use Lewisdale\Webmentions\Exceptions\InvalidTargetException;
 | 
						|
use Lewisdale\Webmentions\Exceptions\InvalidUrlException;
 | 
						|
use Lewisdale\Webmentions\Gateways\WebmentionGatewayInterface;
 | 
						|
use Lewisdale\Webmentions\Models\Webmention;
 | 
						|
use Symfony\Component\HttpClient\HttpClient;
 | 
						|
use League\Uri\Uri;
 | 
						|
use Lewisdale\Webmentions\Exceptions\SourceNotFoundException;
 | 
						|
use Lewisdale\Webmentions\Exceptions\TargetNotMentionedException;
 | 
						|
use Lewisdale\Webmentions\Models\MentionType;
 | 
						|
use Symfony\Component\DomCrawler\Crawler;
 | 
						|
use Symfony\Contracts\HttpClient\HttpClientInterface;
 | 
						|
 | 
						|
class Endpoint {
 | 
						|
    private readonly WebmentionGatewayInterface $gateway;
 | 
						|
 | 
						|
    function __construct(
 | 
						|
        private readonly HttpClientInterface $httpClient
 | 
						|
    )
 | 
						|
    {}
 | 
						|
 | 
						|
    public function validateUrl(string $url) : bool {
 | 
						|
        try {
 | 
						|
            $uri = Uri::createFromString($url);
 | 
						|
            $scheme = $uri->getScheme();
 | 
						|
            $schemeValid = in_array($scheme, ["http", "https"]);
 | 
						|
 | 
						|
            return $schemeValid && !!filter_var($url, FILTER_VALIDATE_URL);
 | 
						|
        
 | 
						|
        } catch (SyntaxError $e)
 | 
						|
        {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    public function receiveWebmention(string $source, string $target) : void
 | 
						|
    {
 | 
						|
        // Validate that both source and target are actual domains
 | 
						|
        if (!$this->validateUrl($source) || !$this->validateUrl($target))
 | 
						|
        {
 | 
						|
            throw new InvalidUrlException();
 | 
						|
        }
 | 
						|
 | 
						|
        // Validate that the webmention target is a domain I care about
 | 
						|
        if (!str_contains($target, "https://lewisdale.dev")) {
 | 
						|
            throw new InvalidTargetException();
 | 
						|
        }
 | 
						|
 | 
						|
        // Parse content from the source
 | 
						|
        $response = $this->httpClient->request('GET', $source);
 | 
						|
 | 
						|
        if ($response->getStatusCode() < 400)
 | 
						|
        {
 | 
						|
            $content = $this->parseContent($response->getContent(), $target);
 | 
						|
            $author = $this->parseAuthor($response->getContent());
 | 
						|
 | 
						|
            $webmention = new Webmention(null, $target, $source, MentionType::from(""), $content, $author);
 | 
						|
            $this->gateway->save($webmention);
 | 
						|
        } else {
 | 
						|
            throw new SourceNotFoundException();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    private function parseContent(string $content, string $target) : ?string
 | 
						|
    {
 | 
						|
        $body = new Crawler($content);
 | 
						|
        $anchors = $body->filter('a[href="'. $target . '"]');
 | 
						|
 | 
						|
        if (!$anchors->count()) {
 | 
						|
            throw new TargetNotMentionedException();
 | 
						|
        }
 | 
						|
 | 
						|
        return null;
 | 
						|
    }
 | 
						|
 | 
						|
    private function parseAuthor(string $author) : ?string
 | 
						|
    {
 | 
						|
        return null;
 | 
						|
    }
 | 
						|
} |