From 51f12696003f885e9621927c8b9761c954a4d3af Mon Sep 17 00:00:00 2001 From: Lewis Dale Date: Thu, 16 Mar 2023 09:34:57 +0000 Subject: [PATCH] Store authors alongside webmentions --- src/Gateways/SqliteGateway.php | 117 ++++++++++++++++++-- src/Gateways/WebmentionGatewayInterface.php | 22 ++-- src/Models/Webmention.php | 2 - tests/Gateways/SqliteGatewayTest.php | 88 ++++++++++++++- 4 files changed, 210 insertions(+), 19 deletions(-) diff --git a/src/Gateways/SqliteGateway.php b/src/Gateways/SqliteGateway.php index 89c5ee3..0bd34e0 100644 --- a/src/Gateways/SqliteGateway.php +++ b/src/Gateways/SqliteGateway.php @@ -21,13 +21,22 @@ class SqliteGateway extends WebmentionGatewayInterface { // Create Webmention table $sql = <<connection->prepare($sql); $statement->execute(["id" => $id]); $row = $statement->fetch(PDO::FETCH_ASSOC); @@ -49,7 +73,7 @@ class SqliteGateway extends WebmentionGatewayInterface $row["source"], MentionType::from($row["type"]), $row["content"], - new Author((int)$row["author"]) + new Author((int)$row["author"], $row["author_name"], $row["author_url"], $row["author_photo"]) ); } @@ -58,7 +82,21 @@ class SqliteGateway extends WebmentionGatewayInterface public function getByPost(string $post): array { - $sql = "SELECT * FROM webmentions WHERE target=:post"; + $sql = <<connection->prepare($sql); $statement->execute(["post" => $post]); @@ -81,8 +119,10 @@ class SqliteGateway extends WebmentionGatewayInterface public function save(Webmention $webmention): ?int { + $author = $this->saveAuthor($webmention->author); + $sql = <<< SQL - INSERT INTO webmentions + REPLACE INTO webmentions (id, target, source, type, content, author) VALUES (:id, :target, :source, :type, :content, :author); @@ -95,13 +135,65 @@ class SqliteGateway extends WebmentionGatewayInterface "source" => $webmention->source, "type" => $webmention->type->toString(), "content" => $webmention->content, - "author" => $webmention->author->id, + "author" => $author, ]); + $statement->closeCursor(); return $success ? (int)$this->connection->lastInsertId() : null; } + protected function saveAuthor(Author $author): ?int + { + if (!$author->name || !$author->url) { + return null; + } + + $sql = <<< SQL + INSERT OR IGNORE INTO authors + (id, name, url, photo) + VALUES + (:id, :name, :url, :photo); + SQL; + + $statement = $this->connection->prepare($sql); + $success = $statement->execute([ + "id" => $author->id, + "name" => $author->name, + "url" => $author->url, + "photo" => $author->photo, + ]); + $statement->closeCursor(); + + return $this->findAuthor($author->name, $author->url)?->id; + } + + protected function findAuthor(string $name, string $url): ?Author + { + + $sql = "SELECT id, name, url, photo FROM authors WHERE url=:url AND name=:name"; + $statement = $this->connection->prepare($sql); + + $success = $statement->execute([ + "url" => $url, + "name" => $name, + ]); + + if (!$success) { + return null; + } + + $row = $statement->fetch(PDO::FETCH_ASSOC); + $statement->closeCursor(); + + return $row ? new Author( + (int)$row['id'], + $row['name'], + $row['url'], + $row['photo'] + ) : null; + } + public function delete(Webmention $webmention): void { $sql = "DELETE FROM webmentions WHERE id=:id;"; @@ -116,7 +208,18 @@ class SqliteGateway extends WebmentionGatewayInterface return "$v=:$v"; }, array_keys($values))); $sql = << \ No newline at end of file + abstract public function getByPost(string $post): array; + + abstract public function save(Webmention $webmention): ?int; + + abstract public function delete(Webmention $webmention): void; + + abstract public function get(int $id): ?Webmention; + + abstract public function find(array $values): array; +} \ No newline at end of file diff --git a/src/Models/Webmention.php b/src/Models/Webmention.php index da6b65b..6f4945d 100644 --- a/src/Models/Webmention.php +++ b/src/Models/Webmention.php @@ -20,5 +20,3 @@ class Webmention return "Webmention (id: {$this->id}, target: {$this->target}, source: {$this->source}, content: {$this->content}, author: {$this->author->name})"; } } - -?> diff --git a/tests/Gateways/SqliteGatewayTest.php b/tests/Gateways/SqliteGatewayTest.php index 0cb6d5b..e24b8cb 100644 --- a/tests/Gateways/SqliteGatewayTest.php +++ b/tests/Gateways/SqliteGatewayTest.php @@ -43,7 +43,7 @@ class SqliteGatewayTest extends TestCase "https://a-source.url", MentionType::Like, "No content", - new \Lewisdale\Webmentions\Models\Author(), + new \Lewisdale\Webmentions\Models\Author(null, null, null, null), ); $webmention->id = $this->gateway->save($webmention); @@ -155,4 +155,90 @@ class SqliteGatewayTest extends TestCase ]) ); } + + public function testItSavesAnAuthorWithTheWebmention() + { + $webmention = new Webmention( + null, + "https://a-target-url.com", + "https://a-source-url.com", + MentionType::Like, + "Liked this post", + new \Lewisdale\Webmentions\Models\Author( + null, + "Doreen Mifah", + "https://my-homepage.com", + "https://cdn.imgserver.com/400/400" + ) + ); + $webmention->id = $this->gateway->save($webmention); + $retrieved = $this->gateway->get($webmention->id)?->author; + $expected = $webmention->author; + + $this->assertEquals($expected->name, $retrieved?->name); + $this->assertEquals($expected->url, $retrieved?->url); + $this->assertEquals($expected->photo, $retrieved?->photo); + } + + public function testItLooksUpWebmentionsByAuthorName() + { + $this->gateway->save(new Webmention( + null, + "https://a-target-url.com", + "https://a-source-url.com", + MentionType::Like, + "Liked this post", + new \Lewisdale\Webmentions\Models\Author( + null, + "Doreen Mifah", + "https://my-homepage.com", + "https://cdn.imgserver.com/400/400" + ) + )); + + $this->gateway->save(new Webmention( + null, + "https://a-target-url.com", + "https://a-source-url.com", + MentionType::Like, + "Liked this post", + new \Lewisdale\Webmentions\Models\Author( + null, + "Carl Weathers", + "https://carl-weathers.com", + "https://cdn.imgserver.com/400/400" + ) + )); + + $this->gateway->save(new Webmention( + null, + "https://a-target-url.com", + "https://a-source-url.com", + MentionType::Like, + "Liked this post", + new \Lewisdale\Webmentions\Models\Author( + null, + "Barry White", + "https://barry.white.com", + "https://cdn.imgserver.com/400/400" + ) + )); + + $this->gateway->save(new Webmention( + null, + "https://a-target-url.com", + "https://a-source-url.com", + MentionType::Reply, + "This was a cool post!", + new \Lewisdale\Webmentions\Models\Author( + null, + "Carl Weathers", + "https://carl-weathers.com", + "https://cdn.imgserver.com/400/400" + ) + )); + + $retrieved = $this->gateway->find(["author_name" => "Carl Weathers"]); + $this->assertCount(2, $retrieved); + } }