예제 #1
0
파일: Store.php 프로젝트: FTeichmann/Erfurt
 /**
  * check and manipulate the declared FROMs according to the access control
  */
 protected function _prepareQuery($queryObject, &$options = array())
 {
     /*
      * clone the Query2 Object to not modify the original one
      * could be used elsewhere, could have side-effects
      */
     if ($queryObject instanceof Erfurt_Sparql_Query2) {
         //always clone
         //the query will be altered here to implement AC and owl:imports
         //dont make these changes global
         $queryObject = clone $queryObject;
         //bring triples etc. to canonical order
         // $queryObject->optimize();
     }
     $defaultOptions = array(Erfurt_Store::RESULTFORMAT => Erfurt_Store::RESULTFORMAT_PLAIN, Erfurt_Store::USE_AC => true, Erfurt_Store::USE_OWL_IMPORTS => true, Erfurt_Store::USE_ADDITIONAL_IMPORTS => true);
     if (!is_array($options)) {
         $options = array();
     }
     $options = array_merge($defaultOptions, $options);
     //typechecking
     if (is_string($queryObject)) {
         $queryObject = Erfurt_Sparql_SimpleQuery::initWithString($queryObject);
     }
     if (!($queryObject instanceof Erfurt_Sparql_Query2 || $queryObject instanceof Erfurt_Sparql_SimpleQuery)) {
         throw new Erfurt_Store_Exception('Argument 1 passed to Erfurt_Store::sparqlQuery must be instance of ' . 'Erfurt_Sparql_Query2, Erfurt_Sparql_SimpleQuery or string', 1);
     }
     /*
     if ($options[Erfurt_Store::USE_AC] == false) {
                 //we are done preparing early
                 return $queryObject;
             }
     */
     $logger = $this->_getQueryLogger();
     $noBindings = false;
     //get available models (readable)
     $available = array();
     if ($options[Erfurt_Store::USE_AC] === true) {
         $logger->debug('AC: use ac ');
         $availablepre = $this->getAvailableModels(true);
         //all readable (with ac)
         foreach ($availablepre as $key => $true) {
             $available[] = array('uri' => $key, 'named' => false);
         }
     } else {
         $logger->debug('AC: dont use ac ');
         $allpre = $this->_backendAdapter->getAvailableModels();
         //really all (without ac)
         foreach ($allpre as $key => $true) {
             $available[] = array('uri' => $key, 'named' => false);
         }
     }
     $logger->debug('AC: available models ' . $this->toStr($available));
     // examine froms (for access control and imports) in 5 steps
     // 1. extract froms for easier handling
     $froms = array();
     if ($queryObject instanceof Erfurt_Sparql_Query2) {
         foreach ($queryObject->getFroms() as $graphClause) {
             $uri = $graphClause->getGraphIri()->getIri();
             $froms[] = array('uri' => $uri, 'named' => $graphClause->isNamed());
         }
     } else {
         //SimpleQuery
         foreach ($queryObject->getFrom() as $graphClause) {
             $froms[] = array('uri' => $graphClause, 'named' => false);
         }
         foreach ($queryObject->getFromNamed() as $graphClause) {
             $froms[] = array('uri' => $graphClause, 'named' => true);
         }
     }
     $logger->debug('AC: requested FROMs' . $this->toStr($froms));
     // 2. no froms in query -> froms = availableModels
     if (empty($froms)) {
         $logger->debug('AC: no requested FROM -> take all available: ' . $this->toStr($available));
         $froms = $available;
     }
     // 3. filter froms by availability and existence - if filtering deletes all -> give empty result back
     if ($options[Erfurt_Store::USE_AC] === true) {
         $froms = $this->_maskModelList($froms, $available);
         $logger->debug('AC: after filtering (read-rights and existence): ' . $this->toStr($froms));
         if (empty($froms)) {
             $logger->debug('AC:  all disallowed - empty result');
             $noBindings = true;
         }
     }
     // 4. get import closure for every remaining from
     if ($options[Erfurt_Store::USE_OWL_IMPORTS] === true) {
         foreach ($froms as $from) {
             $importsClosure = $this->getImportsClosure($from['uri'], $options[Erfurt_Store::USE_ADDITIONAL_IMPORTS], $options[Erfurt_Store::USE_AC]);
             $logger->debug('AC:  import ' . $from['uri'] . ' -> ' . (empty($importsClosure) ? 'none' : implode(' ', $importsClosure)));
             foreach ($importsClosure as $importedGraphUri) {
                 $addCandidate = array('uri' => $importedGraphUri, 'named' => false);
                 //avoid duplicates
                 if (in_array($addCandidate, $available) && array_search($addCandidate, $froms) === false) {
                     $froms[] = $addCandidate;
                 }
             }
         }
     }
     $logger->debug('AC:  after imports: ' . $this->toStr($froms));
     // 5. put froms back
     if ($queryObject instanceof Erfurt_Sparql_Query2) {
         $queryObject->setFroms(array());
         foreach ($froms as $from) {
             $queryObject->addFrom($from['uri'], $from['named']);
         }
     } else {
         $queryObject->setFrom(array());
         $queryObject->setFromNamed(array());
         foreach ($froms as $from) {
             if (!$from['named']) {
                 $queryObject->addFrom($from['uri']);
             } else {
                 $queryObject->addFromNamed($from['uri']);
             }
         }
     }
     // if there were froms and all got deleted due to access controll - give back empty result set
     // this is achieved by replacing the where-part with an unsatisfiable one
     // i think this is efficient because otherwise we would have to deal with result formating und variables
     if ($noBindings) {
         $logger->debug('AC: force no bindings');
         if ($queryObject instanceof Erfurt_Sparql_SimpleQuery) {
             $queryObject->setWherePart('{FILTER(false)}');
         } else {
             if ($queryObject instanceof Erfurt_Sparql_Query2) {
                 $ggp = new Erfurt_Sparql_Query2_GroupGraphPattern();
                 $ggp->addFilter(false);
                 //unsatisfiable
                 $queryObject->removeAllProjectionVars();
                 $queryObject->setWhere($ggp);
             }
         }
     }
     return (string) $queryObject;
 }
예제 #2
0
파일: Model.php 프로젝트: FTeichmann/Erfurt
 /**
  * Moves resource to new URI
  * renaming all occurences of the resource.
  *
  * @param string $oldUri The URI that identifies the resource.
  * @param string $newUri The URI to move resource to.
  *
  * @return void
  */
 public function renameResource($oldUri, $newUri)
 {
     $query = new Erfurt_Sparql_Query2();
     $query->setDistinct(true);
     $vars = array();
     foreach (array('s', 'p', 'o') as $varName) {
         $vars[$varName] = new Erfurt_Sparql_Query2_Var($varName);
         $query->addProjectionVar($vars[$varName]);
     }
     $oldUriRef = new Erfurt_Sparql_Query2_IriRef($oldUri);
     $union = new Erfurt_Sparql_Query2_GroupOrUnionGraphPattern();
     foreach ($vars as $var) {
         $group = new Erfurt_Sparql_Query2_GroupGraphPattern();
         $group->addTriple($vars['s'], $vars['p'], $vars['o']);
         $group->addFilter(new Erfurt_Sparql_Query2_sameTerm($var, $oldUriRef));
         $union->addElement($group);
     }
     $query->addElement($union);
     $result = $this->sparqlQuery($query, array('result_format' => 'extended'));
     $removed = array();
     $added = array();
     foreach ($result['results']['bindings'] as $s) {
         // result format from sparqlQuery
         // isn't the same as format for delete/addMultipleStatements
         if (array_key_exists('xml:lang', $s['o'])) {
             $s['o']['lang'] = $s['o']['xml:lang'];
             unset($s['o']['xml:lang']);
         }
         $removed[$s['s']['value']][$s['p']['value']][] = $s['o'];
         foreach (array('s', 'p', 'o') as $varName) {
             if ($s[$varName]['type'] === 'uri' && $s[$varName]['value'] === $oldUri) {
                 $s[$varName]['value'] = $newUri;
             }
         }
         $added[$s['s']['value']][$s['p']['value']][] = $s['o'];
     }
     $this->deleteMultipleStatements($removed);
     $this->addMultipleStatements($added);
 }