Flux RSS de gandbox.fr - eZ Publish Flux RSS de gandbox.fr - eZ Publish Sun, 27 Jun 2010 15:34:50 +0000 http://www.gandbox.fr/rss2 eZ Conference 2010 slides about eZ Find 2.2 customization & advanced development <div class="object-left"> <p> <a href="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-conference-ez-find-cover-slides/20211-1-fre-FR/eZ-Conference-eZ-Find-cover-slides.png" target="_blank"> <img src="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-conference-ez-find-cover-slides/20211-1-fre-FR/eZ-Conference-eZ-Find-cover-slides_medium.png" width="200" height="149" style="border: 0px;" alt="eZ Conference - eZ Find cover slides" title="eZ Conference - eZ Find cover slides" /> </a> </p></div><p>On <b>June 24th</b>, at the <a href="http://ez.no/fr/company/ez_conference_awards/developer_track" target="_blank">2010 eZ Conference developer track</a>, I proposed a talk about <b>eZ Find 2.2 customization &amp; advanced development</b>. This talk illustrate and summarize <a href="http://www.gandbox.fr/Blogs/Technologies-Web/eZ-Conference-2010-slides-about-eZ-Find-2.2-customization-advanced-development#articles" target="_self">my eZ Find articles / tutorials you'll find below</a>, with new schemas and real project exemples. Thanks to all the eZ Community for their interest and questions during the conference. I hope to have time to write one of <a href="http://share.ez.no/tutorials/write-a-tutorial-win-an-award" target="_blank">these requested tutorials in coming month</a>.</p><p>I'd like to thanks <b>Nicolas Pastorino</b> for the english translation of my articles on <a href="http://share.ez.no/" target="_blank">share.ez.no</a>.</p><p><a href="/content/download/3583/20215/version/1/file/20100622_eZ_Find_Slides_GiG_V2.1.pdf" target="_self" class="download">Download the PDF version</a>, or <a href="http://www.gandbox.fr/Blogs/Technologies-Web/eZ-Conference-2010-slides-about-eZ-Find-2.2-customization-advanced-development#slideshare" target="_self">browse the slideshare version</a>.</p><a name="eztoc20203_1" id="eztoc20203_1"></a><h2> <a name='slideshare'></a>Slideshare version</h2><div class="video"> <object width="600" height="450" type="application/x-shockwave-flash" data="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=20100622ezfindslidesgigv2-1-100627082934-phpapp02&amp;stripped_title=20100622-e-zfindslidesgigv21"> <param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=20100622ezfindslidesgigv2-1-100627082934-phpapp02&amp;stripped_title=20100622-e-zfindslidesgigv21"></param> <param name="allowfullscreen" value="true"></param> </object> </div> <a name="eztoc20203_2" id="eztoc20203_2"></a><h2> <a name='articles'></a>Articles / tutorials about eZ Find</h2><p><b>French articles about eZ Find on <a href="http://www.gandbox.fr" target="_self">gandbox.fr</a> :</b></p> <ul> <li><a href="http://www.gandbox.fr/Blogs/Technologies-Web/Developpement-avance-avec-eZ-Find-partie-1-La-gestion-des-datatypes-entre-eZ-Find-Solr" target="_self">Développement avancé avec eZ Find (partie 1 : La gestion des datatypes entre eZ Find &amp; Solr)</a></li> <li><a href="http://www.gandbox.fr/Blogs/Technologies-Web/Developpement-avance-avec-eZ-Find-partie-2-Indexer-des-champs-supplementaires-dans-Solr" target="_self">Développement avancé avec eZ Find (partie 2 : Indexer des champs supplémentaires dans Solr)</a></li> <li><a href="http://www.gandbox.fr/Blogs/Technologies-Web/Developpement-avance-avec-eZ-Find-partie-3-Tirer-profit-de-la-syntaxe-Solr" target="_self">Développement avancé avec eZ Find (partie 3 : Tirer profit de la syntaxe Solr)</a></li> </ul> <p><b>English articles about eZ Find (translation from French), on <a href="http://share.ez.no" target="_blank">share.ez.no</a> :</b></p> <ul> <li><a href="http://share.ez.no/tutorials/ez-publish/advanced-development-with-ez-find-part-1-datatypes-in-solr-and-ez-find" target="_blank">Advanced development with eZ Find - part 1 : Datatypes in Solr and eZ Find</a></li> <li><a href="http://share.ez.no/tutorials/ez-publish/advanced-development-with-ez-find-part-2-indexing-additional-fields-in-solr" target="_blank">Advanced development with eZ Find - part 2 : Indexing additional fields in Solr</a></li> <li>Advanced development with eZ Find - part 3 : Not yet publish... coming soon</li> </ul> Sun, 27 Jun 2010 15:34:50 +0000 http://gandbox.fr/Blogs/Technologies-Web/eZ-Conference-2010-slides-about-eZ-Find-2.2-customization-advanced-development Développement avancé avec eZ Find (partie 3 : Tirer profit de la syntaxe Solr) <div class="object-left"> <p> <a href="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-find-chapter-3/20011-1-fre-FR/eZ-Find-Chapter-3.png" target="_blank"> <img src="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-find-chapter-3/20011-1-fre-FR/eZ-Find-Chapter-3.png" width="185" height="102" style="border: 0px;" alt="eZ Find - Chapter 3" title="eZ Find - Chapter 3" /> </a> </p></div><p>Le <a href="http://www.gandbox.fr/Blogs/Technologies-Web/Developpement-avance-avec-eZ-Find-partie-2-Indexer-des-champs-supplementaires-dans-Solr" target="_self">billet précédent décrit comment ajouter des champs supplémentaires dans Solr</a>, afin de pouvoir les exploiter avec la syntaxe native d'<a href="http://ez.no/ezfind" target="_blank">eZ Find</a> sous la forme<b> 'mycontentclass/mycontentattribute/mycontentsubattribute'</b>.</p><p>Cette syntaxe spécifique à <a href="http://ez.no/ezfind" target="_blank">eZ Find</a> est certes confortable mais non exclusive, à savoir qu'il est possible de <b>mixer des éléments de syntaxes eZ Find et des éléments de syntaxes Solr</b>, comme par exemple les noms des champs (<b>'attr_myfield_type'</b>) ou encore des opérateurs logiques (<b>AND</b>, <b>NOT</b>, etc.).</p><blockquote><span class="quoteleft">“</span><p> - <b>OUI c'est une mauvaise pratique</b>. Une syntaxe 'interface' n'est pas faites pour être outrepasser, au risque de compromettre l'évolutivité de la couche basse, à savoir <a href="http://lucene.apache.org/solr/" target="_blank">Solr</a><br />- <b>OUI cela peut faciliter les développements</b>, voir même sauver la vie du développeur sur certaines situations complexes</p><span class="quoteright">”</span></blockquote> <p>Ce billet montre quelques exemples d'exploitation de la syntaxe <b>Solr</b>, volontairement simplifiés pour en faciliter la compréhension.</p><a name="eztoc20003_1" id="eztoc20003_1"></a><h2>Faire un tri sur un attribut commun à plusieurs classes</h2><p>Il s'agit d'un grand classique des problématiques d'<b>eZ Publish</b>, à savoir : </p> <ul> <li>On crée 2 classes différentes pour X raisons &quot;<b>Post</b>&quot; et &quot;<b>Article</b>&quot;</li> <li>On ajoute dans chacune des classes des attributs communs, parceque utile dans les 2 cas, par exemple un attribut &quot;<b>Date</b>&quot;</li> </ul> <p><b>Résultat : </b>Impossible de mélanger les &quot;<b>Post</b>&quot; et &quot;<b>Article</b>&quot; en les triant par dates décroissante (sauf à développer un terrifiant <a href="http://ezpedia.org/ez/template_operators" target="_blank">opérateur de template</a>). Généralement, les développeurs font en sorte d'utiliser une seule classe plus générique afin de contourner ou plutôt déplacer le problème (la mutualisation d'une classe peut avoir d'autres inconvénients).</p><p><b>La solution des attributs communs entre les classes avec eZ Find :</b></p><p><a href="http://www.gandbox.fr/Blogs/Technologies-Web/Developpement-avance-avec-eZ-Find-partie-1-La-gestion-des-datatypes-entre-eZ-Find-Solr" target="_self">Le premier billet de cette série consacré à <b>eZ Find</b> décrit la logique de nommage des champs dans <b>Solr</b></a>. Une effet secondaire positif de cette convention (lié au concept de dynamicfields de <b>Solr</b>) est <b>l'absence bienheureuse de l'identifiant de la classe dans le nom de chaque champs</b>. Il est ainsi possible d'exploiter les <b>champs homonymes</b> comme bon nous semble, au travers de recherche, filtres ou tris en fonction du besoin.</p><p><b>Exemple de code de template eZ Publish sur la seule classe &quot;Post&quot; :</b></p> <pre class="eztemplate"><span style="color: #D36900;">&#123;</span>def <span style="">$search_result</span> = <a href="http://ez.no/doc/content/advancedsearch?SearchText=fetch"><span style="color: #008000;">fetch</span></a><span style="color: #D36900;">&#40;</span> <span style="color: #ff0000;">'content'</span>, <span style="color: #ff0000;">'list'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=hash"><span style="color: #804040;">hash</span></a><span style="color: #D36900;">&#40;</span> <span style="color: #ff0000;">'parent_node_id'</span>, <span style="color: #cc66cc;">2</span>, <span style="color: #ff0000;">'class_filter_type'</span>, <span style="color: #ff0000;">'include'</span>, <span style="color: #ff0000;">'class_filter_array'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=array"><span style="color: #804040;">array</span></a><span style="color: #D36900;">&#40;</span><span style="color: #cc66cc;">24</span><span style="color: #D36900;">&#41;</span>, <span style="color: #ff0000;">'sort_by'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=array"><span style="color: #804040;">array</span></a><span style="color: #D36900;">&#40;</span> <a href="http://ez.no/doc/content/advancedsearch?SearchText=array"><span style="color: #804040;">array</span></a><span style="color: #D36900;">&#40;</span> <span style="color: #ff0000;">'attribute'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=false"><span style="color: #0600FF;">false</span></a><span style="color: #D36900;">&#40;</span><span style="color: #D36900;">&#41;</span>, <span style="color: #ff0000;">'post/date'</span> <span style="color: #D36900;">&#41;</span> <span style="color: #D36900;">&#41;</span>, <span style="color: #ff0000;">'limit'</span>, <span style="color: #cc66cc;">10</span>, <span style="color: #ff0000;">'depth'</span>, <span style="color: #cc66cc;">3</span> <span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span> &nbsp;</pre><p><b>Exemple équivalent de code de template eZ Find pour notre problématique de tri inter-classes &quot;Post&quot; et &quot;Article&quot; :</b></p> <pre class="eztemplate"><span style="color: #D36900;">&#123;</span>def <span style="">$search</span>=<a href="http://ez.no/doc/content/advancedsearch?SearchText=fetch"><span style="color: #008000;">fetch</span></a><span style="color: #D36900;">&#40;</span> ezfind, search, <a href="http://ez.no/doc/content/advancedsearch?SearchText=hash"><span style="color: #804040;">hash</span></a><span style="color: #D36900;">&#40;</span> query , <span style="color: #ff0000;">''</span>, <span style="color: #ff0000;">'class_id'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=array"><span style="color: #804040;">array</span></a><span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">'post'</span>, <span style="color: #ff0000;">'article'</span><span style="color: #D36900;">&#41;</span>, <span style="color: #ff0000;">'limit'</span>, <span style="color: #cc66cc;">10</span>, <span style="color: #ff0000;">'sort_by'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=hash"><span style="color: #804040;">hash</span></a><span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">'attr_date_dt'</span>, <span style="color: #ff0000;">'desc'</span><span style="color: #D36900;">&#41;</span> <span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span> &nbsp;</pre><p><b>A noter :</b> une évolution souhaitable d'<b>eZ Find</b> serait de pouvoir exploiter une syntaxe du type '<b>//date</b>', afin de rendre facultatif l'ajout de la classe dans le filtre <b>Solr</b> généré.</p><a name="eztoc20003_2" id="eztoc20003_2"></a><h2>Travailler avec les keywords</h2><p>Contrairement à l'exemple précédent sur les dates, les <b>keywords</b> disposent dans <b>eZ Publish</b> d'une table externe au contenu (<b>ezkeyword_attribute_link</b>), permettant de lier chaque <b>keyword</b> à divers contenus de diverses classes. Cependant <a href="http://ez.no/doc/ez_publish/technical_manual/4_x/reference/modules/content/fetch_functions/keyword" target="_blank">le fetch par keyword</a> ne dispose pas de tous les filtres possibles d'un <a href="http://ez.no/doc/ez_publish/technical_manual/4_x/reference/modules/content/fetch_functions/list" target="_blank">fetch par list</a> par exemple (<b>class_filter_type, class_filter_array, extended_attribute_filter</b>, etc.). Cette limitation se comprend puisque permettre un filtre inter-classes engendre forcement une limitation sur les fonctionnalités liées aux attributs spécifiques à chaque classes.</p><p>Sur le même logique que le traitement par date, on peut donc exploiter <b>eZ Find</b> pour effectuer toutes les opérations nécessaires autour des <b>keywords</b>. Voici un exemple de code :</p> <pre class="eztemplate">'filter', array('attr_tags_lk:&quot;ez publish&quot;', 'NOT attr_title_t:&quot;RSS&quot;') &nbsp;</pre><p><b>Résultat :</b> Retourne uniquement les résultats associés au keyword &quot;<b>eZ Publish</b>&quot; ou &quot;<b>ez publish</b>&quot; (notez l'utilisation du <b>_lk</b> pour lowercase), ne contenant pas &quot;<b>RSS</b>&quot; dans le titre</p> <pre class="eztemplate">'filter', array('attr_tags_lk:&quot;ez publish&quot;', 'attr_tags_lk:&quot;mootools&quot;') &nbsp;</pre><p><b>Résultat :</b> Retourne uniquement les résultats associés à la fois au keyword &quot;<b>eZ Publish</b>&quot; ou &quot;<b>ez publish</b>&quot;, et au keyword &quot;<b>Mootools</b>&quot; ou &quot;<b>mootools</b>&quot;</p><a name="eztoc20003_3" id="eztoc20003_3"></a><h2>Faire des filtres complexes</h2><p>Voici quelques exemples de filtres, qui n'ont rien d'exhaustif puisqu'il est possible d'exploiter <a href="http://lucene.apache.org/java/2_9_1/queryparsersyntax.html" target="_blank">l'ensemble des opérateurs Lucene</a> en fonction de la version de Solr déployée (version de <b>Solr 1.4</b>, disponible dans <b>eZ Find 2.2</b> lors de la rédaction de ce billet).</p> <pre class="eztemplate">'filter', array('NOT ( attr_title_t:(ez+find) OR attr_intro_t:(ez+find) )') &nbsp;</pre><p><b>Résultat : </b>Retourne uniquement les résultats qui possèdent l'expression '<b>ez find</b>' ou '<b>eZ Find</b>', dans l'attribut '<b>title</b>' ou l'attribut '<b>Intro</b>'. Il faut noter l'utilisation de la version '<b>text</b>' (<b>_t</b>) sur l'attribut '<b>title</b>' permettant de profiter du non respect de la casse (contrairement au type '<b>string</b>').</p> <pre class="eztemplate">'filter', array('attr_title_s:[A TO G] AND ezf_df_text:google~0.7') &nbsp;</pre><p><b>Résultat : </b>Retourne uniquement les résultats dont le '<b>title</b>' commence par A,B,C,D, E ou F (G exclu), et dont le contenu possède approximativement l'expression '<b>google</b>' (Google, iGoogle, etc.).</p> <ul> <li><b>A noter : </b>Le ratio '0.7' peut être ajuster au besoin</li> <li><b>A noter : </b>le champs <b>'ezf_df_text'</b> est un champs constitué dynamiquement et par recopie de tous les autres champs de types <b>'string'</b>, <b>'text'</b> ou <b>'keyword'</b>. On peut aussi utiliser le champs <b>'ezf_sp_words'</b> si la fonctionnalité de spellcheck est exploitable. Voir le fichier <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Fstable%2F2.2%2Fextension%2Fezfind%2Fjava%2Fsolr%2Fconf%2Fschema.xml" target="_blank">schema.xml</a> et la définition de ces champs par <a href="http://wiki.apache.org/solr/SchemaXml#Copy_Fields" target="_blank">copyField</a> pour plus de détail.</li> </ul> Sun, 23 May 2010 17:17:36 +0000 http://gandbox.fr/Blogs/Technologies-Web/Developpement-avance-avec-eZ-Find-partie-3-Tirer-profit-de-la-syntaxe-Solr Développement avancé avec eZ Find (partie 2 : Indexer des champs supplémentaires dans Solr) <div class="object-left"> <p> <a href="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-find-chapter-2/19880-1-fre-FR/eZ-Find-Chapter-2.png" target="_blank"> <img src="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-find-chapter-2/19880-1-fre-FR/eZ-Find-Chapter-2.png" width="185" height="102" style="border: 0px;" alt="eZ Find - Chapter 2" title="eZ Find - Chapter 2" /> </a> </p></div><p>Le <a href="http://www.gandbox.fr/Blogs/Technologies-Web/Developpement-avance-avec-eZ-Find-partie-1-La-gestion-des-datatypes-entre-eZ-Find-Solr" target="_self">billet précédent</a> décrit les mécanismes bas niveaux d'<a href="http://ez.no/ezfind" target="_blank">eZ Find</a>, et la façon dont les <a href="http://www.gandbox.fr/Blogs/Technologies-Web/Developpement-avance-avec-eZ-Find-partie-1-La-gestion-des-datatypes-entre-eZ-Find-Solr" target="_self">correspondances entre les attributs <b>eZ Publish</b> (noms, types de champs) et les champs Solr</a> sont gérés. <b>Ce billet décrit comment eZ Find peut considérablement faciliter le développement de certaines fonctionnalités</b> (en évitant de complexes opérateurs de templates aux multiples requêtes SQL...), en ajoutant automatiquement des champs dans <a href="http://lucene.apache.org/solr/" target="_blank">Solr</a> lors de l'indexation d'un contenu, ré-exploitables par la suite pour la construction d'une facette par exemple ou pour profiter d'un filtre supplémentaire.</p><a name="eztoc19872_1" id="eztoc19872_1"></a><h2>Etude de cas : un filtre par années, et par mois-années</h2> <div class="object-left"> <p> <a href="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-find-facettes-par-dates/19883-1-fre-FR/eZ-Find-Facettes-par-dates.png" target="_blank"> <img src="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-find-facettes-par-dates/19883-1-fre-FR/eZ-Find-Facettes-par-dates_medium.png" width="113" height="200" style="border: 0px;" alt="eZ Find - Facettes par dates" title="eZ Find - Facettes par dates" /> </a> </p></div><p>L'exemple étudié a surtout une valeur pédagogique, puisqu'il s'agit d'un besoin générique et relativement simple à implémenter. Les listes d'actualités, ou les listes de billets sur les Blogs proposent généralement des <b>filtres par années (2010) ou par mois / année (Janvier 2010)</b> (comme sur ce blog par exemple dans la colonne de droite). Habituellement, pour ce genre de filtre on développe un <a href="http://ezpedia.org/ez/template_operators" target="_blank">opérateur de template</a> permettant d'effectuer la requête SQL nécessaire, ce qui peut rapidement devenir très complexe. <b>Il suffit de lire le code de l'opérateur de template <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezwebin%2Ftrunk%2Fpackages%2Fezwebin_extension%2Fezextension%2Fezwebin%2Fautoloads%2Fezarchive.php" target="_blank">eZArchive</a> pour en comprendre les limites</b>.</p><p>Il est relativement fréquent que ces manipulations SQL souffrent de carences fonctionnelles, comme la propagation des droits, la gestion des langues, la gestion de certaines subtilités entre <b>MySql</b> ou <b>PostGreSql</b>. Ce sont des problématiques à la charge du développeur, puisque l'on contourne les API pour exploiter directement du SQL. Par ailleurs, l'opérateur <b><a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezwebin%2Ftrunk%2Fpackages%2Fezwebin_extension%2Fezextension%2Fezwebin%2Fautoloads%2Fezarchive.php" target="_blank">eZArchive</a></b> montre une autre limite importante, puisqu'il se contente de travailler sur la date de publication '<b>publication_date</b>' (par facilité), et ne permet donc pas d'exploiter <b>un attribut de date spécifique à la classe</b>.</p><a name="eztoc19872_2" id="eztoc19872_2"></a><h2>Développer le filtre par années, et par mois-années avec eZ Find</h2><a name="eztoc19872_2_1" id="eztoc19872_2_1"></a><h3>Etape 1 : Indexer les années, mois / année vers Solr</h3><p>Les <b>settings</b> d'<b>eZ Find</b> (<a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Ftrunk%2Fextension%2Fezfind%2Fsettings%2Fezfind.ini" target="_blank">ezfind.ini</a>, à surcharger dans le <b>ezfind.ini.append.php</b> de votre extension) permettent de déléguer le traitement de l'indexation d'un <b>datatype eZ Publish</b> vers une classe <b>PHP</b> :</p> <pre class="ini"><span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>SolrFieldMapSettings<span style="">&#93;</span></span> CustomMap<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>ezdate<span style="">&#93;</span></span>=<span style="color: #660066;">ezfSolrDocumentFieldDate</span> &nbsp;</pre><p>Notre classe <b>PHP</b>, nommée arbitrairement <b>ezfSolrDocumentFieldDate</b> hérite de la classe <b><a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Ftrunk%2Fextension%2Fezfind%2Fclasses%2Fezfsolrdocumentfieldbase.php" target="_blank">ezfSolrDocumentFieldBase</a></b> et doit être ajoutée dans le dossier <b>/extension/myextension/classes/ezfsolrdocumentfielddate.php</b> avec le squelette suivante :</p> <pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #000000; font-weight: bold;">class</span> ezfSolrDocumentFieldDate <span style="color: #000000; font-weight: bold;">extends</span> ezfSolrDocumentFieldBase <span style="color: #66cc66;">&#123;</span> <span style="color: #000000; font-weight: bold;">public</span> <a href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #000000; font-weight: bold;">function</span> getFieldName<span style="color: #66cc66;">&#40;</span> eZContentClassAttribute <span style="color: #0000ff;">$classAttribute</span>, <span style="color: #0000ff;">$subAttribute</span> = <span style="color: #000000; font-weight: bold;">null</span>, <span style="color: #0000ff;">$context</span> = <span style="color: #ff0000;">'search'</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #808080; font-style: italic;">// return the fieldname like : attr_mydate_d</span> <span style="color: #66cc66;">&#125;</span> &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getData<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #808080; font-style: italic;">// return the array keys (fieldname =&gt; value), like : array('attr_mydate_dt' =&gt; '2010-04-30T00:00:00Z')</span> <span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span> &nbsp;</pre><a name="eztoc19872_3" id="eztoc19872_3"></a><h2>Le rôle de la méthode getFieldName</h2><p>Cette méthode est invoquée pour transformer les noms des attributs <b>eZ Find</b> vers les noms de champs <b>Solr</b>. Ainsi lorsqu'on construit une facette avec la syntaxe '<b>mycontentclass/mydateattribute</b>', cette méthode reçoit '<b>mydateattribute</b>' et doit retourner '<b>attr_mydateattribute_dt</b>'. Nous allons donc implémenter cette fonction de la façon suivante :</p> <ul> <li>Si un sous attribut est spécifié (par exemple '<b>mycontentclass/mydateattribute/year</b>'), alors retourne le nom composé du sous attribut</li> <li>Si aucun sous attribut n'est spécifié, alors exécute le code de la classe parent</li> <li><b>Important : </b>Pour profiter d'une certaine généricité, et éviter de nommer '<b>en dur</b>' les champs <b>Solr</b>, nous utilisons les méthodes parents <b>generateSubattributeFieldName</b> et <b>generateAttributeFieldName</b></li> </ul> <pre class="php">const DEFAULT_SUBATTRIBUTE_TYPE = <span style="color: #ff0000;">'date'</span>; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <a href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #000000; font-weight: bold;">function</span> getFieldName<span style="color: #66cc66;">&#40;</span> eZContentClassAttribute <span style="color: #0000ff;">$classAttribute</span>, <span style="color: #0000ff;">$subAttribute</span> = <span style="color: #000000; font-weight: bold;">null</span>, <span style="color: #0000ff;">$context</span> = <span style="color: #ff0000;">'search'</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #b1b100;">switch</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$classAttribute</span>-&gt;<span style="color: #006600;">attribute</span><span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'data_type_string'</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #b1b100;">case</span> <span style="color: #ff0000;">'ezdate'</span> : <span style="color: #66cc66;">&#123;</span> <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$subAttribute</span> and <span style="color: #0000ff;">$subAttribute</span> !== <span style="color: #ff0000;">''</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #808080; font-style: italic;">// A subattribute was passed</span> <span style="color: #b1b100;">return</span> parent::<span style="color: #006600;">generateSubattributeFieldName</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$classAttribute</span>, <span style="color: #0000ff;">$subAttribute</span>, self::<span style="color: #006600;">DEFAULT_SUBATTRIBUTE_TYPE</span> <span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #808080; font-style: italic;">// return the default field name here.</span> <span style="color: #b1b100;">return</span> parent::<span style="color: #006600;">generateAttributeFieldName</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$classAttribute</span>, self::<span style="color: #006600;">getClassAttributeType</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$classAttribute</span>, <span style="color: #000000; font-weight: bold;">null</span>, <span style="color: #0000ff;">$context</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">break</span>; <span style="color: #000000; font-weight: bold;">default</span>: <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">break</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span> &nbsp;</pre><a name="eztoc19872_4" id="eztoc19872_4"></a><h2>Le rôle de la méthode getData</h2><p>Cette méthode est invoquée pour extraire les données d'<b>eZ Publish</b>, et les préparer pour leur indexation vers <b>Solr</b>. C'est donc dans cette méthode que l'on peut ajouter nos champs supplémentaires '<b>year</b>' et '<b>yearmonth</b>'. Pour faciliter la future exploitation de ces champs avec <b>eZ Find</b>, je souhaite pouvoir construire des facettes ou des filtres selon la syntaxe classique :</p> <ul> <li>'<b>mycontentclass/mydateattribute/year</b>', dont la transposition <b>Solr</b> serait '<b>subattr_date-year_dt</b>'</li> <li>'<b>mycontentclass/mydateattribute/yearmonth</b>', dont la transposition <b>Solr</b> serait '<b>subattr_date-yearmonth_dt</b>'</li> </ul> <pre class="php"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getData<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #0000ff;">$contentClassAttribute</span> = <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">ContentObjectAttribute</span>-&gt;<span style="color: #006600;">attribute</span><span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'contentclass_attribute'</span> <span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #b1b100;">switch</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$contentClassAttribute</span>-&gt;<span style="color: #006600;">attribute</span><span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'data_type_string'</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #b1b100;">case</span> <span style="color: #ff0000;">'ezdate'</span> : <span style="color: #66cc66;">&#123;</span> <span style="color: #0000ff;">$returnArray</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #808080; font-style: italic;">// Get timestamp attribute value</span> <span style="color: #0000ff;">$value</span> = <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">ContentObjectAttribute</span>-&gt;<span style="color: #006600;">metaData</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #808080; font-style: italic;">// Generate the main filedName attr_XXX_dt </span> <span style="color: #0000ff;">$fieldName</span> = parent::<span style="color: #006600;">generateAttributeFieldName</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$contentClassAttribute</span>, self::<span style="color: #006600;">DEFAULT_ATTRIBUTE_TYPE</span> <span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #0000ff;">$returnArray</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$fieldName</span><span style="color: #66cc66;">&#93;</span> = parent::<span style="color: #006600;">convertTimestampToDate</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$value</span> <span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #808080; font-style: italic;">// Generate the yearmonth subattribute filedName subattr_year_dt</span> <span style="color: #0000ff;">$fieldName</span> = parent::<span style="color: #006600;">generateSubattributeFieldName</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$contentClassAttribute</span>, <span style="color: #ff0000;">'year'</span>, self::<span style="color: #006600;">DEFAULT_SUBATTRIBUTE_TYPE</span> <span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #0000ff;">$year</span> = <a href="http://www.php.net/date"><span style="color: #000066;">date</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Y&quot;</span>, <span style="color: #0000ff;">$value</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #808080; font-style: italic;">// Get Year value : 2010</span> <span style="color: #0000ff;">$returnArray</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$fieldName</span><span style="color: #66cc66;">&#93;</span> = parent::<span style="color: #006600;">convertTimestampToDate</span><span style="color: #66cc66;">&#40;</span> <a href="http://www.php.net/strtotime"><span style="color: #000066;">strtotime</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$year</span>.<span style="color: #ff0000;">'-01-01'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #808080; font-style: italic;">// Generate the yearmonth subattribute filedName subattr_yearmonth_dt</span> <span style="color: #0000ff;">$fieldName</span> = parent::<span style="color: #006600;">generateSubattributeFieldName</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$contentClassAttribute</span>, <span style="color: #ff0000;">'yearmonth'</span>, self::<span style="color: #006600;">DEFAULT_SUBATTRIBUTE_TYPE</span> <span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #0000ff;">$month</span> = <a href="http://www.php.net/date"><span style="color: #000066;">date</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;n&quot;</span>, <span style="color: #0000ff;">$value</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #808080; font-style: italic;">// Get Month value : 3</span> <span style="color: #0000ff;">$returnArray</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$fieldName</span><span style="color: #66cc66;">&#93;</span> = parent::<span style="color: #006600;">convertTimestampToDate</span><span style="color: #66cc66;">&#40;</span> <a href="http://www.php.net/strtotime"><span style="color: #000066;">strtotime</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$year</span>.<span style="color: #ff0000;">'-'</span>.<span style="color: #0000ff;">$month</span>.<span style="color: #ff0000;">'-01'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>; <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$returnArray</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">break</span>; &nbsp; <span style="color: #000000; font-weight: bold;">default</span>: <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">break</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span> &nbsp;</pre><p><b>A noter :</b> <b>$returnArray</b> contient un tableau à clés, dont voici un exemple de sortie (effectuer avec <a href="http://php.net/manual/fr/function.var-dump.php" target="_blank">var_dump</a>) :</p> <pre class="ini">array<span style="">&#40;</span><span style="">3</span><span style="">&#41;</span> <span style="">&#123;</span> <span style="">&#91;</span><span style="color: #933;">&quot;attr_date_dt&quot;</span><span style="">&#93;</span>=&gt; string<span style="">&#40;</span><span style="">24</span><span style="">&#41;</span> <span style="color: #933;">&quot;2008-12-28T00:00:00.000Z&quot;</span> <span style="">&#91;</span><span style="color: #933;">&quot;subattr_date-year_dt&quot;</span><span style="">&#93;</span>=&gt; string<span style="">&#40;</span><span style="">24</span><span style="">&#41;</span> <span style="color: #933;">&quot;2008-01-01T00:00:00.000Z&quot;</span> <span style="">&#91;</span><span style="color: #933;">&quot;subattr_date-yearmonth_dt&quot;</span><span style="">&#93;</span>=&gt; string<span style="">&#40;</span><span style="">24</span><span style="">&#41;</span> <span style="color: #933;">&quot;2008-12-01T00:00:00.000Z&quot;</span> <span style="">&#125;</span> &nbsp;</pre><p><b>A noter : Solr</b> utilise le format de date <a href="http://fr.wikipedia.org/wiki/ISO_8601" target="_blank">ISO 8601</a>, du type '2010-04-30T00:00:00Z'. La classe parent <b><a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Ftrunk%2Fextension%2Fezfind%2Fclasses%2Fezfsolrdocumentfieldbase.php" target="_blank">ezfSolrDocumentFieldBase</a></b> propose la méthode <b>convertTimestampToDate()</b> pour convertir un format <a href="http://fr.wikipedia.org/wiki/Timestamp" target="_blank">timestamp</a> vers un format <a href="http://fr.wikipedia.org/wiki/ISO_8601" target="_blank">ISO 8601</a>.</p><a name="eztoc19872_5" id="eztoc19872_5"></a><h2>Le template de construction des facettes</h2><p>Nos données par années et par mois-année sont maintenant disponibles. Il ne reste plus qu'à construire nos facettes avec la syntaxe habituelle :</p> <pre class="eztemplate"><span style="color: #D36900;">&#123;</span>def <span style="">$search_yearmonth</span>=<a href="http://ez.no/doc/content/advancedsearch?SearchText=fetch"><span style="color: #008000;">fetch</span></a><span style="color: #D36900;">&#40;</span> ezfind, search, <a href="http://ez.no/doc/content/advancedsearch?SearchText=hash"><span style="color: #804040;">hash</span></a><span style="color: #D36900;">&#40;</span> query , <span style="color: #ff0000;">''</span>, <span style="color: #ff0000;">'facet'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=array"><span style="color: #804040;">array</span></a><span style="color: #D36900;">&#40;</span> <a href="http://ez.no/doc/content/advancedsearch?SearchText=hash"><span style="color: #804040;">hash</span></a><span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">'field'</span>, <span style="color: #ff0000;">'billet/date/year'</span>, <span style="color: #ff0000;">'sort'</span>, <span style="color: #ff0000;">'alpha'</span>, <span style="color: #ff0000;">'limit'</span>, <span style="color: #cc66cc;">20</span> <span style="color: #D36900;">&#41;</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=hash"><span style="color: #804040;">hash</span></a><span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">'field'</span>, <span style="color: #ff0000;">'billet/date/yearmonth'</span>, <span style="color: #ff0000;">'sort'</span>, <span style="color: #ff0000;">'alpha'</span>, <span style="color: #ff0000;">'limit'</span>, <span style="color: #cc66cc;">20</span> <span style="color: #D36900;">&#41;</span> <span style="color: #D36900;">&#41;</span>, <span style="color: #ff0000;">'class_id'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=array"><span style="color: #804040;">array</span></a><span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">'billet'</span><span style="color: #D36900;">&#41;</span>, <span style="color: #ff0000;">'subtree_array'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=array"><span style="color: #804040;">array</span></a><span style="color: #D36900;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #D36900;">&#41;</span> <span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span> &nbsp; <span style="color: #D36900;">&#123;</span>def <span style="">$search_extras_year</span>=<span style="">$search_yearmonth</span><span style="color: #D36900;">&#91;</span><span style="color: #ff0000;">'SearchExtras'</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">nameList</span>|reverse<span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>def <span style="">$search_extras_yearmonth</span>=<span style="">$search_yearmonth</span><span style="color: #D36900;">&#91;</span><span style="color: #ff0000;">'SearchExtras'</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">nameList</span>|reverse<span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>def <span style="">$date_count</span> = <span style="color: #cc66cc;">0</span> <span style="">$date_ts</span> = <span style="color: #cc66cc;">0</span><span style="color: #D36900;">&#125;</span> &nbsp; &lt;li id=&quot;blog_block_10&quot; class=&quot;colonne_block&quot;&gt; &lt;h1&gt;Archives par années :&lt;/h1&gt; &lt;ul class=&quot;<span style="color: #D36900;">&#123;</span><span style="">$current_css</span><span style="color: #D36900;">&#125;</span> list&quot;&gt; <span style="color: #D36900;">&#123;</span>foreach <span style="">$search_extras_year</span> as <span style="">$facetID</span> =&<a href="http://ez.no/doc/content/advancedsearch?SearchText=gt"><span style="color: #0600FF;">gt</span></a>; <span style="">$datevalue</span><span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span><a href="http://ez.no/doc/content/advancedsearch?SearchText=set"><span style="color: #0600FF;">set</span></a> <span style="">$date_count</span> = <span style="">$search_yearmonth</span><span style="color: #D36900;">&#91;</span><span style="color: #ff0000;">'SearchExtras'</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">countList</span><span style="color: #D36900;">&#91;</span><span style="">$facetID</span><span style="color: #D36900;">&#93;</span><span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span><a href="http://ez.no/doc/content/advancedsearch?SearchText=set"><span style="color: #0600FF;">set</span></a> <span style="">$date_ts</span> = <span style="">$datevalue</span>|strtotime<span style="color: #D36900;">&#125;</span> &lt;li&gt;&lt;a href=<span style="color: #D36900;">&#123;</span><a href="http://ez.no/doc/content/advancedsearch?SearchText=concat"><span style="color: #804040;">concat</span></a><span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">'/Blogs/(year)/'</span>,<span style="">$date_ts</span>|datetime<span style="color: #D36900;">&#40;</span> <span style="color: #ff0000;">'custom'</span>, <span style="color: #ff0000;">'%Y'</span> <span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#41;</span>|ezurl<span style="color: #D36900;">&#125;</span> title=&quot;Archives : <span style="color: #D36900;">&#123;</span><span style="">$date_ts</span>|datetime<span style="color: #D36900;">&#40;</span> <span style="color: #ff0000;">'custom'</span>, <span style="color: #ff0000;">'%Y'</span> <span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span> // <span style="color: #D36900;">&#123;</span><span style="">$date_count</span><span style="color: #D36900;">&#125;</span> Billet(s)&quot;&gt;<span style="color: #D36900;">&#123;</span><span style="">$date_ts</span>|datetime<span style="color: #D36900;">&#40;</span> <span style="color: #ff0000;">'custom'</span>, <span style="color: #ff0000;">'%Y'</span> <span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span>&lt;/a&gt;&lt;/li&gt; <span style="color: #D36900;">&#123;</span>/foreach<span style="color: #D36900;">&#125;</span> &lt;/ul&gt; &lt;/li&gt; &lt;li id=&quot;blog_block_11&quot; class=&quot;colonne_block&quot;&gt; &lt;h1&gt;Archives par mois / années :&lt;/h1&gt; &lt;ul class=&quot;<span style="color: #D36900;">&#123;</span><span style="">$current_css</span><span style="color: #D36900;">&#125;</span> list&quot;&gt; <span style="color: #D36900;">&#123;</span>foreach <span style="">$search_extras_yearmonth</span> as <span style="">$facetID</span> =&<a href="http://ez.no/doc/content/advancedsearch?SearchText=gt"><span style="color: #0600FF;">gt</span></a>; <span style="">$datevalue</span><span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span><a href="http://ez.no/doc/content/advancedsearch?SearchText=set"><span style="color: #0600FF;">set</span></a> <span style="">$date_count</span> = <span style="">$search_yearmonth</span><span style="color: #D36900;">&#91;</span><span style="color: #ff0000;">'SearchExtras'</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">countList</span><span style="color: #D36900;">&#91;</span><span style="">$facetID</span><span style="color: #D36900;">&#93;</span><span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span><a href="http://ez.no/doc/content/advancedsearch?SearchText=set"><span style="color: #0600FF;">set</span></a> <span style="">$date_ts</span> = <span style="">$datevalue</span>|strtotime<span style="color: #D36900;">&#125;</span> &lt;li&gt;&lt;a href=<span style="color: #D36900;">&#123;</span><a href="http://ez.no/doc/content/advancedsearch?SearchText=concat"><span style="color: #804040;">concat</span></a><span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">'/Blogs/(year)/'</span>,<span style="">$date_ts</span>|datetime<span style="color: #D36900;">&#40;</span> <span style="color: #ff0000;">'custom'</span>, <span style="color: #ff0000;">'%Y'</span> <span style="color: #D36900;">&#41;</span>,<span style="color: #ff0000;">'/(month)/'</span>,<span style="">$date_ts</span>|datetime<span style="color: #D36900;">&#40;</span> <span style="color: #ff0000;">'custom'</span>, <span style="color: #ff0000;">'%n'</span> <span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#41;</span>|ezurl<span style="color: #D36900;">&#125;</span> title=&quot;Archives : <span style="color: #D36900;">&#123;</span><span style="">$date_ts</span>|datetime<span style="color: #D36900;">&#40;</span> <span style="color: #ff0000;">'custom'</span>, <span style="color: #ff0000;">'%F %Y'</span> <span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span> // <span style="color: #D36900;">&#123;</span><span style="">$date_count</span><span style="color: #D36900;">&#125;</span> Billet(s)&quot;&gt;<span style="color: #D36900;">&#123;</span><span style="">$date_ts</span>|datetime<span style="color: #D36900;">&#40;</span> <span style="color: #ff0000;">'custom'</span>, <span style="color: #ff0000;">'%F %Y'</span> <span style="color: #D36900;">&#41;</span>|upfirst<span style="color: #D36900;">&#125;</span>&lt;/a&gt;&lt;/li&gt; <span style="color: #D36900;">&#123;</span>/foreach<span style="color: #D36900;">&#125;</span> &lt;/ul&gt; &nbsp; &lt;/li&gt; <span style="color: #D36900;">&#123;</span>undef <span style="">$date_ts</span> <span style="">$date_count</span> <span style="">$search_yearmonth</span> <span style="">$search_extras_yearmonth</span><span style="color: #D36900;">&#125;</span> &nbsp;</pre><p><b>A noter : </b>Le <b>fetch</b> proposé est relativement basique, afin de faciliter la compréhension du mécanisme. Il faut bien sur faire évoluer le code pour obtenir le fonctionnel attendu (utiliser les filtres par exemple), mais ce n'est pas l'objet de ce billet puisque la <a href="http://ez.no/doc/extensions/ez_find/upgrading_to_ez_find_2_2" target="_blank">documentation officielle</a> détaille déjà la façon de procéder.</p><p><b>A noter :</b> le '<b>sort</b>', '<b>alpha</b>' ne permet pas réellement de spécifier que l'on souhaite un tri alphabétique. Il s'agit surtout de spécifier que l'on ne souhaite pas un tri par '<b>count</b>' (nombre d'items associés à la facette). Dans ce cas <b>Solr</b> applique un tri automatique '<b>croissant</b>' en fonction de son index et du type de donnée (ce qui explique l'utilisation de l'opérateur <a href="http://ez.no/doc/ez_publish/technical_manual/4_x/reference/template_operators/arrays/reverse" target="_blank">reverse</a> pour obtenir une liste décroissante).</p> Sun, 16 May 2010 13:30:10 +0000 http://gandbox.fr/Blogs/Technologies-Web/Developpement-avance-avec-eZ-Find-partie-2-Indexer-des-champs-supplementaires-dans-Solr Développement avancé avec eZ Find (partie 1 : La gestion des datatypes entre eZ Find & Solr) <div class="object-left"> <p> <a href="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-find-chapter-1/19768-1-fre-FR/eZ-Find-Chapter-1.png" target="_blank"> <img src="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-find-chapter-1/19768-1-fre-FR/eZ-Find-Chapter-1.png" width="185" height="102" style="border: 0px;" alt="eZ Find - Chapter 1" title="eZ Find - Chapter 1" /> </a> </p></div><p>Après 2 billets un peu &quot;rapides&quot; sur <a href="http://ez.no/ezfind" target="_blank">eZ Find</a> et <a href="http://www.gandbox.fr/Blogs/Technologies-Web/eZ-Find-et-la-gestion-des-datatypes" target="_self">la gestion des datatypes</a>, ainsi que <a href="http://www.gandbox.fr/Blogs/Technologies-Web/eZ-Find-et-ses-utilisations-alternatives-Faire-un-nuage-de-tags" target="_self">l'utilisation des facettes pour construire un nuage de tags</a>, voici le premier billet d'une série de tutoriels à propos d'<a href="http://ez.no/ezfind" target="_blank">eZ Find</a>, qui décrivent plus en détail son fonctionnement et son utilisation avancée dans divers contextes. Cette série de tutoriels introduit <b>quelques nouveautés de la version 2.2</b>, sera traduite progressivement sur le <a href="http://share.ez.no/" target="_blank">share.ez.no</a>, et servira de base pour une conférence de la <a href="http://ez.no/company/ez_conference_awards" target="_blank">eZ Conference 2010</a>, ainsi qu'aux <a href="http://2010.rmll.info/Travailler-avec-eZ-Find-et-SolR.html" target="_blank">Recontres Mondiales du Logiciel Libre 2010</a></p><p><b>Cet article décrit comment <a href="http://ez.no/ezfind" target="_blank">eZ Find</a> transforme et adapte les contenus eZ Publish, et leurs datatypes respectifs pour les indexer dans <a href="http://lucene.apache.org/solr/" target="_blank">Solr</a></b>. <b>La compréhension de ces mécanismes bas niveaux d'eZ Find sont des prérequis indispensables lors des phases de développement et de debug, </b>ne serait ce que pour savoir ou chercher et lire les portions de codes permettant de comprendre le rôle exact d'un settings, d'un paramètre ou d'un filtre.</p><a name="eztoc19760_1" id="eztoc19760_1"></a><h2>Etape 1 : Prérequis avant de démarrer</h2><p>Cet article n'a pas vocation à expliquer à nouveau comment installer et indexer son contenu avec eZ Find. La <a href="http://ez.no/doc/extensions/ez_find/2_2" target="_blank">documentation</a> décrit avec précision les opérations à effectuer. Cependant voici quelques astuces permettant de développer dans de bonnes conditions :</p><a name="eztoc19760_1_1" id="eztoc19760_1_1"></a><h3>Relancer l'indexation du contenu après une modification</h3><p>Il est parfois laborieux de relancer une indexation complète juste pour tester l'impact d'une modification mineure. Alors il existe pour cela quelques paramètres cachés dans le script <b>/bin/php/updatesearchindexsolr.php</b>, qui permettent de désigner un noeud parent de départ, ainsi q'une limite (attention les 3 paramètres combinés sont nécessaires) :</p> <pre class="php">php extension/ezfind/bin/php/updatesearchindexsolr.php --siteaccess=monsiteaccess --topNodeID=<span style="color: #cc66cc;">2546</span> --offset=<span style="color: #cc66cc;">0</span> --limit=<span style="color: #cc66cc;">10</span> &nbsp; &nbsp;</pre><a name="eztoc19760_1_2" id="eztoc19760_1_2"></a><h3>Vérifier ce que Solr a réellement indexé</h3> <div class="object-left"> <p> <a href="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/solr-web-administration/19771-1-fre-FR/Solr-Web-administration.png" target="_blank"> <img src="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/solr-web-administration/19771-1-fre-FR/Solr-Web-administration_medium.png" width="200" height="89" style="border: 0px;" alt="Solr - Web administration" title="Solr - Web administration" /> </a> </p></div><p>Pour savoir si vos contenus et vos attributs sont correctement indexés, il suffit d'effectuer une recherche dans l'interface Web d'administration de Solr : <i><b>http://localhost:8983/solr/admin/. </b></i>Cette interface est également utile pour <b>vérifier comment les champs Solr ont été nommés</b>, par exemple sur la version d'<b>eZ Find 2.2</b>, on peut observer 2 champs qui semblent des doublons concernent les titres des articles : <b>attr_title_s</b> et <b>attr_title_t</b>. La suite du billet détaille le comment et le pourquoi de ce comportement.</p><a name="eztoc19760_1_3" id="eztoc19760_1_3"></a><h3>Debug direct avec Solr</h3><p>En laissant une console active, pour pourrez observer les messages envoyés vers <b>Solr</b> de la forme :</p> <pre class="ini">INFO: <span style="">&#91;</span><span style="">&#93;</span> <span style="color: #000099;">webapp</span>=<span style="color: #660066;">/solr path=/select params=<span style="">&#123;</span> ... MESSAGE ... <span style="">&#125;</span> status=<span style="">400</span> QTime=<span style="">5</span></span> &nbsp;</pre> <div class="object-left"> <p> <a href="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-find-console/19774-1-fre-FR/eZ-Find-Console.png" target="_blank"> <img src="http://www.gandbox.fr/var/plain_site/storage/images/media/images/technologie-web/ez-find-console/19774-1-fre-FR/eZ-Find-Console_small.png" width="100" height="61" style="border: 0px;" alt="eZ Find - Console" title="eZ Find - Console" /> </a> </p></div><p>Ce message peut être copier / coller à partir de la console, vers la fin de l'URL dans l'interfaçe d'administration de Solr :<i><b> http://localhost:8983/solr/select/?MESSAGE. </b></i>On obtient ainsi <b>une sortie exacte de ce que Solr envois à eZ Find avant transformation</b>. Cette manipulation est utile lors des phases de Debug, par exemple en manipulant directement le message pour obtenir exactement le résultat attendu.</p><a name="eztoc19760_2" id="eztoc19760_2"></a><h2>Etape 2 : Comment eZ Find pousse le contenu eZ Publish vers Solr</h2><p>Voici le parcours d'exécution du code lors de l'ajout / modification d'un contenu <b>eZ Publish</b> :</p> <ul> <li> Exécution de la méthode <b>registerSearchObject</b>, de la classe <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=nextgen&amp;path=%2Ftrunk%2Fkernel%2Fcontent%2Fezcontentoperationcollection.php" target="_blank">eZContentOperationCollection</a> <br />Si <b>DelayedIndexing</b> activé (voir détail ci dessous) : ajout d'objectID à la table '<b>ezpending_actions</b>' pour un traitement ultérieur</li> <li>Si <b>DelayedIndexing </b>désactivé, fetch de l'objet et transmission de l'objet à la méthode <b>eZSearch::addObject( $object, $needCommit )</b></li> <li><b>Si eZ Find installé et activé</b>, appel de la méthode <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Fstable%2F2.2%2Fextension%2Fezfind%2Fsearch%2Fplugins%2Fezsolr%2Fezsolr.php" target="_blank"><b>eZSolr::addObject( $contentObject, $commit = true )</b></a></li> <li>Au final, une fois les contenus préparés, appel de la méthode <b>addDocs</b> de la classe<b> <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Ftrunk%2Fextension%2Fezfind%2Fclasses%2Fezsolrbase.php" target="_blank">/extension/ezfind/classes/ezsolrbase.php</a></b>, qui <b>POST</b> ensuite les données via <b>HTTP</b> à l'aide de <a href="http://php.net/manual/fr/ref.curl.php" target="_blank">cURL</a></li> </ul> <a name="eztoc19760_2_4" id="eztoc19760_2_4"></a><h3>eZ Find, un plug-in de recherche</h3><p><b>eZ Find</b> est construit comme un <b>plug-in de recherche</b>, c'est à dire que le module<i> <b>/content/search</b></i><b> </b>a été nativement construit pour être déporté sous forme de plug-in. Ainsi dans l'extension <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Fstable%2F2.2%2Fextension%2Fezfind%2Fsettings%2Fsite.ini.append.php" target="_blank">/ezfind/settings/site.ini.append.php</a> on trouve la déclaration du plug-in :</p> <pre class="ini"><span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>SearchSettings<span style="">&#93;</span></span> <span style="color: #000099;">SearchEngine</span>=<span style="color: #660066;">ezsolr</span> &nbsp; &nbsp;</pre><p>C'est ensuite la méthode <a href="http://pubsvn.ez.no/doxygen/4.0/html/ezsearch_8php_source.html#l00399" target="_blank">getEngine()</a> (<i>kernel/classes/ezsearch.php</i>) qui s'occupe d'affecter la bonne classe PHP pour interfacer le plug-in de recherche, à savoir : <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Fstable%2F2.2%2Fextension%2Fezfind%2Fsearch%2Fplugins%2Fezsolr%2Fezsolr.php" target="_blank">/search/plugins/ezsolr/ezsolr.php</a></p><a name="eztoc19760_2_5" id="eztoc19760_2_5"></a><h3>eZ Find et le mécanisme natif du DelayedIndexing</h3><p>Lors des différentes opérations de mises à jours de contenus, <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Fstable%2F2.2%2Fextension%2Fezfind%2Fsearch%2Fplugins%2Fezsolr%2Fezsolr.php" target="_blank">la méthode <b>addObject</b> de la classe <b>eZSolr</b></a> sera invoqué. Ce mode de fonctionnement en plug-in permet également d'hériter des autres mécanismes natifs de la recherche<b> eZ Publish</b>, comme par exemple le <b>DelayedIndexing</b>, qui permet de déporter l'indexation (complète ou par classes) vers une tache planifiée : <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=nextgen&amp;path=%2Ftrunk%2Fcronjobs%2Findexcontent.php" target="_blank">indexcontent.php</a> : </p> <pre class="ini"><span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>SearchSettings<span style="">&#93;</span></span> <span style="color: #000099;">DelayedIndexing</span>=<span style="color: #660066;">disabled|enabled|classbased</span> DelayedIndexingClassList<span style="">&#91;</span><span style="">&#93;</span> DelayedIndexingClassList<span style="">&#91;</span><span style="">&#93;</span>=mycontentclass &nbsp;</pre><p><b>A noter : </b>Cette technique est relativement efficace pour optimiser les temps de réponses Back Office, ou les imports de contenus régulier. Cependant, le <b>DelayedIndexing</b> souffre de quelques limites, puisqu'il est générique (et non optimisé spécifiquement pour <b>eZ Find</b>) et qu'il se contente donc de boucler sur la table '<b>ezpending_actions</b>' afin d'indexer les objets un par un sans se préoccuper des autres finesses de <a href="http://lucene.apache.org/solr/" target="_blank">Solr</a>, comme par exemple l'ajout massif de contenus à indexer, suivi d'un unique '<i>commit</i>'.</p><a name="eztoc19760_3" id="eztoc19760_3"></a><h2>Etape 3 : Le fonctionnement de la méthode addObject</h2><p>La méthode <b>addObject</b> (<a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Fstable%2F2.2%2Fextension%2Fezfind%2Fsearch%2Fplugins%2Fezsolr%2Fezsolr.php" target="_blank">/search/plugins/ezsolr/ezsolr.php</a>) reçoit :</p> <ul> <li>un unique objet de contenu en paramètre</li> <li>un paramètre optionnel indiquant s'il faut 'commiter' ou non le contenu ajouté (une très bonne façon d'optimiser les indexations massives de contenus)</li> </ul> <p>Cette méthode agit de la façon suivante, dans les grandes lignes :</p> <ul> <li>Vérification s'il faut indexer ou non le contenu, en fonction des classes exclues (settings : [<b>IndexExclude</b>])</li> <li>Récupération des <b>méta données de l'objet</b>, et création des noms et valeurs des champs pour Solr</li> <li>Récupération des <b>méta données des noeuds</b>, et création des noms et valeurs des champs pour Solr</li> <li>Récupération des <b>données des attributs de l'objet</b>, dans chacune des langues, et création des noms et valeurs des champs pour Solr</li> <li>Insertion dans l'index de Solr de l'ensemble des données collectées, en mono ou multicore selon les settings</li> <li><b>Commit final</b>, en fonction du paramètre optionnel de la méthode <b>addObject</b></li> </ul> <p><b>A noter :</b> Depuis <b>eZ Find 2.2</b>, il est possible d'utiliser des 'cores' spécifiques à chaque langues (<i>/extension/ezfind/java/solr.multicore</i>), ce qui permet de dédier des index et des fichiers de configurations spécifiques à chaque langue (spellings.txt, synonmys.txt, stopwords.txt, etc.)</p><a name="eztoc19760_4" id="eztoc19760_4"></a><h2>Etape 4 : Les nommage des champs côté Solr</h2><p> Il est nécessaire de revenir sur <b>la façon dont eZ Find nomme les champs transmis à Solr</b>. Les principales techniques d'exploitations avancées d'<b>eZ Find</b> pour <b>eZ Publish</b> nécessitent de bien comprendre la sémantique et le mécanisme de nommage des champs.<br />C'est la classe <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Fstable%2F2.2%2Fextension%2Fezfind%2Fclasses%2Fezfsolrdocumentfieldbase.php" target="_blank">/ezfind/classes/ezfsolrdocumentfieldbase.php</a>, ou d'éventuelles classes héritées pour certains datatypes complexes (voir ma contribution <a href="http://svn.projects.ez.no/ezfsolrdocumentfieldobjectrelation/ezfind2.2/ezfsolrdocumentfieldobjectrelation.php" target="_blank">ezfsolrdocumentfieldobjectrelation</a> par exemple) qui a vocation à créer les noms des champs pour <b>Solr</b>, en respectant une sémantique très précise. On obtient ainsi la sémantique suivante :</p><p><b>Le nom des attributs :</b></p> <ul> <li>Nom Solr : <b>attr_[contentattributename]_[contentattributetype], </b>exemple : <b>'attr_title_s'</b>. Il faut noter l'absence de l'identifiant de la classe, ce qui ouvre des perspectives d'exploitation des attributs Solr pour <b>filtrer plusieurs classes sur des attributs homonymes</b> (l'objet d'un prochain billet).</li> <li> Mapping dans un Fetch eZ Find (filtre par exemple) : <b>[contentclassname]/[contentattributename]/[contentsubattributename]</b>, par exemple <b>'article/title'</b>. <br />Le nom de la classe <b>'article'</b> est utilisé comme un filtre supplémentaire lors de la construction de la requête</li> <li>Le <b>'title'</b> est tranformé en <b>'attr_title_s'</b>, le <b>_s</b> étant déduit de settings eZ Find (voir ci-dessous)</li> </ul> <p><b>Le nom des métadonnées :</b></p> <ul> <li>Nom Solr : <b>meta_[metadataname]_[metadatatype]</b>, exemple : <b>meta_class_identifier_s</b></li> <li>Mapping dans un Fetch eZ Find (tri par exemple) : usage interne, par exemple pour un tri par 'class_identifier'</li> </ul> <p><b>Le nom des sous-attributs (inexploité par défaut) :</b></p> <ul> <li>Nom Solr :<b> subattr_[contentattributename]-[contentsubattributename]_[contentsubattributetype]</b>, example : <b>subattr_relatedimage-alttext_s</b></li> </ul> <p><b>Nativement, les sous attributs sont peu ou pas exploités. C'est par contre un formidable outil pour étendre le fonctionnement d'eZ Find et indexer des champs supplémentaire</b>. Voir par exemple ma contribution : <a href="http://projects.ez.no/ezfsolrdocumentfieldobjectrelation" target="_blank">ezfsolrdocumentfieldobjectrelation</a>, qui indexe tous les attributs des objets en relations, en les stockant dans des sous attributs, ce qui permet ensuite d'effectuer toutes les opérations nécessaires sur ces sous attributs (recherche, filtre, facettes), selon la syntaxe <b>'myclass/myattribute/mysubattribute'</b>. Les prochains billets détailleront comment exploiter ce mécanisme pour bien d'autres usages.</p><a name="eztoc19760_5" id="eztoc19760_5"></a><h2>Etape 5 : La gestion des types de champs côté eZ Find</h2><p> Dans les noms de champs <b>Solr</b>, <b>la dernière information désigne le type de champs</b>, et donc comment Solr va devoir considérer l'information (entre un string, un texte, une date, un tableau, etc.)<br />Coté eZ Find, cette définition se fait comme toujours dans les settings. <b>Depuis eZ Find 2.2, il est maintenant possible de définir un type de champs spécifique à chaque contexte d'utilisation :</b></p> <ul> <li><b>DatatypeMap[] : </b>le setting global, s'appliquant à tous les contextes par défaut</li> <li><b>DatatypeMapSort[] :</b> settings spécifique pour les tris</li> <li><b>DatatypeMapFacet[] :</b> settings spécifique pour les facettes</li> <li><b>DatatypeMapFilter[] :</b> settings spécifique pour les filtres</li> </ul> <p>Par exemple, par défaut, dans la version actuelle d'eZ Find 2.2, les attributs de type 'textline' sont définis différemment pour les tris :</p> <ul> <li><b>DatatypeMap[ezstring]=text</b></li> <li><b>DatatypeMapSort[ezstring]=string</b></li> </ul> <p>L'impact au niveau de <b>Solr</b>, c'est que tous les attributs de type 'textline' auront systématiquement 2 champs de correspondance :</p> <ul> <li><b>attr_title_t</b> (utilisé pour la recherche, les facettes et les filtres)</li> <li><b>attr_title_s</b> (utilisé pour les tris)</li> </ul> <p><b>A noter :</b> il est conseillé d'utiliser également le type '<b>string</b>' pour les facettes, afin de considérer le caractère espace comme un caractère lambda, et ainsi obtenir des facettes de type '<b>ma facette</b>', plutôt que '<b>ma</b>' et '<b>facette</b>'.</p><a name="eztoc19760_6" id="eztoc19760_6"></a><h2>Etape 6 : La gestion des types de champs côté Solr</h2><p> <b>Solr</b> possède un fichier de configuration permettant à <b>eZ Find</b> de lui spécifier que le <b>'_s'</b> signifie un <b>string</b>, le <b>'_t'</b> un <b>texte</b>, etc. Il s'agit du fichier <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezfind%2Fezp4%2Fstable%2F2.2%2Fextension%2Fezfind%2Fjava%2Fsolr%2Fconf%2Fschema.xml" target="_blank">/ezfind/java/solr/conf/schema.xml</a><br />Ce fichier de configuration contient la définition d'un certain nombre de noms de champs en dur (pour les meta-données par exemple), mais définie également les correspondances pour tous les noms de champs dynamiques (nos fameux attributs de classes <b>eZ Publish</b>) :</p> <pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_i&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;int&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_f&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;float&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_d&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;double&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_si&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;sint&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_sf&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;sfloat&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_sd&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;sdouble&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_s&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;string&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">termVectors</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_sl&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;slong&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_l&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;long&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_t&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">termVectors</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_b&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;boolean&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_dt&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;date&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_random&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;random&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_k&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;keyword&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_lk&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;lckeyword&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">multiValued</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!-- some trie-coded dynamic fields for faster range queries --&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_ti&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;tint&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_tl&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;tlong&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_tf&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;tfloat&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_td&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;tdouble&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_tdt&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;tdate&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!-- geopoint for geospatial/location searches, boosting, ... --&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dynamicField</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;*_gpt&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;geopoint&quot;</span> <span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> &nbsp;</pre><p><b>Ce fichier permet aussi de définir des comportements plus complexes sur certains datatypes eZ Publish</b>, comme par exemple les mots clés (<b>keyword</b>). On y trouve par exemple 2 types de champs différents pour la gestion des keywords ('<b>keyword</b>' pour un respect de la casse et '<b>lckeyword</b>' pour une casse en lowercase), qui peuvent etre exploité indifféremment au niveau d'eZ Find (<b>DatatypeMap</b>).</p> <pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;fieldtype</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;lckeyword&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.TextField&quot;</span> <span style="color: #000066;">positionIncrementGap</span>=<span style="color: #ff0000;">&quot;100&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;analyzer</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;index&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;tokenizer</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.PatternTokenizerFactory&quot;</span> <span style="color: #000066;">pattern</span>=<span style="color: #ff0000;">&quot;, *&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.TrimFilterFactory&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.StopFilterFactory&quot;</span> <span style="color: #000066;">ignoreCase</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">words</span>=<span style="color: #ff0000;">&quot;stopwords.txt&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.LowerCaseFilterFactory&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.RemoveDuplicatesTokenFilterFactory&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/analyzer<span style="font-weight: bold; color: black;">&gt;</span></span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;analyzer</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;query&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;tokenizer</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.PatternTokenizerFactory&quot;</span> <span style="color: #000066;">pattern</span>=<span style="color: #ff0000;">&quot;, *&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.TrimFilterFactory&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.SynonymFilterFactory&quot;</span> <span style="color: #000066;">synonyms</span>=<span style="color: #ff0000;">&quot;synonyms.txt&quot;</span> <span style="color: #000066;">ignoreCase</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">expand</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.StopFilterFactory&quot;</span> <span style="color: #000066;">ignoreCase</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">words</span>=<span style="color: #ff0000;">&quot;stopwords.txt&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.LowerCaseFilterFactory&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.RemoveDuplicatesTokenFilterFactory&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/analyzer<span style="font-weight: bold; color: black;">&gt;</span></span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/fieldtype<span style="font-weight: bold; color: black;">&gt;</span></span></span> &nbsp;</pre><p>La définition des keywords est riche d'enseignement sur la configuration de Solr. On peut observer le fonctionnement des appels des <b>filtres Solr</b>, et comment sont traités les séparations de mots par des virgules (<b>PatternTokenizerFactory</b>), la gestion de la casse (<b>LowerCaseFilterFactory</b>), ou encore la suppression des doublons (<b>RemoveDuplicatesTokenFilterFactory</b>), etc.</p> Sun, 09 May 2010 13:07:06 +0000 http://gandbox.fr/Blogs/Technologies-Web/Developpement-avance-avec-eZ-Find-partie-1-La-gestion-des-datatypes-entre-eZ-Find-Solr eZ Find et ses utilisations alternatives : Faire un nuage de tags <div class="object-left"> <p> <a href="http://ez.no/ezfind" target="_blank"> <img src="http://www.gandbox.fr/var/plain_site/storage/images/media/images/ez-find-logo/19256-1-fre-FR/eZ-Find-Logo.png" width="183" height="32" style="border: 0px;" alt="eZ Find Logo" title="eZ Find Logo" /> </a> </p></div><p><b><a href="http://ez.no/ezfind" target="_blank">eZ Find</a> est une extension native d'eZ Publish</b>, maintenant disponible dans les diverses installations du <b>CMS</b>. Mon précédent billet donne une courte définition du fonctionnement d'<b>eZ Find</b>, de son couplage avec <b>Solr</b>, et de sa relation avec les <b>datatypes</b>.</p><p><b>eZ Find</b> est généralement présenté et vendu comme un moteur de recherche, et les utilisateurs (et développeurs) peuvent donc s'attendre à un mécanisme du type :</p> <ul> <li>Je saisie une expression libre</li> <li>J'envoie ma recherche</li> <li>J'obtiens une liste de résultat, et j'applique quelques tris (alphabétique, dates, pertinence) et quelques filtres disponibles (par rubriques, par <a href="http://fr.wikipedia.org/wiki/Classification_%C3%A0_facettes" target="_blank">facettes</a>, etc.) </li> </ul> <p><b>Cependant, le cadre d'exploitation d'eZ Find est plus vaste que ce schéma fonctionnel. Ce billet décrit un cas d'utilisation certes relativement inutile mais signification d'une utilisation alternative d'eZ Find : construire un nuage de tags</b>.</p><p>A partir d'un exemple simple, on peut facilement en déduire d'autres cas d'utilisation qui facilitent énormément le développement de certains projets, comme par exemple les agrégateurs de contenus, les portails et autres mécanismes de navigations complexes dans un catalogue.</p><a name="eztoc19248_1" id="eztoc19248_1"></a><h2>Comment construire un nuage de tags sur eZ Publish ? </h2><p>La seule méthode un peu optimisée et fonctionnelle de procéder actuellement est l'utilisation d'un <a href="http://ezpedia.org/ez/template_operators" target="_blank">opérateur de template</a> qui explore la base de données, et notamment la table <b>ezkeyword</b>. Le package <a href="http://ez.no/download/ez_publish/ez_publish_4_stable_releases/4_0/packages/4_0_3" target="_blank">ezwebin</a> propose l'opérateur <b>eztagcloud</b>, qui est facile à déployer et à utiliser.</p> <ul> <li>Voici <b>un exemple d'appel de l'opérateur dans un template</b></li> </ul> <pre class="eztemplate">&lt;div&gt; <span style="color: #D36900;">&#123;</span>eztagcloud<span style="color: #D36900;">&#40;</span> <a href="http://ez.no/doc/content/advancedsearch?SearchText=hash"><span style="color: #804040;">hash</span></a><span style="color: #D36900;">&#40;</span> <span style="color: #ff0000;">'class_identifier'</span>, <span style="color: #ff0000;">'billet'</span>, <span style="color: #ff0000;">'parent_node_id'</span>, <span style="color: #cc66cc;">2</span> <span style="color: #D36900;">&#41;</span> <span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span> &lt;/div&gt; &nbsp;</pre> <ul> <li>Voici <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezwebin%2Ftrunk%2Fpackages%2Fezwebin_extension%2Fezextension%2Fezwebin%2Fautoloads%2Feztagcloud.php" target="_blank">le code de l'opérateur eztagcloud</a></li> <li>Voici <a href="http://pubsvn.ez.no/websvn2/filedetails.php?repname=ez_extensions&amp;path=%2Fezwebin%2Ftrunk%2Fpackages%2Fezwebin_extension%2Fezextension%2Fezwebin%2Fdesign%2Fezwebin%2Ftemplates%2Ftagcloud%2Ftagcloud.tpl" target="_blank">le code du template tagcloud.tpl</a> associé à l'opérateur (que l'on peut donc surcharger)</li> </ul> <a name="eztoc19248_1_1" id="eztoc19248_1_1"></a><h3>Avantages de l'opérateur</h3><p>Les <a href="http://ez.no/doc/ez_publish/technical_manual/4_x/reference/template_fetch_functions" target="_blank">fonctions fetch natives</a> ne permettent pas de lister un ensemble de keywords en fonction des paramètres utiles (subtree, classes, etc.), c'est donc la seule façon &quot;économique&quot; et &quot;optimisée&quot; de procéder. <b>Les opérateurs permettent souvent aux développeurs eZ Publish avancés d'optimiser certains traitements</b>, en économisant le nombre de requêtes SQL par exemple, ou en facilitant certains algorithmes laborieux à transposer avec le langage de template (par exemple le calcul des pourcentages des styles CSS inline dans cet opérateur)</p><a name="eztoc19248_1_2" id="eztoc19248_1_2"></a><h3>Inconvénients de l'opérateur</h3><p><b>L'écriture de ce type d'opérateur est peu accessible aux développeurs occasionnels</b>, et la manipulation du SQL est une pratique dangereuse si le modèle de données eZ Publish est mal maîtrisé (prise en compte des versions, des visibilités, des langues, des droits...). Par ailleurs cet opérateur encapsule la logique algorithmique du calcul des pourcentages transmis au &quot;<i>font-size</i>&quot; en style inline. Les amoureux du CSS full externe, ou de l'accessibilité devront donc adapter cet opérateur à leur besoin.</p><a name="eztoc19248_2" id="eztoc19248_2"></a><h2>Comment construire un nuage de tags avec eZ Find ? </h2><a name="eztoc19248_2_3" id="eztoc19248_2_3"></a><h3>Comprendre le concept de facettes</h3><p>Derrière ce terme &quot;géométrique&quot; se cache un concept finalement assez simple et naturel, que l'on pourrait appeler : &quot;<b>groupement des résultats pour un champs</b>&quot;, à savoir : </p> <ul> <li>Supposons qu'un résultat de recherche contienne 100 billets</li> <li>Sur ces 100 billets, on peut lister 20 mots clés distincts associés</li> <li>Parmi ces 20 mots clés, le mot clés A est associé à 10 billets, le mot clés B est associé à 5 billets, et ainsi dessuite </li> </ul> <p>On peut transposer cet exemple sur tous les attributs et meta données d'une classe (name, dates, auteur, attribut quelconque), et même obtenir N listes de facettes sur N attributs et méta différents </p><a name="eztoc19248_2_4" id="eztoc19248_2_4"></a><h3>Construite le nuage de mots clés avec des facettes </h3><p>Cet exemple de code montre comment construire sa requête <b>eZ Find</b>, récupérer les <b>facettes</b> résultantes sur l'attribut &quot;<i>tags</i>&quot; de type &quot;<a href="http://ez.no/doc/ez_publish/technical_manual/4_x/reference/datatypes/keywords" target="_blank">keywords</a>&quot;, et gérer le poids des keywords en fonction d'un algorithme simplifié (j'ai un peu triché sur cet aspect, puisque ce n'est pas l'objet de la démonstration). </p> <pre class="eztemplate"><span style="color: #D36900;">&#123;</span>def <span style="">$search_keywords</span>=<a href="http://ez.no/doc/content/advancedsearch?SearchText=fetch"><span style="color: #008000;">fetch</span></a><span style="color: #D36900;">&#40;</span> ezfind , search, <a href="http://ez.no/doc/content/advancedsearch?SearchText=hash"><span style="color: #804040;">hash</span></a><span style="color: #D36900;">&#40;</span> query , <span style="color: #ff0000;">''</span>, <span style="color: #ff0000;">'facet'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=array"><span style="color: #804040;">array</span></a><span style="color: #D36900;">&#40;</span> <a href="http://ez.no/doc/content/advancedsearch?SearchText=hash"><span style="color: #804040;">hash</span></a><span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">'field'</span>, <span style="color: #ff0000;">'billet/tags'</span>, <span style="color: #ff0000;">'sort'</span>, <span style="color: #ff0000;">'alpha'</span>, <span style="color: #ff0000;">'limit'</span>, <span style="color: #cc66cc;">100</span> <span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#41;</span>, <span style="color: #ff0000;">'class_id'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=array"><span style="color: #804040;">array</span></a><span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">'billet'</span><span style="color: #D36900;">&#41;</span>, <span style="color: #ff0000;">'filter'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=array"><span style="color: #804040;">array</span></a><span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">'not'</span>, <span style="color: #ff0000;">'billet/tags:&quot;&quot;'</span><span style="color: #D36900;">&#41;</span>, <span style="color: #ff0000;">'subtree_array'</span>, <a href="http://ez.no/doc/content/advancedsearch?SearchText=array"><span style="color: #804040;">array</span></a><span style="color: #D36900;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #D36900;">&#41;</span> <span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>def <span style="">$search_extras_keywords</span>=<span style="">$search_keywords</span><span style="color: #D36900;">&#91;</span><span style="color: #ff0000;">'SearchExtras'</span><span style="color: #D36900;">&#93;</span><span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>def <span style="">$search_count_keywords</span>=<span style="">$search_keywords</span><span style="color: #D36900;">&#91;</span><span style="color: #ff0000;">'SearchCount'</span><span style="color: #D36900;">&#93;</span><span style="color: #D36900;">&#125;</span> &nbsp; &lt;li id=&quot;blog_block_<span style="color: #D36900;">&#123;</span><span style="">$bloc_count</span><span style="color: #D36900;">&#125;</span>&quot; class=&quot;colonne_block&quot;&gt; &lt;h1&gt;Tags ezfind :&lt;/h1&gt; &lt;div class=&quot;tagclouds <span style="color: #D36900;">&#123;</span><span style="">$current_css</span><span style="color: #D36900;">&#125;</span>&quot;&gt; <span style="color: #D36900;">&#123;</span>foreach <span style="">$search_extras_keywords</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">nameList</span> as <span style="">$facetID</span> =&<a href="http://ez.no/doc/content/advancedsearch?SearchText=gt"><span style="color: #0600FF;">gt</span></a>; <span style="">$name</span><span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>def <span style="">$keyword_count</span> = <span style="">$search_extras_keywords</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">countList</span><span style="color: #D36900;">&#91;</span><span style="">$facetID</span><span style="color: #D36900;">&#93;</span><span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>def <span style="">$percent</span> = <span style="">$keyword_count</span>|div<span style="color: #D36900;">&#40;</span> <span style="">$search_count_keywords</span> <span style="color: #D36900;">&#41;</span>|mul<span style="color: #D36900;">&#40;</span> <span style="color: #cc66cc;">200</span> <span style="color: #D36900;">&#41;</span>|floor|sum<span style="color: #D36900;">&#40;</span> <span style="color: #cc66cc;">100</span> <span style="color: #D36900;">&#41;</span> <span style="color: #D36900;">&#125;</span> &lt;a href=<span style="color: #D36900;">&#123;</span><a href="http://ez.no/doc/content/advancedsearch?SearchText=concat"><span style="color: #804040;">concat</span></a><span style="color: #D36900;">&#40;</span> <span style="">$root_blog_node</span>.<span style="color: #006600;">url_alias</span>, <span style="color: #ff0000;">'/(tag)/'</span>, <span style="">$name</span> <span style="color: #D36900;">&#41;</span>|ezurl<span style="color: #D36900;">&#40;</span><span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span> style=&quot;font-size: <span style="color: #D36900;">&#123;</span><span style="">$percent</span><span style="color: #D36900;">&#125;</span>%&quot; title=&quot;<span style="color: #D36900;">&#123;</span><span style="">$keyword_count</span><span style="color: #D36900;">&#125;</span> billets taggés '<span style="color: #D36900;">&#123;</span><span style="">$name</span><span style="color: #D36900;">&#125;</span>' // &quot;&gt;<span style="color: #D36900;">&#123;</span><span style="">$name</span>|wash<span style="color: #D36900;">&#40;</span><span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span>&lt;/a&gt;, <span style="color: #D36900;">&#123;</span>undef <span style="">$percent</span><span style="color: #D36900;">&#125;</span> &nbsp; <span style="color: #D36900;">&#123;</span>/foreach<span style="color: #D36900;">&#125;</span> &nbsp; &lt;/div&gt; &lt;/li&gt; <span style="color: #D36900;">&#123;</span>undef <span style="">$search_extras_keywords</span> <span style="">$search_keywords</span> <span style="">$search_count_keywords</span><span style="color: #D36900;">&#125;</span> &nbsp;</pre><a name="eztoc19248_3" id="eztoc19248_3"></a><h2>Quelques astuces &amp; clés de compréhensions</h2> <ul> <li><b>La recherche sur une chaine vide (query , '')</b> est une technique permettant d'explorer l'ensemble des contenus indexés, en appliquant uniquement les filtres et limitations utiles (<i>class_id</i>, <i>subtree_array</i> par exemple)</li> <li>L'opérateur '<b>NOT</b>' n'est pas natif et nécessite <a href="http://www.stuffandcontent.com/2009/10/adding-negative-filters-to-ez-find.html" target="_blank">un petit '<i>hack</i>' proposé par Bruce Morrison</a>, qui sera sans doute disponible dans les futures versions d'eZ Find</li> <li><b>Par défaut les facettes sur des datatypes 'keywords' sont présentés en minuscule</b>. Ce n'est pas un bug, mais une fonctionnalité visant à homogénéiser la <i>casse</i> sur les syntaxes similaires (eZ Publish, ez Publish, Ez Publish, etc.). Cependant lorsqu'on est confiant dans la qualité de sa saisie (puisqu'on utilise <a href="http://projects.ez.no/ezkeyword_autocomplete" target="_blank">une extension d'autocomplétion</a> par exemple), il peut être souhaitable de ne pas forcer l'utilisation du minuscule. Pour cela il faut désactiver le filtre <i>solr.LowerCaseFilterFactory</i> dans le fichier<b> <i>/extension/ezfind/java/solr/conf/schema.xml</i></b></li> </ul> <pre class="xml"><span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!-- eZ Find: This field type is dedicated to ez publish keywords. --&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;fieldtype</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;keyword&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.TextField&quot;</span> <span style="color: #000066;">positionIncrementGap</span>=<span style="color: #ff0000;">&quot;100&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;analyzer</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;index&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;tokenizer</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.PatternTokenizerFactory&quot;</span> <span style="color: #000066;">pattern</span>=<span style="color: #ff0000;">&quot;, *&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.TrimFilterFactory&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.StopFilterFactory&quot;</span> <span style="color: #000066;">ignoreCase</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">words</span>=<span style="color: #ff0000;">&quot;stopwords.txt&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!--&lt;filter class=&quot;solr.LowerCaseFilterFactory&quot;/&gt;</span></span>--&gt; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.RemoveDuplicatesTokenFilterFactory&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/analyzer<span style="font-weight: bold; color: black;">&gt;</span></span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;analyzer</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;query&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;tokenizer</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.PatternTokenizerFactory&quot;</span> <span style="color: #000066;">pattern</span>=<span style="color: #ff0000;">&quot;, *&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.TrimFilterFactory&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.SynonymFilterFactory&quot;</span> <span style="color: #000066;">synonyms</span>=<span style="color: #ff0000;">&quot;synonyms.txt&quot;</span> <span style="color: #000066;">ignoreCase</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">expand</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.StopFilterFactory&quot;</span> <span style="color: #000066;">ignoreCase</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000066;">words</span>=<span style="color: #ff0000;">&quot;stopwords.txt&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.LowerCaseFilterFactory&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;filter</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;solr.RemoveDuplicatesTokenFilterFactory&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/analyzer<span style="font-weight: bold; color: black;">&gt;</span></span></span> <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/fieldtype<span style="font-weight: bold; color: black;">&gt;</span></span></span> &nbsp;</pre> Mon, 22 Feb 2010 23:11:18 +0000 http://gandbox.fr/Blogs/Technologies-Web/eZ-Find-et-ses-utilisations-alternatives-Faire-un-nuage-de-tags My gandbox.fr's slides talk from the 2010 eZ Community Day in Geneva <p>On <b>2010 January 21</b>, for the <a href="http://share.ez.no/blogs/ez/community-day-at-the-ez-international-winter-conference-2010-in-geneva" target="_blank">eZ Community Day in Geneva</a>, i <i><b>tried</b></i> to tanslate in english language some of my &quot;<b>french</b>&quot; blog posts i write on <a href="http://www.gandbox.fr/" target="_self">http://www.gandbox.fr</a>. There is my &quot;<b><i>english</i></b>&quot; slides from this talk :</p> <ul> <li><a href="/content/download/3380/19094/version/1/file/100116_eZCommunity_Widget_V1.0.pdf" target="_self" class="download">Download the PDF version (1.6 Mo)</a></li> <li><a href="http://www.gandbox.fr/Blogs/Technologies-Web/My-gandbox.fr-s-slides-talk-from-the-2010-eZ-Community-Day-in-Geneva#slideshare" target="_self">Slideshare version</a></li> </ul> <a name="eztoc19098_1" id="eztoc19098_1"></a><h2>List of the french blog post i used for my talk</h2><p><b>Working with Google Maps :</b></p> <ul> <li><a href="http://www.gandbox.fr/Blogs/Technologies-Web/Ma-cave-sur-eZ-Publish-Google-Maps-Partie-3" target="_self">Ma cave sur eZ Publish : Google Maps (Partie 3)</a></li> </ul> <p><b>Building an UWA Widget (Netvibes / iGoogle) :</b></p> <ul> <li><a href="http://www.gandbox.fr/Blogs/Technologies-Web/Faire-un-Widget-Netvibes-iGoogle-avec-UWA-AJAX-eZ-Publish-Introduction-a-UWA-Partie-1" target="_self">Faire un Widget Netvibes &amp; iGoogle avec UWA, AJAX &amp; eZ Publish : Introduction à UWA (Partie 1)</a></li> <li><a href="http://www.gandbox.fr/Blogs/Technologies-Web/Faire-un-Widget-Netvibes-iGoogle-avec-UWA-AJAX-eZ-Publish-La-couche-eZ-Publish-Partie-2" target="_self">Faire un Widget Netvibes &amp; iGoogle avec UWA, AJAX &amp; eZ Publish : La couche eZ Publish (Partie 2)</a></li> </ul> <p><b>Building a custom RSS</b> :</p> <ul> <li><a href="http://www.gandbox.fr/Blogs/Technologies-Web/Un-flux-RSS-par-Keyword-ou-autre-sur-eZ-Publish" target="_self">Un flux RSS par Keyword (ou autre) sur eZ Publish</a></li> </ul> <a name="eztoc19098_2" id="eztoc19098_2"></a><h2> <a name='slideshare'></a>Slideshare presentation</h2><div class="video"> <object width="600" height="450" type="application/x-shockwave-flash" data="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=100116ezcommunitywidgetv1-0-100124102940-phpapp02&amp;rel=0&amp;stripped_title=ez-community-gandboxfr"> <param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=100116ezcommunitywidgetv1-0-100124102940-phpapp02&amp;rel=0&amp;stripped_title=ez-community-gandboxfr"></param> <param name="allowfullscreen" value="true"></param> </object> </div> Sun, 24 Jan 2010 21:08:13 +0000 http://gandbox.fr/Blogs/Technologies-Web/My-gandbox.fr-s-slides-talk-from-the-2010-eZ-Community-Day-in-Geneva eZ Find et la gestion des datatypes <p>J'ai publié une &quot;mini&quot; <b><a href="http://projects.ez.no/ezfsolrdocumentfieldobjectrelation" target="_blank">contribution sur la gestion des relations d'objet(s) dans eZ Find</a></b>. Cette contribution est relativement confidentielle (exploitation marginale), mais constitue une bonne occasion pour présenter <b>le fonctionnement d'<a href="http://ez.no/ezfind" target="_blank">eZ Find</a> et sa relation avec les <a href="http://ez.no/doc/ez_publish/technical_manual/4_x/reference/datatypes" target="_blank">datatypes</a></b>. <b><a href="http://ez.no/ezfind" target="_blank">eZ Find</a></b> est une extension encore sous exploitée, alors qu'elle constitue une avancée majeure d'eZ Publish sur la cible &quot;<b>système d'information professionnel</b>&quot;, au côté des extensions <a href="http://projects.ez.no/ezsi" target="_blank"><b>EZSI</b></a> ou encore <b><a href="http://projects.ez.no/nxc_cmis_client" target="_blank">CMIS</a></b>.</p><p><b><a href="http://projects.ez.no/ezfsolrdocumentfieldobjectrelation" target="_blank">Voir la page du projet ezfsolrdocumentfieldobjectrelation</a></b></p><a name="eztoc19035_1" id="eztoc19035_1"></a><h2>eZ Find en quelques mots &quot;faciles à comprendre&quot;</h2> <ul> <li><a href="http://ez.no/ezfind" target="_blank">eZ Find</a> est une &quot;<b>interface</b>&quot; entre eZ Publish (le CMS) et <a href="http://lucene.apache.org/solr/" target="_blank">Solr</a> (le moteur de recherche)</li> <li><a href="http://lucene.apache.org/solr/" target="_blank">Solr</a> est un moteur de recherche autonome, qui s'exécute comme un service JAVA, et qui fonctionne en mode <a href="http://fr.wikipedia.org/wiki/Representational_state_transfer" target="_blank">REST</a>, à savoir : <ul> <li>Lors d'une publication, <b>eZ Find</b> prépare le contenu dans une URL et le &quot;pousse&quot; vers <a href="http://lucene.apache.org/solr/" target="_blank">Solr</a> (HTTP)</li> <li>Lors d'une recherche (full text, filtres, <a href="http://fr.wikipedia.org/wiki/Classification_%C3%A0_facettes" target="_blank">facettes</a>), <b>eZ Find</b> prépare la question dans une URL et demande à <b>eZ Find</b> la réponse</li> </ul> </li> </ul> <p>Toutes ces opérations complexes sont &quot;<b>masquées</b>&quot; pour le développeur, qui doit uniquement se soucier de bien formuler ses requêtes dans son habituel <b>langage de template</b> : <i>fecth( ezfind, search, params...)</i>. La puissance d'<b>eZ Find</b> réside dans cette simplicité d'exploitation, au profit de le puissance fonctionnelle de <a href="http://lucene.apache.org/solr/" target="_blank">Solr</a> et des &quot;questions&quot; que l'on peut formuler, notamment sur la pertinence (façon <a href="http://www.google.fr/" target="_blank">google</a>) ou sur les classifications à facettes.</p><a name="eztoc19035_2" id="eztoc19035_2"></a><h2>eZ Find est les datatypes</h2><p><b>eZ Publish</b> fonctionne sur le concept de &quot;<a href="http://ez.no/doc/ez_publish/technical_manual/4_x/reference/datatypes" target="_blank">datatype</a>&quot;, à savoir des <b>types de données &quot;riches&quot;</b> permettant de représenter des lignes de textes, des numériques, des dates, mais aussi des types de données plus complexes ou exotiques comme des images, des vidéos, des relations d'objet(s) ou de la géolocalisation. eZ Publish permet également de définir <b>ses propres datatypes</b>, on peut donc comprendre que les correspondances entre les types de données <b>eZ Publish</b> et les types de données <a href="http://lucene.apache.org/solr/" target="_blank">Solr</a> nécessite quelques paramétrages, selon 2 cas de figures :</p> <ul> <li>Les correspondances de données parfaitement symétriques : <b>ligne de texte = string</b></li> <li>Les correspondances de données &quot;<b>sur mesure</b>&quot; : <b>relations d'objets</b> (et gestion des sous attributs)</li> </ul> <p>Pour définir ces correspondances <b>eZ Find</b> propose un fichier de paramétrage <i><b>extension/ezfind/settings/ezfind.ini</b></i></p><a name="eztoc19035_3" id="eztoc19035_3"></a><h2>Fonctionnement de la classe ezfSolrDocumentFieldObjectRelation</h2><p>L'aspect &quot;<b>sur mesure</b>&quot; de la correspondance entre les <a href="http://ez.no/doc/ez_publish/technical_manual/4_x/reference/datatypes" target="_blank">datatypes</a> eZ Publish et les <b>types de données eZ Find </b>implique un &quot;point de vue&quot; de développement dans la façon de gérer les cas particuliers et complexes. L'indexation des relations d'objets multiples est une bonne illustration de l'éternel dilemme du développeur : &quot;<b>jusqu'où faut-il aller ?</b>&quot;</p><a name="eztoc19035_3_1" id="eztoc19035_3_1"></a><h3>Comportement natif de ezfSolrDocumentFieldObjectRelation</h3><p>Tous les objets en relation permettent de générer un unique champs &quot;text&quot; par concaténation de tous les attributs de tous les objets. On obtient ainsi un contenu indexé de type &quot;<i>objet1/attribut1 objet1/attribut2 objet2/attribut1 objet2/attribut2</i>&quot;. Cette logique est tout à fait adaptée à la recherche &quot;full text&quot;, mais inadaptée à l'exploitation de <a href="http://fr.wikipedia.org/wiki/Classification_%C3%A0_facettes" target="_blank">facette</a>. Pour un objet en relation dont le &quot;<i>name</i>&quot; est &quot;<b>mon objet en relation</b>&quot;, on obtient les facettes suivantes sur &quot;<i>myclass/myattribute</i>&quot; :</p> <ul> <li>&quot;<b>mon</b>&quot; (10 résultats)</li> <li>&quot;<b>objet</b>&quot; (3 résultats)</li> <li>&quot;<b>en</b>&quot; (30 résultats)</li> <li>&quot;<b>relation</b>&quot; (5 résultats)</li> </ul> <a name="eztoc19035_3_2" id="eztoc19035_3_2"></a><h3>Comportement de l'évolution ezfSolrDocumentFieldObjectRelation</h3><p>La gestion des facettes devient possible, en spécifiant un attribut en particulier ou alors en invoquant le &quot;<i>name</i>&quot;. La page du projet montre <a href="http://projects.ez.no/ezfsolrdocumentfieldobjectrelation" target="_blank">quelques exemples de codes basiques</a>. En exploitant l'exemple précédent, on obtient alors l'unique facette suivante :</p> <ul> <li>&quot;<b>mon objet en relation</b>&quot; (3 résultats)</li> </ul> <a name="eztoc19035_4" id="eztoc19035_4"></a><h2>Gestion des filtres de type string</h2><p>Un fois les facettes générées, il est nécessaire de construire le lien permettant de filtrer les résultats par &quot;<b>mon objet en relation</b>&quot;. eZ Find (ou plutôt <a href="http://lucene.apache.org/solr/" target="_blank">Solr</a>) exige logiquement que les chaînes de caractères (string) soient encapsulées par des &quot;<b>doubles côtes</b>&quot;.</p><p>Cet extrait de code (un peu complexe) montre comment étendre le <b><i>search.tpl</i></b> pour générer des filtres pour les chaînes de caractères : filtres par &quot;<b>text line</b>&quot;, &quot;<b>keywords</b>&quot; ou &quot;<b>relation d'objet(s)</b>&quot;</p> <pre class="eztemplate"><span style="color: #D36900;">&#123;</span>foreach <span style="">$search_extras</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="">$index</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">nameList</span> as <span style="">$facetID</span> =&<a href="http://ez.no/doc/content/advancedsearch?SearchText=gt"><span style="color: #0600FF;">gt</span></a>; <span style="">$name</span><span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>if <span style="">$name</span>|trim|count_chars|gt<span style="color: #D36900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span> &lt;li&gt; <span style="color: #D36900;">&#123;</span>if <span style="">$search_extras</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="">$index</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">field</span>|compare<span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">'facet_fields'</span><span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>def <span style="">$url_link</span> = <a href="http://ez.no/doc/content/advancedsearch?SearchText=concat"><span style="color: #804040;">concat</span></a><span style="color: #D36900;">&#40;</span><span style="">$search_extras</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="">$index</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">queryLimit</span><span style="color: #D36900;">&#91;</span><span style="">$facetID</span><span style="color: #D36900;">&#93;</span>|explode<span style="color: #D36900;">&#40;</span><span style="color: #ff0000;">':'</span><span style="color: #D36900;">&#41;</span>.<span style="color: #cc66cc;">0</span>,<span style="color: #ff0000;">':&quot;'</span>,<span style="">$name</span>|urlencode,<span style="color: #ff0000;">'&quot;'</span><span style="color: #D36900;">&#41;</span><span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>else<span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>def <span style="">$url_link</span> = <span style="">$search_extras</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="">$index</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">queryLimit</span><span style="color: #D36900;">&#91;</span><span style="">$facetID</span><span style="color: #D36900;">&#93;</span>|wash<span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>/if<span style="color: #D36900;">&#125;</span> &lt;a title=&quot;<span style="color: #D36900;">&#123;</span><span style="">$search_extras</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="">$index</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">countList</span><span style="color: #D36900;">&#91;</span><span style="">$facetID</span><span style="color: #D36900;">&#93;</span><span style="color: #D36900;">&#125;</span> Réponse(s) trouvée(s) dans les '<span style="color: #D36900;">&#123;</span><span style="">$name</span>|wash<span style="color: #D36900;">&#125;</span>' // &quot; href=<span style="color: #D36900;">&#123;</span><a href="http://ez.no/doc/content/advancedsearch?SearchText=concat"><span style="color: #804040;">concat</span></a><span style="color: #D36900;">&#40;</span> <span style="">$baseURI</span>, <span style="color: #ff0000;">'&amp;facet_field='</span>, <span style="">$facetField</span>|wash, <span style="color: #ff0000;">'&amp;filter[]='</span>, <span style="">$url_link</span> <span style="color: #D36900;">&#41;</span>|ezurl<span style="color: #D36900;">&#125;</span>&gt;<span style="color: #D36900;">&#123;</span><span style="">$name</span>|wash<span style="color: #D36900;">&#125;</span>&lt;/a&gt; (<span style="color: #D36900;">&#123;</span><span style="">$search_extras</span>.<span style="color: #006600;">facet_fields</span><span style="color: #D36900;">&#91;</span><span style="">$index</span><span style="color: #D36900;">&#93;</span>.<span style="color: #006600;">countList</span><span style="color: #D36900;">&#91;</span><span style="">$facetID</span><span style="color: #D36900;">&#93;</span><span style="color: #D36900;">&#125;</span>) <span style="color: #D36900;">&#123;</span>undef <span style="">$url_link</span><span style="color: #D36900;">&#125;</span> &lt;/li&gt; <span style="color: #D36900;">&#123;</span>/if<span style="color: #D36900;">&#125;</span> <span style="color: #D36900;">&#123;</span>/foreach<span style="color: #D36900;">&#125;</span> &nbsp; &nbsp;</pre><p><b>A noter : </b>L'opérateur <i><b>urlencode</b></i> n'est pas natif (fonction PHP) et doit être déclaré dans <i><b>template.ini.append.php</b></i> :</p> <ul> <li><b>PHPOperatorList[urlencode]=urlencode</b></li> </ul> Wed, 13 Jan 2010 21:33:06 +0000 http://gandbox.fr/Blogs/Technologies-Web/eZ-Find-et-la-gestion-des-datatypes Faire de l'édition frontale AJAX avec eZ Publish & Mootools (Partie 3) <p>Pour terminer cette série de billet (voir la <a href="http://www.gandbox.fr/Blogs/Technologies-Web/Faire-de-l-edition-frontale-AJAX-avec-eZ-Publish-Mootools-Partie-1" target="_self">partie 1</a> et la <a href="http://www.gandbox.fr/Blogs/Technologies-Web/Faire-de-l-edition-frontale-AJAX-avec-eZ-Publish-Mootools-Partie-2" target="_self">partie 2</a>) concernant l'édition frontal <a href="http://fr.wikipedia.org/wiki/Asynchronous_JavaScript_and_XML" target="_blank">AJAX</a> sur <b>eZ Publish</b>, voici des extraits de code et quelques détails de fonctionnement concernant ce qui n'est pas encore décrit à ce stade, à savoir :</p> <ul> <li>La génération de masques de saisie en <a href="http://mootools.net/" target="_blank">mootools</a> (mes fameux <b>custom captions</b>)</li> <li>La couche <b>eZ Publish</b> et la mise à jour des données</li> </ul> <a name="eztoc18316_1" id="eztoc18316_1"></a><h2>Les custom captions en Mootools</h2><p>Comme vue dans le précédent billet, la déclaration de la classe <b>ajaxwebin</b> nécessite de renseigner la propriété <b>caption</b> par l'instance d'une classe spécifique permettant de générer le masque de saisie attendu sur clic d'une zone éditable, comme par exemple :</p><a name="eztoc18316_1_1" id="eztoc18316_1_1"></a><h3>Instance d'une classe pour une liste déroulante</h3> <pre class="javascript"><span style="color: #003366; font-weight: bold;">new</span> ajaxcaptionsSelect<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> <span style="color: #3366CC;">'minValue'</span>: <span style="color: #CC0000;">0</span>, <span style="color: #3366CC;">'maxValue'</span>: <span style="color: #CC0000;">12</span>, <span style="color: #3366CC;">'setStyles'</span>: <span style="color: #66cc66;">&#123;</span>margin: <span style="color: #3366CC;">'0 -10px'</span>, border: <span style="color: #3366CC;">'1px dotted #000'</span>, background: <span style="color: #3366CC;">'#ffffdd'</span><span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> &nbsp; &nbsp;</pre><a name="eztoc18316_1_2" id="eztoc18316_1_2"></a><h3>Instance d'une classe pour un champs de saisie</h3> <pre class="javascript"><span style="color: #003366; font-weight: bold;">new</span> ajaxcaptionsInput<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> <span style="color: #3366CC;">'setStyles'</span>: <span style="color: #66cc66;">&#123;</span>border: <span style="color: #3366CC;">'1px dotted #000'</span>, background: <span style="color: #3366CC;">'#ffffdd'</span><span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span> &nbsp; &nbsp;</pre><a name="eztoc18316_1_3" id="eztoc18316_1_3"></a><h3>Définition de la superclasse et des classes hérités</h3><p>J'aurais pu exploiter diverses techniques pour définir une superclasse <b>ajaxcaptions</b> et ses classes dérivées <b>ajaxcaptionSelect</b> et <b>ajaxcaptionsInput</b>, comme par exemple l'utilisation du mécanisme de <a href="http://fr.wikipedia.org/wiki/Programmation_orient%C3%A9e_prototype" target="_blank">prototype</a> du langage <b>JavaScript</b>. J'ai opté pour le plus scolaire <a href="http://mootools.net/docs/core/Class/Class#Class:implement" target="_blank">implement</a>, qui reste le plus facile à manipuler dans l'esprit de <a href="http://mootools.net/" target="_blank">mootools</a>.</p><p>Le principe est trivial, il s'agit de déclarer une classe, en spécifiant que l'ensemble des propriétés et des méthodes d'une autre classe sont à dupliquer. Rien n'empêche par la suite d'exploiter ou de mixer dans l'exécution du code des évolutions du <a href="http://fr.wikipedia.org/wiki/Programmation_orient%C3%A9e_prototype" target="_blank">prototype</a> des objets, ou encore d'invoquer à nouveau la méthode <a href="http://mootools.net/docs/core/Class/Class#Class:implement" target="_blank">implement</a> dynamiquement.</p><p><b>Ce formalisme a pour avantage d'être facilement compréhensible (assez scolaire), et facilement extensible :</b></p> <pre class="javascript"><span style="color: #009900; font-style: italic;">// Classe abstraite de génération d'éléments xHTML</span> <span style="color: #003366; font-weight: bold;">var</span> ajaxcaptions = <span style="color: #003366; font-weight: bold;">new</span> <span style="color: #003366; font-weight: bold;">Class</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> Implements: <span style="color: #66cc66;">&#91;</span>Options<span style="color: #66cc66;">&#93;</span>, &nbsp; options: <span style="color: #66cc66;">&#123;</span> minValue: <span style="color: #CC0000;">0</span>, maxValue: <span style="color: #CC0000;">0</span>, setStyles: <span style="color: #003366; font-weight: bold;">null</span>, myElement: <span style="color: #003366; font-weight: bold;">null</span> <span style="color: #66cc66;">&#125;</span>, <span style="color: #009900; font-style: italic;">// Constructeur de la classe</span> initialize: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>options<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">setOptions</span><span style="color: #66cc66;">&#40;</span>options<span style="color: #66cc66;">&#41;</span>; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">process</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>, <span style="color: #009900; font-style: italic;">// Retourne le caption</span> getElement: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">myElement</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #009900; font-style: italic;">// Classe de génération xHTML d'un 'select-one', contenant des valeurs de minValue à maxValue</span> <span style="color: #003366; font-weight: bold;">var</span> ajaxcaptionsSelect = <span style="color: #003366; font-weight: bold;">new</span> <span style="color: #003366; font-weight: bold;">Class</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> Implements: ajaxcaptions, process: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> &nbsp; <span style="color: #003366; font-weight: bold;">var</span> myElement; myElement = <span style="color: #003366; font-weight: bold;">new</span> Element<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'select'</span><span style="color: #66cc66;">&#41;</span>; myElement.<span style="color: #006600;">setStyles</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">setStyles</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span>i=<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">minValue</span>; i&lt;=<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">maxValue</span>; i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> myElement.<span style="color: #006600;">adopt</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> Element<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'option'</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">set</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'text'</span>, i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">myElement</span> = myElement; <span style="color: #66cc66;">&#125;</span>, getValue: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">myElement</span>.<span style="color: #006600;">selectedIndex</span>; <span style="color: #66cc66;">&#125;</span>, setValue: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>value<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">myElement</span>.<span style="color: #006600;">selectedIndex</span> = value; <span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #009900; font-style: italic;">// Classe de génération xHTML d'un 'input'</span> <span style="color: #003366; font-weight: bold;">var</span> ajaxcaptionsInput = <span style="color: #003366; font-weight: bold;">new</span> <span style="color: #003366; font-weight: bold;">Class</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> Implements: ajaxcaptions, process: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> &nbsp; <span style="color: #003366; font-weight: bold;">var</span> myElement; myElement = <span style="color: #003366; font-weight: bold;">new</span> Element<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'input'</span><span style="color: #66cc66;">&#41;</span>; myElement.<span style="color: #006600;">setStyles</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">setStyles</span><span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">myElement</span> = myElement; <span style="color: #66cc66;">&#125;</span>, getValue: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">myElement</span>.<span style="color: #006600;">value</span>; <span style="color: #66cc66;">&#125;</span>, setValue: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>value<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">myElement</span>.<span style="color: #006600;">value</span> = value; <span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>; &nbsp; &nbsp;</pre><a name="eztoc18316_2" id="eztoc18316_2"></a><h2>La couche eZ Publish de mise à jour des données</h2><p>Comme décrit dans le <a href="http://www.gandbox.fr/Blogs/Technologies-Web/Faire-de-l-edition-frontale-AJAX-avec-eZ-Publish-Mootools-Partie-2" target="_self">précédent billet</a>, l'appel des <b>URL eZ Publish</b> correspond au motif suivant : <b>/ajaxwebin/action/[<i>attribute_id</i>]/[<i>object_id</i>]/[<i>value</i>]</b> :</p> <pre class="javascript"><span style="color: #003366; font-weight: bold;">var</span> url = <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">ajaxmodule</span> + <span style="color: #3366CC;">'/'</span> + <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">attributeID</span> + <span style="color: #3366CC;">'/'</span> + object_id + <span style="color: #3366CC;">'/'</span> + value; &nbsp; &nbsp;</pre> <ul> <li><b>ajaxmodule</b> est spécifié en dur dans l'instance des classes <a href="http://mootools.net/" target="_blank">mootools</a>, et correspond à la racine du module, par exemple : <b>/ajaxwebin/action</b></li> <li><b>attributeID </b>est spécifié en dur dans l'instance des classes <a href="http://mootools.net/" target="_blank">mootools</a>, et correspond à l'identifiant <b>eZ Publish</b> du champ à modifier, par exemple <b>stock</b> ou <b>title</b></li> <li><b>object_id </b>est fixé dynamiquement dans les classes CSS, et permet de transmettre l'identifiant (objet_id) de l'objet <b>eZ Publish</b> à modifier</li> <li><b>value</b> correspond à la valeur à appliquer lors de la modification</li> </ul> <a name="eztoc18316_3" id="eztoc18316_3"></a><h2>L'implémentation du module eZ Publish</h2><p>Je ne reviendrai pas sur l'implémentation du module qui est déjà abordé en détail sur plusieurs articles, comme par exemple le <a href="http://ezpedia.org/en/ez/module" target="_blank">tutoriel de module d'eZPedia</a>.</p><a name="eztoc18316_3_4" id="eztoc18316_3_4"></a><h3>Quelques précisions concernant le code</h3> <ul> <li>La méthode de modification est la plus classique, mais il aurait été possible d'utiliser la méthode <b>fromString</b> (<a href="http://www.lifeissheet.info/2009/07/17/modification-des-valeurs-dattibuts-dun-object-ezpublish/" target="_blank">voir le billet de Mox</a>), ou encore l'expérimental <b>kernelwrapper</b> et sa classe <b>ezpObject</b> (mais ce sera pour un prochain billet)</li> <li><b>A noter :</b> L'utilisation de la méthode <a href="http://pubsvn.ez.no/doxygen/4.1/html/classeZContentCacheManager.html#28963decd313fdec93602147ce0f914d" target="_blank">clearObjectViewCache</a>, qui permet de <b>forcer le rafraîchissement de tous les caches impactés par la modification de l'objet</b> (selon les différentes directives, dont le <a href="http://ez.no/doc/ez_publish/technical_manual/4_x/features/view_caching/smart_view_cache_cleaning" target="_blank">Smartviewcache</a>)</li> </ul> <a name="eztoc18316_3_5" id="eztoc18316_3_5"></a><h3>Code du module eZ Publish de modification de l'objet</h3> <pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #0000ff;">$Module</span> = <span style="color: #0000ff;">$Params</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">&quot;Module&quot;</span><span style="color: #66cc66;">&#93;</span>; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$Params</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'action'</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #0000ff;">$action</span> = <span style="color: #0000ff;">$Params</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'action'</span><span style="color: #66cc66;">&#93;</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #0000ff;">$action</span> = <span style="color: #ff0000;">''</span>; <span style="color: #66cc66;">&#125;</span> &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$Params</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'object'</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #0000ff;">$object_id</span> = <span style="color: #0000ff;">$Params</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'object'</span><span style="color: #66cc66;">&#93;</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #0000ff;">$object_id</span> = <span style="color: #000000; font-weight: bold;">null</span>; <span style="color: #66cc66;">&#125;</span> &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$Params</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'value'</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #0000ff;">$value</span> = <span style="color: #0000ff;">$Params</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'value'</span><span style="color: #66cc66;">&#93;</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #0000ff;">$value</span> = <span style="color: #000000; font-weight: bold;">null</span>; <span style="color: #66cc66;">&#125;</span> &nbsp; <span style="color: #0000ff;">$Result</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #0000ff;">$Result</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'path'</span><span style="color: #66cc66;">&#93;</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #0000ff;">$Result</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'pagelayout'</span><span style="color: #66cc66;">&#93;</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #0000ff;">$Result</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'content'</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #ff0000;">''</span>; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$action</span> != <span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span>!<a href="http://www.php.net/is_null"><span style="color: #000066;">is_null</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$object_id</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> &amp;&amp; <span style="color: #66cc66;">&#40;</span>!<a href="http://www.php.net/is_null"><span style="color: #000066;">is_null</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$value</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> &nbsp; <span style="color: #0000ff;">$object</span> = eZContentObject::<span style="color: #006600;">fetch</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$object_id</span> <span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$object</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #0000ff;">$data_map</span> = <span style="color: #0000ff;">$object</span>-&gt;<span style="color: #006600;">attribute</span><span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'data_map'</span> <span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$data_map</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$action</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #0000ff;">$attribute</span> = <span style="color: #0000ff;">$data_map</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$action</span><span style="color: #66cc66;">&#93;</span>; &nbsp; <span style="color: #b1b100;">switch</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$data_map</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$action</span><span style="color: #66cc66;">&#93;</span>-&gt;<span style="color: #006600;">DataTypeString</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #b1b100;">case</span> <span style="color: #ff0000;">'ezinteger'</span>: <span style="color: #0000ff;">$attribute</span>-&gt;<span style="color: #006600;">setAttribute</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'data_int'</span>, <span style="color: #0000ff;">$value</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #b1b100;">break</span>; <span style="color: #b1b100;">case</span> <span style="color: #ff0000;">'ezstring'</span>: <span style="color: #0000ff;">$attribute</span>-&gt;<span style="color: #006600;">setAttribute</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'data_text'</span>, <span style="color: #0000ff;">$value</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #b1b100;">break</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #0000ff;">$attribute</span>-&gt;<span style="color: #006600;">sync</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; eZContentCacheManager::<span style="color: #006600;">clearObjectViewCache</span><span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$object_id</span> <span style="color: #66cc66;">&#41;</span>; <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #0000ff;">$value</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #66cc66;">&#123;</span> <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">''</span>; <span style="color: #66cc66;">&#125;</span> &nbsp; <span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #66cc66;">&#123;</span> <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">''</span>; <span style="color: #66cc66;">&#125;</span> &nbsp; <span style="color: #66cc66;">&#125;</span> &nbsp; eZDB::<span style="color: #006600;">checkTransactionCounter</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; eZExecution::<span style="color: #006600;">cleanExit</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #66cc66;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #66cc66;">&#123;</span> <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">''</span>; <span style="color: #66cc66;">&#125;</span> &nbsp; <span style="color: #000000; font-weight: bold;">?&gt;</span> &nbsp; &nbsp;</pre> Wed, 07 Oct 2009 21:23:50 +0000 http://gandbox.fr/Blogs/Technologies-Web/Faire-de-l-edition-frontale-AJAX-avec-eZ-Publish-Mootools-Partie-3 Faire de l'édition frontale AJAX avec eZ Publish & Mootools (Partie 2) <p>Ce billet décrit pas à pas le développement de l'édition frontale dont le fonctionnement est visible sur la vidéo du <a href="http://www.gandbox.fr/Blogs/Technologies-Web/Faire-de-l-edition-frontale-AJAX-avec-eZ-Publish-Mootools-Partie-1" target="_self">précédent billet</a> (principe du cliquer / éditer). Le <b>framework JavaScript</b> utilisé est <a href="http://mootools.net/" target="_blank">Mootools</a>, dont le fonctionnement est tout à fait similaire à ses principaux concurrents, à savoir : <a href="http://jquery.com/" target="_blank">jQuery</a>, <a href="http://www.prototypejs.org/" target="_blank">Prototype</a> &amp; <a href="http://script.aculo.us/" target="_blank">Script.aculo.us</a>, <a href="http://developer.yahoo.com/yui/" target="_blank">YUI</a>, <a href="http://www.dojotoolkit.org/" target="_blank">Dojo</a>, etc.</p><p>Pour ceux qui n'ont jamais utilisés un framework JavaScript, j'en profite pour introduire les objectifs et les fonctionnalités de base que l'on peut trouver dans tous ces frameworks, sans pour autant vous aider à faire un choix... <b>Les critères de choix d'un framework dépendent de bien d'autres critères que leur simple capacités individuelles, comme par exemple :</b></p> <ul> <li><b>Eviter la multiplication des frameworks sur un même site</b> (ce que l'on constate malheureusement un peu partout)</li> <li>Rester dans la logique de <b>dépendance d'un </b><b>framework</b><b> et de son environnement de développement</b> (<a href="http://developer.yahoo.com/yui/" target="_blank">YUI</a> pour eZ Publish, <a href="http://framework.zend.com/manual/fr/zend.dojo.html" target="_blank">Dojo pour Zend</a>, <a href="http://www.prototypejs.org/" target="_blank">Prototype</a> pour <a href="http://www.symfony-project.org/" target="_blank">Symfony</a>, etc.)</li> <li>Maîtriser un framework correctement, plutôt que 3 frameworks passablement</li> </ul> <a name="eztoc18246_1" id="eztoc18246_1"></a><h2>Introduction aux FrameWorks JavaScript</h2><p>Un framework JavaScript est écrit en JavaScript, et n'est donc pas plus puissant que le langage lui même. Il s'agit seulement d'un ensemble de librairies et d'extensions du modèle objet qui facilitent l'écriture du code, notamment pour :</p> <ul> <li>Manipuler le <a href="http://www.w3.org/DOM/" target="_blank">DOM</a> (atteindre, ajouter, modifier ou supprimer des balises et des attributs dans la page)</li> <li>Manipuler les évènements (évènements de la souris, du clavier)</li> <li>Automatiser des effets complexes (effets de fondus, de Drag &amp; Drop, etc.)</li> <li>Faciliter les appels et traitements <a href="http://fr.wikipedia.org/wiki/Asynchronous_JavaScript_and_XML" target="_blank">AJAX</a></li> <li>Faciliter la <a href="http://fr.wikipedia.org/wiki/Poo" target="_blank">POO</a>, en proposant une syntaxe plus familière (classes, héritage)</li> <li>Masquer certaines incompatibilités de navigateurs</li> </ul> <p>La popularisation de ces frameworks a permis de démocratiser un modèle objet de manipulation du <a href="http://www.w3.org/DOM/" target="_blank">DOM</a>, ainsi qu'une syntaxe grammaticale de sélection de noeuds déclinée du <a href="http://www.w3.org/TR/css3-selectors/" target="_blank">CSS3 Selector</a> (dont <a href="http://mootools.net/slickspeed/%20" target="_blank">voici une liste d'exemple en forme de benchmark pro-Mootools</a>) bien plus lisible et compréhensible que l'<a href="http://www.w3.org/TR/DOM-Level-3-Core/" target="_blank">API DOM</a> &amp; <a href="http://www.w3.org/TR/xpath" target="_blank">XPATH</a> du <a href="http://www.w3.org/TR/css3-selectors/" target="_blank">W3C</a>, ce qui génère d'ailleurs des initiatives de portage hors JavaScript comme par exemple : <a href="http://code.google.com/p/phpquery/" target="_blank">http://code.google.com/p/phpquery/</a></p><a name="eztoc18246_2" id="eztoc18246_2"></a><h2>Spécification de la classe Mootools ajaxwebin</h2><p>Cette classe a pour vocation de déclarer et d'exécuter le comportement de type &quot;<b>cliquer / éditer</b>&quot; sur un ensemble d'éléments similaires dans la page, comme par exemple :</p> <ul> <li><b>Cas 1 :</b> Remplacer sur clic toutes les balises A contenant une classe CSS '<b>cuvee_invert</b>', par un champs de saisie</li> <li><b>Cas 2 :</b> Remplacer sur clic toutes les balises A, positionnées sous une balise TD et contenant une classe CSS commençant par '<b>stock_</b>', par une liste de déroulante de 1 à 10</li> </ul> <a name="eztoc18246_2_1" id="eztoc18246_2_1"></a><h3>Prérequis dans le xHTML :</h3><p>Les xHTML propulsés doivent être préparés pour faciliter l'identification des éléments éditables, et des correspondances entre les objets et les attributs cibles. <b>Le motif xHTML est la suivante :</b></p> <pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;HTMLElement</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;rootID_ContentObjectID&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;MatchName&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span> &nbsp;</pre><a name="eztoc18246_2_2" id="eztoc18246_2_2"></a><h3>Par exemple concernant le cas 1 :</h3> <pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;a</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;cuvee_invert&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;cuveename_2224&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/a<span style="font-weight: bold; color: black;">&gt;</span></span></span> &nbsp;</pre><a name="eztoc18246_2_3" id="eztoc18246_2_3"></a><h3>Par exemple concernant le cas 2 :</h3> <pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;td</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;td80 stock_3&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;stock_2254&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;a</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>3<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/a<span style="font-weight: bold; color: black;">&gt;</span></span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/td<span style="font-weight: bold; color: black;">&gt;</span></span></span> &nbsp;</pre><a name="eztoc18246_2_4" id="eztoc18246_2_4"></a><h3>Voici la liste des paramètres et leurs rôles respectifs :</h3> <ul> <li><b>ajaxmodule (obligatoire) :</b> Racine du module eZ Publish : <b>ajaxmodule/attributeID/objectID/value</b></li> <li><b>parentMatch (obligatoire) : </b>Syntaxe CSS3 (transmise en l'état à Mootools dans un <a href="http://mootools.net/docs/core/Utilities/Selectors" target="_blank">sélecteur</a>) qui permet d'atteindre tous les éléments impactés par l'édition frontale</li> <li><b>targetMatch (optionnel) :</b> Balise optionnelle à atteindre, comme enfant des éléments résultat du parentMatch (permet par exemple d'atteindre les balises A, enfants des balises TD)</li> <li><b>styleMatch (optionnel) :</b> Permet de définir un style CSS pour faciliter l'identification des éléments éditables dans la page (bordures, couleurs)</li> <li><b>rootID (obligatoire) :</b> &lt;HTMLElement id=&quot;rootID_ContentObjectID&quot; class=&quot;MatchName&quot; /&gt;</li> <li><b>attributeID (obligatoire) :</b> Permet de transmettre le paramètre dans l'URL <b>ajaxmodule/attributeID/objectID</b>/value</li> <li><b>caption </b><b>(obligatoire) </b><b>:</b> Permet d'affecter le masque de saisie personnalisé sur clic, <b>détaillé dans le prochain billet</b></li> </ul> <a name="eztoc18246_3" id="eztoc18246_3"></a><h2>Instanciation des objets de la classe Mootools ajaxwebin</h2><p><b>A noter :</b> les objets instanciés dans la propriété '<b><i>caption</i></b>' seront décrits dans le prochain billet</p> <pre class="javascript">window.<span style="color: #006600;">addEvent</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'domready'</span>, <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> &nbsp; <span style="color: #003366; font-weight: bold;">var</span> myajaxwebin = <span style="color: #003366; font-weight: bold;">new</span> Array<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">// Ajout de la gestion des stocks</span> myajaxwebin.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span> <span style="color: #003366; font-weight: bold;">new</span> ajaxwebin<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> ajaxmodule: <span style="color: #3366CC;">'/ajaxwebin/action'</span>, parentMatch: <span style="color: #3366CC;">'td[class*=&quot;stock_&quot;]'</span>, targetMatch: <span style="color: #3366CC;">'a'</span>, styleMatch: <span style="color: #66cc66;">&#123;</span>border: <span style="color: #3366CC;">'1px dotted #ff0000'</span>, background: <span style="color: #3366CC;">'#ffffdd'</span><span style="color: #66cc66;">&#125;</span>, rootID: <span style="color: #3366CC;">'stock_'</span>, attributeID: <span style="color: #3366CC;">'stock'</span>, caption: <span style="color: #66cc66;">&#40;</span> <span style="color: #003366; font-weight: bold;">new</span> ajaxcaptionsSelect<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> <span style="color: #3366CC;">'minValue'</span>: <span style="color: #CC0000;">0</span>, <span style="color: #3366CC;">'maxValue'</span>: <span style="color: #CC0000;">12</span>, <span style="color: #3366CC;">'setStyles'</span>: <span style="color: #66cc66;">&#123;</span>margin: <span style="color: #3366CC;">'0 -10px'</span>, border: <span style="color: #3366CC;">'1px dotted #000'</span>, background: <span style="color: #3366CC;">'#ffffdd'</span><span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">// Ajout de la gestion des title des cuvées</span> myajaxwebin.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span> <span style="color: #003366; font-weight: bold;">new</span> ajaxwebin<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> ajaxmodule: <span style="color: #3366CC;">'/ajaxwebin/action'</span>, parentMatch: <span style="color: #3366CC;">'a[class=&quot;cuvee_invert&quot;]'</span>, styleMatch: <span style="color: #66cc66;">&#123;</span>border: <span style="color: #3366CC;">'1px dotted #ff0000'</span>, background: <span style="color: #3366CC;">'#ffffdd'</span><span style="color: #66cc66;">&#125;</span>, rootID: <span style="color: #3366CC;">'cuveename_'</span>, attributeID: <span style="color: #3366CC;">'title'</span>, caption: <span style="color: #66cc66;">&#40;</span> <span style="color: #003366; font-weight: bold;">new</span> ajaxcaptionsInput<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> <span style="color: #3366CC;">'setStyles'</span>: <span style="color: #66cc66;">&#123;</span>border: <span style="color: #3366CC;">'1px dotted #000'</span>, background: <span style="color: #3366CC;">'#ffffdd'</span><span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>; &nbsp; &nbsp;</pre><a name="eztoc18246_4" id="eztoc18246_4"></a><h2>Code commenté de la classe Mootools ajaxwebin</h2><p>Il est difficile d'expliquer et de décrire l'ensemble du code. Les commentaires devraient être suffisants quant à la compréhension des mécanismes. Cependant voici quelques éléments clés de compréhension :</p> <ul> <li>Voir la documentation des <a href="http://mootools.net/docs/core/Class/Class" target="_blank">classes sur Mootools</a>, et notamment l'utilisation du <a href="http://mootools.net/docs/core/Class/Class.Extras#Options:setOptions" target="_blank">setOptions</a></li> <li>Voir la documentation sur <a href="http://mootools.net/docs/core/Native/Function" target="_blank">bind</a> qui est essentielle à la construction des mécanismes qui mixent la construction dynamique du <a href="http://www.w3.org/DOM/" target="_blank">DOM</a> et l'ajout dynamique d'évènements. Cette méthode permet de modifier la portée du <b><i>this</i></b>, pour définir <b>quelle est la valeur du <i>this</i> dans l'exécution des évènements</b> (clics ou autres)</li> </ul> <pre class="javascript"><span style="color: #003366; font-weight: bold;">var</span> ajaxwebin = <span style="color: #003366; font-weight: bold;">new</span> <span style="color: #003366; font-weight: bold;">Class</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> Implements: <span style="color: #66cc66;">&#91;</span>Options<span style="color: #66cc66;">&#93;</span>, &nbsp; options: <span style="color: #66cc66;">&#123;</span> ajaxmodule: <span style="color: #003366; font-weight: bold;">null</span>, parentMatch: <span style="color: #003366; font-weight: bold;">null</span>, targetMatch: <span style="color: #003366; font-weight: bold;">null</span>, styleMatch: <span style="color: #003366; font-weight: bold;">null</span>, rootID: <span style="color: #003366; font-weight: bold;">null</span>, attributeID:<span style="color: #003366; font-weight: bold;">null</span>, caption:<span style="color: #003366; font-weight: bold;">null</span>, currentselected:<span style="color: #003366; font-weight: bold;">null</span>, currentID:<span style="color: #003366; font-weight: bold;">null</span>, targetElement:<span style="color: #003366; font-weight: bold;">null</span> <span style="color: #66cc66;">&#125;</span>, initialize: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>options<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">setOptions</span><span style="color: #66cc66;">&#40;</span>options<span style="color: #66cc66;">&#41;</span>; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">process</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>, <span style="color: #009900; font-style: italic;">// Appel AJAX au module eZ Publish, et Mise à jour de l'élément en fonction de la valeur retournée</span> updateAJAX: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>value<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #003366; font-weight: bold;">var</span> object_id = <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">currentID</span>; <span style="color: #009900; font-style: italic;">// Définition de l'URL du module eZ Publish</span> <span style="color: #003366; font-weight: bold;">var</span> url = <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">ajaxmodule</span> + <span style="color: #3366CC;">'/'</span> + <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">attributeID</span> + <span style="color: #3366CC;">'/'</span> + object_id + <span style="color: #3366CC;">'/'</span> + value; <span style="color: #003366; font-weight: bold;">new</span> Request<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> method: <span style="color: #3366CC;">'get'</span>, url: url, onSuccess: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>responseText, responseXML<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">targetElement</span>.<span style="color: #006600;">set</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'html'</span>, responseText<span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>.<span style="color: #006600;">bind</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">send</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>, <span style="color: #009900; font-style: italic;">// Supprime le caption généré</span> disposeCaption: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">targetElement</span>.<span style="color: #006600;">setStyle</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'display'</span>, <span style="color: #3366CC;">''</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">currentselected</span> = <span style="color: #003366; font-weight: bold;">null</span>; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">caption</span>.<span style="color: #006600;">getElement</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">dispose</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>, <span style="color: #009900; font-style: italic;">//Remplace la zone cible par le caption attendu</span> setCaption: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>element<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #003366; font-weight: bold;">var</span> currentselected = <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">currentselected</span>; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">currentID</span> = element.<span style="color: #006600;">getProperty</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'id'</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">replace</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">rootID</span>, <span style="color: #3366CC;">''</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">attributeID</span> = <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">attributeID</span>; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>currentselected != element<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> &nbsp; <span style="color: #009900; font-style: italic;">//Vérfie si une balise cible enfant a été définie, sinon exploite la balise courante</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">targetElement</span> = <span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">targetMatch</span><span style="color: #66cc66;">&#41;</span> ? element.<span style="color: #006600;">getElement</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">targetMatch</span><span style="color: #66cc66;">&#41;</span> : element; <span style="color: #009900; font-style: italic;">// On restore l'élément précent, si 'change' ou 'blur' non provoqué </span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>currentselected<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #003366; font-weight: bold;">var</span> restore_selected = <span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">targetMatch</span><span style="color: #66cc66;">&#41;</span> ? currentselected.<span style="color: #006600;">getElement</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">targetMatch</span><span style="color: #66cc66;">&#41;</span> : currentselected; restore_selected.<span style="color: #006600;">setStyle</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'display'</span>, <span style="color: #3366CC;">''</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #009900; font-style: italic;">//On rend invisible l'élement cible, pour pouvoir le remplacer </span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">targetElement</span>.<span style="color: #006600;">setStyle</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'display'</span>, <span style="color: #3366CC;">'none'</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">//On affecte le caption xHTML généré avec la valeur de la page</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">caption</span>.<span style="color: #006600;">setValue</span><span style="color: #66cc66;">&#40;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">targetElement</span>.<span style="color: #006600;">get</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'text'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">//On supprime les évènements, par sécurité</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">caption</span>.<span style="color: #006600;">getElement</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">removeEvents</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">//On affecte les évènements génériques à tous les captions xHTML</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">caption</span>.<span style="color: #006600;">getElement</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">addEvents</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> <span style="color: #3366CC;">'change'</span>: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #009900; font-style: italic;">//Sur changement, on update les données </span> <span style="color: #003366; font-weight: bold;">var</span> value = <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">caption</span>.<span style="color: #006600;">getValue</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">updateAJAX</span><span style="color: #66cc66;">&#40;</span>value<span style="color: #66cc66;">&#41;</span>; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">disposeCaption</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#125;</span>.<span style="color: #006600;">bind</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #3366CC;">'blur'</span>: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #009900; font-style: italic;">//Sur perte du focus </span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">disposeCaption</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#125;</span>.<span style="color: #006600;">bind</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">//On injecte le caption après l'élément cible</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">caption</span>.<span style="color: #006600;">getElement</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">inject</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">targetElement</span>, <span style="color: #3366CC;">'after'</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">currentselected</span> = element; &nbsp; <span style="color: #66cc66;">&#125;</span> &nbsp; <span style="color: #66cc66;">&#125;</span>, process: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #009900; font-style: italic;">//Recherche tous les éléments selon le motif parentMatch, et boucle sur les résultats</span> $$<span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">parentMatch</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">each</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>element, index<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #003366; font-weight: bold;">var</span> elementID = element.<span style="color: #006600;">getProperty</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'id'</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">//Teste si les éléments possèdents des ID</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>elementID &amp;&amp; <span style="color: #66cc66;">&#40;</span>elementID.<span style="color: #006600;">indexOf</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">rootID</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> == <span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #009900; font-style: italic;">//Neutralise les liens &lt;a&gt;, pour faciliter l'insertion des captions</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>element.<span style="color: #006600;">getProperty</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> element.<span style="color: #006600;">setProperty</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'href'</span>, <span style="color: #3366CC;">'javascript:void(0)'</span><span style="color: #66cc66;">&#41;</span>;; element.<span style="color: #006600;">getElements</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'a'</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">each</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>element_a<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> element_a.<span style="color: #006600;">setProperty</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'href'</span>, <span style="color: #3366CC;">'javascript:void(0)'</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">//Ajoute l'évènement de clic sur tous les éléments matché</span> element.<span style="color: #006600;">addEvents</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span> <span style="color: #3366CC;">'click'</span>: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">setCaption</span><span style="color: #66cc66;">&#40;</span>element<span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>.<span style="color: #006600;">bind</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>; element.<span style="color: #006600;">setStyles</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">options</span>.<span style="color: #006600;">styleMatch</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span>.<span style="color: #006600;">bind</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>; &nbsp; <span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>; &nbsp; &nbsp;</pre> Sun, 27 Sep 2009 20:12:15 +0000 http://gandbox.fr/Blogs/Technologies-Web/Faire-de-l-edition-frontale-AJAX-avec-eZ-Publish-Mootools-Partie-2 Faire de l'édition frontale AJAX avec eZ Publish & Mootools (Partie 1) <p>La rubrique <a href="http://www.gandbox.fr/ma-Cave" target="_self">ma cave</a> est certes un bon prétexte à la rédaction d'articles techniques sur <b>eZ Publish</b>, mais il s'agit également de la seule information numérique à jour concernant mes stocks de vins. Le volume des entrées / sorties est relativement important (si si !) et cette mise à jour des stocks est rapidement devenue un calvaire. La recherche d'une bonne solution de feignant m'a permis de tester l'édition frontale sur <b>eZ Publish</b>, et surtout d'expérimenter <b>un mécanisme de mise à jour plus immédiat en <a href="http://fr.wikipedia.org/wiki/Asynchronous_JavaScript_and_XML" target="_blank">AJAX</a> du type : &quot;cliquer / éditer&quot;</b>.</p><p><b>J'en profite pour rédiger une série de billets détaillant :</b></p> <ul> <li>Le fonctionnement et les limites de l'<b>édition frontale standard</b></li> <li>La <a href="http://fr.wikipedia.org/wiki/Programmation_orient%C3%A9e_objet" target="_blank">programmation orientée objet</a> en <b>JavaScript</b> avec <a href="http://mootools.net/" target="_blank">Mootools</a></li> <li>La mise à jour de contenus <b>eZ Publish</b> via <a href="http://fr.wikipedia.org/wiki/Asynchronous_JavaScript_and_XML" target="_blank">AJAX</a></li> </ul> <a name="eztoc18176_1" id="eztoc18176_1"></a><h2>La classique édition frontale eZ Publish et ses limites</h2><p>L'édition frontale est le mécanisme le plus exploité pour promouvoir les <a href="http://fr.wikipedia.org/wiki/Syst%C3%A8me_de_gestion_de_contenu" target="_blank">CMS</a> (<a href="http://ez.no/" target="_blank">eZ Publish</a>, <a href="http://drupal.org/" target="_blank">Drupal</a> ou autres), ce qui est relativement paradoxal, puisqu'au final il s'agit du mécanisme le moins exploité par les Webmasters sur les sites en productions. Ce constat s'explique assez bien, pour plusieurs raisons que je détaille par la suite.</p><a name="eztoc18176_1_1" id="eztoc18176_1_1"></a><h3>Pourquoi si peu de sites exploitent l'édition frontale ?</h3><p>La logique ergonomique de l'édition frontale est des plus simple : je navigue sur mon site, et une barre d'édition me permet :</p> <ul> <li>d'éditer l'objet que je suis en train de visionner (sa vue 'full')</li> <li>d'ajouter un objet de contenu positionné &quot;en dessous&quot; de l'objet que je suis en train de visionner</li> <li>quelques autres actions classiques comme 'déplacer', 'ajouter des emplacements', 'supprimer', etc.</li> </ul> <p><b>Donc la capacité d'éditer (ou non) un contenu dépend de la capacité d'atteindre une page dont le contenu principal est le contenu à éditer</b> (vue full), ce qui se complique fortement dès qu'il s'agit d'une liste de commentaires (généralement empilés, sans affichage individuel), d'un utilisateur, d'un contenu associé à partir de la médiathèque (image), d'un contenu non représenté dans l'arborescence de l'internaute (divers dossiers de rangement), d'un contenu masqué ou supprimé, etc..</p><p><b>Les Webmasters vont donc devoir naviguer entre l'édition frontale et le Back Office, ce qui finalement se résume assez vite à l'utilisation exclusive du Back Office</b>.</p><p>Il faut aussi ajouter que les front-end des sites sont très variés dans leur logique de navigation, et parfois graphiquement inadaptés à l'inclusion de formulaires d'édition. Pour pouvoir profiter d'une édition frontale efficace, il faut en quelque sorte organiser le contenu en conséquence, <b>ce qui cependant fonctionne positivement sur certains types de publications, comme les Blogs ou les contenus arborescences (catalogues, référentiels)</b>.</p><a name="eztoc18176_1_2" id="eztoc18176_1_2"></a><h3>Pourquoi vendre un CMS à l'aide de l'édition frontale ?</h3><p>Les acheteurs des solutions Web sont rarement les utilisateurs finaux, et il faut donc les séduire avec des mécanismes percutants et rassurants tels que l'édition frontale, l'upload massif (voir <a href="http://projects.ez.no/ezmultiupload" target="_blank">ezmultiupload</a>), ou l'importation directe à partir de <b>Word</b> (voir <a href="http://projects.ez.no/ezwordtoolbar" target="_blank">ezwordtoolbar</a>) ou <b>Open Office</b> (extension native <a href="http://ez.no/doc/extensions/odf_import_export" target="_blank">ezodf</a>). Généralement un <a href="http://fr.wikipedia.org/wiki/Syst%C3%A8me_de_gestion_de_contenu" target="_blank">CMS</a> succède à du <a href="http://www.adobe.com/fr/products/dreamweaver/" target="_blank">DreamWeaver</a> (fabrication <b>HTML</b> frontale) ou du <a href="http://www.php.net/" target="_blank">PHP</a> maison (bricolé, insécure, mais libre d'action), il faut donc insister sur des mécanismes qui ne suppriment pas définitivement des conforts de fabrication durement acquis au fil du temps...</p><a name="eztoc18176_1_3" id="eztoc18176_1_3"></a><h3>Installation d'une édition frontale sur eZ Publish</h3><p>De nombreux articles détaillent déjà l'installation de l'édition frontale (que l'on trouve par défaut lors de l'installation des packages <b>ezwebin</b> ou <b>ezflow</b>), comme par exemple :</p> <ul> <li>L'article sur <a href="http://ezpedia.org/solution/overriding_the_ez_web_interface_ezwebin_with_custom_designs" target="_blank">ezpedia</a></li> <li>L'article sur <a href="http://pwet.fr/blog/install_ezwebin_toolbar_into_an_existing_site" target="_blank">pwet</a></li> </ul> <p>Il est à noter qu'une nouvelle extension <a href="http://projects.ez.no/ezwebsitetoolbar" target="_blank">ezwebsitetoolbar</a> (code extrait de <b>ezwebin</b>) permet d'intégrer une barre d'édition frontale sans transporter l'ensemble de l'extension <a href="http://ez.no/doc/extensions/website_interface" target="_blank">ezwebin</a>.</p><a name="eztoc18176_2" id="eztoc18176_2"></a><h2>L'interface de mise à jour des stocks ?</h2><p>En posant le problème, l'idéal ergonomique pour cette mise à jour fréquente est finalement de pouvoir cliquer et éditer le stock directement dans la page quel que soit la page affichée (les listes de cuvées résumées, les tableaux de stocks, les fiches détaillées, etc.). Ce mécanisme est particulièrement efficace pour des mises à jour multiples sur des affichages en tableaux (vue d'ensemble).</p><p><b>Voici <a href="http://www.youtube.com/watch?v=Z9E3r6fi1bM&amp;feature=player_embedded" target="_blank">un exemple en vidéo</a>, qui montre en image :</b></p> <ul> <li>Un exemple de boite de connexion frontale</li> <li>Un exemple de mise à jour du stock par l'édition frontale standard</li> <li>Un exemple de mise à jour du stock par un développement spécifique, <b>permettant le &quot;cliquer / éditer&quot; en <a href="http://fr.wikipedia.org/wiki/Asynchronous_JavaScript_and_XML" target="_blank">AJAX</a> avec <a href="http://mootools.net/" target="_blank">Mootools</a></b></li> <li>Ce même mécanisme décliné pour mettre à jour les noms des cuvées (je modifie souvent l'année dans le nom des cuvées)</li> </ul> <p>Les prochains billets détailleront pas à pas le développement d'une telle extension.</p><div class="video"> <object width="600" height="500" type="application/x-shockwave-flash" data="http://www.youtube.com/v/Z9E3r6fi1bM&amp;hl=fr&amp;fs=1&amp;"> <param name="movie" value="http://www.youtube.com/v/Z9E3r6fi1bM&amp;hl=fr&amp;fs=1&amp;"></param> <param name="allowfullscreen" value="true"></param> </object> </div> Sun, 20 Sep 2009 20:05:30 +0000 http://gandbox.fr/Blogs/Technologies-Web/Faire-de-l-edition-frontale-AJAX-avec-eZ-Publish-Mootools-Partie-1