Hello
j'avais besoin de ça pour un outil de gestion de cours, et j'ai beau avoir bien cherché, je n'ai rien trouvé sur le net. Juste un truc qui à partir d'une liste de cours, avec heure début/ heure fin vous génère un beau tableau HTML avec les colspan qui vont bien, et des couleurs de fond de cellule.
Donc j'ai fait une petite classe rapidos, que je partage avec vous. C'est fait un peu à la va-vite, ça pourrait être carrément plus paramétrable et mieux construit (là une classe Planning qui fait toutes les manips, une classe de contenu de cellule et une classe Mapper qui fait le lien entre votre objet cours et mon objet contenu de cellule) mais bon déjà ça marche et ça fait ce que je voulais. Ah, c'est pas trop documenté non plus (mais bon ça va, y'a que 3 fichiers dont 1 presque inutile) et il reste des bouts d'Anglais dedans (mais pas beaucoup). Peut-être que c'est pas bien écrit aussi, parceque moi vous savez le PHP, j'en fais jamais
Voici le code, si vous voyez des petits bugs, des petites améliorations possibles et que vous voulez les partager, n'hésitez pas. Par exemple, il faudrait gérer les formats d'heures, si possible dans le mapper pas dans l'objet de contenu. Mais bon, ça si c'est vous êtes motivés. Allez c'est parti.
Planning.php
<?php
class Planning {
private $joursFr = Array(0=>'Dimanche', 1=>'Lundi', 2=>'Mardi', 3=>'Mercredi', 4=>'Jeudi', 5=>'Vendredi', 6=>'Samedi');
private $jourDebut; // jour de début du planning (0 à 6)
private $jourFin; // jour de fin du planning
private $heureDebut; // heure de début de chaque jour (en minutes)
private $heureFin; // heure de fin de chaque jour (en minutes)
private $pas; // durée d'une case (en minutes)
private $minutesKeys;
private $contenu; // contenu général du planning (tableau de PlanningCellule)
private $tabSemaine; // stockage des données (tableau initialisé avec des cellules vides)
const htmlSpace = ' ';
const htmlEmptyCell = '<td> </td>';
const htmlCellOpen = '<td>';
const htmlCellClose = '</td>';
const htmlRowOpen = '<tr>';
const htmlRowClose = '</tr>';
const htmlTableOpen = '<table class="tabPlanning">';
const htmlTableClose = '</table>';
const separateurHeure = 'h';
public function __construct($jourDebut=1, $jourFin=5, $heureDebut=540, $heureFin=1260, $pas=30, $contenu = Array()){
$this->jourDebut = $jourDebut;
$this->jourFin = $jourFin;
$this->heureDebut = $heureDebut;
$this->heureFin = $heureFin;
$this->pas = $pas;
$this->contenu = $contenu;
$this->initTableauSemaine($this->contenu);
// $this->debugPHPArrays();
$this->insererContenus($contenu);
}
/**
* Génère un tableau dont les clés sont les heures de début de chaque case (en minutes)
* Serviront à identifier facilement chaque case du planning
* @return unknown_type
*/
private function genererMinutesKeys() {
$keys = Array();
for ($key=$this->heureDebut; $key<=$this->heureFin; $key+=$this->pas) {
$keys[] = $key;
}
$this->keys = $keys;
return $keys;
}
/**
* Génère un tableau correspondant à un jour
* @return unknown_type
*/
private function initTableauJour() {
if ($this->pas != 0) {
$numCells = ($this->heureDebut - $this->heureFin) / $this->pas;
} else {
echo 'pas == 0 !!';
}
$keys = $this->genererMinutesKeys();
$tabJour = array_fill_keys($keys, self::htmlEmptyCell);
return $tabJour;
}
private function initTableauSemaine() {
$this->tabSemaine = Array();
$tabJour = $this->initTableauJour();
for($i=$this->jourDebut; $i<=$this->jourFin; $i++) {
$this->tabSemaine[$i] = $tabJour;
}
}
private function getNumeroCellule($minutesDebut, $minutesFin) {
return ($minutesFin - $minutesDebut) / $this->pas;
}
/**
* Insère tous les contenus de cellulés envoyés
* @param $contenuPlanning
* @return unknown_type
*/
private function insererContenus($contenuPlanning) {
foreach ($contenuPlanning as $contenuCellule) {
$this->insererContenu($contenuCellule);
}
}
/**
* Insère le contenu d'une cellule précise
* @param $contenuCellule
* @return unknown_type
*/
private function insererContenu($contenuCellule) {
// ajout de la cellule fusionnée
$duree = $this->getNumeroCellule($contenuCellule->heureDebut, $contenuCellule->heureFin);
$contenu = $contenuCellule->contenu.'<br />';
$contenu .= $this->convertMinutesEnHeuresMinutes($contenuCellule->heureDebut);
$contenu .= ' - '.$this->convertMinutesEnHeuresMinutes($contenuCellule->heureFin);
$this->tabSemaine[$contenuCellule->numJour][$contenuCellule->heureDebut] = $this->genererCelluleHTML($contenu, $duree, '', $contenuCellule->bgColor);
// suppression du contenu suivant
$key = $contenuCellule->heureDebut;
for ($cpt = $duree-1; $cpt>0; $cpt--) {
$key += $this->pas;
$this->tabSemaine[$contenuCellule->numJour][$key] = '';
}
}
/* Affichage */
public function debugPHPArrays() {
echo '<pre>';
print_r($this->tabSemaine);
echo '</pre>';
}
public function genererHtmlTable() {
$htmlTable = self::htmlTableOpen;
$htmlTable .= $this->genererBandeauJours();
$key = $this->heureDebut;
$keyEnd = $this->heureFin;
for ($key; $key <= $keyEnd; $key+=$this->pas) {
$htmlTable .= self::htmlRowOpen;
$htmlTable .= '<td class="cellHour">'.$this->convertMinutesEnHeuresMinutes($key).'</td>';
foreach ($this->tabSemaine as $tabHeures) {
$htmlTable .= $tabHeures[$key];
}
$htmlTable .= self::htmlRowClose;
}
$htmlTable .= self::htmlTableClose;
return $htmlTable;
}
public function afficherHtmlTable() {
echo $this->genererHtmlTable();
}
private function genererBandeauJours() {
$daysLine = self::htmlRowOpen;
$daysLine .= $this->genererCelluleHTML(self::htmlSpace);
$day = $this->jourDebut;
while ($day <= $this->jourFin) {
$daysLine .= $this->genererCelluleHTML($this->jourFr($day), '', 'cellDay');
$day++;
}
$daysLine .= self::htmlRowClose;
return $daysLine;
}
/**
* Génère une ligne HTML contenant le libellé des jours utilisés dans le planning
* @param $contenuCellule
* @param $colspan
* @param $class
* @param $bgColor
* @return unknown_type
*/
private function genererCelluleHTML($contenuCellule, $colspan = '', $class = '', $bgColor = '') {
$celluleHTML = '<td';
if (!empty($colspan))
$celluleHTML .= ' rowspan="'.$colspan.'"';
if (!empty($class))
$celluleHTML .= ' class="'.$class.'"';
if (!empty($bgColor))
$celluleHTML .= ' bgcolor="'.$bgColor.'"';
$celluleHTML .= '/>';
$celluleHTML .= $contenuCellule;
$celluleHTML .= '</td>';
return $celluleHTML;
}
/**
* Renvoie le libellé d'un jour en Français
* @param $dayNum
* @return unknown_type
*/
private function jourFr($dayNum) {
return $this->joursFr[$dayNum];
}
private function convertMinutesEnHeuresMinutes($minutes) {
$heure = floor($minutes / 60);
$minutes = ($minutes % 60);
$minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
return ($heure. self::separateurHeure .$minutes);
}
}
?>
PlanningCellule
<?php
class PlanningCellule {
private $data;
public function __construct($numJour, $heureDebut, $heureFin, $bgColor, $contenu) {
$this->numJour = $numJour;
$this->heureDebut = $heureDebut;
$this->heureFin = $heureFin;
$this->bgColor = $bgColor;
$this->contenu = $contenu;
}
public function __set($name, $value) {
if ($name == 'heureDebut' || $name == 'heureFin') {
$tabHeure = explode(':', $value);
$value = (int)$tabHeure[0];
if ($tabHeure[1] == 30)
$value += 0.5;
$value = $value*60;
}
$this->data[$name] = $value;
}
public function __get($name) {
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
$trace = debug_backtrace();
trigger_error(
'Propriété non-définie via __get(): ' . $name .
' dans ' . $trace[0]['file'] .
' à la ligne ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
public function __toString() {
$str = 'heure début : '.$this->heureDebut."<br />\n";
$str .= 'heure fin : '.$this->heureFin."<br />\n";
$str .= 'couleur : '.$this->bgColor."<br />\n";
$str .= 'contenu : '.$this->contenu."<br />\n";
return $str;
}
}
?>
PlanningMapper
<?php
Class PlanningMapper {
// instance de la classe
private static $instance;
// Un constructeur privé ; empêche la création directe d'objet
private function __construct() { }
// La méthode singleton
public static function getInstance() {
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
public function genererPlanningCellule($cours) {
// $lienNiveau = UrlHelper::link_to($cours->getAlphaNiveaux()->getLibelleNiveau(), 'niveaux/listApprenantsParNiveau/idNiveau'.$cours->getAlphaNiveaux()->getIdNiveau());
$contenuCellule = '<b>'.$cours->getAlphaFormateurs()->getPrenomFormateur().'</b><br />'
.$cours->getAlphaNiveaux()->getLibelleNiveau();
$planningContent = new PlanningCellule($cours->getJour(),
$cours->getHeureDebut(),
$cours->getHeureFin(),
$cours->getAlphaNiveaux()->getCodeCouleur(),
$contenuCellule);
return $planningContent;
}
public function __clone() {
trigger_error('Le clônage n\'est pas autorisé.', E_USER_ERROR);
}
}
?>
Une démo rapide (qui ne fait pas appel au mapper, que j'utilise dans mon appli symfony):
<html>
<head>
<title>Démo planning dynamique</title>
<link rel="stylesheet" type="text/css" media="screen" href="planning.css" />
<body>
<div id="planning">
<?php
include('Planning.php');
include('PlanningCellule.php');
include('PlanningMapper.php');
$contenusCellules[] = new PlanningCellule(1,'17:30:00','19:00:00','#008000','<b>Zeus</b><br />B1/1');
$contenusCellules[] = new PlanningCellule(1,'19:30:00','21:00:00','#7CCAF4','<b>Ryle</b><br />A2');
$contenusCellules[] = new PlanningCellule(2,'12:30:00','14:00:00','#7CCAF4','<b>Mère-Térésa</b><br />A2');
$contenusCellules[] = new PlanningCellule(2,'14:00:00','15:30:00','#314E8C','<b>Truc</b><br />A1');
$contenusCellules[] = new PlanningCellule(2,'16:00:00','17:30:00','#314E8C','<b>Albat</b><br />A1');
$contenusCellules[] = new PlanningCellule(2,'17:30:00','19:00:00','#C080C0','<b>Calimero</b><br />B3');
$contenusCellules[] = new PlanningCellule(3,'10:30:00','12:00:00','#800080','<b>Damien</b><br />B2');
$contenusCellules[] = new PlanningCellule(3,'13:00:00','14:30:00','#314E8C','<b>Cobaye</b><br />A1');
$contenusCellules[] = new PlanningCellule(3,'14:30:00','16:00:00','#80C080','<b>Moosh</b><br />B1/2');
$contenusCellules[] = new PlanningCellule(3,'16:00:00','17:30:00','#008000','<b>@rthur</b><br />B1/1');
$contenusCellules[] = new PlanningCellule(3,'18:30:00','20:00:00','#80C080','<b>Dunbar</b><br />B1/2');
$contenusCellules[] = new PlanningCellule(3,'20:00:00','21:30:00','#7CCAF4','<b>Ryle</b><br />A2');
$contenusCellules[] = new PlanningCellule(4,'11:00:00','12:30:00','#314E8C','<b>AB</b><br />A1');
$contenusCellules[] = new PlanningCellule(4,'14:00:00','15:30:00','#7CCAF4','<b>Hywan</b><br />A2');
$contenusCellules[] = new PlanningCellule(4,'17:00:00','18:30:00','#7CCAF4','<b>Sekiltoyai</b><br />A2');
$contenusCellules[] = new PlanningCellule(4,'18:30:00','20:00:00','#800080','<b>Genova</b><br />B2');
$contenusCellules[] = new PlanningCellule(4,'20:00:00','21:30:00','#008000','<b>Ouckileou</b><br />B1/1');
$contenusCellules[] = new PlanningCellule(5,'09:00:00','10:30:00','#314E8C','<b>Nagol</b><br />A1');
$contenusCellules[] = new PlanningCellule(5,'18:00:00','19:30:00','#80C080','<b>Fab</b><br />B1/2');
$contenusCellules[] = new PlanningCellule(6,'10:30:00','12:00:00','#80C080','<b>Naholyr</b><br />B1/2');
$planning = new Planning(1, 6, 540, 1260, 30, $contenusCellules);
$planning->afficherHtmlTable();
?>
</div>
</body>
</html>
La CSS qui va avec :
Code : Tout sélectionner
/* PLANNING */
#planning {
padding-left: 0;
margin-left: 210px;
overflow: auto;
}
#planning table, #planning tr, #planning td {
text-align: center;
border-width:1px;
border-style:solid;
border-color:black;
}
td.cellDay {
width: 120px;
font-weight: bold;
}
td.cellHour {
width: 70px;
vertical-align: top;
height: 30px;
font-weight: bold;
}
Voilà, c'est pas le grand art de la programmation, mais ça peut toujours aider