-
Notifications
You must be signed in to change notification settings - Fork 89
Plugins: Data Wiki
semsol edited this page Mar 14, 2011
·
2 revisions
Create an index.php file and put it in your wiki target directory:
/* ARC2 static class inclusion */
include_once('path/to/arc/ARC2.php');
/* configuration */
$config = array(
// no config needed for now
);
/* instantiation */
$wiki = ARC2::getComponent('DataWikiPlugin', $config);
/* request handling */
$wiki->go();
Now you need a .htaccess file (or alternatively tweak the Apache configuration directly). If your server supports mod_headers, you can let Apache handle GET requests and send the "MS-Author-Via" Header:
# indicate SPARQL Update friendliness
Header set MS-Author-Via: SPARQL
# enable rewrites
RewriteEngine on
RewriteBase /path/to/wiki
# redirect POSTs to the Wiki script
RewriteCond %{REQUEST_METHOD} POST
RewriteRule !^index\.php index.php [L]
# redirect 404s to the Wiki script
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !^index\.php index.php [L]
Otherwise (w/o the mod_headers module), you have to route GET request through the PHP script, too:
# enable rewrites
RewriteEngine on
RewriteBase /path/to/wiki
# redirect requests to the Wiki script
RewriteRule !^index\.php index.php [L]
Place the .htaccess file in the wiki directory.
Make sure the index.php script has write privileges for the wiki directory.
Now you should be able to use a SPARQL-enabled RDF editor such as Tabulator to create and edit RDF documents.
Save to "plugins/ARC2_DataWikiPlugin.php".
<?php
/*
homepage: http://arc.semsol.org/
license: http://arc.semsol.org/license
class: ARC2 Data Wiki Plugin
author: Benjamin Nowack
version: 2008-01-14
*/
ARC2::inc('Class');
class ARC2_DataWikiPlugin extends ARC2_Class {
function __construct($a = '', &$caller) {
parent::__construct($a, $caller);
}
function ARC2_DataWikiPlugin($a = '', &$caller) {
$this->__construct($a, $caller);
}
function __init() {
parent::__init();
$this->headers = array('http' => 'HTTP/1.1 200 OK');
}
/* */
function handleRequest() {
$rel_path = $this->getRequestPath();
if (!$rel_path) {
$this->handleRootRequest();
}
elseif (preg_match('/^post$/i', $_SERVER['REQUEST_METHOD'])) {
$this->handleUpdateRequest();
}
elseif (!file_exists($rel_path)) {
$this->handle404Request();
}
else {
$this->handlePassThroughRequest();
}
}
function setHeader($k, $v) {
$this->headers[$k] = $v;
}
function sendHeaders() {
foreach ($this->headers as $k => $v) {
header($v);
}
}
function getResult() {
return $this->result;
}
function go() {
$this->handleRequest();
$this->sendHeaders();
echo $this->getResult();
}
/* */
function getAbsBase() {
return preg_replace('/index\.php$/', '', ARC2::getScriptURI());
}
function getRelBase() {
return preg_replace('/index\.php$/', '', $_SERVER["SCRIPT_NAME"]);
}
function getRequestPath() {
$r = $_SERVER['REQUEST_URI'];
$r = preg_match('/^[^\/][a-z0-9]+\:[\/]+[^\/]+(.*)$/i', $r, $m) ? $m[1] : $r;
$r = substr($r, strlen($this->getRelBase()));
if (!$r || ($r == 'index.php')) return '';
$r = preg_replace('/\.[^\.]+$/', '', $r) . '.rdf';
return $r;
}
function getRequestURI(){
return $this->getAbsBase() . $this->getRequestPath();
}
function getTargetGraph() {
$r = preg_replace('/[\#\?].*$/', '', $this->getRequestURI());
$r = preg_replace('/\.rdf$/', '', $r);
return $r;
}
/* */
function handleRootRequest() {
$this->setHeader('content-type', 'Content-type: text/html; charset=utf-8');
$this->result = $this->getWelcomeDoc();
}
function handle404Request() {
$this->setHeader('content-type', 'Content-type: application/rdf+xml; charset=utf-8');
$this->setHeader('author-via', 'MS-Author-Via: SPARQL');
$this->result = '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"></rdf:RDF>';
}
function handlePassThroughRequest() {
$rel_path = $this->getRequestPath();
$this->setHeader('content-type', 'Content-type: application/rdf+xml; charset=utf-8');
$this->setHeader('author-via', 'MS-Author-Via: SPARQL');
$this->result = file_get_contents($rel_path);
}
function handleUpdateRequest() {
$this->result = '';
$this->setHeader('http', 'HTTP/1.1 403 Forbidden');
$rel_path = $this->getRequestPath();
if ($q = @file_get_contents('php://input')) {
$triples = array();
if (file_exists($rel_path)) {
$parser = ARC2::getRDFParser($this->a);
$parser->parse($rel_path);
$triples = $parser->getTriples();
}
$index = ARC2::getSimpleIndex($triples, 0);
/* split combined INSERT/DELETE query */
if (preg_match('/^\s*(DELETE.*)\s*(INSERT.*)$/is', $q, $m)) {
$qs = array($m[1], $m[2]);
}
else {
$qs = array($q);
}
$this->writeLog(print_r($qs, 1));
foreach ($qs as $q) {
$index = $this->getUpdatedIndex($index, $q);
$this->writeLog(print_r($index, 1));
if (!$this->getErrors()) {
$this->setHeader('http', 'HTTP/1.1 200 OK');
if ($index) {
/* todo: create dirs, if necessary */
$fp = fopen($rel_path, 'w');
fwrite($fp, $this->toRDFXML($index));
fclose($fp);
}
else {
unlink($rel_path);
}
}
}
}
}
function getUpdatedIndex($old_index, $q) {
if (!preg_match('/^\s*(INSERT|DELETE)\s*(INTO|FROM)?\s*(.*)$/is', $q, $m)) {
return 0;
}
$qt = strtolower($m[1]);
$g = $this->getTargetGraph();
/* inject a target graph, if necessary */
if (!$m[2]) {
$q = strtoupper($qt) . (($qt == 'insert') ? ' INTO ' : ' FROM') . ' <' . $g . '> ' . $m[3];
}
/* parse the query */
$this->writeLog($q);
ARC2::inc('SPARQLPlusParser');
$p = & new ARC2_SPARQLPlusParser($this->a, $this);
$p->parse($q);
$infos = $p->getQueryInfos();
/* errors? */
if ($errors = $this->getErrors()) {
$this->setHeader('http', 'HTTP/1.1 400 Bad Request');
$this->setHeader('content-type', 'Content-type: text/plain; charset=utf-8');
$this->result = join("\n", $errors);
return 0;
}
$q_index = ARC2::getSimpleIndex($infos['query']['construct_triples'], 0);
if ($qt == 'insert') {
return ARC2::getMergedIndex($old_index, $q_index);
}
elseif ($qt == 'delete') {
return ARC2::getCleanedIndex($old_index, $q_index);
}
}
/* */
function getWelcomeDoc() {
if (file_exists('welcome.htm')) {
return file_get_contents('welcome.htm');
}
else {
return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>ARC Data Wiki</title>
<style type="text/css">
body {
font-size: 14px;
font-family: Trebuchet MS, Verdana, Geneva, sans-serif;
background-color: #fcfcfc;
padding: 20px 20% 20px 20%;
color: #666;
}
h1 { font-size: 1.6em; font-weight: normal; }
a { color: #c00000; }
</style>
</head>
<body>
<h1>ARC Data Wiki (v' . ARC2::getVersion() . ')</h1>
<p>
This Web space allows the manipulation of RDF documents via
<a href="https://github.com/semsol/arc2/wiki/SPARQL%2B">SPARQL+</a>
(or, more precisely, a slightly tweaked version of it which
accepts INSERT and DELETE queries without an explicitly specified target graph).
</p>
<p>
<a href="https://github.com/semsol/arc2/wiki/Plugins:-Data-Wiki">Plugin Documentation</a>
</p>
</body>
</html>
';
}
}
/* */
function writeLog($v) {
return 1;
$fp = fopen('log.txt', 'a');
$now = time();
fwrite($fp, date('Y-m-d\TH:i:s\Z', $now) . ' : ' . $v . '' . "\r\n");
fclose($fp);
}
/* */
}