Skip to content

Commit

Permalink
Merge pull request #22 from pdsinterop/feature/notificationsInterface
Browse files Browse the repository at this point in the history
add notifications interface
  • Loading branch information
Potherca authored Sep 30, 2022
2 parents 055de9c + 27fd9c3 commit 4059f0a
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 52 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"autoload": {
"psr-4": {
"Pdsinterop\\Solid\\Resources\\": "src/"
"Pdsinterop\\Solid\\Resources\\": "src/",
"Pdsinterop\\Solid\\SolidNotifications\\": "src/"
}
},
"autoload-dev": {
Expand Down
72 changes: 21 additions & 51 deletions src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Pdsinterop\Solid\Resources;

use Pdsinterop\Solid\SolidNotifications\SolidNotificationsInterface;
use EasyRdf\Exception as RdfException;
use EasyRdf\Graph as Graph;
use Laminas\Diactoros\ServerRequest;
Expand All @@ -11,7 +12,6 @@
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Throwable;
use WebSocket\Client;
use pietercolpaert\hardf\TriGWriter;
use pietercolpaert\hardf\TriGParser;

Expand All @@ -37,6 +37,10 @@ class Server
private const MIME_TYPE_DIRECTORY = 'directory';
private const QUERY_PARAM_HTTP_METHOD = 'http-method';

private const NOTIFICATION_TYPE_CREATE = "Create";
private const NOTIFICATION_TYPE_UPDATE = "Update";
private const NOTIFICATION_TYPE_DELETE = "Delete";

/** @var string[] */
private $availableMethods = [
'DELETE',
Expand All @@ -55,8 +59,8 @@ class Server
private $filesystem;
/** @var Graph */
private $graph;
/** @var string */
private $pubsub;
/** @var SolidNotificationsInterface */
private $notifications;
/** @var Response */
private $response;

Expand Down Expand Up @@ -85,19 +89,17 @@ final public function setBaseUrl($url)
$this->basePath = $serverRequest->getUri()->getPath();
}

final public function setPubSubUrl($url)
final public function setNotifications(SolidNotificationsInterface $notifications)
{
$this->pubsub = $url;
$this->notifications = $notifications;
}

//////////////////////////////// PUBLIC API \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

// @TODO: The Graph should be injected by the caller
final public function __construct(Filesystem $filesystem, Response $response, Graph $graph = null)
{
$this->basePath = '';
$this->baseUrl = '';
$this->pubsub = '';
$this->filesystem = $filesystem;
$this->graph = $graph ?? new Graph();
$this->response = $response;
Expand Down Expand Up @@ -152,17 +154,6 @@ private function handle(string $method, string $path, $contents, $request): Resp
// Lets assume the worst...
$response = $response->withStatus(500);

// Set Accept, Allow, and CORS headers
// $response = $response
// ->withHeader('Access-Control-Allow-Origin', '*')
// ->withHeader('Access-Control-Allow-Credentials','true')
// ->withHeader('Access-Control-Allow-Headers', '*, authorization, accept, content-type')
// @FIXME: Add correct headers to resources (for instance allow DELETE on a GET resource)
// ->withAddedHeader('Accept-Patch', 'text/ldpatch')
// ->withAddedHeader('Accept-Post', 'text/turtle, application/ld+json, image/bmp, image/jpeg')
// ->withHeader('Allow', 'GET, HEAD, OPTIONS, PATCH, POST, PUT')
//;

switch ($method) {
case 'DELETE':
$response = $this->handleDeleteRequest($response, $path, $contents);
Expand All @@ -175,9 +166,6 @@ private function handle(string $method, string $path, $contents, $request): Resp
$response->getBody()->rewind();
$response->getBody()->write('');
$response = $response->withStatus(204); // CHECKME: nextcloud will remove the updates-via header - any objections to give the 'HEAD' request a 'no content' response type?
if ($this->pubsub) {
$response = $response->withHeader("updates-via", $this->pubsub);
}
}
break;

Expand Down Expand Up @@ -350,7 +338,7 @@ private function handleSparqlUpdate(Response $response, string $path, $contents)

if ($success) {
$this->removeLinkFromMetaFileFor($path);
$this->sendWebsocketUpdate($path);
$this->sendNotificationUpdate($path, self::NOTIFICATION_TYPE_UPDATE);
}
} catch (RdfException $exception) {
$response->getBody()->write(self::ERROR_CAN_NOT_PARSE_FOR_PATCH);
Expand Down Expand Up @@ -501,7 +489,7 @@ private function handleN3Update(Response $response, string $path, $contents): Re

if ($success) {
$this->removeLinkFromMetaFileFor($path);
$this->sendWebsocketUpdate($path);
$this->sendNotificationUpdate($path, self::NOTIFICATION_TYPE_UPDATE);
}
} catch (RdfException $exception) {
$response->getBody()->write(self::ERROR_CAN_NOT_PARSE_FOR_PATCH);
Expand Down Expand Up @@ -551,7 +539,7 @@ private function handleCreateRequest(Response $response, string $path, $contents
$this->removeLinkFromMetaFileFor($path);
$response = $response->withHeader("Location", $this->baseUrl . $path);
$response = $response->withStatus(201);
$this->sendWebsocketUpdate($path);
$this->sendNotificationUpdate($path, self::NOTIFICATION_TYPE_CREATE);
} else {
$response = $response->withStatus(500);
}
Expand Down Expand Up @@ -585,39 +573,21 @@ private function handleCreateDirectoryRequest(Response $response, string $path):
$response = $response->withStatus($success ? 201 : 500);
if ($success) {
$this->removeLinkFromMetaFileFor($path);
$this->sendWebsocketUpdate($path);
$this->sendNotificationUpdate($path, self::NOTIFICATION_TYPE_CREATE);
}
}

return $response;
}

private function sendWebsocketUpdate($path)
private function sendNotificationUpdate($path, $type)
{
$pubsub = $this->pubsub;
if (!$pubsub) {
return; // no pubsub server available, don't even try;
}

$pubsub = str_replace(["https://", "http://"], "ws://", $pubsub);

$baseUrl = $this->baseUrl;
$this->notifications->send($baseUrl . $path, $type);

$client = new Client($pubsub, array(
'headers' => array(
'Sec-WebSocket-Protocol' => 'solid-0.1'
)
));

try {
$client->send("pub $baseUrl$path\n");

while ($path !== "/") {
$path = $this->parentPath($path);
$client->send("pub $baseUrl$path\n");
}
} catch (\WebSocket\Exception $exception) {
throw new Exception('Could not write to pub-sup server', 502, $exception);
while ($path !== "/") {
$path = $this->parentPath($path);
$this->notifications->send($baseUrl . $path, self::NOTIFICATION_TYPE_UPDATE); // checkme: delete on a directory triggers update notifications on parents
}
}

Expand All @@ -637,15 +607,15 @@ private function handleDeleteRequest(Response $response, string $path, $contents
} else {
$success = $filesystem->deleteDir($path);
if ($success) {
$this->sendWebsocketUpdate($path);
$this->sendNotificationUpdate($path, self::NOTIFICATION_TYPE_DELETE);
}

$status = $success ? 204 : 500;
}
} else {
$success = $filesystem->delete($path);
if ($success) {
$this->sendWebsocketUpdate($path);
$this->sendNotificationUpdate($path, self::NOTIFICATION_TYPE_DELETE);
}
$status = $success ? 204 : 500;
}
Expand Down Expand Up @@ -673,7 +643,7 @@ private function handleUpdateRequest(Response $response, string $path, string $c
$response = $response->withStatus($success ? 201 : 500);
if ($success) {
$this->removeLinkFromMetaFileFor($path);
$this->sendWebsocketUpdate($path);
$this->sendNotificationUpdate($path, self::NOTIFICATION_TYPE_UPDATE);
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/SolidNotificationsInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php
namespace Pdsinterop\Solid\SolidNotifications;

interface SolidNotificationsInterface
{
public function send($path, $type);
}

0 comments on commit 4059f0a

Please sign in to comment.