diff --git a/index.php b/index.php
index 4acadba..791c814 100644
--- a/index.php
+++ b/index.php
@@ -2,10 +2,20 @@
require_once __DIR__ . "/vendor/autoload.php";
+use Lewisdale\Webmentions\Router\Router;
+use Lewisdale\Webmentions\Router\Response;
use Lewisdale\Webmentions\Webmention;
$mentioner = new Webmention();
-$mentioner->sendForPage("https://lewisdale.dev/post/bringing-my-omg-lol-now-page-into-eleventy/");
+// $mentioner->sendForPage("https://lewisdale.dev/post/bringing-my-omg-lol-now-page-into-eleventy/");
+
+$router = new Router();
+
+$router->get("/send", function($req, Response $response) {
+ return "
Hello world
";
+});
+
+$router->dispatch();
?>
\ No newline at end of file
diff --git a/src/Endpoint.php b/src/Endpoint.php
index 71d363a..efe961f 100644
--- a/src/Endpoint.php
+++ b/src/Endpoint.php
@@ -2,7 +2,11 @@
namespace Lewisdale\Webmentions;
+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;
class Endpoint {
private readonly WebmentionGatewayInterface $gateway;
@@ -16,19 +20,35 @@ class Endpoint {
// Validate that both source and target are actual domains
if (!$this->validateUrl($source) || !$this->validateUrl($target))
{
- return;
+ throw new InvalidUrlException();
}
// Validate that the webmention target is a domain I care about
if (!str_contains($target, "https://lewisdale.dev")) {
- // Should throw a Bad Request error
- return;
+ throw new InvalidTargetException();
}
// Parse content from the source
+ $client = HttpClient::create();
+ $response = $client->request('GET', $source);
- // Store the webmention
+ if ($response->getStatusCode() === 200)
+ {
+ $content = $this->parseContent($response->getContent());
+ $author = $this->parseAuthor($response->getContent());
- // Send the appropriate response
+ $webmention = new Webmention(null, $target, $source, $content, $author);
+ $this->gateway->save($webmention);
+ }
+ }
+
+ private function parseContent(string $content) : ?string
+ {
+ return null;
+ }
+
+ private function parseAuthor(string $author) : ?string
+ {
+ return null;
}
}
\ No newline at end of file
diff --git a/src/Exceptions/InvalidTargetException.php b/src/Exceptions/InvalidTargetException.php
new file mode 100644
index 0000000..a16fd9c
--- /dev/null
+++ b/src/Exceptions/InvalidTargetException.php
@@ -0,0 +1,6 @@
+execute(["id" => $webmention->id]);
$statement->closeCursor();
}
+
+ public function find(array $values) : array
+ {
+ $keys = implode(" AND ", array_map(function($v) {
+ return "$v=:$v";
+ }, array_keys($values)));
+ $sql = <<connection->prepare($sql);
+ $statement->execute($values);
+
+ return $statement->fetchAll();
+ }
}
?>
\ No newline at end of file
diff --git a/src/Gateways/WebmentionGatewayInterface.php b/src/Gateways/WebmentionGatewayInterface.php
index 9d996a5..8a16ba6 100644
--- a/src/Gateways/WebmentionGatewayInterface.php
+++ b/src/Gateways/WebmentionGatewayInterface.php
@@ -10,6 +10,7 @@ abstract class WebmentionGatewayInterface {
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/Router/Method.php b/src/Router/Method.php
new file mode 100644
index 0000000..2db42ed
--- /dev/null
+++ b/src/Router/Method.php
@@ -0,0 +1,11 @@
+
\ No newline at end of file
diff --git a/src/Router/Response.php b/src/Router/Response.php
new file mode 100644
index 0000000..3570f48
--- /dev/null
+++ b/src/Router/Response.php
@@ -0,0 +1,37 @@
+render($values);
+ // }
+}
\ No newline at end of file
diff --git a/src/Router/Route.php b/src/Router/Route.php
new file mode 100644
index 0000000..cab3217
--- /dev/null
+++ b/src/Router/Route.php
@@ -0,0 +1,14 @@
+
diff --git a/src/Router/Router.php b/src/Router/Router.php
new file mode 100644
index 0000000..388af46
--- /dev/null
+++ b/src/Router/Router.php
@@ -0,0 +1,102 @@
+trim_route($route);
+ return "#^$formatted$#";
+ }
+
+ public function get(string $route, callable $fn) {
+ $this->routes[] = new Route(Method::GET, $this->format_route($route), $fn);
+ }
+
+ public function post(string $route, callable $fn) {
+ $this->routes[] = new Route(Method::POST, $this->format_route($route), $fn);
+ }
+
+ private function method_to_enum(string $method): Method {
+ switch ($method) {
+ case "GET":
+ return Method::GET;
+ case "POST":
+ return Method::POST;
+ default:
+ return Method::UNKNOWN;
+ }
+ }
+
+ private function get_params(array $matches): array {
+ array_shift($matches);
+ $results = array();
+
+ foreach ($matches as $match) {
+ $results[] = $match[0];
+ }
+ return $results;
+ }
+
+ public function dispatch() {
+ $uri = $_SERVER['REQUEST_URI'];
+ $method = $this->method_to_enum($_SERVER['REQUEST_METHOD']);
+
+ $num_matched = 0;
+
+ $response = new Response();
+
+ foreach($this->routes as $route) {
+ if ($method == $route->type) {
+ $matches = array();
+ if (preg_match_all($route->pattern, $uri, $matches)) {
+ $num_matched++;
+ $fn = $route->fn;
+ $params = $this->get_params($matches);
+ $response->status_code = StatusCode::Ok;
+ $response->body .= $fn(new Request($params, $uri, $method, $_POST), $response);
+ }
+ }
+ }
+
+ if (!$num_matched) {
+ // Handle 404
+ $response->status_code = StatusCode::NotFound;
+ }
+
+ $this->respond($response);
+ }
+
+ private function map_status_code(StatusCode $code): int {
+ switch ($code) {
+ case StatusCode::NotFound:
+ return 404;
+ case StatusCode::Ok:
+ return 200;
+ case StatusCode::InternalError:
+ return 500;
+ case StatusCode::Redirect:
+ return 300;
+ case StatusCode::BadRequest:
+ return 400;
+ default:
+ return 501;
+ }
+ }
+
+ private function respond(Response $response) {
+ http_response_code($this->map_status_code($response->status_code));
+
+ echo $response->body;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/src/Router/StatusCode.php b/src/Router/StatusCode.php
new file mode 100644
index 0000000..effe9a4
--- /dev/null
+++ b/src/Router/StatusCode.php
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/tests/Gateways/SqliteGatewayTest.php b/tests/Gateways/SqliteGatewayTest.php
index 3bc416f..1f62aba 100644
--- a/tests/Gateways/SqliteGatewayTest.php
+++ b/tests/Gateways/SqliteGatewayTest.php
@@ -34,8 +34,6 @@ class SqliteGatewayTest extends TestCase
public function testCanRetrieveAWebmention()
{
- $this->gateway = new SqliteGateway(":memory:");
-
$webmention = new Webmention(
null,
"https://lewisdale.dev/post/a-post",
@@ -53,8 +51,6 @@ class SqliteGatewayTest extends TestCase
public function testCanDeleteAWebmention()
{
- $this->gateway = new SqliteGateway(":memory:");
-
$webmention = new Webmention(
null,
"https://lewisdale.dev/post/a-post",
@@ -73,8 +69,6 @@ class SqliteGatewayTest extends TestCase
public function testCanGetByPost()
{
- $this->gateway = new SqliteGateway(":memory:");
-
foreach(range(0, 4) as $_) {
$this->gateway->save(new Webmention(
null,
@@ -99,4 +93,56 @@ class SqliteGatewayTest extends TestCase
$this->assertCount(5, $mentions);
}
+
+ public function testCanFindByParams()
+ {
+ $this->gateway->save(new Webmention(
+ null,
+ "https://lewisdale.dev/post/a-new-post",
+ "https://a-source.url",
+ "No content",
+ "Some Author Name"
+ ));
+
+ $this->gateway->save(new Webmention(
+ null,
+ "https://lewisdale.dev/post/a-new-post",
+ "https://a-different-source.url",
+ "No content",
+ "Some Author Name"
+ ));
+
+ $this->gateway->save(new Webmention(
+ null,
+ "https://lewisdale.dev/post/a-new-post",
+ "https://a-source.url",
+ "Some content",
+ "Some Author Name"
+ ));
+
+ $this->assertCount(
+ 2,
+ $this->gateway->find([
+ "target" => "https://lewisdale.dev/post/a-new-post",
+ "source" => "https://a-source.url"
+ ])
+ );
+
+ $this->assertCount(
+ 1,
+ $this->gateway->find([
+ "target" => "https://lewisdale.dev/post/a-new-post",
+ "source" => "https://a-different-source.url"
+ ])
+ );
+
+ $this->assertCount(
+ 1,
+ $this->gateway->find([
+ "target" => "https://lewisdale.dev/post/a-new-post",
+ "source" => "https://a-source.url",
+ "content" => "Some content"
+ ])
+ );
+ }
}