view includes/class.skeleton.php @ 75:49b0a2f3a118

Fix IE: Rend l'administration utilisable avec Internet Explorer 6 En réalité, seulement trois réels changements sont introduits ici: - il existait quelques problèmes dans le code supposé être executés lorsque le navigateur ne connait pas les treewalkers, le code fait désormais ce qu'il faut (la mauvaise fonction était associé à l'édition des brouillons, la fonction de test ne renvoyait pas true / false) - Internet Explorer 6 ne connait pas textContent. Une fonction essayant diverses possibilités de remplacement, et faisant un parcours récursif de tous les noeuds fils dans le pire des cas a été mise en place - le code cherchant un remplacement à DOMParser supposait que l'objet ActiveX XMLDOM fournissait exactement la même API, ce qui aurait été trop beau. Un wrapper a été développé autour de XMLDOM qui fournit la seule fonction de DOMParser utilisé dans le script. Evidemment ce n'est pas une solution totalement générique... Avec ces modifications, il est possible de poster depuis Internet Explorer (testé sur la version 6), Safari (testé avec la version 3.1) et Firefox (testé avec les versions 2 et 3)
author Franck Deroche <webmaster@defr.org>
date Mon, 31 Mar 2008 15:07:21 +0200
parents 25c6e59f019e
children
line wrap: on
line source
<?php
class Skeleton extends Template {

  private $styleSheets;
  private $blogPosts;
  private $lastUpdate = 0;
  private $showCalendar = false;
  private $calendarMonth;
  private $calendarYear;
  private $useXML;

  const OUTPUT_XHTML = 'xhtml';
  const OUTPUT_ATOM  = 'atom';
  const OUTPUT_RSS   = 'rss';

  private static $outputType = OUTPUT_XHTML;
  private static $templates = array();

  public function __construct() {
     parent::__construct(Skeleton::getTemplateFile('skeleton'));
     parent::shouldStripAttributesInTemplateNS(true);
     $this->styleSheets = array();
     $this->addDefaultSheets();
     $this->blogPosts = array();
     $this->useXML = empty($_SERVER['HTTP_ACCEPT']) || 
     		     stristr($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml');
  }

  public function setTitle($titre) {
    $this->setParams(array('title' => $titre));
  }

  private function buildSidebar() {
      $sidebar = new Template('sidebar.xml');
      // 1. Récupération des archives
      $db = Factory::getDB();
      $db->Query("
        SELECT 
            MONTH(DatePost) As Month, 
            YEAR(DatePost) As Year, 
            COUNT(num_mess) As Nb 
        FROM Mess 
        GROUP BY 
            MONTH(DatePost), 
            YEAR(DatePost) 
        ORDER BY 
            YEAR(DatePost) DESC, 
            Month(DatePost) DESC
       ");
       $archives = array();
	   while($row = $db->GetRow()) {
            $curArchiveTpl = new Template('archive.xml');
            $monthName = TextUtils::getMonthName($row['Month']);
            $curArchiveTpl->setParams(array(
                'a' =>  $monthName . ' ' . $row['Year'],
                'a@href' => BLOG_URL . "/posts/{$row['Year']}/{$row['Month']}",
                'postCount' => '(' . $row['Nb'] . ')'
            ));
            $archives[] = array('li' => $curArchiveTpl);
	   }
      // 2. Récupération des derniers commentaires
      $db->Query("
        SELECT C.*, M.Titre 
        FROM Commentaires C, Mess M 
        WHERE C.MessId = M.num_mess AND C.Visible=1
        ORDER BY num_comm DESC LIMIT 20");
      $i = 0;
      $comments = array();
      while($row = $db->GetRow()) {
        $curCommentTpl = new Template('commentIndex.xml');
        // On récupère une version filtrée du titre du post ...
        $tf = TextUtils::StripTitle($row['Titre']);
        // ... Qui nous permet d'obtenir l'adresse du commentaire sur le post
        $c_url = BLOG_URL . "/posts/{$row['MessId']}-$tf#c{$row['num_comm']}";
        // Si jamais on a une adresse mail, on rajoute un mailto:
        if(strpos($row['Adresse'], '@') !== false) 
            $row['Adresse'] = 'mailto:' . $row['Adresse'];
        // On commence par définir les paramètres généraux
        $params = array(                
                '#CommentAuthor' => $row['Auteur'],
                '#CommentAuthor@href' => $row['Adresse'],
                '#Post' => $row['Titre'],
                '#Post@href' => $c_url
        );
        // On affiche les 5 commentaires les plus récents en version complète
        // puis les 15 autres en versions résumées
        if($i < 5) {
            $Comment = nl2br($row['Comment']);
        }
        else {
            $Comment = str_replace("\n", " ", strip_tags($row['Comment']));
    		if(strlen($Comment > 100))
                $Comment = utf8_encode(substr(utf8_decode($Comment), 0, 97)) . "...";
            $params['li@class'] = 'fold';
        }

        $frag = $curCommentTpl->getDocumentFragment();
        $frag->appendXML($Comment);
        $params['comment'] = $frag;
        $curCommentTpl->setParams($params);
        $comments[] = array('blogComment' => $curCommentTpl);
        $i++;
      }
      // 3. Application des paramètres
      $sidebar->setParams(array(
            '#archives' => $archives,
            '#BlogCommentIndex' => $comments
      ));
      return $sidebar;
  }

  private function buildLinks() {
      $links = new Template('links.xml');
      return $links;
  }

  private function buildCalendar() {
    $retVal = null;
    if($this->showCalendar) {
       $cMonth = $this->calendarMonth;
       $cYear = $this->calendarYear;
       $nextMonth = ($cMonth % 12) + 1;
       $nextYear = ($nextMonth == 1) ? $cYear + 1 : $cYear;
       $prevMonth = $cMonth - 1;
       if($prevMonth == 0)
       	 $prevMonth = 12;
       $prevYear = ($prevMonth == 12) ? $cYear - 1 : $cYear;
       $retVal = new Template('calendar.xml');
       $retVal->setParams(array(
         '#calPrev' => TextUtils::getMonthName($prevMonth) . ' ' . $prevYear,
         '#calPrev@href' => BLOG_URL . '/posts/' . $prevYear . '/' . $prevMonth,
         '#calNext' => TextUtils::getMonthName($nextMonth) . ' ' . $nextYear,
         '#calNext@href' => BLOG_URL . '/posts/' . $nextYear . '/' . $nextMonth,
         'currentMonth' => TextUtils::getMonthName($cMonth) . ' ' . $cYear
       ));
    } else {
      $retVal = '';
    }
    return $retVal;
  }

  public function addStyleSheet($SheetName, $CSSFile, $enabled = false) {
    $this->styleSheets[] = (object)array(
        'name' => $SheetName,
        'CSSFile' => $CSSFile,
        'enabled' => $enabled
    );
  }

  public function enableStyleSheet($styleSheetName) {
    foreach($this->styleSheets as $styleSheet) {
      $styleSheet->enabled = ($styleSheet->name == $styleSheetName);
    }
  }

  public function addDefaultSheets() {
    $StyleSheets = array(
   	    "Somatic" => "Somatic.css",
	    "OliveVerde" => "OliveVerde.css",
	    "Lite:Reloaded" => "Lite_nv.css",
	    "Brushed" => "Brushed.css",
	    ":Hover" => "HoverExp.css");
    $CkStyle = (array_key_exists("style", $_COOKIE) && 
                array_key_exists($_COOKIE['style'], $StyleSheets))
               ? $_COOKIE['style']
               :"Somatic";
    foreach($StyleSheets as $SheetName => $CSSFile)
        $this->addStyleSheet($SheetName, $CSSFile, ($SheetName == $CkStyle));
  }

  public function addBlogPost(Template $blogPost) {
    $this->blogPosts[] = $blogPost;
  }

  public function checkUpdateTime($time) {
    if($time > $this->lastUpdate)
        $this->lastUpdate = $time;
  }

  public function showCalendar($newValue = false) {
    $this->showCalendar = $newValue;
  }

  public function setCalendarMonth($month, $year) {
    $this->calendarMonth = $month;
    $this->calendarYear = $year;
  }

  private function prepareOutput() {
     $params = array();

     // Ajout de la sidebar
     $params['sidebar'] = $this->buildSideBar();

     // Ajout de la liste des liens
     $params['links']   = $this->buildLinks();

     // Ajout des feuilles de style
     $params['possibleStyleSheets'] = array();
     foreach($this->styleSheets as $styleSheet) {
        $type = ($styleSheet->enabled) ? "" : "Alternate ";
        $type .= "StyleSheet";
        $params['possibleStyleSheets'][] = array(
            'link@href'  => BLOG_URL . '/css/' . $styleSheet->CSSFile,
            'link@rel'   => $type,
            'link@title' => $styleSheet->name
        );
     }

     // Affichage éventuel des liens vers les mois précédents et suivants
     $params['calendarPrevNext'] = $this->buildCalendar();

     // Ajout des posts de blog
     $params['#Posts'] = array();
     foreach($this->blogPosts as $blogPost) {
        $params['#Posts'][] = array('post' => $blogPost);
     }

     // Date de dernière modification
     $params['modifiedDate'] = date('c', $this->lastUpdate);

     // Application des l'ensemble de ces paramètres
     $this->setParams($params);
  }

  public function __toString() {
    $this->prepareOutput();
    $returnValue = parent::__toString();
    $this->setContentTypeHeader();
    // L'ajout d'un preambule XML fait sortir IE de son mode de
    // respect des standards
    if(!$this->useXML)
      $returnValue = ereg_replace('<\?xml[^\?]*\?>', '', $returnValue);
    return $returnValue;
  }

  private function setContentTypeHeader() {
    $contentType = null;
    if(Skeleton::getOutputType() == Skeleton::OUTPUT_ATOM)
        $contentType = 'application/atom+xml';
    else if($this->useXML && Skeleton::getOutputType() == Skeleton::OUTPUT_XHTML)
        $contentType = 'application/xhtml+xml; charset=utf-8';
    if(!is_null($contentType))
        header('Content-Type: ' . $contentType);
  }

  public static function getTemplateFile($type) {
    if(count(Skeleton::$templates) == 0) {
      // Construction du tableau des différents templates
      // permettant de répondre au "type" de sortie demandé
      $iniFile = parse_ini_file('templates.conf', true);

      // Récupération de la requete
      $requete = Factory::getRequete();
    
      // On essaie de trouver le format en Query-String
      // On recherche tout d'abord un paramètre correspondant
      // au nom d'un des formats. On prend le premier mentionné,
      // par ordre d'apparition dans le fichier templates.conf
      $format = null;
      while(is_null($format) && list($key, ) = each($iniFile)) {
         $format = $requete->get($key, null, null);
      }
      
      // Si on a trouvé un format, on l'applique. 
      // Sinon, on prend le template nommé 'xhtml'
      if(!is_null($format)) {
        Skeleton::$templates = $iniFile[$format];
        Skeleton::$outputType = $format;
      } else {
        Skeleton::$templates = $iniFile[Skeleton::OUTPUT_XHTML];
        Skeleton::$outputType = Skeleton::OUTPUT_XHTML;
      }
    }
    return Skeleton::$templates[$type];
  }

  public static function getOutputType() {
    // On s'assure que la demande a été analysée, si ce n'est pas
    // le cas on le fait maintenant, en demandant un template
    if(count(Skeleton::$templates) == 0)
        Skeleton::getTemplateFile('skeleton');
    return Skeleton::$outputType;
  }
}
?>