<?
#
# Sparqlette 0.4 - A SPARQL demo query service
#
# (c) 2003-2005 Morten Frederiksen
# License: http://www.gnu.org/licenses/gpl
#
# Background, documentation, and changelog:
# http://www.wasab.dk/morten/blog/archives/2005/05/02/the-gargonza-experiment
#

#include_once('dbSwitcher.php');
#$dbs=new dbSwitcher();
#define('REDLANDURI','mysql://mysql/'.$dbs->get('photo', 'online').'/photos');
define('REDLANDURI','mysql://mysql/online/sparqlette');
include_once(
'service.php');

# Accept 'default-graph-uri' as alias for 'data'.
if (array_key_exists('default-graph-uri',$_REQUEST)
        && !
array_key_exists('data',$_REQUEST))
    
$_REQUEST['data']=$_REQUEST['default-graph-uri'];

# Initialization.
$base='http://www.wasab.dk/morten/2005/04/sparqlette/';
$service=new Service(array(
        
'uri'=>$base,
#        'xslt'=>'morten-service.xsl',
        
'defaults'=>array(''=>array(
            
'format'=>'xml',
            
'output-type'=>'text/html; charset=utf-8',
            
'query-lang'=>'sparql'))));
$formats=array(
        
'rdfxml'=>'application/rdf+xml; charset=utf-8',
        
'xml'=>'application/xml; charset=utf-8',
        
'turtle'=>'application/x-turtle',
        
'ntriples'=>'text/plain; charset=utf-8');

# Parse and run query?
if ($service->match('',array('query'))
        && (!
array_key_exists('execute',$_REQUEST) || 'no'!=$_REQUEST['execute'])) {
    
# Get query options.
    
$query=$service->input('','query');
    
$querylang=$service->input('','query-lang');
    
$data=$service->input('','data');
    
$format=$service->input('','format');
    
$outputxslt=$service->input('','output-xslt');
    
$outputtype=$service->input('','output-type');
    
# Check remote XSLT...
    
if (!preg_match('|^http://|',$outputxslt))
        
$outputxslt='';
    
# Construct XML comment with query and options.
    
$comment="<!--";
    foreach (
$service->inputs() as $input)
        
$comment.="\n".str_replace('--','- -',$input.': '.str_replace("\n","\n  ",$service->input('',$input)));
    
$comment.="\n-->\n";
    
# Construct array of XSLT parameters.
    
$xsltparms=array(
            
'_now'=>date('Y-m-d\TH:i:s').(date('Z')>0?'+':'').sprintf('%02d',date('Z')/3600).':00',
            
'_id'=>md5($query),
            
'_uri'=>'http://'.$_SERVER['SERVER_NAME'].
                    (
$_SERVER['SERVER_PORT']!=80?$_SERVER['SERVER_PORT']:'').
                    
$_SERVER['REQUEST_URI']);
    while (list(
$name,$value)=each($_REQUEST))
        
$xsltparms['sparql-'.$name]=$value;
    
# Create Redland objects and process request.
    
$nulluri=librdf_new_uri($World, '-');
    if (
'xml1'==$format) {
        
$format='xml';
        
$dawgxmluri=librdf_new_uri($World, 'http://www.w3.org/TR/2004/WD-rdf-sparql-XMLres-20041221');
    } else
        
$dawgxmluri=librdf_new_uri($World, 'http://www.w3.org/2005/sparql-results#');
    
$results='';
    
$xslt_error_message='';
    
$Storage=0;
    
$Model=0;
    
$Query=0;
    
$CBDStorage=0;
    
$CBDModel=0;
    if (
$data && !($Storage=librdf_new_storage($World,
            
'hashes','temp',"hash-type='memory',contexts='yes'")))
        
$service->error('500 Internal Server Error [Unable to create temporary storage for model'.redland_error().']');
    elseif (!
$data && !($Storage=librdf_new_storage($World,
            
$redland_config['redland_storage_type'],
            
$redland_config['redland_model_name'],
            
$redland_config['redland_storage_options'])))
        
$service->error('500 Internal Server Error [Unable to create storage for model'.redland_error().']');
    elseif (!(
$Model=librdf_new_model($World, $Storage, '')))
        
$service->error('500 Internal Server Error [Unable to create model'.redland_error().']');
    elseif (
$data && load_content($data,$Model))
        
$service->error('500 Internal Server Error [Unable to load content'.redland_error().'');
    elseif (!(
$Query=librdf_new_query($World, $querylang, $nulluri, $query, $nulluri)))
        
$service->error('500 Internal Server Error [Unable to create query'.redland_error().']');
    elseif (!(
$Results=librdf_query_execute($Query, $Model))
            ||
librdf_query_results_is_boolean($Results)
            &&
librdf_query_results_is_graph($Results)
            &&
librdf_query_results_is_bindings($Results))
        
$service->error('500 Internal Server Error [Unable to execute query'.redland_error().']');
    elseif ((
$cbd=(librdf_query_results_is_bindings($Results)
            &&
'xml'!=$format
            
&& 1==librdf_query_results_get_bindings_count($Results)
            &&
'cbd'==librdf_query_results_get_binding_name($Results, 0)))
            && !(
$CBDStorage=librdf_new_storage($World,
            
'hashes','cbd',"hash-type='memory',contexts='yes'")))
        
$service->error('500 Internal Server Error [Unable to create temporary storage for CBD model'.redland_error().']');
    elseif (
$cbd
            
&& !($CBDModel=librdf_new_model($World, $CBDStorage, '')))
        
$service->error('500 Internal Server Error [Unable to create CBD model'.redland_error().']');
    elseif (
$cbd
            
&& !librdfutil_mysql_query_results_to_model_with_cbd($Results,$CBDModel))
        
$service->error('500 Internal Server Error [Unable to populate CBD model from query results'.redland_error().']');
    elseif (
$cbd
            
&& !($result=librdfutil_model_to_string($CBDModel,'rdfxml'==$format?'r3x':$format)))
        
$service->error('500 Internal Server Error [Unable to serialize CBD model from query results'.redland_error().']');
    elseif (
librdf_query_results_is_graph($Results)
            && (
$format=('xml'==$format?'rdfxml':$format))
            && !(
$result=librdfutil_stream_to_string(librdf_query_results_as_stream($Results),'rdfxml'==$format?'r3x':$format)))
        
$service->error('500 Internal Server Error [Unable to serialise query results from graph'.redland_error().']');
    elseif (
$cbd
            
|| librdf_query_results_is_graph($Results)) {
        
header('Content-Type: '.$formats[$format]);
        print
$result;
        if (
'rdfxml'==$format)
            print
$comment;
        
$service->free();
    } elseif ((
librdf_query_results_is_bindings($Results)
            ||
librdf_query_results_is_boolean($Results))
            && !(
$result=librdfutil_query_results_to_string($Results,$dawgxmluri,$nulluri,preg_match('|select\s+distinct|i',$query))))
        
$service->error('500 Internal Server Error [Unable to serialise query results from bindings'.redland_error().']');
    elseif ((
librdf_query_results_is_bindings($Results)
            ||
librdf_query_results_is_boolean($Results))
            &&
$outputxslt
            
&& (!($xslt=xslt_create())
            ||
xslt_set_error_handler($xslt, 'xslt_error_handler')
            || !(
$result=xslt_process($xslt, 'arg:/_xml', 'arg:/_xsl', NULL,
                array(
'/_xml'=>$result,'/_xsl'=>@join('',@file($outputxslt))),
                
$xsltparms))
            ||
$xslt_error_message
            
|| xslt_free($xslt)))
        
$service->error('500 Internal Server Error [Unable to transform query results with XSLT ('.$xslt_error_message.').]');
    elseif ((
librdf_query_results_is_bindings($Results)
            ||
librdf_query_results_is_boolean($Results))
            &&
$outputxslt) {
        
header('Content-Type: '.$outputtype);
        print
$result;
        
$service->free();
    } elseif ((
librdf_query_results_is_bindings($Results)
            ||
librdf_query_results_is_boolean($Results))) {
        
header('Content-Type: application/xml; charset=utf-8');
        print
$result.$comment;
        
$service->free();
    } else {
        
$Node=librdfutil_new_node($World);
        
$service->add($Node, 'content:encoded', '<pre class="results">'.htmlspecialchars($result).'</pre>');
        
$service->result($Node);
        
librdf_free_node($Node);
    }
    
librdf_free_uri($nulluri);
    
librdf_free_uri($dawgxmluri);
    if (
$Query)
        
librdf_free_query($Query);
    if (
$Model)
        
librdf_free_model($Model);
    if (
$Storage)
        
librdf_free_storage($Storage);
    if (
$CBDModel)
        
librdf_free_model($CBDModel);
    if (
$CBDStorage)
        
librdf_free_storage($CBDStorage);
}

# Finish.
$service->finish();

# Retrieve, parse and load content URIs into model.
function load_content($contenturis,$Model) {
    global
$World, $nulluri;
    
$uris=preg_split('/\s+/',$contenturis);
    foreach (
$uris as $uri) {
        
$uri=librdf_new_uri($World,$uri);
        if (
librdf_model_load($Model,$uri,'','',$nulluri))
            return
1;
        
librdf_free_uri($uri);
    }
    return
0;
}

# Handle XSLT errors.
function xslt_error_handler($x,$e,$l,$f) {
    global
$xslt_error_message;
    
$xslt_error_message='Sablotron XSLT transformation error';
    
reset($f);
    while(list(
$key,$val)=each($f)) {
        if (
$key=='line')
            
$xslt_error_message.=' on line '.$val;
        if (
$key=='msg')
            
$xslt_error_message.=': <strong>'.$val.'</strong>';
    }
}

function
redland_error() {
    global
$World;
    
$nulluri=librdf_new_uri($World,'-');
    
$log=librdf_world_get_feature($World,$nulluri);
    
librdf_free_uri($nulluri);
    if (
$log)
        return
': <strong>'.librdf_log_message_message($log).'</strong>';
    else
        return
'.';
}

?>