PageRenderTime 49ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/graphs/configgraph.class.php

http://puelia-php.googlecode.com/
PHP | 980 lines | 820 code | 138 blank | 22 comment | 99 complexity | 37a73098be0bbfb735d784aaa620d628 MD5 | raw file
Possible License(s): Apache-2.0, GPL-2.0
  1. <?php
  2. require_once 'exceptions.inc.php';
  3. require_once 'lda.inc.php';
  4. require_once 'lib/moriarty/moriarty.inc.php';
  5. require_once 'graphs/pueliagraph.class.php';
  6. require_once 'lib/moriarty/httprequestfactory.class.php';
  7. define('uriTemplateVariableRegex', '@\{([a-zA-Z0-9_\.]+)\}@');
  8. class ConfigGraph extends PueliaGraph {
  9. private $_endPointRequestVariables = array();
  10. private $_request;
  11. private $_endpointUri;
  12. private $_uriTemplate;
  13. private $_paramVariableBindings;
  14. private $_pathVariableBindings;
  15. private $_allVariableBindings;
  16. private $_requestFactory = null;
  17. private $_formatters = null;
  18. var $apiUri = false;
  19. var $prefixesFromLoadedTurtle = array();
  20. var $_vocab = null;
  21. function __construct($rdf, $request, $requestFactory=false){
  22. $this->_request = $request;
  23. parent::__construct($rdf);
  24. if(!$requestFactory){
  25. $this->_requestFactory = new HttpRequestFactory();
  26. } else {
  27. $this->_requestFactory = $requestFactory;
  28. }
  29. // built-in formatters
  30. $this->add_literal_triple(API.'JsonFormatter', API.'mimeType', 'application/json');
  31. $this->add_literal_triple(API.'JsonFormatter', API.'name', 'json');
  32. $this->add_literal_triple(API.'JsonFormatter', RDFS_LABEL, 'Simple JSON');
  33. $this->add_literal_triple(API.'RdfJsonFormatter', API.'mimeType', 'application/json');
  34. $this->add_literal_triple(API.'RdfJsonFormatter', API.'mimeType', 'application/x-rdf+json');
  35. $this->add_literal_triple(API.'RdfJsonFormatter', API.'name', 'rdfjson');
  36. $this->add_literal_triple(API.'RdfJsonFormatter', RDFS_LABEL, 'RDF/JSON');
  37. $this->add_literal_triple(API.'XmlFormatter', API.'mimeType', 'application/xml');
  38. $this->add_literal_triple(API.'XmlFormatter', API.'name', 'xml');
  39. $this->add_literal_triple(API.'XmlFormatter', RDFS_LABEL, 'Simple XML');
  40. $this->add_literal_triple(API.'TurtleFormatter', API.'mimeType', 'text/turtle');
  41. $this->add_literal_triple(API.'TurtleFormatter', API.'name', 'ttl');
  42. $this->add_literal_triple(API.'TurtleFormatter', RDFS_LABEL, 'Turtle');
  43. $this->add_literal_triple(API.'RdfXmlFormatter', API.'mimeType', 'application/rdf+xml');
  44. $this->add_literal_triple(API.'RdfXmlFormatter', API.'name', 'rdf');
  45. $this->add_literal_triple(API.'RdfXmlFormatter', RDFS_LABEL, 'RDF/XML');
  46. $this->add_resource_triple(API.'JsonFormatter', RDF.'type', API.'Formatter');
  47. $this->add_resource_triple(API.'XmlFormatter', RDF.'type', API.'Formatter');
  48. $this->add_resource_triple(API.'RdfXmlFormatter', RDF.'type', API.'Formatter');
  49. $this->add_resource_triple(API.'TurtleFormatter', RDF.'type', API.'Formatter');
  50. $this->add_resource_triple(API.'RdfJsonFormatter', RDF.'type', API.'Formatter');
  51. //built-in viewer: basic
  52. $this->add_resource_triple(API.'basicViewer', RDF_TYPE, API.'Viewer');
  53. $this->add_literal_triple(API.'basicViewer', API.'name', "basic");
  54. $this->add_resource_triple(API.'basicViewer', API.'property', RDF_TYPE);
  55. $this->add_resource_triple(API.'basicViewer', API.'property', RDFS_LABEL);
  56. //built-in viewer: describe
  57. $this->add_resource_triple(API.'describeViewer', RDF_TYPE, API.'Viewer');
  58. $this->add_literal_triple(API.'describeViewer', API.'name', "description");
  59. $this->add_literal_triple(API.'describeViewer', API.'properties', "*");
  60. //built-in viewer: labelled describe
  61. $this->add_resource_triple(API.'labelledDescribeViewer', RDF_TYPE, API.'Viewer');
  62. $this->add_literal_triple(API.'labelledDescribeViewer', API.'name', "all");
  63. $this->add_literal_triple(API.'labelledDescribeViewer', API.'properties', "*.label");
  64. $this->add_literal_triple(RDFS_LABEL, API.'label', "label");
  65. }
  66. /* added so Config Can be reused between Requests */
  67. function setRequest($Request){
  68. $this->_request = $Request;
  69. }
  70. function getRequest(){
  71. return $this->_request;
  72. }
  73. function init(){
  74. $this->apiUri = false;
  75. $this->_endpointUri = false;
  76. $this->_uriTemplate = false;
  77. $this->_allVariableBindings = false;
  78. $this->_paramVariableBindings = false;
  79. $this->_pathVariableBindings = false;
  80. $this->_vocab = false;
  81. $this->_endPointRequestVariables = false;
  82. $this->PropertyLabels = false;
  83. $this->apiUri = $this->getApiUri();
  84. $endpointInfo = $this->getEndpointMatchingRequest();
  85. $this->_endpointUri = $endpointInfo['endpoint'];
  86. $this->_uriTemplate = $endpointInfo['uriTemplate'];
  87. $this->_paramVariableBindings = $endpointInfo['variableBindings']['paramBindings'];
  88. $this->_pathVariableBindings = $endpointInfo['variableBindings']['pathBindings'];
  89. }
  90. function resetApiAndEndpoint($api='_:resetAPI', $endpoint='_:resetEndpoint'){
  91. $this->_endpointUri = $endpoint;
  92. $this->apiUri = $api;
  93. $this->_formatters = false;
  94. }
  95. function getListEndpoints(){
  96. return $this->getEndpointsByType(API.'ListEndpoint'); }
  97. function getItemEndpoints(){
  98. return $this->getEndpointsByType(API.'ItemEndpoint');
  99. }
  100. function getSearchEndpoint(){
  101. return $this->getEndpointsByType(PUELIA.'SearchEndpoint');
  102. }
  103. function getEndpointsByType($type){
  104. $endpoints = array();
  105. foreach ($this->get_resource_triple_values($this->apiUri, API.'endpoint') as $endpointUri){
  106. if($this->has_resource_triple($endpointUri, RDF_TYPE, $type)){
  107. $endpoints[]=$endpointUri;
  108. }
  109. }
  110. return $endpoints;
  111. }
  112. function getRssTextSearchIndex(){
  113. return $this->get_first_resource($this->getEndpointUri(),PUELIA.'rssTextSearchIndex');
  114. }
  115. function getPrefixesFromLoadedTurtle(){
  116. return $this->prefixesFromLoadedTurtle;
  117. }
  118. function add_rdf($rdf=false, $base=''){
  119. preg_match_all('/@prefix\s+(.+?):\s+<(.+?)>/', $rdf, $m);
  120. foreach($m[1] as $n => $prefix){
  121. $this->prefixesFromLoadedTurtle[$prefix] = $m[2][$n];
  122. }
  123. parent::add_rdf($rdf, $base);
  124. }
  125. function getApiUri(){
  126. if($this->apiUri) return $this->apiUri;
  127. $requestUri = $this->_request->getUri();
  128. $api_subjects = $this->get_subjects_of_type(API.'API');
  129. foreach($api_subjects as $s){
  130. $configBase = $this->get_first_literal($s, API.'base');
  131. if(!empty($configBase)){
  132. $requestUri = rtrim($requestUri, '/');
  133. $configBase = rtrim($configBase, '/');
  134. if(strpos($requestUri, $configBase)===0){
  135. $this->apiUri = $s;
  136. return $s;
  137. }
  138. }
  139. }
  140. return false;
  141. }
  142. function getApisWithoutBase(){
  143. $api_subjects = $this->get_subjects_of_type(API.'API');
  144. $return = array();
  145. foreach($api_subjects as $s){
  146. if(! $apiBase = $this->get_first_literal($s, API.'base')){
  147. $return[]=$s;
  148. }
  149. }
  150. return $return;
  151. }
  152. function getEndpointMatchingRequest(){
  153. $apiSubject = $this->getApiUri();
  154. if(!$apiSubject){
  155. $endpoints = array();
  156. $api_subjects = $this->getApisWithoutBase();
  157. foreach($api_subjects as $s){
  158. $endpoints = array_merge($endpoints, $this->get_resource_triple_values($s, API.'endpoint'));
  159. }
  160. } else {
  161. $endpoints = $this->get_resource_triple_values($apiSubject, API.'endpoint');
  162. }
  163. foreach($endpoints as $endpoint){
  164. foreach($this->get_literal_triple_values($endpoint, API.'uriTemplate') as $uriTemplate){
  165. if($variableBindings = $this->getRequestMatchesFromUriTemplate($uriTemplate)){
  166. $this->apiUri = array_pop($this->get_subjects_where_resource(API.'endpoint', $endpoint));
  167. $this->_endPointRequestVariables[$endpoint] = $variableBindings;
  168. return array('endpoint' => $endpoint, 'uriTemplate' => $uriTemplate, 'variableBindings'=> $variableBindings);
  169. }
  170. }
  171. }
  172. return false;
  173. }
  174. function getRequestMatchesFromUriTemplate($uriTemplate){
  175. $path = $this->_request->getPathWithoutExtension();
  176. /* if an api:base is set, strip it from the request URI */
  177. if($this->getApiUri() AND $apiBase = $this->get_first_literal($this->getApiUri(), API.'base')){
  178. $fullRequestUriWithoutExtension = $this->_request->getBase().$path;
  179. $path = str_replace($apiBase, '', $fullRequestUriWithoutExtension);
  180. } else {
  181. /* strip install subdir */
  182. $path = str_replace($this->_request->getInstallSubDir(), '', $path);
  183. }
  184. $params = $this->_request->getParams();
  185. $pathTemplate = $this->getPathTemplate($uriTemplate);
  186. $parameterTemplates = $this->getParameterTemplates($uriTemplate);
  187. $paramMatches = $this->paramsTemplateMatches($parameterTemplates, $params);
  188. $pathMatches = $this->pathTemplateMatches($pathTemplate, $path);
  189. if(
  190. $pathMatches !== false
  191. AND
  192. $paramMatches !== false
  193. ){
  194. return array('paramBindings' => $paramMatches, 'pathBindings' => $pathMatches);
  195. } else {
  196. return false;
  197. }
  198. }
  199. function getParamVariableBindings(){
  200. return $this->_paramVariableBindings;
  201. }
  202. function getPathVariableBindings(){
  203. return $this->_pathVariableBindings;
  204. }
  205. function paramsTemplateMatches($templates, $params){
  206. $variables = array();
  207. foreach($templates as $k => $v){
  208. if(isset($params[$k]) AND (preg_match(uriTemplateVariableRegex, $v, $m) OR ($v==$params[$k]) )){
  209. $variables[$m[1]] = array('value' => $params[$k]);
  210. } else {
  211. return false;
  212. }
  213. }
  214. if(!empty($templates) AND count($variables) < count($templates)) return false;
  215. return $variables;
  216. }
  217. /**
  218. * pathTemplateMatches - returns an array of variables if template matches path
  219. *
  220. * @return array
  221. * @author Keith Alexander
  222. **/
  223. function pathTemplateMatches( $template, $path){
  224. if(substr($template, -1,1)!='/'){ #trailing slash optional unless specified in template
  225. $path = rtrim($path, '/');
  226. }
  227. preg_match_all(uriTemplateVariableRegex, $template, $ms);
  228. $templateVariables = array();
  229. $uriTemplateRegex = $template;
  230. if(!empty($ms[0])){
  231. foreach($ms[0] as $n => $match){
  232. $templateVariables[]=$ms[1][$n];
  233. $uriTemplateRegex = str_replace($match, '([^/]+?)', $uriTemplateRegex);
  234. }
  235. }
  236. if(preg_match('@^'.$uriTemplateRegex.'$@', $path, $pathMatches)){
  237. $variableValuesFromPath = array();
  238. foreach($templateVariables as $n => $templateVariable){
  239. $variableValuesFromPath[$templateVariable] = array('value'=> urldecode($pathMatches[$n+1]), 'source' => 'request');
  240. }
  241. return $variableValuesFromPath;
  242. } else {
  243. return false;
  244. }
  245. }
  246. function getPathTemplate($template){
  247. return array_shift(explode('?', $template));
  248. }
  249. function getParameterTemplates($template){
  250. $query = parse_url($template, PHP_URL_QUERY);
  251. $params = queryStringToParams($query);
  252. return $params;
  253. }
  254. function getEndpointUri(){
  255. return $this->_endpointUri;
  256. }
  257. function getEndpointConfigVariableBindings(){
  258. $endpointUri = $this->getEndpointUri();
  259. $variableBindings = array();
  260. foreach($this->get_resource_triple_values($endpointUri, API.'variable') as $variableUri){
  261. $name = $this->get_first_literal($variableUri, API.'name');
  262. $value = $this->get_first_literal($variableUri, API.'value');
  263. $variableBindings[$name]['value'] = $value;
  264. if($type = $this->get_first_resource($variableUri, API.'type')){
  265. $variableBindings[$name]['type'] = $type;
  266. }
  267. }
  268. return $variableBindings;
  269. }
  270. function getApiConfigVariableBindings(){
  271. $endpointUri = $this->getEndpointUri();
  272. $endpointApiUris = $this->get_subjects_where_resource(API.'endpoint', $endpointUri);
  273. $variableBindings = array();
  274. foreach($endpointApiUris as $apiUri){
  275. foreach($this->get_resource_triple_values($apiUri, API.'variable') as $variableUri){
  276. $name = $this->get_first_literal($variableUri, API.'name');
  277. $value = $this->get_first_literal($variableUri, API.'value');
  278. $variableBindings[$name]['value'] = $value;
  279. if($type = $this->get_first_resource($variableUri, API.'type')){
  280. $variableBindings[$name]['type'] = $type;
  281. }
  282. }
  283. }
  284. return $variableBindings;
  285. }
  286. function bindVariablesInValue($value, $variables, $valueType=false){
  287. foreach($variables as $name => $props){
  288. if($valueType==RDFS.'Resource'
  289. AND isset($props['source'])
  290. AND $props['source']=='request'){
  291. $props['value'] = urlencode($props['value']);
  292. }
  293. $value = str_replace('{'.$name.'}', $props['value'], $value);
  294. }
  295. return $value;
  296. }
  297. function getCompletedItemTemplate(){
  298. $itemTemplate = $this->getEndpointItemTemplate();
  299. $bindings = $this->getAllProcessedVariableBindings();
  300. $filledInTemplate = $this->bindVariablesInValue($itemTemplate, $bindings, RDFS.'Resource' );
  301. return $filledInTemplate;
  302. }
  303. /**
  304. * dataUriToEndpointItem
  305. * takes a URI from the data, and transforms it into a URI one of the ItemEndpoints knows how to handle - if it does.
  306. * @param $dataUri
  307. * @return URL Path
  308. * @author Keith Alexander
  309. **/
  310. function dataUriToEndpointItem($dataUri){
  311. if($results = $this->getMatchesFromDataUri( $dataUri ) ){
  312. $result= $results[0]; # we can only return one URI
  313. $uriTemplate = $result['uriTemplate'];
  314. $matches = $result['matches'];
  315. $endpointItem = $this->bindVariablesInValue($uriTemplate, $matches, RDFS.'Resource');
  316. return $endpointItem;
  317. } else {
  318. return false;
  319. }
  320. }
  321. function getMatchesFromDataUri($dataUri){
  322. $return = array();
  323. $subjects = $this->get_subjects_of_type(API.'ItemEndpoint');
  324. foreach($subjects as $s){
  325. foreach($this->get_subject_properties($s) as $p){
  326. if($p==API.'itemTemplate'){
  327. $itemTemplate = $this->get_first_literal($s, $p);
  328. $dataPath = parse_url($dataUri, PHP_URL_PATH);
  329. $uriTemplate = $this->get_first_literal($s, API.'uriTemplate');
  330. $itemPathTemplate = parse_url($itemTemplate, PHP_URL_PATH);
  331. if($matches = $this->pathTemplateMatches($itemPathTemplate, $dataPath )){
  332. $return[]= array(
  333. 'matches' => $matches,
  334. 'uriTemplate' => $uriTemplate,
  335. 'endpointUri' => $s,
  336. );
  337. }
  338. }
  339. }
  340. }
  341. if(!empty($return)) return $return;
  342. return false;
  343. }
  344. function getRequestVariableBindings(){
  345. $bindings= array();
  346. $langBindings = array();
  347. $params = $this->_request->getParams();
  348. foreach($params as $k => $v){
  349. if (strpos($k, 'lang-') === 0) {
  350. $langBindings[substr($k, 5)] = $v;
  351. } else {
  352. $bindings[$k] = array('value' => $v, 'source' => 'request');
  353. }
  354. }
  355. foreach($langBindings as $k => $v) {
  356. if (array_key_exists($k, $bindings)) {
  357. $bindings[$k]['lang'] = $v;
  358. }
  359. }
  360. return $bindings;
  361. }
  362. function getAllProcessedVariableBindings(){
  363. $bindings = $this->getAllVariableBindings();
  364. foreach($bindings as $name => $value){
  365. if($name==='callback'){
  366. throw new ConfigGraphException("'callback' is reserved and cannot be used as a variable name");
  367. }
  368. $bindings[$name]['value'] = $this->processVariableBinding($name, $bindings);
  369. }
  370. return $bindings;
  371. }
  372. function processVariableBinding($name, $bindings, $history=array()){
  373. if(in_array($name, $history)){
  374. throw new ConfigGraphException("The variable '$name' has a circular dependency and cannot be resolved");
  375. }
  376. $history[]=$name;
  377. if(array_key_exists($name, $bindings)){
  378. $val = $bindings[$name]['value'];
  379. } else {
  380. $val = '';
  381. }
  382. if(isset($bindings[$name]['type'])){
  383. $type = $bindings[$name]['type'];
  384. } else {
  385. $type = RDFS.'Literal';
  386. }
  387. $varNames = $this->variableNamesInValue($val);
  388. if(is_array($varNames)){
  389. foreach($varNames as $var){
  390. $bindings[$var]['value'] = $this->processVariableBinding($var, $bindings, $history);
  391. }
  392. return $this->bindVariablesInValue($val, $bindings, $type);
  393. } else {
  394. return $val;
  395. }
  396. }
  397. function variableNamesInValue($val){
  398. if(preg_match_all(uriTemplateVariableRegex, $val, $matches)){
  399. return $matches[1];
  400. } else {
  401. return false;
  402. }
  403. }
  404. function getAllVariableBindings(){
  405. if(empty($this->_allVariableBindings)){
  406. $this->_allVariableBindings = array_merge(
  407. $this->getApiConfigVariableBindings(),
  408. $this->getPathVariableBindings(),
  409. $this->getParamVariableBindings(),
  410. $this->getRequestVariableBindings(),
  411. $this->getEndpointConfigVariableBindings()
  412. );
  413. }
  414. return $this->_allVariableBindings;
  415. }
  416. function getEndpointItemTemplate(){
  417. $endpointUri = $this->getEndpointUri();
  418. return $this->get_first_literal($endpointUri, API.'itemTemplate');
  419. }
  420. function getDatasetUri(){
  421. if($uri = $this->get_first_resource($this->getEndpointUri(), API.'dataset')) return $uri;
  422. else if($uri = $this->get_first_resource($this->getApiUri(), API.'dataset')) return $uri;
  423. else return false;
  424. }
  425. function getSelectorUri(){
  426. return $this->get_first_resource($this->getEndpointUri(), API.'selector');
  427. }
  428. function getSelectQuery(){
  429. return $this->get_first_literal($this->getSelectorUri(), API.'select');
  430. }
  431. function getSelectWhere(){
  432. return $this->get_first_literal($this->getSelectorUri(), API.'where');
  433. }
  434. function getSelectFilter(){
  435. return $this->get_first_literal($this->getSelectorUri(), API.'filter');
  436. }
  437. function getOrderBy(){
  438. return $this->get_first_literal($this->getSelectorUri(), API.'orderBy');
  439. }
  440. function getSort(){
  441. return $this->get_first_literal($this->getSelectorUri(), API.'sort');
  442. }
  443. function getApiDefaultFormatter(){
  444. return $this->get_first_resource($this->getApiUri(), API.'defaultFormatter');
  445. }
  446. function getEndpointDefaultFormatter(){
  447. return $this->get_first_resource($this->getEndpointUri(), API.'defaultFormatter');
  448. }
  449. function getDefaultMimeTypes() {
  450. $formatter = $this->getEndpointDefaultFormatter();
  451. if (!$formatter) {
  452. $formatter = $this->getApiDefaultFormatter();
  453. }
  454. return $this->get_literal_triple_values($formatter, API.'mimeType');
  455. }
  456. function getMimeTypesOfFormatterByName($formatName){
  457. $formatterUri = $this->getFormatterUriByName($formatName);
  458. return $this->get_literal_triple_values($formatterUri, API.'mimeType');
  459. }
  460. function getMimeTypesOfFormatter($formatterUri){
  461. return $this->get_literal_triple_values($formatterUri, API.'mimeType');
  462. }
  463. function getXsltStylesheetOfFormatterByName($formatName){
  464. $formatterUri = $this->getFormatterUriByName($formatName);
  465. return $this->get_first_literal($formatterUri, API.'stylesheet');
  466. }
  467. function getFormatterTypeByName($formatName){
  468. $formatterUri = $this->getFormatterUriByName($formatName);
  469. return $this->get_first_resource($formatterUri, RDF.'type');
  470. }
  471. function getInheritedSelectFilters(){
  472. $filters = array();
  473. foreach($this->get_resource_triple_values($this->getSelectorUri(), API.'parent') as $parent){
  474. $filter = $this->get_first_literal($parent, API.'filter');
  475. if(!$filter){
  476. $selectUri = $this->getSelectorUri();
  477. throw new ConfigGraphException("<{$selectUri}> has a parent (<{$parent}>) which doesn't use the api:filter property.");
  478. }
  479. $filters[]=$filter;
  480. }
  481. return $filters;
  482. }
  483. function getAllFilters(){
  484. return array_merge(array($this->getSelectFilter()), $this->getInheritedSelectFilters());
  485. }
  486. function getMaxPageSize(){
  487. return $this->get_first_literal($this->getApiUri(), API.'maxPageSize');
  488. }
  489. function getApiDefaultPageSize(){
  490. return $this->get_first_literal($this->getApiUri(), API.'defaultPageSize');
  491. }
  492. function getEndpointDefaultPageSize(){
  493. return $this->get_first_literal($this->getEndpointUri(), API.'defaultPageSize');
  494. }
  495. function getApiDefaultLangs(){
  496. return $this->get_first_literal($this->getApiUri(), API.'lang');
  497. }
  498. function getEndpointDefaultLangs(){
  499. return $this->get_first_literal($this->getEndpointUri(), API.'lang');
  500. }
  501. function getVocabularies(){
  502. return $this->get_resource_triple_values($this->getApiUri(), API.'vocabulary');
  503. }
  504. function getSparqlEndpointUri(){
  505. if($uri = $this->get_first_resource($this->getApiUri(), API.'sparqlEndpoint')){
  506. return $uri;
  507. } else {
  508. throw new ConfigGraphException("No sparqlEndpoint was specified for <".$this->getApiUri().">");
  509. }
  510. }
  511. function getSparqlEndpointGraphs(){
  512. return array_merge(
  513. $this->get_resource_triple_values($this->getApiUri(), PUELIA.'sparqlEndpointGraph'),
  514. $this->get_resource_triple_values($this->getEndpointUri(), PUELIA.'sparqlEndpointGraph')
  515. );
  516. }
  517. function getViewers(){
  518. $viewers = array_merge(
  519. $this->get_resource_triple_values($this->getApiUri(), API.'viewer'),
  520. $this->get_resource_triple_values($this->getApiUri(), API.'defaultViewer'),
  521. $this->get_resource_triple_values($this->getEndpointUri(), API.'viewer'),
  522. $this->get_resource_triple_values($this->getEndpointUri(), API.'defaultViewer')
  523. );
  524. return $viewers;
  525. return array_filter($viewers);
  526. }
  527. function getViewerByName($name){
  528. $viewers = $this->getViewers();
  529. foreach($viewers as $uri){
  530. if($this->has_literal_triple($uri, API.'name', $name)){
  531. return $uri;
  532. }
  533. }
  534. if($name=='all'){
  535. return API.'labelledDescribeViewer' ;
  536. } else if($name=='description'){
  537. return API.'describeViewer';
  538. } else if($name=='basic'){
  539. return API.'basicViewer';
  540. }
  541. }
  542. function getApiDefaultViewer(){
  543. return $this->get_first_resource($this->getApiUri(), API.'defaultViewer');
  544. }
  545. function getEndpointDefaultViewer(){
  546. return $this->get_first_resource($this->getEndpointUri(), API.'defaultViewer');
  547. }
  548. function getVocabularyGraph(){
  549. if(!empty($this->_vocab)){
  550. return $this->_vocab;
  551. }
  552. else {
  553. $this->_vocab = new VocabularyGraph();
  554. $vocabUris = $this->getVocabularies();
  555. $vocabUris = array_unique($vocabUris);
  556. if(!empty($vocabUris)){
  557. foreach($this->getVocabularies() as $vocab){
  558. $vocabUrl = preg_replace('/#.*/', '', $vocab);
  559. $request = $this->_requestFactory->make('GET', $vocabUrl);
  560. $request->set_accept('application/rdf+xml,application/turtle,text/turtle,text/rdf+n3,application/xml;q=0.5,text/plain;q=0.5,text/html;q=0.5,*/*;q=0.4');
  561. $response = $request->execute();
  562. if($response->status_code >= 200 && $response->status_code <= 400){
  563. $this->_vocab->add_rdf($response->body);
  564. }
  565. else {
  566. throw new ConfigGraphException("The vocabulary {$vocabUrl} could not be fetched. a GET returned a {$response->status_code}");
  567. }
  568. }
  569. }
  570. return $this->_vocab;
  571. }
  572. }
  573. function getEndpointType(){
  574. if(!$this->getEndpointUri()) return false;
  575. if($types = $this->get_resource_triple_values($this->getEndpointUri(), RDF_TYPE)){
  576. if(in_array(API.'ItemEndpoint', $types)){
  577. return API.'ItemEndpoint';
  578. } else if(in_array(API.'ListEndpoint', $types)){
  579. return API.'ListEndpoint';
  580. } else if(in_array(PUELIA.'SearchEndpoint', $types)){
  581. return PUELIA.'SearchEndpoint';
  582. }
  583. }
  584. $itemTemplate = $this->getEndpointItemTemplate();
  585. if(!empty($itemTemplate)){
  586. return API.'ItemEndpoint';
  587. }
  588. }
  589. function getDisplayPropertiesOfViewer($viewerUri){
  590. $properties = $this->get_resource_triple_values($viewerUri, API.'property');
  591. $propertiesNotLists = array();
  592. foreach($properties as $p){
  593. if(!$this->resource_is_a_list($p)){
  594. $propertiesNotLists[]=$p;
  595. }
  596. }
  597. return $propertiesNotLists;
  598. }
  599. function getDisplayPropertyChainsOfViewer($viewerUri){
  600. $properties = $this->get_resource_triple_values($viewerUri, API.'property');
  601. $chains = array();
  602. foreach($properties as $p){
  603. if($this->resource_is_a_list($p)){
  604. $chains[]=$this->list_to_array($p);
  605. } else {
  606. $chains[] = array($p);
  607. }
  608. }
  609. return $chains;
  610. }
  611. function getAllViewerPropertyChains($viewerUri){
  612. $currentViewerChains = array_merge(
  613. $this->getDisplayPropertyChainsOfViewer($viewerUri),
  614. $this->getViewerDisplayPropertiesValueAsPropertyChainArray($viewerUri)
  615. );
  616. if($includedViewers = $this->get_resource_triple_values($viewerUri, API.'include')){
  617. foreach($includedViewers as $includeViewerUri){
  618. $includeChain = array_merge(
  619. $this->getDisplayPropertyChainsOfViewer($includeViewerUri),
  620. $this->getViewerDisplayPropertiesValueAsPropertyChainArray($includeViewerUri)
  621. );
  622. foreach($includeChain as $chain){
  623. $currentViewerChains[]=$chain;
  624. }
  625. }
  626. }
  627. return $currentViewerChains;
  628. }
  629. function list_to_array($listUri){
  630. $array = array();
  631. while(!empty($listUri) AND $listUri != RDF.'nil'){
  632. $array[]=$this->get_first_resource($listUri, RDF_FIRST);
  633. $listUri = $this->get_first_resource($listUri, RDF_REST);
  634. }
  635. return $array;
  636. }
  637. function resource_is_a_list($uri){
  638. if($this->has_resource_triple($uri, RDF_TYPE, RDF_LIST)){
  639. return true;
  640. } else if($this->get_first_resource($uri, RDF_FIRST)){
  641. return true;
  642. } else {
  643. return false;
  644. }
  645. }
  646. function getViewerTemplate($viewerUri){
  647. return $this->get_first_literal($viewerUri, API.'template');
  648. }
  649. function getViewerDisplayPropertiesValueAsPropertyChainArray($viewerUri){
  650. $vocab = $this->getVocabularyGraph();
  651. $viewerDisplayPropertiesValue = $this->get_first_literal($viewerUri, API.'properties');
  652. return $this->propertiesStringToArray($viewerDisplayPropertiesValue);
  653. }
  654. function getRequestPropertyChainArray(){
  655. $chainString = $this->_request->getParam('_properties');
  656. return $this->propertiesStringToArray($chainString);
  657. }
  658. function propertiesStringToArray($chainString){
  659. if(empty($chainString)){
  660. return array();
  661. } else {
  662. $chains = array();
  663. $sections = explode(',',$chainString);
  664. foreach($sections as $section){
  665. $chain = array();
  666. $names = explode('.', $section);
  667. foreach($names as $name){
  668. $propertyUri = $this->getUriForVocabPropertyLabel($name);
  669. if(empty($propertyUri)) throw new UnknownPropertyException($name);
  670. $chain[]=$propertyUri;
  671. }
  672. $chains[]=$chain;
  673. }
  674. return $chains;
  675. }
  676. }
  677. function getProjectionPropertyBindings(){
  678. $selectorUri = $this->getSelectorUri();
  679. if(!$selectorUri) throw new Exception("No Selector Uri available");
  680. $bindingUris = $this->get_resource_triple_values($selectorUri, API.'projectionPropertyBinding');
  681. $bindings = array();
  682. foreach($bindingUris as $bUri){
  683. $bindings[]=array(
  684. 'varName' => $this->get_first_literal($bUri, API.'sparqlVarName'),
  685. 'targetProperty' => $this->get_first_resource($bUri, API.'projectionTargetProperty'),
  686. );
  687. }
  688. return $bindings;
  689. }
  690. function getApiContentNegotiation(){
  691. return $this->get_first_resource($this->getApiUri(), API.'contentNegotiation');
  692. }
  693. function apiSupportsFormat($format){
  694. if($uri = $this->getFormatterUriByName($format)){
  695. return true;
  696. } else {
  697. return false;
  698. }
  699. }
  700. function getFormatters(){
  701. if(!empty($this->_formatters)){
  702. return $this->_formatters;
  703. }
  704. $formatters = array( # builtins
  705. 'rdf' => API.'RdfXmlFormatter',
  706. 'rdfjson' => API.'RdfJsonFormatter',
  707. 'ttl' => API.'TurtleFormatter',
  708. 'json' => API.'JsonFormatter',
  709. 'xml' => API.'XmlFormatter',
  710. );
  711. foreach($this->get_resource_triple_values($this->getApiUri(), API.'formatter') as $formatterUri){
  712. $name = $this->get_first_literal($formatterUri, API.'name');
  713. $formatters[$name] = $formatterUri;
  714. }
  715. if($apiDefaultUri = $this->getApiDefaultFormatter()){
  716. $apiDefaultName = $this->get_first_literal($apiDefaultUri, API.'name');
  717. $formatters[$apiDefaultName] = $apiDefaultUri;
  718. }
  719. foreach($this->get_resource_triple_values($this->getEndpointUri(), API.'formatter') as $formatterUri){
  720. $name = $this->get_first_literal($formatterUri, API.'name');
  721. $formatters[$name] = $formatterUri;
  722. }
  723. if($endpointDefaultUri = $this->getEndpointDefaultFormatter()){
  724. $endpointDefaultName = $this->get_first_literal($endpointDefaultUri, API.'name');
  725. $formatters[$endpointDefaultName] = $endpointDefaultUri;
  726. }
  727. $this->_formatters = array_filter($formatters);
  728. return $this->_formatters;
  729. }
  730. function getFormatterUriByName($name){
  731. foreach($this->getFormatters() as $formatter_name => $uri){
  732. if($formatter_name == $name) return $uri;
  733. }
  734. return false;
  735. }
  736. function getUriForVocabPropertyLabel($label){
  737. if ($label == '*') {
  738. return API.'allProperties';
  739. } else if($configLabelUri = $this->getUriForPropertyLabel($label)){
  740. return $configLabelUri;
  741. } else {
  742. return $this->getVocabularyGraph()->getUriForPropertyLabel($label);
  743. }
  744. }
  745. function getVocabPropertyRange($uri){
  746. if($range = $this->getPropertyRange($uri)){
  747. return $range;
  748. } else {
  749. return $this->getVocabularyGraph()->getPropertyRange($uri);
  750. }
  751. }
  752. function getVocabPropertyLabels(){
  753. return array_merge($this->getPropertyLabels(), $this->getVocabularyGraph()->getPropertyLabels());
  754. }
  755. function getInverseOfProperty($uri){
  756. # return an array
  757. if(in_array($uri,$this->getInverseProperties() ) ) return $this->get_resource_triple_values($uri, OWL_INVERSEOF);
  758. else return false;
  759. }
  760. function getInverseProperties(){
  761. return array_merge(
  762. $this->get_resource_triple_values($this->getApiUri(), PUELIA.'inverseProperty'),
  763. $this->get_resource_triple_values($this->getEndpointUri(), PUELIA.'inverseProperty')
  764. );
  765. }
  766. function getPageTitle(){
  767. $endpointUri = $this->getEndpointUri();
  768. if($label = $this->get_first_literal($endpointUri, API.'label')){
  769. return $this->bindVariablesInValue($label, $this->getAllProcessedVariableBindings());
  770. } else {
  771. return $this->get_label($endpointUri);
  772. }
  773. }
  774. function getRelatedEndpointsForViewer($viewerUri,$history=array()){
  775. if(in_array($viewerUri, $history)){
  776. throw new ConfigGraphException("Viewer: {$viewerUri} has a circular dependency with api:include ");
  777. } else {
  778. $history[]=$viewerUri;
  779. }
  780. $relatedEndpoints = array_merge(
  781. $this->get_resource_triple_values($viewerUri, PUELIA.'endpointRelatedToResultItems'),
  782. $this->get_resource_triple_values($this->getEndpointUri(), PUELIA.'endpointRelatedToResultItems')
  783. );
  784. if($includeViewers = $this->get_resource_triple_values($viewerUri, API.'include')){
  785. foreach($includeViewers as $includeViewer){
  786. $relatedEndpoints = array_merge(
  787. $this->getRelatedEndpointsForViewer($includeViewer, $history),
  788. $relatedEndpoints
  789. );
  790. }
  791. }
  792. return $relatedEndpoints;
  793. }
  794. function getViewerRelatedPagesForItemUri($viewerUri, $itemUri){
  795. $base = $this->getRequest()->getBaseAndSubDir();
  796. # get variable bindings from item endpoint
  797. $result = $this->getMatchesFromDataUri($itemUri);
  798. if(empty($result)) return false;
  799. $endpointUri = $result[0]['endpointUri'];
  800. $matches = $result[0]['matches'];
  801. $relatedPages = array();
  802. $relatedEndpoints = $this->getRelatedEndpointsForViewer($viewerUri);
  803. foreach($relatedEndpoints as $relatedEndpoint){
  804. $uriTemplate = $this->get_first_literal($relatedEndpoint, API.'uriTemplate');
  805. $endpointItem = $this->bindVariablesInValue($uriTemplate, $matches, RDFS.'Resource');
  806. if(!$this->variableNamesInValue($endpointItem)){
  807. $relatedUri = $base . $endpointItem;
  808. $pageLabel = $this->get_first_literal($relatedEndpoint, API.'label');
  809. $completedLabel = $this->bindVariablesInValue($pageLabel, $matches);
  810. if(empty($pageLabel)) $completedLabel = $this->get_label($endpointUri);
  811. $relatedPages[$relatedUri] = $completedLabel;
  812. }
  813. }
  814. return $relatedPages;
  815. }
  816. function getUriTemplatesWithoutVariables(){
  817. $templates = array();
  818. foreach($this->getEndpointsByType(API.'ListEndpoint') as $listEndpoint){
  819. if($uriTemplate = $this->get_first_literal($listEndpoint, API.'uriTemplate')){
  820. if(!$this->variableNamesInValue($uriTemplate)){
  821. $templates[$uriTemplate] = $this->get_label($listEndpoint);
  822. }
  823. }
  824. }
  825. return $templates;
  826. }
  827. }
  828. ?>