27

Structure du contenu

Créez site19 en copiant site18.

  1. /cms
    1. ...
    2. site18
    3. site19

Dans ce chapitre, nous allons programmer la gestion du contenu du site et son affichage.

Pour tester le résultat en ligne, entrez http://www.frasq.org/cms/site19/fr/noeud/1 dans la barre d'adresse de votre navigateur. Le site affiche le contenu du nœud 1 en français. Entrez http://www.frasq.org/cms/site19/en/node/1 pour afficher sa traduction en anglais.

Un nœud a un titre, un nom, un extrait et un nuage de mots qui lui sont associés. Un nœud a un contenu, en l'occurrence, un texte en HTML.

Affichez le code source de la page. Remarquez que la balise <meta name="description" /> contient l'extrait du nœud et que la balise <meta name="keywords" /> contient le nuage de mots. Ces informations sont normalement exploitées par les moteurs de recherche. Le nom d'un nœud pourra permettre de le désigner dans une URL. Son titre est généralement affiché en début de page.

Démarrez le processeur de commandes de MySQL et entrez dans la BD du site :

$ mysql -u root -p
mysql> use frasqdb2;

NOTE : Utilisez phpMyAdmin pour plus de confort.

Ajoutez la table node puis la table node_locale à la BD du site :

CREATE TABLE node (
node_id INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT ,
user_id INT( 10 ) UNSIGNED NOT NULL ,
created datetime NOT NULL ,
modified datetime NOT NULL ,
PRIMARY KEY ( node_id )
) ENGINE = MYISAM DEFAULT CHARSET = utf8;

Un node contient les propriétés d'un nœud communes à toutes les langues : son identifiant, l'identifiant de l'utilisateur qui l'a modifié pour la dernière fois, ses dates de création et de modification. La clé primaire d'un node est son identifiant.

CREATE TABLE node_locale (
node_id INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT ,
locale enum( 'fr', 'en' ) NOT NULL DEFAULT 'fr',
name VARCHAR( 100 ) NOT NULL ,
title VARCHAR( 100 ) NOT NULL ,
abstract text,
cloud text,
PRIMARY KEY ( node_id , locale )
) ENGINE = MYISAM DEFAULT CHARSET = utf8;

Un node_locale contient les propriétés d'un nœud qui dépendent de la langue : la désignation de la langue du contenu, le nom du nœud, son titre, l'extrait et la liste de mots associés au nœud. L'identifiant d'un node_locale correspond à l'identifiant d'un node. Les désignations des langues doivent correspondre aux langues listées par le paramètre de configuration $supported_languages défini dans le fichier includes/config.inc. La clé primaire d'un node_locale est son identifiant et la désignation de la langue de son contenu.

CREATE TABLE content_text (
content_id INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT ,
locale enum( 'fr', 'en' ) NOT NULL DEFAULT 'fr',
text text,
PRIMARY KEY ( content_id , locale )
) ENGINE = MYISAM DEFAULT CHARSET = utf8;

Un content_text contient un contenu de type text dans une langue donnée, en général du HTML. La clé primaire d'un content_text est son identifiant et la désignation de la langue de son contenu.

Le lien entre un nœud et son contenu est fait par la table node_content :

CREATE TABLE node_content (
node_id INT( 10 ) UNSIGNED NOT NULL ,
content_id INT( 10 ) UNSIGNED NOT NULL ,
content_type enum( 'text' ) CHARACTER SET ascii NOT NULL DEFAULT 'text',
`number` INT( 3 ) UNSIGNED NOT NULL ,
PRIMARY KEY ( node_id , content_id , content_type )
) ENGINE = MYISAM DEFAULT CHARSET = utf8;

Un node_content liste et ordonne les contenus d'un nœud. L'identifiant d'un node_id correspond à l'identifiant d'un node. content_id associé à content_type correspond à l'identifiant d'un contenu dans content_text. La clé primaire d'un node_content est l'identifiant d'un nœud, l'identifiant d'un contenu et son type.

Créez un premier nœud :

INSERT INTO node (node_id, user_id, created, modified) VALUES
(1, 1, NOW(), NOW());

Le nœud 1 est créé par l'utilisateur 1, l'administrateur du site. Vérifiez dans la table user.

Ajoutez ses propriétés en français :

INSERT INTO node_locale (node_id, locale, name, title, abstract, cloud) VALUES
(1, 'fr', 'informations-legales', 'Informations légales', 'Responsabilité de l''auteur - Droits.', 'copyright responsabilité auteur droits diffusion');

Ajoutez la version en anglais :

INSERT INTO node_locale (node_id, locale, name, title, abstract, cloud) VALUES
(1, 'en', 'legal-information', 'Legal information', 'Author''s liability - Rights.', 'copyright liability author rights distribution');

Ajoutez un contenu en français :

INSERT INTO content_text (content_id, locale, text) VALUES
(1, 'fr', '<p>Les informations, les techniques et les logiciels ("CONTENU")\r\nfournis par ce site ont un but purement éducatif\r\net ne doivent pas être interprétés comme un engagement par leur auteur ("AUTEUR").</p>\r\n<p>Le CONTENU est fourni "EN L''ÉTAT" sans garantie d''aucune sorte, expresse ou implicite,\r\ny compris, mais sans limitation, les garanties de qualité marchande,\r\nd''adéquation à un usage particulier et de non-violation des droits de tierces parties.\r\nL''AUTEUR ne saurait en aucun cas être tenu responsable de toute réclamation\r\nou dommage indirect ou consécutif ou de tout autre dommage\r\nlié à la perte d''utilisation, de données ou de bénéfices,\r\nque ce soit dans le cadre d''un contrat, d''une négligence ou d''une autre action préjudiciable,\r\ndus ou liés à l''utilisation ou aux performances du CONTENU.</p>');

Ajoutez sa traduction en anglais :

INSERT INTO content_text (content_id, locale, text) VALUES
(1, 'en', '<p>The information, the techniques and the software ("CONTENT")\r\nprovided by this web site are for educational purposes only\r\nand should not be construed as a commitment by their author ("AUTHOR").</p>\r\n<p>The CONTENT is provided "AS IS", without warranty of any kind, express or implied,\r\nincluding but not limited to the warranties of merchantability,\r\nfitness for a particular purpose and noninfringment of third party rights.\r\nIn no event shall the AUTHOR be liable for any claim,\r\nor any special indirect or consequential damages,\r\nor any damages whatsoever resulting from loss of use, data or profits,\r\nwhether in an action of contract, negligence or other tortious action,\r\narising out of or in connection with the use or performance of the CONTENT.</p>');

Remarquez que les identifiants des deux versions sont identiques mais que la langue diffère.

Créez l'association entre le nœud et son contenu :

INSERT INTO node_content (node_id, content_id, content_type, `number`) VALUES
('1', '1', 'text', '1');

Associe le nœud 1 au contenu 1 de type texte et le place en position 1.

Essayez quelques requêtes sur la BD :

SELECT node_id FROM node WHERE node_id=1 LIMIT 1;

Vérifie que le nœud 1 a bien été créé.

SELECT nloc.name AS node_name, nloc.title AS node_title, nloc.abstract AS node_abstract, nloc.cloud AS node_cloud, n.user_id AS node_user, n.created AS node_created, n.modified AS node_modified
FROM node n
JOIN node_locale nloc ON nloc.node_id=n.node_id AND nloc.locale='fr'
WHERE n.node_id=1
LIMIT 1;

Retourne tous les attributs de la version en français du nœud 1.

SELECT nc.content_id AS content_id, nc.content_type AS content_type, `nc.number` AS content_number, ct.text AS content_text
FROM node_content nc
JOIN content_text ct ON nc.content_type='text' AND ct.content_id=nc.content_id AND ct.locale='fr'
WHERE nc.node_id=1
ORDER BY `nc.number`;

Retourne le contenu en français du nœud 1.

Ajoutez le fichier node.inc dans le dossier models avec le contenu suivant :

  1. function node_id($node) {
  2.     if (!is_numeric($node)) {
  3.         return false;
  4.     }
  5.  
  6.     $tabnode=db_prefix_table('node');
  7.  
  8.     $sql="SELECT node_id FROM $tabnode WHERE node_id=$node LIMIT 1";
  9.  
  10.     $r = db_query($sql);
  11.  
  12.     return $r ? $r[0]['node_id'] : false;
  13. }

node_id retourne l'identifiant du nœud dont l'identifiant est $node, ou false si le nœud $node n'existe pas.

  1. function node_get($lang, $node_id) {
  2.     $sqllang=db_sql_arg($lang, false);
  3.  
  4.     $tabnode=db_prefix_table('node');
  5.     $tabnodelocale=db_prefix_table('node_locale');
  6.  
  7.     $sql="SELECT nloc.name AS node_name, nloc.title AS node_title, nloc.abstract AS node_abstract, nloc.cloud AS node_cloud, n.user_id AS node_user, UNIX_TIMESTAMP(n.created) AS node_created, UNIX_TIMESTAMP(n.modified) AS node_modified FROM $tabnode n JOIN $tabnodelocale nloc ON nloc.node_id=n.node_id AND nloc.locale=$sqllang WHERE n.node_id=$node_id LIMIT 1";
  8.  
  9.     $r = db_query($sql);
  10.  
  11.     return $r ? $r[0] : false;
  12. }

node_get retourne tous les attributs pour la langue $lang du nœud dont l'identifiant est $node_id, ou false en cas d'erreur. Remarquez que les champs node_created et node_modified sont convertis en temps Unix.

  1. function node_get_contents($lang, $node_id) {
  2.     $sqllang=db_sql_arg($lang, false);
  3.  
  4.     $tabnodecontent=db_prefix_table('node_content');
  5.     $tabcontenttext=db_prefix_table('content_text');
  6.  
  7.     $sql="SELECT nc.content_id AS content_id, nc.content_type AS content_type, nc.number AS content_number, ct.text AS content_text FROM $tabnodecontent nc JOIN $tabcontenttext ct ON nc.content_type='text' AND ct.content_id=nc.content_id AND ct.locale=$sqllang WHERE nc.node_id=$node_id ORDER BY nc.number";
  8.  
  9.     $r = db_query($sql);
  10.  
  11.     return $r;
  12. }

node_get_contents retourne le contenu du nœud $node_id pour la langue $lang, ou false en cas d'erreur.

Créez l'action node en ajoutant le fichier node.php dans le dossier actions avec le contenu suivant :

  1. /cms/site19
    1. actions
      1. node.php
  1. require_once 'models/node.inc';
  2.  
  3. function node($lang, $arglist=false) {
  4.     $node=false;
  5.  
  6.     if (is_array($arglist)) {
  7.         if (isset($arglist[0])) {
  8.             $node=$arglist[0];
  9.         }
  10.     }
  11.  
  12.     if (!$node) {
  13.         return run('error/notfound', $lang);
  14.     }
  15.  
  16.     $node_id = node_id($node);
  17.     if (!$node_id) {
  18.         return run('error/notfound', $lang);
  19.     }
  20.  
  21.     $r = node_get($lang, $node_id);
  22.     if (!$r) {
  23.         return run('error/notfound', $lang);
  24.     }
  25.     extract($r); /* node_name node_title node_abstract node_cloud */
  26.  
  27.     head('title', $node_id);
  28.     head('description', $node_abstract);
  29.     head('keywords', $node_cloud);
  30.     head('robots', 'noindex, nofollow');
  31.  
  32.     $banner = build('banner', $lang);
  33.  
  34.     $node_contents = build('nodecontent', $lang, $node_id);
  35.  
  36.     $content = view('node', $lang, compact('node_name', 'node_title', 'node_abstract', 'node_cloud', 'node_contents'));
  37.  
  38.     $output = layout('standard', compact('banner', 'content'));
  39.  
  40.     return $output;
  41. }

L'action node retourne une page affichant le contenu d'un nœud construit par le bloc nodecontent. node prend un argument, un numéro de nœud. Si le numéro de nœud est manquant ou invalide, node renvoie une erreur HTTP 404 Not Found.

Pour donner accès à l'action node, ajoutez un alias par langue dans le fichier includes/aliases.inc :

  1.         'noeud'                 => 'node',
  1.         'node'                  => 'node',

Ajoutez la vue d'un nœud dans les dossiers views/fr pour la version en français et views/en pour la version en anglais :

  1. /cms/site19
    1. views
      1. fr
        1. node.phtml
      2. en
        1. node.phtml
  1. <h3><?php echo htmlspecialchars($node_title, ENT_COMPAT, 'UTF-8'); ?></h3>
  2. <?php if ($node_abstract): ?>
  3. <h5>Extrait</h5>
  4. <p><?php echo htmlspecialchars($node_abstract, ENT_COMPAT, 'UTF-8'); ?></p>
  5. <?php endif; ?>
  6. <?php if ($node_cloud): ?>
  7. <h6>Nuage</h6>
  8. <p class="smaller"><?php echo htmlspecialchars($node_cloud, ENT_COMPAT, 'UTF-8'); ?></p>
  9. <?php endif; ?>
  10. <?php if ($node_contents): ?>
  11. <h4>Contenu</h4>
  12. <?php echo $node_contents; ?>
  13. <?php endif; ?>
  1. <h3><?php echo htmlspecialchars($node_title, ENT_COMPAT, 'UTF-8'); ?></h3>
  2. <?php if ($node_abstract): ?>
  3. <h5>Abstract</h5>
  4. <p><?php echo htmlspecialchars($node_abstract, ENT_COMPAT, 'UTF-8'); ?></p>
  5. <?php endif; ?>
  6. <?php if ($node_cloud): ?>
  7. <h6>Cloud</h6>
  8. <p class="smaller"><?php echo htmlspecialchars($node_cloud, ENT_COMPAT, 'UTF-8'); ?></p>
  9. <?php endif; ?>
  10. <?php if ($node_contents): ?>
  11. <h4>Contents</h4>
  12. <?php echo $node_contents; ?>
  13. <?php endif; ?>

Ajoutez la fonction nodecontent qui retourne le contenu d'un nœud :

  1. /cms/site19
    1. blocks
      1. nodecontent.php
  1. require_once 'models/node.inc';
  2.  
  3. function nodecontent($lang, $node_id) {
  4.     $contents = array();
  5.     $r = node_get_contents($lang, $node_id);
  6.  
  7.     if ($r) {
  8.         foreach ($r as $c) {    /* content_id content_number content_type content_text */
  9.             $type=$c['content_type'];
  10.             switch($type) {
  11.                 case 'text':
  12.                     $s=$c['content_text'];
  13.                     if (!empty($s)) {
  14.                         $text = $s;
  15.                         $contents[] = compact('type', 'text');
  16.                     }
  17.                     break;
  18.                 default:
  19.                     break;
  20.             }
  21.         }
  22.     }
  23.  
  24.     $output = view('nodecontent', false, compact('contents'));
  25.  
  26.     return $output;
  27. }

Comme la vue du bloc ne dépend pas de la langue, ajoutez-la directement dans le dossier views :

  1. /cms/site19
    1. views
      1. nodecontent.phtml
  1. <?php
  2. foreach ($contents as $c) {
  3.     switch($c['type']) {
  4.         case 'text':
  5.             $text_content = $c['text'];
  6.             echo $text_content, PHP_EOL;
  7.             break;
  8.         default:
  9.             break;
  10.     }
  11. }
  12. ?>

Entrez http://localhost/cms/site19/fr/noeud/1 puis http://localhost/cms/site19/en/node/1 dans la barre d'adresse de votre navigateur.

Ajoutez un second contenu à la page :

INSERT INTO content_text (content_id, locale, text) VALUES
(2, 'fr', '<p><i>13 mai 2010</i></p>\r\n<p><b>frasq.org</b></p>'),
(2, 'en', '<p><i>May 13, 2010</i></p>\r\n<p><b>frasq.org</b></p>');
INSERT INTO node_content (node_id, content_id, content_type, `number`) VALUES
('1', '2', 'text', '2');

Rechargez les pages Informations légales et Legal information.

Commentaires

Votre commentaire :
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip aide 2000

Entrez un maximum de 2000 caractères.
Améliorez la présentation de votre texte avec les balises de formatage suivantes :
[p]paragraphe[/p], [b]gras[/b], [i]italique[/i], [u]souligné[/u], [s]barré[/s], [quote]citation[/quote], [pre]tel quel[/pre], [br]à la ligne,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]commande[/code], [code=langage]code source en c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].