|
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 } |