PageRenderTime 45ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/graphs/linkeddataapigraph.class.php

http://puelia-php.googlecode.com/
PHP | 367 lines | 321 code | 45 blank | 1 comment | 73 complexity | de2087bc197229649f35e533c9a33d20 MD5 | raw file
Possible License(s): Apache-2.0, GPL-2.0
  1. <?php
  2. require_once 'graphs/pueliagraph.class.php';
  3. class LinkedDataApiGraph extends PueliaGraph {
  4. private $_config;
  5. private $_usedProperties;
  6. var $_current_page_uri = false;
  7. private $_nodeCounter = 1;
  8. var $_primary_resource=null;
  9. function __construct($a, $config){
  10. $this->_config = $config;
  11. $this->_usedProperties = array();
  12. date_default_timezone_set('UTC');
  13. parent::__construct($a);
  14. }
  15. public function add_rdf($rdf, $base=false){
  16. $return = parent::add_rdf($rdf, $base);
  17. foreach($this->get_subjects() as $s){
  18. $this->remove_property_values($s, 'http://schemas.talis.com/2005/dir/schema#etag');
  19. }
  20. return $return;
  21. }
  22. private function getNewNodeNumber(){
  23. return $this->_nodeCounter++;
  24. }
  25. function getConfigGraph(){
  26. return $this->_config;
  27. }
  28. function getVocabularyGraph(){
  29. return $this->getConfigGraph()->getVocabularyGraph();
  30. }
  31. function to_simple_json($pageUri){
  32. $this->_current_page_uri = $pageUri;
  33. $container = array(
  34. 'format' => 'linked-data-api',
  35. "version" => "0.2",
  36. "result" => $this->_resource_to_simple_json_object($pageUri, $pageUri, false, array()),
  37. );
  38. $index = $this->get_index();
  39. $nodeCounter = 1;
  40. $bnodeIdIndex = array();
  41. $this->_current_page_uri = false;
  42. return json_encode($container);
  43. }
  44. function _resource_to_simple_json_object($uri, $subjectUri, $propertyUri=false, $parentUris){
  45. if(
  46. !in_array($uri, $parentUris)
  47. )
  48. {
  49. $parentUris[]=$uri;
  50. $index = $this->get_index();
  51. $properties = $this->get_subject_properties($uri);
  52. $resource = array();
  53. if($this->node_is_blank($uri)){
  54. if(count($this->get_subjects_where_object($uri)) > 1){
  55. $bnodeNewId = 'node'.$this->getNewNodeNumber();
  56. $bnodeIdIndex[$uri] = $bnodeNewId;
  57. $resource['_id'] = $uri;
  58. }
  59. } else if(!empty($uri)) {
  60. $resource['_about'] = $uri;
  61. }
  62. sort($properties);
  63. foreach($properties as $propertyUri){
  64. $objects = $index[$uri][$propertyUri];
  65. $jsonPropertyName = $this->get_short_name_for_uri($propertyUri);
  66. $val = $this->get_simple_json_property_value($objects, $propertyUri, $subjectUri, $parentUris);
  67. $resource[$jsonPropertyName] = $val;
  68. }
  69. if(!empty($resource)) return $resource;
  70. } else {
  71. return $uri;
  72. }
  73. }
  74. function get_simple_json_property_value($objects, $propertyUri, $subjectUri, $parentUris){
  75. if(count($objects) > 1 OR $this->propertyIsMultiValued($propertyUri)){
  76. $returnArray = array();
  77. foreach($objects as $object){
  78. $val = $this->map_rdf_value_to_json_value($object, $propertyUri, $subjectUri, $parentUris);
  79. if($val!==null) $returnArray[]=$val;
  80. }
  81. return $returnArray;
  82. } else {
  83. return $this->map_rdf_value_to_json_value($objects[0], $propertyUri, $subjectUri, $parentUris);
  84. }
  85. }
  86. function map_rdf_value_to_json_value($object, $propertyUri, $subjectUri, $parentUris){
  87. $target = array();
  88. if($object['type']!=='literal') $subject_properties = $this->get_subject_properties($object['value']);
  89. $xsd_numeric_datatypes = array(
  90. XSD.'integer',
  91. XSD.'float',
  92. XSD.'decimal',
  93. XSD.'double',
  94. XSD.'int',
  95. XSD.'byte',
  96. XSD.'long',
  97. XSD.'short',
  98. XSD.'negativeInteger',
  99. XSD.'nonNegativeInteger',
  100. XSD.'nonPositiveInteger',
  101. XSD.'positiveInteger',
  102. XSD.'unsignedLong',
  103. XSD.'unsignedShort',
  104. XSD.'unsignedInt',
  105. XSD.'unsignedByte',
  106. );
  107. if( $this->getConfigGraph()->get_first_literal($propertyUri, API.'structured')=='true'
  108. OR
  109. $this->getVocabularyGraph()->get_first_literal($propertyUri, API.'structured')=='true'){
  110. $target['_value'] = $object['value'];
  111. if(!empty($object['lang'])){
  112. $target['_lang'] = $object['lang'];
  113. } else if(!empty($object['datatype'])){
  114. $target['_datatype'] = array_pop(preg_split('@/|#@', $object['datatype']));
  115. }
  116. return $target;
  117. } else if(isset($object['datatype']) AND $object['datatype']==XSD.'boolean'){
  118. $target= (strtolower($object['value']) == 'true');
  119. } else if(isset($object['datatype']) AND in_array($object['datatype'], $xsd_numeric_datatypes) AND is_numeric($object['value'])){
  120. $target = $object['value']+0;
  121. } else if(isset($object['datatype']) AND $object['datatype'] == XSD.'dateTime'){
  122. $target = date(DATE_COOKIE, strtotime($object['value']));
  123. } else if(isset($object['datatype']) AND $object['datatype'] == XSD.'date'){
  124. $target = date(DATE_W3C, strtotime($object['value']));
  125. } else if($this->has_resource_triple($object['value'], RDF_TYPE, RDF_LIST)){
  126. $target = array();
  127. $listValues = $this->list_to_array($object['value']);
  128. foreach($listValues as $listUri){
  129. $val = $this->_resource_to_simple_json_object($listUri, $subjectUri, $propertyUri, $parentUris);
  130. if($val!==null) $target[]=$val;
  131. }
  132. } else if(!empty($subject_properties)){
  133. $target=$this->_resource_to_simple_json_object($object['value'], $subjectUri, $propertyUri, $parentUris);
  134. } else if($object['type'] =='bnode' AND empty($subject_properties)) {
  135. $target = new BlankObject();
  136. } else {
  137. $target = $object['value'];
  138. }
  139. return $target;
  140. }
  141. function is_legal_short_name($shortName){
  142. return (!empty($shortName) AND preg_match('/^[a-zA-Z_0-9][a-zA-Z_0-9]+$/', $shortName));
  143. }
  144. function get_short_name_for_uri($propertyUri){
  145. if(
  146. $name = $this->get_first_literal($propertyUri, API.'label')
  147. OR
  148. $name = $this->_config->get_first_literal($propertyUri, API.'label')
  149. ){
  150. $this->_usedProperties[$name] = $propertyUri;
  151. return $name;
  152. } else if($name = $this->get_label($propertyUri) and $this->is_legal_short_name($name)){
  153. $this->_usedProperties[$name] = $propertyUri;
  154. return $name;
  155. }
  156. $mappings = $this->getConfigGraph()->getVocabPropertyLabels();
  157. $mappings = array_flip($mappings);
  158. if(isset($mappings[$propertyUri]) AND $this->is_legal_short_name($mappings[$propertyUri])){
  159. $this->_usedProperties[$mappings[$propertyUri]] = $propertyUri;
  160. return $mappings[$propertyUri];
  161. } else {
  162. preg_match('@^(.+[#/])([^#/]+)$@', $propertyUri, $m);
  163. $ns = $m[1];
  164. $localName = $m[2];
  165. if(!in_array($localName, array_values($mappings)) AND $this->is_legal_short_name($localName)){
  166. $this->_usedProperties[$localName] = $propertyUri;
  167. return $localName;
  168. } else {
  169. $prefix = $this->get_prefix($ns);
  170. $name = $prefix.'_'.$localName;
  171. if($this->is_legal_short_name($name)) {
  172. $this->_usedProperties[$name] = $propertyUri;
  173. return $name;
  174. } else {
  175. logDebug("{$propertyUri} has no legal short name");
  176. $name = preg_replace('/[^a-zA-Z0-9_]/','_', $name);
  177. $this->_usedProperties[$name] = $propertyUri;
  178. return $name;
  179. }
  180. }
  181. }
  182. }
  183. function node_is_blank($node){
  184. return (strpos($node, '_:')===0);
  185. }
  186. function get_subjects_where_object($object){
  187. $subjects = array();
  188. $index = $this->get_index();
  189. foreach($index as $uri => $properties){
  190. foreach($properties as $p => $objs){
  191. foreach($objs as $o){
  192. if($o['type'] == 'uri' && $object == $o['value']){
  193. $subjects[]=$uri;
  194. }
  195. }
  196. }
  197. }
  198. return $subjects;
  199. }
  200. function to_simple_xml($pageUri){
  201. $this->_uris_processed_by_simple_xml = array();
  202. $this->_current_page_uri = $pageUri;
  203. $dom = new DOMDocument('1.0', 'utf-8');
  204. $resultEl = $dom->createElement('result');
  205. $format = $dom->createAttribute('format');
  206. $format->appendChild($dom->createTextNode('linked-data-api'));
  207. $version = $dom->createAttribute('version');
  208. $version->appendChild($dom->createTextNode('0.2'));
  209. $resultEl->appendChild($format);
  210. $resultEl->appendChild($version);
  211. $resultEl = $this->write_resource_on_xml_element($dom, $pageUri, $resultEl, array());
  212. $dom->appendChild($resultEl);
  213. $this->_current_page_uri = false;
  214. return $dom->saveXml();
  215. }
  216. function write_resource_on_xml_element(DomDocument $dom, $uri, DomElement $el, $parentUris){
  217. /* resource ID */
  218. if($this->node_is_blank($uri)){
  219. $idAttr = $dom->createAttribute('id');
  220. } else {
  221. $idAttr = $dom->createAttribute('href');
  222. }
  223. $idAttr->appendChild($dom->createTextNode($uri));
  224. if(!empty($uri)) $el->appendChild($idAttr);
  225. $index = $this->get_index();
  226. $isPrimaryTopicSameAsResult = ($el->tagName == 'primaryTopic' AND count($parentUris) == 1);
  227. if(
  228. !in_array($uri, $parentUris) ||
  229. $isPrimaryTopicSameAsResult
  230. ){
  231. $resourceProperties = array(
  232. FOAF.'primaryTopic',
  233. FOAF.'isPrimaryTopicOf',
  234. API.'definition',
  235. DCT.'hasFormat',
  236. DCT.'hasVersion'
  237. );
  238. $parentUris[]=$uri;
  239. $properties = $this->get_subject_properties($uri);
  240. arsort($properties); //producing predictable output
  241. foreach($properties as $property){
  242. if (!$isPrimaryTopicSameAsResult || !in_array($property, $resourceProperties)) {
  243. $propertyName = $this->get_short_name_for_uri($property);
  244. $propEl = $dom->createElement($propertyName);
  245. $propValues = $index[$uri][$property];
  246. if(count($propValues) > 1 || $this->propertyIsMultiValued($property)){
  247. foreach($propValues as $val){
  248. $item = $dom->createElement('item');
  249. $item = $this->write_rdf_value_to_xml_element($dom, $val, $item, $uri, $property, $parentUris);
  250. $propEl->appendChild($item);
  251. }
  252. } else if (count($propValues) == 1) {
  253. $val = $propValues[0];
  254. $propEl = $this->write_rdf_value_to_xml_element($dom, $val, $propEl, $uri, $property, $parentUris);
  255. }
  256. $el->appendChild($propEl);
  257. }
  258. }
  259. }
  260. return $el;
  261. }
  262. private function write_rdf_value_to_xml_element(DomDocument $dom, $val, DomElement $el, $s, $p, $parentUris){
  263. if(in_array($val['type'], array('uri','bnode')) AND $this->resource_is_a_list($val['value'])) {
  264. $listValues = $this->list_to_array($val['value']);
  265. foreach($listValues as $itemURI){
  266. $item = $dom->createElement('item');
  267. $item = $this->write_resource_on_xml_element($dom, $itemURI, $item, $parentUris);
  268. $el->appendChild($item);
  269. }
  270. }
  271. else if($val['type']=='literal'){
  272. $el->appendChild($dom->createTextNode($val['value']));
  273. if(isset($val['lang'])){
  274. $xmllang = $dom->createAttribute('xml:lang');
  275. $xmllang->appendChild($dom->createTextNode($val['lang']));
  276. $el->appendChild($xmllang);
  277. } else if(isset($val['datatype'])){
  278. $shortname = $this->get_short_name_for_uri($val['datatype']);
  279. $datatypeAttr = $dom->createAttribute('datatype');
  280. $datatypeAttr->appendChild($dom->createTextNode($shortname));
  281. $el->appendChild($datatypeAttr);
  282. }
  283. } else if($val['type'] =='bnode' OR $val['type']=='uri'){
  284. $el = $this->write_resource_on_xml_element($dom, $val['value'], $el, $parentUris);
  285. }
  286. return $el;
  287. }
  288. function get_count_of_id_mentions($id){
  289. $Count = count($this->get_subjects_where_object($id));
  290. if($this->has_triples_about($id)) $Count++;
  291. return $Count;
  292. }
  293. function propertyIsMultiValued($propertyUri){
  294. return (
  295. $this->getConfigGraph()->has_literal_triple($propertyUri, API.'multiValued', "true")
  296. OR
  297. $this->getVocabularyGraph()->has_literal_triple($propertyUri, API.'multiValued', "true")
  298. );
  299. }
  300. function resource_is_a_page_list_item($pageUri, $resourceUri){
  301. $itemsList = $this->get_first_resource($pageUri, API.'items');
  302. $itemsArray = $this->list_to_array($itemsList);
  303. return in_array($resourceUri, $itemsArray);
  304. }
  305. function get_all_predicates(){
  306. $predicates = array();
  307. foreach($this->get_index() as $uri => $props){
  308. foreach($props as $p) $predicates[]=$p;
  309. }
  310. $predicates = array_unique($predicates);
  311. sort($predicates);
  312. return $predicates;
  313. }
  314. function get_label($uri, $capitalize = false, $use_qnames = FALSE){
  315. if($label = $this->_config->get_first_literal($uri, RDFS_LABEL)) return $label;
  316. if($label = $this->_config->get_first_literal($uri, API.'name')) return $label;
  317. if($label = $this->_config->get_first_literal($uri, API.'label')) return $label;
  318. else return parent::get_label($uri, $capitalize, $use_qnames);
  319. }
  320. }
  321. class BlankObject {}
  322. ?>