server/src/app/Libraries/Sparql/SparqlQueryAnalyser.php
changeset 386 c731ab9b934d
child 387 7fba86fa8604
equal deleted inserted replaced
385:f8200c5482ec 386:c731ab9b934d
       
     1 <?php
       
     2 namespace CorpusParole\Libraries\Sparql;
       
     3 
       
     4 use CorpusParole\Libraries\Utils;
       
     5 
       
     6 class SparqlQueryAnalyser {
       
     7 
       
     8     const SPARQL_PREFIX_BASE_REGEXP = '(((?:prefix\s+([\p{L}-\d]+)\s*\:)|base)\s*\<((?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?)\>)\s*';
       
     9 
       
    10     const SPARQL_SELECT_QUERY_REGEXP = '^(?:\s*(?:'.self::SPARQL_PREFIX_BASE_REGEXP.')*select)';
       
    11     const SPARQL_ASK_QUERY_REGEXP = '^(?:\s*(?:'.self::SPARQL_PREFIX_BASE_REGEXP.')*ask)';
       
    12     const SPARQL_GRAPH_QUERY_REGEXP = '^(?:\s*(?:'.self::SPARQL_PREFIX_BASE_REGEXP.')*(?:(?:construct)|(?:describe)))';
       
    13 
       
    14     const SPARQL_LIMIT_OFFSET_QUERY_REGEXP = '(?:(?:(limit\s+(\d+))|(offset\s+(\d+)))\s*)+\s*$';
       
    15 
       
    16     const UNKNOWN_QUERY = 0;
       
    17     const SELECT_QUERY = 1;
       
    18     const GRAPH_QUERY = 2;
       
    19     const ASK_QUERY = 2;
       
    20 
       
    21     private $query;
       
    22     private $queryType = false;
       
    23     private $rawPrefixes = false;
       
    24     private $prefixes = false;
       
    25     private $limit = false;
       
    26     private $offset = false;
       
    27     private $rawQuery = false;
       
    28     private $countVar = false;
       
    29 
       
    30     public function __construct($query) {
       
    31         $this->query = $query;
       
    32     }
       
    33 
       
    34     public function getQueryType() {
       
    35 
       
    36         if($this->queryType === false) {
       
    37             if(preg_match("%".self::SPARQL_SELECT_QUERY_REGEXP."%iu", $this->query) === 1) {
       
    38                 $this->queryType = self::SELECT_QUERY;
       
    39             } elseif(preg_match("%".self::SPARQL_GRAPH_QUERY_REGEXP."%iu", $this->query) === 1) {
       
    40                 $this->queryType = self::GRAPH_QUERY;
       
    41             } elseif(preg_match("%".self::SPARQL_ASK_QUERY_REGEXP."%iu", $this->query) === 1) {
       
    42                 $this->queryType = self::ASK_QUERY;
       
    43             } else {
       
    44                 $this->queryType = self::UNKNOWN_QUERY;
       
    45             }
       
    46         }
       
    47         return $this->queryType;
       
    48     }
       
    49 
       
    50     private function extractPrefix() {
       
    51         $prefixes = [];
       
    52         $rawPrefixes = [];
       
    53         $res = preg_replace_callback("%".self::SPARQL_PREFIX_BASE_REGEXP."%iu", function($m) use (&$prefixes, &$rawPrefixes) {
       
    54             $rawPrefixes[] = trim($m[0]);
       
    55             $prefixes[$m[3]?$m[3]:""] = $m[4];
       
    56             return "";
       
    57         }, $this->query);
       
    58 
       
    59         return [$rawPrefixes, $prefixes, trim($res)];
       
    60     }
       
    61 
       
    62     public function getRawPrefixes() {
       
    63         if($this->rawPrefixes === false) {
       
    64             list($this->rawPrefixes, $this->prefixes, $this->rawQuery) = $this->extractPrefix();
       
    65         }
       
    66         return $this->rawPrefixes;
       
    67     }
       
    68 
       
    69     public function getPrefixes() {
       
    70         if($this->prefixes === false) {
       
    71             list($this->rawPrefixes, $this->prefixes, $this->rawQuery) = $this->extractPrefix();
       
    72         }
       
    73         return $this->prefixes;
       
    74     }
       
    75 
       
    76     public function getRawQuery() {
       
    77         if($this->rawQuery === false) {
       
    78             list($this->rawPrefixes, $this->prefixes, $this->rawQuery) = $this->extractPrefix();
       
    79         }
       
    80         return $this->rawQuery;
       
    81     }
       
    82 
       
    83     public function getCountVar() {
       
    84         if($this->countVar === false) {
       
    85             $this->countVar = "?count_cp_".hash('md5', $this->query);
       
    86         }
       
    87         return $this->countVar;
       
    88     }
       
    89 
       
    90     public function getCountQuery() {
       
    91         return implode(" ", $this->getRawPrefixes())." select (count(*) as ".$this->getCountVar().") { ".$this->getRawQuery()." }";
       
    92     }
       
    93 
       
    94     private function setLimitOffset() {
       
    95         if(preg_match("%".self::SPARQL_LIMIT_OFFSET_QUERY_REGEXP."%iu", $this->query, $m) === 1) {
       
    96             for($i=0;$i<(count($m)-1)/2;$i++) {
       
    97                 if(Utils::startsWith(strtolower($m[2*$i+1]), "limit")) {
       
    98                     $this->limit = intval($m[$i*2+2]);
       
    99                 } elseif (Utils::startsWith(strtolower($m[2*$i+1]), "offset")) {
       
   100                     $this->offset = intval($m[$i*2+2]);
       
   101                 }
       
   102             }
       
   103         }
       
   104         if($this->limit === false) {
       
   105             $this->limit = null;
       
   106         }
       
   107         if($this->offset === false) {
       
   108             $this->offset = null;
       
   109         }
       
   110     }
       
   111 
       
   112     public function getLimit() {
       
   113         if($this->limit === false) {
       
   114             $this->setLimitOffset();
       
   115         }
       
   116         return $this->limit;
       
   117     }
       
   118 
       
   119     public function getOffset() {
       
   120         if($this->offset === false) {
       
   121             $this->setLimitOffset();
       
   122         }
       
   123         return $this->offset;
       
   124     }
       
   125 
       
   126 }