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 '<' and '>' instead |
| 206 | + * @param string $instring |
| 207 | + * @return string $outstring |
| 208 | + */ |
| 209 | + function unhtmlify( $instring ) { |
| 210 | + $outstring = str_replace('<','<',$instring); |
| 211 | + $outstring = str_replace('>','>',$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 |
1 | 236 | + 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 |
1 | 9 | + 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 |
1 | 9 | + 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 |
1 | 74 | + 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 |
1 | 10 | + 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 |
1 | 9 | + 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 |
1 | 27 | + 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> </td> |
| 902 | + <td> </td> |
| 903 | + <td> </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 |
1 | 969 | + 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 |
1 | 10 | + 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 |
1 | 302 | + 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 |
1 | 27 | + 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 |
1 | 10 | + 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 |
1 | 27 | + 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 |
1 | 70 | + 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 |
1 | 202 | + 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 |
1 | 206 | + 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 |
1 | 252 | + 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 |
1 | 707 | + 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 |
1 | 162 | + native |