5 * @author Benjamin Nowack
6 * @license <http://arc.semsol.org/license>
7 * @homepage <http://arc.semsol.org/>
16 function __construct($a = '', &$caller) {
17 $a = is_array($a) ? $a : array();
19 $this->caller = &$caller;
23 function ARC2_Class($a = '', &$caller) {
24 $this->__construct($a, $caller);
27 function __destruct() {
28 //echo "\ndestructing " . get_class($this);
31 function __init() {/* base, time_limit */
32 if (!$_POST && isset($GLOBALS['HTTP_RAW_POST_DATA'])) parse_str($GLOBALS['HTTP_RAW_POST_DATA'], $_POST); /* php5 bug */
33 $this->inc_path = ARC2::getIncPath();
35 $this->nsp = array('http://www.w3.org/1999/02/22-rdf-syntax-ns#' => 'rdf');
36 $this->used_ns = array('http://www.w3.org/1999/02/22-rdf-syntax-ns#');
37 $this->ns = $this->v('ns', array(), $this->a);
39 $this->base = $this->v('base', ARC2::getRequestURI(), $this->a);
40 $this->errors = array();
41 $this->warnings = array();
42 $this->adjust_utf8 = $this->v('adjust_utf8', 0, $this->a);
43 $this->max_errors = $this->v('max_errors', 25, $this->a);
48 function v($name, $default = false, $o = false) {/* value if set */
49 if ($o === false) $o =& $this;
51 return isset($o[$name]) ? $o[$name] : $default;
53 return isset($o->$name) ? $o->$name : $default;
56 function v1($name, $default = false, $o = false) {/* value if 1 (= not empty) */
57 if ($o === false) $o =& $this;
59 return (isset($o[$name]) && $o[$name]) ? $o[$name] : $default;
61 return (isset($o->$name) && $o->$name) ? $o->$name : $default;
64 function m($name, $a = false, $default = false, $o = false) {/* call method */
65 if ($o === false) $o =& $this;
66 return method_exists($o, $name) ? $o->$name($a) : $default;
71 function camelCase($v, $lc_first = 0, $keep_boundaries = 0) {
73 while (preg_match('/^(.*)[^a-z0-9](.*)$/si', $r, $m)) {
74 /* don't fuse 2 upper-case chars */
75 if ($keep_boundaries && $m[1]) {
76 $boundary = substr($m[1], -1);
77 if (strtoupper($boundary) == $boundary) $m[1] .= 'CAMELCASEBOUNDARY';
79 $r = $m[1] . ucfirst($m[2]);
81 $r = str_replace('CAMELCASEBOUNDARY', '_', $r);
82 if ((strlen($r) > 1) && $lc_first && !preg_match('/[A-Z]/', $r[1])) $r = strtolower($r[0]) . substr($r, 1);
86 function deCamelCase($v, $uc_first = 0) {
87 $r = str_replace('_', ' ', $v);
88 $r = preg_replace('/([a-z0-9])([A-Z])/e', '"\\1 " . strtolower("\\2")', $r);
89 return $uc_first ? ucfirst($r) : $r;
92 function extractTermLabel($uri, $loops = 0) {
93 list($ns, $r) = $this->splitURI($uri);
94 $r = $this->deCamelCase($this->camelCase($r, 1, 1));
95 if (($loops < 1) && preg_match('/^(self|it|this|me)$/i', $r)) {
96 return $this->extractTermLabel(preg_replace('/\#.+$/', '', $uri), $loops + 1);
98 if ($uri && !$r && ($loops < 2)) {
99 return $this->extractTermLabel(preg_replace('/[\#\/]$/', '', $uri), $loops + 1);
106 function addError($v) {
107 if (!in_array($v, $this->errors)) {
108 $this->errors[] = $v;
110 if ($this->caller && method_exists($this->caller, 'addError')) {
111 $glue = strpos($v, ' in ') ? ' via ' : ' in ';
112 $this->caller->addError($v . $glue . get_class($this));
114 if (count($this->errors) > $this->max_errors) {
115 die('Too many errors (limit: ' . $this->max_errors . '): ' . print_r($this->errors, 1));
120 function getErrors() {
121 return $this->errors;
124 function getWarnings() {
125 return $this->warnings;
128 function resetErrors() {
129 $this->errors = array();
130 if ($this->caller && method_exists($this->caller, 'resetErrors')) {
131 $this->caller->resetErrors();
137 function splitURI($v) {
138 return ARC2::splitURI($v);
143 function getPName($v, $connector = ':') {
144 /* is already a pname */
145 if ($ns = $this->getPNameNamespace($v, $connector)) {
146 if (!in_array($ns, $this->used_ns)) $this->used_ns[] = $ns;
150 if ($parts = $this->splitURI($v)) {
152 foreach ($this->ns as $prefix => $ns) {
153 if ($parts[0] == $ns) {
154 if (!in_array($ns, $this->used_ns)) $this->used_ns[] = $ns;
155 return $prefix . $connector . $parts[1];
159 $prefix = $this->getPrefix($parts[0]);
160 return $prefix . $connector . $parts[1];
165 function getPNameNamespace($v, $connector = ':') {
166 $re = '/^([a-z0-9\_\-]+)\:([a-z0-9\_\-\.\%]+)$/i';
167 if ($connector != ':') {
168 $connectors = array('\:', '\-', '\_', '\.');
169 $chars = join('', array_diff($connectors, array($connector)));
170 $re = '/^([a-z0-9' . $chars . ']+)\\' . $connector . '([a-z0-9\_\-\.\%]+)$/i';
172 if (!preg_match($re, $v, $m)) return 0;
173 if (!isset($this->ns[$m[1]])) return 0;
174 return $this->ns[$m[1]];
177 function getPrefix($ns) {
178 if (!isset($this->nsp[$ns])) {
179 $this->ns['ns' . $this->ns_count] = $ns;
180 $this->nsp[$ns] = 'ns' . $this->ns_count;
183 if (!in_array($ns, $this->used_ns)) $this->used_ns[] = $ns;
184 return $this->nsp[$ns];
187 function expandPName($v, $connector = ':') {
188 $re = '/^([a-z0-9\_\-]+)\:([a-z0-9\_\-\.\%]+)$/i';
189 if ($connector != ':') {
190 $connectors = array(':', '-', '_', '.');
191 $chars = '\\' . join('\\', array_diff($connectors, array($connector)));
192 $re = '/^([a-z0-9' . $chars . ']+)\\' . $connector . '([a-z0-9\_\-\.\%]+)$/Ui';
194 if (preg_match($re, $v, $m) && isset($this->ns[$m[1]])) {
195 return $this->ns[$m[1]] . $m[2];
200 function expandPNames($index) {
202 foreach ($index as $s => $ps) {
203 $s = $this->expandPName($s);
205 foreach ($ps as $p => $os) {
206 $p = $this->expandPName($p);
207 if (!is_array($os)) $os = array($os);
208 foreach ($os as $i => $o) {
210 $o_val = $this->expandPName($o);
211 $o_type = preg_match('/^[a-z]+\:[^\s\<\>]+$/si', $o_val) ? 'uri' : 'literal';
212 $o = array('value' => $o_val, 'type' => $o_type);
224 function calcURI($path, $base = "") {
226 if (preg_match("/^[a-z0-9\_]+\:/i", $path)) {/* abs path or bnode */
229 if (preg_match('/^\$\{.*\}/', $path)) {/* placeholder, assume abs URI */
232 if (preg_match("/^\/\//", $path)) {/* net path, assume http */
233 return 'http:' . $path;
236 $base = $base ? $base : $this->base;
237 $base = preg_replace('/\#.*$/', '', $base);
238 if ($path === true) {/* empty (but valid) URIref via turtle parser: <> */
241 $path = preg_replace("/^\.\//", '', $path);
242 $root = preg_match('/(^[a-z0-9]+\:[\/]{1,3}[^\/]+)[\/|$]/i', $base, $m) ? $m[1] : $base; /* w/o trailing slash */
243 $base .= ($base == $root) ? '/' : '';
244 if (preg_match('/^\//', $path)) {/* leading slash */
245 return $root . $path;
250 if (preg_match('/^([\#\?])/', $path, $m)) {
251 return preg_replace('/\\' .$m[1]. '.*$/', '', $base) . $path;
253 if (preg_match('/^(\&)(.*)$/', $path, $m)) {/* not perfect yet */
254 return preg_match('/\?/', $base) ? $base . $m[1] . $m[2] : $base . '?' . $m[2];
256 if (preg_match("/^[a-z0-9]+\:/i", $path)) {/* abs path */
259 /* rel path: remove stuff after last slash */
260 $base = substr($base, 0, strrpos($base, '/')+1);
262 while (preg_match('/^(\.\.\/)(.*)$/', $path, $m)) {
264 $base = ($base == $root.'/') ? $base : preg_replace('/^(.*\/)[^\/]+\/$/', '\\1', $base);
266 return $base . $path;
271 function calcBase($path) {
273 $r = preg_replace('/\#.*$/', '', $r);/* remove hash */
274 $r = preg_replace('/^\/\//', 'http://', $r);/* net path (//), assume http */
275 if (preg_match('/^[a-z0-9]+\:/', $r)) {/* scheme, abs path */
276 while (preg_match('/^(.+\/)(\.\.\/.*)$/U', $r, $m)) {
277 $r = $this->calcURI($m[1], $m[2]);
281 return 'file://' . realpath($r);/* real path */
286 function getResource($uri, $store_or_props = '') {
287 $res = ARC2::getResource($this->a);
289 if (is_array($store_or_props)) {
290 $res->setProps($store_or_props);
293 $res->setStore($store_or_props);
298 function toIndex($v) {
300 if (isset($v[0]) && isset($v[0]['s'])) return ARC2::getSimpleIndex($v, 0);
303 $parser = ARC2::getRDFParser($this->a);
304 if ($v && !preg_match('/\s/', $v)) {/* assume graph URI */
308 $parser->parse('', $v);
310 return $parser->getSimpleIndex(0);
313 function toTriples($v) {
315 if (isset($v[0]) && isset($v[0]['s'])) return $v;
316 return ARC2::getTriplesFromIndex($v);
318 $parser = ARC2::getRDFParser($this->a);
319 if ($v && !preg_match('/\s/', $v)) {/* assume graph URI */
323 $parser->parse('', $v);
325 return $parser->getTriples();
330 function toNTriples($v, $ns = '', $raw = 0) {
331 ARC2::inc('NTriplesSerializer');
332 if (!$ns) $ns = isset($this->a['ns']) ? $this->a['ns'] : array();
333 $ser = new ARC2_NTriplesSerializer(array_merge($this->a, array('ns' => $ns)), $this);
334 return (isset($v[0]) && isset($v[0]['s'])) ? $ser->getSerializedTriples($v, $raw) : $ser->getSerializedIndex($v, $raw);
337 function toTurtle($v, $ns = '', $raw = 0) {
338 ARC2::inc('TurtleSerializer');
339 if (!$ns) $ns = isset($this->a['ns']) ? $this->a['ns'] : array();
340 $ser = new ARC2_TurtleSerializer(array_merge($this->a, array('ns' => $ns)), $this);
341 return (isset($v[0]) && isset($v[0]['s'])) ? $ser->getSerializedTriples($v, $raw) : $ser->getSerializedIndex($v, $raw);
344 function toRDFXML($v, $ns = '', $raw = 0) {
345 ARC2::inc('RDFXMLSerializer');
346 if (!$ns) $ns = isset($this->a['ns']) ? $this->a['ns'] : array();
347 $ser = new ARC2_RDFXMLSerializer(array_merge($this->a, array('ns' => $ns)), $this);
348 return (isset($v[0]) && isset($v[0]['s'])) ? $ser->getSerializedTriples($v, $raw) : $ser->getSerializedIndex($v, $raw);
351 function toRDFJSON($v, $ns = '') {
352 ARC2::inc('RDFJSONSerializer');
353 if (!$ns) $ns = isset($this->a['ns']) ? $this->a['ns'] : array();
354 $ser = new ARC2_RDFJSONSerializer(array_merge($this->a, array('ns' => $ns)), $this);
355 return (isset($v[0]) && isset($v[0]['s'])) ? $ser->getSerializedTriples($v) : $ser->getSerializedIndex($v);
358 function toRSS10($v, $ns = '') {
359 ARC2::inc('RSS10Serializer');
360 if (!$ns) $ns = isset($this->a['ns']) ? $this->a['ns'] : array();
361 $ser = new ARC2_RSS10Serializer(array_merge($this->a, array('ns' => $ns)), $this);
362 return (isset($v[0]) && isset($v[0]['s'])) ? $ser->getSerializedTriples($v) : $ser->getSerializedIndex($v);
365 function toLegacyXML($v, $ns = '') {
366 ARC2::inc('LegacyXMLSerializer');
367 if (!$ns) $ns = isset($this->a['ns']) ? $this->a['ns'] : array();
368 $ser = new ARC2_LegacyXMLSerializer(array_merge($this->a, array('ns' => $ns)), $this);
369 return $ser->getSerializedArray($v);
372 function toLegacyJSON($v, $ns = '') {
373 ARC2::inc('LegacyJSONSerializer');
374 if (!$ns) $ns = isset($this->a['ns']) ? $this->a['ns'] : array();
375 $ser = new ARC2_LegacyJSONSerializer(array_merge($this->a, array('ns' => $ns)), $this);
376 return $ser->getSerializedArray($v);
379 function toLegacyHTML($v, $ns = '') {
380 ARC2::inc('LegacyHTMLSerializer');
381 if (!$ns) $ns = isset($this->a['ns']) ? $this->a['ns'] : array();
382 $ser = new ARC2_LegacyHTMLSerializer(array_merge($this->a, array('ns' => $ns)), $this);
383 return $ser->getSerializedArray($v);
386 function toHTML($v, $ns = '', $label_store = '') {
387 ARC2::inc('MicroRDFSerializer');
388 if (!$ns) $ns = isset($this->a['ns']) ? $this->a['ns'] : array();
389 $conf = array_merge($this->a, array('ns' => $ns));
390 if ($label_store) $conf['label_store'] = $label_store;
391 $ser = new ARC2_MicroRDFSerializer($conf, $this);
392 return (isset($v[0]) && isset($v[0]['s'])) ? $ser->getSerializedTriples($v) : $ser->getSerializedIndex($v);
397 function getFilledTemplate($t, $vals, $g = '') {
398 $parser = ARC2::getTurtleParser();
399 $parser->parse($g, $this->getTurtleHead() . $t);
400 return $parser->getSimpleIndex(0, $vals);
403 function getTurtleHead() {
405 $ns = $this->v('ns', array(), $this->a);
406 foreach ($ns as $k => $v) {
407 $r .= "@prefix " . $k . ": <" .$v. "> .\n";
412 function completeQuery($q, $ns = '') {
413 if (!$ns) $ns = isset($this->a['ns']) ? $this->a['ns'] : array();
414 $added_prefixes = array();
416 foreach ($ns as $k => $v) {
418 if (in_array($k, $added_prefixes)) continue;
419 if (preg_match('/(^|\s)' . $k . ':/s', $q) && !preg_match('/PREFIX\s+' . $k . '\:/is', $q)) {
420 $prologue .= "\n" . 'PREFIX ' . $k . ': <' . $v . '>';
422 $added_prefixes[] = $k;
424 return $prologue . "\n" . $q;
429 function toUTF8($str) {
430 return $this->adjust_utf8 ? ARC2::toUTF8($str) : $str;
433 function toDataURI($str) {
434 return 'data:text/plain;charset=utf-8,' . rawurlencode($str);
437 function fromDataURI($str) {
438 return str_replace('data:text/plain;charset=utf-8,', '', rawurldecode($str));
441 /* prevent SQL injections via SPARQL REGEX */
443 function checkRegex($str) {
444 return addslashes($str); // @@todo extend
447 /* Microdata methods */
449 function getMicrodataAttrs($id, $type = '') {
450 $type = $type ? $this->expandPName($type) : $this->expandPName('owl:Thing');
451 return 'itemscope="" itemtype="' . htmlspecialchars($type) . '" itemid="' . htmlspecialchars($id) . '"';
454 function mdAttrs($id, $type = '') {
455 return $this->getMicrodataAttrs($id, $type);
458 /* central DB query hook */
460 function queryDB($sql, $con, $log_errors = 0) {
462 $r = mysql_query($sql, $con);
463 $t2 = ARC2::mtime() - $t1;
465 //echo "\n needed " . $t2 . ' secs for ' . $sql;
467 if ($log_errors && ($er = mysql_error($con))) $this->addError($er);