r73290 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r73289‎ | r73290 | r73291 >
Date:14:05, 18 September 2010
Author:samuellampa
Status:deferred
Tags:
Comment:
Initial check-in of the RDFIO extension for MediaWiki/Semantic MediaWiki
Modified paths:
  • /trunk/extensions/RDFIO/COPYING (added) (history)
  • /trunk/extensions/RDFIO/INSTALL (added) (history)
  • /trunk/extensions/RDFIO/RDFIO.php (added) (history)
  • /trunk/extensions/RDFIO/README (added) (history)
  • /trunk/extensions/RDFIO/RELEASE-NOTES (added) (history)
  • /trunk/extensions/RDFIO/bundle (added) (history)
  • /trunk/extensions/RDFIO/bundle/ARC2_SPARQLSerializerPlugin.php (added) (history)
  • /trunk/extensions/RDFIO/classes (added) (history)
  • /trunk/extensions/RDFIO/classes/PageHandler.php (added) (history)
  • /trunk/extensions/RDFIO/classes/RDFStore.php (added) (history)
  • /trunk/extensions/RDFIO/classes/SMWBatchWriter.php (added) (history)
  • /trunk/extensions/RDFIO/classes/Utils.php (added) (history)
  • /trunk/extensions/RDFIO/specials (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialARC2Admin.alias.php (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialARC2Admin.i18n.php (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialARC2Admin.php (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialARC2Admin_body.php (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialRDFImport.alias.php (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialRDFImport.i18n.php (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialRDFImport.php (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialRDFImport_body.php (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint.alias.php (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint.i18n.php (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint.php (added) (history)
  • /trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint_body.php (added) (history)
  • /trunk/extensions/RDFIO/stores (added) (history)
  • /trunk/extensions/RDFIO/stores/SMW_ARC2Store.php (added) (history)

Diff [purge]

Index: trunk/extensions/RDFIO/stores/SMW_ARC2Store.php
@@ -0,0 +1,234 @@
 2+<?php
 3+
 4+global $IP;
 5+
 6+require_once("$IP/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php");
 7+
 8+if( !defined( 'MEDIAWIKI' ) ) {
 9+ die( 'Not a valid entry point.' );
 10+}
 11+
 12+/**
 13+ * SMWARC2Store extends SMWSQLStore2 and forwards all update/delete to ARC2 via SPARQL+
 14+ * queries. The class was based on JosekiStore in the SparqlExtension, which in turn is
 15+ * losely based on/insipred by RAPStore.
 16+ * @author samuel.lampa@gmail.com
 17+ * @package RDFIO
 18+ */
 19+class SMWARC2Store extends SMWSQLStore2 {
 20+ protected $arc2store;
 21+
 22+ public function SMWARC2Store() {
 23+ global $wgDBserver, $wgDBname, $wgDBuser, $wgDBpassword, $smwgARC2StoreConfig;
 24+
 25+ /* instantiation */
 26+ $this->arc2store = ARC2::getStore($smwgARC2StoreConfig);
 27+ }
 28+
 29+ /**
 30+ * wraps removeDataForURI
 31+ * @param $subject
 32+ */
 33+ function deleteSubject(Title $subject) {
 34+ $subject_uri = SMWExporter::expandURI($this->getURI($subject));
 35+ $this->removeDataForURI($subject_uri);
 36+
 37+ return parent::deleteSubject($subject);
 38+ }
 39+
 40+ /**
 41+ * deletes triples that have $uri as subject
 42+ * @param $uri
 43+ */
 44+ function removeDataForURI($uri) {
 45+ $sparqlUpdateText = "DELETE { <".$uri."> ?x ?y . }";
 46+ wfDebugLog('SPARQL_LOG', "===DELETE===\n".$sparqlUpdateText);
 47+ $response = $this->do_arc2_query($sparqlUpdateText);
 48+ return $response;
 49+ }
 50+
 51+ /**
 52+ * Does update. First deletes, then inserts.
 53+ * @param $data
 54+ */
 55+ function updateData(SMWSemanticData $data) {
 56+ $export = SMWExporter::makeExportData($data);
 57+ $subject_uri = SMWExporter::expandURI($export->getSubject()->getName());
 58+
 59+ // remove subject from triple store
 60+ $this->removeDataForURI($subject_uri);
 61+
 62+ $triple_list = $export->getTripleList();
 63+
 64+ $sparqlUpdateText = "INSERT INTO <> {\n";
 65+
 66+ foreach ($triple_list as $triple) {
 67+
 68+ $subject = $triple[0];
 69+ $predicate = $triple[1];
 70+ $object = $triple[2];
 71+
 72+ $obj_str = "";
 73+ $sub_str = "";
 74+ $pre_str = "";
 75+
 76+ if ($object instanceof SMWExpLiteral) {
 77+ $obj_str = "\"".$object->getName()."\"".(($object->getDatatype() == "") ? "" : "^^<".$object->getDatatype().">");
 78+ } else if ($object instanceof SMWExpResource) {
 79+ $obj_str = "<".SMWExporter::expandURI($object->getName()).">";
 80+ } else {
 81+ $obj_str = "\"\"";
 82+ }
 83+
 84+ if ($subject instanceof SMWExpResource) {
 85+ $sub_str = "<".SMWExporter::expandURI($subject->getName()).">";
 86+ }
 87+
 88+ if ($predicate instanceof SMWExpResource) {
 89+ $pre_str = "<".SMWExporter::expandURI($predicate->getName()).">";
 90+ }
 91+
 92+ $sparqlUpdateText .= $sub_str." ".$pre_str." ".$obj_str." .\n";
 93+ }
 94+ $sparqlUpdateText .= "}\n";
 95+
 96+ // echo "<p style='background: #ccddff'><pre>SPARQL Update text:" . $this->unhtmlify( $sparqlUpdateText ) . " ... tjohoo</pre></p>";
 97+ // var_dump();
 98+ // TODO Debug-code
 99+
 100+ wfDebugLog('SPARQL_LOG', "===INSERT===\n".$sparqlUpdateText);
 101+
 102+ $response = $this->do_arc2_query($sparqlUpdateText);
 103+
 104+ return parent::updateData($data);
 105+ }
 106+
 107+ /**
 108+ * Insert new pages into endpoint. Used to import data.
 109+ * @param $title
 110+ */
 111+ function insertData(Title $title, $pageid) {
 112+ $newpage = SMWDataValueFactory::newTypeIDValue('_wpg');
 113+ $newpage->setValues($title->getDBkey(), $title->getNamespace(), $pageid);
 114+ $semdata = $this->getSemanticData($newpage);
 115+ $this->updateData($semdata);
 116+ }
 117+
 118+ /**
 119+ * Move/rename page
 120+ * @param $oldtitle
 121+ * @param $newtitle
 122+ * @param $pageid
 123+ * @param $redirid
 124+ */
 125+ function changeTitle(Title $oldtitle, Title $newtitle, $pageid, $redirid=0) {
 126+
 127+ // Save it in parent store now!
 128+ // We need that so we get all information correctly!
 129+ $result = parent::changeTitle($oldtitle, $newtitle, $pageid, $redirid);
 130+
 131+ // delete old stuff
 132+ $old_uri = SMWExporter::expandURI($this->getURI($oldtitle));
 133+ $this->removeDataForURI($old_uri);
 134+
 135+ $newpage = SMWDataValueFactory::newTypeIDValue('_wpg');
 136+ $newpage->setValues($newtitle->getDBkey(), $newtitle->getNamespace(), $pageid);
 137+ $semdata = $this->getSemanticData($newpage);
 138+ $this->updateData($semdata);
 139+
 140+ $oldpage = SMWDataValueFactory::newTypeIDValue('_wpg');
 141+ $oldpage->setValues($oldtitle->getDBkey(), $oldtitle->getNamespace(), $redirid);
 142+ $semdata = $this->getSemanticData($oldpage);
 143+ $this->updateData($semdata,false);
 144+
 145+ return $result;
 146+ }
 147+
 148+ /**
 149+ * no setup required
 150+ * @param unknown_type $verbose
 151+ */
 152+ function setup($verbose = true) {
 153+ return parent::setup($verbose);
 154+ }
 155+
 156+
 157+ function drop($verbose = true) {
 158+ return parent::drop();
 159+ }
 160+
 161+ /**
 162+ * Communicates with joseki update service via post
 163+ * TODO: Deprecated, replaced by do_arc2_query
 164+ * @param $requestString
 165+ */
 166+ function do_arc2_post($requestString) {
 167+ $postdata = http_build_query(
 168+ array(
 169+ 'request' => $requestString
 170+ )
 171+ );
 172+ $opts = array('http' =>
 173+ array(
 174+ 'method' => 'POST',
 175+ 'header' => 'Content-type: application/x-www-form-urlencoded',
 176+ 'content' => $postdata
 177+ )
 178+ );
 179+
 180+ $context = stream_context_create($opts);
 181+ $result = file_get_contents(SPARQL_ENDPOINT_UPDATE_URL, false, $context);
 182+ return $result;
 183+ }
 184+
 185+
 186+ /**
 187+ * Communicates with ARC2 RDF Store
 188+ * @param $requestString
 189+ */
 190+ function do_arc2_query($requestString) {
 191+
 192+ $q = $requestString;
 193+ $rs = $this->arc2store->query($q);
 194+ $result = $rs;
 195+
 196+ // echo( "<pre>" . $this->unhtmlify( $requestString ) . "</pre>" );
 197+ // echo( "<pre>ERRORS:<br>");
 198+ // print_r($this->arc2store->getErrors());
 199+ // echo("</pre>");
 200+
 201+ return $result;
 202+ }
 203+
 204+ /**
 205+ * Convert '<' and '>' to '&lt;' and '&gt;' instead
 206+ * @param string $instring
 207+ * @return string $outstring
 208+ */
 209+ function unhtmlify( $instring ) {
 210+ $outstring = str_replace('<','&lt;',$instring);
 211+ $outstring = str_replace('>','&gt;',$outstring);
 212+ return $outstring;
 213+ }
 214+
 215+ /**
 216+ * Having a title of a page, what is the URI that is described by that page?
 217+ * The result still requires expandURI()
 218+ * @param string $title
 219+ * @return string $uri
 220+ */
 221+ protected function getURI($title) {
 222+ $uri = "";
 223+ if($title instanceof Title){
 224+ $dv = SMWDataValueFactory::newTypeIDValue('_wpg');
 225+ $dv->setTitle($title);
 226+ $exp = $dv->getExportData();
 227+ $uri = $exp->getSubject()->getName();
 228+ }else{
 229+ // There could be other types as well that we do NOT handle here
 230+ }
 231+
 232+ return $uri; // still requires expandURI()
 233+ }
 234+}
 235+
Property changes on: trunk/extensions/RDFIO/stores/SMW_ARC2Store.php
___________________________________________________________________
Added: svn:eol-style
1236 + native
Index: trunk/extensions/RDFIO/specials/SpecialARC2Admin.alias.php
@@ -0,0 +1,7 @@
 2+<?php
 3+$aliases = array();
 4+
 5+/** English */
 6+$aliases['en'] = array(
 7+ 'SpecialARC2Admin' => array( 'ARC2Admin' ),
 8+);
Property changes on: trunk/extensions/RDFIO/specials/SpecialARC2Admin.alias.php
___________________________________________________________________
Added: svn:eol-style
19 + native
Index: trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint.alias.php
@@ -0,0 +1,7 @@
 2+<?php
 3+$aliases = array();
 4+
 5+/** English */
 6+$aliases['en'] = array(
 7+ 'SPARQLEndpoint' => array( 'SPARQLEndpoint' ),
 8+);
Property changes on: trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint.alias.php
___________________________________________________________________
Added: svn:eol-style
19 + native
Index: trunk/extensions/RDFIO/specials/SpecialARC2Admin_body.php
@@ -0,0 +1,72 @@
 2+<?php
 3+/**
 4+ * SpecialARC2Admin is a Special page for setting up the database tables for an ARC2 RDF Store
 5+ * @author samuel.lampa@gmail.com
 6+ * @package SMWRDFConnector
 7+ */
 8+class SpecialARC2Admin extends SpecialPage {
 9+
 10+ protected $m_issysop;
 11+
 12+ function __construct() {
 13+ global $wgUser;
 14+
 15+ $usergroups = $wgUser->getGroups();
 16+ if ( in_array( 'sysop', $usergroups ) ) {
 17+ $this->m_issysop = true;
 18+ } else {
 19+ $this->m_issysop = false;
 20+ }
 21+
 22+ parent::__construct( 'SpecialARC2Admin' );
 23+ wfLoadExtensionMessages('SpecialARC2Admin');
 24+ }
 25+
 26+ function execute( $par ) {
 27+ global $wgRequest, $wgOut, $wgDBserver, $wgDBname, $wgDBuser,
 28+ $wgDBpassword, $smwgARC2StoreConfig, $wgArticlePath,
 29+ $wgServer, $wgScriptPath, $wgUser;
 30+
 31+ $this->setHeaders();
 32+ $output = "";
 33+
 34+ # Get request data from, e.g.
 35+ $rdfio_action = $wgRequest->getText('rdfio_action');
 36+
 37+ # instantiation
 38+ $store = ARC2::getStore($smwgARC2StoreConfig);
 39+
 40+ $output .= "\n===RDF Store Setup===\n'''Status:'''\n\n";
 41+
 42+ if (!$store->isSetUp()) {
 43+ $output .= "* Store is '''not''' set up\n";
 44+ if ( $rdfio_action == "setup" ) {
 45+ if ( !$wgUser->matchEditToken( $wgRequest->getText( 'token' ) ) ) {
 46+ die( 'Cross-site request forgery detected!' );
 47+ } else {
 48+ if ( $this->m_issysop ) {
 49+ $output .= "* Setting up now ...\n";
 50+ $store->setUp();
 51+ $output .= "* Done!\n";
 52+ } else{
 53+ $errormessage = "Only sysops can perform this operation!";
 54+ $wgOut->addHTML( RDFIOUtils::formatErrorHTML("Permission Error", $errormessage) );
 55+ }
 56+ }
 57+ }
 58+ } else {
 59+ $output .= "* Store is already set up.\n";
 60+ }
 61+
 62+ $wgOut->addWikiText( $output );
 63+
 64+ $htmlOutput = '<form method="get" action="' . $wgServer . $wgScriptPath . '/index.php/Special:ARC2Admin"
 65+ name="createEditQuery">
 66+ <input type="submit" name="rdfio_action" value="setup">' .
 67+ Xml::hidden( 'token', $wgUser->editToken() ) . '
 68+ </form>';
 69+
 70+ $wgOut->addHTML( $htmlOutput );
 71+
 72+ }
 73+}
Property changes on: trunk/extensions/RDFIO/specials/SpecialARC2Admin_body.php
___________________________________________________________________
Added: svn:eol-style
174 + native
Index: trunk/extensions/RDFIO/specials/SpecialARC2Admin.i18n.php
@@ -0,0 +1,8 @@
 2+<?php
 3+$messages = array();
 4+
 5+$messages['en'] = array(
 6+ 'specialarc2admin' => 'ARC2 RDF Store Admin Page',
 7+ 'specialarc2admin-desc' => 'Administration page for the ARC2 RDF Store for Semantic MediaWiki',
 8+);
 9+
Property changes on: trunk/extensions/RDFIO/specials/SpecialARC2Admin.i18n.php
___________________________________________________________________
Added: svn:eol-style
110 + native
Index: trunk/extensions/RDFIO/specials/SpecialRDFImport.alias.php
@@ -0,0 +1,7 @@
 2+<?php
 3+$aliases = array();
 4+
 5+/** English */
 6+$aliases['en'] = array(
 7+ 'RDFImport' => array( 'RDFImport' ),
 8+);
Property changes on: trunk/extensions/RDFIO/specials/SpecialRDFImport.alias.php
___________________________________________________________________
Added: svn:eol-style
19 + native
Index: trunk/extensions/RDFIO/specials/SpecialARC2Admin.php
@@ -0,0 +1,25 @@
 2+<?php
 3+# Alert the user that this is not a valid entry point to MediaWiki if they try to access the special pages file directly.
 4+if (!defined('MEDIAWIKI')) {
 5+ echo <<<EOT
 6+To install my extension, put the following line in LocalSettings.php:
 7+require_once( "\$IP/extensions/SMWRDFConnector/SpecialARC2Admin.php" );
 8+EOT;
 9+ exit( 1 );
 10+}
 11+
 12+$wgExtensionCredits['specialpage'][] = array(
 13+ 'name' => 'SpecialARC2Admin',
 14+ 'author' => 'Samuel Lampa',
 15+ 'url' => 'http://www.mediawiki.org/wiki/Extension:SMWRDFConnector',
 16+ 'description' => 'Administration page for the ARC2 RDF Store for Semantic MediaWiki',
 17+ 'descriptionmsg' => 'arc2admin-desc',
 18+ 'version' => '0.0.0',
 19+);
 20+
 21+$dir = dirname(__FILE__) . '/';
 22+
 23+$wgAutoloadClasses['SpecialARC2Admin'] = $dir . 'SpecialARC2Admin_body.php'; # Tell MediaWiki to load the extension body.
 24+$wgExtensionMessagesFiles['SpecialARC2Admin'] = $dir . 'SpecialARC2Admin.i18n.php';
 25+$wgExtensionAliasesFiles['SpecialARC2Admin'] = $dir . 'SpecialARC2Admin.alias.php';
 26+$wgSpecialPages['SpecialARC2Admin'] = 'SpecialARC2Admin'; # Let MediaWiki know about your new special page.
Property changes on: trunk/extensions/RDFIO/specials/SpecialARC2Admin.php
___________________________________________________________________
Added: svn:eol-style
127 + native
Index: trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint_body.php
@@ -0,0 +1,967 @@
 2+<?php
 3+class SPARQLEndpoint extends SpecialPage {
 4+
 5+ protected $m_sparqlendpointconfig;
 6+ protected $m_sparqlendpoint;
 7+ protected $m_sparqlparser;
 8+ protected $m_store;
 9+ protected $m_query;
 10+ protected $m_query_parsed;
 11+ protected $m_querytype;
 12+ protected $m_outputtype;
 13+ protected $m_querybyoriguri;
 14+ protected $m_querybyequivuri;
 15+ protected $m_outputoriguris;
 16+ protected $m_outputequivuris;
 17+ protected $m_haswriteaccess; // User permission
 18+ protected $m_hasdeleteaccess; // User permission
 19+
 20+ function __construct() {
 21+ global $wgUser, $rdfiogQueryByOrigURI;
 22+
 23+ parent::__construct( 'SPARQLEndpoint' );
 24+ wfLoadExtensionMessages('SPARQLEndpoint');
 25+ $this->m_sparqlendpointconfig = $this->getSPARQLEndpointConfig();
 26+ $this->m_sparqlendpoint = ARC2::getStoreEndpoint( $this->m_sparqlendpointconfig );
 27+ $this->m_sparqlparser = ARC2::getSPARQLPlusParser();
 28+ $this->m_store = new RDFIOStore();
 29+
 30+ $userrights = $wgUser->getRights();
 31+ if ( in_array( 'edit', $userrights ) && in_array( 'createpage', $userrights ) ) {
 32+ $this->m_haswriteaccess = true;
 33+ } else {
 34+ $this->m_haswriteaccess = false;
 35+ }
 36+ if ( in_array( 'edit', $userrights ) && in_array( 'delete', $userrights ) ) {
 37+ $this->m_hasdeleteaccess = true;
 38+ } else {
 39+ $this->m_hasdeleteaccess = false;
 40+ }
 41+ }
 42+
 43+ /**
 44+ * The main function
 45+ */
 46+ function execute() {
 47+ global $wgRequest, $wgOut, $wgUser;
 48+
 49+ $this->setHeaders();
 50+ $this->handleRequestData();
 51+
 52+ $executesparql = true;
 53+
 54+ if ( $this->m_query == '' ) {
 55+ $this->printHTMLForm();
 56+ } else {
 57+ $this->ensureSparqlEndpointInstalled();
 58+ $this->convertURIsInQuery();
 59+
 60+ if ( $this->m_querytype == 'insert' ) { // TODO
 61+ if ( $this->checkAllowInsert() ) {
 62+ $this->importTriplesInQuery();
 63+ }
 64+ $this->printHTMLForm();
 65+ } else if ( $this->m_querytype == 'delete' ) {
 66+ if ( $this->checkAllowDelete() ) {
 67+ $this->deleteTriplesInQuery();
 68+ }
 69+ // TODO Add a "successfully inserted/deleted" message here
 70+ $this->printHTMLForm();
 71+ } else { // We are querying/outputting data, not editing
 72+
 73+ if ( $this->m_outputtype == 'htmltab' ) {
 74+ $this->printHTMLForm();
 75+ if ( $wgRequest->getBool( 'showquery', false ) ) {
 76+ $this->printQueryStructure();
 77+ $executesparql = false;
 78+ }
 79+ } else if ( $this->m_outputtype == 'rdfxml' && $this->m_querytype != 'construct' ) {
 80+ $errormessage = "RDF/XML can only be used with CONSTRUCT, if constructing triples";
 81+ $wgOut->addHTML( RDFIOUtils::formatErrorHTML( "Invalid choice", $errormessage ) );
 82+ $this->printHTMLForm();
 83+ $executesparql = false;
 84+ } else {
 85+ $this->prepareCreatingDownloadableFile();
 86+ }
 87+
 88+ if ( $executesparql ) {
 89+ $outputtype = $this->m_outputtype;
 90+ if ( $outputtype == '' && $this->m_querytype == 'construct' ) {
 91+ $outputtype = 'rdfxml';
 92+ }
 93+ if ( $outputtype == 'rdfxml' || $outputtype == 'xml' || $outputtype == '' ) {
 94+ // Make sure that ARC outputs data in a format that we can
 95+ // easily work with programmatically
 96+ $this->setOutputTypeInPost( 'php_ser' );
 97+ }
 98+
 99+ // Pass on the request handling to ARC2:s SPARQL Endpoint
 100+ $this->m_sparqlendpoint->handleRequest();
 101+ $this->handleSPARQLErrors();
 102+ $output = $this->m_sparqlendpoint->getResult();
 103+
 104+ if ( $outputtype == 'htmltab' ) {
 105+ if ( $this->m_outputoriguris ) {
 106+ $output = $this->convertURIsToOrigURIsInText( $output );
 107+ }
 108+ $output = $this->extractPrepareARCHTMLOutput( $output );
 109+ $wgOut->addHTML( $output );
 110+ } else if ( $outputtype == 'rdfxml' ) {
 111+ $output_structure = unserialize( $output );
 112+ $tripleindex = $output_structure['result'];
 113+ $triples = ARC2::getTriplesFromIndex( $tripleindex );
 114+ if ( $this->m_outputoriguris ) {
 115+ $triples = $this->convertURIsToOrigURIsInTriples( $triples );
 116+ }
 117+ if ( $this->m_outputequivuris ) {
 118+ # $triples = $this->complementTriplesWithEquivURIsForProperties( $triples );
 119+ if ( $this->m_filtervocab && ( $this->m_filtervocaburl != '' ) ) {
 120+ $vocab_p_uri_filter = $this->getVocabPropertyUriFilter();
 121+ $triples = $this->complementTriplesWithEquivURIs( $triples, $vocab_p_uri_filter );
 122+ } else {
 123+ $triples = $this->complementTriplesWithEquivURIs( $triples );
 124+ }
 125+ }
 126+ $output = $this->triplesToRDFXML( $triples );
 127+ echo $output;
 128+ } else {
 129+ $output_structure = unserialize( $output );
 130+ if ( $this->m_outputoriguris ) {
 131+ $output_structure = $this->convertURIsToOrigURIsInSPARQLResultSet( $output_structure );
 132+ }
 133+ if ( $this->m_outputequivuris ) {
 134+ $vocab_p_uri_filter = $this->getVocabPropertyUriFilter();
 135+ $output_structure = $this->complementSPARQLResultRowsWithEquivURIs( $output_structure, $vocab_p_uri_filter );
 136+ }
 137+ $output = $this->m_sparqlendpoint->getSPARQLXMLSelectResultDoc( $output_structure );
 138+ echo $output;
 139+ }
 140+ }
 141+ }
 142+ }
 143+ }
 144+
 145+ /**
 146+ * Take care of data from the request object and store
 147+ * in class variables
 148+ */
 149+ function handleRequestData() {
 150+ global $wgRequest,
 151+ $rdfiogQueryByOrigURI,
 152+ $rdfiogQueryByEquivURI,
 153+ $rdfiogOutputOrigURIs,
 154+ $rdfiogOutputEquivURIs;
 155+
 156+ $this->m_query = $wgRequest->getText( 'query' );
 157+
 158+ if ( $rdfiogQueryByOrigURI == '' ) {
 159+ $this->m_querybyoriguri = $wgRequest->getBool( 'origuri_q' ); // No default value, as to not overwrite configurable setting in LocalSettings.php
 160+ } else {
 161+ $this->m_querybyoriguri = $rdfiogQueryByOrigURI;
 162+ }
 163+
 164+ if ( $rdfiogQueryByEquivURI == '' ) {
 165+ $this->m_querybyequivuri = $wgRequest->getBool( 'equivuri_q' );
 166+ } else {
 167+ $this->m_querybyequivuri = $rdfiogQueryByEquivURI;
 168+ }
 169+
 170+ if ( $rdfiogOutputOrigURIs == '' ) {
 171+ $this->m_outputoriguris = $wgRequest->getBool( 'origuri_o' );
 172+ } else {
 173+ $this->m_outputoriguris = $rdfiogOutputOrigURIs;
 174+ }
 175+
 176+ if ( $rdfiogOutputEquivURIs == '' ) {
 177+ $this->m_outputequivuris = $wgRequest->getBool( 'equivuri_o' );
 178+ } else {
 179+ $this->m_outputequivuris = $rdfiogOutputEquivURIs;
 180+ }
 181+
 182+ $this->m_filtervocab = $wgRequest->getBool( 'filtervocab', false );
 183+ $this->m_filtervocaburl = $wgRequest->getText( 'filtervocaburl');
 184+ $this->m_outputtype = $wgRequest->getText( 'output' );
 185+ if ( $this->m_query !== '' ) {
 186+ $this->m_sparqlparser->parse( $this->m_query, '' );
 187+ $this->m_query_parsed = $this->m_sparqlparser->getQueryInfos();
 188+ if ( array_key_exists( 'query', $this->m_query_parsed ) ) {
 189+ $this->m_querytype = $this->m_query_parsed['query']['type'];
 190+ }
 191+ }
 192+ }
 193+
 194+ function ensureSparqlEndpointInstalled() {
 195+ if (!$this->m_sparqlendpoint->isSetUp()) {
 196+ $this->m_sparqlendpoint->setUp(); /* create MySQL tables */
 197+ }
 198+ }
 199+
 200+ /**
 201+ * If option is so chosen, convert URIs in the query to
 202+ * their corresponding "Original URIs" or "Equivalent URIs"
 203+ */
 204+ function convertURIsInQuery() {
 205+ if ( $this->m_querybyoriguri ) {
 206+ $this->convertOrigURIsToInternalURIsInQuery();
 207+ } else if ( $this->m_querybyequivuri ) {
 208+ $query_structure = $this->m_query_parsed;
 209+ $triple = $query_structure['query']['pattern']['patterns'][0]['patterns'][0];
 210+ $s = $triple['s'];
 211+ $p = $triple['p'];
 212+ $o = $triple['o'];
 213+ $s_type = $triple['s_type'];
 214+ $p_type = $triple['p_type'];
 215+ $o_type = $triple['o_type'];
 216+ if ( $s_type === 'uri' ) {
 217+ $triple['s'] = 's';
 218+ $triple['s_type'] = 'var';
 219+ $newtriple = $this->createEquivURITriple( $s, 's' );
 220+ $query_structure['query']['pattern']['patterns'][0]['patterns'][] = $newtriple;
 221+ }
 222+ if ( $p_type === 'uri' ) {
 223+ $triple['p'] = 'p';
 224+ $triple['p_type'] = 'var';
 225+ $newtriple = $this->createEquivURITriple( $p, 'p', true );
 226+ $query_structure['query']['pattern']['patterns'][0]['patterns'][] = $newtriple;
 227+ }
 228+ if ( $o_type === 'uri' ) {
 229+ $triple['o'] = 'o';
 230+ $triple['o_type'] = 'var';
 231+ $newtriple = $this->createEquivURITriple( $o, 'o' );
 232+ $query_structure['query']['pattern']['patterns'][0]['patterns'][] = $newtriple;
 233+ }
 234+ // restore the first triple into its original location
 235+ $query_structure['query']['pattern']['patterns'][0]['patterns'][0] = $triple;
 236+ require_once(__DIR__ . "/bundle/ARC2_SPARQLSerializerPlugin.php");
 237+ $sparqlserializer = new ARC2_SPARQLSerializerPlugin();
 238+ $query = $sparqlserializer->toString( $query_structure );
 239+
 240+ $this->setQueryInPost( $query );
 241+ # $this->convertEquivURIsToInternalURIsInQuery(); // TODO DEPRECATED
 242+ }
 243+ }
 244+
 245+ /**
 246+ * Get an array of property URIs from the specified ontology,
 247+ * to function as a filter
 248+ * @return array $vocab_p_uri_filter
 249+ */
 250+ function getVocabPropertyUriFilter() {
 251+ $vocaburl = $this->m_filtervocaburl;
 252+ $RDFXMLParser = ARC2::getRDFXMLParser();
 253+ $RDFXMLParser->parse( $vocaburl );
 254+ $vocabtriples = $RDFXMLParser->getTriples();
 255+ $vocab_p_uri_filter = array();
 256+ foreach ( $vocabtriples as $vocabtriple ) {
 257+ $p = $vocabtriple['p'];
 258+ $o = $vocabtriple['o'];
 259+ // For OWL vocabularies:
 260+ if ( $p === 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' &&
 261+ $o === 'http://www.w3.org/2002/07/owl#ObjectProperty' ) {
 262+ $vocab_p_uri = $vocabtriple['s'];
 263+ $vocab_p_uri_filter[] = $vocab_p_uri;
 264+ }
 265+ }
 266+ return $vocab_p_uri_filter;
 267+ }
 268+
 269+ /**
 270+ * Create an RDF triple that links a wiki page to its corresponding
 271+ * equivalent URI
 272+ * @param string $uri
 273+ * @param string $varname
 274+ * @param boolean $isproperty
 275+ * @return array $equivuritriple
 276+ */
 277+ function createEquivURITriple( $uri, $varname, $isproperty = false ) {
 278+ if ( $isproperty ) {
 279+ $equivuriuri = $this->m_store->getEquivURIURIForProperty();
 280+ } else {
 281+ $equivuriuri = $this->m_store->getEquivURIURI();
 282+ }
 283+ $equivuritriple = array(
 284+ 'type' => 'triple',
 285+ 's' => $varname,
 286+ 'p' => $equivuriuri,
 287+ 'o' => $uri,
 288+ 's_type' => 'var',
 289+ 'p_type' => 'uri',
 290+ 'o_type' => 'uri',
 291+ 'o_datatype' => '',
 292+ 'o_lang' => ''
 293+ );
 294+ return $equivuritriple;
 295+ }
 296+
 297+ /**
 298+ * Check if writing to wiki is allowed, and handle a number
 299+ * of exceptions to that, by showing error messages etc
 300+ */
 301+ function checkAllowInsert() {
 302+ global $wgRequest, $wgUser, $wgOut, $rdfiogAllowRemoteEdit;
 303+ if ( $rdfiogAllowRemoteEdit == '' ) {
 304+ $rdfiogAllowRemoteEdit = false;
 305+ }
 306+ if ( !$wgUser->matchEditToken( $wgRequest->getText( 'token' ) ) &&
 307+ !$rdfiogAllowRemoteEdit ) {
 308+ $errortitle = "Error";
 309+ $errormessage = "Cross-site request forgery detected!";
 310+ $wgOut->addHTML( RDFIOUtils::formatErrorHTML( $errortitle, $errormessage ) );
 311+ return false;
 312+ } else {
 313+ if ( $this->m_haswriteaccess ) {
 314+ return true;
 315+ } else {
 316+ $errortitle = "Permission error";
 317+ $errormessage = "The current user lacks access either to edit or create pages (or both) in this wiki.";
 318+ $wgOut->addHTML( RDFIOUtils::formatErrorHTML( $errortitle, $errormessage ) );
 319+ return false;
 320+ }
 321+ }
 322+ }
 323+
 324+ /**
 325+ * Check if deleting from wiki is allowed, and handle a number
 326+ * of exceptions to that, by showing error messages etc
 327+ */
 328+ function checkAllowDelete() {
 329+ global $wgRequest, $wgUser, $wgOut, $rdfiogAllowRemoteEdit;
 330+ if ( !$wgUser->matchEditToken( $wgRequest->getText( 'token' ) ) &&
 331+ !$rdfiogAllowRemoteEdit ) {
 332+ die( 'Cross-site request forgery detected!' );
 333+ } else {
 334+ if ( $this->m_hasdeleteaccess || $rdfiogAllowRemoteEdit ) {
 335+ return true;
 336+ } else {
 337+ $errortitle = "Permission error";
 338+ $errormessage = "The current user lacks access either to edit or delete pages (or both) in this wiki.";
 339+ $wgOut->addHTML( RDFIOUtils::formatErrorHTML( $errortitle, $errormessage ) );
 340+ return false;
 341+ }
 342+ }
 343+ }
 344+
 345+ /**
 346+ * Print out the datastructure of the query in preformatted text
 347+ */
 348+ function printQueryStructure() {
 349+ global $wgOut;
 350+ $wgOut->addHTML( "<h3>Query structure</h3><pre>" . print_r( $this->m_query_parsed, true ) . "</pre>" );
 351+ }
 352+
 353+ /**
 354+ * Do preparations for getting outputted data as a downloadable file
 355+ * rather than written to the current page
 356+ */
 357+ function prepareCreatingDownloadableFile() {
 358+ global $wgOut;
 359+ // Disable MediaWikis theming
 360+ $wgOut->disable();
 361+ // Enables downloading as a stream, which is important for large dumps
 362+ wfResetOutputBuffers();
 363+ // Send headers telling that this is a special content type
 364+ // and potentially is to be downloaded as a file
 365+ $this->sendHeadersForOutputType( $this->m_outputtype );
 366+ }
 367+
 368+ /**
 369+ * Print out the HTML Form
 370+ */
 371+ function printHTMLForm() {
 372+ global $wgOut;
 373+ $wgOut->addScript( $this->getHTMLFormScript() );
 374+ $wgOut->addHTML( $this->getHTMLForm( $this->m_query ) );
 375+ }
 376+
 377+ /**
 378+ * Extract the main content form ARC:s SPARQL result HTML
 379+ * and do some processing (wikify tables)
 380+ * @param string $output
 381+ * @return string $html
 382+ */
 383+ function extractPrepareARCHTMLOutput( $output ) {
 384+ $html = RDFIOUtils::extractHTMLBodyContent( $output );
 385+ $html = RDFIOUtils::wikifyTables( $html );
 386+ $html = "<h3>Result:</h3><div style='font-size: 11px;'>" . $html . "</div>";
 387+ return $html;
 388+ }
 389+
 390+ /**
 391+ * After a query is parsed, import the parsed data to the wiki
 392+ */
 393+ function importTriplesInQuery() {
 394+ $triples = $this->m_query_parsed['query']['construct_triples'];
 395+ $rdfImporter = new RDFIOSMWBatchWriter( $triples, 'triples_array');
 396+ $rdfImporter->execute();
 397+ }
 398+
 399+ /**
 400+ * After a query is parsed, delete the parsed data from the wiki
 401+ */
 402+ function deleteTriplesInQuery() {
 403+ $triples = $this->m_query_parsed['query']['construct_triples'];
 404+ $rdfImporter = new RDFIOSMWBatchWriter( $triples, 'triples_array');
 405+ $rdfImporter->executeDelete();
 406+ }
 407+
 408+ /**
 409+ * Die and display current errors
 410+ */
 411+ function handleSPARQLErrors() {
 412+ global $wgOut;
 413+ $sparqlEndpointErrors = $this->m_sparqlendpoint->getErrors();
 414+ if ( count( $sparqlEndpointErrors ) > 0 ) {
 415+ $errormessage = '';
 416+ if ( is_array( $sparqlEndpointErrors ) ) {
 417+ foreach ( $sparqlEndpointErrors as $sparqlEndpointError ) {
 418+ $errormessage .= "<p>$sparqlEndpointError</p>";
 419+ }
 420+ } else {
 421+ $errormessage = "<p>$sparqlEndpointErrors</p>";
 422+ }
 423+ RDFIOUtils::showErrorMessage( "SPARQL Error", $errormessage );
 424+ }
 425+ }
 426+
 427+ /**
 428+ * For each URI in the (unparsed) query that is set by an "Original URI" property in
 429+ * the wiki, replace it with the page's corresponding URI Resolver URI
 430+ */
 431+ function convertOrigURIsToInternalURIsInQuery() {
 432+ $query = $this->m_query;
 433+ $origuris = RDFIOUtils::extractURIs( $this->m_query ); // TODO: Use parsed query instead
 434+ $count = count( $origuris );
 435+ if ( $count > 1 || ($count > 0 && !RDFIOUtils::contains("URIResolver", $origuris[0])) ) { // The first URI is the URI Resolver one, which always is there
 436+ foreach ( $origuris as $origuri ) {
 437+ $uri = $this->m_store->getURIForOrigURI( $origuri );
 438+ if ( $uri != '' ) {
 439+ // Replace original uri:s into SMW:s internal URIs
 440+ // (The "http://.../Special:URIResolver/..." ones)
 441+ $query = str_replace( $origuri, $uri, $this->m_query );
 442+ }
 443+ }
 444+ $this->setQueryInPost( $query );
 445+ }
 446+ }
 447+
 448+ /**
 449+ * For each URI in the (unparsed) query that is set by an "Equivalent URI" property in
 450+ * the wiki, replace it with the page's corresponding URI Resolver URI
 451+ */
 452+ function convertEquivURIsToInternalURIsInQuery() {
 453+ $equivuris = RDFIOUtils::extractURIs( $this->m_query ); // TODO: Use parsed query instead
 454+ $count = count( $equivuris );
 455+ if ( count( $equivuris ) > 1 ) { // The first URI is the URI Resolver one, which always is there
 456+ // TODO: Create a more robust check
 457+ foreach ( $equivuris as $equivuri ) {
 458+ $uri = $this->m_store->getURIForEquivURI( $equivuri );
 459+ if ( $uri != '' ) {
 460+ // Replace original uri:s into SMW:s internal URIs
 461+ // (The "http://.../Special:URIResolver/..." ones)
 462+ $query = str_replace( $equivuri, $uri, $this->m_query );
 463+ }
 464+ }
 465+ $this->setQueryInPost( $query );
 466+ }
 467+ }
 468+
 469+ /**
 470+ * Convert all URI Resolver URIs which have a corresponding Original URI,
 471+ * to that Original URI.
 472+ * @param array $triples
 473+ * @return array $triples
 474+ */
 475+ function convertURIsToOrigURIsInTriples( $triples ) {
 476+ $variables = array( 's', 'p', 'o' );
 477+ foreach ( $triples as $tripleid => $triple ) {
 478+ foreach ( $variables as $variableid => $variable ) {
 479+ $tripletypestr = $variable . "_type";
 480+ $type = $triple[$tripletypestr];
 481+ if ( $type === "uri" ) {
 482+ $uri = $triple[$variable];
 483+ $origuri = $this->m_store->getOrigURIForURI( $uri );
 484+ if ( $origuri != '' ) {
 485+ $triples[$tripleid][$variable] = $origuri;
 486+ }
 487+ }
 488+ }
 489+ }
 490+ return $triples;
 491+ }
 492+
 493+ /**
 494+ * Convert all URI Resolver URIs which have a corresponding Original URI,
 495+ * to that Original URI.
 496+ * @param array $triples
 497+ * @return array $triples
 498+ */
 499+ function convertURIsToOrigURIsInSPARQLResultSet( $output_structure ) {
 500+ $variables = $output_structure['result']['variables'];
 501+ $rows = $output_structure['result']['rows'];
 502+ # $predvarname = $this->getPredicateVariableName();
 503+ foreach ( $rows as $rowid => $row ) {
 504+ foreach ( $variables as $variable ) {
 505+ $typekey = "$variable type";
 506+ $type = $row[$typekey];
 507+ if ( $type === 'uri' ) {
 508+ $uri = $row[$variable];
 509+ $origuri = $this->m_store->getOrigURIForURI( $uri );
 510+ if ( $origuri != '' ) {
 511+ $output_structure['result']['rows'][$rowid][$variable] = $origuri;
 512+ }
 513+ }
 514+ }
 515+ }
 516+ return $output_structure;
 517+ }
 518+
 519+ /**
 520+ * For all property URIs, add triples using equivalent uris for the,
 521+ * current property uri
 522+ * @param array $triples
 523+ * @return array $triples
 524+ */
 525+ function addEquivUrisForProperties( $triples ) {
 526+ $variables = array( 's', 'p', 'o' );
 527+ $newtriples = array();
 528+ foreach ( $triples as $tripleid => $triple ) {
 529+ $propertyuri = $triple['p'];
 530+ $equivuris = $this->m_store->getEquivURIsForURI( $propertyuri, true );
 531+ foreach ( $equivuris as $equivuri ) {
 532+ $newtriple = array(
 533+ 's' => $triple['s'],
 534+ 'p' => $equivuri,
 535+ 'o' => $triple['o']
 536+ );
 537+ $newtriples[] = $newtriple;
 538+ }
 539+ }
 540+ $triples = array_merge( $triples, $newtriples );
 541+ return $triples;
 542+ }
 543+
 544+ /**
 545+ * For all property URIs and all subject and objects which have URIs,
 546+ * add triples using equivalent uris for these URIs (in all combinations
 547+ * thereof). If $p_uris_filter is set, allow only triples with properties
 548+ * included in this filter array
 549+ * @param array $triples
 550+ * @param array $p_uris_filter
 551+ * @return array $triples
 552+ */
 553+ function complementTriplesWithEquivURIs( $triples, $p_uris_filter = '' ) {
 554+ $variables = array( 's', 'p', 'o' );
 555+ $newtriples = array();
 556+ foreach ( $triples as $tripleid => $triple ) {
 557+ // Subject
 558+ $s_equivuris = array( $triple['s'] );
 559+ if ( $triple['s_type'] === 'uri' ) {
 560+ $s_uri = $triple['s'];
 561+ $s_equivuris_temp = $this->m_store->getEquivURIsForURI( $s_uri );
 562+ if ( count( $s_equivuris_temp ) > 0 ) {
 563+ $s_equivuris = $s_equivuris_temp;
 564+ }
 565+ }
 566+
 567+ // Property
 568+ $propertyuri = $triple['p'];
 569+ $p_equivuris = array( $triple['p'] );
 570+ $p_equivuris_temp = $this->m_store->getEquivURIsForURI( $propertyuri, true );
 571+ if ( count( $p_equivuris_temp ) > 0 ) {
 572+ if ( $p_uris_filter != '' ) {
 573+ // Only include URIs that occur in the filter
 574+ $p_equivuris_temp = array_intersect( $p_equivuris_temp, $p_uris_filter );
 575+ }
 576+ if ( $p_equivuris_temp != '' ) {
 577+ $p_equivuris = $p_equivuris_temp;
 578+ }
 579+ }
 580+
 581+ // Object
 582+ $o_equivuris = array( $triple['o'] );
 583+ if ( $triple['o_type'] === 'uri' ) {
 584+ $o_uri = $triple['o'];
 585+ $o_equivuris_temp = $this->m_store->getEquivURIsForURI( $o_uri );
 586+ if ( count( $o_equivuris_temp ) > 0 ) {
 587+ $o_equivuris = $o_equivuris_temp;
 588+ }
 589+ }
 590+
 591+ // Generate triples
 592+ foreach ( $s_equivuris as $s_equivuri ) {
 593+ foreach ( $p_equivuris as $p_equivuri ) {
 594+ foreach ( $o_equivuris as $o_equivuri ) {
 595+ $newtriple = array(
 596+ 's' => $s_equivuri,
 597+ 'p' => $p_equivuri,
 598+ 'o' => $o_equivuri
 599+ );
 600+ $newtriples[] = $newtriple;
 601+ }
 602+ }
 603+ }
 604+ }
 605+ return $newtriples;
 606+ }
 607+
 608+ function complementSPARQLResultRowsWithEquivURIs( $output_structure, $p_uris_filter = '' ) {
 609+ $predvarname = $this->getPredicateVariableName();
 610+ $variables = $output_structure['result']['variables'];
 611+ $rows = $output_structure['result']['rows'];
 612+
 613+ $predvarname = 'p'; // TODO DO a real check up
 614+ $newrows_total = array();
 615+ foreach ( $rows as $rowid => $row ) {
 616+ $newrows = array();
 617+ foreach ( $variables as $variable ) {
 618+ $typekey = "$variable type";
 619+ $type = $row[$typekey];
 620+ $uri = $row[$variable];
 621+ $equivuris = array();
 622+ if ( $type === 'uri' ) {
 623+ $equivuris = $this->m_store->getEquivURIsForURI( $uri );
 624+ if ( $variable == $predvarname ) {
 625+ $equivuris = array_intersect( $equivuris, $p_uris_filter );
 626+ }
 627+ }
 628+ if ( count( $newrows ) < 1 ) {
 629+ if ( count( $equivuris ) > 0 ) {
 630+ foreach ( $equivuris as $equivuri ) {
 631+ $newrows[] = array( $variable => $equivuri, $typekey => 'uri' );
 632+ }
 633+ } else {
 634+ $newrows[] = array( $variable => $uri, $typekey => 'uri' );
 635+ }
 636+ } else {
 637+ foreach ( $newrows as $newrowid => $newrow ) {
 638+ if ( count( $equivuris ) > 0 ) {
 639+ foreach ( $equivuris as $equivuri ) {
 640+ $newrowcontent = array( $variable => $equivuri, $typekey => 'uri' );
 641+ $newrows[$newrowid] = array_merge( $newrow, $newrowcontent );
 642+ }
 643+ } else {
 644+ $newrowcontent = array( $variable => $uri, $typekey => 'uri' );
 645+ $newrows[$newrowid] = array_merge( $newrow, $newrowcontent );
 646+ }
 647+ }
 648+ }
 649+ }
 650+ $newrows_total = array_merge( $newrows_total, $newrows );
 651+ }
 652+ $output_structure['result']['rows'] = $newrows_total;
 653+ return $output_structure;
 654+ }
 655+
 656+ /**
 657+ * Convert an ARC triple index array structure into RDF/XML
 658+ * @param array $tripleindex
 659+ * @return string $rdfxml
 660+ */
 661+ function tripleIndexToRDFXML( $tripleindex ) {
 662+ $ser = ARC2::getRDFXMLSerializer(); // TODO: Choose format depending on user choice
 663+ // Serialize into RDF/XML, since it will contain
 664+ // all URIs in un-abbreviated form, so that they
 665+ // can easily be replaced by search-and-replace
 666+ $rdfxml = $ser->getSerializedIndex( $tripleindex );
 667+ if ( $ser->getErrors() ) {
 668+ die( "ARC Serializer Error: " . $ser->getErrors() );
 669+ }
 670+ return $rdfxml;
 671+ }
 672+
 673+ /**
 674+ * Convert an ARC triples array into RDF/XML
 675+ * @param array $triples
 676+ * @return string $rdfxml
 677+ */
 678+ function triplesToRDFXML( $triples ) {
 679+ $ser = ARC2::getRDFXMLSerializer(); // TODO: Choose format depending on user choice
 680+ // Serialize into RDF/XML, since it will contain
 681+ // all URIs in un-abbreviated form, so that they
 682+ // can easily be replaced by search-and-replace
 683+ $rdfxml = $ser->getSerializedTriples( $triples );
 684+ if ( $ser->getErrors() ) {
 685+ die( "ARC Serializer Error: " . $ser->getErrors() );
 686+ }
 687+ return $rdfxml;
 688+ }
 689+
 690+ /**
 691+ * Convert all URI Resolver URIs which have a corresponding Original URI,
 692+ * to that Original URI.
 693+ * @param string $text
 694+ * @return string $text
 695+ */
 696+ function convertURIsToOrigURIsInText( $text ) {
 697+ $uris = RDFIOUtils::extractURIs( $text );
 698+ if ( $uris != '' ) {
 699+ foreach ( $uris as $uri ) {
 700+ $origuri = $this->m_store->getOrigURIForURI( $uri );
 701+ if ( $origuri != '' ) {
 702+ $text = str_replace( $uri, $origuri, $text );
 703+ }
 704+ }
 705+ }
 706+ return $text;
 707+ }
 708+
 709+ function getPredicateVariableName() {
 710+ $predvarname = $this->m_query_parsed['vars'][1];
 711+ return $predvarname;
 712+ }
 713+
 714+ /**
 715+ * Get a configuration array for initializing the ARCs
 716+ * SPARQL endpoint
 717+ */
 718+ private function getSPARQLEndpointConfig() {
 719+ global $wgDBserver, $wgDBname, $wgDBuser, $wgDBpassword, $smwgARC2StoreConfig;
 720+ $epconfig = array(
 721+ 'db_host' => $wgDBserver, /* optional, default is localhost */
 722+ 'db_name' => $wgDBname,
 723+ 'db_user' => $wgDBuser,
 724+ 'db_pwd' => $wgDBpassword,
 725+ 'store_name' => $smwgARC2StoreConfig['store_name'],
 726+ 'endpoint_features' =>
 727+ array(
 728+ 'select',
 729+ 'construct',
 730+ 'ask',
 731+ 'describe',
 732+ # 'load',
 733+ # 'insert', // This is not needed, since it is done via SMWWriter instead
 734+ # 'delete', // This is not needed, since it is done via SMWWriter instead
 735+ # 'dump' /* dump is a special command for streaming SPOG export */
 736+ ),
 737+ 'endpoint_timeout' => 60, /* not implemented in ARC2 preview */
 738+ # 'endpoint_read_key' => '', /* optional */
 739+ # 'endpoint_write_key' => 'somekey', /* optional */
 740+ # 'endpoint_max_limit' => 250, /* optional */
 741+ );
 742+ return $epconfig;
 743+ }
 744+
 745+ /**
 746+ * Set headers appropriate to the filetype specified in $outputtype
 747+ * @param string $outputtype
 748+ */
 749+ private function sendHeadersForOutputType( $outputtype ) {
 750+ global $wgRequest;
 751+ // Provide a sane filename suggestion
 752+ $basefilename = 'SPARQLOutput_';
 753+ switch( $outputtype )
 754+ {
 755+ case 'xml':
 756+ $wgRequest->response()->header( "Content-type: application/xml; charset=utf-8" );
 757+ $filename = urlencode( $basefilename . wfTimestampNow() . '.xml' );
 758+ $wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" );
 759+ break;
 760+ case 'rdfxml':
 761+ $wgRequest->response()->header( "Content-type: application/xml; charset=utf-8" );
 762+ $filename = urlencode( $basefilename . wfTimestampNow() . '.rdf.xml' );
 763+ $wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" );
 764+ break;
 765+ case 'json':
 766+ $wgRequest->response()->header( "Content-type: text/html; charset=utf-8" );
 767+ $filename = urlencode( $basefilename . wfTimestampNow() . '.json.txt' );
 768+ $wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" );
 769+ break;
 770+ case 'turtle':
 771+ $wgRequest->response()->header( "Content-type: text/html; charset=utf-8" );
 772+ $filename = urlencode( $basefilename . wfTimestampNow() . '.turtle.txt' );
 773+ $wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" );
 774+ break;
 775+ case 'htmltab':
 776+ // For HTML table we are taking care of the output earlier
 777+ # $wgRequest->response()->header( "Content-type: text/html; charset=utf-8" );
 778+ # $filename = urlencode( $basefilename . wfTimestampNow() . '.html' );
 779+ break;
 780+ case 'tsv':
 781+ $wgRequest->response()->header( "Content-type: text/html; charset=utf-8" );
 782+ $filename = urlencode( $basefilename . wfTimestampNow() . '.tsv.txt' );
 783+ $wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" );
 784+ break;
 785+ default:
 786+ $wgRequest->response()->header( "Content-type: application/xml; charset=utf-8" );
 787+ $filename = urlencode( $basefilename . wfTimestampNow() . '.xml' );
 788+ $wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" );
 789+ }
 790+
 791+ }
 792+
 793+ /**
 794+ * Get the HTML for the main SPARQL querying form. If $query is set, use it to prefill the main textarea
 795+ * @param string $query
 796+ * @return string $htmlForm
 797+ */
 798+ private function getHTMLForm( $query = '') {
 799+ global $wgArticlePath, $wgUser, $wgRequest;
 800+
 801+ $uriResolverURI = $this->m_store->getURIResolverURI();
 802+
 803+ $defaultQuery = "@PREFIX w : <$uriResolverURI> .\n\nSELECT ?s ?p ?o\nWHERE { ?s ?p ?o }\nLIMIT 25";
 804+
 805+ if ( $query == '' ) {
 806+ $query = $defaultQuery;
 807+ }
 808+
 809+ $checked_origuri_q = $wgRequest->getBool( 'origuri_q', false ) == 1 ? ' checked="true" ' : '';
 810+ $checked_origuri_o = $wgRequest->getBool( 'origuri_o', false ) == 1 ? ' checked="true" ' : '';
 811+ $checked_equivuri_q = $wgRequest->getBool( 'equivuri_q', false ) == 1 ? ' checked="true" ' : '';
 812+ $checked_equivuri_o = $wgRequest->getBool( 'equivuri_o', false ) == 1 ? ' checked="true" ' : '';
 813+ $checked_filtervocab = $wgRequest->getBool( 'filtervocab', false ) == 1 ? ' checked="true" ' : '';
 814+ $checked_allowwrite = $wgRequest->getBool( 'allowwrite', false ) == 1 ? ' checked="true" ' : '';
 815+ $checked_showquery = $wgRequest->getBool( 'showquery', false ) == 1 ? ' checked="true" ' : '';
 816+
 817+ $selected_output_html = $wgRequest->getText( 'output', '' ) == 'htmltab' ? ' selected="selected" ' : '';
 818+ $selected_output_rdfxml = $wgRequest->getText( 'output', '' ) == 'rdfxml' ? ' selected="selected" ' : '';
 819+
 820+ // Make the HTML format selected by default
 821+ if ( $selected_output_rdfxml == '' ) {
 822+ $selected_output_html = ' selected="selected" ';
 823+ }
 824+
 825+ $htmlForm = '<form method="post" action="' . str_replace('/$1', '', $wgArticlePath) . '/Special:SPARQLEndpoint"
 826+ name="createEditQuery">
 827+ <div style="font-size: 10px">
 828+
 829+ <table border="0"><tbody>
 830+ <tr><td colspan="3">Enter SPARQL query:</td><tr>
 831+ <tr><td colspan="3"><textarea cols="80" rows="9" name="query">' . $query . '</textarea></td></tr>
 832+ <tr>
 833+ <td style="vertical-align: top; border-right: 1px solid #ccc;">
 834+
 835+ <table border="0" style="background: transparent; font-size: 11px;">
 836+ <tr><td width="160" style="text-align: right">Query by original URIs:</td>
 837+ <td>
 838+ <input type="checkbox" name="origuri_q" value="1" ' . $checked_origuri_q . '/>
 839+ </td></tr>
 840+ <tr><td style="text-align: right">Query by Equivalent URIs:</td>
 841+ <td>
 842+ <input type="checkbox" name="equivuri_q" value="1" ' . $checked_equivuri_q . '/>
 843+ </td></tr>
 844+ </table>
 845+
 846+ </td>
 847+ <td width="170" style="vertical-align: top; border-right: 1px solid #ccc;">
 848+
 849+ <table border="0" style="font-size: 11px; background: transparent;">
 850+ <tr><td style="text-align: right">Output original URIs:</td>
 851+ <td>
 852+ <input type="checkbox" name="origuri_o" value="1" ' . $checked_origuri_o . '/>
 853+ </td></tr>
 854+ <tr><td style="text-align: right">Output Equivalent URIs:</td>
 855+ <td>
 856+ <input type="checkbox" name="equivuri_o" id="outputequivuri" value="1" ' . $checked_equivuri_o . ' onChange="toggleDisplay(\'byontology\');" />
 857+ </td></tr>
 858+ </table>
 859+
 860+ </td>
 861+ <td width="260" style="vertical-align: top;">
 862+
 863+ <table border="0" style="font-size: 11px; background: transparent;" >
 864+ <tr><td style="text-align: right" width="180">Output format:</td>
 865+ <td style="vertical-align: top">
 866+ <select id="output" name="output" onChange="toggleDisplay(\'byontology\');" >
 867+ <!-- <option value="" >default</option> -->
 868+ <!-- <option value="json" >JSON</option> -->
 869+ <!-- <option value="plain" >Plain</option> -->
 870+ <!-- <option value="php_ser" >Serialized PHP</option> -->
 871+ <!-- <option value="turtle" >Turtle</option> -->
 872+ <option value="htmltab" ' . $selected_output_html . '>HTML</option>
 873+ <option value="xml" >XML Resultset</option>
 874+ <option value="rdfxml" ' . $selected_output_rdfxml . '>RDF/XML</option>
 875+ <!-- <option value="infos" >Query Structure</option> -->
 876+ <!-- <option value="tsv" >TSV</option> -->
 877+ </select>
 878+ </td></tr>
 879+ <tr>
 880+ <td colspan="2">
 881+ <span style="font-family: arial, helvetica, sans-serif; font-size: 10px; color: #777;">(RDF/XML requires creating triples using <a href="http://www.w3.org/TR/rdf-sparql-query/#construct">CONSTRUCT</a>)</span>
 882+ </td>
 883+ </table>
 884+
 885+ </td>
 886+ </tr>
 887+ <tr>
 888+ <td colspan="3">
 889+
 890+ <div id="byontology" style="display: none; background: #ffd; border: 1px solid #ee7;">
 891+ <table border="0" style="font-size: 11px; background: transparent;" >
 892+ <tr><td style="text-align: right;">Filter by vocabulary:</td>
 893+ <td>
 894+ <input type="checkbox" name="filtervocab" value="1" ' . $checked_filtervocab . '/>
 895+ </td>
 896+ <td style="text-align: right">Vocabulary URL:</td>
 897+ <td>
 898+ <input type="text" name="filtervocaburl" size="48" />
 899+ </td></tr>
 900+ <tr>
 901+ <td>&nbsp;</td>
 902+ <td>&nbsp;</td>
 903+ <td>&nbsp;</td>
 904+ <td>
 905+ <span style="font-family: arial, helvetica, sans-serif; font-size: 10px; color: #777">Example: http://xmlns.com/foaf/spec/index.rdf</span>
 906+ </td></tr>
 907+ </table>
 908+ </div>
 909+
 910+ </td>
 911+ </table>
 912+ </div>
 913+
 914+ <input type="submit" value="Submit">' . Xml::hidden( 'token', $wgUser->editToken() ) . '
 915+ </form>';
 916+ return $htmlForm;
 917+ }
 918+
 919+ /**
 920+ * Get the javascript used for some functionality in the main SPARQL
 921+ * querying HTML form
 922+ * @return string $htmlFormScript
 923+ */
 924+ private function getHTMLFormScript() {
 925+ $htmlFormScript = "<script type=\"text/javascript\">
 926+ function toggleDisplay(id1) {
 927+ var bostyle = document.getElementById(id1).style.display;
 928+ var fmtsel = document.getElementById('output');
 929+ var fmt = fmtsel.options[fmtsel.selectedIndex].value;
 930+ var outsel = document.getElementById('outputequivuri');
 931+ if ( outsel.checked && fmt.match('rdfxml') ) {
 932+ document.getElementById(id1).style.display = 'block';
 933+ } else {
 934+ document.getElementById(id1).style.display = 'none';
 935+ }
 936+ }
 937+ </script>";
 938+ return $htmlFormScript;
 939+ }
 940+
 941+ /**
 942+ * Get the query parameter from the request object
 943+ * @return string $query
 944+ */
 945+ function getQuery() {
 946+ $query = $wgRequest->getText('query');
 947+ return $query;
 948+ }
 949+
 950+ /**
 951+ * Update the query variable in the $_POST object.
 952+ * Useful for passing on parsing to ARC, since $_POST is what ARC reads
 953+ * @param string $query
 954+ */
 955+ function setQueryInPost( $query ) {
 956+ // Set the query in $_POST, so that ARC will grab the modified query
 957+ $_POST['query'] = $query;
 958+ }
 959+
 960+ /**
 961+ * Update the output (type) variable in the $_POST object.
 962+ * Useful for passing on parsing to ARC, since $_POST is what ARC reads
 963+ * @param string $type
 964+ */
 965+ function setOutputTypeInPost( $type ) {
 966+ $_POST['output'] = $type;
 967+ }
 968+}
Property changes on: trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint_body.php
___________________________________________________________________
Added: svn:eol-style
1969 + native
Index: trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint.i18n.php
@@ -0,0 +1,8 @@
 2+<?php
 3+$messages = array();
 4+
 5+$messages['en'] = array(
 6+ 'sparqlendpoint' => 'SPARQL Endpoint',
 7+ 'sparqlendpoint-desc' => 'A SPARQLEndpoint provided by the SMWRDFConnector',
 8+);
 9+
Property changes on: trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint.i18n.php
___________________________________________________________________
Added: svn:eol-style
110 + native
Index: trunk/extensions/RDFIO/specials/SpecialRDFImport_body.php
@@ -0,0 +1,300 @@
 2+<?php
 3+class RDFImport extends SpecialPage {
 4+
 5+ protected $m_action;
 6+ protected $m_dataformat;
 7+ protected $m_importdata;
 8+ protected $m_edittoken;
 9+ protected $m_smwbatchwriter;
 10+ protected $m_haswriteaccess;
 11+ protected $m_nsprefix_in_wikititles_properties;
 12+ protected $m_nsprefix_in_wikititles_entities;
 13+ protected $m_show_abbrscreen_properties;
 14+ protected $m_show_abbrscreen_entities;
 15+
 16+ function __construct() {
 17+ global $wgUser;
 18+
 19+ $userrights = $wgUser->getRights();
 20+ if ( in_array( 'edit', $userrights ) && in_array( 'createpage', $userrights ) ) {
 21+ $this->m_haswriteaccess = true;
 22+ } else {
 23+ $this->m_haswriteaccess = false;
 24+ }
 25+ parent::__construct( 'RDFImport' );
 26+ wfLoadExtensionMessages('RDFImport');
 27+ }
 28+
 29+ function execute( $par ) {
 30+ global $wgRequest, $wgOut, $wgUser, $wgDBserver, $wgDBname, $wgDBuser, $wgDBpassword, $wgEnableWriteAPI, $wgArticlePath;
 31+
 32+ $this->setHeaders();
 33+ $this->handleRequestData();
 34+
 35+ if ( $this->m_action == 'Import' ) {
 36+ if ( !$wgUser->matchEditToken( $this->m_edittoken ) ) {
 37+ die( 'Cross-site request forgery detected!' );
 38+ } else if ( !$this->m_haswriteaccess ) {
 39+ $errortitle = "Permission error";
 40+ $errormessage = "The current user lacks access either to edit or create pages (or both) in this wiki.";
 41+ $wgOut->addHTML( RDFIOUtils::formatErrorHTML( $errortitle, $errormessage ) );
 42+ $this->outputHTMLForm();
 43+ } else {
 44+ $this->initSMWBatchWriter();
 45+ $existunabbrpropertyuris = $this->m_smwbatchwriter->checkForNamespacesWithoutPrefix();
 46+ $abbreviateuriscreen = '';
 47+ $unabbrentityurilist = '';
 48+ if ( $existunabbrpropertyuris && $this->m_show_abbrscreen_properties ) {
 49+ $suggestedbaseuris = $this->m_smwbatchwriter->getNamespacesWithoutPrefix();
 50+ $abbreviateuriscreen = $this->generateURIAbbreviationScreen( $suggestedbaseuris );
 51+ $showscreensonly = true;
 52+ }
 53+ if ( $this->m_show_abbrscreen_entities ) {
 54+ $unabbrentityuris = $this->m_smwbatchwriter->getUnabbrEntityURIs();
 55+ $unabbrentityurilist = $this->generateUnabbrEntityList( $unabbrentityuris );
 56+ $showscreensonly = true;
 57+ }
 58+ if ( $showscreensonly ) {
 59+ $contentbeforehtmlform = $abbreviateuriscreen . "\n" . $unabbrentityurilist;
 60+ $wgOut->addHTML( $this->getHTMLFormContent( $contentbeforehtmlform ) );
 61+ } else {
 62+ $this->executeSMWBatchWriter();
 63+ }
 64+ }
 65+ } else if ( $this->m_action == 'AddNsPrefixes' ) {
 66+ $this->addNewNsPrefixes();
 67+ $this->executeSMWBatchWriter();
 68+ } else {
 69+ $this->outputHTMLForm();
 70+ }
 71+ }
 72+
 73+ /**
 74+ * Get data from the request object and store it in class variables
 75+ */
 76+ function handleRequestData() {
 77+ global $wgRequest;
 78+ $this->m_action = $wgRequest->getText('action');
 79+ $this->m_dataformat = $wgRequest->getText('dataformat');
 80+ $this->m_importdata = $wgRequest->getText('importdata');
 81+ $this->m_edittoken = $wgRequest->getText( 'token' );
 82+ $this->m_nsprefix_in_wikititles_properties = $wgRequest->getBool( 'nspintitle_prop', false );
 83+ $this->m_show_abbrscreen_properties = $wgRequest->getBool( 'abbrscr_prop', false );
 84+ $this->m_nsprefix_in_wikititles_entities = $wgRequest->getBool( 'nspintitle_ent', false );
 85+ $this->m_show_abbrscreen_entities = $wgRequest->getBool( 'abbrscr_ent', false );
 86+ }
 87+
 88+ /**
 89+ * Create a new SMWBatchWriter object, store it in a class variable, and
 90+ * set some options, like which ns prefixes to use.
 91+ */
 92+ function initSMWBatchWriter() {
 93+ $this->m_smwbatchwriter = new RDFIOSMWBatchWriter( $this->m_importdata, $this->m_dataformat );
 94+ $this->m_smwbatchwriter->setUseNSPInTitlesForProperties( $this->m_nsprefix_in_wikititles_properties );
 95+ $this->m_smwbatchwriter->setUseNSPInTitlesForEntities( $this->m_nsprefix_in_wikititles_entities );
 96+ }
 97+
 98+ /**
 99+ * Tell the SMWBatchWriter object to execute the import
 100+ */
 101+ function executeSMWBatchWriter() {
 102+ global $wgOut;
 103+ $this->m_smwbatchwriter->execute();
 104+ $wgOut->addScript( $this->getExampleDataJs() );
 105+ $wgOut->addHTML( $this->getHTMLFormContent() );
 106+ }
 107+
 108+ /**
 109+ * Add more namespace prefixes in the configured namespace mapping
 110+ */
 111+ function addNewNsPrefixes() {
 112+ $nss = $wgRequest->getArray('ns',array());
 113+ $nsprefixes = $wgRequest->getArray('nsprefixes',array());
 114+ $newnsmappings = array();
 115+ $nsid = 0;
 116+ foreach ( $nss as $ns ) {
 117+ $nsprefix = $nsprefixes[$nsid];
 118+ $newnsmappings[$ns] = $nsprefix;
 119+ $nsid++;
 120+ }
 121+ $this->initSMWBatchWriter();
 122+ $this->m_smwbatchwriter->AddNamespacePrefixes( $newnsmappings );
 123+ }
 124+
 125+ /**
 126+ * Output the HTML for the form, to the user
 127+ */
 128+ function outputHTMLForm() {
 129+ global $wgOut;
 130+ $wgOut->addScript( $this->getExampleDataJs() );
 131+ $wgOut->addHTML( $this->getHTMLFormContent() );
 132+ }
 133+
 134+ /**
 135+ * For a number of base uri:s, generate the HTML for a screen for
 136+ * configuring abbreviation for them
 137+ * @param array $baseuris
 138+ */
 139+ public function generateURIAbbreviationScreen( $baseuris ) {
 140+ global $wgArticlePath;
 141+ $baseuriscreen = "<fieldset><label><b>Choose Prefix for unabbreviated property namespaces:</b></label>
 142+ <table class=\"wikitable\">";
 143+ $fieldid = 0;
 144+ foreach ( $baseuris as $baseuri ) {
 145+ $baseuriscreen .= "\n<tr><td style=\"color:#777\">$baseuri<input type=\"hidden\" name=\"ns[$fieldid]\" value=\"$baseuri\" /></input></td>
 146+ <td><input type=\"text\" name=\"nsprefixes[$fieldid]\" size=\"7\" /></td>
 147+ </tr>\n";
 148+ $fieldid++;
 149+ }
 150+ $baseuriscreen .= "</table>
 151+ <input type=\"hidden\" name=\"action\" value=\"AddNsPrefixes\">
 152+ <p><span style=\"font-size: 11px\"><b>Note:</b> These abbreviations will not be used if, for a property, there already exists a wiki article with the same uri set as \"Original URI\".</span></p>
 153+ </fieldset>
 154+ ";
 155+ return $baseuriscreen;
 156+ }
 157+
 158+ /**
 159+ * For an array of unabbreviated entities, generate HTML for a
 160+ * formatted list of these entities' URIs
 161+ * @param array $unabbrentities
 162+ * @return array $unabbrentitylist
 163+ */
 164+ public function generateUnabbrEntityList( $unabbrentities ) {
 165+ global $wgArticlePath;
 166+ $unabbrentitylist = "<fieldset><label><b>Entity (i.e: non-property) URIs lacking namespace prefix</b></label>
 167+ <table class=\"wikitable\">";
 168+ $rowdid = 0;
 169+ foreach ( $unabbrentities as $unabbrentity ) {
 170+ $unabbrentitylist .= "\n<tr><td style=\"color:#777\">$unabbrentity</td></tr>\n";
 171+ $fieldid++;
 172+ }
 173+ $unabbrentitylist .= "</table>
 174+ <p><span style=\"font-size: 11px\"><b>Hint:</b> Namespace prefix configuration can be added as an attribute in in the RDF tag below according to the following syntax: <code>xmlns:[prefix]=\"[namespace-uri]\"</code></span></p>
 175+ </fieldset>";
 176+ return $unabbrentitylist;
 177+ }
 178+
 179+ /**
 180+ * Get RDF/XML stub for for the import form, including namespace definitions
 181+ * @return string
 182+ */
 183+ public function getExampleRDFXMLData() {
 184+ return '<rdf:RDF\\n\
 185+ xmlns:rdfs=\\"http://www.w3.org/2000/01/rdf-schema#\\"\\n\
 186+ xmlns:rdf=\\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\\"\\n\
 187+ xmlns:n0pred=\\"http://bio2rdf.org/go_resource:\\"\\n\
 188+ xmlns:ns0pred=\\"http://www.w3.org/2002/07/owl#\\">\\n\
 189+ \\n\
 190+ <rdf:Description rdf:about=\\"http://bio2rdf.org/go:0032283\\">\\n\
 191+ <n0pred:accession>GO:0032283</n0pred:accession>\\n\
 192+ <rdfs:label>plastid acetate CoA-transferase complex [go:0032283]</rdfs:label>\\n\
 193+ <n0pred:definition>An acetate CoA-transferase complex located in the stroma of a plastid.</n0pred:definition>\\n\
 194+ <rdf:type rdf:resource=\\"http://bio2rdf.org/go_resource:term\\"/>\\n\
 195+ <n0pred:name>plastid acetate CoA-transferase complex</n0pred:name>\\n\
 196+ <n0pred:is_a rdf:resource=\\"http://bio2rdf.org/go:0009329\\"/>\\n\
 197+ <rdf:type rdf:resource=\\"http://bio2rdf.org/go_resource:Term\\"/>\\n\
 198+ <urlImage xmlns=\\"http://bio2rdf.org/bio2rdf_resource:\\">http://bio2rdf.org/image/go:0032283</urlImage>\\n\
 199+ <xmlUrl xmlns=\\"http://bio2rdf.org/bio2rdf_resource:\\">http://bio2rdf.org/xml/go:0032283</xmlUrl>\\n\
 200+ <rights xmlns=\\"http://purl.org/dc/terms/\\" rdf:resource=\\"http://www.geneontology.org/GO.cite.shtml\\"/>\\n\
 201+ <ns0pred:sameAs rdf:resource=\\"http://purl.org/obo/owl/GO#GO_0032283\\"/>\\n\
 202+ <url xmlns=\\"http://bio2rdf.org/bio2rdf_resource:\\">http://bio2rdf.org/html/go:0032283</url>\\n\
 203+ </rdf:Description>\\n\
 204+ \\n\
 205+ </rdf:RDF>';
 206+ }
 207+
 208+ /**
 209+ * Generate the main HTML form, if the variable $extraFormContent is set, the
 210+ * content of it will be prepended before the form
 211+ * @param string $extraFormContent
 212+ * @return string $htmlFormContent
 213+ */
 214+ public function getHTMLFormContent( $extraFormContent = '' ) {
 215+ global $wgRequest, $wgUser, $wgArticlePath;
 216+
 217+ // Abbreviation (and screen) options for properties
 218+ $checked_nspintitle_properties = $wgRequest->getBool( 'nspintitle_prop', false ) == 1 ? ' checked="true" ' : '';
 219+ $checked_abbrscr_properties = $wgRequest->getBool( 'abbrscr_prop', false ) == 1 ? ' checked="true" ' : '';
 220+
 221+ // Abbreviation (and screen) options for entities
 222+ $checked_nspintitle_entities = $wgRequest->getBool( 'nspintitle_ent', false ) == 1 ? ' checked="true" ' : '';
 223+ $checked_abbrscr_entities = $wgRequest->getBool( 'abbrscr_ent', false ) == 1 ? ' checked="true" ' : '';
 224+
 225+ $this->m_importdata = $wgRequest->getText( 'importdata', '' );
 226+
 227+ // Create the HTML form for RDF/XML Import
 228+ $htmlFormContent = '<form method="post" action="' . str_replace('/$1', '', $wgArticlePath) . '/Special:RDFImport"
 229+ name="createEditQuery"><input type="hidden" name="action" value="Import">
 230+ ' . $extraFormContent . '
 231+ <table border="0"><tbody>
 232+ <tr><td colspan="3">RDF/XML data to import:</td><tr>
 233+ <tr><td colspan="3"><textarea cols="80" rows="9" name="importdata" id="importdata">' . $this->m_importdata . '</textarea>
 234+ </td></tr>
 235+ <tr><td width="100">Data format:</td>
 236+ <td>
 237+ <select id="dataformat" name="dataformat">
 238+ <option value="rdfxml" selected="selected">RDF/XML</option>
 239+ <option value="turtle" >Turtle</option>
 240+ </select>
 241+ </td>
 242+ <td style="text-align: right; font-size: 10px;">
 243+ [<a href="#" onClick="pasteExampleRDFXMLData(\'importdata\');">Paste example data</a>]
 244+ [<a href="#" onClick="document.getElementById(\'importdata\').value = \'\';">Clear</a>]
 245+ </td>
 246+ </tr>
 247+ <tr>
 248+ <td colspan="3">
 249+ <table width="100%" class="wikitable">
 250+ <tr>
 251+ <th style="text-size: 11px">
 252+ Options for properties
 253+ </th>
 254+ <th style="text-size: 11px">
 255+ Options for non-properties
 256+ </th>
 257+ </tr>
 258+ <tr>
 259+ <td style="font-size: 11px">
 260+ <input type="checkbox" name="nspintitle_prop" id="abbrprop" value="1" ' . $checked_nspintitle_properties . ' /> Use namespace prefixes in wiki titles
 261+ </td>
 262+ <td style="font-size: 11px">
 263+ <input type="checkbox" name="nspintitle_ent" id="abbrent" value="1" ' . $checked_nspintitle_entities . ' /> Use namespace prefixes in wiki titles
 264+ </td>
 265+ </tr>
 266+ <tr>
 267+ <td style="font-size: 11px">
 268+ <input type="checkbox" name="abbrscr_prop" id="abbrscrprop" value="1" ' . $checked_abbrscr_properties . ' /> Show abbreviation screen
 269+ </td>
 270+ <td style="font-size: 11px">
 271+ <input type="checkbox" name="abbrscr_ent" id="abbrscrent" value="1" ' . $checked_abbrscr_entities . ' /> Show abbreviation screen
 272+ </td>
 273+ </tr>
 274+ </table>
 275+ </td>
 276+ </tr>
 277+ </tbody></table>
 278+ <input type="submit" value="Submit">' . Xml::hidden( 'token', $wgUser->editToken() ) . '
 279+ </form>';
 280+ return $htmlFormContent;
 281+ }
 282+
 283+ /**
 284+ * Generate the javascriptcode used in the main HTML form for
 285+ * loading example data into the main textarea
 286+ * @return string $exampleDataJs
 287+ */
 288+ public function getExampleDataJs() {
 289+ $exampleDataJs = '
 290+ <script type="text/javascript">
 291+ function pasteExampleRDFXMLData(textFieldId) {
 292+ var textfield = document.getElementById(textFieldId);
 293+ var exampledata = "' . $this->getExampleRDFXMLData() . '";
 294+ textfield.value = exampledata;
 295+ }
 296+ </script>
 297+ ';
 298+ return $exampleDataJs;
 299+ }
 300+
 301+}
Property changes on: trunk/extensions/RDFIO/specials/SpecialRDFImport_body.php
___________________________________________________________________
Added: svn:eol-style
1302 + native
Index: trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint.php
@@ -0,0 +1,25 @@
 2+<?php
 3+# Alert the user that this is not a valid entry point to MediaWiki if they try to access the special pages file directly.
 4+if (!defined('MEDIAWIKI')) {
 5+ echo <<<EOT
 6+To install my extension, put the following line in LocalSettings.php:
 7+require_once( "\$IP/extensions/SMWRDFConnector/SpecialSPARQLEndpoint.php" );
 8+EOT;
 9+ exit( 1 );
 10+}
 11+
 12+$wgExtensionCredits['specialpage'][] = array(
 13+ 'name' => 'SPARQLEndpoint',
 14+ 'author' => 'Samuel Lampa',
 15+ 'url' => 'http://www.mediawiki.org/wiki/Extension:SMWRDFConnector',
 16+ 'description' => 'SPARQL Endpoint',
 17+ 'descriptionmsg' => 'sparqlendpoint-desc',
 18+ 'version' => '0.0.0',
 19+);
 20+
 21+$dir = dirname(__FILE__) . '/';
 22+
 23+$wgAutoloadClasses['SPARQLEndpoint'] = $dir . 'SpecialSPARQLEndpoint_body.php'; # Tell MediaWiki to load the extension body.
 24+$wgExtensionMessagesFiles['SPARQLEndpoint'] = $dir . 'SpecialSPARQLEndpoint.i18n.php';
 25+$wgExtensionAliasesFiles['SPARQLEndpoint'] = $dir . 'SpecialSPARQLEndpoint.alias.php';
 26+$wgSpecialPages['SPARQLEndpoint'] = 'SPARQLEndpoint'; # Let MediaWiki know about your new special page.
Property changes on: trunk/extensions/RDFIO/specials/SpecialSPARQLEndpoint.php
___________________________________________________________________
Added: svn:eol-style
127 + native
Index: trunk/extensions/RDFIO/specials/SpecialRDFImport.i18n.php
@@ -0,0 +1,8 @@
 2+<?php
 3+$messages = array();
 4+
 5+$messages['en'] = array(
 6+ 'rdfimport' => 'RDF Import',
 7+ 'rdfimport-desc' => 'A Special page to import semantic data in RDF/XML format',
 8+);
 9+
Property changes on: trunk/extensions/RDFIO/specials/SpecialRDFImport.i18n.php
___________________________________________________________________
Added: svn:eol-style
110 + native
Index: trunk/extensions/RDFIO/specials/SpecialRDFImport.php
@@ -0,0 +1,25 @@
 2+<?php
 3+# Alert the user that this is not a valid entry point to MediaWiki if they try to access the special pages file directly.
 4+if (!defined('MEDIAWIKI')) {
 5+ echo <<<EOT
 6+To install my extension, put the following line in LocalSettings.php:
 7+require_once( "\$IP/extensions/SMWRDFConnector/SpecialRDFImport.php" );
 8+EOT;
 9+ exit( 1 );
 10+}
 11+
 12+$wgExtensionCredits['specialpage'][] = array(
 13+ 'name' => 'RDFImport',
 14+ 'author' => 'Samuel Lampa',
 15+ 'url' => 'http://www.mediawiki.org/wiki/Extension:SMWRDFConnector',
 16+ 'description' => 'RDF Import',
 17+ 'descriptionmsg' => 'rdfimport-desc',
 18+ 'version' => '0.0.0',
 19+);
 20+
 21+$dir = dirname(__FILE__) . '/';
 22+
 23+$wgAutoloadClasses['RDFImport'] = $dir . 'SpecialRDFImport_body.php'; # Tell MediaWiki to load the extension body.
 24+$wgExtensionMessagesFiles['RDFImport'] = $dir . 'SpecialRDFImport.i18n.php';
 25+$wgExtensionAliasesFiles['RDFImport'] = $dir . 'SpecialRDFImport.alias.php';
 26+$wgSpecialPages['RDFImport'] = 'RDFImport'; # Let MediaWiki know about your new special page.
Property changes on: trunk/extensions/RDFIO/specials/SpecialRDFImport.php
___________________________________________________________________
Added: svn:eol-style
127 + native
Index: trunk/extensions/RDFIO/INSTALL
@@ -0,0 +1,3 @@
 2+For easily readable install instructions, see:
 3+http://www.mediawiki.org/wiki/Extension:RDFIO#Installing_RDFIO
 4+
Index: trunk/extensions/RDFIO/RELEASE-NOTES
@@ -0,0 +1,79 @@
 2+For a documentation of all features, see
 3+http://www.mediawiki.org/wiki/Extension:RDFIO
 4+
 5+(Note: The version numbering below are not consistent with MediaWiki or Semantic
 6+MediaWiki core)
 7+
 8+== RDFIO 0.5.0 ==
 9+
 10+Released on 2010-09-17
 11+
 12+:Summary
 13+;Numerous fixes to make remote SPARQL querying work
 14+
 15+* Improved file hierarchy
 16+* Made querying and output of/querying by Original URIs and Equivalent URIs
 17+ configurable from LocalSettings.php in SPARQL endpoint (So this can be turned on for remote queries too)
 18+* In total five new configurable settings for LocalSettings.php (see
 19+ http://www.mediawiki.org/wiki/Extension:RDFIO#LocalSettings.php_configuration
 20+ for full list):
 21+** $rdfiogQueryByOrigURI = true;
 22+** $rdfiogOutputOrigURIs = true;
 23+** $rdfiogQueryByEquivURI = false;
 24+** $rdfiogOutputEquivURIs = false;
 25+** $rdfiogAllowRemoteEdit = false;
 26+* Lots of serious bug fixes encountered when making SPARQL querying from
 27+ Bioclipse/Jena work
 28+
 29+
 30+== RDFIO 0.4.0 ==
 31+
 32+Released on 2010-08-16
 33+
 34+* Support for configuring extra namespace prefixes in LocalSettings.php
 35+* More options in RDF Import screen
 36+* Output SPARQL resultset as default for remote queries, and HTML for form
 37+ queries
 38+* Enable output as Original URI/Equivalent URI also for XML Resultset output
 39+ format
 40+* Refactorings (Merged EquivalentURIHandler and SMWBatchWriter classes, Broke
 41+ out RDFIOPageHandler in separate file)
 42+* Many bugfixes
 43+
 44+== RDFIO 0.3.0 ==
 45+
 46+Released on 2010-07-30
 47+
 48+:Summary
 49+;Added output filtering options and other improvements.
 50+
 51+* Option to query by Equivalent URI
 52+* Refined SPARQL Endpoint screen
 53+* Option to output all Equivalent URIs (For RDF/XML format only)
 54+* Option to filter properties by ontology (when outputting equivalent URIs) by
 55+ specified an URL to an OWL ontology definition. (For RDF/XML format only).
 56+* Much improved processing of SPARQL queries
 57+* Various refactoring
 58+* Fixed various bugs
 59+** Initialize query variable (r150)
 60+** Don't delete Original URI properties etc when deleting other facts (r151)
 61+** Fixed error in isURL check (r153)
 62+
 63+== RDFIO 0.2.0 ==
 64+
 65+Released on 2010-07-20
 66+
 67+:Summary
 68+;Important security improvements
 69+
 70+* Checking for appropriate user rights on all special pages
 71+* Improved code structure and comments
 72+* Various small fixes
 73+
 74+== RDFIO 0.1.0 ==
 75+
 76+Released on 2010-07-21
 77+
 78+:Summary
 79+;First release
 80+
Index: trunk/extensions/RDFIO/COPYING
@@ -0,0 +1,348 @@
 2+The license text below "----" applies to all files within this distribution, other
 3+than those that are in a directory which contains files named "LICENSE" or
 4+"COPYING", or a subdirectory thereof. For those files, the license text contained in
 5+said file overrides any license information contained in directories of smaller depth.
 6+Alternative licenses are typically used for software that is provided by external
 7+parties, and merely packaged with the SemanticResultFormats release for convenience.
 8+----
 9+
 10+ GNU GENERAL PUBLIC LICENSE
 11+ Version 2, June 1991
 12+
 13+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
 14+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 15+ Everyone is permitted to copy and distribute verbatim copies
 16+ of this license document, but changing it is not allowed.
 17+
 18+ Preamble
 19+
 20+ The licenses for most software are designed to take away your
 21+freedom to share and change it. By contrast, the GNU General Public
 22+License is intended to guarantee your freedom to share and change free
 23+software--to make sure the software is free for all its users. This
 24+General Public License applies to most of the Free Software
 25+Foundation's software and to any other program whose authors commit to
 26+using it. (Some other Free Software Foundation software is covered by
 27+the GNU Library General Public License instead.) You can apply it to
 28+your programs, too.
 29+
 30+ When we speak of free software, we are referring to freedom, not
 31+price. Our General Public Licenses are designed to make sure that you
 32+have the freedom to distribute copies of free software (and charge for
 33+this service if you wish), that you receive source code or can get it
 34+if you want it, that you can change the software or use pieces of it
 35+in new free programs; and that you know you can do these things.
 36+
 37+ To protect your rights, we need to make restrictions that forbid
 38+anyone to deny you these rights or to ask you to surrender the rights.
 39+These restrictions translate to certain responsibilities for you if you
 40+distribute copies of the software, or if you modify it.
 41+
 42+ For example, if you distribute copies of such a program, whether
 43+gratis or for a fee, you must give the recipients all the rights that
 44+you have. You must make sure that they, too, receive or can get the
 45+source code. And you must show them these terms so they know their
 46+rights.
 47+
 48+ We protect your rights with two steps: (1) copyright the software, and
 49+(2) offer you this license which gives you legal permission to copy,
 50+distribute and/or modify the software.
 51+
 52+ Also, for each author's protection and ours, we want to make certain
 53+that everyone understands that there is no warranty for this free
 54+software. If the software is modified by someone else and passed on, we
 55+want its recipients to know that what they have is not the original, so
 56+that any problems introduced by others will not reflect on the original
 57+authors' reputations.
 58+
 59+ Finally, any free program is threatened constantly by software
 60+patents. We wish to avoid the danger that redistributors of a free
 61+program will individually obtain patent licenses, in effect making the
 62+program proprietary. To prevent this, we have made it clear that any
 63+patent must be licensed for everyone's free use or not licensed at all.
 64+
 65+ The precise terms and conditions for copying, distribution and
 66+modification follow.
 67+
 68+ GNU GENERAL PUBLIC LICENSE
 69+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 70+
 71+ 0. This License applies to any program or other work which contains
 72+a notice placed by the copyright holder saying it may be distributed
 73+under the terms of this General Public License. The "Program", below,
 74+refers to any such program or work, and a "work based on the Program"
 75+means either the Program or any derivative work under copyright law:
 76+that is to say, a work containing the Program or a portion of it,
 77+either verbatim or with modifications and/or translated into another
 78+language. (Hereinafter, translation is included without limitation in
 79+the term "modification".) Each licensee is addressed as "you".
 80+
 81+Activities other than copying, distribution and modification are not
 82+covered by this License; they are outside its scope. The act of
 83+running the Program is not restricted, and the output from the Program
 84+is covered only if its contents constitute a work based on the
 85+Program (independent of having been made by running the Program).
 86+Whether that is true depends on what the Program does.
 87+
 88+ 1. You may copy and distribute verbatim copies of the Program's
 89+source code as you receive it, in any medium, provided that you
 90+conspicuously and appropriately publish on each copy an appropriate
 91+copyright notice and disclaimer of warranty; keep intact all the
 92+notices that refer to this License and to the absence of any warranty;
 93+and give any other recipients of the Program a copy of this License
 94+along with the Program.
 95+
 96+You may charge a fee for the physical act of transferring a copy, and
 97+you may at your option offer warranty protection in exchange for a fee.
 98+
 99+ 2. You may modify your copy or copies of the Program or any portion
 100+of it, thus forming a work based on the Program, and copy and
 101+distribute such modifications or work under the terms of Section 1
 102+above, provided that you also meet all of these conditions:
 103+
 104+ a) You must cause the modified files to carry prominent notices
 105+ stating that you changed the files and the date of any change.
 106+
 107+ b) You must cause any work that you distribute or publish, that in
 108+ whole or in part contains or is derived from the Program or any
 109+ part thereof, to be licensed as a whole at no charge to all third
 110+ parties under the terms of this License.
 111+
 112+ c) If the modified program normally reads commands interactively
 113+ when run, you must cause it, when started running for such
 114+ interactive use in the most ordinary way, to print or display an
 115+ announcement including an appropriate copyright notice and a
 116+ notice that there is no warranty (or else, saying that you provide
 117+ a warranty) and that users may redistribute the program under
 118+ these conditions, and telling the user how to view a copy of this
 119+ License. (Exception: if the Program itself is interactive but
 120+ does not normally print such an announcement, your work based on
 121+ the Program is not required to print an announcement.)
 122+
 123+These requirements apply to the modified work as a whole. If
 124+identifiable sections of that work are not derived from the Program,
 125+and can be reasonably considered independent and separate works in
 126+themselves, then this License, and its terms, do not apply to those
 127+sections when you distribute them as separate works. But when you
 128+distribute the same sections as part of a whole which is a work based
 129+on the Program, the distribution of the whole must be on the terms of
 130+this License, whose permissions for other licensees extend to the
 131+entire whole, and thus to each and every part regardless of who wrote it.
 132+
 133+Thus, it is not the intent of this section to claim rights or contest
 134+your rights to work written entirely by you; rather, the intent is to
 135+exercise the right to control the distribution of derivative or
 136+collective works based on the Program.
 137+
 138+In addition, mere aggregation of another work not based on the Program
 139+with the Program (or with a work based on the Program) on a volume of
 140+a storage or distribution medium does not bring the other work under
 141+the scope of this License.
 142+
 143+ 3. You may copy and distribute the Program (or a work based on it,
 144+under Section 2) in object code or executable form under the terms of
 145+Sections 1 and 2 above provided that you also do one of the following:
 146+
 147+ a) Accompany it with the complete corresponding machine-readable
 148+ source code, which must be distributed under the terms of Sections
 149+ 1 and 2 above on a medium customarily used for software interchange; or,
 150+
 151+ b) Accompany it with a written offer, valid for at least three
 152+ years, to give any third party, for a charge no more than your
 153+ cost of physically performing source distribution, a complete
 154+ machine-readable copy of the corresponding source code, to be
 155+ distributed under the terms of Sections 1 and 2 above on a medium
 156+ customarily used for software interchange; or,
 157+
 158+ c) Accompany it with the information you received as to the offer
 159+ to distribute corresponding source code. (This alternative is
 160+ allowed only for noncommercial distribution and only if you
 161+ received the program in object code or executable form with such
 162+ an offer, in accord with Subsection b above.)
 163+
 164+The source code for a work means the preferred form of the work for
 165+making modifications to it. For an executable work, complete source
 166+code means all the source code for all modules it contains, plus any
 167+associated interface definition files, plus the scripts used to
 168+control compilation and installation of the executable. However, as a
 169+special exception, the source code distributed need not include
 170+anything that is normally distributed (in either source or binary
 171+form) with the major components (compiler, kernel, and so on) of the
 172+operating system on which the executable runs, unless that component
 173+itself accompanies the executable.
 174+
 175+If distribution of executable or object code is made by offering
 176+access to copy from a designated place, then offering equivalent
 177+access to copy the source code from the same place counts as
 178+distribution of the source code, even though third parties are not
 179+compelled to copy the source along with the object code.
 180+
 181+ 4. You may not copy, modify, sublicense, or distribute the Program
 182+except as expressly provided under this License. Any attempt
 183+otherwise to copy, modify, sublicense or distribute the Program is
 184+void, and will automatically terminate your rights under this License.
 185+However, parties who have received copies, or rights, from you under
 186+this License will not have their licenses terminated so long as such
 187+parties remain in full compliance.
 188+
 189+ 5. You are not required to accept this License, since you have not
 190+signed it. However, nothing else grants you permission to modify or
 191+distribute the Program or its derivative works. These actions are
 192+prohibited by law if you do not accept this License. Therefore, by
 193+modifying or distributing the Program (or any work based on the
 194+Program), you indicate your acceptance of this License to do so, and
 195+all its terms and conditions for copying, distributing or modifying
 196+the Program or works based on it.
 197+
 198+ 6. Each time you redistribute the Program (or any work based on the
 199+Program), the recipient automatically receives a license from the
 200+original licensor to copy, distribute or modify the Program subject to
 201+these terms and conditions. You may not impose any further
 202+restrictions on the recipients' exercise of the rights granted herein.
 203+You are not responsible for enforcing compliance by third parties to
 204+this License.
 205+
 206+ 7. If, as a consequence of a court judgment or allegation of patent
 207+infringement or for any other reason (not limited to patent issues),
 208+conditions are imposed on you (whether by court order, agreement or
 209+otherwise) that contradict the conditions of this License, they do not
 210+excuse you from the conditions of this License. If you cannot
 211+distribute so as to satisfy simultaneously your obligations under this
 212+License and any other pertinent obligations, then as a consequence you
 213+may not distribute the Program at all. For example, if a patent
 214+license would not permit royalty-free redistribution of the Program by
 215+all those who receive copies directly or indirectly through you, then
 216+the only way you could satisfy both it and this License would be to
 217+refrain entirely from distribution of the Program.
 218+
 219+If any portion of this section is held invalid or unenforceable under
 220+any particular circumstance, the balance of the section is intended to
 221+apply and the section as a whole is intended to apply in other
 222+circumstances.
 223+
 224+It is not the purpose of this section to induce you to infringe any
 225+patents or other property right claims or to contest validity of any
 226+such claims; this section has the sole purpose of protecting the
 227+integrity of the free software distribution system, which is
 228+implemented by public license practices. Many people have made
 229+generous contributions to the wide range of software distributed
 230+through that system in reliance on consistent application of that
 231+system; it is up to the author/donor to decide if he or she is willing
 232+to distribute software through any other system and a licensee cannot
 233+impose that choice.
 234+
 235+This section is intended to make thoroughly clear what is believed to
 236+be a consequence of the rest of this License.
 237+
 238+ 8. If the distribution and/or use of the Program is restricted in
 239+certain countries either by patents or by copyrighted interfaces, the
 240+original copyright holder who places the Program under this License
 241+may add an explicit geographical distribution limitation excluding
 242+those countries, so that distribution is permitted only in or among
 243+countries not thus excluded. In such case, this License incorporates
 244+the limitation as if written in the body of this License.
 245+
 246+ 9. The Free Software Foundation may publish revised and/or new versions
 247+of the General Public License from time to time. Such new versions will
 248+be similar in spirit to the present version, but may differ in detail to
 249+address new problems or concerns.
 250+
 251+Each version is given a distinguishing version number. If the Program
 252+specifies a version number of this License which applies to it and "any
 253+later version", you have the option of following the terms and conditions
 254+either of that version or of any later version published by the Free
 255+Software Foundation. If the Program does not specify a version number of
 256+this License, you may choose any version ever published by the Free Software
 257+Foundation.
 258+
 259+ 10. If you wish to incorporate parts of the Program into other free
 260+programs whose distribution conditions are different, write to the author
 261+to ask for permission. For software which is copyrighted by the Free
 262+Software Foundation, write to the Free Software Foundation; we sometimes
 263+make exceptions for this. Our decision will be guided by the two goals
 264+of preserving the free status of all derivatives of our free software and
 265+of promoting the sharing and reuse of software generally.
 266+
 267+ NO WARRANTY
 268+
 269+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 270+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
 271+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 272+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
 273+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 274+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
 275+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
 276+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 277+REPAIR OR CORRECTION.
 278+
 279+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 280+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 281+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 282+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
 283+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
 284+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
 285+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 286+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 287+POSSIBILITY OF SUCH DAMAGES.
 288+
 289+ END OF TERMS AND CONDITIONS
 290+
 291+ How to Apply These Terms to Your New Programs
 292+
 293+ If you develop a new program, and you want it to be of the greatest
 294+possible use to the public, the best way to achieve this is to make it
 295+free software which everyone can redistribute and change under these terms.
 296+
 297+ To do so, attach the following notices to the program. It is safest
 298+to attach them to the start of each source file to most effectively
 299+convey the exclusion of warranty; and each file should have at least
 300+the "copyright" line and a pointer to where the full notice is found.
 301+
 302+ <one line to give the program's name and a brief idea of what it does.>
 303+ Copyright (C) <year> <name of author>
 304+
 305+ This program is free software; you can redistribute it and/or modify
 306+ it under the terms of the GNU General Public License as published by
 307+ the Free Software Foundation; either version 2 of the License, or
 308+ (at your option) any later version.
 309+
 310+ This program is distributed in the hope that it will be useful,
 311+ but WITHOUT ANY WARRANTY; without even the implied warranty of
 312+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 313+ GNU General Public License for more details.
 314+
 315+ You should have received a copy of the GNU General Public License
 316+ along with this program; if not, write to the Free Software
 317+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 318+
 319+
 320+Also add information on how to contact you by electronic and paper mail.
 321+
 322+If the program is interactive, make it output a short notice like this
 323+when it starts in an interactive mode:
 324+
 325+ Gnomovision version 69, Copyright (C) year name of author
 326+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 327+ This is free software, and you are welcome to redistribute it
 328+ under certain conditions; type `show c' for details.
 329+
 330+The hypothetical commands `show w' and `show c' should show the appropriate
 331+parts of the General Public License. Of course, the commands you use may
 332+be called something other than `show w' and `show c'; they could even be
 333+mouse-clicks or menu items--whatever suits your program.
 334+
 335+You should also get your employer (if you work as a programmer) or your
 336+school, if any, to sign a "copyright disclaimer" for the program, if
 337+necessary. Here is a sample; alter the names:
 338+
 339+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
 340+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
 341+
 342+ <signature of Ty Coon>, 1 April 1989
 343+ Ty Coon, President of Vice
 344+
 345+This General Public License does not permit incorporating your program into
 346+proprietary programs. If your program is a subroutine library, you may
 347+consider it more useful to permit linking proprietary applications with the
 348+library. If this is what you want to do, use the GNU Library General
 349+Public License instead of this License.
Index: trunk/extensions/RDFIO/RDFIO.php
@@ -0,0 +1,68 @@
 2+<?php
 3+
 4+/**
 5+ * Initializing file for SMW RDFIO extension.
 6+ *
 7+ * @file
 8+ * @ingroup RDFIO
 9+ */
 10+if( !defined( 'MEDIAWIKI' ) ) {
 11+ die( 'Not an entry point.' );
 12+}
 13+
 14+define('RDFIO_VERSION', '0.5.0');
 15+
 16+global $wgExtensionCredits;
 17+
 18+$wgExtensionCredits['other'][]= array(
 19+ 'path' => __FILE__,
 20+ 'name' => 'RDFIO',
 21+ 'version' => RDFIO_VERSION,
 22+ 'author' => array( '[http://saml.rilspace.org Samuel Lampa]' ),
 23+ 'url' => 'http://www.mediawiki.org/wiki/Extension:RDFIO',
 24+ 'description' => 'Extended RDF Import/Export functionality, including SPARQL endpoint, for Semantic MediaWiki'
 25+);
 26+
 27+/****************************
 28+ * ARC2 RDF library for PHP *
 29+ ****************************/
 30+
 31+$smwgARC2Path = $smwgIP . '/libs/arc/';
 32+require_once($smwgARC2Path . '/ARC2.php');
 33+
 34+/**************************
 35+ * ARC2 RDF Store config *
 36+ **************************/
 37+
 38+$smwgARC2StoreConfig = array(
 39+ /* Customize these details if you *
 40+ * want to use an external database */
 41+ 'db_host' => $wgDBserver,
 42+ 'db_name' => $wgDBname,
 43+ 'db_user' => $wgDBuser,
 44+ 'db_pwd' => $wgDBpassword,
 45+ 'store_name' => $wgDBprefix . 'arc2store',
 46+);
 47+$smwgDefaultStore = 'SMWARC2Store'; // Determines database table prefix
 48+
 49+require_once("$IP/extensions/RDFIO/stores/SMW_ARC2Store.php");
 50+require_once("$IP/extensions/RDFIO/specials/SpecialARC2Admin.php");
 51+
 52+/**************************
 53+ * SMWWriter settings *
 54+ **************************/
 55+
 56+include_once("$IP/extensions/PageObjectModel/POM.php");
 57+include_once("$IP/extensions/SMWWriter/SMWWriter.php");
 58+
 59+/**************************
 60+ * RDFIO Components *
 61+ **************************/
 62+
 63+require_once("classes/Utils.php");
 64+require_once("classes/RDFStore.php");
 65+require_once("classes/SMWBatchWriter.php");
 66+require_once("classes/PageHandler.php");
 67+require_once("specials/SpecialRDFImport.php");
 68+require_once("specials/SpecialSPARQLEndpoint.php");
 69+
Property changes on: trunk/extensions/RDFIO/RDFIO.php
___________________________________________________________________
Added: svn:eol-style
170 + native
Index: trunk/extensions/RDFIO/bundle/ARC2_SPARQLSerializerPlugin.php
@@ -0,0 +1,200 @@
 2+<?php
 3+/*
 4+homepage: ARC or plugin homepage
 5+license: http://arc.semsol.org/license
 6+
 7+class: ARC2 SPARQL Serialiser Plugin
 8+author: Keith Alexander
 9+version: 2008-06-22
 10+
 11+fixed some bugs with literal typing and escaping
 12+
 13+*/
 14+
 15+ARC2::inc('Class');
 16+
 17+class ARC2_SPARQLSerializerPlugin extends ARC2_Class {
 18+
 19+ function __construct($a = '', &$caller) {
 20+ parent::__construct($a, $caller);
 21+ }
 22+
 23+ function ARC2_SPARQLSerializerPlugin ($a = '', &$caller) {
 24+ $this->__construct($a, $caller);
 25+ }
 26+
 27+ function __init() {
 28+ parent::__init();
 29+ }
 30+
 31+ function toString($infos){
 32+ $this->infos = $infos;
 33+ return self::sparql_info_to_string($infos['query']);
 34+ }
 35+
 36+ function sparql_info_to_string($t, $only_triples=false){
 37+ $string = '';
 38+ if(isset($t['type'])){
 39+ switch($t['type']){
 40+ case 'construct':
 41+ $string .='CONSTRUCT { '.$this->sparql_info_to_string($t['construct_triples'], true).' } ';
 42+ case 'describe':
 43+ case 'select':
 44+ if(in_array($t['type'], array('select','describe'))){
 45+ $string.= ' '.strtoupper($t['type']).' ';
 46+ if (isset($t['result_vars'])) foreach($t['result_vars'] as $v){
 47+ $string.= ' ?'.$v['var'];
 48+ }
 49+ if (isset($t['result_iris'])) foreach($t['result_iris'] as $v){
 50+ $string.= ' <'.$v['iri'].'> ';
 51+ }
 52+ }
 53+ case 'ask':
 54+ if(!empty($t['dataset'])){
 55+ foreach($t['dataset'] as $dataset){
 56+ $string.= ' FROM '.(($dataset['named'])? 'NAMED ': '').'<'.$dataset['graph'].'> ';
 57+ }
 58+ }
 59+ if(!isset($t['pattern'])) var_dump($this->infos);
 60+ else $string .= ' WHERE '.$this->sparql_info_to_string($t['pattern']).'';
 61+ break;
 62+ case 'triple':
 63+ $string.= $this->triple_to_string($t);
 64+ break;
 65+ case 'union':
 66+ $patterns = array();
 67+ foreach($t['patterns'] as $pattern){
 68+ $patterns[]='{'.$this->sparql_info_to_string($pattern, $only_triples).'}';
 69+ }
 70+ $string .= implode(' UNION ', $patterns);
 71+ break;
 72+ case 'group':
 73+ case 'triples':
 74+ case 'optional':
 75+ $pattern_string ='';
 76+ foreach($t['patterns'] as $pattern){
 77+ $pattern_string.=" ".$this->sparql_info_to_string($pattern, $only_triples)." ";
 78+ }
 79+ switch($t['type']){
 80+ case 'group':
 81+ $string.='{ '.$pattern_string.' }';
 82+ break;
 83+ case 'triples':
 84+ $string.= $pattern_string;
 85+ break;
 86+ case 'optional':
 87+ $string.= (!$only_triples)? 'OPTIONAL { '.$pattern_string.' }' : '{ '.$pattern_string.' }' ;
 88+ break;
 89+ }
 90+ break;
 91+ case 'filter':
 92+ $string .=(!$only_triples)? "FILTER(".$this->sparql_info_to_string($t['constraint']).")" : '';
 93+ break;
 94+ case 'built_in_call':
 95+ $string .=$t['operator'].strtoupper($t['call'])."(";
 96+ $args=array();
 97+ foreach($t['args'] as $arg){ $args[]=$this->sparql_info_to_string($arg);
 98+ }
 99+ $string .=implode(',', $args).') ';
 100+ break;
 101+ case 'var':
 102+ $var_string ='?'.$t['value'];
 103+ if(isset($t['direction'])) $var_string = strtoupper($t['direction'])."(".$var_string.")";
 104+ $string .= $var_string;
 105+ break;
 106+ case 'literal':
 107+ case 'literal1':
 108+ case 'literal2':
 109+ $string .= $this->term_to_string($t['type'], $t['value']);
 110+ if(isset($t['datatype'])) $string .= '^^'.$t['datatype'];
 111+ else if (isset($t['lang'])) $string .= '@'.$t['lang'];
 112+ break;
 113+ case 'expression':
 114+ $expressions = array();
 115+ foreach($t['patterns'] as $p) { $expressions[]=$this->sparql_info_to_string($p);
 116+ }
 117+ switch($t['sub_type']){
 118+ case 'relational':
 119+ $string.= implode($t['operator'], $expressions);
 120+ break;
 121+ case 'and':
 122+ $string.= implode(' && ', $expressions);
 123+ break;
 124+ case 'or':
 125+ $string.= implode(' || ', $expressions);
 126+ break;
 127+
 128+ default:
 129+ $string.= implode($t['sub_type'], $expressions);
 130+ break;
 131+ }
 132+ break;
 133+ }
 134+
 135+ }
 136+ else if(is_array($t)){
 137+ foreach($t as $item){
 138+ $string.= $this->sparql_info_to_string($item);
 139+ }
 140+ }
 141+ if(isset($t['order_infos'])){
 142+ foreach($t['order_infos'] as $order){
 143+ $string.= " ORDER BY ".$this->sparql_info_to_string($order);
 144+ }
 145+ }
 146+ if(isset($t['limit'])){
 147+ $string .= ' LIMIT '.$t['limit'];
 148+ }
 149+ if(isset($t['offset'])){
 150+ $string .= ' OFFSET '.$t['offset'];
 151+ }
 152+
 153+ return $string;
 154+ }
 155+
 156+ function triple_to_string($t){
 157+ $str = '';
 158+ if(empty($t)) return '';
 159+ foreach(array('s','p','o') as $term){
 160+ $str.= ' '.$this->term_to_string($t[$term.'_type'], $t[$term]);
 161+ }
 162+ return $str.' . ';
 163+ }
 164+
 165+ function term_to_string($type, $val){
 166+ switch($type){
 167+ case 'var':
 168+ return '?'.$val;
 169+ case 'literal':
 170+ case 'literal1':
 171+ case 'literal2':
 172+ case 'literal_long1':
 173+ case 'literal_long2':
 174+ $quot = '"';
 175+ if (preg_match('/\"/', $val)) {
 176+ $quot = "'";
 177+ if (preg_match('/\'/', $val)) {
 178+ $quot = '"""';
 179+ if (preg_match('/\"\"\"/', $val) || preg_match('/\"$/', $val) || preg_match('/^\"/', $val)) {
 180+ $quot = "'''";
 181+ $val = preg_replace("/'$/", "' ", $val);
 182+ $val = preg_replace("/^'/", " '", $val);
 183+ $val = str_replace("'''", '\\\'\\\'\\\'', $val);
 184+ }
 185+ }
 186+ }
 187+ if ((strlen($quot) == 1) && preg_match('/[\x0d\x0a]/', $val)) {
 188+ $quot = $quot . $quot . $quot;
 189+ }
 190+ return $quot .$val. $quot ;
 191+ case 'uri':
 192+ return '<'.$val.'>';
 193+ case 'bnode':
 194+ default:
 195+ return $val;
 196+ }
 197+ }
 198+
 199+}
 200+
 201+?>
\ No newline at end of file
Property changes on: trunk/extensions/RDFIO/bundle/ARC2_SPARQLSerializerPlugin.php
___________________________________________________________________
Added: svn:eol-style
1202 + native
Index: trunk/extensions/RDFIO/README
@@ -0,0 +1,59 @@
 2+Last updated 2010-09-07 by Samuel Lampa (samuel.lampa@gmail.com)
 3+
 4+= RDF IO Extension for Semantic MediaWiki =
 5+
 6+You can find this information in a more readable format at
 7+ <http://www.mediawiki.org/wiki/Extension:RDFIO>
 8+
 9+
 10+== Introduction ==
 11+
 12+This extension extends the RDF import and export functionality in Semantic MediaWiki
 13+by providing import of arbitrary RDF triples (not only OWL ontologies, as before
 14+(see http://semantic-mediawiki.org/wiki/Help:Ontology_import), and a SPARQL endpoint
 15+that allows write operations.
 16+
 17+Technically, RDFIO implements the PHP/MySQL based triple store (and its accompanying
 18+SPARQL Endpoint) provided by the [http://arc.semsol.org/ ARC2] library. For updating
 19+wiki pages with new triples on import/sparql update, the SMWWriter extension is used.
 20+
 21+The RDF import stores the original URI of all imported RDF entities (in a special
 22+property), which can later be used by the SPARQL endpoint, instead of SMW's internal
 23+URIs, which thus allows to expose the imported RDF data "in its original formats",
 24+with its original URIs. This allows to use SMW as a collaborative RDF editor, in
 25+workflows together with other semantic tools, from which it is then possible to
 26+"export, collaboratively edit, and import again", to/from SMW.
 27+
 28+This extensions was developed as part of a Google Summer of Code 2010 project. The
 29+project description can be found at http://www.mediawiki.org/wiki/User:SHL/GSoC2010
 30+
 31+*Caution!* This extension is not yet ready for production use! Use it on your own risk!
 32+
 33+
 34+== Installation ==
 35+
 36+* See http://www.mediawiki.org/wiki/Extension:RDFIO#Installation
 37+
 38+
 39+== Dependencies ==
 40+
 41+Semantic MediaWiki Extension
 42+http://www.mediawiki.org/wiki/Extension:Semantic_MediaWiki
 43+
 44+SMWWriter Extension
 45+http://www.mediawiki.org/wiki/Extension:SMWWriter
 46+
 47+Page Object Model Extension (Dependency of SMWWriter)
 48+http://www.mediawiki.org/wiki/Extension:Page_Object_Model
 49+
 50+ARC2 RDF library for PHP (http://arc.semsol.org)
 51+http://arc.semsol.org/
 52+
 53+
 54+== Bugs, new feature request and contact information ==
 55+
 56+Please reports bugs and feature requests at Bugzilla:
 57+https://bugzilla.wikimedia.org/
 58+General feedback can be given at http://www.mediawiki.org/w/index.php?title=Extension_talk:RDFIO
 59+
 60+
Index: trunk/extensions/RDFIO/classes/PageHandler.php
@@ -0,0 +1,204 @@
 2+<?php
 3+
 4+class RDFIOPageHandler {
 5+ protected $m_wikititle;
 6+ protected $m_wikititlefull;
 7+ protected $m_ns;
 8+ protected $m_properties;
 9+ protected $m_edittoken;
 10+ protected $m_smwwriter;
 11+ protected $m_smwwriter_add;
 12+ protected $m_smwwriter_remove;
 13+ protected $m_errors;
 14+ protected $m_haserrors;
 15+
 16+ function __construct( $wikititle, $ns, $properties ) {
 17+ $this->m_wikititle = $wikititle;
 18+ $this->m_ns = $ns;
 19+ if ( $ns == SMW_NS_PROPERTY ) {
 20+ $wikititle = str_replace( 'Property-3A', '', $wikititle );
 21+ $wikititle = str_replace( 'Property:', '', $wikititle );
 22+ $this->m_wikititlefull = 'Property:' . $wikititle;
 23+ } else {
 24+ $this->m_wikititlefull = $wikititle;
 25+ }
 26+ $this->m_properties = $properties;
 27+ $this->m_haserrors = false;
 28+ }
 29+
 30+ /**
 31+ * Write (or delte, if $delete is set to true) the data in the object
 32+ * variables, to the wiki page corresponding to this page handler
 33+ * @param boolean $delete
 34+ */
 35+ public function writeOrDeleteDataToWiki( $delete = false ) {
 36+ if ( $delete ) {
 37+ if ( $this->checkWikiPageExists() ) {
 38+ $this->initSMWWriter( $delete = true );
 39+ } else {
 40+ return;
 41+ }
 42+ } else {
 43+ $this->ensureWikiPageExists();
 44+ $this->initSMWWriter();
 45+ }
 46+
 47+ $properties = $this->m_properties;
 48+ foreach ( $properties as $cur_prop ) {
 49+ $propertystring = $cur_prop['p'];
 50+ $property = SMWPropertyValue::makeUserProperty( $propertystring );
 51+ $valuestring = RDFIOUtils::sanitizeSMWValue( $cur_prop['v'] );
 52+ $value = SMWDataValueFactory::newPropertyObjectValue( $property, $valuestring );
 53+
 54+ $propertyErrorText = $property->getErrorText();
 55+ $propertyHasError = ( $propertyErrorText != '' );
 56+ if ( $propertyHasError ) {
 57+ $this->addError( "<p>In RDFIOPageHandler::writeOrDeleteDataToWiki(): " . $property->getErrorText() . "</p>");
 58+ }
 59+
 60+ $valueErrorText = $value->getErrorText();
 61+ $valueHasError = ( $valueErrorText != '' );
 62+ if ( $valueHasError ) {
 63+ $this->addError( "<p>Error creating property value object in RDFIOPageHandler::writeOrDeleteDataToWiki():</p><p>" . $value->getErrorText() . "</p>");
 64+ }
 65+ if ( $delete ) {
 66+ $this->m_smwwriter_remove->addPropertyObjectValue( $property, $value );
 67+ $editmessage = "Deleting properties. Last property delete: " . $propertystring . " : " . $valuestring;
 68+ } else {
 69+ $this->m_smwwriter_add->addPropertyObjectValue( $property, $value );
 70+ $editmessage = "Importing properties. Last property added: " . $propertystring . " : " . $valuestring;
 71+ }
 72+ }
 73+
 74+ $this->m_smwwriter->update( $this->m_smwwriter_remove, $this->m_smwwriter_add, $editmessage );
 75+ $smwWriterError = $this->m_smwwriter->getError();
 76+ $smwWriterHasError = ( $smwWriterError != '' );
 77+ if ( $smwWriterHasError ) {
 78+ $this->addError( "<p>SMWWriter Error: " . $smwWriterError . "</p>" );
 79+ }
 80+ }
 81+
 82+ /**
 83+ * Delete the data in the object variables from the wiki page
 84+ * corresponding to this page handler
 85+ */
 86+ public function deleteDataFromWiki() {
 87+ $this->writeOrDeleteDataToWiki( $delete = true );
 88+ }
 89+
 90+ /**
 91+ * Wrapper method for wikiPageExistsSaveEditToken()
 92+ * TODO Is this really needed?
 93+ */
 94+ private function checkWikiPageExists() {
 95+ $this->m_wikipageexists = $this->wikiPageExistsSaveEditToken();
 96+ return $this->m_wikipageexists;
 97+ }
 98+
 99+ /**
 100+ * For a wiki page title, check if it exists (and at the same time, store an edit token),
 101+ * and if not, create it.
 102+ * @param string $wikititle
 103+ */
 104+ private function ensureWikiPageExists() {
 105+ $this->m_wikipageexists = $this->wikiPageExistsSaveEditToken();
 106+ if ( !$this->m_wikipageexists ) {
 107+ $this->createWikiPage();
 108+ }
 109+ }
 110+
 111+ /**
 112+ * For a create the wiki page, without writing any content to it.
 113+ */
 114+ private function createWikiPage() {
 115+ // Prepare a 'fake' request to the MediaWiki API, which we use internally
 116+ // See http://www.mediawiki.org/wiki/API:Calling_internally for more info
 117+ $fauxEditRequest = new FauxRequest(array (
 118+ 'action' => 'edit',
 119+ 'title' => $this->m_wikititlefull, // For the faux request, the namespace must be included in text form
 120+ 'section' => '0',
 121+ 'summary' => 'New Page (by SMWRDFConnector)',
 122+ 'text' => '<!-- Empty page -->',
 123+ 'token' => $this->m_edittoken
 124+ ));
 125+ $editApi = new ApiMain($fauxEditRequest, $enableWrite = true);
 126+ $editApi->execute();
 127+ $editApiOutput = & $editApi->getResultData(); // TODO: Take care of this
 128+ }
 129+
 130+ /**
 131+ * Checks whether a wiki article with the given title exists. It also receives
 132+ * an edit token for this article and stores in a class variable.
 133+ * @return boolean
 134+ */
 135+ private function wikiPageExistsSaveEditToken() {
 136+ $fauxRequest = new FauxRequest(array (
 137+ 'action' => 'query',
 138+ 'prop' => 'info',
 139+ 'intoken' => 'edit',
 140+ 'titles' => $this->m_wikititlefull
 141+ ));
 142+ // We are using the MediaWiki API internally.
 143+ // See http://www.mediawiki.org/wiki/API:Calling_internally
 144+ // for more info
 145+ $api = new ApiMain($fauxRequest);
 146+ $api->execute();
 147+ $apioutput = & $api->getResultData(); // TODO: Take care of this
 148+ $apioutputpages = $apioutput['query']['pages'];
 149+ foreach ( $apioutputpages as $page ) {
 150+ $this->m_edittoken = $page['edittoken'];
 151+ }
 152+ // Using intricacies of array structure to determine if page exists
 153+ // TODO: Use more robust method
 154+ $pageismissing = count($apioutput['query']['pages'][-1]) > 0;
 155+ return !$pageismissing;
 156+ }
 157+
 158+ /**
 159+ * Initialize SMWWriter for the page corresponding to title
 160+ * in object variable
 161+ * @param boolean $delete
 162+ */
 163+ private function initSMWWriter( $delete = false ) {
 164+ // Create add and remove objects, to use in SMWWriter calls
 165+ $page = SMWWikiPageValue::makePage( $this->m_wikititle, $this->m_ns );
 166+ $this->m_smwwriter = new SMWWriter( $page->getTitle() );
 167+ if ( $delete ) {
 168+ // We are not adding anything, so create a "page" with "false" title
 169+ $this->m_smwwriter_add = new SMWSemanticData( SMWWikiPageValue::makePage( false, $this->m_ns ) );
 170+ $this->m_smwwriter_remove = new SMWSemanticData( $page );
 171+ } else {
 172+ $this->m_smwwriter_add = new SMWSemanticData( $page );
 173+ // We are not removing anything, so create a "page" with "false" title
 174+ $this->m_smwwriter_remove = new SMWSemanticData( SMWWikiPageValue::makePage( false, $this->m_ns ) );
 175+ }
 176+ }
 177+
 178+ public function getWikiTitleFull() {
 179+ return $this->m_wikititlefull;
 180+ }
 181+
 182+ private function addError( $errormessage ) {
 183+ $this->m_errors[] = $errormessage;
 184+ $this->m_haserrors = true;
 185+ }
 186+
 187+ public function hasErrors() {
 188+ return $this->m_haserrors;
 189+ }
 190+
 191+ public function getErrors( ) {
 192+ return $this->m_errors;
 193+ }
 194+
 195+ public function getErrorText() {
 196+ $errors = $this->m_errors;
 197+ $errortext = '';
 198+ $i = 1;
 199+ foreach ( $errors as $error ) {
 200+ $errortext .= "$error\n";
 201+ $i++;
 202+ }
 203+ return $errortext;
 204+ }
 205+}
Property changes on: trunk/extensions/RDFIO/classes/PageHandler.php
___________________________________________________________________
Added: svn:eol-style
1206 + native
Index: trunk/extensions/RDFIO/classes/Utils.php
@@ -0,0 +1,250 @@
 2+<?php
 3+
 4+class RDFIOUtils {
 5+
 6+ /**
 7+ * Checks if $uri is an URI Resolver URI (i.e. an URI used by SMW to identify wiki pages)
 8+ * @param string $uri
 9+ * @return boolean $isURIResolverURI
 10+ */
 11+ static function isURIResolverURI( $uri ) {
 12+ $isURIResolverURI = ( preg_match( '/Special:URIResolver/', $uri, $matches ) > 0 );
 13+ return $isURIResolverURI;
 14+ }
 15+
 16+ /**
 17+ * Checks if $uri is an ARC untitled identifier
 18+ * @param string $uri
 19+ * @return boolean $isArcUntitledNode
 20+ */
 21+ static function isArcUntitledNode( $uri ) {
 22+ $isArcUntitledNode1 = ( preg_match( '/^Arc/', $uri, $matches ) > 0 );
 23+ $isArcUntitledNode2 = ( preg_match( '/_:arc/', $uri, $matches ) > 0 );
 24+ $isArcUntitledNode = ( $isArcUntitledNode1 || $isArcUntitledNode2 );
 25+ return $isArcUntitledNode;
 26+ }
 27+
 28+ /**
 29+ * Checks if a string is a URL (i.e., starts with 'http:')
 30+ * @param $text
 31+ * @return boolean $isURL
 32+ */
 33+ static function isURL( $text ) {
 34+ $isURL = ( preg_match( '/^http(s)?:/', $text, $matches ) > 0 );
 35+ return $isURL;
 36+ }
 37+
 38+ /**
 39+ * Extracts the "label", or "local part" of an URI, i.e. it removes
 40+ * its namespace, or base URI
 41+ * @param string $uri
 42+ * @return string
 43+ */
 44+ static function extractLabelFromURI( $uri ) {
 45+ $uriparts = RDFIOUtils::splitURI( $uri );
 46+ $basepart = $uriparts[0];
 47+ $localpart = $uriparts[1];
 48+ if ( $localpart[1] != '' ) {
 49+ return $localpart;
 50+ } else {
 51+ return $basepart;
 52+ }
 53+ }
 54+
 55+ /**
 56+ * Customized version of the splitURI($uri) of the ARC2 library (http://arc.semsol.org)
 57+ * Splits a URI into its base part and local part, and returns them as an
 58+ * array of two strings
 59+ * @param string $uri
 60+ * @return array
 61+ */
 62+ static function splitURI( $uri ) {
 63+ global $rdfiogBaseURIs;
 64+ /* ADAPTED FROM ARC2 WITH SOME MODIFICATIONS
 65+ * the following namespaces may lead to conflated URIs,
 66+ * we have to set the split position manually
 67+ */
 68+ if (strpos($uri, 'www.w3.org')) {
 69+ $specials = array(
 70+ 'http://www.w3.org/XML/1998/namespace',
 71+ 'http://www.w3.org/2005/Atom',
 72+ 'http://www.w3.org/1999/xhtml',
 73+ );
 74+ if ( $rdfiogBaseURIs != '' ) {
 75+ $specials = array_merge( $specials, $rdfiogBaseURIs );
 76+ }
 77+ foreach ($specials as $ns) {
 78+ if (strpos($uri, $ns) === 0) {
 79+ $local_part = substr($uri, strlen($ns));
 80+ if (!preg_match('/^[\/\#]/', $local_part)) {
 81+ return array( $ns, $local_part );
 82+ }
 83+ }
 84+ }
 85+ }
 86+ /* auto-splitting on / or # */
 87+ //$re = '^(.*?)([A-Z_a-z][-A-Z_a-z0-9.]*)$';
 88+ if (preg_match('/^(.*[\#])([^\#]+)$/', $uri, $matches)) {
 89+ return array($matches[1], $matches[2]);
 90+ }
 91+ if (preg_match('/^(.*[\:])([^\:\/]+)$/', $uri, $matches)) {
 92+ return array($matches[1], $matches[2]);
 93+ }
 94+ if (preg_match('/^(.*[\/])([^\/]+)$/', $uri, $matches)) {
 95+ return array($matches[1], $matches[2]);
 96+ } /* auto-splitting on last special char, e.g. urn:foo:bar */
 97+ return array($uri, '');
 98+
 99+ }
 100+
 101+ static function contains( $word, $subject ) {
 102+ $contains = preg_match( "/$word/i", $subject ) > 0;
 103+ return $contains;
 104+ }
 105+
 106+ /**
 107+ * Prints out the structure of an array enclosed in <pre> tags. Used for debugging
 108+ * @param array $arrayToShow
 109+ * @param string $title
 110+ */
 111+ static function showArray( $arrayToShow, $title ) {
 112+ echo "<h2>$title</h2><pre style=\"font-size: 12px; font-weight: bold;\">";
 113+ print_r( $arrayToShow );
 114+ echo "</pre>";
 115+ }
 116+
 117+ static function showErrorMessage( $title, $message ) {
 118+ global $wgOut;
 119+ $errorhtml = RDFIOUtils::formatErrorHTML( $title, $message );
 120+ $wgOut->addHTML( $errorhtml );
 121+ }
 122+
 123+ /**
 124+ * Format an error message with HTML, based on a message title and the message
 125+ * @param string $title
 126+ * @param string $message
 127+ * @return string $errorhtml
 128+ */
 129+ static function formatErrorHTML( $title, $message ) {
 130+ $errorhtml = '<div style="margin: .4em 0; padding: .4em .7em; border: 1px solid #D8000C; background-color: #FFBABA;">
 131+ <h3>' . $title . '</h3>
 132+ <p>' . $message . '</p>
 133+ </div>';
 134+ return $errorhtml;
 135+ }
 136+
 137+ /**
 138+ * Extract everything between <body> and </body> in a string
 139+ * @param string $html
 140+ * @return string $html
 141+ */
 142+ static function extractHTMLBodyContent( $html ) {
 143+ $foundmatch = preg_match( '#<body[^\>]*>(.*?)</body>#Us', $html, $match );
 144+ if ( $foundmatch ) {
 145+ $html = $match[1];
 146+ }
 147+ // Convert any table to sortable wiki table
 148+ return $html;
 149+ }
 150+
 151+ /**
 152+ * Add css class attributes which make tables styled and sortable inside the wiki
 153+ * @param string $html
 154+ * @return string $html
 155+ */
 156+ static function wikifyTables( $html ) {
 157+ $html = preg_replace( '#<table[^\>]*?>#U', '<table class="wikitable sortable">', $html );
 158+ return $html;
 159+ }
 160+
 161+ /**
 162+ * Extract URIs from a string
 163+ * @param string $text
 164+ * @return $array $uris
 165+ */
 166+ static function extractURIs( $text ) {
 167+ $uris = array();
 168+ preg_match_all( '/http:[^\s<>"]+/', $text, $uris );
 169+ return $uris[0];
 170+ }
 171+
 172+ /**
 173+ * Convert to character identifiers used to make URLs XML compliant
 174+ * @param string $text
 175+ * @return string $text
 176+ */
 177+ static function xmlifyUris( $text ) { // TODO Used anywhere?
 178+ $text = str_replace( '#', '-23', $text );
 179+ $text = str_replace( ':', '-3A', $text );
 180+ $text = str_replace( '?', '-3F', $text );
 181+ $text = str_replace( ' ', '-20', $text );
 182+ return $text;
 183+ }
 184+
 185+ /**
 186+ * Convert back character identifiers used to make URLs XML compliant
 187+ * @param string $text
 188+ * @return string $text
 189+ */
 190+ static function unXmlifyUris( $text ) { // TODO Used anywhere?
 191+ $text = str_replace( '-23', '#', $text );
 192+ $text = str_replace( '-3A', ':', $text );
 193+ $text = str_replace( '-3F', '?', $text );
 194+ $text = str_replace( '-2D', '-', $text );
 195+ $text = str_replace( '-20', ' ', $text );
 196+ $text = str_replace( '-3D', '=', $text );
 197+ return $text;
 198+ }
 199+
 200+ /**
 201+ * @param string $text
 202+ * @return string $text
 203+ */
 204+ static function skipUnallowedCharsInURLsInValue( $text ) { // TODO Used anywhere?
 205+ $text = str_replace( ' ', '', $text );
 206+ $text = str_replace( '#', '-23', $text );
 207+ $text = str_replace( '_', '-20', $text );
 208+ return $text;
 209+ }
 210+
 211+ /**
 212+ * @param string $text
 213+ * @return string $text
 214+ */
 215+ static function restoreUnallowedCharsInValue( $text ) { // TODO Used anywhere?
 216+ $text = str_replace( '-23', '#', $text );
 217+ $text = str_replace( '-20', '_', $text );
 218+ return $text;
 219+ }
 220+
 221+ /**
 222+ * Remove characters which don't work in wiki titles
 223+ * @param string $uri
 224+ * @return string $title
 225+ */
 226+ static function sanitizeWikiTitle( $title ) {
 227+ # $uri = SMWExporter::encodeURI( $uri );
 228+ // Optimally we should rely on SMWExporter::encodeURI
 229+ // but seems we cannot. TODO: Think through if this is true
 230+ $title = str_replace( '#', '-23', $title );
 231+ $title = str_replace( '[', '', $title );
 232+ $title = str_replace( ']', '', $title );
 233+ # $title = preg_replace( '/[\[\]]/', '', $title );
 234+ return $title;
 235+ }
 236+
 237+ /**
 238+ * Remove characters which don't work in smw values
 239+ * @param string $value
 240+ * @return string $value
 241+ */
 242+ static function sanitizeSMWValue( $value ) {
 243+ # $uri = SMWExporter::encodeURI( $uri );
 244+ // Optimally we should rely on SMWExporter::encodeURI
 245+ // but seems we cannot. TODO: Think through if this is true
 246+ $value = str_replace( '[', '', $value );
 247+ $value = str_replace( ']', '', $value );
 248+ return $value;
 249+ }
 250+
 251+}
Property changes on: trunk/extensions/RDFIO/classes/Utils.php
___________________________________________________________________
Added: svn:eol-style
1252 + native
Index: trunk/extensions/RDFIO/classes/SMWBatchWriter.php
@@ -0,0 +1,705 @@
 2+<?php
 3+
 4+/**
 5+ * RDFIOSMWBatchWriter can take data in different formats (RDF/XML, SPARQL query
 6+ * structure etc) and perform write operations on the resulting wiki articles by
 7+ * calling SMWWriter
 8+ * @author samuel.lampa@gmail.com
 9+ * @package RDFIO
 10+ */
 11+class RDFIOSMWBatchWriter {
 12+ protected $m_delete;
 13+ protected $m_unparseddata;
 14+ protected $m_dataformat;
 15+ protected $m_parser;
 16+ protected $m_triples;
 17+ protected $m_tripleindex;
 18+ protected $m_tripleindexflat;
 19+ protected $m_nsprefixes;
 20+ protected $m_importedtriples;
 21+ protected $m_pages;
 22+ protected $m_errors;
 23+ protected $m_haserrors;
 24+ // Previously in Equiv URI Class
 25+ protected $m_wikititlepropertyuris;
 26+ protected $m_usenspintitles_properties = false;
 27+ protected $m_usenspintitles_entities = false;
 28+ protected $m_store;
 29+
 30+ function __construct( $importdata, $dataformat ) {
 31+ global $rdfiogExtraNSPrefixes,
 32+ $rdfiogPropertiesToUseAsWikiTitle,
 33+ $rdfiogUseNSPrefixInWikiTitleForProperties,
 34+ $rdfiogUseNSPrefixInWikiTitleForEntities;
 35+
 36+ if ( $dataformat == 'triples_array' ) {
 37+ $this->m_triples = $importdata;
 38+ } else {
 39+ $this->m_unparseddata = $importdata;
 40+ }
 41+ $this->m_dataformat = $dataformat;
 42+ $this->m_haserrors = false;
 43+ $this->m_delete = false;
 44+ if ( $this->m_dataformat == 'rdfxml' ) {
 45+ $this->m_unparseddata = $this->cleanupXML( $this->m_unparseddata );
 46+ $this->m_parser = ARC2::getRDFXMLParser();
 47+ $this->parse();
 48+ } else if ( $this->m_dataformat == 'turtle' ) {
 49+ $this->m_unparseddata = $wgRequest->getText('importdata');
 50+ $this->m_parser = ARC2::getTurtleParser();
 51+ $this->parse();
 52+ }
 53+ $this->extractTripleIndex();
 54+ $this->m_nsprefixes = $this->getNSPrefixMappingFromParser();
 55+ if ( $rdfiogExtraNSPrefixes != '' ) {
 56+ $this->addNamespacePrefixes( $rdfiogExtraNSPrefixes );
 57+ }
 58+ $nsprefixes = $this->m_nsprefixes;
 59+ $this->setNSPrefixes( $nsprefixes );
 60+ $this->setTripleIndex( $this->m_tripleindex );
 61+
 62+ // Previously in Equiv URI Class
 63+
 64+ if ( $rdfiogUsePseudoNamespacesForProperties != '' ) { // TODO: Change to check options from import screen
 65+ // use parameter set in LocalSettings.php
 66+ $this->m_usenspintitles_properties = $rdfiogUsePseudoNamespacesForProperties;
 67+ }
 68+
 69+ if ( $rdfiogUsePseudoNamespacesForEntities != '' ) {
 70+ // use parameter set in LocalSettings.php
 71+ $this->m_usenspintitles_entities = $rdfiogUsePseudoNamespacesForEntities;
 72+ }
 73+
 74+ if ( !empty( $rdfiogPropertiesToUseAsWikiTitle ) ) {
 75+ $this->m_wikititlepropertyuris = $rdfiogPropertiesToUseAsWikiTitle;
 76+ } else {
 77+ $this->m_wikititlepropertyuris = array(
 78+ 'http://semantic-mediawiki.org/swivt/1.0#page', // Suggestion for new property
 79+ 'http://www.w3.org/2000/01/rdf-schema#label',
 80+ 'http://purl.org/dc/elements/1.1/title',
 81+ 'http://www.w3.org/2004/02/skos/core#preferredLabel',
 82+ 'http://xmlns.com/foaf/0.1/name'
 83+ );
 84+ }
 85+
 86+ $this->m_store = new RDFIOStore();
 87+ }
 88+
 89+ /**
 90+ * Execute Import of data sent to RDFImporter object upon creation.
 91+ */
 92+ public function execute() {
 93+ $this->preparePageHandlers();
 94+ if ( $this->m_delete ) {
 95+ $this->deletePageDataFromWiki();
 96+ } else {
 97+ $this->writePagesToWiki();
 98+ }
 99+ }
 100+
 101+ /**
 102+ * Check for namespaces lacking a prefix ("abbreviation"), in the
 103+ * current namespace prefix configuration
 104+ */
 105+ public function checkForNamespacesWithoutPrefix() {
 106+ $nsprefixes = $this->getNSPrefixMapping();
 107+ $existunabbreviatedpropertyuris = in_array( false, $nsprefixes );
 108+ return $existunabbreviatedpropertyuris;
 109+ }
 110+
 111+ /**
 112+ * Get namespaces lacking a prefix, from the current namespace
 113+ * configuration
 114+ * @return array $nsswithoutprefix
 115+ */
 116+ public function getNamespacesWithoutPrefix() {
 117+ $nsprefixes = $this->m_nsprefixes;
 118+ $nsswithoutprefix = array();
 119+ foreach ( $nsprefixes as $namespace => $abbreviation ) {
 120+ if ( $abbreviation == false ) {
 121+ $nsswithoutprefix[] = $namespace;
 122+ }
 123+ }
 124+ return $nsswithoutprefix;
 125+ }
 126+
 127+ /**
 128+ * Get URIs for entities (non-properties) which are not abbreviated
 129+ * by a namespace prefix
 130+ */
 131+ public function getUnabbrEntityURIs() {
 132+ $subjecturis = $this->getUniqueSubjectURIs();
 133+ $valueuris = $this->getUniqueValueURIs();
 134+ $entityuris = array_merge( $subjecturis, $valueuris );
 135+ $entityuris = array_unique( $entityuris );
 136+ $unabbreviateduris = array();
 137+ foreach( $entityuris as $entityuri ) {
 138+ $titlebypropertyuriindex = '';
 139+ $titlebypropertyuriindex = $this->getWikiTitleByPropertyURIIndex( $entityuri );
 140+ if ( $titlebypropertyuriindex == '' ) {
 141+ $nsprefixes = $this->m_nsprefixes;
 142+ $uricontainsns = false;
 143+ foreach ( $nsprefixes as $ns => $nsprefix ) {
 144+ $nslength = strlen( $ns );
 145+ if ( substr( $entityuri, 0, $nslength ) === $ns ) {
 146+ $uricontainsns = true;
 147+ }
 148+ }
 149+ // If no match was found above:
 150+ if ( !$uricontainsns ) {
 151+ $unabbreviateduris[] = $entityuri;
 152+ }
 153+ }
 154+ }
 155+ return $unabbreviateduris;
 156+ }
 157+
 158+ /**
 159+ * Add namespace prefixes to current namespace prefix configuration
 160+ * @param array $newnsmappings
 161+ */
 162+ public function addNamespacePrefixes( $newnsmappings ) {
 163+ $nsmapping = $this->m_nsprefixes;
 164+ foreach ( $newnsmappings as $namespace => $prefix ) {
 165+ $nsmapping[$namespace] = $prefix;
 166+ }
 167+ $this->m_nsprefixes = $nsmapping;
 168+ // Right now this has to be duplicated (until Equiv URI handler is merged with SMWBatchWriter)
 169+ $this->setNSPrefixes( $nsmapping );
 170+ }
 171+
 172+ /**
 173+ * Delete imported facts instead of adding them
 174+ */
 175+ public function executeDelete() {
 176+ $this->m_delete = true;
 177+ $this->execute();
 178+ $this->m_delete = false;
 179+ }
 180+
 181+ /**
 182+ * Parse the imported data into ARC2 data structures which are stored in object variables.
 183+ */
 184+ private function parse() {
 185+ $this->m_parser->parse( '', $this->m_unparseddata );
 186+ $this->extractTriples();
 187+ }
 188+
 189+ /**
 190+ * Prepare page handlers, which represent wiki pages to be written to/deleted from,
 191+ * and the corresponding facts to add/remove
 192+ */
 193+ private function preparePageHandlers() {
 194+ // The page below should not be deleted on delete operations
 195+ if ( !$this->m_delete ) {
 196+ // Add type info to the Original URI property
 197+ $property_hastypeurl = array( array( 'p' => 'Has type', 'v' => 'URL') );
 198+ $origuripage = new RDFIOPageHandler( 'Original URI', SMW_NS_PROPERTY, $property_hastypeurl );
 199+ $this->addToPages( $origuripage );
 200+ }
 201+
 202+ // Prepare for storing the data to write in internal data structure ($this->m_pages)
 203+ $unique_subject_uris = $this->getUniqueSubjectURIs();
 204+ foreach ( $unique_subject_uris as $subject_uri ) {
 205+ $properties = array();
 206+ // A URIResolver URI indicates that internal titles only are used and we have no Original URI available
 207+ if ( !$this->m_delete && !RDFIOUtils::isURIResolverURI( $subject_uri ) && !RDFIOUtils::isArcUntitledNode( $subject_uri ) ) {
 208+ // Add the Original URI fact to the list of properties
 209+ $properties[0] = $this->createOrigURIPropertyArray( $subject_uri );
 210+ $properties[1] = $this->createEquivURIPropertyArray( $subject_uri );
 211+ $i++;
 212+ }
 213+
 214+ $wikititle = $this->getWikiTitleForURI( $subject_uri );
 215+ $triplesforpage = $this->getTriplesForSubject( $subject_uri );
 216+
 217+ $i = 2;
 218+ foreach ( $triplesforpage as $triple ) {
 219+ $propertyuri = $triple['p'];
 220+ $valueorig = $triple['o'];
 221+ $valuetype = $triple['o_type'];
 222+ $property = $this->getWikiTitleForURI( $propertyuri, $isproperty = true );
 223+ if ( $valuetype == 'uri' ) {
 224+ $value = $this->getWikiTitleForURI( $valueorig );
 225+ } else {
 226+ $value = RDFIOUtils::sanitizeSMWValue( $valueorig );
 227+ }
 228+ $properties[$i] = array( 'p' => $property, 'v' => $value );
 229+ $i++;
 230+ }
 231+
 232+ $this->addToPages( new RDFIOPageHandler( $wikititle, NS_MAIN, $properties ) );
 233+ }
 234+
 235+ // The data generated below should not be deleted when doing delete operations, and thus,
 236+ // pagehandlers for them should not be prepared on delete.
 237+ if ( !$this->m_delete ) {
 238+ // Prepare property pages
 239+ $unique_property_uris = $this->getUniquePropertyURIs();
 240+ foreach ( $unique_property_uris as $property_uri => $property_uridata ) {
 241+ $wikititle = $this->getWikiTitleForURI( $property_uri, $isproperty = true );
 242+
 243+ $type = $this->convertARCTypeToSMWType( $property_uridata['type'], $property_uridata['datatype'] );
 244+ $property_hastype = array( 'p' => 'Has type', 'v' => $type );
 245+ // A URIResolver URI indicates that internal titles only are used and we have no Original URI available
 246+ if ( !RDFIOUtils::isURIResolverURI( $property_uri ) && !RDFIOUtils::isArcUntitledNode( $wikititle ) ) {
 247+ $property_origuri = $this->createOrigURIPropertyArray( $property_uri );
 248+ $property_equivuri = $this->createEquivURIPropertyArray( $property_uri );
 249+ $properties = array( $property_origuri, $property_equivuri, $property_hastype );
 250+ } else {
 251+ $properties = array( $property_hastype );
 252+ }
 253+ $propertypage = new RDFIOPageHandler( $wikititle, SMW_NS_PROPERTY, $properties );
 254+ $this->addToPages( $propertypage );
 255+ }
 256+
 257+ // Prepare value pages
 258+ // TODO: Look for a way to merge with the above code, or otherwise refactor ...
 259+ $unique_value_uris = $this->getUniqueValueURIs();
 260+ foreach ( $unique_value_uris as $unique_value_uri ) {
 261+ $wikititle = $this->getWikiTitleForURI( $unique_value_uri );
 262+
 263+ // A URIResolver URI indicates that internal titles only are used and we have no Original URI available
 264+ if ( !RDFIOUtils::isURIResolverURI( $unique_value_uri ) && !RDFIOUtils::isArcUntitledNode( $unique_value_uri ) ) {
 265+ $value_origuri = $this->createOrigURIPropertyArray( $unique_value_uri );
 266+ $value_equivuri = $this->createEquivURIPropertyArray( $unique_value_uri );
 267+ $values = array( $value_origuri, $value_equivuri );
 268+ }
 269+ $valuepage = new RDFIOPageHandler( $wikititle, NS_MAIN, $values );
 270+ $this->addToPages( $valuepage );
 271+ }
 272+ }
 273+ }
 274+
 275+ /**
 276+ * Write the pages, with corresponding facts, represented as page handlers, to the wiki
 277+ */
 278+ private function writePagesToWiki() {
 279+ global $wgOut;
 280+
 281+ $pages = $this->m_pages;
 282+ foreach ( $pages as $page ) {
 283+ $page->writeOrDeleteDataToWiki();
 284+ if ( $page->hasErrors() ) {
 285+ $errortitle = "Error for wikipage \"" . $page->getWikiTitleFull() . "\"</h3>";
 286+ $wgOut->addHTML( RDFIOUtils::formatErrorHTML( $errortitle, $page->getErrorText() ));
 287+ }
 288+ }
 289+ }
 290+
 291+ /**
 292+ * Delete the facts stored in page handlers, from the wiki
 293+ */
 294+ private function deletePageDataFromWiki() {
 295+ global $wgOut;
 296+
 297+ $pages = $this->m_pages;
 298+ foreach ( $pages as $page ) {
 299+ $page->deleteDataFromWiki();
 300+ if ( $page->hasErrors() ) {
 301+ $errortitle = "Error for wikipage \"" . $page->getWikiTitleFull() . "\"</h3>";
 302+ $wgOut->addHTML( RDFIOUtils::formatErrorHTML( $errortitle, $page->getErrorText() ));
 303+ }
 304+ }
 305+ }
 306+
 307+ /**
 308+ * Get generated triples from the ARC2 parser and store in object variable
 309+ */
 310+ private function extractTriples() {
 311+ $triples = $this->m_parser->getTriples();
 312+ $this->m_triples = $triples;
 313+ }
 314+
 315+ /**
 316+ * Get generated triple index from the ARC2 parser and store in object variable
 317+ */
 318+ private function extractTripleIndex() {
 319+ $this->m_tripleindex = ARC2::getSimpleIndex( $this->m_triples, false );
 320+ $this->m_tripleindexflat = ARC2::getSimpleIndex( $this->m_triples, true );
 321+ }
 322+
 323+ /**
 324+ * Add a page handler to the current SMWBatchWriter
 325+ * @param RDFIOPageHandler $page
 326+ */
 327+ private function addToPages( $page ) {
 328+ $this->m_pages[] = $page;
 329+ }
 330+
 331+ /**
 332+ * Get all triples with a given subject
 333+ * @param string $subjecturi
 334+ * @return array $triples
 335+ */
 336+ function getTriplesForSubject( $subjecturi ) {
 337+ $reconstructedIndex = array( $subjecturi => $this->m_tripleindex[$subjecturi]);
 338+ $triples = ARC2::getTriplesFromIndex( $reconstructedIndex );
 339+ return $triples;
 340+ }
 341+
 342+ /**
 343+ * Get a list of unique subject URI:s from the internally stored triple index
 344+ * @return array
 345+ */
 346+ function getUniqueSubjectURIs() {
 347+ return array_keys( $this->m_tripleindex );
 348+ }
 349+
 350+ /**
 351+ * Get a list of unique property URI:s and corresponding type info, from the
 352+ * internally stored triple index
 353+ * @return array $properties
 354+ */
 355+ function getUniquePropertyURIs() {
 356+ $tripleindex = $this->m_tripleindex;
 357+ $properties = array();
 358+ foreach( $tripleindex as $cur_props ) {
 359+ foreach( $cur_props as $cur_prop => $cur_propdata ) {
 360+ $properties[$cur_prop] = array(
 361+ 'type' => $cur_propdata[0]['type'],
 362+ 'datatype' => $cur_propdata[0]['datatype']
 363+ ); // Only the type info is interesting here
 364+ }
 365+ }
 366+ return $properties;
 367+ }
 368+
 369+ /**
 370+ * Get an array of unique URIs occuring as values in imported data
 371+ * @return array $value_uris
 372+ */
 373+ function getUniqueValueURIs() {
 374+ $tripleindex = $this->m_tripleindex;
 375+ $value_uris_data = array();
 376+ foreach( $tripleindex as $cur_props ) {
 377+ foreach( $cur_props as $cur_prop => $cur_propdatas ) {
 378+ foreach ( $cur_propdatas as $cur_propdata ) {
 379+ $value = $cur_propdata['value'];
 380+ $valuetype = $cur_propdata['type'];
 381+ $valuedatatype = $cur_propdata['datatype'];
 382+ if ( $valuetype == 'uri' ) {
 383+ $value_uris_data[$value] = array(
 384+ 'type' => $valuetype,
 385+ 'datatype' => $valuedatatype
 386+ );
 387+ }
 388+ }
 389+ }
 390+ }
 391+ $value_uris = array_keys( $value_uris_data );
 392+ return $value_uris;
 393+ }
 394+
 395+ /**
 396+ * Create a property array with "Original URI" as property,
 397+ * and $uri as subject
 398+ * @param string $uri
 399+ * @return array $origuripropertyarray
 400+ */
 401+ function createOrigURIPropertyArray( $uri ) {
 402+ $origuripropertyarray = array(
 403+ 'p' => 'Original URI',
 404+ 'v' => $uri );
 405+ return $origuripropertyarray;
 406+ }
 407+
 408+ /**
 409+ * Create a property array with "Equivalent URI" as property,
 410+ * and $uri as subject
 411+ * @param string $uri
 412+ * @return array $equivuripropertyarray
 413+ */
 414+ function createEquivURIPropertyArray( $uri ) {
 415+ $equivuripropertyarray = array(
 416+ 'p' => 'Equivalent URI',
 417+ 'v' => $uri );
 418+ return $equivuripropertyarray;
 419+ }
 420+
 421+ /**
 422+ * Convert an entity type identifier used by ARC, to one used by SMW
 423+ * (Example: "uri" --> "Page")
 424+ * @param string $arctype
 425+ * @param string $arcdatatype
 426+ *
 427+ */
 428+ function convertARCTypeToSMWType( $arctype, $arcdatatype ) {
 429+ if ( $arctype == 'uri' ) {
 430+ return 'Page';
 431+ } else if ( $arctype == 'literal' ) {
 432+ if ( $arcdatatype == 'http://www.w3.org/2001/XMLSchema#decimal' ) {
 433+ return 'Number';
 434+ } else {
 435+ return 'String';
 436+ }
 437+ } else {
 438+ $this->addError('Unknown entity type in SMWBatchWriter.php:convertARCTypeToSMWType');
 439+ }
 440+ // TODO: Expand with more options
 441+ }
 442+
 443+ /**
 444+ * Get the currently configured namespace prefix mapping
 445+ * @return array
 446+ */
 447+ function getNSPrefixMapping() {
 448+ return $this->m_nsprefixes;
 449+ }
 450+
 451+ /**
 452+ * Get from the ARC2 parser, an array index, of namespace prefixes, and the
 453+ * corresponding full namespaces.
 454+ * @return array
 455+ */
 456+ function getNSPrefixMappingFromParser() {
 457+ return $this->m_parser->nsp;
 458+ }
 459+
 460+ /**
 461+ * Cleanup some unfortunate combination of tags and linebreaks, that breaks the ARC2 parser
 462+ * @param string $xmldata
 463+ * @return boolean
 464+ */
 465+ private function cleanupXML( $xmldata ) {
 466+ // Cleaning up unfortunate line breaks, which tend to bread RDFXML parser
 467+ $xmldata = str_replace( ">\r\n", '>', $xmldata );
 468+ $xmldata = str_replace( ">\n", '>', $xmldata );
 469+ return $xmldata;
 470+ }
 471+
 472+ /**
 473+ * Add an $errormessage to the objects current errors
 474+ * @param unknown_type $errormessage
 475+ */
 476+ private function addError( $errormessage ) {
 477+ $this->m_errors[] = $errormessage;
 478+ $this->m_haserrors = true;
 479+ }
 480+
 481+ /**
 482+ * Check if current object contains errors
 483+ * @return boolean
 484+ */
 485+ public function hasErrors() {
 486+ return $this->m_haserrors;
 487+ }
 488+
 489+
 490+ /**
 491+ * Get an array with current errors
 492+ * @return array
 493+ */
 494+ public function getErrors( ) {
 495+ return $this->m_errors;
 496+ }
 497+
 498+ /**
 499+ * Get a textual representation of current errors
 500+ * @return string $errortext
 501+ */
 502+ public function getErrorText() {
 503+ $errors = $this->m_errors;
 504+ $errortext = '';
 505+ $i = 1;
 506+ foreach ( $errors as $error ) {
 507+ $errortext .= "$error\n";
 508+ $i++;
 509+ }
 510+ return $errortext;
 511+ }
 512+
 513+
 514+ ///////////// PREVIOUSLY THE EQUIV URI CLASS //////////////////////
 515+
 516+
 517+ /**
 518+ * Takes an ARC2 ns prefix mapping array and stores in class variable
 519+ * @param array $nsprefixmapping
 520+ */
 521+ public function setNSPrefixes( $nsprefixmapping ) {
 522+ $this->m_nsprefixes = $nsprefixmapping;
 523+ }
 524+
 525+ /**
 526+ * Takes an ARC2 triple index and stores in class variable
 527+ * @param array $tripleindex
 528+ */
 529+ public function setTripleIndex( $tripleindex ) {
 530+ $this->m_tripleindex = $tripleindex;
 531+ }
 532+
 533+ /**
 534+ * Converts a (full) URI into a string suitable for use as wiki title
 535+ * @param string $uri
 536+ * @param boolean $isproperty
 537+ * @return string $wikititle
 538+ */
 539+ public function getWikiTitleForURI( $uri, $isproperty = false ) {
 540+ // URI resolver URIs should never be used as original URI, and therefore is not
 541+ // checked for.
 542+ if ( !RDFIOUtils::isURIResolverURI( $uri ) ) {
 543+ $titleByStoredOriginalUri = $this->getWikiTitleByStoredOriginalUri( $uri );
 544+ }
 545+
 546+ if ( $titleByStoredOriginalUri != '' ) {
 547+ $wikititle = $titleByStoredOriginalUri;
 548+ } else {
 549+ $titlebypropertyuriindex = $this->getWikiTitleByPropertyURIIndex( $uri );
 550+ if ( $titlebypropertyuriindex != '' ) {
 551+ $wikititle = $titlebypropertyuriindex;
 552+ } else if ( ( $this->m_usenspintitles_entities && !$isproperty ) ||
 553+ ( $this->m_usenspintitles_properties && $isproperty ) ){
 554+ $wikititle = $this->abbreviateNSFromURI( $uri );
 555+ } else {
 556+ $wikititle = RDFIOUtils::extractLabelFromURI( $uri );
 557+ }
 558+ $wikititle = RDFIOUtils::sanitizeWikiTitle( $wikititle );
 559+ }
 560+ if ( !RDFIOUtils::isURL( $wikititle ) ) {
 561+ $wikititle = ucfirst( $wikititle );
 562+ }
 563+ return $wikititle;
 564+ }
 565+
 566+ /**
 567+ * Check the wiki for an article with the $origuri set as "Original URI" through
 568+ * the "Original URI" property, and return the title of that article.
 569+ * @param string $origuri
 570+ * @return string $wikititle
 571+ */
 572+ public function getWikiTitleByStoredOriginalUri( $origuri ) {
 573+ $wikititle = $this->m_store->getWikiTitleByOriginalURI( $origuri );
 574+ return $wikititle;
 575+ }
 576+
 577+ /**
 578+ * Convert a namespace into its corresponding prefix, using prefix definitions
 579+ * submitted in imported RDF/XML, if available.
 580+ * @param string $ns
 581+ * @return string $prefix
 582+ */
 583+ function getPrefixForNS( $ns ) {
 584+ // Namespace prefis definitions are stored in the 'nsp' array
 585+ // of the (RDF/XML) parser object, since import.
 586+ $prefix = $this->m_nsprefixes[$ns];
 587+ if ( $prefix == '' ) $prefix = $ns;
 588+ return $prefix;
 589+ }
 590+
 591+ /**
 592+ * Use a "natural language" property, such as dc:title or similar, as wiki title
 593+ * @param string $subject
 594+ * @return string $title
 595+ */
 596+ function getWikiTitleByPropertyURIIndex( $subject ) {
 597+ // Looks through, in order, the uri:s in $this->m_wikititlepropertyuris
 598+ // to see if any of them is set for $subject. if so, return corresponding
 599+ // value as title.
 600+ $title = '';
 601+ foreach ( $this->m_wikititlepropertyuris as $wikititlepropertyuri ) {
 602+ $title = $this->m_tripleindex[$subject][$wikititlepropertyuri][0]['value'];
 603+ if ( $title != '' ) {
 604+ // When we have found a "$wikititlepropertyuri" that matches,
 605+ // return the value immediately
 606+ return $title;
 607+ }
 608+ }
 609+ return $title;
 610+ }
 611+
 612+ /**
 613+ * Abbreviate the base URI into a "pseudo-wiki-title-namespace"
 614+ * @param string $uri
 615+ * @return string $uri
 616+ */
 617+ public function abbreviateNSFromURI( $uri ) {
 618+ $prefixes = $this->m_nsprefixes;
 619+
 620+ foreach ( $prefixes as $ns => $prefix ) {
 621+ $nslength = strlen( $ns );
 622+ $uricontainsns = substr( $uri, 0, $nslength ) === $ns;
 623+ if ( $uricontainsns ) {
 624+ $basepart = $prefix;
 625+ $localpart = substr( $uri, $nslength );
 626+ }
 627+ }
 628+
 629+ if ( $basepart == '' && $localpart == '' ) {
 630+ $uriParts = RDFIOUtils::splitURI( $uri );
 631+ $basepart = $uriParts[0];
 632+ $localpart = $uriParts[1];
 633+ }
 634+
 635+ if ( $localpart == '' ) {
 636+ $uri = $basepart;
 637+ } else if ( substr($basepart, 0, 1) == '_' ) {
 638+ // Change ARC:s default "random string", to indicate more clearly that
 639+ // it lacks title
 640+ $uri = str_replace('arc','untitled',$localpart);
 641+ } else if ( substr($basepart, 0, 7) == 'http://' ) {
 642+ // If the abbreviation does not seem to have succeeded,
 643+ // fall back to use only the local part
 644+ $uri = $localpart;
 645+ } else if ( substr($basepart, -1) == ':' ) {
 646+ // Don't add another colon
 647+ $uri = $basepart . $localpart;
 648+ } else if ( $basepart == false || $basepart == '' ) {
 649+ $uri = $localpart;
 650+ } else {
 651+ $uri = $basepart . ':' . $localpart;
 652+ }
 653+
 654+ return $uri;
 655+ }
 656+
 657+ /**
 658+ * Abbreviate the base URI into a "pseudo-wiki-title-namespace"
 659+ * @param string $uri
 660+ * @return string $uri
 661+ */
 662+ public function abbreviateNSFromURIOld( $uri ) {
 663+ $uriParts = RDFIOUtils::splitURI( $uri );
 664+ $basepart = $uriParts[0];
 665+ $localpart = $uriParts[1];
 666+
 667+ if ( $localpart == '' ) {
 668+ $uri = $basepart;
 669+ } else if ( substr($basepart, 0, 1) == '_' ) {
 670+ // Change ARC:s default "random string", to indicate more clearly that
 671+ // it lacks title
 672+ $uri = str_replace('arc','untitled',$localpart);
 673+ } else {
 674+ $basepart = $this->getPrefixForNS($basepart);
 675+ if ( substr($basepart, 0, 7) == 'http://' ) {
 676+ // If the abbreviation does not seem to have succeeded,
 677+ // fall back to use only the local part
 678+ $uri = $localpart;
 679+ } else if ( substr($basepart, -1) == ':' ) {
 680+ // Don't add another colon
 681+ $uri = $basepart . $localpart;
 682+ } else {
 683+ $uri = $basepart . ':' . $localpart;
 684+ }
 685+ }
 686+ return $uri;
 687+ }
 688+
 689+ /**
 690+ * Set the object parameter whether to use namespace prefixes
 691+ * in wiki titles, for properties
 692+ * @param boolean $usenspintitles_properties
 693+ */
 694+ public function setUseNSPInTitlesForProperties( $usenspintitles_properties ) {
 695+ $this->m_usenspintitles_properties = $usenspintitles_properties;
 696+ }
 697+
 698+ /**
 699+ * Set the object parameter whether to use namespace prefixes
 700+ * in wiki titles, for entities (non-properties)
 701+ * @param boolean $usenspintitles_entities
 702+ */
 703+ public function setUseNSPInTitlesForEntities( $usenspintitles_entities ) {
 704+ $this->m_usenspintitles_entities = $usenspintitles_entities;
 705+ }
 706+}
Property changes on: trunk/extensions/RDFIO/classes/SMWBatchWriter.php
___________________________________________________________________
Added: svn:eol-style
1707 + native
Index: trunk/extensions/RDFIO/classes/RDFStore.php
@@ -0,0 +1,160 @@
 2+<?php
 3+
 4+/**
 5+ * RDFIOStore contains utility functionality that requires connecting to the
 6+ * ARC based RDF store
 7+ * @author samuel.lampa@gmail.com
 8+ * @package RDFIO
 9+ */
 10+class RDFIOStore {
 11+ protected $m_store;
 12+
 13+ function __construct() {
 14+ global $smwgARC2StoreConfig;
 15+ $this->m_arcstore = ARC2::getStore( $smwgARC2StoreConfig );
 16+ }
 17+
 18+ /**
 19+ * Get SMWs internal URI for the "Original URI" property used by RDFIO
 20+ * @return string
 21+ */
 22+ function getOrigURIURI() {
 23+ return $this->getURIResolverURI() . 'Property-3AOriginal_URI';
 24+ }
 25+
 26+ /**
 27+ * Get SMWs internal URI for corresponding to the "Equivalent URI" property
 28+ * @return string
 29+ */
 30+ function getEquivURIURI() {
 31+ return 'http://www.w3.org/2002/07/owl#sameAs';
 32+ }
 33+
 34+ /**
 35+ * Get SMWs internal URI for corresponding to the "Equivalent URI" property,
 36+ * for property pages
 37+ * @return string
 38+ */
 39+ function getEquivURIURIForProperty() {
 40+ return 'http://www.w3.org/2002/07/owl#equivalentProperty';
 41+ }
 42+
 43+ /**
 44+ * For a given RDF URI, return it's original URI, as defined in wiki articles
 45+ * by the "Original URI" property
 46+ * @param string $uri
 47+ * @return string $origuri
 48+ */
 49+ function getOrigURIForUri( $uri ) {
 50+ $origuri = '';
 51+ $store = $this->m_arcstore;
 52+ $origuriuri = $this->getOrigURIURI();
 53+ $q = "SELECT ?origuri WHERE { <$uri> <$origuriuri> ?origuri }";
 54+ $rs = $store->query($q);
 55+ if (!$store->getErrors()) {
 56+ $rows = $rs['result']['rows'];
 57+ $row = $rows[0];
 58+ $origuri = $row['origuri'];
 59+ } else {
 60+ die( "Error in ARC Store: " . print_r( $store->getErrors(), true ) );
 61+ }
 62+ return $origuri;
 63+ }
 64+
 65+ /**
 66+ * For a given RDF URI, return it's corresponding equivalend URIs
 67+ * as defined in wiki articles by the Equivalent URI property
 68+ * @param string $uri
 69+ * @param boolean $is_property
 70+ * @return array $equivuris
 71+ */
 72+ function getEquivURIsForURI( $uri, $is_property = false ) {
 73+ $equivuris = array();
 74+ $store = $this->m_arcstore;
 75+ if ( $is_property ) {
 76+ $equivuriuri = $this->getEquivURIURIForProperty();
 77+ } else {
 78+ $equivuriuri = $this->getEquivURIURI();
 79+ }
 80+ $q = "SELECT ?equivuri WHERE { <$uri> <$equivuriuri> ?equivuri }";
 81+ $rs = $store->query($q);
 82+ if (!$store->getErrors()) {
 83+ $equivuris = $rs['result']['rows'];
 84+ foreach ( $equivuris as $equivuriid => $equivuri ) {
 85+ $equivuris[$equivuriid] = $equivuri['equivuri'];
 86+ }
 87+ } else {
 88+ die( "Error in ARC Store: " . print_r( $store->getErrors(), true ) );
 89+ }
 90+ return $equivuris;
 91+ }
 92+
 93+ /**
 94+ * @param string $ouri
 95+ * @return string $uri
 96+ */
 97+ function getURIForOrigURI( $origuri ) {
 98+ $uri = '';
 99+ $store = $this->m_arcstore;
 100+ $origuriuri = $this->getOrigURIURI();
 101+ $q = "SELECT ?uri WHERE { ?uri <$origuriuri> <$origuri> }";
 102+ $rs = $store->query($q);
 103+ if (!$store->getErrors()) {
 104+ if ( $rs !== '' ) {
 105+ $rows = $rs['result']['rows'];
 106+ $row = $rows[0];
 107+ $uri = $row['uri'];
 108+ }
 109+ } else {
 110+ die( "Error in ARC Store: " . print_r( $store->getErrors(), true ) );
 111+ }
 112+ return $uri;
 113+ }
 114+
 115+ /**
 116+ * Given an Equivalent URI (ast defined in a wiki article, return the URI used by SMW
 117+ * @param string $equivuri
 118+ * @return string $uri
 119+ */
 120+ function getURIForEquivURI( $equivuri ) {
 121+ $uri = '';
 122+ $store = $this->m_arcstore;
 123+ $equivuriuri = $this->getEquivURIURI();
 124+ $q = "SELECT ?uri WHERE { ?uri <$equivuriuri> <$equivuri> }";
 125+ $rs = $store->query($q);
 126+ if (!$store->getErrors()) {
 127+ $rows = $rs['result']['rows'];
 128+ $row = $rows[0];
 129+ $uri = $row['uri'];
 130+ } else {
 131+ die( "Error in ARC Store: " . print_r( $store->getErrors(), true ) );
 132+ }
 133+ return $uri;
 134+ }
 135+
 136+ /**
 137+ * Get the base URI used by SMW to identify wiki articles
 138+ * @return string $uriresolveruri
 139+ */
 140+ function getURIResolverURI() {
 141+ $resolver = SpecialPage::getTitleFor( 'URIResolver' );
 142+ $uriresolveruri = $resolver->getFullURL() . '/';
 143+ return $uriresolveruri;
 144+ }
 145+
 146+ /**
 147+ * For a URI that is defined using the "Original URI" property, return the wiki
 148+ * article corresponding to that entity
 149+ * @param string $uri
 150+ * @return string $wikititle;
 151+ */
 152+ function getWikiTitleByOriginalURI( $uri ) {
 153+ $wikititleresolveruri = $this->getURIForOrigURI( $uri );
 154+ $resolveruri = $this->getURIResolverURI();
 155+ $wikititle = str_replace( $resolveruri, '', $wikititleresolveruri );
 156+ $wikititle = str_replace( 'Property-3A', '', $wikititle );
 157+ $wikititle = str_replace( 'Property:', '', $wikititle );
 158+ $wikititle = RDFIOUtils::unXmlifyUris( $wikititle );
 159+ return $wikititle;
 160+ }
 161+}
Property changes on: trunk/extensions/RDFIO/classes/RDFStore.php
___________________________________________________________________
Added: svn:eol-style
1162 + native

Status & tagging log