Wijzigen voor document Home

Laatst gewijzigd door Jesse Veentjer op 13-11-2025 04:39

Van versie 10.12
gewijzigd door Jesse Veentjer
op 15-2-2024 05:47
Opmerking bij wijziging: Er is geen opmerking bij deze versie
Naar versie 11.1
gewijzigd door Jesse Veentjer
op 15-2-2024 05:53
Opmerking bij wijziging: Er is geen opmerking bij deze versie

Samenvatting

Details

Paginaeigenschappen
Inhoud
... ... @@ -1,24 +1,148 @@
1 +(% class="floatinginfobox wbrechts" %)
2 +(((
3 +(% class="wbrb" %)
4 +(% aria-label="aanhetwerk.gif afbeelding widget" contenteditable="false" data-xwiki-image-style-alignment="center" role="region" tabindex="-1" data-widget="image" %)[[image:aanhetwerk.gif||data-xwiki-image-style-alignment="center"]](% title="Klik en sleep om te herschalen" %)​(% aria-label="aanhetwerk.gif afbeelding widget" contenteditable="false" data-xwiki-image-style-alignment="center" role="region" tabindex="-1" style="background-color:rgba(220,220,220,0.5)" %)[[image:data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==||draggable="true" height="15" role="presentation" title="Klik en sleep om te verplaatsen" width="15"]]
5 +
6 +(% class="wbtoc" %)
7 +(((
8 + (% class="wbtocheader" %)Inhoud
9 +
10 +(% aria-label="macro:toc widget" contenteditable="false" role="region" tabindex="-1" %)
11 +(((
12 +(% class="macro" data-macro="startmacro:toc|-|" data-widget="xwiki-macro" data-xwiki-dom-updated="true" %)
13 +(((
14 +(% class="macro-placeholder hidden" %)
15 +(((
16 +macro:toc
17 +)))
18 +
19 +(% class="wikitoc" %)
20 +* [[Nieuws>>doc:null||anchor="HNieuws"]]
21 +)))
22 +
23 +(% style="background-color:rgba(220,220,220,0.5)" %)[[image:data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==||height="15" role="presentation" title="Klik en sleep om te verplaatsen" width="15"]]
24 +)))
25 +)))
26 +)))
27 +
1 1  (% class="wblinks" %)
2 2  (((
3 -{{velocity}}
30 +(% aria-label="macro:velocity widget" contenteditable="false" role="region" tabindex="-1" %)
31 +(((
32 +(% class="macro" data-macro="startmacro:velocity|-||-|Welkom op de Kennisbank! Toegang tot (kwalitatief) goede informatie is een uitdaging waar iedereen mee worstelt, met het lanceren van dit digitale archief waarin we kennis, de laatste ontwikkelingen (nieuws), bestanden en ideeën kunnen plaatsen en delen gaan we het vinden van informatie eenvoudiger maken. In de kern maakt kennisbank het mogelijk om informatie te genereren organiseren en delen
33 +
34 +\{\{showhide showmessage=~"We kunnen dit op vele manieren gebruiken, klik hier om enkele voorbeelden te zien:~" hidemessage=~"Verstop voorbeelden~" effectduration=~"1~"}}
35 +✅ Toegang tot informatie , verbreed je kennis naar nieuwe onderwerpen.
36 +* Gedeelde kennis is makkelijk doorzoekbaar, je kan naar specifieke delen van pagina’s linken met een weblink!
37 +* Kennis van collega's wordt met elkaar gedeeld. Het voorkomt dat je zelf het wiel moet uitvinden terwijl er al informatie van een collega over een bepaald onderwerp is.
38 +* //Help collega's en klanten door hen in staat te stellen zichzelf te helpen//[[(Nb. zonder in te loggen zien bezoekers ook de 'Openbaar' folder)>>path:/Main/Openbaar/]]
39 +
40 +✅ Dankzij de nieuwssectie kunnen ook de laatste ontwikkelingen per 'nieuwsonderwerp' op de kennisbank geplaatst worden.
41 +
42 +✅ Deel je kennis door het vast te leggen in de kennisbank
43 +
44 +* Of het nou gaat om een bekende fout in een apparaat/softwareversie of een handige manier om een installatie te configureren, als je tijd hebt geïnvesteerd om een probleem oplossen is het jammer wanneer bijvoorbeeld een collega moet zwoegen om tot dezelfde oplossing te komen.
45 +
46 +✅ Zorgt voor transparantie en duidelijkheid op kennisgebied
47 +
48 +* Uitleg en handleidingen van installaties maar ook onze werkprocessen kunnen vastgelegd en gedeeld worden met de kennisbank.
49 +* Ervaringen en discussies kunnen per onderwerp geplaatst en besproken worden.
50 +\{\{/showhide}}
51 +-\-\-\-
52 +* [[Klik hier voor uitleg hoe de kennisbank werkt>>path:/Main/Werkwijze/Kennisbank/]]. //Als je verdwaald raakt kan je altijd linksbovenin op het logo klikken, dan ga je terug naar deze homepagina. //
53 +* [[Voor discussies,vragen en/of opmerkingen over de kennisbank kan je aan dit teamkanaal meedoen>>url:https://teams.microsoft.com/l/team/19%3aAxo-k8j1CVRGXTb0t3Dc6tjNDNudeTZjcP_KZVFR5381%40thread.tacv2/conversations?groupId=4da292cd-ff72-4d4c-adc5-8aa3dfc4ae3f&tenantId=42b413cc-67db-4507-a4a6-ce30ce798022||rel=~"noopener noreferrer~" target=~"_blank~"]].
54 +
55 +
56 +
4 4  #if($isGuest)
5 5  #set($loginscherm = 'https://kennis.wardenburg.nl/login/XWiki/XWikiLogin')
6 -{{html}}
7 -<a href=$loginscherm>
8 -<button class="login-btn" onclick="this.classList.add('clicked')"><span>Login</span></button>
9 -</a>
10 -{{/html}}
11 -Door in te loggen krijg je meer functies op de kennisbank, log in met je voornaam.achternaam (het wachtwoord is dezelfde als bij je e-mail).
59 +\{\{html}}
60 +<button class=~"login-btn~" onclick=~"this.classList.add('clicked')~"><span>Login</span></button>
61 +\{\{/html}}
62 +Door in te loggen krijg je meer functies op de kennisbank, log in met je voornaam.achternaam (hetzelfde als je e-mail zonder het @wardenburg.nl gedeelte).
12 12  #else
64 += Nieuws =
65 +\{\{blogpostlist blog=~"Nieuws.WebHome~" limit=~"6~" layout=~"cards~" layoutParams=~"displayTitle=true|useSummary=true~"/}}
66 +#end" data-widget="xwiki-macro" data-xwiki-dom-updated="true" %)
67 +(((
68 +(% class="macro-placeholder hidden" %)
69 +(((
70 +macro:velocity
71 +)))
13 13  
14 -#end
73 +Welkom op de Kennisbank! Toegang tot (kwalitatief) goede informatie is een uitdaging waar iedereen mee worstelt, met het lanceren van dit digitale archief waarin we kennis, de laatste ontwikkelingen (nieuws), bestanden en ideeën kunnen plaatsen en delen gaan we het vinden van informatie eenvoudiger maken. In de kern maakt kennisbank het mogelijk om informatie te genereren organiseren en delen
15 15  
16 -=Welkom op onze Kennisbank=
75 +(% class="macro" data-macro="startmacro:showhide|-|showmessage=~"We kunnen dit op vele manieren gebruiken, klik hier om enkele voorbeelden te zien:~" hidemessage=~"Verstop voorbeelden~" effectduration=~"1~"|-|✅ Toegang tot informatie , verbreed je kennis naar nieuwe onderwerpen.
76 +* Gedeelde kennis is makkelijk doorzoekbaar, je kan naar specifieke delen van pagina’s linken met een weblink!
77 +* Kennis van collega's wordt met elkaar gedeeld. Het voorkomt dat je zelf het wiel moet uitvinden terwijl er al informatie van een collega over een bepaald onderwerp is.
78 +* //Help collega's en klanten door hen in staat te stellen zichzelf te helpen//[[(Nb. zonder in te loggen zien bezoekers ook de 'Openbaar' folder)>>path:/Main/Openbaar/]]
17 17  
18 -Toegang tot (kwalitatief) goede informatie is een uitdaging waar iedereen mee worstelt, met het lanceren van dit digitale archief waarin we kennis, de laatste ontwikkelingen (nieuws), bestanden en ideeën kunnen plaatsen en delen gaan we het vinden van informatie eenvoudiger maken. In de kern maakt kennisbank het mogelijk om informatie te genereren organiseren en delen
80 +✅ Dankzij de nieuwssectie kunnen ook de laatste ontwikkelingen per 'nieuwsonderwerp' op de kennisbank geplaatst worden.
19 19  
20 -{{showhide showmessage="We kunnen dit op vele manieren gebruiken, klik hier om enkele voorbeelden te zien:" hidemessage="Verstop voorbeelden" effectduration="1"}}
82 +✅ Deel je kennis door het vast te leggen in de kennisbank
83 +
84 +* Of het nou gaat om een bekende fout in een apparaat/softwareversie of een handige manier om een installatie te configureren, als je tijd hebt geïnvesteerd om een probleem oplossen is het jammer wanneer bijvoorbeeld een collega moet zwoegen om tot dezelfde oplossing te komen.
85 +
86 +✅ Zorgt voor transparantie en duidelijkheid op kennisgebied
87 +
88 +* Uitleg en handleidingen van installaties maar ook onze werkprocessen kunnen vastgelegd en gedeeld worden met de kennisbank.
89 +* Ervaringen en discussies kunnen per onderwerp geplaatst en besproken worden." %)
90 +(((
91 +(% class="macro-placeholder hidden" %)
92 +(((
93 +macro:showhide
94 +)))
95 +
96 +(% class="macro" data-macro="startmacro:velocity|-||-|#set($discard = $xwiki.jsx.use(~"Macros.ShowHideMacro~"))
97 +#set($mparams = $wikimacro.parameters)
98 +#if(!$mparams)
99 + #set($mparams = $xcontext.macro.params)
100 +#end
101 +#if($mparams.id)
102 + #set($id = $util.convertToAlphaNumeric($mparams.id))
103 +#end
104 +#set($showmessage = $escapetool.xml($mparams.showmessage))
105 +#set($hidemessage = $escapetool.xml($mparams.hidemessage))
106 +#set($divstyle = $escapetool.xml($mparams.style))
107 +#set($effect = $escapetool.xml($mparams.effect))
108 +#if($effect == ~"appear~" || $effect == ~"fade~")
109 + #set($effect = ~"fadeToggle~")
110 +#elseif ($effect == ~"blind~" || $effect == ~"slide~")
111 + #set($effect = ~"slideToggle~")
112 +#end
113 +#set($effectduration = $mathtool.mul(1000,$mparams.effectduration))
114 +(% #if($divstyle && $divstyle!=~"~") style=~"$\{divstyle}~" #end ~%)
115 +(((
116 +(% class=~"showhidebutton~" ~%)
117 +(((
118 +\{\{html clean=false}}
119 +<a href=~"javascript:void(0)~" #if($id && $id!=~"~")id=~"showhidebuttontext$\{id}~" #end data-show-duration=~"$effectduration~" data-show-effect=~"$effect~" data-show-message=~"$showmessage~" data-hide-message=~"$hidemessage~">$mparams.showmessage</a>
120 +\{\{/html}}
121 +)))
122 +(% class=~"showhidecontent~" #if($id && $id!=~"~")id=~"showhidecontent$\{id}~" #end style=~"display: none;~" ~%)
123 +(((
124 +(((
125 +$xcontext.macro.content
126 +)))
127 +)))
128 +)))" %)
129 +(((
130 +(% class="macro-placeholder hidden" %)
131 +(((
132 +macro:velocity
133 +)))
134 +
135 +(((
136 +(% class="showhidebutton" %)
137 +(((
138 +(% data-macro="startmacro:html|-|clean=~"false~"|-|<a href=~"javascript:void(0)~" data-show-duration=~"1000~" data-show-effect=~"toggle~" data-show-message=~"We kunnen dit op vele manieren gebruiken, klik hier om enkele voorbeelden te zien:~" data-hide-message=~"Verstop voorbeelden~">We kunnen dit op vele manieren gebruiken, klik hier om enkele voorbeelden te zien:</a>" class="macro hidden macro-placeholder" %)macro:html(% class="macro" data-macro="startmacro:html|-|clean=~"false~"|-|<a href=~"javascript:void(0)~" data-show-duration=~"1000~" data-show-effect=~"toggle~" data-show-message=~"We kunnen dit op vele manieren gebruiken, klik hier om enkele voorbeelden te zien:~" data-hide-message=~"Verstop voorbeelden~">We kunnen dit op vele manieren gebruiken, klik hier om enkele voorbeelden te zien:</a>" %)[[We kunnen dit op vele manieren gebruiken, klik hier om enkele voorbeelden te zien:>>path:javascript:void(0)||data-hide-message="Verstop voorbeelden" data-show-duration="1000" data-show-effect="toggle" data-show-message="We kunnen dit op vele manieren gebruiken, klik hier om enkele voorbeelden te zien:"]]
139 +)))
140 +
141 +(% class="showhidecontent" style="display: none;" %)
142 +(((
143 +(((
21 21  ✅ Toegang tot informatie , verbreed je kennis naar nieuwe onderwerpen.
145 +
22 22  * Gedeelde kennis is makkelijk doorzoekbaar, je kan naar specifieke delen van pagina’s linken met een weblink!
23 23  * Kennis van collega's wordt met elkaar gedeeld. Het voorkomt dat je zelf het wiel moet uitvinden terwijl er al informatie van een collega over een bepaald onderwerp is.
24 24  * //Help collega's en klanten door hen in staat te stellen zichzelf te helpen//[[(Nb. zonder in te loggen zien bezoekers ook de 'Openbaar' folder)>>path:/Main/Openbaar/]]
... ... @@ -33,28 +33,10117 @@
33 33  
34 34  * Uitleg en handleidingen van installaties maar ook onze werkprocessen kunnen vastgelegd en gedeeld worden met de kennisbank.
35 35  * Ervaringen en discussies kunnen per onderwerp geplaatst en besproken worden.
36 -{{/showhide}}
160 +)))
161 +)))
162 +)))
163 +)))
164 +)))
165 +
37 37  ----
38 -* [[Klik hier voor uitleg hoe de kennisbank werkt>>path:/Main/Werkwijze/Kennisbank/]]. //Als je verdwaald raakt kan je altijd linksbovenin op het logo klikken, dan ga je terug naar deze homepagina. //
167 +
168 +* [[Klik hier voor uitleg hoe de kennisbank werkt>>path:/Main/Werkwijze/Kennisbank/]]. //Als je verdwaald raakt kan je altijd linksbovenin op het logo klikken, dan ga je terug naar deze homepagina.  //
39 39  * [[Voor discussies,vragen en/of opmerkingen over de kennisbank kan je aan dit teamkanaal meedoen>>url:https://teams.microsoft.com/l/team/19%3aAxo-k8j1CVRGXTb0t3Dc6tjNDNudeTZjcP_KZVFR5381%40thread.tacv2/conversations?groupId=4da292cd-ff72-4d4c-adc5-8aa3dfc4ae3f&tenantId=42b413cc-67db-4507-a4a6-ce30ce798022||rel="noopener noreferrer" target="_blank"]].
40 40  
41 41  
42 -
43 -#if(!$isGuest)
44 -(% style="clear:right" %)
45 45  = Nieuws =
46 -{{blogpostlist blog="Nieuws.WebHome" limit="6" layout="cards" layoutParams="displayTitle=true|useSummary=true"/}}
47 47  
174 +(% class="macro" data-macro="startmacro:blogpostlist|-|blog=~"Nieuws.WebHome~" limit=~"6~" layout=~"cards~" layoutParams=~"displayTitle=true|useSummary=true~"" %)
175 +(((
176 +(% class="macro-placeholder hidden" %)
177 +(((
178 +macro:blogpostlist
179 +)))
180 +
181 +(% class="macro" data-macro="startmacro:blogPostLayoutCards|-|reference=~"Nieuws.Nieuwsbrief januari 2024~" params=~"displayTitle=true|useSummary=true|list-limit=6|list-layout=cards|list-blog=Nieuws.WebHome|list-paginated=no|list-results-count=6|postIndex=0|previousPostReference=~"" %)
182 +(((
183 +(% class="macro-placeholder hidden" %)
184 +(((
185 +macro:blogPostLayoutCards
186 +)))
187 +
188 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogCode~"" %)
189 +(((
190 +(% class="macro-placeholder hidden" %)
191 +(((
192 +macro:include
193 +)))
194 +
195 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogParameters~"" %)
196 +(((
197 +(% class="macro-placeholder hidden" %)
198 +(((
199 +macro:include
200 +)))
201 +
202 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|## Blog
203 +#set($blogClassname = 'Blog.BlogClass')
204 +#set($blogTemplate = 'Blog.BlogTemplate')
205 +#set($blogSheet = 'Blog.BlogSheet')
206 +## Blog entries
207 +#set($blogPostClassname = 'Blog.BlogPostClass')
208 +#set($blogPostTemplate = 'Blog.BlogPostTemplate')
209 +#set($blogPostSheet = 'Blog.BlogPostSheet')
210 +#set($blogPostObjectNumber = $xwiki.getDocument($blogPostTemplate).getObject($blogPostClassname).number)
211 +#set($oldArticleClassname = 'XWiki.ArticleClass')
212 +## Categories
213 +#set($blogCategoryClassname = 'Blog.CategoryClass')
214 +#set($blogCategoryTemplate = 'Blog.CategoryTemplate')
215 +#set($blogCategorySheet = 'Blog.CategorySheet')
216 +#set($blogCategoriesSheet = 'Blog.CategoriesSheet')
217 +#set($oldBlogCategoryClassname = 'Blog.Categories')
218 +#set($defaultCategoryParent = 'Blog.Categories')
219 +## Style
220 +#set($blogStyleDocumentName = 'Blog.BlogStyle')
221 +#set($blogStyleDocument = $xwiki.getDocument($blogStyleDocumentName))
222 +## Clientside scripts
223 +#set($blogScriptsDocumentName = 'Blog.BlogScripts')
224 +#set($blogPublisher = $xwiki.getDocument('Blog.Publisher'))
225 +## Misc
226 +#set($thisURL = $doc.getURL($xcontext.action, $request.queryString))
227 +#set($isBlogPost = $doc.getObject($blogPostClassname))
228 +#set($defaultBlogSpace = 'Blog')
229 +#set($isCategoryPage = $doc.getObject($blogCategoryClassname))
230 +#set($isCategoriesHomePage = $doc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
231 +##
232 +##
233 +##
234 +#**
235 + * Displays an image, taken from the blog style document.
236 + *
237 + * @param $imgName The name of the icon from icons set to use.
238 + *#
239 +#macro(toolImage $imgName)(% class=~"icon-manage~"~%)$services.icon.render($imgName)(%~%)#end" %)
240 +(((
241 +(% class="macro-placeholder hidden" %)
242 +(((
243 +macro:velocity
244 +)))
245 +)))
246 +)))
247 +
248 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|##
249 +##
250 +##
251 +## Import the blog skin and javascripts.
252 +$!xwiki.ssx.use($blogStyleDocumentName)##
253 +$!xwiki.jsx.use($blogScriptsDocumentName)##
254 +##
255 +## import the hierarchy for the path the blog post footer (in displayEntryBlogLocation)
256 +#template('hierarchy_macros.vm')##
257 +##
258 +##
259 +#**
260 + * Prints a blog. This is the main macro used in the BlogSheet.
261 + *
262 + * @param blogDoc the XDocument holding the blog definition object.
263 + *###
264 +#macro(printBlog $blogDoc)
265 + \{\{include reference='Blog.CreatePost'/}}
266 +
267 + ## Use the blogPostList macro to display the blogposts
268 + ## The blogPostList is used only in case of 'all' or 'paged' blog display type because the blogPostList macro
269 + ## do not support FTM the monthly and weekly blog display types
270 + #getBlogDisplayType($blogDoc $displayType)
271 + #if ($displayType == 'weekly' || $displayType == 'monthly')
272 + #getBlogEntries($blogDoc $entries)
273 + #displayBlog($entries 'index' true true)
274 + #displayNavigationLinks($blogDoc)
275 + #else
276 + #getBlogDisplayType($blogDoc $displayType)
277 + #set ($paginated = 'no')
278 + #if ($displayType == 'paginated')
279 + #set ($paginated = 'yes')
280 + #end
281 + #getBlogPostsLayout($blogDoc $postsLayout)
282 + (% class=~"hfeed index~" ~%)(((\{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$paginated~" layout=~"$!postsLayout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" /}})))
283 + #end
48 48  #end
285 +##
286 +##
287 +##
288 +#**
289 + * Shows blog information. In view mode, the description is printed. In edit mode, allows changing blog settings: title,
290 + * description, blog type (global or in-space), index display type (fixed size pagination, weekly index, monthly index,
291 + * all entries).
292 + *
293 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
294 + *###
295 +#macro(showBlogInfo $blogDoc)
296 + #if($blogDoc.getObject($blogClassname))
297 + ## Keep testing for inline action for backward compatibility with older blogs.
298 + #if($xcontext.action == 'edit' || $xcontext.action == 'inline')
299 + #macro(displayProperty $blogDoc $propname)
300 + ; #displayPropName($xwiki.getClass($blogClassname).get($propname)):
301 + : $blogDoc.display($propname)
302 + #end
303 + #displayProperty($blogDoc 'title')
304 + #displayProperty($blogDoc 'description')
305 + #displayProperty($blogDoc 'displayType')
306 + #displayProperty($blogDoc 'itemsPerPage')
307 + #displayProperty($blogDoc 'postsLayout')
308 + #displayProperty($blogDoc 'postsLayoutParameters')
309 + #else
310 + $blogDoc.display('description')
311 + #end
312 + #elseif($doc.fullName == $blogSheet)
313 += $services.localization.render('blog.code.blogsheet') =
314 + \{\{translation key='blog.code.sheetexplanation'/}}
315 + #else
316 + \{\{warning}}\{\{translation key='blog.code.notblog'/}}\{\{/warning}}
317 + #end
318 +#end
319 +##
320 +##
321 +##
322 +#**
323 + * Retrieve the blog document, which usually is either <tt>&lt;Space&gt;.WebHome</tt> for whole-spaces blogs, or
324 + * <tt>&lt;Space&gt;.Blog</tt> for in-space blogs. If none of these documents contains a blog object, then the first
325 + * (alphabetically) document in the target space that contains one is returned. Finally, if no document in the current
326 + * space contains a blog object, then <tt>Blog.WebHome</tt> is returned as the default blog.
327 + *
328 + * @param space A <tt>String</tt>, the name of the space where to search.
329 + * @param blogDoc The resulting XDocument.
330 + *###
331 +#macro(getBlogDocument $space $blogDoc)
332 + #set ($result = $NULL)
333 + ## Check if the current space has a WebPreferences page that contains a Blog.EnablePanelsConfigurationClass object.
334 + ## It is possible to display a blog's panels info in a page that is not inside a blog and in that case we need to
335 + ## identify the right blog based on a configuration object in a WebPreferences page.
336 + #set ($spaceReference = $services.model.resolveSpace($space))
337 + #set ($preferencesDocRef = $services.model.createDocumentReference('WebPreferences', $spaceReference))
338 + #set ($preferencesDoc = $xwiki.getDocument($preferencesDocRef))
339 + #set ($preferencesObj = $preferencesDoc.getObject('Blog.EnablePanelsConfigurationClass'))
340 + #if ($preferencesObj)
341 + #set ($result = $xwiki.getDocument( $preferencesObj.getValue('blog')))
342 + #end
343 + ## If no special case occurs (like the previous one), identify a blog by checking the current location from its hierarchy.
344 + #if (~"$!result~" == '')
345 + ## First, try the Space.WebHome, for a whole-space blog
346 + #set($result = $xwiki.getDocument(~"$\{space}.WebHome~"))
347 + #if(!$result.getObject($blogClassname))
348 + ## Second, try the Space.Blog document
349 + #set($result = $xwiki.getDocument(~"$\{space}.Blog~"))
350 + #if(!$result.getObject($blogClassname))
351 + ## Third, try searching for a blog document in the current space
352 + ## Prevent the query fail when the space contains dots '.'
353 + #set($blogDocs = $services.query.hql(~", BaseObject obj where doc.space = :space and obj.name = doc.fullName and obj.className = '$blogClassname' order by doc.name~").setLimit(1).setOffset(0).bindValue('space', $space).execute())
354 + #if($blogDocs.size() > 0)
355 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
356 + #else
357 + ## Fourth, try searching for a blog document that have the its 'postsLocation' set to the current space
358 + #set($blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as postsLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=postsLocationProp.id.id and postsLocationProp.id.name='postsLocation' and postsLocationProp.value=:postsLocation order by doc.name~").setLimit(1).setOffset(0).bindValue('postsLocation', $space).execute())
359 + #if($blogDocs.size() > 0)
360 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
361 + #else
362 + ## Last, fallback to Blog.WebHome, the default blog
363 + #set($result = $xwiki.getDocument('Blog.WebHome'))
364 + #end
365 + #end
366 + #end
367 + #end
368 + #end
369 + #set ($blogDoc = $NULL)
370 + #setVariable (~"$blogDoc~" $result)
371 +#end
372 +##
373 +##
374 +##
375 +#**
376 + * Retrieve the blog title.
377 + *
378 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass<tt> object with the <tt>title</tt> property set.
379 + * @param title The resulting title.
380 + *###
381 +#macro(getBlogTitle $blogDoc $title)
382 + ## Titles can contain velocity code (most commonly translations), so we should evaluate them.
383 + #set ($title = $NULL)
384 + #setVariable (~"$title~" $!blogDoc.displayTitle)
385 +#end
386 +##
387 +##
388 +##
389 +#**
390 + * Retrieve the blog description.
391 + *
392 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>description</tt>
393 + * property set.
394 + * @param description The resulting description.
395 + *###
396 +#macro(getBlogDescription $blogDoc $description)
397 + #getBlogProperty($blogDoc 'description' '' $result)
398 + #set ($description = $NULL)
399 + #setVariable (~"$description~" $result)
400 +#end
401 +##
402 +##
403 +##
404 +#**
405 + * Retrieves a list of entries to be displayed. The entries are either part of the blog's space, or have the blog
406 + * document set as a parent. The number and range of entries returned (from all those belonging to this blog) depends on
407 + * the blog display type: paginated (fixed number of entries), weekly (all entries in a week), monthly (all entries in a
408 + * month), or all.
409 + *
410 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
411 + * @param entries The resulting list of entries to display, a list of XDocument names.
412 + *###
413 +#macro(getBlogEntries $blogDoc $entries)
414 + #if (!$entries)
415 + #setVariable (~"$entries~" [])
416 + #end
417 + #getAllBlogPostsQuery($query)
418 + #isDefaultBlog($blogDoc $isDefault)
419 + #set($queryParams = \{})
420 + #if ($isDefault)
421 + #getCategoryAllBlogPostsQuery($query)
422 + #set($query = ~"$\{query} and (doc.creator = :creator or (isPublished.value = 1 and hidden.value = 0)) and (doc.space = :space or catList like :catList escape '!')~")
423 + #set($discard = $queryParams.put('creator', $xcontext.user))
424 + #set($discard = $queryParams.put('space', $blogDoc.space))
425 + #set($sanitizedBlogSpace = $blogDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
426 + #set($discard = $queryParams.put('catList', $sanitizedBlogSpace))
427 + #else
428 + #set($query = ~"$\{query} and (doc.space = :space or doc.parent = :parent)~")
429 + #getBlogPostsLocation($blogDoc.space $blogPostsLocation)
430 + #set($discard = $queryParams.put('space', $blogPostsLocation))
431 + #set($discard = $queryParams.put('parent', $blogDoc.space))
432 + #end
433 + #getBlogDisplayType($blogDoc $displayType)
434 + #if($displayType == 'weekly')
435 + #getWeeklyBlogEntries($blogDoc $query $entries $queryParams)
436 + #elseif($displayType == 'monthly')
437 + #getMonthlyBlogEntries($blogDoc $query $entries $queryParams)
438 + #elseif($displayType == 'all')
439 + #getAllBlogEntries($blogDoc $query $entries $queryParams)
440 + #else
441 + #getPagedBlogEntries($blogDoc $query $entries $queryParams)
442 + #end
443 +#end
444 +##
445 +##
446 +##
447 +#**
448 + * Retrieves a list of entries to be displayed. The entries are taken from a ~"page~" of the blog, a sequence of documents
449 + * defined by the request parameters <tt>ipp</tt> (items per page) and <tt>page</tt> (the current page). Initially the
450 + * first page is displayed, with the number of entries defined in the blog object in the <tt>itemsPerPage</tt> property
451 + * (10 if not defined).
452 + *
453 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
454 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
455 + * refined to restrict to a given space, or to a given search criteria, etc.
456 + * @param entries The resulting list of entries to display, a list of XDocument names.
457 + * @param queryParams The parameters to bind with the query.
458 + *###
459 +#macro(getPagedBlogEntries $blogDoc $query $entries $queryParams)
460 + #if (!$entries)
461 + #setVariable (~"$entries~" [])
462 + #end
463 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
464 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~"))
465 + #bindQueryParameters($countQueryObj $queryParams)
466 + #bindQueryParameters($queryObj $queryParams)
467 + #set($totalEntries = $countQueryObj.count())
468 + #getBlogProperty($blogDoc 'itemsPerPage' '10' $defaultItemsPerPage)
469 + #set($defaultItemsPerPage = $numbertool.toNumber($defaultItemsPerPage).intValue())
470 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
471 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
472 + #set($discard = $entries.addAll($queryObj.setLimit($itemsPerPage).setOffset($startAt).addFilter(~"unique~").execute()))
473 +#end
474 +##
475 +##
476 +##
477 +#**
478 + * Retrieves a list of entries to be displayed. The entries are taken from a week of the blog. The target week is
479 + * defined by the request parameters <tt>week</tt> (the week number in the year, from 1 to 52) and <tt>year</tt> (4
480 + * digit year). Initially the current week is displayed.
481 + *
482 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
483 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
484 + * refined to restrict to a given space, or to a given search criteria, etc.
485 + * @param entries The resulting list of entries to display, a list of XDocument names.
486 + * @param queryParams The parameters to bind with the query.
487 + *###
488 +#macro(getWeeklyBlogEntries $blogDoc $query $entries $queryParams)
489 + #if (!$entries)
490 + #setVariable (~"$entries~" [])
491 + #end
492 + #getRequestedWeek($weekDate)
493 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
494 + #set($minDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundFloor()))
495 + #set($maxDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundCeiling()))
496 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
497 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
498 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
499 + #bindQueryParameters($countQueryObj $queryParams)
500 + #bindQueryParameters($queryObj $queryParams)
501 + #set($totalEntries = $countQueryObj.count())
502 + #set($discard = $entries.addAll($queryObj.execute()))
503 +#end
504 +##
505 +##
506 +##
507 +#**
508 + * Retrieves a list of entries to be displayed. The entries are taken from a month of the blog. The target month is
509 + * defined by the request parameters <tt>month</tt> (the month number, from 1 to 12) and <tt>year</tt> (4
510 + * digit year). Initially the current month is displayed.
511 + *
512 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
513 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
514 + * refined to restrict to a given space, or to a given search criteria, etc.
515 + * @param entries The resulting list of entries to display, a list of XDocument names.
516 + * @param queryParams The parameters to bind with the query.
517 + *###
518 +#macro(getMonthlyBlogEntries $blogDoc $query $entries)
519 + #if (!$entries)
520 + #setVariable (~"$entries~" [])
521 + #end
522 + #getRequestedMonth($monthDate)
523 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
524 + #set($minDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundFloor()))
525 + #set($maxDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundCeiling()))
526 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
527 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
528 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
529 + #bindQueryParameters($countQueryObj $queryParams)
530 + #bindQueryParameters($queryObj $queryParams)
531 + #set($totalEntries = $countQueryObj.count())
532 + #set($discard = $entries.addAll($queryObj.execute()))
533 +#end
534 +##
535 +##
536 +##
537 +#**
538 + * Retrieves a list of entries to be displayed. All entries belonging to the current blog are returned.
539 + *
540 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
541 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
542 + * refined to restrict to a given space, or to a given search criteria, etc.
543 + * @param entries The resulting list of entries to display, a list of XDocument names.
544 + * @param queryParams The parameters to bind with the query.
545 + *###
546 +#macro(getAllBlogEntries $blogDoc $query $entries $queryParams)
547 + #if (!$entries)
548 + #setVariable (~"$entries~" [])
549 + #end
550 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
551 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
552 + #bindQueryParameters($countQueryObj $queryParams)
553 + #bindQueryParameters($queryObj $queryParams)
554 + #set($totalEntries = $countQueryObj.count())
555 + #set($discard = $entries.addAll($queryObj.execute()))
556 +#end
557 +##
558 +##
559 +##
560 +#**
561 + * Retrieves a list of entries to be displayed. Only (and all) unpublished entries are returned.
562 + *
563 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
564 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
565 + * refined to restrict to a given space, or to a given search criteria, etc.
566 + * @param queryParams The parameters to bind with the query.
567 + * @param entries The resulting list of entries to display, a list of XDocument names.
568 + *###
569 +#macro(getUnpublishedBlogEntries $blogDoc $query $queryParams $entries)
570 + #if (!$entries)
571 + #setVariable (~"$entries~" [])
572 + #end
573 + #set($query = ~"$\{query} and isPublished.value = 0~")
574 + #set ($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
575 + #set ($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
576 + #bindQueryParameters($countQueryObj $queryParams)
577 + #bindQueryParameters($queryObj $queryParams)
578 + #set($totalEntries = $countQueryObj.count())
579 + #set($discard = $entries.addAll($queryObj.execute()))
580 +#end
581 +##
582 +##
583 +##
584 +#**
585 + * Retrieves a list of entries to be displayed. The entries are taken from all the wiki, and not from a specific blog.
586 + *
587 + * @param entries The resulting list of entries to display, a list of XDocument names.
588 + *###
589 +#macro(getGlobalBlogEntries $entries)
590 + #if (!$entries)
591 + #setVariable (~"$entries~" [])
592 + #end
593 + #getAllBlogPostsQuery($query)
594 + #set($totalEntries = $services.query.hql($query).count())
595 + #set($defaultItemsPerPage = 20)
596 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
597 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
598 + #set($discard = $entries.addAll($services.query.hql(~"$\{query} order by publishDate.value desc~").setLimit($itemsPerPage).setOffset($startAt).execute()))
599 +#end
600 +#**
601 + * Return the base query for selecting blog entries. It filters only visible entries, but does not bind to a specific
602 + * blog, nor specify a range or an ordering criteria.
603 + *
604 + * This macro is a duplicate of #getAllBlogPostsQuery($query). Keep it in case it's used outside, in custom code.
605 + *
606 + * @param query The basic query for selecting blog entries.
607 + *#
608 +#macro(getBlogEntriesBaseQuery $query)
609 + #getAllBlogPostsQuery($query)
610 +#end
611 +#**
612 + * Return the Query for selecting the all wiki blog posts without filtering
613 + *
614 + * @param query The basic query for selecting blog entries.
615 + *#
616 +#macro(getAllBlogPostsQuery $query)
617 + #set ($query = $NULL)
618 + #setVariable(~"$query~" ~", BaseObject as obj, IntegerProperty isPublished,
619 + IntegerProperty hidden, DateProperty publishDate
620 + where doc.fullName <> '$blogPostTemplate' and
621 + obj.name=doc.fullName and obj.className='$blogPostClassname' and
622 + isPublished.id.id = obj.id and isPublished.id.name = 'published' and
623 + hidden.id.id = obj.id and hidden.id.name='hidden' and
624 + publishDate.id.id = obj.id and publishDate.id.name='publishDate' and
625 + (doc.creator = '$escapetool.sql($xcontext.user)' or (isPublished.value = 1 and hidden.value = 0))~")
626 +#end
627 +##
628 +##
629 +##
630 +###**
631 + * Return the Query for selecting the all wiki blog posts with categories filtering
632 + *
633 + * @param query The basic query for selecting blog entries.
634 + *###
635 +#macro(getCategoryAllBlogPostsQuery $query)
636 + #set ($query = $NULL)
637 + #getAllBlogPostsQuery($baseQuery)
638 + #set ($baseQuery = $baseQuery.replace('DateProperty publishDate', 'DateProperty publishDate, DBStringListProperty as category left join category.list catList'))
639 + #setVariable(~"$query~" ~"$\{baseQuery} and obj.id=category.id.id and category.id.name='category'~")
640 +#end
641 +##
642 +##
643 +##
644 +#**
645 + * Determines how is the blog index split into pages: paginated (fixed number of entries), weekly (all entries in a
646 + * week), monthly (all entries in a month), or all.
647 + *
648 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>displayType</tt>
649 + * property set.
650 + * @param displayType The resulting string. If the blog object does not define anything, it is considered paginated.
651 + *###
652 +#macro(getBlogDisplayType $blogDoc $displayType)
653 + #getBlogProperty($blogDoc 'displayType' 'paginated' $result)
654 + #set ($displayType = $NULL)
655 + #setVariable (~"$displayType~" $result)
656 +#end
657 +##
658 +##
659 +##
660 +#**
661 + * Displays a list of entries.
662 + *
663 + * @param entries The entries to display, a list of XDocument names.
664 + * @param displaying What exactly is displayed: blog index, a single blog entry, a blog category, search results,
665 + * unpublished entries, etc. This will be used as the classname(s) for the container div (hfeed). Currently
666 + * used values: index, single, category, search, unpublished, hidden.
667 + * @param onlyExtract If <tt>true</tt>, only display the extract of articles where available, otherwise display the full content.
668 + * @param shouldDisplayTitles If <tt>true</tt>, display the blog title (blog posts shouldn't display the title when they're
669 + * displayed alone on their page since it's the page title which is used in this case)
670 + *###
671 +#macro(displayBlog $entries $displaying $onlyExtract $shouldDisplayTitles)
672 + #set($blogDay = '')
673 + (% class=~"hfeed $!\{displaying}~" ~%)(((
674 + (% class=~"blogDay~" ~%)(((
675 + #foreach ($entryDoc in $xwiki.wrapDocs($entries))
676 + #getEntryObject($entryDoc $entryObj)
677 + ## Although all entries should have one of the two objects, better check to be sure.
678 + #if(~"$!\{entryObj}~" != '')
679 + #getEntryDate($entryDoc $entryObj $entryDate)
680 + ## Display a ~"calendar sheet~" for each day. All entries posted on the same day share one such sheet.
681 + #set($entryDateStr = $xwiki.formatDate($entryDate, 'yyyyMMMMdd'))
682 + #if($blogDay != $entryDateStr)
683 + #if($blogDay != '')
684 + )))
685 + (% class=~"blogDay~" ~%)(((
686 + #end
687 + #displayBlogDate($entryDate)
688 + #set ($blogDay = $entryDateStr)
689 + #end
690 + ## Finally, display the entry.
691 + #displayEntry($entryDoc $entryObj $onlyExtract $shouldDisplayTitles true)
692 + #end
693 + #end
694 + )))## blogDay
695 + )))## hfeed
696 +#end
697 +##
698 +##
699 +##
700 +#**
701 + * Get the entry object, either a new BlogPost or an old Article.
702 + *
703 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
704 + * @param entryObj The resulting xobject of the blog post.
705 + *###
706 +#macro(getEntryObject $entryDoc $__entryObj)
707 + #set($result = $entryDoc.getObject(~"$\{blogPostClassname}~"))
708 + #if(!$result)
709 + #set($result = $entryDoc.getObject(~"$\{oldArticleClassname}~"))
710 + #end
711 + ## NOTE: The reason we put an underscore in front of the variable name is to prevent the following line from
712 + ## overwriting the $entryObj variable that may be defined before this macro is called. Of course, $__entryObj may be
713 + ## overwritten in this case but it's less likely to have such a variable defined before.
714 + #set ($__entryObj = $NULL)
715 + #setVariable (~"$__entryObj~" $result)
716 +#end
717 +##
718 +##
719 +##
720 +#**
721 + * Gets the date associated with a blog entry. This is the publication date. For unpublished entries, initially this is
722 + * the document creation date, but can be edited by the user.
723 + *
724 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
725 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
726 + * @param result The resulting date, an instance of <tt>java.util.Date</tt>.
727 + *###
728 +#macro(getEntryDate $entryDoc $entryObj $result)
729 + #set ($result = $NULL)
730 + #setVariable (~"$result~" $entryObj.getProperty('publishDate').value)
731 +#end
732 +##
733 +##
734 +##
735 +#**
736 + * Displays a date, nicely formatted as a calendar page.
737 + *
738 + * @param date The date to display, an instance of <tt>java.util.Date</tt>.
739 + *###
740 +#macro(displayBlogDate $date)
741 + #set($year = $xwiki.formatDate($date, 'yyyy'))
742 + ## 3 letter month name, like Jan, Dec.
743 + #set($month = $xwiki.formatDate($date, 'MMM'))
744 + ## Uncomment to get a full length month name, like January, December.
745 + ## TODO: this could be defined somewhere in the blog style.
746 + ## #set($month = $xwiki.formatDate($date, 'MMMM'))
747 + #set($day = $xwiki.formatDate($date, 'dd'))
748 + (% class=~"blogdate~" ~%)
749 + == (% class=~"month~" ~%)$month(%~%) (% class=~"day~" ~%)$day(%~%) (% class=~"year~" ~%)$year(%~%) ==
750 +#end
751 +##
752 +##
753 +##
754 +#**
755 + * Displays a blog article: management tools, header, content, footer.
756 + *
757 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
758 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
759 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
760 + * @param shouldDisplayTitle If <tt>true</tt>, display the blog title (blog posts shouldn't display the title
761 + * when they're displayed alone on their page since it's the page title which is used in this case)
762 + * @param shouldDisplayActions If <tt>true</tt>, display the blog post actions buttons
763 + *###
764 +#macro(displayEntry $entryDoc $entryObj $onlyExtract $shouldDisplayTitle $shouldDisplayActions)
765 + ## Only articles with an explicit hidden setting or an explicit unpublished setting are hidden
766 + #isPublished($entryObj $isPublished)
767 + #isHidden($entryObj $isHidden)
768 + #if($doc.fullName == $entryDoc.fullName)
769 + (% class=~"hentry single-article~" ~%)(((
770 + #else
771 + (% class=~"hentry#if(!$isPublished) unpublished-article#elseif($isHidden) hidden-article#end~" ~%)(((
772 + #end
773 + #if ($shouldDisplayActions)
774 + #displayEntryTools($entryDoc $entryObj)
775 + #end
776 + #if($shouldDisplayTitle)
777 + #displayEntryTitle($entryDoc $entryObj)
778 + #end
779 + #if($doc.fullName == $entryDoc.fullName)
780 + #if(!$isPublished)
781 + \{\{warning}}\{\{translation key='blog.code.published'/}}\{\{/warning}}
782 + #elseif($isHidden)
783 + \{\{warning}}\{\{translation key='blog.code.hidden'/}}\{\{/warning}}
784 + #end
785 + #end
786 + #displayEntryContent($entryDoc $entryObj $onlyExtract)
787 + #displayEntryFooter($entryDoc $entryObj)
788 + )))## hentry
789 +#end
790 +##
791 +##
792 +##
793 +#**
794 + * Checks if the provided blog is published or not.
795 + *
796 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
797 + * @param isPublished The resulting boolean, true if the entry is considered published.
798 + *###
799 +#macro(isPublished $entryObj $isPublished)
800 + #set ($isPublished = $NULL)
801 + ## This should work for both old articles, which don't have the 'published' property at all, and
802 + ## are considered published by default, and new entries, that should have 1 if published.
803 + #if (~"$!\{entryObj.getProperty('published').value}~" != '0')
804 + #setVariable (~"$isPublished~" true)
805 + #else
806 + #setVariable (~"$isPublished~" false)
807 + #end
808 +#end
809 +##
810 +##
811 +##
812 +#**
813 + * Checks if the provided blog is hidden or not.
814 + *
815 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass<tt> xclass.
816 + * @param isHiddel The resulting boolean, true if the entry is considered hidden.
817 + *###
818 +#macro(isHidden $entryObj $isHidden)
819 + #set ($isHidden = $NULL)
820 + ## This should work for both old articles, which don't have the 'hidden' property at all, and
821 + ## are considered visible by default, and new entries, that should have 1 if hidden.
822 + #if (~"$!\{entryObj.getProperty('hidden').value}~" == '1')
823 + #setVariable (~"$isHidden~" true)
824 + #else
825 + #setVariable (~"$isHidden~" false)
826 + #end
827 +#end
828 +##
829 +##
830 +##
831 +#**
832 + * Displays several ~"tools~" for manipulating blog posts: hide/show, publish, edit.
833 + *
834 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
835 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
836 + *###
837 +#macro(displayEntryTools $entryDoc $entryObj)
838 + #if($xcontext.action == 'view')
839 + (% class=~"blog-entry-toolbox~" ~%)(((
840 + #displayPublishButton($entryDoc $entryObj)
841 + #displayHideShowButton($entryDoc $entryObj)
842 + #displayEditButton($entryDoc $entryObj)
843 + #displayDeleteButton($entryDoc $entryObj)
844 + )))
845 + #end
846 +#end
847 +##
848 +##
849 +##
850 +#**
851 + * Displays the publish button to the entry <strong>creator</strong>, if the article is not published yet.
852 + *
853 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
854 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
855 + * @todo AJAX calls.
856 + *###
857 +#macro(displayPublishButton $entryDoc $entryObj)
858 + #isPublished($entryObj $isPublished)
859 + #if(!$isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
860 + [[#toolImage('world')>>path:$blogPublisher.getURL('view', ~"entryName=$\{escapetool.url($entryDoc.fullName)}&xredirect=$\{escapetool.url($thisURL)}&form_token=$!\{services.csrf.getToken()}~")||title=~"$services.localization.render('blog.code.notpublished')~"]]##
861 + #end
862 +#end
863 +##
864 +##
865 +##
866 +#**
867 + * Displays the hide or show button to the entry <strong>creator</strong>, if the article is already published.
868 + *
869 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
870 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
871 + *###
872 +#macro(displayHideShowButton $entryDoc $entryObj)
873 + #isPublished($entryObj $isPublished)
874 + #isHidden($entryObj $isHidden)
875 + ## Only published articles can be hidden. Unpublished articles are considered already hidden.
876 + #if($isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
877 + #set ($queryString = \{
878 + 'xredirect' : $thisURL,
879 + 'form_token' : $services.csrf.getToken()
880 + })
881 + #if ($isHidden)
882 + #set ($discard = $queryString.putAll(\{
883 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 0,
884 + 'comment' : $services.localization.render('blog.code.madevisible')
885 + }))
886 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
887 + [[#toolImage('unlock')>>path:$lockURL||class=~"blog-tool-show~" title=~"$services.localization.render('blog.code.makevisible')~"]]##
888 + #else
889 + #set ($discard = $queryString.putAll(\{
890 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 1,
891 + 'comment' : $services.localization.render('blog.code.hid')
892 + }))
893 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
894 + [[#toolImage('lock')>>path:$lockURL||class=~"blog-tool-hide~" title=~"$services.localization.render('blog.code.hide')~"]]##
895 + #end
896 + #end
897 +#end
898 +##
899 +##
900 +##
901 +#**
902 + * Displays the edit button to those that can edit the article.
903 + *
904 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
905 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
906 + *###
907 +#macro(displayEditButton $entryDoc $entryObj)
908 + #if($xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
909 + ## Call getDefaultEditMode() for backward compatibility with older blog posts.
910 + [[#toolImage('pencil')>>path:$entryDoc.getURL('edit')||title=~"$services.localization.render('blog.code.editpost')~"]]##
911 + #end
912 +#end
913 +##
914 +##
915 +##
916 +#**
917 + * Displays the delete button to those that can edit the article.
918 + *
919 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
920 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
921 + * @todo AJAX calls.
922 + *###
923 +#macro(displayDeleteButton $entryDoc $entryObj)
924 + #if($xwiki.hasAccessLevel('delete', $xcontext.user, $entryDoc.fullName))
925 + [[#toolImage('cross')>>path:$entryDoc.getURL('delete')||title=~"$services.localization.render('blog.code.deletepost')~"]]##
926 + #end
927 +#end
928 +##
929 +##
930 +##
931 +#**
932 + * Displays the title of the entry.
933 + *
934 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
935 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
936 + *###
937 +#macro(displayEntryTitle $entryDoc $entryObj)
938 + #if($doc.fullName == $entryDoc.fullName)
939 + (% class=~"entry-title~" ~%)
940 + = $services.rendering.escape($entryDoc.display('title', 'view', $entryObj), $xwiki.getCurrentContentSyntaxId()) =
941 + #else
942 + (% class=~"entry-title~" ~%)
943 + === [[$services.rendering.escape($entryDoc.display('title', 'view', $entryObj),$xwiki.getCurrentContentSyntaxId())>>doc:$services.rendering.escape($services.model.serialize($entryDoc.getDocumentReference(),'default'),$xwiki.getCurrentContentSyntaxId())]] ===
944 + #end
945 +#end
946 +##
947 +##
948 +##
949 +#**
950 + * Displays the body of the entry.
951 + *
952 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
953 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
954 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
955 + *###
956 +#macro(displayEntryContent $entryDoc $entryObj $onlyExtract)
957 + (% class=~"#if($onlyExtract)entry-summary#\{else}entry-content#end~" ~%)(((
958 + #getEntryContent($entryDoc $entryObj $onlyExtract $entryContent)
959 + ## FIXME: This causes the blog's content to not be annotatable. See http://jira.xwiki.org/browse/XWIKI-6328
960 + ## Should probably be replaced by a display macro call with a reference to the object property holding the post's content
961 + \{\{html wiki=~"false~"}}$entryDoc.getRenderedContent($entryContent, $entryDoc.syntax.toIdString())\{\{/html}}
962 + ))) ## entry-content
963 + (% class=~"clearfloats~" ~%)((()))
964 +#end
965 +##
966 +##
967 +##
968 +#**
969 + * Extracts the body of the entry that should be displayed. If <tt>onlyExtract</tt> is <tt>true</tt>, display the content
970 + * of the <tt>extract</tt> field (if not empty).
971 + *
972 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
973 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
974 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
975 + * @param entryContent The resulting content.
976 + * @param removeEllipsis If <tt>true</tt>, then don't display an ellipsis at the end of the content (only used when
977 + * <tt>onlyExtract</tt> is <tt>true</tt>)
978 + *###
979 +#macro(getEntryContent $entryDoc $entryObj $onlyExtract $entryContent $removeEllipsis)
980 + #if ($onlyExtract)
981 + ## Note: We trim the summary so that if there's some white space it won't cause the summary to be used instead
982 + ## of the content.
983 + #set ($macro.result = $entryObj.getProperty('extract').value.trim())
984 + #end
985 + #if(~"$!macro.result~" == '')
986 + #set($macro.result = $entryObj.getProperty('content').value)
987 +#* Disabled until the content can be cleanly cut.
988 +* #if($onlyExtract && $result.length()>$maxchars)
989 +* #set($i = $macro.result.lastIndexOf(~" ~", $maxchars))
990 +* #set($i = $i + 1)
991 +* #set($macro.result = ~"$\{macro.result.substring(0,$i)} *[...>$\{entryDoc.fullName}]*~")
992 +* #end
993 +## *###
994 + #elseif (!$removeEllipsis)
995 + #if($entryDoc.syntax.toIdString() == 'xwiki/1.0')
996 + #set($macro.result = ~"$\{macro.result} <a href='$\{entryDoc.getExternalURL()}' title='$services.localization.render('blog.code.readpost')'>...</a>~")
997 + #elseif($entryDoc.syntax.toIdString() == 'xwiki/2.0' || $entryDoc.syntax.toIdString() == 'xwiki/2.1')
998 + #set($macro.result = ~"$\{macro.result} [[...>>$\{services.rendering.escape($entryDoc.getFullName(), $entryDoc.getSyntax())}||title='$services.localization.render('blog.code.readpost')']]~")
999 + #end
1000 + #end
1001 + #set ($entryContent = $NULL)
1002 + #setVariable (~"$entryContent~" $macro.result)
1003 +#end
1004 +##
1005 +##
1006 +##
1007 +#**
1008 + * Displays the footer of the entry.
1009 + *
1010 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
1011 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
1012 + *###
1013 +#macro(displayEntryFooter $entryDoc $entryObj)
1014 + (% class=~"entry-footer~" ~%)(((
1015 + #isPublished($entryObj $isPublished)
1016 + (% class='entry-author-label' ~%)
1017 + #if($isPublished)
1018 + \{\{translation key='blog.code.postedby'/}} ##
1019 + #else
1020 + \{\{translation key='blog.code.createdby'/}} ##
1021 + #end
1022 + \{\{html wiki=~"false~" clean=~"false~"}}<span class='author vcard'>#userfn($entryDoc.creator)</span>\{\{/html}} ##
1023 + #getEntryDate($entryDoc $entryObj $entryDate)
1024 + #listCategories($entryObj) #*
1025 + ## Since the publish date and update date are not set at the exact same time, there could be a small difference that
1026 + ## we assume cannot be more than 3 seconds.
1027 + *#(% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.permalink'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||rel=~"bookmark~"]] ##
1028 + #if ($showcomments)
1029 + (% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.comments'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||anchor=~"Comments~"]] (% class=~"itemCount~" ~%)($entryDoc.comments.size())(%~%) ##
1030 + #end ##
1031 + #if($entryDoc != $doc) ##
1032 + #displayEntryBlogLocation($entryDoc $entryObj) ##
1033 + #end
1034 + )))## entry-footer
1035 +#end
1036 +##
1037 +##
1038 +#**
1039 + * Display the blog for the entry (if it is not the currently displayed blog)
1040 + *
1041 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
1042 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
1043 + *###
1044 +#macro(displayEntryBlogLocation $entryDoc $entryObj)
1045 + #getBlogPostsLocation($entryDoc.getSpace() $blogPostsLocation) ##
1046 + #if(~"$!blogPostsLocation~" != ~"~") ##
1047 + #set($blogSpaceRef = $services.model.resolveSpace($blogPostsLocation)) ##
1048 + #set($blogDocRef = $services.model.createDocumentReference($services.model.getEntityReference('DOCUMENT', 'default').getName(), $blogSpaceRef)) ##
1049 + #if($doc.documentReference != $blogDocRef) ##
1050 + #set($blogDoc = $xwiki.getDocument($blogDocRef)) ##
1051 + #set($blogObj = $blogDoc.getObject('Blog.BlogClass')) ##
1052 + #if($blogObj) (% class=~"blogrefpath~" ~%)((( ##
1053 + $services.localization.render('blog.code.postedin') \{\{html clean=~"false~" wiki=~"false~"}} #hierarchy($blogDocRef, \{'selfIsActive' : true, 'local': true}) \{\{/html}} ##
1054 + )))(%~%)##
1055 + #end
1056 + #end
1057 + #end
1058 +#end
1059 +##
1060 +##
1061 +##
1062 +##
1063 +#**
1064 + * List the categories an entry belongs to. Used in the footer. The categories are instances of <tt>Blog.CategoryClass</tt>.
1065 + *
1066 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
1067 + *###
1068 +#macro(listCategories $entryObj)
1069 + #if($entryObj.getxWikiClass().getName() == $blogPostClassname)
1070 + #set($categories = $entryObj.getProperty('category').value)
1071 + #set($first = true)
1072 + #if($categories.size() > 0)
1073 + #foreach($category in $categories)
1074 + #set($categoryDoc = $!xwiki.getDocument($category))
1075 + #if(!$categoryDoc.isNew() && $categoryDoc.getObject($\{blogCategoryClassname}))
1076 + #if($foreach.count == 1)
1077 + (% class='separator' ~%)·(%~%) $services.localization.render('blog.code.categories') ##
1078 + #else
1079 + , ##
1080 + #end##
1081 + [[$!\{categoryDoc.getObject($blogCategoryClassname).getValue('name')}>>$\{category}||rel='tag']]##
1082 + #end##
1083 + #end##
1084 + #end
1085 + #end
1086 +#end
1087 +##
1088 +##
1089 +##
1090 +#**
1091 + * Displays blog pagination links (older and newer entries).
1092 + *
1093 + * @param blogDoc the XDocument holding the blog definition object.
1094 + *###
1095 +#macro(displayNavigationLinks $blogDoc)
1096 + (% class=~"clearfloats~" ~%)((()))
1097 + #getBlogDisplayType($blogDoc $displayType)
1098 + #if($displayType == 'weekly')
1099 + (% class=~"pagingLinks~" ~%)(((
1100 + #getRequestedWeek($weekDate)
1101 + $weekDate.addWeeks(-1)##
1102 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousweek'/}}>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
1103 + #sep()
1104 + $weekDate.addWeeks(2)## 2 because we already subtracted 1 above
1105 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextweek'/}} »>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
1106 + )))
1107 + #elseif($displayType == 'monthly')
1108 + (% class=~"pagingLinks~" ~%)(((
1109 + #getRequestedMonth($monthDate)
1110 + $monthDate.addMonths(-1)##
1111 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousmonth'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
1112 + #sep()
1113 + $monthDate.addMonths(2)## 2 because we already subtracted 1 above
1114 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextmonth'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
1115 + )))
1116 + #elseif($displayType == 'all')
1117 + #else
1118 + ## Paginated
1119 + #if(($totalPages > 1))
1120 + #set($queryString = '')
1121 + #foreach($p in $request.getParameterNames())
1122 + #if($p != 'page' && $p != 'ipp')
1123 + #foreach($v in $request.getParameterValues($p))
1124 + #set($queryString = ~"$\{queryString}&$\{escapetool.url($p)}=$\{escapetool.url($v)}~")
1125 + #end
1126 + #end
1127 + #end
1128 + (% class=~"pagingLinks~" ~%)(((
1129 + #if ($currentPageNumber < $totalPages)
1130 + #set($currentPageNumber = $currentPageNumber + 1)
1131 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.olderposts'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
1132 + #set($currentPageNumber = $currentPageNumber - 1)
1133 + #end
1134 + #if ($currentPageNumber > 1)
1135 + #if ($currentPageNumber < $totalPages)
1136 + #sep()
1137 + #end
1138 + #set($currentPageNumber = $currentPageNumber - 1)
1139 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.newerposts'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
1140 + #set($currentPageNumber = $currentPageNumber + 1)
1141 + #end
1142 + (% class=~"clear~" ~%)(%~%)
1143 + )))## pagingLinks
1144 + #end
1145 + #end
1146 +#end
1147 +##
1148 +##
1149 +##
1150 +#**
1151 + * Displays a message box with ~"publish~" icon.
1152 + *
1153 + * @param message A text message concerning blog article publishing
1154 + *###
1155 +#macro(publishMessageBox $message)
1156 +(% class=~"plainmessage publish-message~" ~%)((($services.icon.render('world') $message)))
1157 +#end
1158 +#**
1159 + * Displays a message box with ~"show/hide~" icon.
1160 + *
1161 + * @param message A text message concerning blog article hiding
1162 + *###
1163 +#macro(hideMessageBox $message)
1164 +(% class=~"plainmessage hide-message~" ~%)((($services.icon.render('unlock') $message)))
1165 +#end
1166 +##
1167 +##
1168 +##
1169 +#**
1170 + * Determine the requested week, for using in a weekly-indexed blog. The relevant request parameters are
1171 + * <tt>year</tt> and <tt>week</tt>. By default, the current week is used.
1172 + *
1173 + * @param monthDate The resulting week, a JODATime MutableDateTime.
1174 + *###
1175 +#macro(getRequestedWeek $weekDate)
1176 + #set ($weekDate = $NULL)
1177 + #setVariable (~"$weekDate~" $xwiki.jodatime.mutableDateTime)
1178 + #if(~"$!\{request.year}~" != '')
1179 + #set ($discard = $weekDate.setYear($numbertool.toNumber($request.year).intValue()))
1180 + #end
1181 + #if(~"$!\{request.week}~" != '')
1182 + #set ($discard = $weekDate.setWeekOfWeekyear($numbertool.toNumber($request.week).intValue()))
1183 + #end
1184 +#end
1185 +##
1186 +##
1187 +##
1188 +#**
1189 + * Determine the requested month, for using in a monthly-indexed blog. The relevant request parameters are
1190 + * <tt>year</tt> and <tt>month</tt>. By default, the current month is used.
1191 + *
1192 + * @param monthDate The resulting month, a JODATime MutableDateTime.
1193 + *###
1194 +#macro(getRequestedMonth $monthDate)
1195 + #set ($monthDate = $NULL)
1196 + #setVariable (~"$monthDate~" $xwiki.jodatime.mutableDateTime)
1197 + #if(~"$!\{request.year}~" != '')
1198 + #set ($discard = $monthDate.setYear($numbertool.toNumber($request.year).intValue()))
1199 + #end
1200 + #if(~"$!\{request.month}~" != '')
1201 + #set ($discard = $monthDate.setMonthOfYear($numbertool.toNumber($request.month).intValue()))
1202 + #end
1203 +#end
1204 +##
1205 +##
1206 +##
1207 +#**
1208 + * Retrieve a blog property (title, display type, etc).
1209 + *
1210 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
1211 + * @param propertyName The name of the property to be retrieved. One of the <tt>Blog.BlogClass</tt>'s properties.
1212 + * @param defaultValue The default value to use in case the blog object does not define one.
1213 + * @param propertyValue The resulting value.
1214 + *###
1215 +#macro(getBlogProperty $blogDoc $propertyName $defaultValue $propertyValue)
1216 + #set($result = ~"$!\{blogDoc.getObject($\{blogClassname}).getProperty($propertyName).value}~")
1217 + #if($result == '')
1218 + #set($result = $defaultValue)
1219 + #end
1220 + #set ($propertyValue = $NULL)
1221 + #setVariable (~"$propertyValue~" $result)
1222 +#end
49 49  
50 -{{/velocity}}
1224 +#**
1225 + * If an error occurs when executing an action, set a specific response status and display an error message.
1226 + *
1227 + * @param status The response status.
1228 + * @param text The user readable error to be displayed. Can be a translation key.
1229 + * @param parameters The parameters to use when decoding the translation key.
1230 + *###
1231 +#macro(blog__actionResponseError $status $text $parameters)
1232 + $response.setStatus($status)
1233 + #if($request.ajax)
1234 + $services.localization.render($text, $!parameters)
1235 + #else
1236 + \{\{error}}$services.localization.render($text, $!parameters)\{\{/error}}
1237 + #end
1238 +#end
1239 +##
1240 +##
1241 +##
1242 +#**
1243 + * Check if a blog is the Default blog (The one in the 'Blog' space).
1244 + *
1245 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
1246 + * @param isDefault The resulting boolean.
1247 + *###
1248 +#macro(isDefaultBlog $blogDoc $isDefault)
1249 + #set ($result = false)
1250 + #if ($blogDoc.space == 'Blog')
1251 + #set ($result = true)
1252 + #end
1253 + #setVariable(~"$isDefault~" $result)
1254 +#end
1255 +##
1256 +##
1257 +##
1258 +#**
1259 + * Retrieve the blog posts location (space).
1260 + *
1261 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
1262 + * @param postsLocation The resulting location.
1263 + *###
1264 +#macro(getBlogPostsLocation $blogSpace $postsLocation)
1265 + #getBlogDocument($blogSpace $blogDoc)
1266 + #getBlogProperty($blogDoc 'postsLocation' $blogDoc.space $result)
1267 + #set ($postsLocation = $NULL)
1268 + #setVariable (~"$postsLocation~" $result)
1269 +#end
1270 +##
1271 +##
1272 +##
1273 +#**
1274 + * Retrieve the blog categories location (space).
1275 + *
1276 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
1277 + * @param categoriesLocation The resulting location.
1278 + *###
1279 +#macro(getBlogCategoriesLocation $blogSpace $categoriesLocation)
1280 + #getBlogDocument($blogSpace $blogDoc)
1281 + #getBlogProperty($blogDoc 'categoriesLocation' 'Blog' $result)
1282 + #set ($postsLocation = $NULL)
1283 + #setVariable (~"$categoriesLocation~" $result)
1284 +#end
1285 +###**
1286 + * Return the Query for selecting the blog posts based on the context where the posts are displayed.
1287 + * for example there is 4 different panel contexts:
1288 + * aBlog.aPost or aBlog.WebHome
1289 + * aCategorySpace.aCategory
1290 + * aCategorySpace.WebHome
1291 + * Blog.aPost or Blog.WebHome
1292 + *
1293 + * @param query The query for selecting blog entries.
1294 + * @param queryParams The parameters to bind with the generated query.
1295 + * @param targetDoc The document in which the articles will be displayed.
1296 + *###
1297 +#macro(getAllBlogPostsQueryBasedOnDisplayContext $targetDoc $query $queryParams)
1298 + #set ($query = $NULL)
1299 + #set ($queryParams = $NULL)
1300 + #getCategoryAllBlogPostsQuery($resultQuery)
1301 + #set ($resultQueryParams = \{})
1302 + #set($sanitizedSpace = $targetDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
1303 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
1304 + ## Get all posts that are in the default blog space('Blog') or in category 'Blog.%'
1305 + #set ($discard = $resultQueryParams.put('space', $targetDoc.space))
1306 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
1307 + #set($resultQuery = ~"$\{resultQuery} and (doc.space = :space or catList like :catList escape '!')~")
1308 + #elseif($targetDoc.getObject($blogCategoryClassname))
1309 + ## Get all posts that are in a category aCategorySpace.aCategory
1310 + #set ($discard = $resultQueryParams.put('catList', $targetDoc.fullName))
1311 + #set($resultQuery = ~"$\{resultQuery} and (catList=:catList)~")
1312 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
1313 + ## Get all posts that are in a category aCategorySpace.%
1314 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
1315 + ## Exclude incategorized posts
1316 + #set ($excludedCategory = ~"$\{targetDoc.space}.WebHome~")
1317 + #if ($targetDoc.space == $defaultBlogSpace)
1318 + #set ($excludedCategory = ~"Blog.Categories.WebHome~")
1319 + #end
1320 + #set ($discard = $resultQueryParams.put('excludedCategory', $excludedCategory))
1321 + #set($resultQuery = ~"$\{resultQuery} and (catList<>:excludedCategory) and (catList like :catList escape '!')~")
1322 + #else
1323 + ## Get all posts in blog space aBlog
1324 + #getAllBlogPostsQuery($resultQuery)
1325 + #getBlogPostsLocation($targetDoc.space $postsLocation)
1326 + #set ($discard = $resultQueryParams.put('space', $postsLocation))
1327 + #set($resultQuery = ~"$\{resultQuery} and doc.space = :space~")
1328 + #end
1329 + #setVariable(~"$query~" $resultQuery)
1330 + #setVariable(~"$queryParams~" $resultQueryParams)
1331 +#end
1332 +##
1333 +##
1334 +##
1335 +###**
1336 + * Display blog posts based on the context where the posts are displayed.
1337 + * for example there is 4 different panel contexts:
1338 + * aBlog.aPost or aBlog.WebHome
1339 + * aCategorySpace.aCategory
1340 + * aCategorySpace.WebHome
1341 + * Blog.aPost or Blog.WebHome
1342 + *
1343 + * @param targetDoc The document in which the articles will be displayed.
1344 + * @param postsVisiblity The visibility of the posts to display: recent, unpublished, ...
1345 + * @param layout Layout of the the posts to display
1346 + * @param layoutParams additional layout parameters, it is a string like 'param1=val1|...|paramN=valueN'
1347 + * @param limit the number of posts to display
1348 + *###
1349 +#macro(displayBlogPostsBasedOnContext $targetDoc $postsVisiblity $layout $layoutParams $limit)
1350 + #if ($postLayout == 'full')
1351 + #set ($macro.paginated = 'yes')
1352 + #end
1353 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
1354 + ## Display all posts that are in the default blog space('Blog') or in category 'Blog.%'
1355 + #getBlogPostsLayout($xwiki.getDocument(~"$\{defaultBlogSpace}.WebHome~") $postsLayout)
1356 + #if (~"$!layout~" == '')
1357 + #set ($layout = $postsLayout)
1358 + #end
1359 + #if ($postsVisiblity == 'recent')
1360 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
1361 + #elseif($postsVisiblity == 'unpublished')
1362 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
1363 + #end
1364 + #elseif($targetDoc.getObject($blogCategoryClassname))
1365 + ## Display all posts that are in a category aCategorySpace.aCategory
1366 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
1367 + #getBlogPostsLayout($blogDoc $postsLayout)
1368 + #if (~"$!layout~" == '')
1369 + #set ($layout = $postsLayout)
1370 + #end
1371 + #if ($postsVisiblity == 'recent')
1372 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
1373 + #elseif($postsVisiblity == 'unpublished')
1374 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
1375 + #end
1376 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
1377 + ## Display all posts that are in a category aCategorySpace.%
1378 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
1379 + #getBlogPostsLayout($blogDoc $postsLayout)
1380 + #if (~"$!layout~" == '')
1381 + #set ($layout = $postsLayout)
1382 + #end
1383 + #if ($postsVisiblity == 'recent')
1384 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
1385 + #elseif($postsVisiblity == 'unpublished')
1386 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
1387 + #end
1388 + #else
1389 + ## Display all posts in blog space aBlog
1390 + #getBlogDocument($targetDoc.space $blogDoc)
1391 + #getBlogPostsLayout($blogDoc $postsLayout)
1392 + #if (~"$!layout~" == '')
1393 + #set ($layout = $postsLayout)
1394 + #end
1395 + #if ($postsVisiblity == 'recent')
1396 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
1397 + #elseif($postsVisiblity == 'unpublished')
1398 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
1399 + #end
1400 + #end
1401 +#end
1402 +##
1403 +##
1404 +##
1405 +#**
1406 + * Bind parameters to a query object.
1407 + *
1408 + * @param queryObj The query object (org.xwiki.query.internal.ScriptQuery object)
1409 + * @param queryParams the query parameters.
1410 + *###
1411 +#macro(bindQueryParameters $queryObj $queryParams)
1412 + #set ($output = $queryObj)
1413 + #foreach( $key in $queryParams.keySet() )
1414 + #set($output = $queryObj.bindValue($key, $queryParams.get($key)))
1415 + #end
1416 + #setVariable(~"$queryObj~" $output)
1417 +#end
1418 +##
1419 +##
1420 +##
1421 +#**
1422 + * Determines the blogposts layout: Default layout (Calendar), Image thumbnail
1423 + *
1424 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>postsLayout</tt>
1425 + * property set.
1426 + * @param postsLayout The resulting string. If the blog object does not define anything, it is considered full (default).
1427 + *###
1428 +#macro(getBlogPostsLayout $blogDoc $postsLayout)
1429 + #getBlogProperty($blogDoc 'postsLayout' 'full' $res)
1430 + #set ($postsLayout = $NULL)
1431 + #setVariable (~"$postsLayout~" $res)
1432 +#end
1433 +##
1434 +##
1435 +##
1436 +#**
1437 + * Retrieve the blog document of a categories space, which is the blog descriptor that have its categoriesLocation property set to the categories space
1438 + *
1439 + * @param categoriesSpace A <tt>String</tt>, the name of the space.
1440 + * @param blogDoc The resulting XDocument.
1441 + *###
1442 +#macro(getBlogDocumentForCategoriesSpace $categoriesSpace $blogDoc)
1443 + #set($macro.blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as categoriesLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=categoriesLocationProp.id.id and categoriesLocationProp.id.name='categoriesLocation' and categoriesLocationProp.value=:categoriesLocation order by doc.creationDate~").setLimit(1).setOffset(0).bindValue('categoriesLocation', $categoriesSpace).execute())
1444 + #if($macro.blogDocs.size() > 0 && $categoriesSpace != $defaultBlogSpace)
1445 + #set($macro.result = $xwiki.getDocument($macro.blogDocs.get(0)))
1446 + #else
1447 + ## Fallback to Blog.WebHome, the default blog
1448 + #set($macro.result = $xwiki.getDocument('Blog.WebHome'))
1449 + #end
1450 + #set ($blogDoc = $NULL)
1451 + #setVariable (~"$blogDoc~" $macro.result)
1452 +#end" %)
1453 +(((
1454 +(% class="macro-placeholder hidden" %)
1455 +(((
1456 +macro:velocity
1457 +)))
1458 +)))
1459 +)))
51 51  
1461 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogPostLayoutMacros~"" %)
1462 +(((
1463 +(% class="macro-placeholder hidden" %)
1464 +(((
1465 +macro:include
52 52  )))
53 -{{velocity}}
54 -#if (!$hasEdit)
1467 +
1468 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|#**
1469 + * Extract the layout parameters from a string.
1470 + *
1471 + * @param layoutParamsString The string representation of the layout parameters.
1472 + * It should contain a String following this format ~"paramName1=Value1|paramName2=Value2|...|paramNameK=ValueK~"
1473 + * @param layoutsParameters The resulting layout parameters Map.
1474 + *###
1475 +#macro(extractLayoutParametersFromString $layoutParamsString $layoutsParameters)
1476 + #set ($layoutsParameters = $NULL)
1477 + #set ($macro.layoutParams = \{})
1478 + #if (~"$!layoutParamsString~" != '')
1479 + #set ($macro.paramsArr = $layoutParamsString.split('\\|'))
1480 + #foreach ($item in $macro.paramsArr)
1481 + #set ($itemSplit = $item.split('='))
1482 + #if ($itemSplit.size() == 2)
1483 + #set ($discard = $macro.layoutParams.put($itemSplit[0].trim(), $itemSplit[1].trim()))
1484 + #end
1485 + #end
1486 + #end
1487 + #setVariable(~"$layoutsParameters~" $macro.layoutParams)
1488 +#end" %)
1489 +(((
1490 +(% class="macro-placeholder hidden" %)
1491 +(((
1492 +macro:velocity
1493 +)))
1494 +)))
1495 +)))
1496 +
1497 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-| #macro(displaySmallPost $pDoc $pObj)
1498 + #initLayoutVars($pDoc $pObj)
1499 + <div class=~"col-xs-12 col-sm-6 next_blog~">
1500 + <a href=~"$pDoc.uRL~" class=~"thumbnail~">
1501 + <div class=~"row~">
1502 + <div class=~"col-xs-4~">
1503 + #if ($imageAtt)
1504 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
1505 + #end
1506 + </div>
1507 + <div class=~"col-xs-8 art_det~">
1508 + <p class=~"text-left~">
1509 + #if($displayTitle)$!postTitle #end
1510 + <br/><span class=~"date_info~"> $!dateStr </span>
1511 + </p>
1512 + #displayPostDetails($pDoc)
1513 + </div>
1514 + </div>
1515 + </a>
1516 + </div>
1517 + #end
1518 + ##
1519 + ##
1520 + ##
1521 + #macro(displayPinnedPost $pDoc $pObj)
1522 + #initLayoutVars($pDoc $pObj)
1523 + <div class=~"col-xs-12 col-sm-4 col-md-4 blog_pin~">
1524 + <a href=~"$pDoc.uRL~" class=~"all-post-link~">
1525 + <div class=~"thumbnail~">
1526 + #if ($displayTitle && $displayTitleFirstOnPinnedPosts)
1527 + <h5 class=~"title-top~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
1528 + #end
1529 + #if ($imageAtt)
1530 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
1531 + #end
1532 + <div class=~"caption~">
1533 + #if ($displayTitle && !$displayTitleFirstOnPinnedPosts)
1534 + <h5 class=~"text-left~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
1535 + #end
1536 + #if ($displaySummaryOnPinnedPosts)
1537 + <div class=~"text-left post-summary~">
1538 + #set ($postContent = $pObj.getProperty('extract').value)
1539 + $!pDoc.getRenderedContent($postContent, $pDoc.syntax.toIdString())
1540 + </div>
1541 + #end
1542 + #displayPostDetails($pDoc)
1543 + </div>
1544 + </div>
1545 + </a>
1546 + </div>
1547 + #end
1548 + ##
1549 + ##
1550 + ##
1551 + #macro(formatPostDate $pDoc $pObj)
1552 + #set ($formattedDate = $NULL)
1553 + #set($dateStr = $datetool.format('medium', $postDate, $xcontext.locale))
1554 + #if (~"$!dateStr~" != '')
1555 + #set ($dateArr = $dateStr.split(' '))
1556 + #if ($dateArr.size() > 3)
1557 + #set ($dateStr = ~"~")
1558 + #foreach($s in $dateArr.subList(0, 3))
1559 + #set ($dateStr = ~"$\{dateStr}$\{s} ~")
1560 + #end
1561 + #end
1562 + #end
1563 + #setVariable(~"$formattedDate~" $dateStr)
1564 + #end
1565 + ##
1566 + ##
1567 + ##
1568 + #macro(displayPostDetails $pDoc)
1569 + <div class=~"row post-details~">
1570 + <div class=~"col-xs-8 detail~">
1571 + #if ($services.like.displayButton($pDoc.documentReference))
1572 + #set ($optLikeRecord = $services.like.getLikes($pDoc.documentReference))
1573 + ## Retrieve the likes number in XWiki 12.9+
1574 + #set ($likeNumber = $optLikeRecord.get())
1575 + #if (!$stringtool.isNumeric($likeNumber.toString()))
1576 + ## Retrieve the likes number in XWiki versions greater than 12.7 and lower than 12.9.
1577 + #set ($likeNumber = $optLikeRecord.get().likeNumber)
1578 + #end
1579 + #if ($stringtool.isNumeric($likeNumber.toString()))
1580 + <div class=~"post-likes btn btn-default disabled badge~"
1581 + title=~"$escapetool.xml($services.localization.render('like.button.title', [$likeNumber]))~">
1582 + $services.icon.renderHTML('heart') <span class=~"like-number~">$likeNumber</span>
1583 + </div>
1584 + #end
1585 + #elseif ($services.ratings)
1586 + #set ($ratingsConfigDoc = $services.ratings.getConfigurationDocument($pDoc.documentReference))
1587 + #if ($ratingsConfigDoc.getValue('displayRatings') == 1)
1588 + <ul class=~"pull-left note list-inline~">
1589 + #foreach ($x in [1..5])
1590 + #set ($cls = ~"~")
1591 + #if ($x > $averageVote)
1592 + #set ($cls = ~"-o~")
1593 + #end
1594 + <li><span class=~"fa fa-star$\{cls}~"></span></li>
1595 + #end
1596 + </ul>
1597 + #end
1598 + #end
1599 + </div>
1600 + #if ($showPostComments)
1601 + <div class=~"col-xs-4 com_det~">
1602 + <p class=~"text-right~">$services.icon.renderHTML('comments') ($!nbComments)</p>
1603 + </div>
1604 + #end
1605 + </div>
1606 + #end
1607 + ##
1608 + ##
1609 + ##
1610 + #macro(initLayoutVars $pDoc $pObj)
1611 + #set ($postTitle = $pDoc.display('title', 'view', $pObj))
1612 + #set ($imageAtt = $pDoc.getAttachment($pObj.getValue('image')))
1613 + #isPublished($pObj $isPublished)
1614 + #isHidden($pObj $isHidden)
1615 + #getEntryDate($pDoc $pObj $postDate)
1616 + #formatPostDate($postDate $dateStr)
1617 + #set ($averageVote = $mathtool.round($services.ratings.getAverageRating($pDoc.documentReference).getAverageVote()))
1618 + #set ($nbComments = $pDoc.getComments().size())
1619 + #set ($showPostComments = true)
1620 + #if ($xwiki.getSpacePreferenceFor('showcomments', $pDoc.documentReference.lastSpaceReference, '1') == '0')
1621 + #set ($showPostComments = false)
1622 + #end
1623 + #end
1624 + ##
1625 + ##
1626 + ##
1627 + #macro(displayEditPinnedPostsButton)
1628 + #if (~"$!macroAdditionalParams.get('postIndex')~" == '0' && $services.security.authorization.hasAccess('edit', $pinnedPostsSourceDoc.fullName))
1629 + #set ($discard = $xwiki.ssx.use('Blog.PinnedPostsSheet'))
1630 + #set ($discard = $xwiki.jsx.use('Blog.PinnedPostsSheet'))
1631 + #set ($editPinnedPostsURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'get', 'sheet=Blog.PinnedPostsSheet'))
1632 + #set ($newPinnedPostsObjectURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'objectadd', ~"classname=Blog.PinnedPostsClass&form_token=$!\{services.csrf.getToken()}~"))
1633 + <div class=~"edit-pinned-posts-container~">
1634 + <div class=~"col-xs-12 col-sm-12 col-md-12 text-right edit-pinned-posts~">
1635 + <a href=~"javascript:;~" class=~"editPinnedPosts~">
1636 + <span class=~"glyphicon glyphicon-edit~" aria-hidden=~"true~"></span> $services.localization.render('blog.post.layout.cards.pinnedposts.edit')
1637 + </a>
1638 + <input type=~"hidden~" id=~"editPinnedPostsURL~" value=~"$escapetool.xml($editPinnedPostsURL)~"/>
1639 + <input type=~"hidden~" id=~"newPinnedPostsObjectURL~" value=~"$escapetool.xml($newPinnedPostsObjectURL)~"/>
1640 + </div>
1641 + </div>
1642 + #if (~"$!pinnedPostsObj~" == '')
1643 + <input type=~"hidden~" name=~"createPinnedPostsObject~" value=~"1~"/>
1644 + #end
1645 + #end
1646 + #end" %)
1647 +(((
1648 +(% class="macro-placeholder hidden" %)
1649 +(((
1650 +macro:velocity
1651 +)))
1652 +)))
1653 +
1654 +(% class="macro" data-macro="startmacro:velocity|-||-| #if ($services.security.authorization.hasAccess('view', $xcontext.macro.params.reference))
1655 + #set ($postDoc = $xwiki.getDocument($xcontext.macro.params.reference))
1656 + #getEntryObject($postDoc $postObj)
1657 + #if (~"$!postObj~" != '')
1658 + #extractLayoutParametersFromString($xcontext.macro.params.params $macroAdditionalParams)
1659 + ##
1660 + #set ($displayTitle = true)
1661 + #if (~"$!macroAdditionalParams.get('displayTitle')~" == 'false')
1662 + #set ($displayTitle = false)
1663 + #end
1664 + ##
1665 + #set ($displayTitleFirstOnPinnedPosts = false)
1666 + #if (~"$!macroAdditionalParams.get('displayTitleFirstOnPinnedPosts')~" == 'true')
1667 + #set ($displayTitleFirstOnPinnedPosts = true)
1668 + #end
1669 + ##
1670 + #set ($displaySummaryOnPinnedPosts = true)
1671 + #if (~"$!macroAdditionalParams.get('displaySummaryOnPinnedPosts')~" == 'false')
1672 + #set ($displaySummaryOnPinnedPosts = false)
1673 + #end
1674 + ##
1675 + #set ($postIndex = $numbertool.toNumber($macroAdditionalParams.get('postIndex')).intValue())
1676 + #if ($postIndex == 0)
1677 + #set ($stopBlogPostsDisplay = false)
1678 + #end
1679 + #set ($listResultsCount = $numbertool.toNumber($macroAdditionalParams.get('list-results-count')).intValue())
1680 + #set($discard = $xwiki.ssx.use('Blog.BlogPostLayoutCards'))
1681 + #set($scaleWidth = 600)
1682 + #set($imgQs=~"width=$scaleWidth~")
1683 + ## Display pinned posts
1684 + ## Get the list of pinned posts
1685 + #set ($pinnedPosts = [])
1686 + #set ($pinnedPostsSourceDoc = $NULL)
1687 + #if (~"$!macroAdditionalParams.get('forceDisplayPinnedPosts')~" == 'true' && ~"$!macroAdditionalParams.get('list-blog')~" != '')
1688 + #set ($pinnedPostsSourceDoc = $xwiki.getDocument($macroAdditionalParams.get('list-blog')))
1689 + ## Note that the 'list-blog' parameter contains the value of the 'blog' parameter of the blogpostlist macro passed to the current layout macro
1690 + #end
1691 + #if (~"$!pinnedPostsSourceDoc~" != '')
1692 + #set ($pinnedPostsObj = $pinnedPostsSourceDoc.getObject('Blog.PinnedPostsClass'))
1693 + #if (~"$!pinnedPostsObj~" != '')
1694 + #set ($orderedPinnedPostsJSON = $pinnedPostsObj.getProperty('orderedPosts').value)
1695 + #if (~"$!orderedPinnedPostsJSON~" != '')
1696 + #set ($pinnedPosts = $jsontool.parse($orderedPinnedPostsJSON))
1697 + #else
1698 + #set ($pinnedPosts = $pinnedPostsObj.getProperty('posts').value)
1699 + #end
1700 + #end
1701 + #if ($postIndex == 0 && $pinnedPosts.size() > 0)
1702 + \{\{html clean=~"false~"}}
1703 + #set ($x = 0)
1704 + #set ($showPinnedPostsButton = true)
1705 + #foreach ($pinnedPost in $pinnedPosts)
1706 + #if ($x == 0)
1707 + <div class=~"row flex-container~">
1708 + #if ($showPinnedPostsButton)
1709 + #displayEditPinnedPostsButton()
1710 + #set($showPinnedPostsButton = false)
1711 + #end
1712 + #end
1713 + #set ($pinnedPostDoc = $xwiki.getDocument($pinnedPost))
1714 + #getEntryObject($pinnedPostDoc $pinnedPostObj)
1715 + #if (~"$!pinnedPostObj~" != '')
1716 + #displayPinnedPost($pinnedPostDoc $pinnedPostObj)
1717 + #end
1718 + #set ($x = $mathtool.add($x, 1))
1719 + #if ($x == 3)
1720 + #set ($x = 0)
1721 + </div>
1722 + #end
1723 + #end
1724 + #if ($mathtool.mod($x, 3) != 0)
1725 + </div>
1726 + #end
1727 + \{\{/html}}
1728 +
1729 + ## If the first post is a pinned post : this means that all the posts are pinned
1730 + ## In this case, avoid displaying the posts again after the pinned posts section.
1731 + #if ($pinnedPosts.contains($xcontext.macro.params.reference))
1732 + #set ($stopBlogPostsDisplay = true)
1733 + #end
1734 + #elseif($postIndex == 0 && $pinnedPosts.size() == 0)
1735 +
1736 + \{\{html}}
1737 + <div class=~"row no-pinnded-posts~">
1738 + #displayEditPinnedPostsButton()
1739 + </div>
1740 + \{\{/html}}
1741 +
1742 + #end
1743 + #end
1744 + #if (!$stopBlogPostsDisplay)
1745 + \{\{html clean=~"false~"}}
1746 + #if (~"$!nbDisplayedPosts~" == '' || $postIndex == 0)
1747 + #set ($nbDisplayedPosts = 0)
1748 + #end
1749 + #if($mathtool.mod($nbDisplayedPosts, 2) == 0)
1750 + #if ($nbDisplayedPosts != 0)
1751 + </div>
1752 + #set ($lastHtmlTag = 'c')
1753 + #end
1754 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
1755 + <div class=~"row~">
1756 + #set ($lastHtmlTag = 'o')
1757 + #set ($lastRowClass = ~"~")
1758 + #else
1759 + <div class=~"row flex-container~">
1760 + #set ($lastHtmlTag = 'o')
1761 + #set ($lastRowClass = ~"flex~")
1762 + #end
1763 + #end
1764 + #displaySmallPost($postDoc $postObj)
1765 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
1766 + </div>
1767 + #set ($lastHtmlTag = 'c')
1768 + #end
1769 + #set ($nbDisplayedPosts = $mathtool.add($nbDisplayedPosts, 1))
1770 + #if ($postIndex == $mathtool.sub($listResultsCount, 1))
1771 + #if (~"$!lastHtmlTag~" == 'o')
1772 + #if ($mathtool.mod($nbDisplayedPosts, 2) == 1 && $lastRowClass == ~"flex~")
1773 + <div class=~"col-xs-12 col-sm-6~"></div>
1774 + #end
1775 + </div>
1776 + #end
1777 + #end
1778 + \{\{/html}}
1779 + #end
1780 + #else
1781 + \{\{error}}$services.localization.render('blog.blogpostlayout.notpost', [$xcontext.macro.params.reference])\{\{/error}}
1782 + #end
1783 + #else
1784 + \{\{error}}$services.localization.render('blog.blogpostlayout.post_view_not_allowed', [$xcontext.macro.params.reference])\{\{/error}}
1785 + #end" %)
1786 +(((
1787 +(% class="macro-placeholder hidden" %)
1788 +(((
1789 +macro:velocity
1790 +)))
1791 +
1792 +(% class="macro" data-macro="startmacro:html|-|clean=~"false~"|-|<div class=~"row flex-container~">
1793 +<div class=~"col-xs-12 col-sm-6 next_blog~">
1794 +<a href=~"/Nieuws/Nieuwsbrief%20januari%202024~" class=~"thumbnail~">
1795 +<div class=~"row~">
1796 +<div class=~"col-xs-4~">
1797 +<img src=~"/download/Nieuws/Nieuwsbrief%20januari%202024/man-outdoor-light-architecture-people-street-1194699-pxhere.com.jpg?width=600&rev=1.1~" />
1798 +</div>
1799 +<div class=~"col-xs-8 art_det~">
1800 +<p class=~"text-left~">
1801 +Nieuwsbrief januari 2024 <br/><span class=~"date_info~"> 5 feb. 2024 </span>
1802 +</p>
1803 +<div class=~"row post-details~">
1804 +<div class=~"col-xs-8 detail~">
1805 +<div class=~"post-likes btn btn-default disabled badge~"
1806 +title=~"Number of likes on this page: 3~">
1807 +<span class=~"fa fa-heart~"></span> <span class=~"like-number~">3</span>
1808 +</div>
1809 +</div>
1810 +<div class=~"col-xs-4 com_det~">
1811 +<p class=~"text-right~"><span class=~"fa fa-comments~"></span> (0)</p>
1812 +</div>
1813 +</div>
1814 +</div>
1815 +</div>
1816 +</a>
1817 +</div>" %)
1818 +(((
1819 +(% class="macro-placeholder hidden" %)
1820 +(((
1821 +macro:html
1822 +)))
1823 +
1824 +(% class="row flex-container" %)
1825 +(((
1826 +(% class="col-xs-12 col-sm-6 next_blog" %)
1827 +(((
1828 +(% class="row" %)
1829 +(((
1830 +(% class="col-xs-4" %)
1831 +(((
1832 +[[~[~[image:/download/Nieuws/Nieuwsbrief%20januari%202024/man-outdoor-light-architecture-people-street-1194699-pxhere.com.jpg?width=600&rev=1.1~]~]>>path:/Nieuws/Nieuwsbrief%20januari%202024||class="thumbnail"]]
1833 +)))
1834 +
1835 +(% class="col-xs-8 art_det" %)
1836 +(((
1837 +(% class="text-left" %)
1838 +[[Nieuwsbrief januari 2024
1839 +(% class="date_info" %) 5 feb. 2024>>path:/Nieuws/Nieuwsbrief%20januari%202024||class="thumbnail"]]
1840 +
1841 +(% class="row post-details" %)
1842 +(((
1843 +(% class="col-xs-8 detail" %)
1844 +(((
1845 +(% class="post-likes btn btn-default disabled badge" title="Number of likes on this page: 3" %)
1846 +(((
1847 +[[(% class="like-number" %)3>>path:/Nieuws/Nieuwsbrief%20januari%202024||class="thumbnail"]]
1848 +)))
1849 +)))
1850 +
1851 +(% class="col-xs-4 com_det" %)
1852 +(((
1853 +(% class="text-right" %)
1854 +[[(0)>>path:/Nieuws/Nieuwsbrief%20januari%202024||class="thumbnail"]]
1855 +)))
1856 +)))
1857 +)))
1858 +)))
1859 +)))
1860 +
1861 +(% class="macro" data-macro="startmacro:blogPostLayoutCards|-|reference=~"Nieuws.Audit BMI en BORG~" params=~"displayTitle=true|useSummary=true|list-limit=6|list-layout=cards|list-blog=Nieuws.WebHome|list-paginated=no|list-results-count=6|postIndex=0|previousPostReference=|postIndex=1|previousPostReference=Nieuws.Nieuwsbrief januari 2024~"" %)
1862 +(((
1863 +(% class="macro-placeholder hidden" %)
1864 +(((
1865 +macro:blogPostLayoutCards
1866 +)))
1867 +
1868 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogCode~"" %)
1869 +(((
1870 +(% class="macro-placeholder hidden" %)
1871 +(((
1872 +macro:include
1873 +)))
1874 +
1875 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogParameters~"" %)
1876 +(((
1877 +(% class="macro-placeholder hidden" %)
1878 +(((
1879 +macro:include
1880 +)))
1881 +
1882 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|## Blog
1883 +#set($blogClassname = 'Blog.BlogClass')
1884 +#set($blogTemplate = 'Blog.BlogTemplate')
1885 +#set($blogSheet = 'Blog.BlogSheet')
1886 +## Blog entries
1887 +#set($blogPostClassname = 'Blog.BlogPostClass')
1888 +#set($blogPostTemplate = 'Blog.BlogPostTemplate')
1889 +#set($blogPostSheet = 'Blog.BlogPostSheet')
1890 +#set($blogPostObjectNumber = $xwiki.getDocument($blogPostTemplate).getObject($blogPostClassname).number)
1891 +#set($oldArticleClassname = 'XWiki.ArticleClass')
1892 +## Categories
1893 +#set($blogCategoryClassname = 'Blog.CategoryClass')
1894 +#set($blogCategoryTemplate = 'Blog.CategoryTemplate')
1895 +#set($blogCategorySheet = 'Blog.CategorySheet')
1896 +#set($blogCategoriesSheet = 'Blog.CategoriesSheet')
1897 +#set($oldBlogCategoryClassname = 'Blog.Categories')
1898 +#set($defaultCategoryParent = 'Blog.Categories')
1899 +## Style
1900 +#set($blogStyleDocumentName = 'Blog.BlogStyle')
1901 +#set($blogStyleDocument = $xwiki.getDocument($blogStyleDocumentName))
1902 +## Clientside scripts
1903 +#set($blogScriptsDocumentName = 'Blog.BlogScripts')
1904 +#set($blogPublisher = $xwiki.getDocument('Blog.Publisher'))
1905 +## Misc
1906 +#set($thisURL = $doc.getURL($xcontext.action, $request.queryString))
1907 +#set($isBlogPost = $doc.getObject($blogPostClassname))
1908 +#set($defaultBlogSpace = 'Blog')
1909 +#set($isCategoryPage = $doc.getObject($blogCategoryClassname))
1910 +#set($isCategoriesHomePage = $doc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
1911 +##
1912 +##
1913 +##
1914 +#**
1915 + * Displays an image, taken from the blog style document.
1916 + *
1917 + * @param $imgName The name of the icon from icons set to use.
1918 + *#
1919 +#macro(toolImage $imgName)(% class=~"icon-manage~"~%)$services.icon.render($imgName)(%~%)#end" %)
1920 +(((
1921 +(% class="macro-placeholder hidden" %)
1922 +(((
1923 +macro:velocity
1924 +)))
1925 +)))
1926 +)))
1927 +
1928 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|##
1929 +##
1930 +##
1931 +## Import the blog skin and javascripts.
1932 +$!xwiki.ssx.use($blogStyleDocumentName)##
1933 +$!xwiki.jsx.use($blogScriptsDocumentName)##
1934 +##
1935 +## import the hierarchy for the path the blog post footer (in displayEntryBlogLocation)
1936 +#template('hierarchy_macros.vm')##
1937 +##
1938 +##
1939 +#**
1940 + * Prints a blog. This is the main macro used in the BlogSheet.
1941 + *
1942 + * @param blogDoc the XDocument holding the blog definition object.
1943 + *###
1944 +#macro(printBlog $blogDoc)
1945 + \{\{include reference='Blog.CreatePost'/}}
1946 +
1947 + ## Use the blogPostList macro to display the blogposts
1948 + ## The blogPostList is used only in case of 'all' or 'paged' blog display type because the blogPostList macro
1949 + ## do not support FTM the monthly and weekly blog display types
1950 + #getBlogDisplayType($blogDoc $displayType)
1951 + #if ($displayType == 'weekly' || $displayType == 'monthly')
1952 + #getBlogEntries($blogDoc $entries)
1953 + #displayBlog($entries 'index' true true)
1954 + #displayNavigationLinks($blogDoc)
1955 + #else
1956 + #getBlogDisplayType($blogDoc $displayType)
1957 + #set ($paginated = 'no')
1958 + #if ($displayType == 'paginated')
1959 + #set ($paginated = 'yes')
1960 + #end
1961 + #getBlogPostsLayout($blogDoc $postsLayout)
1962 + (% class=~"hfeed index~" ~%)(((\{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$paginated~" layout=~"$!postsLayout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" /}})))
1963 + #end
1964 +#end
1965 +##
1966 +##
1967 +##
1968 +#**
1969 + * Shows blog information. In view mode, the description is printed. In edit mode, allows changing blog settings: title,
1970 + * description, blog type (global or in-space), index display type (fixed size pagination, weekly index, monthly index,
1971 + * all entries).
1972 + *
1973 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
1974 + *###
1975 +#macro(showBlogInfo $blogDoc)
1976 + #if($blogDoc.getObject($blogClassname))
1977 + ## Keep testing for inline action for backward compatibility with older blogs.
1978 + #if($xcontext.action == 'edit' || $xcontext.action == 'inline')
1979 + #macro(displayProperty $blogDoc $propname)
1980 + ; #displayPropName($xwiki.getClass($blogClassname).get($propname)):
1981 + : $blogDoc.display($propname)
1982 + #end
1983 + #displayProperty($blogDoc 'title')
1984 + #displayProperty($blogDoc 'description')
1985 + #displayProperty($blogDoc 'displayType')
1986 + #displayProperty($blogDoc 'itemsPerPage')
1987 + #displayProperty($blogDoc 'postsLayout')
1988 + #displayProperty($blogDoc 'postsLayoutParameters')
1989 + #else
1990 + $blogDoc.display('description')
1991 + #end
1992 + #elseif($doc.fullName == $blogSheet)
1993 += $services.localization.render('blog.code.blogsheet') =
1994 + \{\{translation key='blog.code.sheetexplanation'/}}
1995 + #else
1996 + \{\{warning}}\{\{translation key='blog.code.notblog'/}}\{\{/warning}}
1997 + #end
1998 +#end
1999 +##
2000 +##
2001 +##
2002 +#**
2003 + * Retrieve the blog document, which usually is either <tt>&lt;Space&gt;.WebHome</tt> for whole-spaces blogs, or
2004 + * <tt>&lt;Space&gt;.Blog</tt> for in-space blogs. If none of these documents contains a blog object, then the first
2005 + * (alphabetically) document in the target space that contains one is returned. Finally, if no document in the current
2006 + * space contains a blog object, then <tt>Blog.WebHome</tt> is returned as the default blog.
2007 + *
2008 + * @param space A <tt>String</tt>, the name of the space where to search.
2009 + * @param blogDoc The resulting XDocument.
2010 + *###
2011 +#macro(getBlogDocument $space $blogDoc)
2012 + #set ($result = $NULL)
2013 + ## Check if the current space has a WebPreferences page that contains a Blog.EnablePanelsConfigurationClass object.
2014 + ## It is possible to display a blog's panels info in a page that is not inside a blog and in that case we need to
2015 + ## identify the right blog based on a configuration object in a WebPreferences page.
2016 + #set ($spaceReference = $services.model.resolveSpace($space))
2017 + #set ($preferencesDocRef = $services.model.createDocumentReference('WebPreferences', $spaceReference))
2018 + #set ($preferencesDoc = $xwiki.getDocument($preferencesDocRef))
2019 + #set ($preferencesObj = $preferencesDoc.getObject('Blog.EnablePanelsConfigurationClass'))
2020 + #if ($preferencesObj)
2021 + #set ($result = $xwiki.getDocument( $preferencesObj.getValue('blog')))
2022 + #end
2023 + ## If no special case occurs (like the previous one), identify a blog by checking the current location from its hierarchy.
2024 + #if (~"$!result~" == '')
2025 + ## First, try the Space.WebHome, for a whole-space blog
2026 + #set($result = $xwiki.getDocument(~"$\{space}.WebHome~"))
2027 + #if(!$result.getObject($blogClassname))
2028 + ## Second, try the Space.Blog document
2029 + #set($result = $xwiki.getDocument(~"$\{space}.Blog~"))
2030 + #if(!$result.getObject($blogClassname))
2031 + ## Third, try searching for a blog document in the current space
2032 + ## Prevent the query fail when the space contains dots '.'
2033 + #set($blogDocs = $services.query.hql(~", BaseObject obj where doc.space = :space and obj.name = doc.fullName and obj.className = '$blogClassname' order by doc.name~").setLimit(1).setOffset(0).bindValue('space', $space).execute())
2034 + #if($blogDocs.size() > 0)
2035 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
2036 + #else
2037 + ## Fourth, try searching for a blog document that have the its 'postsLocation' set to the current space
2038 + #set($blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as postsLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=postsLocationProp.id.id and postsLocationProp.id.name='postsLocation' and postsLocationProp.value=:postsLocation order by doc.name~").setLimit(1).setOffset(0).bindValue('postsLocation', $space).execute())
2039 + #if($blogDocs.size() > 0)
2040 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
2041 + #else
2042 + ## Last, fallback to Blog.WebHome, the default blog
2043 + #set($result = $xwiki.getDocument('Blog.WebHome'))
2044 + #end
2045 + #end
2046 + #end
2047 + #end
2048 + #end
2049 + #set ($blogDoc = $NULL)
2050 + #setVariable (~"$blogDoc~" $result)
2051 +#end
2052 +##
2053 +##
2054 +##
2055 +#**
2056 + * Retrieve the blog title.
2057 + *
2058 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass<tt> object with the <tt>title</tt> property set.
2059 + * @param title The resulting title.
2060 + *###
2061 +#macro(getBlogTitle $blogDoc $title)
2062 + ## Titles can contain velocity code (most commonly translations), so we should evaluate them.
2063 + #set ($title = $NULL)
2064 + #setVariable (~"$title~" $!blogDoc.displayTitle)
2065 +#end
2066 +##
2067 +##
2068 +##
2069 +#**
2070 + * Retrieve the blog description.
2071 + *
2072 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>description</tt>
2073 + * property set.
2074 + * @param description The resulting description.
2075 + *###
2076 +#macro(getBlogDescription $blogDoc $description)
2077 + #getBlogProperty($blogDoc 'description' '' $result)
2078 + #set ($description = $NULL)
2079 + #setVariable (~"$description~" $result)
2080 +#end
2081 +##
2082 +##
2083 +##
2084 +#**
2085 + * Retrieves a list of entries to be displayed. The entries are either part of the blog's space, or have the blog
2086 + * document set as a parent. The number and range of entries returned (from all those belonging to this blog) depends on
2087 + * the blog display type: paginated (fixed number of entries), weekly (all entries in a week), monthly (all entries in a
2088 + * month), or all.
2089 + *
2090 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
2091 + * @param entries The resulting list of entries to display, a list of XDocument names.
2092 + *###
2093 +#macro(getBlogEntries $blogDoc $entries)
2094 + #if (!$entries)
2095 + #setVariable (~"$entries~" [])
2096 + #end
2097 + #getAllBlogPostsQuery($query)
2098 + #isDefaultBlog($blogDoc $isDefault)
2099 + #set($queryParams = \{})
2100 + #if ($isDefault)
2101 + #getCategoryAllBlogPostsQuery($query)
2102 + #set($query = ~"$\{query} and (doc.creator = :creator or (isPublished.value = 1 and hidden.value = 0)) and (doc.space = :space or catList like :catList escape '!')~")
2103 + #set($discard = $queryParams.put('creator', $xcontext.user))
2104 + #set($discard = $queryParams.put('space', $blogDoc.space))
2105 + #set($sanitizedBlogSpace = $blogDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
2106 + #set($discard = $queryParams.put('catList', $sanitizedBlogSpace))
2107 + #else
2108 + #set($query = ~"$\{query} and (doc.space = :space or doc.parent = :parent)~")
2109 + #getBlogPostsLocation($blogDoc.space $blogPostsLocation)
2110 + #set($discard = $queryParams.put('space', $blogPostsLocation))
2111 + #set($discard = $queryParams.put('parent', $blogDoc.space))
2112 + #end
2113 + #getBlogDisplayType($blogDoc $displayType)
2114 + #if($displayType == 'weekly')
2115 + #getWeeklyBlogEntries($blogDoc $query $entries $queryParams)
2116 + #elseif($displayType == 'monthly')
2117 + #getMonthlyBlogEntries($blogDoc $query $entries $queryParams)
2118 + #elseif($displayType == 'all')
2119 + #getAllBlogEntries($blogDoc $query $entries $queryParams)
2120 + #else
2121 + #getPagedBlogEntries($blogDoc $query $entries $queryParams)
2122 + #end
2123 +#end
2124 +##
2125 +##
2126 +##
2127 +#**
2128 + * Retrieves a list of entries to be displayed. The entries are taken from a ~"page~" of the blog, a sequence of documents
2129 + * defined by the request parameters <tt>ipp</tt> (items per page) and <tt>page</tt> (the current page). Initially the
2130 + * first page is displayed, with the number of entries defined in the blog object in the <tt>itemsPerPage</tt> property
2131 + * (10 if not defined).
2132 + *
2133 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
2134 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
2135 + * refined to restrict to a given space, or to a given search criteria, etc.
2136 + * @param entries The resulting list of entries to display, a list of XDocument names.
2137 + * @param queryParams The parameters to bind with the query.
2138 + *###
2139 +#macro(getPagedBlogEntries $blogDoc $query $entries $queryParams)
2140 + #if (!$entries)
2141 + #setVariable (~"$entries~" [])
2142 + #end
2143 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
2144 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~"))
2145 + #bindQueryParameters($countQueryObj $queryParams)
2146 + #bindQueryParameters($queryObj $queryParams)
2147 + #set($totalEntries = $countQueryObj.count())
2148 + #getBlogProperty($blogDoc 'itemsPerPage' '10' $defaultItemsPerPage)
2149 + #set($defaultItemsPerPage = $numbertool.toNumber($defaultItemsPerPage).intValue())
2150 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
2151 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
2152 + #set($discard = $entries.addAll($queryObj.setLimit($itemsPerPage).setOffset($startAt).addFilter(~"unique~").execute()))
2153 +#end
2154 +##
2155 +##
2156 +##
2157 +#**
2158 + * Retrieves a list of entries to be displayed. The entries are taken from a week of the blog. The target week is
2159 + * defined by the request parameters <tt>week</tt> (the week number in the year, from 1 to 52) and <tt>year</tt> (4
2160 + * digit year). Initially the current week is displayed.
2161 + *
2162 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
2163 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
2164 + * refined to restrict to a given space, or to a given search criteria, etc.
2165 + * @param entries The resulting list of entries to display, a list of XDocument names.
2166 + * @param queryParams The parameters to bind with the query.
2167 + *###
2168 +#macro(getWeeklyBlogEntries $blogDoc $query $entries $queryParams)
2169 + #if (!$entries)
2170 + #setVariable (~"$entries~" [])
2171 + #end
2172 + #getRequestedWeek($weekDate)
2173 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
2174 + #set($minDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundFloor()))
2175 + #set($maxDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundCeiling()))
2176 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
2177 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
2178 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
2179 + #bindQueryParameters($countQueryObj $queryParams)
2180 + #bindQueryParameters($queryObj $queryParams)
2181 + #set($totalEntries = $countQueryObj.count())
2182 + #set($discard = $entries.addAll($queryObj.execute()))
2183 +#end
2184 +##
2185 +##
2186 +##
2187 +#**
2188 + * Retrieves a list of entries to be displayed. The entries are taken from a month of the blog. The target month is
2189 + * defined by the request parameters <tt>month</tt> (the month number, from 1 to 12) and <tt>year</tt> (4
2190 + * digit year). Initially the current month is displayed.
2191 + *
2192 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
2193 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
2194 + * refined to restrict to a given space, or to a given search criteria, etc.
2195 + * @param entries The resulting list of entries to display, a list of XDocument names.
2196 + * @param queryParams The parameters to bind with the query.
2197 + *###
2198 +#macro(getMonthlyBlogEntries $blogDoc $query $entries)
2199 + #if (!$entries)
2200 + #setVariable (~"$entries~" [])
2201 + #end
2202 + #getRequestedMonth($monthDate)
2203 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
2204 + #set($minDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundFloor()))
2205 + #set($maxDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundCeiling()))
2206 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
2207 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
2208 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
2209 + #bindQueryParameters($countQueryObj $queryParams)
2210 + #bindQueryParameters($queryObj $queryParams)
2211 + #set($totalEntries = $countQueryObj.count())
2212 + #set($discard = $entries.addAll($queryObj.execute()))
2213 +#end
2214 +##
2215 +##
2216 +##
2217 +#**
2218 + * Retrieves a list of entries to be displayed. All entries belonging to the current blog are returned.
2219 + *
2220 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
2221 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
2222 + * refined to restrict to a given space, or to a given search criteria, etc.
2223 + * @param entries The resulting list of entries to display, a list of XDocument names.
2224 + * @param queryParams The parameters to bind with the query.
2225 + *###
2226 +#macro(getAllBlogEntries $blogDoc $query $entries $queryParams)
2227 + #if (!$entries)
2228 + #setVariable (~"$entries~" [])
2229 + #end
2230 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
2231 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
2232 + #bindQueryParameters($countQueryObj $queryParams)
2233 + #bindQueryParameters($queryObj $queryParams)
2234 + #set($totalEntries = $countQueryObj.count())
2235 + #set($discard = $entries.addAll($queryObj.execute()))
2236 +#end
2237 +##
2238 +##
2239 +##
2240 +#**
2241 + * Retrieves a list of entries to be displayed. Only (and all) unpublished entries are returned.
2242 + *
2243 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
2244 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
2245 + * refined to restrict to a given space, or to a given search criteria, etc.
2246 + * @param queryParams The parameters to bind with the query.
2247 + * @param entries The resulting list of entries to display, a list of XDocument names.
2248 + *###
2249 +#macro(getUnpublishedBlogEntries $blogDoc $query $queryParams $entries)
2250 + #if (!$entries)
2251 + #setVariable (~"$entries~" [])
2252 + #end
2253 + #set($query = ~"$\{query} and isPublished.value = 0~")
2254 + #set ($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
2255 + #set ($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
2256 + #bindQueryParameters($countQueryObj $queryParams)
2257 + #bindQueryParameters($queryObj $queryParams)
2258 + #set($totalEntries = $countQueryObj.count())
2259 + #set($discard = $entries.addAll($queryObj.execute()))
2260 +#end
2261 +##
2262 +##
2263 +##
2264 +#**
2265 + * Retrieves a list of entries to be displayed. The entries are taken from all the wiki, and not from a specific blog.
2266 + *
2267 + * @param entries The resulting list of entries to display, a list of XDocument names.
2268 + *###
2269 +#macro(getGlobalBlogEntries $entries)
2270 + #if (!$entries)
2271 + #setVariable (~"$entries~" [])
2272 + #end
2273 + #getAllBlogPostsQuery($query)
2274 + #set($totalEntries = $services.query.hql($query).count())
2275 + #set($defaultItemsPerPage = 20)
2276 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
2277 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
2278 + #set($discard = $entries.addAll($services.query.hql(~"$\{query} order by publishDate.value desc~").setLimit($itemsPerPage).setOffset($startAt).execute()))
2279 +#end
2280 +#**
2281 + * Return the base query for selecting blog entries. It filters only visible entries, but does not bind to a specific
2282 + * blog, nor specify a range or an ordering criteria.
2283 + *
2284 + * This macro is a duplicate of #getAllBlogPostsQuery($query). Keep it in case it's used outside, in custom code.
2285 + *
2286 + * @param query The basic query for selecting blog entries.
2287 + *#
2288 +#macro(getBlogEntriesBaseQuery $query)
2289 + #getAllBlogPostsQuery($query)
2290 +#end
2291 +#**
2292 + * Return the Query for selecting the all wiki blog posts without filtering
2293 + *
2294 + * @param query The basic query for selecting blog entries.
2295 + *#
2296 +#macro(getAllBlogPostsQuery $query)
2297 + #set ($query = $NULL)
2298 + #setVariable(~"$query~" ~", BaseObject as obj, IntegerProperty isPublished,
2299 + IntegerProperty hidden, DateProperty publishDate
2300 + where doc.fullName <> '$blogPostTemplate' and
2301 + obj.name=doc.fullName and obj.className='$blogPostClassname' and
2302 + isPublished.id.id = obj.id and isPublished.id.name = 'published' and
2303 + hidden.id.id = obj.id and hidden.id.name='hidden' and
2304 + publishDate.id.id = obj.id and publishDate.id.name='publishDate' and
2305 + (doc.creator = '$escapetool.sql($xcontext.user)' or (isPublished.value = 1 and hidden.value = 0))~")
2306 +#end
2307 +##
2308 +##
2309 +##
2310 +###**
2311 + * Return the Query for selecting the all wiki blog posts with categories filtering
2312 + *
2313 + * @param query The basic query for selecting blog entries.
2314 + *###
2315 +#macro(getCategoryAllBlogPostsQuery $query)
2316 + #set ($query = $NULL)
2317 + #getAllBlogPostsQuery($baseQuery)
2318 + #set ($baseQuery = $baseQuery.replace('DateProperty publishDate', 'DateProperty publishDate, DBStringListProperty as category left join category.list catList'))
2319 + #setVariable(~"$query~" ~"$\{baseQuery} and obj.id=category.id.id and category.id.name='category'~")
2320 +#end
2321 +##
2322 +##
2323 +##
2324 +#**
2325 + * Determines how is the blog index split into pages: paginated (fixed number of entries), weekly (all entries in a
2326 + * week), monthly (all entries in a month), or all.
2327 + *
2328 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>displayType</tt>
2329 + * property set.
2330 + * @param displayType The resulting string. If the blog object does not define anything, it is considered paginated.
2331 + *###
2332 +#macro(getBlogDisplayType $blogDoc $displayType)
2333 + #getBlogProperty($blogDoc 'displayType' 'paginated' $result)
2334 + #set ($displayType = $NULL)
2335 + #setVariable (~"$displayType~" $result)
2336 +#end
2337 +##
2338 +##
2339 +##
2340 +#**
2341 + * Displays a list of entries.
2342 + *
2343 + * @param entries The entries to display, a list of XDocument names.
2344 + * @param displaying What exactly is displayed: blog index, a single blog entry, a blog category, search results,
2345 + * unpublished entries, etc. This will be used as the classname(s) for the container div (hfeed). Currently
2346 + * used values: index, single, category, search, unpublished, hidden.
2347 + * @param onlyExtract If <tt>true</tt>, only display the extract of articles where available, otherwise display the full content.
2348 + * @param shouldDisplayTitles If <tt>true</tt>, display the blog title (blog posts shouldn't display the title when they're
2349 + * displayed alone on their page since it's the page title which is used in this case)
2350 + *###
2351 +#macro(displayBlog $entries $displaying $onlyExtract $shouldDisplayTitles)
2352 + #set($blogDay = '')
2353 + (% class=~"hfeed $!\{displaying}~" ~%)(((
2354 + (% class=~"blogDay~" ~%)(((
2355 + #foreach ($entryDoc in $xwiki.wrapDocs($entries))
2356 + #getEntryObject($entryDoc $entryObj)
2357 + ## Although all entries should have one of the two objects, better check to be sure.
2358 + #if(~"$!\{entryObj}~" != '')
2359 + #getEntryDate($entryDoc $entryObj $entryDate)
2360 + ## Display a ~"calendar sheet~" for each day. All entries posted on the same day share one such sheet.
2361 + #set($entryDateStr = $xwiki.formatDate($entryDate, 'yyyyMMMMdd'))
2362 + #if($blogDay != $entryDateStr)
2363 + #if($blogDay != '')
2364 + )))
2365 + (% class=~"blogDay~" ~%)(((
2366 + #end
2367 + #displayBlogDate($entryDate)
2368 + #set ($blogDay = $entryDateStr)
2369 + #end
2370 + ## Finally, display the entry.
2371 + #displayEntry($entryDoc $entryObj $onlyExtract $shouldDisplayTitles true)
2372 + #end
2373 + #end
2374 + )))## blogDay
2375 + )))## hfeed
2376 +#end
2377 +##
2378 +##
2379 +##
2380 +#**
2381 + * Get the entry object, either a new BlogPost or an old Article.
2382 + *
2383 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2384 + * @param entryObj The resulting xobject of the blog post.
2385 + *###
2386 +#macro(getEntryObject $entryDoc $__entryObj)
2387 + #set($result = $entryDoc.getObject(~"$\{blogPostClassname}~"))
2388 + #if(!$result)
2389 + #set($result = $entryDoc.getObject(~"$\{oldArticleClassname}~"))
2390 + #end
2391 + ## NOTE: The reason we put an underscore in front of the variable name is to prevent the following line from
2392 + ## overwriting the $entryObj variable that may be defined before this macro is called. Of course, $__entryObj may be
2393 + ## overwritten in this case but it's less likely to have such a variable defined before.
2394 + #set ($__entryObj = $NULL)
2395 + #setVariable (~"$__entryObj~" $result)
2396 +#end
2397 +##
2398 +##
2399 +##
2400 +#**
2401 + * Gets the date associated with a blog entry. This is the publication date. For unpublished entries, initially this is
2402 + * the document creation date, but can be edited by the user.
2403 + *
2404 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2405 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2406 + * @param result The resulting date, an instance of <tt>java.util.Date</tt>.
2407 + *###
2408 +#macro(getEntryDate $entryDoc $entryObj $result)
2409 + #set ($result = $NULL)
2410 + #setVariable (~"$result~" $entryObj.getProperty('publishDate').value)
2411 +#end
2412 +##
2413 +##
2414 +##
2415 +#**
2416 + * Displays a date, nicely formatted as a calendar page.
2417 + *
2418 + * @param date The date to display, an instance of <tt>java.util.Date</tt>.
2419 + *###
2420 +#macro(displayBlogDate $date)
2421 + #set($year = $xwiki.formatDate($date, 'yyyy'))
2422 + ## 3 letter month name, like Jan, Dec.
2423 + #set($month = $xwiki.formatDate($date, 'MMM'))
2424 + ## Uncomment to get a full length month name, like January, December.
2425 + ## TODO: this could be defined somewhere in the blog style.
2426 + ## #set($month = $xwiki.formatDate($date, 'MMMM'))
2427 + #set($day = $xwiki.formatDate($date, 'dd'))
2428 + (% class=~"blogdate~" ~%)
2429 + == (% class=~"month~" ~%)$month(%~%) (% class=~"day~" ~%)$day(%~%) (% class=~"year~" ~%)$year(%~%) ==
2430 +#end
2431 +##
2432 +##
2433 +##
2434 +#**
2435 + * Displays a blog article: management tools, header, content, footer.
2436 + *
2437 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2438 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2439 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
2440 + * @param shouldDisplayTitle If <tt>true</tt>, display the blog title (blog posts shouldn't display the title
2441 + * when they're displayed alone on their page since it's the page title which is used in this case)
2442 + * @param shouldDisplayActions If <tt>true</tt>, display the blog post actions buttons
2443 + *###
2444 +#macro(displayEntry $entryDoc $entryObj $onlyExtract $shouldDisplayTitle $shouldDisplayActions)
2445 + ## Only articles with an explicit hidden setting or an explicit unpublished setting are hidden
2446 + #isPublished($entryObj $isPublished)
2447 + #isHidden($entryObj $isHidden)
2448 + #if($doc.fullName == $entryDoc.fullName)
2449 + (% class=~"hentry single-article~" ~%)(((
2450 + #else
2451 + (% class=~"hentry#if(!$isPublished) unpublished-article#elseif($isHidden) hidden-article#end~" ~%)(((
2452 + #end
2453 + #if ($shouldDisplayActions)
2454 + #displayEntryTools($entryDoc $entryObj)
2455 + #end
2456 + #if($shouldDisplayTitle)
2457 + #displayEntryTitle($entryDoc $entryObj)
2458 + #end
2459 + #if($doc.fullName == $entryDoc.fullName)
2460 + #if(!$isPublished)
2461 + \{\{warning}}\{\{translation key='blog.code.published'/}}\{\{/warning}}
2462 + #elseif($isHidden)
2463 + \{\{warning}}\{\{translation key='blog.code.hidden'/}}\{\{/warning}}
2464 + #end
2465 + #end
2466 + #displayEntryContent($entryDoc $entryObj $onlyExtract)
2467 + #displayEntryFooter($entryDoc $entryObj)
2468 + )))## hentry
2469 +#end
2470 +##
2471 +##
2472 +##
2473 +#**
2474 + * Checks if the provided blog is published or not.
2475 + *
2476 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2477 + * @param isPublished The resulting boolean, true if the entry is considered published.
2478 + *###
2479 +#macro(isPublished $entryObj $isPublished)
2480 + #set ($isPublished = $NULL)
2481 + ## This should work for both old articles, which don't have the 'published' property at all, and
2482 + ## are considered published by default, and new entries, that should have 1 if published.
2483 + #if (~"$!\{entryObj.getProperty('published').value}~" != '0')
2484 + #setVariable (~"$isPublished~" true)
2485 + #else
2486 + #setVariable (~"$isPublished~" false)
2487 + #end
2488 +#end
2489 +##
2490 +##
2491 +##
2492 +#**
2493 + * Checks if the provided blog is hidden or not.
2494 + *
2495 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass<tt> xclass.
2496 + * @param isHiddel The resulting boolean, true if the entry is considered hidden.
2497 + *###
2498 +#macro(isHidden $entryObj $isHidden)
2499 + #set ($isHidden = $NULL)
2500 + ## This should work for both old articles, which don't have the 'hidden' property at all, and
2501 + ## are considered visible by default, and new entries, that should have 1 if hidden.
2502 + #if (~"$!\{entryObj.getProperty('hidden').value}~" == '1')
2503 + #setVariable (~"$isHidden~" true)
2504 + #else
2505 + #setVariable (~"$isHidden~" false)
2506 + #end
2507 +#end
2508 +##
2509 +##
2510 +##
2511 +#**
2512 + * Displays several ~"tools~" for manipulating blog posts: hide/show, publish, edit.
2513 + *
2514 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2515 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2516 + *###
2517 +#macro(displayEntryTools $entryDoc $entryObj)
2518 + #if($xcontext.action == 'view')
2519 + (% class=~"blog-entry-toolbox~" ~%)(((
2520 + #displayPublishButton($entryDoc $entryObj)
2521 + #displayHideShowButton($entryDoc $entryObj)
2522 + #displayEditButton($entryDoc $entryObj)
2523 + #displayDeleteButton($entryDoc $entryObj)
2524 + )))
2525 + #end
2526 +#end
2527 +##
2528 +##
2529 +##
2530 +#**
2531 + * Displays the publish button to the entry <strong>creator</strong>, if the article is not published yet.
2532 + *
2533 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2534 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2535 + * @todo AJAX calls.
2536 + *###
2537 +#macro(displayPublishButton $entryDoc $entryObj)
2538 + #isPublished($entryObj $isPublished)
2539 + #if(!$isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
2540 + [[#toolImage('world')>>path:$blogPublisher.getURL('view', ~"entryName=$\{escapetool.url($entryDoc.fullName)}&xredirect=$\{escapetool.url($thisURL)}&form_token=$!\{services.csrf.getToken()}~")||title=~"$services.localization.render('blog.code.notpublished')~"]]##
2541 + #end
2542 +#end
2543 +##
2544 +##
2545 +##
2546 +#**
2547 + * Displays the hide or show button to the entry <strong>creator</strong>, if the article is already published.
2548 + *
2549 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2550 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2551 + *###
2552 +#macro(displayHideShowButton $entryDoc $entryObj)
2553 + #isPublished($entryObj $isPublished)
2554 + #isHidden($entryObj $isHidden)
2555 + ## Only published articles can be hidden. Unpublished articles are considered already hidden.
2556 + #if($isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
2557 + #set ($queryString = \{
2558 + 'xredirect' : $thisURL,
2559 + 'form_token' : $services.csrf.getToken()
2560 + })
2561 + #if ($isHidden)
2562 + #set ($discard = $queryString.putAll(\{
2563 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 0,
2564 + 'comment' : $services.localization.render('blog.code.madevisible')
2565 + }))
2566 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
2567 + [[#toolImage('unlock')>>path:$lockURL||class=~"blog-tool-show~" title=~"$services.localization.render('blog.code.makevisible')~"]]##
2568 + #else
2569 + #set ($discard = $queryString.putAll(\{
2570 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 1,
2571 + 'comment' : $services.localization.render('blog.code.hid')
2572 + }))
2573 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
2574 + [[#toolImage('lock')>>path:$lockURL||class=~"blog-tool-hide~" title=~"$services.localization.render('blog.code.hide')~"]]##
2575 + #end
2576 + #end
2577 +#end
2578 +##
2579 +##
2580 +##
2581 +#**
2582 + * Displays the edit button to those that can edit the article.
2583 + *
2584 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2585 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2586 + *###
2587 +#macro(displayEditButton $entryDoc $entryObj)
2588 + #if($xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
2589 + ## Call getDefaultEditMode() for backward compatibility with older blog posts.
2590 + [[#toolImage('pencil')>>path:$entryDoc.getURL('edit')||title=~"$services.localization.render('blog.code.editpost')~"]]##
2591 + #end
2592 +#end
2593 +##
2594 +##
2595 +##
2596 +#**
2597 + * Displays the delete button to those that can edit the article.
2598 + *
2599 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2600 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2601 + * @todo AJAX calls.
2602 + *###
2603 +#macro(displayDeleteButton $entryDoc $entryObj)
2604 + #if($xwiki.hasAccessLevel('delete', $xcontext.user, $entryDoc.fullName))
2605 + [[#toolImage('cross')>>path:$entryDoc.getURL('delete')||title=~"$services.localization.render('blog.code.deletepost')~"]]##
2606 + #end
2607 +#end
2608 +##
2609 +##
2610 +##
2611 +#**
2612 + * Displays the title of the entry.
2613 + *
2614 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2615 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2616 + *###
2617 +#macro(displayEntryTitle $entryDoc $entryObj)
2618 + #if($doc.fullName == $entryDoc.fullName)
2619 + (% class=~"entry-title~" ~%)
2620 + = $services.rendering.escape($entryDoc.display('title', 'view', $entryObj), $xwiki.getCurrentContentSyntaxId()) =
2621 + #else
2622 + (% class=~"entry-title~" ~%)
2623 + === [[$services.rendering.escape($entryDoc.display('title', 'view', $entryObj),$xwiki.getCurrentContentSyntaxId())>>doc:$services.rendering.escape($services.model.serialize($entryDoc.getDocumentReference(),'default'),$xwiki.getCurrentContentSyntaxId())]] ===
2624 + #end
2625 +#end
2626 +##
2627 +##
2628 +##
2629 +#**
2630 + * Displays the body of the entry.
2631 + *
2632 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2633 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2634 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
2635 + *###
2636 +#macro(displayEntryContent $entryDoc $entryObj $onlyExtract)
2637 + (% class=~"#if($onlyExtract)entry-summary#\{else}entry-content#end~" ~%)(((
2638 + #getEntryContent($entryDoc $entryObj $onlyExtract $entryContent)
2639 + ## FIXME: This causes the blog's content to not be annotatable. See http://jira.xwiki.org/browse/XWIKI-6328
2640 + ## Should probably be replaced by a display macro call with a reference to the object property holding the post's content
2641 + \{\{html wiki=~"false~"}}$entryDoc.getRenderedContent($entryContent, $entryDoc.syntax.toIdString())\{\{/html}}
2642 + ))) ## entry-content
2643 + (% class=~"clearfloats~" ~%)((()))
2644 +#end
2645 +##
2646 +##
2647 +##
2648 +#**
2649 + * Extracts the body of the entry that should be displayed. If <tt>onlyExtract</tt> is <tt>true</tt>, display the content
2650 + * of the <tt>extract</tt> field (if not empty).
2651 + *
2652 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2653 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2654 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
2655 + * @param entryContent The resulting content.
2656 + * @param removeEllipsis If <tt>true</tt>, then don't display an ellipsis at the end of the content (only used when
2657 + * <tt>onlyExtract</tt> is <tt>true</tt>)
2658 + *###
2659 +#macro(getEntryContent $entryDoc $entryObj $onlyExtract $entryContent $removeEllipsis)
2660 + #if ($onlyExtract)
2661 + ## Note: We trim the summary so that if there's some white space it won't cause the summary to be used instead
2662 + ## of the content.
2663 + #set ($macro.result = $entryObj.getProperty('extract').value.trim())
2664 + #end
2665 + #if(~"$!macro.result~" == '')
2666 + #set($macro.result = $entryObj.getProperty('content').value)
2667 +#* Disabled until the content can be cleanly cut.
2668 +* #if($onlyExtract && $result.length()>$maxchars)
2669 +* #set($i = $macro.result.lastIndexOf(~" ~", $maxchars))
2670 +* #set($i = $i + 1)
2671 +* #set($macro.result = ~"$\{macro.result.substring(0,$i)} *[...>$\{entryDoc.fullName}]*~")
2672 +* #end
2673 +## *###
2674 + #elseif (!$removeEllipsis)
2675 + #if($entryDoc.syntax.toIdString() == 'xwiki/1.0')
2676 + #set($macro.result = ~"$\{macro.result} <a href='$\{entryDoc.getExternalURL()}' title='$services.localization.render('blog.code.readpost')'>...</a>~")
2677 + #elseif($entryDoc.syntax.toIdString() == 'xwiki/2.0' || $entryDoc.syntax.toIdString() == 'xwiki/2.1')
2678 + #set($macro.result = ~"$\{macro.result} [[...>>$\{services.rendering.escape($entryDoc.getFullName(), $entryDoc.getSyntax())}||title='$services.localization.render('blog.code.readpost')']]~")
2679 + #end
2680 + #end
2681 + #set ($entryContent = $NULL)
2682 + #setVariable (~"$entryContent~" $macro.result)
2683 +#end
2684 +##
2685 +##
2686 +##
2687 +#**
2688 + * Displays the footer of the entry.
2689 + *
2690 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2691 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2692 + *###
2693 +#macro(displayEntryFooter $entryDoc $entryObj)
2694 + (% class=~"entry-footer~" ~%)(((
2695 + #isPublished($entryObj $isPublished)
2696 + (% class='entry-author-label' ~%)
2697 + #if($isPublished)
2698 + \{\{translation key='blog.code.postedby'/}} ##
2699 + #else
2700 + \{\{translation key='blog.code.createdby'/}} ##
2701 + #end
2702 + \{\{html wiki=~"false~" clean=~"false~"}}<span class='author vcard'>#userfn($entryDoc.creator)</span>\{\{/html}} ##
2703 + #getEntryDate($entryDoc $entryObj $entryDate)
2704 + #listCategories($entryObj) #*
2705 + ## Since the publish date and update date are not set at the exact same time, there could be a small difference that
2706 + ## we assume cannot be more than 3 seconds.
2707 + *#(% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.permalink'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||rel=~"bookmark~"]] ##
2708 + #if ($showcomments)
2709 + (% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.comments'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||anchor=~"Comments~"]] (% class=~"itemCount~" ~%)($entryDoc.comments.size())(%~%) ##
2710 + #end ##
2711 + #if($entryDoc != $doc) ##
2712 + #displayEntryBlogLocation($entryDoc $entryObj) ##
2713 + #end
2714 + )))## entry-footer
2715 +#end
2716 +##
2717 +##
2718 +#**
2719 + * Display the blog for the entry (if it is not the currently displayed blog)
2720 + *
2721 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
2722 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2723 + *###
2724 +#macro(displayEntryBlogLocation $entryDoc $entryObj)
2725 + #getBlogPostsLocation($entryDoc.getSpace() $blogPostsLocation) ##
2726 + #if(~"$!blogPostsLocation~" != ~"~") ##
2727 + #set($blogSpaceRef = $services.model.resolveSpace($blogPostsLocation)) ##
2728 + #set($blogDocRef = $services.model.createDocumentReference($services.model.getEntityReference('DOCUMENT', 'default').getName(), $blogSpaceRef)) ##
2729 + #if($doc.documentReference != $blogDocRef) ##
2730 + #set($blogDoc = $xwiki.getDocument($blogDocRef)) ##
2731 + #set($blogObj = $blogDoc.getObject('Blog.BlogClass')) ##
2732 + #if($blogObj) (% class=~"blogrefpath~" ~%)((( ##
2733 + $services.localization.render('blog.code.postedin') \{\{html clean=~"false~" wiki=~"false~"}} #hierarchy($blogDocRef, \{'selfIsActive' : true, 'local': true}) \{\{/html}} ##
2734 + )))(%~%)##
2735 + #end
2736 + #end
2737 + #end
2738 +#end
2739 +##
2740 +##
2741 +##
2742 +##
2743 +#**
2744 + * List the categories an entry belongs to. Used in the footer. The categories are instances of <tt>Blog.CategoryClass</tt>.
2745 + *
2746 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
2747 + *###
2748 +#macro(listCategories $entryObj)
2749 + #if($entryObj.getxWikiClass().getName() == $blogPostClassname)
2750 + #set($categories = $entryObj.getProperty('category').value)
2751 + #set($first = true)
2752 + #if($categories.size() > 0)
2753 + #foreach($category in $categories)
2754 + #set($categoryDoc = $!xwiki.getDocument($category))
2755 + #if(!$categoryDoc.isNew() && $categoryDoc.getObject($\{blogCategoryClassname}))
2756 + #if($foreach.count == 1)
2757 + (% class='separator' ~%)·(%~%) $services.localization.render('blog.code.categories') ##
2758 + #else
2759 + , ##
2760 + #end##
2761 + [[$!\{categoryDoc.getObject($blogCategoryClassname).getValue('name')}>>$\{category}||rel='tag']]##
2762 + #end##
2763 + #end##
2764 + #end
2765 + #end
2766 +#end
2767 +##
2768 +##
2769 +##
2770 +#**
2771 + * Displays blog pagination links (older and newer entries).
2772 + *
2773 + * @param blogDoc the XDocument holding the blog definition object.
2774 + *###
2775 +#macro(displayNavigationLinks $blogDoc)
2776 + (% class=~"clearfloats~" ~%)((()))
2777 + #getBlogDisplayType($blogDoc $displayType)
2778 + #if($displayType == 'weekly')
2779 + (% class=~"pagingLinks~" ~%)(((
2780 + #getRequestedWeek($weekDate)
2781 + $weekDate.addWeeks(-1)##
2782 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousweek'/}}>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
2783 + #sep()
2784 + $weekDate.addWeeks(2)## 2 because we already subtracted 1 above
2785 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextweek'/}} »>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
2786 + )))
2787 + #elseif($displayType == 'monthly')
2788 + (% class=~"pagingLinks~" ~%)(((
2789 + #getRequestedMonth($monthDate)
2790 + $monthDate.addMonths(-1)##
2791 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousmonth'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
2792 + #sep()
2793 + $monthDate.addMonths(2)## 2 because we already subtracted 1 above
2794 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextmonth'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
2795 + )))
2796 + #elseif($displayType == 'all')
2797 + #else
2798 + ## Paginated
2799 + #if(($totalPages > 1))
2800 + #set($queryString = '')
2801 + #foreach($p in $request.getParameterNames())
2802 + #if($p != 'page' && $p != 'ipp')
2803 + #foreach($v in $request.getParameterValues($p))
2804 + #set($queryString = ~"$\{queryString}&$\{escapetool.url($p)}=$\{escapetool.url($v)}~")
2805 + #end
2806 + #end
2807 + #end
2808 + (% class=~"pagingLinks~" ~%)(((
2809 + #if ($currentPageNumber < $totalPages)
2810 + #set($currentPageNumber = $currentPageNumber + 1)
2811 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.olderposts'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
2812 + #set($currentPageNumber = $currentPageNumber - 1)
2813 + #end
2814 + #if ($currentPageNumber > 1)
2815 + #if ($currentPageNumber < $totalPages)
2816 + #sep()
2817 + #end
2818 + #set($currentPageNumber = $currentPageNumber - 1)
2819 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.newerposts'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
2820 + #set($currentPageNumber = $currentPageNumber + 1)
2821 + #end
2822 + (% class=~"clear~" ~%)(%~%)
2823 + )))## pagingLinks
2824 + #end
2825 + #end
2826 +#end
2827 +##
2828 +##
2829 +##
2830 +#**
2831 + * Displays a message box with ~"publish~" icon.
2832 + *
2833 + * @param message A text message concerning blog article publishing
2834 + *###
2835 +#macro(publishMessageBox $message)
2836 +(% class=~"plainmessage publish-message~" ~%)((($services.icon.render('world') $message)))
2837 +#end
2838 +#**
2839 + * Displays a message box with ~"show/hide~" icon.
2840 + *
2841 + * @param message A text message concerning blog article hiding
2842 + *###
2843 +#macro(hideMessageBox $message)
2844 +(% class=~"plainmessage hide-message~" ~%)((($services.icon.render('unlock') $message)))
2845 +#end
2846 +##
2847 +##
2848 +##
2849 +#**
2850 + * Determine the requested week, for using in a weekly-indexed blog. The relevant request parameters are
2851 + * <tt>year</tt> and <tt>week</tt>. By default, the current week is used.
2852 + *
2853 + * @param monthDate The resulting week, a JODATime MutableDateTime.
2854 + *###
2855 +#macro(getRequestedWeek $weekDate)
2856 + #set ($weekDate = $NULL)
2857 + #setVariable (~"$weekDate~" $xwiki.jodatime.mutableDateTime)
2858 + #if(~"$!\{request.year}~" != '')
2859 + #set ($discard = $weekDate.setYear($numbertool.toNumber($request.year).intValue()))
2860 + #end
2861 + #if(~"$!\{request.week}~" != '')
2862 + #set ($discard = $weekDate.setWeekOfWeekyear($numbertool.toNumber($request.week).intValue()))
2863 + #end
2864 +#end
2865 +##
2866 +##
2867 +##
2868 +#**
2869 + * Determine the requested month, for using in a monthly-indexed blog. The relevant request parameters are
2870 + * <tt>year</tt> and <tt>month</tt>. By default, the current month is used.
2871 + *
2872 + * @param monthDate The resulting month, a JODATime MutableDateTime.
2873 + *###
2874 +#macro(getRequestedMonth $monthDate)
2875 + #set ($monthDate = $NULL)
2876 + #setVariable (~"$monthDate~" $xwiki.jodatime.mutableDateTime)
2877 + #if(~"$!\{request.year}~" != '')
2878 + #set ($discard = $monthDate.setYear($numbertool.toNumber($request.year).intValue()))
2879 + #end
2880 + #if(~"$!\{request.month}~" != '')
2881 + #set ($discard = $monthDate.setMonthOfYear($numbertool.toNumber($request.month).intValue()))
2882 + #end
2883 +#end
2884 +##
2885 +##
2886 +##
2887 +#**
2888 + * Retrieve a blog property (title, display type, etc).
2889 + *
2890 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
2891 + * @param propertyName The name of the property to be retrieved. One of the <tt>Blog.BlogClass</tt>'s properties.
2892 + * @param defaultValue The default value to use in case the blog object does not define one.
2893 + * @param propertyValue The resulting value.
2894 + *###
2895 +#macro(getBlogProperty $blogDoc $propertyName $defaultValue $propertyValue)
2896 + #set($result = ~"$!\{blogDoc.getObject($\{blogClassname}).getProperty($propertyName).value}~")
2897 + #if($result == '')
2898 + #set($result = $defaultValue)
2899 + #end
2900 + #set ($propertyValue = $NULL)
2901 + #setVariable (~"$propertyValue~" $result)
2902 +#end
2903 +
2904 +#**
2905 + * If an error occurs when executing an action, set a specific response status and display an error message.
2906 + *
2907 + * @param status The response status.
2908 + * @param text The user readable error to be displayed. Can be a translation key.
2909 + * @param parameters The parameters to use when decoding the translation key.
2910 + *###
2911 +#macro(blog__actionResponseError $status $text $parameters)
2912 + $response.setStatus($status)
2913 + #if($request.ajax)
2914 + $services.localization.render($text, $!parameters)
2915 + #else
2916 + \{\{error}}$services.localization.render($text, $!parameters)\{\{/error}}
2917 + #end
2918 +#end
2919 +##
2920 +##
2921 +##
2922 +#**
2923 + * Check if a blog is the Default blog (The one in the 'Blog' space).
2924 + *
2925 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
2926 + * @param isDefault The resulting boolean.
2927 + *###
2928 +#macro(isDefaultBlog $blogDoc $isDefault)
2929 + #set ($result = false)
2930 + #if ($blogDoc.space == 'Blog')
2931 + #set ($result = true)
2932 + #end
2933 + #setVariable(~"$isDefault~" $result)
2934 +#end
2935 +##
2936 +##
2937 +##
2938 +#**
2939 + * Retrieve the blog posts location (space).
2940 + *
2941 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
2942 + * @param postsLocation The resulting location.
2943 + *###
2944 +#macro(getBlogPostsLocation $blogSpace $postsLocation)
2945 + #getBlogDocument($blogSpace $blogDoc)
2946 + #getBlogProperty($blogDoc 'postsLocation' $blogDoc.space $result)
2947 + #set ($postsLocation = $NULL)
2948 + #setVariable (~"$postsLocation~" $result)
2949 +#end
2950 +##
2951 +##
2952 +##
2953 +#**
2954 + * Retrieve the blog categories location (space).
2955 + *
2956 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
2957 + * @param categoriesLocation The resulting location.
2958 + *###
2959 +#macro(getBlogCategoriesLocation $blogSpace $categoriesLocation)
2960 + #getBlogDocument($blogSpace $blogDoc)
2961 + #getBlogProperty($blogDoc 'categoriesLocation' 'Blog' $result)
2962 + #set ($postsLocation = $NULL)
2963 + #setVariable (~"$categoriesLocation~" $result)
2964 +#end
2965 +###**
2966 + * Return the Query for selecting the blog posts based on the context where the posts are displayed.
2967 + * for example there is 4 different panel contexts:
2968 + * aBlog.aPost or aBlog.WebHome
2969 + * aCategorySpace.aCategory
2970 + * aCategorySpace.WebHome
2971 + * Blog.aPost or Blog.WebHome
2972 + *
2973 + * @param query The query for selecting blog entries.
2974 + * @param queryParams The parameters to bind with the generated query.
2975 + * @param targetDoc The document in which the articles will be displayed.
2976 + *###
2977 +#macro(getAllBlogPostsQueryBasedOnDisplayContext $targetDoc $query $queryParams)
2978 + #set ($query = $NULL)
2979 + #set ($queryParams = $NULL)
2980 + #getCategoryAllBlogPostsQuery($resultQuery)
2981 + #set ($resultQueryParams = \{})
2982 + #set($sanitizedSpace = $targetDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
2983 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
2984 + ## Get all posts that are in the default blog space('Blog') or in category 'Blog.%'
2985 + #set ($discard = $resultQueryParams.put('space', $targetDoc.space))
2986 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
2987 + #set($resultQuery = ~"$\{resultQuery} and (doc.space = :space or catList like :catList escape '!')~")
2988 + #elseif($targetDoc.getObject($blogCategoryClassname))
2989 + ## Get all posts that are in a category aCategorySpace.aCategory
2990 + #set ($discard = $resultQueryParams.put('catList', $targetDoc.fullName))
2991 + #set($resultQuery = ~"$\{resultQuery} and (catList=:catList)~")
2992 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
2993 + ## Get all posts that are in a category aCategorySpace.%
2994 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
2995 + ## Exclude incategorized posts
2996 + #set ($excludedCategory = ~"$\{targetDoc.space}.WebHome~")
2997 + #if ($targetDoc.space == $defaultBlogSpace)
2998 + #set ($excludedCategory = ~"Blog.Categories.WebHome~")
2999 + #end
3000 + #set ($discard = $resultQueryParams.put('excludedCategory', $excludedCategory))
3001 + #set($resultQuery = ~"$\{resultQuery} and (catList<>:excludedCategory) and (catList like :catList escape '!')~")
3002 + #else
3003 + ## Get all posts in blog space aBlog
3004 + #getAllBlogPostsQuery($resultQuery)
3005 + #getBlogPostsLocation($targetDoc.space $postsLocation)
3006 + #set ($discard = $resultQueryParams.put('space', $postsLocation))
3007 + #set($resultQuery = ~"$\{resultQuery} and doc.space = :space~")
3008 + #end
3009 + #setVariable(~"$query~" $resultQuery)
3010 + #setVariable(~"$queryParams~" $resultQueryParams)
3011 +#end
3012 +##
3013 +##
3014 +##
3015 +###**
3016 + * Display blog posts based on the context where the posts are displayed.
3017 + * for example there is 4 different panel contexts:
3018 + * aBlog.aPost or aBlog.WebHome
3019 + * aCategorySpace.aCategory
3020 + * aCategorySpace.WebHome
3021 + * Blog.aPost or Blog.WebHome
3022 + *
3023 + * @param targetDoc The document in which the articles will be displayed.
3024 + * @param postsVisiblity The visibility of the posts to display: recent, unpublished, ...
3025 + * @param layout Layout of the the posts to display
3026 + * @param layoutParams additional layout parameters, it is a string like 'param1=val1|...|paramN=valueN'
3027 + * @param limit the number of posts to display
3028 + *###
3029 +#macro(displayBlogPostsBasedOnContext $targetDoc $postsVisiblity $layout $layoutParams $limit)
3030 + #if ($postLayout == 'full')
3031 + #set ($macro.paginated = 'yes')
3032 + #end
3033 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
3034 + ## Display all posts that are in the default blog space('Blog') or in category 'Blog.%'
3035 + #getBlogPostsLayout($xwiki.getDocument(~"$\{defaultBlogSpace}.WebHome~") $postsLayout)
3036 + #if (~"$!layout~" == '')
3037 + #set ($layout = $postsLayout)
3038 + #end
3039 + #if ($postsVisiblity == 'recent')
3040 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
3041 + #elseif($postsVisiblity == 'unpublished')
3042 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
3043 + #end
3044 + #elseif($targetDoc.getObject($blogCategoryClassname))
3045 + ## Display all posts that are in a category aCategorySpace.aCategory
3046 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
3047 + #getBlogPostsLayout($blogDoc $postsLayout)
3048 + #if (~"$!layout~" == '')
3049 + #set ($layout = $postsLayout)
3050 + #end
3051 + #if ($postsVisiblity == 'recent')
3052 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
3053 + #elseif($postsVisiblity == 'unpublished')
3054 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
3055 + #end
3056 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
3057 + ## Display all posts that are in a category aCategorySpace.%
3058 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
3059 + #getBlogPostsLayout($blogDoc $postsLayout)
3060 + #if (~"$!layout~" == '')
3061 + #set ($layout = $postsLayout)
3062 + #end
3063 + #if ($postsVisiblity == 'recent')
3064 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
3065 + #elseif($postsVisiblity == 'unpublished')
3066 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
3067 + #end
3068 + #else
3069 + ## Display all posts in blog space aBlog
3070 + #getBlogDocument($targetDoc.space $blogDoc)
3071 + #getBlogPostsLayout($blogDoc $postsLayout)
3072 + #if (~"$!layout~" == '')
3073 + #set ($layout = $postsLayout)
3074 + #end
3075 + #if ($postsVisiblity == 'recent')
3076 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
3077 + #elseif($postsVisiblity == 'unpublished')
3078 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
3079 + #end
3080 + #end
3081 +#end
3082 +##
3083 +##
3084 +##
3085 +#**
3086 + * Bind parameters to a query object.
3087 + *
3088 + * @param queryObj The query object (org.xwiki.query.internal.ScriptQuery object)
3089 + * @param queryParams the query parameters.
3090 + *###
3091 +#macro(bindQueryParameters $queryObj $queryParams)
3092 + #set ($output = $queryObj)
3093 + #foreach( $key in $queryParams.keySet() )
3094 + #set($output = $queryObj.bindValue($key, $queryParams.get($key)))
3095 + #end
3096 + #setVariable(~"$queryObj~" $output)
3097 +#end
3098 +##
3099 +##
3100 +##
3101 +#**
3102 + * Determines the blogposts layout: Default layout (Calendar), Image thumbnail
3103 + *
3104 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>postsLayout</tt>
3105 + * property set.
3106 + * @param postsLayout The resulting string. If the blog object does not define anything, it is considered full (default).
3107 + *###
3108 +#macro(getBlogPostsLayout $blogDoc $postsLayout)
3109 + #getBlogProperty($blogDoc 'postsLayout' 'full' $res)
3110 + #set ($postsLayout = $NULL)
3111 + #setVariable (~"$postsLayout~" $res)
3112 +#end
3113 +##
3114 +##
3115 +##
3116 +#**
3117 + * Retrieve the blog document of a categories space, which is the blog descriptor that have its categoriesLocation property set to the categories space
3118 + *
3119 + * @param categoriesSpace A <tt>String</tt>, the name of the space.
3120 + * @param blogDoc The resulting XDocument.
3121 + *###
3122 +#macro(getBlogDocumentForCategoriesSpace $categoriesSpace $blogDoc)
3123 + #set($macro.blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as categoriesLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=categoriesLocationProp.id.id and categoriesLocationProp.id.name='categoriesLocation' and categoriesLocationProp.value=:categoriesLocation order by doc.creationDate~").setLimit(1).setOffset(0).bindValue('categoriesLocation', $categoriesSpace).execute())
3124 + #if($macro.blogDocs.size() > 0 && $categoriesSpace != $defaultBlogSpace)
3125 + #set($macro.result = $xwiki.getDocument($macro.blogDocs.get(0)))
3126 + #else
3127 + ## Fallback to Blog.WebHome, the default blog
3128 + #set($macro.result = $xwiki.getDocument('Blog.WebHome'))
3129 + #end
3130 + #set ($blogDoc = $NULL)
3131 + #setVariable (~"$blogDoc~" $macro.result)
3132 +#end" %)
3133 +(((
3134 +(% class="macro-placeholder hidden" %)
3135 +(((
3136 +macro:velocity
3137 +)))
3138 +)))
3139 +)))
3140 +
3141 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogPostLayoutMacros~"" %)
3142 +(((
3143 +(% class="macro-placeholder hidden" %)
3144 +(((
3145 +macro:include
3146 +)))
3147 +
3148 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|#**
3149 + * Extract the layout parameters from a string.
3150 + *
3151 + * @param layoutParamsString The string representation of the layout parameters.
3152 + * It should contain a String following this format ~"paramName1=Value1|paramName2=Value2|...|paramNameK=ValueK~"
3153 + * @param layoutsParameters The resulting layout parameters Map.
3154 + *###
3155 +#macro(extractLayoutParametersFromString $layoutParamsString $layoutsParameters)
3156 + #set ($layoutsParameters = $NULL)
3157 + #set ($macro.layoutParams = \{})
3158 + #if (~"$!layoutParamsString~" != '')
3159 + #set ($macro.paramsArr = $layoutParamsString.split('\\|'))
3160 + #foreach ($item in $macro.paramsArr)
3161 + #set ($itemSplit = $item.split('='))
3162 + #if ($itemSplit.size() == 2)
3163 + #set ($discard = $macro.layoutParams.put($itemSplit[0].trim(), $itemSplit[1].trim()))
3164 + #end
3165 + #end
3166 + #end
3167 + #setVariable(~"$layoutsParameters~" $macro.layoutParams)
3168 +#end" %)
3169 +(((
3170 +(% class="macro-placeholder hidden" %)
3171 +(((
3172 +macro:velocity
3173 +)))
3174 +)))
3175 +)))
3176 +
3177 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-| #macro(displaySmallPost $pDoc $pObj)
3178 + #initLayoutVars($pDoc $pObj)
3179 + <div class=~"col-xs-12 col-sm-6 next_blog~">
3180 + <a href=~"$pDoc.uRL~" class=~"thumbnail~">
3181 + <div class=~"row~">
3182 + <div class=~"col-xs-4~">
3183 + #if ($imageAtt)
3184 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
3185 + #end
3186 + </div>
3187 + <div class=~"col-xs-8 art_det~">
3188 + <p class=~"text-left~">
3189 + #if($displayTitle)$!postTitle #end
3190 + <br/><span class=~"date_info~"> $!dateStr </span>
3191 + </p>
3192 + #displayPostDetails($pDoc)
3193 + </div>
3194 + </div>
3195 + </a>
3196 + </div>
3197 + #end
3198 + ##
3199 + ##
3200 + ##
3201 + #macro(displayPinnedPost $pDoc $pObj)
3202 + #initLayoutVars($pDoc $pObj)
3203 + <div class=~"col-xs-12 col-sm-4 col-md-4 blog_pin~">
3204 + <a href=~"$pDoc.uRL~" class=~"all-post-link~">
3205 + <div class=~"thumbnail~">
3206 + #if ($displayTitle && $displayTitleFirstOnPinnedPosts)
3207 + <h5 class=~"title-top~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
3208 + #end
3209 + #if ($imageAtt)
3210 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
3211 + #end
3212 + <div class=~"caption~">
3213 + #if ($displayTitle && !$displayTitleFirstOnPinnedPosts)
3214 + <h5 class=~"text-left~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
3215 + #end
3216 + #if ($displaySummaryOnPinnedPosts)
3217 + <div class=~"text-left post-summary~">
3218 + #set ($postContent = $pObj.getProperty('extract').value)
3219 + $!pDoc.getRenderedContent($postContent, $pDoc.syntax.toIdString())
3220 + </div>
3221 + #end
3222 + #displayPostDetails($pDoc)
3223 + </div>
3224 + </div>
3225 + </a>
3226 + </div>
3227 + #end
3228 + ##
3229 + ##
3230 + ##
3231 + #macro(formatPostDate $pDoc $pObj)
3232 + #set ($formattedDate = $NULL)
3233 + #set($dateStr = $datetool.format('medium', $postDate, $xcontext.locale))
3234 + #if (~"$!dateStr~" != '')
3235 + #set ($dateArr = $dateStr.split(' '))
3236 + #if ($dateArr.size() > 3)
3237 + #set ($dateStr = ~"~")
3238 + #foreach($s in $dateArr.subList(0, 3))
3239 + #set ($dateStr = ~"$\{dateStr}$\{s} ~")
3240 + #end
3241 + #end
3242 + #end
3243 + #setVariable(~"$formattedDate~" $dateStr)
3244 + #end
3245 + ##
3246 + ##
3247 + ##
3248 + #macro(displayPostDetails $pDoc)
3249 + <div class=~"row post-details~">
3250 + <div class=~"col-xs-8 detail~">
3251 + #if ($services.like.displayButton($pDoc.documentReference))
3252 + #set ($optLikeRecord = $services.like.getLikes($pDoc.documentReference))
3253 + ## Retrieve the likes number in XWiki 12.9+
3254 + #set ($likeNumber = $optLikeRecord.get())
3255 + #if (!$stringtool.isNumeric($likeNumber.toString()))
3256 + ## Retrieve the likes number in XWiki versions greater than 12.7 and lower than 12.9.
3257 + #set ($likeNumber = $optLikeRecord.get().likeNumber)
3258 + #end
3259 + #if ($stringtool.isNumeric($likeNumber.toString()))
3260 + <div class=~"post-likes btn btn-default disabled badge~"
3261 + title=~"$escapetool.xml($services.localization.render('like.button.title', [$likeNumber]))~">
3262 + $services.icon.renderHTML('heart') <span class=~"like-number~">$likeNumber</span>
3263 + </div>
3264 + #end
3265 + #elseif ($services.ratings)
3266 + #set ($ratingsConfigDoc = $services.ratings.getConfigurationDocument($pDoc.documentReference))
3267 + #if ($ratingsConfigDoc.getValue('displayRatings') == 1)
3268 + <ul class=~"pull-left note list-inline~">
3269 + #foreach ($x in [1..5])
3270 + #set ($cls = ~"~")
3271 + #if ($x > $averageVote)
3272 + #set ($cls = ~"-o~")
3273 + #end
3274 + <li><span class=~"fa fa-star$\{cls}~"></span></li>
3275 + #end
3276 + </ul>
3277 + #end
3278 + #end
3279 + </div>
3280 + #if ($showPostComments)
3281 + <div class=~"col-xs-4 com_det~">
3282 + <p class=~"text-right~">$services.icon.renderHTML('comments') ($!nbComments)</p>
3283 + </div>
3284 + #end
3285 + </div>
3286 + #end
3287 + ##
3288 + ##
3289 + ##
3290 + #macro(initLayoutVars $pDoc $pObj)
3291 + #set ($postTitle = $pDoc.display('title', 'view', $pObj))
3292 + #set ($imageAtt = $pDoc.getAttachment($pObj.getValue('image')))
3293 + #isPublished($pObj $isPublished)
3294 + #isHidden($pObj $isHidden)
3295 + #getEntryDate($pDoc $pObj $postDate)
3296 + #formatPostDate($postDate $dateStr)
3297 + #set ($averageVote = $mathtool.round($services.ratings.getAverageRating($pDoc.documentReference).getAverageVote()))
3298 + #set ($nbComments = $pDoc.getComments().size())
3299 + #set ($showPostComments = true)
3300 + #if ($xwiki.getSpacePreferenceFor('showcomments', $pDoc.documentReference.lastSpaceReference, '1') == '0')
3301 + #set ($showPostComments = false)
3302 + #end
3303 + #end
3304 + ##
3305 + ##
3306 + ##
3307 + #macro(displayEditPinnedPostsButton)
3308 + #if (~"$!macroAdditionalParams.get('postIndex')~" == '0' && $services.security.authorization.hasAccess('edit', $pinnedPostsSourceDoc.fullName))
3309 + #set ($discard = $xwiki.ssx.use('Blog.PinnedPostsSheet'))
3310 + #set ($discard = $xwiki.jsx.use('Blog.PinnedPostsSheet'))
3311 + #set ($editPinnedPostsURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'get', 'sheet=Blog.PinnedPostsSheet'))
3312 + #set ($newPinnedPostsObjectURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'objectadd', ~"classname=Blog.PinnedPostsClass&form_token=$!\{services.csrf.getToken()}~"))
3313 + <div class=~"edit-pinned-posts-container~">
3314 + <div class=~"col-xs-12 col-sm-12 col-md-12 text-right edit-pinned-posts~">
3315 + <a href=~"javascript:;~" class=~"editPinnedPosts~">
3316 + <span class=~"glyphicon glyphicon-edit~" aria-hidden=~"true~"></span> $services.localization.render('blog.post.layout.cards.pinnedposts.edit')
3317 + </a>
3318 + <input type=~"hidden~" id=~"editPinnedPostsURL~" value=~"$escapetool.xml($editPinnedPostsURL)~"/>
3319 + <input type=~"hidden~" id=~"newPinnedPostsObjectURL~" value=~"$escapetool.xml($newPinnedPostsObjectURL)~"/>
3320 + </div>
3321 + </div>
3322 + #if (~"$!pinnedPostsObj~" == '')
3323 + <input type=~"hidden~" name=~"createPinnedPostsObject~" value=~"1~"/>
3324 + #end
3325 + #end
3326 + #end" %)
3327 +(((
3328 +(% class="macro-placeholder hidden" %)
3329 +(((
3330 +macro:velocity
3331 +)))
3332 +)))
3333 +
3334 +(% class="macro" data-macro="startmacro:velocity|-||-| #if ($services.security.authorization.hasAccess('view', $xcontext.macro.params.reference))
3335 + #set ($postDoc = $xwiki.getDocument($xcontext.macro.params.reference))
3336 + #getEntryObject($postDoc $postObj)
3337 + #if (~"$!postObj~" != '')
3338 + #extractLayoutParametersFromString($xcontext.macro.params.params $macroAdditionalParams)
3339 + ##
3340 + #set ($displayTitle = true)
3341 + #if (~"$!macroAdditionalParams.get('displayTitle')~" == 'false')
3342 + #set ($displayTitle = false)
3343 + #end
3344 + ##
3345 + #set ($displayTitleFirstOnPinnedPosts = false)
3346 + #if (~"$!macroAdditionalParams.get('displayTitleFirstOnPinnedPosts')~" == 'true')
3347 + #set ($displayTitleFirstOnPinnedPosts = true)
3348 + #end
3349 + ##
3350 + #set ($displaySummaryOnPinnedPosts = true)
3351 + #if (~"$!macroAdditionalParams.get('displaySummaryOnPinnedPosts')~" == 'false')
3352 + #set ($displaySummaryOnPinnedPosts = false)
3353 + #end
3354 + ##
3355 + #set ($postIndex = $numbertool.toNumber($macroAdditionalParams.get('postIndex')).intValue())
3356 + #if ($postIndex == 0)
3357 + #set ($stopBlogPostsDisplay = false)
3358 + #end
3359 + #set ($listResultsCount = $numbertool.toNumber($macroAdditionalParams.get('list-results-count')).intValue())
3360 + #set($discard = $xwiki.ssx.use('Blog.BlogPostLayoutCards'))
3361 + #set($scaleWidth = 600)
3362 + #set($imgQs=~"width=$scaleWidth~")
3363 + ## Display pinned posts
3364 + ## Get the list of pinned posts
3365 + #set ($pinnedPosts = [])
3366 + #set ($pinnedPostsSourceDoc = $NULL)
3367 + #if (~"$!macroAdditionalParams.get('forceDisplayPinnedPosts')~" == 'true' && ~"$!macroAdditionalParams.get('list-blog')~" != '')
3368 + #set ($pinnedPostsSourceDoc = $xwiki.getDocument($macroAdditionalParams.get('list-blog')))
3369 + ## Note that the 'list-blog' parameter contains the value of the 'blog' parameter of the blogpostlist macro passed to the current layout macro
3370 + #end
3371 + #if (~"$!pinnedPostsSourceDoc~" != '')
3372 + #set ($pinnedPostsObj = $pinnedPostsSourceDoc.getObject('Blog.PinnedPostsClass'))
3373 + #if (~"$!pinnedPostsObj~" != '')
3374 + #set ($orderedPinnedPostsJSON = $pinnedPostsObj.getProperty('orderedPosts').value)
3375 + #if (~"$!orderedPinnedPostsJSON~" != '')
3376 + #set ($pinnedPosts = $jsontool.parse($orderedPinnedPostsJSON))
3377 + #else
3378 + #set ($pinnedPosts = $pinnedPostsObj.getProperty('posts').value)
3379 + #end
3380 + #end
3381 + #if ($postIndex == 0 && $pinnedPosts.size() > 0)
3382 + \{\{html clean=~"false~"}}
3383 + #set ($x = 0)
3384 + #set ($showPinnedPostsButton = true)
3385 + #foreach ($pinnedPost in $pinnedPosts)
3386 + #if ($x == 0)
3387 + <div class=~"row flex-container~">
3388 + #if ($showPinnedPostsButton)
3389 + #displayEditPinnedPostsButton()
3390 + #set($showPinnedPostsButton = false)
3391 + #end
3392 + #end
3393 + #set ($pinnedPostDoc = $xwiki.getDocument($pinnedPost))
3394 + #getEntryObject($pinnedPostDoc $pinnedPostObj)
3395 + #if (~"$!pinnedPostObj~" != '')
3396 + #displayPinnedPost($pinnedPostDoc $pinnedPostObj)
3397 + #end
3398 + #set ($x = $mathtool.add($x, 1))
3399 + #if ($x == 3)
3400 + #set ($x = 0)
3401 + </div>
3402 + #end
3403 + #end
3404 + #if ($mathtool.mod($x, 3) != 0)
3405 + </div>
3406 + #end
3407 + \{\{/html}}
3408 +
3409 + ## If the first post is a pinned post : this means that all the posts are pinned
3410 + ## In this case, avoid displaying the posts again after the pinned posts section.
3411 + #if ($pinnedPosts.contains($xcontext.macro.params.reference))
3412 + #set ($stopBlogPostsDisplay = true)
3413 + #end
3414 + #elseif($postIndex == 0 && $pinnedPosts.size() == 0)
3415 +
3416 + \{\{html}}
3417 + <div class=~"row no-pinnded-posts~">
3418 + #displayEditPinnedPostsButton()
3419 + </div>
3420 + \{\{/html}}
3421 +
3422 + #end
3423 + #end
3424 + #if (!$stopBlogPostsDisplay)
3425 + \{\{html clean=~"false~"}}
3426 + #if (~"$!nbDisplayedPosts~" == '' || $postIndex == 0)
3427 + #set ($nbDisplayedPosts = 0)
3428 + #end
3429 + #if($mathtool.mod($nbDisplayedPosts, 2) == 0)
3430 + #if ($nbDisplayedPosts != 0)
3431 + </div>
3432 + #set ($lastHtmlTag = 'c')
3433 + #end
3434 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
3435 + <div class=~"row~">
3436 + #set ($lastHtmlTag = 'o')
3437 + #set ($lastRowClass = ~"~")
3438 + #else
3439 + <div class=~"row flex-container~">
3440 + #set ($lastHtmlTag = 'o')
3441 + #set ($lastRowClass = ~"flex~")
3442 + #end
3443 + #end
3444 + #displaySmallPost($postDoc $postObj)
3445 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
3446 + </div>
3447 + #set ($lastHtmlTag = 'c')
3448 + #end
3449 + #set ($nbDisplayedPosts = $mathtool.add($nbDisplayedPosts, 1))
3450 + #if ($postIndex == $mathtool.sub($listResultsCount, 1))
3451 + #if (~"$!lastHtmlTag~" == 'o')
3452 + #if ($mathtool.mod($nbDisplayedPosts, 2) == 1 && $lastRowClass == ~"flex~")
3453 + <div class=~"col-xs-12 col-sm-6~"></div>
3454 + #end
3455 + </div>
3456 + #end
3457 + #end
3458 + \{\{/html}}
3459 + #end
3460 + #else
3461 + \{\{error}}$services.localization.render('blog.blogpostlayout.notpost', [$xcontext.macro.params.reference])\{\{/error}}
3462 + #end
3463 + #else
3464 + \{\{error}}$services.localization.render('blog.blogpostlayout.post_view_not_allowed', [$xcontext.macro.params.reference])\{\{/error}}
3465 + #end" %)
3466 +(((
3467 +(% class="macro-placeholder hidden" %)
3468 +(((
3469 +macro:velocity
3470 +)))
3471 +
3472 +(% class="macro" data-macro="startmacro:html|-|clean=~"false~"|-|<div class=~"col-xs-12 col-sm-6 next_blog~">
3473 +<a href=~"/Nieuws/Audit%20BMI%20en%20BORG~" class=~"thumbnail~">
3474 +<div class=~"row~">
3475 +<div class=~"col-xs-4~">
3476 +<img src=~"/download/Nieuws/Audit%20BMI%20en%20BORG/giphy.gif?width=600&rev=1.1~" />
3477 +</div>
3478 +<div class=~"col-xs-8 art_det~">
3479 +<p class=~"text-left~">
3480 +Audit BMI en BORG <br/><span class=~"date_info~"> 15 jan. 2024 </span>
3481 +</p>
3482 +<div class=~"row post-details~">
3483 +<div class=~"col-xs-8 detail~">
3484 +<div class=~"post-likes btn btn-default disabled badge~"
3485 +title=~"Number of likes on this page: 0~">
3486 +<span class=~"fa fa-heart~"></span> <span class=~"like-number~">0</span>
3487 +</div>
3488 +</div>
3489 +<div class=~"col-xs-4 com_det~">
3490 +<p class=~"text-right~"><span class=~"fa fa-comments~"></span> (0)</p>
3491 +</div>
3492 +</div>
3493 +</div>
3494 +</div>
3495 +</a>
3496 +</div>" %)
3497 +(((
3498 +(% class="macro-placeholder hidden" %)
3499 +(((
3500 +macro:html
3501 +)))
3502 +
3503 +(% class="col-xs-12 col-sm-6 next_blog" %)
3504 +(((
3505 +(% class="row" %)
3506 +(((
3507 +(% class="col-xs-4" %)
3508 +(((
3509 +[[~[~[image:/download/Nieuws/Audit%20BMI%20en%20BORG/giphy.gif?width=600&rev=1.1~]~]>>path:/Nieuws/Audit%20BMI%20en%20BORG||class="thumbnail"]]
3510 +)))
3511 +
3512 +(% class="col-xs-8 art_det" %)
3513 +(((
3514 +(% class="text-left" %)
3515 +[[Audit BMI en BORG
3516 +(% class="date_info" %) 15 jan. 2024>>path:/Nieuws/Audit%20BMI%20en%20BORG||class="thumbnail"]]
3517 +
3518 +(% class="row post-details" %)
3519 +(((
3520 +(% class="col-xs-8 detail" %)
3521 +(((
3522 +(% class="post-likes btn btn-default disabled badge" title="Number of likes on this page: 0" %)
3523 +(((
3524 +[[(% class="like-number" %)0>>path:/Nieuws/Audit%20BMI%20en%20BORG||class="thumbnail"]]
3525 +)))
3526 +)))
3527 +
3528 +(% class="col-xs-4 com_det" %)
3529 +(((
3530 +(% class="text-right" %)
3531 +[[(0)>>path:/Nieuws/Audit%20BMI%20en%20BORG||class="thumbnail"]]
3532 +)))
3533 +)))
3534 +)))
3535 +)))
3536 +)))
3537 +)))
3538 +)))
3539 +)))
3540 +
3541 +(% class="macro" data-macro="startmacro:blogPostLayoutCards|-|reference=~"Nieuws.Nieuwsbrief december 2023~" params=~"displayTitle=true|useSummary=true|list-limit=6|list-layout=cards|list-blog=Nieuws.WebHome|list-paginated=no|list-results-count=6|postIndex=0|previousPostReference=|postIndex=1|previousPostReference=Nieuws.Nieuwsbrief januari 2024|postIndex=2|previousPostReference=Nieuws.Audit BMI en BORG~"" %)
3542 +(((
3543 +(% class="macro-placeholder hidden" %)
3544 +(((
3545 +macro:blogPostLayoutCards
3546 +)))
3547 +
3548 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogCode~"" %)
3549 +(((
3550 +(% class="macro-placeholder hidden" %)
3551 +(((
3552 +macro:include
3553 +)))
3554 +
3555 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogParameters~"" %)
3556 +(((
3557 +(% class="macro-placeholder hidden" %)
3558 +(((
3559 +macro:include
3560 +)))
3561 +
3562 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|## Blog
3563 +#set($blogClassname = 'Blog.BlogClass')
3564 +#set($blogTemplate = 'Blog.BlogTemplate')
3565 +#set($blogSheet = 'Blog.BlogSheet')
3566 +## Blog entries
3567 +#set($blogPostClassname = 'Blog.BlogPostClass')
3568 +#set($blogPostTemplate = 'Blog.BlogPostTemplate')
3569 +#set($blogPostSheet = 'Blog.BlogPostSheet')
3570 +#set($blogPostObjectNumber = $xwiki.getDocument($blogPostTemplate).getObject($blogPostClassname).number)
3571 +#set($oldArticleClassname = 'XWiki.ArticleClass')
3572 +## Categories
3573 +#set($blogCategoryClassname = 'Blog.CategoryClass')
3574 +#set($blogCategoryTemplate = 'Blog.CategoryTemplate')
3575 +#set($blogCategorySheet = 'Blog.CategorySheet')
3576 +#set($blogCategoriesSheet = 'Blog.CategoriesSheet')
3577 +#set($oldBlogCategoryClassname = 'Blog.Categories')
3578 +#set($defaultCategoryParent = 'Blog.Categories')
3579 +## Style
3580 +#set($blogStyleDocumentName = 'Blog.BlogStyle')
3581 +#set($blogStyleDocument = $xwiki.getDocument($blogStyleDocumentName))
3582 +## Clientside scripts
3583 +#set($blogScriptsDocumentName = 'Blog.BlogScripts')
3584 +#set($blogPublisher = $xwiki.getDocument('Blog.Publisher'))
3585 +## Misc
3586 +#set($thisURL = $doc.getURL($xcontext.action, $request.queryString))
3587 +#set($isBlogPost = $doc.getObject($blogPostClassname))
3588 +#set($defaultBlogSpace = 'Blog')
3589 +#set($isCategoryPage = $doc.getObject($blogCategoryClassname))
3590 +#set($isCategoriesHomePage = $doc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
3591 +##
3592 +##
3593 +##
3594 +#**
3595 + * Displays an image, taken from the blog style document.
3596 + *
3597 + * @param $imgName The name of the icon from icons set to use.
3598 + *#
3599 +#macro(toolImage $imgName)(% class=~"icon-manage~"~%)$services.icon.render($imgName)(%~%)#end" %)
3600 +(((
3601 +(% class="macro-placeholder hidden" %)
3602 +(((
3603 +macro:velocity
3604 +)))
3605 +)))
3606 +)))
3607 +
3608 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|##
3609 +##
3610 +##
3611 +## Import the blog skin and javascripts.
3612 +$!xwiki.ssx.use($blogStyleDocumentName)##
3613 +$!xwiki.jsx.use($blogScriptsDocumentName)##
3614 +##
3615 +## import the hierarchy for the path the blog post footer (in displayEntryBlogLocation)
3616 +#template('hierarchy_macros.vm')##
3617 +##
3618 +##
3619 +#**
3620 + * Prints a blog. This is the main macro used in the BlogSheet.
3621 + *
3622 + * @param blogDoc the XDocument holding the blog definition object.
3623 + *###
3624 +#macro(printBlog $blogDoc)
3625 + \{\{include reference='Blog.CreatePost'/}}
3626 +
3627 + ## Use the blogPostList macro to display the blogposts
3628 + ## The blogPostList is used only in case of 'all' or 'paged' blog display type because the blogPostList macro
3629 + ## do not support FTM the monthly and weekly blog display types
3630 + #getBlogDisplayType($blogDoc $displayType)
3631 + #if ($displayType == 'weekly' || $displayType == 'monthly')
3632 + #getBlogEntries($blogDoc $entries)
3633 + #displayBlog($entries 'index' true true)
3634 + #displayNavigationLinks($blogDoc)
3635 + #else
3636 + #getBlogDisplayType($blogDoc $displayType)
3637 + #set ($paginated = 'no')
3638 + #if ($displayType == 'paginated')
3639 + #set ($paginated = 'yes')
3640 + #end
3641 + #getBlogPostsLayout($blogDoc $postsLayout)
3642 + (% class=~"hfeed index~" ~%)(((\{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$paginated~" layout=~"$!postsLayout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" /}})))
3643 + #end
3644 +#end
3645 +##
3646 +##
3647 +##
3648 +#**
3649 + * Shows blog information. In view mode, the description is printed. In edit mode, allows changing blog settings: title,
3650 + * description, blog type (global or in-space), index display type (fixed size pagination, weekly index, monthly index,
3651 + * all entries).
3652 + *
3653 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
3654 + *###
3655 +#macro(showBlogInfo $blogDoc)
3656 + #if($blogDoc.getObject($blogClassname))
3657 + ## Keep testing for inline action for backward compatibility with older blogs.
3658 + #if($xcontext.action == 'edit' || $xcontext.action == 'inline')
3659 + #macro(displayProperty $blogDoc $propname)
3660 + ; #displayPropName($xwiki.getClass($blogClassname).get($propname)):
3661 + : $blogDoc.display($propname)
3662 + #end
3663 + #displayProperty($blogDoc 'title')
3664 + #displayProperty($blogDoc 'description')
3665 + #displayProperty($blogDoc 'displayType')
3666 + #displayProperty($blogDoc 'itemsPerPage')
3667 + #displayProperty($blogDoc 'postsLayout')
3668 + #displayProperty($blogDoc 'postsLayoutParameters')
3669 + #else
3670 + $blogDoc.display('description')
3671 + #end
3672 + #elseif($doc.fullName == $blogSheet)
3673 += $services.localization.render('blog.code.blogsheet') =
3674 + \{\{translation key='blog.code.sheetexplanation'/}}
3675 + #else
3676 + \{\{warning}}\{\{translation key='blog.code.notblog'/}}\{\{/warning}}
3677 + #end
3678 +#end
3679 +##
3680 +##
3681 +##
3682 +#**
3683 + * Retrieve the blog document, which usually is either <tt>&lt;Space&gt;.WebHome</tt> for whole-spaces blogs, or
3684 + * <tt>&lt;Space&gt;.Blog</tt> for in-space blogs. If none of these documents contains a blog object, then the first
3685 + * (alphabetically) document in the target space that contains one is returned. Finally, if no document in the current
3686 + * space contains a blog object, then <tt>Blog.WebHome</tt> is returned as the default blog.
3687 + *
3688 + * @param space A <tt>String</tt>, the name of the space where to search.
3689 + * @param blogDoc The resulting XDocument.
3690 + *###
3691 +#macro(getBlogDocument $space $blogDoc)
3692 + #set ($result = $NULL)
3693 + ## Check if the current space has a WebPreferences page that contains a Blog.EnablePanelsConfigurationClass object.
3694 + ## It is possible to display a blog's panels info in a page that is not inside a blog and in that case we need to
3695 + ## identify the right blog based on a configuration object in a WebPreferences page.
3696 + #set ($spaceReference = $services.model.resolveSpace($space))
3697 + #set ($preferencesDocRef = $services.model.createDocumentReference('WebPreferences', $spaceReference))
3698 + #set ($preferencesDoc = $xwiki.getDocument($preferencesDocRef))
3699 + #set ($preferencesObj = $preferencesDoc.getObject('Blog.EnablePanelsConfigurationClass'))
3700 + #if ($preferencesObj)
3701 + #set ($result = $xwiki.getDocument( $preferencesObj.getValue('blog')))
3702 + #end
3703 + ## If no special case occurs (like the previous one), identify a blog by checking the current location from its hierarchy.
3704 + #if (~"$!result~" == '')
3705 + ## First, try the Space.WebHome, for a whole-space blog
3706 + #set($result = $xwiki.getDocument(~"$\{space}.WebHome~"))
3707 + #if(!$result.getObject($blogClassname))
3708 + ## Second, try the Space.Blog document
3709 + #set($result = $xwiki.getDocument(~"$\{space}.Blog~"))
3710 + #if(!$result.getObject($blogClassname))
3711 + ## Third, try searching for a blog document in the current space
3712 + ## Prevent the query fail when the space contains dots '.'
3713 + #set($blogDocs = $services.query.hql(~", BaseObject obj where doc.space = :space and obj.name = doc.fullName and obj.className = '$blogClassname' order by doc.name~").setLimit(1).setOffset(0).bindValue('space', $space).execute())
3714 + #if($blogDocs.size() > 0)
3715 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
3716 + #else
3717 + ## Fourth, try searching for a blog document that have the its 'postsLocation' set to the current space
3718 + #set($blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as postsLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=postsLocationProp.id.id and postsLocationProp.id.name='postsLocation' and postsLocationProp.value=:postsLocation order by doc.name~").setLimit(1).setOffset(0).bindValue('postsLocation', $space).execute())
3719 + #if($blogDocs.size() > 0)
3720 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
3721 + #else
3722 + ## Last, fallback to Blog.WebHome, the default blog
3723 + #set($result = $xwiki.getDocument('Blog.WebHome'))
3724 + #end
3725 + #end
3726 + #end
3727 + #end
3728 + #end
3729 + #set ($blogDoc = $NULL)
3730 + #setVariable (~"$blogDoc~" $result)
3731 +#end
3732 +##
3733 +##
3734 +##
3735 +#**
3736 + * Retrieve the blog title.
3737 + *
3738 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass<tt> object with the <tt>title</tt> property set.
3739 + * @param title The resulting title.
3740 + *###
3741 +#macro(getBlogTitle $blogDoc $title)
3742 + ## Titles can contain velocity code (most commonly translations), so we should evaluate them.
3743 + #set ($title = $NULL)
3744 + #setVariable (~"$title~" $!blogDoc.displayTitle)
3745 +#end
3746 +##
3747 +##
3748 +##
3749 +#**
3750 + * Retrieve the blog description.
3751 + *
3752 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>description</tt>
3753 + * property set.
3754 + * @param description The resulting description.
3755 + *###
3756 +#macro(getBlogDescription $blogDoc $description)
3757 + #getBlogProperty($blogDoc 'description' '' $result)
3758 + #set ($description = $NULL)
3759 + #setVariable (~"$description~" $result)
3760 +#end
3761 +##
3762 +##
3763 +##
3764 +#**
3765 + * Retrieves a list of entries to be displayed. The entries are either part of the blog's space, or have the blog
3766 + * document set as a parent. The number and range of entries returned (from all those belonging to this blog) depends on
3767 + * the blog display type: paginated (fixed number of entries), weekly (all entries in a week), monthly (all entries in a
3768 + * month), or all.
3769 + *
3770 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
3771 + * @param entries The resulting list of entries to display, a list of XDocument names.
3772 + *###
3773 +#macro(getBlogEntries $blogDoc $entries)
3774 + #if (!$entries)
3775 + #setVariable (~"$entries~" [])
3776 + #end
3777 + #getAllBlogPostsQuery($query)
3778 + #isDefaultBlog($blogDoc $isDefault)
3779 + #set($queryParams = \{})
3780 + #if ($isDefault)
3781 + #getCategoryAllBlogPostsQuery($query)
3782 + #set($query = ~"$\{query} and (doc.creator = :creator or (isPublished.value = 1 and hidden.value = 0)) and (doc.space = :space or catList like :catList escape '!')~")
3783 + #set($discard = $queryParams.put('creator', $xcontext.user))
3784 + #set($discard = $queryParams.put('space', $blogDoc.space))
3785 + #set($sanitizedBlogSpace = $blogDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
3786 + #set($discard = $queryParams.put('catList', $sanitizedBlogSpace))
3787 + #else
3788 + #set($query = ~"$\{query} and (doc.space = :space or doc.parent = :parent)~")
3789 + #getBlogPostsLocation($blogDoc.space $blogPostsLocation)
3790 + #set($discard = $queryParams.put('space', $blogPostsLocation))
3791 + #set($discard = $queryParams.put('parent', $blogDoc.space))
3792 + #end
3793 + #getBlogDisplayType($blogDoc $displayType)
3794 + #if($displayType == 'weekly')
3795 + #getWeeklyBlogEntries($blogDoc $query $entries $queryParams)
3796 + #elseif($displayType == 'monthly')
3797 + #getMonthlyBlogEntries($blogDoc $query $entries $queryParams)
3798 + #elseif($displayType == 'all')
3799 + #getAllBlogEntries($blogDoc $query $entries $queryParams)
3800 + #else
3801 + #getPagedBlogEntries($blogDoc $query $entries $queryParams)
3802 + #end
3803 +#end
3804 +##
3805 +##
3806 +##
3807 +#**
3808 + * Retrieves a list of entries to be displayed. The entries are taken from a ~"page~" of the blog, a sequence of documents
3809 + * defined by the request parameters <tt>ipp</tt> (items per page) and <tt>page</tt> (the current page). Initially the
3810 + * first page is displayed, with the number of entries defined in the blog object in the <tt>itemsPerPage</tt> property
3811 + * (10 if not defined).
3812 + *
3813 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
3814 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
3815 + * refined to restrict to a given space, or to a given search criteria, etc.
3816 + * @param entries The resulting list of entries to display, a list of XDocument names.
3817 + * @param queryParams The parameters to bind with the query.
3818 + *###
3819 +#macro(getPagedBlogEntries $blogDoc $query $entries $queryParams)
3820 + #if (!$entries)
3821 + #setVariable (~"$entries~" [])
3822 + #end
3823 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
3824 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~"))
3825 + #bindQueryParameters($countQueryObj $queryParams)
3826 + #bindQueryParameters($queryObj $queryParams)
3827 + #set($totalEntries = $countQueryObj.count())
3828 + #getBlogProperty($blogDoc 'itemsPerPage' '10' $defaultItemsPerPage)
3829 + #set($defaultItemsPerPage = $numbertool.toNumber($defaultItemsPerPage).intValue())
3830 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
3831 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
3832 + #set($discard = $entries.addAll($queryObj.setLimit($itemsPerPage).setOffset($startAt).addFilter(~"unique~").execute()))
3833 +#end
3834 +##
3835 +##
3836 +##
3837 +#**
3838 + * Retrieves a list of entries to be displayed. The entries are taken from a week of the blog. The target week is
3839 + * defined by the request parameters <tt>week</tt> (the week number in the year, from 1 to 52) and <tt>year</tt> (4
3840 + * digit year). Initially the current week is displayed.
3841 + *
3842 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
3843 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
3844 + * refined to restrict to a given space, or to a given search criteria, etc.
3845 + * @param entries The resulting list of entries to display, a list of XDocument names.
3846 + * @param queryParams The parameters to bind with the query.
3847 + *###
3848 +#macro(getWeeklyBlogEntries $blogDoc $query $entries $queryParams)
3849 + #if (!$entries)
3850 + #setVariable (~"$entries~" [])
3851 + #end
3852 + #getRequestedWeek($weekDate)
3853 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
3854 + #set($minDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundFloor()))
3855 + #set($maxDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundCeiling()))
3856 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
3857 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
3858 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
3859 + #bindQueryParameters($countQueryObj $queryParams)
3860 + #bindQueryParameters($queryObj $queryParams)
3861 + #set($totalEntries = $countQueryObj.count())
3862 + #set($discard = $entries.addAll($queryObj.execute()))
3863 +#end
3864 +##
3865 +##
3866 +##
3867 +#**
3868 + * Retrieves a list of entries to be displayed. The entries are taken from a month of the blog. The target month is
3869 + * defined by the request parameters <tt>month</tt> (the month number, from 1 to 12) and <tt>year</tt> (4
3870 + * digit year). Initially the current month is displayed.
3871 + *
3872 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
3873 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
3874 + * refined to restrict to a given space, or to a given search criteria, etc.
3875 + * @param entries The resulting list of entries to display, a list of XDocument names.
3876 + * @param queryParams The parameters to bind with the query.
3877 + *###
3878 +#macro(getMonthlyBlogEntries $blogDoc $query $entries)
3879 + #if (!$entries)
3880 + #setVariable (~"$entries~" [])
3881 + #end
3882 + #getRequestedMonth($monthDate)
3883 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
3884 + #set($minDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundFloor()))
3885 + #set($maxDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundCeiling()))
3886 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
3887 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
3888 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
3889 + #bindQueryParameters($countQueryObj $queryParams)
3890 + #bindQueryParameters($queryObj $queryParams)
3891 + #set($totalEntries = $countQueryObj.count())
3892 + #set($discard = $entries.addAll($queryObj.execute()))
3893 +#end
3894 +##
3895 +##
3896 +##
3897 +#**
3898 + * Retrieves a list of entries to be displayed. All entries belonging to the current blog are returned.
3899 + *
3900 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
3901 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
3902 + * refined to restrict to a given space, or to a given search criteria, etc.
3903 + * @param entries The resulting list of entries to display, a list of XDocument names.
3904 + * @param queryParams The parameters to bind with the query.
3905 + *###
3906 +#macro(getAllBlogEntries $blogDoc $query $entries $queryParams)
3907 + #if (!$entries)
3908 + #setVariable (~"$entries~" [])
3909 + #end
3910 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
3911 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
3912 + #bindQueryParameters($countQueryObj $queryParams)
3913 + #bindQueryParameters($queryObj $queryParams)
3914 + #set($totalEntries = $countQueryObj.count())
3915 + #set($discard = $entries.addAll($queryObj.execute()))
3916 +#end
3917 +##
3918 +##
3919 +##
3920 +#**
3921 + * Retrieves a list of entries to be displayed. Only (and all) unpublished entries are returned.
3922 + *
3923 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
3924 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
3925 + * refined to restrict to a given space, or to a given search criteria, etc.
3926 + * @param queryParams The parameters to bind with the query.
3927 + * @param entries The resulting list of entries to display, a list of XDocument names.
3928 + *###
3929 +#macro(getUnpublishedBlogEntries $blogDoc $query $queryParams $entries)
3930 + #if (!$entries)
3931 + #setVariable (~"$entries~" [])
3932 + #end
3933 + #set($query = ~"$\{query} and isPublished.value = 0~")
3934 + #set ($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
3935 + #set ($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
3936 + #bindQueryParameters($countQueryObj $queryParams)
3937 + #bindQueryParameters($queryObj $queryParams)
3938 + #set($totalEntries = $countQueryObj.count())
3939 + #set($discard = $entries.addAll($queryObj.execute()))
3940 +#end
3941 +##
3942 +##
3943 +##
3944 +#**
3945 + * Retrieves a list of entries to be displayed. The entries are taken from all the wiki, and not from a specific blog.
3946 + *
3947 + * @param entries The resulting list of entries to display, a list of XDocument names.
3948 + *###
3949 +#macro(getGlobalBlogEntries $entries)
3950 + #if (!$entries)
3951 + #setVariable (~"$entries~" [])
3952 + #end
3953 + #getAllBlogPostsQuery($query)
3954 + #set($totalEntries = $services.query.hql($query).count())
3955 + #set($defaultItemsPerPage = 20)
3956 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
3957 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
3958 + #set($discard = $entries.addAll($services.query.hql(~"$\{query} order by publishDate.value desc~").setLimit($itemsPerPage).setOffset($startAt).execute()))
3959 +#end
3960 +#**
3961 + * Return the base query for selecting blog entries. It filters only visible entries, but does not bind to a specific
3962 + * blog, nor specify a range or an ordering criteria.
3963 + *
3964 + * This macro is a duplicate of #getAllBlogPostsQuery($query). Keep it in case it's used outside, in custom code.
3965 + *
3966 + * @param query The basic query for selecting blog entries.
3967 + *#
3968 +#macro(getBlogEntriesBaseQuery $query)
3969 + #getAllBlogPostsQuery($query)
3970 +#end
3971 +#**
3972 + * Return the Query for selecting the all wiki blog posts without filtering
3973 + *
3974 + * @param query The basic query for selecting blog entries.
3975 + *#
3976 +#macro(getAllBlogPostsQuery $query)
3977 + #set ($query = $NULL)
3978 + #setVariable(~"$query~" ~", BaseObject as obj, IntegerProperty isPublished,
3979 + IntegerProperty hidden, DateProperty publishDate
3980 + where doc.fullName <> '$blogPostTemplate' and
3981 + obj.name=doc.fullName and obj.className='$blogPostClassname' and
3982 + isPublished.id.id = obj.id and isPublished.id.name = 'published' and
3983 + hidden.id.id = obj.id and hidden.id.name='hidden' and
3984 + publishDate.id.id = obj.id and publishDate.id.name='publishDate' and
3985 + (doc.creator = '$escapetool.sql($xcontext.user)' or (isPublished.value = 1 and hidden.value = 0))~")
3986 +#end
3987 +##
3988 +##
3989 +##
3990 +###**
3991 + * Return the Query for selecting the all wiki blog posts with categories filtering
3992 + *
3993 + * @param query The basic query for selecting blog entries.
3994 + *###
3995 +#macro(getCategoryAllBlogPostsQuery $query)
3996 + #set ($query = $NULL)
3997 + #getAllBlogPostsQuery($baseQuery)
3998 + #set ($baseQuery = $baseQuery.replace('DateProperty publishDate', 'DateProperty publishDate, DBStringListProperty as category left join category.list catList'))
3999 + #setVariable(~"$query~" ~"$\{baseQuery} and obj.id=category.id.id and category.id.name='category'~")
4000 +#end
4001 +##
4002 +##
4003 +##
4004 +#**
4005 + * Determines how is the blog index split into pages: paginated (fixed number of entries), weekly (all entries in a
4006 + * week), monthly (all entries in a month), or all.
4007 + *
4008 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>displayType</tt>
4009 + * property set.
4010 + * @param displayType The resulting string. If the blog object does not define anything, it is considered paginated.
4011 + *###
4012 +#macro(getBlogDisplayType $blogDoc $displayType)
4013 + #getBlogProperty($blogDoc 'displayType' 'paginated' $result)
4014 + #set ($displayType = $NULL)
4015 + #setVariable (~"$displayType~" $result)
4016 +#end
4017 +##
4018 +##
4019 +##
4020 +#**
4021 + * Displays a list of entries.
4022 + *
4023 + * @param entries The entries to display, a list of XDocument names.
4024 + * @param displaying What exactly is displayed: blog index, a single blog entry, a blog category, search results,
4025 + * unpublished entries, etc. This will be used as the classname(s) for the container div (hfeed). Currently
4026 + * used values: index, single, category, search, unpublished, hidden.
4027 + * @param onlyExtract If <tt>true</tt>, only display the extract of articles where available, otherwise display the full content.
4028 + * @param shouldDisplayTitles If <tt>true</tt>, display the blog title (blog posts shouldn't display the title when they're
4029 + * displayed alone on their page since it's the page title which is used in this case)
4030 + *###
4031 +#macro(displayBlog $entries $displaying $onlyExtract $shouldDisplayTitles)
4032 + #set($blogDay = '')
4033 + (% class=~"hfeed $!\{displaying}~" ~%)(((
4034 + (% class=~"blogDay~" ~%)(((
4035 + #foreach ($entryDoc in $xwiki.wrapDocs($entries))
4036 + #getEntryObject($entryDoc $entryObj)
4037 + ## Although all entries should have one of the two objects, better check to be sure.
4038 + #if(~"$!\{entryObj}~" != '')
4039 + #getEntryDate($entryDoc $entryObj $entryDate)
4040 + ## Display a ~"calendar sheet~" for each day. All entries posted on the same day share one such sheet.
4041 + #set($entryDateStr = $xwiki.formatDate($entryDate, 'yyyyMMMMdd'))
4042 + #if($blogDay != $entryDateStr)
4043 + #if($blogDay != '')
4044 + )))
4045 + (% class=~"blogDay~" ~%)(((
4046 + #end
4047 + #displayBlogDate($entryDate)
4048 + #set ($blogDay = $entryDateStr)
4049 + #end
4050 + ## Finally, display the entry.
4051 + #displayEntry($entryDoc $entryObj $onlyExtract $shouldDisplayTitles true)
4052 + #end
4053 + #end
4054 + )))## blogDay
4055 + )))## hfeed
4056 +#end
4057 +##
4058 +##
4059 +##
4060 +#**
4061 + * Get the entry object, either a new BlogPost or an old Article.
4062 + *
4063 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4064 + * @param entryObj The resulting xobject of the blog post.
4065 + *###
4066 +#macro(getEntryObject $entryDoc $__entryObj)
4067 + #set($result = $entryDoc.getObject(~"$\{blogPostClassname}~"))
4068 + #if(!$result)
4069 + #set($result = $entryDoc.getObject(~"$\{oldArticleClassname}~"))
4070 + #end
4071 + ## NOTE: The reason we put an underscore in front of the variable name is to prevent the following line from
4072 + ## overwriting the $entryObj variable that may be defined before this macro is called. Of course, $__entryObj may be
4073 + ## overwritten in this case but it's less likely to have such a variable defined before.
4074 + #set ($__entryObj = $NULL)
4075 + #setVariable (~"$__entryObj~" $result)
4076 +#end
4077 +##
4078 +##
4079 +##
4080 +#**
4081 + * Gets the date associated with a blog entry. This is the publication date. For unpublished entries, initially this is
4082 + * the document creation date, but can be edited by the user.
4083 + *
4084 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4085 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4086 + * @param result The resulting date, an instance of <tt>java.util.Date</tt>.
4087 + *###
4088 +#macro(getEntryDate $entryDoc $entryObj $result)
4089 + #set ($result = $NULL)
4090 + #setVariable (~"$result~" $entryObj.getProperty('publishDate').value)
4091 +#end
4092 +##
4093 +##
4094 +##
4095 +#**
4096 + * Displays a date, nicely formatted as a calendar page.
4097 + *
4098 + * @param date The date to display, an instance of <tt>java.util.Date</tt>.
4099 + *###
4100 +#macro(displayBlogDate $date)
4101 + #set($year = $xwiki.formatDate($date, 'yyyy'))
4102 + ## 3 letter month name, like Jan, Dec.
4103 + #set($month = $xwiki.formatDate($date, 'MMM'))
4104 + ## Uncomment to get a full length month name, like January, December.
4105 + ## TODO: this could be defined somewhere in the blog style.
4106 + ## #set($month = $xwiki.formatDate($date, 'MMMM'))
4107 + #set($day = $xwiki.formatDate($date, 'dd'))
4108 + (% class=~"blogdate~" ~%)
4109 + == (% class=~"month~" ~%)$month(%~%) (% class=~"day~" ~%)$day(%~%) (% class=~"year~" ~%)$year(%~%) ==
4110 +#end
4111 +##
4112 +##
4113 +##
4114 +#**
4115 + * Displays a blog article: management tools, header, content, footer.
4116 + *
4117 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4118 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4119 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
4120 + * @param shouldDisplayTitle If <tt>true</tt>, display the blog title (blog posts shouldn't display the title
4121 + * when they're displayed alone on their page since it's the page title which is used in this case)
4122 + * @param shouldDisplayActions If <tt>true</tt>, display the blog post actions buttons
4123 + *###
4124 +#macro(displayEntry $entryDoc $entryObj $onlyExtract $shouldDisplayTitle $shouldDisplayActions)
4125 + ## Only articles with an explicit hidden setting or an explicit unpublished setting are hidden
4126 + #isPublished($entryObj $isPublished)
4127 + #isHidden($entryObj $isHidden)
4128 + #if($doc.fullName == $entryDoc.fullName)
4129 + (% class=~"hentry single-article~" ~%)(((
4130 + #else
4131 + (% class=~"hentry#if(!$isPublished) unpublished-article#elseif($isHidden) hidden-article#end~" ~%)(((
4132 + #end
4133 + #if ($shouldDisplayActions)
4134 + #displayEntryTools($entryDoc $entryObj)
4135 + #end
4136 + #if($shouldDisplayTitle)
4137 + #displayEntryTitle($entryDoc $entryObj)
4138 + #end
4139 + #if($doc.fullName == $entryDoc.fullName)
4140 + #if(!$isPublished)
4141 + \{\{warning}}\{\{translation key='blog.code.published'/}}\{\{/warning}}
4142 + #elseif($isHidden)
4143 + \{\{warning}}\{\{translation key='blog.code.hidden'/}}\{\{/warning}}
4144 + #end
4145 + #end
4146 + #displayEntryContent($entryDoc $entryObj $onlyExtract)
4147 + #displayEntryFooter($entryDoc $entryObj)
4148 + )))## hentry
4149 +#end
4150 +##
4151 +##
4152 +##
4153 +#**
4154 + * Checks if the provided blog is published or not.
4155 + *
4156 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4157 + * @param isPublished The resulting boolean, true if the entry is considered published.
4158 + *###
4159 +#macro(isPublished $entryObj $isPublished)
4160 + #set ($isPublished = $NULL)
4161 + ## This should work for both old articles, which don't have the 'published' property at all, and
4162 + ## are considered published by default, and new entries, that should have 1 if published.
4163 + #if (~"$!\{entryObj.getProperty('published').value}~" != '0')
4164 + #setVariable (~"$isPublished~" true)
4165 + #else
4166 + #setVariable (~"$isPublished~" false)
4167 + #end
4168 +#end
4169 +##
4170 +##
4171 +##
4172 +#**
4173 + * Checks if the provided blog is hidden or not.
4174 + *
4175 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass<tt> xclass.
4176 + * @param isHiddel The resulting boolean, true if the entry is considered hidden.
4177 + *###
4178 +#macro(isHidden $entryObj $isHidden)
4179 + #set ($isHidden = $NULL)
4180 + ## This should work for both old articles, which don't have the 'hidden' property at all, and
4181 + ## are considered visible by default, and new entries, that should have 1 if hidden.
4182 + #if (~"$!\{entryObj.getProperty('hidden').value}~" == '1')
4183 + #setVariable (~"$isHidden~" true)
4184 + #else
4185 + #setVariable (~"$isHidden~" false)
4186 + #end
4187 +#end
4188 +##
4189 +##
4190 +##
4191 +#**
4192 + * Displays several ~"tools~" for manipulating blog posts: hide/show, publish, edit.
4193 + *
4194 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4195 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4196 + *###
4197 +#macro(displayEntryTools $entryDoc $entryObj)
4198 + #if($xcontext.action == 'view')
4199 + (% class=~"blog-entry-toolbox~" ~%)(((
4200 + #displayPublishButton($entryDoc $entryObj)
4201 + #displayHideShowButton($entryDoc $entryObj)
4202 + #displayEditButton($entryDoc $entryObj)
4203 + #displayDeleteButton($entryDoc $entryObj)
4204 + )))
4205 + #end
4206 +#end
4207 +##
4208 +##
4209 +##
4210 +#**
4211 + * Displays the publish button to the entry <strong>creator</strong>, if the article is not published yet.
4212 + *
4213 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4214 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4215 + * @todo AJAX calls.
4216 + *###
4217 +#macro(displayPublishButton $entryDoc $entryObj)
4218 + #isPublished($entryObj $isPublished)
4219 + #if(!$isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
4220 + [[#toolImage('world')>>path:$blogPublisher.getURL('view', ~"entryName=$\{escapetool.url($entryDoc.fullName)}&xredirect=$\{escapetool.url($thisURL)}&form_token=$!\{services.csrf.getToken()}~")||title=~"$services.localization.render('blog.code.notpublished')~"]]##
4221 + #end
4222 +#end
4223 +##
4224 +##
4225 +##
4226 +#**
4227 + * Displays the hide or show button to the entry <strong>creator</strong>, if the article is already published.
4228 + *
4229 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4230 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4231 + *###
4232 +#macro(displayHideShowButton $entryDoc $entryObj)
4233 + #isPublished($entryObj $isPublished)
4234 + #isHidden($entryObj $isHidden)
4235 + ## Only published articles can be hidden. Unpublished articles are considered already hidden.
4236 + #if($isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
4237 + #set ($queryString = \{
4238 + 'xredirect' : $thisURL,
4239 + 'form_token' : $services.csrf.getToken()
4240 + })
4241 + #if ($isHidden)
4242 + #set ($discard = $queryString.putAll(\{
4243 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 0,
4244 + 'comment' : $services.localization.render('blog.code.madevisible')
4245 + }))
4246 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
4247 + [[#toolImage('unlock')>>path:$lockURL||class=~"blog-tool-show~" title=~"$services.localization.render('blog.code.makevisible')~"]]##
4248 + #else
4249 + #set ($discard = $queryString.putAll(\{
4250 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 1,
4251 + 'comment' : $services.localization.render('blog.code.hid')
4252 + }))
4253 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
4254 + [[#toolImage('lock')>>path:$lockURL||class=~"blog-tool-hide~" title=~"$services.localization.render('blog.code.hide')~"]]##
4255 + #end
4256 + #end
4257 +#end
4258 +##
4259 +##
4260 +##
4261 +#**
4262 + * Displays the edit button to those that can edit the article.
4263 + *
4264 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4265 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4266 + *###
4267 +#macro(displayEditButton $entryDoc $entryObj)
4268 + #if($xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
4269 + ## Call getDefaultEditMode() for backward compatibility with older blog posts.
4270 + [[#toolImage('pencil')>>path:$entryDoc.getURL('edit')||title=~"$services.localization.render('blog.code.editpost')~"]]##
4271 + #end
4272 +#end
4273 +##
4274 +##
4275 +##
4276 +#**
4277 + * Displays the delete button to those that can edit the article.
4278 + *
4279 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4280 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4281 + * @todo AJAX calls.
4282 + *###
4283 +#macro(displayDeleteButton $entryDoc $entryObj)
4284 + #if($xwiki.hasAccessLevel('delete', $xcontext.user, $entryDoc.fullName))
4285 + [[#toolImage('cross')>>path:$entryDoc.getURL('delete')||title=~"$services.localization.render('blog.code.deletepost')~"]]##
4286 + #end
4287 +#end
4288 +##
4289 +##
4290 +##
4291 +#**
4292 + * Displays the title of the entry.
4293 + *
4294 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4295 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4296 + *###
4297 +#macro(displayEntryTitle $entryDoc $entryObj)
4298 + #if($doc.fullName == $entryDoc.fullName)
4299 + (% class=~"entry-title~" ~%)
4300 + = $services.rendering.escape($entryDoc.display('title', 'view', $entryObj), $xwiki.getCurrentContentSyntaxId()) =
4301 + #else
4302 + (% class=~"entry-title~" ~%)
4303 + === [[$services.rendering.escape($entryDoc.display('title', 'view', $entryObj),$xwiki.getCurrentContentSyntaxId())>>doc:$services.rendering.escape($services.model.serialize($entryDoc.getDocumentReference(),'default'),$xwiki.getCurrentContentSyntaxId())]] ===
4304 + #end
4305 +#end
4306 +##
4307 +##
4308 +##
4309 +#**
4310 + * Displays the body of the entry.
4311 + *
4312 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4313 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4314 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
4315 + *###
4316 +#macro(displayEntryContent $entryDoc $entryObj $onlyExtract)
4317 + (% class=~"#if($onlyExtract)entry-summary#\{else}entry-content#end~" ~%)(((
4318 + #getEntryContent($entryDoc $entryObj $onlyExtract $entryContent)
4319 + ## FIXME: This causes the blog's content to not be annotatable. See http://jira.xwiki.org/browse/XWIKI-6328
4320 + ## Should probably be replaced by a display macro call with a reference to the object property holding the post's content
4321 + \{\{html wiki=~"false~"}}$entryDoc.getRenderedContent($entryContent, $entryDoc.syntax.toIdString())\{\{/html}}
4322 + ))) ## entry-content
4323 + (% class=~"clearfloats~" ~%)((()))
4324 +#end
4325 +##
4326 +##
4327 +##
4328 +#**
4329 + * Extracts the body of the entry that should be displayed. If <tt>onlyExtract</tt> is <tt>true</tt>, display the content
4330 + * of the <tt>extract</tt> field (if not empty).
4331 + *
4332 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4333 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4334 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
4335 + * @param entryContent The resulting content.
4336 + * @param removeEllipsis If <tt>true</tt>, then don't display an ellipsis at the end of the content (only used when
4337 + * <tt>onlyExtract</tt> is <tt>true</tt>)
4338 + *###
4339 +#macro(getEntryContent $entryDoc $entryObj $onlyExtract $entryContent $removeEllipsis)
4340 + #if ($onlyExtract)
4341 + ## Note: We trim the summary so that if there's some white space it won't cause the summary to be used instead
4342 + ## of the content.
4343 + #set ($macro.result = $entryObj.getProperty('extract').value.trim())
4344 + #end
4345 + #if(~"$!macro.result~" == '')
4346 + #set($macro.result = $entryObj.getProperty('content').value)
4347 +#* Disabled until the content can be cleanly cut.
4348 +* #if($onlyExtract && $result.length()>$maxchars)
4349 +* #set($i = $macro.result.lastIndexOf(~" ~", $maxchars))
4350 +* #set($i = $i + 1)
4351 +* #set($macro.result = ~"$\{macro.result.substring(0,$i)} *[...>$\{entryDoc.fullName}]*~")
4352 +* #end
4353 +## *###
4354 + #elseif (!$removeEllipsis)
4355 + #if($entryDoc.syntax.toIdString() == 'xwiki/1.0')
4356 + #set($macro.result = ~"$\{macro.result} <a href='$\{entryDoc.getExternalURL()}' title='$services.localization.render('blog.code.readpost')'>...</a>~")
4357 + #elseif($entryDoc.syntax.toIdString() == 'xwiki/2.0' || $entryDoc.syntax.toIdString() == 'xwiki/2.1')
4358 + #set($macro.result = ~"$\{macro.result} [[...>>$\{services.rendering.escape($entryDoc.getFullName(), $entryDoc.getSyntax())}||title='$services.localization.render('blog.code.readpost')']]~")
4359 + #end
4360 + #end
4361 + #set ($entryContent = $NULL)
4362 + #setVariable (~"$entryContent~" $macro.result)
4363 +#end
4364 +##
4365 +##
4366 +##
4367 +#**
4368 + * Displays the footer of the entry.
4369 + *
4370 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4371 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4372 + *###
4373 +#macro(displayEntryFooter $entryDoc $entryObj)
4374 + (% class=~"entry-footer~" ~%)(((
4375 + #isPublished($entryObj $isPublished)
4376 + (% class='entry-author-label' ~%)
4377 + #if($isPublished)
4378 + \{\{translation key='blog.code.postedby'/}} ##
4379 + #else
4380 + \{\{translation key='blog.code.createdby'/}} ##
4381 + #end
4382 + \{\{html wiki=~"false~" clean=~"false~"}}<span class='author vcard'>#userfn($entryDoc.creator)</span>\{\{/html}} ##
4383 + #getEntryDate($entryDoc $entryObj $entryDate)
4384 + #listCategories($entryObj) #*
4385 + ## Since the publish date and update date are not set at the exact same time, there could be a small difference that
4386 + ## we assume cannot be more than 3 seconds.
4387 + *#(% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.permalink'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||rel=~"bookmark~"]] ##
4388 + #if ($showcomments)
4389 + (% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.comments'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||anchor=~"Comments~"]] (% class=~"itemCount~" ~%)($entryDoc.comments.size())(%~%) ##
4390 + #end ##
4391 + #if($entryDoc != $doc) ##
4392 + #displayEntryBlogLocation($entryDoc $entryObj) ##
4393 + #end
4394 + )))## entry-footer
4395 +#end
4396 +##
4397 +##
4398 +#**
4399 + * Display the blog for the entry (if it is not the currently displayed blog)
4400 + *
4401 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
4402 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4403 + *###
4404 +#macro(displayEntryBlogLocation $entryDoc $entryObj)
4405 + #getBlogPostsLocation($entryDoc.getSpace() $blogPostsLocation) ##
4406 + #if(~"$!blogPostsLocation~" != ~"~") ##
4407 + #set($blogSpaceRef = $services.model.resolveSpace($blogPostsLocation)) ##
4408 + #set($blogDocRef = $services.model.createDocumentReference($services.model.getEntityReference('DOCUMENT', 'default').getName(), $blogSpaceRef)) ##
4409 + #if($doc.documentReference != $blogDocRef) ##
4410 + #set($blogDoc = $xwiki.getDocument($blogDocRef)) ##
4411 + #set($blogObj = $blogDoc.getObject('Blog.BlogClass')) ##
4412 + #if($blogObj) (% class=~"blogrefpath~" ~%)((( ##
4413 + $services.localization.render('blog.code.postedin') \{\{html clean=~"false~" wiki=~"false~"}} #hierarchy($blogDocRef, \{'selfIsActive' : true, 'local': true}) \{\{/html}} ##
4414 + )))(%~%)##
4415 + #end
4416 + #end
4417 + #end
4418 +#end
4419 +##
4420 +##
4421 +##
4422 +##
4423 +#**
4424 + * List the categories an entry belongs to. Used in the footer. The categories are instances of <tt>Blog.CategoryClass</tt>.
4425 + *
4426 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
4427 + *###
4428 +#macro(listCategories $entryObj)
4429 + #if($entryObj.getxWikiClass().getName() == $blogPostClassname)
4430 + #set($categories = $entryObj.getProperty('category').value)
4431 + #set($first = true)
4432 + #if($categories.size() > 0)
4433 + #foreach($category in $categories)
4434 + #set($categoryDoc = $!xwiki.getDocument($category))
4435 + #if(!$categoryDoc.isNew() && $categoryDoc.getObject($\{blogCategoryClassname}))
4436 + #if($foreach.count == 1)
4437 + (% class='separator' ~%)·(%~%) $services.localization.render('blog.code.categories') ##
4438 + #else
4439 + , ##
4440 + #end##
4441 + [[$!\{categoryDoc.getObject($blogCategoryClassname).getValue('name')}>>$\{category}||rel='tag']]##
4442 + #end##
4443 + #end##
4444 + #end
4445 + #end
4446 +#end
4447 +##
4448 +##
4449 +##
4450 +#**
4451 + * Displays blog pagination links (older and newer entries).
4452 + *
4453 + * @param blogDoc the XDocument holding the blog definition object.
4454 + *###
4455 +#macro(displayNavigationLinks $blogDoc)
4456 + (% class=~"clearfloats~" ~%)((()))
4457 + #getBlogDisplayType($blogDoc $displayType)
4458 + #if($displayType == 'weekly')
4459 + (% class=~"pagingLinks~" ~%)(((
4460 + #getRequestedWeek($weekDate)
4461 + $weekDate.addWeeks(-1)##
4462 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousweek'/}}>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
4463 + #sep()
4464 + $weekDate.addWeeks(2)## 2 because we already subtracted 1 above
4465 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextweek'/}} »>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
4466 + )))
4467 + #elseif($displayType == 'monthly')
4468 + (% class=~"pagingLinks~" ~%)(((
4469 + #getRequestedMonth($monthDate)
4470 + $monthDate.addMonths(-1)##
4471 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousmonth'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
4472 + #sep()
4473 + $monthDate.addMonths(2)## 2 because we already subtracted 1 above
4474 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextmonth'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
4475 + )))
4476 + #elseif($displayType == 'all')
4477 + #else
4478 + ## Paginated
4479 + #if(($totalPages > 1))
4480 + #set($queryString = '')
4481 + #foreach($p in $request.getParameterNames())
4482 + #if($p != 'page' && $p != 'ipp')
4483 + #foreach($v in $request.getParameterValues($p))
4484 + #set($queryString = ~"$\{queryString}&$\{escapetool.url($p)}=$\{escapetool.url($v)}~")
4485 + #end
4486 + #end
4487 + #end
4488 + (% class=~"pagingLinks~" ~%)(((
4489 + #if ($currentPageNumber < $totalPages)
4490 + #set($currentPageNumber = $currentPageNumber + 1)
4491 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.olderposts'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
4492 + #set($currentPageNumber = $currentPageNumber - 1)
4493 + #end
4494 + #if ($currentPageNumber > 1)
4495 + #if ($currentPageNumber < $totalPages)
4496 + #sep()
4497 + #end
4498 + #set($currentPageNumber = $currentPageNumber - 1)
4499 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.newerposts'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
4500 + #set($currentPageNumber = $currentPageNumber + 1)
4501 + #end
4502 + (% class=~"clear~" ~%)(%~%)
4503 + )))## pagingLinks
4504 + #end
4505 + #end
4506 +#end
4507 +##
4508 +##
4509 +##
4510 +#**
4511 + * Displays a message box with ~"publish~" icon.
4512 + *
4513 + * @param message A text message concerning blog article publishing
4514 + *###
4515 +#macro(publishMessageBox $message)
4516 +(% class=~"plainmessage publish-message~" ~%)((($services.icon.render('world') $message)))
4517 +#end
4518 +#**
4519 + * Displays a message box with ~"show/hide~" icon.
4520 + *
4521 + * @param message A text message concerning blog article hiding
4522 + *###
4523 +#macro(hideMessageBox $message)
4524 +(% class=~"plainmessage hide-message~" ~%)((($services.icon.render('unlock') $message)))
4525 +#end
4526 +##
4527 +##
4528 +##
4529 +#**
4530 + * Determine the requested week, for using in a weekly-indexed blog. The relevant request parameters are
4531 + * <tt>year</tt> and <tt>week</tt>. By default, the current week is used.
4532 + *
4533 + * @param monthDate The resulting week, a JODATime MutableDateTime.
4534 + *###
4535 +#macro(getRequestedWeek $weekDate)
4536 + #set ($weekDate = $NULL)
4537 + #setVariable (~"$weekDate~" $xwiki.jodatime.mutableDateTime)
4538 + #if(~"$!\{request.year}~" != '')
4539 + #set ($discard = $weekDate.setYear($numbertool.toNumber($request.year).intValue()))
4540 + #end
4541 + #if(~"$!\{request.week}~" != '')
4542 + #set ($discard = $weekDate.setWeekOfWeekyear($numbertool.toNumber($request.week).intValue()))
4543 + #end
4544 +#end
4545 +##
4546 +##
4547 +##
4548 +#**
4549 + * Determine the requested month, for using in a monthly-indexed blog. The relevant request parameters are
4550 + * <tt>year</tt> and <tt>month</tt>. By default, the current month is used.
4551 + *
4552 + * @param monthDate The resulting month, a JODATime MutableDateTime.
4553 + *###
4554 +#macro(getRequestedMonth $monthDate)
4555 + #set ($monthDate = $NULL)
4556 + #setVariable (~"$monthDate~" $xwiki.jodatime.mutableDateTime)
4557 + #if(~"$!\{request.year}~" != '')
4558 + #set ($discard = $monthDate.setYear($numbertool.toNumber($request.year).intValue()))
4559 + #end
4560 + #if(~"$!\{request.month}~" != '')
4561 + #set ($discard = $monthDate.setMonthOfYear($numbertool.toNumber($request.month).intValue()))
4562 + #end
4563 +#end
4564 +##
4565 +##
4566 +##
4567 +#**
4568 + * Retrieve a blog property (title, display type, etc).
4569 + *
4570 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
4571 + * @param propertyName The name of the property to be retrieved. One of the <tt>Blog.BlogClass</tt>'s properties.
4572 + * @param defaultValue The default value to use in case the blog object does not define one.
4573 + * @param propertyValue The resulting value.
4574 + *###
4575 +#macro(getBlogProperty $blogDoc $propertyName $defaultValue $propertyValue)
4576 + #set($result = ~"$!\{blogDoc.getObject($\{blogClassname}).getProperty($propertyName).value}~")
4577 + #if($result == '')
4578 + #set($result = $defaultValue)
4579 + #end
4580 + #set ($propertyValue = $NULL)
4581 + #setVariable (~"$propertyValue~" $result)
4582 +#end
4583 +
4584 +#**
4585 + * If an error occurs when executing an action, set a specific response status and display an error message.
4586 + *
4587 + * @param status The response status.
4588 + * @param text The user readable error to be displayed. Can be a translation key.
4589 + * @param parameters The parameters to use when decoding the translation key.
4590 + *###
4591 +#macro(blog__actionResponseError $status $text $parameters)
4592 + $response.setStatus($status)
4593 + #if($request.ajax)
4594 + $services.localization.render($text, $!parameters)
4595 + #else
4596 + \{\{error}}$services.localization.render($text, $!parameters)\{\{/error}}
4597 + #end
4598 +#end
4599 +##
4600 +##
4601 +##
4602 +#**
4603 + * Check if a blog is the Default blog (The one in the 'Blog' space).
4604 + *
4605 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
4606 + * @param isDefault The resulting boolean.
4607 + *###
4608 +#macro(isDefaultBlog $blogDoc $isDefault)
4609 + #set ($result = false)
4610 + #if ($blogDoc.space == 'Blog')
4611 + #set ($result = true)
4612 + #end
4613 + #setVariable(~"$isDefault~" $result)
4614 +#end
4615 +##
4616 +##
4617 +##
4618 +#**
4619 + * Retrieve the blog posts location (space).
4620 + *
4621 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
4622 + * @param postsLocation The resulting location.
4623 + *###
4624 +#macro(getBlogPostsLocation $blogSpace $postsLocation)
4625 + #getBlogDocument($blogSpace $blogDoc)
4626 + #getBlogProperty($blogDoc 'postsLocation' $blogDoc.space $result)
4627 + #set ($postsLocation = $NULL)
4628 + #setVariable (~"$postsLocation~" $result)
4629 +#end
4630 +##
4631 +##
4632 +##
4633 +#**
4634 + * Retrieve the blog categories location (space).
4635 + *
4636 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
4637 + * @param categoriesLocation The resulting location.
4638 + *###
4639 +#macro(getBlogCategoriesLocation $blogSpace $categoriesLocation)
4640 + #getBlogDocument($blogSpace $blogDoc)
4641 + #getBlogProperty($blogDoc 'categoriesLocation' 'Blog' $result)
4642 + #set ($postsLocation = $NULL)
4643 + #setVariable (~"$categoriesLocation~" $result)
4644 +#end
4645 +###**
4646 + * Return the Query for selecting the blog posts based on the context where the posts are displayed.
4647 + * for example there is 4 different panel contexts:
4648 + * aBlog.aPost or aBlog.WebHome
4649 + * aCategorySpace.aCategory
4650 + * aCategorySpace.WebHome
4651 + * Blog.aPost or Blog.WebHome
4652 + *
4653 + * @param query The query for selecting blog entries.
4654 + * @param queryParams The parameters to bind with the generated query.
4655 + * @param targetDoc The document in which the articles will be displayed.
4656 + *###
4657 +#macro(getAllBlogPostsQueryBasedOnDisplayContext $targetDoc $query $queryParams)
4658 + #set ($query = $NULL)
4659 + #set ($queryParams = $NULL)
4660 + #getCategoryAllBlogPostsQuery($resultQuery)
4661 + #set ($resultQueryParams = \{})
4662 + #set($sanitizedSpace = $targetDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
4663 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
4664 + ## Get all posts that are in the default blog space('Blog') or in category 'Blog.%'
4665 + #set ($discard = $resultQueryParams.put('space', $targetDoc.space))
4666 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
4667 + #set($resultQuery = ~"$\{resultQuery} and (doc.space = :space or catList like :catList escape '!')~")
4668 + #elseif($targetDoc.getObject($blogCategoryClassname))
4669 + ## Get all posts that are in a category aCategorySpace.aCategory
4670 + #set ($discard = $resultQueryParams.put('catList', $targetDoc.fullName))
4671 + #set($resultQuery = ~"$\{resultQuery} and (catList=:catList)~")
4672 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
4673 + ## Get all posts that are in a category aCategorySpace.%
4674 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
4675 + ## Exclude incategorized posts
4676 + #set ($excludedCategory = ~"$\{targetDoc.space}.WebHome~")
4677 + #if ($targetDoc.space == $defaultBlogSpace)
4678 + #set ($excludedCategory = ~"Blog.Categories.WebHome~")
4679 + #end
4680 + #set ($discard = $resultQueryParams.put('excludedCategory', $excludedCategory))
4681 + #set($resultQuery = ~"$\{resultQuery} and (catList<>:excludedCategory) and (catList like :catList escape '!')~")
4682 + #else
4683 + ## Get all posts in blog space aBlog
4684 + #getAllBlogPostsQuery($resultQuery)
4685 + #getBlogPostsLocation($targetDoc.space $postsLocation)
4686 + #set ($discard = $resultQueryParams.put('space', $postsLocation))
4687 + #set($resultQuery = ~"$\{resultQuery} and doc.space = :space~")
4688 + #end
4689 + #setVariable(~"$query~" $resultQuery)
4690 + #setVariable(~"$queryParams~" $resultQueryParams)
4691 +#end
4692 +##
4693 +##
4694 +##
4695 +###**
4696 + * Display blog posts based on the context where the posts are displayed.
4697 + * for example there is 4 different panel contexts:
4698 + * aBlog.aPost or aBlog.WebHome
4699 + * aCategorySpace.aCategory
4700 + * aCategorySpace.WebHome
4701 + * Blog.aPost or Blog.WebHome
4702 + *
4703 + * @param targetDoc The document in which the articles will be displayed.
4704 + * @param postsVisiblity The visibility of the posts to display: recent, unpublished, ...
4705 + * @param layout Layout of the the posts to display
4706 + * @param layoutParams additional layout parameters, it is a string like 'param1=val1|...|paramN=valueN'
4707 + * @param limit the number of posts to display
4708 + *###
4709 +#macro(displayBlogPostsBasedOnContext $targetDoc $postsVisiblity $layout $layoutParams $limit)
4710 + #if ($postLayout == 'full')
4711 + #set ($macro.paginated = 'yes')
4712 + #end
4713 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
4714 + ## Display all posts that are in the default blog space('Blog') or in category 'Blog.%'
4715 + #getBlogPostsLayout($xwiki.getDocument(~"$\{defaultBlogSpace}.WebHome~") $postsLayout)
4716 + #if (~"$!layout~" == '')
4717 + #set ($layout = $postsLayout)
4718 + #end
4719 + #if ($postsVisiblity == 'recent')
4720 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
4721 + #elseif($postsVisiblity == 'unpublished')
4722 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
4723 + #end
4724 + #elseif($targetDoc.getObject($blogCategoryClassname))
4725 + ## Display all posts that are in a category aCategorySpace.aCategory
4726 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
4727 + #getBlogPostsLayout($blogDoc $postsLayout)
4728 + #if (~"$!layout~" == '')
4729 + #set ($layout = $postsLayout)
4730 + #end
4731 + #if ($postsVisiblity == 'recent')
4732 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
4733 + #elseif($postsVisiblity == 'unpublished')
4734 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
4735 + #end
4736 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
4737 + ## Display all posts that are in a category aCategorySpace.%
4738 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
4739 + #getBlogPostsLayout($blogDoc $postsLayout)
4740 + #if (~"$!layout~" == '')
4741 + #set ($layout = $postsLayout)
4742 + #end
4743 + #if ($postsVisiblity == 'recent')
4744 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
4745 + #elseif($postsVisiblity == 'unpublished')
4746 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
4747 + #end
4748 + #else
4749 + ## Display all posts in blog space aBlog
4750 + #getBlogDocument($targetDoc.space $blogDoc)
4751 + #getBlogPostsLayout($blogDoc $postsLayout)
4752 + #if (~"$!layout~" == '')
4753 + #set ($layout = $postsLayout)
4754 + #end
4755 + #if ($postsVisiblity == 'recent')
4756 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
4757 + #elseif($postsVisiblity == 'unpublished')
4758 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
4759 + #end
4760 + #end
4761 +#end
4762 +##
4763 +##
4764 +##
4765 +#**
4766 + * Bind parameters to a query object.
4767 + *
4768 + * @param queryObj The query object (org.xwiki.query.internal.ScriptQuery object)
4769 + * @param queryParams the query parameters.
4770 + *###
4771 +#macro(bindQueryParameters $queryObj $queryParams)
4772 + #set ($output = $queryObj)
4773 + #foreach( $key in $queryParams.keySet() )
4774 + #set($output = $queryObj.bindValue($key, $queryParams.get($key)))
4775 + #end
4776 + #setVariable(~"$queryObj~" $output)
4777 +#end
4778 +##
4779 +##
4780 +##
4781 +#**
4782 + * Determines the blogposts layout: Default layout (Calendar), Image thumbnail
4783 + *
4784 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>postsLayout</tt>
4785 + * property set.
4786 + * @param postsLayout The resulting string. If the blog object does not define anything, it is considered full (default).
4787 + *###
4788 +#macro(getBlogPostsLayout $blogDoc $postsLayout)
4789 + #getBlogProperty($blogDoc 'postsLayout' 'full' $res)
4790 + #set ($postsLayout = $NULL)
4791 + #setVariable (~"$postsLayout~" $res)
4792 +#end
4793 +##
4794 +##
4795 +##
4796 +#**
4797 + * Retrieve the blog document of a categories space, which is the blog descriptor that have its categoriesLocation property set to the categories space
4798 + *
4799 + * @param categoriesSpace A <tt>String</tt>, the name of the space.
4800 + * @param blogDoc The resulting XDocument.
4801 + *###
4802 +#macro(getBlogDocumentForCategoriesSpace $categoriesSpace $blogDoc)
4803 + #set($macro.blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as categoriesLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=categoriesLocationProp.id.id and categoriesLocationProp.id.name='categoriesLocation' and categoriesLocationProp.value=:categoriesLocation order by doc.creationDate~").setLimit(1).setOffset(0).bindValue('categoriesLocation', $categoriesSpace).execute())
4804 + #if($macro.blogDocs.size() > 0 && $categoriesSpace != $defaultBlogSpace)
4805 + #set($macro.result = $xwiki.getDocument($macro.blogDocs.get(0)))
4806 + #else
4807 + ## Fallback to Blog.WebHome, the default blog
4808 + #set($macro.result = $xwiki.getDocument('Blog.WebHome'))
4809 + #end
4810 + #set ($blogDoc = $NULL)
4811 + #setVariable (~"$blogDoc~" $macro.result)
4812 +#end" %)
4813 +(((
4814 +(% class="macro-placeholder hidden" %)
4815 +(((
4816 +macro:velocity
4817 +)))
4818 +)))
4819 +)))
4820 +
4821 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogPostLayoutMacros~"" %)
4822 +(((
4823 +(% class="macro-placeholder hidden" %)
4824 +(((
4825 +macro:include
4826 +)))
4827 +
4828 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|#**
4829 + * Extract the layout parameters from a string.
4830 + *
4831 + * @param layoutParamsString The string representation of the layout parameters.
4832 + * It should contain a String following this format ~"paramName1=Value1|paramName2=Value2|...|paramNameK=ValueK~"
4833 + * @param layoutsParameters The resulting layout parameters Map.
4834 + *###
4835 +#macro(extractLayoutParametersFromString $layoutParamsString $layoutsParameters)
4836 + #set ($layoutsParameters = $NULL)
4837 + #set ($macro.layoutParams = \{})
4838 + #if (~"$!layoutParamsString~" != '')
4839 + #set ($macro.paramsArr = $layoutParamsString.split('\\|'))
4840 + #foreach ($item in $macro.paramsArr)
4841 + #set ($itemSplit = $item.split('='))
4842 + #if ($itemSplit.size() == 2)
4843 + #set ($discard = $macro.layoutParams.put($itemSplit[0].trim(), $itemSplit[1].trim()))
4844 + #end
4845 + #end
4846 + #end
4847 + #setVariable(~"$layoutsParameters~" $macro.layoutParams)
4848 +#end" %)
4849 +(((
4850 +(% class="macro-placeholder hidden" %)
4851 +(((
4852 +macro:velocity
4853 +)))
4854 +)))
4855 +)))
4856 +
4857 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-| #macro(displaySmallPost $pDoc $pObj)
4858 + #initLayoutVars($pDoc $pObj)
4859 + <div class=~"col-xs-12 col-sm-6 next_blog~">
4860 + <a href=~"$pDoc.uRL~" class=~"thumbnail~">
4861 + <div class=~"row~">
4862 + <div class=~"col-xs-4~">
4863 + #if ($imageAtt)
4864 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
4865 + #end
4866 + </div>
4867 + <div class=~"col-xs-8 art_det~">
4868 + <p class=~"text-left~">
4869 + #if($displayTitle)$!postTitle #end
4870 + <br/><span class=~"date_info~"> $!dateStr </span>
4871 + </p>
4872 + #displayPostDetails($pDoc)
4873 + </div>
4874 + </div>
4875 + </a>
4876 + </div>
4877 + #end
4878 + ##
4879 + ##
4880 + ##
4881 + #macro(displayPinnedPost $pDoc $pObj)
4882 + #initLayoutVars($pDoc $pObj)
4883 + <div class=~"col-xs-12 col-sm-4 col-md-4 blog_pin~">
4884 + <a href=~"$pDoc.uRL~" class=~"all-post-link~">
4885 + <div class=~"thumbnail~">
4886 + #if ($displayTitle && $displayTitleFirstOnPinnedPosts)
4887 + <h5 class=~"title-top~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
4888 + #end
4889 + #if ($imageAtt)
4890 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
4891 + #end
4892 + <div class=~"caption~">
4893 + #if ($displayTitle && !$displayTitleFirstOnPinnedPosts)
4894 + <h5 class=~"text-left~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
4895 + #end
4896 + #if ($displaySummaryOnPinnedPosts)
4897 + <div class=~"text-left post-summary~">
4898 + #set ($postContent = $pObj.getProperty('extract').value)
4899 + $!pDoc.getRenderedContent($postContent, $pDoc.syntax.toIdString())
4900 + </div>
4901 + #end
4902 + #displayPostDetails($pDoc)
4903 + </div>
4904 + </div>
4905 + </a>
4906 + </div>
4907 + #end
4908 + ##
4909 + ##
4910 + ##
4911 + #macro(formatPostDate $pDoc $pObj)
4912 + #set ($formattedDate = $NULL)
4913 + #set($dateStr = $datetool.format('medium', $postDate, $xcontext.locale))
4914 + #if (~"$!dateStr~" != '')
4915 + #set ($dateArr = $dateStr.split(' '))
4916 + #if ($dateArr.size() > 3)
4917 + #set ($dateStr = ~"~")
4918 + #foreach($s in $dateArr.subList(0, 3))
4919 + #set ($dateStr = ~"$\{dateStr}$\{s} ~")
4920 + #end
4921 + #end
4922 + #end
4923 + #setVariable(~"$formattedDate~" $dateStr)
4924 + #end
4925 + ##
4926 + ##
4927 + ##
4928 + #macro(displayPostDetails $pDoc)
4929 + <div class=~"row post-details~">
4930 + <div class=~"col-xs-8 detail~">
4931 + #if ($services.like.displayButton($pDoc.documentReference))
4932 + #set ($optLikeRecord = $services.like.getLikes($pDoc.documentReference))
4933 + ## Retrieve the likes number in XWiki 12.9+
4934 + #set ($likeNumber = $optLikeRecord.get())
4935 + #if (!$stringtool.isNumeric($likeNumber.toString()))
4936 + ## Retrieve the likes number in XWiki versions greater than 12.7 and lower than 12.9.
4937 + #set ($likeNumber = $optLikeRecord.get().likeNumber)
4938 + #end
4939 + #if ($stringtool.isNumeric($likeNumber.toString()))
4940 + <div class=~"post-likes btn btn-default disabled badge~"
4941 + title=~"$escapetool.xml($services.localization.render('like.button.title', [$likeNumber]))~">
4942 + $services.icon.renderHTML('heart') <span class=~"like-number~">$likeNumber</span>
4943 + </div>
4944 + #end
4945 + #elseif ($services.ratings)
4946 + #set ($ratingsConfigDoc = $services.ratings.getConfigurationDocument($pDoc.documentReference))
4947 + #if ($ratingsConfigDoc.getValue('displayRatings') == 1)
4948 + <ul class=~"pull-left note list-inline~">
4949 + #foreach ($x in [1..5])
4950 + #set ($cls = ~"~")
4951 + #if ($x > $averageVote)
4952 + #set ($cls = ~"-o~")
4953 + #end
4954 + <li><span class=~"fa fa-star$\{cls}~"></span></li>
4955 + #end
4956 + </ul>
4957 + #end
4958 + #end
4959 + </div>
4960 + #if ($showPostComments)
4961 + <div class=~"col-xs-4 com_det~">
4962 + <p class=~"text-right~">$services.icon.renderHTML('comments') ($!nbComments)</p>
4963 + </div>
4964 + #end
4965 + </div>
4966 + #end
4967 + ##
4968 + ##
4969 + ##
4970 + #macro(initLayoutVars $pDoc $pObj)
4971 + #set ($postTitle = $pDoc.display('title', 'view', $pObj))
4972 + #set ($imageAtt = $pDoc.getAttachment($pObj.getValue('image')))
4973 + #isPublished($pObj $isPublished)
4974 + #isHidden($pObj $isHidden)
4975 + #getEntryDate($pDoc $pObj $postDate)
4976 + #formatPostDate($postDate $dateStr)
4977 + #set ($averageVote = $mathtool.round($services.ratings.getAverageRating($pDoc.documentReference).getAverageVote()))
4978 + #set ($nbComments = $pDoc.getComments().size())
4979 + #set ($showPostComments = true)
4980 + #if ($xwiki.getSpacePreferenceFor('showcomments', $pDoc.documentReference.lastSpaceReference, '1') == '0')
4981 + #set ($showPostComments = false)
4982 + #end
4983 + #end
4984 + ##
4985 + ##
4986 + ##
4987 + #macro(displayEditPinnedPostsButton)
4988 + #if (~"$!macroAdditionalParams.get('postIndex')~" == '0' && $services.security.authorization.hasAccess('edit', $pinnedPostsSourceDoc.fullName))
4989 + #set ($discard = $xwiki.ssx.use('Blog.PinnedPostsSheet'))
4990 + #set ($discard = $xwiki.jsx.use('Blog.PinnedPostsSheet'))
4991 + #set ($editPinnedPostsURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'get', 'sheet=Blog.PinnedPostsSheet'))
4992 + #set ($newPinnedPostsObjectURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'objectadd', ~"classname=Blog.PinnedPostsClass&form_token=$!\{services.csrf.getToken()}~"))
4993 + <div class=~"edit-pinned-posts-container~">
4994 + <div class=~"col-xs-12 col-sm-12 col-md-12 text-right edit-pinned-posts~">
4995 + <a href=~"javascript:;~" class=~"editPinnedPosts~">
4996 + <span class=~"glyphicon glyphicon-edit~" aria-hidden=~"true~"></span> $services.localization.render('blog.post.layout.cards.pinnedposts.edit')
4997 + </a>
4998 + <input type=~"hidden~" id=~"editPinnedPostsURL~" value=~"$escapetool.xml($editPinnedPostsURL)~"/>
4999 + <input type=~"hidden~" id=~"newPinnedPostsObjectURL~" value=~"$escapetool.xml($newPinnedPostsObjectURL)~"/>
5000 + </div>
5001 + </div>
5002 + #if (~"$!pinnedPostsObj~" == '')
5003 + <input type=~"hidden~" name=~"createPinnedPostsObject~" value=~"1~"/>
5004 + #end
5005 + #end
5006 + #end" %)
5007 +(((
5008 +(% class="macro-placeholder hidden" %)
5009 +(((
5010 +macro:velocity
5011 +)))
5012 +)))
5013 +
5014 +(% data-macro="startmacro:velocity|-||-| #if ($services.security.authorization.hasAccess('view', $xcontext.macro.params.reference))
5015 + #set ($postDoc = $xwiki.getDocument($xcontext.macro.params.reference))
5016 + #getEntryObject($postDoc $postObj)
5017 + #if (~"$!postObj~" != '')
5018 + #extractLayoutParametersFromString($xcontext.macro.params.params $macroAdditionalParams)
5019 + ##
5020 + #set ($displayTitle = true)
5021 + #if (~"$!macroAdditionalParams.get('displayTitle')~" == 'false')
5022 + #set ($displayTitle = false)
5023 + #end
5024 + ##
5025 + #set ($displayTitleFirstOnPinnedPosts = false)
5026 + #if (~"$!macroAdditionalParams.get('displayTitleFirstOnPinnedPosts')~" == 'true')
5027 + #set ($displayTitleFirstOnPinnedPosts = true)
5028 + #end
5029 + ##
5030 + #set ($displaySummaryOnPinnedPosts = true)
5031 + #if (~"$!macroAdditionalParams.get('displaySummaryOnPinnedPosts')~" == 'false')
5032 + #set ($displaySummaryOnPinnedPosts = false)
5033 + #end
5034 + ##
5035 + #set ($postIndex = $numbertool.toNumber($macroAdditionalParams.get('postIndex')).intValue())
5036 + #if ($postIndex == 0)
5037 + #set ($stopBlogPostsDisplay = false)
5038 + #end
5039 + #set ($listResultsCount = $numbertool.toNumber($macroAdditionalParams.get('list-results-count')).intValue())
5040 + #set($discard = $xwiki.ssx.use('Blog.BlogPostLayoutCards'))
5041 + #set($scaleWidth = 600)
5042 + #set($imgQs=~"width=$scaleWidth~")
5043 + ## Display pinned posts
5044 + ## Get the list of pinned posts
5045 + #set ($pinnedPosts = [])
5046 + #set ($pinnedPostsSourceDoc = $NULL)
5047 + #if (~"$!macroAdditionalParams.get('forceDisplayPinnedPosts')~" == 'true' && ~"$!macroAdditionalParams.get('list-blog')~" != '')
5048 + #set ($pinnedPostsSourceDoc = $xwiki.getDocument($macroAdditionalParams.get('list-blog')))
5049 + ## Note that the 'list-blog' parameter contains the value of the 'blog' parameter of the blogpostlist macro passed to the current layout macro
5050 + #end
5051 + #if (~"$!pinnedPostsSourceDoc~" != '')
5052 + #set ($pinnedPostsObj = $pinnedPostsSourceDoc.getObject('Blog.PinnedPostsClass'))
5053 + #if (~"$!pinnedPostsObj~" != '')
5054 + #set ($orderedPinnedPostsJSON = $pinnedPostsObj.getProperty('orderedPosts').value)
5055 + #if (~"$!orderedPinnedPostsJSON~" != '')
5056 + #set ($pinnedPosts = $jsontool.parse($orderedPinnedPostsJSON))
5057 + #else
5058 + #set ($pinnedPosts = $pinnedPostsObj.getProperty('posts').value)
5059 + #end
5060 + #end
5061 + #if ($postIndex == 0 && $pinnedPosts.size() > 0)
5062 + \{\{html clean=~"false~"}}
5063 + #set ($x = 0)
5064 + #set ($showPinnedPostsButton = true)
5065 + #foreach ($pinnedPost in $pinnedPosts)
5066 + #if ($x == 0)
5067 + <div class=~"row flex-container~">
5068 + #if ($showPinnedPostsButton)
5069 + #displayEditPinnedPostsButton()
5070 + #set($showPinnedPostsButton = false)
5071 + #end
5072 + #end
5073 + #set ($pinnedPostDoc = $xwiki.getDocument($pinnedPost))
5074 + #getEntryObject($pinnedPostDoc $pinnedPostObj)
5075 + #if (~"$!pinnedPostObj~" != '')
5076 + #displayPinnedPost($pinnedPostDoc $pinnedPostObj)
5077 + #end
5078 + #set ($x = $mathtool.add($x, 1))
5079 + #if ($x == 3)
5080 + #set ($x = 0)
5081 + </div>
5082 + #end
5083 + #end
5084 + #if ($mathtool.mod($x, 3) != 0)
5085 + </div>
5086 + #end
5087 + \{\{/html}}
5088 +
5089 + ## If the first post is a pinned post : this means that all the posts are pinned
5090 + ## In this case, avoid displaying the posts again after the pinned posts section.
5091 + #if ($pinnedPosts.contains($xcontext.macro.params.reference))
5092 + #set ($stopBlogPostsDisplay = true)
5093 + #end
5094 + #elseif($postIndex == 0 && $pinnedPosts.size() == 0)
5095 +
5096 + \{\{html}}
5097 + <div class=~"row no-pinnded-posts~">
5098 + #displayEditPinnedPostsButton()
5099 + </div>
5100 + \{\{/html}}
5101 +
5102 + #end
5103 + #end
5104 + #if (!$stopBlogPostsDisplay)
5105 + \{\{html clean=~"false~"}}
5106 + #if (~"$!nbDisplayedPosts~" == '' || $postIndex == 0)
5107 + #set ($nbDisplayedPosts = 0)
5108 + #end
5109 + #if($mathtool.mod($nbDisplayedPosts, 2) == 0)
5110 + #if ($nbDisplayedPosts != 0)
5111 + </div>
5112 + #set ($lastHtmlTag = 'c')
5113 + #end
5114 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
5115 + <div class=~"row~">
5116 + #set ($lastHtmlTag = 'o')
5117 + #set ($lastRowClass = ~"~")
5118 + #else
5119 + <div class=~"row flex-container~">
5120 + #set ($lastHtmlTag = 'o')
5121 + #set ($lastRowClass = ~"flex~")
5122 + #end
5123 + #end
5124 + #displaySmallPost($postDoc $postObj)
5125 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
5126 + </div>
5127 + #set ($lastHtmlTag = 'c')
5128 + #end
5129 + #set ($nbDisplayedPosts = $mathtool.add($nbDisplayedPosts, 1))
5130 + #if ($postIndex == $mathtool.sub($listResultsCount, 1))
5131 + #if (~"$!lastHtmlTag~" == 'o')
5132 + #if ($mathtool.mod($nbDisplayedPosts, 2) == 1 && $lastRowClass == ~"flex~")
5133 + <div class=~"col-xs-12 col-sm-6~"></div>
5134 + #end
5135 + </div>
5136 + #end
5137 + #end
5138 + \{\{/html}}
5139 + #end
5140 + #else
5141 + \{\{error}}$services.localization.render('blog.blogpostlayout.notpost', [$xcontext.macro.params.reference])\{\{/error}}
5142 + #end
5143 + #else
5144 + \{\{error}}$services.localization.render('blog.blogpostlayout.post_view_not_allowed', [$xcontext.macro.params.reference])\{\{/error}}
5145 + #end" class="macro hidden macro-placeholder" %)macro:velocity(% data-macro="startmacro:html|-|clean=~"false~"|-|</div>
5146 +<div class=~"row flex-container~">
5147 +<div class=~"col-xs-12 col-sm-6 next_blog~">
5148 +<a href=~"/Nieuws/Nieuwsbrief%20december%202023~" class=~"thumbnail~">
5149 +<div class=~"row~">
5150 +<div class=~"col-xs-4~">
5151 +<img src=~"/download/Nieuws/Nieuwsbrief%20december%202023/snow-cold-winter-white-sweet-weather-1363025-pxhere.com.jpg?width=600&rev=1.1~" />
5152 +</div>
5153 +<div class=~"col-xs-8 art_det~">
5154 +<p class=~"text-left~">
5155 +Nieuwsbrief december 2023 <br/><span class=~"date_info~"> 10 jan. 2024 </span>
5156 +</p>
5157 +<div class=~"row post-details~">
5158 +<div class=~"col-xs-8 detail~">
5159 +<div class=~"post-likes btn btn-default disabled badge~"
5160 +title=~"Number of likes on this page: 1~">
5161 +<span class=~"fa fa-heart~"></span> <span class=~"like-number~">1</span>
5162 +</div>
5163 +</div>
5164 +<div class=~"col-xs-4 com_det~">
5165 +<p class=~"text-right~"><span class=~"fa fa-comments~"></span> (0)</p>
5166 +</div>
5167 +</div>
5168 +</div>
5169 +</div>
5170 +</a>
5171 +</div>" class="macro macro hidden macro-placeholder" %)macro:html
5172 +)))
5173 +)))
5174 +
5175 +(% class="row flex-container" %)
5176 +(((
5177 +(% class="col-xs-12 col-sm-6 next_blog" %)
5178 +(((
5179 +(% class="row" %)
5180 +(((
5181 +(% class="col-xs-4" %)
5182 +(((
5183 +[[~[~[image:/download/Nieuws/Nieuwsbrief%20december%202023/snow-cold-winter-white-sweet-weather-1363025-pxhere.com.jpg?width=600&rev=1.1~]~]>>path:/Nieuws/Nieuwsbrief%20december%202023||class="thumbnail"]]
5184 +)))
5185 +
5186 +(% class="col-xs-8 art_det" %)
5187 +(((
5188 +(% class="text-left" %)
5189 +[[Nieuwsbrief december 2023
5190 +(% class="date_info" %) 10 jan. 2024>>path:/Nieuws/Nieuwsbrief%20december%202023||class="thumbnail"]]
5191 +
5192 +(% class="row post-details" %)
5193 +(((
5194 +(% class="col-xs-8 detail" %)
5195 +(((
5196 +(% class="post-likes btn btn-default disabled badge" title="Number of likes on this page: 1" %)
5197 +(((
5198 +[[(% class="like-number" %)1>>path:/Nieuws/Nieuwsbrief%20december%202023||class="thumbnail"]]
5199 +)))
5200 +)))
5201 +
5202 +(% class="col-xs-4 com_det" %)
5203 +(((
5204 +(% class="text-right" %)
5205 +[[(0)>>path:/Nieuws/Nieuwsbrief%20december%202023||class="thumbnail"]]
5206 +)))
5207 +)))
5208 +)))
5209 +)))
5210 +)))
5211 +
5212 +(% class="macro" data-macro="startmacro:blogPostLayoutCards|-|reference=~"Nieuws.Nieuwsbrief november 2023~" params=~"displayTitle=true|useSummary=true|list-limit=6|list-layout=cards|list-blog=Nieuws.WebHome|list-paginated=no|list-results-count=6|postIndex=0|previousPostReference=|postIndex=1|previousPostReference=Nieuws.Nieuwsbrief januari 2024|postIndex=2|previousPostReference=Nieuws.Audit BMI en BORG|postIndex=3|previousPostReference=Nieuws.Nieuwsbrief december 2023~"" %)
5213 +(((
5214 +(% class="macro-placeholder hidden" %)
5215 +(((
5216 +macro:blogPostLayoutCards
5217 +)))
5218 +
5219 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogCode~"" %)
5220 +(((
5221 +(% class="macro-placeholder hidden" %)
5222 +(((
5223 +macro:include
5224 +)))
5225 +
5226 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogParameters~"" %)
5227 +(((
5228 +(% class="macro-placeholder hidden" %)
5229 +(((
5230 +macro:include
5231 +)))
5232 +
5233 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|## Blog
5234 +#set($blogClassname = 'Blog.BlogClass')
5235 +#set($blogTemplate = 'Blog.BlogTemplate')
5236 +#set($blogSheet = 'Blog.BlogSheet')
5237 +## Blog entries
5238 +#set($blogPostClassname = 'Blog.BlogPostClass')
5239 +#set($blogPostTemplate = 'Blog.BlogPostTemplate')
5240 +#set($blogPostSheet = 'Blog.BlogPostSheet')
5241 +#set($blogPostObjectNumber = $xwiki.getDocument($blogPostTemplate).getObject($blogPostClassname).number)
5242 +#set($oldArticleClassname = 'XWiki.ArticleClass')
5243 +## Categories
5244 +#set($blogCategoryClassname = 'Blog.CategoryClass')
5245 +#set($blogCategoryTemplate = 'Blog.CategoryTemplate')
5246 +#set($blogCategorySheet = 'Blog.CategorySheet')
5247 +#set($blogCategoriesSheet = 'Blog.CategoriesSheet')
5248 +#set($oldBlogCategoryClassname = 'Blog.Categories')
5249 +#set($defaultCategoryParent = 'Blog.Categories')
5250 +## Style
5251 +#set($blogStyleDocumentName = 'Blog.BlogStyle')
5252 +#set($blogStyleDocument = $xwiki.getDocument($blogStyleDocumentName))
5253 +## Clientside scripts
5254 +#set($blogScriptsDocumentName = 'Blog.BlogScripts')
5255 +#set($blogPublisher = $xwiki.getDocument('Blog.Publisher'))
5256 +## Misc
5257 +#set($thisURL = $doc.getURL($xcontext.action, $request.queryString))
5258 +#set($isBlogPost = $doc.getObject($blogPostClassname))
5259 +#set($defaultBlogSpace = 'Blog')
5260 +#set($isCategoryPage = $doc.getObject($blogCategoryClassname))
5261 +#set($isCategoriesHomePage = $doc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
5262 +##
5263 +##
5264 +##
5265 +#**
5266 + * Displays an image, taken from the blog style document.
5267 + *
5268 + * @param $imgName The name of the icon from icons set to use.
5269 + *#
5270 +#macro(toolImage $imgName)(% class=~"icon-manage~"~%)$services.icon.render($imgName)(%~%)#end" %)
5271 +(((
5272 +(% class="macro-placeholder hidden" %)
5273 +(((
5274 +macro:velocity
5275 +)))
5276 +)))
5277 +)))
5278 +
5279 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|##
5280 +##
5281 +##
5282 +## Import the blog skin and javascripts.
5283 +$!xwiki.ssx.use($blogStyleDocumentName)##
5284 +$!xwiki.jsx.use($blogScriptsDocumentName)##
5285 +##
5286 +## import the hierarchy for the path the blog post footer (in displayEntryBlogLocation)
5287 +#template('hierarchy_macros.vm')##
5288 +##
5289 +##
5290 +#**
5291 + * Prints a blog. This is the main macro used in the BlogSheet.
5292 + *
5293 + * @param blogDoc the XDocument holding the blog definition object.
5294 + *###
5295 +#macro(printBlog $blogDoc)
5296 + \{\{include reference='Blog.CreatePost'/}}
5297 +
5298 + ## Use the blogPostList macro to display the blogposts
5299 + ## The blogPostList is used only in case of 'all' or 'paged' blog display type because the blogPostList macro
5300 + ## do not support FTM the monthly and weekly blog display types
5301 + #getBlogDisplayType($blogDoc $displayType)
5302 + #if ($displayType == 'weekly' || $displayType == 'monthly')
5303 + #getBlogEntries($blogDoc $entries)
5304 + #displayBlog($entries 'index' true true)
5305 + #displayNavigationLinks($blogDoc)
5306 + #else
5307 + #getBlogDisplayType($blogDoc $displayType)
5308 + #set ($paginated = 'no')
5309 + #if ($displayType == 'paginated')
5310 + #set ($paginated = 'yes')
5311 + #end
5312 + #getBlogPostsLayout($blogDoc $postsLayout)
5313 + (% class=~"hfeed index~" ~%)(((\{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$paginated~" layout=~"$!postsLayout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" /}})))
5314 + #end
5315 +#end
5316 +##
5317 +##
5318 +##
5319 +#**
5320 + * Shows blog information. In view mode, the description is printed. In edit mode, allows changing blog settings: title,
5321 + * description, blog type (global or in-space), index display type (fixed size pagination, weekly index, monthly index,
5322 + * all entries).
5323 + *
5324 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
5325 + *###
5326 +#macro(showBlogInfo $blogDoc)
5327 + #if($blogDoc.getObject($blogClassname))
5328 + ## Keep testing for inline action for backward compatibility with older blogs.
5329 + #if($xcontext.action == 'edit' || $xcontext.action == 'inline')
5330 + #macro(displayProperty $blogDoc $propname)
5331 + ; #displayPropName($xwiki.getClass($blogClassname).get($propname)):
5332 + : $blogDoc.display($propname)
5333 + #end
5334 + #displayProperty($blogDoc 'title')
5335 + #displayProperty($blogDoc 'description')
5336 + #displayProperty($blogDoc 'displayType')
5337 + #displayProperty($blogDoc 'itemsPerPage')
5338 + #displayProperty($blogDoc 'postsLayout')
5339 + #displayProperty($blogDoc 'postsLayoutParameters')
5340 + #else
5341 + $blogDoc.display('description')
5342 + #end
5343 + #elseif($doc.fullName == $blogSheet)
5344 += $services.localization.render('blog.code.blogsheet') =
5345 + \{\{translation key='blog.code.sheetexplanation'/}}
5346 + #else
5347 + \{\{warning}}\{\{translation key='blog.code.notblog'/}}\{\{/warning}}
5348 + #end
5349 +#end
5350 +##
5351 +##
5352 +##
5353 +#**
5354 + * Retrieve the blog document, which usually is either <tt>&lt;Space&gt;.WebHome</tt> for whole-spaces blogs, or
5355 + * <tt>&lt;Space&gt;.Blog</tt> for in-space blogs. If none of these documents contains a blog object, then the first
5356 + * (alphabetically) document in the target space that contains one is returned. Finally, if no document in the current
5357 + * space contains a blog object, then <tt>Blog.WebHome</tt> is returned as the default blog.
5358 + *
5359 + * @param space A <tt>String</tt>, the name of the space where to search.
5360 + * @param blogDoc The resulting XDocument.
5361 + *###
5362 +#macro(getBlogDocument $space $blogDoc)
5363 + #set ($result = $NULL)
5364 + ## Check if the current space has a WebPreferences page that contains a Blog.EnablePanelsConfigurationClass object.
5365 + ## It is possible to display a blog's panels info in a page that is not inside a blog and in that case we need to
5366 + ## identify the right blog based on a configuration object in a WebPreferences page.
5367 + #set ($spaceReference = $services.model.resolveSpace($space))
5368 + #set ($preferencesDocRef = $services.model.createDocumentReference('WebPreferences', $spaceReference))
5369 + #set ($preferencesDoc = $xwiki.getDocument($preferencesDocRef))
5370 + #set ($preferencesObj = $preferencesDoc.getObject('Blog.EnablePanelsConfigurationClass'))
5371 + #if ($preferencesObj)
5372 + #set ($result = $xwiki.getDocument( $preferencesObj.getValue('blog')))
5373 + #end
5374 + ## If no special case occurs (like the previous one), identify a blog by checking the current location from its hierarchy.
5375 + #if (~"$!result~" == '')
5376 + ## First, try the Space.WebHome, for a whole-space blog
5377 + #set($result = $xwiki.getDocument(~"$\{space}.WebHome~"))
5378 + #if(!$result.getObject($blogClassname))
5379 + ## Second, try the Space.Blog document
5380 + #set($result = $xwiki.getDocument(~"$\{space}.Blog~"))
5381 + #if(!$result.getObject($blogClassname))
5382 + ## Third, try searching for a blog document in the current space
5383 + ## Prevent the query fail when the space contains dots '.'
5384 + #set($blogDocs = $services.query.hql(~", BaseObject obj where doc.space = :space and obj.name = doc.fullName and obj.className = '$blogClassname' order by doc.name~").setLimit(1).setOffset(0).bindValue('space', $space).execute())
5385 + #if($blogDocs.size() > 0)
5386 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
5387 + #else
5388 + ## Fourth, try searching for a blog document that have the its 'postsLocation' set to the current space
5389 + #set($blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as postsLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=postsLocationProp.id.id and postsLocationProp.id.name='postsLocation' and postsLocationProp.value=:postsLocation order by doc.name~").setLimit(1).setOffset(0).bindValue('postsLocation', $space).execute())
5390 + #if($blogDocs.size() > 0)
5391 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
5392 + #else
5393 + ## Last, fallback to Blog.WebHome, the default blog
5394 + #set($result = $xwiki.getDocument('Blog.WebHome'))
5395 + #end
5396 + #end
5397 + #end
5398 + #end
5399 + #end
5400 + #set ($blogDoc = $NULL)
5401 + #setVariable (~"$blogDoc~" $result)
5402 +#end
5403 +##
5404 +##
5405 +##
5406 +#**
5407 + * Retrieve the blog title.
5408 + *
5409 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass<tt> object with the <tt>title</tt> property set.
5410 + * @param title The resulting title.
5411 + *###
5412 +#macro(getBlogTitle $blogDoc $title)
5413 + ## Titles can contain velocity code (most commonly translations), so we should evaluate them.
5414 + #set ($title = $NULL)
5415 + #setVariable (~"$title~" $!blogDoc.displayTitle)
5416 +#end
5417 +##
5418 +##
5419 +##
5420 +#**
5421 + * Retrieve the blog description.
5422 + *
5423 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>description</tt>
5424 + * property set.
5425 + * @param description The resulting description.
5426 + *###
5427 +#macro(getBlogDescription $blogDoc $description)
5428 + #getBlogProperty($blogDoc 'description' '' $result)
5429 + #set ($description = $NULL)
5430 + #setVariable (~"$description~" $result)
5431 +#end
5432 +##
5433 +##
5434 +##
5435 +#**
5436 + * Retrieves a list of entries to be displayed. The entries are either part of the blog's space, or have the blog
5437 + * document set as a parent. The number and range of entries returned (from all those belonging to this blog) depends on
5438 + * the blog display type: paginated (fixed number of entries), weekly (all entries in a week), monthly (all entries in a
5439 + * month), or all.
5440 + *
5441 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
5442 + * @param entries The resulting list of entries to display, a list of XDocument names.
5443 + *###
5444 +#macro(getBlogEntries $blogDoc $entries)
5445 + #if (!$entries)
5446 + #setVariable (~"$entries~" [])
5447 + #end
5448 + #getAllBlogPostsQuery($query)
5449 + #isDefaultBlog($blogDoc $isDefault)
5450 + #set($queryParams = \{})
5451 + #if ($isDefault)
5452 + #getCategoryAllBlogPostsQuery($query)
5453 + #set($query = ~"$\{query} and (doc.creator = :creator or (isPublished.value = 1 and hidden.value = 0)) and (doc.space = :space or catList like :catList escape '!')~")
5454 + #set($discard = $queryParams.put('creator', $xcontext.user))
5455 + #set($discard = $queryParams.put('space', $blogDoc.space))
5456 + #set($sanitizedBlogSpace = $blogDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
5457 + #set($discard = $queryParams.put('catList', $sanitizedBlogSpace))
5458 + #else
5459 + #set($query = ~"$\{query} and (doc.space = :space or doc.parent = :parent)~")
5460 + #getBlogPostsLocation($blogDoc.space $blogPostsLocation)
5461 + #set($discard = $queryParams.put('space', $blogPostsLocation))
5462 + #set($discard = $queryParams.put('parent', $blogDoc.space))
5463 + #end
5464 + #getBlogDisplayType($blogDoc $displayType)
5465 + #if($displayType == 'weekly')
5466 + #getWeeklyBlogEntries($blogDoc $query $entries $queryParams)
5467 + #elseif($displayType == 'monthly')
5468 + #getMonthlyBlogEntries($blogDoc $query $entries $queryParams)
5469 + #elseif($displayType == 'all')
5470 + #getAllBlogEntries($blogDoc $query $entries $queryParams)
5471 + #else
5472 + #getPagedBlogEntries($blogDoc $query $entries $queryParams)
5473 + #end
5474 +#end
5475 +##
5476 +##
5477 +##
5478 +#**
5479 + * Retrieves a list of entries to be displayed. The entries are taken from a ~"page~" of the blog, a sequence of documents
5480 + * defined by the request parameters <tt>ipp</tt> (items per page) and <tt>page</tt> (the current page). Initially the
5481 + * first page is displayed, with the number of entries defined in the blog object in the <tt>itemsPerPage</tt> property
5482 + * (10 if not defined).
5483 + *
5484 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
5485 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
5486 + * refined to restrict to a given space, or to a given search criteria, etc.
5487 + * @param entries The resulting list of entries to display, a list of XDocument names.
5488 + * @param queryParams The parameters to bind with the query.
5489 + *###
5490 +#macro(getPagedBlogEntries $blogDoc $query $entries $queryParams)
5491 + #if (!$entries)
5492 + #setVariable (~"$entries~" [])
5493 + #end
5494 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
5495 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~"))
5496 + #bindQueryParameters($countQueryObj $queryParams)
5497 + #bindQueryParameters($queryObj $queryParams)
5498 + #set($totalEntries = $countQueryObj.count())
5499 + #getBlogProperty($blogDoc 'itemsPerPage' '10' $defaultItemsPerPage)
5500 + #set($defaultItemsPerPage = $numbertool.toNumber($defaultItemsPerPage).intValue())
5501 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
5502 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
5503 + #set($discard = $entries.addAll($queryObj.setLimit($itemsPerPage).setOffset($startAt).addFilter(~"unique~").execute()))
5504 +#end
5505 +##
5506 +##
5507 +##
5508 +#**
5509 + * Retrieves a list of entries to be displayed. The entries are taken from a week of the blog. The target week is
5510 + * defined by the request parameters <tt>week</tt> (the week number in the year, from 1 to 52) and <tt>year</tt> (4
5511 + * digit year). Initially the current week is displayed.
5512 + *
5513 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
5514 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
5515 + * refined to restrict to a given space, or to a given search criteria, etc.
5516 + * @param entries The resulting list of entries to display, a list of XDocument names.
5517 + * @param queryParams The parameters to bind with the query.
5518 + *###
5519 +#macro(getWeeklyBlogEntries $blogDoc $query $entries $queryParams)
5520 + #if (!$entries)
5521 + #setVariable (~"$entries~" [])
5522 + #end
5523 + #getRequestedWeek($weekDate)
5524 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
5525 + #set($minDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundFloor()))
5526 + #set($maxDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundCeiling()))
5527 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
5528 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
5529 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
5530 + #bindQueryParameters($countQueryObj $queryParams)
5531 + #bindQueryParameters($queryObj $queryParams)
5532 + #set($totalEntries = $countQueryObj.count())
5533 + #set($discard = $entries.addAll($queryObj.execute()))
5534 +#end
5535 +##
5536 +##
5537 +##
5538 +#**
5539 + * Retrieves a list of entries to be displayed. The entries are taken from a month of the blog. The target month is
5540 + * defined by the request parameters <tt>month</tt> (the month number, from 1 to 12) and <tt>year</tt> (4
5541 + * digit year). Initially the current month is displayed.
5542 + *
5543 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
5544 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
5545 + * refined to restrict to a given space, or to a given search criteria, etc.
5546 + * @param entries The resulting list of entries to display, a list of XDocument names.
5547 + * @param queryParams The parameters to bind with the query.
5548 + *###
5549 +#macro(getMonthlyBlogEntries $blogDoc $query $entries)
5550 + #if (!$entries)
5551 + #setVariable (~"$entries~" [])
5552 + #end
5553 + #getRequestedMonth($monthDate)
5554 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
5555 + #set($minDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundFloor()))
5556 + #set($maxDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundCeiling()))
5557 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
5558 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
5559 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
5560 + #bindQueryParameters($countQueryObj $queryParams)
5561 + #bindQueryParameters($queryObj $queryParams)
5562 + #set($totalEntries = $countQueryObj.count())
5563 + #set($discard = $entries.addAll($queryObj.execute()))
5564 +#end
5565 +##
5566 +##
5567 +##
5568 +#**
5569 + * Retrieves a list of entries to be displayed. All entries belonging to the current blog are returned.
5570 + *
5571 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
5572 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
5573 + * refined to restrict to a given space, or to a given search criteria, etc.
5574 + * @param entries The resulting list of entries to display, a list of XDocument names.
5575 + * @param queryParams The parameters to bind with the query.
5576 + *###
5577 +#macro(getAllBlogEntries $blogDoc $query $entries $queryParams)
5578 + #if (!$entries)
5579 + #setVariable (~"$entries~" [])
5580 + #end
5581 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
5582 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
5583 + #bindQueryParameters($countQueryObj $queryParams)
5584 + #bindQueryParameters($queryObj $queryParams)
5585 + #set($totalEntries = $countQueryObj.count())
5586 + #set($discard = $entries.addAll($queryObj.execute()))
5587 +#end
5588 +##
5589 +##
5590 +##
5591 +#**
5592 + * Retrieves a list of entries to be displayed. Only (and all) unpublished entries are returned.
5593 + *
5594 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
5595 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
5596 + * refined to restrict to a given space, or to a given search criteria, etc.
5597 + * @param queryParams The parameters to bind with the query.
5598 + * @param entries The resulting list of entries to display, a list of XDocument names.
5599 + *###
5600 +#macro(getUnpublishedBlogEntries $blogDoc $query $queryParams $entries)
5601 + #if (!$entries)
5602 + #setVariable (~"$entries~" [])
5603 + #end
5604 + #set($query = ~"$\{query} and isPublished.value = 0~")
5605 + #set ($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
5606 + #set ($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
5607 + #bindQueryParameters($countQueryObj $queryParams)
5608 + #bindQueryParameters($queryObj $queryParams)
5609 + #set($totalEntries = $countQueryObj.count())
5610 + #set($discard = $entries.addAll($queryObj.execute()))
5611 +#end
5612 +##
5613 +##
5614 +##
5615 +#**
5616 + * Retrieves a list of entries to be displayed. The entries are taken from all the wiki, and not from a specific blog.
5617 + *
5618 + * @param entries The resulting list of entries to display, a list of XDocument names.
5619 + *###
5620 +#macro(getGlobalBlogEntries $entries)
5621 + #if (!$entries)
5622 + #setVariable (~"$entries~" [])
5623 + #end
5624 + #getAllBlogPostsQuery($query)
5625 + #set($totalEntries = $services.query.hql($query).count())
5626 + #set($defaultItemsPerPage = 20)
5627 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
5628 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
5629 + #set($discard = $entries.addAll($services.query.hql(~"$\{query} order by publishDate.value desc~").setLimit($itemsPerPage).setOffset($startAt).execute()))
5630 +#end
5631 +#**
5632 + * Return the base query for selecting blog entries. It filters only visible entries, but does not bind to a specific
5633 + * blog, nor specify a range or an ordering criteria.
5634 + *
5635 + * This macro is a duplicate of #getAllBlogPostsQuery($query). Keep it in case it's used outside, in custom code.
5636 + *
5637 + * @param query The basic query for selecting blog entries.
5638 + *#
5639 +#macro(getBlogEntriesBaseQuery $query)
5640 + #getAllBlogPostsQuery($query)
5641 +#end
5642 +#**
5643 + * Return the Query for selecting the all wiki blog posts without filtering
5644 + *
5645 + * @param query The basic query for selecting blog entries.
5646 + *#
5647 +#macro(getAllBlogPostsQuery $query)
5648 + #set ($query = $NULL)
5649 + #setVariable(~"$query~" ~", BaseObject as obj, IntegerProperty isPublished,
5650 + IntegerProperty hidden, DateProperty publishDate
5651 + where doc.fullName <> '$blogPostTemplate' and
5652 + obj.name=doc.fullName and obj.className='$blogPostClassname' and
5653 + isPublished.id.id = obj.id and isPublished.id.name = 'published' and
5654 + hidden.id.id = obj.id and hidden.id.name='hidden' and
5655 + publishDate.id.id = obj.id and publishDate.id.name='publishDate' and
5656 + (doc.creator = '$escapetool.sql($xcontext.user)' or (isPublished.value = 1 and hidden.value = 0))~")
5657 +#end
5658 +##
5659 +##
5660 +##
5661 +###**
5662 + * Return the Query for selecting the all wiki blog posts with categories filtering
5663 + *
5664 + * @param query The basic query for selecting blog entries.
5665 + *###
5666 +#macro(getCategoryAllBlogPostsQuery $query)
5667 + #set ($query = $NULL)
5668 + #getAllBlogPostsQuery($baseQuery)
5669 + #set ($baseQuery = $baseQuery.replace('DateProperty publishDate', 'DateProperty publishDate, DBStringListProperty as category left join category.list catList'))
5670 + #setVariable(~"$query~" ~"$\{baseQuery} and obj.id=category.id.id and category.id.name='category'~")
5671 +#end
5672 +##
5673 +##
5674 +##
5675 +#**
5676 + * Determines how is the blog index split into pages: paginated (fixed number of entries), weekly (all entries in a
5677 + * week), monthly (all entries in a month), or all.
5678 + *
5679 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>displayType</tt>
5680 + * property set.
5681 + * @param displayType The resulting string. If the blog object does not define anything, it is considered paginated.
5682 + *###
5683 +#macro(getBlogDisplayType $blogDoc $displayType)
5684 + #getBlogProperty($blogDoc 'displayType' 'paginated' $result)
5685 + #set ($displayType = $NULL)
5686 + #setVariable (~"$displayType~" $result)
5687 +#end
5688 +##
5689 +##
5690 +##
5691 +#**
5692 + * Displays a list of entries.
5693 + *
5694 + * @param entries The entries to display, a list of XDocument names.
5695 + * @param displaying What exactly is displayed: blog index, a single blog entry, a blog category, search results,
5696 + * unpublished entries, etc. This will be used as the classname(s) for the container div (hfeed). Currently
5697 + * used values: index, single, category, search, unpublished, hidden.
5698 + * @param onlyExtract If <tt>true</tt>, only display the extract of articles where available, otherwise display the full content.
5699 + * @param shouldDisplayTitles If <tt>true</tt>, display the blog title (blog posts shouldn't display the title when they're
5700 + * displayed alone on their page since it's the page title which is used in this case)
5701 + *###
5702 +#macro(displayBlog $entries $displaying $onlyExtract $shouldDisplayTitles)
5703 + #set($blogDay = '')
5704 + (% class=~"hfeed $!\{displaying}~" ~%)(((
5705 + (% class=~"blogDay~" ~%)(((
5706 + #foreach ($entryDoc in $xwiki.wrapDocs($entries))
5707 + #getEntryObject($entryDoc $entryObj)
5708 + ## Although all entries should have one of the two objects, better check to be sure.
5709 + #if(~"$!\{entryObj}~" != '')
5710 + #getEntryDate($entryDoc $entryObj $entryDate)
5711 + ## Display a ~"calendar sheet~" for each day. All entries posted on the same day share one such sheet.
5712 + #set($entryDateStr = $xwiki.formatDate($entryDate, 'yyyyMMMMdd'))
5713 + #if($blogDay != $entryDateStr)
5714 + #if($blogDay != '')
5715 + )))
5716 + (% class=~"blogDay~" ~%)(((
5717 + #end
5718 + #displayBlogDate($entryDate)
5719 + #set ($blogDay = $entryDateStr)
5720 + #end
5721 + ## Finally, display the entry.
5722 + #displayEntry($entryDoc $entryObj $onlyExtract $shouldDisplayTitles true)
5723 + #end
5724 + #end
5725 + )))## blogDay
5726 + )))## hfeed
5727 +#end
5728 +##
5729 +##
5730 +##
5731 +#**
5732 + * Get the entry object, either a new BlogPost or an old Article.
5733 + *
5734 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
5735 + * @param entryObj The resulting xobject of the blog post.
5736 + *###
5737 +#macro(getEntryObject $entryDoc $__entryObj)
5738 + #set($result = $entryDoc.getObject(~"$\{blogPostClassname}~"))
5739 + #if(!$result)
5740 + #set($result = $entryDoc.getObject(~"$\{oldArticleClassname}~"))
5741 + #end
5742 + ## NOTE: The reason we put an underscore in front of the variable name is to prevent the following line from
5743 + ## overwriting the $entryObj variable that may be defined before this macro is called. Of course, $__entryObj may be
5744 + ## overwritten in this case but it's less likely to have such a variable defined before.
5745 + #set ($__entryObj = $NULL)
5746 + #setVariable (~"$__entryObj~" $result)
5747 +#end
5748 +##
5749 +##
5750 +##
5751 +#**
5752 + * Gets the date associated with a blog entry. This is the publication date. For unpublished entries, initially this is
5753 + * the document creation date, but can be edited by the user.
5754 + *
5755 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
5756 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
5757 + * @param result The resulting date, an instance of <tt>java.util.Date</tt>.
5758 + *###
5759 +#macro(getEntryDate $entryDoc $entryObj $result)
5760 + #set ($result = $NULL)
5761 + #setVariable (~"$result~" $entryObj.getProperty('publishDate').value)
5762 +#end
5763 +##
5764 +##
5765 +##
5766 +#**
5767 + * Displays a date, nicely formatted as a calendar page.
5768 + *
5769 + * @param date The date to display, an instance of <tt>java.util.Date</tt>.
5770 + *###
5771 +#macro(displayBlogDate $date)
5772 + #set($year = $xwiki.formatDate($date, 'yyyy'))
5773 + ## 3 letter month name, like Jan, Dec.
5774 + #set($month = $xwiki.formatDate($date, 'MMM'))
5775 + ## Uncomment to get a full length month name, like January, December.
5776 + ## TODO: this could be defined somewhere in the blog style.
5777 + ## #set($month = $xwiki.formatDate($date, 'MMMM'))
5778 + #set($day = $xwiki.formatDate($date, 'dd'))
5779 + (% class=~"blogdate~" ~%)
5780 + == (% class=~"month~" ~%)$month(%~%) (% class=~"day~" ~%)$day(%~%) (% class=~"year~" ~%)$year(%~%) ==
5781 +#end
5782 +##
5783 +##
5784 +##
5785 +#**
5786 + * Displays a blog article: management tools, header, content, footer.
5787 + *
5788 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
5789 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
5790 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
5791 + * @param shouldDisplayTitle If <tt>true</tt>, display the blog title (blog posts shouldn't display the title
5792 + * when they're displayed alone on their page since it's the page title which is used in this case)
5793 + * @param shouldDisplayActions If <tt>true</tt>, display the blog post actions buttons
5794 + *###
5795 +#macro(displayEntry $entryDoc $entryObj $onlyExtract $shouldDisplayTitle $shouldDisplayActions)
5796 + ## Only articles with an explicit hidden setting or an explicit unpublished setting are hidden
5797 + #isPublished($entryObj $isPublished)
5798 + #isHidden($entryObj $isHidden)
5799 + #if($doc.fullName == $entryDoc.fullName)
5800 + (% class=~"hentry single-article~" ~%)(((
5801 + #else
5802 + (% class=~"hentry#if(!$isPublished) unpublished-article#elseif($isHidden) hidden-article#end~" ~%)(((
5803 + #end
5804 + #if ($shouldDisplayActions)
5805 + #displayEntryTools($entryDoc $entryObj)
5806 + #end
5807 + #if($shouldDisplayTitle)
5808 + #displayEntryTitle($entryDoc $entryObj)
5809 + #end
5810 + #if($doc.fullName == $entryDoc.fullName)
5811 + #if(!$isPublished)
5812 + \{\{warning}}\{\{translation key='blog.code.published'/}}\{\{/warning}}
5813 + #elseif($isHidden)
5814 + \{\{warning}}\{\{translation key='blog.code.hidden'/}}\{\{/warning}}
5815 + #end
5816 + #end
5817 + #displayEntryContent($entryDoc $entryObj $onlyExtract)
5818 + #displayEntryFooter($entryDoc $entryObj)
5819 + )))## hentry
5820 +#end
5821 +##
5822 +##
5823 +##
5824 +#**
5825 + * Checks if the provided blog is published or not.
5826 + *
5827 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
5828 + * @param isPublished The resulting boolean, true if the entry is considered published.
5829 + *###
5830 +#macro(isPublished $entryObj $isPublished)
5831 + #set ($isPublished = $NULL)
5832 + ## This should work for both old articles, which don't have the 'published' property at all, and
5833 + ## are considered published by default, and new entries, that should have 1 if published.
5834 + #if (~"$!\{entryObj.getProperty('published').value}~" != '0')
5835 + #setVariable (~"$isPublished~" true)
5836 + #else
5837 + #setVariable (~"$isPublished~" false)
5838 + #end
5839 +#end
5840 +##
5841 +##
5842 +##
5843 +#**
5844 + * Checks if the provided blog is hidden or not.
5845 + *
5846 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass<tt> xclass.
5847 + * @param isHiddel The resulting boolean, true if the entry is considered hidden.
5848 + *###
5849 +#macro(isHidden $entryObj $isHidden)
5850 + #set ($isHidden = $NULL)
5851 + ## This should work for both old articles, which don't have the 'hidden' property at all, and
5852 + ## are considered visible by default, and new entries, that should have 1 if hidden.
5853 + #if (~"$!\{entryObj.getProperty('hidden').value}~" == '1')
5854 + #setVariable (~"$isHidden~" true)
5855 + #else
5856 + #setVariable (~"$isHidden~" false)
5857 + #end
5858 +#end
5859 +##
5860 +##
5861 +##
5862 +#**
5863 + * Displays several ~"tools~" for manipulating blog posts: hide/show, publish, edit.
5864 + *
5865 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
5866 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
5867 + *###
5868 +#macro(displayEntryTools $entryDoc $entryObj)
5869 + #if($xcontext.action == 'view')
5870 + (% class=~"blog-entry-toolbox~" ~%)(((
5871 + #displayPublishButton($entryDoc $entryObj)
5872 + #displayHideShowButton($entryDoc $entryObj)
5873 + #displayEditButton($entryDoc $entryObj)
5874 + #displayDeleteButton($entryDoc $entryObj)
5875 + )))
5876 + #end
5877 +#end
5878 +##
5879 +##
5880 +##
5881 +#**
5882 + * Displays the publish button to the entry <strong>creator</strong>, if the article is not published yet.
5883 + *
5884 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
5885 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
5886 + * @todo AJAX calls.
5887 + *###
5888 +#macro(displayPublishButton $entryDoc $entryObj)
5889 + #isPublished($entryObj $isPublished)
5890 + #if(!$isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
5891 + [[#toolImage('world')>>path:$blogPublisher.getURL('view', ~"entryName=$\{escapetool.url($entryDoc.fullName)}&xredirect=$\{escapetool.url($thisURL)}&form_token=$!\{services.csrf.getToken()}~")||title=~"$services.localization.render('blog.code.notpublished')~"]]##
5892 + #end
5893 +#end
5894 +##
5895 +##
5896 +##
5897 +#**
5898 + * Displays the hide or show button to the entry <strong>creator</strong>, if the article is already published.
5899 + *
5900 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
5901 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
5902 + *###
5903 +#macro(displayHideShowButton $entryDoc $entryObj)
5904 + #isPublished($entryObj $isPublished)
5905 + #isHidden($entryObj $isHidden)
5906 + ## Only published articles can be hidden. Unpublished articles are considered already hidden.
5907 + #if($isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
5908 + #set ($queryString = \{
5909 + 'xredirect' : $thisURL,
5910 + 'form_token' : $services.csrf.getToken()
5911 + })
5912 + #if ($isHidden)
5913 + #set ($discard = $queryString.putAll(\{
5914 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 0,
5915 + 'comment' : $services.localization.render('blog.code.madevisible')
5916 + }))
5917 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
5918 + [[#toolImage('unlock')>>path:$lockURL||class=~"blog-tool-show~" title=~"$services.localization.render('blog.code.makevisible')~"]]##
5919 + #else
5920 + #set ($discard = $queryString.putAll(\{
5921 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 1,
5922 + 'comment' : $services.localization.render('blog.code.hid')
5923 + }))
5924 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
5925 + [[#toolImage('lock')>>path:$lockURL||class=~"blog-tool-hide~" title=~"$services.localization.render('blog.code.hide')~"]]##
5926 + #end
5927 + #end
5928 +#end
5929 +##
5930 +##
5931 +##
5932 +#**
5933 + * Displays the edit button to those that can edit the article.
5934 + *
5935 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
5936 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
5937 + *###
5938 +#macro(displayEditButton $entryDoc $entryObj)
5939 + #if($xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
5940 + ## Call getDefaultEditMode() for backward compatibility with older blog posts.
5941 + [[#toolImage('pencil')>>path:$entryDoc.getURL('edit')||title=~"$services.localization.render('blog.code.editpost')~"]]##
5942 + #end
5943 +#end
5944 +##
5945 +##
5946 +##
5947 +#**
5948 + * Displays the delete button to those that can edit the article.
5949 + *
5950 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
5951 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
5952 + * @todo AJAX calls.
5953 + *###
5954 +#macro(displayDeleteButton $entryDoc $entryObj)
5955 + #if($xwiki.hasAccessLevel('delete', $xcontext.user, $entryDoc.fullName))
5956 + [[#toolImage('cross')>>path:$entryDoc.getURL('delete')||title=~"$services.localization.render('blog.code.deletepost')~"]]##
5957 + #end
5958 +#end
5959 +##
5960 +##
5961 +##
5962 +#**
5963 + * Displays the title of the entry.
5964 + *
5965 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
5966 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
5967 + *###
5968 +#macro(displayEntryTitle $entryDoc $entryObj)
5969 + #if($doc.fullName == $entryDoc.fullName)
5970 + (% class=~"entry-title~" ~%)
5971 + = $services.rendering.escape($entryDoc.display('title', 'view', $entryObj), $xwiki.getCurrentContentSyntaxId()) =
5972 + #else
5973 + (% class=~"entry-title~" ~%)
5974 + === [[$services.rendering.escape($entryDoc.display('title', 'view', $entryObj),$xwiki.getCurrentContentSyntaxId())>>doc:$services.rendering.escape($services.model.serialize($entryDoc.getDocumentReference(),'default'),$xwiki.getCurrentContentSyntaxId())]] ===
5975 + #end
5976 +#end
5977 +##
5978 +##
5979 +##
5980 +#**
5981 + * Displays the body of the entry.
5982 + *
5983 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
5984 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
5985 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
5986 + *###
5987 +#macro(displayEntryContent $entryDoc $entryObj $onlyExtract)
5988 + (% class=~"#if($onlyExtract)entry-summary#\{else}entry-content#end~" ~%)(((
5989 + #getEntryContent($entryDoc $entryObj $onlyExtract $entryContent)
5990 + ## FIXME: This causes the blog's content to not be annotatable. See http://jira.xwiki.org/browse/XWIKI-6328
5991 + ## Should probably be replaced by a display macro call with a reference to the object property holding the post's content
5992 + \{\{html wiki=~"false~"}}$entryDoc.getRenderedContent($entryContent, $entryDoc.syntax.toIdString())\{\{/html}}
5993 + ))) ## entry-content
5994 + (% class=~"clearfloats~" ~%)((()))
5995 +#end
5996 +##
5997 +##
5998 +##
5999 +#**
6000 + * Extracts the body of the entry that should be displayed. If <tt>onlyExtract</tt> is <tt>true</tt>, display the content
6001 + * of the <tt>extract</tt> field (if not empty).
6002 + *
6003 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
6004 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
6005 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
6006 + * @param entryContent The resulting content.
6007 + * @param removeEllipsis If <tt>true</tt>, then don't display an ellipsis at the end of the content (only used when
6008 + * <tt>onlyExtract</tt> is <tt>true</tt>)
6009 + *###
6010 +#macro(getEntryContent $entryDoc $entryObj $onlyExtract $entryContent $removeEllipsis)
6011 + #if ($onlyExtract)
6012 + ## Note: We trim the summary so that if there's some white space it won't cause the summary to be used instead
6013 + ## of the content.
6014 + #set ($macro.result = $entryObj.getProperty('extract').value.trim())
6015 + #end
6016 + #if(~"$!macro.result~" == '')
6017 + #set($macro.result = $entryObj.getProperty('content').value)
6018 +#* Disabled until the content can be cleanly cut.
6019 +* #if($onlyExtract && $result.length()>$maxchars)
6020 +* #set($i = $macro.result.lastIndexOf(~" ~", $maxchars))
6021 +* #set($i = $i + 1)
6022 +* #set($macro.result = ~"$\{macro.result.substring(0,$i)} *[...>$\{entryDoc.fullName}]*~")
6023 +* #end
6024 +## *###
6025 + #elseif (!$removeEllipsis)
6026 + #if($entryDoc.syntax.toIdString() == 'xwiki/1.0')
6027 + #set($macro.result = ~"$\{macro.result} <a href='$\{entryDoc.getExternalURL()}' title='$services.localization.render('blog.code.readpost')'>...</a>~")
6028 + #elseif($entryDoc.syntax.toIdString() == 'xwiki/2.0' || $entryDoc.syntax.toIdString() == 'xwiki/2.1')
6029 + #set($macro.result = ~"$\{macro.result} [[...>>$\{services.rendering.escape($entryDoc.getFullName(), $entryDoc.getSyntax())}||title='$services.localization.render('blog.code.readpost')']]~")
6030 + #end
6031 + #end
6032 + #set ($entryContent = $NULL)
6033 + #setVariable (~"$entryContent~" $macro.result)
6034 +#end
6035 +##
6036 +##
6037 +##
6038 +#**
6039 + * Displays the footer of the entry.
6040 + *
6041 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
6042 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
6043 + *###
6044 +#macro(displayEntryFooter $entryDoc $entryObj)
6045 + (% class=~"entry-footer~" ~%)(((
6046 + #isPublished($entryObj $isPublished)
6047 + (% class='entry-author-label' ~%)
6048 + #if($isPublished)
6049 + \{\{translation key='blog.code.postedby'/}} ##
6050 + #else
6051 + \{\{translation key='blog.code.createdby'/}} ##
6052 + #end
6053 + \{\{html wiki=~"false~" clean=~"false~"}}<span class='author vcard'>#userfn($entryDoc.creator)</span>\{\{/html}} ##
6054 + #getEntryDate($entryDoc $entryObj $entryDate)
6055 + #listCategories($entryObj) #*
6056 + ## Since the publish date and update date are not set at the exact same time, there could be a small difference that
6057 + ## we assume cannot be more than 3 seconds.
6058 + *#(% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.permalink'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||rel=~"bookmark~"]] ##
6059 + #if ($showcomments)
6060 + (% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.comments'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||anchor=~"Comments~"]] (% class=~"itemCount~" ~%)($entryDoc.comments.size())(%~%) ##
6061 + #end ##
6062 + #if($entryDoc != $doc) ##
6063 + #displayEntryBlogLocation($entryDoc $entryObj) ##
6064 + #end
6065 + )))## entry-footer
6066 +#end
6067 +##
6068 +##
6069 +#**
6070 + * Display the blog for the entry (if it is not the currently displayed blog)
6071 + *
6072 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
6073 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
6074 + *###
6075 +#macro(displayEntryBlogLocation $entryDoc $entryObj)
6076 + #getBlogPostsLocation($entryDoc.getSpace() $blogPostsLocation) ##
6077 + #if(~"$!blogPostsLocation~" != ~"~") ##
6078 + #set($blogSpaceRef = $services.model.resolveSpace($blogPostsLocation)) ##
6079 + #set($blogDocRef = $services.model.createDocumentReference($services.model.getEntityReference('DOCUMENT', 'default').getName(), $blogSpaceRef)) ##
6080 + #if($doc.documentReference != $blogDocRef) ##
6081 + #set($blogDoc = $xwiki.getDocument($blogDocRef)) ##
6082 + #set($blogObj = $blogDoc.getObject('Blog.BlogClass')) ##
6083 + #if($blogObj) (% class=~"blogrefpath~" ~%)((( ##
6084 + $services.localization.render('blog.code.postedin') \{\{html clean=~"false~" wiki=~"false~"}} #hierarchy($blogDocRef, \{'selfIsActive' : true, 'local': true}) \{\{/html}} ##
6085 + )))(%~%)##
6086 + #end
6087 + #end
6088 + #end
6089 +#end
6090 +##
6091 +##
6092 +##
6093 +##
6094 +#**
6095 + * List the categories an entry belongs to. Used in the footer. The categories are instances of <tt>Blog.CategoryClass</tt>.
6096 + *
6097 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
6098 + *###
6099 +#macro(listCategories $entryObj)
6100 + #if($entryObj.getxWikiClass().getName() == $blogPostClassname)
6101 + #set($categories = $entryObj.getProperty('category').value)
6102 + #set($first = true)
6103 + #if($categories.size() > 0)
6104 + #foreach($category in $categories)
6105 + #set($categoryDoc = $!xwiki.getDocument($category))
6106 + #if(!$categoryDoc.isNew() && $categoryDoc.getObject($\{blogCategoryClassname}))
6107 + #if($foreach.count == 1)
6108 + (% class='separator' ~%)·(%~%) $services.localization.render('blog.code.categories') ##
6109 + #else
6110 + , ##
6111 + #end##
6112 + [[$!\{categoryDoc.getObject($blogCategoryClassname).getValue('name')}>>$\{category}||rel='tag']]##
6113 + #end##
6114 + #end##
6115 + #end
6116 + #end
6117 +#end
6118 +##
6119 +##
6120 +##
6121 +#**
6122 + * Displays blog pagination links (older and newer entries).
6123 + *
6124 + * @param blogDoc the XDocument holding the blog definition object.
6125 + *###
6126 +#macro(displayNavigationLinks $blogDoc)
6127 + (% class=~"clearfloats~" ~%)((()))
6128 + #getBlogDisplayType($blogDoc $displayType)
6129 + #if($displayType == 'weekly')
6130 + (% class=~"pagingLinks~" ~%)(((
6131 + #getRequestedWeek($weekDate)
6132 + $weekDate.addWeeks(-1)##
6133 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousweek'/}}>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
6134 + #sep()
6135 + $weekDate.addWeeks(2)## 2 because we already subtracted 1 above
6136 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextweek'/}} »>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
6137 + )))
6138 + #elseif($displayType == 'monthly')
6139 + (% class=~"pagingLinks~" ~%)(((
6140 + #getRequestedMonth($monthDate)
6141 + $monthDate.addMonths(-1)##
6142 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousmonth'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
6143 + #sep()
6144 + $monthDate.addMonths(2)## 2 because we already subtracted 1 above
6145 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextmonth'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
6146 + )))
6147 + #elseif($displayType == 'all')
6148 + #else
6149 + ## Paginated
6150 + #if(($totalPages > 1))
6151 + #set($queryString = '')
6152 + #foreach($p in $request.getParameterNames())
6153 + #if($p != 'page' && $p != 'ipp')
6154 + #foreach($v in $request.getParameterValues($p))
6155 + #set($queryString = ~"$\{queryString}&$\{escapetool.url($p)}=$\{escapetool.url($v)}~")
6156 + #end
6157 + #end
6158 + #end
6159 + (% class=~"pagingLinks~" ~%)(((
6160 + #if ($currentPageNumber < $totalPages)
6161 + #set($currentPageNumber = $currentPageNumber + 1)
6162 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.olderposts'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
6163 + #set($currentPageNumber = $currentPageNumber - 1)
6164 + #end
6165 + #if ($currentPageNumber > 1)
6166 + #if ($currentPageNumber < $totalPages)
6167 + #sep()
6168 + #end
6169 + #set($currentPageNumber = $currentPageNumber - 1)
6170 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.newerposts'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
6171 + #set($currentPageNumber = $currentPageNumber + 1)
6172 + #end
6173 + (% class=~"clear~" ~%)(%~%)
6174 + )))## pagingLinks
6175 + #end
6176 + #end
6177 +#end
6178 +##
6179 +##
6180 +##
6181 +#**
6182 + * Displays a message box with ~"publish~" icon.
6183 + *
6184 + * @param message A text message concerning blog article publishing
6185 + *###
6186 +#macro(publishMessageBox $message)
6187 +(% class=~"plainmessage publish-message~" ~%)((($services.icon.render('world') $message)))
6188 +#end
6189 +#**
6190 + * Displays a message box with ~"show/hide~" icon.
6191 + *
6192 + * @param message A text message concerning blog article hiding
6193 + *###
6194 +#macro(hideMessageBox $message)
6195 +(% class=~"plainmessage hide-message~" ~%)((($services.icon.render('unlock') $message)))
6196 +#end
6197 +##
6198 +##
6199 +##
6200 +#**
6201 + * Determine the requested week, for using in a weekly-indexed blog. The relevant request parameters are
6202 + * <tt>year</tt> and <tt>week</tt>. By default, the current week is used.
6203 + *
6204 + * @param monthDate The resulting week, a JODATime MutableDateTime.
6205 + *###
6206 +#macro(getRequestedWeek $weekDate)
6207 + #set ($weekDate = $NULL)
6208 + #setVariable (~"$weekDate~" $xwiki.jodatime.mutableDateTime)
6209 + #if(~"$!\{request.year}~" != '')
6210 + #set ($discard = $weekDate.setYear($numbertool.toNumber($request.year).intValue()))
6211 + #end
6212 + #if(~"$!\{request.week}~" != '')
6213 + #set ($discard = $weekDate.setWeekOfWeekyear($numbertool.toNumber($request.week).intValue()))
6214 + #end
6215 +#end
6216 +##
6217 +##
6218 +##
6219 +#**
6220 + * Determine the requested month, for using in a monthly-indexed blog. The relevant request parameters are
6221 + * <tt>year</tt> and <tt>month</tt>. By default, the current month is used.
6222 + *
6223 + * @param monthDate The resulting month, a JODATime MutableDateTime.
6224 + *###
6225 +#macro(getRequestedMonth $monthDate)
6226 + #set ($monthDate = $NULL)
6227 + #setVariable (~"$monthDate~" $xwiki.jodatime.mutableDateTime)
6228 + #if(~"$!\{request.year}~" != '')
6229 + #set ($discard = $monthDate.setYear($numbertool.toNumber($request.year).intValue()))
6230 + #end
6231 + #if(~"$!\{request.month}~" != '')
6232 + #set ($discard = $monthDate.setMonthOfYear($numbertool.toNumber($request.month).intValue()))
6233 + #end
6234 +#end
6235 +##
6236 +##
6237 +##
6238 +#**
6239 + * Retrieve a blog property (title, display type, etc).
6240 + *
6241 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
6242 + * @param propertyName The name of the property to be retrieved. One of the <tt>Blog.BlogClass</tt>'s properties.
6243 + * @param defaultValue The default value to use in case the blog object does not define one.
6244 + * @param propertyValue The resulting value.
6245 + *###
6246 +#macro(getBlogProperty $blogDoc $propertyName $defaultValue $propertyValue)
6247 + #set($result = ~"$!\{blogDoc.getObject($\{blogClassname}).getProperty($propertyName).value}~")
6248 + #if($result == '')
6249 + #set($result = $defaultValue)
6250 + #end
6251 + #set ($propertyValue = $NULL)
6252 + #setVariable (~"$propertyValue~" $result)
6253 +#end
6254 +
6255 +#**
6256 + * If an error occurs when executing an action, set a specific response status and display an error message.
6257 + *
6258 + * @param status The response status.
6259 + * @param text The user readable error to be displayed. Can be a translation key.
6260 + * @param parameters The parameters to use when decoding the translation key.
6261 + *###
6262 +#macro(blog__actionResponseError $status $text $parameters)
6263 + $response.setStatus($status)
6264 + #if($request.ajax)
6265 + $services.localization.render($text, $!parameters)
6266 + #else
6267 + \{\{error}}$services.localization.render($text, $!parameters)\{\{/error}}
6268 + #end
6269 +#end
6270 +##
6271 +##
6272 +##
6273 +#**
6274 + * Check if a blog is the Default blog (The one in the 'Blog' space).
6275 + *
6276 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
6277 + * @param isDefault The resulting boolean.
6278 + *###
6279 +#macro(isDefaultBlog $blogDoc $isDefault)
6280 + #set ($result = false)
6281 + #if ($blogDoc.space == 'Blog')
6282 + #set ($result = true)
6283 + #end
6284 + #setVariable(~"$isDefault~" $result)
6285 +#end
6286 +##
6287 +##
6288 +##
6289 +#**
6290 + * Retrieve the blog posts location (space).
6291 + *
6292 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
6293 + * @param postsLocation The resulting location.
6294 + *###
6295 +#macro(getBlogPostsLocation $blogSpace $postsLocation)
6296 + #getBlogDocument($blogSpace $blogDoc)
6297 + #getBlogProperty($blogDoc 'postsLocation' $blogDoc.space $result)
6298 + #set ($postsLocation = $NULL)
6299 + #setVariable (~"$postsLocation~" $result)
6300 +#end
6301 +##
6302 +##
6303 +##
6304 +#**
6305 + * Retrieve the blog categories location (space).
6306 + *
6307 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
6308 + * @param categoriesLocation The resulting location.
6309 + *###
6310 +#macro(getBlogCategoriesLocation $blogSpace $categoriesLocation)
6311 + #getBlogDocument($blogSpace $blogDoc)
6312 + #getBlogProperty($blogDoc 'categoriesLocation' 'Blog' $result)
6313 + #set ($postsLocation = $NULL)
6314 + #setVariable (~"$categoriesLocation~" $result)
6315 +#end
6316 +###**
6317 + * Return the Query for selecting the blog posts based on the context where the posts are displayed.
6318 + * for example there is 4 different panel contexts:
6319 + * aBlog.aPost or aBlog.WebHome
6320 + * aCategorySpace.aCategory
6321 + * aCategorySpace.WebHome
6322 + * Blog.aPost or Blog.WebHome
6323 + *
6324 + * @param query The query for selecting blog entries.
6325 + * @param queryParams The parameters to bind with the generated query.
6326 + * @param targetDoc The document in which the articles will be displayed.
6327 + *###
6328 +#macro(getAllBlogPostsQueryBasedOnDisplayContext $targetDoc $query $queryParams)
6329 + #set ($query = $NULL)
6330 + #set ($queryParams = $NULL)
6331 + #getCategoryAllBlogPostsQuery($resultQuery)
6332 + #set ($resultQueryParams = \{})
6333 + #set($sanitizedSpace = $targetDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
6334 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
6335 + ## Get all posts that are in the default blog space('Blog') or in category 'Blog.%'
6336 + #set ($discard = $resultQueryParams.put('space', $targetDoc.space))
6337 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
6338 + #set($resultQuery = ~"$\{resultQuery} and (doc.space = :space or catList like :catList escape '!')~")
6339 + #elseif($targetDoc.getObject($blogCategoryClassname))
6340 + ## Get all posts that are in a category aCategorySpace.aCategory
6341 + #set ($discard = $resultQueryParams.put('catList', $targetDoc.fullName))
6342 + #set($resultQuery = ~"$\{resultQuery} and (catList=:catList)~")
6343 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
6344 + ## Get all posts that are in a category aCategorySpace.%
6345 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
6346 + ## Exclude incategorized posts
6347 + #set ($excludedCategory = ~"$\{targetDoc.space}.WebHome~")
6348 + #if ($targetDoc.space == $defaultBlogSpace)
6349 + #set ($excludedCategory = ~"Blog.Categories.WebHome~")
6350 + #end
6351 + #set ($discard = $resultQueryParams.put('excludedCategory', $excludedCategory))
6352 + #set($resultQuery = ~"$\{resultQuery} and (catList<>:excludedCategory) and (catList like :catList escape '!')~")
6353 + #else
6354 + ## Get all posts in blog space aBlog
6355 + #getAllBlogPostsQuery($resultQuery)
6356 + #getBlogPostsLocation($targetDoc.space $postsLocation)
6357 + #set ($discard = $resultQueryParams.put('space', $postsLocation))
6358 + #set($resultQuery = ~"$\{resultQuery} and doc.space = :space~")
6359 + #end
6360 + #setVariable(~"$query~" $resultQuery)
6361 + #setVariable(~"$queryParams~" $resultQueryParams)
6362 +#end
6363 +##
6364 +##
6365 +##
6366 +###**
6367 + * Display blog posts based on the context where the posts are displayed.
6368 + * for example there is 4 different panel contexts:
6369 + * aBlog.aPost or aBlog.WebHome
6370 + * aCategorySpace.aCategory
6371 + * aCategorySpace.WebHome
6372 + * Blog.aPost or Blog.WebHome
6373 + *
6374 + * @param targetDoc The document in which the articles will be displayed.
6375 + * @param postsVisiblity The visibility of the posts to display: recent, unpublished, ...
6376 + * @param layout Layout of the the posts to display
6377 + * @param layoutParams additional layout parameters, it is a string like 'param1=val1|...|paramN=valueN'
6378 + * @param limit the number of posts to display
6379 + *###
6380 +#macro(displayBlogPostsBasedOnContext $targetDoc $postsVisiblity $layout $layoutParams $limit)
6381 + #if ($postLayout == 'full')
6382 + #set ($macro.paginated = 'yes')
6383 + #end
6384 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
6385 + ## Display all posts that are in the default blog space('Blog') or in category 'Blog.%'
6386 + #getBlogPostsLayout($xwiki.getDocument(~"$\{defaultBlogSpace}.WebHome~") $postsLayout)
6387 + #if (~"$!layout~" == '')
6388 + #set ($layout = $postsLayout)
6389 + #end
6390 + #if ($postsVisiblity == 'recent')
6391 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
6392 + #elseif($postsVisiblity == 'unpublished')
6393 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
6394 + #end
6395 + #elseif($targetDoc.getObject($blogCategoryClassname))
6396 + ## Display all posts that are in a category aCategorySpace.aCategory
6397 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
6398 + #getBlogPostsLayout($blogDoc $postsLayout)
6399 + #if (~"$!layout~" == '')
6400 + #set ($layout = $postsLayout)
6401 + #end
6402 + #if ($postsVisiblity == 'recent')
6403 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
6404 + #elseif($postsVisiblity == 'unpublished')
6405 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
6406 + #end
6407 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
6408 + ## Display all posts that are in a category aCategorySpace.%
6409 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
6410 + #getBlogPostsLayout($blogDoc $postsLayout)
6411 + #if (~"$!layout~" == '')
6412 + #set ($layout = $postsLayout)
6413 + #end
6414 + #if ($postsVisiblity == 'recent')
6415 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
6416 + #elseif($postsVisiblity == 'unpublished')
6417 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
6418 + #end
6419 + #else
6420 + ## Display all posts in blog space aBlog
6421 + #getBlogDocument($targetDoc.space $blogDoc)
6422 + #getBlogPostsLayout($blogDoc $postsLayout)
6423 + #if (~"$!layout~" == '')
6424 + #set ($layout = $postsLayout)
6425 + #end
6426 + #if ($postsVisiblity == 'recent')
6427 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
6428 + #elseif($postsVisiblity == 'unpublished')
6429 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
6430 + #end
6431 + #end
6432 +#end
6433 +##
6434 +##
6435 +##
6436 +#**
6437 + * Bind parameters to a query object.
6438 + *
6439 + * @param queryObj The query object (org.xwiki.query.internal.ScriptQuery object)
6440 + * @param queryParams the query parameters.
6441 + *###
6442 +#macro(bindQueryParameters $queryObj $queryParams)
6443 + #set ($output = $queryObj)
6444 + #foreach( $key in $queryParams.keySet() )
6445 + #set($output = $queryObj.bindValue($key, $queryParams.get($key)))
6446 + #end
6447 + #setVariable(~"$queryObj~" $output)
6448 +#end
6449 +##
6450 +##
6451 +##
6452 +#**
6453 + * Determines the blogposts layout: Default layout (Calendar), Image thumbnail
6454 + *
6455 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>postsLayout</tt>
6456 + * property set.
6457 + * @param postsLayout The resulting string. If the blog object does not define anything, it is considered full (default).
6458 + *###
6459 +#macro(getBlogPostsLayout $blogDoc $postsLayout)
6460 + #getBlogProperty($blogDoc 'postsLayout' 'full' $res)
6461 + #set ($postsLayout = $NULL)
6462 + #setVariable (~"$postsLayout~" $res)
6463 +#end
6464 +##
6465 +##
6466 +##
6467 +#**
6468 + * Retrieve the blog document of a categories space, which is the blog descriptor that have its categoriesLocation property set to the categories space
6469 + *
6470 + * @param categoriesSpace A <tt>String</tt>, the name of the space.
6471 + * @param blogDoc The resulting XDocument.
6472 + *###
6473 +#macro(getBlogDocumentForCategoriesSpace $categoriesSpace $blogDoc)
6474 + #set($macro.blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as categoriesLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=categoriesLocationProp.id.id and categoriesLocationProp.id.name='categoriesLocation' and categoriesLocationProp.value=:categoriesLocation order by doc.creationDate~").setLimit(1).setOffset(0).bindValue('categoriesLocation', $categoriesSpace).execute())
6475 + #if($macro.blogDocs.size() > 0 && $categoriesSpace != $defaultBlogSpace)
6476 + #set($macro.result = $xwiki.getDocument($macro.blogDocs.get(0)))
6477 + #else
6478 + ## Fallback to Blog.WebHome, the default blog
6479 + #set($macro.result = $xwiki.getDocument('Blog.WebHome'))
6480 + #end
6481 + #set ($blogDoc = $NULL)
6482 + #setVariable (~"$blogDoc~" $macro.result)
6483 +#end" %)
6484 +(((
6485 +(% class="macro-placeholder hidden" %)
6486 +(((
6487 +macro:velocity
6488 +)))
6489 +)))
6490 +)))
6491 +
6492 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogPostLayoutMacros~"" %)
6493 +(((
6494 +(% class="macro-placeholder hidden" %)
6495 +(((
6496 +macro:include
6497 +)))
6498 +
6499 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|#**
6500 + * Extract the layout parameters from a string.
6501 + *
6502 + * @param layoutParamsString The string representation of the layout parameters.
6503 + * It should contain a String following this format ~"paramName1=Value1|paramName2=Value2|...|paramNameK=ValueK~"
6504 + * @param layoutsParameters The resulting layout parameters Map.
6505 + *###
6506 +#macro(extractLayoutParametersFromString $layoutParamsString $layoutsParameters)
6507 + #set ($layoutsParameters = $NULL)
6508 + #set ($macro.layoutParams = \{})
6509 + #if (~"$!layoutParamsString~" != '')
6510 + #set ($macro.paramsArr = $layoutParamsString.split('\\|'))
6511 + #foreach ($item in $macro.paramsArr)
6512 + #set ($itemSplit = $item.split('='))
6513 + #if ($itemSplit.size() == 2)
6514 + #set ($discard = $macro.layoutParams.put($itemSplit[0].trim(), $itemSplit[1].trim()))
6515 + #end
6516 + #end
6517 + #end
6518 + #setVariable(~"$layoutsParameters~" $macro.layoutParams)
6519 +#end" %)
6520 +(((
6521 +(% class="macro-placeholder hidden" %)
6522 +(((
6523 +macro:velocity
6524 +)))
6525 +)))
6526 +)))
6527 +
6528 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-| #macro(displaySmallPost $pDoc $pObj)
6529 + #initLayoutVars($pDoc $pObj)
6530 + <div class=~"col-xs-12 col-sm-6 next_blog~">
6531 + <a href=~"$pDoc.uRL~" class=~"thumbnail~">
6532 + <div class=~"row~">
6533 + <div class=~"col-xs-4~">
6534 + #if ($imageAtt)
6535 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
6536 + #end
6537 + </div>
6538 + <div class=~"col-xs-8 art_det~">
6539 + <p class=~"text-left~">
6540 + #if($displayTitle)$!postTitle #end
6541 + <br/><span class=~"date_info~"> $!dateStr </span>
6542 + </p>
6543 + #displayPostDetails($pDoc)
6544 + </div>
6545 + </div>
6546 + </a>
6547 + </div>
6548 + #end
6549 + ##
6550 + ##
6551 + ##
6552 + #macro(displayPinnedPost $pDoc $pObj)
6553 + #initLayoutVars($pDoc $pObj)
6554 + <div class=~"col-xs-12 col-sm-4 col-md-4 blog_pin~">
6555 + <a href=~"$pDoc.uRL~" class=~"all-post-link~">
6556 + <div class=~"thumbnail~">
6557 + #if ($displayTitle && $displayTitleFirstOnPinnedPosts)
6558 + <h5 class=~"title-top~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
6559 + #end
6560 + #if ($imageAtt)
6561 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
6562 + #end
6563 + <div class=~"caption~">
6564 + #if ($displayTitle && !$displayTitleFirstOnPinnedPosts)
6565 + <h5 class=~"text-left~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
6566 + #end
6567 + #if ($displaySummaryOnPinnedPosts)
6568 + <div class=~"text-left post-summary~">
6569 + #set ($postContent = $pObj.getProperty('extract').value)
6570 + $!pDoc.getRenderedContent($postContent, $pDoc.syntax.toIdString())
6571 + </div>
6572 + #end
6573 + #displayPostDetails($pDoc)
6574 + </div>
6575 + </div>
6576 + </a>
6577 + </div>
6578 + #end
6579 + ##
6580 + ##
6581 + ##
6582 + #macro(formatPostDate $pDoc $pObj)
6583 + #set ($formattedDate = $NULL)
6584 + #set($dateStr = $datetool.format('medium', $postDate, $xcontext.locale))
6585 + #if (~"$!dateStr~" != '')
6586 + #set ($dateArr = $dateStr.split(' '))
6587 + #if ($dateArr.size() > 3)
6588 + #set ($dateStr = ~"~")
6589 + #foreach($s in $dateArr.subList(0, 3))
6590 + #set ($dateStr = ~"$\{dateStr}$\{s} ~")
6591 + #end
6592 + #end
6593 + #end
6594 + #setVariable(~"$formattedDate~" $dateStr)
6595 + #end
6596 + ##
6597 + ##
6598 + ##
6599 + #macro(displayPostDetails $pDoc)
6600 + <div class=~"row post-details~">
6601 + <div class=~"col-xs-8 detail~">
6602 + #if ($services.like.displayButton($pDoc.documentReference))
6603 + #set ($optLikeRecord = $services.like.getLikes($pDoc.documentReference))
6604 + ## Retrieve the likes number in XWiki 12.9+
6605 + #set ($likeNumber = $optLikeRecord.get())
6606 + #if (!$stringtool.isNumeric($likeNumber.toString()))
6607 + ## Retrieve the likes number in XWiki versions greater than 12.7 and lower than 12.9.
6608 + #set ($likeNumber = $optLikeRecord.get().likeNumber)
6609 + #end
6610 + #if ($stringtool.isNumeric($likeNumber.toString()))
6611 + <div class=~"post-likes btn btn-default disabled badge~"
6612 + title=~"$escapetool.xml($services.localization.render('like.button.title', [$likeNumber]))~">
6613 + $services.icon.renderHTML('heart') <span class=~"like-number~">$likeNumber</span>
6614 + </div>
6615 + #end
6616 + #elseif ($services.ratings)
6617 + #set ($ratingsConfigDoc = $services.ratings.getConfigurationDocument($pDoc.documentReference))
6618 + #if ($ratingsConfigDoc.getValue('displayRatings') == 1)
6619 + <ul class=~"pull-left note list-inline~">
6620 + #foreach ($x in [1..5])
6621 + #set ($cls = ~"~")
6622 + #if ($x > $averageVote)
6623 + #set ($cls = ~"-o~")
6624 + #end
6625 + <li><span class=~"fa fa-star$\{cls}~"></span></li>
6626 + #end
6627 + </ul>
6628 + #end
6629 + #end
6630 + </div>
6631 + #if ($showPostComments)
6632 + <div class=~"col-xs-4 com_det~">
6633 + <p class=~"text-right~">$services.icon.renderHTML('comments') ($!nbComments)</p>
6634 + </div>
6635 + #end
6636 + </div>
6637 + #end
6638 + ##
6639 + ##
6640 + ##
6641 + #macro(initLayoutVars $pDoc $pObj)
6642 + #set ($postTitle = $pDoc.display('title', 'view', $pObj))
6643 + #set ($imageAtt = $pDoc.getAttachment($pObj.getValue('image')))
6644 + #isPublished($pObj $isPublished)
6645 + #isHidden($pObj $isHidden)
6646 + #getEntryDate($pDoc $pObj $postDate)
6647 + #formatPostDate($postDate $dateStr)
6648 + #set ($averageVote = $mathtool.round($services.ratings.getAverageRating($pDoc.documentReference).getAverageVote()))
6649 + #set ($nbComments = $pDoc.getComments().size())
6650 + #set ($showPostComments = true)
6651 + #if ($xwiki.getSpacePreferenceFor('showcomments', $pDoc.documentReference.lastSpaceReference, '1') == '0')
6652 + #set ($showPostComments = false)
6653 + #end
6654 + #end
6655 + ##
6656 + ##
6657 + ##
6658 + #macro(displayEditPinnedPostsButton)
6659 + #if (~"$!macroAdditionalParams.get('postIndex')~" == '0' && $services.security.authorization.hasAccess('edit', $pinnedPostsSourceDoc.fullName))
6660 + #set ($discard = $xwiki.ssx.use('Blog.PinnedPostsSheet'))
6661 + #set ($discard = $xwiki.jsx.use('Blog.PinnedPostsSheet'))
6662 + #set ($editPinnedPostsURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'get', 'sheet=Blog.PinnedPostsSheet'))
6663 + #set ($newPinnedPostsObjectURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'objectadd', ~"classname=Blog.PinnedPostsClass&form_token=$!\{services.csrf.getToken()}~"))
6664 + <div class=~"edit-pinned-posts-container~">
6665 + <div class=~"col-xs-12 col-sm-12 col-md-12 text-right edit-pinned-posts~">
6666 + <a href=~"javascript:;~" class=~"editPinnedPosts~">
6667 + <span class=~"glyphicon glyphicon-edit~" aria-hidden=~"true~"></span> $services.localization.render('blog.post.layout.cards.pinnedposts.edit')
6668 + </a>
6669 + <input type=~"hidden~" id=~"editPinnedPostsURL~" value=~"$escapetool.xml($editPinnedPostsURL)~"/>
6670 + <input type=~"hidden~" id=~"newPinnedPostsObjectURL~" value=~"$escapetool.xml($newPinnedPostsObjectURL)~"/>
6671 + </div>
6672 + </div>
6673 + #if (~"$!pinnedPostsObj~" == '')
6674 + <input type=~"hidden~" name=~"createPinnedPostsObject~" value=~"1~"/>
6675 + #end
6676 + #end
6677 + #end" %)
6678 +(((
6679 +(% class="macro-placeholder hidden" %)
6680 +(((
6681 +macro:velocity
6682 +)))
6683 +)))
6684 +
6685 +(% class="macro" data-macro="startmacro:velocity|-||-| #if ($services.security.authorization.hasAccess('view', $xcontext.macro.params.reference))
6686 + #set ($postDoc = $xwiki.getDocument($xcontext.macro.params.reference))
6687 + #getEntryObject($postDoc $postObj)
6688 + #if (~"$!postObj~" != '')
6689 + #extractLayoutParametersFromString($xcontext.macro.params.params $macroAdditionalParams)
6690 + ##
6691 + #set ($displayTitle = true)
6692 + #if (~"$!macroAdditionalParams.get('displayTitle')~" == 'false')
6693 + #set ($displayTitle = false)
6694 + #end
6695 + ##
6696 + #set ($displayTitleFirstOnPinnedPosts = false)
6697 + #if (~"$!macroAdditionalParams.get('displayTitleFirstOnPinnedPosts')~" == 'true')
6698 + #set ($displayTitleFirstOnPinnedPosts = true)
6699 + #end
6700 + ##
6701 + #set ($displaySummaryOnPinnedPosts = true)
6702 + #if (~"$!macroAdditionalParams.get('displaySummaryOnPinnedPosts')~" == 'false')
6703 + #set ($displaySummaryOnPinnedPosts = false)
6704 + #end
6705 + ##
6706 + #set ($postIndex = $numbertool.toNumber($macroAdditionalParams.get('postIndex')).intValue())
6707 + #if ($postIndex == 0)
6708 + #set ($stopBlogPostsDisplay = false)
6709 + #end
6710 + #set ($listResultsCount = $numbertool.toNumber($macroAdditionalParams.get('list-results-count')).intValue())
6711 + #set($discard = $xwiki.ssx.use('Blog.BlogPostLayoutCards'))
6712 + #set($scaleWidth = 600)
6713 + #set($imgQs=~"width=$scaleWidth~")
6714 + ## Display pinned posts
6715 + ## Get the list of pinned posts
6716 + #set ($pinnedPosts = [])
6717 + #set ($pinnedPostsSourceDoc = $NULL)
6718 + #if (~"$!macroAdditionalParams.get('forceDisplayPinnedPosts')~" == 'true' && ~"$!macroAdditionalParams.get('list-blog')~" != '')
6719 + #set ($pinnedPostsSourceDoc = $xwiki.getDocument($macroAdditionalParams.get('list-blog')))
6720 + ## Note that the 'list-blog' parameter contains the value of the 'blog' parameter of the blogpostlist macro passed to the current layout macro
6721 + #end
6722 + #if (~"$!pinnedPostsSourceDoc~" != '')
6723 + #set ($pinnedPostsObj = $pinnedPostsSourceDoc.getObject('Blog.PinnedPostsClass'))
6724 + #if (~"$!pinnedPostsObj~" != '')
6725 + #set ($orderedPinnedPostsJSON = $pinnedPostsObj.getProperty('orderedPosts').value)
6726 + #if (~"$!orderedPinnedPostsJSON~" != '')
6727 + #set ($pinnedPosts = $jsontool.parse($orderedPinnedPostsJSON))
6728 + #else
6729 + #set ($pinnedPosts = $pinnedPostsObj.getProperty('posts').value)
6730 + #end
6731 + #end
6732 + #if ($postIndex == 0 && $pinnedPosts.size() > 0)
6733 + \{\{html clean=~"false~"}}
6734 + #set ($x = 0)
6735 + #set ($showPinnedPostsButton = true)
6736 + #foreach ($pinnedPost in $pinnedPosts)
6737 + #if ($x == 0)
6738 + <div class=~"row flex-container~">
6739 + #if ($showPinnedPostsButton)
6740 + #displayEditPinnedPostsButton()
6741 + #set($showPinnedPostsButton = false)
6742 + #end
6743 + #end
6744 + #set ($pinnedPostDoc = $xwiki.getDocument($pinnedPost))
6745 + #getEntryObject($pinnedPostDoc $pinnedPostObj)
6746 + #if (~"$!pinnedPostObj~" != '')
6747 + #displayPinnedPost($pinnedPostDoc $pinnedPostObj)
6748 + #end
6749 + #set ($x = $mathtool.add($x, 1))
6750 + #if ($x == 3)
6751 + #set ($x = 0)
6752 + </div>
6753 + #end
6754 + #end
6755 + #if ($mathtool.mod($x, 3) != 0)
6756 + </div>
6757 + #end
6758 + \{\{/html}}
6759 +
6760 + ## If the first post is a pinned post : this means that all the posts are pinned
6761 + ## In this case, avoid displaying the posts again after the pinned posts section.
6762 + #if ($pinnedPosts.contains($xcontext.macro.params.reference))
6763 + #set ($stopBlogPostsDisplay = true)
6764 + #end
6765 + #elseif($postIndex == 0 && $pinnedPosts.size() == 0)
6766 +
6767 + \{\{html}}
6768 + <div class=~"row no-pinnded-posts~">
6769 + #displayEditPinnedPostsButton()
6770 + </div>
6771 + \{\{/html}}
6772 +
6773 + #end
6774 + #end
6775 + #if (!$stopBlogPostsDisplay)
6776 + \{\{html clean=~"false~"}}
6777 + #if (~"$!nbDisplayedPosts~" == '' || $postIndex == 0)
6778 + #set ($nbDisplayedPosts = 0)
6779 + #end
6780 + #if($mathtool.mod($nbDisplayedPosts, 2) == 0)
6781 + #if ($nbDisplayedPosts != 0)
6782 + </div>
6783 + #set ($lastHtmlTag = 'c')
6784 + #end
6785 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
6786 + <div class=~"row~">
6787 + #set ($lastHtmlTag = 'o')
6788 + #set ($lastRowClass = ~"~")
6789 + #else
6790 + <div class=~"row flex-container~">
6791 + #set ($lastHtmlTag = 'o')
6792 + #set ($lastRowClass = ~"flex~")
6793 + #end
6794 + #end
6795 + #displaySmallPost($postDoc $postObj)
6796 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
6797 + </div>
6798 + #set ($lastHtmlTag = 'c')
6799 + #end
6800 + #set ($nbDisplayedPosts = $mathtool.add($nbDisplayedPosts, 1))
6801 + #if ($postIndex == $mathtool.sub($listResultsCount, 1))
6802 + #if (~"$!lastHtmlTag~" == 'o')
6803 + #if ($mathtool.mod($nbDisplayedPosts, 2) == 1 && $lastRowClass == ~"flex~")
6804 + <div class=~"col-xs-12 col-sm-6~"></div>
6805 + #end
6806 + </div>
6807 + #end
6808 + #end
6809 + \{\{/html}}
6810 + #end
6811 + #else
6812 + \{\{error}}$services.localization.render('blog.blogpostlayout.notpost', [$xcontext.macro.params.reference])\{\{/error}}
6813 + #end
6814 + #else
6815 + \{\{error}}$services.localization.render('blog.blogpostlayout.post_view_not_allowed', [$xcontext.macro.params.reference])\{\{/error}}
6816 + #end" %)
6817 +(((
6818 +(% class="macro-placeholder hidden" %)
6819 +(((
6820 +macro:velocity
6821 +)))
6822 +
6823 +(% class="macro" data-macro="startmacro:html|-|clean=~"false~"|-|<div class=~"col-xs-12 col-sm-6 next_blog~">
6824 +<a href=~"/Nieuws/Nieuwsbrief%20november%202023~" class=~"thumbnail~">
6825 +<div class=~"row~">
6826 +<div class=~"col-xs-4~">
6827 +<img src=~"/download/Nieuws/Nieuwsbrief%20november%202023/man-person-light-bokeh-blur-road-1268120-pxhere.com.jpg?width=600&rev=1.1~" />
6828 +</div>
6829 +<div class=~"col-xs-8 art_det~">
6830 +<p class=~"text-left~">
6831 +Nieuwsbrief november 2023 <br/><span class=~"date_info~"> 18 dec. 2023 </span>
6832 +</p>
6833 +<div class=~"row post-details~">
6834 +<div class=~"col-xs-8 detail~">
6835 +<div class=~"post-likes btn btn-default disabled badge~"
6836 +title=~"Number of likes on this page: 0~">
6837 +<span class=~"fa fa-heart~"></span> <span class=~"like-number~">0</span>
6838 +</div>
6839 +</div>
6840 +<div class=~"col-xs-4 com_det~">
6841 +<p class=~"text-right~"><span class=~"fa fa-comments~"></span> (0)</p>
6842 +</div>
6843 +</div>
6844 +</div>
6845 +</div>
6846 +</a>
6847 +</div>" %)
6848 +(((
6849 +(% class="macro-placeholder hidden" %)
6850 +(((
6851 +macro:html
6852 +)))
6853 +
6854 +(% class="col-xs-12 col-sm-6 next_blog" %)
6855 +(((
6856 +(% class="row" %)
6857 +(((
6858 +(% class="col-xs-4" %)
6859 +(((
6860 +[[~[~[image:/download/Nieuws/Nieuwsbrief%20november%202023/man-person-light-bokeh-blur-road-1268120-pxhere.com.jpg?width=600&rev=1.1~]~]>>path:/Nieuws/Nieuwsbrief%20november%202023||class="thumbnail"]]
6861 +)))
6862 +
6863 +(% class="col-xs-8 art_det" %)
6864 +(((
6865 +(% class="text-left" %)
6866 +[[Nieuwsbrief november 2023
6867 +(% class="date_info" %) 18 dec. 2023>>path:/Nieuws/Nieuwsbrief%20november%202023||class="thumbnail"]]
6868 +
6869 +(% class="row post-details" %)
6870 +(((
6871 +(% class="col-xs-8 detail" %)
6872 +(((
6873 +(% class="post-likes btn btn-default disabled badge" title="Number of likes on this page: 0" %)
6874 +(((
6875 +[[(% class="like-number" %)0>>path:/Nieuws/Nieuwsbrief%20november%202023||class="thumbnail"]]
6876 +)))
6877 +)))
6878 +
6879 +(% class="col-xs-4 com_det" %)
6880 +(((
6881 +(% class="text-right" %)
6882 +[[(0)>>path:/Nieuws/Nieuwsbrief%20november%202023||class="thumbnail"]]
6883 +)))
6884 +)))
6885 +)))
6886 +)))
6887 +)))
6888 +)))
6889 +)))
6890 +)))
6891 +
6892 +(% class="macro" data-macro="startmacro:blogPostLayoutCards|-|reference=~"Nieuws.Feestelijke afsluiting, keuring materieel en tellen voorraden~" params=~"displayTitle=true|useSummary=true|list-limit=6|list-layout=cards|list-blog=Nieuws.WebHome|list-paginated=no|list-results-count=6|postIndex=0|previousPostReference=|postIndex=1|previousPostReference=Nieuws.Nieuwsbrief januari 2024|postIndex=2|previousPostReference=Nieuws.Audit BMI en BORG|postIndex=3|previousPostReference=Nieuws.Nieuwsbrief december 2023|postIndex=4|previousPostReference=Nieuws.Nieuwsbrief november 2023~"" %)
6893 +(((
6894 +(% class="macro-placeholder hidden" %)
6895 +(((
6896 +macro:blogPostLayoutCards
6897 +)))
6898 +
6899 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogCode~"" %)
6900 +(((
6901 +(% class="macro-placeholder hidden" %)
6902 +(((
6903 +macro:include
6904 +)))
6905 +
6906 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogParameters~"" %)
6907 +(((
6908 +(% class="macro-placeholder hidden" %)
6909 +(((
6910 +macro:include
6911 +)))
6912 +
6913 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|## Blog
6914 +#set($blogClassname = 'Blog.BlogClass')
6915 +#set($blogTemplate = 'Blog.BlogTemplate')
6916 +#set($blogSheet = 'Blog.BlogSheet')
6917 +## Blog entries
6918 +#set($blogPostClassname = 'Blog.BlogPostClass')
6919 +#set($blogPostTemplate = 'Blog.BlogPostTemplate')
6920 +#set($blogPostSheet = 'Blog.BlogPostSheet')
6921 +#set($blogPostObjectNumber = $xwiki.getDocument($blogPostTemplate).getObject($blogPostClassname).number)
6922 +#set($oldArticleClassname = 'XWiki.ArticleClass')
6923 +## Categories
6924 +#set($blogCategoryClassname = 'Blog.CategoryClass')
6925 +#set($blogCategoryTemplate = 'Blog.CategoryTemplate')
6926 +#set($blogCategorySheet = 'Blog.CategorySheet')
6927 +#set($blogCategoriesSheet = 'Blog.CategoriesSheet')
6928 +#set($oldBlogCategoryClassname = 'Blog.Categories')
6929 +#set($defaultCategoryParent = 'Blog.Categories')
6930 +## Style
6931 +#set($blogStyleDocumentName = 'Blog.BlogStyle')
6932 +#set($blogStyleDocument = $xwiki.getDocument($blogStyleDocumentName))
6933 +## Clientside scripts
6934 +#set($blogScriptsDocumentName = 'Blog.BlogScripts')
6935 +#set($blogPublisher = $xwiki.getDocument('Blog.Publisher'))
6936 +## Misc
6937 +#set($thisURL = $doc.getURL($xcontext.action, $request.queryString))
6938 +#set($isBlogPost = $doc.getObject($blogPostClassname))
6939 +#set($defaultBlogSpace = 'Blog')
6940 +#set($isCategoryPage = $doc.getObject($blogCategoryClassname))
6941 +#set($isCategoriesHomePage = $doc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
6942 +##
6943 +##
6944 +##
6945 +#**
6946 + * Displays an image, taken from the blog style document.
6947 + *
6948 + * @param $imgName The name of the icon from icons set to use.
6949 + *#
6950 +#macro(toolImage $imgName)(% class=~"icon-manage~"~%)$services.icon.render($imgName)(%~%)#end" %)
6951 +(((
6952 +(% class="macro-placeholder hidden" %)
6953 +(((
6954 +macro:velocity
6955 +)))
6956 +)))
6957 +)))
6958 +
6959 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|##
6960 +##
6961 +##
6962 +## Import the blog skin and javascripts.
6963 +$!xwiki.ssx.use($blogStyleDocumentName)##
6964 +$!xwiki.jsx.use($blogScriptsDocumentName)##
6965 +##
6966 +## import the hierarchy for the path the blog post footer (in displayEntryBlogLocation)
6967 +#template('hierarchy_macros.vm')##
6968 +##
6969 +##
6970 +#**
6971 + * Prints a blog. This is the main macro used in the BlogSheet.
6972 + *
6973 + * @param blogDoc the XDocument holding the blog definition object.
6974 + *###
6975 +#macro(printBlog $blogDoc)
6976 + \{\{include reference='Blog.CreatePost'/}}
6977 +
6978 + ## Use the blogPostList macro to display the blogposts
6979 + ## The blogPostList is used only in case of 'all' or 'paged' blog display type because the blogPostList macro
6980 + ## do not support FTM the monthly and weekly blog display types
6981 + #getBlogDisplayType($blogDoc $displayType)
6982 + #if ($displayType == 'weekly' || $displayType == 'monthly')
6983 + #getBlogEntries($blogDoc $entries)
6984 + #displayBlog($entries 'index' true true)
6985 + #displayNavigationLinks($blogDoc)
6986 + #else
6987 + #getBlogDisplayType($blogDoc $displayType)
6988 + #set ($paginated = 'no')
6989 + #if ($displayType == 'paginated')
6990 + #set ($paginated = 'yes')
6991 + #end
6992 + #getBlogPostsLayout($blogDoc $postsLayout)
6993 + (% class=~"hfeed index~" ~%)(((\{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$paginated~" layout=~"$!postsLayout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" /}})))
6994 + #end
6995 +#end
6996 +##
6997 +##
6998 +##
6999 +#**
7000 + * Shows blog information. In view mode, the description is printed. In edit mode, allows changing blog settings: title,
7001 + * description, blog type (global or in-space), index display type (fixed size pagination, weekly index, monthly index,
7002 + * all entries).
7003 + *
7004 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
7005 + *###
7006 +#macro(showBlogInfo $blogDoc)
7007 + #if($blogDoc.getObject($blogClassname))
7008 + ## Keep testing for inline action for backward compatibility with older blogs.
7009 + #if($xcontext.action == 'edit' || $xcontext.action == 'inline')
7010 + #macro(displayProperty $blogDoc $propname)
7011 + ; #displayPropName($xwiki.getClass($blogClassname).get($propname)):
7012 + : $blogDoc.display($propname)
7013 + #end
7014 + #displayProperty($blogDoc 'title')
7015 + #displayProperty($blogDoc 'description')
7016 + #displayProperty($blogDoc 'displayType')
7017 + #displayProperty($blogDoc 'itemsPerPage')
7018 + #displayProperty($blogDoc 'postsLayout')
7019 + #displayProperty($blogDoc 'postsLayoutParameters')
7020 + #else
7021 + $blogDoc.display('description')
7022 + #end
7023 + #elseif($doc.fullName == $blogSheet)
7024 += $services.localization.render('blog.code.blogsheet') =
7025 + \{\{translation key='blog.code.sheetexplanation'/}}
7026 + #else
7027 + \{\{warning}}\{\{translation key='blog.code.notblog'/}}\{\{/warning}}
7028 + #end
7029 +#end
7030 +##
7031 +##
7032 +##
7033 +#**
7034 + * Retrieve the blog document, which usually is either <tt>&lt;Space&gt;.WebHome</tt> for whole-spaces blogs, or
7035 + * <tt>&lt;Space&gt;.Blog</tt> for in-space blogs. If none of these documents contains a blog object, then the first
7036 + * (alphabetically) document in the target space that contains one is returned. Finally, if no document in the current
7037 + * space contains a blog object, then <tt>Blog.WebHome</tt> is returned as the default blog.
7038 + *
7039 + * @param space A <tt>String</tt>, the name of the space where to search.
7040 + * @param blogDoc The resulting XDocument.
7041 + *###
7042 +#macro(getBlogDocument $space $blogDoc)
7043 + #set ($result = $NULL)
7044 + ## Check if the current space has a WebPreferences page that contains a Blog.EnablePanelsConfigurationClass object.
7045 + ## It is possible to display a blog's panels info in a page that is not inside a blog and in that case we need to
7046 + ## identify the right blog based on a configuration object in a WebPreferences page.
7047 + #set ($spaceReference = $services.model.resolveSpace($space))
7048 + #set ($preferencesDocRef = $services.model.createDocumentReference('WebPreferences', $spaceReference))
7049 + #set ($preferencesDoc = $xwiki.getDocument($preferencesDocRef))
7050 + #set ($preferencesObj = $preferencesDoc.getObject('Blog.EnablePanelsConfigurationClass'))
7051 + #if ($preferencesObj)
7052 + #set ($result = $xwiki.getDocument( $preferencesObj.getValue('blog')))
7053 + #end
7054 + ## If no special case occurs (like the previous one), identify a blog by checking the current location from its hierarchy.
7055 + #if (~"$!result~" == '')
7056 + ## First, try the Space.WebHome, for a whole-space blog
7057 + #set($result = $xwiki.getDocument(~"$\{space}.WebHome~"))
7058 + #if(!$result.getObject($blogClassname))
7059 + ## Second, try the Space.Blog document
7060 + #set($result = $xwiki.getDocument(~"$\{space}.Blog~"))
7061 + #if(!$result.getObject($blogClassname))
7062 + ## Third, try searching for a blog document in the current space
7063 + ## Prevent the query fail when the space contains dots '.'
7064 + #set($blogDocs = $services.query.hql(~", BaseObject obj where doc.space = :space and obj.name = doc.fullName and obj.className = '$blogClassname' order by doc.name~").setLimit(1).setOffset(0).bindValue('space', $space).execute())
7065 + #if($blogDocs.size() > 0)
7066 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
7067 + #else
7068 + ## Fourth, try searching for a blog document that have the its 'postsLocation' set to the current space
7069 + #set($blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as postsLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=postsLocationProp.id.id and postsLocationProp.id.name='postsLocation' and postsLocationProp.value=:postsLocation order by doc.name~").setLimit(1).setOffset(0).bindValue('postsLocation', $space).execute())
7070 + #if($blogDocs.size() > 0)
7071 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
7072 + #else
7073 + ## Last, fallback to Blog.WebHome, the default blog
7074 + #set($result = $xwiki.getDocument('Blog.WebHome'))
7075 + #end
7076 + #end
7077 + #end
7078 + #end
7079 + #end
7080 + #set ($blogDoc = $NULL)
7081 + #setVariable (~"$blogDoc~" $result)
7082 +#end
7083 +##
7084 +##
7085 +##
7086 +#**
7087 + * Retrieve the blog title.
7088 + *
7089 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass<tt> object with the <tt>title</tt> property set.
7090 + * @param title The resulting title.
7091 + *###
7092 +#macro(getBlogTitle $blogDoc $title)
7093 + ## Titles can contain velocity code (most commonly translations), so we should evaluate them.
7094 + #set ($title = $NULL)
7095 + #setVariable (~"$title~" $!blogDoc.displayTitle)
7096 +#end
7097 +##
7098 +##
7099 +##
7100 +#**
7101 + * Retrieve the blog description.
7102 + *
7103 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>description</tt>
7104 + * property set.
7105 + * @param description The resulting description.
7106 + *###
7107 +#macro(getBlogDescription $blogDoc $description)
7108 + #getBlogProperty($blogDoc 'description' '' $result)
7109 + #set ($description = $NULL)
7110 + #setVariable (~"$description~" $result)
7111 +#end
7112 +##
7113 +##
7114 +##
7115 +#**
7116 + * Retrieves a list of entries to be displayed. The entries are either part of the blog's space, or have the blog
7117 + * document set as a parent. The number and range of entries returned (from all those belonging to this blog) depends on
7118 + * the blog display type: paginated (fixed number of entries), weekly (all entries in a week), monthly (all entries in a
7119 + * month), or all.
7120 + *
7121 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
7122 + * @param entries The resulting list of entries to display, a list of XDocument names.
7123 + *###
7124 +#macro(getBlogEntries $blogDoc $entries)
7125 + #if (!$entries)
7126 + #setVariable (~"$entries~" [])
7127 + #end
7128 + #getAllBlogPostsQuery($query)
7129 + #isDefaultBlog($blogDoc $isDefault)
7130 + #set($queryParams = \{})
7131 + #if ($isDefault)
7132 + #getCategoryAllBlogPostsQuery($query)
7133 + #set($query = ~"$\{query} and (doc.creator = :creator or (isPublished.value = 1 and hidden.value = 0)) and (doc.space = :space or catList like :catList escape '!')~")
7134 + #set($discard = $queryParams.put('creator', $xcontext.user))
7135 + #set($discard = $queryParams.put('space', $blogDoc.space))
7136 + #set($sanitizedBlogSpace = $blogDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
7137 + #set($discard = $queryParams.put('catList', $sanitizedBlogSpace))
7138 + #else
7139 + #set($query = ~"$\{query} and (doc.space = :space or doc.parent = :parent)~")
7140 + #getBlogPostsLocation($blogDoc.space $blogPostsLocation)
7141 + #set($discard = $queryParams.put('space', $blogPostsLocation))
7142 + #set($discard = $queryParams.put('parent', $blogDoc.space))
7143 + #end
7144 + #getBlogDisplayType($blogDoc $displayType)
7145 + #if($displayType == 'weekly')
7146 + #getWeeklyBlogEntries($blogDoc $query $entries $queryParams)
7147 + #elseif($displayType == 'monthly')
7148 + #getMonthlyBlogEntries($blogDoc $query $entries $queryParams)
7149 + #elseif($displayType == 'all')
7150 + #getAllBlogEntries($blogDoc $query $entries $queryParams)
7151 + #else
7152 + #getPagedBlogEntries($blogDoc $query $entries $queryParams)
7153 + #end
7154 +#end
7155 +##
7156 +##
7157 +##
7158 +#**
7159 + * Retrieves a list of entries to be displayed. The entries are taken from a ~"page~" of the blog, a sequence of documents
7160 + * defined by the request parameters <tt>ipp</tt> (items per page) and <tt>page</tt> (the current page). Initially the
7161 + * first page is displayed, with the number of entries defined in the blog object in the <tt>itemsPerPage</tt> property
7162 + * (10 if not defined).
7163 + *
7164 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
7165 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
7166 + * refined to restrict to a given space, or to a given search criteria, etc.
7167 + * @param entries The resulting list of entries to display, a list of XDocument names.
7168 + * @param queryParams The parameters to bind with the query.
7169 + *###
7170 +#macro(getPagedBlogEntries $blogDoc $query $entries $queryParams)
7171 + #if (!$entries)
7172 + #setVariable (~"$entries~" [])
7173 + #end
7174 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
7175 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~"))
7176 + #bindQueryParameters($countQueryObj $queryParams)
7177 + #bindQueryParameters($queryObj $queryParams)
7178 + #set($totalEntries = $countQueryObj.count())
7179 + #getBlogProperty($blogDoc 'itemsPerPage' '10' $defaultItemsPerPage)
7180 + #set($defaultItemsPerPage = $numbertool.toNumber($defaultItemsPerPage).intValue())
7181 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
7182 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
7183 + #set($discard = $entries.addAll($queryObj.setLimit($itemsPerPage).setOffset($startAt).addFilter(~"unique~").execute()))
7184 +#end
7185 +##
7186 +##
7187 +##
7188 +#**
7189 + * Retrieves a list of entries to be displayed. The entries are taken from a week of the blog. The target week is
7190 + * defined by the request parameters <tt>week</tt> (the week number in the year, from 1 to 52) and <tt>year</tt> (4
7191 + * digit year). Initially the current week is displayed.
7192 + *
7193 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
7194 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
7195 + * refined to restrict to a given space, or to a given search criteria, etc.
7196 + * @param entries The resulting list of entries to display, a list of XDocument names.
7197 + * @param queryParams The parameters to bind with the query.
7198 + *###
7199 +#macro(getWeeklyBlogEntries $blogDoc $query $entries $queryParams)
7200 + #if (!$entries)
7201 + #setVariable (~"$entries~" [])
7202 + #end
7203 + #getRequestedWeek($weekDate)
7204 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
7205 + #set($minDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundFloor()))
7206 + #set($maxDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundCeiling()))
7207 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
7208 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
7209 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
7210 + #bindQueryParameters($countQueryObj $queryParams)
7211 + #bindQueryParameters($queryObj $queryParams)
7212 + #set($totalEntries = $countQueryObj.count())
7213 + #set($discard = $entries.addAll($queryObj.execute()))
7214 +#end
7215 +##
7216 +##
7217 +##
7218 +#**
7219 + * Retrieves a list of entries to be displayed. The entries are taken from a month of the blog. The target month is
7220 + * defined by the request parameters <tt>month</tt> (the month number, from 1 to 12) and <tt>year</tt> (4
7221 + * digit year). Initially the current month is displayed.
7222 + *
7223 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
7224 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
7225 + * refined to restrict to a given space, or to a given search criteria, etc.
7226 + * @param entries The resulting list of entries to display, a list of XDocument names.
7227 + * @param queryParams The parameters to bind with the query.
7228 + *###
7229 +#macro(getMonthlyBlogEntries $blogDoc $query $entries)
7230 + #if (!$entries)
7231 + #setVariable (~"$entries~" [])
7232 + #end
7233 + #getRequestedMonth($monthDate)
7234 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
7235 + #set($minDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundFloor()))
7236 + #set($maxDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundCeiling()))
7237 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
7238 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
7239 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
7240 + #bindQueryParameters($countQueryObj $queryParams)
7241 + #bindQueryParameters($queryObj $queryParams)
7242 + #set($totalEntries = $countQueryObj.count())
7243 + #set($discard = $entries.addAll($queryObj.execute()))
7244 +#end
7245 +##
7246 +##
7247 +##
7248 +#**
7249 + * Retrieves a list of entries to be displayed. All entries belonging to the current blog are returned.
7250 + *
7251 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
7252 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
7253 + * refined to restrict to a given space, or to a given search criteria, etc.
7254 + * @param entries The resulting list of entries to display, a list of XDocument names.
7255 + * @param queryParams The parameters to bind with the query.
7256 + *###
7257 +#macro(getAllBlogEntries $blogDoc $query $entries $queryParams)
7258 + #if (!$entries)
7259 + #setVariable (~"$entries~" [])
7260 + #end
7261 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
7262 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
7263 + #bindQueryParameters($countQueryObj $queryParams)
7264 + #bindQueryParameters($queryObj $queryParams)
7265 + #set($totalEntries = $countQueryObj.count())
7266 + #set($discard = $entries.addAll($queryObj.execute()))
7267 +#end
7268 +##
7269 +##
7270 +##
7271 +#**
7272 + * Retrieves a list of entries to be displayed. Only (and all) unpublished entries are returned.
7273 + *
7274 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
7275 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
7276 + * refined to restrict to a given space, or to a given search criteria, etc.
7277 + * @param queryParams The parameters to bind with the query.
7278 + * @param entries The resulting list of entries to display, a list of XDocument names.
7279 + *###
7280 +#macro(getUnpublishedBlogEntries $blogDoc $query $queryParams $entries)
7281 + #if (!$entries)
7282 + #setVariable (~"$entries~" [])
7283 + #end
7284 + #set($query = ~"$\{query} and isPublished.value = 0~")
7285 + #set ($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
7286 + #set ($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
7287 + #bindQueryParameters($countQueryObj $queryParams)
7288 + #bindQueryParameters($queryObj $queryParams)
7289 + #set($totalEntries = $countQueryObj.count())
7290 + #set($discard = $entries.addAll($queryObj.execute()))
7291 +#end
7292 +##
7293 +##
7294 +##
7295 +#**
7296 + * Retrieves a list of entries to be displayed. The entries are taken from all the wiki, and not from a specific blog.
7297 + *
7298 + * @param entries The resulting list of entries to display, a list of XDocument names.
7299 + *###
7300 +#macro(getGlobalBlogEntries $entries)
7301 + #if (!$entries)
7302 + #setVariable (~"$entries~" [])
7303 + #end
7304 + #getAllBlogPostsQuery($query)
7305 + #set($totalEntries = $services.query.hql($query).count())
7306 + #set($defaultItemsPerPage = 20)
7307 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
7308 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
7309 + #set($discard = $entries.addAll($services.query.hql(~"$\{query} order by publishDate.value desc~").setLimit($itemsPerPage).setOffset($startAt).execute()))
7310 +#end
7311 +#**
7312 + * Return the base query for selecting blog entries. It filters only visible entries, but does not bind to a specific
7313 + * blog, nor specify a range or an ordering criteria.
7314 + *
7315 + * This macro is a duplicate of #getAllBlogPostsQuery($query). Keep it in case it's used outside, in custom code.
7316 + *
7317 + * @param query The basic query for selecting blog entries.
7318 + *#
7319 +#macro(getBlogEntriesBaseQuery $query)
7320 + #getAllBlogPostsQuery($query)
7321 +#end
7322 +#**
7323 + * Return the Query for selecting the all wiki blog posts without filtering
7324 + *
7325 + * @param query The basic query for selecting blog entries.
7326 + *#
7327 +#macro(getAllBlogPostsQuery $query)
7328 + #set ($query = $NULL)
7329 + #setVariable(~"$query~" ~", BaseObject as obj, IntegerProperty isPublished,
7330 + IntegerProperty hidden, DateProperty publishDate
7331 + where doc.fullName <> '$blogPostTemplate' and
7332 + obj.name=doc.fullName and obj.className='$blogPostClassname' and
7333 + isPublished.id.id = obj.id and isPublished.id.name = 'published' and
7334 + hidden.id.id = obj.id and hidden.id.name='hidden' and
7335 + publishDate.id.id = obj.id and publishDate.id.name='publishDate' and
7336 + (doc.creator = '$escapetool.sql($xcontext.user)' or (isPublished.value = 1 and hidden.value = 0))~")
7337 +#end
7338 +##
7339 +##
7340 +##
7341 +###**
7342 + * Return the Query for selecting the all wiki blog posts with categories filtering
7343 + *
7344 + * @param query The basic query for selecting blog entries.
7345 + *###
7346 +#macro(getCategoryAllBlogPostsQuery $query)
7347 + #set ($query = $NULL)
7348 + #getAllBlogPostsQuery($baseQuery)
7349 + #set ($baseQuery = $baseQuery.replace('DateProperty publishDate', 'DateProperty publishDate, DBStringListProperty as category left join category.list catList'))
7350 + #setVariable(~"$query~" ~"$\{baseQuery} and obj.id=category.id.id and category.id.name='category'~")
7351 +#end
7352 +##
7353 +##
7354 +##
7355 +#**
7356 + * Determines how is the blog index split into pages: paginated (fixed number of entries), weekly (all entries in a
7357 + * week), monthly (all entries in a month), or all.
7358 + *
7359 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>displayType</tt>
7360 + * property set.
7361 + * @param displayType The resulting string. If the blog object does not define anything, it is considered paginated.
7362 + *###
7363 +#macro(getBlogDisplayType $blogDoc $displayType)
7364 + #getBlogProperty($blogDoc 'displayType' 'paginated' $result)
7365 + #set ($displayType = $NULL)
7366 + #setVariable (~"$displayType~" $result)
7367 +#end
7368 +##
7369 +##
7370 +##
7371 +#**
7372 + * Displays a list of entries.
7373 + *
7374 + * @param entries The entries to display, a list of XDocument names.
7375 + * @param displaying What exactly is displayed: blog index, a single blog entry, a blog category, search results,
7376 + * unpublished entries, etc. This will be used as the classname(s) for the container div (hfeed). Currently
7377 + * used values: index, single, category, search, unpublished, hidden.
7378 + * @param onlyExtract If <tt>true</tt>, only display the extract of articles where available, otherwise display the full content.
7379 + * @param shouldDisplayTitles If <tt>true</tt>, display the blog title (blog posts shouldn't display the title when they're
7380 + * displayed alone on their page since it's the page title which is used in this case)
7381 + *###
7382 +#macro(displayBlog $entries $displaying $onlyExtract $shouldDisplayTitles)
7383 + #set($blogDay = '')
7384 + (% class=~"hfeed $!\{displaying}~" ~%)(((
7385 + (% class=~"blogDay~" ~%)(((
7386 + #foreach ($entryDoc in $xwiki.wrapDocs($entries))
7387 + #getEntryObject($entryDoc $entryObj)
7388 + ## Although all entries should have one of the two objects, better check to be sure.
7389 + #if(~"$!\{entryObj}~" != '')
7390 + #getEntryDate($entryDoc $entryObj $entryDate)
7391 + ## Display a ~"calendar sheet~" for each day. All entries posted on the same day share one such sheet.
7392 + #set($entryDateStr = $xwiki.formatDate($entryDate, 'yyyyMMMMdd'))
7393 + #if($blogDay != $entryDateStr)
7394 + #if($blogDay != '')
7395 + )))
7396 + (% class=~"blogDay~" ~%)(((
7397 + #end
7398 + #displayBlogDate($entryDate)
7399 + #set ($blogDay = $entryDateStr)
7400 + #end
7401 + ## Finally, display the entry.
7402 + #displayEntry($entryDoc $entryObj $onlyExtract $shouldDisplayTitles true)
7403 + #end
7404 + #end
7405 + )))## blogDay
7406 + )))## hfeed
7407 +#end
7408 +##
7409 +##
7410 +##
7411 +#**
7412 + * Get the entry object, either a new BlogPost or an old Article.
7413 + *
7414 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7415 + * @param entryObj The resulting xobject of the blog post.
7416 + *###
7417 +#macro(getEntryObject $entryDoc $__entryObj)
7418 + #set($result = $entryDoc.getObject(~"$\{blogPostClassname}~"))
7419 + #if(!$result)
7420 + #set($result = $entryDoc.getObject(~"$\{oldArticleClassname}~"))
7421 + #end
7422 + ## NOTE: The reason we put an underscore in front of the variable name is to prevent the following line from
7423 + ## overwriting the $entryObj variable that may be defined before this macro is called. Of course, $__entryObj may be
7424 + ## overwritten in this case but it's less likely to have such a variable defined before.
7425 + #set ($__entryObj = $NULL)
7426 + #setVariable (~"$__entryObj~" $result)
7427 +#end
7428 +##
7429 +##
7430 +##
7431 +#**
7432 + * Gets the date associated with a blog entry. This is the publication date. For unpublished entries, initially this is
7433 + * the document creation date, but can be edited by the user.
7434 + *
7435 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7436 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7437 + * @param result The resulting date, an instance of <tt>java.util.Date</tt>.
7438 + *###
7439 +#macro(getEntryDate $entryDoc $entryObj $result)
7440 + #set ($result = $NULL)
7441 + #setVariable (~"$result~" $entryObj.getProperty('publishDate').value)
7442 +#end
7443 +##
7444 +##
7445 +##
7446 +#**
7447 + * Displays a date, nicely formatted as a calendar page.
7448 + *
7449 + * @param date The date to display, an instance of <tt>java.util.Date</tt>.
7450 + *###
7451 +#macro(displayBlogDate $date)
7452 + #set($year = $xwiki.formatDate($date, 'yyyy'))
7453 + ## 3 letter month name, like Jan, Dec.
7454 + #set($month = $xwiki.formatDate($date, 'MMM'))
7455 + ## Uncomment to get a full length month name, like January, December.
7456 + ## TODO: this could be defined somewhere in the blog style.
7457 + ## #set($month = $xwiki.formatDate($date, 'MMMM'))
7458 + #set($day = $xwiki.formatDate($date, 'dd'))
7459 + (% class=~"blogdate~" ~%)
7460 + == (% class=~"month~" ~%)$month(%~%) (% class=~"day~" ~%)$day(%~%) (% class=~"year~" ~%)$year(%~%) ==
7461 +#end
7462 +##
7463 +##
7464 +##
7465 +#**
7466 + * Displays a blog article: management tools, header, content, footer.
7467 + *
7468 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7469 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7470 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
7471 + * @param shouldDisplayTitle If <tt>true</tt>, display the blog title (blog posts shouldn't display the title
7472 + * when they're displayed alone on their page since it's the page title which is used in this case)
7473 + * @param shouldDisplayActions If <tt>true</tt>, display the blog post actions buttons
7474 + *###
7475 +#macro(displayEntry $entryDoc $entryObj $onlyExtract $shouldDisplayTitle $shouldDisplayActions)
7476 + ## Only articles with an explicit hidden setting or an explicit unpublished setting are hidden
7477 + #isPublished($entryObj $isPublished)
7478 + #isHidden($entryObj $isHidden)
7479 + #if($doc.fullName == $entryDoc.fullName)
7480 + (% class=~"hentry single-article~" ~%)(((
7481 + #else
7482 + (% class=~"hentry#if(!$isPublished) unpublished-article#elseif($isHidden) hidden-article#end~" ~%)(((
7483 + #end
7484 + #if ($shouldDisplayActions)
7485 + #displayEntryTools($entryDoc $entryObj)
7486 + #end
7487 + #if($shouldDisplayTitle)
7488 + #displayEntryTitle($entryDoc $entryObj)
7489 + #end
7490 + #if($doc.fullName == $entryDoc.fullName)
7491 + #if(!$isPublished)
7492 + \{\{warning}}\{\{translation key='blog.code.published'/}}\{\{/warning}}
7493 + #elseif($isHidden)
7494 + \{\{warning}}\{\{translation key='blog.code.hidden'/}}\{\{/warning}}
7495 + #end
7496 + #end
7497 + #displayEntryContent($entryDoc $entryObj $onlyExtract)
7498 + #displayEntryFooter($entryDoc $entryObj)
7499 + )))## hentry
7500 +#end
7501 +##
7502 +##
7503 +##
7504 +#**
7505 + * Checks if the provided blog is published or not.
7506 + *
7507 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7508 + * @param isPublished The resulting boolean, true if the entry is considered published.
7509 + *###
7510 +#macro(isPublished $entryObj $isPublished)
7511 + #set ($isPublished = $NULL)
7512 + ## This should work for both old articles, which don't have the 'published' property at all, and
7513 + ## are considered published by default, and new entries, that should have 1 if published.
7514 + #if (~"$!\{entryObj.getProperty('published').value}~" != '0')
7515 + #setVariable (~"$isPublished~" true)
7516 + #else
7517 + #setVariable (~"$isPublished~" false)
7518 + #end
7519 +#end
7520 +##
7521 +##
7522 +##
7523 +#**
7524 + * Checks if the provided blog is hidden or not.
7525 + *
7526 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass<tt> xclass.
7527 + * @param isHiddel The resulting boolean, true if the entry is considered hidden.
7528 + *###
7529 +#macro(isHidden $entryObj $isHidden)
7530 + #set ($isHidden = $NULL)
7531 + ## This should work for both old articles, which don't have the 'hidden' property at all, and
7532 + ## are considered visible by default, and new entries, that should have 1 if hidden.
7533 + #if (~"$!\{entryObj.getProperty('hidden').value}~" == '1')
7534 + #setVariable (~"$isHidden~" true)
7535 + #else
7536 + #setVariable (~"$isHidden~" false)
7537 + #end
7538 +#end
7539 +##
7540 +##
7541 +##
7542 +#**
7543 + * Displays several ~"tools~" for manipulating blog posts: hide/show, publish, edit.
7544 + *
7545 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7546 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7547 + *###
7548 +#macro(displayEntryTools $entryDoc $entryObj)
7549 + #if($xcontext.action == 'view')
7550 + (% class=~"blog-entry-toolbox~" ~%)(((
7551 + #displayPublishButton($entryDoc $entryObj)
7552 + #displayHideShowButton($entryDoc $entryObj)
7553 + #displayEditButton($entryDoc $entryObj)
7554 + #displayDeleteButton($entryDoc $entryObj)
7555 + )))
7556 + #end
7557 +#end
7558 +##
7559 +##
7560 +##
7561 +#**
7562 + * Displays the publish button to the entry <strong>creator</strong>, if the article is not published yet.
7563 + *
7564 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7565 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7566 + * @todo AJAX calls.
7567 + *###
7568 +#macro(displayPublishButton $entryDoc $entryObj)
7569 + #isPublished($entryObj $isPublished)
7570 + #if(!$isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
7571 + [[#toolImage('world')>>path:$blogPublisher.getURL('view', ~"entryName=$\{escapetool.url($entryDoc.fullName)}&xredirect=$\{escapetool.url($thisURL)}&form_token=$!\{services.csrf.getToken()}~")||title=~"$services.localization.render('blog.code.notpublished')~"]]##
7572 + #end
7573 +#end
7574 +##
7575 +##
7576 +##
7577 +#**
7578 + * Displays the hide or show button to the entry <strong>creator</strong>, if the article is already published.
7579 + *
7580 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7581 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7582 + *###
7583 +#macro(displayHideShowButton $entryDoc $entryObj)
7584 + #isPublished($entryObj $isPublished)
7585 + #isHidden($entryObj $isHidden)
7586 + ## Only published articles can be hidden. Unpublished articles are considered already hidden.
7587 + #if($isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
7588 + #set ($queryString = \{
7589 + 'xredirect' : $thisURL,
7590 + 'form_token' : $services.csrf.getToken()
7591 + })
7592 + #if ($isHidden)
7593 + #set ($discard = $queryString.putAll(\{
7594 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 0,
7595 + 'comment' : $services.localization.render('blog.code.madevisible')
7596 + }))
7597 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
7598 + [[#toolImage('unlock')>>path:$lockURL||class=~"blog-tool-show~" title=~"$services.localization.render('blog.code.makevisible')~"]]##
7599 + #else
7600 + #set ($discard = $queryString.putAll(\{
7601 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 1,
7602 + 'comment' : $services.localization.render('blog.code.hid')
7603 + }))
7604 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
7605 + [[#toolImage('lock')>>path:$lockURL||class=~"blog-tool-hide~" title=~"$services.localization.render('blog.code.hide')~"]]##
7606 + #end
7607 + #end
7608 +#end
7609 +##
7610 +##
7611 +##
7612 +#**
7613 + * Displays the edit button to those that can edit the article.
7614 + *
7615 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7616 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7617 + *###
7618 +#macro(displayEditButton $entryDoc $entryObj)
7619 + #if($xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
7620 + ## Call getDefaultEditMode() for backward compatibility with older blog posts.
7621 + [[#toolImage('pencil')>>path:$entryDoc.getURL('edit')||title=~"$services.localization.render('blog.code.editpost')~"]]##
7622 + #end
7623 +#end
7624 +##
7625 +##
7626 +##
7627 +#**
7628 + * Displays the delete button to those that can edit the article.
7629 + *
7630 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7631 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7632 + * @todo AJAX calls.
7633 + *###
7634 +#macro(displayDeleteButton $entryDoc $entryObj)
7635 + #if($xwiki.hasAccessLevel('delete', $xcontext.user, $entryDoc.fullName))
7636 + [[#toolImage('cross')>>path:$entryDoc.getURL('delete')||title=~"$services.localization.render('blog.code.deletepost')~"]]##
7637 + #end
7638 +#end
7639 +##
7640 +##
7641 +##
7642 +#**
7643 + * Displays the title of the entry.
7644 + *
7645 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7646 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7647 + *###
7648 +#macro(displayEntryTitle $entryDoc $entryObj)
7649 + #if($doc.fullName == $entryDoc.fullName)
7650 + (% class=~"entry-title~" ~%)
7651 + = $services.rendering.escape($entryDoc.display('title', 'view', $entryObj), $xwiki.getCurrentContentSyntaxId()) =
7652 + #else
7653 + (% class=~"entry-title~" ~%)
7654 + === [[$services.rendering.escape($entryDoc.display('title', 'view', $entryObj),$xwiki.getCurrentContentSyntaxId())>>doc:$services.rendering.escape($services.model.serialize($entryDoc.getDocumentReference(),'default'),$xwiki.getCurrentContentSyntaxId())]] ===
7655 + #end
7656 +#end
7657 +##
7658 +##
7659 +##
7660 +#**
7661 + * Displays the body of the entry.
7662 + *
7663 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7664 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7665 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
7666 + *###
7667 +#macro(displayEntryContent $entryDoc $entryObj $onlyExtract)
7668 + (% class=~"#if($onlyExtract)entry-summary#\{else}entry-content#end~" ~%)(((
7669 + #getEntryContent($entryDoc $entryObj $onlyExtract $entryContent)
7670 + ## FIXME: This causes the blog's content to not be annotatable. See http://jira.xwiki.org/browse/XWIKI-6328
7671 + ## Should probably be replaced by a display macro call with a reference to the object property holding the post's content
7672 + \{\{html wiki=~"false~"}}$entryDoc.getRenderedContent($entryContent, $entryDoc.syntax.toIdString())\{\{/html}}
7673 + ))) ## entry-content
7674 + (% class=~"clearfloats~" ~%)((()))
7675 +#end
7676 +##
7677 +##
7678 +##
7679 +#**
7680 + * Extracts the body of the entry that should be displayed. If <tt>onlyExtract</tt> is <tt>true</tt>, display the content
7681 + * of the <tt>extract</tt> field (if not empty).
7682 + *
7683 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7684 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7685 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
7686 + * @param entryContent The resulting content.
7687 + * @param removeEllipsis If <tt>true</tt>, then don't display an ellipsis at the end of the content (only used when
7688 + * <tt>onlyExtract</tt> is <tt>true</tt>)
7689 + *###
7690 +#macro(getEntryContent $entryDoc $entryObj $onlyExtract $entryContent $removeEllipsis)
7691 + #if ($onlyExtract)
7692 + ## Note: We trim the summary so that if there's some white space it won't cause the summary to be used instead
7693 + ## of the content.
7694 + #set ($macro.result = $entryObj.getProperty('extract').value.trim())
7695 + #end
7696 + #if(~"$!macro.result~" == '')
7697 + #set($macro.result = $entryObj.getProperty('content').value)
7698 +#* Disabled until the content can be cleanly cut.
7699 +* #if($onlyExtract && $result.length()>$maxchars)
7700 +* #set($i = $macro.result.lastIndexOf(~" ~", $maxchars))
7701 +* #set($i = $i + 1)
7702 +* #set($macro.result = ~"$\{macro.result.substring(0,$i)} *[...>$\{entryDoc.fullName}]*~")
7703 +* #end
7704 +## *###
7705 + #elseif (!$removeEllipsis)
7706 + #if($entryDoc.syntax.toIdString() == 'xwiki/1.0')
7707 + #set($macro.result = ~"$\{macro.result} <a href='$\{entryDoc.getExternalURL()}' title='$services.localization.render('blog.code.readpost')'>...</a>~")
7708 + #elseif($entryDoc.syntax.toIdString() == 'xwiki/2.0' || $entryDoc.syntax.toIdString() == 'xwiki/2.1')
7709 + #set($macro.result = ~"$\{macro.result} [[...>>$\{services.rendering.escape($entryDoc.getFullName(), $entryDoc.getSyntax())}||title='$services.localization.render('blog.code.readpost')']]~")
7710 + #end
7711 + #end
7712 + #set ($entryContent = $NULL)
7713 + #setVariable (~"$entryContent~" $macro.result)
7714 +#end
7715 +##
7716 +##
7717 +##
7718 +#**
7719 + * Displays the footer of the entry.
7720 + *
7721 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7722 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7723 + *###
7724 +#macro(displayEntryFooter $entryDoc $entryObj)
7725 + (% class=~"entry-footer~" ~%)(((
7726 + #isPublished($entryObj $isPublished)
7727 + (% class='entry-author-label' ~%)
7728 + #if($isPublished)
7729 + \{\{translation key='blog.code.postedby'/}} ##
7730 + #else
7731 + \{\{translation key='blog.code.createdby'/}} ##
7732 + #end
7733 + \{\{html wiki=~"false~" clean=~"false~"}}<span class='author vcard'>#userfn($entryDoc.creator)</span>\{\{/html}} ##
7734 + #getEntryDate($entryDoc $entryObj $entryDate)
7735 + #listCategories($entryObj) #*
7736 + ## Since the publish date and update date are not set at the exact same time, there could be a small difference that
7737 + ## we assume cannot be more than 3 seconds.
7738 + *#(% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.permalink'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||rel=~"bookmark~"]] ##
7739 + #if ($showcomments)
7740 + (% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.comments'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||anchor=~"Comments~"]] (% class=~"itemCount~" ~%)($entryDoc.comments.size())(%~%) ##
7741 + #end ##
7742 + #if($entryDoc != $doc) ##
7743 + #displayEntryBlogLocation($entryDoc $entryObj) ##
7744 + #end
7745 + )))## entry-footer
7746 +#end
7747 +##
7748 +##
7749 +#**
7750 + * Display the blog for the entry (if it is not the currently displayed blog)
7751 + *
7752 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
7753 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7754 + *###
7755 +#macro(displayEntryBlogLocation $entryDoc $entryObj)
7756 + #getBlogPostsLocation($entryDoc.getSpace() $blogPostsLocation) ##
7757 + #if(~"$!blogPostsLocation~" != ~"~") ##
7758 + #set($blogSpaceRef = $services.model.resolveSpace($blogPostsLocation)) ##
7759 + #set($blogDocRef = $services.model.createDocumentReference($services.model.getEntityReference('DOCUMENT', 'default').getName(), $blogSpaceRef)) ##
7760 + #if($doc.documentReference != $blogDocRef) ##
7761 + #set($blogDoc = $xwiki.getDocument($blogDocRef)) ##
7762 + #set($blogObj = $blogDoc.getObject('Blog.BlogClass')) ##
7763 + #if($blogObj) (% class=~"blogrefpath~" ~%)((( ##
7764 + $services.localization.render('blog.code.postedin') \{\{html clean=~"false~" wiki=~"false~"}} #hierarchy($blogDocRef, \{'selfIsActive' : true, 'local': true}) \{\{/html}} ##
7765 + )))(%~%)##
7766 + #end
7767 + #end
7768 + #end
7769 +#end
7770 +##
7771 +##
7772 +##
7773 +##
7774 +#**
7775 + * List the categories an entry belongs to. Used in the footer. The categories are instances of <tt>Blog.CategoryClass</tt>.
7776 + *
7777 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
7778 + *###
7779 +#macro(listCategories $entryObj)
7780 + #if($entryObj.getxWikiClass().getName() == $blogPostClassname)
7781 + #set($categories = $entryObj.getProperty('category').value)
7782 + #set($first = true)
7783 + #if($categories.size() > 0)
7784 + #foreach($category in $categories)
7785 + #set($categoryDoc = $!xwiki.getDocument($category))
7786 + #if(!$categoryDoc.isNew() && $categoryDoc.getObject($\{blogCategoryClassname}))
7787 + #if($foreach.count == 1)
7788 + (% class='separator' ~%)·(%~%) $services.localization.render('blog.code.categories') ##
7789 + #else
7790 + , ##
7791 + #end##
7792 + [[$!\{categoryDoc.getObject($blogCategoryClassname).getValue('name')}>>$\{category}||rel='tag']]##
7793 + #end##
7794 + #end##
7795 + #end
7796 + #end
7797 +#end
7798 +##
7799 +##
7800 +##
7801 +#**
7802 + * Displays blog pagination links (older and newer entries).
7803 + *
7804 + * @param blogDoc the XDocument holding the blog definition object.
7805 + *###
7806 +#macro(displayNavigationLinks $blogDoc)
7807 + (% class=~"clearfloats~" ~%)((()))
7808 + #getBlogDisplayType($blogDoc $displayType)
7809 + #if($displayType == 'weekly')
7810 + (% class=~"pagingLinks~" ~%)(((
7811 + #getRequestedWeek($weekDate)
7812 + $weekDate.addWeeks(-1)##
7813 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousweek'/}}>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
7814 + #sep()
7815 + $weekDate.addWeeks(2)## 2 because we already subtracted 1 above
7816 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextweek'/}} »>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
7817 + )))
7818 + #elseif($displayType == 'monthly')
7819 + (% class=~"pagingLinks~" ~%)(((
7820 + #getRequestedMonth($monthDate)
7821 + $monthDate.addMonths(-1)##
7822 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousmonth'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
7823 + #sep()
7824 + $monthDate.addMonths(2)## 2 because we already subtracted 1 above
7825 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextmonth'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
7826 + )))
7827 + #elseif($displayType == 'all')
7828 + #else
7829 + ## Paginated
7830 + #if(($totalPages > 1))
7831 + #set($queryString = '')
7832 + #foreach($p in $request.getParameterNames())
7833 + #if($p != 'page' && $p != 'ipp')
7834 + #foreach($v in $request.getParameterValues($p))
7835 + #set($queryString = ~"$\{queryString}&$\{escapetool.url($p)}=$\{escapetool.url($v)}~")
7836 + #end
7837 + #end
7838 + #end
7839 + (% class=~"pagingLinks~" ~%)(((
7840 + #if ($currentPageNumber < $totalPages)
7841 + #set($currentPageNumber = $currentPageNumber + 1)
7842 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.olderposts'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
7843 + #set($currentPageNumber = $currentPageNumber - 1)
7844 + #end
7845 + #if ($currentPageNumber > 1)
7846 + #if ($currentPageNumber < $totalPages)
7847 + #sep()
7848 + #end
7849 + #set($currentPageNumber = $currentPageNumber - 1)
7850 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.newerposts'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
7851 + #set($currentPageNumber = $currentPageNumber + 1)
7852 + #end
7853 + (% class=~"clear~" ~%)(%~%)
7854 + )))## pagingLinks
7855 + #end
7856 + #end
7857 +#end
7858 +##
7859 +##
7860 +##
7861 +#**
7862 + * Displays a message box with ~"publish~" icon.
7863 + *
7864 + * @param message A text message concerning blog article publishing
7865 + *###
7866 +#macro(publishMessageBox $message)
7867 +(% class=~"plainmessage publish-message~" ~%)((($services.icon.render('world') $message)))
7868 +#end
7869 +#**
7870 + * Displays a message box with ~"show/hide~" icon.
7871 + *
7872 + * @param message A text message concerning blog article hiding
7873 + *###
7874 +#macro(hideMessageBox $message)
7875 +(% class=~"plainmessage hide-message~" ~%)((($services.icon.render('unlock') $message)))
7876 +#end
7877 +##
7878 +##
7879 +##
7880 +#**
7881 + * Determine the requested week, for using in a weekly-indexed blog. The relevant request parameters are
7882 + * <tt>year</tt> and <tt>week</tt>. By default, the current week is used.
7883 + *
7884 + * @param monthDate The resulting week, a JODATime MutableDateTime.
7885 + *###
7886 +#macro(getRequestedWeek $weekDate)
7887 + #set ($weekDate = $NULL)
7888 + #setVariable (~"$weekDate~" $xwiki.jodatime.mutableDateTime)
7889 + #if(~"$!\{request.year}~" != '')
7890 + #set ($discard = $weekDate.setYear($numbertool.toNumber($request.year).intValue()))
7891 + #end
7892 + #if(~"$!\{request.week}~" != '')
7893 + #set ($discard = $weekDate.setWeekOfWeekyear($numbertool.toNumber($request.week).intValue()))
7894 + #end
7895 +#end
7896 +##
7897 +##
7898 +##
7899 +#**
7900 + * Determine the requested month, for using in a monthly-indexed blog. The relevant request parameters are
7901 + * <tt>year</tt> and <tt>month</tt>. By default, the current month is used.
7902 + *
7903 + * @param monthDate The resulting month, a JODATime MutableDateTime.
7904 + *###
7905 +#macro(getRequestedMonth $monthDate)
7906 + #set ($monthDate = $NULL)
7907 + #setVariable (~"$monthDate~" $xwiki.jodatime.mutableDateTime)
7908 + #if(~"$!\{request.year}~" != '')
7909 + #set ($discard = $monthDate.setYear($numbertool.toNumber($request.year).intValue()))
7910 + #end
7911 + #if(~"$!\{request.month}~" != '')
7912 + #set ($discard = $monthDate.setMonthOfYear($numbertool.toNumber($request.month).intValue()))
7913 + #end
7914 +#end
7915 +##
7916 +##
7917 +##
7918 +#**
7919 + * Retrieve a blog property (title, display type, etc).
7920 + *
7921 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
7922 + * @param propertyName The name of the property to be retrieved. One of the <tt>Blog.BlogClass</tt>'s properties.
7923 + * @param defaultValue The default value to use in case the blog object does not define one.
7924 + * @param propertyValue The resulting value.
7925 + *###
7926 +#macro(getBlogProperty $blogDoc $propertyName $defaultValue $propertyValue)
7927 + #set($result = ~"$!\{blogDoc.getObject($\{blogClassname}).getProperty($propertyName).value}~")
7928 + #if($result == '')
7929 + #set($result = $defaultValue)
7930 + #end
7931 + #set ($propertyValue = $NULL)
7932 + #setVariable (~"$propertyValue~" $result)
7933 +#end
7934 +
7935 +#**
7936 + * If an error occurs when executing an action, set a specific response status and display an error message.
7937 + *
7938 + * @param status The response status.
7939 + * @param text The user readable error to be displayed. Can be a translation key.
7940 + * @param parameters The parameters to use when decoding the translation key.
7941 + *###
7942 +#macro(blog__actionResponseError $status $text $parameters)
7943 + $response.setStatus($status)
7944 + #if($request.ajax)
7945 + $services.localization.render($text, $!parameters)
7946 + #else
7947 + \{\{error}}$services.localization.render($text, $!parameters)\{\{/error}}
7948 + #end
7949 +#end
7950 +##
7951 +##
7952 +##
7953 +#**
7954 + * Check if a blog is the Default blog (The one in the 'Blog' space).
7955 + *
7956 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
7957 + * @param isDefault The resulting boolean.
7958 + *###
7959 +#macro(isDefaultBlog $blogDoc $isDefault)
7960 + #set ($result = false)
7961 + #if ($blogDoc.space == 'Blog')
7962 + #set ($result = true)
7963 + #end
7964 + #setVariable(~"$isDefault~" $result)
7965 +#end
7966 +##
7967 +##
7968 +##
7969 +#**
7970 + * Retrieve the blog posts location (space).
7971 + *
7972 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
7973 + * @param postsLocation The resulting location.
7974 + *###
7975 +#macro(getBlogPostsLocation $blogSpace $postsLocation)
7976 + #getBlogDocument($blogSpace $blogDoc)
7977 + #getBlogProperty($blogDoc 'postsLocation' $blogDoc.space $result)
7978 + #set ($postsLocation = $NULL)
7979 + #setVariable (~"$postsLocation~" $result)
7980 +#end
7981 +##
7982 +##
7983 +##
7984 +#**
7985 + * Retrieve the blog categories location (space).
7986 + *
7987 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
7988 + * @param categoriesLocation The resulting location.
7989 + *###
7990 +#macro(getBlogCategoriesLocation $blogSpace $categoriesLocation)
7991 + #getBlogDocument($blogSpace $blogDoc)
7992 + #getBlogProperty($blogDoc 'categoriesLocation' 'Blog' $result)
7993 + #set ($postsLocation = $NULL)
7994 + #setVariable (~"$categoriesLocation~" $result)
7995 +#end
7996 +###**
7997 + * Return the Query for selecting the blog posts based on the context where the posts are displayed.
7998 + * for example there is 4 different panel contexts:
7999 + * aBlog.aPost or aBlog.WebHome
8000 + * aCategorySpace.aCategory
8001 + * aCategorySpace.WebHome
8002 + * Blog.aPost or Blog.WebHome
8003 + *
8004 + * @param query The query for selecting blog entries.
8005 + * @param queryParams The parameters to bind with the generated query.
8006 + * @param targetDoc The document in which the articles will be displayed.
8007 + *###
8008 +#macro(getAllBlogPostsQueryBasedOnDisplayContext $targetDoc $query $queryParams)
8009 + #set ($query = $NULL)
8010 + #set ($queryParams = $NULL)
8011 + #getCategoryAllBlogPostsQuery($resultQuery)
8012 + #set ($resultQueryParams = \{})
8013 + #set($sanitizedSpace = $targetDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
8014 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
8015 + ## Get all posts that are in the default blog space('Blog') or in category 'Blog.%'
8016 + #set ($discard = $resultQueryParams.put('space', $targetDoc.space))
8017 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
8018 + #set($resultQuery = ~"$\{resultQuery} and (doc.space = :space or catList like :catList escape '!')~")
8019 + #elseif($targetDoc.getObject($blogCategoryClassname))
8020 + ## Get all posts that are in a category aCategorySpace.aCategory
8021 + #set ($discard = $resultQueryParams.put('catList', $targetDoc.fullName))
8022 + #set($resultQuery = ~"$\{resultQuery} and (catList=:catList)~")
8023 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
8024 + ## Get all posts that are in a category aCategorySpace.%
8025 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
8026 + ## Exclude incategorized posts
8027 + #set ($excludedCategory = ~"$\{targetDoc.space}.WebHome~")
8028 + #if ($targetDoc.space == $defaultBlogSpace)
8029 + #set ($excludedCategory = ~"Blog.Categories.WebHome~")
8030 + #end
8031 + #set ($discard = $resultQueryParams.put('excludedCategory', $excludedCategory))
8032 + #set($resultQuery = ~"$\{resultQuery} and (catList<>:excludedCategory) and (catList like :catList escape '!')~")
8033 + #else
8034 + ## Get all posts in blog space aBlog
8035 + #getAllBlogPostsQuery($resultQuery)
8036 + #getBlogPostsLocation($targetDoc.space $postsLocation)
8037 + #set ($discard = $resultQueryParams.put('space', $postsLocation))
8038 + #set($resultQuery = ~"$\{resultQuery} and doc.space = :space~")
8039 + #end
8040 + #setVariable(~"$query~" $resultQuery)
8041 + #setVariable(~"$queryParams~" $resultQueryParams)
8042 +#end
8043 +##
8044 +##
8045 +##
8046 +###**
8047 + * Display blog posts based on the context where the posts are displayed.
8048 + * for example there is 4 different panel contexts:
8049 + * aBlog.aPost or aBlog.WebHome
8050 + * aCategorySpace.aCategory
8051 + * aCategorySpace.WebHome
8052 + * Blog.aPost or Blog.WebHome
8053 + *
8054 + * @param targetDoc The document in which the articles will be displayed.
8055 + * @param postsVisiblity The visibility of the posts to display: recent, unpublished, ...
8056 + * @param layout Layout of the the posts to display
8057 + * @param layoutParams additional layout parameters, it is a string like 'param1=val1|...|paramN=valueN'
8058 + * @param limit the number of posts to display
8059 + *###
8060 +#macro(displayBlogPostsBasedOnContext $targetDoc $postsVisiblity $layout $layoutParams $limit)
8061 + #if ($postLayout == 'full')
8062 + #set ($macro.paginated = 'yes')
8063 + #end
8064 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
8065 + ## Display all posts that are in the default blog space('Blog') or in category 'Blog.%'
8066 + #getBlogPostsLayout($xwiki.getDocument(~"$\{defaultBlogSpace}.WebHome~") $postsLayout)
8067 + #if (~"$!layout~" == '')
8068 + #set ($layout = $postsLayout)
8069 + #end
8070 + #if ($postsVisiblity == 'recent')
8071 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
8072 + #elseif($postsVisiblity == 'unpublished')
8073 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
8074 + #end
8075 + #elseif($targetDoc.getObject($blogCategoryClassname))
8076 + ## Display all posts that are in a category aCategorySpace.aCategory
8077 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
8078 + #getBlogPostsLayout($blogDoc $postsLayout)
8079 + #if (~"$!layout~" == '')
8080 + #set ($layout = $postsLayout)
8081 + #end
8082 + #if ($postsVisiblity == 'recent')
8083 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
8084 + #elseif($postsVisiblity == 'unpublished')
8085 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
8086 + #end
8087 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
8088 + ## Display all posts that are in a category aCategorySpace.%
8089 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
8090 + #getBlogPostsLayout($blogDoc $postsLayout)
8091 + #if (~"$!layout~" == '')
8092 + #set ($layout = $postsLayout)
8093 + #end
8094 + #if ($postsVisiblity == 'recent')
8095 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
8096 + #elseif($postsVisiblity == 'unpublished')
8097 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
8098 + #end
8099 + #else
8100 + ## Display all posts in blog space aBlog
8101 + #getBlogDocument($targetDoc.space $blogDoc)
8102 + #getBlogPostsLayout($blogDoc $postsLayout)
8103 + #if (~"$!layout~" == '')
8104 + #set ($layout = $postsLayout)
8105 + #end
8106 + #if ($postsVisiblity == 'recent')
8107 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
8108 + #elseif($postsVisiblity == 'unpublished')
8109 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
8110 + #end
8111 + #end
8112 +#end
8113 +##
8114 +##
8115 +##
8116 +#**
8117 + * Bind parameters to a query object.
8118 + *
8119 + * @param queryObj The query object (org.xwiki.query.internal.ScriptQuery object)
8120 + * @param queryParams the query parameters.
8121 + *###
8122 +#macro(bindQueryParameters $queryObj $queryParams)
8123 + #set ($output = $queryObj)
8124 + #foreach( $key in $queryParams.keySet() )
8125 + #set($output = $queryObj.bindValue($key, $queryParams.get($key)))
8126 + #end
8127 + #setVariable(~"$queryObj~" $output)
8128 +#end
8129 +##
8130 +##
8131 +##
8132 +#**
8133 + * Determines the blogposts layout: Default layout (Calendar), Image thumbnail
8134 + *
8135 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>postsLayout</tt>
8136 + * property set.
8137 + * @param postsLayout The resulting string. If the blog object does not define anything, it is considered full (default).
8138 + *###
8139 +#macro(getBlogPostsLayout $blogDoc $postsLayout)
8140 + #getBlogProperty($blogDoc 'postsLayout' 'full' $res)
8141 + #set ($postsLayout = $NULL)
8142 + #setVariable (~"$postsLayout~" $res)
8143 +#end
8144 +##
8145 +##
8146 +##
8147 +#**
8148 + * Retrieve the blog document of a categories space, which is the blog descriptor that have its categoriesLocation property set to the categories space
8149 + *
8150 + * @param categoriesSpace A <tt>String</tt>, the name of the space.
8151 + * @param blogDoc The resulting XDocument.
8152 + *###
8153 +#macro(getBlogDocumentForCategoriesSpace $categoriesSpace $blogDoc)
8154 + #set($macro.blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as categoriesLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=categoriesLocationProp.id.id and categoriesLocationProp.id.name='categoriesLocation' and categoriesLocationProp.value=:categoriesLocation order by doc.creationDate~").setLimit(1).setOffset(0).bindValue('categoriesLocation', $categoriesSpace).execute())
8155 + #if($macro.blogDocs.size() > 0 && $categoriesSpace != $defaultBlogSpace)
8156 + #set($macro.result = $xwiki.getDocument($macro.blogDocs.get(0)))
8157 + #else
8158 + ## Fallback to Blog.WebHome, the default blog
8159 + #set($macro.result = $xwiki.getDocument('Blog.WebHome'))
8160 + #end
8161 + #set ($blogDoc = $NULL)
8162 + #setVariable (~"$blogDoc~" $macro.result)
8163 +#end" %)
8164 +(((
8165 +(% class="macro-placeholder hidden" %)
8166 +(((
8167 +macro:velocity
8168 +)))
8169 +)))
8170 +)))
8171 +
8172 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogPostLayoutMacros~"" %)
8173 +(((
8174 +(% class="macro-placeholder hidden" %)
8175 +(((
8176 +macro:include
8177 +)))
8178 +
8179 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|#**
8180 + * Extract the layout parameters from a string.
8181 + *
8182 + * @param layoutParamsString The string representation of the layout parameters.
8183 + * It should contain a String following this format ~"paramName1=Value1|paramName2=Value2|...|paramNameK=ValueK~"
8184 + * @param layoutsParameters The resulting layout parameters Map.
8185 + *###
8186 +#macro(extractLayoutParametersFromString $layoutParamsString $layoutsParameters)
8187 + #set ($layoutsParameters = $NULL)
8188 + #set ($macro.layoutParams = \{})
8189 + #if (~"$!layoutParamsString~" != '')
8190 + #set ($macro.paramsArr = $layoutParamsString.split('\\|'))
8191 + #foreach ($item in $macro.paramsArr)
8192 + #set ($itemSplit = $item.split('='))
8193 + #if ($itemSplit.size() == 2)
8194 + #set ($discard = $macro.layoutParams.put($itemSplit[0].trim(), $itemSplit[1].trim()))
8195 + #end
8196 + #end
8197 + #end
8198 + #setVariable(~"$layoutsParameters~" $macro.layoutParams)
8199 +#end" %)
8200 +(((
8201 +(% class="macro-placeholder hidden" %)
8202 +(((
8203 +macro:velocity
8204 +)))
8205 +)))
8206 +)))
8207 +
8208 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-| #macro(displaySmallPost $pDoc $pObj)
8209 + #initLayoutVars($pDoc $pObj)
8210 + <div class=~"col-xs-12 col-sm-6 next_blog~">
8211 + <a href=~"$pDoc.uRL~" class=~"thumbnail~">
8212 + <div class=~"row~">
8213 + <div class=~"col-xs-4~">
8214 + #if ($imageAtt)
8215 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
8216 + #end
8217 + </div>
8218 + <div class=~"col-xs-8 art_det~">
8219 + <p class=~"text-left~">
8220 + #if($displayTitle)$!postTitle #end
8221 + <br/><span class=~"date_info~"> $!dateStr </span>
8222 + </p>
8223 + #displayPostDetails($pDoc)
8224 + </div>
8225 + </div>
8226 + </a>
8227 + </div>
8228 + #end
8229 + ##
8230 + ##
8231 + ##
8232 + #macro(displayPinnedPost $pDoc $pObj)
8233 + #initLayoutVars($pDoc $pObj)
8234 + <div class=~"col-xs-12 col-sm-4 col-md-4 blog_pin~">
8235 + <a href=~"$pDoc.uRL~" class=~"all-post-link~">
8236 + <div class=~"thumbnail~">
8237 + #if ($displayTitle && $displayTitleFirstOnPinnedPosts)
8238 + <h5 class=~"title-top~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
8239 + #end
8240 + #if ($imageAtt)
8241 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
8242 + #end
8243 + <div class=~"caption~">
8244 + #if ($displayTitle && !$displayTitleFirstOnPinnedPosts)
8245 + <h5 class=~"text-left~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
8246 + #end
8247 + #if ($displaySummaryOnPinnedPosts)
8248 + <div class=~"text-left post-summary~">
8249 + #set ($postContent = $pObj.getProperty('extract').value)
8250 + $!pDoc.getRenderedContent($postContent, $pDoc.syntax.toIdString())
8251 + </div>
8252 + #end
8253 + #displayPostDetails($pDoc)
8254 + </div>
8255 + </div>
8256 + </a>
8257 + </div>
8258 + #end
8259 + ##
8260 + ##
8261 + ##
8262 + #macro(formatPostDate $pDoc $pObj)
8263 + #set ($formattedDate = $NULL)
8264 + #set($dateStr = $datetool.format('medium', $postDate, $xcontext.locale))
8265 + #if (~"$!dateStr~" != '')
8266 + #set ($dateArr = $dateStr.split(' '))
8267 + #if ($dateArr.size() > 3)
8268 + #set ($dateStr = ~"~")
8269 + #foreach($s in $dateArr.subList(0, 3))
8270 + #set ($dateStr = ~"$\{dateStr}$\{s} ~")
8271 + #end
8272 + #end
8273 + #end
8274 + #setVariable(~"$formattedDate~" $dateStr)
8275 + #end
8276 + ##
8277 + ##
8278 + ##
8279 + #macro(displayPostDetails $pDoc)
8280 + <div class=~"row post-details~">
8281 + <div class=~"col-xs-8 detail~">
8282 + #if ($services.like.displayButton($pDoc.documentReference))
8283 + #set ($optLikeRecord = $services.like.getLikes($pDoc.documentReference))
8284 + ## Retrieve the likes number in XWiki 12.9+
8285 + #set ($likeNumber = $optLikeRecord.get())
8286 + #if (!$stringtool.isNumeric($likeNumber.toString()))
8287 + ## Retrieve the likes number in XWiki versions greater than 12.7 and lower than 12.9.
8288 + #set ($likeNumber = $optLikeRecord.get().likeNumber)
8289 + #end
8290 + #if ($stringtool.isNumeric($likeNumber.toString()))
8291 + <div class=~"post-likes btn btn-default disabled badge~"
8292 + title=~"$escapetool.xml($services.localization.render('like.button.title', [$likeNumber]))~">
8293 + $services.icon.renderHTML('heart') <span class=~"like-number~">$likeNumber</span>
8294 + </div>
8295 + #end
8296 + #elseif ($services.ratings)
8297 + #set ($ratingsConfigDoc = $services.ratings.getConfigurationDocument($pDoc.documentReference))
8298 + #if ($ratingsConfigDoc.getValue('displayRatings') == 1)
8299 + <ul class=~"pull-left note list-inline~">
8300 + #foreach ($x in [1..5])
8301 + #set ($cls = ~"~")
8302 + #if ($x > $averageVote)
8303 + #set ($cls = ~"-o~")
8304 + #end
8305 + <li><span class=~"fa fa-star$\{cls}~"></span></li>
8306 + #end
8307 + </ul>
8308 + #end
8309 + #end
8310 + </div>
8311 + #if ($showPostComments)
8312 + <div class=~"col-xs-4 com_det~">
8313 + <p class=~"text-right~">$services.icon.renderHTML('comments') ($!nbComments)</p>
8314 + </div>
8315 + #end
8316 + </div>
8317 + #end
8318 + ##
8319 + ##
8320 + ##
8321 + #macro(initLayoutVars $pDoc $pObj)
8322 + #set ($postTitle = $pDoc.display('title', 'view', $pObj))
8323 + #set ($imageAtt = $pDoc.getAttachment($pObj.getValue('image')))
8324 + #isPublished($pObj $isPublished)
8325 + #isHidden($pObj $isHidden)
8326 + #getEntryDate($pDoc $pObj $postDate)
8327 + #formatPostDate($postDate $dateStr)
8328 + #set ($averageVote = $mathtool.round($services.ratings.getAverageRating($pDoc.documentReference).getAverageVote()))
8329 + #set ($nbComments = $pDoc.getComments().size())
8330 + #set ($showPostComments = true)
8331 + #if ($xwiki.getSpacePreferenceFor('showcomments', $pDoc.documentReference.lastSpaceReference, '1') == '0')
8332 + #set ($showPostComments = false)
8333 + #end
8334 + #end
8335 + ##
8336 + ##
8337 + ##
8338 + #macro(displayEditPinnedPostsButton)
8339 + #if (~"$!macroAdditionalParams.get('postIndex')~" == '0' && $services.security.authorization.hasAccess('edit', $pinnedPostsSourceDoc.fullName))
8340 + #set ($discard = $xwiki.ssx.use('Blog.PinnedPostsSheet'))
8341 + #set ($discard = $xwiki.jsx.use('Blog.PinnedPostsSheet'))
8342 + #set ($editPinnedPostsURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'get', 'sheet=Blog.PinnedPostsSheet'))
8343 + #set ($newPinnedPostsObjectURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'objectadd', ~"classname=Blog.PinnedPostsClass&form_token=$!\{services.csrf.getToken()}~"))
8344 + <div class=~"edit-pinned-posts-container~">
8345 + <div class=~"col-xs-12 col-sm-12 col-md-12 text-right edit-pinned-posts~">
8346 + <a href=~"javascript:;~" class=~"editPinnedPosts~">
8347 + <span class=~"glyphicon glyphicon-edit~" aria-hidden=~"true~"></span> $services.localization.render('blog.post.layout.cards.pinnedposts.edit')
8348 + </a>
8349 + <input type=~"hidden~" id=~"editPinnedPostsURL~" value=~"$escapetool.xml($editPinnedPostsURL)~"/>
8350 + <input type=~"hidden~" id=~"newPinnedPostsObjectURL~" value=~"$escapetool.xml($newPinnedPostsObjectURL)~"/>
8351 + </div>
8352 + </div>
8353 + #if (~"$!pinnedPostsObj~" == '')
8354 + <input type=~"hidden~" name=~"createPinnedPostsObject~" value=~"1~"/>
8355 + #end
8356 + #end
8357 + #end" %)
8358 +(((
8359 +(% class="macro-placeholder hidden" %)
8360 +(((
8361 +macro:velocity
8362 +)))
8363 +)))
8364 +
8365 +(% data-macro="startmacro:velocity|-||-| #if ($services.security.authorization.hasAccess('view', $xcontext.macro.params.reference))
8366 + #set ($postDoc = $xwiki.getDocument($xcontext.macro.params.reference))
8367 + #getEntryObject($postDoc $postObj)
8368 + #if (~"$!postObj~" != '')
8369 + #extractLayoutParametersFromString($xcontext.macro.params.params $macroAdditionalParams)
8370 + ##
8371 + #set ($displayTitle = true)
8372 + #if (~"$!macroAdditionalParams.get('displayTitle')~" == 'false')
8373 + #set ($displayTitle = false)
8374 + #end
8375 + ##
8376 + #set ($displayTitleFirstOnPinnedPosts = false)
8377 + #if (~"$!macroAdditionalParams.get('displayTitleFirstOnPinnedPosts')~" == 'true')
8378 + #set ($displayTitleFirstOnPinnedPosts = true)
8379 + #end
8380 + ##
8381 + #set ($displaySummaryOnPinnedPosts = true)
8382 + #if (~"$!macroAdditionalParams.get('displaySummaryOnPinnedPosts')~" == 'false')
8383 + #set ($displaySummaryOnPinnedPosts = false)
8384 + #end
8385 + ##
8386 + #set ($postIndex = $numbertool.toNumber($macroAdditionalParams.get('postIndex')).intValue())
8387 + #if ($postIndex == 0)
8388 + #set ($stopBlogPostsDisplay = false)
8389 + #end
8390 + #set ($listResultsCount = $numbertool.toNumber($macroAdditionalParams.get('list-results-count')).intValue())
8391 + #set($discard = $xwiki.ssx.use('Blog.BlogPostLayoutCards'))
8392 + #set($scaleWidth = 600)
8393 + #set($imgQs=~"width=$scaleWidth~")
8394 + ## Display pinned posts
8395 + ## Get the list of pinned posts
8396 + #set ($pinnedPosts = [])
8397 + #set ($pinnedPostsSourceDoc = $NULL)
8398 + #if (~"$!macroAdditionalParams.get('forceDisplayPinnedPosts')~" == 'true' && ~"$!macroAdditionalParams.get('list-blog')~" != '')
8399 + #set ($pinnedPostsSourceDoc = $xwiki.getDocument($macroAdditionalParams.get('list-blog')))
8400 + ## Note that the 'list-blog' parameter contains the value of the 'blog' parameter of the blogpostlist macro passed to the current layout macro
8401 + #end
8402 + #if (~"$!pinnedPostsSourceDoc~" != '')
8403 + #set ($pinnedPostsObj = $pinnedPostsSourceDoc.getObject('Blog.PinnedPostsClass'))
8404 + #if (~"$!pinnedPostsObj~" != '')
8405 + #set ($orderedPinnedPostsJSON = $pinnedPostsObj.getProperty('orderedPosts').value)
8406 + #if (~"$!orderedPinnedPostsJSON~" != '')
8407 + #set ($pinnedPosts = $jsontool.parse($orderedPinnedPostsJSON))
8408 + #else
8409 + #set ($pinnedPosts = $pinnedPostsObj.getProperty('posts').value)
8410 + #end
8411 + #end
8412 + #if ($postIndex == 0 && $pinnedPosts.size() > 0)
8413 + \{\{html clean=~"false~"}}
8414 + #set ($x = 0)
8415 + #set ($showPinnedPostsButton = true)
8416 + #foreach ($pinnedPost in $pinnedPosts)
8417 + #if ($x == 0)
8418 + <div class=~"row flex-container~">
8419 + #if ($showPinnedPostsButton)
8420 + #displayEditPinnedPostsButton()
8421 + #set($showPinnedPostsButton = false)
8422 + #end
8423 + #end
8424 + #set ($pinnedPostDoc = $xwiki.getDocument($pinnedPost))
8425 + #getEntryObject($pinnedPostDoc $pinnedPostObj)
8426 + #if (~"$!pinnedPostObj~" != '')
8427 + #displayPinnedPost($pinnedPostDoc $pinnedPostObj)
8428 + #end
8429 + #set ($x = $mathtool.add($x, 1))
8430 + #if ($x == 3)
8431 + #set ($x = 0)
8432 + </div>
8433 + #end
8434 + #end
8435 + #if ($mathtool.mod($x, 3) != 0)
8436 + </div>
8437 + #end
8438 + \{\{/html}}
8439 +
8440 + ## If the first post is a pinned post : this means that all the posts are pinned
8441 + ## In this case, avoid displaying the posts again after the pinned posts section.
8442 + #if ($pinnedPosts.contains($xcontext.macro.params.reference))
8443 + #set ($stopBlogPostsDisplay = true)
8444 + #end
8445 + #elseif($postIndex == 0 && $pinnedPosts.size() == 0)
8446 +
8447 + \{\{html}}
8448 + <div class=~"row no-pinnded-posts~">
8449 + #displayEditPinnedPostsButton()
8450 + </div>
8451 + \{\{/html}}
8452 +
8453 + #end
8454 + #end
8455 + #if (!$stopBlogPostsDisplay)
8456 + \{\{html clean=~"false~"}}
8457 + #if (~"$!nbDisplayedPosts~" == '' || $postIndex == 0)
8458 + #set ($nbDisplayedPosts = 0)
8459 + #end
8460 + #if($mathtool.mod($nbDisplayedPosts, 2) == 0)
8461 + #if ($nbDisplayedPosts != 0)
8462 + </div>
8463 + #set ($lastHtmlTag = 'c')
8464 + #end
8465 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
8466 + <div class=~"row~">
8467 + #set ($lastHtmlTag = 'o')
8468 + #set ($lastRowClass = ~"~")
8469 + #else
8470 + <div class=~"row flex-container~">
8471 + #set ($lastHtmlTag = 'o')
8472 + #set ($lastRowClass = ~"flex~")
8473 + #end
8474 + #end
8475 + #displaySmallPost($postDoc $postObj)
8476 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
8477 + </div>
8478 + #set ($lastHtmlTag = 'c')
8479 + #end
8480 + #set ($nbDisplayedPosts = $mathtool.add($nbDisplayedPosts, 1))
8481 + #if ($postIndex == $mathtool.sub($listResultsCount, 1))
8482 + #if (~"$!lastHtmlTag~" == 'o')
8483 + #if ($mathtool.mod($nbDisplayedPosts, 2) == 1 && $lastRowClass == ~"flex~")
8484 + <div class=~"col-xs-12 col-sm-6~"></div>
8485 + #end
8486 + </div>
8487 + #end
8488 + #end
8489 + \{\{/html}}
8490 + #end
8491 + #else
8492 + \{\{error}}$services.localization.render('blog.blogpostlayout.notpost', [$xcontext.macro.params.reference])\{\{/error}}
8493 + #end
8494 + #else
8495 + \{\{error}}$services.localization.render('blog.blogpostlayout.post_view_not_allowed', [$xcontext.macro.params.reference])\{\{/error}}
8496 + #end" class="macro hidden macro-placeholder" %)macro:velocity(% data-macro="startmacro:html|-|clean=~"false~"|-|</div>
8497 +<div class=~"row flex-container~">
8498 +<div class=~"col-xs-12 col-sm-6 next_blog~">
8499 +<a href=~"/Nieuws/Feestelijke%20afsluiting%2C%20keuring%20materieel%20en%20tellen%20voorraden~" class=~"thumbnail~">
8500 +<div class=~"row~">
8501 +<div class=~"col-xs-4~">
8502 +<img src=~"/download/Nieuws/Feestelijke%20afsluiting%2C%20keuring%20materieel%20en%20tellen%20voorraden/OIP.jpg?width=600&rev=1.1~" />
8503 +</div>
8504 +<div class=~"col-xs-8 art_det~">
8505 +<p class=~"text-left~">
8506 +Feestelijke afsluiting, keuring materieel en tellen voorraden <br/><span class=~"date_info~"> 14 dec. 2023 </span>
8507 +</p>
8508 +<div class=~"row post-details~">
8509 +<div class=~"col-xs-8 detail~">
8510 +<div class=~"post-likes btn btn-default disabled badge~"
8511 +title=~"Number of likes on this page: 1~">
8512 +<span class=~"fa fa-heart~"></span> <span class=~"like-number~">1</span>
8513 +</div>
8514 +</div>
8515 +<div class=~"col-xs-4 com_det~">
8516 +<p class=~"text-right~"><span class=~"fa fa-comments~"></span> (0)</p>
8517 +</div>
8518 +</div>
8519 +</div>
8520 +</div>
8521 +</a>
8522 +</div>" class="macro macro hidden macro-placeholder" %)macro:html
8523 +)))
8524 +)))
8525 +
8526 +(% class="row flex-container" %)
8527 +(((
8528 +(% class="col-xs-12 col-sm-6 next_blog" %)
8529 +(((
8530 +(% class="row" %)
8531 +(((
8532 +(% class="col-xs-4" %)
8533 +(((
8534 +[[~[~[image:/download/Nieuws/Feestelijke%20afsluiting%2C%20keuring%20materieel%20en%20tellen%20voorraden/OIP.jpg?width=600&rev=1.1~]~]>>path:/Nieuws/Feestelijke%20afsluiting%2C%20keuring%20materieel%20en%20tellen%20voorraden||class="thumbnail"]]
8535 +)))
8536 +
8537 +(% class="col-xs-8 art_det" %)
8538 +(((
8539 +(% class="text-left" %)
8540 +[[Feestelijke afsluiting, keuring materieel en tellen voorraden
8541 +(% class="date_info" %) 14 dec. 2023>>path:/Nieuws/Feestelijke%20afsluiting%2C%20keuring%20materieel%20en%20tellen%20voorraden||class="thumbnail"]]
8542 +
8543 +(% class="row post-details" %)
8544 +(((
8545 +(% class="col-xs-8 detail" %)
8546 +(((
8547 +(% class="post-likes btn btn-default disabled badge" title="Number of likes on this page: 1" %)
8548 +(((
8549 +[[(% class="like-number" %)1>>path:/Nieuws/Feestelijke%20afsluiting%2C%20keuring%20materieel%20en%20tellen%20voorraden||class="thumbnail"]]
8550 +)))
8551 +)))
8552 +
8553 +(% class="col-xs-4 com_det" %)
8554 +(((
8555 +(% class="text-right" %)
8556 +[[(0)>>path:/Nieuws/Feestelijke%20afsluiting%2C%20keuring%20materieel%20en%20tellen%20voorraden||class="thumbnail"]]
8557 +)))
8558 +)))
8559 +)))
8560 +)))
8561 +)))
8562 +
8563 +(% class="macro" data-macro="startmacro:blogPostLayoutCards|-|reference=~"Nieuws.RI&E 2023~" params=~"displayTitle=true|useSummary=true|list-limit=6|list-layout=cards|list-blog=Nieuws.WebHome|list-paginated=no|list-results-count=6|postIndex=0|previousPostReference=|postIndex=1|previousPostReference=Nieuws.Nieuwsbrief januari 2024|postIndex=2|previousPostReference=Nieuws.Audit BMI en BORG|postIndex=3|previousPostReference=Nieuws.Nieuwsbrief december 2023|postIndex=4|previousPostReference=Nieuws.Nieuwsbrief november 2023|postIndex=5|previousPostReference=Nieuws.Feestelijke afsluiting, keuring materieel en tellen voorraden~"" %)
8564 +(((
8565 +(% class="macro-placeholder hidden" %)
8566 +(((
8567 +macro:blogPostLayoutCards
8568 +)))
8569 +
8570 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogCode~"" %)
8571 +(((
8572 +(% class="macro-placeholder hidden" %)
8573 +(((
8574 +macro:include
8575 +)))
8576 +
8577 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogParameters~"" %)
8578 +(((
8579 +(% class="macro-placeholder hidden" %)
8580 +(((
8581 +macro:include
8582 +)))
8583 +
8584 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|## Blog
8585 +#set($blogClassname = 'Blog.BlogClass')
8586 +#set($blogTemplate = 'Blog.BlogTemplate')
8587 +#set($blogSheet = 'Blog.BlogSheet')
8588 +## Blog entries
8589 +#set($blogPostClassname = 'Blog.BlogPostClass')
8590 +#set($blogPostTemplate = 'Blog.BlogPostTemplate')
8591 +#set($blogPostSheet = 'Blog.BlogPostSheet')
8592 +#set($blogPostObjectNumber = $xwiki.getDocument($blogPostTemplate).getObject($blogPostClassname).number)
8593 +#set($oldArticleClassname = 'XWiki.ArticleClass')
8594 +## Categories
8595 +#set($blogCategoryClassname = 'Blog.CategoryClass')
8596 +#set($blogCategoryTemplate = 'Blog.CategoryTemplate')
8597 +#set($blogCategorySheet = 'Blog.CategorySheet')
8598 +#set($blogCategoriesSheet = 'Blog.CategoriesSheet')
8599 +#set($oldBlogCategoryClassname = 'Blog.Categories')
8600 +#set($defaultCategoryParent = 'Blog.Categories')
8601 +## Style
8602 +#set($blogStyleDocumentName = 'Blog.BlogStyle')
8603 +#set($blogStyleDocument = $xwiki.getDocument($blogStyleDocumentName))
8604 +## Clientside scripts
8605 +#set($blogScriptsDocumentName = 'Blog.BlogScripts')
8606 +#set($blogPublisher = $xwiki.getDocument('Blog.Publisher'))
8607 +## Misc
8608 +#set($thisURL = $doc.getURL($xcontext.action, $request.queryString))
8609 +#set($isBlogPost = $doc.getObject($blogPostClassname))
8610 +#set($defaultBlogSpace = 'Blog')
8611 +#set($isCategoryPage = $doc.getObject($blogCategoryClassname))
8612 +#set($isCategoriesHomePage = $doc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
8613 +##
8614 +##
8615 +##
8616 +#**
8617 + * Displays an image, taken from the blog style document.
8618 + *
8619 + * @param $imgName The name of the icon from icons set to use.
8620 + *#
8621 +#macro(toolImage $imgName)(% class=~"icon-manage~"~%)$services.icon.render($imgName)(%~%)#end" %)
8622 +(((
8623 +(% class="macro-placeholder hidden" %)
8624 +(((
8625 +macro:velocity
8626 +)))
8627 +)))
8628 +)))
8629 +
8630 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|##
8631 +##
8632 +##
8633 +## Import the blog skin and javascripts.
8634 +$!xwiki.ssx.use($blogStyleDocumentName)##
8635 +$!xwiki.jsx.use($blogScriptsDocumentName)##
8636 +##
8637 +## import the hierarchy for the path the blog post footer (in displayEntryBlogLocation)
8638 +#template('hierarchy_macros.vm')##
8639 +##
8640 +##
8641 +#**
8642 + * Prints a blog. This is the main macro used in the BlogSheet.
8643 + *
8644 + * @param blogDoc the XDocument holding the blog definition object.
8645 + *###
8646 +#macro(printBlog $blogDoc)
8647 + \{\{include reference='Blog.CreatePost'/}}
8648 +
8649 + ## Use the blogPostList macro to display the blogposts
8650 + ## The blogPostList is used only in case of 'all' or 'paged' blog display type because the blogPostList macro
8651 + ## do not support FTM the monthly and weekly blog display types
8652 + #getBlogDisplayType($blogDoc $displayType)
8653 + #if ($displayType == 'weekly' || $displayType == 'monthly')
8654 + #getBlogEntries($blogDoc $entries)
8655 + #displayBlog($entries 'index' true true)
8656 + #displayNavigationLinks($blogDoc)
8657 + #else
8658 + #getBlogDisplayType($blogDoc $displayType)
8659 + #set ($paginated = 'no')
8660 + #if ($displayType == 'paginated')
8661 + #set ($paginated = 'yes')
8662 + #end
8663 + #getBlogPostsLayout($blogDoc $postsLayout)
8664 + (% class=~"hfeed index~" ~%)(((\{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$paginated~" layout=~"$!postsLayout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" /}})))
8665 + #end
8666 +#end
8667 +##
8668 +##
8669 +##
8670 +#**
8671 + * Shows blog information. In view mode, the description is printed. In edit mode, allows changing blog settings: title,
8672 + * description, blog type (global or in-space), index display type (fixed size pagination, weekly index, monthly index,
8673 + * all entries).
8674 + *
8675 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
8676 + *###
8677 +#macro(showBlogInfo $blogDoc)
8678 + #if($blogDoc.getObject($blogClassname))
8679 + ## Keep testing for inline action for backward compatibility with older blogs.
8680 + #if($xcontext.action == 'edit' || $xcontext.action == 'inline')
8681 + #macro(displayProperty $blogDoc $propname)
8682 + ; #displayPropName($xwiki.getClass($blogClassname).get($propname)):
8683 + : $blogDoc.display($propname)
8684 + #end
8685 + #displayProperty($blogDoc 'title')
8686 + #displayProperty($blogDoc 'description')
8687 + #displayProperty($blogDoc 'displayType')
8688 + #displayProperty($blogDoc 'itemsPerPage')
8689 + #displayProperty($blogDoc 'postsLayout')
8690 + #displayProperty($blogDoc 'postsLayoutParameters')
8691 + #else
8692 + $blogDoc.display('description')
8693 + #end
8694 + #elseif($doc.fullName == $blogSheet)
8695 += $services.localization.render('blog.code.blogsheet') =
8696 + \{\{translation key='blog.code.sheetexplanation'/}}
8697 + #else
8698 + \{\{warning}}\{\{translation key='blog.code.notblog'/}}\{\{/warning}}
8699 + #end
8700 +#end
8701 +##
8702 +##
8703 +##
8704 +#**
8705 + * Retrieve the blog document, which usually is either <tt>&lt;Space&gt;.WebHome</tt> for whole-spaces blogs, or
8706 + * <tt>&lt;Space&gt;.Blog</tt> for in-space blogs. If none of these documents contains a blog object, then the first
8707 + * (alphabetically) document in the target space that contains one is returned. Finally, if no document in the current
8708 + * space contains a blog object, then <tt>Blog.WebHome</tt> is returned as the default blog.
8709 + *
8710 + * @param space A <tt>String</tt>, the name of the space where to search.
8711 + * @param blogDoc The resulting XDocument.
8712 + *###
8713 +#macro(getBlogDocument $space $blogDoc)
8714 + #set ($result = $NULL)
8715 + ## Check if the current space has a WebPreferences page that contains a Blog.EnablePanelsConfigurationClass object.
8716 + ## It is possible to display a blog's panels info in a page that is not inside a blog and in that case we need to
8717 + ## identify the right blog based on a configuration object in a WebPreferences page.
8718 + #set ($spaceReference = $services.model.resolveSpace($space))
8719 + #set ($preferencesDocRef = $services.model.createDocumentReference('WebPreferences', $spaceReference))
8720 + #set ($preferencesDoc = $xwiki.getDocument($preferencesDocRef))
8721 + #set ($preferencesObj = $preferencesDoc.getObject('Blog.EnablePanelsConfigurationClass'))
8722 + #if ($preferencesObj)
8723 + #set ($result = $xwiki.getDocument( $preferencesObj.getValue('blog')))
8724 + #end
8725 + ## If no special case occurs (like the previous one), identify a blog by checking the current location from its hierarchy.
8726 + #if (~"$!result~" == '')
8727 + ## First, try the Space.WebHome, for a whole-space blog
8728 + #set($result = $xwiki.getDocument(~"$\{space}.WebHome~"))
8729 + #if(!$result.getObject($blogClassname))
8730 + ## Second, try the Space.Blog document
8731 + #set($result = $xwiki.getDocument(~"$\{space}.Blog~"))
8732 + #if(!$result.getObject($blogClassname))
8733 + ## Third, try searching for a blog document in the current space
8734 + ## Prevent the query fail when the space contains dots '.'
8735 + #set($blogDocs = $services.query.hql(~", BaseObject obj where doc.space = :space and obj.name = doc.fullName and obj.className = '$blogClassname' order by doc.name~").setLimit(1).setOffset(0).bindValue('space', $space).execute())
8736 + #if($blogDocs.size() > 0)
8737 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
8738 + #else
8739 + ## Fourth, try searching for a blog document that have the its 'postsLocation' set to the current space
8740 + #set($blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as postsLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=postsLocationProp.id.id and postsLocationProp.id.name='postsLocation' and postsLocationProp.value=:postsLocation order by doc.name~").setLimit(1).setOffset(0).bindValue('postsLocation', $space).execute())
8741 + #if($blogDocs.size() > 0)
8742 + #set($result = $xwiki.getDocument($blogDocs.get(0)))
8743 + #else
8744 + ## Last, fallback to Blog.WebHome, the default blog
8745 + #set($result = $xwiki.getDocument('Blog.WebHome'))
8746 + #end
8747 + #end
8748 + #end
8749 + #end
8750 + #end
8751 + #set ($blogDoc = $NULL)
8752 + #setVariable (~"$blogDoc~" $result)
8753 +#end
8754 +##
8755 +##
8756 +##
8757 +#**
8758 + * Retrieve the blog title.
8759 + *
8760 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass<tt> object with the <tt>title</tt> property set.
8761 + * @param title The resulting title.
8762 + *###
8763 +#macro(getBlogTitle $blogDoc $title)
8764 + ## Titles can contain velocity code (most commonly translations), so we should evaluate them.
8765 + #set ($title = $NULL)
8766 + #setVariable (~"$title~" $!blogDoc.displayTitle)
8767 +#end
8768 +##
8769 +##
8770 +##
8771 +#**
8772 + * Retrieve the blog description.
8773 + *
8774 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>description</tt>
8775 + * property set.
8776 + * @param description The resulting description.
8777 + *###
8778 +#macro(getBlogDescription $blogDoc $description)
8779 + #getBlogProperty($blogDoc 'description' '' $result)
8780 + #set ($description = $NULL)
8781 + #setVariable (~"$description~" $result)
8782 +#end
8783 +##
8784 +##
8785 +##
8786 +#**
8787 + * Retrieves a list of entries to be displayed. The entries are either part of the blog's space, or have the blog
8788 + * document set as a parent. The number and range of entries returned (from all those belonging to this blog) depends on
8789 + * the blog display type: paginated (fixed number of entries), weekly (all entries in a week), monthly (all entries in a
8790 + * month), or all.
8791 + *
8792 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
8793 + * @param entries The resulting list of entries to display, a list of XDocument names.
8794 + *###
8795 +#macro(getBlogEntries $blogDoc $entries)
8796 + #if (!$entries)
8797 + #setVariable (~"$entries~" [])
8798 + #end
8799 + #getAllBlogPostsQuery($query)
8800 + #isDefaultBlog($blogDoc $isDefault)
8801 + #set($queryParams = \{})
8802 + #if ($isDefault)
8803 + #getCategoryAllBlogPostsQuery($query)
8804 + #set($query = ~"$\{query} and (doc.creator = :creator or (isPublished.value = 1 and hidden.value = 0)) and (doc.space = :space or catList like :catList escape '!')~")
8805 + #set($discard = $queryParams.put('creator', $xcontext.user))
8806 + #set($discard = $queryParams.put('space', $blogDoc.space))
8807 + #set($sanitizedBlogSpace = $blogDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
8808 + #set($discard = $queryParams.put('catList', $sanitizedBlogSpace))
8809 + #else
8810 + #set($query = ~"$\{query} and (doc.space = :space or doc.parent = :parent)~")
8811 + #getBlogPostsLocation($blogDoc.space $blogPostsLocation)
8812 + #set($discard = $queryParams.put('space', $blogPostsLocation))
8813 + #set($discard = $queryParams.put('parent', $blogDoc.space))
8814 + #end
8815 + #getBlogDisplayType($blogDoc $displayType)
8816 + #if($displayType == 'weekly')
8817 + #getWeeklyBlogEntries($blogDoc $query $entries $queryParams)
8818 + #elseif($displayType == 'monthly')
8819 + #getMonthlyBlogEntries($blogDoc $query $entries $queryParams)
8820 + #elseif($displayType == 'all')
8821 + #getAllBlogEntries($blogDoc $query $entries $queryParams)
8822 + #else
8823 + #getPagedBlogEntries($blogDoc $query $entries $queryParams)
8824 + #end
8825 +#end
8826 +##
8827 +##
8828 +##
8829 +#**
8830 + * Retrieves a list of entries to be displayed. The entries are taken from a ~"page~" of the blog, a sequence of documents
8831 + * defined by the request parameters <tt>ipp</tt> (items per page) and <tt>page</tt> (the current page). Initially the
8832 + * first page is displayed, with the number of entries defined in the blog object in the <tt>itemsPerPage</tt> property
8833 + * (10 if not defined).
8834 + *
8835 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
8836 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
8837 + * refined to restrict to a given space, or to a given search criteria, etc.
8838 + * @param entries The resulting list of entries to display, a list of XDocument names.
8839 + * @param queryParams The parameters to bind with the query.
8840 + *###
8841 +#macro(getPagedBlogEntries $blogDoc $query $entries $queryParams)
8842 + #if (!$entries)
8843 + #setVariable (~"$entries~" [])
8844 + #end
8845 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
8846 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~"))
8847 + #bindQueryParameters($countQueryObj $queryParams)
8848 + #bindQueryParameters($queryObj $queryParams)
8849 + #set($totalEntries = $countQueryObj.count())
8850 + #getBlogProperty($blogDoc 'itemsPerPage' '10' $defaultItemsPerPage)
8851 + #set($defaultItemsPerPage = $numbertool.toNumber($defaultItemsPerPage).intValue())
8852 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
8853 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
8854 + #set($discard = $entries.addAll($queryObj.setLimit($itemsPerPage).setOffset($startAt).addFilter(~"unique~").execute()))
8855 +#end
8856 +##
8857 +##
8858 +##
8859 +#**
8860 + * Retrieves a list of entries to be displayed. The entries are taken from a week of the blog. The target week is
8861 + * defined by the request parameters <tt>week</tt> (the week number in the year, from 1 to 52) and <tt>year</tt> (4
8862 + * digit year). Initially the current week is displayed.
8863 + *
8864 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
8865 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
8866 + * refined to restrict to a given space, or to a given search criteria, etc.
8867 + * @param entries The resulting list of entries to display, a list of XDocument names.
8868 + * @param queryParams The parameters to bind with the query.
8869 + *###
8870 +#macro(getWeeklyBlogEntries $blogDoc $query $entries $queryParams)
8871 + #if (!$entries)
8872 + #setVariable (~"$entries~" [])
8873 + #end
8874 + #getRequestedWeek($weekDate)
8875 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
8876 + #set($minDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundFloor()))
8877 + #set($maxDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundCeiling()))
8878 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
8879 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
8880 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
8881 + #bindQueryParameters($countQueryObj $queryParams)
8882 + #bindQueryParameters($queryObj $queryParams)
8883 + #set($totalEntries = $countQueryObj.count())
8884 + #set($discard = $entries.addAll($queryObj.execute()))
8885 +#end
8886 +##
8887 +##
8888 +##
8889 +#**
8890 + * Retrieves a list of entries to be displayed. The entries are taken from a month of the blog. The target month is
8891 + * defined by the request parameters <tt>month</tt> (the month number, from 1 to 12) and <tt>year</tt> (4
8892 + * digit year). Initially the current month is displayed.
8893 + *
8894 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
8895 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
8896 + * refined to restrict to a given space, or to a given search criteria, etc.
8897 + * @param entries The resulting list of entries to display, a list of XDocument names.
8898 + * @param queryParams The parameters to bind with the query.
8899 + *###
8900 +#macro(getMonthlyBlogEntries $blogDoc $query $entries)
8901 + #if (!$entries)
8902 + #setVariable (~"$entries~" [])
8903 + #end
8904 + #getRequestedMonth($monthDate)
8905 + #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd'))
8906 + #set($minDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundFloor()))
8907 + #set($maxDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundCeiling()))
8908 + #set($query = ~"$\{query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'~")
8909 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
8910 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
8911 + #bindQueryParameters($countQueryObj $queryParams)
8912 + #bindQueryParameters($queryObj $queryParams)
8913 + #set($totalEntries = $countQueryObj.count())
8914 + #set($discard = $entries.addAll($queryObj.execute()))
8915 +#end
8916 +##
8917 +##
8918 +##
8919 +#**
8920 + * Retrieves a list of entries to be displayed. All entries belonging to the current blog are returned.
8921 + *
8922 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
8923 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
8924 + * refined to restrict to a given space, or to a given search criteria, etc.
8925 + * @param entries The resulting list of entries to display, a list of XDocument names.
8926 + * @param queryParams The parameters to bind with the query.
8927 + *###
8928 +#macro(getAllBlogEntries $blogDoc $query $entries $queryParams)
8929 + #if (!$entries)
8930 + #setVariable (~"$entries~" [])
8931 + #end
8932 + #set($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
8933 + #set($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
8934 + #bindQueryParameters($countQueryObj $queryParams)
8935 + #bindQueryParameters($queryObj $queryParams)
8936 + #set($totalEntries = $countQueryObj.count())
8937 + #set($discard = $entries.addAll($queryObj.execute()))
8938 +#end
8939 +##
8940 +##
8941 +##
8942 +#**
8943 + * Retrieves a list of entries to be displayed. Only (and all) unpublished entries are returned.
8944 + *
8945 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
8946 + * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be
8947 + * refined to restrict to a given space, or to a given search criteria, etc.
8948 + * @param queryParams The parameters to bind with the query.
8949 + * @param entries The resulting list of entries to display, a list of XDocument names.
8950 + *###
8951 +#macro(getUnpublishedBlogEntries $blogDoc $query $queryParams $entries)
8952 + #if (!$entries)
8953 + #setVariable (~"$entries~" [])
8954 + #end
8955 + #set($query = ~"$\{query} and isPublished.value = 0~")
8956 + #set ($countQueryObj = $services.query.hql($query).addFilter(~"unique~"))
8957 + #set ($queryObj = $services.query.hql(~"$\{query} order by publishDate.value desc~").addFilter(~"unique~"))
8958 + #bindQueryParameters($countQueryObj $queryParams)
8959 + #bindQueryParameters($queryObj $queryParams)
8960 + #set($totalEntries = $countQueryObj.count())
8961 + #set($discard = $entries.addAll($queryObj.execute()))
8962 +#end
8963 +##
8964 +##
8965 +##
8966 +#**
8967 + * Retrieves a list of entries to be displayed. The entries are taken from all the wiki, and not from a specific blog.
8968 + *
8969 + * @param entries The resulting list of entries to display, a list of XDocument names.
8970 + *###
8971 +#macro(getGlobalBlogEntries $entries)
8972 + #if (!$entries)
8973 + #setVariable (~"$entries~" [])
8974 + #end
8975 + #getAllBlogPostsQuery($query)
8976 + #set($totalEntries = $services.query.hql($query).count())
8977 + #set($defaultItemsPerPage = 20)
8978 + ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt.
8979 + #preparePagedViewParams($totalEntries $defaultItemsPerPage)
8980 + #set($discard = $entries.addAll($services.query.hql(~"$\{query} order by publishDate.value desc~").setLimit($itemsPerPage).setOffset($startAt).execute()))
8981 +#end
8982 +#**
8983 + * Return the base query for selecting blog entries. It filters only visible entries, but does not bind to a specific
8984 + * blog, nor specify a range or an ordering criteria.
8985 + *
8986 + * This macro is a duplicate of #getAllBlogPostsQuery($query). Keep it in case it's used outside, in custom code.
8987 + *
8988 + * @param query The basic query for selecting blog entries.
8989 + *#
8990 +#macro(getBlogEntriesBaseQuery $query)
8991 + #getAllBlogPostsQuery($query)
8992 +#end
8993 +#**
8994 + * Return the Query for selecting the all wiki blog posts without filtering
8995 + *
8996 + * @param query The basic query for selecting blog entries.
8997 + *#
8998 +#macro(getAllBlogPostsQuery $query)
8999 + #set ($query = $NULL)
9000 + #setVariable(~"$query~" ~", BaseObject as obj, IntegerProperty isPublished,
9001 + IntegerProperty hidden, DateProperty publishDate
9002 + where doc.fullName <> '$blogPostTemplate' and
9003 + obj.name=doc.fullName and obj.className='$blogPostClassname' and
9004 + isPublished.id.id = obj.id and isPublished.id.name = 'published' and
9005 + hidden.id.id = obj.id and hidden.id.name='hidden' and
9006 + publishDate.id.id = obj.id and publishDate.id.name='publishDate' and
9007 + (doc.creator = '$escapetool.sql($xcontext.user)' or (isPublished.value = 1 and hidden.value = 0))~")
9008 +#end
9009 +##
9010 +##
9011 +##
9012 +###**
9013 + * Return the Query for selecting the all wiki blog posts with categories filtering
9014 + *
9015 + * @param query The basic query for selecting blog entries.
9016 + *###
9017 +#macro(getCategoryAllBlogPostsQuery $query)
9018 + #set ($query = $NULL)
9019 + #getAllBlogPostsQuery($baseQuery)
9020 + #set ($baseQuery = $baseQuery.replace('DateProperty publishDate', 'DateProperty publishDate, DBStringListProperty as category left join category.list catList'))
9021 + #setVariable(~"$query~" ~"$\{baseQuery} and obj.id=category.id.id and category.id.name='category'~")
9022 +#end
9023 +##
9024 +##
9025 +##
9026 +#**
9027 + * Determines how is the blog index split into pages: paginated (fixed number of entries), weekly (all entries in a
9028 + * week), monthly (all entries in a month), or all.
9029 + *
9030 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>displayType</tt>
9031 + * property set.
9032 + * @param displayType The resulting string. If the blog object does not define anything, it is considered paginated.
9033 + *###
9034 +#macro(getBlogDisplayType $blogDoc $displayType)
9035 + #getBlogProperty($blogDoc 'displayType' 'paginated' $result)
9036 + #set ($displayType = $NULL)
9037 + #setVariable (~"$displayType~" $result)
9038 +#end
9039 +##
9040 +##
9041 +##
9042 +#**
9043 + * Displays a list of entries.
9044 + *
9045 + * @param entries The entries to display, a list of XDocument names.
9046 + * @param displaying What exactly is displayed: blog index, a single blog entry, a blog category, search results,
9047 + * unpublished entries, etc. This will be used as the classname(s) for the container div (hfeed). Currently
9048 + * used values: index, single, category, search, unpublished, hidden.
9049 + * @param onlyExtract If <tt>true</tt>, only display the extract of articles where available, otherwise display the full content.
9050 + * @param shouldDisplayTitles If <tt>true</tt>, display the blog title (blog posts shouldn't display the title when they're
9051 + * displayed alone on their page since it's the page title which is used in this case)
9052 + *###
9053 +#macro(displayBlog $entries $displaying $onlyExtract $shouldDisplayTitles)
9054 + #set($blogDay = '')
9055 + (% class=~"hfeed $!\{displaying}~" ~%)(((
9056 + (% class=~"blogDay~" ~%)(((
9057 + #foreach ($entryDoc in $xwiki.wrapDocs($entries))
9058 + #getEntryObject($entryDoc $entryObj)
9059 + ## Although all entries should have one of the two objects, better check to be sure.
9060 + #if(~"$!\{entryObj}~" != '')
9061 + #getEntryDate($entryDoc $entryObj $entryDate)
9062 + ## Display a ~"calendar sheet~" for each day. All entries posted on the same day share one such sheet.
9063 + #set($entryDateStr = $xwiki.formatDate($entryDate, 'yyyyMMMMdd'))
9064 + #if($blogDay != $entryDateStr)
9065 + #if($blogDay != '')
9066 + )))
9067 + (% class=~"blogDay~" ~%)(((
9068 + #end
9069 + #displayBlogDate($entryDate)
9070 + #set ($blogDay = $entryDateStr)
9071 + #end
9072 + ## Finally, display the entry.
9073 + #displayEntry($entryDoc $entryObj $onlyExtract $shouldDisplayTitles true)
9074 + #end
9075 + #end
9076 + )))## blogDay
9077 + )))## hfeed
9078 +#end
9079 +##
9080 +##
9081 +##
9082 +#**
9083 + * Get the entry object, either a new BlogPost or an old Article.
9084 + *
9085 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9086 + * @param entryObj The resulting xobject of the blog post.
9087 + *###
9088 +#macro(getEntryObject $entryDoc $__entryObj)
9089 + #set($result = $entryDoc.getObject(~"$\{blogPostClassname}~"))
9090 + #if(!$result)
9091 + #set($result = $entryDoc.getObject(~"$\{oldArticleClassname}~"))
9092 + #end
9093 + ## NOTE: The reason we put an underscore in front of the variable name is to prevent the following line from
9094 + ## overwriting the $entryObj variable that may be defined before this macro is called. Of course, $__entryObj may be
9095 + ## overwritten in this case but it's less likely to have such a variable defined before.
9096 + #set ($__entryObj = $NULL)
9097 + #setVariable (~"$__entryObj~" $result)
9098 +#end
9099 +##
9100 +##
9101 +##
9102 +#**
9103 + * Gets the date associated with a blog entry. This is the publication date. For unpublished entries, initially this is
9104 + * the document creation date, but can be edited by the user.
9105 + *
9106 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9107 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9108 + * @param result The resulting date, an instance of <tt>java.util.Date</tt>.
9109 + *###
9110 +#macro(getEntryDate $entryDoc $entryObj $result)
9111 + #set ($result = $NULL)
9112 + #setVariable (~"$result~" $entryObj.getProperty('publishDate').value)
9113 +#end
9114 +##
9115 +##
9116 +##
9117 +#**
9118 + * Displays a date, nicely formatted as a calendar page.
9119 + *
9120 + * @param date The date to display, an instance of <tt>java.util.Date</tt>.
9121 + *###
9122 +#macro(displayBlogDate $date)
9123 + #set($year = $xwiki.formatDate($date, 'yyyy'))
9124 + ## 3 letter month name, like Jan, Dec.
9125 + #set($month = $xwiki.formatDate($date, 'MMM'))
9126 + ## Uncomment to get a full length month name, like January, December.
9127 + ## TODO: this could be defined somewhere in the blog style.
9128 + ## #set($month = $xwiki.formatDate($date, 'MMMM'))
9129 + #set($day = $xwiki.formatDate($date, 'dd'))
9130 + (% class=~"blogdate~" ~%)
9131 + == (% class=~"month~" ~%)$month(%~%) (% class=~"day~" ~%)$day(%~%) (% class=~"year~" ~%)$year(%~%) ==
9132 +#end
9133 +##
9134 +##
9135 +##
9136 +#**
9137 + * Displays a blog article: management tools, header, content, footer.
9138 + *
9139 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9140 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9141 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
9142 + * @param shouldDisplayTitle If <tt>true</tt>, display the blog title (blog posts shouldn't display the title
9143 + * when they're displayed alone on their page since it's the page title which is used in this case)
9144 + * @param shouldDisplayActions If <tt>true</tt>, display the blog post actions buttons
9145 + *###
9146 +#macro(displayEntry $entryDoc $entryObj $onlyExtract $shouldDisplayTitle $shouldDisplayActions)
9147 + ## Only articles with an explicit hidden setting or an explicit unpublished setting are hidden
9148 + #isPublished($entryObj $isPublished)
9149 + #isHidden($entryObj $isHidden)
9150 + #if($doc.fullName == $entryDoc.fullName)
9151 + (% class=~"hentry single-article~" ~%)(((
9152 + #else
9153 + (% class=~"hentry#if(!$isPublished) unpublished-article#elseif($isHidden) hidden-article#end~" ~%)(((
9154 + #end
9155 + #if ($shouldDisplayActions)
9156 + #displayEntryTools($entryDoc $entryObj)
9157 + #end
9158 + #if($shouldDisplayTitle)
9159 + #displayEntryTitle($entryDoc $entryObj)
9160 + #end
9161 + #if($doc.fullName == $entryDoc.fullName)
9162 + #if(!$isPublished)
9163 + \{\{warning}}\{\{translation key='blog.code.published'/}}\{\{/warning}}
9164 + #elseif($isHidden)
9165 + \{\{warning}}\{\{translation key='blog.code.hidden'/}}\{\{/warning}}
9166 + #end
9167 + #end
9168 + #displayEntryContent($entryDoc $entryObj $onlyExtract)
9169 + #displayEntryFooter($entryDoc $entryObj)
9170 + )))## hentry
9171 +#end
9172 +##
9173 +##
9174 +##
9175 +#**
9176 + * Checks if the provided blog is published or not.
9177 + *
9178 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9179 + * @param isPublished The resulting boolean, true if the entry is considered published.
9180 + *###
9181 +#macro(isPublished $entryObj $isPublished)
9182 + #set ($isPublished = $NULL)
9183 + ## This should work for both old articles, which don't have the 'published' property at all, and
9184 + ## are considered published by default, and new entries, that should have 1 if published.
9185 + #if (~"$!\{entryObj.getProperty('published').value}~" != '0')
9186 + #setVariable (~"$isPublished~" true)
9187 + #else
9188 + #setVariable (~"$isPublished~" false)
9189 + #end
9190 +#end
9191 +##
9192 +##
9193 +##
9194 +#**
9195 + * Checks if the provided blog is hidden or not.
9196 + *
9197 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass<tt> xclass.
9198 + * @param isHiddel The resulting boolean, true if the entry is considered hidden.
9199 + *###
9200 +#macro(isHidden $entryObj $isHidden)
9201 + #set ($isHidden = $NULL)
9202 + ## This should work for both old articles, which don't have the 'hidden' property at all, and
9203 + ## are considered visible by default, and new entries, that should have 1 if hidden.
9204 + #if (~"$!\{entryObj.getProperty('hidden').value}~" == '1')
9205 + #setVariable (~"$isHidden~" true)
9206 + #else
9207 + #setVariable (~"$isHidden~" false)
9208 + #end
9209 +#end
9210 +##
9211 +##
9212 +##
9213 +#**
9214 + * Displays several ~"tools~" for manipulating blog posts: hide/show, publish, edit.
9215 + *
9216 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9217 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9218 + *###
9219 +#macro(displayEntryTools $entryDoc $entryObj)
9220 + #if($xcontext.action == 'view')
9221 + (% class=~"blog-entry-toolbox~" ~%)(((
9222 + #displayPublishButton($entryDoc $entryObj)
9223 + #displayHideShowButton($entryDoc $entryObj)
9224 + #displayEditButton($entryDoc $entryObj)
9225 + #displayDeleteButton($entryDoc $entryObj)
9226 + )))
9227 + #end
9228 +#end
9229 +##
9230 +##
9231 +##
9232 +#**
9233 + * Displays the publish button to the entry <strong>creator</strong>, if the article is not published yet.
9234 + *
9235 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9236 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9237 + * @todo AJAX calls.
9238 + *###
9239 +#macro(displayPublishButton $entryDoc $entryObj)
9240 + #isPublished($entryObj $isPublished)
9241 + #if(!$isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
9242 + [[#toolImage('world')>>path:$blogPublisher.getURL('view', ~"entryName=$\{escapetool.url($entryDoc.fullName)}&xredirect=$\{escapetool.url($thisURL)}&form_token=$!\{services.csrf.getToken()}~")||title=~"$services.localization.render('blog.code.notpublished')~"]]##
9243 + #end
9244 +#end
9245 +##
9246 +##
9247 +##
9248 +#**
9249 + * Displays the hide or show button to the entry <strong>creator</strong>, if the article is already published.
9250 + *
9251 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9252 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9253 + *###
9254 +#macro(displayHideShowButton $entryDoc $entryObj)
9255 + #isPublished($entryObj $isPublished)
9256 + #isHidden($entryObj $isHidden)
9257 + ## Only published articles can be hidden. Unpublished articles are considered already hidden.
9258 + #if($isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
9259 + #set ($queryString = \{
9260 + 'xredirect' : $thisURL,
9261 + 'form_token' : $services.csrf.getToken()
9262 + })
9263 + #if ($isHidden)
9264 + #set ($discard = $queryString.putAll(\{
9265 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 0,
9266 + 'comment' : $services.localization.render('blog.code.madevisible')
9267 + }))
9268 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
9269 + [[#toolImage('unlock')>>path:$lockURL||class=~"blog-tool-show~" title=~"$services.localization.render('blog.code.makevisible')~"]]##
9270 + #else
9271 + #set ($discard = $queryString.putAll(\{
9272 + ~"$\{entryObj.getxWikiClass().getName()}_$\{entryObj.number}_hidden~" : 1,
9273 + 'comment' : $services.localization.render('blog.code.hid')
9274 + }))
9275 + #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString)))
9276 + [[#toolImage('lock')>>path:$lockURL||class=~"blog-tool-hide~" title=~"$services.localization.render('blog.code.hide')~"]]##
9277 + #end
9278 + #end
9279 +#end
9280 +##
9281 +##
9282 +##
9283 +#**
9284 + * Displays the edit button to those that can edit the article.
9285 + *
9286 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9287 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9288 + *###
9289 +#macro(displayEditButton $entryDoc $entryObj)
9290 + #if($xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName))
9291 + ## Call getDefaultEditMode() for backward compatibility with older blog posts.
9292 + [[#toolImage('pencil')>>path:$entryDoc.getURL('edit')||title=~"$services.localization.render('blog.code.editpost')~"]]##
9293 + #end
9294 +#end
9295 +##
9296 +##
9297 +##
9298 +#**
9299 + * Displays the delete button to those that can edit the article.
9300 + *
9301 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9302 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9303 + * @todo AJAX calls.
9304 + *###
9305 +#macro(displayDeleteButton $entryDoc $entryObj)
9306 + #if($xwiki.hasAccessLevel('delete', $xcontext.user, $entryDoc.fullName))
9307 + [[#toolImage('cross')>>path:$entryDoc.getURL('delete')||title=~"$services.localization.render('blog.code.deletepost')~"]]##
9308 + #end
9309 +#end
9310 +##
9311 +##
9312 +##
9313 +#**
9314 + * Displays the title of the entry.
9315 + *
9316 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9317 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9318 + *###
9319 +#macro(displayEntryTitle $entryDoc $entryObj)
9320 + #if($doc.fullName == $entryDoc.fullName)
9321 + (% class=~"entry-title~" ~%)
9322 + = $services.rendering.escape($entryDoc.display('title', 'view', $entryObj), $xwiki.getCurrentContentSyntaxId()) =
9323 + #else
9324 + (% class=~"entry-title~" ~%)
9325 + === [[$services.rendering.escape($entryDoc.display('title', 'view', $entryObj),$xwiki.getCurrentContentSyntaxId())>>doc:$services.rendering.escape($services.model.serialize($entryDoc.getDocumentReference(),'default'),$xwiki.getCurrentContentSyntaxId())]] ===
9326 + #end
9327 +#end
9328 +##
9329 +##
9330 +##
9331 +#**
9332 + * Displays the body of the entry.
9333 + *
9334 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9335 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9336 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
9337 + *###
9338 +#macro(displayEntryContent $entryDoc $entryObj $onlyExtract)
9339 + (% class=~"#if($onlyExtract)entry-summary#\{else}entry-content#end~" ~%)(((
9340 + #getEntryContent($entryDoc $entryObj $onlyExtract $entryContent)
9341 + ## FIXME: This causes the blog's content to not be annotatable. See http://jira.xwiki.org/browse/XWIKI-6328
9342 + ## Should probably be replaced by a display macro call with a reference to the object property holding the post's content
9343 + \{\{html wiki=~"false~"}}$entryDoc.getRenderedContent($entryContent, $entryDoc.syntax.toIdString())\{\{/html}}
9344 + ))) ## entry-content
9345 + (% class=~"clearfloats~" ~%)((()))
9346 +#end
9347 +##
9348 +##
9349 +##
9350 +#**
9351 + * Extracts the body of the entry that should be displayed. If <tt>onlyExtract</tt> is <tt>true</tt>, display the content
9352 + * of the <tt>extract</tt> field (if not empty).
9353 + *
9354 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9355 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9356 + * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content.
9357 + * @param entryContent The resulting content.
9358 + * @param removeEllipsis If <tt>true</tt>, then don't display an ellipsis at the end of the content (only used when
9359 + * <tt>onlyExtract</tt> is <tt>true</tt>)
9360 + *###
9361 +#macro(getEntryContent $entryDoc $entryObj $onlyExtract $entryContent $removeEllipsis)
9362 + #if ($onlyExtract)
9363 + ## Note: We trim the summary so that if there's some white space it won't cause the summary to be used instead
9364 + ## of the content.
9365 + #set ($macro.result = $entryObj.getProperty('extract').value.trim())
9366 + #end
9367 + #if(~"$!macro.result~" == '')
9368 + #set($macro.result = $entryObj.getProperty('content').value)
9369 +#* Disabled until the content can be cleanly cut.
9370 +* #if($onlyExtract && $result.length()>$maxchars)
9371 +* #set($i = $macro.result.lastIndexOf(~" ~", $maxchars))
9372 +* #set($i = $i + 1)
9373 +* #set($macro.result = ~"$\{macro.result.substring(0,$i)} *[...>$\{entryDoc.fullName}]*~")
9374 +* #end
9375 +## *###
9376 + #elseif (!$removeEllipsis)
9377 + #if($entryDoc.syntax.toIdString() == 'xwiki/1.0')
9378 + #set($macro.result = ~"$\{macro.result} <a href='$\{entryDoc.getExternalURL()}' title='$services.localization.render('blog.code.readpost')'>...</a>~")
9379 + #elseif($entryDoc.syntax.toIdString() == 'xwiki/2.0' || $entryDoc.syntax.toIdString() == 'xwiki/2.1')
9380 + #set($macro.result = ~"$\{macro.result} [[...>>$\{services.rendering.escape($entryDoc.getFullName(), $entryDoc.getSyntax())}||title='$services.localization.render('blog.code.readpost')']]~")
9381 + #end
9382 + #end
9383 + #set ($entryContent = $NULL)
9384 + #setVariable (~"$entryContent~" $macro.result)
9385 +#end
9386 +##
9387 +##
9388 +##
9389 +#**
9390 + * Displays the footer of the entry.
9391 + *
9392 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9393 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9394 + *###
9395 +#macro(displayEntryFooter $entryDoc $entryObj)
9396 + (% class=~"entry-footer~" ~%)(((
9397 + #isPublished($entryObj $isPublished)
9398 + (% class='entry-author-label' ~%)
9399 + #if($isPublished)
9400 + \{\{translation key='blog.code.postedby'/}} ##
9401 + #else
9402 + \{\{translation key='blog.code.createdby'/}} ##
9403 + #end
9404 + \{\{html wiki=~"false~" clean=~"false~"}}<span class='author vcard'>#userfn($entryDoc.creator)</span>\{\{/html}} ##
9405 + #getEntryDate($entryDoc $entryObj $entryDate)
9406 + #listCategories($entryObj) #*
9407 + ## Since the publish date and update date are not set at the exact same time, there could be a small difference that
9408 + ## we assume cannot be more than 3 seconds.
9409 + *#(% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.permalink'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||rel=~"bookmark~"]] ##
9410 + #if ($showcomments)
9411 + (% class=~"separator~" ~%)·(%~%) [[\{\{translation key='blog.code.comments'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||anchor=~"Comments~"]] (% class=~"itemCount~" ~%)($entryDoc.comments.size())(%~%) ##
9412 + #end ##
9413 + #if($entryDoc != $doc) ##
9414 + #displayEntryBlogLocation($entryDoc $entryObj) ##
9415 + #end
9416 + )))## entry-footer
9417 +#end
9418 +##
9419 +##
9420 +#**
9421 + * Display the blog for the entry (if it is not the currently displayed blog)
9422 + *
9423 + * @param entryDoc The xdocument of the blog post. Each post resides in its own document.
9424 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9425 + *###
9426 +#macro(displayEntryBlogLocation $entryDoc $entryObj)
9427 + #getBlogPostsLocation($entryDoc.getSpace() $blogPostsLocation) ##
9428 + #if(~"$!blogPostsLocation~" != ~"~") ##
9429 + #set($blogSpaceRef = $services.model.resolveSpace($blogPostsLocation)) ##
9430 + #set($blogDocRef = $services.model.createDocumentReference($services.model.getEntityReference('DOCUMENT', 'default').getName(), $blogSpaceRef)) ##
9431 + #if($doc.documentReference != $blogDocRef) ##
9432 + #set($blogDoc = $xwiki.getDocument($blogDocRef)) ##
9433 + #set($blogObj = $blogDoc.getObject('Blog.BlogClass')) ##
9434 + #if($blogObj) (% class=~"blogrefpath~" ~%)((( ##
9435 + $services.localization.render('blog.code.postedin') \{\{html clean=~"false~" wiki=~"false~"}} #hierarchy($blogDocRef, \{'selfIsActive' : true, 'local': true}) \{\{/html}} ##
9436 + )))(%~%)##
9437 + #end
9438 + #end
9439 + #end
9440 +#end
9441 +##
9442 +##
9443 +##
9444 +##
9445 +#**
9446 + * List the categories an entry belongs to. Used in the footer. The categories are instances of <tt>Blog.CategoryClass</tt>.
9447 + *
9448 + * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass.
9449 + *###
9450 +#macro(listCategories $entryObj)
9451 + #if($entryObj.getxWikiClass().getName() == $blogPostClassname)
9452 + #set($categories = $entryObj.getProperty('category').value)
9453 + #set($first = true)
9454 + #if($categories.size() > 0)
9455 + #foreach($category in $categories)
9456 + #set($categoryDoc = $!xwiki.getDocument($category))
9457 + #if(!$categoryDoc.isNew() && $categoryDoc.getObject($\{blogCategoryClassname}))
9458 + #if($foreach.count == 1)
9459 + (% class='separator' ~%)·(%~%) $services.localization.render('blog.code.categories') ##
9460 + #else
9461 + , ##
9462 + #end##
9463 + [[$!\{categoryDoc.getObject($blogCategoryClassname).getValue('name')}>>$\{category}||rel='tag']]##
9464 + #end##
9465 + #end##
9466 + #end
9467 + #end
9468 +#end
9469 +##
9470 +##
9471 +##
9472 +#**
9473 + * Displays blog pagination links (older and newer entries).
9474 + *
9475 + * @param blogDoc the XDocument holding the blog definition object.
9476 + *###
9477 +#macro(displayNavigationLinks $blogDoc)
9478 + (% class=~"clearfloats~" ~%)((()))
9479 + #getBlogDisplayType($blogDoc $displayType)
9480 + #if($displayType == 'weekly')
9481 + (% class=~"pagingLinks~" ~%)(((
9482 + #getRequestedWeek($weekDate)
9483 + $weekDate.addWeeks(-1)##
9484 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousweek'/}}>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
9485 + #sep()
9486 + $weekDate.addWeeks(2)## 2 because we already subtracted 1 above
9487 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextweek'/}} »>>$doc.documentReference.name||queryString=~"year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear~" class=~"button~"]]**(%~%)
9488 + )))
9489 + #elseif($displayType == 'monthly')
9490 + (% class=~"pagingLinks~" ~%)(((
9491 + #getRequestedMonth($monthDate)
9492 + $monthDate.addMonths(-1)##
9493 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.previousmonth'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
9494 + #sep()
9495 + $monthDate.addMonths(2)## 2 because we already subtracted 1 above
9496 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.nextmonth'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"year=$monthDate.year&month=$monthDate.monthOfYear~" class=~"button~"]]**(%~%)
9497 + )))
9498 + #elseif($displayType == 'all')
9499 + #else
9500 + ## Paginated
9501 + #if(($totalPages > 1))
9502 + #set($queryString = '')
9503 + #foreach($p in $request.getParameterNames())
9504 + #if($p != 'page' && $p != 'ipp')
9505 + #foreach($v in $request.getParameterValues($p))
9506 + #set($queryString = ~"$\{queryString}&$\{escapetool.url($p)}=$\{escapetool.url($v)}~")
9507 + #end
9508 + #end
9509 + #end
9510 + (% class=~"pagingLinks~" ~%)(((
9511 + #if ($currentPageNumber < $totalPages)
9512 + #set($currentPageNumber = $currentPageNumber + 1)
9513 + (% class=~"prevPage~" ~%)**[[« \{\{translation key='blog.code.olderposts'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
9514 + #set($currentPageNumber = $currentPageNumber - 1)
9515 + #end
9516 + #if ($currentPageNumber > 1)
9517 + #if ($currentPageNumber < $totalPages)
9518 + #sep()
9519 + #end
9520 + #set($currentPageNumber = $currentPageNumber - 1)
9521 + (% class=~"nextPage~" ~%)**[[\{\{translation key='blog.code.newerposts'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString=~"page=$\{currentPageNumber}&ipp=$\{itemsPerPage}$queryString~" class=~"button~"]]**(%~%)
9522 + #set($currentPageNumber = $currentPageNumber + 1)
9523 + #end
9524 + (% class=~"clear~" ~%)(%~%)
9525 + )))## pagingLinks
9526 + #end
9527 + #end
9528 +#end
9529 +##
9530 +##
9531 +##
9532 +#**
9533 + * Displays a message box with ~"publish~" icon.
9534 + *
9535 + * @param message A text message concerning blog article publishing
9536 + *###
9537 +#macro(publishMessageBox $message)
9538 +(% class=~"plainmessage publish-message~" ~%)((($services.icon.render('world') $message)))
9539 +#end
9540 +#**
9541 + * Displays a message box with ~"show/hide~" icon.
9542 + *
9543 + * @param message A text message concerning blog article hiding
9544 + *###
9545 +#macro(hideMessageBox $message)
9546 +(% class=~"plainmessage hide-message~" ~%)((($services.icon.render('unlock') $message)))
9547 +#end
9548 +##
9549 +##
9550 +##
9551 +#**
9552 + * Determine the requested week, for using in a weekly-indexed blog. The relevant request parameters are
9553 + * <tt>year</tt> and <tt>week</tt>. By default, the current week is used.
9554 + *
9555 + * @param monthDate The resulting week, a JODATime MutableDateTime.
9556 + *###
9557 +#macro(getRequestedWeek $weekDate)
9558 + #set ($weekDate = $NULL)
9559 + #setVariable (~"$weekDate~" $xwiki.jodatime.mutableDateTime)
9560 + #if(~"$!\{request.year}~" != '')
9561 + #set ($discard = $weekDate.setYear($numbertool.toNumber($request.year).intValue()))
9562 + #end
9563 + #if(~"$!\{request.week}~" != '')
9564 + #set ($discard = $weekDate.setWeekOfWeekyear($numbertool.toNumber($request.week).intValue()))
9565 + #end
9566 +#end
9567 +##
9568 +##
9569 +##
9570 +#**
9571 + * Determine the requested month, for using in a monthly-indexed blog. The relevant request parameters are
9572 + * <tt>year</tt> and <tt>month</tt>. By default, the current month is used.
9573 + *
9574 + * @param monthDate The resulting month, a JODATime MutableDateTime.
9575 + *###
9576 +#macro(getRequestedMonth $monthDate)
9577 + #set ($monthDate = $NULL)
9578 + #setVariable (~"$monthDate~" $xwiki.jodatime.mutableDateTime)
9579 + #if(~"$!\{request.year}~" != '')
9580 + #set ($discard = $monthDate.setYear($numbertool.toNumber($request.year).intValue()))
9581 + #end
9582 + #if(~"$!\{request.month}~" != '')
9583 + #set ($discard = $monthDate.setMonthOfYear($numbertool.toNumber($request.month).intValue()))
9584 + #end
9585 +#end
9586 +##
9587 +##
9588 +##
9589 +#**
9590 + * Retrieve a blog property (title, display type, etc).
9591 + *
9592 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
9593 + * @param propertyName The name of the property to be retrieved. One of the <tt>Blog.BlogClass</tt>'s properties.
9594 + * @param defaultValue The default value to use in case the blog object does not define one.
9595 + * @param propertyValue The resulting value.
9596 + *###
9597 +#macro(getBlogProperty $blogDoc $propertyName $defaultValue $propertyValue)
9598 + #set($result = ~"$!\{blogDoc.getObject($\{blogClassname}).getProperty($propertyName).value}~")
9599 + #if($result == '')
9600 + #set($result = $defaultValue)
9601 + #end
9602 + #set ($propertyValue = $NULL)
9603 + #setVariable (~"$propertyValue~" $result)
9604 +#end
9605 +
9606 +#**
9607 + * If an error occurs when executing an action, set a specific response status and display an error message.
9608 + *
9609 + * @param status The response status.
9610 + * @param text The user readable error to be displayed. Can be a translation key.
9611 + * @param parameters The parameters to use when decoding the translation key.
9612 + *###
9613 +#macro(blog__actionResponseError $status $text $parameters)
9614 + $response.setStatus($status)
9615 + #if($request.ajax)
9616 + $services.localization.render($text, $!parameters)
9617 + #else
9618 + \{\{error}}$services.localization.render($text, $!parameters)\{\{/error}}
9619 + #end
9620 +#end
9621 +##
9622 +##
9623 +##
9624 +#**
9625 + * Check if a blog is the Default blog (The one in the 'Blog' space).
9626 + *
9627 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object.
9628 + * @param isDefault The resulting boolean.
9629 + *###
9630 +#macro(isDefaultBlog $blogDoc $isDefault)
9631 + #set ($result = false)
9632 + #if ($blogDoc.space == 'Blog')
9633 + #set ($result = true)
9634 + #end
9635 + #setVariable(~"$isDefault~" $result)
9636 +#end
9637 +##
9638 +##
9639 +##
9640 +#**
9641 + * Retrieve the blog posts location (space).
9642 + *
9643 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
9644 + * @param postsLocation The resulting location.
9645 + *###
9646 +#macro(getBlogPostsLocation $blogSpace $postsLocation)
9647 + #getBlogDocument($blogSpace $blogDoc)
9648 + #getBlogProperty($blogDoc 'postsLocation' $blogDoc.space $result)
9649 + #set ($postsLocation = $NULL)
9650 + #setVariable (~"$postsLocation~" $result)
9651 +#end
9652 +##
9653 +##
9654 +##
9655 +#**
9656 + * Retrieve the blog categories location (space).
9657 + *
9658 + * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object
9659 + * @param categoriesLocation The resulting location.
9660 + *###
9661 +#macro(getBlogCategoriesLocation $blogSpace $categoriesLocation)
9662 + #getBlogDocument($blogSpace $blogDoc)
9663 + #getBlogProperty($blogDoc 'categoriesLocation' 'Blog' $result)
9664 + #set ($postsLocation = $NULL)
9665 + #setVariable (~"$categoriesLocation~" $result)
9666 +#end
9667 +###**
9668 + * Return the Query for selecting the blog posts based on the context where the posts are displayed.
9669 + * for example there is 4 different panel contexts:
9670 + * aBlog.aPost or aBlog.WebHome
9671 + * aCategorySpace.aCategory
9672 + * aCategorySpace.WebHome
9673 + * Blog.aPost or Blog.WebHome
9674 + *
9675 + * @param query The query for selecting blog entries.
9676 + * @param queryParams The parameters to bind with the generated query.
9677 + * @param targetDoc The document in which the articles will be displayed.
9678 + *###
9679 +#macro(getAllBlogPostsQueryBasedOnDisplayContext $targetDoc $query $queryParams)
9680 + #set ($query = $NULL)
9681 + #set ($queryParams = $NULL)
9682 + #getCategoryAllBlogPostsQuery($resultQuery)
9683 + #set ($resultQueryParams = \{})
9684 + #set($sanitizedSpace = $targetDoc.space.replaceAll('([%_!])', '!$1').concat('.%'))
9685 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
9686 + ## Get all posts that are in the default blog space('Blog') or in category 'Blog.%'
9687 + #set ($discard = $resultQueryParams.put('space', $targetDoc.space))
9688 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
9689 + #set($resultQuery = ~"$\{resultQuery} and (doc.space = :space or catList like :catList escape '!')~")
9690 + #elseif($targetDoc.getObject($blogCategoryClassname))
9691 + ## Get all posts that are in a category aCategorySpace.aCategory
9692 + #set ($discard = $resultQueryParams.put('catList', $targetDoc.fullName))
9693 + #set($resultQuery = ~"$\{resultQuery} and (catList=:catList)~")
9694 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
9695 + ## Get all posts that are in a category aCategorySpace.%
9696 + #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace))
9697 + ## Exclude incategorized posts
9698 + #set ($excludedCategory = ~"$\{targetDoc.space}.WebHome~")
9699 + #if ($targetDoc.space == $defaultBlogSpace)
9700 + #set ($excludedCategory = ~"Blog.Categories.WebHome~")
9701 + #end
9702 + #set ($discard = $resultQueryParams.put('excludedCategory', $excludedCategory))
9703 + #set($resultQuery = ~"$\{resultQuery} and (catList<>:excludedCategory) and (catList like :catList escape '!')~")
9704 + #else
9705 + ## Get all posts in blog space aBlog
9706 + #getAllBlogPostsQuery($resultQuery)
9707 + #getBlogPostsLocation($targetDoc.space $postsLocation)
9708 + #set ($discard = $resultQueryParams.put('space', $postsLocation))
9709 + #set($resultQuery = ~"$\{resultQuery} and doc.space = :space~")
9710 + #end
9711 + #setVariable(~"$query~" $resultQuery)
9712 + #setVariable(~"$queryParams~" $resultQueryParams)
9713 +#end
9714 +##
9715 +##
9716 +##
9717 +###**
9718 + * Display blog posts based on the context where the posts are displayed.
9719 + * for example there is 4 different panel contexts:
9720 + * aBlog.aPost or aBlog.WebHome
9721 + * aCategorySpace.aCategory
9722 + * aCategorySpace.WebHome
9723 + * Blog.aPost or Blog.WebHome
9724 + *
9725 + * @param targetDoc The document in which the articles will be displayed.
9726 + * @param postsVisiblity The visibility of the posts to display: recent, unpublished, ...
9727 + * @param layout Layout of the the posts to display
9728 + * @param layoutParams additional layout parameters, it is a string like 'param1=val1|...|paramN=valueN'
9729 + * @param limit the number of posts to display
9730 + *###
9731 +#macro(displayBlogPostsBasedOnContext $targetDoc $postsVisiblity $layout $layoutParams $limit)
9732 + #if ($postLayout == 'full')
9733 + #set ($macro.paginated = 'yes')
9734 + #end
9735 + #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname))
9736 + ## Display all posts that are in the default blog space('Blog') or in category 'Blog.%'
9737 + #getBlogPostsLayout($xwiki.getDocument(~"$\{defaultBlogSpace}.WebHome~") $postsLayout)
9738 + #if (~"$!layout~" == '')
9739 + #set ($layout = $postsLayout)
9740 + #end
9741 + #if ($postsVisiblity == 'recent')
9742 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
9743 + #elseif($postsVisiblity == 'unpublished')
9744 + \{\{blogpostlist blog=~"$\{defaultBlogSpace.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')}.WebHome~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
9745 + #end
9746 + #elseif($targetDoc.getObject($blogCategoryClassname))
9747 + ## Display all posts that are in a category aCategorySpace.aCategory
9748 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
9749 + #getBlogPostsLayout($blogDoc $postsLayout)
9750 + #if (~"$!layout~" == '')
9751 + #set ($layout = $postsLayout)
9752 + #end
9753 + #if ($postsVisiblity == 'recent')
9754 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
9755 + #elseif($postsVisiblity == 'unpublished')
9756 + \{\{blogpostlist category=~"$targetDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
9757 + #end
9758 + #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet')
9759 + ## Display all posts that are in a category aCategorySpace.%
9760 + #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc)
9761 + #getBlogPostsLayout($blogDoc $postsLayout)
9762 + #if (~"$!layout~" == '')
9763 + #set ($layout = $postsLayout)
9764 + #end
9765 + #if ($postsVisiblity == 'recent')
9766 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
9767 + #elseif($postsVisiblity == 'unpublished')
9768 + \{\{blogpostlist category=~"$targetDoc.space.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
9769 + #end
9770 + #else
9771 + ## Display all posts in blog space aBlog
9772 + #getBlogDocument($targetDoc.space $blogDoc)
9773 + #getBlogPostsLayout($blogDoc $postsLayout)
9774 + #if (~"$!layout~" == '')
9775 + #set ($layout = $postsLayout)
9776 + #end
9777 + #if ($postsVisiblity == 'recent')
9778 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='yes' hidden='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" limit=~"$limit~" /}}
9779 + #elseif($postsVisiblity == 'unpublished')
9780 + \{\{blogpostlist blog=~"$blogDoc.fullName.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" published='no' layout=~"$!layout.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" layoutParams=~"$!layoutParams.replaceAll('~~', '~~~~').replaceAll('~"', '~~~"')~" paginated=~"$!macro.paginated~" limit=~"$limit~" /}}
9781 + #end
9782 + #end
9783 +#end
9784 +##
9785 +##
9786 +##
9787 +#**
9788 + * Bind parameters to a query object.
9789 + *
9790 + * @param queryObj The query object (org.xwiki.query.internal.ScriptQuery object)
9791 + * @param queryParams the query parameters.
9792 + *###
9793 +#macro(bindQueryParameters $queryObj $queryParams)
9794 + #set ($output = $queryObj)
9795 + #foreach( $key in $queryParams.keySet() )
9796 + #set($output = $queryObj.bindValue($key, $queryParams.get($key)))
9797 + #end
9798 + #setVariable(~"$queryObj~" $output)
9799 +#end
9800 +##
9801 +##
9802 +##
9803 +#**
9804 + * Determines the blogposts layout: Default layout (Calendar), Image thumbnail
9805 + *
9806 + * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>postsLayout</tt>
9807 + * property set.
9808 + * @param postsLayout The resulting string. If the blog object does not define anything, it is considered full (default).
9809 + *###
9810 +#macro(getBlogPostsLayout $blogDoc $postsLayout)
9811 + #getBlogProperty($blogDoc 'postsLayout' 'full' $res)
9812 + #set ($postsLayout = $NULL)
9813 + #setVariable (~"$postsLayout~" $res)
9814 +#end
9815 +##
9816 +##
9817 +##
9818 +#**
9819 + * Retrieve the blog document of a categories space, which is the blog descriptor that have its categoriesLocation property set to the categories space
9820 + *
9821 + * @param categoriesSpace A <tt>String</tt>, the name of the space.
9822 + * @param blogDoc The resulting XDocument.
9823 + *###
9824 +#macro(getBlogDocumentForCategoriesSpace $categoriesSpace $blogDoc)
9825 + #set($macro.blogDocs = $services.query.hql(~", BaseObject obj, StringProperty as categoriesLocationProp where obj.name = doc.fullName and obj.className = '$blogClassname' and obj.id=categoriesLocationProp.id.id and categoriesLocationProp.id.name='categoriesLocation' and categoriesLocationProp.value=:categoriesLocation order by doc.creationDate~").setLimit(1).setOffset(0).bindValue('categoriesLocation', $categoriesSpace).execute())
9826 + #if($macro.blogDocs.size() > 0 && $categoriesSpace != $defaultBlogSpace)
9827 + #set($macro.result = $xwiki.getDocument($macro.blogDocs.get(0)))
9828 + #else
9829 + ## Fallback to Blog.WebHome, the default blog
9830 + #set($macro.result = $xwiki.getDocument('Blog.WebHome'))
9831 + #end
9832 + #set ($blogDoc = $NULL)
9833 + #setVariable (~"$blogDoc~" $macro.result)
9834 +#end" %)
9835 +(((
9836 +(% class="macro-placeholder hidden" %)
9837 +(((
9838 +macro:velocity
9839 +)))
9840 +)))
9841 +)))
9842 +
9843 +(% class="macro" data-macro="startmacro:include|-|reference=~"Blog.BlogPostLayoutMacros~"" %)
9844 +(((
9845 +(% class="macro-placeholder hidden" %)
9846 +(((
9847 +macro:include
9848 +)))
9849 +
9850 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-|#**
9851 + * Extract the layout parameters from a string.
9852 + *
9853 + * @param layoutParamsString The string representation of the layout parameters.
9854 + * It should contain a String following this format ~"paramName1=Value1|paramName2=Value2|...|paramNameK=ValueK~"
9855 + * @param layoutsParameters The resulting layout parameters Map.
9856 + *###
9857 +#macro(extractLayoutParametersFromString $layoutParamsString $layoutsParameters)
9858 + #set ($layoutsParameters = $NULL)
9859 + #set ($macro.layoutParams = \{})
9860 + #if (~"$!layoutParamsString~" != '')
9861 + #set ($macro.paramsArr = $layoutParamsString.split('\\|'))
9862 + #foreach ($item in $macro.paramsArr)
9863 + #set ($itemSplit = $item.split('='))
9864 + #if ($itemSplit.size() == 2)
9865 + #set ($discard = $macro.layoutParams.put($itemSplit[0].trim(), $itemSplit[1].trim()))
9866 + #end
9867 + #end
9868 + #end
9869 + #setVariable(~"$layoutsParameters~" $macro.layoutParams)
9870 +#end" %)
9871 +(((
9872 +(% class="macro-placeholder hidden" %)
9873 +(((
9874 +macro:velocity
9875 +)))
9876 +)))
9877 +)))
9878 +
9879 +(% class="macro" data-macro="startmacro:velocity|-|output=~"false~"|-| #macro(displaySmallPost $pDoc $pObj)
9880 + #initLayoutVars($pDoc $pObj)
9881 + <div class=~"col-xs-12 col-sm-6 next_blog~">
9882 + <a href=~"$pDoc.uRL~" class=~"thumbnail~">
9883 + <div class=~"row~">
9884 + <div class=~"col-xs-4~">
9885 + #if ($imageAtt)
9886 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
9887 + #end
9888 + </div>
9889 + <div class=~"col-xs-8 art_det~">
9890 + <p class=~"text-left~">
9891 + #if($displayTitle)$!postTitle #end
9892 + <br/><span class=~"date_info~"> $!dateStr </span>
9893 + </p>
9894 + #displayPostDetails($pDoc)
9895 + </div>
9896 + </div>
9897 + </a>
9898 + </div>
9899 + #end
9900 + ##
9901 + ##
9902 + ##
9903 + #macro(displayPinnedPost $pDoc $pObj)
9904 + #initLayoutVars($pDoc $pObj)
9905 + <div class=~"col-xs-12 col-sm-4 col-md-4 blog_pin~">
9906 + <a href=~"$pDoc.uRL~" class=~"all-post-link~">
9907 + <div class=~"thumbnail~">
9908 + #if ($displayTitle && $displayTitleFirstOnPinnedPosts)
9909 + <h5 class=~"title-top~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
9910 + #end
9911 + #if ($imageAtt)
9912 + <img src=~"$escapetool.xml($pDoc.getAttachmentURL($pObj.getValue('image'),'download',$imgQs))~" />
9913 + #end
9914 + <div class=~"caption~">
9915 + #if ($displayTitle && !$displayTitleFirstOnPinnedPosts)
9916 + <h5 class=~"text-left~">$!postTitle <br/> <span class=~"date_info~"> $!dateStr </span> </h5>
9917 + #end
9918 + #if ($displaySummaryOnPinnedPosts)
9919 + <div class=~"text-left post-summary~">
9920 + #set ($postContent = $pObj.getProperty('extract').value)
9921 + $!pDoc.getRenderedContent($postContent, $pDoc.syntax.toIdString())
9922 + </div>
9923 + #end
9924 + #displayPostDetails($pDoc)
9925 + </div>
9926 + </div>
9927 + </a>
9928 + </div>
9929 + #end
9930 + ##
9931 + ##
9932 + ##
9933 + #macro(formatPostDate $pDoc $pObj)
9934 + #set ($formattedDate = $NULL)
9935 + #set($dateStr = $datetool.format('medium', $postDate, $xcontext.locale))
9936 + #if (~"$!dateStr~" != '')
9937 + #set ($dateArr = $dateStr.split(' '))
9938 + #if ($dateArr.size() > 3)
9939 + #set ($dateStr = ~"~")
9940 + #foreach($s in $dateArr.subList(0, 3))
9941 + #set ($dateStr = ~"$\{dateStr}$\{s} ~")
9942 + #end
9943 + #end
9944 + #end
9945 + #setVariable(~"$formattedDate~" $dateStr)
9946 + #end
9947 + ##
9948 + ##
9949 + ##
9950 + #macro(displayPostDetails $pDoc)
9951 + <div class=~"row post-details~">
9952 + <div class=~"col-xs-8 detail~">
9953 + #if ($services.like.displayButton($pDoc.documentReference))
9954 + #set ($optLikeRecord = $services.like.getLikes($pDoc.documentReference))
9955 + ## Retrieve the likes number in XWiki 12.9+
9956 + #set ($likeNumber = $optLikeRecord.get())
9957 + #if (!$stringtool.isNumeric($likeNumber.toString()))
9958 + ## Retrieve the likes number in XWiki versions greater than 12.7 and lower than 12.9.
9959 + #set ($likeNumber = $optLikeRecord.get().likeNumber)
9960 + #end
9961 + #if ($stringtool.isNumeric($likeNumber.toString()))
9962 + <div class=~"post-likes btn btn-default disabled badge~"
9963 + title=~"$escapetool.xml($services.localization.render('like.button.title', [$likeNumber]))~">
9964 + $services.icon.renderHTML('heart') <span class=~"like-number~">$likeNumber</span>
9965 + </div>
9966 + #end
9967 + #elseif ($services.ratings)
9968 + #set ($ratingsConfigDoc = $services.ratings.getConfigurationDocument($pDoc.documentReference))
9969 + #if ($ratingsConfigDoc.getValue('displayRatings') == 1)
9970 + <ul class=~"pull-left note list-inline~">
9971 + #foreach ($x in [1..5])
9972 + #set ($cls = ~"~")
9973 + #if ($x > $averageVote)
9974 + #set ($cls = ~"-o~")
9975 + #end
9976 + <li><span class=~"fa fa-star$\{cls}~"></span></li>
9977 + #end
9978 + </ul>
9979 + #end
9980 + #end
9981 + </div>
9982 + #if ($showPostComments)
9983 + <div class=~"col-xs-4 com_det~">
9984 + <p class=~"text-right~">$services.icon.renderHTML('comments') ($!nbComments)</p>
9985 + </div>
9986 + #end
9987 + </div>
9988 + #end
9989 + ##
9990 + ##
9991 + ##
9992 + #macro(initLayoutVars $pDoc $pObj)
9993 + #set ($postTitle = $pDoc.display('title', 'view', $pObj))
9994 + #set ($imageAtt = $pDoc.getAttachment($pObj.getValue('image')))
9995 + #isPublished($pObj $isPublished)
9996 + #isHidden($pObj $isHidden)
9997 + #getEntryDate($pDoc $pObj $postDate)
9998 + #formatPostDate($postDate $dateStr)
9999 + #set ($averageVote = $mathtool.round($services.ratings.getAverageRating($pDoc.documentReference).getAverageVote()))
10000 + #set ($nbComments = $pDoc.getComments().size())
10001 + #set ($showPostComments = true)
10002 + #if ($xwiki.getSpacePreferenceFor('showcomments', $pDoc.documentReference.lastSpaceReference, '1') == '0')
10003 + #set ($showPostComments = false)
10004 + #end
10005 + #end
10006 + ##
10007 + ##
10008 + ##
10009 + #macro(displayEditPinnedPostsButton)
10010 + #if (~"$!macroAdditionalParams.get('postIndex')~" == '0' && $services.security.authorization.hasAccess('edit', $pinnedPostsSourceDoc.fullName))
10011 + #set ($discard = $xwiki.ssx.use('Blog.PinnedPostsSheet'))
10012 + #set ($discard = $xwiki.jsx.use('Blog.PinnedPostsSheet'))
10013 + #set ($editPinnedPostsURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'get', 'sheet=Blog.PinnedPostsSheet'))
10014 + #set ($newPinnedPostsObjectURL = $xwiki.getURL($pinnedPostsSourceDoc.fullName, 'objectadd', ~"classname=Blog.PinnedPostsClass&form_token=$!\{services.csrf.getToken()}~"))
10015 + <div class=~"edit-pinned-posts-container~">
10016 + <div class=~"col-xs-12 col-sm-12 col-md-12 text-right edit-pinned-posts~">
10017 + <a href=~"javascript:;~" class=~"editPinnedPosts~">
10018 + <span class=~"glyphicon glyphicon-edit~" aria-hidden=~"true~"></span> $services.localization.render('blog.post.layout.cards.pinnedposts.edit')
10019 + </a>
10020 + <input type=~"hidden~" id=~"editPinnedPostsURL~" value=~"$escapetool.xml($editPinnedPostsURL)~"/>
10021 + <input type=~"hidden~" id=~"newPinnedPostsObjectURL~" value=~"$escapetool.xml($newPinnedPostsObjectURL)~"/>
10022 + </div>
10023 + </div>
10024 + #if (~"$!pinnedPostsObj~" == '')
10025 + <input type=~"hidden~" name=~"createPinnedPostsObject~" value=~"1~"/>
10026 + #end
10027 + #end
10028 + #end" %)
10029 +(((
10030 +(% class="macro-placeholder hidden" %)
10031 +(((
10032 +macro:velocity
10033 +)))
10034 +)))
10035 +
10036 +(% class="macro" data-macro="startmacro:velocity|-||-| #if ($services.security.authorization.hasAccess('view', $xcontext.macro.params.reference))
10037 + #set ($postDoc = $xwiki.getDocument($xcontext.macro.params.reference))
10038 + #getEntryObject($postDoc $postObj)
10039 + #if (~"$!postObj~" != '')
10040 + #extractLayoutParametersFromString($xcontext.macro.params.params $macroAdditionalParams)
10041 + ##
10042 + #set ($displayTitle = true)
10043 + #if (~"$!macroAdditionalParams.get('displayTitle')~" == 'false')
10044 + #set ($displayTitle = false)
10045 + #end
10046 + ##
10047 + #set ($displayTitleFirstOnPinnedPosts = false)
10048 + #if (~"$!macroAdditionalParams.get('displayTitleFirstOnPinnedPosts')~" == 'true')
10049 + #set ($displayTitleFirstOnPinnedPosts = true)
10050 + #end
10051 + ##
10052 + #set ($displaySummaryOnPinnedPosts = true)
10053 + #if (~"$!macroAdditionalParams.get('displaySummaryOnPinnedPosts')~" == 'false')
10054 + #set ($displaySummaryOnPinnedPosts = false)
10055 + #end
10056 + ##
10057 + #set ($postIndex = $numbertool.toNumber($macroAdditionalParams.get('postIndex')).intValue())
10058 + #if ($postIndex == 0)
10059 + #set ($stopBlogPostsDisplay = false)
10060 + #end
10061 + #set ($listResultsCount = $numbertool.toNumber($macroAdditionalParams.get('list-results-count')).intValue())
10062 + #set($discard = $xwiki.ssx.use('Blog.BlogPostLayoutCards'))
10063 + #set($scaleWidth = 600)
10064 + #set($imgQs=~"width=$scaleWidth~")
10065 + ## Display pinned posts
10066 + ## Get the list of pinned posts
10067 + #set ($pinnedPosts = [])
10068 + #set ($pinnedPostsSourceDoc = $NULL)
10069 + #if (~"$!macroAdditionalParams.get('forceDisplayPinnedPosts')~" == 'true' && ~"$!macroAdditionalParams.get('list-blog')~" != '')
10070 + #set ($pinnedPostsSourceDoc = $xwiki.getDocument($macroAdditionalParams.get('list-blog')))
10071 + ## Note that the 'list-blog' parameter contains the value of the 'blog' parameter of the blogpostlist macro passed to the current layout macro
10072 + #end
10073 + #if (~"$!pinnedPostsSourceDoc~" != '')
10074 + #set ($pinnedPostsObj = $pinnedPostsSourceDoc.getObject('Blog.PinnedPostsClass'))
10075 + #if (~"$!pinnedPostsObj~" != '')
10076 + #set ($orderedPinnedPostsJSON = $pinnedPostsObj.getProperty('orderedPosts').value)
10077 + #if (~"$!orderedPinnedPostsJSON~" != '')
10078 + #set ($pinnedPosts = $jsontool.parse($orderedPinnedPostsJSON))
10079 + #else
10080 + #set ($pinnedPosts = $pinnedPostsObj.getProperty('posts').value)
10081 + #end
10082 + #end
10083 + #if ($postIndex == 0 && $pinnedPosts.size() > 0)
10084 + \{\{html clean=~"false~"}}
10085 + #set ($x = 0)
10086 + #set ($showPinnedPostsButton = true)
10087 + #foreach ($pinnedPost in $pinnedPosts)
10088 + #if ($x == 0)
10089 + <div class=~"row flex-container~">
10090 + #if ($showPinnedPostsButton)
10091 + #displayEditPinnedPostsButton()
10092 + #set($showPinnedPostsButton = false)
10093 + #end
10094 + #end
10095 + #set ($pinnedPostDoc = $xwiki.getDocument($pinnedPost))
10096 + #getEntryObject($pinnedPostDoc $pinnedPostObj)
10097 + #if (~"$!pinnedPostObj~" != '')
10098 + #displayPinnedPost($pinnedPostDoc $pinnedPostObj)
10099 + #end
10100 + #set ($x = $mathtool.add($x, 1))
10101 + #if ($x == 3)
10102 + #set ($x = 0)
10103 + </div>
10104 + #end
10105 + #end
10106 + #if ($mathtool.mod($x, 3) != 0)
10107 + </div>
10108 + #end
10109 + \{\{/html}}
10110 +
10111 + ## If the first post is a pinned post : this means that all the posts are pinned
10112 + ## In this case, avoid displaying the posts again after the pinned posts section.
10113 + #if ($pinnedPosts.contains($xcontext.macro.params.reference))
10114 + #set ($stopBlogPostsDisplay = true)
10115 + #end
10116 + #elseif($postIndex == 0 && $pinnedPosts.size() == 0)
10117 +
10118 + \{\{html}}
10119 + <div class=~"row no-pinnded-posts~">
10120 + #displayEditPinnedPostsButton()
10121 + </div>
10122 + \{\{/html}}
10123 +
10124 + #end
10125 + #end
10126 + #if (!$stopBlogPostsDisplay)
10127 + \{\{html clean=~"false~"}}
10128 + #if (~"$!nbDisplayedPosts~" == '' || $postIndex == 0)
10129 + #set ($nbDisplayedPosts = 0)
10130 + #end
10131 + #if($mathtool.mod($nbDisplayedPosts, 2) == 0)
10132 + #if ($nbDisplayedPosts != 0)
10133 + </div>
10134 + #set ($lastHtmlTag = 'c')
10135 + #end
10136 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
10137 + <div class=~"row~">
10138 + #set ($lastHtmlTag = 'o')
10139 + #set ($lastRowClass = ~"~")
10140 + #else
10141 + <div class=~"row flex-container~">
10142 + #set ($lastHtmlTag = 'o')
10143 + #set ($lastRowClass = ~"flex~")
10144 + #end
10145 + #end
10146 + #displaySmallPost($postDoc $postObj)
10147 + #if ($nbDisplayedPosts == $mathtool.sub($listResultsCount, 1))
10148 + </div>
10149 + #set ($lastHtmlTag = 'c')
10150 + #end
10151 + #set ($nbDisplayedPosts = $mathtool.add($nbDisplayedPosts, 1))
10152 + #if ($postIndex == $mathtool.sub($listResultsCount, 1))
10153 + #if (~"$!lastHtmlTag~" == 'o')
10154 + #if ($mathtool.mod($nbDisplayedPosts, 2) == 1 && $lastRowClass == ~"flex~")
10155 + <div class=~"col-xs-12 col-sm-6~"></div>
10156 + #end
10157 + </div>
10158 + #end
10159 + #end
10160 + \{\{/html}}
10161 + #end
10162 + #else
10163 + \{\{error}}$services.localization.render('blog.blogpostlayout.notpost', [$xcontext.macro.params.reference])\{\{/error}}
10164 + #end
10165 + #else
10166 + \{\{error}}$services.localization.render('blog.blogpostlayout.post_view_not_allowed', [$xcontext.macro.params.reference])\{\{/error}}
10167 + #end" %)
10168 +(((
10169 +(% class="macro-placeholder hidden" %)
10170 +(((
10171 +macro:velocity
10172 +)))
10173 +
10174 +(% class="macro" data-macro="startmacro:html|-|clean=~"false~"|-|<div class=~"col-xs-12 col-sm-6 next_blog~">
10175 +<a href=~"/Nieuws/RI%26E%202023~" class=~"thumbnail~">
10176 +<div class=~"row~">
10177 +<div class=~"col-xs-4~">
10178 +<img src=~"/download/Nieuws/RI%26E%202023/Knipsel.JPG?width=600&rev=1.1~" />
10179 +</div>
10180 +<div class=~"col-xs-8 art_det~">
10181 +<p class=~"text-left~">
10182 +RI en E 2023 <br/><span class=~"date_info~"> 13 dec. 2023 </span>
10183 +</p>
10184 +<div class=~"row post-details~">
10185 +<div class=~"col-xs-8 detail~">
10186 +<div class=~"post-likes btn btn-default disabled badge~"
10187 +title=~"Number of likes on this page: 1~">
10188 +<span class=~"fa fa-heart~"></span> <span class=~"like-number~">1</span>
10189 +</div>
10190 +</div>
10191 +<div class=~"col-xs-4 com_det~">
10192 +<p class=~"text-right~"><span class=~"fa fa-comments~"></span> (0)</p>
10193 +</div>
10194 +</div>
10195 +</div>
10196 +</div>
10197 +</a>
10198 +</div>
10199 +</div>" %)
10200 +(((
10201 +(% class="macro-placeholder hidden" %)
10202 +(((
10203 +macro:html
10204 +)))
10205 +
10206 +(% class="col-xs-12 col-sm-6 next_blog" %)
10207 +(((
10208 +(% class="row" %)
10209 +(((
10210 +(% class="col-xs-4" %)
10211 +(((
10212 +[[~[~[image:/download/Nieuws/RI%26E%202023/Knipsel.JPG?width=600&rev=1.1~]~]>>path:/Nieuws/RI%26E%202023||class="thumbnail"]]
10213 +)))
10214 +
10215 +(% class="col-xs-8 art_det" %)
10216 +(((
10217 +(% class="text-left" %)
10218 +[[RI en E 2023
10219 +(% class="date_info" %) 13 dec. 2023>>path:/Nieuws/RI%26E%202023||class="thumbnail"]]
10220 +
10221 +(% class="row post-details" %)
10222 +(((
10223 +(% class="col-xs-8 detail" %)
10224 +(((
10225 +(% class="post-likes btn btn-default disabled badge" title="Number of likes on this page: 1" %)
10226 +(((
10227 +[[(% class="like-number" %)1>>path:/Nieuws/RI%26E%202023||class="thumbnail"]]
10228 +)))
10229 +)))
10230 +
10231 +(% class="col-xs-4 com_det" %)
10232 +(((
10233 +(% class="text-right" %)
10234 +[[(0)>>path:/Nieuws/RI%26E%202023||class="thumbnail"]]
10235 +)))
10236 +)))
10237 +)))
10238 +)))
10239 +)))
10240 +)))
10241 +)))
10242 +)))
10243 +)))
10244 +)))
10245 +)))
10246 +)))
10247 +)))
10248 +)))
10249 +
10250 +(% style="background:url(~"https://kennis.wardenburg.nl/webjars/wiki%3Axwiki/xwiki-platform-ckeditor-webjar/15.8/plugins/widget/images/handle.png~") rgba(220, 220, 220, 0.5); left:0px; top:-15px" %)[[image:data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==||height="15" role="presentation" title="Klik en sleep om te verplaatsen" width="15"]]
10251 +)))
10252 +
10253 +
10254 +
10255 +)))
10256 +
10257 +(% aria-label="macro:velocity widget" contenteditable="false" role="region" tabindex="-1" %)
10258 +(((
10259 +(% class="macro" data-macro="startmacro:velocity|-||-|#if (!$hasEdit)
55 55   ## Verstop tabs
56 56   #set($displayDocExtra = false)
57 57   ## En de balken onderin
58 58   #set ($displayShortcuts = false)
59 -#end
60 -{{/velocity}}
10264 +#end" data-widget="xwiki-macro" data-xwiki-dom-updated="true" %)
10265 +(((
10266 +(% class="macro-placeholder" %)
10267 +(((
10268 +macro:velocity
10269 +)))
10270 +)))
10271 +
10272 +(% style="background:url(~"https://kennis.wardenburg.nl/webjars/wiki%3Axwiki/xwiki-platform-ckeditor-webjar/15.8/plugins/widget/images/handle.png~") rgba(220, 220, 220, 0.5); left:0px; top:-15px" %)[[image:data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==||height="15" role="presentation" title="Klik en sleep om te verplaatsen" width="15"]]
10273 +)))