Example #1
0
$mtime = explode(' ', $mtime);
$mtime = $mtime[1] + $mtime[0];
$starttime = $mtime;
$start_datetime = date("Y-m-d h:i:s");
$requester_ip = "0.0.0.0";
if (isset($_SERVER['REMOTE_ADDR'])) {
    $requester_ip = $_SERVER['REMOTE_ADDR'];
}
$parameters = "";
if (isset($_SERVER['REQUEST_URI'])) {
    $parameters = $_SERVER['REQUEST_URI'];
    $pos = strpos($parameters, "?");
    if ($pos !== FALSE) {
        $parameters = substr($parameters, $pos, strlen($parameters) - $pos);
    }
} elseif (isset($_SERVER['PHP_SELF'])) {
    $parameters = $_SERVER['PHP_SELF'];
}
$ws_al = new AuthLister($mode, $dataset, $registered_ip, $requester_ip, $target_webservice, $interface, $version);
$ws_al->ws_conneg(isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : "", isset($_SERVER['HTTP_ACCEPT_CHARSET']) ? $_SERVER['HTTP_ACCEPT_CHARSET'] : "", isset($_SERVER['HTTP_ACCEPT_ENCODING']) ? $_SERVER['HTTP_ACCEPT_ENCODING'] : "", isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : "");
$ws_al->process();
$ws_al->ws_respond($ws_al->ws_serialize());
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$endtime = $mtime;
$totaltime = $endtime - $starttime;
if ($ws_al->isLoggingEnabled()) {
    $logger = new Logger("auth_lister", $requester_ip, "?mode=" . $mode . "&dataset=" . $dataset . "&registered_ip=" . $registered_ip . "&requester_ip={$requester_ip}", isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER[''] : "HTTP_ACCEPT", $start_datetime, $totaltime, $ws_al->pipeline_getResponseHeaderStatus(), isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER[''] : "HTTP_USER_AGENT");
}
//@}
 /** Update all ontological structures used by the WSF
 
         @author Frederick Giasson, Structured Dynamics LLC.
     */
 public function createOntology()
 {
     // Make sure there was no conneg error prior to this process call
     if ($this->ws->conneg->getStatus() == 200) {
         $this->ws->validateQuery();
         // If the query is still valid
         if ($this->ws->conneg->getStatus() == 200) {
             // Starts the OWLAPI process/bridge
             require_once $this->ws->owlapiBridgeURI;
             // Create the OWLAPI session object that could have been persisted on the OWLAPI instance.
             // Second param "false" => we re-use the pre-created session without destroying the previous one
             // third param "0" => it nevers timeout.
             $OwlApiSession = java_session("OWLAPI", false, 0);
             $register = java_values($OwlApiSession->get("ontologiesRegister"));
             // Check if the ontology is already existing
             if (!is_null(java_values($OwlApiSession->get($this->getOntologySessionID($this->ws->ontologyUri)))) || $register != NULL && array_search($this->getOntologySessionID($this->ws->ontologyUri), $register) !== FALSE) {
                 $this->ws->returnError(400, "Bad Request", "_302", "");
                 return;
             }
             try {
                 $ontology = new OWLOntology($this->ws->ontologyUri, $OwlApiSession, FALSE);
                 if (strtolower($this->ws->owlapiReasoner) == "pellet") {
                     $ontology->usePelletReasoner();
                 } elseif (strtolower($this->ws->owlapiReasoner) == "hermit") {
                     $ontology->useHermitReasoner();
                 } elseif (strtolower($this->ws->owlapiReasoner) == "factpp") {
                     $ontology->useFactppReasoner();
                 }
             } catch (Exception $e) {
                 $this->ws->returnError(400, "Bad Request", "_300", (string) java_values($e));
                 return;
             }
             // Get the description of the ontology
             $ontologyDescription = $ontology->getOntologyDescription();
             $ontologyName = $this->getLabel($this->ws->ontologyUri, $ontologyDescription);
             $ontologyDescription = $this->getDescription($ontologyDescription);
             // Get the list of webservices that will be accessible for this ontology dataset.
             $authLister = new AuthLister("ws", $this->ws->ontologyUri, $this->ws->requester_ip, $this->ws->wsf_local_ip);
             $authLister->pipeline_conneg($this->ws->conneg->getAccept(), $this->ws->conneg->getAcceptCharset(), $this->ws->conneg->getAcceptEncoding(), $this->ws->conneg->getAcceptLanguage());
             $authLister->process();
             if ($authLister->pipeline_getResponseHeaderStatus() != 200) {
                 $this->ws->conneg->setStatus($authLister->pipeline_getResponseHeaderStatus());
                 $this->ws->conneg->setStatusMsg($authLister->pipeline_getResponseHeaderStatusMsg());
                 $this->ws->conneg->setStatusMsgExt($authLister->pipeline_getResponseHeaderStatusMsgExt());
                 $this->ws->conneg->setError($authLister->pipeline_getError()->id, $authLister->pipeline_getError()->webservice, $authLister->pipeline_getError()->name, $authLister->pipeline_getError()->description, $authLister->pipeline_getError()->debugInfo, $authLister->pipeline_getError()->level);
                 return;
             }
             /* Get all web services */
             $webservices = "";
             $xml = new ProcessorXML();
             $xml->loadXML($authLister->pipeline_getResultset());
             $webServiceElements = $xml->getXPath('//predicate/object[attribute::type="wsf:WebService"]');
             foreach ($webServiceElements as $element) {
                 if (stristr($xml->getURI($element), "/wsf/ws/search/") !== FALSE || stristr($xml->getURI($element), "/wsf/ws/browse/") !== FALSE || stristr($xml->getURI($element), "/wsf/ws/sparql/") !== FALSE || stristr($xml->getURI($element), "/wsf/ws/crud/create/") !== FALSE || stristr($xml->getURI($element), "/wsf/ws/crud/update/") !== FALSE || stristr($xml->getURI($element), "/wsf/ws/crud/delete/") !== FALSE || stristr($xml->getURI($element), "/wsf/ws/crud/read/") !== FALSE || stristr($xml->getURI($element), "/wsf/ws/ontology/create/") !== FALSE || stristr($xml->getURI($element), "/wsf/ws/ontology/read/") !== FALSE || stristr($xml->getURI($element), "/wsf/ws/ontology/update/") !== FALSE || stristr($xml->getURI($element), "/wsf/ws/ontology/delete/") !== FALSE) {
                     $webservices .= $xml->getURI($element) . ";";
                 }
             }
             $webservices = rtrim($webservices, ";");
             unset($xml);
             unset($authLister);
             // Create a new dataset for this ontology
             $globalPermissions = "";
             if ($this->ws->globalPermissionCreate === FALSE) {
                 $globalPermissions .= "False;";
             } else {
                 $globalPermissions .= "True;";
             }
             if ($this->ws->globalPermissionRead === FALSE) {
                 $globalPermissions .= "False;";
             } else {
                 $globalPermissions .= "True;";
             }
             if ($this->ws->globalPermissionUpdate === FALSE) {
                 $globalPermissions .= "False;";
             } else {
                 $globalPermissions .= "True;";
             }
             if ($this->ws->globalPermissionDelete === FALSE) {
                 $globalPermissions .= "False";
             } else {
                 $globalPermissions .= "True";
             }
             $datasetCreate = new DatasetCreate($this->ws->ontologyUri, $ontologyName, $ontologyDescription, "", $this->ws->registered_ip, $this->ws->requester_ip, $webservices, $globalPermissions);
             $datasetCreate->ws_conneg($_SERVER['HTTP_ACCEPT'], $_SERVER['HTTP_ACCEPT_CHARSET'], $_SERVER['HTTP_ACCEPT_ENCODING'], $_SERVER['HTTP_ACCEPT_LANGUAGE']);
             $datasetCreate->process();
             if ($datasetCreate->pipeline_getResponseHeaderStatus() != 200) {
                 if ($datasetCreate->pipeline_getError()->id != "WS-DATASET-CREATE-202") {
                     $this->ws->conneg->setStatus($datasetCreate->pipeline_getResponseHeaderStatus());
                     $this->ws->conneg->setStatusMsg($datasetCreate->pipeline_getResponseHeaderStatusMsg());
                     $this->ws->conneg->setStatusMsgExt($datasetCreate->pipeline_getResponseHeaderStatusMsgExt());
                     $this->ws->conneg->setError($datasetCreate->pipeline_getError()->id, $datasetCreate->pipeline_getError()->webservice, $datasetCreate->pipeline_getError()->name, $datasetCreate->pipeline_getError()->description, $datasetCreate->pipeline_getError()->debugInfo, $datasetCreate->pipeline_getError()->level);
                 }
                 // If the dataset already exists, then we simply stop the processing of the advancedIndexation
                 // mode. This means that the tomcat instance has been rebooted, and that the datasets
                 // have been leaved there, and that a procedure, normally using the advancedIndexation mode
                 // is currently being re-processed.
                 return;
             }
             unset($datasetCreate);
             // Tag the new dataset as being a dataset that host an ontology description
             $query = "insert into <" . $this->ws->wsf_graph . "datasets/>\n                  {\n                    <" . $this->ws->ontologyUri . "> <http://purl.org/ontology/wsf#holdOntology> \"true\" .\n                  }";
             @$this->ws->db->query($this->ws->db->build_sparql_query(str_replace(array("\n", "\r", "\t"), " ", $query), array(), FALSE));
             if (odbc_error()) {
                 $this->ws->conneg->setStatus(500);
                 $this->ws->conneg->setStatusMsg("Internal Error");
                 $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_301->name);
                 $this->ws->conneg->setError($this->ws->errorMessenger->_301->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_301->name, $this->ws->errorMessenger->_301->description, odbc_errormsg(), $this->ws->errorMessenger->_301->level);
                 return;
             }
             // Check if we want to enable the advanced indexation: so, if we want to import all the ontologies
             // description into the other structWSF data stores to enable search and filtering using the other
             // endpoints such as search, sparql, read, etc.
             if ($this->ws->advancedIndexation) {
                 // Once we start the ontology creation process, we have to make sure that even if the server
                 // loose the connection with the user the process will still finish.
                 ignore_user_abort(true);
                 // However, maybe there is an issue with the server handling that file tht lead to some kind of infinite
                 // or near infinite loop; so we have to limit the execution time of this procedure to 45 mins.
                 set_time_limit(86400);
                 // Get the description of the classes, properties and named individuals of this ontology.
                 // Check the size of the Ontology file to import. If the size is bigger than 8MB, then we will
                 // use another method that incurs some Virtuoso indexing. If it is the case, you have to make sure
                 // that Virtuoso is properly configured so that it can access (DirsAllowed Virtuoso config option)
                 // the folder where the ontology file has been saved.
                 if (filesize($this->ws->ontologyUri) > 8000000) {
                     $sliceSize = 100;
                     // Import the big file into Virtuoso
                     $sqlQuery = "DB.DBA.RDF_LOAD_RDFXML_MT(file_to_string_output('" . str_replace("file://localhost", "", $this->ws->ontologyUri) . "'),'" . $this->ws->ontologyUri . "/import','" . $this->ws->ontologyUri . "/import')";
                     $resultset = $this->ws->db->query($sqlQuery);
                     if (odbc_error()) {
                         // If there is an error, try to load it using the Turtle parser
                         $sqlQuery = "DB.DBA.TTLP_MT(file_to_string_output('" . str_replace("file://localhost", "", $this->ws->ontologyUri) . "'),'" . $this->ws->ontologyUri . "/import','" . $this->ws->ontologyUri . "/import')";
                         $resultset = $this->ws->db->query($sqlQuery);
                         if (odbc_error()) {
                             //            echo "Error: can't import the file: $file, into the triple store.\n";
                             //            return;
                         }
                     }
                     unset($resultset);
                     // count the number of records
                     $sparqlQuery = "\n              \n                select count(distinct ?s) as ?nb from <" . $this->ws->ontologyUri . "/import>\n                where\n                {\n                  ?s a ?o .\n                }\n              \n              ";
                     $resultset = $this->ws->db->query($this->ws->db->build_sparql_query($sparqlQuery, array('nb'), FALSE));
                     $nb = odbc_result($resultset, 1);
                     unset($resultset);
                     $nbRecordsDone = 0;
                     while ($nbRecordsDone < $nb && $nb > 0) {
                         // Create slices of 100 records.
                         $sparqlQuery = "\n                  \n                  select ?s ?p ?o (DATATYPE(?o)) as ?otype (LANG(?o)) as ?olang\n                  where \n                  {\n                    {\n                      select distinct ?s from <" . $this->ws->ontologyUri . "/import> \n                      where \n                      {\n                        ?s a ?type.\n                      } \n                      limit " . $sliceSize . " \n                      offset " . $nbRecordsDone . "\n                    } \n                    \n                    ?s ?p ?o\n                  }\n                \n                ";
                         $resultset = $this->ws->db->query($this->ws->db->build_sparql_query($sparqlQuery, array('s', 'p', 'o', 'otype', 'olang'), FALSE));
                         if (odbc_error()) {
                             //              echo "Error: can't get records slices.\n";
                             //              return;
                         }
                         $crudCreates = "";
                         $crudUpdates = "";
                         $crudDeletes = array();
                         $rdfDocumentN3 = "";
                         $currentSubject = "";
                         $subjectDescription = "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n";
                         while (odbc_fetch_row($resultset)) {
                             $s = odbc_result($resultset, 1);
                             $p = odbc_result($resultset, 2);
                             $o = $this->ws->db->odbc_getPossibleLongResult($resultset, 3);
                             $otype = odbc_result($resultset, 4);
                             $olang = odbc_result($resultset, 5);
                             if ($otype != "" || $olang != "") {
                                 $subjectDescription .= "<{$s}> <{$p}> \"\"\"" . $this->n3Encode($o) . "\"\"\" .\n";
                             } else {
                                 $subjectDescription .= "<{$s}> <{$p}> <{$o}> .\n";
                             }
                         }
                         unset($resultset);
                         $wsq = new WebServiceQuerier(rtrim($this->ws->wsf_base_url, "/") . "/ws/crud/create/", "post", "application/rdf+xml", "document=" . urlencode($subjectDescription) . "&dataset=" . urlencode($this->ws->ontologyUri) . "&mime=" . urlencode("application/rdf+n3") . "&mode=full" . "&registered_ip=" . urlencode($this->ws->registered_ip));
                         if ($wsq->getStatus() != 200) {
                             $this->ws->conneg->setStatus($wsq->getStatus());
                             $this->ws->conneg->setStatusMsg($wsq->getStatusMessage());
                             $this->ws->conneg->setStatusMsgExt($wsq->getStatusMessageDescription());
                             /*
                             $this->ws->conneg->setError($wsq->pipeline_getError()->id,
                               $crudCreate->pipeline_getError()->webservice, $crudCreate->pipeline_getError()->name,
                               $crudCreate->pipeline_getError()->description, $crudCreate->pipeline_getError()->debugInfo,
                               $crudCreate->pipeline_getError()->level);               
                             */
                             // In case of error, we delete the dataset we previously created.
                             $ontologyDelete = new OntologyDelete($this->ws->ontologyUri, $this->ws->registered_ip, $this->ws->requester_ip);
                             $ontologyDelete->ws_conneg($_SERVER['HTTP_ACCEPT'], $_SERVER['HTTP_ACCEPT_CHARSET'], $_SERVER['HTTP_ACCEPT_ENCODING'], $_SERVER['HTTP_ACCEPT_LANGUAGE']);
                             $ontologyDelete->deleteOntology();
                             if ($ontologyDelete->pipeline_getResponseHeaderStatus() != 200) {
                                 $this->ws->conneg->setStatus($ontologyDelete->pipeline_getResponseHeaderStatus());
                                 $this->ws->conneg->setStatusMsg($ontologyDelete->pipeline_getResponseHeaderStatusMsg());
                                 $this->ws->conneg->setStatusMsgExt($ontologyDelete->pipeline_getResponseHeaderStatusMsgExt());
                                 $this->ws->conneg->setError($ontologyDelete->pipeline_getError()->id, $ontologyDelete->pipeline_getError()->webservice, $ontologyDelete->pipeline_getError()->name, $ontologyDelete->pipeline_getError()->description, $ontologyDelete->pipeline_getError()->debugInfo, $ontologyDelete->pipeline_getError()->level);
                                 //return;
                             }
                             //return;
                         }
                         $nbRecordsDone += $sliceSize;
                     }
                     // Now delete the graph we used to import the file
                     $sqlQuery = "sparql clear graph <" . $this->ws->ontologyUri . "/import>";
                     $resultset = $this->ws->db->query($sqlQuery);
                     if (odbc_error()) {
                         //            echo "Error: can't delete the graph sued for importing the file\n";
                         //            return;
                     }
                     unset($resultset);
                 } else {
                     $nbClasses = $ontology->getNbClasses();
                     $sliceSize = 200;
                     // Note: in OntologyCreate, we have to merge all the classes, properties and named individuals
                     //       together. This is needed to properly handle possible punning used in imported ontologies.
                     //       If we don't do this, and that a resource is both a class and an individual, then only
                     //       the individual will be in the Solr index because it would overwrite the Class
                     //       record document with the same URI.
                     include_once "../../framework/arc2/ARC2.php";
                     $rdfxmlParser = ARC2::getRDFParser();
                     $rdfxmlSerializer = ARC2::getRDFXMLSerializer();
                     $resourcesIndex = $rdfxmlParser->getSimpleIndex(0);
                     for ($i = 0; $i < $nbClasses; $i += $sliceSize) {
                         $ontologyRead = new OntologyRead($this->ws->ontologyUri, "getClasses", "mode=descriptions;limit={$sliceSize};offset={$i}", $this->ws->registered_ip, $this->ws->requester_ip);
                         // Since we are in pipeline mode, we have to set the owlapisession using the current one.
                         // otherwise the java bridge will return an error
                         $ontologyRead->setOwlApiSession($OwlApiSession);
                         $ontologyRead->ws_conneg("application/rdf+xml", $_SERVER['HTTP_ACCEPT_CHARSET'], $_SERVER['HTTP_ACCEPT_ENCODING'], $_SERVER['HTTP_ACCEPT_LANGUAGE']);
                         if ($this->ws->reasoner) {
                             $ontologyRead->useReasoner();
                         } else {
                             $ontologyRead->stopUsingReasoner();
                         }
                         $ontologyRead->process();
                         $classesRDF = $ontologyRead->ws_serialize();
                         $rdfxmlParser->parse($this->ws->ontologyUri, $classesRDF);
                         $resourceIndex = $rdfxmlParser->getSimpleIndex(0);
                         $resourcesIndex = ARC2::getMergedIndex($resourcesIndex, $resourceIndex);
                         unset($ontologyRead);
                     }
                     $nbProperties = 0;
                     $nbProperties += $ontology->getNbObjectProperties();
                     $nbProperties += $ontology->getNbDataProperties();
                     $nbProperties += $ontology->getNbAnnotationProperties();
                     $sliceSize = 200;
                     for ($i = 0; $i < $nbProperties; $i += $sliceSize) {
                         $ontologyRead = new OntologyRead($this->ws->ontologyUri, "getProperties", "mode=descriptions;limit={$sliceSize};offset={$i};type=all", $this->ws->registered_ip, $this->ws->requester_ip);
                         // Since we are in pipeline mode, we have to set the owlapisession using the current one.
                         // otherwise the java bridge will return an error
                         $ontologyRead->setOwlApiSession($OwlApiSession);
                         $ontologyRead->ws_conneg("application/rdf+xml", $_SERVER['HTTP_ACCEPT_CHARSET'], $_SERVER['HTTP_ACCEPT_ENCODING'], $_SERVER['HTTP_ACCEPT_LANGUAGE']);
                         if ($this->ws->reasoner) {
                             $ontologyRead->useReasoner();
                         } else {
                             $ontologyRead->stopUsingReasoner();
                         }
                         $ontologyRead->process();
                         $propertiesRDF = $ontologyRead->ws_serialize();
                         $rdfxmlParser->parse($this->ws->ontologyUri, $propertiesRDF);
                         $resourceIndex = $rdfxmlParser->getSimpleIndex(0);
                         $resourcesIndex = ARC2::getMergedIndex($resourcesIndex, $resourceIndex);
                         unset($ontologyRead);
                     }
                     $nbNamedIndividuals = $ontology->getNbNamedIndividuals();
                     $sliceSize = 200;
                     for ($i = 0; $i < $nbNamedIndividuals; $i += $sliceSize) {
                         $ontologyRead = new OntologyRead($this->ws->ontologyUri, "getNamedIndividuals", "classuri=all;mode=descriptions;limit={$sliceSize};offset={$i}", $this->ws->registered_ip, $this->ws->requester_ip);
                         // Since we are in pipeline mode, we have to set the owlapisession using the current one.
                         // otherwise the java bridge will return an error
                         $ontologyRead->setOwlApiSession($OwlApiSession);
                         $ontologyRead->ws_conneg("application/rdf+xml", $_SERVER['HTTP_ACCEPT_CHARSET'], $_SERVER['HTTP_ACCEPT_ENCODING'], $_SERVER['HTTP_ACCEPT_LANGUAGE']);
                         if ($this->ws->reasoner) {
                             $ontologyRead->useReasoner();
                         } else {
                             $ontologyRead->stopUsingReasoner();
                         }
                         $ontologyRead->process();
                         $namedIndividualsRDF = $ontologyRead->ws_serialize();
                         $rdfxmlParser->parse($this->ws->ontologyUri, $namedIndividualsRDF);
                         $resourceIndex = $rdfxmlParser->getSimpleIndex(0);
                         $resourcesIndex = ARC2::getMergedIndex($resourcesIndex, $resourceIndex);
                         unset($ontologyRead);
                     }
                     // Now, let's index the resources of this ontology within structWSF (for the usage of browse, search
                     // and sparql)
                     // Split the aggregated resources in multiple slices
                     $nbResources = count($resourcesIndex);
                     $sliceSize = 200;
                     for ($i = 0; $i < $nbResources; $i += $sliceSize) {
                         $slicedResourcesIndex = array_slice($resourcesIndex, $i, $sliceSize);
                         $resourcesRDF = $rdfxmlSerializer->getSerializedIndex($slicedResourcesIndex);
                         $crudCreate = new CrudCreate($resourcesRDF, "application/rdf+xml", "full", $this->ws->ontologyUri, $this->ws->registered_ip, $this->ws->requester_ip);
                         $crudCreate->ws_conneg($_SERVER['HTTP_ACCEPT'], $_SERVER['HTTP_ACCEPT_CHARSET'], $_SERVER['HTTP_ACCEPT_ENCODING'], $_SERVER['HTTP_ACCEPT_LANGUAGE']);
                         $crudCreate->process();
                         if ($crudCreate->pipeline_getResponseHeaderStatus() != 200) {
                             $this->ws->conneg->setStatus($crudCreate->pipeline_getResponseHeaderStatus());
                             $this->ws->conneg->setStatusMsg($crudCreate->pipeline_getResponseHeaderStatusMsg());
                             $this->ws->conneg->setStatusMsgExt($crudCreate->pipeline_getResponseHeaderStatusMsgExt());
                             $this->ws->conneg->setError($crudCreate->pipeline_getError()->id, $crudCreate->pipeline_getError()->webservice, $crudCreate->pipeline_getError()->name, $crudCreate->pipeline_getError()->description, $crudCreate->pipeline_getError()->debugInfo, $crudCreate->pipeline_getError()->level);
                             // In case of error, we delete the dataset we previously created.
                             $ontologyDelete = new OntologyDelete($this->ws->ontologyUri, $this->ws->registered_ip, $this->ws->requester_ip);
                             $ontologyDelete->ws_conneg($_SERVER['HTTP_ACCEPT'], $_SERVER['HTTP_ACCEPT_CHARSET'], $_SERVER['HTTP_ACCEPT_ENCODING'], $_SERVER['HTTP_ACCEPT_LANGUAGE']);
                             $ontologyDelete->deleteOntology();
                             if ($ontologyDelete->pipeline_getResponseHeaderStatus() != 200) {
                                 $this->ws->conneg->setStatus($ontologyDelete->pipeline_getResponseHeaderStatus());
                                 $this->ws->conneg->setStatusMsg($ontologyDelete->pipeline_getResponseHeaderStatusMsg());
                                 $this->ws->conneg->setStatusMsgExt($ontologyDelete->pipeline_getResponseHeaderStatusMsgExt());
                                 $this->ws->conneg->setError($ontologyDelete->pipeline_getError()->id, $ontologyDelete->pipeline_getError()->webservice, $ontologyDelete->pipeline_getError()->name, $ontologyDelete->pipeline_getError()->description, $ontologyDelete->pipeline_getError()->debugInfo, $ontologyDelete->pipeline_getError()->level);
                                 return;
                             }
                             return;
                         }
                         unset($crudCreate);
                     }
                 }
             }
         }
     }
 }
Example #3
0
 /** Validate a query to this web service
 
       @return TRUE if valid; FALSE otherwise
     
       @note This function is not used by the authentication validator web service
     
       @author Frederick Giasson, Structured Dynamics LLC.
   */
 public function validateQuery()
 {
     if (array_search($this->lang, $this->supportedLanguages) === FALSE && $this->lang != "") {
         $this->conneg->setStatus(400);
         $this->conneg->setStatusMsg("Bad Request");
         $this->conneg->setStatusMsgExt($this->errorMessenger->_308->name);
         $this->conneg->setError($this->errorMessenger->_308->id, $this->errorMessenger->ws, $this->errorMessenger->_308->name, $this->errorMessenger->_308->description, "", $this->errorMessenger->_308->level);
         return;
     }
     /*
      Check if dataset(s) URI(s) have been defined for this request. If not, then we query the
      AuthLister web service endpoint to get the list of datasets accessible by this user to see
      if the URI he wants to read is defined in one of these accessible dataset. 
     */
     if ($this->globalDataset === TRUE) {
         $ws_al = new AuthLister("access_user", "", $this->registered_ip, $this->wsf_local_ip, "none");
         $ws_al->pipeline_conneg($this->conneg->getAccept(), $this->conneg->getAcceptCharset(), $this->conneg->getAcceptEncoding(), $this->conneg->getAcceptLanguage());
         $ws_al->process();
         $xml = new ProcessorXML();
         $xml->loadXML($ws_al->pipeline_getResultset());
         $accesses = $xml->getSubjectsByType("wsf:Access");
         $accessibleDatasets = array();
         foreach ($accesses as $access) {
             $predicates = $xml->getPredicatesByType($access, "wsf:datasetAccess");
             $objects = $xml->getObjects($predicates->item(0));
             $datasetUri = $xml->getURI($objects->item(0));
             $predicates = $xml->getPredicatesByType($access, "wsf:read");
             $objects = $xml->getObjects($predicates->item(0));
             $read = $xml->getContent($objects->item(0));
             if (strtolower($read) == "true") {
                 $this->dataset .= "{$datasetUri};";
                 array_push($accessibleDatasets, $datasetUri);
             }
         }
         if (count($accessibleDatasets) <= 0) {
             $this->conneg->setStatus(400);
             $this->conneg->setStatusMsg("Bad Request");
             $this->conneg->setStatusMsgExt($this->errorMessenger->_202->name);
             $this->conneg->setError($this->errorMessenger->_202->id, $this->errorMessenger->ws, $this->errorMessenger->_202->name, $this->errorMessenger->_202->description, "", $this->errorMessenger->_202->level);
             return;
         }
         unset($ws_al);
         $this->dataset = rtrim($this->dataset, ";");
     } else {
         $datasets = explode(";", $this->dataset);
         $datasets = array_unique($datasets);
         // Validate for each requested records of each dataset
         foreach ($datasets as $dataset) {
             // Validation of the "requester_ip" to make sure the system that is sending the query as the rights.
             $ws_av = new AuthValidator($this->requester_ip, $dataset, $this->uri);
             $ws_av->pipeline_conneg("text/xml", $this->conneg->getAcceptCharset(), $this->conneg->getAcceptEncoding(), $this->conneg->getAcceptLanguage());
             $ws_av->process();
             if ($ws_av->pipeline_getResponseHeaderStatus() != 200) {
                 $this->conneg->setStatus($ws_av->pipeline_getResponseHeaderStatus());
                 $this->conneg->setStatusMsg($ws_av->pipeline_getResponseHeaderStatusMsg());
                 $this->conneg->setStatusMsgExt($ws_av->pipeline_getResponseHeaderStatusMsgExt());
                 $this->conneg->setError($ws_av->pipeline_getError()->id, $ws_av->pipeline_getError()->webservice, $ws_av->pipeline_getError()->name, $ws_av->pipeline_getError()->description, $ws_av->pipeline_getError()->debugInfo, $ws_av->pipeline_getError()->level);
                 return;
             }
             unset($ws_av);
             // Validation of the "registered_ip" to make sure the user of this system has the rights
             $ws_av = new AuthValidator($this->registered_ip, $dataset, $this->uri);
             $ws_av->pipeline_conneg("text/xml", $this->conneg->getAcceptCharset(), $this->conneg->getAcceptEncoding(), $this->conneg->getAcceptLanguage());
             $ws_av->process();
             if ($ws_av->pipeline_getResponseHeaderStatus() != 200) {
                 $this->conneg->setStatus($ws_av->pipeline_getResponseHeaderStatus());
                 $this->conneg->setStatusMsg($ws_av->pipeline_getResponseHeaderStatusMsg());
                 $this->conneg->setStatusMsgExt($ws_av->pipeline_getResponseHeaderStatusMsgExt());
                 $this->conneg->setError($ws_av->pipeline_getError()->id, $ws_av->pipeline_getError()->webservice, $ws_av->pipeline_getError()->name, $ws_av->pipeline_getError()->description, $ws_av->pipeline_getError()->debugInfo, $ws_av->pipeline_getError()->level);
                 return;
             }
         }
     }
 }
 public function processInterface()
 {
     // Make sure there was no conneg error prior to this process call
     if ($this->ws->conneg->getStatus() == 200) {
         $query = "insert into <" . $this->ws->wsf_graph . "datasets/>\n                {\n                  <" . $this->ws->datasetUri . "> a <http://rdfs.org/ns/void#Dataset> ;\n                  " . ($this->ws->datasetTitle != "" ? "<http://purl.org/dc/terms/title> \"\"\"" . str_replace("'", "\\'", $this->ws->datasetTitle) . "\"\"\" ; " : "") . "\n                  " . ($this->ws->description != "" ? "<http://purl.org/dc/terms/description> \"\"\"" . str_replace("'", "\\'", $this->ws->description) . "\"\"\" ; " : "") . "\n                  " . ($this->ws->creator != "" ? "<http://purl.org/dc/terms/creator> <" . $this->ws->creator . "> ; " : "") . "\n                  <http://purl.org/dc/terms/created> \"" . date("Y-n-j") . "\" .\n                }";
         @$this->ws->db->query($this->ws->db->build_sparql_query(str_replace(array("\n", "\r", "\t"), " ", $query), array(), FALSE));
         if (odbc_error()) {
             $this->ws->conneg->setStatus(500);
             $this->ws->conneg->setStatusMsg("Internal Error");
             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_300->name);
             $this->ws->conneg->setError($this->ws->errorMessenger->_300->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_300->name, $this->ws->errorMessenger->_300->description, odbc_errormsg(), $this->ws->errorMessenger->_300->level);
             return;
         }
         /* 
           If the dataset has been created, the next step is to create the permissions for this user (full crud)
           and for the public one (no crud).
         */
         /* Get the list of web services registered to this structWSF instance. */
         if (strtolower($this->ws->webservices) == "all") {
             $ws_al = new AuthLister("ws", $this->ws->datasetUri, $this->ws->requester_ip, $this->ws->wsf_local_ip);
             $ws_al->pipeline_conneg($this->ws->conneg->getAccept(), $this->ws->conneg->getAcceptCharset(), $this->ws->conneg->getAcceptEncoding(), $this->ws->conneg->getAcceptLanguage());
             $ws_al->process();
             if ($ws_al->pipeline_getResponseHeaderStatus() != 200) {
                 $this->ws->conneg->setStatus($ws_al->pipeline_getResponseHeaderStatus());
                 $this->ws->conneg->setStatusMsg($ws_al->pipeline_getResponseHeaderStatusMsg());
                 $this->ws->conneg->setStatusMsgExt($ws_al->pipeline_getResponseHeaderStatusMsgExt());
                 $this->ws->conneg->setError($ws_al->pipeline_getError()->id, $ws_al->pipeline_getError()->webservice, $ws_al->pipeline_getError()->name, $ws_al->pipeline_getError()->description, $ws_al->pipeline_getError()->debugInfo, $ws_al->pipeline_getError()->level);
                 return;
             }
             /* Get all web services */
             $webservices = "";
             $xml = new ProcessorXML();
             $xml->loadXML($ws_al->pipeline_getResultset());
             $webServiceElements = $xml->getXPath('//predicate/object[attribute::type="wsf:WebService"]');
             foreach ($webServiceElements as $element) {
                 $webservices .= $xml->getURI($element) . ";";
             }
             $webservices = substr($webservices, 0, strlen($webservices) - 1);
             unset($xml);
             unset($ws_al);
             $this->ws->webservices = $webservices;
         }
         /* Register full CRUD for the creator of the dataset, for the dataset's ID */
         $ws_ara = new AuthRegistrarAccess("True;True;True;True", $this->ws->webservices, $this->ws->datasetUri, "create", "", $this->ws->requester_ip, $this->ws->wsf_local_ip);
         $ws_ara->pipeline_conneg($this->ws->conneg->getAccept(), $this->ws->conneg->getAcceptCharset(), $this->ws->conneg->getAcceptEncoding(), $this->ws->conneg->getAcceptLanguage());
         $ws_ara->process();
         if ($ws_ara->pipeline_getResponseHeaderStatus() != 200) {
             $this->ws->conneg->setStatus($ws_ara->pipeline_getResponseHeaderStatus());
             $this->ws->conneg->setStatusMsg($ws_ara->pipeline_getResponseHeaderStatusMsg());
             $this->ws->conneg->setStatusMsgExt($ws_ara->pipeline_getResponseHeaderStatusMsgExt());
             $this->ws->conneg->setError($ws_ara->pipeline_getError()->id, $ws_ara->pipeline_getError()->webservice, $ws_ara->pipeline_getError()->name, $ws_ara->pipeline_getError()->description, $ws_ara->pipeline_getError()->debugInfo, $ws_ara->pipeline_getError()->level);
             return;
         }
         unset($ws_ara);
         /* Register no CRUD for the public user, for the dataset's ID */
         $ws_ara = new AuthRegistrarAccess($this->ws->globalPermissions, $this->ws->webservices, $this->ws->datasetUri, "create", "", "0.0.0.0", $this->ws->wsf_local_ip);
         $ws_ara->pipeline_conneg($this->ws->conneg->getAccept(), $this->ws->conneg->getAcceptCharset(), $this->ws->conneg->getAcceptEncoding(), $this->ws->conneg->getAcceptLanguage());
         $ws_ara->process();
         if ($ws_ara->pipeline_getResponseHeaderStatus() != 200) {
             $this->ws->conneg->setStatus($ws_ara->pipeline_getResponseHeaderStatus());
             $this->ws->conneg->setStatusMsg($ws_ara->pipeline_getResponseHeaderStatusMsg());
             $this->ws->conneg->setStatusMsgExt($ws_ara->pipeline_getResponseHeaderStatusMsgExt());
             $this->ws->conneg->setError($ws_ara->pipeline_getError()->id, $ws_ara->pipeline_getError()->webservice, $ws_ara->pipeline_getError()->name, $ws_ara->pipeline_getError()->description, $ws_ara->pipeline_getError()->debugInfo, $ws_ara->pipeline_getError()->level);
             return;
         }
         unset($ws_ara);
     }
 }
 public function processInterface()
 {
     // Make sure there was no conneg error prior to this process call
     if ($this->ws->conneg->getStatus() == 200) {
         $solr = new Solr($this->ws->wsf_solr_core, $this->ws->solr_host, $this->ws->solr_port, $this->ws->fields_index_folder);
         $solrQuery = "";
         // Get all datasets accessible to that user
         $accessibleDatasets = array();
         $ws_al = new AuthLister("access_user", "", $this->ws->registered_ip, $this->ws->wsf_local_ip, "none");
         $ws_al->pipeline_conneg($this->ws->conneg->getAccept(), $this->ws->conneg->getAcceptCharset(), $this->ws->conneg->getAcceptEncoding(), $this->ws->conneg->getAcceptLanguage());
         $ws_al->process();
         $xml = new ProcessorXML();
         $xml->loadXML($ws_al->pipeline_getResultset());
         $accesses = $xml->getSubjectsByType("wsf:Access");
         foreach ($accesses as $access) {
             $predicates = $xml->getPredicatesByType($access, "wsf:datasetAccess");
             $objects = $xml->getObjects($predicates->item(0));
             $datasetUri = $xml->getURI($objects->item(0));
             $predicates = $xml->getPredicatesByType($access, "wsf:read");
             $objects = $xml->getObjects($predicates->item(0));
             $read = $xml->getContent($objects->item(0));
             if (strtolower($read) == "true" && array_search($datasetUri, $accessibleDatasets) === FALSE) {
                 array_push($accessibleDatasets, $datasetUri);
             }
         }
         unset($ws_al);
         /*
           if registered_ip != requester_ip, this means that the query is sent by a registered system
           on the behalf of someone else. In this case, we want to make sure that that system 
           (the one that send the actual query) has access to the same datasets. Otherwise, it means that
           it tries to personificate that registered_ip user.
         */
         if ($this->ws->registered_ip != $this->ws->requester_ip) {
             // Get all datasets accessible to that system
             $accessibleDatasetsSystem = array();
             $ws_al = new AuthLister("access_user", "", $this->ws->requester_ip, $this->ws->wsf_local_ip, "none");
             $ws_al->pipeline_conneg($this->ws->conneg->getAccept(), $this->ws->conneg->getAcceptCharset(), $this->ws->conneg->getAcceptEncoding(), $this->ws->conneg->getAcceptLanguage());
             $ws_al->process();
             $xml = new ProcessorXML();
             $xml->loadXML($ws_al->pipeline_getResultset());
             $accesses = $xml->getSubjectsByType("wsf:Access");
             foreach ($accesses as $access) {
                 $predicates = $xml->getPredicatesByType($access, "wsf:datasetAccess");
                 $objects = $xml->getObjects($predicates->item(0));
                 $datasetUri = $xml->getURI($objects->item(0));
                 $predicates = $xml->getPredicatesByType($access, "wsf:read");
                 $objects = $xml->getObjects($predicates->item(0));
                 $read = $xml->getContent($objects->item(0));
                 if (strtolower($read) == "true") {
                     array_push($accessibleDatasetsSystem, $datasetUri);
                 }
             }
             unset($ws_al);
             /*
               Finally we use the intersection of the two set of dataset URIs as the list of accessible
               datasets to include for the query.
             */
             $accessibleDatasets = array_intersect($accessibleDatasets, $accessibleDatasetsSystem);
         }
         if (count($accessibleDatasets) <= 0) {
             $this->ws->conneg->setStatus(400);
             $this->ws->conneg->setStatusMsg("Bad Request");
             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_300->name);
             $this->ws->conneg->setError($this->ws->errorMessenger->_300->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_300->name, $this->ws->errorMessenger->_300->description, "", $this->ws->errorMessenger->_300->level);
             return;
         }
         $queryParam = "*:*";
         if ($this->ws->query != "") {
             $queryParam = urlencode($this->ws->query);
         }
         $distanceQueryRevelencyBooster = "";
         if ($this->ws->geoEnabled && isset($this->ws->resultsLocationAggregator[0]) && isset($this->ws->resultsLocationAggregator[1]) && ($this->ws->distanceFilter || $this->ws->rangeFilter)) {
             // Here, "^0" is added to zero-out the boost (revelency) value of the keyword
             // in this query, we simply want to aggregate the results related to their
             // distance of the center point.
             //$distanceQueryRevelencyBooster = '^0 AND _val_:"recip(dist(2, lat, long, '.$this->ws->resultsLocationAggregator[0].', '.$this->ws->resultsLocationAggregator[1].'), 1, 1, 0)"^100';
             $distanceQueryRevelencyBooster = '^0 AND _val_:"recip(geodist(geohash, ' . $this->ws->resultsLocationAggregator[0] . ', ' . $this->ws->resultsLocationAggregator[1] . '), 1, 1, 0)"^100';
         }
         $boostingRules = "";
         // Types boosting rules
         if ($this->ws->typesBoost != "") {
             $boostRules = explode(";", $this->ws->typesBoost);
             foreach ($boostRules as $key => $rule) {
                 $boost = explode("^", $rule);
                 $type = str_replace(array("%3B", "%5E"), array(";", "^"), $boost[0]);
                 $modifier = $boost[1];
                 $boostingRules .= '&bq=type:"' . urlencode($type) . '"^' . $modifier;
                 if (strtolower($this->ws->inference) == "on") {
                     $boostingRules .= '&bq=inferred_type:"' . urlencode($type) . '"^' . $modifier;
                 }
             }
             $insertOR = TRUE;
         }
         // Datasets boosting rules
         if ($this->ws->datasetsBoost != "") {
             $boostRules = explode(";", $this->ws->datasetsBoost);
             foreach ($boostRules as $key => $rule) {
                 $boost = explode("^", $rule);
                 $dataset = str_replace(array("%3B", "%5E"), array(";", "^"), $boost[0]);
                 $modifier = $boost[1];
                 $boostingRules .= '&bq=dataset:"' . urlencode($dataset) . '"^' . $modifier;
             }
             $insertOR = TRUE;
         }
         // Attributes & Attributes/values boosting rules
         if ($this->ws->attributesBoost != "") {
             $boostRules = explode(";", $this->ws->attributesBoost);
             foreach ($boostRules as $key => $rule) {
                 $isAttributeValue = FALSE;
                 if (strpos($rule, '::') !== FALSE) {
                     $isAttributeValue = TRUE;
                 }
                 $boost = explode("^", $rule);
                 $attribute = str_replace(array("%3B", "%5E"), array(";", "^"), $boost[0]);
                 $modifier = $boost[1];
                 if ($isAttributeValue) {
                     $attribute = explode("::", $attribute);
                     $attributeValue = $attribute[1];
                     $attribute = $attribute[0];
                     $indexedFields = array();
                     if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                         $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
                     }
                     // Fix the reference to some of the core attributes
                     $isCoreAttribute = $this->isCoreAttribute($attribute, $attribute);
                     // If it is not a core attribute, check if we have to make that attribute
                     // single-valued. We check that by checking if a single_valued version
                     // of that field is currently used in the Solr index.
                     $singleValuedDesignator = "";
                     if (!$isCoreAttribute && (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . "_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_date_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_int_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_float_single_valued"), $indexedFields) !== FALSE)) {
                         $singleValuedDesignator = "_single_valued";
                     }
                     $attributeFound = FALSE;
                     // Get the Solr field ID for this attribute
                     if (!$isCoreAttribute) {
                         // Check if it is an object property, and check if the pattern of this object property
                         // is using URIs as values
                         $valuesAsURI = FALSE;
                         if (stripos($attribute, "[uri]") !== FALSE) {
                             $valuesAsURI = TRUE;
                             $attribute = str_replace("[uri]", "", $attribute);
                         }
                         $attribute = urlencode($attribute);
                         if (array_search($attribute . "_attr_date" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                             $attribute = urlencode($attribute) . "_attr_date" . $singleValuedDesignator;
                         } elseif (array_search($attribute . "_attr_int" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                             $attribute = urlencode($attribute) . "_attr_int" . $singleValuedDesignator;
                         } elseif (array_search($attribute . "_attr_float" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                             $attribute = urlencode($attribute) . "_attr_float" . $singleValuedDesignator;
                         } elseif (array_search($attribute . "_attr_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE && $valuesAsURI === FALSE) {
                             $attribute = urlencode($attribute) . "_attr_" . $this->ws->lang . $singleValuedDesignator;
                         } elseif (array_search($attribute . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE) {
                             // Check if the value of that filter is a URI or not.
                             if ($valuesAsURI) {
                                 $attribute = urlencode($attribute) . "_attr_obj_uri";
                             } else {
                                 $attribute = urlencode($attribute) . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator;
                             }
                         }
                     }
                     $boostingRules .= '&bq=' . $attribute . ':"' . urlencode($attributeValue) . '"^' . $modifier;
                 } else {
                     $boostingRules .= '&bq=attribute:"' . urlencode($attribute) . '"^' . $modifier;
                 }
             }
         }
         // Attributes phrases boosting rules
         if ($this->ws->attributesPhraseBoost != "") {
             $boostRules = explode(";", $this->ws->attributesPhraseBoost);
             $indexedFields = array();
             if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                 $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
             }
             foreach ($boostRules as $key => $rule) {
                 if ($rule == '') {
                     continue;
                 }
                 $boost = explode("^", $rule);
                 $attribute = str_replace(array("%3B", "%5E"), array(";", "^"), $boost[0]);
                 $modifier = $boost[1];
                 $isCoreAttribute = $this->isCoreAttribute($attribute, $attribute);
                 $singleValuedDesignator = "";
                 if (!$isCoreAttribute) {
                     if (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . "_single_valued"), $indexedFields) !== FALSE) {
                         $singleValuedDesignator = "_single_valued";
                     }
                     if (array_search($attribute . "_attr_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE && $valuesAsURI === FALSE) {
                         $attribute = str_replace($attribute, urlencode($attribute) . "_attr_" . $this->ws->lang . $singleValuedDesignator, $attribute);
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $attribute = str_replace($attribute . ":", urlencode($attribute) . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator . ":", $attribute);
                         $attributeFound = TRUE;
                     }
                 }
                 $boostingRules .= '&pf=' . urlencode($attribute) . '^' . $modifier;
             }
             $boostingRules .= '&qs=' . $this->ws->phraseBoostDistance;
         }
         $restrictionRules = '';
         // Define properties restricted for search and their boost
         if (!empty($this->ws->searchRestrictions)) {
             $restrictionRules .= '&qf=';
             $restrictions = explode(';', $this->ws->searchRestrictions);
             foreach ($restrictions as $restriction) {
                 if (empty($restriction)) {
                     continue;
                 }
                 $modifier = 1;
                 $attribute = $restriction;
                 if (strpos($restriction, '^')) {
                     $res = explode('^', $restriction);
                     $modifier = $res[1];
                     $attribute = $res[0];
                 }
                 $indexedFields = array();
                 if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                     $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
                 }
                 // Fix the reference to some of the core attributes
                 $isCoreAttribute = $this->isCoreAttribute($attribute, $attribute);
                 // If it is not a core attribute, check if we have to make that attribute
                 // single-valued. We check that by checking if a single_valued version
                 // of that field is currently used in the Solr index.
                 $singleValuedDesignator = "";
                 if (!$isCoreAttribute && (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . "_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_date_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_int_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_float_single_valued"), $indexedFields) !== FALSE)) {
                     $singleValuedDesignator = "_single_valued";
                 }
                 $attributeFound = FALSE;
                 // Get the Solr field ID for this attribute
                 if (!$isCoreAttribute) {
                     $attribute = urlencode($attribute);
                     /*
                      @NOTE: here we can only include fields that uses the "solr.StopFilterFactory" setting in their
                             defined workflow. Otherwise, if a stopword is used in the search query, 0 results
                             will always be returned with the eDisMax query parser.
                     */
                     if (array_search($attribute . "_attr_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $attribute = urlencode($attribute) . "_attr_" . $this->ws->lang . $singleValuedDesignator;
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $attribute = urlencode($attribute) . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator;
                         $attributeFound = TRUE;
                     }
                 } else {
                     $attributeFound = TRUE;
                 }
                 if ($attributeFound) {
                     $restrictionRules .= $attribute . '^' . $modifier . ' ';
                 }
             }
         }
         $restrictionRules = rtrim($restrictionRules);
         $solrQuery = "q=" . $queryParam . $distanceQueryRevelencyBooster . $boostingRules . $restrictionRules . "&start=" . $this->ws->page . "&rows=" . $this->ws->items . (strtolower($this->ws->includeAggregates) == "true" ? "&facet=true" . "&facet.sort=count" . "&facet.limit=-1" . "&facet.field=type" . "&facet.field=attribute" . (strtolower($this->ws->inference) == "on" ? "&facet.field=inferred_type" : "") . "&facet.field=dataset&facet.mincount=1" : "");
         if (strtolower($this->ws->datasets) == "all") {
             $datasetList = "";
             foreach ($accessibleDatasets as $key => $dataset) {
                 if ($key == 0) {
                     $solrQuery .= "&fq=dataset:%22" . urlencode($dataset) . "%22";
                 } else {
                     $solrQuery .= " OR dataset:%22" . urlencode($dataset) . "%22";
                 }
             }
         } else {
             $datasets = explode(";", $this->ws->datasets);
             $solrQuery .= "&fq=dataset:%22%22";
             foreach ($datasets as $dataset) {
                 // Check if the dataset is accessible to the user
                 if (array_search($dataset, $accessibleDatasets) !== FALSE) {
                     // Decoding potentially encoded ";" characters
                     $dataset = str_replace(array("%3B", "%3b"), ";", $dataset);
                     $solrQuery .= " OR dataset:%22" . urlencode($dataset) . "%22";
                 }
             }
         }
         if ($this->ws->types != "all") {
             // Lets include the information to facet per type.
             $types = explode(";", $this->ws->types);
             $nbProcessed = 0;
             foreach ($types as $type) {
                 // Decoding potentially encoded ";" characters
                 $type = str_replace(array("%3B", "%3b"), ";", $type);
                 if ($nbProcessed == 0) {
                     $solrQuery .= "&fq=type:%22" . urlencode($type) . "%22";
                 } else {
                     $solrQuery .= " OR type:%22" . urlencode($type) . "%22";
                 }
                 $nbProcessed++;
                 if (strtolower($this->ws->inference) == "on") {
                     $solrQuery .= " OR inferred_type:%22" . urlencode($type) . "%22";
                 }
             }
         }
         if ($this->ws->extendedFilters != "") {
             // Get the fields (attributes) from the extended attributes query
             preg_match_all("/([#%\\.A-Za-z0-9_\\-\\[\\]]+):[\\(\"#%\\.A-Za-z0-9_\\-\\+*]+/Uim", $this->ws->extendedFilters, $matches);
             $attributes = $matches[1];
             $indexedFields = array();
             if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                 $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
             }
             $attributes = array_unique($attributes);
             foreach ($attributes as $attribute) {
                 $attribute = urldecode($attribute);
                 if ($attribute == "dataset") {
                     // Make sure the user has access to this dataset
                     // Get all the dataset values referenced in the extended filters
                     $usedDatasets = array();
                     preg_match_all("/dataset:[\"(](.*)[\")]/Uim", $this->ws->extendedFilters, $matches);
                     $usedDatasets = array_merge($usedDatasets, $matches[1]);
                     preg_match_all("/dataset:([^\"()]*)[\\s\$)]+/Uim", $this->ws->extendedFilters, $matches);
                     $usedDatasets = array_merge($usedDatasets, $matches[1]);
                     $usedDatasets = array_unique($usedDatasets);
                     // Make sure that all defined dataset extended filters are accessible to the requester
                     foreach ($usedDatasets as $key => $usedDataset) {
                         // Unescape values (remove "\" from the Solr query)
                         $usedDataset = str_replace('\\', '', $usedDataset);
                         if (array_search($usedDataset, $accessibleDatasets) === FALSE) {
                             $this->ws->conneg->setStatus(400);
                             $this->ws->conneg->setStatusMsg("Bad Request");
                             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_309->name);
                             $this->ws->conneg->setError($this->ws->errorMessenger->_309->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_309->name, $this->ws->errorMessenger->_309->description, "Unaccessible dataset: " . $usedDataset, $this->ws->errorMessenger->_309->level);
                             return;
                         }
                     }
                 }
                 // Fix the reference to some of the core attributes
                 $coreAttribute = "";
                 $isCoreAttribute = $this->isCoreAttribute($attribute, $coreAttribute);
                 // If it is not a core attribute, check if we have to make that attribute
                 // single-valued. We check that by checking if a single_valued version
                 // of that field is currently used in the Solr index.
                 $singleValuedDesignator = "";
                 if (!$isCoreAttribute && (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . "_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_date_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_int_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_float_single_valued"), $indexedFields) !== FALSE)) {
                     $singleValuedDesignator = "_single_valued";
                 }
                 $attributeFound = FALSE;
                 // Get the Solr field ID for this attribute
                 if ($isCoreAttribute) {
                     $attribute = urlencode($attribute);
                     $this->ws->extendedFilters = str_replace($attribute, $coreAttribute, $this->ws->extendedFilters);
                     $attributeFound = TRUE;
                 } else {
                     // Check if it is an object property, and check if the pattern of this object property
                     // is using URIs as values
                     $valuesAsURI = FALSE;
                     if (stripos($attribute, "[uri]") !== FALSE) {
                         $valuesAsURI = TRUE;
                         $attribute = str_replace("[uri]", "", $attribute);
                     }
                     $attribute = urlencode($attribute);
                     if (array_search($attribute . "_attr_date" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $this->ws->extendedFilters = str_replace($attribute, urlencode($attribute) . "_attr_date" . $singleValuedDesignator, $this->ws->extendedFilters);
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_int" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $this->ws->extendedFilters = str_replace($attribute, urlencode($attribute) . "_attr_int" . $singleValuedDesignator, $this->ws->extendedFilters);
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_float" . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         $this->ws->extendedFilters = str_replace($attribute, urlencode($attribute) . "_attr_float" . $singleValuedDesignator, $this->ws->extendedFilters);
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE && $valuesAsURI === FALSE) {
                         $this->ws->extendedFilters = str_replace($attribute, urlencode($attribute) . "_attr_" . $this->ws->lang . $singleValuedDesignator, $this->ws->extendedFilters);
                         $attributeFound = TRUE;
                     } elseif (array_search($attribute . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator, $indexedFields) !== FALSE) {
                         // Check if the value of that filter is a URI or not.
                         if ($valuesAsURI) {
                             $this->ws->extendedFilters = str_replace($attribute . "[uri]:", urlencode($attribute) . "_attr_obj_uri:", $this->ws->extendedFilters);
                         } else {
                             $this->ws->extendedFilters = str_replace($attribute . ":", urlencode($attribute) . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator . ":", $this->ws->extendedFilters);
                         }
                         $attributeFound = TRUE;
                     }
                 }
                 if ($attributeFound === FALSE) {
                     $this->ws->conneg->setStatus(400);
                     $this->ws->conneg->setStatusMsg("Bad Request");
                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_310->name);
                     $this->ws->conneg->setError($this->ws->errorMessenger->_310->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_310->name, $this->ws->errorMessenger->_310->description, "Undefined filter: " . urldecode($attribute), $this->ws->errorMessenger->_310->level);
                     return;
                 }
             }
             $solrQuery .= "&fq=" . $this->ws->extendedFilters;
         }
         if ($this->ws->attributes != "all") {
             // Lets include the information to facet per type.
             $attributes = explode(";", $this->ws->attributes);
             $nbProcessed = 0;
             $indexedFields = array();
             if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                 $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
             }
             foreach ($attributes as $attribute) {
                 $attributeValue = explode("::", $attribute);
                 $attribute = urldecode($attributeValue[0]);
                 // Skip possible "dataset" field request. This is handled bia the "dataset" parameter
                 // of this web service endpoint.
                 if ($attribute == "dataset") {
                     continue;
                 }
                 if (isset($attributeValue[1]) && $attributeValue[1] != "") {
                     // Fix the reference to some of the core attributes
                     $coreAttr = $this->isCoreAttribute($attribute, $attribute);
                     // Special handling for some core attributes
                     switch (urldecode($attributeValue[0])) {
                         case "prefLabel":
                         case Namespaces::$iron . "prefLabel":
                             // Check if we are performing an autocompletion task on the pref label
                             $label = urldecode($attributeValue[1]);
                             if (substr($label, strlen($label) - 2) == "**") {
                                 $attribute = "prefLabelAutocompletion_" . $this->ws->lang;
                                 $attributeValue[1] = urlencode(strtolower(str_replace(" ", "\\ ", substr($label, 0, strlen($label) - 1))));
                             }
                             break;
                         case "lat":
                         case Namespaces::$geo . "lat":
                             if (!is_numeric(urldecode($attributeValue[1]))) {
                                 // If the value is not numeric, we skip that attribute/value.
                                 // Otherwise an exception will be raised by Solr.
                                 continue;
                             }
                             break;
                         case "long":
                         case Namespaces::$geo . "long":
                             if (!is_numeric(urldecode($attributeValue[1]))) {
                                 // If the value is not numeric, we skip that attribute/value.
                                 // Otherwise an exception will be raised by Solr.
                                 continue;
                             }
                             break;
                     }
                     // A filtering value as been defined for this attribute.
                     $val = urldecode($attributeValue[1]);
                     // If it is not a core attribute, check if we have to make that attribute
                     // single-valued. We check that by checking if a single_valued version
                     // of that field is currently used in the Solr index.
                     $singleValuedDesignator = "";
                     if (!$coreAttr && (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . "_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_date_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_int_single_valued"), $indexedFields) !== FALSE || array_search(urlencode($attribute . "_attr_float_single_valued"), $indexedFields) !== FALSE)) {
                         $singleValuedDesignator = "_single_valued";
                     }
                     if ($nbProcessed == 0) {
                         if ($coreAttr) {
                             switch ($attribute) {
                                 case "type":
                                     if (strtolower($this->ws->inference) == "on") {
                                         $solrQuery .= "&fq=((type:" . urlencode($this->escapeSolrValue($val)) . ") OR (inferred_type:" . urlencode($this->escapeSolrValue($val)) . "))";
                                     } else {
                                         $solrQuery .= "&fq=(type:" . urlencode($this->escapeSolrValue($val)) . ")";
                                     }
                                     break;
                                 case "located_in":
                                     $solrQuery .= "&fq=(located_in:" . urlencode($this->escapeSolrValue($val)) . ")";
                                     break;
                                 default:
                                     $solrQuery .= "&fq=(" . $attribute . ":" . urlencode($this->arrangeSolrValue($val)) . ")";
                                     break;
                             }
                         } else {
                             $solrQuery .= "&fq=(";
                         }
                     } else {
                         if ($coreAttr) {
                             switch ($attribute) {
                                 case "type":
                                     if (strtolower($this->ws->inference) == "on") {
                                         $solrQuery .= " " . $this->ws->attributesBooleanOperator . " ((type:" . urlencode($this->escapeSolrValue($val)) . ") OR (inferred_type:" . urlencode($this->escapeSolrValue($val)) . "))";
                                     } else {
                                         $solrQuery .= " " . $this->ws->attributesBooleanOperator . " (type:" . urlencode($this->escapeSolrValue($val)) . ")";
                                     }
                                     break;
                                 case "located_in":
                                     $solrQuery .= " " . $this->ws->attributesBooleanOperator . " (located_in:" . urlencode($this->escapeSolrValue($val)) . ")";
                                     break;
                                 default:
                                     $solrQuery .= " " . $this->ws->attributesBooleanOperator . " (" . $attribute . ":" . urlencode($this->escapeSolrValue($this->arrangeSolrValue($val))) . ")";
                                     break;
                             }
                         } else {
                             if (substr($solrQuery, strlen($solrQuery) - 3) != "fq=") {
                                 $solrQuery .= " " . $this->ws->attributesBooleanOperator . " (";
                             } else {
                                 $solrQuery .= "(";
                             }
                         }
                     }
                     $addOR = FALSE;
                     $empty = TRUE;
                     // We have to detect if the fields are existing in Solr, otherwise Solr will throw
                     // "undefined fields" errors, and there is no way to ignore them and process
                     // the query anyway.
                     if (!$coreAttr && array_search(urlencode($attribute), $indexedFields) !== FALSE) {
                         $solrQuery .= "(" . urlencode(urlencode($attribute)) . ":" . urlencode($this->escapeSolrValue($this->arrangeSolrValue($val))) . ")";
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_" . $this->ws->lang . $singleValuedDesignator), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_" . $this->ws->lang . $singleValuedDesignator . ":" . urlencode($this->escapeSolrValue($this->arrangeSolrValue($val))) . ")";
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_int" . $singleValuedDesignator), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         if (is_numeric($val)) {
                             $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_int" . $singleValuedDesignator . ":" . $val . ")";
                         } else {
                             // Extract the FROM and TO numbers range
                             $numbers = explode(" TO ", trim(str_replace(" to ", " TO ", $val), "[]"));
                             if ($numbers[0] != "*") {
                                 if (!is_numeric($numbers[0])) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_306->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_306->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_306->name, $this->ws->errorMessenger->_306->description, "", $this->ws->errorMessenger->_306->level);
                                     return;
                                 }
                             }
                             if ($numbers[1] != "*") {
                                 if (!is_numeric($numbers[1])) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_306->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_306->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_306->name, $this->ws->errorMessenger->_306->description, "", $this->ws->errorMessenger->_306->level);
                                     return;
                                 }
                             }
                             $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_int" . $singleValuedDesignator . ":" . urlencode("[" . $numbers[0] . " TO " . $numbers[1] . "]") . ")";
                         }
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_float" . $singleValuedDesignator), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         if (is_numeric($val)) {
                             $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_float" . $singleValuedDesignator . ":" . $val . ")";
                         } else {
                             // Extract the FROM and TO numbers range
                             $numbers = explode(" TO ", trim(str_replace(" to ", " TO ", $val), "[]"));
                             if ($numbers[0] != "*") {
                                 if (!is_numeric($numbers[0])) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_306->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_306->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_306->name, $this->ws->errorMessenger->_306->description, "", $this->ws->errorMessenger->_306->level);
                                     return;
                                 }
                             }
                             if ($numbers[1] != "*") {
                                 if (!is_numeric($numbers[1])) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_306->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_306->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_306->name, $this->ws->errorMessenger->_306->description, "", $this->ws->errorMessenger->_306->level);
                                     return;
                                 }
                             }
                             $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_float" . $singleValuedDesignator . ":" . urlencode("[" . $numbers[0] . " TO " . $numbers[1] . "]") . ")";
                         }
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_date" . $singleValuedDesignator), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         $dateFrom = "";
                         $dateTo = "NOW";
                         // Check if it is a range query
                         if (substr($val, 0, 1) == "[" && substr($val, strlen($val) - 1, 1) == "]") {
                             // Extract the FROM and TO dates range
                             $dates = explode(" TO ", trim(str_replace(" to ", " TO ", $val), "[]"));
                             if ($dates[0] != "*") {
                                 $dateFrom = $this->safeDate($dates[0]);
                                 if ($dateFrom === FALSE) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_305->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_305->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_305->name, $this->ws->errorMessenger->_305->description, "", $this->ws->errorMessenger->_305->level);
                                     return;
                                 }
                             }
                             if ($dates[1] != "*") {
                                 $dateTo = $this->safeDate($dates[1]);
                                 if ($dateTo === FALSE) {
                                     $this->ws->conneg->setStatus(400);
                                     $this->ws->conneg->setStatusMsg("Bad Request");
                                     $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_305->name);
                                     $this->ws->conneg->setError($this->ws->errorMessenger->_305->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_305->name, $this->ws->errorMessenger->_305->description, "", $this->ws->errorMessenger->_305->level);
                                     return;
                                 }
                             }
                         } else {
                             // If no range is defined, we consider the input date to be the initial date to use
                             // until now.
                             $dateFrom = $this->safeDate($val);
                             if ($dateFrom === FALSE) {
                                 $this->ws->conneg->setStatus(400);
                                 $this->ws->conneg->setStatusMsg("Bad Request");
                                 $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_305->name);
                                 $this->ws->conneg->setError($this->ws->errorMessenger->_305->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_305->name, $this->ws->errorMessenger->_305->description, "", $this->ws->errorMessenger->_305->level);
                                 return;
                             }
                         }
                         $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_date" . $singleValuedDesignator . ":" . urlencode("[" . $dateFrom . " TO " . $dateTo) . "]" . ")";
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_obj_" . $this->ws->lang . $singleValuedDesignator . ":" . urlencode($this->escapeSolrValue($val)) . ")";
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if (array_search(urlencode($attribute . "_attr_obj_uri"), $indexedFields) !== FALSE) {
                         if ($addOR) {
                             $solrQuery .= " OR ";
                         }
                         $solrQuery .= "(" . urlencode(urlencode($attribute)) . "_attr_obj_uri:" . urlencode($this->escapeURIValue($val)) . ")";
                         $addOR = TRUE;
                         $empty = FALSE;
                     }
                     if ($nbProcessed == 0) {
                         if (!$coreAttr) {
                             if ($empty) {
                                 $solrQuery = substr($solrQuery, 0, strlen($solrQuery) - 1);
                             } else {
                                 $solrQuery .= ")";
                             }
                         }
                     } else {
                         if (!$coreAttr) {
                             if (substr($solrQuery, strlen($solrQuery) - 4) != "fq=(") {
                                 if ($empty) {
                                     $solrQuery = substr($solrQuery, 0, strlen($solrQuery) - 5);
                                 } else {
                                     $solrQuery .= ")";
                                 }
                             } else {
                                 $solrQuery = substr($solrQuery, 0, strlen($solrQuery) - 1);
                             }
                         }
                     }
                 } else {
                     if ($nbProcessed == 0) {
                         $solrQuery .= "&fq=(attribute:%22" . urlencode($attribute) . "%22)";
                     } else {
                         $solrQuery .= " " . $this->ws->attributesBooleanOperator . " (attribute:%22" . urlencode($attribute) . "%22)";
                     }
                 }
                 $nbProcessed++;
             }
         }
         // Check if this query is geo-enabled and if a distance-filter is requested
         if ($this->ws->geoEnabled && $this->ws->distanceFilter != "") {
             /*
               $params[0] == latitude
               $params[1] == longitude
               $params[2] == distance
               $params[3] == (0) distance in kilometers, (1) distance in miles
             */
             $params = explode(";", $this->ws->distanceFilter);
             $earthRadius = 6371;
             if ($params[3] == 1) {
                 $earthRadius = 3963.205;
             }
             $solrQuery .= "&fq={!frange l=0 u=" . $params[2] . "}hsin(" . $params[0] . "," . $params[1] . " , lat_rad, long_rad, " . $earthRadius . ")";
         }
         // Check if this query is geo-enabled and if a range-filter is requested
         if ($this->ws->geoEnabled && $this->ws->rangeFilter != "") {
             /*
               $params[0] == latitude top-left
               $params[1] == longitude top-left
               $params[2] == latitude bottom-right
               $params[3] == longitude bottom-right
             */
             $params = explode(";", $this->ws->rangeFilter);
             // Make sure the ranges are respected according to the way the cartesian coordinate
             // system works.
             $p1 = $params[0];
             $p2 = $params[2];
             $p3 = $params[1];
             $p4 = $params[3];
             if ($params[0] > $params[2]) {
                 $p1 = $params[2];
                 $p2 = $params[0];
             }
             if ($params[1] > $params[3]) {
                 $p3 = $params[3];
                 $p4 = $params[1];
             }
             $solrQuery .= "&fq=lat:[" . $p1 . " TO " . $p2 . "]&fq=long:[" . $p3 . " TO " . $p4 . "]";
         }
         // Add the attribute/value aggregates if needed
         if (count($this->ws->aggregateAttributes) > 0 && strtolower($this->ws->includeAggregates) == "true") {
             foreach ($this->ws->aggregateAttributes as $attribute) {
                 $solrQuery .= "&facet.field=" . urlencode(urlencode($attribute));
                 $solrQuery .= "&f." . urlencode(urlencode($attribute)) . ".facet.limit=" . $this->ws->aggregateAttributesNb;
             }
         }
         // Only return these fields in the resultset
         if (count($this->ws->includeAttributesList) > 0) {
             if (strtolower($this->ws->includeAttributesList[0]) == "none") {
                 $solrQuery .= "&fl=";
                 $solrQuery .= "uri ";
                 $solrQuery .= "type ";
                 $solrQuery .= "inferred_type ";
                 $solrQuery .= "dataset ";
                 $solrQuery .= "prefLabelAutocompletion_" . $this->ws->lang . "";
             } else {
                 $solrQuery .= "&fl=";
                 foreach ($this->ws->includeAttributesList as $atl) {
                     if ($atl != "none") {
                         $isCoreAttribute = $this->isCoreAttribute($atl, $atl);
                         if (!$isCoreAttribute) {
                             $solrQuery .= urlencode(urlencode($atl)) . "_attr_" . $this->ws->lang . " ";
                             $solrQuery .= urlencode(urlencode($atl)) . "_attr_obj_" . $this->ws->lang . " ";
                             $solrQuery .= urlencode(urlencode($atl)) . "_attr_obj_uri ";
                         } else {
                             $solrQuery .= $atl . " ";
                         }
                     }
                 }
                 // Also add the core attributes to the mixte
                 $solrQuery .= "uri ";
                 $solrQuery .= "type ";
                 $solrQuery .= "inferred_type ";
                 $solrQuery .= "dataset ";
                 $solrQuery .= "prefLabelAutocompletion_" . $this->ws->lang . "";
             }
         }
         // Remove possible left-over introduced by the procedure above for some rare usecases.
         $solrQuery = str_replace("fq= OR ", "fq=", $solrQuery);
         $solrQuery = str_replace("fq= AND ", "fq=", $solrQuery);
         // Set the default field of the search
         $solrQuery .= "&df=all_text_" . $this->ws->lang;
         // The the sorting parameter
         if (count($this->ws->sort) > 0) {
             $indexedFields = array();
             if (file_exists($this->ws->fields_index_folder . "fieldsIndex.srz")) {
                 $indexedFields = unserialize(file_get_contents($this->ws->fields_index_folder . "fieldsIndex.srz"));
                 $solrQuery .= "&sort=";
                 foreach ($this->ws->sort as $sortProperty => $order) {
                     $lSortProperty = strtolower($sortProperty);
                     if ($lSortProperty == "preflabel") {
                         $sortProperty = "prefLabelAutocompletion_" . $this->ws->lang;
                     } else {
                         if ($lSortProperty == "type") {
                             $sortProperty = "type_single_valued";
                         } else {
                             if ($lSortProperty != "uri" && $lSortProperty != "dataset" && $lSortProperty != "score") {
                                 $uSortProperty = urlencode($sortProperty);
                                 if (array_search($uSortProperty . "_attr_date_single_valued", $indexedFields) !== FALSE) {
                                     $sortProperty = urlencode($uSortProperty) . "_attr_date_single_valued";
                                 } else {
                                     if (array_search($uSortProperty . "_attr_float_single_valued", $indexedFields) !== FALSE) {
                                         $sortProperty = urlencode($uSortProperty) . "_attr_float_single_valued";
                                     } else {
                                         if (array_search($uSortProperty . "_attr_int_single_valued", $indexedFields) !== FALSE) {
                                             $sortProperty = urlencode($uSortProperty) . "_attr_int_single_valued";
                                         } else {
                                             if (array_search($uSortProperty . "_attr_obj_" . $this->ws->lang . "_single_valued", $indexedFields) !== FALSE) {
                                                 $sortProperty = urlencode($uSortProperty) . "_attr_obj_" . $this->ws->lang . "_single_valued";
                                             } else {
                                                 if (array_search($uSortProperty . "_attr_" . $this->ws->lang . "_single_valued", $indexedFields) !== FALSE) {
                                                     $sortProperty = urlencode($uSortProperty) . "_attr_" . $this->ws->lang . "_single_valued";
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                     $solrQuery .= $sortProperty . " " . $order . ",";
                 }
                 $solrQuery = rtrim($solrQuery, ",");
             }
         }
         if (!empty($this->ws->includeScores)) {
             $solrQuery .= '&fl=' . urlencode('* score');
         }
         // Specify the default search operator
         if ($this->ws->defaultOperator != 'and') {
             if (strpos($this->ws->defaultOperator, '::') !== FALSE) {
                 $orOp = explode('::', $this->ws->defaultOperator .= '&q.op=AND');
                 if ($orOp[0] == 'or') {
                     $solrQuery .= '&q.op=OR';
                     $solrQuery .= '&mm=' . $orOp[1];
                 }
             } else {
                 if ($this->ws->defaultOperator == 'or') {
                     $solrQuery .= '&q.op=OR';
                 }
             }
         } else {
             $solrQuery .= '&q.op=AND';
         }
         // Check if we enable the spellchecker
         if ($this->ws->spellcheck === TRUE) {
             $solrQuery .= '&spellcheck=true';
         }
         // Specifies that the query parser is eDisMax
         $solrQuery .= '&defType=edismax';
         $resultset = $solr->select($solrQuery);
         if ($resultset === FALSE) {
             $this->ws->conneg->setStatus(400);
             $this->ws->conneg->setStatusMsg("Bad Request");
             $this->ws->conneg->setStatusMsgExt($this->ws->errorMessenger->_311->name);
             $this->ws->conneg->setError($this->ws->errorMessenger->_311->id, $this->ws->errorMessenger->ws, $this->ws->errorMessenger->_311->name, $this->ws->errorMessenger->_311->description, $solr->errorMessage . '[Debugging information: ]' . $solr->errorMessageDebug, $this->ws->errorMessenger->_311->level);
             return;
         }
         // Create the internal representation of the resultset.
         $domResultset = new DomDocument("1.0", "utf-8");
         $domResultset->loadXML($resultset);
         $xpath = new DOMXPath($domResultset);
         // Get the number of results
         $founds = $xpath->query("*[@numFound]");
         foreach ($founds as $found) {
             $nbResources = $found->attributes->getNamedItem("numFound")->nodeValue;
             break;
         }
         // If no results are returned, check if spellchecking was enabled, if it was then
         // try to get the spell suggestions & the the collation
         if ($nbResources <= 0 && $this->ws->spellcheck === TRUE) {
             // Try to get the collation
             $collation = $xpath->query("//*/lst[@name='suggestions']//str[@name='collation']");
             if ($collation->length > 0) {
                 $collation = $collation->item(0)->nodeValue;
             }
             $subject = new Subject($this->ws->uri . "suggestions/" . md5(microtime()));
             $subject->setType(Namespaces::$wsf . "SpellSuggestion");
             $subject->setDataAttribute(Namespaces::$wsf . "collation", $collation);
             $this->ws->rset->addSubject($subject);
             // Try to get the suggested terms
             $suggestedWords = $xpath->query("//*/lst[@name='suggestions']/lst");
             foreach ($suggestedWords as $sw) {
                 $misspelledWord = $sw->getAttribute('name');
                 $suggestion = $xpath->query("arr[@name='suggestion']/lst", $sw);
                 foreach ($suggestion as $word_frequency) {
                     $word = $word_frequency->getElementsByTagName('str')->item(0)->nodeValue;
                     $frequency = $word_frequency->getElementsByTagName('int')->item(0)->nodeValue;
                     $subject = new Subject($this->ws->uri . "suggestions/" . md5(microtime()));
                     $subject->setType(Namespaces::$wsf . "SpellSuggestion");
                     $subject->setDataAttribute(Namespaces::$wsf . "misspelledWord", $misspelledWord);
                     $subject->setDataAttribute(Namespaces::$wsf . "suggestion", $word);
                     $subject->setDataAttribute(Namespaces::$wsf . "frequency", $frequency);
                     $this->ws->rset->addSubject($subject);
                 }
             }
         }
         // Get all the "type" facets with their counts
         $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='type']/int");
         // Set types aggregates
         foreach ($founds as $found) {
             $subject = new Subject($this->ws->uri . "aggregate/" . md5(microtime()));
             $subject->setType(Namespaces::$aggr . "Aggregate");
             $subject->setObjectAttribute(Namespaces::$aggr . "property", Namespaces::$rdf . "type");
             $subject->setObjectAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
             $subject->setDataAttribute(Namespaces::$aggr . "count", $found->nodeValue);
             $this->ws->rset->addSubject($subject);
         }
         // Set types aggregates for inferred types
         if (strtolower($this->ws->inference) == "on") {
             // Get all the "inferred_type" facets with their counts
             $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='inferred_type']/int");
             // Get types counts
             foreach ($founds as $found) {
                 $subject = new Subject($this->ws->uri . "aggregate/" . md5(microtime()));
                 $subject->setType(Namespaces::$aggr . "Aggregate");
                 $subject->setObjectAttribute(Namespaces::$aggr . "property", Namespaces::$rdf . "type");
                 $subject->setObjectAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
                 $subject->setDataAttribute(Namespaces::$aggr . "count", $found->nodeValue);
                 $this->ws->rset->addSubject($subject);
             }
         }
         // Set the dataset aggregates
         $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='dataset']/int");
         foreach ($founds as $found) {
             $subject = new Subject($this->ws->uri . "aggregate/" . md5(microtime()));
             $subject->setType(Namespaces::$aggr . "Aggregate");
             $subject->setObjectAttribute(Namespaces::$aggr . "property", Namespaces::$void . "Dataset");
             $subject->setObjectAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
             $subject->setDataAttribute(Namespaces::$aggr . "count", $found->nodeValue);
             $this->ws->rset->addSubject($subject);
         }
         // Set the attributes aggregates
         $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='attribute']/int");
         foreach ($founds as $found) {
             $subject = new Subject($this->ws->uri . "aggregate/" . md5(microtime()));
             $subject->setType(Namespaces::$aggr . "Aggregate");
             $subject->setObjectAttribute(Namespaces::$aggr . "property", Namespaces::$rdf . "Property");
             $subject->setObjectAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
             $subject->setDataAttribute(Namespaces::$aggr . "count", $found->nodeValue);
             $this->ws->rset->addSubject($subject);
         }
         // Set all the attributes/values aggregates
         foreach ($this->ws->aggregateAttributes as $attribute) {
             $founds = $xpath->query("//*/lst[@name='facet_fields']//lst[@name='" . urlencode($attribute) . "']/int");
             foreach ($founds as $found) {
                 $subject = new Subject($this->ws->uri . "aggregate/" . md5(microtime()));
                 $subject->setType(Namespaces::$aggr . "Aggregate");
                 $subject->setObjectAttribute(Namespaces::$aggr . "property", str_replace(array("_attr_uri_label_facets", "_attr_facets", "_attr_obj_uri"), "", urldecode($attribute)));
                 if ($this->ws->aggregateAttributesObjectType == "uri") {
                     $subject->setObjectAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
                 } elseif ($this->ws->aggregateAttributesObjectType == "literal") {
                     $subject->setDataAttribute(Namespaces::$aggr . "object", $found->attributes->getNamedItem("name")->nodeValue);
                 } elseif ($this->ws->aggregateAttributesObjectType == "uriliteral") {
                     $values = explode("::", $found->attributes->getNamedItem("name")->nodeValue);
                     $subject->setObjectAttribute(Namespaces::$aggr . "object", $values[0]);
                     $subject->setDataAttribute(Namespaces::$aggr . "object", $values[1]);
                 }
                 $subject->setDataAttribute(Namespaces::$aggr . "count", $found->nodeValue);
                 $this->ws->rset->addSubject($subject);
             }
         }
         // Set all the results
         $resultsDom = $xpath->query("//doc");
         foreach ($resultsDom as $result) {
             // get URI
             $resultURI = $xpath->query("str[@name='uri']", $result);
             $uri = "";
             if ($resultURI->length > 0) {
                 $uri = $resultURI->item(0)->nodeValue;
             } else {
                 continue;
             }
             $subject = new Subject($uri);
             // get Dataset URI
             $resultDatasetURI = $xpath->query("str[@name='dataset']", $result);
             if ($resultDatasetURI->length > 0) {
                 $subject->setObjectAttribute(Namespaces::$dcterms . "isPartOf", $resultDatasetURI->item(0)->nodeValue);
             }
             // get records preferred label
             $resultPrefLabelURI = $xpath->query("str[@name='prefLabel_" . $this->ws->lang . "']", $result);
             if ($resultPrefLabelURI->length > 0) {
                 $subject->setPrefLabel($resultPrefLabelURI->item(0)->nodeValue);
             }
             // get records aternative labels
             $resultAltLabelURI = $xpath->query("arr[@name='altLabel_" . $this->ws->lang . "']/str", $result);
             for ($i = 0; $i < $resultAltLabelURI->length; ++$i) {
                 $subject->setAltLabel($resultAltLabelURI->item($i)->nodeValue);
             }
             // Get possible Lat/Long and shapes descriptions
             // First check if there is a polygonCoordinates pr a polylineCoordinates attribute for that record
             // If there is one, then we simply ignore the lat/long coordinates since they come from these
             // attributes and that we don't want to duplicate that information.
             $skipLatLong = FALSE;
             $resultPolygonCoordinates = $xpath->query("arr[@name='polygonCoordinates']/str", $result);
             if ($resultPolygonCoordinates->length > 0) {
                 foreach ($resultPolygonCoordinates as $value) {
                     $subject->setDataAttribute(Namespaces::$sco . "polygonCoordinates", $value->nodeValue);
                 }
                 $skipLatLong = TRUE;
             }
             $resultPolylineCoordinates = $xpath->query("arr[@name='polylineCoordinates']/str", $result);
             if ($resultPolylineCoordinates->length > 0) {
                 foreach ($resultPolylineCoordinates as $value) {
                     $subject->setDataAttribute(Namespaces::$sco . "polylineCoordinates", $value->nodeValue);
                 }
                 $skipLatLong = TRUE;
             }
             if (!$skipLatLong) {
                 $resultDescriptionLat = $xpath->query("arr[@name='lat']/double", $result);
                 if ($resultDescriptionLat->length > 0) {
                     $subject->setDataAttribute(Namespaces::$geo . "lat", $resultDescriptionLat->item(0)->nodeValue);
                 }
                 $resultDescriptionLong = $xpath->query("arr[@name='long']/double", $result);
                 if ($resultDescriptionLong->length > 0) {
                     $subject->setDataAttribute(Namespaces::$geo . "long", $resultDescriptionLong->item(0)->nodeValue);
                 }
             }
             // Set possible score
             if (!empty($this->ws->includeScores)) {
                 $score = $xpath->query("float[@name='score']", $result);
                 if ($score->length > 0) {
                     $subject->setDataAttribute(Namespaces::$wsf . "score", $score->item(0)->nodeValue);
                 }
             }
             // get possible locatedIn URI(s)
             $resultLocatedIn = $xpath->query("arr[@name='located_in']/str", $result);
             if ($resultLocatedIn->length > 0) {
                 $subject->setObjectAttribute(Namespaces::$geoname . "locatedIn", $resultLocatedIn->item(0)->nodeValue);
             }
             // get records description
             $resultDescriptionURI = $xpath->query("arr[@name='description_" . $this->ws->lang . "']/str", $result);
             if ($resultDescriptionURI->length > 0) {
                 $subject->setDescription($resultDescriptionURI->item(0)->nodeValue);
             }
             // Get all dynamic fields attributes that are multi-valued
             $resultProperties = $xpath->query("arr", $result);
             $objectPropertyLabels = array();
             $objectPropertyUris = array();
             foreach ($resultProperties as $property) {
                 $attribute = $property->getAttribute("name");
                 // Check what kind of attribute it is
                 $attributeType = $this->getSolrAttributeType($attribute);
                 // Get the URI of the attribute
                 $attributeURI = urldecode(str_replace($attributeType, "", $attribute));
                 // Exclude the attributes that have to be ignored by the Search endpoint
                 // when creating the new resultset.
                 if (array_search($attributeURI, $this->ws->searchExcludedAttributes) !== FALSE) {
                     continue;
                 }
                 if ($attributeURI == Namespaces::$rdf . "type") {
                     continue;
                 }
                 switch ($attributeType) {
                     case "_attr_" . $this->ws->lang:
                         $values = $property->getElementsByTagName("str");
                         foreach ($values as $value) {
                             $subject->setDataAttribute($attributeURI, $value->nodeValue);
                         }
                         break;
                     case "_attr_date":
                         $values = $property->getElementsByTagName("date");
                         foreach ($values as $value) {
                             $subject->setDataAttribute($attributeURI, $value->nodeValue, Datatypes::$date);
                         }
                         break;
                     case "_attr_int":
                         $values = $property->getElementsByTagName("int");
                         foreach ($values as $value) {
                             $subject->setDataAttribute($attributeURI, $value->nodeValue, Datatypes::$int);
                         }
                         break;
                     case "_attr_float":
                         $values = $property->getElementsByTagName("float");
                         foreach ($values as $value) {
                             $subject->setDataAttribute($attributeURI, $value->nodeValue, Datatypes::$float);
                         }
                         break;
                     case "_attr_obj_" . $this->ws->lang:
                         $values = $property->getElementsByTagName("str");
                         foreach ($values as $value) {
                             if (!is_array($objectPropertyLabels[$attributeURI])) {
                                 $objectPropertyLabels[$attributeURI] = array();
                             }
                             array_push($objectPropertyLabels[$attributeURI], $value->nodeValue);
                         }
                         break;
                     case "_attr_obj_uri":
                         $values = $property->getElementsByTagName("str");
                         foreach ($values as $value) {
                             if (!is_array($objectPropertyUris[$attributeURI])) {
                                 $objectPropertyUris[$attributeURI] = array();
                             }
                             array_push($objectPropertyUris[$attributeURI], $value->nodeValue);
                         }
                         break;
                     case "_reify_attr":
                     case "_reify_attr_obj":
                     case "_reify_obj":
                     case "_reify_value_" . $this->ws->lang:
                         // @todo Implement reification in Search result. This means that reified statements should appears in the resultsets.
                         break;
                 }
             }
             // Get all dynamic fields attributes that are single-valued and for which the value is a string
             $resultProperties = $xpath->query("str", $result);
             foreach ($resultProperties as $property) {
                 $attribute = $property->getAttribute("name");
                 // Check what kind of attribute it is
                 $attributeType = $this->getSolrAttributeType($attribute);
                 // Get the URI of the attribute
                 $attributeURI = urldecode(str_replace($attributeType, "", $attribute));
                 if ($attributeType == "_attr_" . $this->ws->lang . "_single_valued") {
                     $subject->setDataAttribute($attributeURI, $property->nodeValue);
                 }
             }
             // Get all dynamic fields attributes that are single-valued and for which the value is a date
             $resultProperties = $xpath->query("date", $result);
             foreach ($resultProperties as $property) {
                 $attribute = $property->getAttribute("name");
                 // Check what kind of attribute it is
                 $attributeType = $this->getSolrAttributeType($attribute);
                 // Get the URI of the attribute
                 $attributeURI = urldecode(str_replace($attributeType, "", $attribute));
                 if ($attributeType == "_attr_date_single_valued") {
                     $subject->setDataAttribute($attributeURI, $property->nodeValue, Datatypes::$date);
                 }
             }
             // Get all dynamic fields attributes that are single-valued and for which the value is a integer
             $resultProperties = $xpath->query("int", $result);
             foreach ($resultProperties as $property) {
                 $attribute = $property->getAttribute("name");
                 // Check what kind of attribute it is
                 $attributeType = $this->getSolrAttributeType($attribute);
                 // Get the URI of the attribute
                 $attributeURI = urldecode(str_replace($attributeType, "", $attribute));
                 if ($attributeType == "_attr_int_single_valued") {
                     $subject->setDataAttribute($attributeURI, $property->nodeValue, Datatypes::$int);
                 }
             }
             // Get all dynamic fields attributes that are single-valued and for which the value is a float
             $resultProperties = $xpath->query("float", $result);
             foreach ($resultProperties as $property) {
                 $attribute = $property->getAttribute("name");
                 // Check what kind of attribute it is
                 $attributeType = $this->getSolrAttributeType($attribute);
                 // Get the URI of the attribute
                 $attributeURI = urldecode(str_replace($attributeType, "", $attribute));
                 if ($attributeType == "_attr_float_single_valued") {
                     $subject->setDataAttribute($attributeURI, $property->nodeValue, Datatypes::$float);
                 }
             }
             foreach ($objectPropertyUris as $attributeUri => $objectUris) {
                 foreach ($objectUris as $key => $objectUri) {
                     if (isset($objectPropertyLabels[$attributeUri][$key])) {
                         $subject->setObjectAttribute($attributeUri, $objectUri, array(Namespaces::$wsf . "objectLabel" => array($label = $objectPropertyLabels[$attributeUri][$key])));
                     } else {
                         $subject->setObjectAttribute($attributeUri, $objectUri);
                     }
                 }
             }
             unset($objectPropertyUris);
             unset($objectPropertyLabels);
             // Get the types of the resource.
             $resultTypes = $xpath->query("arr[@name='type']/str", $result);
             for ($i = 0; $i < $resultTypes->length; ++$i) {
                 if ($resultTypes->item($i)->nodeValue != "-") {
                     $subject->setType($resultTypes->item($i)->nodeValue);
                 }
             }
             $this->ws->rset->addSubject($subject, $resultDatasetURI->item(0)->nodeValue);
         }
     }
 }