From 6f614f5fda9671d76b20c7ce2dbf31ebd1a5dad7 Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Thu, 24 Sep 2026 13:52:45 +0200 Subject: [PATCH 01/15] update php to 8.3 and laminas to ^3 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index c2d7e80..ad83f64 100644 --- a/composer.json +++ b/composer.json @@ -18,9 +18,9 @@ "license": "MIT", "name": "pdsinterop/solid-crud", "require": { - "php": "^8.0", + "php": "^8.3", "ext-mbstring": "*", - "laminas/laminas-diactoros": "^2.14", + "laminas/laminas-diactoros": "^3", "league/flysystem": "^1.0", "mjrider/flysystem-factory": "^0.7", "pdsinterop/flysystem-rdf": "^0.6.1", From 24d5f3db71fd3a21bf44f67516d1606260dc77a5 Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Thu, 24 Sep 2026 15:24:53 +0200 Subject: [PATCH 02/15] easyrdf fix --- src/Server.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Server.php b/src/Server.php index bab4982..c8e8640 100644 --- a/src/Server.php +++ b/src/Server.php @@ -298,7 +298,7 @@ private function handleSparqlUpdate(Response $response, string $path, $contents) try { // Assuming this is in our native format, turtle - $graph->parse($data, "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); + $graph->parse($data . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format instead of 'turtle'? // parse query in contents @@ -312,14 +312,14 @@ private function handleSparqlUpdate(Response $response, string $path, $contents) case "INSERT": // insert $triple(s) into $graph // @CHECKME: Does the Graph Parse here also need an URI? - $graph->parse($triples, "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: The triples here are in sparql format, not in turtle; + $graph->parse($triples . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: The triples here are in sparql format, not in turtle; break; case "DELETE": // delete $triples from $graph $deleteGraph = $this->getGraph(); // @CHECKME: Does the Graph Parse here also need an URI? - $deleteGraph->parse($triples, "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: The triples here are in sparql format, not in turtle; + $deleteGraph->parse($triples . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: The triples here are in sparql format, not in turtle; $resources = $deleteGraph->resources(); foreach ($resources as $resource) { $properties = $resource->propertyUris(); @@ -455,7 +455,7 @@ private function handleN3Update(Response $response, string $path, $contents): Re try { // Assuming this is in our native format, turtle - $graph->parse($data, "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); + $graph->parse($data . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format instead of 'turtle'? $instructions = $this->n3Convert($contents); foreach ($instructions as $key => $value) { @@ -463,14 +463,14 @@ private function handleN3Update(Response $response, string $path, $contents): Re case "insert": // error_log("INSERT"); // error_log($instructions['insert']); - $graph->parse($instructions['insert'], "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); + $graph->parse($instructions['insert'] . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); break; case "delete": $deleteGraph = $this->getGraph(); // error_log("DELETE"); // error_log($instructions['delete']); - $deleteGraph->parse($instructions['delete'], "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); + $deleteGraph->parse($instructions['delete'] . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); $resources = $deleteGraph->resources(); foreach ($resources as $resource) { $properties = $resource->propertyUris(); @@ -1016,7 +1016,7 @@ private function parseLinkedMetadata(string $path) $graph = $this->getGraph(); try { - $graph->parse($describedByContents, null, '/'.$describedByPath); + $graph->parse($describedByContents . "\n", null, '/'.$describedByPath); } catch (RdfException $exception) { // If the metadata can not be parsed, the resource should still be returned (or a 404) // @CHECKME: Should the upstream add a message to the header or something? @@ -1115,7 +1115,7 @@ private function removeLinkFromMetaFileFor($path): bool try { $contents = $this->filesystem->read($describedByPath); - $graph->parse($contents, 'turtle', '/'.$describedByPath); + $graph->parse($contents . "\n", 'turtle', '/'.$describedByPath); } catch (\Throwable $e) { return false; } From 57c4267642751d9c438837015afd0be2e730fc91 Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Mon, 28 Sep 2026 15:04:35 +0200 Subject: [PATCH 03/15] update method names to align with flysystem 3 --- src/Server.php | 56 ++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/src/Server.php b/src/Server.php index c8e8640..5b3518d 100644 --- a/src/Server.php +++ b/src/Server.php @@ -208,9 +208,9 @@ private function handle(string $method, string $path, $contents, $request): Resp } break; case 'POST': - $pathExists = $filesystem->has($path); + $pathExists = $filesystem->fileExists($path); if ($pathExists) { - $mimetype = $filesystem->getMimetype($path); + $mimetype = $filesystem->mimeType($path); } if ($path === "/") { $pathExists = true; @@ -268,7 +268,7 @@ private function handle(string $method, string $path, $contents, $request): Resp $response = $this->handleCreateDirectoryRequest($response, $path); break; default: - if ($filesystem->has($path) === true) { + if ($filesystem->fileExists($path) === true) { $response = $this->handleUpdateRequest($response, $path, $contents); } else { $response = $this->handleCreateRequest($response, $path, $contents); @@ -289,7 +289,7 @@ private function handleSparqlUpdate(Response $response, string $path, $contents) $filesystem = $this->filesystem; $graph = $this->getGraph(); - if ($filesystem->has($path) === false) { + if ($filesystem->fileExists($path) === false) { $data = ''; } else { // read ttl data @@ -349,11 +349,7 @@ private function handleSparqlUpdate(Response $response, string $path, $contents) $output = $graph->serialise("turtle"); // FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format? // write ttl data - if ($filesystem->has($path) === true) { - $success = $filesystem->update($path, $output); - } else { - $success = $filesystem->write($path, $output); - } + $success = $filesystem->write($path, $output); $response = $response->withStatus($success ? 201 : 500); @@ -446,7 +442,7 @@ private function handleN3Update(Response $response, string $path, $contents): Re $graph = $this->getGraph(); $n3Graph = $this->getGraph(); - if ($filesystem->has($path) === false) { + if ($filesystem->fileExists($path) === false) { $data = ''; } else { // read ttl data @@ -497,11 +493,7 @@ private function handleN3Update(Response $response, string $path, $contents): Re $output = $graph->serialise("turtle"); // FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format? // write ttl data - if ($filesystem->has($path) === true) { - $success = $filesystem->update($path, $output); - } else { - $success = $filesystem->write($path, $output); - } + $success = $filesystem->write($path, $output); $response = $response->withStatus($success ? 201 : 500); @@ -525,7 +517,7 @@ private function handleCreateRequest(Response $response, string $path, $contents { $filesystem = $this->filesystem; - if ($filesystem->has($path) === true) { + if ($filesystem->fileExists($path) === true) { $message = vsprintf(self::ERROR_PUT_EXISTING_RESOURCE, [$path]); $response->getBody()->write($message); $response = $response->withStatus(400); @@ -582,12 +574,12 @@ private function parentPath($path) private function handleCreateDirectoryRequest(Response $response, string $path): Response { $filesystem = $this->filesystem; - if ($filesystem->has($path) === true) { + if ($filesystem->fileExists($path) === true) { $message = vsprintf(self::ERROR_PUT_EXISTING_RESOURCE, [$path]); $response->getBody()->write($message); $response = $response->withStatus(400); } else { - $success = $filesystem->createDir($path); + $success = $filesystem->createDirectory($path); $response = $response->withStatus($success ? 201 : 500); if ($success) { $this->removeLinkFromMetaFileFor($path); @@ -617,8 +609,8 @@ private function handleDeleteRequest(Response $response, string $path, $contents { $filesystem = $this->filesystem; - if ($filesystem->has($path)) { - $mimetype = $filesystem->getMimetype($path); + if ($filesystem->fileExists($path)) { + $mimetype = $filesystem->mimeType($path); if ($mimetype === self::MIME_TYPE_DIRECTORY) { $directoryContents = $filesystem->listContents($path, true); @@ -627,7 +619,7 @@ private function handleDeleteRequest(Response $response, string $path, $contents $message = vsprintf(self::ERROR_CAN_NOT_DELETE_NON_EMPTY_CONTAINER, [$path]); $response->getBody()->write($message); } else { - $success = $filesystem->deleteDir($path); + $success = $filesystem->deleteDirectory($path); if ($success) { $this->sendNotificationUpdate($path, self::NOTIFICATION_TYPE_DELETE); } @@ -656,12 +648,12 @@ private function handleUpdateRequest(Response $response, string $path, string $c { $filesystem = $this->filesystem; - if ($filesystem->has($path) === false) { + if ($filesystem->fileExists($path) === false) { $message = vsprintf(self::ERROR_PUT_NON_EXISTING_RESOURCE, [$path]); $response->getBody()->write($message); $response = $response->withStatus(400); } else { - $success = $filesystem->update($path, $contents); + $success = $filesystem->write($path, $contents); $response = $response->withStatus($success ? 201 : 500); if ($success) { $this->removeLinkFromMetaFileFor($path); @@ -707,12 +699,12 @@ private function handleReadRequest(Response $response, string $path, $contents, '; rel="type"', ]); $response = $response->withStatus(200); - } elseif(($filesystem->has($path) === false) && (($path == ".meta") || ($path == "/.meta"))) { + } elseif(($filesystem->fileExists($path) === false) && (($path == ".meta") || ($path == "/.meta"))) { $contents = ''; $response->getBody()->write($contents); $response = $response->withHeader("Content-type", "text/turtle"); $response = $response->withStatus(200); - } elseif ($filesystem->has($path) === false && $this->hasDescribedBy($path) === false) { + } elseif ($filesystem->fileExists($path) === false && $this->hasDescribedBy($path) === false) { /*/ The file does not exist and no link-metadata is present /*/ $message = vsprintf(self::ERROR_PATH_DOES_NOT_EXIST, [$path]); $response->getBody()->write($message); @@ -722,21 +714,21 @@ private function handleReadRequest(Response $response, string $path, $contents, if ($linkMetadataResponse !== null) { /*/ Link-metadata is present, return the altered response /*/ $response = $linkMetadataResponse; - } elseif ($filesystem->getMimetype($path) === self::MIME_TYPE_DIRECTORY) { + } elseif ($filesystem->mimeType($path) === self::MIME_TYPE_DIRECTORY) { $contents = $this->listDirectoryAsTurtle($path); $response->getBody()->write($contents); $response = $response->withHeader("Content-type", "text/turtle")->withStatus(200); - } elseif ($filesystem->asMime($mime)->has($path)) { + } elseif ($filesystem->asMime($mime)->fileExists($path)) { /*/ The file does exist and no link-metadata is present /*/ $response = $this->addLinkRelationHeaders($response, $path, $mime); if (preg_match('/\.(acl|meta|ttl)$/', $path)) { $mimetype = "text/turtle"; // FIXME: teach flysystem that .acl/.meta/.ttl means text/turtle } else { - $mimetype = $filesystem->asMime($mime)->getMimetype($path); + $mimetype = $filesystem->asMime($mime)->mimeType($path); } - $fileMimeType = $filesystem->asMime('')->getMimetype($path); + $fileMimeType = $filesystem->asMime('')->mimeType($path); if (in_array($fileMimeType, $acceptedMimeTypes)) { $contents = $filesystem->asMime('')->read($path); $mimetype = $fileMimeType; @@ -748,7 +740,7 @@ private function handleReadRequest(Response $response, string $path, $contents, $response->getBody()->write($contents); $response = $response->withHeader("Content-type", $mimetype)->withStatus(200); } else { - // FIXME: we should not get here if the file does not exist, but here we are. It looks like $filesystem->has("/.meta") always returns true even if the file does not exist; + // FIXME: we should not get here if the file does not exist, but here we are. It looks like $filesystem->fileExists("/.meta") always returns true even if the file does not exist; if ($path == "/.meta") { $contents = ''; $response->getBody()->write($contents); @@ -1090,7 +1082,7 @@ private function findPath(array $rdfPaths, string $path) foreach ($rdfPaths as $rdfPath) { if ( strrpos($path, $rdfPath) === 0 - && $this->filesystem->has($rdfPath) + && $this->filesystem->fileExists($rdfPath) ) { // @FIXME: We have no way of knowing if the file is a directory or a file. // This means that, unless we make a trialing slash `/` required, @@ -1151,7 +1143,7 @@ private function removeLinkFromMetaFileFor($path): bool if ($changed) { $changedContents = $graph->serialise('turtle'); try { - $result = $this->filesystem->update($describedByPath, $changedContents); + $result = $this->filesystem->write($describedByPath, $changedContents); } catch (FileNotFoundException $exception) { // $result is already false; } From 577fd9fd51e8f324048a1362ad2f0f9d04897c54 Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Mon, 28 Sep 2026 15:05:07 +0200 Subject: [PATCH 04/15] use dev-branch flysystem-3 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ad83f64..0301788 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "laminas/laminas-diactoros": "^3", "league/flysystem": "^1.0", "mjrider/flysystem-factory": "^0.7", - "pdsinterop/flysystem-rdf": "^0.6.1", + "pdsinterop/flysystem-rdf": "dev-feature/flysystem-3", "pietercolpaert/hardf": "^0.3", "psr/http-factory": "^1.0", "psr/http-message": "^1.0" From 9716ce2056e997e33d30096dc781d90a17f3e9ae Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Mon, 28 Sep 2026 15:06:42 +0200 Subject: [PATCH 05/15] drop php 8.0, 8.1 and 8.2. Add 8.4 --- .github/workflows/php.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 33c065c..b871f2c 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -74,10 +74,8 @@ jobs: fail-fast: false matrix: php: - - '8.0' # from 2020-11 to 2022-11 (2023-11) - - '8.1' # from 2021-11 to 2023-11 (2025-12) - - '8.2' # from 2022-12 to 2024-12 (2026-12) - '8.3' # from 2023-11 to 2025-12 (2027-12) + - '8.4' steps: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 @@ -118,10 +116,8 @@ jobs: fail-fast: false matrix: php: - - '8.0' # from 2020-11 to 2022-11 (2023-11) - - '8.1' # from 2021-11 to 2023-11 (2025-12) - - '8.2' # from 2022-12 to 2024-12 (2026-12) - '8.3' # from 2023-11 to 2025-12 (2027-12) + - '8.4' steps: - uses: actions/checkout@v4 - uses: docker://pipelinecomponents/php-codesniffer From f7a254174474e46c34e9eb943520b6c4379b2fd8 Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Mon, 28 Sep 2026 15:07:45 +0200 Subject: [PATCH 06/15] Revert "easyrdf fix" This reverts commit 24d5f3db71fd3a21bf44f67516d1606260dc77a5. --- src/Server.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Server.php b/src/Server.php index 5b3518d..28f8c87 100644 --- a/src/Server.php +++ b/src/Server.php @@ -298,7 +298,7 @@ private function handleSparqlUpdate(Response $response, string $path, $contents) try { // Assuming this is in our native format, turtle - $graph->parse($data . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); + $graph->parse($data, "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format instead of 'turtle'? // parse query in contents @@ -312,14 +312,14 @@ private function handleSparqlUpdate(Response $response, string $path, $contents) case "INSERT": // insert $triple(s) into $graph // @CHECKME: Does the Graph Parse here also need an URI? - $graph->parse($triples . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: The triples here are in sparql format, not in turtle; + $graph->parse($triples, "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: The triples here are in sparql format, not in turtle; break; case "DELETE": // delete $triples from $graph $deleteGraph = $this->getGraph(); // @CHECKME: Does the Graph Parse here also need an URI? - $deleteGraph->parse($triples . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: The triples here are in sparql format, not in turtle; + $deleteGraph->parse($triples, "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: The triples here are in sparql format, not in turtle; $resources = $deleteGraph->resources(); foreach ($resources as $resource) { $properties = $resource->propertyUris(); @@ -451,7 +451,7 @@ private function handleN3Update(Response $response, string $path, $contents): Re try { // Assuming this is in our native format, turtle - $graph->parse($data . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); + $graph->parse($data, "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); // FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format instead of 'turtle'? $instructions = $this->n3Convert($contents); foreach ($instructions as $key => $value) { @@ -459,14 +459,14 @@ private function handleN3Update(Response $response, string $path, $contents): Re case "insert": // error_log("INSERT"); // error_log($instructions['insert']); - $graph->parse($instructions['insert'] . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); + $graph->parse($instructions['insert'], "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); break; case "delete": $deleteGraph = $this->getGraph(); // error_log("DELETE"); // error_log($instructions['delete']); - $deleteGraph->parse($instructions['delete'] . "\n", "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); + $deleteGraph->parse($instructions['delete'], "turtle", $this->baseUrl . $this->basePath . $this->requestedPath); $resources = $deleteGraph->resources(); foreach ($resources as $resource) { $properties = $resource->propertyUris(); @@ -1008,7 +1008,7 @@ private function parseLinkedMetadata(string $path) $graph = $this->getGraph(); try { - $graph->parse($describedByContents . "\n", null, '/'.$describedByPath); + $graph->parse($describedByContents, null, '/'.$describedByPath); } catch (RdfException $exception) { // If the metadata can not be parsed, the resource should still be returned (or a 404) // @CHECKME: Should the upstream add a message to the header or something? @@ -1107,7 +1107,7 @@ private function removeLinkFromMetaFileFor($path): bool try { $contents = $this->filesystem->read($describedByPath); - $graph->parse($contents . "\n", 'turtle', '/'.$describedByPath); + $graph->parse($contents, 'turtle', '/'.$describedByPath); } catch (\Throwable $e) { return false; } From 1697024ba029382cb0eb747d19c51e093f7527c4 Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Wed, 30 Sep 2026 15:37:55 +0200 Subject: [PATCH 07/15] fix for metadata, use dev-main --- composer.json | 2 +- src/Server.php | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 0301788..723ef8b 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "laminas/laminas-diactoros": "^3", "league/flysystem": "^1.0", "mjrider/flysystem-factory": "^0.7", - "pdsinterop/flysystem-rdf": "dev-feature/flysystem-3", + "pdsinterop/flysystem-rdf": "dev-main", "pietercolpaert/hardf": "^0.3", "psr/http-factory": "^1.0", "psr/http-message": "^1.0" diff --git a/src/Server.php b/src/Server.php index 28f8c87..8c62696 100644 --- a/src/Server.php +++ b/src/Server.php @@ -718,22 +718,22 @@ private function handleReadRequest(Response $response, string $path, $contents, $contents = $this->listDirectoryAsTurtle($path); $response->getBody()->write($contents); $response = $response->withHeader("Content-type", "text/turtle")->withStatus(200); - } elseif ($filesystem->asMime($mime)->fileExists($path)) { + } elseif ($filesystem->asMime($mime)->fileExists($path)) { // FIXME: setFormat instead /*/ The file does exist and no link-metadata is present /*/ $response = $this->addLinkRelationHeaders($response, $path, $mime); if (preg_match('/\.(acl|meta|ttl)$/', $path)) { $mimetype = "text/turtle"; // FIXME: teach flysystem that .acl/.meta/.ttl means text/turtle } else { - $mimetype = $filesystem->asMime($mime)->mimeType($path); + $mimetype = $filesystem->asMime($mime)->mimeType($path); // FIXME: setFormat instead } - $fileMimeType = $filesystem->asMime('')->mimeType($path); + $fileMimeType = $filesystem->asMime('')->mimeType($path); // FIXME: setFormat instead if (in_array($fileMimeType, $acceptedMimeTypes)) { - $contents = $filesystem->asMime('')->read($path); + $contents = $filesystem->asMime('')->read($path); // FIXME: setFormat instead $mimetype = $fileMimeType; } else { - $contents = $filesystem->asMime($mime)->read($path); + $contents = $filesystem->asMime($mime)->read($path); // FIXME: setFormat instead } if ($contents !== false) { @@ -916,10 +916,11 @@ private function getMetadata(string $path, $mime) : array try { if ($mime) { - $metadata = $filesystem->asMime($mime)->getMetadata($path); + $fileAttributes = $filesystem->asMime($mime)->getAttributes($path); // FIXME: setFormat instead } else { - $metadata = $filesystem->getMetadata($path); + $fileAttributes = $filesystem->getAttributes($path); } + $metadata = $fileAttributes->extraMetaData(); } catch (FileNotFoundException $e) { $metadata = []; } @@ -997,7 +998,7 @@ private function parseLinkedMetadata(string $path) $linkMeta = []; try { - $describedByPath = $this->filesystem->getMetadata($path)['describedby'] ?? ''; + $describedByPath = $this->filesystem->getAttributes($path)->extraMetaData()['describedby'] ?? ''; $describedByContents = $this->filesystem->read($describedByPath); } catch (FileNotFoundException $e) { // If, for whatever reason, the file is not present after all, the resource should still be returned (or a 404) From 0c7619ee2967c578ca85657a26458c60527da311 Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Wed, 30 Sep 2026 15:44:24 +0200 Subject: [PATCH 08/15] update composer to flysystem 3 --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 723ef8b..fda3470 100644 --- a/composer.json +++ b/composer.json @@ -21,8 +21,7 @@ "php": "^8.3", "ext-mbstring": "*", "laminas/laminas-diactoros": "^3", - "league/flysystem": "^1.0", - "mjrider/flysystem-factory": "^0.7", + "league/flysystem": "^3", "pdsinterop/flysystem-rdf": "dev-main", "pietercolpaert/hardf": "^0.3", "psr/http-factory": "^1.0", From 75a0fec12ca4444910da6300ddfbd8315f434973 Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Wed, 30 Sep 2026 17:08:10 +0200 Subject: [PATCH 09/15] changed constructor to expect the adapter as well, so we can call setFormat instead of asMime --- src/Server.php | 52 +++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/Server.php b/src/Server.php index 8c62696..6a3cbb0 100644 --- a/src/Server.php +++ b/src/Server.php @@ -8,7 +8,8 @@ use Laminas\Diactoros\ServerRequest; use League\Flysystem\FileExistsException; use League\Flysystem\FileNotFoundException; -use League\Flysystem\FilesystemInterface as Filesystem; +use League\Flysystem\FilesystemOperator as Filesystem; +use League\Flysystem\FilesystemAdapter; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Throwable; @@ -61,6 +62,8 @@ class Server private $requestedPath; /** @var Filesystem */ private $filesystem; + /** @var FilesystemAdapter */ + private $adapter; /** @var Graph */ private $graph; /** @var SolidNotificationsInterface */ @@ -105,12 +108,13 @@ final public function setNotifications(SolidNotificationsInterface $notification //////////////////////////////// PUBLIC API \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ // @TODO: The Graph should be injected by the caller - final public function __construct(Filesystem $filesystem, Response $response, ?Graph $graph = null) + final public function __construct(Filesystem $filesystem, FilesystemAdapter $adapter, Response $response, ?Graph $graph = null) { $this->basePath = ''; $this->baseUrl = ''; $this->lockedPath = false; $this->filesystem = $filesystem; + $this->adapter = $adapter; $this->graph = $graph ?? new Graph(); $this->response = $response; // @TODO: Mention \EasyRdf_Namespace::set('lm', 'https://purl.org/pdsinterop/link-metadata#'); @@ -349,8 +353,8 @@ private function handleSparqlUpdate(Response $response, string $path, $contents) $output = $graph->serialise("turtle"); // FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format? // write ttl data - $success = $filesystem->write($path, $output); - + $filesystem->write($path, $output, []); + $success = true; $response = $response->withStatus($success ? 201 : 500); if ($success) { @@ -493,8 +497,8 @@ private function handleN3Update(Response $response, string $path, $contents): Re $output = $graph->serialise("turtle"); // FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format? // write ttl data - $success = $filesystem->write($path, $output); - + $filesystem->write($path, $output, []); + $success = true; $response = $response->withStatus($success ? 201 : 500); if ($success) { @@ -516,20 +520,19 @@ private function handleN3Update(Response $response, string $path, $contents): Re private function handleCreateRequest(Response $response, string $path, $contents): Response { $filesystem = $this->filesystem; - if ($filesystem->fileExists($path) === true) { $message = vsprintf(self::ERROR_PUT_EXISTING_RESOURCE, [$path]); $response->getBody()->write($message); $response = $response->withStatus(400); } else { $success = false; - set_error_handler(static function ($severity, $message, $filename, $line) { throw new \ErrorException($message, 0, $severity, $filename, $line); }); try { - $success = $filesystem->write($path, $contents); + $filesystem->write($path, $contents, []); + $success = true; } catch (FileExistsException $e) { $message = vsprintf(self::ERROR_PUT_EXISTING_RESOURCE, [$path]); $response->getBody()->write($message); @@ -544,7 +547,6 @@ private function handleCreateRequest(Response $response, string $path, $contents } finally { restore_error_handler(); } - if ($success) { $this->removeLinkFromMetaFileFor($path); $response = $response->withHeader("Location", $this->baseUrl . $path); @@ -653,7 +655,8 @@ private function handleUpdateRequest(Response $response, string $path, string $c $response->getBody()->write($message); $response = $response->withStatus(400); } else { - $success = $filesystem->write($path, $contents); + $filesystem->write($path, $contents, []); + $success = true; $response = $response->withStatus($success ? 201 : 500); if ($success) { $this->removeLinkFromMetaFileFor($path); @@ -718,22 +721,26 @@ private function handleReadRequest(Response $response, string $path, $contents, $contents = $this->listDirectoryAsTurtle($path); $response->getBody()->write($contents); $response = $response->withHeader("Content-type", "text/turtle")->withStatus(200); - } elseif ($filesystem->asMime($mime)->fileExists($path)) { // FIXME: setFormat instead + } elseif ((true | $this->adapter->setFormat($mime)) && $filesystem->fileExists($path)) { /*/ The file does exist and no link-metadata is present /*/ $response = $this->addLinkRelationHeaders($response, $path, $mime); if (preg_match('/\.(acl|meta|ttl)$/', $path)) { $mimetype = "text/turtle"; // FIXME: teach flysystem that .acl/.meta/.ttl means text/turtle } else { - $mimetype = $filesystem->asMime($mime)->mimeType($path); // FIXME: setFormat instead + $this->adapter->setFormat($mime); + $mimetype = $filesystem->mimeType($path); } - $fileMimeType = $filesystem->asMime('')->mimeType($path); // FIXME: setFormat instead + $this->adapter->setFormat(''); + $fileMimeType = $filesystem->mimeType($path); if (in_array($fileMimeType, $acceptedMimeTypes)) { - $contents = $filesystem->asMime('')->read($path); // FIXME: setFormat instead + $this->adapter->setFormat(''); + $contents = $filesystem->read($path); $mimetype = $fileMimeType; } else { - $contents = $filesystem->asMime($mime)->read($path); // FIXME: setFormat instead + $this->adapter->setFormat($mime); + $contents = $filesystem->read($path); } if ($contents !== false) { @@ -912,13 +919,13 @@ private function getMetadata(string $path, $mime) : array static $metadataCache = []; if (isset($metadataCache[$path]) === false) { - $filesystem = $this->filesystem; - try { if ($mime) { - $fileAttributes = $filesystem->asMime($mime)->getAttributes($path); // FIXME: setFormat instead + $this->adapter->setFormat($mime); + $fileAttributes = $this->adapter->fileSize($path); + $this->adapter->setFormat(''); } else { - $fileAttributes = $filesystem->getAttributes($path); + $fileAttributes = $this->adapter->fileSize($path); } $metadata = $fileAttributes->extraMetaData(); } catch (FileNotFoundException $e) { @@ -998,7 +1005,7 @@ private function parseLinkedMetadata(string $path) $linkMeta = []; try { - $describedByPath = $this->filesystem->getAttributes($path)->extraMetaData()['describedby'] ?? ''; + $describedByPath = $this->adapter->fileSize($path)->extraMetaData()['describedby'] ?? ''; $describedByContents = $this->filesystem->read($describedByPath); } catch (FileNotFoundException $e) { // If, for whatever reason, the file is not present after all, the resource should still be returned (or a 404) @@ -1144,7 +1151,8 @@ private function removeLinkFromMetaFileFor($path): bool if ($changed) { $changedContents = $graph->serialise('turtle'); try { - $result = $this->filesystem->write($describedByPath, $changedContents); + $this->filesystem->write($describedByPath, $changedContents, []); + $result = true; } catch (FileNotFoundException $exception) { // $result is already false; } From 40c66ce5dd5436ffbe8058064e3a1b8aa07f5363 Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Wed, 30 Sep 2026 17:08:35 +0200 Subject: [PATCH 10/15] updated tests --- tests/unit/ServerTest.php | 80 ++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 23 deletions(-) diff --git a/tests/unit/ServerTest.php b/tests/unit/ServerTest.php index df0b2a7..9bed1b4 100644 --- a/tests/unit/ServerTest.php +++ b/tests/unit/ServerTest.php @@ -9,7 +9,9 @@ use EasyRdf\Graph; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequest; -use League\Flysystem\FilesystemInterface; +use League\Flysystem\FilesystemAdapter; +use League\Flysystem\FilesystemOperator; +use League\Flysystem\FileAttributes; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -44,24 +46,40 @@ public function testInstatiationWithoutFileSystem() new Server(); } - /** @testdox Server should complain when instantiated without Response */ - public function testInstatiationWithoutResponse() + /** @testdox Server should complain when instantiated without Adapter */ + public function testInstatiationWithoutAdapter() { $this->expectException(ArgumentCountError::class); $this->expectExceptionMessageMatches('/Too few arguments .+ 1 passed/'); - $mockFileSystem = $this->getMockBuilder(FilesystemInterface::class)->getMock(); + $mockFileSystem = $this->getMockBuilder(FilesystemOperator::class)->getMock(); new Server($mockFileSystem); } + /** @testdox Server should be instantiated when constructed without Response */ + public function testInstatiationWithoutResponse() + { + $this->expectException(ArgumentCountError::class); + $this->expectExceptionMessageMatches('/Too few arguments .+ 2 passed/'); + + $mockFileSystem = $this->getMockBuilder(FilesystemOperator::class)->getMock(); + $mockAdapter = $this->getMockBuilder(FilesystemAdapter::class)->getMock(); + + $actual = new Server($mockFileSystem, $mockAdapter); + $expected = Server::class; + + $this->assertInstanceOf($expected, $actual); + } + /** @testdox Server should be instantiated when constructed without Graph */ public function testInstatiationWithoutGraph() { - $mockFileSystem = $this->getMockBuilder(FilesystemInterface::class)->getMock(); + $mockFileSystem = $this->getMockBuilder(FilesystemOperator::class)->getMock(); + $mockAdapter = $this->getMockBuilder(FilesystemAdapter::class)->getMock(); $mockResponse = $this->getMockBuilder(ResponseInterface::class)->getMock(); - $actual = new Server($mockFileSystem, $mockResponse); + $actual = new Server($mockFileSystem, $mockAdapter, $mockResponse); $expected = Server::class; $this->assertInstanceOf($expected, $actual); @@ -70,11 +88,12 @@ public function testInstatiationWithoutGraph() /** @testdox Server should be instantiated when constructed with Graph */ public function testInstatiationWithGraph() { - $mockFileSystem = $this->getMockBuilder(FilesystemInterface::class)->getMock(); + $mockFileSystem = $this->getMockBuilder(FilesystemOperator::class)->getMock(); + $mockAdapter = $this->getMockBuilder(FilesystemAdapter::class)->getMock(); $mockResponse = $this->getMockBuilder(ResponseInterface::class)->getMock(); $mockGraph = $this->getMockBuilder(Graph::class)->getMock(); - $actual = new Server($mockFileSystem, $mockResponse, $mockGraph); + $actual = new Server($mockFileSystem, $mockAdapter, $mockResponse, $mockGraph); $expected = Server::class; $this->assertInstanceOf($expected, $actual); @@ -88,11 +107,12 @@ public function testInstatiationWithGraph() public function testRespondToRequestWithoutRequest() { // Arrange - $mockFileSystem = $this->getMockBuilder(FilesystemInterface::class)->getMock(); + $mockFileSystem = $this->getMockBuilder(FilesystemOperator::class)->getMock(); + $mockAdapter = $this->getMockBuilder(FilesystemAdapter::class)->getMock(); $mockResponse = $this->getMockBuilder(ResponseInterface::class)->getMock(); $mockGraph = $this->getMockBuilder(Graph::class)->getMock(); - $server = new Server($mockFileSystem, $mockResponse, $mockGraph); + $server = new Server($mockFileSystem, $mockAdapter, $mockResponse, $mockGraph); // Assert $this->expectException(ArgumentCountError::class); @@ -112,13 +132,14 @@ public function testRespondToRequestWithoutRequest() public function testRespondToRequestWithUnsupportedHttpMethod($httpMethod) { // Arrange - $mockFileSystem = $this->getMockBuilder(FilesystemInterface::class)->getMock(); + $mockFileSystem = $this->getMockBuilder(FilesystemOperator::class)->getMock(); + $mockAdapter = $this->getMockBuilder(FilesystemAdapter::class)->getMock(); $mockGraph = $this->getMockBuilder(Graph::class)->getMock(); $request = $this->createRequest($httpMethod); $mockResponse = new Response(); - $server = new Server($mockFileSystem, $mockResponse, $mockGraph); + $server = new Server($mockFileSystem, $mockAdapter, $mockResponse, $mockGraph); // Assert $this->expectException(Exception::class); @@ -138,8 +159,11 @@ public function testRespondToRequestWithUnsupportedHttpMethod($httpMethod) public function testRespondToPOSTCreateRequest($slug, $mimetype, $expected) { // Arrange - $mockFileSystem = $this->getMockBuilder(FilesystemInterface::class)->getMock(); + $mockFileSystem = $this->getMockBuilder(FilesystemOperator::class)->getMock(); + $mockAdapter = $this->getMockBuilder(FilesystemAdapter::class)->getMock(); $mockGraph = $this->getMockBuilder(Graph::class)->getMock(); + $mockAttributes = $this->getMockBuilder(FileAttributes::class)->setConstructorArgs(['/'])->getMock(); + $request = $this->createRequest('POST', [ 'Content-Type' => $mimetype, 'Link' => '', @@ -147,24 +171,34 @@ public function testRespondToPOSTCreateRequest($slug, $mimetype, $expected) ]); $mockFileSystem - ->method('has') + ->method('fileExists') + ->willReturnCallback(function($path) { + if ($path === self::MOCK_PATH) { + return true; + } + return false; + }); + + $mockAdapter + ->method('fileSize') + ->withAnyParameters() + ->willReturn($mockAttributes); + + $mockAttributes + ->method('extraMetaData') ->withAnyParameters() - ->willReturnMap([ - [self::MOCK_PATH, true], + ->willReturn([ +// 'describedby' => self::MOCK_PATH . ".meta", +// 'acl' => self::MOCK_PATH . ".acl" ]); $mockFileSystem - ->method('getMimetype') + ->method('mimeType') ->with(self::MOCK_PATH) ->willReturn(Server::MIME_TYPE_DIRECTORY); - $mockFileSystem - ->method('write') - ->withAnyParameters() - ->willReturn(true); - // Act - $server = new Server($mockFileSystem, new Response(), $mockGraph); + $server = new Server($mockFileSystem, $mockAdapter, new Response(), $mockGraph); $response = $server->respondToRequest($request); // Assert From d5932202939bdee65a037a13ad25cd335c5c8ceb Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Wed, 30 Sep 2026 17:57:51 +0200 Subject: [PATCH 11/15] use setMimeFormat as replacement for asMime --- src/Server.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Server.php b/src/Server.php index 6a3cbb0..de33a1d 100644 --- a/src/Server.php +++ b/src/Server.php @@ -721,25 +721,25 @@ private function handleReadRequest(Response $response, string $path, $contents, $contents = $this->listDirectoryAsTurtle($path); $response->getBody()->write($contents); $response = $response->withHeader("Content-type", "text/turtle")->withStatus(200); - } elseif ((true | $this->adapter->setFormat($mime)) && $filesystem->fileExists($path)) { + } elseif ((true | $this->adapter->setMimeFormat($mime)) && $filesystem->fileExists($path)) { /*/ The file does exist and no link-metadata is present /*/ $response = $this->addLinkRelationHeaders($response, $path, $mime); if (preg_match('/\.(acl|meta|ttl)$/', $path)) { $mimetype = "text/turtle"; // FIXME: teach flysystem that .acl/.meta/.ttl means text/turtle } else { - $this->adapter->setFormat($mime); + $this->adapter->setMimeFormat($mime); $mimetype = $filesystem->mimeType($path); } - $this->adapter->setFormat(''); + $this->adapter->setMimeFormat(''); $fileMimeType = $filesystem->mimeType($path); if (in_array($fileMimeType, $acceptedMimeTypes)) { - $this->adapter->setFormat(''); + $this->adapter->setMimeFormat(''); $contents = $filesystem->read($path); $mimetype = $fileMimeType; } else { - $this->adapter->setFormat($mime); + $this->adapter->setMimeFormat($mime); $contents = $filesystem->read($path); } @@ -921,9 +921,9 @@ private function getMetadata(string $path, $mime) : array if (isset($metadataCache[$path]) === false) { try { if ($mime) { - $this->adapter->setFormat($mime); + $this->adapter->setMimeFormat($mime); $fileAttributes = $this->adapter->fileSize($path); - $this->adapter->setFormat(''); + $this->adapter->setMimeFormat(''); } else { $fileAttributes = $this->adapter->fileSize($path); } From 1c8ea17e04456cb09d2554e13d761e5846dfdc01 Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Wed, 30 Sep 2026 21:54:28 +0200 Subject: [PATCH 12/15] use try/catch to determine success --- src/Server.php | 54 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/src/Server.php b/src/Server.php index de33a1d..5a87a12 100644 --- a/src/Server.php +++ b/src/Server.php @@ -353,8 +353,12 @@ private function handleSparqlUpdate(Response $response, string $path, $contents) $output = $graph->serialise("turtle"); // FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format? // write ttl data - $filesystem->write($path, $output, []); - $success = true; + try { + $filesystem->write($path, $output, []); + $success = true; + } catch (\Exception $e) { + $success = false; + } $response = $response->withStatus($success ? 201 : 500); if ($success) { @@ -497,8 +501,12 @@ private function handleN3Update(Response $response, string $path, $contents): Re $output = $graph->serialise("turtle"); // FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format? // write ttl data - $filesystem->write($path, $output, []); - $success = true; + try { + $filesystem->write($path, $output, []); + $success = true; + } catch (\Exception $e) { + $success = false; + } $response = $response->withStatus($success ? 201 : 500); if ($success) { @@ -534,11 +542,13 @@ private function handleCreateRequest(Response $response, string $path, $contents $filesystem->write($path, $contents, []); $success = true; } catch (FileExistsException $e) { + $success = false; $message = vsprintf(self::ERROR_PUT_EXISTING_RESOURCE, [$path]); $response->getBody()->write($message); return $response->withStatus(400); } catch (Throwable $exception) { + $success = false; /*/ An error occurred in the underlying flysystem adapter /*/ $message = vsprintf('Could not write to path %s: %s', [$path, $exception->getMessage()]); $response->getBody()->write($message); @@ -581,7 +591,12 @@ private function handleCreateDirectoryRequest(Response $response, string $path): $response->getBody()->write($message); $response = $response->withStatus(400); } else { - $success = $filesystem->createDirectory($path); + try { + $filesystem->createDirectory($path); + $success = true; + } catch (\Exception $e) { + $success = false; + } $response = $response->withStatus($success ? 201 : 500); if ($success) { $this->removeLinkFromMetaFileFor($path); @@ -621,7 +636,12 @@ private function handleDeleteRequest(Response $response, string $path, $contents $message = vsprintf(self::ERROR_CAN_NOT_DELETE_NON_EMPTY_CONTAINER, [$path]); $response->getBody()->write($message); } else { - $success = $filesystem->deleteDirectory($path); + try { + $filesystem->deleteDirectory($path); + $success = true; + } catch (\Exception $e) { + $success = false; + } if ($success) { $this->sendNotificationUpdate($path, self::NOTIFICATION_TYPE_DELETE); } @@ -629,7 +649,13 @@ private function handleDeleteRequest(Response $response, string $path, $contents $status = $success ? 204 : 500; } } else { - $success = $filesystem->delete($path); + try { + $filesystem->delete($path); + $success = true; + } catch (\Exception $e) { + $success = false; + } + if ($success) { $this->sendNotificationUpdate($path, self::NOTIFICATION_TYPE_DELETE); } @@ -655,8 +681,12 @@ private function handleUpdateRequest(Response $response, string $path, string $c $response->getBody()->write($message); $response = $response->withStatus(400); } else { - $filesystem->write($path, $contents, []); - $success = true; + try { + $filesystem->write($path, $contents, []); + $success = true; + } catch (\Exception $e) { + $success = false; + } $response = $response->withStatus($success ? 201 : 500); if ($success) { $this->removeLinkFromMetaFileFor($path); @@ -707,7 +737,8 @@ private function handleReadRequest(Response $response, string $path, $contents, $response->getBody()->write($contents); $response = $response->withHeader("Content-type", "text/turtle"); $response = $response->withStatus(200); - } elseif ($filesystem->fileExists($path) === false && $this->hasDescribedBy($path) === false) { + } elseif ($filesystem->fileExists($path) === false) { // FIXME: Check with @potherca how this is supposed to work. Removed the hasDescribedBy for now. + // && $this->hasDescribedBy($path) === false) { /*/ The file does not exist and no link-metadata is present /*/ $message = vsprintf(self::ERROR_PATH_DOES_NOT_EXIST, [$path]); $response->getBody()->write($message); @@ -945,6 +976,9 @@ private function hasAcl(string $path, $mime = null): bool private function hasDescribedBy(string $path, $mime = null): bool { + if ($this->adapter->fileExists($path) === false) { + return false; + } return $this->getDescribedByPath($path, $mime) !== ''; } From 52d6cc0d4d2cca79a9416ba10a24bcf0d43b88da Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Thu, 1 Oct 2026 16:37:17 +0200 Subject: [PATCH 13/15] iterator to array --- src/Server.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Server.php b/src/Server.php index 5a87a12..cbc279a 100644 --- a/src/Server.php +++ b/src/Server.php @@ -630,7 +630,7 @@ private function handleDeleteRequest(Response $response, string $path, $contents $mimetype = $filesystem->mimeType($path); if ($mimetype === self::MIME_TYPE_DIRECTORY) { - $directoryContents = $filesystem->listContents($path, true); + $directoryContents = iterator_to_array($filesystem->listContents($path, true)); if (count($directoryContents) > 0) { $status = 400; $message = vsprintf(self::ERROR_CAN_NOT_DELETE_NON_EMPTY_CONTAINER, [$path]); @@ -811,9 +811,9 @@ private function listDirectoryAsTurtle($path) { $filesystem = $this->filesystem; if ($path === "/") { - $listContents = $filesystem->listContents(".");// FIXME: this is a patch to make it work for Solid-Nextcloud; we should be able to just list '/'; + $listContents = iterator_to_array($filesystem->listContents(".")); // FIXME: this is a patch to make it work for Solid-Nextcloud; we should be able to just list '/'; } else { - $listContents = $filesystem->listContents($path); + $listContents = iterator_to_array($filesystem->listContents($path)); } // CHECKME: maybe structure this data als RDF/PHP // https://www.easyrdf.org/docs/rdf-formats-php From 3265bb8556ae7012a73a4ee58ca7a8b345668e3b Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Fri, 2 Oct 2026 13:39:51 +0200 Subject: [PATCH 14/15] properly split out baseUrl and basePath --- src/Server.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Server.php b/src/Server.php index cbc279a..37b8ff9 100644 --- a/src/Server.php +++ b/src/Server.php @@ -90,10 +90,10 @@ private function getGraph(): Graph final public function setBaseUrl($url) { - $this->baseUrl = $url; - - $serverRequest = new ServerRequest(array(),array(), $this->baseUrl); - $this->basePath = $serverRequest->getUri()->getPath(); + $serverRequest = new ServerRequest(array(),array(), $url); + $uri = $serverRequest->getUri(); + $this->basePath = $uri->getPath(); + $this->baseUrl = $uri->getScheme() . '://' . $uri->getAuthority(); } final public function lockToPath($path) @@ -559,7 +559,7 @@ private function handleCreateRequest(Response $response, string $path, $contents } if ($success) { $this->removeLinkFromMetaFileFor($path); - $response = $response->withHeader("Location", $this->baseUrl . $path); + $response = $response->withHeader("Location", $this->baseUrl . $this->basePath . $path); $response = $response->withStatus(201); $this->sendNotificationUpdate($path, self::NOTIFICATION_TYPE_CREATE); } else { @@ -613,12 +613,11 @@ private function sendNotificationUpdate($path, $type) return; } - $baseUrl = $this->baseUrl; - $this->notifications->send($baseUrl . $path, $type); + $this->notifications->send($this->baseUrl . $this->basePath . $path, $type); 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 + $this->notifications->send($this->baseUrl . $this->basePath . $path, self::NOTIFICATION_TYPE_UPDATE); // checkme: delete on a directory triggers update notifications on parents } } From 979f1bad2d18105dd32e7e7362a7b87e7454560b Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Mon, 5 Oct 2026 11:36:43 +0200 Subject: [PATCH 15/15] use release 0.7 for flysystem-rdf --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index fda3470..9bec59d 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "ext-mbstring": "*", "laminas/laminas-diactoros": "^3", "league/flysystem": "^3", - "pdsinterop/flysystem-rdf": "dev-main", + "pdsinterop/flysystem-rdf": "^0.7", "pietercolpaert/hardf": "^0.3", "psr/http-factory": "^1.0", "psr/http-message": "^1.0"