Search.php
Go to the documentation of this file.
00001 <?php 00002 00005 00027 class Search extends WebService 00028 { 00030 private $conneg; 00031 00033 private $dtdURL; 00034 00036 private $attributes = ""; 00037 00039 private $types = ""; 00040 00042 private $datasets = ""; 00043 00045 private $items = ""; 00046 00048 private $page = ""; 00049 00051 private $inference = ""; 00052 00054 private $requester_ip = ""; 00055 00057 private $registered_ip = ""; 00058 00060 private $query = ""; 00061 00063 private $namespaces = 00064 array ("http://www.w3.org/2002/07/owl#" => "owl", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" => "rdf", 00065 "http://www.w3.org/2000/01/rdf-schema#" => "rdfs", "http://purl.org/ontology/wsf#" => "wsf"); 00066 00067 00068 /* @brief The distance filter is a series of parameter that are used to 00069 filter records of the dataset according to the distance they 00070 are located from a given lat;long point. The values are 00071 seperated by a semi-column ";". The format is as follow: 00072 "lat;long;distance;distanceType". The distanceType can 00073 have two values "0" or "1": "0" means that the distance 00074 specified is in kilometers and "1" means that the distance 00075 specified is in miles. An example is: 00076 "-98.45;10.4324;5;0", which means getting all the results that 00077 are at maximum 5 kilometers from the lat/long position. 00078 */ 00079 private $distanceFilter; 00080 00081 /* @brief The range filter is a series of parameter that are used to 00082 filter records of the dataset according to a rectangle bounds 00083 they are located in given their lat;long position. The values are 00084 seperated by a semi-column ";". The format is as follow: 00085 "top-left-lat;top-left-long;bottom-right-lat;bottom-right-long;". 00086 */ 00087 private $rangeFilter; 00088 00090 public $subjectTriples = array(); // 00091 00093 public $objectTriples = array(); 00094 00096 public $resultset = array(); 00097 00099 public $resultsetObjectProperties = array(); 00100 00102 public $resultsetObjectPropertiesUris = array(); 00103 00105 public $aggregates = array(); 00106 00108 public $include_aggregates = array(); 00109 00111 public static $supportedSerializations = 00112 array ("application/json", "application/rdf+xml", "application/rdf+n3", "application/*", "text/xml", "text/*", 00113 "*/*"); 00114 00116 private $errorMessenger = 00117 '{ 00118 "ws": "/ws/search/", 00119 "_200": { 00120 "id": "WS-SEARCH-200", 00121 "level": "Warning", 00122 "name": "Invalid number of items requested", 00123 "description": "The number of items returned per request has to be greater than 0 and lesser than 128" 00124 }, 00125 "_300": { 00126 "id": "WS-SEARCH-300", 00127 "level": "Warning", 00128 "name": "No datasets accessible by that user", 00129 "description": "No datasets are accessible to that user" 00130 }, 00131 "_301": { 00132 "id": "WS-SEARCH-301", 00133 "level": "Warning", 00134 "name": "Not geo-enabled", 00135 "description": "The Search web service endpoint is not geo-enabled. Please modify your query such that it does not use any geo feature such as the distance_filter and the range_filter parameters." 00136 } 00137 00138 }'; 00139 00140 00183 function __construct($query, $types, $attributes, $datasets, $items, $page, $inference, $include_aggregates, 00184 $registered_ip, $requester_ip, $distanceFilter = "", $rangeFilter = "") 00185 { 00186 parent::__construct(); 00187 00188 $this->query = $query; 00189 00190 $this->attributes = $attributes; 00191 $this->items = $items; 00192 $this->page = $page; 00193 $this->inference = $inference; 00194 $this->includeAggregates = $include_aggregates; 00195 00196 $this->types = $types; 00197 $this->datasets = $datasets; 00198 00199 $this->distanceFilter = $distanceFilter; 00200 $this->rangeFilter = $rangeFilter; 00201 $this->distance = $distance; 00202 $this->distanceType = $distanceType; 00203 00204 $this->requester_ip = $requester_ip; 00205 00206 if($registered_ip == "") 00207 { 00208 $this->registered_ip = $requester_ip; 00209 } 00210 else 00211 { 00212 $this->registered_ip = $registered_ip; 00213 } 00214 00215 if(strtolower(substr($this->registered_ip, 0, 4)) == "self") 00216 { 00217 $pos = strpos($this->registered_ip, "::"); 00218 00219 if($pos !== FALSE) 00220 { 00221 $account = substr($this->registered_ip, $pos + 2, strlen($this->registered_ip) - ($pos + 2)); 00222 00223 $this->registered_ip = $requester_ip . "::" . $account; 00224 } 00225 else 00226 { 00227 $this->registered_ip = $requester_ip; 00228 } 00229 } 00230 00231 $this->uri = $this->wsf_base_url . "/wsf/ws/search/"; 00232 $this->title = "Search Web Service"; 00233 $this->crud_usage = new CrudUsage(FALSE, TRUE, FALSE, FALSE); 00234 $this->endpoint = $this->wsf_base_url . "/ws/search/"; 00235 00236 $this->dtdURL = "search/search.dtd"; 00237 00238 $this->errorMessenger = json_decode($this->errorMessenger); 00239 } 00240 00241 function __destruct() { parent::__destruct(); } 00242 00255 protected function validateQuery() 00256 { 00257 if(($this->distanceFilter != "" || $this->rangeFilter != "") && $this->geoEnabled === FALSE) 00258 { 00259 $this->conneg->setStatus(400); 00260 $this->conneg->setStatusMsg("Bad Request"); 00261 $this->conneg->setStatusMsgExt($this->errorMessenger->_301->name); 00262 $this->conneg->setError($this->errorMessenger->_301->id, $this->errorMessenger->ws, 00263 $this->errorMessenger->_301->name, $this->errorMessenger->_301->description, "", 00264 $this->errorMessenger->_301->level); 00265 00266 return; 00267 } 00268 00269 // Here we can have a performance problem when "dataset = all" if we perform the authentication using AuthValidator. 00270 // Since AuthValidator doesn't support multiple datasets at the same time, we will use the AuthLister web service 00271 // in the process() function and check if the user has the permissions to "read" these datasets. 00272 // 00273 // This means that the validation of these queries doesn't happen at this level. 00274 } 00275 00286 public function pipeline_getError() { return ($this->conneg->error); } 00287 00288 00299 public function pipeline_getResultset() 00300 { 00301 $xml = new ProcessorXML(); 00302 00303 // Creation of the RESULTSET 00304 $resultset = $xml->createResultset(); 00305 00306 // Creation of the prefixes elements. 00307 $void = $xml->createPrefix("owl", "http://www.w3.org/2002/07/owl#"); 00308 $resultset->appendChild($void); 00309 $rdf = $xml->createPrefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); 00310 $resultset->appendChild($rdf); 00311 $dcterms = $xml->createPrefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); 00312 $resultset->appendChild($dcterms); 00313 $dcterms = $xml->createPrefix("wsf", "http://purl.org/ontology/wsf#"); 00314 $resultset->appendChild($dcterms); 00315 00316 $subject; 00317 00318 foreach($this->resultset as $uri => $result) 00319 { 00320 // Assigning types 00321 if(isset($result["type"])) 00322 { 00323 foreach($result["type"] as $key => $type) 00324 { 00325 if($key > 0) 00326 { 00327 if(array_search($type, $this->resultsetObjectPropertiesUris[$uri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"]) === FALSE) 00328 { 00329 $pred = $xml->createPredicate("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); 00330 $object = $xml->createObject("", $type); 00331 $pred->appendChild($object); 00332 $subject->appendChild($pred); 00333 } 00334 } 00335 else 00336 { 00337 $subject = $xml->createSubject($type, $uri); 00338 } 00339 } 00340 } 00341 else 00342 { 00343 $subject = $xml->createSubject("http://www.w3.org/2002/07/owl#Thing", $this->resourceUri); 00344 } 00345 00346 // Assigning the Dataset relationship 00347 if(isset($result["dataset"])) 00348 { 00349 $pred = $xml->createPredicate("http://purl.org/dc/terms/isPartOf"); 00350 $object = $xml->createObject("http://rdfs.org/ns/void#Dataset", $result["dataset"]); 00351 $pred->appendChild($object); 00352 $subject->appendChild($pred); 00353 } 00354 00355 // Assigning the preferred label relationship 00356 if(isset($result["prefLabel"])) 00357 { 00358 $pred = $xml->createPredicate(Namespaces::$iron . "prefLabel"); 00359 $object = $xml->createObjectContent($result["prefLabel"]); 00360 $pred->appendChild($object); 00361 $subject->appendChild($pred); 00362 } 00363 00364 // Assigning the alternative label relationship 00365 if(isset($result["altLabel"])) 00366 { 00367 foreach($result["altLabel"] as $altLabel) 00368 { 00369 $pred = $xml->createPredicate(Namespaces::$iron . "altLabel"); 00370 $object = $xml->createObjectContent($altLabel); 00371 $pred->appendChild($object); 00372 $subject->appendChild($pred); 00373 } 00374 } 00375 00376 // Assigning the description relationship 00377 if(isset($result["description"])) 00378 { 00379 $pred = $xml->createPredicate(Namespaces::$iron . "description"); 00380 $object = $xml->createObjectContent($result["description"]); 00381 $pred->appendChild($object); 00382 $subject->appendChild($pred); 00383 } 00384 00385 00386 // Assigning the Properties -> Literal relationships 00387 foreach($result as $property => $values) 00388 { 00389 if($property != "type" && $property != "dataset") 00390 { 00391 foreach($values as $value) 00392 { 00393 $pred = $xml->createPredicate($property); 00394 $object = $xml->createObjectContent($value); 00395 $pred->appendChild($object); 00396 $subject->appendChild($pred); 00397 } 00398 } 00399 } 00400 00401 // Assigning object properties 00402 if(isset($this->resultsetObjectProperties[$uri])) 00403 { 00404 foreach($this->resultsetObjectProperties[$uri] as $property => $values) 00405 { 00406 if($property != "type" && $property != "dataset") 00407 { 00408 foreach($values as $key => $value) 00409 { 00410 $pred = $xml->createPredicate($property); 00411 00412 $object = $xml->createObject("", $this->resultsetObjectPropertiesUris[$uri][$property][$key], ""); 00413 $pred->appendChild($object); 00414 00415 $reify = $xml->createReificationStatement("wsf:objectLabel", $value); 00416 $object->appendChild($reify); 00417 00418 $subject->appendChild($pred); 00419 } 00420 } 00421 } 00422 } 00423 00424 $resultset->appendChild($subject); 00425 } 00426 00427 00428 // Include facet information 00429 00430 // Type 00431 00432 if(strtolower($this->includeAggregates) == "true") 00433 { 00434 $aggregatesUri = $this->uri . "aggregate/" . md5(microtime()); 00435 00436 $typeLabelsCounts = array(); 00437 00438 foreach($this->aggregates["type"] as $ftype => $fcount) 00439 { 00440 // If we have an inferred type, we use that count instead of the normal count. 00441 if(isset($this->aggregates["inferred_type"][$ftype])) 00442 { 00443 $fcount = $this->aggregates["inferred_type"][$ftype]; 00444 } 00445 00446 $subject = 00447 $xml->createSubject("http://purl.org/ontology/aggregate#Aggregate", $aggregatesUri . "/" . md5($ftype) . "/"); 00448 00449 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#property"); 00450 $object = $xml->createObject("", "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); 00451 $pred->appendChild($object); 00452 $subject->appendChild($pred); 00453 00454 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#object"); 00455 $object = $xml->createObject("", $ftype); 00456 $pred->appendChild($object); 00457 $subject->appendChild($pred); 00458 00459 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#count"); 00460 $object = $xml->createObjectContent($fcount); 00461 $pred->appendChild($object); 00462 $subject->appendChild($pred); 00463 00464 $resultset->appendChild($subject); 00465 00466 $typeLabelsCounts = array(); 00467 } 00468 00469 // For each inferred type that have been left so far, we re-introduce them in the aggregates 00470 foreach($this->aggregates["inferred_type"] as $ftype => $fcount) 00471 { 00472 // If we have an inferred type, we use that count instead of the normal count. 00473 if(!isset($this->aggregates["type"][$ftype])) 00474 { 00475 $subject = $xml->createSubject("http://purl.org/ontology/aggregate#Aggregate", 00476 $aggregatesUri . "/" . md5($ftype) . "/"); 00477 00478 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#property"); 00479 $object = $xml->createObject("", "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); 00480 $pred->appendChild($object); 00481 $subject->appendChild($pred); 00482 00483 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#object"); 00484 $object = $xml->createObject("", $ftype); 00485 $pred->appendChild($object); 00486 $subject->appendChild($pred); 00487 00488 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#count"); 00489 $object = $xml->createObjectContent($fcount); 00490 $pred->appendChild($object); 00491 $subject->appendChild($pred); 00492 00493 $resultset->appendChild($subject); 00494 } 00495 } 00496 00497 // Dataset 00498 00499 $aggregatesUri = $this->uri . "aggregate/" . md5(microtime()); 00500 00501 foreach($this->aggregates["dataset"] as $ftype => $fcount) 00502 { 00503 $subject = 00504 $xml->createSubject("http://purl.org/ontology/aggregate#Aggregate", $aggregatesUri . "/" . md5($ftype) . "/"); 00505 00506 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#property"); 00507 $object = $xml->createObject("", "http://rdfs.org/ns/void#Dataset"); 00508 $pred->appendChild($object); 00509 $subject->appendChild($pred); 00510 00511 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#object"); 00512 $object = $xml->createObject("", $ftype); 00513 $pred->appendChild($object); 00514 $subject->appendChild($pred); 00515 00516 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#count"); 00517 $object = $xml->createObjectContent($fcount); 00518 $pred->appendChild($object); 00519 $subject->appendChild($pred); 00520 00521 $resultset->appendChild($subject); 00522 } 00523 00524 00525 // Attributes 00526 00527 $aggregatesUri = $this->uri . "aggregate/" . md5(microtime()); 00528 00529 foreach($this->aggregates["attributes"] as $ftype => $fcount) 00530 { 00531 $subject = 00532 $xml->createSubject("http://purl.org/ontology/aggregate#Aggregate", $aggregatesUri . "/" . md5($ftype) . "/"); 00533 00534 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#property"); 00535 $object = $xml->createObject("", "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"); 00536 $pred->appendChild($object); 00537 $subject->appendChild($pred); 00538 00539 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#object"); 00540 $object = $xml->createObject("", $ftype); 00541 $pred->appendChild($object); 00542 $subject->appendChild($pred); 00543 00544 $pred = $xml->createPredicate("http://purl.org/ontology/aggregate#count"); 00545 $object = $xml->createObjectContent($fcount); 00546 $pred->appendChild($object); 00547 $subject->appendChild($pred); 00548 00549 $resultset->appendChild($subject); 00550 } 00551 } 00552 00553 return ($this->injectDoctype($xml->saveXML($resultset))); 00554 } 00555 00568 public function injectDoctype($xmlDoc) 00569 { 00570 $posHeader = strpos($xmlDoc, '"?>') + 3; 00571 $xmlDoc = substr($xmlDoc, 0, $posHeader) 00572 . "\n<!DOCTYPE resultset PUBLIC \"-//Structured Dynamics LLC//Search DTD 0.1//EN\" \"" . $this->dtdBaseURL 00573 . $this->dtdURL . "\">" . substr($xmlDoc, $posHeader, strlen($xmlDoc) - $posHeader); 00574 00575 return ($xmlDoc); 00576 } 00577 00596 public function ws_conneg($accept, $accept_charset, $accept_encoding, $accept_language) 00597 { 00598 $this->conneg = 00599 new Conneg($accept, $accept_charset, $accept_encoding, $accept_language, Search::$supportedSerializations); 00600 00601 // Validate query 00602 $this->validateQuery(); 00603 00604 // If the query is still valid 00605 if($this->conneg->getStatus() == 200) 00606 { 00607 if($this->items < 0 || $this->items > 128) 00608 { 00609 $this->conneg->setStatus(400); 00610 $this->conneg->setStatusMsg("Bad Request"); 00611 $this->conneg->setStatusMsgExt($this->errorMessenger->_200->name); 00612 $this->conneg->setError($this->errorMessenger->_200->id, $this->errorMessenger->ws, 00613 $this->errorMessenger->_200->name, $this->errorMessenger->_200->description, "", 00614 $this->errorMessenger->_200->level); 00615 return; 00616 } 00617 } 00618 } 00619 00638 public function pipeline_conneg($accept, $accept_charset, $accept_encoding, $accept_language) 00639 { $this->ws_conneg($accept, $accept_charset, $accept_encoding, $accept_language); } 00640 00651 public function pipeline_getResponseHeaderStatus() { return $this->conneg->getStatus(); } 00652 00663 public function pipeline_getResponseHeaderStatusMsg() { return $this->conneg->getStatusMsg(); } 00664 00677 public function pipeline_getResponseHeaderStatusMsgExt() { return $this->conneg->getStatusMsgExt(); } 00678 00689 public function pipeline_serialize() 00690 { 00691 $rdf_part = ""; 00692 00693 switch($this->conneg->getMime()) 00694 { 00695 case "application/json": 00696 $json_part = ""; 00697 $xml = new ProcessorXML(); 00698 $xml->loadXML($this->pipeline_getResultset()); 00699 00700 $subjects = $xml->getSubjects(); 00701 00702 $nsId = 0; 00703 00704 foreach($subjects as $subject) 00705 { 00706 $subjectURI = $xml->getURI($subject); 00707 $subjectType = $xml->getType($subject); 00708 00709 $ns = $this->getNamespace($subjectType); 00710 00711 if(!isset($this->namespaces[$ns[0]])) 00712 { 00713 $this->namespaces[$ns[0]] = "ns" . $nsId; 00714 $nsId++; 00715 } 00716 00717 $json_part .= " { \n"; 00718 $json_part .= " \"uri\": \"" . parent::jsonEncode($subjectURI) . "\", \n"; 00719 $json_part .= " \"type\": \"" . parent::jsonEncode($this->namespaces[$ns[0]] . ":" . $ns[1]) 00720 . "\", \n"; 00721 00722 $predicates = $xml->getPredicates($subject); 00723 00724 $nbPredicates = 0; 00725 00726 foreach($predicates as $predicate) 00727 { 00728 $objects = $xml->getObjects($predicate); 00729 00730 foreach($objects as $object) 00731 { 00732 $nbPredicates++; 00733 00734 if($nbPredicates == 1) 00735 { 00736 $json_part .= " \"predicate\": [ \n"; 00737 } 00738 00739 $objectType = $xml->getType($object); 00740 $predicateType = $xml->getType($predicate); 00741 00742 if($objectType == "rdfs:Literal") 00743 { 00744 $objectValue = $xml->getContent($object); 00745 00746 $ns = $this->getNamespace($predicateType); 00747 00748 if(!isset($this->namespaces[$ns[0]])) 00749 { 00750 $this->namespaces[$ns[0]] = "ns" . $nsId; 00751 $nsId++; 00752 } 00753 00754 $json_part .= " { \n"; 00755 $json_part .= " \"" . parent::jsonEncode($this->namespaces[$ns[0]] . ":" . $ns[1]) . "\": \"" 00756 . parent::jsonEncode($objectValue) . "\" \n"; 00757 $json_part .= " },\n"; 00758 } 00759 else 00760 { 00761 $objectURI = $xml->getURI($object); 00762 00763 $ns = $this->getNamespace($predicateType); 00764 00765 if(!isset($this->namespaces[$ns[0]])) 00766 { 00767 $this->namespaces[$ns[0]] = "ns" . $nsId; 00768 $nsId++; 00769 } 00770 00771 $json_part .= " { \n"; 00772 $json_part .= " \"" . parent::jsonEncode($this->namespaces[$ns[0]] . ":" . $ns[1]) 00773 . "\": { \n"; 00774 $json_part .= " \"uri\": \"" . parent::jsonEncode($objectURI) . "\",\n"; 00775 00776 // Check if there is a reification statement for this object. 00777 $reifies = $xml->getReificationStatements($object, "wsf:objectLabel"); 00778 00779 $nbReification = 0; 00780 00781 foreach($reifies as $reify) 00782 { 00783 $nbReification++; 00784 00785 if($nbReification > 0) 00786 { 00787 $json_part .= " \"reify\": [\n"; 00788 } 00789 00790 $json_part .= " { \n"; 00791 $json_part .= " \"type\": \"wsf:objectLabel\", \n"; 00792 $json_part .= " \"value\": \"" . parent::jsonEncode($xml->getValue($reify)) 00793 . "\" \n"; 00794 $json_part .= " },\n"; 00795 } 00796 00797 if($nbReification > 0) 00798 { 00799 $json_part = substr($json_part, 0, strlen($json_part) - 2) . "\n"; 00800 00801 $json_part .= " ]\n"; 00802 } 00803 else 00804 { 00805 $json_part = substr($json_part, 0, strlen($json_part) - 2) . "\n"; 00806 } 00807 00808 $json_part .= " } \n"; 00809 $json_part .= " },\n"; 00810 } 00811 } 00812 } 00813 00814 if(strlen($json_part) > 0) 00815 { 00816 $json_part = substr($json_part, 0, strlen($json_part) - 2) . "\n"; 00817 } 00818 00819 if($nbPredicates > 0) 00820 { 00821 $json_part .= " ]\n"; 00822 } 00823 00824 $json_part .= " },\n"; 00825 } 00826 00827 if(strlen($json_part) > 0) 00828 { 00829 $json_part = substr($json_part, 0, strlen($json_part) - 2) . "\n"; 00830 } 00831 00832 $json_header .= " \"prefixes\": [ \n"; 00833 $json_header .= " {\n"; 00834 $json_header .= " \"rdf\": \"http://www.w3.org/1999/02/22-rdf-syntax-ns#\",\n"; 00835 $json_header .= " \"wsf\": \"http://purl.org/ontology/wsf#\",\n"; 00836 00837 foreach($this->namespaces as $ns => $prefix) 00838 { 00839 $json_header .= " \"$prefix\": \"$ns\",\n"; 00840 } 00841 00842 if(strlen($json_header) > 0) 00843 { 00844 $json_header = substr($json_header, 0, strlen($json_header) - 2) . "\n"; 00845 } 00846 00847 $json_header .= " } \n"; 00848 $json_header .= " ],\n"; 00849 $json_header .= " \"resultset\": {\n"; 00850 $json_header .= " \"subject\": [\n"; 00851 $json_header .= $json_part; 00852 $json_header .= " ]\n"; 00853 $json_header .= " }\n"; 00854 00855 return ($json_header); 00856 break; 00857 00858 case "application/rdf+n3": 00859 00860 $xml = new ProcessorXML(); 00861 $xml->loadXML($this->pipeline_getResultset()); 00862 00863 $subjects = $xml->getSubjects(); 00864 00865 foreach($subjects as $subject) 00866 { 00867 $subjectURI = $xml->getURI($subject); 00868 $subjectType = $xml->getType($subject, FALSE); 00869 00870 $rdf_part .= "\n <$subjectURI> a <$subjectType> ;\n"; 00871 00872 $predicates = $xml->getPredicates($subject); 00873 00874 foreach($predicates as $predicate) 00875 { 00876 $objects = $xml->getObjects($predicate); 00877 00878 foreach($objects as $object) 00879 { 00880 $objectType = $xml->getType($object); 00881 $predicateType = $xml->getType($predicate, FALSE); 00882 $objectContent = $xml->getContent($object); 00883 00884 if($objectType == "rdfs:Literal") 00885 { 00886 $objectValue = $xml->getContent($object); 00887 $rdf_part .= " <$predicateType> \"\"\"" . str_replace(array( "\\" ), "\\\\", $objectValue) 00888 . "\"\"\" ;\n"; 00889 } 00890 else 00891 { 00892 $objectURI = $xml->getURI($object); 00893 $rdf_part .= " <$predicateType> <$objectURI> ;\n"; 00894 } 00895 } 00896 } 00897 00898 if(strlen($rdf_part) > 0) 00899 { 00900 $rdf_part = substr($rdf_part, 0, strlen($rdf_part) - 2) . ".\n"; 00901 } 00902 } 00903 00904 return ($rdf_part); 00905 break; 00906 00907 case "application/rdf+xml": 00908 $xml = new ProcessorXML(); 00909 $xml->loadXML($this->pipeline_getResultset()); 00910 00911 $subjects = $xml->getSubjects(); 00912 00913 $nsId = 0; 00914 00915 foreach($subjects as $subject) 00916 { 00917 $subjectURI = $xml->getURI($subject); 00918 $subjectType = $xml->getType($subject); 00919 00920 $ns1 = $this->getNamespace($subjectType); 00921 00922 if(!isset($this->namespaces[$ns1[0]])) 00923 { 00924 $this->namespaces[$ns1[0]] = "ns" . $nsId; 00925 $nsId++; 00926 } 00927 00928 $rdf_part .= "\n <" . $this->namespaces[$ns1[0]] . ":" . $ns1[1] . " rdf:about=\"". 00929 $this->xmlEncode($subjectURI)."\">\n"; 00930 00931 $predicates = $xml->getPredicates($subject); 00932 00933 foreach($predicates as $predicate) 00934 { 00935 $objects = $xml->getObjects($predicate); 00936 00937 foreach($objects as $object) 00938 { 00939 $objectType = $xml->getType($object); 00940 $predicateType = $xml->getType($predicate); 00941 00942 if($objectType == "rdfs:Literal") 00943 { 00944 $objectValue = $xml->getContent($object); 00945 00946 $ns = $this->getNamespace($predicateType); 00947 00948 if(!isset($this->namespaces[$ns[0]])) 00949 { 00950 $this->namespaces[$ns[0]] = "ns" . $nsId; 00951 $nsId++; 00952 } 00953 00954 $rdf_part .= " <" . $this->namespaces[$ns[0]] . ":" . $ns[1] . ">" 00955 . $this->xmlEncode($objectValue) . "</" . $this->namespaces[$ns[0]] . ":" . $ns[1] . ">\n"; 00956 } 00957 else 00958 { 00959 $objectURI = $xml->getURI($object); 00960 00961 $ns = $this->getNamespace($predicateType); 00962 00963 if(!isset($this->namespaces[$ns[0]])) 00964 { 00965 $this->namespaces[$ns[0]] = "ns" . $nsId; 00966 $nsId++; 00967 } 00968 00969 $rdf_part .= " <" . $this->namespaces[$ns[0]] . ":" . $ns[1] 00970 . " rdf:resource=\"".$this->xmlEncode($objectURI)."\" />\n"; 00971 } 00972 } 00973 } 00974 00975 $rdf_part .= " </" . $this->namespaces[$ns1[0]] . ":" . $ns1[1] . ">\n"; 00976 } 00977 00978 $rdf_header = "<rdf:RDF "; 00979 00980 foreach($this->namespaces as $ns => $prefix) 00981 { 00982 $rdf_header .= " xmlns:$prefix=\"$ns\""; 00983 } 00984 00985 $rdf_header .= ">\n\n"; 00986 00987 $rdf_part = $rdf_header . $rdf_part; 00988 00989 return ($rdf_part); 00990 break; 00991 } 00992 } 00993 01006 private function getNamespace($uri) 01007 { 01008 $pos = strrpos($uri, "#"); 01009 01010 if($pos !== FALSE) 01011 { 01012 return array (substr($uri, 0, $pos) . "#", substr($uri, $pos + 1, strlen($uri) - ($pos + 1))); 01013 } 01014 else 01015 { 01016 $pos = strrpos($uri, "/"); 01017 01018 if($pos !== FALSE) 01019 { 01020 return array (substr($uri, 0, $pos) . "/", substr($uri, $pos + 1, strlen($uri) - ($pos + 1))); 01021 } 01022 else 01023 { 01024 $pos = strpos($uri, ":"); 01025 01026 if($pos !== FALSE) 01027 { 01028 $nsUri = explode(":", $uri, 2); 01029 01030 foreach($this->namespaces as $uri2 => $prefix2) 01031 { 01032 $uri2 = urldecode($uri2); 01033 01034 if($prefix2 == $nsUri[0]) 01035 { 01036 return (array ($uri2, $nsUri[1])); 01037 } 01038 } 01039 01040 return explode(":", $uri, 2); 01041 } 01042 } 01043 } 01044 01045 return (FALSE); 01046 } 01047 01056 public function pipeline_serialize_reification() 01057 { 01058 $rdf_reification = ""; 01059 01060 switch($this->conneg->getMime()) 01061 { 01062 case "application/rdf+n3": 01063 $xml = new ProcessorXML(); 01064 $xml->loadXML($this->pipeline_getResultset()); 01065 01066 $subjects = $xml->getSubjects(); 01067 01068 $bnodeCounter = 0; 01069 01070 foreach($subjects as $subject) 01071 { 01072 $predicates = $xml->getPredicates($subject); 01073 01074 foreach($predicates as $predicate) 01075 { 01076 $predicateType = $xml->getType($predicate, FALSE); 01077 01078 $objects = $xml->getObjects($predicate); 01079 01080 foreach($objects as $object) 01081 { 01082 $reifies = $xml->getReificationStatementsByType($object, "wsf:objectLabel"); 01083 01084 foreach($reifies as $reify) 01085 { 01086 $rdf_reification .= "_:" . md5($xml->getURI($subject) . $predicateType . $xml->getURI($object)) 01087 . " a rdf:Statement ;\n"; 01088 $bnodeCounter++; 01089 $rdf_reification .= " rdf:subject <" . $xml->getURI($subject) . "> ;\n"; 01090 $rdf_reification .= " rdf:predicate <" . $predicateType . "> ;\n"; 01091 $rdf_reification .= " rdf:object <" . $xml->getURI($object) . "> ;\n"; 01092 $rdf_reification .= " wsf:objectLabel \"" . $xml->getValue($reify) . "\" .\n\n"; 01093 $bnodeCounter++; 01094 } 01095 } 01096 } 01097 } 01098 01099 return ($rdf_reification); 01100 01101 break; 01102 01103 case "application/rdf+xml": 01104 01105 $xml = new ProcessorXML(); 01106 $xml->loadXML($this->pipeline_getResultset()); 01107 01108 $subjects = $xml->getSubjects(); 01109 01110 foreach($subjects as $subject) 01111 { 01112 $predicates = $xml->getPredicates($subject); 01113 01114 foreach($predicates as $predicate) 01115 { 01116 $predicateType = $xml->getType($predicate, FALSE); 01117 01118 $objects = $xml->getObjects($predicate); 01119 01120 foreach($objects as $object) 01121 { 01122 $reifies = $xml->getReificationStatementsByType($object, "wsf:objectLabel"); 01123 01124 foreach($reifies as $reify) 01125 { 01126 $rdf_reification .= "<rdf:Statement rdf:about=\"" 01127 . md5($xml->getURI($subject) . $predicateType . $this->xmlEncode($xml->getURI($object))) . "\">\n"; 01128 $rdf_reification .= " <rdf:subject rdf:resource=\"" . $this->xmlEncode($xml->getURI($subject)) . 01129 "\" />\n"; 01130 $rdf_reification .= " <rdf:predicate rdf:resource=\"" . $this->xmlEncode($predicateType) . "\" />\n"; 01131 $rdf_reification .= " <rdf:object rdf:resource=\"" . $this->xmlEncode($xml->getURI($object)) . 01132 "\" />\n"; 01133 $rdf_reification .= " <wsf:objectLabel>" . $this->xmlEncode($xml->getValue($reify)) 01134 . "</wsf:objectLabel>\n"; 01135 $rdf_reification .= "</rdf:Statement> \n\n"; 01136 } 01137 } 01138 } 01139 } 01140 01141 return ($rdf_reification); 01142 01143 break; 01144 } 01145 } 01146 01157 public function ws_serialize() 01158 { 01159 switch($this->conneg->getMime()) 01160 { 01161 case "application/rdf+n3": 01162 $rdf_document = ""; 01163 $rdf_document .= "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n"; 01164 $rdf_document .= "@prefix wsf: <http://purl.org/ontology/wsf#> .\n"; 01165 01166 $rdf_document .= $this->pipeline_serialize(); 01167 01168 $rdf_document .= $this->pipeline_serialize_reification(); 01169 01170 return $rdf_document; 01171 break; 01172 01173 case "application/rdf+xml": 01174 $rdf_document = ""; 01175 $rdf_document .= "<?xml version=\"1.0\"?>\n"; 01176 01177 $rdf_document .= $this->pipeline_serialize(); 01178 01179 $rdf_document .= $this->pipeline_serialize_reification(); 01180 01181 $rdf_document .= "</rdf:RDF>"; 01182 01183 return $rdf_document; 01184 break; 01185 01186 case "application/json": 01187 $json_document = ""; 01188 $json_document .= "{\n"; 01189 $json_document .= $this->pipeline_serialize(); 01190 $json_document .= "}"; 01191 01192 return ($json_document); 01193 break; 01194 01195 case "text/xml": 01196 return $this->pipeline_getResultset(); 01197 break; 01198 } 01199 } 01200 01213 public function ws_respond($content) 01214 { 01215 // First send the header of the request 01216 $this->conneg->respond(); 01217 01218 // second, send the content of the request 01219 01220 // Make sure there is no error. 01221 if($this->conneg->getStatus() == 200) 01222 { 01223 echo $content; 01224 } 01225 01226 $this->__destruct(); 01227 } 01228 01229 01239 public function process() 01240 { 01241 // Make sure there was no conneg error prior to this process call 01242 if($this->conneg->getStatus() == 200) 01243 { 01244 $solr = new Solr($this->wsf_solr_core, $this->solr_host, $this->solr_port); 01245 01246 $solrQuery = ""; 01247 01248 // Get all datasets accessible to that user 01249 $accessibleDatasets = array(); 01250 01251 $ws_al = new AuthLister("access_user", "", $this->registered_ip, $this->wsf_local_ip); 01252 01253 $ws_al->pipeline_conneg($this->conneg->getAccept(), $this->conneg->getAcceptCharset(), 01254 $this->conneg->getAcceptEncoding(), $this->conneg->getAcceptLanguage()); 01255 01256 $ws_al->process(); 01257 01258 $xml = new ProcessorXML(); 01259 $xml->loadXML($ws_al->pipeline_getResultset()); 01260 01261 $accesses = $xml->getSubjectsByType("wsf:Access"); 01262 01263 foreach($accesses as $access) 01264 { 01265 $predicates = $xml->getPredicatesByType($access, "wsf:datasetAccess"); 01266 $objects = $xml->getObjects($predicates->item(0)); 01267 $datasetUri = $xml->getURI($objects->item(0)); 01268 01269 $predicates = $xml->getPredicatesByType($access, "wsf:read"); 01270 $objects = $xml->getObjects($predicates->item(0)); 01271 $read = $xml->getContent($objects->item(0)); 01272 01273 if(strtolower($read) == "true") 01274 { 01275 array_push($accessibleDatasets, $datasetUri); 01276 } 01277 } 01278 01279 unset($ws_al); 01280 01281 /* 01282 if registered_ip != requester_ip, this means that the query is sent by a registered system 01283 on the behalf of someone else. In this case, we want to make sure that that system 01284 (the one that send the actual query) has access to the same datasets. Otherwise, it means that 01285 it tries to personificate that registered_ip user. 01286 */ 01287 if($this->registered_ip != $this->requester_ip) 01288 { 01289 // Get all datasets accessible to that system 01290 $accessibleDatasetsSystem = array(); 01291 01292 $ws_al = new AuthLister("access_user", "", $this->requester_ip, $this->wsf_local_ip); 01293 01294 $ws_al->pipeline_conneg($this->conneg->getAccept(), $this->conneg->getAcceptCharset(), 01295 $this->conneg->getAcceptEncoding(), $this->conneg->getAcceptLanguage()); 01296 01297 $ws_al->process(); 01298 01299 $xml = new ProcessorXML(); 01300 $xml->loadXML($ws_al->pipeline_getResultset()); 01301 01302 $accesses = $xml->getSubjectsByType("wsf:Access"); 01303 01304 foreach($accesses as $access) 01305 { 01306 $predicates = $xml->getPredicatesByType($access, "wsf:datasetAccess"); 01307 $objects = $xml->getObjects($predicates->item(0)); 01308 $datasetUri = $xml->getURI($objects->item(0)); 01309 01310 $predicates = $xml->getPredicatesByType($access, "wsf:read"); 01311 $objects = $xml->getObjects($predicates->item(0)); 01312 $read = $xml->getContent($objects->item(0)); 01313 01314 if(strtolower($read) == "true") 01315 { 01316 array_push($accessibleDatasetsSystem, $datasetUri); 01317 } 01318 } 01319 01320 unset($ws_al); 01321 01322 /* 01323 Finally we use the intersection of the two set of dataset URIs as the list of accessible 01324 datasets to include for the query. 01325 */ 01326 $accessibleDatasets = array_intersect($accessibleDatasets, $accessibleDatasetsSystem); 01327 } 01328 01329 if(count($accessibleDatasets) <= 0) 01330 { 01331 $this->conneg->setStatus(400); 01332 $this->conneg->setStatusMsg("Bad Request"); 01333 $this->conneg->setStatusMsgExt($this->errorMessenger->_300->name); 01334 $this->conneg->setError($this->errorMessenger->_300->id, $this->errorMessenger->ws, 01335 $this->errorMessenger->_300->name, $this->errorMessenger->_300->description, "", 01336 $this->errorMessenger->_300->level); 01337 return; 01338 } 01339 01340 $queryParam = "*:*"; 01341 01342 if($this->query != "") 01343 { 01344 /* 01345 Check if characters of the Solr query language is used for this query. If some does, we *only* take 01346 them to create the query. 01347 */ 01348 $useLuceneSyntax = FALSE; 01349 $specialChars = array('"', 'AND', 'OR', '?', '*', '~', '+', '-', 'NOT', '&&', '||', '!', '^'); 01350 01351 foreach($specialChars as $char) 01352 { 01353 if(strpos($this->query, $char) !== FALSE) 01354 { 01355 $useLuceneSyntax = TRUE; 01356 break; 01357 } 01358 } 01359 01360 if(!$useLuceneSyntax) 01361 { 01362 $queryParam = "%22" . urlencode(implode(" +", explode(" ", $this->query))) . "%22~5"; 01363 } 01364 else 01365 { 01366 $queryParam = urlencode($this->query); 01367 } 01368 } 01369 01370 if(strtolower($this->datasets) == "all") 01371 { 01372 $datasetList = ""; 01373 01374 $solrQuery = "q=$queryParam&start=" . $this->page . "&rows=" . $this->items 01375 . (strtolower($this->includeAggregates) == "true" ? "&facet=true&facet.limit=-1&facet.field=type" . 01376 "&facet.field=attribute" . (strtolower($this->inference) == "on" ? "&facet.field=inferred_type" : "") . "&" . 01377 "facet.field=dataset&facet.mincount=1" : ""); 01378 01379 foreach($accessibleDatasets as $key => $dataset) 01380 { 01381 if($key == 0) 01382 { 01383 $solrQuery .= "&fq=dataset:%22" . urlencode($dataset) . "%22"; 01384 } 01385 else 01386 { 01387 $solrQuery .= " OR dataset:%22" . urlencode($dataset) . "%22"; 01388 } 01389 } 01390 } 01391 else 01392 { 01393 $datasets = explode(";", $this->datasets); 01394 01395 $solrQuery = "q=$queryParam&start=" . $this->page . "&rows=" . $this->items 01396 . (strtolower($this->includeAggregates) == "true" ? "&facet=true&facet.limit=-1&facet.field=type" . 01397 "&facet.field=attribute" . (strtolower($this->inference) == "on" ? "&facet.field=inferred_type" : "") . "&" . 01398 "facet.field=dataset&facet.mincount=1" : ""); 01399 01400 $solrQuery .= "&fq=dataset:%22%22"; 01401 01402 foreach($datasets as $dataset) 01403 { 01404 // Check if the dataset is accessible to the user 01405 if(array_search($dataset, $accessibleDatasets) !== FALSE) 01406 { 01407 // Decoding potentially encoded ";" characters 01408 $dataset = str_replace(array ("%3B", "%3b"), ";", $dataset); 01409 01410 $solrQuery .= " OR dataset:%22" . urlencode($dataset) . "%22"; 01411 } 01412 } 01413 } 01414 01415 if($this->types != "all") 01416 { 01417 // Lets include the information to facet per type. 01418 01419 $types = explode(";", $this->types); 01420 01421 $nbProcessed = 0; 01422 01423 foreach($types as $type) 01424 { 01425 // Decoding potentially encoded ";" characters 01426 $type = str_replace(array ("%3B", "%3b"), ";", $type); 01427 01428 if($nbProcessed == 0) 01429 { 01430 $solrQuery .= "&fq=type:%22" . urlencode($type) . "%22"; 01431 } 01432 else 01433 { 01434 $solrQuery .= " OR type:%22" . urlencode($type) . "%22"; 01435 } 01436 01437 $nbProcessed++; 01438 01439 if(strtolower($this->inference) == "on") 01440 { 01441 $solrQuery .= " OR inferred_type:%22" . urlencode($type) . "%22"; 01442 } 01443 } 01444 } 01445 01446 if($this->attributes != "all") 01447 { 01448 // Lets include the information to facet per type. 01449 01450 $attributes = explode(";", $this->attributes); 01451 01452 $nbProcessed = 0; 01453 01454 if(file_exists($this->fields_index_folder."fieldsIndex.srz")) 01455 { 01456 $indexedFields = unserialize(file_get_contents($this->fields_index_folder."fieldsIndex.srz")); 01457 } 01458 else 01459 { 01460 $indexedFields = array(); 01461 } 01462 01463 foreach($attributes as $attribute) 01464 { 01465 $attributeValue = explode("::", $attribute); 01466 $attribute = urldecode($attributeValue[0]); 01467 01468 if(isset($attributeValue[1]) && $attributeValue[1] != "") 01469 { 01470 // Fix the reference to some of the core attributes 01471 $coreAttr = FALSE; 01472 switch($attribute) 01473 { 01474 case Namespaces::$iron."prefLabel": 01475 $attribute = "prefLabel"; 01476 $coreAttr = TRUE; 01477 break; 01478 01479 case Namespaces::$iron."description": 01480 $attribute = "description"; 01481 $coreAttr = TRUE; 01482 break; 01483 01484 case Namespaces::$geonames."lat": 01485 $attribute = "lat"; 01486 $coreAttr = TRUE; 01487 break; 01488 01489 case Namespaces::$geonames."long": 01490 $attribute = "long"; 01491 $coreAttr = TRUE; 01492 break; 01493 01494 case Namespaces::$rdf."type": 01495 $attribute = "type"; 01496 $coreAttr = TRUE; 01497 break; 01498 01499 case Namespaces::$geonames."locatedIn": 01500 $attribute = "located_in"; 01501 $coreAttr = TRUE; 01502 break; 01503 } 01504 01505 // A filtering value as been defined for this attribute. 01506 $val = urldecode($attributeValue[1]); 01507 01508 if($nbProcessed == 0) 01509 { 01510 if($coreAttr) 01511 { 01512 $solrQuery .= "&fq=(".urlencode(urlencode($attribute)).":".urlencode($val).")"; 01513 } 01514 else 01515 { 01516 $solrQuery .= "&fq=("; 01517 01518 $addOR = FALSE; 01519 01520 // We have to detect if the fields are existing in Solr, otherwise Solr will throw 01521 // "undefined fields" errors, and there is no way to ignore them and process 01522 // the query anyway. 01523 if(array_search(urlencode($attribute), $indexedFields) !== FALSE) 01524 { 01525 $solrQuery .= "(".urlencode(urlencode($attribute)).":".urlencode($val).")"; 01526 $addOR = TRUE; 01527 } 01528 01529 if(array_search(urlencode($attribute."_attr"), $indexedFields) !== FALSE) 01530 { 01531 if($addOR) 01532 { 01533 $solrQuery .= " OR "; 01534 } 01535 01536 $solrQuery .= "(".urlencode(urlencode($attribute))."_attr:".urlencode($val).")"; 01537 $addOR = TRUE; 01538 } 01539 01540 if(array_search(urlencode($attribute."_attr_obj"), $indexedFields) !== FALSE) 01541 { 01542 if($addOR) 01543 { 01544 $solrQuery .= " OR "; 01545 } 01546 01547 $solrQuery .= "(".urlencode(urlencode($attribute))."_attr_obj:".urlencode($val).")"; 01548 $addOR = TRUE; 01549 } 01550 01551 $solrQuery .= ")"; 01552 } 01553 } 01554 else 01555 { 01556 if($coreAttr) 01557 { 01558 $solrQuery .= " AND (".urlencode(urlencode($attribute)).":".urlencode($val).")"; 01559 } 01560 else 01561 { 01562 $solrQuery .= " AND ("; 01563 01564 $addOR = FALSE; 01565 01566 // We have to detect if the fields are existing in Solr, otherwise Solr will throw 01567 // "undefined fields" errors, and there is no way to ignore them and process 01568 // the query anyway. 01569 if(array_search(urlencode($attribute), $indexedFields) !== FALSE) 01570 { 01571 $solrQuery .= "(".urlencode(urlencode($attribute)).":".urlencode($val).")"; 01572 $addOR = TRUE; 01573 } 01574 01575 if(array_search(urlencode($attribute."_attr"), $indexedFields) !== FALSE) 01576 { 01577 if($addOR) 01578 { 01579 $solrQuery .= " OR "; 01580 } 01581 01582 $solrQuery .= "(".urlencode(urlencode($attribute))."_attr:".urlencode($val).")"; 01583 $addOR = TRUE; 01584 } 01585 01586 if(array_search(urlencode($attribute."_attr_obj"), $indexedFields) !== FALSE) 01587 { 01588 if($addOR) 01589 { 01590 $solrQuery .= " OR "; 01591 } 01592 01593 $solrQuery .= "(".urlencode(urlencode($attribute))."_attr_obj:".urlencode($val).")"; 01594 $addOR = TRUE; 01595 } 01596 01597 $solrQuery .= ")"; 01598 } 01599 } 01600 } 01601 else 01602 { 01603 if($nbProcessed == 0) 01604 { 01605 $solrQuery .= "&fq=(attribute:%22" . urlencode($attribute) . "%22)"; 01606 } 01607 else 01608 { 01609 $solrQuery .= " AND (attribute:%22" . urlencode($attribute) . "%22)"; 01610 } 01611 } 01612 01613 $nbProcessed++; 01614 } 01615 } 01616 01617 // Check if this query is geo-enabled and if a distance-filter is requested 01618 if($this->geoEnabled && $this->distanceFilter != "") 01619 { 01620 /* 01621 $params[0] == latitude 01622 $params[1] == longitude 01623 $params[2] == distance 01624 $params[3] == (0) distance in kilometers, (1) distance in miles 01625 */ 01626 $params = explode(";", $this->distanceFilter); 01627 01628 $earthRadius = 6371; 01629 01630 if($params[3] == 1) 01631 { 01632 $earthRadius = 3963.205; 01633 } 01634 01635 $solrQuery .= "&fq={!frange l=0 u=".$params[2]."}hsin(".$params[0].",".$params[1]. 01636 " , lat_rad, long_rad, ".$earthRadius.")"; 01637 } 01638 01639 // Check if this query is geo-enabled and if a range-filter is requested 01640 if($this->geoEnabled && $this->rangeFilter != "") 01641 { 01642 /* 01643 $params[0] == latitude top-left 01644 $params[1] == longitude top-left 01645 $params[2] == latitude bottom-right 01646 $params[3] == longitude bottom-right 01647 */ 01648 $params = explode(";", $this->rangeFilter); 01649 01650 // Make sure the ranges are respected according to the way the cartesian coordinate 01651 // system works. 01652 $p1 = $params[0]; 01653 $p2 = $params[2]; 01654 $p3 = $params[1]; 01655 $p4 = $params[3]; 01656 01657 if($params[0] > $params[2]) 01658 { 01659 $p1 = $params[2]; 01660 $p2 = $params[0]; 01661 } 01662 01663 if($params[1] > $params[3]) 01664 { 01665 $p3 = $params[3]; 01666 $p4 = $params[1]; 01667 } 01668 01669 $solrQuery .= "&fq=lat:[".$p1." TO ".$p2."]&fq=long:[".$p3." TO ".$p4."]"; 01670 } 01671 01672 $resultset = $solr->select($solrQuery); 01673 01674 $domResultset = new DomDocument("1.0", "utf-8"); 01675 $domResultset->loadXML($resultset); 01676 01677 $xpath = new DOMXPath($domResultset); 01678 01679 // Get the number of results 01680 $founds = $xpath->query("*[@numFound]"); 01681 01682 foreach($founds as $found) 01683 { 01684 $nbResources = $found->attributes->getNamedItem("numFound")->nodeValue; 01685 break; 01686 } 01687 01688 // Get all the "type" facets with their counts 01689 $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='type']/int"); 01690 01691 // Get types counts 01692 01693 $this->aggregates["type"] = array(); 01694 01695 foreach($founds as $found) 01696 { 01697 $this->aggregates["type"][$found->attributes->getNamedItem("name")->nodeValue] = $found->nodeValue; 01698 } 01699 01700 // Get inferred types counts 01701 01702 if(strtolower($this->inference) == "on") 01703 { 01704 // Get all the "inferred_type" facets with their counts 01705 $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='inferred_type']/int"); 01706 01707 // Get types counts 01708 $this->aggregates["inferred_type"] = array(); 01709 01710 foreach($founds as $found) 01711 { 01712 $this->aggregates["inferred_type"][$found->attributes->getNamedItem("name")->nodeValue] = $found->nodeValue; 01713 } 01714 } 01715 01716 // Get all the "dataset" facets with their counts 01717 $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='dataset']/int"); 01718 01719 $this->aggregates["dataset"] = array(); 01720 01721 foreach($founds as $found) 01722 { 01723 $this->aggregates["dataset"][$found->attributes->getNamedItem("name")->nodeValue] = $found->nodeValue; 01724 } 01725 01726 01727 // Get all the "property" and "object_property" facets with their counts 01728 $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='attribute']/int"); 01729 01730 $this->aggregates["attributes"] = array(); 01731 01732 foreach($founds as $found) 01733 { 01734 $this->aggregates["attributes"][$found->attributes->getNamedItem("name")->nodeValue] = $found->nodeValue; 01735 } 01736 01737 01738 // Get all the results 01739 01740 $resultsDom = $xpath->query("//doc"); 01741 01742 foreach($resultsDom as $result) 01743 { 01744 // get URI 01745 $resultURI = $xpath->query("arr[@name='uri']/str", $result); 01746 01747 $uri = ""; 01748 01749 if($resultURI->length > 0) 01750 { 01751 $uri = $resultURI->item(0)->nodeValue; 01752 $this->resultset[$uri] = array(); 01753 } 01754 01755 // get Dataset URI 01756 $resultDatasetURI = $xpath->query("arr[@name='dataset']/str", $result); 01757 01758 $datasetUri = ""; 01759 01760 if($resultDatasetURI->length > 0) 01761 { 01762 $this->resultset[$uri]["dataset"] = $resultDatasetURI->item(0)->nodeValue; 01763 $datasetUri = $resultDatasetURI->item(0)->nodeValue; 01764 } 01765 01766 // get records preferred label 01767 $resultPrefLabelURI = $xpath->query("arr[@name='prefLabel']/str", $result); 01768 01769 if($resultPrefLabelURI->length > 0) 01770 { 01771 $this->resultset[$uri]["prefLabel"] = $resultPrefLabelURI->item(0)->nodeValue; 01772 } 01773 01774 // get records aternative labels 01775 $resultAltLabelURI = $xpath->query("arr[@name='altLabel']/str", $result); 01776 01777 for($i = 0; $i < $resultAltLabelURI->length; ++$i) 01778 { 01779 if(!isset($this->resultset[$uri]["altLabel"])) 01780 { 01781 $this->resultset[$uri]["altLabel"] = array($resultAltLabelURI->item($i)->nodeValue ); 01782 } 01783 else 01784 { 01785 array_push($this->resultset[$uri]["altLabel"], $resultAltLabelURI->item($i)->nodeValue); 01786 } 01787 } 01788 01789 foreach($resultAltLabelURI as $u) 01790 { 01791 if(!isset($this->resultset[$uri]["altLabel"])) 01792 { 01793 $this->resultset[$uri]["altLabel"] = array( $u->nodeValue ); 01794 } 01795 else 01796 { 01797 array_push($this->resultset[$uri]["altLabel"], $u->nodeValue); 01798 } 01799 } 01800 01801 // Get possible Lat/Long 01802 if($this->geoEnabled && ($this->rangeFilter != "" || $this->distanceFilter != "")) 01803 { 01804 // First check if there is a polygonCoordinates pr a polylineCoordinates attribute for that record 01805 // If there is one, then we simply ignore the lat/long coordinates since they come from these 01806 // attributes and that we don't want to duplicate that information. 01807 $skipLatLong == FALSE; 01808 01809 $resultPolygonCoordinates = $xpath->query("arr[@name='polygonCoordinates']/str", $result); 01810 01811 if($resultPolygonCoordinates->length > 0) 01812 { 01813 $this->resultset[$uri][Namespaces::$sco."polygonCoordinates"] = array($resultPolygonCoordinates->item(0)->nodeValue); 01814 $skipLatLong = TRUE; 01815 } 01816 01817 $resultPolylineCoordinates = $xpath->query("arr[@name='polylineCoordinates']/str", $result); 01818 01819 if($resultPolylineCoordinates->length > 0) 01820 { 01821 $this->resultset[$uri][Namespaces::$sco."polylineCoordinates"] = array($resultPolylineCoordinates->item(0)->nodeValue); 01822 $skipLatLong = TRUE; 01823 } 01824 01825 if(!$skipLatLong) 01826 { 01827 $resultDescriptionLat = $xpath->query("arr[@name='lat']/double", $result); 01828 01829 if($resultDescriptionLat->length > 0) 01830 { 01831 $this->resultset[$uri][Namespaces::$geo."lat"] = array($resultDescriptionLat->item(0)->nodeValue); 01832 } 01833 01834 $resultDescriptionLong = $xpath->query("arr[@name='long']/double", $result); 01835 01836 if($resultDescriptionLong->length > 0) 01837 { 01838 $this->resultset[$uri][Namespaces::$geo."long"] = array($resultDescriptionLong->item(0)->nodeValue); 01839 } 01840 } 01841 } 01842 01843 // get records description 01844 $resultDescriptionURI = $xpath->query("arr[@name='description']/str", $result); 01845 01846 if($resultDescriptionURI->length > 0) 01847 { 01848 $this->resultset[$uri]["description"] = $resultDescriptionURI->item(0)->nodeValue; 01849 } 01850 01851 // Get all dynamic fields attributes. 01852 $resultProperties = $xpath->query("arr", $result); 01853 01854 $tempProperties = array(); 01855 01856 foreach($resultProperties as $property) 01857 { 01858 $attribute = $property->getAttribute("name"); 01859 01860 // Check what kind of attribute it is 01861 $attributeType = ""; 01862 01863 if(($pos = stripos($attribute, "_reify")) !== FALSE) 01864 { 01865 $attributeType = substr($attribute, $pos, strlen($attribute) - $pos); 01866 } 01867 elseif(($pos = stripos($attribute, "_attr")) !== FALSE) 01868 { 01869 $attributeType = substr($attribute, $pos, strlen($attribute) - $pos); 01870 } 01871 01872 // Get the URI of the attribute 01873 $attributeURI = urldecode(str_replace($attributeType, "", $attribute)); 01874 01875 switch($attributeType) 01876 { 01877 case "_attr": 01878 $values = $property->getElementsByTagName("str"); 01879 01880 foreach($values as $value) 01881 { 01882 if(!isset($this->resultset[$uri][$attributeURI])) 01883 { 01884 $this->resultset[$uri][$attributeURI] = array( $value->nodeValue ); 01885 } 01886 else 01887 { 01888 array_push($this->resultset[$uri][$attributeURI], $value->nodeValue); 01889 } 01890 } 01891 break; 01892 01893 case "_attr_obj": 01894 $values = $property->getElementsByTagName("str"); 01895 01896 foreach($values as $value) 01897 { 01898 if(!isset($this->resultsetObjectProperties[$uri][$attributeURI])) 01899 { 01900 $this->resultsetObjectProperties[$uri][$attributeURI] = array( $value->nodeValue ); 01901 } 01902 else 01903 { 01904 array_push($this->resultsetObjectProperties[$uri][$attributeURI], $value->nodeValue); 01905 } 01906 } 01907 break; 01908 01909 case "_attr_obj_uri": 01910 $values = $property->getElementsByTagName("str"); 01911 01912 foreach($values as $value) 01913 { 01914 if(!isset($this->resultsetObjectPropertiesUris[$uri][$attributeURI])) 01915 { 01916 $this->resultsetObjectPropertiesUris[$uri][$attributeURI] = array( $value->nodeValue ); 01917 } 01918 else 01919 { 01920 array_push($this->resultsetObjectPropertiesUris[$uri][$attributeURI], $value->nodeValue); 01921 } 01922 } 01923 break; 01924 01925 case "_reify_attr": 01926 case "_reify_attr_obj": 01927 case "_reify_obj": 01928 case "_reify_value": break; 01929 } 01930 } 01931 01932 // Get the first type of the resource. 01933 $resultTypes = $xpath->query("arr[@name='type']/str", $result); 01934 01935 for($i = 0; $i < $resultTypes->length; ++$i) 01936 { 01937 if($resultTypes->item($i)->nodeValue != "-") 01938 { 01939 if(!isset($this->resultset[$uri]["type"])) 01940 { 01941 $this->resultset[$uri]["type"] = array( $resultTypes->item($i)->nodeValue ); 01942 } 01943 else 01944 { 01945 array_push($this->resultset[$uri]["type"], $resultTypes->item($i)->nodeValue); 01946 } 01947 } 01948 } 01949 } 01950 } 01951 } 01952 } 01953 01954 01956 01957 ?>
