Code Listing

/code/erdft/erdft-smarty.phps

<?php
include("erdft_parser.php");

$erdf = file_get_contents('test.erdft');	

//instantiate template parser: params are ($template_string, $sparql_var_regex, $sparql_optional_regex, $arc_config_path)
//
$eRdfT = new eRDFT($erdf, '/{(\$[a-zA-Z_]+)[^\}]*?}/', '/(\$[a-zA-Z_]+?)_optional/', './arc_config.php');	
$data = $eRdfT->get_results();
$vars = array_keys($data[0]);

//set Smarty variables
include('/usr/lib/php/Smarty/libs/Smarty.class.php');
$smarty = new Smarty;
foreach($vars as $var)
{
	//determine whether to give variable a value or an array
	if(strpos($var, '__') )//this is a variable naming convention - array keys being named $singular__key and arrays being named $plural
	{
		//get array name 
		$parts = explode('__', $var);
		$array_name = $parts[0].'s';
		$smarty->assign($array_name, $data);
		$new_form = '$'.$parts[0].'.'.$var;
		$erdf = str_replace( '$'.$var , $new_form , $erdf); //convert to $row.key
	}
	else 
	{
		$v = $data[0][$var];
		$smarty->assign($var, $v);
	}
}
$erdf = preg_replace($eRdfT->REG_EXES['SPARQL_OPTIONAL'],'$1',$erdf);

$smarty->template_dir = './templates';
//now process
$handle = fopen("templates/temp_test.tpl", "w");
if (fwrite($handle, $erdf) === FALSE) {
      echo "Cannot write to file ($filename)";
      exit;
  }
fclose($handle);

$smarty->display("temp_test.tpl");
?>

/code/erdft/json2sparql.phps

<?php 
/**
  * A script to process an Exhibit JSON template 
  * file into one or more SPARQL queries, and return the results as
  * an Exhibit JSON file.
  *  The template file should be a normal Exhibit database, except objects under the "types" and "properties" objects    
  *  should have a property called "uri", containing the URI of the Class or Property, 
  *  items should have some properties with empty values, 
  *  and an item's "label" should be the name of another property.
  * Author: Keith Alexander 
 */

/*Instantiate ARC API */
require_once("arc/ARC_api.php");
$api_args = array(
  "inc_path"=>"./arc/",
  "config_path"=>"./arc_config.php"
);
$api = new ARC_api($api_args);
$api->db_connect();

//read the JSON template file
require('json.php');
$json = new Services_JSON();
$data = $json->decode(file_get_contents('template.json'));
//get all the items - we will create a query for each item we find
$template_items = $data->items;
//empty the items array from our original JSON file - we will fill it with results
$data->items = array();
//iterate over the template items, creating a query
foreach($template_items as $item)
{
	//the subject of the graph - can be preset by the user, or left blank
	//so we either turn it into  <http://example.com/users-id#> or ?id
	$subject = (isset($item->id) && !empty($item->id))? '<'.$item->id.'>' : '?id';
	// get the human readable type label
	$type_name = $item->type;
	// get the type's IRI
	$type = '<'.$data->types->$type_name->uri.'>';
	//get the label's property name
	$label_prop_name = $item->label;
	//get the label's property's IRI
	$label_prop = '<'.$data->properties->$label_prop_name->uri.'>';
	
	//for storing WHERE conditions
	$triples = array();
	//vars in the select statement
	$vars = array();
	//jsonc is a parameter that the ARC store accepts to strip out 
	// unwanted meta properties from the JSON results object
	$jsonc = array('id');
	
	//iterate over the template item's properties
	foreach($item as $k => $v)
	{
		//determine node type of object
		if(empty($v))
		{
			$object = '?'.$k;
		}
		elseif( (substr($v,0,1)=='<') && (substr($v,-1,1)=='>') )
		{
			$object = $k;
		}
		else 
		{
			$object ='"'.$v. '"';
		}
		$vars[]='?'.$k;
		$jsonc[]= $k;
		if(!in_array($k, array('type','id','label')) )
		{
			$property = $data->properties->$k->uri;
		 	$triples[] = <<<_SPQL_
		$subject <{$property}> $object  . 
_SPQL_;
		}
	}
	$sparql = "SELECT ?id ".implode(" ", $vars)." \r\n WHERE { \r\n\t GRAPH ?id {
		 $subject <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> $type . \r\n 
$subject <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type . \r\n 
 $subject $label_prop ?label . \r\n 
 ?id $label_prop ?label . \r\n 

".implode("\r\n", $triples)."  \r\n\t }  \r\n   } LIMIT 100";

	$args=array(
	  "result_type"=>'json', // (rows|json|xml|single|rows_n_count|row_count|sql)
	  "query"=>$sparql,
	 "result_type_args"=>array("jsonc"=> implode(",",$jsonc),)
);
	$qr=$api->query($args);
	$result = $json->decode($qr['result']);
	
	foreach($result->results->bindings as $row)
	{
		//make the rdf:type human readable
		$row->type = $type_name;
		$data->items[] = $row;
	}
}
//output
header("Content-type: text");
echo stripslashes($json->encode($data));
?>

/code/erdft/test.erdft.txt

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en">
    <head profile="http://purl.org/NET/erdf/profile">
		<link rel="schema.dc" href="http://purl.org/dc/elements/1.1/" />
		<link rel="schema.foaf" href="http://xmlns.com/foaf/0.1/" />
		<link rel="schema.rdf" href="http://www.w3.org/1999/02/22-rdf-syntax-ns#" />
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>eRDFT test </title>
    </head>
    <body>
	<h1>eRDFT test</h1>
	<h2>Things with dc:titles from the datastore</h2>
	<ul>
	{foreach from="$rows" item="row"}
	<li id="{$row__foo}"><span class="dc-title">{$row__title}</span></li>
	{/foreach}
	</ul>
	<div class="-Person" id="{$someone}">
		<p>My name is <strong class="foaf-name">{$myname}</strong>.</p>
	</div>
	</body>
</html>

/code/erdft/erdf_parser_0.3.phps

<?php
/**
 * 
 *
 * @author Keith Alexander
 * @version 0.3
 * @copyright GPL
 * @package eRDFT
 * class eRDFT : a class that uses ARC_erdf_parser to retrieve triples
 * from an eRDF template and convert them into  SPARQL queries, retrieve data from 
 * the ARC mysql-backed RDF triple store, and store it as an associative array which can then be used     
 * by the eRDF template to display the data.
 *
 *	//Changes: changed the conditions in makeWhereClause to do better optional clause selection
 **/

require_once("arc/ARC_api.php");
require_once("arc/ARC_erdf_parser.php");
class eRDFT
{
	var $erdf,
		$base_href=false,
		$arc_config_path,
		$api,
	    $triple_info = array(),
		$processed_triples = array(),
		$sparql_vars = array(),
		$sparqls = array(),
		$resource_indices = array(),
		$levels = array(),
		$resultsets = array(),
		$top_level_resultset = array(),
		$results = array(),
	    $errors = array(),
		$REG_EXES = array(
			'SPARQL_VAR' => 	'/(\$[a-zA-Z_\.]+)/',
			'IRI' => 			'/^([a-zA-Z]+:\/\/[^\W"\']+)/',
			'SPARQL_OPTIONAL' => '/(\$[a-zA-Z_\.]+?)_optional/',
		
			);
	
	function eRDFT($erdf, $base=false, $regexes=array(), $arc_config_path=null, $auto=true)
	{
		$this->erdf = $erdf;
		$this->arc_config_path = ($arc_config_path)? $arc_config_path : dirname(__FILE__).'/arc/arc_config.php';
			/*Instantiate API */
		$api_args = array(
		  "inc_path"=> dirname(__FILE__)."/arc/",
		  "config_path"=> $this->arc_config_path,
		);
		$this->api = new ARC_api($api_args);
		$this->api->db_connect() or die("Couldn't connect to database");
		if(!$this->api->store_exists()) $this->api->create_store() or die("Couldn't create rdfstore - check user permissions");
		
		if($base) $this->base_href = $base;
		
		foreach($regexes as $k => $v)
		{
			$this->REG_EXES[$k] = $v;
		}
		
		if($auto)
		{
			$this->parse_erdf($erdf);
		
			$this->makeResultsets();
		
		 	$this->doQueries();
			
			$this->format_erdf();
		} //else the user can make changes to the triples before processing
		
	}
	
	function makeResultsets()
	{
		$sparql_vars = $this->sparql_vars;
		foreach($sparql_vars as $v)
		{ 
		$resultsets =& $this->resultsets;
		if(strpos($v, '__')) // __ is the path separator
			{
				$path_keys = array_slice(explode('__', substr($v,1)), 0, -1);
				$path = "['".implode("']['sub_results']['", $path_keys)."']";
				eval('$resultsets["sub_results"]'.$path."['sparql_vars'][] = '".$v."';");
				array_push($path_keys, '');
			$prefix = implode('__', $path_keys);
			eval('$resultsets["sub_results"]'.$path."['row_prefix'] = '{$prefix}';");
			}
			else
			{
				$this->top_level_resultset['sparql_vars'][] = $v;
			}
		}
	}
	
	// parses eRDF html and extracts triples
	function parse_erdf()
	{
		$erdf = $this->erdf;
		$parser_args=array("encoding"=>"auto");
		if($this->base_href) $parser_args['base'] = $this->base_href;
		$parser=new ARC_erdf_parser($parser_args);
		$p_result=$parser->parse_data($this->erdf);
		
		//check if the eRDF parses
		if($p_result["result"] && !$p_result["error"])
		{
			
			//get triples
			$this->triple_info = $parser->get_triple_infos();
			//process triples for sparql syntax
			
			for($x=0; $x < count($this->triple_info['triples'] ); $x++) 
			{
				$t = $this->triple_info['triples'][$x];
				
				//clean s and o into sparql vars. stuff{$name} => $name
				foreach(array('s','o') as $k ) 
				{
					$this->_format_node($k, $t);
				}
				$this->processed_triples[] = $t;
			}
		
		}
		else
		{
			if($p_result["error"]) $this->errors[]=$p_result['error'];
			return false;
		}
		
	}
	
	

	
	function get_triples_by_subject($s, &$qt)
	{
		$nqt = array();
		for ($i=0; $i < count($qt); $i++)
		{
			$t = $qt[$i];
			if($t['s'] == $s) 
			{
				$nqt[]=$t;
				unset($qt[$i]);
			}
		}
		return $nqt;
	}
	
	function doQueries()
	{
		//make prefix head
		$prefixes = '';
		 foreach($this->triple_info['prefixes'] as $k => $v) $prefixes.='PREFIX '.$k.': '.'<'.$v.'>'." \r\n";
	
		$whereclause = $this->makeWhereClause($sparql_vars);
		
			$sparql = $prefixes;
		
			//top level sparql
			if(!empty($this->top_level_resultset['sparql_vars']))
			{
				$sparql.="\r\n SELECT ".implode(" ", array_unique($this->top_level_resultset['sparql_vars']))."\r\n WHERE { $whereclause } LIMIT 1";
			
			$this->top_level_resultset['sparql'] = $sparql;
							
			$data = $this->get_data($sparql);
			if($data[0]) foreach($data[0] as $k => $v) $this->results[$k] = $v;
			}		
		//get nested loops recursively
		
		$this->nested_data($this->resultsets['sub_results'], $this->results, $prefixes, $data[0]);
	}
	
	
	
	function nested_data(&$resultset, &$dataset, $prefixes, $parent_row=array(), $parent_row_prefix)
	{
			foreach($resultset as $k => $v)
			{
				//build the sparql query string
				$sparql = $prefixes;
				$sparql_vars = array_unique($v['sparql_vars']);
				$whereclause = $this->makeWhereClause($sparql_vars,$parent_row,$parent_row_prefix);
				
				$sparql.="\r\n SELECT  ".implode(" ",$sparql_vars)."\r\n WHERE { GRAPH ?erdftgraph { $whereclause } } LIMIT 50";
		
			
				$sparql = str_replace($v['row_prefix'],'', $sparql ); //get rid of this particular row prefix
				//eg: cd__artist becomes artist, but artist__name stays artist__name in this query
				
				$resultset[$k]['sparql'] = $sparql;
			//get and save results
			//the $k of resultset is pluralised in dataset by appending an 's'. Better to write 'mouses' than have to think about whether 'mice' will work.
				$dataset[$k.'s'] = ($this->get_data($sparql, 'rows'));
				if(isset($resultset[$k]['sub_results']) && !empty($dataset[$k.'s']))
					{
						//now go through each row of the current result set, making a query for any sub result sets
										$row_number = 0;
										foreach($dataset[$k.'s'] as $row)
										{
											$whereclause = $this->makeWhereClause($v2['sparql_vars'],$row, $v2['row_prefix']);
										
											$this->nested_data($resultset[$k]['sub_results'], $dataset[$k.'s'][$row_number], $prefixes, $row, $v['row_prefix']);
											$row_number++;
											
										}
									}
									
			}
	}
	
	// queries the rdf-store with the sparql query and gets back the data
	function get_data($sparql, $resultype='rows')
	{
		$this->sparqls[] = $sparql;
		$query_args=array(
					  "result_type"=>$resultype, // (rows|json|xml|single|rows_n_count|row_count|sql)
					  "query"=>$sparql
					);
					$qr=$this->api->query($query_args) or die("Couldn't query datastore");
					if (!empty($qr['error'])) $this->errors[] = $qr['error'];
					if (empty($qr['result'])) $this->errors[] = 'Query returned no data.';
					//return $qr['result'];
					return $qr['result'];
	}
	

	
	function get_eRDF()
	{
		return $this->erdf;
	}
	
	function get_results()
	{
		return	$this->results;
	}
	
	function get_sparqls()
	{
		return $this->sparqls;
	}
	
	function index_resources()
	{
		$tri = $this->processed_triples;
		if(empty($tri)) $this->errors[] = 'No Triples were processed!';
		$r = array();
		foreach($tri as $t)
		{
			$r[$t['s']]['props'][] = $t;
			$r[$t['o']]['inverse_props'][] = $t;
			$r[$t['s']]['all_props'][] = $t;
			$r[$t['o']]['all_props'][] = $t;
			//array_unique($r['subjects'][$t['s']]['props']);
		}
		$this->resource_indices = $r;
	}
	
	function _format_node($k, &$t)
	{
		$node &= $t[$k];
			if(preg_match($this->REG_EXES['SPARQL_VAR'], $t[$k], $m))
			{
				if(	preg_match($this->REG_EXES['SPARQL_OPTIONAL'],$m[1],$sub_m))// it's an optional variable
				 {
					//triple is only optional if the optional node is the object
				 	if($t[$k] == $t['o']) $t['SPARQL_TRIPLE_TYPE'] = 'OPTIONAL';
					$t[$k.'_erdft_type'] = 'SPARQL_OPTIONAL_VAR';
					
					$t[$k] = str_replace('.','__',$sub_m[1]);
					$this->sparql_vars[]=$t[$k];
				 }
				else //it's a regular variable
				{
					$t[$k.'_erdft_type'] = 'SPARQL_VAR';
					$t[$k] = str_replace('.','__',$m[1]);					
					$this->sparql_vars[]=$t[$k];
				}
				
			}
			// elseif($t[$k] == '') //if a node is empty, give it a var
			// 		{
			// 			$t[$k] = '?ERDFT';
			// 			$t[$k.'_erdft_type'] = 'SPARQL_VAR';
			// 			$this->errors[]='The query is not accurate - you need to add an id to your top level element' ;	
			// 		}
			elseif( preg_match($this->REG_EXES['IRI'], $t[$k]) ) //IRI syntax
			{
				$t[$k] = 	'<' . $t[$k].'>';
				$t[$k.'_erdft_type'] = 'IRI'; 
				
			}
			else // quote literals
			{
				$t[$k] = '"'.$t[$k].'"';
				$t[$k.'_erdft_type'] = 'LITERAL'; 
			}
			return $t[$k];
	}

	function makeWhereClause($sparql_vars, $datarow=array(), $row_prefix='')
	{
			$conditions = array();
			$optionals = array();
	
		foreach($this->processed_triples as $rt) 
		{
			foreach(array('s','o') as $k)
			{
				//if var is like $foo__bar, we need to get 'bar', which may be a heading in the row
			
					$rowheader = substr($rt[$k], strlen($row_prefix)+1);
					if((!strpos($rowheader,'__') ) && $datarow[$rowheader] )
					{									
						$rt[$k] = $datarow[$rowheader];
						$rt[$k] = $this->_format_node($k, &$rt);
					 }
				
			}
			if((strpos($rt['s_erdft_type'], '_VAR') !== false) || (strpos($rt['o_erdft_type'], '_VAR') !== false)  )
			{
				$condition = "{$rt['s']}  {$rt['p_qname']} {$rt['o']} ."; 

				if ( ($rt['o_erdft_type'] == 'SPARQL_OPTIONAL_VAR') && (in_array($rt['s'], $sparql_vars)   )  )
				{
					 $optionals[] = "\r\n OPTIONAL( {$condition} )";
				}
				elseif ( ( ($rt['s_erdft_type'] == 'SPARQL_OPTIONAL_VAR') 
							&& (!in_array($rt['o'], $sparql_vars)  ) ) 
						||  ($rt['o_erdft_type'] == 'SPARQL_OPTIONAL_VAR') 
							&& (!in_array($rt['o'], $sparql_vars) 
							&&  $rt['s_erdft_type'] == 'IRI'  )  )
				{
					//blank
				}
				else $conditions[] = $condition; 
			}
		}
		 
			if(empty($conditions)) $this->errors[]='The query needs some non-optional clauses';
			$conditions = implode("\t\r\n",$conditions);
			$optionals = implode("\t\r\n",$optionals);
			$whereclause = $conditions.$optionals;
		
		return $whereclause;
	}

	function format_erdf()
	{
		$erdf &= $this->erdf;
		$erdf = preg_replace($this->REG_EXES['SPARQL_OPTIONAL'], '$1', $erdf);
		return $erdf;
	}
	

}


?>

/code/erdft/erdf_parser_0.2.phps

<?php
/**
 * 
 *
 * @author Keith Alexander
 * @version 0.2
 * @copyright GPL
 * @package eRDFT
 * class eRDFT : a class that uses ARC_erdf_parser to retrieve triples
 * from an eRDF template and convert them into  SPARQL queries, retrieve data from 
 * the ARC mysql-backed RDF triple store, and store it as an associative array which can then be used     
 * by the eRDF template to display the data.
 **/

require_once("arc/ARC_api.php");
require_once("arc/ARC_erdf_parser.php");
class eRDFT
{
	var $erdf,
		$arc_config_path,
		$api,
	    $triple_info = array(),
		$processed_triples = array(),
		$sparql_vars = array(),
		$sparqls = array(),
		$resource_indices = array(),
		$levels = array(),
		$resultsets = array(),
		$top_level_resultset = array(),
		$results = array(),
	    $errors = array(),
		$REG_EXES = array(
			'SPARQL_VAR' => 	'/(\$[a-zA-Z_]+)/',
			'IRI' => 			'/^([a-zA-Z]+:\/\/[^\W"\']+)/',
			'SPARQL_OPTIONAL' => '/(\$[a-zA-Z_]+?)_optional/',
		
			);
	
	function eRDFT($erdf, $regexes=array(), $arc_config_path=null, $auto=true)
	{
		$this->erdf = $erdf;
		$this->arc_config_path = ($arc_config_path)? $arc_config_path : dirname(__FILE__).'/arc/arc_config.php';
			/*Instantiate API */
		$api_args = array(
		  "inc_path"=> dirname(__FILE__)."/arc/",
		  "config_path"=> $this->arc_config_path,
		);
		$this->api = new ARC_api($api_args);
		$this->api->db_connect() or die("Couldn't connect to database");
		if(!$this->api->store_exists()) $this->api->create_store() or die("Couldn't create rdfstore - check user permissions");
		foreach($regexes as $k => $v)
		{
			$this->REG_EXES[$k] = $v;
		}
		
		if($auto)
		{
			$this->parse_erdf($erdf);
		
			$this->makeResultsets();
		
		 	$this->doQueries();
			
			$this->format_erdf();
		} //else the user can make changes to the triples before processing
		
	}
	
	function makeResultsets()
	{
		$sparql_vars = $this->sparql_vars;
		foreach($sparql_vars as $v)
		{ 
		$resultsets =& $this->resultsets;
		if(strpos($v, '__')) // __ is the path separator
			{
				$path_keys = array_slice(explode('__', substr($v,1)), 0, -1);
				$path = "['".implode("']['sub_results']['", $path_keys)."']";
				eval('$resultsets["sub_results"]'.$path."['sparql_vars'][] = '".$v."';");
				array_push($path_keys, '');
			$prefix = implode('__', $path_keys);
			eval('$resultsets["sub_results"]'.$path."['row_prefix'] = '{$prefix}';");
			}
			else
			{
				$this->top_level_resultset['sparql_vars'][] = $v;
			}
		}
	}
	
	// parses eRDF html and extracts triples
	function parse_erdf()
	{
		$erdf = $this->erdf;
		$parser_args=array("encoding"=>"auto");
		$parser=new ARC_erdf_parser($parser_args);
		$p_result=$parser->parse_data($this->erdf);
		
		//check if the eRDF parses
		if($p_result["result"] && !$p_result["error"])
		{
			
			//get triples
			$this->triple_info = $parser->get_triple_infos();
			//process triples for sparql syntax
			
			for($x=0; $x < count($this->triple_info['triples'] ); $x++) 
			{
				$t = $this->triple_info['triples'][$x];
				
				//clean s and o into sparql vars. stuff{$name} => $name
				foreach(array('s','o') as $k ) 
				{
					$this->_format_node($t[$k], $t);
				}
				$this->processed_triples[] = $t;
			}
		
		}
		else
		{
			if($p_result["error"]) $this->errors[]=$p_result['error'];
			return false;
		}
		
	}
	
	

	
	function get_triples_by_subject($s, &$qt)
	{
		$nqt = array();
		for ($i=0; $i < count($qt); $i++)
		{
			$t = $qt[$i];
			if($t['s'] == $s) 
			{
				$nqt[]=$t;
				unset($qt[$i]);
			}
		}
		return $nqt;
	}
	
	function doQueries()
	{
		//make prefix head
		$prefixes = '';
		 foreach($this->triple_info['prefixes'] as $k => $v) $prefixes.='PREFIX '.$k.': '.'<'.$v.'>'." \r\n";
		$conditions = array();
		$optionals = array();
		foreach($this->processed_triples as $rt) 
		{
			$condition = "{$rt['s']}  {$rt['p_qname']} {$rt['o']} ."; 
			if ( isset($rt['SPARQL_TRIPLE_TYPE']) && $rt['SPARQL_TRIPLE_TYPE'] == 'OPTIONAL') $optionals[] = "OPTIONAL( {$condition} )";
			else $conditions[] = $condition; 
		}
		
			$sparql = $prefixes;
			if(empty($conditions)) $this->errors[]='The query needs some non-optional clauses';
			$conditions = implode("\t\r\n",$conditions);
			$optionals = implode("\t\r\n",$optionals);
			$whereclause = $conditions.$optionals;
			//top level sparql
			
				$sparql.="\r\n SELECT DISTINCT ".implode(" ", array_unique($this->top_level_resultset['sparql_vars']))."\r\n WHERE { $whereclause } LIMIT 1";
			
			$this->top_level_resultset['sparql'] = $sparql;				
			$data = $this->get_data($sparql);
			if($data[0]) foreach($data[0] as $k => $v) $this->results[$k] = $v;
					
		//get nested loops recursively
		$this->nested_data($this->resultsets['sub_results'], $this->results, $prefixes, $whereclause);
	}
	
	function nested_data(&$resultset, &$dataset, $prefixes, $whereclause)
	{
		//the $k of resultset is pluralised in dataset by appending an 's'. Better to write 'mouses' than have to think about whether 'mice' will work.
		
			foreach($resultset as $k => $v)
			{
				//build the sparql query string
				$sparql = $prefixes;
				$sparql_vars = array_unique($v['sparql_vars']);
				$sparql.="\r\n SELECT ".implode(" ",$sparql_vars)."\r\n WHERE { $whereclause } LIMIT 3";
		
			
				$sparql = str_replace($v['row_prefix'],'', $sparql ); //get rid of this particular row prefix
				//eg: cd__artist becomes artist, but artist__name stays artist__name in this query
				
				$resultset[$k]['sparql'] = $sparql;
			//get and save results
				$dataset[$k.'s'] = $this->get_data($sparql, 'rows');
				if(isset($resultset[$k]['sub_results']) && !empty($dataset[$k.'s']))
					{
						//now go through each row of the current result set, making a query for any sub result sets
										$row_number = 0;
										foreach($dataset[$k.'s'] as $row)
										{
										
											foreach($row as $result_head => $result_value)
											{
												//now we replace the variable with the values we already retrieved for the sub query
												$non_var = $this->_format_node($result_value, $nothing_happens_with_this_variable);
												foreach($resultset[$k]['sub_results'] as $k2 => $v2)
												{
													 $whereclause = str_replace('$'.$v2['row_prefix'].$result_head, $non_var, $whereclause);
												}
												 $this->nested_data($resultset[$k]['sub_results'], $dataset[$k.'s'][$row_number], $prefixes, $whereclause);
												
											}
											$row_number++;
											
										}
									}
									
			}
	}
	
	// queries the rdf-store with the sparql query and gets back the data
	function get_data($sparql, $resultype='rows')
	{
		$this->sparqls[] = $sparql;
		$query_args=array(
					  "result_type"=>$resultype, // (rows|json|xml|single|rows_n_count|row_count|sql)
					  "query"=>$sparql
					);
					$qr=$this->api->query($query_args) or die("Couldn't query datastore");
					if (!empty($qr['error'])) $this->errors[] = $qr['error'];
					if (empty($qr['result'])) $this->errors[] = 'Query returned no data.';
					//return $qr['result'];
					return $qr['result'];
	}
	

	
	function get_eRDF()
	{
		return $this->erdf;
	}
	
	function get_results()
	{
		return	$this->results;
	}
	
	function get_sparqls()
	{
		return $this->sparqls;
	}
	
	function index_resources()
	{
		$tri = $this->processed_triples;
		if(empty($tri)) $this->errors[] = 'No Triples were processed!';
		$r = array();
		foreach($tri as $t)
		{
			$r[$t['s']]['props'][] = $t;
			$r[$t['o']]['inverse_props'][] = $t;
			$r[$t['s']]['all_props'][] = $t;
			$r[$t['o']]['all_props'][] = $t;
			//array_unique($r['subjects'][$t['s']]['props']);
		}
		$this->resource_indices = $r;
	}
	
	function _format_node(&$node, &$t)
	{
			if(preg_match($this->REG_EXES['SPARQL_VAR'], $node, $m))
			{
				if(	preg_match($this->REG_EXES['SPARQL_OPTIONAL'],$m[1],$sub_m))
				 {
					$node = str_replace('.','__',$sub_m[1]);
					$this->sparql_vars[]=$node;
					$t['SPARQL_TRIPLE_TYPE'] = 'OPTIONAL';
				 }
				else
				{

					$node = str_replace('.','__',$m[1]);					
					$this->sparql_vars[]=$m[1];
				}
				$t[$k.'_erdft_type'] = 'SPARQL_VAR';
				
			}
			elseif($node == '') //if a node is empty, give it a var
			{
				$node = '?ERDFT';
				$t[$k.'_erdft_type'] = 'SPARQL_VAR';
				$this->errors[]='The query is not accurate - you need to add an id to your top level element' ;	
			}
			elseif( preg_match($this->REG_EXES['IRI'], $node) ) //IRI syntax
			{
				$node = 	'<' . $node.'>';
				$t[$k.'_erdft_type'] = 'IRI'; 
				
			}
			else // quote literals
			{
				$node = '"'.$node.'"';
				$t[$k.'_erdft_type'] = 'LITERAL'; 
			}
			return $node;
	}

	function format_erdf()
	{
		$erdf &= $this->erdf;
		$erdf = preg_replace($this->REG_EXES['SPARQL_OPTIONAL'], '$1', $erdf);
	}
	

}


?>

/code/erdft/arc_config.phps

<?php
function arc_get_api_config(){
$config = array(
  /* db */
  "db_host"=>"localhost",
  "db_name"=>"YourDBname",
  "db_user"=>"Username",
  "db_pwd"=>"password",

  /* store prefix */
  "prefix"=>"arc",

  /* store */
  "store_type"=>"basic+",            // (basic|basic+|split)
  "id_type"=>"hash_int",             // (hash_int|hash_md5|hash_sha1|incr_int)
  "reversible_consolidation"=>false, // adds additional columns
  "index_type"=>"advanced",          // (basic|advanced)
  "index_graph_iris"=>true,          // add graph columns to indexes
  "index_words"=>true,              // creates FULLTEXT index on values
  "charset"=>"utf8"                  // for MySQL, if supported
);

return $config;
}

?>

/code/erdft/eRdfResource.phps

<?php
require_once 'smartyresource.php';

class eRdfResource extends SmartyResource
{

	
	function eRdfResource(&$tonic, $url, $metadata = array(), $body = NULL, $exists = FALSE)
	{	
		parent::smartyResource(&$tonic, $url, $metadata, $body, $exists);	
	}
	
	function getOwlSameAs()
	{
		//needs some kind of permission checker
		if(array_key_exists('owl-sameAs', $_GET))
			 return 'http://'.$_SERVER['SERVER_NAME'].$this->_tonic->baseUrl.$_GET['owl-sameAs'];
		else return false;
	}
    function get($requestData = NULL, $requestDataType = NULL)
      {
    		require("erdft_parser.php");
			
    		$stringTemplates = new stringTemplates();
    		$this->_smarty->register_resource('string', array(&$stringTemplates,
    												'getTemplate',
    												'getTimestamp',
    												'getSecure',
    												'getTrusted'));
    												
			$resource =& Resource::find($this->_tonic, $this->getUrl());
			$this->_smarty->assign_by_ref('this', $this);
			$this->_smarty->assign_by_ref('resource', $this); // deprecated	
    		$erdf = $resource->getBody();
			$template = $this->getMetadata('template');
            if ($template) {
                $erdf = $this->_smarty->fetch($template, $this->_url, $this->_url);
            } else {
                $erdf = $this->_smarty->fetch('tonic:_body', $this->_url, $this->_url);
            }
    		$eRdfT = new eRDFT($erdf);	//this is the regex for sparql_vars
    		$data = $eRdfT->get_results();
    		//set Smarty variables
			$this->_smarty->assign('errors', $eRdfT->errors);
			$this->_smarty->assign('data', $data);
    		foreach($data as $k => $v) $this->_smarty->assign($k,$v);
    		$stringTemplates->template('erdft', $erdf);
    		$this->_smarty->display("string:erdft");
      }

    function post($requestData = NULL, $requestDataType = NULL)
	{
		parse_str(urldecode($requestData), $post); //makes $post the same as $_POST before tonic flattened it
		
		
		if($post['rdf:RDF'])
		{
			
				$iri = 'http://'.$_SERVER['SERVER_NAME'].$this->getFullUrl();
				$redir = $this->getMetadata('redirect_url');
				$redirect_url = ($redir)? $redir : $this->getUrl();
				
				$form_url = ($this->getMetadata('form_url'))? $this->getMetadata('form_url'): $this->_tonic->basePath.$this->getUrl();
			//process POST by fetching the html form, getting the allowed input names, and passing them through functions named in the class parameters
			
			require 'FormProcessor.class.php';
			$formProcessor = new FormProcessor($post, $iri, $redirect_url);
			
			$processed_POST = $this->_process_POST($form_url, &$post, &$formProcessor);
			//convert data to rdf
			$rdf = $this->_array2rdf(array('rdf:RDF' => $post['rdf:RDF']));
			//save the data
			if(empty($formProcessor->errors))
			{
				require 'ArcAdapter.php';	
				$store = new ArcAdapter('api/api_config.php');
				if ($store->insert($formProcessor->iri, $rdf)	) 
				{
	               $this->get();
				}
				else
				{
					die("couldn't save ".htmlentities( $rdf));
				}
			}
			else
			{
				var_dump($formProcessor->errors);
				$this->_smarty->assign('errors', $formProcessor->errors);
			}
			
		}
		return get();
	}
	
	function _array2rdf($in)
	{
		$rdf='';
		if(is_array($in))
		{
			foreach($in as $k => $v)
			{
				if(is_string($v))
				{
					if(substr($v,0,7)=='http://')
					{
						$rdf.= '<'.$k.' rdf:resource="'. $v.'"/>';
					}
					else
					{
						$rdf.= '<'.$k.'>'. $v .'</'.$k.'>';
					}
				}
				else //$v is an array
				{
					$atts = array();
					foreach(array_keys($v) as $ak)
					{
						if((strpos($ak,'xmlns') === 0 || strtolower($ak)== 'rdf:about') )
						{
							$atts[] = $ak.'="'.$v[$ak].'"';
							unset($v[$ak]);
						}
					}
					$space = (empty($atts))? '':' ';
					
					if(strtolower($k) == 'rdf:li')
					{
						foreach($v as $li)
						{
							$vx =  $this->_array2rdf($li);
							$rdf.= '<'.$k.$space.implode(" \r\n",$atts).'>'. $vx .'</'.$k.'>';
						}
					}
					else
					{	
						$vx =  $this->_array2rdf($v);
						$rdf.= '<'.$k.$space.implode(" \r\n",$atts).'>'. $vx .'</'.$k.'>';
					}
				}
			}
			return $rdf;
		}
		else
		{
			return($in);
		}
	}
	
	function _escape_array($arr = array())
	{
	$rs = array();
	while(list($key,$val) = each($arr)) {
	    if(is_array($val))
	        { $rs[$key] = $this->_escape_array($val); }
	    else
	        { $rs[$key] = htmlspecialchars(utf8_encode($val)); }
	    }
	    return $rs;
	}
	
	function _process_POST($url, $post, &$formProcessor)
	{
		$simple = file_get_contents($url);
		if(!$simple) $formProcessor->errors[]='Couldn\'t retrieve form page to parse.';
		$p = xml_parser_create();
		xml_parse_into_struct($p, $simple, $vals, $index);
		xml_parser_free($p);
		$previous_row_num = -2; //to get the previous row num
		foreach($vals as $r)
		{
			$previous_row_num++;
			if(isset($r['attributes']['NAME'])) //it's (probably) a form element
			{
				parse_str($r['attributes']['NAME'], $out);
				$template_post_array = array_merge_recursive($template_post_array, $out);
				preg_match_all('/([^\[\]]+)/', $r['attributes']['NAME'], $matches);
				
				//this builds up a path to the assoc array element as a string - eg: 'rdf:Rdf[foaf:name]'
					$path = '';
					for($x = 0; $x < count($matches[1]); $x++)
					{
						$curr_key = $matches[1][$x];
						$path.='["'.$curr_key.'"]';
					}
					
				if(isset($r['attributes']['CLASS'])) //now set the classnames string as the value of the name associative array
				{
					preg_match_all('/f_([a-zA-Z_0-9&]+)/', $r['attributes']['CLASS'], $m);
					$functions = $m[1];
					//get user value to be passed through functions
					eval('$user_value =  $post'.$path.';');
					
					if(!empty($functions))
					{
						foreach($functions as $f)
						{
							//presumably calls the functions in the order they appear in the class string
							$identifier = $vals[$previous_row_num]['value'];
							$user_value = call_user_func(array(&$formProcessor, $f), $user_value, $identifier);
						}
						eval('$post'.$path.' = "'.$user_value.'";');	
					}
										
				}
			}
		}
		return $post;
	}
	
}

class stringTemplates {
	var $templates = array();
	 function getTemplate ($tplName, &$tplSource, &$smarty)
	{
		if(array_key_exists($tplName, $this->templates)) {
			$tplSource = $this->templates[$tplName];
			return TRUE;
		}
		return FALSE;
	}

	function getTimestamp($tplName, &$tplTimestamp, &$smarty)
	{
		if(array_key_exists($tplName, $this->templates)) {
			$tplTimestamp = time();
			return TRUE;
		}
		return FALSE;
	}

	function getSecure($tpl_name, &$smarty)
	{
		return TRUE;
	}

	function getTrusted($tpl_name, &$smarty)
	{
	}

	function template($tplName, $tpl)
	{
		if(empty($tplName)) {
			return FALSE;
		}
		$this->templates[$tplName] = $tpl;
	}
}

?>

/code/erdft/FormProcessor.class.phps

<?php

class FormProcessor
{
	var $errors = array();
	var $messages = array();
	var $iri = '';
	var $redirect_location = '';
	var $post = array();
	
	function FormProcessor(&$post, $iri = '', $redirect_location = '')
	{
		$this->post = $post;
		$this->iri = $iri; //now the developer can change the iri of the rdf with the class methods
		$this->redirect_location = $redirect_location; //and the redirect location once the form has been processed
		
	}
	
	function not_empty($val='', $parent_text)
	{
		
		if(strlen($val) < 1 )
		{
			$this->errors[] = $parent_text.' is empty.';
			return false;
		}
		else
		{
			return $val;
		}
	}
	
	function set_iri($val='', $parent_text)
	{
		$this->iri = $val;
	}
}
?>