add_register("cms_modules",true);
require_once($class_path."/cms/cms_modules_parser.class.php");
class cms_build{
var $dom;
var $headers = array();
var $id_version; // version du portail
var $fixed_cadres = array();
//Constructeur
function cms_build(){
}
function transform_html($html){
global $lvl,$pageid,$search_type_asked;
global $charset, $is_opac_included;
if($charset=='utf-8') $html = preg_replace('/[\x00-\x08\x10\x0B\x0C\x0E-\x19\x7F]'.
'|[\x00-\x7F][\x80-\xBF]+'.
'|([\xC0\xC1]|[\xF0-\xFF])[\x80-\xBF]*'.
'|[\xC2-\xDF]((?![\x80-\xBF])|[\x80-\xBF]{2,})'.
'|[\xE0-\xEF](([\x80-\xBF](?![\x80-\xBF]))|(?![\x80-\xBF]{2})|[\x80-\xBF]{3,})/S',
'?', $html );
$pageid+=0;
@ini_set("zend.ze1_compatibility_mode", "0");
$this->cadre_portail_list=array();
$this->dom = new DomDocument();
$this->dom->encoding = $charset;
// si pas d'entete on ajoute le charset
if($is_opac_included) {
$html = ''.$html;
}
if(!@$this->dom->loadHTML($html)) return $html;
//bon, l'histoire se répète, c'est quand on pense que c'est simple que c'est vraiment complexe...
// on commence par récupérer les zones...
$this->id_version=$this->get_version_public();
if(!$this->id_version) return $html;
//On vide ce qui est trop vieux dans la table de cache des cadres
$this->manage_cache_cadres("clean");
$cache_cadre_object=array();//Tableau qui sert à stocker les objets générés pour les cadres.
$query_zones = "select distinct build_parent from cms_build where build_type='cadre' and build_version_num= '".$this->id_version."'";
$result_zones = mysql_query($query_zones);
if(mysql_num_rows($result_zones)){
while($row_zones = mysql_fetch_object($result_zones)){
//pour chaque zone, on récupère les cadres fixes...
$query_cadres = "select cms_build.*,cadre_url from cms_build
LEFT JOIN cms_cadres ON build_obj=CONCAT(cadre_object,'_',id_cadre) AND cadre_memo_url=1
where build_parent = '".$row_zones->build_parent."'
and build_fixed = 1 and build_type='cadre' and build_version_num= '".$this->id_version."' ";
$result_cadres = mysql_query($query_cadres);
if(mysql_num_rows($result_cadres)){
$cadres = array();
//on place les cadres dans un tableau
while($row_cadres = mysql_fetch_object($result_cadres)){
//Si on a récupéré un cadre_url
$cadreOk=true;
if($row_cadres->cadre_url){
$url=substr($row_cadres->cadre_url, strpos($row_cadres->cadre_url, '?')+1);
foreach (explode('&',$url) as $idParam=>$param){
$tmp=array();
$tmp=explode('=', $param);
if(sizeof($tmp)==2){
if(${$tmp[0]}!=$tmp[1] && ($tmp[0]=="lvl" || $tmp[0]=="search_type_asked" || $tmp[0]=="pageid")){
//si le cadre rentre dans le cas ou il n'appartient pas à la page courante.
$cadreOk=false;
}
}
}
}
if($cadreOk){
$cadres[]=$row_cadres;
}
}
$ordered_cadres = $this->order_cadres($cadres,$cache_cadre_object);
$this->fixed_cadres[$row_zones->build_parent] = $ordered_cadres;
foreach($ordered_cadres as $cadre){
$this->apply_change($cadre,$cache_cadre_object);
if($cadre->build_div){
$this->add_div($cadre->build_obj);
}
}
}
//on passe au cadre dynamiques
$query_dynamics = "select cms_build.*,cadre_url from cms_build
LEFT JOIN cms_cadres ON build_obj=CONCAT(cadre_object,'_',id_cadre) AND cadre_memo_url=1
where build_parent = '".$row_zones->build_parent."'
and build_fixed = 0 and build_type='cadre' and build_version_num= '".$this->id_version."'
order by id_build ";
$result_dynamics = mysql_query($query_dynamics);
if(mysql_num_rows($result_dynamics)){
$cadres = array();
while($row_dynamics = mysql_fetch_object($result_dynamics)){
//Si on a récupéré un cadre_url
$cadreOk=true;
if($row_dynamics->cadre_url){
$url=substr($row_dynamics->cadre_url, strpos($row_dynamics->cadre_url, '?')+1);
foreach (explode('&',$url) as $idParam=>$param){
$tmp=array();
$tmp=explode('=', $param);
if(sizeof($tmp)==2){
if(${$tmp[0]}!=$tmp[1] && ($tmp[0]=="lvl" || $tmp[0]=="search_type_asked" || $tmp[0]=="pageid")){
//si le cadre rentre dans le cas ou il n'appartient pas à la page courante.
$cadreOk=false;
}
}
}
}
if($cadreOk){
$cadres[]=$row_dynamics;
}
}
$ordered_cadres = $this->order_cadres($cadres,$cache_cadre_object);
foreach($ordered_cadres as $cadre){
$this->apply_change($cadre,$cache_cadre_object);
if($cadre->build_div){
$this->add_div($cadre->build_obj);
}
}
}
}
}
//on traite la css des Zones. A voir plus tard pour la gestion du placement
$query_css_zones = "select * from cms_build where build_type='zone' and build_version_num= '".$this->id_version."' ";
$res = mysql_query($query_css_zones);
if(mysql_num_rows($res)){
while($r = mysql_fetch_object($res)){
$node = $this->dom->getElementById($r->build_obj);
if($node){
if( $r->build_css){
$this->add_css($node,$r->build_css);
}
if($r->build_div){
$this->add_div($r->build_obj);
}
}
}
}
//gestion du placement des zones du contener
$query_zones = "select * from cms_build where build_type='zone' and build_version_num= '".$this->id_version."' and build_parent='container' ";
$res = mysql_query($query_zones);
$contener = $this->dom->getElementById("container");
$zones=array();
if(mysql_num_rows($res)){
while($r = mysql_fetch_object($res)){
$zones[]=$r;
}
$ordered_zones = $this->order_cadres($zones,$cache_cadre_object);
foreach($ordered_zones as $zone){
$this->apply_change($zone,$cache_cadre_object);
if($cadre->build_div){
// $this->add_div($cadre->build_obj);
}
}
}
//on insère les entêtes des modules dans le head
$this->insert_headers();
$html = $this->dom->saveHTML();
@ini_set("zend.ze1_compatibility_mode", "1");
return $html;
}
function add_div($id){
$node = $this->dom->getElementById($id);
if(!$node) return;
$obj_div= $this->dom->createElement('div');
$obj_div->setAttribute('id',"add_div_".$id);
$obj_div->setAttribute('class',"row");
$node->parentNode->insertBefore($obj_div,$node);
}
function clear_session_version(){
$_SESSION["build_id_version"]="";
}
function get_version_public(){
global $dbh,$opac_cms;
global $build_id_version; // passer en get si constrution de l'opac en cours
if($build_id_version){
$_SESSION["build_id_version"]=$build_id_version;
} else{
$build_id_version=$_SESSION["build_id_version"];
}
if($build_id_version ) {
// mode opac en constuction
$requete = "select * from cms_version where
id_version='$build_id_version'
order by version_date desc
";
} elseif($opac_cms){
// mode opac, on prend la dernière version
$requete = "select * from cms_version where
version_cms_num=$opac_cms
order by version_date desc
";
}else{
return"";
}
$res = mysql_query($requete, $dbh);
if($row = mysql_fetch_object($res)){
return $row->id_version;
} else {
$_SESSION["build_id_version"]="";
}
}
function apply_change($cadre,&$cache_cadre_object){
global $charset,$opac_parse_html;
if(substr($cadre->build_obj,0,strlen("cms_module_"))=="cms_module_"){
$id_cadre= substr($cadre->build_obj,strrpos($cadre->build_obj,"_")+1);
if($cache_cadre_object[$cadre->build_obj]){
$obj=$cache_cadre_object[$cadre->build_obj];
}else{
$obj=cms_modules_parser::get_module_class_by_id($id_cadre);
$cache_cadre_object[$cadre->build_obj]=$obj;
}
if($obj){
//on va chercher ses entetes...
$this->headers = array_merge($this->headers,$obj->get_headers());
$this->headers = array_unique($this->headers);
//on s'occupe du cadre en lui-même
//on récupère le contenu du cadre
$res = $this->manage_cache_cadres("select",$cadre->build_obj,"html");
if($res["select"]){
$html = $res["value"];
}else{
$html = $obj->show_cadre();
if($opac_parse_html){
$html = parseHTML($html);
}
//on regarde si une condition n'empeche pas la mise en cache !
if($obj->check_for_cache()){
$this->manage_cache_cadres("insert",$cadre->build_obj,"html",$html);
}
}
//ca a peut-être l'air complexe, mais c'est logique...
$tmp_dom = new domDocument();
if($charset == "utf-8"){
@$tmp_dom->loadHTML("".$html);
}else{
@$tmp_dom->loadHTML($html);
}
if (!$tmp_dom->getElementById($obj->get_dom_id())) $this->setAllId($tmp_dom);
if($this->dom->getElementById($cadre->build_parent) ){
$this->dom->getElementById($cadre->build_parent)->appendChild($this->dom->importNode($tmp_dom->getElementById($obj->get_dom_id()),true));
}
$dom_id =$obj->get_dom_id();
//on rappelle le tout histoire de récupérer les CSS and co...
$this->apply_dom_change($obj->get_dom_id(),$cadre);
}
}else{
$this->apply_dom_change($cadre->build_obj,$cadre);
}
}
function order_cadres($cadres,&$cache_cadre_object){
//on retente de mettre de l'ordre dans tout ca...
//init
$ordered_cadres = array();
$cadres_dom = array();
$zone = "";
//on élimine ce qui n'est pas dans le dom (ou ne va pas l'être)
for($i=0 ; $ibuild_parent;
if(substr($cadres[$i]->build_obj,0,strlen("cms_module_"))=="cms_module_"){
$id_cadre= substr($cadres[$i]->build_obj,strrpos($cadres[$i]->build_obj,"_")+1);
$res = $this->manage_cache_cadres("select",$cadres[$i]->build_obj,"object");
if($res["select"] == true){
if($res["value"]){
$cadres_dom[] = $res["value"];
}
}else{
if($cache_cadre_object[$cadres[$i]->build_obj]){
$obj=$cache_cadre_object[$cadres[$i]->build_obj];
}else{
$obj=cms_modules_parser::get_module_class_by_id($id_cadre);
$cache_cadre_object[$cadres[$i]->build_obj]=$obj;
}
if($obj && $obj->check_conditions()){
$cadres_dom[] = $cadres[$i];
if($obj->check_for_cache()){
$this->manage_cache_cadres("insert",$cadres[$i]->build_obj,"object",$cadres[$i]);
}
}elseif($obj && $obj->check_for_cache()){
$this->manage_cache_cadres("insert",$cadres[$i]->build_obj,"object","");
}
}
}else if($cadres[$i]->build_fixed || $this->dom->getElementById($cadres[$i]->build_obj)){
$cadres_dom[] = $cadres[$i];
}
}
$cadres = $cadres_dom;
//après ce petit tour de passe passe, il nous reste ques les éléments présent sur la page...
$ordered_cadres[] =$this->get_next_cadre($cadres,$zone);
$i=0;
$nb =count($cadres);
while(count($cadres)){
$ordered_cadres[] =$this->get_next_cadre($cadres,$zone,$ordered_cadres[count($ordered_cadres)-1]->build_obj);
if($i==$nb) break;
$i++;
}
//le reste, c'est que l'on à jamais pu placer (perte de chainage via supression de cadres)...
foreach($cadres as $cadre){
$ordered_cadres[] = $cadre;
}
return $ordered_cadres;
}
/*
* Permets la gestion du cache pour les cadres du portail dans l'opac
*/
protected function manage_cache_cadres($todo,$build_object_name="",$content_type="",$content=""){
$res=array($todo=>false,"value"=>"");
if($_SESSION["cms_build_activate"]){
return $res;
}
if($todo == "clean"){
global $cms_cache_ttl;//Variable en seconde
$requete="DELETE FROM cms_cache_cadres WHERE NOW() > DATE_ADD(`cache_cadre_create_date`, INTERVAL ".($cms_cache_ttl*1)." SECOND)";
mysql_query($requete);
$res=array($todo=>true,"value"=>"");
return $res;
}
$elems = explode("_",$build_object_name);
$id = array_pop($elems);
$id+=0;
$cadre_name = implode("_",$elems);
$my_hash_cadre = call_user_func(array($cadre_name,"get_hash_cache"), $build_object_name,$id);
//il est possible que la méthode ne nous retourne pas de cache, cela signifie que l'on ne doit pas cacher les éléments associés
if(!$my_hash_cadre){
$res=array($todo=>false,"value"=>"");
return $res;
}
switch ($todo) {
case "select":
$requete="SELECT cache_cadre_hash,cache_cadre_content FROM cms_cache_cadres WHERE cache_cadre_hash='".addslashes($my_hash_cadre)."' AND cache_cadre_type_content='".addslashes($content_type)."'";
$res=mysql_query($requete);
if($res && mysql_num_rows($res)){
$html = mysql_result($res,0,1);
if($html){
if($content_type == "object"){
$value = unserialize($html);
}else{
$value = $html;
}
}else{
$value = "";
}
$res=array($todo=>true,"value"=>$value);
}
break;
case "insert":
$cache_cadre_content="";
if($content_type == "object"){
if($content){
$cache_cadre_content=serialize($content);
}
}else{
$cache_cadre_content=$content;
}
$requete="INSERT INTO cms_cache_cadres(cache_cadre_hash,cache_cadre_type_content,cache_cadre_content) VALUES('".addslashes($my_hash_cadre)."','".addslashes($content_type)."','".addslashes($cache_cadre_content)."')";
$res2=mysql_query($requete);
if($res2){
$res=array($todo=>true,"value"=>"");
}
break;
}
return $res;
}
function get_next_cadre(&$cadres,$zone,$before=""){
$next = false;
//on commence par aller par rapport au dynamiques
foreach($cadres as $key => $cadre){
if($cadre->build_child_before == $before){
$next = $cadre;
unset($cadres[$key]);
return $next;
}
}
// on perd le fil, on reprend les valeurs sures, les éléments fixe
for($i=0 ; $ifixed_cadres[$zone]) ; $i++){
foreach($cadres as $key => $cadre){
if($cadre->build_child_before != "" && $cadre->build_child_before == $this->fixed_cadres[$zone][$i]->build_obj){
$next = $cadre;
unset($cadres[$key]);
return $next;
}
}
}
return $next;
}
function setAllId($DOMNode){
if($DOMNode->hasChildNodes()){
for ($i=0; $i<$DOMNode->childNodes->length;$i++) {
$this->setAllId($DOMNode->childNodes->item($i));
}
}
if($DOMNode->hasAttributes()){
$id=$DOMNode->getAttribute("id");
if($id){
$DOMNode->setIdAttribute("id",true);
}
}
}
function apply_dom_change($id,$infos){
//on s'assure que la zone existe !
$parent = $this->dom->getElementById($infos->build_parent);
if($parent){
$node = $this->dom->getElementById($id);
if($node){
//on ajoute l'attribut fixed si on est sur un élément fixé!
if($infos->build_fixed){
$node->setAttribute("fixed","yes");
}
//on lui ajoute les éléments de la CSS
$node = $this->add_css($node,$infos->build_css);
//on le place dans la bonne zone
$this->place($node,$parent,$infos);
}
}
}
function add_css($node,$css){
if($css){
$node->setAttribute("style",$css);
}
return $node;
}
function get_first_child($zone) {
$childs=$zone->childNodes;
$first_child=null;
for ($i=0; $i<$childs->length;$i++) {
$child=$childs->item($i);
if (($child->nodeType==XML_ELEMENT_NODE)&&($child->getAttribute("id"))) {
$first_child=$child;
break;
}
}
return $first_child;
}
function get_nextSibling($zone,$field) {
$childs=$zone->childNodes;
$next=null;
$found=0;
for ($i=0; $i<$childs->length;$i++) {
$child=$childs->item($i);
if (($child->nodeType==XML_ELEMENT_NODE)&&($child->getAttribute("id"))){
if($child->getAttribute("id")==$field->getAttribute("id")) {
$found=1;
}elseif($found){// coup suivant, c'est le bon
$next=$child;
break;
}
}
}
return $next;
}
function get_previousSibling($zone,$field) {
$childs=$zone->childNodes;
$previous=null;
for ($i=0; $i<$childs->length;$i++) {
$child=$childs->item($i);
if (($child->nodeType==XML_ELEMENT_NODE)&&($child->getAttribute("id"))){
if(($child->getAttribute("id")==$field->getAttribute("id")) ) {
return $previous;
break;
}else{
$previous=$child;
}
}
}
return null;
}
function place($node,$parent,$infos){
$previous_brother = $this->get_previous_node_id($infos);
if($previous_brother!== false){
if($previous_brother!= ""){
//un précédent connu, on insère le noeud juste avant le précédent, puis on remet le précédent au dessus...
$node_next= $this->get_nextSibling($parent,$this->dom->getElementById($previous_brother));
if($node_next && ($node->getAttribute("id") !=$node_next->getAttribute("id"))){
$parent->insertBefore($node,$node_next);
} elseif(!$node_next) {
$parent->appendChild($node);
} else {
}
}else{
//pas de parent, c'est le premier...
$node_child=$this->get_first_child($parent);
if($node_child && ($node->getAttribute("id")!=$node_child->getAttribute("id"))){
$parent->insertBefore($node,$node_child);
} elseif(!$node_child) {
$parent->appendChild($node);
} else {
}
}
}else{
$next_brother = $this->get_next_node_id($infos);
if($next_brother){
$node_previous=$this->get_previousSibling($parent,$this->dom->getElementById($next_brother));
if($node_previous && ($node->getAttribute("id")!=$node_previous->getAttribute("id"))){
$node = $parent->insertBefore($node,$node_previous);
}elseif(!$node_previous){
$parent->appendChild($node);
}else {
}
}else{
$parent->appendChild($node);
}
}
}
function get_previous_node_id($infos){
if($this->dom->getElementById($infos->build_child_before)){
return $infos->build_child_before;
}else{
return $this->_get_previous_node_id($infos->build_child_before);
}
}
function _get_previous_node_id($node_id){
if($node_id === ""){
return $node_id;
}else{
if($this->dom->getElementById($node_id)){
$query = "select build_child_before from cms_build where build_obj = '".$node_id."' and build_version_num= '".$this->id_version."' ";
$result = mysql_query($query);
if(mysql_num_rows($result)){
$previous = mysql_result($result,0,0);
if($this->dom->getElementById($previous)){
return $previous;
}else{
return $this->_get_previous_node_id($previous);
}
}
}else{
return false;
}
}
}
function get_next_node_id($infos){
return $this->_get_next_node_id($infos->build_obj);
}
function _get_next_node_id($node_id){
if($node_id === ""){
return $node_id;
}else{
if($this->dom->getElementById($node_id)){
$query = "select build_child_after from cms_build where build_obj = '".$node_id."' and build_version_num= '".$this->id_version."'";
$result = mysql_query($query);
if(mysql_num_rows($result)){
$next = mysql_result($result,0,0);
if($this->dom->getElementById($next)){
return $next;
}else{
return $this->_get_next_node_id($next);
}
}
}else{
return false;
}
}
}
function insert_headers(){
if(count($this->headers)){
$headers = implode("\n",$this->headers);
$tmp_dom = new domDocument();
@$tmp_dom->loadHTML($headers);
for ($i=0 ; $i<$tmp_dom->getElementsByTagName("head")->item(0)->childNodes->length ; $i++){
$this->dom->getElementsByTagName("head")->item(0)->appendChild($this->dom->importNode($tmp_dom->getElementsByTagName("head")->item(0)->childNodes->item($i),true));
}
}
}
// class end
}