source: spip-zone/_plugins_/_stable_/qcm/qcm_pipelines.php @ 7572

Last change on this file since 7572 was 7572, checked in by patfr@…, 13 years ago
File size: 11.9 KB
Line 
1<?php
2/*
3  Nom du plugin      :  Un QCM dans vos articles
4  Auteur             :  Patrice VANNEUFVILLE
5                                                patfr@ifrance.com
6                                                (sur une idee originale de Mathieu GIANNECCHINI, 2003)
7  Date               :  30 octobre 2006
8  Fonction du plugin :  Parse le code du QCM tape dans SPIP et stocke
9                        les questions, reponses et commentaires
10                        dans un tableau et retourne le code HTML du QCM
11  Mode d'emploi          :      http://www.spip-contrib.net/Un-QCM-dans-vos-articles
12 
13  Titre du QCM :
14        - soit sur une ligne de la forme 'T Voici mon titre' placee entre les
15          balises <qcm> et </qcm>
16        - soit entre les balises <qcm-titre> et </qcm-titre>
17        - soit entre les balises <intro> et </intro>
18                (Spip s'en servira egalement en cas d'absence de descriptif pour
19                calculer la balise #INTRODUCTION utilisee pour resumer l'article)
20
21  Calcul de #INTRODUCTION : si introduction() n'est pas surchargee, Spip cherche
22  d'abord le descriptif, puis en cas d'echec, le contenu du texte situé entre
23  les balises <intro> et </intro>. En dernier lieu, Spip utilise les 500 premiers
24  caractères du chapeau suivi du texte.
25  Attention donc : pour ne pas faire apparaitre le contenu du QCM avec les
26  reponses, il vaut mieux penser à bien définir :
27        - soit le descriptif de l'article
28        - soit une introduction placee entre les balises <intro> et </intro>
29                (utiliser dans ce cas les balises <qcm-titre> et </qcm-titre>
30                pour definir le titre du QCM)
31        - soit le titre du QCM place entre les balises <intro> et </intro>
32 
33*/
34 
35 define(_QCM_DEBUT, '<qcm>');
36 define(_QCM_FIN, '</qcm>');
37 define(_QCM_TITRE_DEBUT, '<qcm-titre>');
38 define(_QCM_TITRE_FIN, '</qcm-titre>');
39 
40// cette fonction remplit le tableau $qcms sur la question $indexQCM
41function qcm_analyse_le_qcm($qcm, $indexQCM, &$titreQCM) {
42  global $qcms;
43  $lignes = split("\n", $qcm);
44  foreach ($lignes as $ligne) {
45        $li=trim($ligne); 
46    switch($li[0]){
47      case 'T' : 
48                // On extrait le titre
49                $titreQCM=propre(substr($li,1));
50                break;
51
52      case 'Q' : 
53                // On extrait la question
54                $qcms[$indexQCM]['question'] = trim(substr($li, 1));
55                $qcms[$indexQCM]['maxscore'] = 0;
56                $qcms['nbquestions']++;
57        break;
58
59      case 'P' : 
60                // On extrait une proposition
61               
62                // On extrait les precisions de la proposition
63                list($reponse, $precision)=explode("|", $li);
64       
65                // On extrait le numero de la proposition et son contenu
66                ereg("^P([0-9]+)(.*)", $reponse, $eregResult); 
67                $indexProposition = $eregResult[1];
68                $suiteProposition = trim($eregResult[2]);
69                $qcms[$indexQCM]['nbpropositions']++;
70
71        // On extrait les points eventuellement associes a chaque reponse
72        if(ereg("^\.(-?[0-9]+)(.*)", $suiteProposition, $eregResult)){
73          $qcms[$indexQCM]['points'][$indexProposition] = intval($eregResult[1]);
74          $qcms[$indexQCM]['propositions'][$indexProposition] = trim($eregResult[2]);
75        }
76                else {
77          $qcms[$indexQCM]['points'][$indexProposition] = 0;
78          $qcms[$indexQCM]['propositions'][$indexProposition] = $suiteProposition;
79        }     
80               
81                // la precision eventuelle...
82        $qcms[$indexQCM]['precisions'][$indexProposition] = trim($precision);
83                break;
84       
85      case 'R' :
86                // On recupere le numero et les points de la bonne reponse
87                ereg("^R([0-9]+)", $li, $eregResult);   
88                $qcms[$indexQCM]['bonnereponse'] = $eregResult[1];
89
90                // au cas ou les points ne sont pas specifies pour la bonne reponse
91                if ($qcms[$indexQCM]['points'][$eregResult[1]]==0) 
92                  $qcms[$indexQCM]['points'][$eregResult[1]] = 1;
93
94                // total des points des bonnes reponses
95                $qcms[$indexQCM]['maxscore'] = $qcms[$indexQCM]['points'][$eregResult[1]];
96                break;
97
98      default : break;
99    }
100  } // foreach
101} // function
102
103// cette fonction retourne le texte entre deux balises si elles sont presentes
104// et false dans le cas contraire
105function qcm_recupere_le_titre(&$chaine, $ouvrant, $fermant) {
106  // si les balises ouvrantes et fermantes ne sont pas presentes, c'est mort
107  if (strpos($chaine, $ouvrant)===false || strpos($chaine, $fermant)===false) return false;
108  list($texteAvant, $suite) = explode($ouvrant, $chaine, 2); 
109  list($texte, $texteApres) = explode($fermant, $suite, 2); 
110  // on supprime les balises de l'affichage...
111  $chaine = $texteAvant.'<!QCM-DEBUT-#0>'.$texteApres;
112  return trim($texte);
113}
114
115
116// cette fonction modifie $chaine et retourne true si un qcm est trouve, false dans le cas contraire
117function qcm_recupere_une_question(&$chaine, &$indexQCM, &$titreQCM) {
118  global $qcms;
119 
120  // si les balises ouvrantes et fermantes ne sont pas presentes
121  if (strpos($chaine, _QCM_DEBUT)===false || strpos($chaine, _QCM_FIN)===false) return false;
122
123  // remplacement des qcm par : <ATTENTE_QCM>ii</ATTENTE_QCM>
124  list($texteAvant, $suite) = explode(_QCM_DEBUT, $chaine, 2); 
125  list($qcm, $texteApres) = explode(_QCM_FIN, $suite, 2); 
126  $chaine = "$texteAvant<ATTENTE_QCM>$indexQCM</ATTENTE_QCM>$texteApres";
127 
128  // On analyse le QCM
129  qcm_analyse_le_qcm($qcm, $indexQCM, $titreQCM);
130 
131  return true;
132}
133
134function qcm_les_points($phrase, $points) {
135    $pointsHTML = '<span class="spip_qcm_point"> ('.$points. _T('qcm:qcm_point'.($points>1?'s':'')).')</span>';
136        if (ereg('^(.*)( ?:)( *)$', $phrase, $eregResult)) $phrase = $eregResult[1].$pointsHTML.$eregResult[2].$eregResult[3];
137          else $phrase .= $pointsHTML;
138        return $phrase; 
139}
140
141function qcm_affiche_la_question($indexQCM, $corrigee, $gestionPoints) {
142  global $qcms, $qcm_score;
143  if ($qcms[$indexQCM]['propositions']==0) return '';
144
145  // Initialisation du code a retourner
146  $nomVarSelect = 'var_Q'.$indexQCM;
147  $question = trim(str_replace('&nbsp;', ' ', $qcms[$indexQCM]['question']));
148 
149  // affichage des points dans la question
150  if ($gestionPoints) {
151    $pointsQ = $qcms[$indexQCM]['maxscore'];
152        $question = qcm_les_points($question, $pointsQ);
153  } else $pointsQ = 1;
154
155  $codeHTML = "<div class=\"spip_qcm_question\">".definir_puce().$question.'</div>';
156  if (!$corrigee){
157    // affichage sans correction :
158     $codeHTML.="\n<div class=\"spip_qcm_proposition\">";
159
160      // Si il ya plus de 5 choix, on utilise une liste
161      if(count($qcms[$indexQCM]['propositions'])>5){
162        $codeHTML.='<select name="'.$nomVarSelect.'" class="spip_qcm_select">';
163                foreach($qcms[$indexQCM]['propositions'] as $i=>$v) $codeHTML.="<option value=\"$i\">$v</option>";
164                $codeHTML.='</select>';
165      }
166      // Sinon des radio boutons
167      else {
168                foreach($qcms[$indexQCM]['propositions'] as $i=>$v)
169          $codeHTML.='<input type="radio" name="'.$nomVarSelect
170                        . '" value="'.$i.'" id="'.$nomVarSelect.$i.'"><label for="'.$nomVarSelect.$i.'">'
171                . $v.'</label><br />';
172       }
173       $codeHTML.="</div><br />";
174       
175    }   //Fin du cas sans correction
176
177  // Sinon on affiche la correction
178  else {
179 
180         if ($_POST[$nomVarSelect]) {
181                // les points de la reponse donnee...
182                $pointsR = $qcms[$indexQCM]['points'][$_POST[$nomVarSelect]];
183               
184                // la reponse donnee & precision des points eventuels de la mauvaise reponse...
185                $codeHTML.='<div class="spip_qcm_reponse">'
186                         .((($pointsR==$pointsQ) || ($pointsR==0))?_T('qcm:qcm_introReponse'):qcm_les_points(_T('qcm:qcm_introReponse'), $pointsR))
187                         .$qcms[$indexQCM]['propositions'][$_POST[$nomVarSelect]].'</div>';
188
189                // on donne les points de la reponse quoiqu'il arrive
190                $qcm_score += $pointsR;
191               
192        if ($qcms[$indexQCM]['bonnereponse']==$_POST[$nomVarSelect])
193        // Si c'est juste
194                        $codeHTML .= '<div class="spip_qcm_correction_juste">'._T('qcm:qcm_reponseJuste').'</div>';
195        // Si c'est faux
196         else $codeHTML .= '<div class="spip_qcm_correction_faux">'._T('qcm:qcm_reponseFausse').'</div>';
197           
198        // les precisions eventuelles
199        if ($qcms[$indexQCM]['precisions'][$_POST[$nomVarSelect]]<>"")
200             $codeHTML.='<div align="center"><div class="spip_qcm_precision">'
201                                 .$qcms[$indexQCM]['precisions'][$_POST[$nomVarSelect]]
202                         .'</div></div>';
203
204        // pas de reponse postee...
205        } else $codeHTML.='<div class="spip_qcm_correction_null">'._T('qcm:qcm_reponseNulle').'</div>';
206           
207        $codeHTML.='<br />';
208     
209  } //Fin du cas avec correction
210  return $codeHTML;
211}
212
213function qcm_inserer_les_qcm(&$chaine, $gestionPoints) {
214  global $qcms;
215  if (ereg('<ATTENTE_QCM>([0-9]+)</ATTENTE_QCM>', $chaine, $eregResult)) {
216        $indexQCM = intval($eregResult[1]);
217        list($texteAvant, $texteApres) = explode($eregResult[0], $chaine, 2);
218        $chaine = "$texteAvant<!QCM-DEBUT-#$indexQCM>\n"
219                . qcm_affiche_la_question($indexQCM, isset($_POST["var_correction"]), $gestionPoints)
220                . "<!QCM-FIN-#$indexQCM>\n"
221                . qcm_inserer_les_qcm($texteApres, $gestionPoints); 
222  }
223  return $chaine;
224}
225
226function qcm_qcm($chaine) {
227  // premiere verification
228  if (strpos($chaine, _QCM_DEBUT)===false || strpos($chaine, _QCM_FIN)===false) return $chaine;
229
230  // initialisation 
231  global $qcms, $qcm_score;
232  $titreQCM = false;
233  $indexQCM =  $qcm_score = 0;
234  $qcms['nbquestions'] = $qcms['totalscore'] = $qcms['totalpropositions'] = 0;
235 
236  // on cherche les questions
237  while (qcm_recupere_une_question($chaine, $indexQCM, $titreQCM)) {
238    $qcms['totalpropositions'] +=  count($qcms[$indexQCM]['propositions']);
239    $qcms['totalscore'] +=  $qcms[$indexQCM]['maxscore'];
240        $indexQCM++;
241  }
242 
243  // est-ce certaines questions ne valent pas 1 point ?
244  $gestionPoints = $qcms['totalscore']<>$qcms['nbquestions'];
245
246  // trouver un titre, coute que coute...
247  if (!$titreQCM) $titreQCM = qcm_recupere_le_titre($chaine, _QCM_TITRE_DEBUT, _QCM_TITRE_FIN);
248  if (!$titreQCM) $titreQCM = qcm_recupere_le_titre($chaine, '<intro>', '</intro>');
249  if (!$titreQCM) $titreQCM = _T('qcm:qcm_titre');
250 
251  // reinserer les qcms mis en forme
252  $chaine = qcm_inserer_les_qcm($chaine, $gestionPoints);
253
254  $tete = '<div class="spip_qcm"><div class="spip_qcm_titre">'.$titreQCM.'<hr /></div>';
255  if (!isset($_POST["var_correction"])) { 
256        $tete .= '<form method="post" action="">';
257        $pied = '<br>
258        <input type="hidden" name="var_correction" value="yes">
259        <div align="center"><input type="submit" value="'._T('qcm:qcm_corriger').'" class="spip_qcm_bouton_corriger"></div>
260        </form>';
261  } else {
262      // On ajoute le score final
263      $pied = '<center><div class="spip_qcm_score">'._T('qcm:qcm_score')
264                                . "&nbsp;$qcm_score&nbsp;/&nbsp;".$qcms['totalscore'].'<br>'
265                                . ($qcm_score==$qcms['totalscore']?_T('qcm:qcm_bravo'):'').'</div></center>'
266                                . '<div class="spip_qcm_bouton_corriger" align="right">[ <a href="'
267                                . parametre_url(self(),'var_mode','recalcul').'">'._T('qcm:qcm_reinitialiser').'</a> ]</div>';
268  }
269 
270  // introduire l'entete et le pied
271  $chaine = preg_replace(',(<!QCM-DEBUT-#0>),', $tete."\\1", $chaine, 1);
272  $chaine = str_replace($temp='<!QCM-FIN-#'.($indexQCM-1).'>', $temp.$pied.'</div>', $chaine);
273
274  unset($qcms);
275  return "<!PLUGIN-DEBUT>$chaine<!PLUGIN-FIN>";
276}
277
278function qcm_qcm2($chaine){
279 if (ereg(_QCM_DEBUT, $chaine)) {
280        ob_start();
281        $chaine = qcm($chaine);
282        $data = ob_get_contents();
283        ob_end_clean();
284        $chaine = nl2br(str_replace("\t",'&nbsp;&nbsp;&nbsp;&nbsp;',$data)).$chaine;
285 }
286 return $chaine;
287}
288
289
290function qcm_stylesheet_public($b) {
291 return '<link rel="stylesheet" href="'.find_in_path($b)."\" type=\"text/css\" media=\"projection, screen\" />\n";
292}
293function qcm_stylesheet_prive($b) {
294 return '<link rel="stylesheet" href="'._DIR_PLUGIN_QCM."$b\" type=\"text/css\" media=\"projection, screen\" />\n";
295}
296
297function qcm_header_prive($flux){
298        return $flux . qcm_stylesheet_prive('qcm.css');
299}
300
301function qcm_insert_head($flux){
302        return $flux 
303        . "<!-- CSS QCM -->\n"
304        . qcm_stylesheet_public('qcm.css');
305}
306
307function qcm_pre_propre($texte) {
308        return qcm_qcm($texte);
309}       
310
311function qcm_post_propre($texte) { 
312        return preg_replace(',<!((QCM|PLUGIN)-(DEBUT|FIN)(-#[0-9]+)?)>,UimsS', '<!-- \\1 -->', $texte);
313}       
314
315
316?>
Note: See TracBrowser for help on using the repository browser.