|
6 | 6 | use EasyRdf_Graph as Graph; |
7 | 7 | use Laminas\Diactoros\ServerRequest; |
8 | 8 | use League\Flysystem\FileExistsException; |
| 9 | +use League\Flysystem\FileNotFoundException; |
9 | 10 | use League\Flysystem\FilesystemInterface as Filesystem; |
10 | 11 | use Psr\Http\Message\ResponseInterface as Response; |
11 | 12 | use Psr\Http\Message\ServerRequestInterface as Request; |
@@ -550,8 +551,10 @@ private function handleReadRequest(Response $response, string $path, $contents, |
550 | 551 | $response = $response->withStatus(200); |
551 | 552 | } else { |
552 | 553 | if ($filesystem->asMime($mime)->has($path)) { |
553 | | - $mimetype = $filesystem->asMime($mime)->getMimetype($path); |
554 | 554 | $contents = $filesystem->asMime($mime)->read($path); |
| 555 | + |
| 556 | + $response = $this->addLinkRelationHeaders($response, $path, $mime); |
| 557 | + |
555 | 558 | if (preg_match('/.ttl$/', $path)) { |
556 | 559 | $mimetype = "text/turtle"; // FIXME: teach flysystem that .ttl means text/turtle |
557 | 560 | } elseif (preg_match('/.acl$/', $path)) { |
@@ -655,4 +658,80 @@ private function listDirectoryAsTurtle($path) |
655 | 658 |
|
656 | 659 | return $container; |
657 | 660 | } |
| 661 | + |
| 662 | + // ========================================================================= |
| 663 | + // @TODO: All Auxiliary Resources logic should probably be moved to a separate class. |
| 664 | + |
| 665 | + /** |
| 666 | + * Currently, in the spec channel, it is under consideration to use |
| 667 | + * <http://www.w3.org/ns/auth/acl#accessControl> or <http://www.w3.org/ns/solid/terms#acl> |
| 668 | + * instead of (or besides) "acl" and <https://www.w3.org/ns/iana/link-relations/relation#describedby> |
| 669 | + * instead of (or besides) "describedby". |
| 670 | + * |
| 671 | + * @see https://github.com/solid/specification/issues/172 |
| 672 | + */ |
| 673 | + private function addLinkRelationHeaders(Response $response, string $path, $mime=null): Response |
| 674 | + { |
| 675 | + // @FIXME: If a `.meta` file is requested, it must have header `Link: </path/to/resource>; rel="describes"` |
| 676 | + |
| 677 | + if ($this->hasAcl($path, $mime)) { |
| 678 | + $value = sprintf('<%s>; rel="acl"', $this->getDescribedByPath($path, $mime)); |
| 679 | + $response = $response->withAddedHeader('Link', $value); |
| 680 | + } |
| 681 | + |
| 682 | + if ($this->hasDescribedBy($path, $mime)) { |
| 683 | + $value = sprintf('<%s>; rel="describedby"', $this->getDescribedByPath($path, $mime)); |
| 684 | + $response = $response->withAddedHeader('Link', $value); |
| 685 | + } |
| 686 | + |
| 687 | + return $response; |
| 688 | + } |
| 689 | + |
| 690 | + private function getAclPath(string $path, $mime = null): string |
| 691 | + { |
| 692 | + $metadataCache = $this->getMetadata($path, $mime); |
| 693 | + |
| 694 | + return $metadataCache[$path]['acl'] ?? ''; |
| 695 | + } |
| 696 | + |
| 697 | + private function getDescribedByPath(string $path, $mime = null): string |
| 698 | + { |
| 699 | + $metadataCache = $this->getMetadata($path, $mime); |
| 700 | + |
| 701 | + return $metadataCache[$path]['describedby'] ?? ''; |
| 702 | + } |
| 703 | + |
| 704 | + private function getMetadata(string $path, $mime) : array |
| 705 | + { |
| 706 | + // @NOTE: Because the lookup can be expensive, we cache the result |
| 707 | + static $metadataCache = []; |
| 708 | + |
| 709 | + if (isset($metadataCache[$path]) === false) { |
| 710 | + $filesystem = $this->filesystem; |
| 711 | + |
| 712 | + try { |
| 713 | + if ($mime) { |
| 714 | + $metadata = $filesystem->asMime($mime)->getMetadata($path); |
| 715 | + } else { |
| 716 | + $metadata = $filesystem->getMetadata($path); |
| 717 | + } |
| 718 | + } catch (FileNotFoundException $e) { |
| 719 | + $metadata = []; |
| 720 | + } |
| 721 | + |
| 722 | + $metadataCache[$path . $mime] = $metadata; |
| 723 | + } |
| 724 | + |
| 725 | + return $metadataCache; |
| 726 | + } |
| 727 | + |
| 728 | + private function hasAcl(string $path, $mime = null): bool |
| 729 | + { |
| 730 | + return $this->getAclPath($path, $mime) !== ''; |
| 731 | + } |
| 732 | + |
| 733 | + private function hasDescribedBy(string $path, $mime = null): bool |
| 734 | + { |
| 735 | + return $this->getDescribedByPath($path, $mime) !== ''; |
| 736 | + } |
658 | 737 | } |
0 commit comments