// autoload
function__autoload($Class){if(is_dir($dir=dirname(dirname(__FILE__))."/modules/$Class/"))returnrequire_once$dir.$Class.'.php';elserequire_oncedirname(__FILE__)."/".$Class.'.php';}classDiple{/** Constant used to make function call more readable */constFORCE=true;/** Constant used to make function call more readable */constMULTIBOOK=true;/** Requested path */
static $request;/** Absolute filePath of Diple */
static $dipleDir;/** Relative Uri to Diple */
static $dipleHref;/** Corpus code */
static $corpusId;/** Absolute filePath of corpus */
static $corpusDir;/** Relative Uri to the corpus */
static $corpusHref;/** if a book is requested, set the code */
static $bookId;/** A directory where to find generated files */
static $htmlDir;/** A directory where to find doc files */
static $docDir;/** A directory where to find source xml Files */
static $xmlDir;/** An xml File to transform */
static $xmlFile;/** An xsl transfomation for direct html */
static $xslHtml;/** An xsl transfomation for direct html */
static $xslSplit;
static functiontheme($Class=null,$href=null){if(!$Class)$Class='neutre';$dir=mb_strtolower($Class,"utf-8");$Class=mb_strtoupper(mb_substr($dir,0,1,"UTF-8"),"UTF-8").mb_substr($dir,1,10000,"UTF-8");require_once(self::$dipleDir."theme/".$dir.'/'.$Class.'.php');// pas génial
if(!$href)$href=Diple::$dipleHref."theme/";returnnew$Class($href);}
static functiondoc($path=null,$nosplit=false){$docs=self::docs($path,$nosplit);return$docs[0];}
static functiondocs($path=null,$nosplit=false){if($path===null)$path=self::$request;// direct service of a file, especially images
// is it too much intelligent ?
// if ( is_file($file=self::$htmlDir.$path)) Web::get($file);
// if ( is_file($file=preg_replace('@/html/@', '/', $file))) Web::get($file);
// yes it is, let index.php manage that
$docs=array();// array of docs
@list($book,$item)=explode("/",$path);// if nothing requested, welcome page
if($book===""){$doc=newHtmlInc(self::$htmlDir."index.html");if($doc->error)$doc=newHtmlInc(self::$htmlDir."welcome.html");if($doc->error)$doc=newHtmlInc(self::$docDir."index.html");// if found, return, if not, let do the split
if(!$doc->error)returnarray($doc);}else{// needed !
if(file_exists(self::$xmlDir.$book.'.xml'))self::$bookId=$book;}// Pour la doc etc ?
if(($book=="src"||$book=="doc")&&$html=self::htmlFile($path))returnarray(newHtmlInc($html));if($nosplit);else{// try to generate book or corpus tests are done in the split method
self::split(self::$xmlDir."$book.xml",true);self::split(self::$xmlDir.self::$corpusId.".xml");}// priority to folder
if(is_dir($dir=self::$htmlDir.$book."/")){if($item===""){$docs[]=newHtmlInc($dir."index.html");return$docs;}$idList=explode(",",$item);// allow multiple items displayed with uris like book/id1,id2,id3
foreach($idListas$id){$id=trim($id);if($id==="")continue;// works if id=0
$doc=newHtmlInc($dir.$book."_".$id.".html");if($doc->error)$doc=newHtmlInc($dir.$id.".html");// if no error append the doc to the list
if(!$doc->error)$docs[]=$doc;}// if no item found, send message
if(!count($docs)){$docs[0]=newHtmlInc(null);$docs[0]->error="L'item <b>$item</b> semble introuvable dans : <i>$book</i>.";}return$docs;}$idList=explode(",",$book);// allow multiple items displayed with uris like id1,id2,id3
foreach($idListas$id){$id=trim($id);if($id==="")continue;// works if id=0
$doc=newHtmlInc(self::$htmlDir.self::$corpusId."_$id.html");if($doc->error)$doc=newHtmlInc(self::$htmlDir."$id.html");// if no error append the doc to the list
if(!$doc->error)$docs[]=$doc;}if(count($docs))return$docs;// no item found, maybe in doc ?
$doc=newHtmlInc(self::$docDir."$book.html");if(!$doc->error){$docs[]=$doc;return$docs;}// On demande le schéma
if($book=="schema")$doc=newHtmlInc(self::schema());// try an html file ?
$htmlFile=self::htmlFile(null,null,self::$corpusDir);if($htmlFile)$doc=newHtmlInc($htmlFile);if($doc->error)$doc->error="Le document <b>$path</b> semble introuvable.";$docs[]=$doc;return$docs;}
static functionsplit($xmlFile,$multibook=null,$force=null){// regenerate on force reload maybe dangerous on public site
// if ($force === null) $force=Web::noCache();
if(!file_exists($xmlFile))returnfalse;// Inform object user that we fond a source file
self::$xmlFile=$xmlFile;// dest html file
$xmlBasename=basename($xmlFile,".xml");$destFile=self::$htmlDir.$xmlBasename.".html";// dest html dir
if($multibook===false)$destDir=self::$htmlDir;elseif(self::$corpusId==$xmlBasename)$destDir=self::$htmlDir;// multibook
else{$destDir=self::$htmlDir.$xmlBasename."/";$multibook=true;}// dest file newer than xmlFile, go away
if(!$force&&is_file($destFile)&&filemtime($destFile)>filemtime($xmlFile))return$destDir;self::$xmlFile=$xmlFile;// A file matched, inform object user
// split transformation, remplacer les antislashs pour win
// split local
if(file_exists($xsl=self::$corpusDir."transform/".self::$corpusId."_split.xsl"));// vue html locale, surtout garder cet ordre dans les imports
elseif(file_exists($f=self::$corpusDir."transform/".self::$corpusId."_html.xsl")){$xsl='<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="'.strtr($f,array('\\'=>"/")).'"/>
<xsl:import href="'.strtr(self::$dipleDir,array('\\'=>"/")).'transform/tei_split.xsl"/>
</xsl:transform>';// a default split transformation
}// split par défaut
else{$xsl='<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="'.strtr(self::$dipleDir,array('\\'=>"/")).'transform/tei_html.xsl"/>
<xsl:import href="'.strtr(self::$dipleDir,array('\\'=>"/")).'transform/tei_split.xsl"/>
</xsl:transform>';// a default split transformation
}if(!is_writable($destDir)){mkdir($destDir,0775,true);@chmod($destDir,0775);// laisser @, si www-data a le droit d'écrire mais n'est pas propriétaire
// File::clean($destDir); // do not strip all files in folder, some may have been set before
}// local theme
if($multibook)$theme="../theme/";else$theme="theme/";// Generate HTML files for the book, cache on timestamp, dir param should be absolute for split file projection
Transform::xsl($xmlFile,// xml file
$xsl,$destFile,// dest file
array('dir'=> $destDir,'corpusId'=>self::$corpusId,'bookId'=>self::$bookId,'theme'=>$theme),null,$force);// A split transform have been done copy some static resources for an HTML site
if(Transform::$done){// if destDir is tmp, give an alert to the developper
if(strpos($destDir,sys_get_temp_dir())===0)echo'<p class="error">Régénération, impossible d’écrire dans <tt>html</tt> ou <tt>var</tt>, pages écrites dans le dossier temporaire : ',$destDir,'</p>';// make generated files writable by group (verify if it creates problems on OVH)
File::scan($destDir,null,null,"chmod",null,array(0664));// one page transform, cant't be done by the split transform, because of link resolution context
$xsl=self::$corpusDir."transform/".self::$corpusId."_html.xsl";if(!file_exists($xsl))$xsl=self::$dipleDir."transform/tei_html.xsl";Transform::xsl($xmlFile,// xml file
$xsl,$destFile,// dest file
array('dir'=> $destDir,'bookId'=>$xmlBasename,'corpusId'=>self::$corpusId,'theme'=>'theme/'),null,true);File::cp(self::$dipleDir."theme/neutre",self::$htmlDir."theme");File::cp(self::$dipleDir."js/Tree.js",self::$htmlDir."theme/");File::cp(self::$corpusDir."theme",self::$htmlDir."theme");}return$destDir;}
static functionrewrite($html,$base=""){// rewrite static links of included files according to uri policy here
$reLinks=array(// '@href="(?<=http://|https://)@' => 'href="'.self::$corpusHref, // trop dangereux
'@href="../php/Diple.phps/@' => 'href="'.self::$corpusHref.$base,// liens relatifs déclarés
'/href="('.self::$bookId.'|'.self::$corpusId.')_([^"?#]+)\.html/' => 'href="$2','/href="([A-Za-z0-9\-_]+)\.html/' => 'href="$1','/ id="(nav|article)"/'=>' id="${1}2"',// avoid html id collisions
'@src="@' => 'src="code>,);returnpreg_replace(array_keys($reLinks),array_values($reLinks),$html);}
static functionschema($srcDir=false){if(!$srcDir)$srcDir=self::$xmlDir;$destDir=$srcDir;if(!is_writable($destDir))$destDir=self::$htmlDir;// files to generate
$schemaRng=$destDir."schema.rng";$schemaHtml=$destDir."schema.html";// a way to get the first rng file of a folder
foreach(glob($srcDir."*.rng")as$xml){// exclude the dest schema with links resolved
if($xml==$schemaRng)continue;// Schema, resolve inclusion for doc generation
Transform::xsl($xml,self::$dipleDir.'modules/xrem/rng_inc.xsl',$schemaRng,array("inclien"=>"1"));// test here the timestamps, if transform not done, go out
if(!Transform::$done)return$schemaHtml;// alert, on rights
if(!is_writable(self::$xmlDir)){echo'<p class="error">Schéma, les droits ne permettent pas de générer la documentation dans le dossier des sources.</p>';}// html generation
Transform::xsl($schemaRng,self::$dipleDir.'modules/xrem/rng_html.xsl',$schemaHtml,array("css"=>"../../diple/modules/xrem/xrem.css"),null,true);// generate a one file schema with no deps, for download, force transform
Transform::xsl($xml,self::$dipleDir.'modules/xrem/rng_inc.xsl',$schemaRng,null,null,true);break;}return$schemaHtml;}
static functionariane($doc,$welcomeFile="index.html,index_fr.html,welcome.html,couverture.html"){$html="";$count=0;if(!is_array($doc));elseif($count=count($doc)<1)return$html;// tableau vide, sortir
else$doc=$doc[0];$props=$doc->props();// si isPartOf, alors le premier contient le titre de corpus, le retirer de la pile
if(isset($props['isPartOf'])){$meta=array_shift($props['isPartOf']);// parfois, le titre de corpus est introuvable
if(isset($meta['string'])){$html=' <a href="'.$meta['uri'].'">'.$meta['string'].'</a> »';}}if(isset($_REQUEST['q']))return$html." » Recherche";// page de résultat philologic
if(strpos(",".$welcomeFile.",",",".basename($doc->uri).",")!==false)return$html;// accueil du corpus, ne rien ajouter
if($count>1)return$html." » Accueil";// plusieurs doc, résultat d'index
// accueil du corpus ?
// possible ?
if(isset($props['isPartOf'])){foreach($props['isPartOf']as$meta){$html .= ' <a href="'.$meta['uri'].'">'.$meta['string'].'</a> » ';}}$html .= ' <a href="">'.$doc->label().'</a>';return$html;}
static functionredirect(){$basepath=dirname(realpath($_SERVER['SCRIPT_FILENAME'])).'/'.Diple::$request;// candidate file
$index_php=basename($_SERVER['SCRIPT_FILENAME']);$request_uri=$_SERVER['REQUEST_URI'];// the path file exist, redirect to it without index.php/
if(is_file($basepath)){if(($pos=strpos($request_uri,$index_php.'/'))!==false)$location=substr($request_uri,0,$pos);else$location=$request_uri;header("Location: $location");echo'<a href="'.$location.'">Redirection vers '.$location.'</a>';exit;}// redirection à l'accueil vers …/index.php/
if(Diple::$request==""&&strpos($request_uri,$index_php.'/')===false){$location=dirname($_SERVER['REQUEST_URI']."o")."/".basename($_SERVER['SCRIPT_FILENAME'])."/";header("Location: $location");echo'<a href="'.$location.'">redirection vers '.$location.'</a>';exit;}Diple::$dipleHref="../../diple/";}
protected static $ob_file;
static functionob_file_callback($buffer){fwrite(Diple::$ob_file,$buffer);}
static functionphpHtml($pathinfo=null){if($pathinfo===null)$pathinfo=self::$request;$srcPath=self::$xmlDir.$pathinfo;// php File to execute ?
if(realpath($file=$srcPath.".php"));elseif(realpath($file=$srcPath."/index.php"));else{echo'<!-- Diple::phpHtml not found for :',$srcPath," -->\n";returnfalse;}// no infinite loop
if($file==__FILE__)returnnull;elseif($file==realpath($_SERVER['SCRIPT_FILENAME']))returnnull;$class=basename($file,".php");// convention un peu locale, index.php comporte une classe du nom de son dossier
if($class=="index")$class=basename(dirname($file));// include may change global vars but not constants
define('CLASS_TMP',$class);ob_start();require_once$file;$html=ob_get_contents();ob_end_clean();$class=CLASS_TMP;// DO NOT TRY AUTOLOAD
if(class_exists($class,false))define('CLASS_INC',$class);return$html;}
static functionhtmlFile($pathinfo=null,$force=null,$srcDir=null,$destDir=null){// default values
if($pathinfo===null)$pathinfo=self::$request;if($srcDir===null)$srcDir=self::$xmlDir;if($destDir===null)$destDir=self::$htmlDir;// if ($force === null) $force=Web::noCache(); // too dangerous in work
// a path to test source file presence, strip trailing slash in case of folder
$srcPath=rtrim($srcDir.$pathinfo,'/');// extension, take note of $a=explode(), workaround to a warning
$ext=explode(".",$srcPath);$ext=end($ext);// If source file exists, returns its path
if(is_file($srcPath))return$srcPath;// a dest file may be created, generate parent dir of dest files
$destFile=$destDir.$pathinfo.".html";// if RNG, transform
if(file_exists($file=$srcPath.".rng")){returnTransform::xsl($file,// src file
dirname(dirname(__FILE__)).'/modules/xrem/rng_html.xsl',// transformation
$destFile,// dest file
null,// params
null,//deps
$force// no-cache ?
);}if(($ext=="phps")&&file_exists($file=substr($srcPath,0,-1)))$phpdoc="php";elseif(file_exists($file=$srcPath.".css"))$phpdoc="css";elseif(file_exists($file=$srcPath.".js"))$phpdoc="js";else$phpdoc=null;if($phpdoc){if(!file_exists($destFile)||filemtime($destFile)<filemtime($file)||$force)PhpDoc::html($file,$destFile,$phpdoc);return$destFile;}// if (file_exists($file=$srcPath.".php")) return PhpDoc::html($file, $srcPath.$ext, $force); // NO, because php may produce HTML
// if XSL, transform
if(file_exists($file=$srcPath.".xsl")){// return the dest file in case of md5 tmpcache
returnTransform::xsl($file,// src file
dirname(dirname(__FILE__)).'/modules/xrem/xsl_html.xsl',// transformation
$destFile,// dest file
null,// params
null,//deps
$force// no-cache ?
);}// if odt, transformer in tei, and in html
if(file_exists($srcPath.".odt")){// compare dates here for cache
if(file_exists($destFile)&&filemtime($destFile)>filemtime($srcPath.".odt"))return$destFile;$odt_tei=dirname(dirname(__FILE__)).'/modules/odt_tei/';include_once$odt_tei.'Odt.php';// write tei here and let work next step ? the dest file is used for images
$tei=Odt::tei($srcPath.".odt",$destDir.$pathinfo.".xml");// return nothing if transformation as a problem
returnTransform::xsl($tei,// tei en string
dirname(dirname(__FILE__)).'/transform/tei_html.xsl',// transformation tei vers html
$destFile,// destination
array("dipleHref"=>self::$dipleHref,"corpusId" =>basename($srcPath),),// paramètres
// dépendances pour date de fraîcheur, le fichier odt, et les transformations odt
array($srcPath.".odt",$odt_tei.'Odt.php',$odt_tei.'odt_tei.xsl',),$force);}// xml file, supposed to be tei, after rng and so on
if(file_exists($file=$srcPath.".xml")){Diple::$xslHtml=Diple::$dipleDir."transform/tei_html.xsl";if(file_exists($file_xsl=Diple::$corpusDir.'transform/'.Diple::$corpusId.'_html.xsl'))Diple::$xslHtml=$file_xsl;Transform::xsl($file,// xml file
self::$xslHtml,// transformation
$destFile,// dest file
null,null,$force);return$destFile;}// if requested path is a folder (after files), search for a welcome file
if(is_dir($srcPath)){$file=self::htmlFile($pathinfo.'/welcome',$force,$srcDir,$destDir);// test if an index file exist, be careful with index.php
if(!$file)$file=self::htmlFile($pathinfo.'/index',$force,$srcDir,$destDir);return$file;// historic ??, /doc, ../, should be fixed upper when calling method
}// at the end, in case of cache
if(file_exists($file=$srcPath.".htm"))return$file;if(file_exists($file=$srcPath.".html"))return$file;echo"<!-- Diple::htmlFile Failed with src=",$srcPath,"-->\n";returnnull;}
static public functionwriteMeta($corpus,$htmlIncArray){// on affiche plusieurs documents, renvoyer les métadonnées de corpus.
if(count($htmlIncArray)>1){foreach($corpusas$key => $value){// si plusieurs valeurs pour la même propriété DC
if(is_array($value)){foreach($valueas$lastvalue)echo"<meta name=\"dc.$key\" content=\"$lastvalue\"/>\n";}elseif($key=="title"&&$value)echo"<title>$value</title>\n";// titre du corpus
elseif($value)echo"<meta name=\"dc.$key\" content=\"$value\"/>\n";}}// on affiche un seul document, renvoyer les métadonnées de ce document.
elseif($var=reset($htmlIncArray))echo$var->meta();unset($var);}}// Répertoire de Diple par défaut
Diple::$dipleDir=dirname(dirname(__FILE__))."/";// Chemin de ressource demandée
Diple::$request=Web::pathinfo();// Adressage de type corpus.php/..., ou corpus/...
if(($corpus=basename($_SERVER['SCRIPT_FILENAME'],".php"))!="index"&&is_dir(dirname($_SERVER['SCRIPT_FILENAME'])."/".$corpus)){Diple::$corpusId=$corpus;Diple::$corpusDir=dirname($_SERVER['SCRIPT_FILENAME'])."/".$corpus."/";Diple::$corpusHref=str_repeat("../",substr_count(Diple::$request,'/'));// how much ../../ to get to CORPUS root
}// Adressage de type corpus/index.php/...
else{Diple::$corpusId=basename(dirname($_SERVER['SCRIPT_FILENAME']));Diple::$corpusDir=dirname($_SERVER['SCRIPT_FILENAME'])."/";Diple::$corpusHref=str_repeat("../",substr_count(Diple::$request,'/'));// how much ../../ to get to CORPUS root
}// chemin relatif au dossier Diple
Diple::$dipleHref=Diple::$corpusHref."../diple/";// Dossier de documents XML source
if(file_exists(Diple::$xmlDir=Diple::$corpusDir."xml/"));elseif(file_exists(Diple::$xmlDir=Diple::$corpusDir."src/"));elseDiple::$xmlDir=Diple::$corpusDir;// set an alternate doc dir
if(file_exists(Diple::$docDir=Diple::$corpusDir."doc/"));require_oncedirname(__FILE__).'/File.php';// ensure a sys_get_temp_dir() function even in php 5.1
// dest dir for generated html files
// html dir inside corpus
if(is_writable(Diple::$htmlDir=Diple::$corpusDir."html/"));// html files aside source
elseif(Diple::$xmlDir==Diple::$corpusDir&&is_writable(Diple::$htmlDir=Diple::$corpusDir));// cache dir shared by corporas
elseif(is_writable($dir=dirname(Diple::$corpusDir).'/cache/')||is_writable($dir=dirname(Diple::$corpusDir).'/html/')){Diple::$htmlDir=$dir.Diple::$corpusId."/";if(!is_dir(Diple::$htmlDir))mkdir(Diple::$htmlDir,0777,true);chmod(Diple::$htmlDir,0777);}else{Diple::$htmlDir=sys_get_temp_dir()."/diple/".Diple::$corpusId."/";if(!file_exists(Diple::$htmlDir))mkdir(Diple::$htmlDir,0777,true);chmod(Diple::$htmlDir,0777);}// Warning: set_time_limit() has been disabled for security reasons
@set_time_limit(3600);// regenerate may take time
?>