diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..b5ac520
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,24 @@
+---
+name: Test jobs
+
+on:
+ - pull_request
+ - push
+
+jobs:
+ phpunit:
+ runs-on: ubuntu-20.04
+
+ strategy:
+ matrix:
+ php: ['7.3', '7.4']
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ - uses: "ramsey/composer-install@v1"
+ with:
+ composer-options: --no-scripts
+ - run: bin/phpunit
diff --git a/.github_changelog_generator b/.github_changelog_generator
new file mode 100644
index 0000000..cd1f087
--- /dev/null
+++ b/.github_changelog_generator
@@ -0,0 +1,109 @@
+# ==============================================================================
+# Project Specific
+# ------------------------------------------------------------------------------
+user=pdsinterop
+project=flysystem-rdf
+# ------------------------------------------------------------------------------
+breaking-labels=backwards-incompatible, Backwards incompatible, breaking
+bug-labels=bug
+deprecated-labels=deprecated, Deprecated, Type: Deprecated
+enhancement-labels=improvement, documentation, enhancement
+exclude-labels=question, duplicate,invalid
+removed-labels=removed, Removed, Type: Removed
+security-labels=security, Security, Type: Security
+summary-labels=Release summary, release-summary, Summary, summary
+unreleased-label=Unreleased
+# ==============================================================================
+
+# ==============================================================================
+# Organisation-wide
+# ------------------------------------------------------------------------------
+# Output and content related
+# ------------------------------------------------------------------------------
+date-format=%Y-%m-%d
+output=CHANGELOG.md
+header=# Changelog
+breaking-prefix=### Breaking changes
+bug-prefix=### Fixes
+deprecated-prefix=### Deprecates
+enhancement-prefix=### Changes
+issue-prefix=### Closes
+merge-prefix=### Pull request(s) without label
+removed-prefix=### Removes
+security-prefix=### Security
+# ------------------------------------------------------------------------------
+add-issues-wo-labels=true
+add-pr-wo-labels=true
+author=true
+compare-link=true
+filter-issues-by-milestone=true
+# http-cache=true
+issues=true
+pulls=true
+# unreleased-only=true
+unreleased=true
+usernames-as-github-logins=true
+verbose=false
+# ==============================================================================
+
+;user USER Username of the owner of the target GitHub repo OR the namespace of target Github repo if owned by an organization.
+;project PROJECT Name of project on GitHub.
+;token TOKEN To make more than 50 requests per hour your GitHub token is required. You can generate it at: https://github.com/settings/tokens/new
+;date-format FORMAT Date format. Default is %Y-%m-%d.
+;output NAME Output file. To print to STDOUT instead, use blank as path. Default is CHANGELOG.md
+;base NAME Optional base file to append generated changes to. Default is HISTORY.md
+;summary-label LABEL Set up custom label for the release summary section. Default is "".
+;breaking-label LABEL Set up custom label for the breaking changes section. Default is "**Breaking changes:**".
+;enhancement-label LABEL Set up custom label for enhancements section. Default is "**Implemented enhancements:**".
+;bugs-label LABEL Set up custom label for bug-fixes section. Default is "**Fixed bugs:**".
+;deprecated-label LABEL Set up custom label for the deprecated changes section. Default is "**Deprecated:**".
+;removed-label LABEL Set up custom label for the removed changes section. Default is "**Removed:**".
+;security-label LABEL Set up custom label for the security changes section. Default is "**Security fixes:**".
+;issues-label LABEL Set up custom label for closed-issues section. Default is "**Closed issues:**".
+;header-label LABEL Set up custom header label. Default is "# Changelog".
+;configure-sections STRING Define your own set of sections which overrides all default sections.
+;add-sections HASH, STRING Add new sections but keep the default sections.
+;front-matter JSON Add YAML front matter. Formatted as JSON because it's easier to add on the command line.
+;pr-label LABEL Set up custom label for pull requests section. Default is "**Merged pull requests:**".
+;issues Include closed issues in changelog. Default is true.
+;issues-wo-labels Include closed issues without labels in changelog. Default is true.
+;pr-wo-labels Include pull requests without labels in changelog. Default is true.
+;pull-requests Include pull-requests in changelog. Default is true.
+;filter-by-milestone Use milestone to detect when issue was resolved. Default is true.
+;issues-of-open-milestones Include issues of open milestones. Default is true.
+;author Add author of pull request at the end. Default is true.
+;usernames-as-github-logins Use GitHub tags instead of Markdown links for the author of an issue or pull-request.
+;unreleased-only Generate log from unreleased closed issues only.
+;unreleased Add to log unreleased closed issues. Default is true.
+;unreleased-label LABEL Set up custom label for unreleased closed issues section. Default is "**Unreleased:**".
+;compare-link Include compare link (Full Changelog) between older version and newer version. Default is true.
+;include-labels x,y,z Of the labeled issues, only include the ones with the specified labels.
+;exclude-labels x,y,z Issues with the specified labels will be excluded from changelog. Default is 'duplicate,question,invalid,wontfix'.
+;summary-labels x,y,z Issues with these labels will be added to a new section, called "Release Summary". The section display only body of issues. Default is 'release-summary,summary'.
+;breaking-labels x,y,z Issues with these labels will be added to a new section, called "Breaking changes". Default is 'backwards-incompatible,breaking'.
+;enhancement-labels x,y,z Issues with the specified labels will be added to "Implemented enhancements" section. Default is 'enhancement,Enhancement'.
+;bug-labels x,y,z Issues with the specified labels will be added to "Fixed bugs" section. Default is 'bug,Bug'.
+;deprecated-labels x,y,z Issues with the specified labels will be added to a section called "Deprecated". Default is 'deprecated,Deprecated'.
+;removed-labels x,y,z Issues with the specified labels will be added to a section called "Removed". Default is 'removed,Removed'.
+;security-labels x,y,z Issues with the specified labels will be added to a section called "Security fixes". Default is 'security,Security'.
+;issue-line-labels x,y,z The specified labels will be shown in brackets next to each matching issue. Use "ALL" to show all labels. Default is [].
+;include-tags-regex REGEX Apply a regular expression on tag names so that they can be included, for example: --include-tags-regex ".*+d{1,}".
+;exclude-tags x,y,z Changelog will exclude specified tags
+;exclude-tags-regex REGEX Apply a regular expression on tag names so that they can be excluded, for example: --exclude-tags-regex ".*+d{1,}".
+;since-tag x Changelog will start after specified tag.
+;due-tag x Changelog will end before specified tag.
+;since-commit x Fetch only commits after this time. eg. "2017-01-01 10:00:00"
+;max-issues NUMBER Maximum number of issues to fetch from GitHub. Default is unlimited.
+;release-url URL The URL to point to for release links, in printf format (with the tag as variable).
+;github-site URL The Enterprise GitHub site where your project is hosted.
+;github-api URL The enterprise endpoint to use for your GitHub API.
+;simple-list Create a simple list from issues and pull requests. Default is false.
+;future-release VERSION Put the unreleased changes in the specified release number.
+;release-branch BRANCH Limit pull requests to the release branch, such as master or release.
+;http-cache Use HTTP Cache to cache GitHub API requests (useful for large repos). Default is true.
+;cache-file CACHE-FILE Filename to use for cache. Default is github-changelog-http-cache in a temporary directory.
+;cache-log CACHE-LOG Filename to use for cache log. Default is github-changelog-logger.log in a temporary directory.
+;config-file CONFIG-FILE Path to configuration file. Default is .github_changelog_generator.
+;ssl-ca-file PATH Path to cacert.pem file. Default is a bundled lib/github_changelog_generator/ssl_certs/cacert.pem. Respects SSL_CA_PATH.
+;require x,y,z Path to Ruby file(s) to require before generating changelog.
+;verbose Run verbosely. Default is true.
diff --git a/.gitignore b/.gitignore
index 3af7618..265830f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
# Directories to ignore
+/.phpunit.cache
+/build
/vendor
# Files to ignore
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..6a1cd43
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,33 @@
+# Changelog
+
+## [v0.3.0](https://github.com/pdsinterop/flysystem-rdf/tree/v0.3.0) (2020-11-09)
+
+[Full Changelog](https://github.com/pdsinterop/flysystem-rdf/compare/v0.2.1...v0.3.0)
+
+## [v0.2.1](https://github.com/pdsinterop/flysystem-rdf/tree/v0.2.1) (2020-11-02)
+
+[Full Changelog](https://github.com/pdsinterop/flysystem-rdf/compare/v0.2.0...v0.2.1)
+
+### Closes
+
+- Cherry-pick from php5-librdf? [\#1](https://github.com/pdsinterop/flysystem-rdf/issues/1)
+
+## [v0.2.0](https://github.com/pdsinterop/flysystem-rdf/tree/v0.2.0) (2020-09-24)
+
+[Full Changelog](https://github.com/pdsinterop/flysystem-rdf/compare/v0.1.0...v0.2.0)
+
+### Closes
+
+- Errors in foaf.rdf [\#2](https://github.com/pdsinterop/flysystem-rdf/issues/2)
+
+### Pull request(s) without label
+
+- Take base URL for parsing [\#3](https://github.com/pdsinterop/flysystem-rdf/pull/3) (@michielbdejong)
+
+## [v0.1.0](https://github.com/pdsinterop/flysystem-rdf/tree/v0.1.0) (2020-07-19)
+
+[Full Changelog](https://github.com/pdsinterop/flysystem-rdf/compare/v0.0.0...v0.1.0)
+
+## [v0.0.0](https://github.com/pdsinterop/flysystem-rdf/tree/v0.0.0) (2020-07-19)
+
+[Full Changelog](https://github.com/pdsinterop/flysystem-rdf/compare/3afc40850b2e61d3a7fc0005f7c3ae48aebbcceb...v0.0.0)
diff --git a/README.md b/README.md
index 4dc5135..65323d4 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,13 @@
# Flysystem RDF Converter Plugin
-
-[![PDS Interop][pdsinterop-shield]][pdsinterop-site]
[![Project stage: Development][project-stage-badge: Development]][project-stage-page]
[![License][license-shield]][license-link]
[![Latest Version][version-shield]][version-link]
-[![standard-readme compliant][standard-readme-shield]][standard-readme-link]
![Maintained][maintained-shield]
+[![PDS Interop][pdsinterop-shield]][pdsinterop-site]
+[![standard-readme compliant][standard-readme-shield]][standard-readme-link]
+[![keep-a-changelog compliant][keep-a-changelog-shield]][keep-a-changelog-link]
+
_Flysystem plugin to transform RDF data between various serialization formats._
When using RDF, you will notice there are several different popular
@@ -52,11 +53,11 @@ separate package.
The advised install method is through composer:
-```
+```sh
composer require pdsinterop/flysystem-rdf
```
-PHP version 7.1 and higher is supported. The [`mbstring`](https://www.php.net/manual/en/book.mbstring.php)
+PHP version 7.3 and higher is supported. The [`mbstring`](https://www.php.net/manual/en/book.mbstring.php)
extension needs to be enabled in order for this package to work.
## Usage
@@ -118,10 +119,16 @@ $convertedMimeType = $filesystem
// This also works for `has`
$hasConvertedContents = $filesystem
->asMime('text/turtle')
- ->has('/foaf.rdf');
+ ->has('/foaf.ttl');
+
+// Without using the plugin, this will be false
+$hasContents = $filesystem->has('/foaf.ttl');
```
+The adapter adds any found `.meta` files that reference a file to that file's
+metadata, which can be retrieved with `$filesystem->getMetadata($path)`.
+
### Plugin
To use the plugin, instantiate it and add it to a Flysystem filesystem.
@@ -141,8 +148,19 @@ $filesystem->addPlugin($plugin);
// Read the contents of a RDF file in another format from what was stored in
$content = $filesystem->readRdf('/foaf.rdf', \Pdsinterop\Rdf\Enum\Format::TURTLE);
+
```
+## Develop
+
+- Do not forget to install the required dependencies using `composer`.
+
+- Most of the logic here involves EasyRdf and/or FlySystem. You'll want to familiarise yourself with their workings.
+
+- Test are available in the `tests/` directory. They are run by GitHub actions for any pull request. To run them,call `./bin/phpunit`
+
+- The changelog can be automatically generated using [`github_changelog_generator`](https://github.com/github-changelog-generator/github-changelog-generator) with the [provided configuration file](.github_changelog_generator)
+
## Contribute
Questions or feedback can be given by [opening an issue on GitHub](https://github.com/pdsinterop/flysystem-rdf/issues).
@@ -163,14 +181,16 @@ For a list of changes see the [CHANGELOG](CHANGELOG.md) or the GitHub releases p
All code created by PDS Interop is licensed under the [MIT License][license-link].
[contributors-page]: https://github.com/pdsinterop/flysystem-rdf/contributors
+[keep-a-changelog-link]: https://keepachangelog.com/
+[keep-a-changelog-shield]: https://img.shields.io/badge/Keep%20a%20Changelog-f15d30.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIHZpZXdCb3g9IjAgMCAxODcgMTg1Ij48cGF0aCBkPSJNNjIgN2MtMTUgMy0yOCAxMC0zNyAyMmExMjIgMTIyIDAgMDAtMTggOTEgNzQgNzQgMCAwMDE2IDM4YzYgOSAxNCAxNSAyNCAxOGE4OSA4OSAwIDAwMjQgNCA0NSA0NSAwIDAwNiAwbDMtMSAxMy0xYTE1OCAxNTggMCAwMDU1LTE3IDYzIDYzIDAgMDAzNS01MiAzNCAzNCAwIDAwLTEtNWMtMy0xOC05LTMzLTE5LTQ3LTEyLTE3LTI0LTI4LTM4LTM3QTg1IDg1IDAgMDA2MiA3em0zMCA4YzIwIDQgMzggMTQgNTMgMzEgMTcgMTggMjYgMzcgMjkgNTh2MTJjLTMgMTctMTMgMzAtMjggMzhhMTU1IDE1NSAwIDAxLTUzIDE2bC0xMyAyaC0xYTUxIDUxIDAgMDEtMTItMWwtMTctMmMtMTMtNC0yMy0xMi0yOS0yNy01LTEyLTgtMjQtOC0zOWExMzMgMTMzIDAgMDE4LTUwYzUtMTMgMTEtMjYgMjYtMzMgMTQtNyAyOS05IDQ1LTV6TTQwIDQ1YTk0IDk0IDAgMDAtMTcgNTQgNzUgNzUgMCAwMDYgMzJjOCAxOSAyMiAzMSA0MiAzMiAyMSAyIDQxLTIgNjAtMTRhNjAgNjAgMCAwMDIxLTE5IDUzIDUzIDAgMDA5LTI5YzAtMTYtOC0zMy0yMy01MWE0NyA0NyAwIDAwLTUtNWMtMjMtMjAtNDUtMjYtNjctMTgtMTIgNC0yMCA5LTI2IDE4em0xMDggNzZhNTAgNTAgMCAwMS0yMSAyMmMtMTcgOS0zMiAxMy00OCAxMy0xMSAwLTIxLTMtMzAtOS01LTMtOS05LTEzLTE2YTgxIDgxIDAgMDEtNi0zMiA5NCA5NCAwIDAxOC0zNSA5MCA5MCAwIDAxNi0xMmwxLTJjNS05IDEzLTEzIDIzLTE2IDE2LTUgMzItMyA1MCA5IDEzIDggMjMgMjAgMzAgMzYgNyAxNSA3IDI5IDAgNDJ6bS00My03M2MtMTctOC0zMy02LTQ2IDUtMTAgOC0xNiAyMC0xOSAzN2E1NCA1NCAwIDAwNSAzNGM3IDE1IDIwIDIzIDM3IDIyIDIyLTEgMzgtOSA0OC0yNGE0MSA0MSAwIDAwOC0yNCA0MyA0MyAwIDAwLTEtMTJjLTYtMTgtMTYtMzEtMzItMzh6bS0yMyA5MWgtMWMtNyAwLTE0LTItMjEtN2EyNyAyNyAwIDAxLTEwLTEzIDU3IDU3IDAgMDEtNC0yMCA2MyA2MyAwIDAxNi0yNWM1LTEyIDEyLTE5IDI0LTIxIDktMyAxOC0yIDI3IDIgMTQgNiAyMyAxOCAyNyAzM3MtMiAzMS0xNiA0MGMtMTEgOC0yMSAxMS0zMiAxMXptMS0zNHYxNGgtOFY2OGg4djI4bDEwLTEwaDExbC0xNCAxNSAxNyAxOEg5NnoiLz48L3N2Zz4K
[license-link]: ./LICENSE
[license-shield]: https://img.shields.io/github/license/pdsinterop/flysystem-rdf.svg
-[maintained-shield]: https://img.shields.io/maintenance/yes/2020
-[pdsinterop-shield]: https://img.shields.io/badge/-PDS%20Interop-gray.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii01IC01IDExMCAxMTAiIGZpbGw9IiNGRkYiIHN0cm9rZS13aWR0aD0iMCI+CiAgICA8cGF0aCBkPSJNLTEgNTJoMTdhMzcuNSAzNC41IDAgMDAyNS41IDMxLjE1di0xMy43NWEyMC43NSAyMSAwIDAxOC41LTQwLjI1IDIwLjc1IDIxIDAgMDE4LjUgNDAuMjV2MTMuNzVhMzcgMzQuNSAwIDAwMjUuNS0zMS4xNWgxN2EyMiAyMS4xNSAwIDAxLTEwMiAweiIvPgogICAgPHBhdGggZD0iTSAxMDEgNDhhMi43NyAyLjY3IDAgMDAtMTAyIDBoIDE3YTIuOTcgMi44IDAgMDE2OCAweiIvPgo8L3N2Zz4K
+[maintained-shield]: https://img.shields.io/maintenance/yes/2022.svg
+[pdsinterop-shield]: https://img.shields.io/badge/-PDS%20Interop-7C4DFF.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii01IC01IDExMCAxMTAiIGZpbGw9IiNGRkYiIHN0cm9rZS13aWR0aD0iMCI+CiAgICA8cGF0aCBkPSJNLTEgNTJoMTdhMzcuNSAzNC41IDAgMDAyNS41IDMxLjE1di0xMy43NWEyMC43NSAyMSAwIDAxOC41LTQwLjI1IDIwLjc1IDIxIDAgMDE4LjUgNDAuMjV2MTMuNzVhMzcgMzQuNSAwIDAwMjUuNS0zMS4xNWgxN2EyMiAyMS4xNSAwIDAxLTEwMiAweiIvPgogICAgPHBhdGggZD0iTSAxMDEgNDhhMi43NyAyLjY3IDAgMDAtMTAyIDBoIDE3YTIuOTcgMi44IDAgMDE2OCAweiIvPgo8L3N2Zz4K
[pdsinterop-site]: https://pdsinterop.org/
[project-stage-badge: Development]: https://img.shields.io/badge/Project%20Stage-Development-yellowgreen.svg
[project-stage-page]: https://blog.pother.ca/project-stages/
[standard-readme-link]: https://github.com/RichardLitt/standard-readme
-[standard-readme-shield]: https://img.shields.io/badge/readme%20style-standard-brightgreen.svg
+[standard-readme-shield]: https://img.shields.io/badge/-Standard%20Readme-brightgreen.svg
[version-link]: https://packagist.org/packages/pdsinterop/flysystem-rdf
[version-shield]: https://img.shields.io/github/v/release/pdsinterop/flysystem-rdf?sort=semver
diff --git a/composer.json b/composer.json
index efd3ab1..bcf189d 100644
--- a/composer.json
+++ b/composer.json
@@ -5,25 +5,21 @@
}
},
"config": {
- "sort-packages": true,
"bin-dir": "./bin",
- "platform": {
- "php": "7.1.33",
- "ext-mbstring": "0.0.0"
- }
+ "sort-packages": true
},
"description": "Flysystem plugin to transform RDF data between various serialization formats.",
"license": "MIT",
"name": "pdsinterop/flysystem-rdf",
"require": {
- "php": "^7.1",
+ "php": "^7.3",
"ext-mbstring": "*",
"easyrdf/easyrdf": "^0.9.1",
"league/flysystem": "^1.0",
"ml/json-ld": "^1.2"
},
- "type": "library",
"require-dev": {
- "phpunit/phpunit": "^7|^8|^9"
- }
+ "phpunit/phpunit": "^8|^9"
+ },
+ "type": "library"
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 0000000..6c43fed
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,49 @@
+
+
+
+
+ tests/
+
+
+
+
+
+
+ src/
+
+
+
+
+
+
+
+
+
+
+
+
+ src/
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Enum/Format.php b/src/Enum/Format.php
index ebd3431..e4fb2b3 100644
--- a/src/Enum/Format.php
+++ b/src/Enum/Format.php
@@ -11,7 +11,7 @@ class Format
public const TURTLE = 'turtle';
public const UNKNOWN = 'guess';
- final public static function has($value) : bool
+ final public static function has($value): bool
{
return in_array($value, self::keys(), true);
}
@@ -21,7 +21,7 @@ final public static function has($value) : bool
*
* @return string[]
*/
- final public static function keys() : array
+ final public static function keys(): array
{
$keys = (new \ReflectionClass(__CLASS__))->getConstants();
diff --git a/src/Flysystem/Adapter/Rdf.php b/src/Flysystem/Adapter/Rdf.php
index cbe3ade..e72bc01 100644
--- a/src/Flysystem/Adapter/Rdf.php
+++ b/src/Flysystem/Adapter/Rdf.php
@@ -2,52 +2,73 @@
namespace Pdsinterop\Rdf\Flysystem\Adapter;
-use EasyRdf_Exception;
-use EasyRdf_Graph;
+use EasyRdf_Exception as RdfException;
+use EasyRdf_Graph as Graph;
use League\Flysystem\AdapterInterface;
use League\Flysystem\Config;
+use ML\JsonLD\JsonLD;
use Pdsinterop\Rdf\Enum\Format;
use Pdsinterop\Rdf\Flysystem\Exception;
-use Pdsinterop\Rdf\Formats;
-use ML\JsonLD;
+use Pdsinterop\Rdf\FormatsInterface;
+
/**
* Filesystem adapter to convert RDF files to and from a default format
*/
-class Rdf implements AdapterInterface
+class Rdf implements RdfAdapterInterface
{
- private const ERROR_COULD_NOT_CONVERT = 'Could not convert file "%s" to format "%s": %s';
+ ////////////////////////////// CLASS PROPERTIES \\\\\\\\\\\\\\\\\\\\\\\\\\\\
+
+ public const ERROR_UNSUPPORTED_FORMAT = 'Given format "%s" is not supported';
+ public const ERROR_COULD_NOT_CONVERT = 'Could not convert file "%s" to format "%s": %s';
/** @var AdapterInterface */
private $adapter;
/** @var string */
private $format = '';
- /** @var Formats */
+ /** @var FormatsInterface */
private $formats;
+ /** @var Graph */
+ private $graph;
/** @var string */
private $url;
- final public function setFormat(string $format) : void
+ //////////////////////////// GETTERS AND SETTERS \\\\\\\\\\\\\\\\\\\\\\\\\\\
+
+ /**
+ * Retrieve a new / clean RDF Graph object
+ *
+ * @return Graph
+ */
+ private function getGraph(): Graph
+ {
+ return clone $this->graph;
+ }
+
+ final public function setFormat(string $format): void
{
- if (($format != "") && (Format::has($format) === false)) {
- throw new Exception('Given format "' . $format . '" is not supported');
+ if (($format !== "") && (Format::has($format) === false)) {
+ throw Exception::create(self::ERROR_UNSUPPORTED_FORMAT, [$format]);
}
$this->format = $format;
}
- final public function getFormat() {
+
+ final public function getFormat(): string
+ {
return $this->format;
}
- // FIXME: remove easyrdf graph from the constructor
- final public function __construct(AdapterInterface $adapter, EasyRdf_Graph $graph, Formats $formats, string $url)
+ //////////////////////////////// PUBLIC API \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+
+ // @FIXME: Add JsonLD as dependency and use static calls to object instance instead of using static calls to class
+ final public function __construct(AdapterInterface $adapter, Graph $graph, FormatsInterface $formats, string $url)
{
$this->adapter = $adapter;
$this->formats = $formats;
+ $this->graph = $graph;
$this->url = $url;
}
- // =========================================================================
-
final public function write($path, $contents, Config $config)
{
return call_user_func_array([$this->adapter, __FUNCTION__], func_get_args());
@@ -100,20 +121,28 @@ final public function setVisibility($path, $visibility)
final public function has($path)
{
- return call_user_func_array([$this->adapter, __FUNCTION__], func_get_args());
+ return $this->getMetadata($path);
}
final public function read($path)
{
- $format = $this->resetFormat();
- return $format !== ''
- ? [
- 'type' => 'file',
+ $format = $this->format;
+
+ if ($format !== '') {
+ $contents = $this->convertedContents($path, $format);
+
+ $metaData = [
+ 'contents' => $contents,
+ 'mimetype' => $this->formats->getMimeForFormat($format),
'path' => $path,
- 'contents' => $this->convertedContents($path, $format),
- ]
- : call_user_func_array([$this->adapter, __FUNCTION__], func_get_args())
- ;
+ 'size' => strlen($contents), // filesize in bytes,
+ 'type' => 'file',
+ ];
+ } else {
+ $metaData = $this->adapter->read($path);
+ }
+
+ return $metaData;
}
final public function readStream($path)
@@ -129,30 +158,48 @@ final public function listContents($directory = '', $recursive = false)
final public function getMetadata($path)
{
- return call_user_func_array([$this->adapter, __FUNCTION__], func_get_args());
+ $metadata = $this->adapter->getMetadata($path) ?? [];
+
+ $format = $this->format;
+
+ if ($format !== '') {
+ // @CHECKME: Does it make more sense to call `guessMimeType` or should `getMimeType` be called?
+ $metadata = array_merge($metadata, ['mimetype' => $this->guessMimeType($path)], $this->read($path));
+ }
+
+ return array_merge($metadata, $this->findAuxiliaryResources($path));
}
final public function getSize($path)
{
- // @TODO: For convert request, get contents, convert and count size
- return call_user_func_array([$this->adapter, __FUNCTION__], func_get_args());
+ $format = $this->format;
+
+ if ($format === '') {
+ $metadata = call_user_func_array([$this->adapter, __FUNCTION__], func_get_args());
+ } else {
+ $metadata = $this->getMetadata($path);
+ }
+
+ return $metadata;
}
final public function getMimeType($path)
{
$format = $this->resetFormat();
- $extension = $this->getExtension($path);
- $possibleFormat = $this->formats->getFormatForExtension($extension);
-
- $mimeType = $this->adapter->getMimetype($path);
if ($format !== '') {
- $mimeType['mimetype'] = $this->formats->getMimeForFormat($format);
- } elseif ($possibleFormat !== '' && $mimeType['mimetype'] === 'text/plain') {
- $mimeType['mimetype'] = $possibleFormat;
+ $metadata = ['mimetype' => $this->formats->getMimeForFormat($format)];
+ } else {
+ $metadata = $this->adapter->getMimetype($path);
+
+ $possibleMimeType = $this->guessMimeType($path, $metadata);
+
+ if ($possibleMimeType !== '') {
+ $metadata['mimetype'] = $possibleMimeType;
+ }
}
- return $mimeType;
+ return $metadata;
}
final public function getTimestamp($path)
@@ -165,7 +212,7 @@ final public function getVisibility($path)
return call_user_func_array([$this->adapter, __FUNCTION__], func_get_args());
}
- // =========================================================================
+ ////////////////////////////// UTILITY METHODS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\
private function convertedContents($path, $format)
{
@@ -173,14 +220,14 @@ private function convertedContents($path, $format)
$originalContents = $this->getOriginalContents($path);
$originalFormat = $this->formats->getFormatForExtension($originalExtension);
- if ($originalFormat == $format) {
+ if ($originalFormat === $format) {
return $originalContents;
}
try {
switch($originalFormat) {
case "jsonld":
- $graph = new \EasyRdf_Graph();
+ $graph = $this->getGraph();
// FIXME: parsing json gives warnings, so we're suppressing those for now.
$graph->parse($originalContents, "jsonld", $this->url);
switch ($format) {
@@ -193,15 +240,16 @@ private function convertedContents($path, $format)
}
break;
default:
- $graph = new \EasyRdf_Graph();
+ $graph = $this->getGraph();
+ // FIXME: guessing here helps pass another test, but we really should provide a correct format.
// FIXME: parsing json gives warnings, so we're suppressing those for now.
- @$graph->parse($originalContents, "guess", $this->url); // FIXME: guessing here helps pass another test, but we really should provide a correct format.
+ @$graph->parse($originalContents, "guess", $this->url);
switch ($format) {
case "jsonld":
// We need to get the expanded version of the json-ld, but easyRdf doesn't provide an option for that, so we call this directly.
$contents = $graph->serialise($format);
- $jsonDoc = \ML\JsonLD\JsonLD::expand($contents);
- $contents = \ML\JsonLD\JsonLD::toString($jsonDoc);
+ $jsonDoc = JsonLD::expand($contents);
+ $contents = JsonLD::toString($jsonDoc);
break;
default:
$contents = $graph->serialise($format);
@@ -209,8 +257,8 @@ private function convertedContents($path, $format)
}
break;
}
- } catch (EasyRdf_Exception $exception) {
- throw new Exception(self::ERROR_COULD_NOT_CONVERT, [
+ } catch (RdfException $exception) {
+ throw Exception::create(self::ERROR_COULD_NOT_CONVERT, [
'file' => $path,
'format' => $format,
'error' => $exception->getMessage(),
@@ -220,7 +268,41 @@ private function convertedContents($path, $format)
return $contents;
}
- private function getExtension(string $path) : string
+ private function findAuxiliaryResources(string $path): array
+ {
+ $metaFiles = [
+ 'describedby' => $this->findInPath($path, '.meta'),
+ 'acl' => $this->findInPath($path, '.acl'),
+ ];
+
+ // Remove any empty values
+ return array_filter($metaFiles);
+ }
+
+ private function findInPath(string $originalPath, $extension)
+ {
+ $subject = false;
+
+ $subjectPath = $originalPath . $extension;
+
+ if ($this->adapter->has($subjectPath)) {
+ $subject = $subjectPath;
+ } else {
+ do {
+ $subjectPath = dirname($subjectPath);
+
+ $path = '/' . ltrim($subjectPath . '/' . $extension, '/');
+
+ if ($this->adapter->has($path)) {
+ $subject = $path;
+ }
+ } while ($subject === false && $subjectPath !== '/');
+ }
+
+ return $subject;
+ }
+
+ private function getExtension(string $path): string
{
return strtolower(pathinfo($path, PATHINFO_EXTENSION));
}
@@ -232,6 +314,33 @@ private function getOriginalContents($path)
return $converted['contents'];
}
+ private function guessMimeType(string $path, array $metadata = []): string
+ {
+ $mimetype = '';
+
+ if ($metadata === []) {
+ $originalMetadata = $this->adapter->getMimetype($path);
+ if (isset($originalMetadata['mimetype'])) {
+ $metadata = $originalMetadata;
+ }
+ }
+
+ $extension = $this->getExtension($path);
+
+ $possibleMime = $this->formats->getMimeForExtension($extension);
+
+ if ($possibleMime !== ''
+ && (
+ ! isset($metadata['mimetype'])
+ || $metadata['mimetype'] === 'text/plain'
+ )
+ ) {
+ $mimetype = $possibleMime;
+ }
+
+ return $mimetype;
+ }
+
private function resetFormat() : string
{
$format = $this->format;
diff --git a/src/Flysystem/Adapter/RdfAdapterInterface.php b/src/Flysystem/Adapter/RdfAdapterInterface.php
new file mode 100644
index 0000000..b6baaf2
--- /dev/null
+++ b/src/Flysystem/Adapter/RdfAdapterInterface.php
@@ -0,0 +1,15 @@
+formats = $formats;
}
- public function handle(string $mime) : FilesystemInterface
+ public function handle(string $mime): FilesystemInterface
{
$filesystem = $this->filesystem;
- $adapter = $filesystem->getAdapter();
-
+ if (! is_callable([$filesystem, 'getAdapter'])) {
+ throw Exception::create(self::ERROR_MISSING_ADAPTER, [__CLASS__]);
+ }
- if ($adapter instanceof Rdf) {
+ if ($filesystem->getAdapter() instanceof RdfAdapterInterface) {
$format = $this->formats->getFormatForMime($mime);
- $adapter->setFormat($format);
+ $filesystem->getAdapter()->setFormat($format);
}
return $filesystem;
diff --git a/src/Flysystem/Plugin/ReadRdf.php b/src/Flysystem/Plugin/ReadRdf.php
index 28dbaa7..438e0aa 100644
--- a/src/Flysystem/Plugin/ReadRdf.php
+++ b/src/Flysystem/Plugin/ReadRdf.php
@@ -48,12 +48,12 @@ final public function __construct(EasyRdf_Graph $rdfConverter)
* @param string $format RDF format to convert file to
* @param string $url base url for parsing
*
- * @return array|false metadata
+ * @return string|false converted contents
*
* @throws FileNotFoundException
* @throws Exception
*/
- public function handle(string $path, string $format, string $url) : string
+ public function handle(string $path, string $format, string $url)
{
$converter = $this->converter;
@@ -65,7 +65,7 @@ public function handle(string $path, string $format, string $url) : string
try {
$converter->parse($contents, Format::UNKNOWN, $url);
} catch (EasyRdf_Exception $exception) {
- $this->throwException(self::ERROR_COULD_NOT_CONVERT, [
+ throw Exception::create(self::ERROR_COULD_NOT_CONVERT, [
'file' => $path,
'format' => $format,
'error' => $exception->getMessage(),
@@ -83,16 +83,4 @@ public function handle(string $path, string $format, string $url) : string
return $contents;
}
-
- /**
- * @param string $error
- * @param array $context
- * @param \Exception|null $previous
- *
- * @throws Exception
- */
- private function throwException(string $error, array $context, \Exception $previous = null) : void
- {
- throw new Exception(vsprintf($error, $context), 0, $previous);
- }
}
diff --git a/src/Formats.php b/src/Formats.php
index 787ca60..2ab4d73 100644
--- a/src/Formats.php
+++ b/src/Formats.php
@@ -4,7 +4,7 @@
use Pdsinterop\Rdf\Enum\Format;
-class Formats
+class Formats implements FormatsInterface
{
////////////////////////////// CLASS PROPERTIES \\\\\\\\\\\\\\\\\\\\\\\\\\\\
@@ -55,12 +55,12 @@ class Formats
//////////////////////////// GETTERS AND SETTERS \\\\\\\\\\\\\\\\\\\\\\\\\\\
- final public function getAllExtensions() : array
+ final public function getAllExtensions(): array
{
return $this->getAll('extensions');
}
- final public function getAllMimeTypes() : array
+ final public function getAllMimeTypes(): array
{
$all = $this->getAll('mimeTypes');
@@ -69,19 +69,19 @@ final public function getAllMimeTypes() : array
}, $all);
}
- private function getData() : array
+ private function getData(): array
{
return $this->data;
}
//////////////////////////////// PUBLIC API \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
- final public function getExtensionsForFormat(string $format) : array
+ final public function getExtensionsForFormat(string $format): array
{
return $this->getAllExtensions()[$format] ?? [];
}
- final public function getFormatForExtension(string $extension) : string
+ final public function getFormatForExtension(string $extension): string
{
$extension = ltrim($extension, '.');
@@ -96,7 +96,7 @@ final public function getFormatForExtension(string $extension) : string
return reset($formatNames);
}
- final public function getFormatForMime(string $mime) : string
+ final public function getFormatForMime(string $mime): string
{
$all = $this->getAllMimeTypes();
@@ -109,27 +109,28 @@ final public function getFormatForMime(string $mime) : string
return reset($formatNames);
}
- final public function getMimeForFormat(string $format)
+ final public function getMimeForExtension(string $extension): string
{
+ $format = $this->getFormatForExtension($extension);
+ return $this->getMimeForFormat($format);
+ }
+
+ final public function getMimeForFormat(string $format): string
+ {
$mimes = $this->getMimesForFormat($format);
return reset($mimes);
}
- final public function getMimesForFormat(string $format) : array
+ final public function getMimesForFormat(string $format): array
{
return $this->getAllMimeTypes()[$format] ?? [];
}
////////////////////////////// UTILITY METHODS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\
- /**
- * @param string $subject
- *
- * @return array
- */
- private function getAll(string $subject) : array
+ private function getAll(string $subject): array
{
$data = $this->getData();
diff --git a/src/FormatsInterface.php b/src/FormatsInterface.php
new file mode 100644
index 0000000..fd2c5b6
--- /dev/null
+++ b/src/FormatsInterface.php
@@ -0,0 +1,22 @@
+
$format): ?>
- id="tab-= $index ?>" name="tabs" type="radio" class="tab-selector is-hidden" />
+