The support to this project is now discontinued. Update your links.
Find the old version as tagged branch.
This package is an EasyRDF extension to support authentication,reasoning, LDP server endpoints and more.
It extends the default httpclient of EasyRDF to support basic authentication and and provides two content negotiation policies to manage consistently representations for RDF graphs and for Sparql Results data models.
Beside this it contains an implementation of a simple end point to publish linked data supporting many serialization and html according Linked Data Platform Editor Draft specification
This package is available on Packagist.
You can install adding following dependances to composer.json file in your project root:
{
"require": {
"botk/rdf": "*"
}
}
This class is a replacement forEasyRDF http client class. It adds the setAuth(string $user, string $password)
method supporting basic http authentication type. HttpClient in turn it is a
lightware alternative to Zend_Http_client or Guzzle libraries.
HttpClient is normally used as HTTP protocol wrapper for all EasyRDF specialized clients and for SparqlClient
through EasyRdf_Http::setDefaultHttpClient()
method, but it can be also used as a generic Web Resource client.
For example, to use simple client identity in accessing a remote sparql endpoint execute:
// define common properties of http client to use to access RDF web resources
$httpClient = new BOTK\RDF\HttpClient;
$httpClient->setAuth('username', 'password');
EasyRdf_Http::setDefaultHttpClient($httpClient);
// access a private sparql end-point that requires basic authentication
$sparql = new EasyRdf_Sparql_Client('https://private/sparql');
$result=$sparql->query('SELECT * WHERE {?s ?p ?o} LIMIT 10');
HttpClient interface is compatible with ZEND-Http_client library.
HttpClient provides a simple helper to create an authenticated HTTP client and use it in EasyRdf with a
single call of the static method HttpClient::useIdentity(string $usename = null, string $password=null, $timeout=null )
. If not specified the client will reuse the timeout of the calling script (if
available) or 30 sec. otherwise. Using the helper, the previous code can be shorten as:
BOTK\RDF\HttpClient::useIdentity('username','password');
$sparql = new EasyRdf_Sparql_Client('https://private/sparql');
$result=$sparql->query('SELECT * WHERE {?s ?p ?o} LIMIT 10');
.
This content negotiation policy is designed for applications that use EasyRff_Graph data structure as Resource Model.
It provide following response and request representations:
RDF class define following renderer functions:
- RDF::turtleRenderer(mixed $data, Standard::n3Renderer(mixed $data)
- Serializes data structure as RDF text/turle
- RDF::rdfxmlRenderer(mixed $data)
- Serializes data structure as RDF application/xml+rdf.
- RDF::jsonRenderer(mixed $data)
- Serializes data structure using json
- RDF::ntriplesRenderer(mixed $data)
- serializes data structure RDF ntriples.
- RDF::htmlRenderer(mixed $data)
- serializes data structure as html.
- RDF::serialphpRenderer(mixed $data)
- serializes data structure as php.
This content negotiation policy is designed for applications that use EasyRdf_Sparql_Result data structure as Resource Model.
It provide following response and request representations:
This set of classes allow you to implement a simple endpoint to publish linked data according last Linked Data Platform Woking Group Draft Specifications . The provided classes can be used to base Linked Data Platform Server Implementations.
Here is a simple script that realizes an LDP PAGING server:
class MyRouter extends EndPoint
{
protected function setRoutes()
{
$this->get('/', 'ProductsController')
->accept(RDF::renderers())
->through($this->representationCachingProcessor(Caching::SHORT));
}
}
class ProductsController extends SparqlLDPController
{
protected
$pagesize = 10,
$pagingPolicy = self::CONSERVATIVE,
$endpoint = 'http://linkedopencommerce.com/sparql/',
$constructor = '
PREFIX gr: <http://purl.org/goodrelations/v1#>
DESCRIBE ?product WHERE {
?product a gr:ProductOrServiceModel.
}
';
}
$errorManager = BOTK\Core\ErrorManager::getInstance()->registerErrorHandler();
try {
echo BOTK\Core\EndPointFactory::make('MyRouter')->run();
} catch ( Exception $e) {
echo $errorManager->render($e);
}
This class provides an generic abstract implementation of a LDP paged controller. In order to get a working implementation you have to implement three methods:
detectIfHasNextPage()
: that must return true if another linked data page is available. If it is not provided, paging features will be disabled.linkData()
: that populate the protected varresultGraph
(an EasyRdf_Graph object) with linked resourcelinkMetaData()
: that optionally add metadata toresultGraph
It provides a simple template engine (from Core Package) populated with a set of predefine variables placeholders:
{pagedResourceUri}
: the requested uri without page info;{strippedUri}
: the requested uri without query strings and fragment.{requestUri}
: the requested uri as written by user (with or partial page info)
The protected context
variable contains an instance of Core PagedResourceContext.
This class extends LDPController and provides a generic implementation of a Linked Data Platform Server that publish as Linked Data Resources some resources contained in a sparql Server.
You need to redefine following variables to override defaults :
- $username
- the username required to access sparql update endpoint, default is empty
- $password
- the password required to access sparql update endpoint. only Basic method supported, default is empty
- $endpoint
- the sparql endpoint uri. The default is empty. Examples of valid open sparql endpoints are: http://dbpedia.org/sparql, http://lod.openlinksw.com/sparql, http://linkedopencommerce.com/sparql
- $pagingPolicy
- it is a string value that can be `AGGRESSIVE` or `CONSERVATIVE` to drive next page detection algorithm. The default is AGGRESSIVE
- $constructor
- must contain a valid sparq query template that build a graph with linked data. Do not include LIMIT/OFFSET clause.The default is empty.
- $metadata
- optionally contains a turtle template with paged resource metadata. The default is empty
SparqlLDPController class implements LDPController abstract methods:
- it provides an implementation of
detectIfHasNextPage()
based on a parametric algorithm that use the$pagingPolicy
variable. If$pagingPolicy
=AGGRESSIVE thandetectIfHasNextPage()
method returns true when last query to sparqls server resulted in exactly$pagesize
triples, false otherwise. If$pagingPolicy
=CONSERVATIVE returns true when last query to sparql server was not empty. - It provides an implementation of
linkData()
methods based on the sparql query in$selector
variable. - It provides an implementation of
linkMedtadata()
methods based on the turtle template in in$metadata
variable.
Beside this, SparqlLDPController class implements :
get($resourceId=null)
: a default controller get methods with an optional argument that is set by router.
This class add following predefined variables placeholders to the simple template engine:
{endpoint}
: the value of the variable of the same name.{limit}
: same value of PagedResouceContext::getPageSize(){offset}
: a calculated value as PagedResouceContext::getPageNum() * PagedResouceContext::getPageSize(){username}
: the value of the variable of the same name.{containerUri}
: the guessed uri of the container extracted from {strippedUri}{resourceId}
: the value of the router template var argument. If resouceId is an array, it is transformed in string withimplode('/',$resourceId)
php instruction.{encodedResourceId}
: same as {resourceId} but url encoded.
You can use these variables, plus the ones defined in LDPController, in $constructor and $metadata templates.
Here is a full example of a contanainer/resource LDP-PAGING implementation using void and prov ontology to
annotate resources:
class MyRouter extends EndPoint
{
protected function setRoutes()
{
$this->get('/', 'DatasetController');
$this->get('/*','DataDumpController');
$this->always('Accept', RDF::renderers() );
$this->always('Through', $this->representationCachingProcessor(Caching::SHORT));
}
}
class DataDumpController extends SparqlLDPController
{
protected $endpoint = 'http://lod.openlinksw.com/sparql';
protected $constructor = '
PREFIX ld: <http://e-artspace.com/s/eCloud#>
CONSTRUCT {
?ldpr ?p ?o .
} WHERE {
GRAPH <http://e-artspace.com/s/eCloud/> {
?ldpr ?p ?o
FILTER (?ldpr = ld:{resourceId} )
}
} LIMIT {limit} OFFSET {offset}
';
protected $metadata = '
@base <{pagedResourceUri}> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix void: <http://rdfs.org/ns/void#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix ldp: <http://www.w3.org/ns/ldp#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix container: <{containerUri}#> .
@prefix ld: <http://e-artspace.com/s/eCloud#> .
<> a ldp:Resource, foaf:Document, prov:Entity ;
foaf:primaryTopic ld:{resourceId} ;
void:inDataset container:dataset ;
rdfs:seeAlso <{endpoint}?query=DESCRIBE%20%3Chttp%3A%2F%2Fe-artspace.com%2Fs%2FeCloud%23{encodedResourceId}%3E> ;
prov:wasGeneratedBy [
a prov:Activity ;
prov:used <{queryResource}> ;
prov:wasAssociatedWith container:sparqlServerUser ;
]
.
';
}
class DatasetController extends SparqlLDPController
{
protected $type = 'DirectContainer';
protected $endpoint = 'http://lod.openlinksw.com/sparql';
protected $constructor = '
PREFIX void: <http://rdfs.org/ns/void#>
PREFIX ldp: <http://www.w3.org/ns/ldp#>
CONSTRUCT {
<{pagedResourceUri}#dataset> void:dataDump ?ldpr .
} WHERE {
GRAPH <http://e-artspace.com/s/eCloud/> {
?resource a ?type
FILTER(!isBlank(?resource))
}
BIND( IRI(REPLACE(STR(?resource), "http://e-artspace.com/s/eCloud#","{strippedUri}")) AS ?ldpr)
}
';
protected $metadata = '
@base <{pagedResourceUri}> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix void: <http://rdfs.org/ns/void#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix ldp: <http://www.w3.org/ns/ldp#> .
@prefix : <#> .
<> a ldp:DirectContainer, foaf:Document ;
foaf:primaryTopic :dataset ;
ldp:membershipResource :dataset ;
ldp:hasMemberRelation void:dataDump ;
ldp:insertedContentRelation foaf:primaryTopic ;
.
:dataset a void:Dataset, prov:Entity ;
prov:wasGeneratedBy [
a prov:Activity ;
prov:used <{queryResource}> ;
prov:wasAssociatedWith :sparqlServerUser
]
.
:sparqlServerUser a foaf:Agent;
foaf:account [
a foaf:OnlineAccount ;
foaf:accountServiceHomepage <{endpoint}> ;
foaf:accountname "{username}" ;
]
.
';
}
$errorManager = BOTK\Core\ErrorManager::getInstance()->registerErrorHandler();
try {
echo BOTK\Core\EndPointFactory::make('MyRouter')->run();
} catch ( Exception $e) {
echo $errorManager->render($e);
}
Copyright © 2016 by Enrico Fagnoni at LinkedData.Center®
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.