PageRenderTime 48ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/v1/mod_semanticweb/arc/store/ARC2_StoreEndpoint.php

https://code.google.com/p/goodrelations-for-joomla/
PHP | 1012 lines | 884 code | 78 blank | 50 comment | 83 complexity | 2bcce33ff152b42f88f45c0e67ab34a8 MD5 | raw file
  1. <?php
  2. /*
  3. homepage: http://arc.semsol.org/
  4. license: http://arc.semsol.org/license
  5. class: ARC2 SPARQL Endpoint
  6. author: Benjamin Nowack
  7. version: 2008-09-03 (Addition: support for "sql" and "infos" result formats (activate the former via "endpoint_enable_sql_output"))
  8. */
  9. ARC2::inc('Store');
  10. class ARC2_StoreEndpoint extends ARC2_Store {
  11. function __construct($a = '', &$caller) {
  12. parent::__construct($a, $caller);
  13. }
  14. function ARC2_StoreEndpoint($a = '', &$caller) {
  15. $this->__construct($a, $caller);
  16. }
  17. function __init() {
  18. parent::__init();
  19. $this->headers = array('http' => 'HTTP/1.1 200 OK', 'vary' => 'Vary: Accept');
  20. $this->read_key = $this->v('endpoint_read_key', '', $this->a);
  21. $this->write_key = $this->v('endpoint_write_key', '', $this->a);
  22. $this->a['store_allow_extension_functions'] = $this->v('store_allow_extension_functions', 0, $this->a);
  23. $this->allow_sql = $this->v('endpoint_enable_sql_output', 0, $this->a);
  24. $this->result = '';
  25. }
  26. /* */
  27. function getQueryString($mthd = '') {
  28. $r = '';
  29. if (!$mthd || ($mthd == 'post')) {
  30. $r = @file_get_contents('php://input');
  31. }
  32. $r = !$r ?$this->v1('QUERY_STRING', '', $_SERVER) : $r;
  33. return $r;
  34. }
  35. function p($name='', $mthd = '', $multi = '', $default = '') {
  36. $mthd = strtolower($mthd);
  37. if($multi){
  38. $qs = $this->getQueryString($mthd);
  39. if (preg_match_all('/\&' . $name . '=([^\&]*)/', $qs, $m)){
  40. foreach ($m[1] as $i => $val) {
  41. $m[1][$i] = stripslashes($val);
  42. }
  43. return $m[1];
  44. }
  45. return $default ? $default : array();
  46. }
  47. $args = array_merge($_GET, $_POST);
  48. $r = isset($args[$name]) ? $args[$name] : $default;
  49. return is_array($r) ? $r : stripslashes($r);
  50. }
  51. /* */
  52. function getFeatures() {
  53. return $this->v1('endpoint_features', array(), $this->a);
  54. }
  55. function setHeader($k, $v) {
  56. $this->headers[$k] = $v;
  57. }
  58. function sendHeaders() {
  59. if (!isset($this->is_dump) || !$this->is_dump) {
  60. $this->setHeader('content-length', 'Content-Length: ' . strlen($this->getResult()));
  61. foreach ($this->headers as $k => $v) {
  62. header($v);
  63. }
  64. }
  65. }
  66. function getResult() {
  67. return $this->result;
  68. }
  69. /* */
  70. function handleRequest($auto_setup = 0) {
  71. if (!$this->isSetUp()) {
  72. if ($auto_setup) {
  73. $this->setUp();
  74. return $this->handleRequest();
  75. }
  76. else {
  77. $this->setHeader('http', 'HTTP/1.1 400 Bad Request');
  78. $this->setHeader('content-type', 'Content-type: text/plain; charset=utf-8');
  79. $this->result = 'Missing configuration or the endpoint store was not set up yet.';
  80. }
  81. }
  82. elseif ($img = $this->p('img')) {
  83. $this->handleImgRequest($img);
  84. }
  85. elseif ($q = $this->p('query')) {
  86. $this->checkProcesses();
  87. $this->handleQueryRequest($q);
  88. if ($this->p('show_inline')) {
  89. $this->query_result = '
  90. <div class="results">
  91. ' . ($this->p('output') != 'htmltab' ? '<pre>' . htmlspecialchars($this->getResult()) . '</pre>' : $this->getResult()) . '
  92. </div>
  93. ';
  94. $this->handleEmptyRequest();
  95. }
  96. }
  97. else {
  98. $this->handleEmptyRequest();
  99. }
  100. }
  101. function go($auto_setup = 0) {
  102. $this->handleRequest($auto_setup);
  103. $this->sendHeaders();
  104. echo $this->getResult();
  105. }
  106. /* */
  107. function handleImgRequest($img) {
  108. $this->setHeader('content-type', 'Content-type: image/gif');
  109. $imgs = array(
  110. 'bg_body' => base64_decode('R0lGODlhAQBkAMQAAPf39/Hx8erq6vPz8/Ly8u/v7+np6fT09Ovr6/b29u3t7ejo6Pz8/Pv7+/39/fr6+vj4+P7+/vn5+f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAABAGQAAAUp4GIIiFIExHAkAAC9cAxJdG3TT67vTe//jKBQ6Cgaj5GkcpmcOJ/QZwgAOw=='),
  111. );
  112. $this->result = isset($imgs[$img]) ? $imgs[$img] : '';
  113. $this->sendHeaders();
  114. echo $this->getResult();
  115. exit;
  116. }
  117. /* */
  118. function handleEmptyRequest() {
  119. $this->setHeader('content-type', 'Content-type: text/html; charset=utf-8');
  120. $this->result = $this->getHTMLFormDoc();
  121. }
  122. /* */
  123. function checkProcesses() {
  124. }
  125. /* */
  126. function handleQueryRequest($q) {
  127. if (preg_match('/^dump/i', $q)) {
  128. $infos = array('query' => array('type' => 'dump'));
  129. $this->is_dump = 1;
  130. }
  131. else {
  132. ARC2::inc('SPARQLPlusParser');
  133. $p = & new ARC2_SPARQLPlusParser($this->a, $this);
  134. $p->parse($q);
  135. $infos = $p->getQueryInfos();
  136. }
  137. /* errors? */
  138. if ($errors = $this->getErrors()) {
  139. $this->setHeader('http', 'HTTP/1.1 400 Bad Request');
  140. $this->setHeader('content-type', 'Content-type: text/plain; charset=utf-8');
  141. $this->result = join("\n", $errors);
  142. return true;
  143. }
  144. $qt = $infos['query']['type'];
  145. /* wrong read key? */
  146. if ($this->read_key && ($this->p('key') != $this->read_key) && preg_match('/^(select|ask|construct|describe|dump)$/', $qt)) {
  147. $this->setHeader('http', 'HTTP/1.1 401 Access denied');
  148. $this->setHeader('content-type', 'Content-type: text/plain; charset=utf-8');
  149. $this->result = 'Access denied. Missing or wrong "key" parameter.';
  150. return true;
  151. }
  152. /* wrong write key? */
  153. if ($this->write_key && ($this->p('key') != $this->write_key) && preg_match('/^(load|insert|delete|update)$/', $qt)) {
  154. $this->setHeader('http', 'HTTP/1.1 401 Access denied');
  155. $this->setHeader('content-type', 'Content-type: text/plain; charset=utf-8');
  156. $this->result = 'Access denied. Missing or wrong "key" parameter.';
  157. return true;
  158. }
  159. /* non-allowed query type? */
  160. if (!in_array($qt, $this->getFeatures())) {
  161. $this->setHeader('http', 'HTTP/1.1 401 Access denied');
  162. $this->setHeader('content-type', 'Content-type: text/plain; charset=utf-8');
  163. $this->result = 'Access denied for "' .$qt. '" query';
  164. return true;
  165. }
  166. /* load/insert/delete via GET */
  167. if (in_array($qt, array('load', 'insert', 'delete')) && isset($_GET['query'])) {
  168. $this->setHeader('http', 'HTTP/1.1 501 Not Implemented');
  169. $this->setHeader('content-type', 'Content-type: text/plain; charset=utf-8');
  170. $this->result = 'Query type "' .$qt. '" not supported via GET';
  171. return true;
  172. }
  173. /* unsupported query type */
  174. if (!in_array($qt, array('select', 'ask', 'describe', 'construct', 'load', 'insert', 'delete', 'dump'))) {
  175. $this->setHeader('http', 'HTTP/1.1 501 Not Implemented');
  176. $this->setHeader('content-type', 'Content-type: text/plain; charset=utf-8');
  177. $this->result = 'Unsupported query type "' .$qt. '"';
  178. return true;
  179. }
  180. /* adjust infos */
  181. $infos = $this->adjustQueryInfos($infos);
  182. $t1 = ARC2::mtime();
  183. $r = array('result' => $this->runQuery($infos, $qt));
  184. $t2 = ARC2::mtime();
  185. $r['query_time'] = $t2 - $t1;
  186. /* query errors? */
  187. if ($errors = $this->getErrors()) {
  188. $this->setHeader('http', 'HTTP/1.1 400 Bad Request');
  189. $this->setHeader('content-type', 'Content-type: text/plain; charset=utf-8');
  190. $this->result = 'Error: ' . join("\n", $errors);
  191. return true;
  192. }
  193. /* result */
  194. $m = 'get' . ucfirst($qt) . 'ResultDoc';
  195. if (method_exists($this, $m)) {
  196. $this->result = $this->$m($r);
  197. }
  198. else {
  199. $this->setHeader('content-type', 'Content-type: text/plain; charset=utf-8');
  200. $this->result = 'Result serializer not available, dumping raw data:' . "\n" . print_r($r, 1);
  201. }
  202. }
  203. /* */
  204. function adjustQueryInfos($infos) {
  205. /* limit */
  206. if ($max_l = $this->v('endpoint_max_limit', 0, $this->a)) {
  207. if ($this->v('limit', $max_l + 1, $infos['query']) > $max_l) {
  208. $infos['query']['limit'] = $max_l;
  209. }
  210. }
  211. /* default-graph-uri / named-graph-uri */
  212. $dgs = $this->p('default-graph-uri', '', 1);
  213. $ngs = $this->p('named-graph-uri', '', 1);
  214. if (count(array_merge($dgs, $ngs))) {
  215. $ds = array();
  216. foreach ($dgs as $g) {
  217. $ds[] = array('graph' => $this->calcURI($g), 'named' => 0);
  218. }
  219. foreach ($ngs as $g) {
  220. $ds[] = array('graph' => $this->calcURI($g), 'named' => 1);
  221. }
  222. $infos['query']['dataset'] = $ds;
  223. }
  224. /* infos result format */
  225. if (($this->p('format') == 'infos') || ($this->p('output') == 'infos')) {
  226. $infos['result_format'] = 'structure';
  227. }
  228. /* sql result format */
  229. if (($this->p('format') == 'sql') || ($this->p('output') == 'sql')) {
  230. $infos['result_format'] = 'sql';
  231. }
  232. return $infos;
  233. }
  234. /* */
  235. function getResultFormat($formats, $default) {
  236. $prefs = array();
  237. /* arg */
  238. if (($v = $this->p('format')) || ($v = $this->p('output'))) {
  239. $prefs[] = $v;
  240. }
  241. /* accept header */
  242. if ($vals = explode(',', $_SERVER['HTTP_ACCEPT'])) {
  243. $o_vals = array();
  244. foreach ($vals as $val) {
  245. if (preg_match('/(rdf\+n3|x\-turtle|rdf\+xml|sparql\-results\+xml|sparql\-results\+json|json)/', $val, $m)) {
  246. $o_vals[$m[1]] = 1;
  247. if (preg_match('/\;q\=([0-9\.]+)/', $val, $sub_m)) {
  248. $o_vals[$m[1]] = 1 * $sub_m[1];
  249. }
  250. }
  251. }
  252. arsort($o_vals);
  253. foreach ($o_vals as $val => $prio) {
  254. $prefs[] = $val;
  255. }
  256. }
  257. /* default */
  258. $prefs[] = $default;
  259. foreach ($prefs as $pref) {
  260. if (isset($formats[$pref])) {
  261. return $formats[$pref];
  262. }
  263. }
  264. }
  265. /* */
  266. function getSelectResultDoc($r) {
  267. $formats = array(
  268. 'xml' => 'SPARQLXML', 'sparql-results+xml' => 'SPARQLXML',
  269. 'json' => 'SPARQLJSON', 'sparql-results+json' => 'SPARQLJSON',
  270. 'php_ser' => 'PHPSER', 'plain' => 'Plain',
  271. 'sql' => ($this->allow_sql ? 'SQL' : 'xSQL'),
  272. 'infos' => 'Plain',
  273. 'htmltab' => 'HTMLTable',
  274. );
  275. if ($f = $this->getResultFormat($formats, 'xml')) {
  276. $m = 'get' . $f . 'SelectResultDoc';
  277. return method_exists($this, $m) ? $this->$m($r) : 'not implemented';
  278. }
  279. return '';
  280. }
  281. function getSPARQLXMLSelectResultDoc($r) {
  282. $this->setHeader('content-type', 'Content-Type: application/sparql-results+xml');
  283. $vars = $r['result']['variables'];
  284. $rows = $r['result']['rows'];
  285. $dur = $r['query_time'];
  286. $nl = "\n";
  287. /* doc */
  288. $r = '' .
  289. '<?xml version="1.0"?>' .
  290. $nl . '<sparql xmlns="http://www.w3.org/2005/sparql-results#">' .
  291. '';
  292. /* head */
  293. $r .= $nl . ' <head>';
  294. $r .= $nl . ' <!-- query time: '. round($dur, 4) .' sec -->';
  295. if (is_array($vars)) {
  296. foreach ($vars as $var) {
  297. $r .= $nl . ' <variable name="' .$var. '"/>';
  298. }
  299. }
  300. $r .= $nl . ' </head>';
  301. /* results */
  302. $r .= $nl . ' <results>';
  303. if (is_array($rows)) {
  304. foreach ($rows as $row) {
  305. $r .= $nl . ' <result>';
  306. foreach ($vars as $var) {
  307. if (isset($row[$var])) {
  308. $r .= $nl . ' <binding name="' .$var. '">';
  309. if ($row[$var . ' type'] == 'uri') {
  310. $r .= $nl . ' <uri>' .htmlspecialchars($row[$var]). '</uri>';
  311. }
  312. elseif ($row[$var . ' type'] == 'bnode') {
  313. $r .= $nl . ' <bnode>' .substr($row[$var], 2). '</bnode>';
  314. }
  315. else {
  316. $dt = isset($row[$var . ' datatype']) ? ' datatype="' .htmlspecialchars($row[$var . ' datatype']). '"' : '';
  317. $lang = isset($row[$var . ' lang']) ? ' xml:lang="' .htmlspecialchars($row[$var . ' lang']). '"' : '';
  318. $r .= $nl . ' <literal' . $dt . $lang . '>' .htmlspecialchars($row[$var]). '</literal>';
  319. }
  320. $r .= $nl . ' </binding>';
  321. }
  322. }
  323. $r .= $nl . ' </result>';
  324. }
  325. }
  326. $r .= $nl . ' </results>';
  327. /* /doc */
  328. $r .= $nl . '</sparql>';
  329. return $r;
  330. }
  331. function getSPARQLJSONSelectResultDoc($r) {
  332. $con = $this->getDBCon();
  333. $this->setHeader('content-type', 'Content-Type: application/sparql-results+json');
  334. $vars = $r['result']['variables'];
  335. $rows = $r['result']['rows'];
  336. $dur = $r['query_time'];
  337. $nl = "\n";
  338. /* doc */
  339. $r = '{';
  340. /* head */
  341. $r .= $nl . ' "head": {';
  342. $r .= $nl . ' "vars": [';
  343. $first_var = 1;
  344. foreach ($vars as $var) {
  345. $r .= $first_var ? $nl : ',' . $nl;
  346. $r .= ' "' .$var. '"';
  347. $first_var = 0;
  348. }
  349. $r .= $nl . ' ]';
  350. $r .= $nl . ' },';
  351. /* results */
  352. $r .= $nl . ' "results": {';
  353. $r .= $nl . ' "bindings": [';
  354. $first_row = 1;
  355. foreach ($rows as $row) {
  356. $r .= $first_row ? $nl : ',' . $nl;
  357. $r .= ' {';
  358. $first_var = 1;
  359. foreach ($vars as $var) {
  360. if (isset($row[$var])) {
  361. $r .= $first_var ? $nl : ',' . $nl . $nl;
  362. $r .= ' "' .$var. '": {';
  363. if ($row[$var . ' type'] == 'uri') {
  364. $r .= $nl . ' "type": "uri",';
  365. $r .= $nl . ' "value": "' .mysql_real_escape_string($row[$var], $con). '"';
  366. }
  367. elseif ($row[$var . ' type'] == 'bnode') {
  368. $r .= $nl . ' "type": "bnode",';
  369. $r .= $nl . ' "value": "' . substr($row[$var], 2) . '"';
  370. }
  371. else {
  372. $dt = isset($row[$var . ' datatype']) ? ',' . $nl .' "datatype": "' .mysql_real_escape_string($row[$var . ' datatype'], $con). '"' : '';
  373. $lang = isset($row[$var . ' lang']) ? ',' . $nl .' "xml:lang": "' .mysql_real_escape_string($row[$var . ' lang'], $con). '"' : '';
  374. $type = $dt ? 'typed-literal' : 'literal';
  375. $r .= $nl . ' "type": "' . $type . '",';
  376. $r .= $nl . ' "value": "' . $this->jsonEscape($row[$var]) . '"';
  377. $r .= $dt . $lang;
  378. }
  379. $r .= $nl . ' }';
  380. $first_var = 0;
  381. }
  382. }
  383. $r .= $nl . ' }';
  384. $first_row = 0;
  385. }
  386. $r .= $nl . ' ]';
  387. $r .= $nl . ' }';
  388. /* /doc */
  389. $r .= $nl . '}';
  390. if (($v = $this->p('jsonp')) || ($v = $this->p('callback'))) {
  391. $r = $v . '(' . $r . ')';
  392. }
  393. return $r;
  394. }
  395. function getPHPSERSelectResultDoc($r) {
  396. $this->setHeader('content-type', 'Content-Type: text/plain');
  397. return serialize($r);
  398. }
  399. function getSQLSelectResultDoc($r) {
  400. $this->setHeader('content-type', 'Content-Type: text/plain');
  401. return $r['result'];
  402. }
  403. function getPlainSelectResultDoc($r) {
  404. $this->setHeader('content-type', 'Content-Type: text/plain');
  405. return print_r($r['result'], 1);
  406. }
  407. function getHTMLTableSelectResultDoc($r) {
  408. $this->setHeader('content-type', 'Content-Type: text/html; charset=utf-8');
  409. $vars = $r['result']['variables'];
  410. $rows = $r['result']['rows'];
  411. $dur = $r['query_time'];
  412. if ($this->p('show_inline')) return '<table>' . $this->getHTMLTableRows($rows, $vars) . '</table>';
  413. return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  414. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  415. ' .$this->getHTMLDocHead() . '
  416. <body>
  417. <table>
  418. ' . $this->getHTMLTableRows($rows, $vars) . '
  419. </table>
  420. </body>
  421. </html>
  422. ';
  423. }
  424. function getHTMLTableRows($rows, $vars) {
  425. $r = '';
  426. foreach ($rows as $row) {
  427. $hr = '';
  428. $rr = '';
  429. foreach ($vars as $var) {
  430. $hr .= $r ? '' : '<th>' . htmlspecialchars($var) . '</th>';
  431. $rr .= '<td>' . @htmlspecialchars($row[$var]) . '</td>';
  432. }
  433. $r .= $hr ? '<tr>' . $hr . '</tr>' : '';
  434. $r .= '<tr>' . $rr . '</tr>';
  435. }
  436. return $r ? $r : '<em>No results found</em>';
  437. }
  438. /* */
  439. function getAskResultDoc($r) {
  440. $formats = array(
  441. 'xml' => 'SPARQLXML', 'sparql-results+xml' => 'SPARQLXML',
  442. 'json' => 'SPARQLJSON', 'sparql-results+json' => 'SPARQLJSON',
  443. 'plain' => 'Plain',
  444. 'php_ser' => 'PHPSER'
  445. );
  446. if ($f = $this->getResultFormat($formats, 'xml')) {
  447. $m = 'get' . $f . 'AskResultDoc';
  448. return method_exists($this, $m) ? $this->$m($r) : 'not implemented';
  449. }
  450. return '';
  451. }
  452. function getSPARQLXMLAskResultDoc($r) {
  453. $this->setHeader('content-type', 'Content-Type: application/sparql-results+xml');
  454. $r_val = $r['result'] ? 'true' : 'false';
  455. $dur = $r['query_time'];
  456. $nl = "\n";
  457. return '' .
  458. '<?xml version="1.0"?>' .
  459. $nl . '<sparql xmlns="http://www.w3.org/2005/sparql-results#">' .
  460. $nl . ' <head>' .
  461. $nl . ' <!-- query time: '. round($dur, 4) .' sec -->' .
  462. $nl . ' </head>' .
  463. $nl . ' <boolean>' .$r_val. '</boolean>' .
  464. $nl . '</sparql>' .
  465. '';
  466. }
  467. function getSPARQLJSONAskResultDoc($r) {
  468. $this->setHeader('content-type', 'Content-Type: application/sparql-results+json');
  469. $r_val = $r['result'] ? 'true' : 'false';
  470. $dur = $r['query_time'];
  471. $nl = "\n";
  472. $r = '' .
  473. $nl . '{' .
  474. $nl . ' "head": {' .
  475. $nl . ' },' .
  476. $nl . ' "boolean" : ' . $r_val .
  477. $nl . '}' .
  478. '';
  479. if (($v = $this->p('jsonp')) || ($v = $this->p('callback'))) {
  480. $r = $v . '(' . $r . ')';
  481. }
  482. return $r;
  483. }
  484. function getPHPSERAskResultDoc($r) {
  485. $this->setHeader('content-type', 'Content-Type: text/plain');
  486. return serialize($r);
  487. }
  488. function getPlainAskResultDoc($r) {
  489. $this->setHeader('content-type', 'Content-Type: text/plain');
  490. return $r['result'] ? 'true' : 'false';
  491. }
  492. /* */
  493. function getConstructResultDoc($r) {
  494. $formats = array(
  495. 'rdfxml' => 'RDFXML', 'rdf+xml' => 'RDFXML',
  496. 'json' => 'RDFJSON', 'rdf+json' => 'RDFJSON',
  497. 'turtle' => 'Turtle', 'x-turtle' => 'Turtle', 'rdf+n3' => 'Turtle',
  498. 'php_ser' => 'PHPSER'
  499. );
  500. if ($f = $this->getResultFormat($formats, 'rdfxml')) {
  501. $m = 'get' . $f . 'ConstructResultDoc';
  502. return method_exists($this, $m) ? $this->$m($r) : 'not implemented';
  503. }
  504. return '';
  505. }
  506. function getRDFXMLConstructResultDoc($r) {
  507. $this->setHeader('content-type', 'Content-Type: application/rdf+xml');
  508. $index = $r['result'];
  509. $ser = ARC2::getRDFXMLSerializer($this->a);
  510. $dur = $r['query_time'];
  511. return $ser->getSerializedIndex($index) . "\n" . '<!-- query time: ' . $dur . ' -->';
  512. }
  513. function getTurtleConstructResultDoc($r) {
  514. $this->setHeader('content-type', 'Content-Type: application/x-turtle');
  515. $index = $r['result'];
  516. $ser = ARC2::getTurtleSerializer($this->a);
  517. $dur = $r['query_time'];
  518. return '# query time: ' . $dur . "\n" . $ser->getSerializedIndex($index);
  519. }
  520. function getRDFJSONConstructResultDoc($r) {
  521. $this->setHeader('content-type', 'Content-Type: application/json');
  522. $index = $r['result'];
  523. $ser = ARC2::getRDFJSONSerializer($this->a);
  524. $dur = $r['query_time'];
  525. $r = $ser->getSerializedIndex($index);
  526. if (($v = $this->p('jsonp')) || ($v = $this->p('callback'))) {
  527. $r = $v . '(' . $r . ')';
  528. }
  529. return $r;
  530. }
  531. function getPHPSERConstructResultDoc($r) {
  532. $this->setHeader('content-type', 'Content-Type: text/plain');
  533. return serialize($r);
  534. }
  535. /* */
  536. function getDescribeResultDoc($r) {
  537. $formats = array(
  538. 'rdfxml' => 'RDFXML', 'rdf+xml' => 'RDFXML',
  539. 'json' => 'RDFJSON', 'rdf+json' => 'RDFJSON',
  540. 'turtle' => 'Turtle', 'x-turtle' => 'Turtle', 'rdf+n3' => 'Turtle',
  541. 'php_ser' => 'PHPSER'
  542. );
  543. if ($f = $this->getResultFormat($formats, 'rdfxml')) {
  544. $m = 'get' . $f . 'DescribeResultDoc';
  545. return method_exists($this, $m) ? $this->$m($r) : 'not implemented';
  546. }
  547. return '';
  548. }
  549. function getRDFXMLDescribeResultDoc($r) {
  550. $this->setHeader('content-type', 'Content-Type: application/rdf+xml');
  551. $index = $r['result'];
  552. $ser = ARC2::getRDFXMLSerializer($this->a);
  553. $dur = $r['query_time'];
  554. return $ser->getSerializedIndex($index) . "\n" . '<!-- query time: ' . $dur . ' -->';
  555. }
  556. function getTurtleDescribeResultDoc($r) {
  557. $this->setHeader('content-type', 'Content-Type: application/x-turtle');
  558. $index = $r['result'];
  559. $ser = ARC2::getTurtleSerializer($this->a);
  560. $dur = $r['query_time'];
  561. return '# query time: ' . $dur . "\n" . $ser->getSerializedIndex($index);
  562. }
  563. function getRDFJSONDescribeResultDoc($r) {
  564. $this->setHeader('content-type', 'Content-Type: application/json');
  565. $index = $r['result'];
  566. $ser = ARC2::getRDFJSONSerializer($this->a);
  567. $dur = $r['query_time'];
  568. $r = $ser->getSerializedIndex($index);
  569. if (($v = $this->p('jsonp')) || ($v = $this->p('callback'))) {
  570. $r = $v . '(' . $r . ')';
  571. }
  572. return $r;
  573. }
  574. function getPHPSERDescribeResultDoc($r) {
  575. $this->setHeader('content-type', 'Content-Type: text/plain');
  576. return serialize($r);
  577. }
  578. /* */
  579. function getDumpResultDoc() {
  580. $this->headers = array();
  581. return '';
  582. }
  583. /* */
  584. function getLoadResultDoc($r) {
  585. $formats = array(
  586. 'xml' => 'SPARQLXML', 'sparql-results+xml' => 'SPARQLXML',
  587. 'json' => 'SPARQLJSON', 'sparql-results+json' => 'SPARQLJSON',
  588. 'plain' => 'Plain',
  589. 'php_ser' => 'PHPSER'
  590. );
  591. if ($f = $this->getResultFormat($formats, 'xml')) {
  592. $m = 'get' . $f . 'LoadResultDoc';
  593. return method_exists($this, $m) ? $this->$m($r) : 'not implemented';
  594. }
  595. return '';
  596. }
  597. function getSPARQLXMLLoadResultDoc($r) {
  598. $this->setHeader('content-type', 'Content-Type: application/sparql-results+xml');
  599. $r_val = $r['result']['t_count'];
  600. $dur = $r['query_time'];
  601. $nl = "\n";
  602. return '' .
  603. '<?xml version="1.0"?>' .
  604. $nl . '<sparql xmlns="http://www.w3.org/2005/sparql-results#">' .
  605. $nl . ' <head>' .
  606. $nl . ' <!-- query time: '. round($dur, 4) .' sec -->' .
  607. $nl . ' </head>' .
  608. $nl . ' <inserted>' .$r_val. '</inserted>' .
  609. $nl . '</sparql>' .
  610. '';
  611. }
  612. function getSPARQLJSONLoadResultDoc($r) {
  613. $this->setHeader('content-type', 'Content-Type: application/sparql-results+json');
  614. $r_val = $r['result']['t_count'];
  615. $dur = $r['query_time'];
  616. $nl = "\n";
  617. $r = '' .
  618. $nl . '{' .
  619. $nl . ' "head": {' .
  620. $nl . ' },' .
  621. $nl . ' "inserted" : ' . $r_val .
  622. $nl . '}' .
  623. '';
  624. if (($v = $this->p('jsonp')) || ($v = $this->p('callback'))) {
  625. $r = $v . '(' . $r . ')';
  626. }
  627. return $r;
  628. }
  629. function getPHPSERLoadResultDoc($r) {
  630. $this->setHeader('content-type', 'Content-Type: text/plain');
  631. return serialize($r);
  632. }
  633. function getPlainLoadResultDoc($r) {
  634. $this->setHeader('content-type', 'Content-Type: text/plain');
  635. return $r['result'] ? 'true' : 'false';
  636. }
  637. /* */
  638. function getDeleteResultDoc($r) {
  639. $formats = array(
  640. 'xml' => 'SPARQLXML', 'sparql-results+xml' => 'SPARQLXML',
  641. 'json' => 'SPARQLJSON', 'sparql-results+json' => 'SPARQLJSON',
  642. 'plain' => 'Plain',
  643. 'php_ser' => 'PHPSER'
  644. );
  645. if ($f = $this->getResultFormat($formats, 'xml')) {
  646. $m = 'get' . $f . 'DeleteResultDoc';
  647. return method_exists($this, $m) ? $this->$m($r) : 'not implemented';
  648. }
  649. return '';
  650. }
  651. function getSPARQLXMLDeleteResultDoc($r) {
  652. $this->setHeader('content-type', 'Content-Type: application/sparql-results+xml');
  653. $r_val = $r['result']['t_count'];
  654. $dur = $r['query_time'];
  655. $nl = "\n";
  656. return '' .
  657. '<?xml version="1.0"?>' .
  658. $nl . '<sparql xmlns="http://www.w3.org/2005/sparql-results#">' .
  659. $nl . ' <head>' .
  660. $nl . ' <!-- query time: '. round($dur, 4) .' sec -->' .
  661. $nl . ' </head>' .
  662. $nl . ' <deleted>' .$r_val. '</deleted>' .
  663. $nl . '</sparql>' .
  664. '';
  665. }
  666. function getSPARQLJSONDeleteResultDoc($r) {
  667. $this->setHeader('content-type', 'Content-Type: application/sparql-results+json');
  668. $r_val = $r['result']['t_count'];
  669. $dur = $r['query_time'];
  670. $nl = "\n";
  671. $r = '' .
  672. $nl . '{' .
  673. $nl . ' "head": {' .
  674. $nl . ' },' .
  675. $nl . ' "deleted" : ' . $r_val .
  676. $nl . '}' .
  677. '';
  678. if (($v = $this->p('jsonp')) || ($v = $this->p('callback'))) {
  679. $r = $v . '(' . $r . ')';
  680. }
  681. return $r;
  682. }
  683. function getPHPSERDeleteResultDoc($r) {
  684. $this->setHeader('content-type', 'Content-Type: text/plain');
  685. return serialize($r);
  686. }
  687. function getPlainDeleteResultDoc($r) {
  688. $this->setHeader('content-type', 'Content-Type: text/plain');
  689. return $r['result'] ? 'true' : 'false';
  690. }
  691. /* */
  692. function getInsertResultDoc($r) {
  693. $formats = array(
  694. 'xml' => 'SPARQLXML', 'sparql-results+xml' => 'SPARQLXML',
  695. 'json' => 'SPARQLJSON', 'sparql-results+json' => 'SPARQLJSON',
  696. 'plain' => 'Plain',
  697. 'php_ser' => 'PHPSER'
  698. );
  699. if ($f = $this->getResultFormat($formats, 'xml')) {
  700. $m = 'get' . $f . 'InsertResultDoc';
  701. return method_exists($this, $m) ? $this->$m($r) : 'not implemented';
  702. }
  703. return '';
  704. }
  705. function getSPARQLXMLInsertResultDoc($r) {
  706. $this->setHeader('content-type', 'Content-Type: application/sparql-results+xml');
  707. $r_val = $r['result']['t_count'];
  708. $dur = $r['query_time'];
  709. $nl = "\n";
  710. return '' .
  711. '<?xml version="1.0"?>' .
  712. $nl . '<sparql xmlns="http://www.w3.org/2005/sparql-results#">' .
  713. $nl . ' <head>' .
  714. $nl . ' <!-- query time: '. round($dur, 4) .' sec -->' .
  715. $nl . ' </head>' .
  716. $nl . ' <inserted>' .$r_val. '</inserted>' .
  717. $nl . '</sparql>' .
  718. '';
  719. }
  720. function getSPARQLJSONInsertResultDoc($r) {
  721. $this->setHeader('content-type', 'Content-Type: application/sparql-results+json');
  722. $r_val = $r['result']['t_count'];
  723. $dur = $r['query_time'];
  724. $nl = "\n";
  725. $r = '' .
  726. $nl . '{' .
  727. $nl . ' "head": {' .
  728. $nl . ' },' .
  729. $nl . ' "inserted" : ' . $r_val .
  730. $nl . '}' .
  731. '';
  732. if (($v = $this->p('jsonp')) || ($v = $this->p('callback'))) {
  733. $r = $v . '(' . $r . ')';
  734. }
  735. return $r;
  736. }
  737. function getPHPSERInsertResultDoc($r) {
  738. $this->setHeader('content-type', 'Content-Type: text/plain');
  739. return serialize($r);
  740. }
  741. function getPlainInsertResultDoc($r) {
  742. $this->setHeader('content-type', 'Content-Type: text/plain');
  743. return $r['result'] ? 'true' : 'false';
  744. }
  745. /* */
  746. function jsonEscape($v) {
  747. if (function_exists('json_encode')) return trim(json_encode($v), '"');
  748. $from = array("\\", "\r", "\t", "\n", '"', "\b", "\f", "/");
  749. $to = array('\\\\', '\r', '\t', '\n', '\"', '\b', '\f', '\/');
  750. return str_replace($from, $to, $v);
  751. }
  752. /* */
  753. function getHTMLFormDoc() {
  754. return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  755. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  756. ' . $this->getHTMLDocHead() . '
  757. ' . $this->getHTMLDocBody() . '
  758. </html>
  759. ';
  760. }
  761. function getHTMLDocHead() {
  762. return '
  763. <head>
  764. <title>' . $this->getHTMLDocTitle() . '</title>
  765. <style type="text/css">
  766. ' . $this->getHTMLDocCSS() . '
  767. </style>
  768. </head>
  769. ';
  770. }
  771. function getHTMLDocTitle() {
  772. return $this->v('endpoint_title', 'ARC SPARQL+ Endpoint', $this->a);
  773. }
  774. function getHTMLDocHeading() {
  775. return $this->v('endpoint_heading', 'ARC SPARQL+ Endpoint (v' . ARC2::getVersion() . ')', $this->a);
  776. }
  777. function getHTMLDocCSS() {
  778. $default = '
  779. body {
  780. font-size: 14px;
  781. font-family: Trebuchet MS, Verdana, Geneva, sans-serif;
  782. background: #fff url(?img=bg_body) top center repeat-x;
  783. padding: 5px 20px 20px 20px;
  784. color: #666;
  785. }
  786. h1 { font-size: 1.6em; font-weight: normal; }
  787. a { color: #c00000; }
  788. th, td {
  789. border: 1px dotted #eee;
  790. padding: 2px 4px;
  791. }
  792. #sparql-form {
  793. margin-bottom: 30px;
  794. }
  795. #query {
  796. float: left;
  797. width: 60%;
  798. display: block;
  799. height: 265px;
  800. margin-bottom: 10px;
  801. }
  802. .options {
  803. float: right;
  804. font-size: 0.9em;
  805. width: 35%;
  806. border-top: 1px solid #ccc;
  807. }
  808. .options h3 {
  809. margin: 5px;
  810. }
  811. .options dl{
  812. margin: 0px;
  813. padding: 0px 10px 5px 20px;
  814. }
  815. .options dl dt {
  816. border-top: 1px dotted #ddd;
  817. padding-top: 10px;
  818. }
  819. .options dl dt.first {
  820. border: none;
  821. }
  822. .options dl dd {
  823. padding: 5px 0px 7px 0px;
  824. }
  825. .options-2 {
  826. clear: both;
  827. margin: 10px 0px;
  828. }
  829. .form-buttons {
  830. }
  831. .results {
  832. border: 1px solid #eee;
  833. padding: 5px;
  834. background-color: #fcfcfc;
  835. }
  836. ';
  837. return $this->v('endpoint_css', $default, $this->a);
  838. }
  839. function getHTMLDocBody() {
  840. return '
  841. <body>
  842. <h1>' . $this->getHTMLDocHeading() . '</h1>
  843. <div class="intro">
  844. <p>
  845. <a href="?">This interface</a> implements
  846. <a href="http://www.w3.org/TR/rdf-sparql-query/">SPARQL</a> and
  847. <a href="http://arc.semsol.org/docs/v2/sparql+">SPARQL+</a> via <a href="http://www.w3.org/TR/rdf-sparql-protocol/#query-bindings-http">HTTP Bindings</a>.
  848. </p>
  849. <p>
  850. Enabled operations: ' . join(', ', $this->getFeatures()) . '
  851. </p>
  852. <p>
  853. Max. number of results : ' . $this->v('endpoint_max_limit', '<em>unrestricted</em>', $this->a) . '
  854. </p>
  855. </div>
  856. ' . $this->getHTMLDocForm() .'
  857. ' . ($this->p('show_inline') ? $this->query_result : '') . '
  858. </body>
  859. ';
  860. }
  861. function getHTMLDocForm() {
  862. $q = $this->p('query') ? htmlspecialchars($this->p('query')) : "SELECT * WHERE {\n GRAPH ?g { ?s ?p ?o . }\n}\nLIMIT 10";
  863. return '
  864. <form id="sparql-form" action="?" enctype="application/x-www-form-urlencoded" method="' . ($_SERVER['REQUEST_METHOD'] == 'GET' ? 'get' : 'post' ) . '">
  865. <textarea id="query" name="query" rows="20" cols="80">' . $q . '</textarea>
  866. ' . $this->getHTMLDocOptions() . '
  867. <div class="form-buttons">
  868. <input type="submit" value="Send Query" />
  869. <input type="reset" value="Reset" />
  870. </div>
  871. </form>
  872. ';
  873. }
  874. function getHTMLDocOptions() {
  875. $sel = $this->p('output');
  876. $sel_code = ' selected="selected"';
  877. return '
  878. <div class="options">
  879. <h3>Options</h3>
  880. <dl>
  881. <dt class="first">Output format (if supported by query type):</dt>
  882. <dd>
  883. <select id="output" name="output">
  884. <option value="" ' . (!$sel ? $sel_code : '') . '>default</option>
  885. <option value="xml" ' . ($sel == 'xml' ? $sel_code : '') . '>XML</option>
  886. <option value="json" ' . ($sel == 'json' ? $sel_code : '') . '>JSON</option>
  887. <option value="plain" ' . ($sel == 'plain' ? $sel_code : '') . '>Plain</option>
  888. <option value="php_ser" ' . ($sel == 'php_ser' ? $sel_code : '') . '>Serialized PHP</option>
  889. <option value="turtle" ' . ($sel == 'turtle' ? $sel_code : '') . '>Turtle</option>
  890. <option value="rdfxml" ' . ($sel == 'rdfxml' ? $sel_code : '') . '>RDF/XML</option>
  891. <option value="infos" ' . ($sel == 'infos' ? $sel_code : '') . '>Query Structure</option>
  892. ' . ($this->allow_sql ? '<option value="sql" ' . ($sel == 'sql' ? $sel_code : '') . '>SQL</option>' : '') . '
  893. <option value="htmltab" ' . ($sel == 'htmltab' ? $sel_code : '') . '>HTML Table</option>
  894. </select>
  895. </dd>
  896. <dt>jsonp/callback (for JSON results)</dt>
  897. <dd>
  898. <input type="text" id="jsonp" name="jsonp" value="' . htmlspecialchars($this->p('jsonp')) . '" />
  899. </dd>
  900. <dt>API key (if required)</dt>
  901. <dd>
  902. <input type="text" id="key" name="key" value="' . htmlspecialchars($this->p('key')) . '" />
  903. </dd>
  904. <dt>Show results inline: </dt>
  905. <dd>
  906. <input type="checkbox" name="show_inline" value="1" ' . ($this->p('show_inline') ? ' checked="checked"' : '') . ' />
  907. </dd>
  908. </dl>
  909. </div>
  910. <div class="options-2">
  911. Change HTTP method:
  912. <a href="javascript:;" onclick="javascript:document.getElementById(\'sparql-form\').method=\'get\'">GET</a>
  913. <a href="javascript:;" onclick="javascript:document.getElementById(\'sparql-form\').method=\'post\'">POST</a>
  914. </div>
  915. ';
  916. }
  917. /* */
  918. }