Store authors alongside webmentions
This commit is contained in:
parent
3cafc5238e
commit
51f1269600
@ -21,13 +21,22 @@ class SqliteGateway extends WebmentionGatewayInterface
|
|||||||
{
|
{
|
||||||
// Create Webmention table
|
// Create Webmention table
|
||||||
$sql = <<<SQL
|
$sql = <<<SQL
|
||||||
|
PRAGMA foreign_keys = ON;
|
||||||
|
CREATE TABLE IF NOT EXISTS authors (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
url TEXT,
|
||||||
|
photo TEXT,
|
||||||
|
UNIQUE(name, url)
|
||||||
|
);
|
||||||
CREATE TABLE IF NOT EXISTS webmentions (
|
CREATE TABLE IF NOT EXISTS webmentions (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
target TEXT NOT NULL,
|
target TEXT NOT NULL,
|
||||||
source TEXT NOT NULL,
|
source TEXT NOT NULL,
|
||||||
type TEXT NOT NULL,
|
type TEXT NOT NULL,
|
||||||
content TEXT,
|
content TEXT,
|
||||||
author INTEGER
|
author INTEGER,
|
||||||
|
FOREIGN KEY(author) REFERENCES authors(id)
|
||||||
);
|
);
|
||||||
SQL;
|
SQL;
|
||||||
|
|
||||||
@ -36,7 +45,22 @@ class SqliteGateway extends WebmentionGatewayInterface
|
|||||||
|
|
||||||
public function get(int $id): ?Webmention
|
public function get(int $id): ?Webmention
|
||||||
{
|
{
|
||||||
$sql = "SELECT * FROM webmentions WHERE id=:id LIMIT 1;";
|
$sql = <<<SQL
|
||||||
|
SELECT webmentions.id as id,
|
||||||
|
webmentions.source as source,
|
||||||
|
webmentions.target as target,
|
||||||
|
webmentions.type as type,
|
||||||
|
webmentions.content as content,
|
||||||
|
authors.id as author,
|
||||||
|
authors.name as author_name,
|
||||||
|
authors.url as author_url,
|
||||||
|
authors.photo as author_photo
|
||||||
|
FROM webmentions
|
||||||
|
LEFT JOIN
|
||||||
|
authors ON webmentions.author=authors.id
|
||||||
|
WHERE webmentions.id=:id
|
||||||
|
LIMIT 1;
|
||||||
|
SQL;
|
||||||
$statement = $this->connection->prepare($sql);
|
$statement = $this->connection->prepare($sql);
|
||||||
$statement->execute(["id" => $id]);
|
$statement->execute(["id" => $id]);
|
||||||
$row = $statement->fetch(PDO::FETCH_ASSOC);
|
$row = $statement->fetch(PDO::FETCH_ASSOC);
|
||||||
@ -49,7 +73,7 @@ class SqliteGateway extends WebmentionGatewayInterface
|
|||||||
$row["source"],
|
$row["source"],
|
||||||
MentionType::from($row["type"]),
|
MentionType::from($row["type"]),
|
||||||
$row["content"],
|
$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
|
public function getByPost(string $post): array
|
||||||
{
|
{
|
||||||
$sql = "SELECT * FROM webmentions WHERE target=:post";
|
$sql = <<<SQL
|
||||||
|
SELECT webmentions.id as id,
|
||||||
|
webmentions.source as source,
|
||||||
|
webmentions.target as target,
|
||||||
|
webmentions.type as type,
|
||||||
|
webmentions.content as content,
|
||||||
|
authors.id as author,
|
||||||
|
authors.name as author_name,
|
||||||
|
authors.url as author_url,
|
||||||
|
authors.photo as author_photo
|
||||||
|
FROM webmentions
|
||||||
|
LEFT JOIN
|
||||||
|
authors ON webmentions.author=authors.id
|
||||||
|
WHERE target=:post;
|
||||||
|
SQL;
|
||||||
$statement = $this->connection->prepare($sql);
|
$statement = $this->connection->prepare($sql);
|
||||||
$statement->execute(["post" => $post]);
|
$statement->execute(["post" => $post]);
|
||||||
|
|
||||||
@ -81,8 +119,10 @@ class SqliteGateway extends WebmentionGatewayInterface
|
|||||||
|
|
||||||
public function save(Webmention $webmention): ?int
|
public function save(Webmention $webmention): ?int
|
||||||
{
|
{
|
||||||
|
$author = $this->saveAuthor($webmention->author);
|
||||||
|
|
||||||
$sql = <<< SQL
|
$sql = <<< SQL
|
||||||
INSERT INTO webmentions
|
REPLACE INTO webmentions
|
||||||
(id, target, source, type, content, author)
|
(id, target, source, type, content, author)
|
||||||
VALUES
|
VALUES
|
||||||
(:id, :target, :source, :type, :content, :author);
|
(:id, :target, :source, :type, :content, :author);
|
||||||
@ -95,13 +135,65 @@ class SqliteGateway extends WebmentionGatewayInterface
|
|||||||
"source" => $webmention->source,
|
"source" => $webmention->source,
|
||||||
"type" => $webmention->type->toString(),
|
"type" => $webmention->type->toString(),
|
||||||
"content" => $webmention->content,
|
"content" => $webmention->content,
|
||||||
"author" => $webmention->author->id,
|
"author" => $author,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$statement->closeCursor();
|
$statement->closeCursor();
|
||||||
|
|
||||||
return $success ? (int)$this->connection->lastInsertId() : null;
|
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
|
public function delete(Webmention $webmention): void
|
||||||
{
|
{
|
||||||
$sql = "DELETE FROM webmentions WHERE id=:id;";
|
$sql = "DELETE FROM webmentions WHERE id=:id;";
|
||||||
@ -116,7 +208,18 @@ class SqliteGateway extends WebmentionGatewayInterface
|
|||||||
return "$v=:$v";
|
return "$v=:$v";
|
||||||
}, array_keys($values)));
|
}, array_keys($values)));
|
||||||
$sql = <<<SQL
|
$sql = <<<SQL
|
||||||
SELECT * FROM webmentions
|
SELECT webmentions.id as id,
|
||||||
|
webmentions.source as source,
|
||||||
|
webmentions.target as target,
|
||||||
|
webmentions.type as type,
|
||||||
|
webmentions.content as content,
|
||||||
|
authors.id as author,
|
||||||
|
authors.name as author_name,
|
||||||
|
authors.url as author_url,
|
||||||
|
authors.photo as author_photo
|
||||||
|
FROM webmentions
|
||||||
|
LEFT JOIN
|
||||||
|
authors ON webmentions.author=authors.id
|
||||||
WHERE {$keys}
|
WHERE {$keys}
|
||||||
SQL;
|
SQL;
|
||||||
|
|
||||||
|
@ -4,13 +4,17 @@ namespace Lewisdale\Webmentions\Gateways;
|
|||||||
|
|
||||||
use Lewisdale\Webmentions\Models\Webmention;
|
use Lewisdale\Webmentions\Models\Webmention;
|
||||||
|
|
||||||
abstract class WebmentionGatewayInterface {
|
abstract class WebmentionGatewayInterface
|
||||||
abstract protected function up() : void;
|
{
|
||||||
abstract public function getByPost(string $post) : array;
|
abstract protected function up(): void;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
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;
|
||||||
|
}
|
@ -20,5 +20,3 @@ class Webmention
|
|||||||
return "Webmention (id: {$this->id}, target: {$this->target}, source: {$this->source}, content: {$this->content}, author: {$this->author->name})";
|
return "Webmention (id: {$this->id}, target: {$this->target}, source: {$this->source}, content: {$this->content}, author: {$this->author->name})";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
|
||||||
|
@ -43,7 +43,7 @@ class SqliteGatewayTest extends TestCase
|
|||||||
"https://a-source.url",
|
"https://a-source.url",
|
||||||
MentionType::Like,
|
MentionType::Like,
|
||||||
"No content",
|
"No content",
|
||||||
new \Lewisdale\Webmentions\Models\Author(),
|
new \Lewisdale\Webmentions\Models\Author(null, null, null, null),
|
||||||
);
|
);
|
||||||
|
|
||||||
$webmention->id = $this->gateway->save($webmention);
|
$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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user