<?php /* * This is the main Triplify script. * * @version $Id:$ * @license LGPL * @copyright 2008 Sören Auer (soeren.auer@gmail.com) */ error_reporting(E_ALL ^ E_NOTICE);
include('config.inc.php');
$serverURI='http://'.$_SERVER['SERVER_NAME'].($_SERVER['SERVER_PORT']!=80?':'.$_SERVER['SERVER_PORT']:''); $baseURI=$serverURI.substr($_SERVER['REQUEST_URI'],0,strpos($_SERVER['REQUEST_URI'],'/triplify')+9).'/'. (in_array('mod_rewrite',apache_get_modules())?'':'index.php/'); $path=str_replace($baseURI,'',$serverURI.$_SERVER['REQUEST_URI'].(substr($_SERVER['REQUEST_URI'],-1,1)!='/'?'/':''));
if(!$path) { $r=array_filter(explode('/',$path)); $class=array_shift($r); if($class!='update' && count($r)==1) $instance=array_pop($r); foreach($triplify['queries'] as $key=>$val) if(substr($key,0,1)=='/' && preg_match($key,$path)) $exists=true; if(!$exists && (($class!='update' && $r) || !$class || !$triplify['queries'][$class])) { header("HTTP/1.0 404 Not Found"); echo("<h1>Error 404</h1>Resource not found!"); exit; } }
if($_REQUEST['t-output']=='json') header('Content-Type: text/javascript'); else #if(0) header('Content-Type: text/rdf+n3');
$cacheFile=$triplify['cachedir'].md5($_SERVER['REQUEST_URI']); if(file_exists($cacheFile) && filemtime($cacheFile)>time()-$triplify['TTL']) { echo file_get_contents($cacheFile); exit; }
if(!file_exists($triplify['cachedir'].'registered') && $triplify['register']) { $url='http://triplify.org/register/?url='.urlencode($baseURI).'&type='.urlencode($triplify['namespaces']['vocabulary']); if($f=fopen($url,'r')) fclose($f); touch($triplify['cachedir'].'registered'); }
$t=new tripleizer($triplify); if($triplify['TTL']) ob_start();
$t->tripleize($triplify['queries'],$class,$instance); if($_REQUEST['t-output']=='json') echo json_encode($t->json);
if($triplify['TTL']) file_put_contents($cacheFile,ob_get_contents());
/* * */ class tripleizer { var $maxResults; var $json=array(); var $version='V0.5'; /* Constructor * * @param array $config Array of configuration parameters, which are explained in config.inc.php */ function tripleizer($config=array()) { if(is_object($config['db'])) { $this->pdo=$config['db']; $this->pdo->setAttribute(eval('return PDO::MYSQL_ATTR_USE_BUFFERED_QUERY;'),false); } $this->config=$config; $this->ns=$config['namespaces']; $this->objectProperties=$config['objectProperties']; $this->classMap=$config['classMap']; $this->path=explode('/',rtrim($GLOBALS['path'],'/')); } /* * Transforms an SQL query (result) into NTriples * The first column of the query result is used as instance identifier. * * @param string $query an SQL query * @param string $class RDF class URI of the class the instances belong to * @return string $id Id of a specific entry */ function tripleize($queries,$c=NULL,$id=NULL) { static $typed; $self=$GLOBALS['serverURI'].$_SERVER['REQUEST_URI']; #$this->writeTriple($self,$this->uri('owl:imports'),$this->ns['vocabulary']); $this->writeTriple($self,$this->uri('rdfs:comment'),'Generated by Triplify '.$this->version.' (http://Triplify.org)',true); if($this->config['license']) $this->writeTriple($self,'http://creativecommons.org/ns#license',$this->config['license']); if(is_array($this->config['metadata'])) foreach($this->config['metadata'] as $property=>$value) if($value) $this->writeTriple($self,$this->uri($property),$value,true); foreach($queries as $class=>$q) if(!$c || $class==$c || (substr($class,0,1)=='/' && preg_match($class,$GLOBALS['path']))) { foreach(is_array($q)?$q:array($q) as $qid=>$query) { unset($cols,$group); if(substr($class,0,1)=='/') { unset($id); $query=preg_replace($class,$query,rtrim($GLOBALS['path'],'/')); } else if(!$id && $this->config['LinkedDataDepth']==3) { exit; } else if($class=='update') { $cols=count($this->path)==7?'*':'SUBSTR(id,1,'.(count($this->path)*3+1).')'; $group=($this->path[1]?' AND YEAR(id)="'.$this->path[1].'"':''). ($this->path[2]?' AND MONTH(id)="'.$this->path[2].'"':''). ($this->path[3]?' AND DAY(id)="'.$this->path[3].'"':''). ($this->path[4]?' AND HOUR(id)="'.$this->path[4].'"':''). ($this->path[5]?' AND MINUTE(id)="'.$this->path[5].'"':''). ($this->path[6]?' AND SECOND(id)="'.$this->path[6].'"':''); if(count($this->path)!=7) $group.=' GROUP BY SUBSTR(id,1,'.(count($this->path)*3+1).')'; } else if($this->config['LinkedDataDepth']==2&&!$c) { $this->writeTriple($this->uri($class),$this->uri('rdf:type'),$this->uri('owl:Class')); continue(2); } else $cols=($this->config['LinkedDataDepth']==1&&!$c)||($this->config['LinkedDataDepth']==2&&!$id)?'id':'*'; if(($cols && $cols!='*') || $group) $query="SELECT $cols FROM ($query) t WHERE 1".$group; if($class && !$id && $_GET) { foreach($_GET as $key=>$v) if(substr($key,0,2)!='t-' && !strpos($key,'`')) $query.=' AND `'.$key.'`='.$this->dbQuote($v); } $start=is_numeric($_GET['t-start'])?$_GET['t-start']:0; $erg=is_numeric($_GET['t-results'])?($this->maxResults?min($_GET['t-results'],$this->maxResults):$_GET['t-results']):$this->maxResults; $query=$query.($id?' AND '.(is_numeric($qid)?'id':$qid).'='.$this->dbQuote(urldecode($id)):''). (preg_match('/^[A-Za-z0-9: ,]+?$/',$_GET['t-order'])?' ORDER BY '.$_GET['t-order']:''). ($start||$erg?' LIMIT '.($start?$start.','.($erg?$erg:20):$erg):''); #echo $query; if($res=$this->dbQuery($query)) { $dtype=$this->dbDtypes($res); while($cl=$this->dbFetch($res)) $this->makeTriples($cl,$class,$dtype); } $this->typed[$class]=true; if($cols=='id') break; } } } /** * makeTriples creates a number of triples from a database row * * @param array $cl * @param string $class * @param array $dtypes * @return */ function makeTriples($cl,$class,$dtypes) { $rdf_ns='http://www.w3.org/1999/02/22-rdf-syntax-ns#'; $ipref=$this->uri($class.'/'); $uri=array_shift($cl); if($class=='update') $uri=preg_replace('/[^0-9]/','/',$uri).'#'.substr(strstr(key($cl),'->'),2).current($cl); $subject=$this->uri($uri,$ipref); if(!$uri) $uri=md5(join($cl)); if($class && !$this->typed[$class] && substr($class,0,1)!='/') { if($class=='update') $c=count($this->path)==7?'http://triplify.org/vocabulary/update#Update':'http://triplify.org/vocabulary/update#UpdateCollection'; else $c=$this->classMap[$class]?$this->classMap[$class]:$class; $this->writeTriple($subject,$rdf_ns.'type',$this->uri($c,$this->ns['vocabulary'])); } #foreach($cl as $p=>$val) reset($cl); while(list($p, $val) = each($cl)) { if($p=='t:unc') { $p=current($cl); next($cl); } if($val && ($dtypes[$p]!='xsd:dateTime'||$val!='0000-00-00 00:00:00')) { if(strpos($p,'^^')) { $dtype=$this->uri(substr($p,strpos($p,'^^')+2)); $p=substr($p,0,strpos($p,'^')); } else if($dtypes[$p]) { $dtype=$this->uri($dtypes[$p]); } else if(strpos($p,'@')) { $lang=substr(strstr($p,'@'),1); $p=substr($p,0,strpos($p,'@')); } else unset($dtype,$lang);
if(strpos($p,'->')) { $objectProperty=substr(strstr($p,'->'),2); $p=substr($p,0,strpos($p,'->')); } else if(isset($this->objectProperties[$p])) { $objectProperty=$this->objectProperties[$p]; } else unset($objectProperty);
if($this->config['CallbackFunctions'][$p] && is_callable($this->config['CallbackFunctions'][$p])) $val=call_user_func($this->config['CallbackFunctions'][$p],$val); $val=utf8_encode($val);
$prop=$this->uri($p,$this->ns['vocabulary']); if(isset($objectProperty)) { $isLiteral=false; $object=$this->uri($objectProperty.($objectProperty&&substr($objectProperty,-1,1)!='/'?'/':'').$val); } else { $isLiteral=true; $object=($dtypes[$p]=='xsd:dateTime'?str_replace(' ','T',$val):$val); } $this->writeTriple($subject,$prop,$object,$isLiteral,$dtype,$lang); } } return $ret; } /** * writeTriple - writes a triple in a certain output format * * @param string $subject subject of the triple to be written * @param string $predicate predicate of the triple to be written * @param string $object object of the triple to be written * @param boolean $isLiteral boolean flag whether object is a literal, defaults to false * @param string $dtype datatype of a literal object * @param string $lang language of the literal object * @return */ function writeTriple($subject,$predicate,$object,$isLiteral=false,$dtype=NULL,$lang=NULL) { static $oldsubject,$written; if($subject!=$oldsubject) { $oldsubject=$subject; unset($written); } $hash=md5($subject.$predicate.$object.$isLiteral.$dtype.$lang); if($written[$hash]) return; else $written[$hash]=true; if($_REQUEST['t-output']=='json') { $oa=array('value'=>$object,'type'=>($isLiteral?'literal':'uri')); if($isLiteral && $dtype) $oa['datatype']=$dtype; else if($isLiteral && $lang) $oa['language']=$lang; $this->json[$subject][$predicate]=($this->json[$subject][$predicate]?array_merge($this->json[$subject][$predicate],$oa):$oa); } else { if($isLiteral) $object='"'.str_replace(array('\\',"\r","\n",'"'),array('\\\\','\r','\n','\"'),$object).'"'.($dtype?'^^<'.$dtype.'>':($lang?'@'.$lang:'')); else $object='<'.$object.'>'; echo '<'.$subject.'> <'.$predicate.'> '.$object." .\n"; } flush(); } /** * tripleizer::uri() * * @param mixed $name * @param mixed $default * @return */ function uri($name,$default=NULL) { if(strstr($name,'://')) return $name; return (strpos($name,':')?$this->ns[substr($name,0,strpos($name,':'))].substr($name,strpos($name,':')+1): ($default?$default:$GLOBALS['baseURI']).$name); } function dbQuote($string) { return $this->pdo?$this->pdo->quote($string):'\''.mysql_real_escape_string($string).'\''; } function dbQuery($query) { #$this->pdo->query($query,eval('return PDO::FETCH_ASSOC;')); #print_r($this->pdo->errorInfo()); return $this->pdo?$this->pdo->query($query,eval('return PDO::FETCH_ASSOC;')):mysql_query($query); } function dbFetch($res) { return $this->pdo?$res->fetch():mysql_fetch_assoc($res); } function dbDtypes($res){ if(method_exists($res,'getColumnMeta')) for($i=0;$i<$res->columnCount();$i++) { $meta=$res->getColumnMeta($i); if($meta['native_type']=='TIMESTAMP' || $meta['native_type']=='DATETIME') $dtype[$meta['name']]='xsd:dateTime'; } else if(!$this->pdo) { for($i=0;$i<mysql_num_fields($res);$i++) { $type=mysql_field_type($res,$i); if(!strcasecmp($type,'timestamp') || !strcasecmp($type,'datetime')) $dtype[mysql_field_name($res,$i)]='xsd:dateTime'; } } return $dtype; } } ?>
|