MOSS : Content Query WebPart et Audiences - Limitation et Contournement
La Content Query WebPart est une fabuleuse WebPart d’agrégation de contenu. A elle seule elle rend obsolètes de nombreux développements que j’avais pu faire sous SPS2003. Lorsque j’en fais la démonstration en formation, le résultat est systématique : les stagiaires font immédiatement le tour de toutes les problématiques auxquels cette WebPart apporte une réponse.
Son paramétrage n’est pas simple pour autant. Bien sûr, son EditorPart permet un paramétrage déjà poussé et ne représente pas de grande difficulté, mais dans la plupart des cas il faut procéder à un paramétrage avancé. et modifier notamment :
- le fichier .webpart qui lui est associé,
- les fichiers XSL sur lesquelles elle s’appui.
Plutôt que de détailler ici la façon de faire, voici quelques liens vers de très bons ‘How To’ :
Vous trouverez des informations complémentaires sur cette autre page du MSDN.
Pour aller encore plus loin dans les capacités de cette WebPart, vous trouvez l’Enhanced Content Query WebPart sur codeplex.
Les présentations étant faites, passons à un point précis de la WebPart. Cette WebPart est capable de gérer les audiences. Efficace pour filtrer les éléments non pertinents pour l’utilisateur connecté !
Pour cela, il suffit de cocher la case « Appliquer le filtrage de l’audience » dans l’Editor Part. La seconde checkbox permet de déterminer le comportement de la WebPart pour les éléments n’ayant aucune audience associée.
Seulement voilà…ce filtrage est réalisé une fois les données récupérées par la WebPart. Qu’est ce que ça implique ? Et bien si vous limitez le nombre d’éléments retournés par la WebPart, il y aura ce nombre d’éléments affichés moins ceux filtrés par l’audience.
Dans mon cas, j’ai cherché à remonter les trois dernières pages modifiées en configurant la WebPart comme ceci :
Et malheureusement, seules deux de ces pages étaient remontées.
Mon objectif était pourtant de remonter trois pages, et bien sûr remplacer les pages manquantes en cas de filtrage en prenant les suivantes selon mon critère de tri.
Je n’ai pas trouvé de solution de contournement idéale. Il en existe cependant une (qui n’est pas du tout générique). Pour le principe néanmoins, je vais vous l’exposer ici:
Dans mon cas, les règles fonctionnelles prévues pour la gestion des pages me permettent de savoir que j’aurais au moins trois pages après filtrage si je remonte 10 d’entre elles.
Seulement voilà, cette manipulation assure aussi qu’il y aura quasi systématiquement plus de trois pages remontées. Solution de contournement : compter et limiter le nombre d’éléments affichés depuis le XSL. La difficulté ici, c’est que le seul fichier XSL permettant d’avoir la main sur l’ensemble du rendu de la WebPart est le fichier ContentQueryMain.xsl… et par défaut l’édition de ce fichier modifie le rendu de toutes les ContentQueryWebPart de la collection de sites. Pour lui ajouter un branchement conditionnel et ne déclencher le comptage que lorsque c’est nécessaire, il faut alors se baser sur une des données du XML source… au hasard, l’attribut Style J.
Voici comment procéder :
1. Il faut commencer par éditer le fichier ItemStyle.xsl pour lui ajouter un nouveau style :
<xsl:template name="Max3Items" match="Row[@Style='Max3Items']" mode="itemstyle">
<xsl:variable name="SafeLinkUrl">
<xsl:call-template name="OuterTemplate.GetSafeLink">
<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="SafeImageUrl">
<xsl:call-template name="OuterTemplate.GetSafeStaticUrl">
<xsl:with-param name="UrlColumnName" select="'ImageUrl'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="DisplayTitle">
<xsl:call-template name="OuterTemplate.GetTitle">
<xsl:with-param name="Title" select="@Title"/>
<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="LinkTarget">
<xsl:if test="@OpenInNewWindow = 'True'" >_blank</xsl:if>
</xsl:variable>
<div id="linkitem" class="item">
<xsl:if test="string-length($SafeImageUrl) != 0">
<div class="image-area-left">
<a href="{$SafeLinkUrl}" target="{$LinkTarget}">
<img class="image" src="{$SafeImageUrl}" alt="{@ImageUrlAltText}" />
</a>
</div>
</xsl:if>
<div class="link-item">
<xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>
<a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}">
<xsl:value-of select="$DisplayTitle"/>
</a>
<div class="description">
<xsl:value-of select="@Description" />
</div>
</div>
</div>
</xsl:template>
2. Il faut ensuite éditer le fichier ContenQueryMain.xsl. Repérez le template OuterTemplate.Body :
<xsl:template name="OuterTemplate.Body">
C’est ce Template qui se charge du rendu du corps de la ContentQueryWebPart. Ne modifiez surtout pas ce Template. Créez en un autre sur le modèle suivant :
<xsl:template name="OuterTemplate.Max3Items">
<xsl:param name="Rows" />
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<xsl:variable name="BeginColumn1" select="string('<td id="column" width="')" />
<xsl:variable name="BeginColumn2" select="string('%" valign="top">')" />
<xsl:variable name="BeginColumn" select="concat($BeginColumn1, $cbq_columnwidth, $BeginColumn2)" />
<xsl:variable name="EndColumn" select="string('</td >')" />
<xsl:value-of disable-output-escaping="yes" select="$BeginColumn" />
<xsl:for-each select="$Rows">
<xsl:variable name="CurPosition" select="position()" />
<xsl:if test="($CurPosition <= 3)">
<xsl:call-template name="OuterTemplate.CallItemTemplate">
<xsl:with-param name="CurPosition" select="$CurPosition" />
</xsl:call-template>
</xsl:if>
</xsl:for-each>
<xsl:value-of disable-output-escaping="yes" select="$EndColumn" />
</xsl:template>
J’ai voulu ce Template le plus simple possible, les entêtes et les colonnes ne sont donc pas gérées ici.
3. Repérez le template OuterTemplate. Ajoutez-lui une variable xsl basée sur le style.
<xsl:template name="OuterTemplate">
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row" />
<xsl:variable name="RowCount" select="count($Rows)" />
<xsl:variable name="Max3Items" select="$Rows[@Style='Max3Items']" />
Ici, Max3Pages sera à true si et seulement si le style Max3Pages a été sélectionné.
4. Repérez l’appel au Template OuterTemplate.Body un peu plus bas. Le branchement conditionnel est à rajouter ici, comme ceci :
<xsl:choose>
<xsl:when test="$Max3Pages">
<xsl:call-template name="OuterTemplate.Max3Pages ">
<xsl:with-param name="Rows" select="$Rows" />
<xsl:with-param name="FirstRow" select="1" />
<xsl:with-param name="LastRow" select="$RowCount" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="OuterTemplate.Body">
<xsl:with-param name="Rows" select="$Rows" />
<xsl:with-param name="FirstRow" select="1" />
<xsl:with-param name="LastRow" select="$RowCount" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
5. Publiez les deux fichiers XSL. Retournez sur votre ContentQueryWebPart et sélectionnez le style Max3Pages.

Voilà, la WebPart est maintenant prête à afficher 3 éléments après applications des audiences.
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :