planetdrupal https://www.vincentliefooghe.net/ fr Migration Drupal 7 vers Drupal 8 https://www.vincentliefooghe.net/content/migration-drupal-7-vers-drupal-8 <span class="field field--name-title field--type-string field--label-hidden">Migration Drupal 7 vers Drupal 8</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Après plusieurs années sous Drupal 7, et l'arrivée imminente de Drupal 9, il était temps pour moi de migrer mon site sur Drupal 8, d'autant que les dernières versions ont maintenant des utilitaires de migration.</p> <h2>Situation initiale</h2> <p>Mon site perso n'est pas très complexe, ni au niveau contenu (environ 200 articles), ni au niveau modules Drupal.</p> <p>La version utilisée est <strong>Drupal 7.69</strong>.</p> <p>En plus des modules du "<em>core</em>", j'utilise des choses plutôt classiques :</p> <ul> <li>ctools (pré-requis pour pas mal de choses)</li> <li>blog (a disparu de la V8, c'est un type de contenu comme les autres)</li> <li>media et media_wysiwyg (pour insérer les images dans le contenu)</li> <li>colorbox (pour afficher les images dans une box en surimpression)</li> <li>pathauto (permet de générer automatiquement un alias)</li> <li>botcha (comme anti-spam)</li> <li>tagclouds (affiche les tags sous forme de <em>nuage</em>)</li> <li>xmlsitemap</li> </ul> <p>Le thème est un développement <em>custom</em>, basé sur Adaptative Theme. Il sera à refaire.</p> <p>Dans tout ça, les seuls module non portés en D8 et pour lesquels il faudra trouver une alternative sont <em>media_colorbox</em> et <em>botcha</em>.</p> <p>Pour l'antispam, j'ai opté pour le module <em>honeypot</em>, et pour <em>media_colorbox</em>, le paramétrage de l'affichage pour les médias de type image va suffire.</p> <p>Côté volumétrie, on a :</p> <ul> <li>159 fichiers</li> <li>199 articles</li> <li>4 "<em>books</em>" (série d'articles sur le même sujet)</li> <li>64 commentaires.</li> </ul> <p>On utilise 2 langues : français et anglais (9 en anglais, le reste en français ou neutre).</p> <h2>Préparation du site sous Drupal 7</h2> <p>Afin de simplifier la migration, je vais changer la langue des articles en anglais pour les assigner au français ou au neutre.</p> <p>Pour les alias d'URL, même modification (on assigne tout au "All languages").</p> <p>Vu la faible volumétrie, je fais cela directement via l'interface web de Drupal, ce qui me permet de m'assurer que tous les champs sont correctement mis à jour.</p> <p>Suite aux tests effectués, j'ai aussi modifié le champ <em>field_alt_text</em> pour enlever <em>colorbox_link</em> du mode d'affichage.</p> <p>Les différentes étapes de la migration seront détaillées dans la suite de cette série d'articles, avec les problèmes que j'ai pu rencontrer.</p> <p> </p> </div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/1" typeof="schema:Person" property="schema:name" datatype="">Vincent</span></span> <span class="field field--name-created field--type-created field--label-hidden">dim 19/04/2020 - 12:40</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/cms" hreflang="fr">CMS</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/taxonomy/term/1" hreflang="fr">Drupal</a></div> <div class="field__item"><a href="/tags/planetdrupal" hreflang="fr">planetdrupal</a></div> </div> </div> <section class="field field--name-comment-node-book field--type-comment field--label-hidden comment-wrapper"> <h2 class="title comment-form__title">Ajouter un commentaire</h2> <drupal-render-placeholder callback="comment.lazy_builders:renderForm" arguments="0=node&amp;1=202&amp;2=comment_node_book&amp;3=comment_node_book" token="palsdtS-Zk7K9WxnQeMy0V4EXY9tNqt1fpWt9kALVmg"></drupal-render-placeholder> </section> Sun, 19 Apr 2020 10:40:55 +0000 Vincent 202 at https://www.vincentliefooghe.net Cartographie avec Drupal : stockage des données et affichage simple https://www.vincentliefooghe.net/content/cartographie-avec-drupal-stockage-des-donn%C3%A9es-et-affichage-simple <span class="field field--name-title field--type-string field--label-hidden">Cartographie avec Drupal : stockage des données et affichage simple</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Dans un précédent article (<a href="https://www.vincentliefooghe.net/content/cartographie-rapide-avec-drupal">https://www.vincentliefooghe.net/content/cartographie-rapide-avec-drupal</a>), j'ai montré comment on pouvait ajouter rapidement et en quelques modules des fonctions de cartographie.</p> <p>Dans cet article, nous allons aller un peu plus loin dans ce domaine, avec la présentation des principes et de différents modules.</p> <h2>Principes et composants de la cartographie</h2> <p>Lorsque l'on parle de cartographie, on pense souvent à la restitution des données. Google Maps a permis de démocratiser cet aspect.<br />Cependant, la chaîne complète repose sur un ensemble de composants :</p> <ul> <li><a href="stockage">Stockage des coordonnées géographiques (latitude / longitude)</a></li> <li><a href="#encodage">Encodage des coordonnées</a></li> <li><a href="#saisie">Saisie des coordonnées</a></li> <li><a href="#visu">Visualisation / restitution</a></li> </ul> <p>Pour chacun de ces composants, Drupal propose souvent plusieurs solutions, parfois incompatibles. Il convient donc de faire le bon choix afin de construire une solution globale pérenne et fonctionnelle.</p> <p>Nous allons voir, dans les différentes parties de cet article, quels sont les composants / modules Drupal que nous pouvons utiliser.</p> <p>Et pour ceux qui sont pressés et qui veulent rapidement mettre en oeuvre une solution, ils peuvent s'orienter vers le<a href="https://www.vincentliefooghe.net/content/cartographie-rapide-avec-drupal"> guide du mapping rapide</a>, qui permet d'avoir une solution complète en installant 5 modules :</p> <ul> <li>geophp : pré-requis pour les fonctions de géolocalisations</li> <li>ctools : pré-requis pour geofield et views</li> <li>geofield : stockage des données</li> <li>geofield_gmap : widget de saisie Google Maps pour le champ geofield</li> <li>views : pour l'affichage des différents contenus sur une seule page</li> </ul> <p><a name="stockage" id="stockage"> </a></p> <h2><a name="stockage" id="stockage">Stockage des données</a></h2> <p>Pour le stockage des données géographiques, c'est <a href="https://www.drupal.org/project/geofield">geofield</a> qui est le plus utilisé et le plus supporté.<br />Il nécessite en pré-requis les modules <a href="https://www.drupal.org/project/geophp">geophp</a> et <a href="https://www.drupal.org/project/ctools">ctools</a>.</p> <p>L'installation et l'activation du module via <em>drush</em> consiste donc en :</p> <pre>drush dl ctools geophp geofield <em> Project ctools (7.x-1.9) downloaded to sites/all/modules/ctools. [success] Project ctools contains 10 modules: term_depth, ctools_access_ruleset, views_content, page_manager, bulk_export, stylizer, ctools_ajax_sample, ctools_custom_content, ctools_plugin_example, ctools. Project geophp (7.x-1.7) downloaded to sites/all/modules/geophp. [success] Project geofield (7.x-2.3) downloaded to sites/all/modules/geofield. [success] Project geofield contains 2 modules: geofield_map, geofield. </em> drush en -y ctools geophp geofield <em>Do you really want to continue? (y/n): y ctools was enabled successfully. [ok] ctools defines the following permissions: use ctools import geofield was enabled successfully. [ok] geophp was enabled successfully. [ok] </em> </pre><p>A ce stade, on a uniquement un nouveau type de champ, qui peut être ajouté à des contenus.</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/Drupal-geoMapping_001.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Drupal-geoMapping_001.png&quot;}" role="button" title="Drupal-geoMapping_001.png" data-colorbox-gallery="gallery-all-TpMSCu-lQAE" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Drupal-geoMapping_001.png&quot;}"><img src="/sites/default/files/styles/large/public/Drupal-geoMapping_001.png?itok=vviQGIEX" width="480" height="191" alt="Drupal-geoMapping_001.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <h2><a name="saisie" id="saisie">Saisie des coordonnées</a></h2> <p>La saisie des coordonnées peut utiliser plusieurs options :</p> <ul> <li>saisie directe des valeurs de latitude, longitude</li> <li>définition d'une zone à partir d'une carte</li> <li>encodage à partir d'une adresse</li> <li>positionnement direct du marqueur sur une carte</li> <li>combinaison de l'adresse et du positionnement</li> </ul> <p>Le plus intuitif, à mon sens, reste la saisie d'une adresse et/ou le positionnement du marqueur sur la carte, qui est intéressant lorsque la position à saisir n'est pas une adresse (par exemple un point perdu dans la campagne ou la montagne...).</p> <h3>Défaut avec Geofield</h3> <p>Par défaut, une fois que <em>geofield</em> est installé, on peut voir sur la capture d'écran, que seuls 4 types de <em>widgets</em> sont disponibles par défaut :</p> <ul> <li>GeoJSON : données au format json</li> <li>Well Known Text (WKT) : format <a href="https://en.wikipedia.org/wiki/Well-known_text">WKT</a>, un format qui permet de définir le type de d'objet et ses coordonnées</li> <li>Latitude / Longitude : 2 champs de saisie, un pour chaque donnée</li> <li>Bounds : saisie de plusieurs points pour définir une frontière</li> </ul> <p>Dans notre exemple, nous avons choisi Latitude / Longitude. L'ajout d'un contenu de type POI demande donc la saisie de la latitude et de la longitude du point.<br />C'est précis, mais pas très intuitif.</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/Drupal-geoMapping_002.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Drupal-geoMapping_002.png&quot;}" role="button" title="Drupal-geoMapping_002.png" data-colorbox-gallery="gallery-all-TpMSCu-lQAE" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Drupal-geoMapping_002.png&quot;}"><img src="/sites/default/files/styles/large/public/Drupal-geoMapping_002.png?itok=I5WySLLI" width="480" height="232" alt="Drupal-geoMapping_002.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p><p><br />Si on a activé la géolocalisation HTML 5, on peut récupérer la localisation actuelle du navigateur en cliquant sur "Find my location" .</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/Drupal-geoMapping_003.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Drupal-geoMapping_003.png&quot;}" role="button" title="Drupal-geoMapping_003.png" data-colorbox-gallery="gallery-all-TpMSCu-lQAE" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Drupal-geoMapping_003.png&quot;}"><img src="/sites/default/files/styles/large/public/Drupal-geoMapping_003.png?itok=RSCetiQY" width="480" height="278" alt="Drupal-geoMapping_003.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <p>Dans ce deuxième exemple, on a changé le widget de saisie en GeoJSON. La saisie demande donc ce format, par exemple :</p> <pre>{"type":"Point", "coordinates":[3.1,50.0] } </pre><p> <article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/Drupal-geoMapping_004.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Drupal-geoMapping_004.png&quot;}" role="button" title="Drupal-geoMapping_004.png" data-colorbox-gallery="gallery-all-TpMSCu-lQAE" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Drupal-geoMapping_004.png&quot;}"><img src="/sites/default/files/styles/large/public/Drupal-geoMapping_004.png?itok=WBfJzrkg" width="480" height="312" alt="Drupal-geoMapping_004.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <p>On constate également que l'affichage (pour l'instant) n'utilise que des champs textes : WKT, GeoJSON, KML, etc. :</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/Drupal-geoMapping_005.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Drupal-geoMapping_005.png&quot;}" role="button" title="Drupal-geoMapping_005.png" data-colorbox-gallery="gallery-all-TpMSCu-lQAE" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Drupal-geoMapping_005.png&quot;}"><img src="/sites/default/files/styles/large/public/Drupal-geoMapping_005.png?itok=y79esEHv" width="480" height="272" alt="Drupal-geoMapping_005.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <h3>Avec des widgets Graphiques</h3> <p>Plutôt que de faire une saisie manuelle des coordonnées, on peut vouloir placer le marqueur directement sur une carte. Pour ce faire, on peut utiliser plusieurs modules, tels que :</p> <ul> <li><a href="https://www.drupal.org/project/geofield_gmap">Geofield Gmap</a></li> <li><a href="https://www.drupal.org/project/leaflet_widget">Leaflet Widget for Geofield</a></li> </ul> <h4>Geofield Gmap</h4> <p>L'installation est simple avec <em>drush</em> :</p> <pre>drush dl geofield_gmap drush en -y geofield_gmap </pre><p>Une fois le module téléchargé et activé, on dispose d'un nouveau Widget pour notre champ Localisation : Google Map.</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/Drupal-geoMapping_014.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Drupal-geoMapping_014.png&quot;}" role="button" title="Drupal-geoMapping_014.png" data-colorbox-gallery="gallery-all-TpMSCu-lQAE" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Drupal-geoMapping_014.png&quot;}"><img src="/sites/default/files/styles/large/public/Drupal-geoMapping_014.png?itok=hQtrM8Yo" width="480" height="251" alt="Drupal-geoMapping_014.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p><p><br />On peut alors entrer une adresse, ou une ville dans le champ d'adresse, mais aussi travailler directement sur la carte.</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/Drupal-geoMapping_016.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Drupal-geoMapping_016.png&quot;}" role="button" title="Drupal-geoMapping_016.png" data-colorbox-gallery="gallery-all-TpMSCu-lQAE" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Drupal-geoMapping_016.png&quot;}"><img src="/sites/default/files/styles/large/public/Drupal-geoMapping_016.png?itok=aFreydQe" width="480" height="265" alt="Drupal-geoMapping_016.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <p>A ce stade, on a donc une saisie et un rendu graphiques de la localisation sur notre type de contenu, en ayant installé 4 modules : ctools, geophp, geofield et geofield_gmap.</p> <p>Ceci fonctionne bien pour un affichage individuel, mais si on veut afficher sur une seule carte les différents points, il va falloir aller plus loin et utiliser notamment les fonctionnalités de <em><a href="#views">Views</a></em></p> <p><a name="encodage" id="encodage"> </a></p> <h2><a name="encodage" id="encodage">Encodage</a></h2> <p>L'encodage consiste à transformer les données saisies en latitude / longitude, afin d'alimenter le champ <em>geofield</em>. Jusqu'ici, notre exemple n'a pas utilisé d'encodage, et il faut donc saisir ces données manuellement, ce qui n'est pas très <em>user friendly</em>.</p> <p>Des modules d'encodage à partir d'adresse sont souvent utilisés. Dans ce domaine, on utilise souvent le couple de modules :</p> <ul> <li>Address pour la saisie des adresses</li> <li>Geocoder pour l'encodage à partir de l'adresse saisie</li> </ul> <p>Cette partie sera traitée dans un autre article.</p> <p><a name="visu" id="visu"></a></p> <h2>Restitution / affichage</h2> <h3>Avec le module Geofield</h3> <p>Par défaut avec <em>geofield</em>, lorsqu'on visualise le contenu, le résultat est assez austère. L'affichage utilise le format WKT (Well Known Text). Par exemple :</p> <pre>POINT (3.1 50) </pre><p> <article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/Drupal-geoMapping_010.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Drupal-geoMapping_010.png&quot;}" role="button" title="Drupal-geoMapping_010.png" data-colorbox-gallery="gallery-all-TpMSCu-lQAE" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Drupal-geoMapping_010.png&quot;}"><img src="/sites/default/files/styles/large/public/Drupal-geoMapping_010.png?itok=obWml_2l" width="256" height="191" alt="Drupal-geoMapping_010.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <p>On peut modifier cet affichage, pour voir les différents autres formats texte.</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/Drupal-geoMapping_008.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Drupal-geoMapping_008.png&quot;}" role="button" title="Drupal-geoMapping_008.png" data-colorbox-gallery="gallery-all-TpMSCu-lQAE" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Drupal-geoMapping_008.png&quot;}"><img src="/sites/default/files/styles/large/public/Drupal-geoMapping_008.png?itok=uiDQCUUD" width="480" height="307" alt="Drupal-geoMapping_008.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <p>Par exemple, si on choisit GeoJSON, on a alors les coordonnées en format JSON :</p> <pre>{"type":"Point","coordinates":[3.1,50]} </pre><p>Pour améliorer la restitution, on peut activer le module Geofield map qui permet d'avoir un nouveau formatter pour la visualisation.</p> <p>Une fois choisi Geofield Map, on dispose de beaucoup plus d'options pour l'affichage</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/Drupal-geoMapping_013.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Drupal-geoMapping_013.png&quot;}" role="button" title="Drupal-geoMapping_013.png" data-colorbox-gallery="gallery-all-TpMSCu-lQAE" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Drupal-geoMapping_013.png&quot;}"><img src="/sites/default/files/styles/large/public/Drupal-geoMapping_013.png?itok=Pg2_HIQA" width="474" height="480" alt="Drupal-geoMapping_013.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <p>Le résultat est déjà plus intéressant ; quand on affiche un contenu, la localisation est affichée sous la forme d'une Map Google :</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/Drupal-geoMapping_009.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Drupal-geoMapping_009.png&quot;}" role="button" title="Drupal-geoMapping_009.png" data-colorbox-gallery="gallery-all-TpMSCu-lQAE" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Drupal-geoMapping_009.png&quot;}"><img src="/sites/default/files/styles/large/public/Drupal-geoMapping_009.png?itok=HZ-P1taJ" width="480" height="349" alt="Drupal-geoMapping_009.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <h3>Affichage avec d'autres modules</h3> <p>Il existe d'autres modules qui gèrent l'affichage du contenu, et qui peuvent être intégrés avec Views, afin de réaliser des cartes englobants plusieurs points.<br />Ces modules utilisent généralement des librairies Javascript, qui effectuent le rendu côté client.</p> <p>On peut citer notamment :</p> <ul> <li>Leaflet</li> <li>OpenLayers</li> <li>IP Geoloc</li> </ul> <p>Nous verrons dans un autre article comment utiliser Leaflet, avec des <em>clusters</em> de point et des icônes spécifiques selon une taxonomie.</p> <p> </p> </div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span class="field field--name-created field--type-created field--label-hidden">sam 12/03/2016 - 18:04</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/cms" hreflang="fr">CMS</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/tags/cartographie" hreflang="fr">cartographie</a></div> <div class="field__item"><a href="/taxonomy/term/1" hreflang="fr">Drupal</a></div> <div class="field__item"><a href="/tags/planetdrupal" hreflang="fr">planetdrupal</a></div> </div> </div> <section class="field field--name-comment-node-book field--type-comment field--label-hidden comment-wrapper"> </section> Sat, 12 Mar 2016 17:04:17 +0000 vincentl 153 at https://www.vincentliefooghe.net Mode de debug pour les thèmes Drupal https://www.vincentliefooghe.net/content/mode-debug-pour-les-th%C3%A8mes-drupal <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Mode de debug pour les thèmes Drupal</span> <div property="content:encoded" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Depuis la version 7.33, Drupal embarque dans le "core" un mode de debug pour le thème.</p> <p>On peut voir dans le fichier <em>CHANGELOG.txt</em></p> <pre>Drupal 7.33, 2014-11-07 ----------------------- .../... - Added a "theme_hook_original" variable to templates and theme functions and an optional sitewide theme debug mode, to provide contextual information in the page's HTML to theme developers. The theme debug mode is based on the one used with Twig in Drupal 8 and can be accessed by setting the "theme_debug" variable to TRUE (API addition).</pre><p><br />Il s'agit donc d'un "backport" depuis Drupal 8.<br /><br />Ce mode "debug" s'active via un paramètre dans le fichier <strong>sites/default/settings.php</strong> :</p> <pre>$conf['theme_debug'] = true; // ou $conf['theme_debug'] = 1;</pre><p>Une fois activé, si on navigue dans les pages, on ne voit... rien !<br />Sauf à regarder le code source de la page HTML (c'est un mode DEBUG, ne l'oublions pas, réservé aux développeurs).<br />Et là, on découvre des commentaires tels que :<br /><br />En haut de page (au niveau de la balise html)</p> <pre>&lt;!-- THEME DEBUG --&gt; &lt;!-- CALL: theme('html') --&gt; &lt;!-- FILE NAME SUGGESTIONS: * html--mon-etablissement.tpl.php x html.tpl.php --&gt; &lt;!-- BEGIN OUTPUT from 'sites/all/themes/professional_theme/templates/html.tpl.php' --&gt;</pre><p>Et au niveau de chaque bloc :</p> <pre>&lt;!-- THEME DEBUG --&gt; &lt;!-- CALL: theme('block') --&gt; &lt;!-- FILE NAME SUGGESTIONS: * block--hiw-common--hiw-login-block.tpl.php * block--hiw-common.tpl.php * block--header.tpl.php x block.tpl.php --&gt; &lt;!-- BEGIN OUTPUT from 'sites/all/themes/professional_theme/templates/block.tpl.php' --&gt;</pre><p><br />ou encore (pour une vue en mode bloc) :</p> <pre>&lt;!-- THEME DEBUG --&gt; &lt;!-- CALL: theme('block') --&gt; &lt;!-- FILE NAME SUGGESTIONS: * block--views--mes-fichiers-block.tpl.php * block--views.tpl.php * block--content.tpl.php x block.tpl.php --&gt; &lt;!-- BEGIN OUTPUT from 'sites/all/themes/professional_theme/templates/block.tpl.php' --&gt; </pre><p>Ceci permet donc de savoir dans quels fichiers templates aller chercher pour faire les modifications du thème.</p> <p>Le template utilisé est celui marqué par une croix '<strong>x</strong>', et il est indiqué par la ligne <em>BEGIN OUTPUT from...</em> . Les autres sont des suggestions qui pourraient être utilisées.</p> <p>Par exemple, si je duplique le modèle <em>block.tpl.php</em> en <em>block--views.tpl.php</em>, on peut constater que le template utilisé change  :</p> <pre>&lt;!-- THEME DEBUG --&gt; &lt;!-- CALL: theme('block') --&gt; &lt;!-- FILE NAME SUGGESTIONS: * block--views--mes-fichiers-block.tpl.php x block--views.tpl.php * block--content.tpl.php * block.tpl.php --&gt; &lt;!-- BEGIN OUTPUT from 'sites/all/themes/professional_theme/templates/block--views.tpl.php' --&gt;</pre><p>Pratique pour affine le theming, sans devoir installer un module tel que <a href="https://www.drupal.org/project/devel_themer">devel_themer</a> !</p> <p> </p> <p> </p> </div> <span rel="sioc:has_creator" class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span property="dc:date dc:created" content="2015-01-28T16:23:01+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">mer 28/01/2015 - 17:23</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/cms" hreflang="fr">CMS</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/taxonomy/term/1" hreflang="fr">Drupal</a></div> <div class="field__item"><a href="/tags/theme" hreflang="fr">theme</a></div> <div class="field__item"><a href="/tags/planetdrupal" hreflang="fr">planetdrupal</a></div> </div> </div> <section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper"> </section> Wed, 28 Jan 2015 16:23:01 +0000 vincentl 124 at https://www.vincentliefooghe.net https://www.vincentliefooghe.net/content/mode-debug-pour-les-th%C3%A8mes-drupal#comments Récupérer un terme de taxonomie à partir d'un champ spécifique https://www.vincentliefooghe.net/content/r%C3%A9cup%C3%A9rer-un-terme-taxonomie-%C3%A0-partir-dun-champ-sp%C3%A9cifique <span class="field field--name-title field--type-string field--label-hidden">Récupérer un terme de taxonomie à partir d&#039;un champ spécifique</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Depuis Drupal7, on peut ajouter des champs à un terme de taxonomie.</p> <p>Ceci peut être intéressant pour ajouter une image ou d'autres informations. Mais comment dans ce cas chercher un terme de taxonomie sur la base de ce champ spécifique ?<br />Imaginous que nous avons une taxonomie de type "Music Categories", sur laquelle nous ajoutons un champ spécifique, "music_code", qui est utilisé dans une interface avec une autre système.<br /><br />Nous avons alors 2 options :</p> <ul> <li>    utiliser la fonction <em>taxonomy_get_tree</em> et filtrer les résultats sur ce champ</li> <li>    rechercher  directement sur ce champ, via <em>EntityFieldQuery</em></li> </ul> <p>Dans cet article, j'explique comme retrouver un terme, en se basant sur un champ spécifique, en utilisant <em>EntityFieldQuery</em>.</p> <p>Cet example peut être lancé en ligne de commande, sans être inclus dans un module. Voyons le code :<br /> </p> <pre>&lt;?php $_SERVER['REMOTE_ADDR']='localhost'; // drupal bootstrap $drupal_directory = "/var/www/drupal"; chdir($drupal_directory); define('DRUPAL_ROOT', getcwd()); require_once './includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); // Retrieve Vocabulary ID (VID) $vocabulary_name='categories'; $vocab = taxonomy_vocabulary_machine_name_load($vocabulary_name); // bundle = Machine Name of the vocabulary $query = new EntityFieldQuery(); $query ---&gt;entityCondition('entity_type', 'taxonomy_term') -&gt;entityCondition('bundle', $vocabulary_name) -&gt;propertyCondition('vid', $vocab-&gt;vid) -&gt;fieldCondition('field_music_code', 'value', 'C042', '='); $results = $query-&gt;execute(); if (!empty($results['taxonomy_term'])) { foreach($results['taxonomy_term'] as $tid) { $term = taxonomy_term_load($tid-&gt;tid); $name=$term-&gt;name; echo "Term ID = ",$term-&gt;tid," Name = ",$name,PHP_EOL; echo "Field Code Client Value = ",$term-&gt;field_music_code[LANGUAGE_NONE][0]['value'],PHP_EOL; } } else { echo "No result for this code ! ",PHP_EOL; } ?&gt; </pre><p>Les 7 premières lignes sont utilisées pour lancer le bootstrap Drupal puisque nous n'utilisons pas de module.<br />Ensuite, nous recherchons le Vocabulary ID, avec la fonction <em>taxonomy_vocabulary_machine_name_load</em>. Ceci nous donne le VID (vocabulary ID).<br />Nous construisons ensuite la requête Entity Query, avec plusieurs paramètres :</p> <ul> <li>    Entity type : dans notre cas, c'est 'taxonomy_term' car nous travaillons sur les taxonomies</li> <li>    Bundle : le nom machine du vocabulaire</li> <li>    propertyCondition : l'ID du vocabulaire que nous utilisons pour la recherche des termes</li> <li>    fieldCondition : la condition placée sur le champ spécifique.</li> </ul> <p>Dans cet exemple, le code est C042, et nous cherchons tous les termes qui utilisent ce code dans leur champ spécifique.</p> <p>Le résultat, dans notre cas, est  :</p> <pre>Term ID = 4 Name = Funk Field Code Client Value = C042</pre><p> </p> </div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span class="field field--name-created field--type-created field--label-hidden">jeu 09/10/2014 - 14:04</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/cms" hreflang="fr">CMS</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/taxonomy/term/1" hreflang="fr">Drupal</a></div> <div class="field__item"><a href="/tags/taxonomy" hreflang="fr">taxonomy</a></div> <div class="field__item"><a href="/tags/entityfieldquery" hreflang="fr">entityfieldquery</a></div> <div class="field__item"><a href="/tags/planetdrupal" hreflang="fr">planetdrupal</a></div> </div> </div> <section class="field field--name-comment-node-book field--type-comment field--label-hidden comment-wrapper"> </section> Thu, 09 Oct 2014 12:04:34 +0000 vincentl 111 at https://www.vincentliefooghe.net Influence du paramétrage APC sur les performances Drupal https://www.vincentliefooghe.net/content/influence-du-param%C3%A9trage-apc-sur-les-performances-drupal <span class="field field--name-title field--type-string field--label-hidden">Influence du paramétrage APC sur les performances Drupal</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Avec une version PHP inférieure à 5.5 il est recommandé d'utiliser un cache d'OpCode. Ce cache permet d'améliorer les performances de PHP, en mettant en cache le code PHP une fois qu'il a été analysé.</p> <p>L'un des caches les plus utilisés est <a href="http://php.net/manual/en/book.apc.php">APC</a>. Son installation sur une distribution type Debian consiste simplement en une commande</p> <pre>apt-get install php-apc</pre><p>Par défaut, la taille mémoire réservée est de 32 Mo.</p> <p><strong>Si cette taille n'est pas optimale, les performances peuvent être dégradées au lieu d'être améliorées</strong>. En effet, on a alors un phénomène de saturation du cache, de fragmentation, et le code doit passer par des phases de check / miss / insert.</p> <p>Pour nos tests, nous réalisons une première séance de tirs avec l'outil <a href="http://www.joedog.org/siege-home/">siege</a>, pendant 2 minutes, sur une liste de 200 urls (les contenus ont été générés par le module <em>Devel generate</em>).</p> <h2>Résultats sans APC</h2> <pre>Transactions: 770 hits Availability: 100.00 % Elapsed time: 119.15 secs Data transferred: 3.97 MB Response time: 3.81 secs Transaction rate: 6.46 trans/sec Throughput: 0.03 MB/sec Concurrency: 24.63 Successful transactions: 766 Failed transactions: 0 Longest transaction: 4.65 Shortest transaction: 0.55 </pre><p>Typiquement, sans Cache d'OpCode et sans cache Drupal, les performances sont assez faibles.</p> <h2>Résultats avec 16 Mo</h2> <p>Le résultat de la commande siege est :</p> <pre>Transactions: 2928 hits Availability: 100.00 % Elapsed time: 119.51 secs Data transferred: 14.98 MB Response time: 1.02 secs Transaction rate: 24.50 trans/sec Throughput: 0.13 MB/sec Concurrency: 24.89 Successful transactions: 2917 Failed transactions: 0 Longest transaction: 2.78 Shortest transaction: 0.55 </pre><p>Sur cette VM de test, on obtient 24 transactions par secondes, sans cache drupal activé. On constate que la taille mémoire utilisée par le cache est de 15 Mo environ. Par rapport à la configuration sans le cache APC, on augmente les performances d'un rapport 4 environ.</p> <p>La consommation mémoire APC est la suivante :</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/drupal-S%C3%A9lection_001.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;drupal-Sélection_001.png&quot;}" role="button" title="drupal-Sélection_001.png" data-colorbox-gallery="gallery-all-IJWC5mfchb8" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;drupal-Sélection_001.png&quot;}"><img src="/sites/default/files/styles/large/public/drupal-S%C3%A9lection_001.png?itok=YMbLje5e" width="480" height="259" alt="drupal-Sélection_001.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <h2>Résultats avec 12 Mo</h2> <pre>Transactions: 784 hits Availability: 99.87 % Elapsed time: 119.73 secs Data transferred: 3.99 MB Response time: 3.75 secs Transaction rate: 6.55 trans/sec Throughput: 0.03 MB/sec Concurrency: 24.58 Successful transactions: 778 Failed transactions: 1 Longest transaction: 4.42 Shortest transaction: 0.58 </pre><p>Dans ce cas, le paramétrage du cache APC n'est pas correct. En effet, la taille du cache n'est pas suffisante pour stocker toutes les opérations.<br />Du coup, les performances chutent drastiquement (environ 1/4 des performances précédentes), et l'on a des performances identiques au fonctionnement sans le cache APC.</p> <p>On constate que le cache APC est saturé, et que l'on voit des "cache full count", qui signifient que le cache a été rempli et qu'il a fallu vider des éléments, ce qui est très pénalisant.</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/drupal-APC-12Mo.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;drupal-APC-12Mo.png&quot;}" role="button" title="drupal-APC-12Mo.png" data-colorbox-gallery="gallery-all-IJWC5mfchb8" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;drupal-APC-12Mo.png&quot;}"><img src="/sites/default/files/styles/large/public/drupal-APC-12Mo.png?itok=OSIYFlmZ" width="480" height="267" alt="drupal-APC-12Mo.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <h2>Résultats avec 24 Mo</h2> <pre>Transactions: 3104 hits Availability: 100.00 % Elapsed time: 119.67 secs Data transferred: 15.90 MB Response time: 0.96 secs Transaction rate: 25.94 trans/sec Throughput: 0.13 MB/sec Concurrency: 24.89 Successful transactions: 3085 Failed transactions: 0 Longest transaction: 1.53 Shortest transaction: 0.48 </pre><p>Avec 24 Mo, les choses rentrent dans l'ordre. Le cache est correctement utilisé, mais il n'y a pas d'amélioration des performances.</p> <p><article class="media media--type-image media--view-mode-default" data-align="center"> <div class="field field--name-field-media-image field--type-image field--label-visually_hidden"> <div class="field__label visually-hidden">Image</div> <div class="field__item"> <a href="https://www.vincentliefooghe.net/sites/default/files/drupal-APC-24Mo.png" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;drupal-APC-24Mo.png&quot;}" role="button" title="drupal-APC-24Mo.png" data-colorbox-gallery="gallery-all-IJWC5mfchb8" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;drupal-APC-24Mo.png&quot;}"><img src="/sites/default/files/styles/large/public/drupal-APC-24Mo.png?itok=QO_CN2t_" width="480" height="255" alt="drupal-APC-24Mo.png" loading="lazy" typeof="foaf:Image" class="image-style-large" /> </a> </div> </div> </article> </p> <h2>Résultats avec 32 Mo</h2> <pre>Transactions: 2595 hits Availability: 100.00 % Elapsed time: 119.78 secs Data transferred: 13.48 MB Response time: 1.15 secs Transaction rate: 21.66 trans/sec Throughput: 0.11 MB/sec Concurrency: 24.87 Successful transactions: 2583 Failed transactions: 0 Longest transaction: 5.92 Shortest transaction: 0.89 </pre><h2>Conclusion</h2> <p>Cette série de tests a montré que le paramétrage du cache APC doit être régulièrement monitoré et validé, sous peine d'avoir un effet inverse à celui attendu et de dégrader les performances.</p> <p>On peut également constater qu'il ne sert à rien de surallouer la mémoire, car une fois la taille optimale allouée, il n'y a aucun gain.</p> <p>Cela prouve également que le choix de l'hébergeur est important, et que la richesse du CMS Drupal a également des impacts sur les performances de la plate-forme. Il convient donc de faire le bon choix. Un hébergement mutualisé ne pourra généralement pas offrir la souplesse d'un hébergeur spécialisé, capable de mettre en oeuvre les bons composants et les bons paramétrages.</p> <h2>Addendrum : impact du cache Drupal</h2> <p>Les tests ont été réalisés avec le cache désactivé. De ce fait, de nombreuses requêtes MySQL sont générées, et tendent à ralentir le débit.<br />Si on active le cache Drupal pour les utilisateurs anonymes, les résultats sont spectaculaires.</p> <p>Un premier essai sans cache APC, mais avec le cache Drupal :</p> <pre>Transactions: 3610 hits Availability: 100.00 % Elapsed time: 119.95 secs Data transferred: 18.70 MB Response time: 0.83 secs Transaction rate: 30.10 trans/sec Throughput: 0.16 MB/sec Concurrency: 24.91 Successful transactions: 3598 Failed transactions: 0 Longest transaction: 5.18 Shortest transaction: 0.59 </pre><p>On constate une nette amélioration par rapport à un paramétrage sans cache (30 transactions / seconde vs 6.5). Au final, on est assez proche d'une configuration APC sans cache Drupal.</p> <p>Deuxième essai avec le cache Drupal et le cache APC :</p> <pre>Transactions: 23611 hits Availability: 100.00 % Elapsed time: 119.03 secs Data transferred: 122.00 MB Response time: 0.13 secs Transaction rate: 198.36 trans/sec Throughput: 1.02 MB/sec Concurrency: 24.93 Successful transactions: 23483 Failed transactions: 0 Longest transaction: 2.49 Shortest transaction: 0.06 </pre><p>Lorsqu'on active les caches APC et Drupal, les performances sont multipliées par 30 !</p> <p>N'oubliez donc pas, pour avoir de bonnes performances, d'activer tous les niveaux de cache possibles : au niveau Drupal, mais également au niveau PHP. Le choix d'un hébergeur qui supporte ces différents niveaux est un gage de performances. Mon hébergeur, <a href="http://www.hebinweb.com">HebInWeb.com</a>, met en oeuvre APC sur les instances Drupal.</p> <p> </p> </div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span class="field field--name-created field--type-created field--label-hidden">lun 04/08/2014 - 15:33</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/cat%C3%A9gorie/cms" hreflang="fr">CMS</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/taxonomy/term/1" hreflang="fr">Drupal</a></div> <div class="field__item"><a href="/tags/apc" hreflang="fr">apc</a></div> <div class="field__item"><a href="/tags/cache" hreflang="fr">cache</a></div> <div class="field__item"><a href="/tags/performances" hreflang="fr">performances</a></div> <div class="field__item"><a href="/tags/planetdrupal" hreflang="fr">planetdrupal</a></div> </div> </div> <section class="field field--name-comment-node-book field--type-comment field--label-hidden comment-wrapper"> </section> Mon, 04 Aug 2014 13:33:24 +0000 vincentl 105 at https://www.vincentliefooghe.net https://www.vincentliefooghe.net/content/influence-du-param%C3%A9trage-apc-sur-les-performances-drupal#comments Interdire l'accès anonyme sur un site Drupal https://www.vincentliefooghe.net/content/interdire-lacc%C3%A8s-anonyme-sur-un-site-drupal <span property="dc:title" class="field field--name-title field--type-string field--label-hidden">Interdire l&#039;accès anonyme sur un site Drupal</span> <span rel="sioc:has_creator" class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span property="dc:date dc:created" content="2014-03-17T14:11:45+00:00" datatype="xsd:dateTime" class="field field--name-created field--type-created field--label-hidden">lun 17/03/2014 - 15:11</span> Mon, 17 Mar 2014 14:11:45 +0000 vincentl 92 at https://www.vincentliefooghe.net