CrudCreate.php
Go to the documentation of this file.
00001 <?php 00002 00005 00026 class CrudCreate extends WebService 00027 { 00029 private $db; 00030 00032 private $conneg; 00033 00035 private $dtdURL; 00036 00038 public static $supportedSerializations = 00039 array ("application/json", "application/rdf+xml", "application/rdf+n3", "application/*", "text/xml", "text/*", 00040 "*/*"); 00041 00043 private $registered_ip = ""; 00044 00046 private $dataset; 00047 00049 private $document = array(); 00050 00052 private $mime = ""; 00053 00055 private $requester_ip = ""; 00056 00058 private $errorMessenger = 00059 '{ 00060 "ws": "/ws/crud/create/", 00061 "_200": { 00062 "id": "WS-CRUD-CREATE-200", 00063 "level": "Notice", 00064 "name": "No RDF document to index", 00065 "description": "No RDF document has been defined for this query" 00066 }, 00067 "_201": { 00068 "id": "WS-CRUD-CREATE-201", 00069 "level": "Warning", 00070 "name": "Unknown MIME type for this RDF document", 00071 "description": "An unknown MIME type has been defined for this RDF document" 00072 }, 00073 "_202": { 00074 "id": "WS-CRUD-CREATE-202", 00075 "level": "Warning", 00076 "name": "No dataset specified", 00077 "description": "No dataset URI defined for this query" 00078 }, 00079 "_301": { 00080 "id": "WS-CRUD-CREATE-301", 00081 "level": "Warning", 00082 "name": "Can\'t parse RDF document", 00083 "description": "Can\'t parse the specified RDF document" 00084 }, 00085 "_302": { 00086 "id": "WS-CRUD-CREATE-302", 00087 "level": "Warning", 00088 "name": "Syntax error in the RDF document", 00089 "description": "A syntax error exists in the specified RDF document" 00090 }, 00091 "_303": { 00092 "id": "WS-CRUD-CREATE-303", 00093 "level": "Fatal", 00094 "name": "Can\'t update the Solr index", 00095 "description": "An error occured when we tried to update the Solr index" 00096 }, 00097 "_304": { 00098 "id": "WS-CRUD-CREATE-304", 00099 "level": "Fatal", 00100 "name": "Can\'t commit changes to the Solr index", 00101 "description": "An error occured when we tried to commit changes to the Solr index" 00102 }, 00103 "_305": { 00104 "id": "WS-CRUD-CREATE-305", 00105 "level": "Fatal", 00106 "name": "Can\'t create a tracking record for one of the input records", 00107 "description": "We can\'t create the records because we can\'t ensure that we have a track of their changes." 00108 } 00109 }'; 00110 00111 00130 function __construct($document, $mime, $mode, $dataset, $registered_ip, $requester_ip) 00131 { 00132 parent::__construct(); 00133 00134 $this->db = new DB_Virtuoso($this->db_username, $this->db_password, $this->db_dsn, $this->db_host); 00135 00136 $this->requester_ip = $requester_ip; 00137 $this->dataset = $dataset; 00138 00139 if (extension_loaded("mbstring") && mb_detect_encoding($document, "UTF-8", TRUE) != "UTF-8") 00140 { 00141 $this->document = utf8_encode($document); 00142 } 00143 else //we have to assume the input is UTF-8 00144 { 00145 $this->document = $document; 00146 } 00147 00148 00149 $this->mime = $mime; 00150 $this->mode = $mode; 00151 00152 if($registered_ip == "") 00153 { 00154 $this->registered_ip = $requester_ip; 00155 } 00156 else 00157 { 00158 $this->registered_ip = $registered_ip; 00159 } 00160 00161 if(strtolower(substr($this->registered_ip, 0, 4)) == "self") 00162 { 00163 $pos = strpos($this->registered_ip, "::"); 00164 00165 if($pos !== FALSE) 00166 { 00167 $account = substr($this->registered_ip, $pos + 2, strlen($this->registered_ip) - ($pos + 2)); 00168 00169 $this->registered_ip = $requester_ip . "::" . $account; 00170 } 00171 else 00172 { 00173 $this->registered_ip = $requester_ip; 00174 } 00175 } 00176 00177 $this->uri = $this->wsf_base_url . "/wsf/ws/crud/create/"; 00178 $this->title = "Crud Create Web Service"; 00179 $this->crud_usage = new CrudUsage(TRUE, FALSE, FALSE, FALSE); 00180 $this->endpoint = $this->wsf_base_url . "/ws/crud/create/"; 00181 00182 $this->dtdURL = "auth/CrudCreate.dtd"; 00183 00184 $this->errorMessenger = json_decode($this->errorMessenger); 00185 } 00186 00187 function __destruct() 00188 { 00189 parent::__destruct(); 00190 00191 if(isset($this->db)) 00192 { 00193 @$this->db->close(); 00194 } 00195 } 00196 00207 protected function validateQuery() 00208 { 00209 // Validation of the "requester_ip" to make sure the system that is sending the query as the rights. 00210 $ws_av = new AuthValidator($this->requester_ip, $this->dataset, $this->uri); 00211 00212 $ws_av->pipeline_conneg($this->conneg->getAccept(), $this->conneg->getAcceptCharset(), 00213 $this->conneg->getAcceptEncoding(), $this->conneg->getAcceptLanguage()); 00214 00215 $ws_av->process(); 00216 00217 if($ws_av->pipeline_getResponseHeaderStatus() != 200) 00218 { 00219 $this->conneg->setStatus($ws_av->pipeline_getResponseHeaderStatus()); 00220 $this->conneg->setStatusMsg($ws_av->pipeline_getResponseHeaderStatusMsg()); 00221 $this->conneg->setStatusMsgExt($ws_av->pipeline_getResponseHeaderStatusMsgExt()); 00222 $this->conneg->setError($ws_av->pipeline_getError()->id, $ws_av->pipeline_getError()->webservice, 00223 $ws_av->pipeline_getError()->name, $ws_av->pipeline_getError()->description, 00224 $ws_av->pipeline_getError()->debugInfo, $ws_av->pipeline_getError()->level); 00225 00226 return; 00227 } 00228 00229 unset($ws_av); 00230 00231 // If the system send a query on the behalf of another user, we validate that other user as well 00232 if($this->registered_ip != $this->requester_ip) 00233 { 00234 // Validation of the "registered_ip" to make sure the user of this system has the rights 00235 $ws_av = new AuthValidator($this->registered_ip, $this->dataset, $this->uri); 00236 00237 $ws_av->pipeline_conneg($this->conneg->getAccept(), $this->conneg->getAcceptCharset(), 00238 $this->conneg->getAcceptEncoding(), $this->conneg->getAcceptLanguage()); 00239 00240 $ws_av->process(); 00241 00242 if($ws_av->pipeline_getResponseHeaderStatus() != 200) 00243 { 00244 $this->conneg->setStatus($ws_av->pipeline_getResponseHeaderStatus()); 00245 $this->conneg->setStatusMsg($ws_av->pipeline_getResponseHeaderStatusMsg()); 00246 $this->conneg->setStatusMsgExt($ws_av->pipeline_getResponseHeaderStatusMsgExt()); 00247 $this->conneg->setError($ws_av->pipeline_getError()->id, $ws_av->pipeline_getError()->webservice, 00248 $ws_av->pipeline_getError()->name, $ws_av->pipeline_getError()->description, 00249 $ws_av->pipeline_getError()->debugInfo, $ws_av->pipeline_getError()->level); 00250 return; 00251 } 00252 } 00253 } 00254 00265 public function pipeline_getError() { return ($this->conneg->error); } 00266 00267 00278 public function pipeline_getResultset() { return ""; } 00279 00292 public function injectDoctype($xmlDoc) 00293 { 00294 $posHeader = strpos($xmlDoc, '"?>') + 3; 00295 $xmlDoc = substr($xmlDoc, 0, $posHeader) 00296 . "\n<!DOCTYPE resultset PUBLIC \"-//Structured Dynamics LLC//Crud Create DTD 0.1//EN\" \"" . $this->dtdBaseURL 00297 . $this->dtdURL . "\">" . substr($xmlDoc, $posHeader, strlen($xmlDoc) - $posHeader); 00298 00299 return ($xmlDoc); 00300 } 00301 00320 public function ws_conneg($accept, $accept_charset, $accept_encoding, $accept_language) 00321 { 00322 $this->conneg = 00323 new Conneg($accept, $accept_charset, $accept_encoding, $accept_language, CrudCreate::$supportedSerializations); 00324 00325 // Check for errors 00326 00327 if($this->document == "") 00328 { 00329 $this->conneg->setStatus(400); 00330 $this->conneg->setStatusMsg("Bad Request"); 00331 $this->conneg->setStatusMsgExt($this->errorMessenger->_200->name); 00332 $this->conneg->setError($this->errorMessenger->_200->id, $this->errorMessenger->ws, 00333 $this->errorMessenger->_200->name, $this->errorMessenger->_200->description, "", 00334 $this->errorMessenger->_200->level); 00335 return; 00336 } 00337 00338 if($this->mime != "application/rdf+xml" && $this->mime != "application/rdf+n3") 00339 { 00340 $this->conneg->setStatus(400); 00341 $this->conneg->setStatusMsg("Bad Request"); 00342 $this->conneg->setStatusMsgExt($this->errorMessenger->_201->name); 00343 $this->conneg->setError($this->errorMessenger->_201->id, $this->errorMessenger->ws, 00344 $this->errorMessenger->_201->name, $this->errorMessenger->_201->description, ($this->mime), 00345 $this->errorMessenger->_201->level); 00346 return; 00347 } 00348 00349 if($this->dataset == "") 00350 { 00351 $this->conneg->setStatus(400); 00352 $this->conneg->setStatusMsg("Bad Request"); 00353 $this->conneg->setStatusMsgExt($this->errorMessenger->_202->name); 00354 $this->conneg->setError($this->errorMessenger->_202->id, $this->errorMessenger->ws, 00355 $this->errorMessenger->_202->name, $this->errorMessenger->_202->description, "", 00356 $this->errorMessenger->_202->level); 00357 return; 00358 } 00359 00360 // Check if the dataset is created 00361 00362 $ws_dr = new DatasetRead($this->dataset, "false", "self", 00363 $this->wsf_local_ip); // Here the one that makes the request is the WSF (internal request). 00364 00365 $ws_dr->pipeline_conneg($this->conneg->getAccept(), $this->conneg->getAcceptCharset(), 00366 $this->conneg->getAcceptEncoding(), $this->conneg->getAcceptLanguage()); 00367 00368 $ws_dr->process(); 00369 00370 if($ws_dr->pipeline_getResponseHeaderStatus() != 200) 00371 { 00372 $this->conneg->setStatus($ws_dr->pipeline_getResponseHeaderStatus()); 00373 $this->conneg->setStatusMsg($ws_dr->pipeline_getResponseHeaderStatusMsg()); 00374 $this->conneg->setStatusMsgExt($ws_dr->pipeline_getResponseHeaderStatusMsgExt()); 00375 $this->conneg->setError($ws_dr->pipeline_getError()->id, $ws_dr->pipeline_getError()->webservice, 00376 $ws_dr->pipeline_getError()->name, $ws_dr->pipeline_getError()->description, 00377 $ws_dr->pipeline_getError()->debugInfo, $ws_dr->pipeline_getError()->level); 00378 return; 00379 } 00380 } 00381 00400 public function pipeline_conneg($accept, $accept_charset, $accept_encoding, $accept_language) 00401 { $this->ws_conneg($accept, $accept_charset, $accept_encoding, $accept_language); } 00402 00413 public function pipeline_getResponseHeaderStatus() { return $this->conneg->getStatus(); } 00414 00425 public function pipeline_getResponseHeaderStatusMsg() { return $this->conneg->getStatusMsg(); } 00426 00439 public function pipeline_getResponseHeaderStatusMsgExt() { return $this->conneg->getStatusMsgExt(); } 00440 00451 public function pipeline_serialize() { return ""; } 00452 00461 public function pipeline_serialize_reification() { return ""; } 00462 00473 public function ws_serialize() { return ""; } 00474 00487 public function ws_respond($content) 00488 { 00489 // First send the header of the request 00490 $this->conneg->respond(); 00491 00492 // second, send the content of the request 00493 00494 // Make sure there is no error. 00495 if($this->conneg->getStatus() == 200) 00496 { 00497 echo $content; 00498 } 00499 00500 $this->__destruct(); 00501 } 00502 00503 00512 public function process() 00513 { 00514 // Make sure there was no conneg error prior to this process call 00515 if($this->conneg->getStatus() == 200) 00516 { 00517 $this->validateQuery(); 00518 00519 // If the query is still valid 00520 if($this->conneg->getStatus() == 200) 00521 { 00522 // Get triples from ARC for some offline processing. 00523 $parser = ARC2::getRDFParser(); 00524 $parser->parse($this->dataset, $this->document); 00525 $rdfxmlSerializer = ARC2::getRDFXMLSerializer(); 00526 00527 $resourceIndex = $parser->getSimpleIndex(0); 00528 00529 if(count($parser->getErrors()) > 0) 00530 { 00531 $errorsOutput = ""; 00532 $errors = $parser->getErrors(); 00533 00534 foreach($errors as $key => $error) 00535 { 00536 $errorsOutput .= "[Error #$key] $error\n"; 00537 } 00538 00539 $this->conneg->setStatus(400); 00540 $this->conneg->setStatusMsg("Bad Request"); 00541 $this->conneg->setError($this->errorMessenger->_301->id, $this->errorMessenger->ws, 00542 $this->errorMessenger->_301->name, $this->errorMessenger->_301->description, $errorsOutput, 00543 $this->errorMessenger->_301->level); 00544 00545 return; 00546 } 00547 00548 // First: check for a void:Dataset description to add to the "dataset description graph" of structWSF 00549 $break = FALSE; 00550 $datasetUri; 00551 00552 foreach($resourceIndex as $resource => $description) 00553 { 00554 foreach($description as $predicate => $values) 00555 { 00556 if($predicate == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") 00557 { 00558 foreach($values as $value) 00559 { 00560 if($value["type"] == "uri" && $value["value"] == "http://rdfs.org/ns/void#Dataset") 00561 { 00562 $datasetUri = $resource; 00563 break; 00564 } 00565 } 00566 } 00567 00568 if($break) 00569 { 00570 break; 00571 } 00572 } 00573 00574 if($break) 00575 { 00576 break; 00577 } 00578 } 00579 00580 00581 // Second: get all the reification statements 00582 $break = FALSE; 00583 $statementsUri = array(); 00584 00585 foreach($resourceIndex as $resource => $description) 00586 { 00587 foreach($description as $predicate => $values) 00588 { 00589 if($predicate == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") 00590 { 00591 foreach($values as $value) 00592 { 00593 if($value["type"] == "uri" && $value["value"] == "http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement") 00594 { 00595 array_push($statementsUri, $resource); 00596 break; 00597 } 00598 } 00599 } 00600 00601 if($break) 00602 { 00603 break; 00604 } 00605 } 00606 00607 if($break) 00608 { 00609 break; 00610 } 00611 } 00612 00613 // Third, get all references of all instance records resources (except for the statement resources) 00614 $irsUri = array(); 00615 00616 foreach($resourceIndex as $resource => $description) 00617 { 00618 if($resource != $datasetUri && array_search($resource, $statementsUri) === FALSE) 00619 { 00620 array_push($irsUri, $resource); 00621 } 00622 } 00623 00624 // Fourth: Track the record description changes 00625 if($this->track_create === TRUE) 00626 { 00627 foreach($irsUri as $uri) 00628 { 00629 // First check if the record is already existing for this record, within this dataset. 00630 include_once("../read/CrudRead.php"); 00631 00632 $ws_cr = new CrudRead($uri, $this->dataset, FALSE, TRUE, $this->registered_ip, $this->requester_ip); 00633 00634 $ws_cr->ws_conneg("application/rdf+xml", "utf-8", "identity", "en"); 00635 00636 $ws_cr->process(); 00637 00638 $oldRecordDescription = $ws_cr->ws_serialize(); 00639 00640 $ws_cr_error = $ws_cr->pipeline_getError(); 00641 00642 if($ws_cr->pipeline_getResponseHeaderStatus() == 400 && $ws_cr_error->id == "WS-CRUD-READ-300") 00643 { 00644 // The record is not existing within this dataset, so we simply move-on 00645 continue; 00646 } 00647 elseif($ws_cr->pipeline_getResponseHeaderStatus() != 200) 00648 { 00649 // An error occured. Since we can't get the past state of a record, we have to send an error 00650 // for the CrudCreate call since we can't create a tracking record for this record. 00651 $this->conneg->setStatus(400); 00652 $this->conneg->setStatusMsg("Bad Request"); 00653 $this->conneg->setError($this->errorMessenger->_305->id, $this->errorMessenger->ws, 00654 $this->errorMessenger->_305->name, $this->errorMessenger->_305->description, 00655 "We can't create a track record for the following record: $uri", 00656 $this->errorMessenger->_305->level); 00657 00658 break; 00659 } 00660 00661 $endpoint = ""; 00662 if($this->tracking_endpoint != "") 00663 { 00664 // We send the query to a remove tracking endpoint 00665 $endpoint = $this->tracking_endpoint."create/"; 00666 } 00667 else 00668 { 00669 // We send the query to a local tracking endpoint 00670 $endpoint = $this->wsf_base_url."/ws/tracker/create/"; 00671 } 00672 00673 include_once("../../framework/WebServiceQuerier.php"); 00674 00675 $wsq = new WebServiceQuerier($endpoint, "post", 00676 "text/xml", "from_dataset=" . urlencode($this->dataset) . 00677 "&record=" . urlencode($uri) . 00678 "&action=create" . 00679 "&previous_state=" . urlencode($oldRecordDescription) . 00680 "&previous_state_mime=" . urlencode("application/rdf+xml") . 00681 "&performer=" . urlencode($this->registered_ip) . 00682 "®istered_ip=self"); 00683 00684 if($wsq->getStatus() != 200) 00685 { 00686 $this->conneg->setStatus($wsq->getStatus()); 00687 $this->conneg->setStatusMsg($wsq->getStatusMessage()); 00688 /* 00689 $this->conneg->setError($this->errorMessenger->_302->id, $this->errorMessenger->ws, 00690 $this->errorMessenger->_302->name, $this->errorMessenger->_302->description, odbc_errormsg(), 00691 $this->errorMessenger->_302->level); 00692 */ 00693 } 00694 00695 unset($wsq); 00696 } 00697 } 00698 00699 // If the query is still valid 00700 if($this->conneg->getStatus() == 200) 00701 { 00702 // Index all the instance records in the dataset 00703 if($this->mode == "full" || $this->mode == "triplestore") 00704 { 00705 $irs = array(); 00706 00707 foreach($irsUri as $uri) 00708 { 00709 $irs[$uri] = $resourceIndex[$uri]; 00710 } 00711 00712 $this->db->query("DB.DBA.RDF_LOAD_RDFXML_MT('" 00713 . str_replace("'", "\'", $rdfxmlSerializer->getSerializedIndex($irs)) . "', '" . $this->dataset . "', '" 00714 . $this->dataset . "')"); 00715 00716 if(odbc_error()) 00717 { 00718 $this->conneg->setStatus(400); 00719 $this->conneg->setStatusMsg("Bad Request"); 00720 $this->conneg->setError($this->errorMessenger->_302->id, $this->errorMessenger->ws, 00721 $this->errorMessenger->_302->name, $this->errorMessenger->_302->description, odbc_errormsg(), 00722 $this->errorMessenger->_302->level); 00723 00724 return; 00725 } 00726 00727 unset($irs); 00728 00729 // Index all the reification statements into the statements graph 00730 $statements = array(); 00731 00732 foreach($statementsUri as $uri) 00733 { 00734 $statements[$uri] = $resourceIndex[$uri]; 00735 } 00736 00737 $this->db->query("DB.DBA.RDF_LOAD_RDFXML_MT('" 00738 . str_replace("'", "\'", $rdfxmlSerializer->getSerializedIndex($statements)) . "', '" . $this->dataset 00739 . "reification/', '" . $this->dataset . "reification/')"); 00740 00741 if(odbc_error()) 00742 { 00743 $this->conneg->setStatus(400); 00744 $this->conneg->setStatusMsg("Bad Request"); 00745 $this->conneg->setError($this->errorMessenger->_302->id, $this->errorMessenger->ws, 00746 $this->errorMessenger->_302->name, $this->errorMessenger->_302->description, odbc_errormsg(), 00747 $this->errorMessenger->_302->level); 00748 return; 00749 } 00750 00751 unset($statements); 00752 00753 /* Link the dataset description of the file, by using the wsf:meta property, 00754 to its internal description (dataset graph description) 00755 */ 00756 if($datasetUri != "") 00757 { 00758 $datasetRes[$datasetUri] = $resourceIndex[$datasetUri]; 00759 00760 $datasetRes[$this->dataset] = 00761 array( "http://purl.org/ontology/wsf#meta" => array( array ("value" => $datasetUri, "type" => "uri") ) ); 00762 00763 $datasetDescription = $resourceIndex[$datasetRes]; 00764 00765 /* Make the link between the dataset description and its "meta" description (all other 00766 information than its basic description) 00767 */ 00768 $this->db->query("DB.DBA.RDF_LOAD_RDFXML_MT('" 00769 . str_replace("'", "\'", $rdfxmlSerializer->getSerializedIndex($datasetRes)) . "', '" . $this->wsf_graph 00770 . "datasets/', '" . $this->wsf_graph . "datasets/')"); 00771 00772 if(odbc_error()) 00773 { 00774 $this->conneg->setStatus(400); 00775 $this->conneg->setStatusMsg("Bad Request"); 00776 $this->conneg->setError($this->errorMessenger->_302->id, $this->errorMessenger->ws, 00777 $this->errorMessenger->_302->name, $this->errorMessenger->_302->description, "", 00778 $this->errorMessenger->_302->level); 00779 return; 00780 } 00781 00782 unset($datasetRes); 00783 } 00784 } 00785 00786 // Index everything in Solr 00787 if($this->mode == "full" || $this->mode == "searchindex") 00788 { 00789 $labelProperties = array (Namespaces::$iron . "prefLabel", Namespaces::$iron . "altLabel", 00790 Namespaces::$skos_2008 . "prefLabel", Namespaces::$skos_2008 . "altLabel", 00791 Namespaces::$skos_2004 . "prefLabel", Namespaces::$skos_2004 . "altLabel", Namespaces::$rdfs . "label", 00792 Namespaces::$dcterms . "title", Namespaces::$foaf . "name", Namespaces::$foaf . "givenName", 00793 Namespaces::$foaf . "family_name"); 00794 00795 $descriptionProperties = array (Namespaces::$iron . "description", Namespaces::$dcterms . "description", 00796 Namespaces::$skos_2008 . "definition", Namespaces::$skos_2004 . "definition"); 00797 00805 /* 00806 $resultset = $this->db->query("select * from SD.WSF.ws_ontologies where struct_type = 'class'"); 00807 00808 odbc_binmode($resultset, ODBC_BINMODE_PASSTHRU); 00809 odbc_longreadlen($resultset, 16384); 00810 00811 odbc_fetch_row($resultset); 00812 $classHierarchy = unserialize(odbc_result($resultset, "struct")); 00813 00814 if (odbc_error()) 00815 { 00816 $this->conneg->setStatus(500); 00817 $this->conneg->setStatusMsg("Internal Error"); 00818 $this->conneg->setStatusMsgExt("Error #crud-create-103"); 00819 return; 00820 } 00821 */ 00822 00823 $filename = rtrim($this->ontological_structure_folder, "/") . "/classHierarchySerialized.srz"; 00824 00825 $file = fopen($filename, "r"); 00826 $classHierarchy = fread($file, filesize($filename)); 00827 $classHierarchy = unserialize($classHierarchy); 00828 fclose($file); 00829 00830 // Index in Solr 00831 00832 $solr = new Solr($this->wsf_solr_core, $this->solr_host, $this->solr_port); 00833 00834 // Used to detect if we will be creating a new field. If we are, then we will 00835 // update the fields index once the new document will be indexed. 00836 $indexedFields = $solr->getFieldsIndex(); 00837 $newFields = FALSE; 00838 00839 foreach($irsUri as $subject) 00840 { 00841 // Skip Bnodes indexation in Solr 00842 // One of the prerequise is that each records indexed in Solr (and then available in Search and Browse) 00843 // should have a URI. Bnodes are simply skiped. 00844 00845 if(stripos($subject, "_:arc") !== FALSE) 00846 { 00847 continue; 00848 } 00849 00850 $add = "<add><doc><field name=\"uid\">" . md5($this->dataset . $subject) . "</field>"; 00851 $add .= "<field name=\"uri\">".$this->xmlEncode($subject)."</field>"; 00852 $add .= "<field name=\"dataset\">" . $this->dataset . "</field>"; 00853 00854 // Get types for this subject. 00855 $types = array(); 00856 00857 foreach($resourceIndex[$subject]["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"] as $value) 00858 { 00859 array_push($types, $value["value"]); 00860 00861 $add .= "<field name=\"type\">" . $this->xmlEncode($value["value"]) . "</field>"; 00862 } 00863 00864 // get the preferred and alternative labels for this resource 00865 $prefLabelFound = FALSE; 00866 00867 foreach($labelProperties as $property) 00868 { 00869 if(isset($resourceIndex[$subject][$property]) && !$prefLabelFound) 00870 { 00871 $prefLabelFound = TRUE; 00872 $add .= "<field name=\"prefLabel\">" . $this->xmlEncode($resourceIndex[$subject][$property][0]["value"]) 00873 . "</field>"; 00874 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$iron . "prefLabel") . "</field>"; 00875 } 00876 elseif(isset($resourceIndex[$subject][$property])) 00877 { 00878 foreach($resourceIndex[$subject][$property] as $value) 00879 { 00880 $add .= "<field name=\"altLabel\">" . $this->xmlEncode($value["value"]) . "</field>"; 00881 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$iron . "altLabel") . "</field>"; 00882 } 00883 } 00884 } 00885 00886 // get the description of the resource 00887 foreach($descriptionProperties as $property) 00888 { 00889 if(isset($resourceIndex[$subject][$property])) 00890 { 00891 $add .= "<field name=\"description\">" 00892 . $this->xmlEncode($resourceIndex[$subject][$property][0]["value"]) . "</field>"; 00893 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$iron . "description") . "</field>"; 00894 break; 00895 } 00896 } 00897 00898 // Add the prefURL if available 00899 if(isset($resourceIndex[$subject][$iron . "prefURL"])) 00900 { 00901 $add .= "<field name=\"prefURL\">" 00902 . $this->xmlEncode($resourceIndex[$subject][$iron . "prefURL"][0]["value"]) . "</field>"; 00903 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$iron . "prefURL") . "</field>"; 00904 } 00905 00906 // If enabled, and supported by the structWSF setting, let's add any lat/long positionning to the index. 00907 if($this->geoEnabled) 00908 { 00909 // Check if there exists a lat-long coordinate for that resource. 00910 if(isset($resourceIndex[$subject][Namespaces::$geo."lat"]) && 00911 isset($resourceIndex[$subject][Namespaces::$geo."long"])) 00912 { 00913 $lat = $resourceIndex[$subject][Namespaces::$geo."lat"][0]["value"]; 00914 $long = $resourceIndex[$subject][Namespaces::$geo."long"][0]["value"]; 00915 00916 // Add Lat/Long 00917 $add .= "<field name=\"lat\">". 00918 $this->xmlEncode($lat). 00919 "</field>"; 00920 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$geo."lat") . "</field>"; 00921 00922 $add .= "<field name=\"long\">". 00923 $this->xmlEncode($long). 00924 "</field>"; 00925 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$geo."long") . "</field>"; 00926 00927 // Add Lat/Long in radius 00928 00929 $add .= "<field name=\"lat_rad\">". 00930 $this->xmlEncode($lat * (pi() / 180)). 00931 "</field>"; 00932 00933 $add .= "<field name=\"long_rad\">". 00934 $this->xmlEncode($long * (pi() / 180)). 00935 "</field>"; 00936 00937 // Add hashcode 00938 00939 include_once("../../framework/geohash.php"); 00940 00941 $geohash = new Geohash(); 00942 00943 $add .= "<field name=\"geohash\">". 00944 $this->xmlEncode($geohash->encode($lat, $long)). 00945 "</field>"; 00946 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$sco."geohash") . "</field>"; 00947 00948 00949 // Add cartesian tiers 00950 00951 // Note: Cartesian tiers are not currently supported. The Lucene Java API 00952 // for this should be ported to PHP to enable this feature. 00953 } 00954 00955 $coordinates; 00956 00957 // Check if there is a polygonCoordinates property 00958 if(isset($resourceIndex[$subject][Namespaces::$sco."polygonCoordinates"])) 00959 { 00960 $polygonCoordinates = $resourceIndex[$subject][Namespaces::$sco."polygonCoordinates"][0]["value"]; 00961 $coordinates = explode(" ", $polygonCoordinates); 00962 00963 $add .= "<field name=\"polygonCoordinates\">". 00964 $this->xmlEncode($resourceIndex[$subject][Namespaces::$sco."polygonCoordinates"][0]["value"]). 00965 "</field>"; 00966 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$sco."polygonCoordinates") . "</field>"; 00967 } 00968 00969 // Check if there is a polylineCoordinates property 00970 if(isset($resourceIndex[$subject][Namespaces::$sco."polylineCoordinates"])) 00971 { 00972 $polylineCoordinates = $resourceIndex[$subject][Namespaces::$sco."polylineCoordinates"][0]["value"]; 00973 array_push($coordinates, explode(" ", $polygonCoordinates)); 00974 00975 $add .= "<field name=\"polylineCoordinates\">". 00976 $this->xmlEncode($resourceIndex[$subject][Namespaces::$sco."polylineCoordinates"][0]["value"]). 00977 "</field>"; 00978 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$sco."polylineCoordinates") . "</field>"; 00979 } 00980 00981 00982 if(count($coordinates) > 0) 00983 { 00984 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$geo."lat") . "</field>"; 00985 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$geo."long") . "</field>"; 00986 00987 foreach($coordinates as $key => $coordinate) 00988 { 00989 $points = explode(",", $coordinate); 00990 00991 if($points[0] != "" && $points[1] != "") 00992 { 00993 // Add Lat/Long 00994 $add .= "<field name=\"lat\">". 00995 $this->xmlEncode($points[1]). 00996 "</field>"; 00997 00998 $add .= "<field name=\"long\">". 00999 $this->xmlEncode($points[0]). 01000 "</field>"; 01001 01002 // Add altitude 01003 if(isset($points[2]) && $points[2] != "") 01004 { 01005 $add .= "<field name=\"alt\">". 01006 $this->xmlEncode($points[2]). 01007 "</field>"; 01008 if($key == 0) 01009 { 01010 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$geo."alt") . "</field>"; 01011 } 01012 } 01013 01014 // Add Lat/Long in radius 01015 01016 $add .= "<field name=\"lat_rad\">". 01017 $this->xmlEncode($points[1] * (pi() / 180)). 01018 "</field>"; 01019 01020 $add .= "<field name=\"long_rad\">". 01021 $this->xmlEncode($points[0] * (pi() / 180)). 01022 "</field>"; 01023 01024 // Add hashcode 01025 01026 include_once("../../framework/geohash.php"); 01027 01028 $geohash = new Geohash(); 01029 01030 $add .= "<field name=\"geohash\">". 01031 $this->xmlEncode($geohash->encode($points[1], $points[0])). 01032 "</field>"; 01033 01034 if($key == 0) 01035 { 01036 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$sco."geohash") . "</field>"; 01037 } 01038 01039 01040 // Add cartesian tiers 01041 01042 // Note: Cartesian tiers are not currently supported. The Lucene Java API 01043 // for this should be ported to PHP to enable this feature. 01044 } 01045 } 01046 } 01047 01048 // Check if there is any geonames:locatedIn assertion for that resource. 01049 if(isset($resourceIndex[$subject][Namespaces::$geonames."locatedIn"])) 01050 { 01051 $add .= "<field name=\"located_in\">". 01052 $this->xmlEncode($resourceIndex[$subject][Namespaces::$geonames."locatedIn"][0]["value"]). 01053 "</field>"; 01054 } 01055 01056 // Check if there is any wgs84_pos:alt assertion for that resource. 01057 if(isset($resourceIndex[$subject][Namespaces::$geo."alt"])) 01058 { 01059 $add .= "<field name=\"alt\">". 01060 $this->xmlEncode($resourceIndex[$subject][Namespaces::$geo."alt"][0]["value"]). 01061 "</field>"; 01062 $add .= "<field name=\"attribute\">" . $this->xmlEncode(Namespaces::$geo."alt") . "</field>"; 01063 } 01064 } 01065 01066 // Get properties with the type of the object 01067 01068 foreach($resourceIndex[$subject] as $predicate => $values) 01069 { 01070 if(array_search($predicate, $labelProperties) === FALSE && 01071 array_search($predicate, $descriptionProperties) === FALSE && 01072 $predicate != Namespaces::$iron."prefURL" && 01073 $predicate != Namespaces::$geo."long" && 01074 $predicate != Namespaces::$geo."lat" && 01075 $predicate != Namespaces::$geo."alt" && 01076 $predicate != Namespaces::$sco."polygonCoordinates" && 01077 $predicate != Namespaces::$sco."polylineCoordinates") // skip label & description & prefURL properties 01078 { 01079 foreach($values as $value) 01080 { 01081 if($value["type"] == "literal") 01082 { 01083 // Detect if the field currently exists in the fields index 01084 if(!$newFields && array_search(urlencode($predicate) . "_attr", $indexedFields) !== FALSE) 01085 { 01086 $newFields = TRUE; 01087 } 01088 01089 $add .= "<field name=\"" . urlencode($predicate) . "_attr\">" . $this->xmlEncode($value["value"]) 01090 . "</field>"; 01091 $add .= "<field name=\"attribute\">" . $this->xmlEncode($predicate) . "</field>"; 01092 01093 /* 01094 Check if there is a reification statement for that triple. If there is one, we index it in 01095 the index as: 01096 <property> <text> 01097 Note: Eventually we could want to update the Solr index to include a new "reifiedText" field. 01098 */ 01099 foreach($statementsUri as $statementUri) 01100 { 01101 if($resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#subject"][0]["value"] 01102 == $subject 01103 && $resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate"][0][ 01104 "value"] == $predicate 01105 && $resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#object"][0][ 01106 "value"] == $value["value"]) 01107 { 01108 foreach($resourceIndex[$statementUri] as $reiPredicate => $reiValues) 01109 { 01110 if($reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" 01111 && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#subject" 01112 && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate" 01113 && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#object") 01114 { 01115 foreach($reiValues as $reiValue) 01116 { 01117 if($reiValue["type"] == "literal") 01118 { 01119 // Attribute used to reify information to a statement. 01120 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_attr\">" 01121 . $this->xmlEncode($predicate) . 01122 "</field>"; 01123 01124 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_obj\">" 01125 . $this->xmlEncode($value["value"]) . 01126 "</field>"; 01127 01128 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_value\">" 01129 . $this->xmlEncode($reiValue["value"]) . 01130 "</field>"; 01131 01132 $add .= "<field name=\"attribute\">" . $this->xmlEncode($reiPredicate) . "</field>"; 01133 } 01134 } 01135 } 01136 } 01137 } 01138 } 01139 } 01140 elseif($value["type"] == "uri") 01141 { 01142 // Detect if the field currently exists in the fields index 01143 if(!$newFields && array_search(urlencode($predicate) . "_attr", $indexedFields) !== FALSE) 01144 { 01145 $newFields = TRUE; 01146 } 01147 01148 // If it is an object property, we want to bind labels of the resource referenced by that 01149 // object property to the current resource. That way, if we have "paul" -- know --> "bob", and the 01150 // user send a seach query for "bob", then "paul" will be returned as well. 01151 $query = $this->db->build_sparql_query("select ?p ?o from <" . $this->dataset . "> where {<" 01152 . $value["value"] . "> ?p ?o.}", array ('p', 'o'), FALSE); 01153 01154 $resultset3 = $this->db->query($query); 01155 01156 $subjectTriples = array(); 01157 01158 while(odbc_fetch_row($resultset3)) 01159 { 01160 $p = odbc_result($resultset3, 1); 01161 $o = odbc_result($resultset3, 2); 01162 01163 if(!isset($subjectTriples[$p])) 01164 { 01165 $subjectTriples[$p] = array(); 01166 } 01167 01168 array_push($subjectTriples[$p], $o); 01169 } 01170 01171 unset($resultset3); 01172 01173 // We allign all label properties values in a single string so that we can search over all of them. 01174 $labels = ""; 01175 01176 foreach($labelProperties as $property) 01177 { 01178 if(isset($subjectTriples[$property])) 01179 { 01180 $labels .= $subjectTriples[$property][0] . " "; 01181 } 01182 } 01183 01184 // Detect if the field currently exists in the fields index 01185 if(!$newFields && array_search(urlencode($predicate) . "_attr_obj", $indexedFields) !== FALSE) 01186 { 01187 $newFields = TRUE; 01188 } 01189 01190 01191 if($labels != "") 01192 { 01193 $add .= "<field name=\"" . urlencode($predicate) . "_attr_obj\">" . $this->xmlEncode($labels) 01194 . "</field>"; 01195 $add .= "<field name=\"" . urlencode($predicate) . "_attr_obj_uri\">" 01196 . $this->xmlEncode($value["value"]) . "</field>"; 01197 $add .= "<field name=\"attribute\">" . $this->xmlEncode($predicate) . "</field>"; 01198 } 01199 01200 /* 01201 Check if there is a reification statement for that triple. If there is one, we index it in the 01202 index as: 01203 <property> <text> 01204 Note: Eventually we could want to update the Solr index to include a new "reifiedText" field. 01205 */ 01206 $statementAdded = FALSE; 01207 01208 foreach($statementsUri as $statementUri) 01209 { 01210 if($resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#subject"][0]["value"] 01211 == $subject 01212 && $resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate"][0][ 01213 "value"] == $predicate 01214 && $resourceIndex[$statementUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#object"][0][ 01215 "value"] == $value["value"]) 01216 { 01217 foreach($resourceIndex[$statementUri] as $reiPredicate => $reiValues) 01218 { 01219 if($reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" 01220 && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#subject" 01221 && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate" 01222 && $reiPredicate != "http://www.w3.org/1999/02/22-rdf-syntax-ns#object") 01223 { 01224 foreach($reiValues as $reiValue) 01225 { 01226 if($reiValue["type"] == "literal") 01227 { 01228 // Attribute used to reify information to a statement. 01229 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_attr_obj\">" 01230 . $this->xmlEncode($predicate) . 01231 "</field>"; 01232 01233 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_obj\">" 01234 . $this->xmlEncode($value["value"]) . 01235 "</field>"; 01236 01237 $add .= "<field name=\"" . urlencode($reiPredicate) . "_reify_value\">" 01238 . $this->xmlEncode($reiValue["value"]) . 01239 "</field>"; 01240 01241 $add .= "<field name=\"attribute\">" . $this->xmlEncode($reiPredicate) . "</field>"; 01242 $statementAdded = TRUE; 01243 break; 01244 } 01245 } 01246 } 01247 01248 if($statementAdded) 01249 { 01250 break; 01251 } 01252 } 01253 } 01254 } 01255 } 01256 } 01257 } 01258 } 01259 01260 // Get all types by inference 01261 foreach($types as $type) 01262 { 01263 $superClasses = $classHierarchy->getSuperClasses($type); 01264 01265 foreach($superClasses as $sc) 01266 { 01267 $add .= "<field name=\"inferred_type\">" . $this->xmlEncode($sc->name) . "</field>"; 01268 } 01269 } 01270 01271 $add .= "</doc></add>"; 01272 01273 if(!$solr->update($add)) 01274 { 01275 $this->conneg->setStatus(500); 01276 $this->conneg->setStatusMsg("Internal Error"); 01277 $this->conneg->setError($this->errorMessenger->_303->id, $this->errorMessenger->ws, 01278 $this->errorMessenger->_303->name, $this->errorMessenger->_303->description, "", 01279 $this->errorMessenger->_303->level); 01280 return; 01281 } 01282 } 01283 01284 if($this->solr_auto_commit === FALSE) 01285 { 01286 if(!$solr->commit()) 01287 { 01288 $this->conneg->setStatus(500); 01289 $this->conneg->setStatusMsg("Internal Error"); 01290 $this->conneg->setError($this->errorMessenger->_304->id, $this->errorMessenger->ws, 01291 $this->errorMessenger->_304->name, $this->errorMessenger->_304->description, "", 01292 $this->errorMessenger->_304->level); 01293 return; 01294 } 01295 } 01296 01297 // Update the fields index if a new field as been detected. 01298 if($newFields) 01299 { 01300 $solr->updateFieldsIndex(); 01301 } 01302 } 01303 /* 01304 // Optimisation can be time consuming "on-the-fly" (which decrease user's experience) 01305 if(!$solr->optimize()) 01306 { 01307 $this->conneg->setStatus(500); 01308 $this->conneg->setStatusMsg("Internal Error"); 01309 $this->conneg->setStatusMsgExt("Error #crud-create-106"); 01310 return; 01311 } 01312 */ 01313 } 01314 } 01315 } 01316 } 01317 } 01318 01319 01321 01322 ?>
