Show last authors
author | version | line-number | content |
---|---|---|---|
1 | {{include reference="Blog.BlogParameters"/}} | ||
2 | |||
3 | {{velocity output="false"}} | ||
4 | ## | ||
5 | ## | ||
6 | ## | ||
7 | ## Import the blog skin and javascripts. | ||
8 | $!xwiki.ssx.use($blogStyleDocumentName)## | ||
9 | $!xwiki.jsx.use($blogScriptsDocumentName)## | ||
10 | ## | ||
11 | ## import the hierarchy for the path the blog post footer (in displayEntryBlogLocation) | ||
12 | #template('hierarchy_macros.vm')## | ||
13 | ## | ||
14 | ## | ||
15 | #** | ||
16 | * Prints a blog. This is the main macro used in the BlogSheet. | ||
17 | * | ||
18 | * @param blogDoc the XDocument holding the blog definition object. | ||
19 | *### | ||
20 | #macro(printBlog $blogDoc) | ||
21 | {{include reference='Blog.CreatePost'/}} | ||
22 | |||
23 | ## Use the blogPostList macro to display the blogposts | ||
24 | ## The blogPostList is used only in case of 'all' or 'paged' blog display type because the blogPostList macro | ||
25 | ## do not support FTM the monthly and weekly blog display types | ||
26 | #getBlogDisplayType($blogDoc $displayType) | ||
27 | #if ($displayType == 'weekly' || $displayType == 'monthly') | ||
28 | #getBlogEntries($blogDoc $entries) | ||
29 | #displayBlog($entries 'index' true true) | ||
30 | #displayNavigationLinks($blogDoc) | ||
31 | #else | ||
32 | #getBlogDisplayType($blogDoc $displayType) | ||
33 | #set ($paginated = 'no') | ||
34 | #if ($displayType == 'paginated') | ||
35 | #set ($paginated = 'yes') | ||
36 | #end | ||
37 | #getBlogPostsLayout($blogDoc $postsLayout) | ||
38 | (% class="hfeed index" %)((({{blogpostlist blog="$blogDoc.fullName.replaceAll('~', '~~').replaceAll('"', '~"')" paginated="$paginated" layout="$!postsLayout.replaceAll('~', '~~').replaceAll('"', '~"')" /}}))) | ||
39 | #end | ||
40 | #end | ||
41 | ## | ||
42 | ## | ||
43 | ## | ||
44 | #** | ||
45 | * Shows blog information. In view mode, the description is printed. In edit mode, allows changing blog settings: title, | ||
46 | * description, blog type (global or in-space), index display type (fixed size pagination, weekly index, monthly index, | ||
47 | * all entries). | ||
48 | * | ||
49 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object. | ||
50 | *### | ||
51 | #macro(showBlogInfo $blogDoc) | ||
52 | #if($blogDoc.getObject($blogClassname)) | ||
53 | ## Keep testing for inline action for backward compatibility with older blogs. | ||
54 | #if($xcontext.action == 'edit' || $xcontext.action == 'inline') | ||
55 | #macro(displayProperty $blogDoc $propname) | ||
56 | ; #displayPropName($xwiki.getClass($blogClassname).get($propname)): | ||
57 | : $blogDoc.display($propname) | ||
58 | #end | ||
59 | #displayProperty($blogDoc 'title') | ||
60 | #displayProperty($blogDoc 'description') | ||
61 | #displayProperty($blogDoc 'displayType') | ||
62 | #displayProperty($blogDoc 'itemsPerPage') | ||
63 | #displayProperty($blogDoc 'postsLayout') | ||
64 | #displayProperty($blogDoc 'postsLayoutParameters') | ||
65 | #else | ||
66 | $blogDoc.display('description') | ||
67 | #end | ||
68 | #elseif($doc.fullName == $blogSheet) | ||
69 | = $services.localization.render('blog.code.blogsheet') = | ||
70 | {{translation key='blog.code.sheetexplanation'/}} | ||
71 | #else | ||
72 | {{warning}}{{translation key='blog.code.notblog'/}}{{/warning}} | ||
73 | #end | ||
74 | #end | ||
75 | ## | ||
76 | ## | ||
77 | ## | ||
78 | #** | ||
79 | * Retrieve the blog document, which usually is either <tt><Space>.WebHome</tt> for whole-spaces blogs, or | ||
80 | * <tt><Space>.Blog</tt> for in-space blogs. If none of these documents contains a blog object, then the first | ||
81 | * (alphabetically) document in the target space that contains one is returned. Finally, if no document in the current | ||
82 | * space contains a blog object, then <tt>Blog.WebHome</tt> is returned as the default blog. | ||
83 | * | ||
84 | * @param space A <tt>String</tt>, the name of the space where to search. | ||
85 | * @param blogDoc The resulting XDocument. | ||
86 | *### | ||
87 | #macro(getBlogDocument $space $blogDoc) | ||
88 | #set ($result = $NULL) | ||
89 | ## Check if the current space has a WebPreferences page that contains a Blog.EnablePanelsConfigurationClass object. | ||
90 | ## 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 | ||
91 | ## identify the right blog based on a configuration object in a WebPreferences page. | ||
92 | #set ($spaceReference = $services.model.resolveSpace($space)) | ||
93 | #set ($preferencesDocRef = $services.model.createDocumentReference('WebPreferences', $spaceReference)) | ||
94 | #set ($preferencesDoc = $xwiki.getDocument($preferencesDocRef)) | ||
95 | #set ($preferencesObj = $preferencesDoc.getObject('Blog.EnablePanelsConfigurationClass')) | ||
96 | #if ($preferencesObj) | ||
97 | #set ($result = $xwiki.getDocument( $preferencesObj.getValue('blog'))) | ||
98 | #end | ||
99 | ## If no special case occurs (like the previous one), identify a blog by checking the current location from its hierarchy. | ||
100 | #if ("$!result" == '') | ||
101 | ## First, try the Space.WebHome, for a whole-space blog | ||
102 | #set($result = $xwiki.getDocument("${space}.WebHome")) | ||
103 | #if(!$result.getObject($blogClassname)) | ||
104 | ## Second, try the Space.Blog document | ||
105 | #set($result = $xwiki.getDocument("${space}.Blog")) | ||
106 | #if(!$result.getObject($blogClassname)) | ||
107 | ## Third, try searching for a blog document in the current space | ||
108 | ## Prevent the query fail when the space contains dots '.' | ||
109 | #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()) | ||
110 | #if($blogDocs.size() > 0) | ||
111 | #set($result = $xwiki.getDocument($blogDocs.get(0))) | ||
112 | #else | ||
113 | ## Fourth, try searching for a blog document that have the its 'postsLocation' set to the current space | ||
114 | #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()) | ||
115 | #if($blogDocs.size() > 0) | ||
116 | #set($result = $xwiki.getDocument($blogDocs.get(0))) | ||
117 | #else | ||
118 | ## Last, fallback to Blog.WebHome, the default blog | ||
119 | #set($result = $xwiki.getDocument('Blog.WebHome')) | ||
120 | #end | ||
121 | #end | ||
122 | #end | ||
123 | #end | ||
124 | #end | ||
125 | #set ($blogDoc = $NULL) | ||
126 | #setVariable ("$blogDoc" $result) | ||
127 | #end | ||
128 | ## | ||
129 | ## | ||
130 | ## | ||
131 | #** | ||
132 | * Retrieve the blog title. | ||
133 | * | ||
134 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass<tt> object with the <tt>title</tt> property set. | ||
135 | * @param title The resulting title. | ||
136 | *### | ||
137 | #macro(getBlogTitle $blogDoc $title) | ||
138 | ## Titles can contain velocity code (most commonly translations), so we should evaluate them. | ||
139 | #set ($title = $NULL) | ||
140 | #setVariable ("$title" $!blogDoc.displayTitle) | ||
141 | #end | ||
142 | ## | ||
143 | ## | ||
144 | ## | ||
145 | #** | ||
146 | * Retrieve the blog description. | ||
147 | * | ||
148 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>description</tt> | ||
149 | * property set. | ||
150 | * @param description The resulting description. | ||
151 | *### | ||
152 | #macro(getBlogDescription $blogDoc $description) | ||
153 | #getBlogProperty($blogDoc 'description' '' $result) | ||
154 | #set ($description = $NULL) | ||
155 | #setVariable ("$description" $result) | ||
156 | #end | ||
157 | ## | ||
158 | ## | ||
159 | ## | ||
160 | #** | ||
161 | * Retrieves a list of entries to be displayed. The entries are either part of the blog's space, or have the blog | ||
162 | * document set as a parent. The number and range of entries returned (from all those belonging to this blog) depends on | ||
163 | * the blog display type: paginated (fixed number of entries), weekly (all entries in a week), monthly (all entries in a | ||
164 | * month), or all. | ||
165 | * | ||
166 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object. | ||
167 | * @param entries The resulting list of entries to display, a list of XDocument names. | ||
168 | *### | ||
169 | #macro(getBlogEntries $blogDoc $entries) | ||
170 | #if (!$entries) | ||
171 | #setVariable ("$entries" []) | ||
172 | #end | ||
173 | #getAllBlogPostsQuery($query) | ||
174 | #isDefaultBlog($blogDoc $isDefault) | ||
175 | #set($queryParams = {}) | ||
176 | #if ($isDefault) | ||
177 | #getCategoryAllBlogPostsQuery($query) | ||
178 | #set($query = "${query} and (doc.creator = :creator or (isPublished.value = 1 and hidden.value = 0)) and (doc.space = :space or catList like :catList escape '!')") | ||
179 | #set($discard = $queryParams.put('creator', $xcontext.user)) | ||
180 | #set($discard = $queryParams.put('space', $blogDoc.space)) | ||
181 | #set($sanitizedBlogSpace = $blogDoc.space.replaceAll('([%_!])', '!$1').concat('.%')) | ||
182 | #set($discard = $queryParams.put('catList', $sanitizedBlogSpace)) | ||
183 | #else | ||
184 | #set($query = "${query} and (doc.space = :space or doc.parent = :parent)") | ||
185 | #getBlogPostsLocation($blogDoc.space $blogPostsLocation) | ||
186 | #set($discard = $queryParams.put('space', $blogPostsLocation)) | ||
187 | #set($discard = $queryParams.put('parent', $blogDoc.space)) | ||
188 | #end | ||
189 | #getBlogDisplayType($blogDoc $displayType) | ||
190 | #if($displayType == 'weekly') | ||
191 | #getWeeklyBlogEntries($blogDoc $query $entries $queryParams) | ||
192 | #elseif($displayType == 'monthly') | ||
193 | #getMonthlyBlogEntries($blogDoc $query $entries $queryParams) | ||
194 | #elseif($displayType == 'all') | ||
195 | #getAllBlogEntries($blogDoc $query $entries $queryParams) | ||
196 | #else | ||
197 | #getPagedBlogEntries($blogDoc $query $entries $queryParams) | ||
198 | #end | ||
199 | #end | ||
200 | ## | ||
201 | ## | ||
202 | ## | ||
203 | #** | ||
204 | * Retrieves a list of entries to be displayed. The entries are taken from a "page" of the blog, a sequence of documents | ||
205 | * defined by the request parameters <tt>ipp</tt> (items per page) and <tt>page</tt> (the current page). Initially the | ||
206 | * first page is displayed, with the number of entries defined in the blog object in the <tt>itemsPerPage</tt> property | ||
207 | * (10 if not defined). | ||
208 | * | ||
209 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object. | ||
210 | * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be | ||
211 | * refined to restrict to a given space, or to a given search criteria, etc. | ||
212 | * @param entries The resulting list of entries to display, a list of XDocument names. | ||
213 | * @param queryParams The parameters to bind with the query. | ||
214 | *### | ||
215 | #macro(getPagedBlogEntries $blogDoc $query $entries $queryParams) | ||
216 | #if (!$entries) | ||
217 | #setVariable ("$entries" []) | ||
218 | #end | ||
219 | #set($countQueryObj = $services.query.hql($query).addFilter("unique")) | ||
220 | #set($queryObj = $services.query.hql("${query} order by publishDate.value desc")) | ||
221 | #bindQueryParameters($countQueryObj $queryParams) | ||
222 | #bindQueryParameters($queryObj $queryParams) | ||
223 | #set($totalEntries = $countQueryObj.count()) | ||
224 | #getBlogProperty($blogDoc 'itemsPerPage' '10' $defaultItemsPerPage) | ||
225 | #set($defaultItemsPerPage = $numbertool.toNumber($defaultItemsPerPage).intValue()) | ||
226 | ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt. | ||
227 | #preparePagedViewParams($totalEntries $defaultItemsPerPage) | ||
228 | #set($discard = $entries.addAll($queryObj.setLimit($itemsPerPage).setOffset($startAt).addFilter("unique").execute())) | ||
229 | #end | ||
230 | ## | ||
231 | ## | ||
232 | ## | ||
233 | #** | ||
234 | * Retrieves a list of entries to be displayed. The entries are taken from a week of the blog. The target week is | ||
235 | * defined by the request parameters <tt>week</tt> (the week number in the year, from 1 to 52) and <tt>year</tt> (4 | ||
236 | * digit year). Initially the current week is displayed. | ||
237 | * | ||
238 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object. | ||
239 | * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be | ||
240 | * refined to restrict to a given space, or to a given search criteria, etc. | ||
241 | * @param entries The resulting list of entries to display, a list of XDocument names. | ||
242 | * @param queryParams The parameters to bind with the query. | ||
243 | *### | ||
244 | #macro(getWeeklyBlogEntries $blogDoc $query $entries $queryParams) | ||
245 | #if (!$entries) | ||
246 | #setVariable ("$entries" []) | ||
247 | #end | ||
248 | #getRequestedWeek($weekDate) | ||
249 | #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd')) | ||
250 | #set($minDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundFloor())) | ||
251 | #set($maxDay = $dateFormatter.print($weekDate.toMutableDateTime().weekOfWeekyear().roundCeiling())) | ||
252 | #set($query = "${query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'") | ||
253 | #set($countQueryObj = $services.query.hql($query).addFilter("unique")) | ||
254 | #set($queryObj = $services.query.hql("${query} order by publishDate.value desc").addFilter("unique")) | ||
255 | #bindQueryParameters($countQueryObj $queryParams) | ||
256 | #bindQueryParameters($queryObj $queryParams) | ||
257 | #set($totalEntries = $countQueryObj.count()) | ||
258 | #set($discard = $entries.addAll($queryObj.execute())) | ||
259 | #end | ||
260 | ## | ||
261 | ## | ||
262 | ## | ||
263 | #** | ||
264 | * Retrieves a list of entries to be displayed. The entries are taken from a month of the blog. The target month is | ||
265 | * defined by the request parameters <tt>month</tt> (the month number, from 1 to 12) and <tt>year</tt> (4 | ||
266 | * digit year). Initially the current month is displayed. | ||
267 | * | ||
268 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object. | ||
269 | * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be | ||
270 | * refined to restrict to a given space, or to a given search criteria, etc. | ||
271 | * @param entries The resulting list of entries to display, a list of XDocument names. | ||
272 | * @param queryParams The parameters to bind with the query. | ||
273 | *### | ||
274 | #macro(getMonthlyBlogEntries $blogDoc $query $entries) | ||
275 | #if (!$entries) | ||
276 | #setVariable ("$entries" []) | ||
277 | #end | ||
278 | #getRequestedMonth($monthDate) | ||
279 | #set($dateFormatter = $xwiki.jodatime.getDateTimeFormatterForPattern('yyyy-MM-dd')) | ||
280 | #set($minDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundFloor())) | ||
281 | #set($maxDay = $dateFormatter.print($monthDate.toMutableDateTime().monthOfYear().roundCeiling())) | ||
282 | #set($query = "${query} and publishDate.value >= '$minDay' and publishDate.value < '$maxDay'") | ||
283 | #set($countQueryObj = $services.query.hql($query).addFilter("unique")) | ||
284 | #set($queryObj = $services.query.hql("${query} order by publishDate.value desc").addFilter("unique")) | ||
285 | #bindQueryParameters($countQueryObj $queryParams) | ||
286 | #bindQueryParameters($queryObj $queryParams) | ||
287 | #set($totalEntries = $countQueryObj.count()) | ||
288 | #set($discard = $entries.addAll($queryObj.execute())) | ||
289 | #end | ||
290 | ## | ||
291 | ## | ||
292 | ## | ||
293 | #** | ||
294 | * Retrieves a list of entries to be displayed. All entries belonging to the current blog are returned. | ||
295 | * | ||
296 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object. | ||
297 | * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be | ||
298 | * refined to restrict to a given space, or to a given search criteria, etc. | ||
299 | * @param entries The resulting list of entries to display, a list of XDocument names. | ||
300 | * @param queryParams The parameters to bind with the query. | ||
301 | *### | ||
302 | #macro(getAllBlogEntries $blogDoc $query $entries $queryParams) | ||
303 | #if (!$entries) | ||
304 | #setVariable ("$entries" []) | ||
305 | #end | ||
306 | #set($countQueryObj = $services.query.hql($query).addFilter("unique")) | ||
307 | #set($queryObj = $services.query.hql("${query} order by publishDate.value desc").addFilter("unique")) | ||
308 | #bindQueryParameters($countQueryObj $queryParams) | ||
309 | #bindQueryParameters($queryObj $queryParams) | ||
310 | #set($totalEntries = $countQueryObj.count()) | ||
311 | #set($discard = $entries.addAll($queryObj.execute())) | ||
312 | #end | ||
313 | ## | ||
314 | ## | ||
315 | ## | ||
316 | #** | ||
317 | * Retrieves a list of entries to be displayed. Only (and all) unpublished entries are returned. | ||
318 | * | ||
319 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object. | ||
320 | * @param query The base query for selecting entries. Apart from the base query that selects entries, it can further be | ||
321 | * refined to restrict to a given space, or to a given search criteria, etc. | ||
322 | * @param queryParams The parameters to bind with the query. | ||
323 | * @param entries The resulting list of entries to display, a list of XDocument names. | ||
324 | *### | ||
325 | #macro(getUnpublishedBlogEntries $blogDoc $query $queryParams $entries) | ||
326 | #if (!$entries) | ||
327 | #setVariable ("$entries" []) | ||
328 | #end | ||
329 | #set($query = "${query} and isPublished.value = 0") | ||
330 | #set ($countQueryObj = $services.query.hql($query).addFilter("unique")) | ||
331 | #set ($queryObj = $services.query.hql("${query} order by publishDate.value desc").addFilter("unique")) | ||
332 | #bindQueryParameters($countQueryObj $queryParams) | ||
333 | #bindQueryParameters($queryObj $queryParams) | ||
334 | #set($totalEntries = $countQueryObj.count()) | ||
335 | #set($discard = $entries.addAll($queryObj.execute())) | ||
336 | #end | ||
337 | ## | ||
338 | ## | ||
339 | ## | ||
340 | #** | ||
341 | * Retrieves a list of entries to be displayed. The entries are taken from all the wiki, and not from a specific blog. | ||
342 | * | ||
343 | * @param entries The resulting list of entries to display, a list of XDocument names. | ||
344 | *### | ||
345 | #macro(getGlobalBlogEntries $entries) | ||
346 | #if (!$entries) | ||
347 | #setVariable ("$entries" []) | ||
348 | #end | ||
349 | #getAllBlogPostsQuery($query) | ||
350 | #set($totalEntries = $services.query.hql($query).count()) | ||
351 | #set($defaultItemsPerPage = 20) | ||
352 | ## This macro is defined in the default macros.vm library. It also sets $itemsPerPage and $startAt. | ||
353 | #preparePagedViewParams($totalEntries $defaultItemsPerPage) | ||
354 | #set($discard = $entries.addAll($services.query.hql("${query} order by publishDate.value desc").setLimit($itemsPerPage).setOffset($startAt).execute())) | ||
355 | #end | ||
356 | #** | ||
357 | * Return the base query for selecting blog entries. It filters only visible entries, but does not bind to a specific | ||
358 | * blog, nor specify a range or an ordering criteria. | ||
359 | * | ||
360 | * This macro is a duplicate of #getAllBlogPostsQuery($query). Keep it in case it's used outside, in custom code. | ||
361 | * | ||
362 | * @param query The basic query for selecting blog entries. | ||
363 | *# | ||
364 | #macro(getBlogEntriesBaseQuery $query) | ||
365 | #getAllBlogPostsQuery($query) | ||
366 | #end | ||
367 | #** | ||
368 | * Return the Query for selecting the all wiki blog posts without filtering | ||
369 | * | ||
370 | * @param query The basic query for selecting blog entries. | ||
371 | *# | ||
372 | #macro(getAllBlogPostsQuery $query) | ||
373 | #set ($query = $NULL) | ||
374 | #setVariable("$query" ", BaseObject as obj, IntegerProperty isPublished, | ||
375 | IntegerProperty hidden, DateProperty publishDate | ||
376 | where doc.fullName <> '$blogPostTemplate' and | ||
377 | obj.name=doc.fullName and obj.className='$blogPostClassname' and | ||
378 | isPublished.id.id = obj.id and isPublished.id.name = 'published' and | ||
379 | hidden.id.id = obj.id and hidden.id.name='hidden' and | ||
380 | publishDate.id.id = obj.id and publishDate.id.name='publishDate' and | ||
381 | (doc.creator = '$escapetool.sql($xcontext.user)' or (isPublished.value = 1 and hidden.value = 0))") | ||
382 | #end | ||
383 | ## | ||
384 | ## | ||
385 | ## | ||
386 | ###** | ||
387 | * Return the Query for selecting the all wiki blog posts with categories filtering | ||
388 | * | ||
389 | * @param query The basic query for selecting blog entries. | ||
390 | *### | ||
391 | #macro(getCategoryAllBlogPostsQuery $query) | ||
392 | #set ($query = $NULL) | ||
393 | #getAllBlogPostsQuery($baseQuery) | ||
394 | #set ($baseQuery = $baseQuery.replace('DateProperty publishDate', 'DateProperty publishDate, DBStringListProperty as category left join category.list catList')) | ||
395 | #setVariable("$query" "${baseQuery} and obj.id=category.id.id and category.id.name='category'") | ||
396 | #end | ||
397 | ## | ||
398 | ## | ||
399 | ## | ||
400 | #** | ||
401 | * Determines how is the blog index split into pages: paginated (fixed number of entries), weekly (all entries in a | ||
402 | * week), monthly (all entries in a month), or all. | ||
403 | * | ||
404 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>displayType</tt> | ||
405 | * property set. | ||
406 | * @param displayType The resulting string. If the blog object does not define anything, it is considered paginated. | ||
407 | *### | ||
408 | #macro(getBlogDisplayType $blogDoc $displayType) | ||
409 | #getBlogProperty($blogDoc 'displayType' 'paginated' $result) | ||
410 | #set ($displayType = $NULL) | ||
411 | #setVariable ("$displayType" $result) | ||
412 | #end | ||
413 | ## | ||
414 | ## | ||
415 | ## | ||
416 | #** | ||
417 | * Displays a list of entries. | ||
418 | * | ||
419 | * @param entries The entries to display, a list of XDocument names. | ||
420 | * @param displaying What exactly is displayed: blog index, a single blog entry, a blog category, search results, | ||
421 | * unpublished entries, etc. This will be used as the classname(s) for the container div (hfeed). Currently | ||
422 | * used values: index, single, category, search, unpublished, hidden. | ||
423 | * @param onlyExtract If <tt>true</tt>, only display the extract of articles where available, otherwise display the full content. | ||
424 | * @param shouldDisplayTitles If <tt>true</tt>, display the blog title (blog posts shouldn't display the title when they're | ||
425 | * displayed alone on their page since it's the page title which is used in this case) | ||
426 | *### | ||
427 | #macro(displayBlog $entries $displaying $onlyExtract $shouldDisplayTitles) | ||
428 | #set($blogDay = '') | ||
429 | (% class="hfeed $!{displaying}" %)((( | ||
430 | (% class="blogDay" %)((( | ||
431 | #foreach ($entryDoc in $xwiki.wrapDocs($entries)) | ||
432 | #getEntryObject($entryDoc $entryObj) | ||
433 | ## Although all entries should have one of the two objects, better check to be sure. | ||
434 | #if("$!{entryObj}" != '') | ||
435 | #getEntryDate($entryDoc $entryObj $entryDate) | ||
436 | ## Display a "calendar sheet" for each day. All entries posted on the same day share one such sheet. | ||
437 | #set($entryDateStr = $xwiki.formatDate($entryDate, 'yyyyMMMMdd')) | ||
438 | #if($blogDay != $entryDateStr) | ||
439 | #if($blogDay != '') | ||
440 | ))) | ||
441 | (% class="blogDay" %)((( | ||
442 | #end | ||
443 | #displayBlogDate($entryDate) | ||
444 | #set ($blogDay = $entryDateStr) | ||
445 | #end | ||
446 | ## Finally, display the entry. | ||
447 | #displayEntry($entryDoc $entryObj $onlyExtract $shouldDisplayTitles true) | ||
448 | #end | ||
449 | #end | ||
450 | )))## blogDay | ||
451 | )))## hfeed | ||
452 | #end | ||
453 | ## | ||
454 | ## | ||
455 | ## | ||
456 | #** | ||
457 | * Get the entry object, either a new BlogPost or an old Article. | ||
458 | * | ||
459 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
460 | * @param entryObj The resulting xobject of the blog post. | ||
461 | *### | ||
462 | #macro(getEntryObject $entryDoc $__entryObj) | ||
463 | #set($result = $entryDoc.getObject("${blogPostClassname}")) | ||
464 | #if(!$result) | ||
465 | #set($result = $entryDoc.getObject("${oldArticleClassname}")) | ||
466 | #end | ||
467 | ## NOTE: The reason we put an underscore in front of the variable name is to prevent the following line from | ||
468 | ## overwriting the $entryObj variable that may be defined before this macro is called. Of course, $__entryObj may be | ||
469 | ## overwritten in this case but it's less likely to have such a variable defined before. | ||
470 | #set ($__entryObj = $NULL) | ||
471 | #setVariable ("$__entryObj" $result) | ||
472 | #end | ||
473 | ## | ||
474 | ## | ||
475 | ## | ||
476 | #** | ||
477 | * Gets the date associated with a blog entry. This is the publication date. For unpublished entries, initially this is | ||
478 | * the document creation date, but can be edited by the user. | ||
479 | * | ||
480 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
481 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
482 | * @param result The resulting date, an instance of <tt>java.util.Date</tt>. | ||
483 | *### | ||
484 | #macro(getEntryDate $entryDoc $entryObj $result) | ||
485 | #set ($result = $NULL) | ||
486 | #setVariable ("$result" $entryObj.getProperty('publishDate').value) | ||
487 | #end | ||
488 | ## | ||
489 | ## | ||
490 | ## | ||
491 | #** | ||
492 | * Displays a date, nicely formatted as a calendar page. | ||
493 | * | ||
494 | * @param date The date to display, an instance of <tt>java.util.Date</tt>. | ||
495 | *### | ||
496 | #macro(displayBlogDate $date) | ||
497 | #set($year = $xwiki.formatDate($date, 'yyyy')) | ||
498 | ## 3 letter month name, like Jan, Dec. | ||
499 | #set($month = $xwiki.formatDate($date, 'MMM')) | ||
500 | ## Uncomment to get a full length month name, like January, December. | ||
501 | ## TODO: this could be defined somewhere in the blog style. | ||
502 | ## #set($month = $xwiki.formatDate($date, 'MMMM')) | ||
503 | #set($day = $xwiki.formatDate($date, 'dd')) | ||
504 | (% class="blogdate" %) | ||
505 | == (% class="month" %)$month(%%) (% class="day" %)$day(%%) (% class="year" %)$year(%%) == | ||
506 | #end | ||
507 | ## | ||
508 | ## | ||
509 | ## | ||
510 | #** | ||
511 | * Displays a blog article: management tools, header, content, footer. | ||
512 | * | ||
513 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
514 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
515 | * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content. | ||
516 | * @param shouldDisplayTitle If <tt>true</tt>, display the blog title (blog posts shouldn't display the title | ||
517 | * when they're displayed alone on their page since it's the page title which is used in this case) | ||
518 | * @param shouldDisplayActions If <tt>true</tt>, display the blog post actions buttons | ||
519 | *### | ||
520 | #macro(displayEntry $entryDoc $entryObj $onlyExtract $shouldDisplayTitle $shouldDisplayActions) | ||
521 | ## Only articles with an explicit hidden setting or an explicit unpublished setting are hidden | ||
522 | #isPublished($entryObj $isPublished) | ||
523 | #isHidden($entryObj $isHidden) | ||
524 | #if($doc.fullName == $entryDoc.fullName) | ||
525 | (% class="hentry single-article" %)((( | ||
526 | #else | ||
527 | (% class="hentry#if(!$isPublished) unpublished-article#elseif($isHidden) hidden-article#end" %)((( | ||
528 | #end | ||
529 | #if ($shouldDisplayActions) | ||
530 | #displayEntryTools($entryDoc $entryObj) | ||
531 | #end | ||
532 | #if($shouldDisplayTitle) | ||
533 | #displayEntryTitle($entryDoc $entryObj) | ||
534 | #end | ||
535 | #if($doc.fullName == $entryDoc.fullName) | ||
536 | #if(!$isPublished) | ||
537 | {{warning}}{{translation key='blog.code.published'/}}{{/warning}} | ||
538 | #elseif($isHidden) | ||
539 | {{warning}}{{translation key='blog.code.hidden'/}}{{/warning}} | ||
540 | #end | ||
541 | #end | ||
542 | #displayEntryContent($entryDoc $entryObj $onlyExtract) | ||
543 | #displayEntryFooter($entryDoc $entryObj) | ||
544 | )))## hentry | ||
545 | #end | ||
546 | ## | ||
547 | ## | ||
548 | ## | ||
549 | #** | ||
550 | * Checks if the provided blog is published or not. | ||
551 | * | ||
552 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
553 | * @param isPublished The resulting boolean, true if the entry is considered published. | ||
554 | *### | ||
555 | #macro(isPublished $entryObj $isPublished) | ||
556 | #set ($isPublished = $NULL) | ||
557 | ## This should work for both old articles, which don't have the 'published' property at all, and | ||
558 | ## are considered published by default, and new entries, that should have 1 if published. | ||
559 | #if ("$!{entryObj.getProperty('published').value}" != '0') | ||
560 | #setVariable ("$isPublished" true) | ||
561 | #else | ||
562 | #setVariable ("$isPublished" false) | ||
563 | #end | ||
564 | #end | ||
565 | ## | ||
566 | ## | ||
567 | ## | ||
568 | #** | ||
569 | * Checks if the provided blog is hidden or not. | ||
570 | * | ||
571 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass<tt> xclass. | ||
572 | * @param isHiddel The resulting boolean, true if the entry is considered hidden. | ||
573 | *### | ||
574 | #macro(isHidden $entryObj $isHidden) | ||
575 | #set ($isHidden = $NULL) | ||
576 | ## This should work for both old articles, which don't have the 'hidden' property at all, and | ||
577 | ## are considered visible by default, and new entries, that should have 1 if hidden. | ||
578 | #if ("$!{entryObj.getProperty('hidden').value}" == '1') | ||
579 | #setVariable ("$isHidden" true) | ||
580 | #else | ||
581 | #setVariable ("$isHidden" false) | ||
582 | #end | ||
583 | #end | ||
584 | ## | ||
585 | ## | ||
586 | ## | ||
587 | #** | ||
588 | * Displays several "tools" for manipulating blog posts: hide/show, publish, edit. | ||
589 | * | ||
590 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
591 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
592 | *### | ||
593 | #macro(displayEntryTools $entryDoc $entryObj) | ||
594 | #if($xcontext.action == 'view') | ||
595 | (% class="blog-entry-toolbox" %)((( | ||
596 | #displayPublishButton($entryDoc $entryObj) | ||
597 | #displayHideShowButton($entryDoc $entryObj) | ||
598 | #displayEditButton($entryDoc $entryObj) | ||
599 | #displayDeleteButton($entryDoc $entryObj) | ||
600 | ))) | ||
601 | #end | ||
602 | #end | ||
603 | ## | ||
604 | ## | ||
605 | ## | ||
606 | #** | ||
607 | * Displays the publish button to the entry <strong>creator</strong>, if the article is not published yet. | ||
608 | * | ||
609 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
610 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
611 | * @todo AJAX calls. | ||
612 | *### | ||
613 | #macro(displayPublishButton $entryDoc $entryObj) | ||
614 | #isPublished($entryObj $isPublished) | ||
615 | #if(!$isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName)) | ||
616 | [[#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')"]]## | ||
617 | #end | ||
618 | #end | ||
619 | ## | ||
620 | ## | ||
621 | ## | ||
622 | #** | ||
623 | * Displays the hide or show button to the entry <strong>creator</strong>, if the article is already published. | ||
624 | * | ||
625 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
626 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
627 | *### | ||
628 | #macro(displayHideShowButton $entryDoc $entryObj) | ||
629 | #isPublished($entryObj $isPublished) | ||
630 | #isHidden($entryObj $isHidden) | ||
631 | ## Only published articles can be hidden. Unpublished articles are considered already hidden. | ||
632 | #if($isPublished && $entryDoc.creator == $xcontext.user && $xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName)) | ||
633 | #set ($queryString = { | ||
634 | 'xredirect' : $thisURL, | ||
635 | 'form_token' : $services.csrf.getToken() | ||
636 | }) | ||
637 | #if ($isHidden) | ||
638 | #set ($discard = $queryString.putAll({ | ||
639 | "${entryObj.getxWikiClass().getName()}_${entryObj.number}_hidden" : 0, | ||
640 | 'comment' : $services.localization.render('blog.code.madevisible') | ||
641 | })) | ||
642 | #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString))) | ||
643 | [[#toolImage('unlock')>>path:$lockURL||class="blog-tool-show" title="$services.localization.render('blog.code.makevisible')"]]## | ||
644 | #else | ||
645 | #set ($discard = $queryString.putAll({ | ||
646 | "${entryObj.getxWikiClass().getName()}_${entryObj.number}_hidden" : 1, | ||
647 | 'comment' : $services.localization.render('blog.code.hid') | ||
648 | })) | ||
649 | #set ($lockURL = $entryDoc.getURL('save', $escapetool.url($queryString))) | ||
650 | [[#toolImage('lock')>>path:$lockURL||class="blog-tool-hide" title="$services.localization.render('blog.code.hide')"]]## | ||
651 | #end | ||
652 | #end | ||
653 | #end | ||
654 | ## | ||
655 | ## | ||
656 | ## | ||
657 | #** | ||
658 | * Displays the edit button to those that can edit the article. | ||
659 | * | ||
660 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
661 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
662 | *### | ||
663 | #macro(displayEditButton $entryDoc $entryObj) | ||
664 | #if($xwiki.hasAccessLevel('edit', $xcontext.user, $entryDoc.fullName)) | ||
665 | ## Call getDefaultEditMode() for backward compatibility with older blog posts. | ||
666 | [[#toolImage('pencil')>>path:$entryDoc.getURL('edit')||title="$services.localization.render('blog.code.editpost')"]]## | ||
667 | #end | ||
668 | #end | ||
669 | ## | ||
670 | ## | ||
671 | ## | ||
672 | #** | ||
673 | * Displays the delete button to those that can edit the article. | ||
674 | * | ||
675 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
676 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
677 | * @todo AJAX calls. | ||
678 | *### | ||
679 | #macro(displayDeleteButton $entryDoc $entryObj) | ||
680 | #if($xwiki.hasAccessLevel('delete', $xcontext.user, $entryDoc.fullName)) | ||
681 | [[#toolImage('cross')>>path:$entryDoc.getURL('delete')||title="$services.localization.render('blog.code.deletepost')"]]## | ||
682 | #end | ||
683 | #end | ||
684 | ## | ||
685 | ## | ||
686 | ## | ||
687 | #** | ||
688 | * Displays the title of the entry. | ||
689 | * | ||
690 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
691 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
692 | *### | ||
693 | #macro(displayEntryTitle $entryDoc $entryObj) | ||
694 | #if($doc.fullName == $entryDoc.fullName) | ||
695 | (% class="entry-title" %) | ||
696 | = $services.rendering.escape($entryDoc.display('title', 'view', $entryObj), $xwiki.getCurrentContentSyntaxId()) = | ||
697 | #else | ||
698 | (% class="entry-title" %) | ||
699 | === [[$services.rendering.escape($entryDoc.display('title', 'view', $entryObj),$xwiki.getCurrentContentSyntaxId())>>doc:$services.rendering.escape($services.model.serialize($entryDoc.getDocumentReference(),'default'),$xwiki.getCurrentContentSyntaxId())]] === | ||
700 | #end | ||
701 | #end | ||
702 | ## | ||
703 | ## | ||
704 | ## | ||
705 | #** | ||
706 | * Displays the body of the entry. | ||
707 | * | ||
708 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
709 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
710 | * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content. | ||
711 | *### | ||
712 | #macro(displayEntryContent $entryDoc $entryObj $onlyExtract) | ||
713 | (% class="#if($onlyExtract)entry-summary#{else}entry-content#end" %)((( | ||
714 | #getEntryContent($entryDoc $entryObj $onlyExtract $entryContent) | ||
715 | ## FIXME: This causes the blog's content to not be annotatable. See http://jira.xwiki.org/browse/XWIKI-6328 | ||
716 | ## Should probably be replaced by a display macro call with a reference to the object property holding the post's content | ||
717 | {{html wiki="false"}}$entryDoc.getRenderedContent($entryContent, $entryDoc.syntax.toIdString()){{/html}} | ||
718 | ))) ## entry-content | ||
719 | (% class="clearfloats" %)((())) | ||
720 | #end | ||
721 | ## | ||
722 | ## | ||
723 | ## | ||
724 | #** | ||
725 | * Extracts the body of the entry that should be displayed. If <tt>onlyExtract</tt> is <tt>true</tt>, display the content | ||
726 | * of the <tt>extract</tt> field (if not empty). | ||
727 | * | ||
728 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
729 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
730 | * @param onlyExtract If <tt>true</tt>, try to display only a summary of the entry, instead of the full content. | ||
731 | * @param entryContent The resulting content. | ||
732 | * @param removeEllipsis If <tt>true</tt>, then don't display an ellipsis at the end of the content (only used when | ||
733 | * <tt>onlyExtract</tt> is <tt>true</tt>) | ||
734 | *### | ||
735 | #macro(getEntryContent $entryDoc $entryObj $onlyExtract $entryContent $removeEllipsis) | ||
736 | #if ($onlyExtract) | ||
737 | ## Note: We trim the summary so that if there's some white space it won't cause the summary to be used instead | ||
738 | ## of the content. | ||
739 | #set ($macro.result = $entryObj.getProperty('extract').value.trim()) | ||
740 | #end | ||
741 | #if("$!macro.result" == '') | ||
742 | #set($macro.result = $entryObj.getProperty('content').value) | ||
743 | #* Disabled until the content can be cleanly cut. | ||
744 | * #if($onlyExtract && $result.length()>$maxchars) | ||
745 | * #set($i = $macro.result.lastIndexOf(" ", $maxchars)) | ||
746 | * #set($i = $i + 1) | ||
747 | * #set($macro.result = "${macro.result.substring(0,$i)} *[...>${entryDoc.fullName}]*") | ||
748 | * #end | ||
749 | ## *### | ||
750 | #elseif (!$removeEllipsis) | ||
751 | #if($entryDoc.syntax.toIdString() == 'xwiki/1.0') | ||
752 | #set($macro.result = "${macro.result} <a href='${entryDoc.getExternalURL()}' title='$services.localization.render('blog.code.readpost')'>...</a>") | ||
753 | #elseif($entryDoc.syntax.toIdString() == 'xwiki/2.0' || $entryDoc.syntax.toIdString() == 'xwiki/2.1') | ||
754 | #set($macro.result = "${macro.result} [[...>>${services.rendering.escape($entryDoc.getFullName(), $entryDoc.getSyntax())}||title='$services.localization.render('blog.code.readpost')']]") | ||
755 | #end | ||
756 | #end | ||
757 | #set ($entryContent = $NULL) | ||
758 | #setVariable ("$entryContent" $macro.result) | ||
759 | #end | ||
760 | ## | ||
761 | ## | ||
762 | ## | ||
763 | #** | ||
764 | * Displays the footer of the entry. | ||
765 | * | ||
766 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
767 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
768 | *### | ||
769 | #macro(displayEntryFooter $entryDoc $entryObj) | ||
770 | (% class="entry-footer" %)((( | ||
771 | #isPublished($entryObj $isPublished) | ||
772 | (% class='entry-author-label' %) | ||
773 | #if($isPublished) | ||
774 | {{translation key='blog.code.postedby'/}} ## | ||
775 | #else | ||
776 | {{translation key='blog.code.createdby'/}} ## | ||
777 | #end | ||
778 | {{html wiki="false" clean="false"}}<span class='author vcard'>#userfn($entryDoc.creator)</span>{{/html}} ## | ||
779 | #getEntryDate($entryDoc $entryObj $entryDate) | ||
780 | #listCategories($entryObj) #* | ||
781 | ## Since the publish date and update date are not set at the exact same time, there could be a small difference that | ||
782 | ## we assume cannot be more than 3 seconds. | ||
783 | *#(% class="separator" %)·(%%) [[{{translation key='blog.code.permalink'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||rel="bookmark"]] ## | ||
784 | #if ($showcomments) | ||
785 | (% class="separator" %)·(%%) [[{{translation key='blog.code.comments'/}}>>$services.rendering.escape($entryDoc,'xwiki/2.0')||anchor="Comments"]] (% class="itemCount" %)($entryDoc.comments.size())(%%) ## | ||
786 | #end ## | ||
787 | #if($entryDoc != $doc) ## | ||
788 | #displayEntryBlogLocation($entryDoc $entryObj) ## | ||
789 | #end | ||
790 | )))## entry-footer | ||
791 | #end | ||
792 | ## | ||
793 | ## | ||
794 | #** | ||
795 | * Display the blog for the entry (if it is not the currently displayed blog) | ||
796 | * | ||
797 | * @param entryDoc The xdocument of the blog post. Each post resides in its own document. | ||
798 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
799 | *### | ||
800 | #macro(displayEntryBlogLocation $entryDoc $entryObj) | ||
801 | #getBlogPostsLocation($entryDoc.getSpace() $blogPostsLocation) ## | ||
802 | #if("$!blogPostsLocation" != "") ## | ||
803 | #set($blogSpaceRef = $services.model.resolveSpace($blogPostsLocation)) ## | ||
804 | #set($blogDocRef = $services.model.createDocumentReference($services.model.getEntityReference('DOCUMENT', 'default').getName(), $blogSpaceRef)) ## | ||
805 | #if($doc.documentReference != $blogDocRef) ## | ||
806 | #set($blogDoc = $xwiki.getDocument($blogDocRef)) ## | ||
807 | #set($blogObj = $blogDoc.getObject('Blog.BlogClass')) ## | ||
808 | #if($blogObj) (% class="blogrefpath" %)((( ## | ||
809 | $services.localization.render('blog.code.postedin') {{html clean="false" wiki="false"}} #hierarchy($blogDocRef, {'selfIsActive' : true, 'local': true}) {{/html}} ## | ||
810 | )))(%%)## | ||
811 | #end | ||
812 | #end | ||
813 | #end | ||
814 | #end | ||
815 | ## | ||
816 | ## | ||
817 | ## | ||
818 | ## | ||
819 | #** | ||
820 | * List the categories an entry belongs to. Used in the footer. The categories are instances of <tt>Blog.CategoryClass</tt>. | ||
821 | * | ||
822 | * @param entryObj The xobject of the blog post, an instance of the <tt>Blog.BlogPostClass</tt> xclass. | ||
823 | *### | ||
824 | #macro(listCategories $entryObj) | ||
825 | #if($entryObj.getxWikiClass().getName() == $blogPostClassname) | ||
826 | #set($categories = $entryObj.getProperty('category').value) | ||
827 | #set($first = true) | ||
828 | #if($categories.size() > 0) | ||
829 | #foreach($category in $categories) | ||
830 | #set($categoryDoc = $!xwiki.getDocument($category)) | ||
831 | #if(!$categoryDoc.isNew() && $categoryDoc.getObject(${blogCategoryClassname})) | ||
832 | #if($foreach.count == 1) | ||
833 | (% class='separator' %)·(%%) $services.localization.render('blog.code.categories') ## | ||
834 | #else | ||
835 | , ## | ||
836 | #end## | ||
837 | [[$!{categoryDoc.getObject($blogCategoryClassname).getValue('name')}>>${category}||rel='tag']]## | ||
838 | #end## | ||
839 | #end## | ||
840 | #end | ||
841 | #end | ||
842 | #end | ||
843 | ## | ||
844 | ## | ||
845 | ## | ||
846 | #** | ||
847 | * Displays blog pagination links (older and newer entries). | ||
848 | * | ||
849 | * @param blogDoc the XDocument holding the blog definition object. | ||
850 | *### | ||
851 | #macro(displayNavigationLinks $blogDoc) | ||
852 | (% class="clearfloats" %)((())) | ||
853 | #getBlogDisplayType($blogDoc $displayType) | ||
854 | #if($displayType == 'weekly') | ||
855 | (% class="pagingLinks" %)((( | ||
856 | #getRequestedWeek($weekDate) | ||
857 | $weekDate.addWeeks(-1)## | ||
858 | (% class="prevPage" %)**[[« {{translation key='blog.code.previousweek'/}}>>$doc.documentReference.name||queryString="year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear" class="button"]]**(%%) | ||
859 | #sep() | ||
860 | $weekDate.addWeeks(2)## 2 because we already subtracted 1 above | ||
861 | (% class="nextPage" %)**[[{{translation key='blog.code.nextweek'/}} »>>$doc.documentReference.name||queryString="year=$weekDate.weekyear&week=$weekDate.weekOfWeekyear" class="button"]]**(%%) | ||
862 | ))) | ||
863 | #elseif($displayType == 'monthly') | ||
864 | (% class="pagingLinks" %)((( | ||
865 | #getRequestedMonth($monthDate) | ||
866 | $monthDate.addMonths(-1)## | ||
867 | (% class="prevPage" %)**[[« {{translation key='blog.code.previousmonth'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString="year=$monthDate.year&month=$monthDate.monthOfYear" class="button"]]**(%%) | ||
868 | #sep() | ||
869 | $monthDate.addMonths(2)## 2 because we already subtracted 1 above | ||
870 | (% class="nextPage" %)**[[{{translation key='blog.code.nextmonth'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString="year=$monthDate.year&month=$monthDate.monthOfYear" class="button"]]**(%%) | ||
871 | ))) | ||
872 | #elseif($displayType == 'all') | ||
873 | #else | ||
874 | ## Paginated | ||
875 | #if(($totalPages > 1)) | ||
876 | #set($queryString = '') | ||
877 | #foreach($p in $request.getParameterNames()) | ||
878 | #if($p != 'page' && $p != 'ipp') | ||
879 | #foreach($v in $request.getParameterValues($p)) | ||
880 | #set($queryString = "${queryString}&${escapetool.url($p)}=${escapetool.url($v)}") | ||
881 | #end | ||
882 | #end | ||
883 | #end | ||
884 | (% class="pagingLinks" %)((( | ||
885 | #if ($currentPageNumber < $totalPages) | ||
886 | #set($currentPageNumber = $currentPageNumber + 1) | ||
887 | (% class="prevPage" %)**[[« {{translation key='blog.code.olderposts'/}}>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString="page=${currentPageNumber}&ipp=${itemsPerPage}$queryString" class="button"]]**(%%) | ||
888 | #set($currentPageNumber = $currentPageNumber - 1) | ||
889 | #end | ||
890 | #if ($currentPageNumber > 1) | ||
891 | #if ($currentPageNumber < $totalPages) | ||
892 | #sep() | ||
893 | #end | ||
894 | #set($currentPageNumber = $currentPageNumber - 1) | ||
895 | (% class="nextPage" %)**[[{{translation key='blog.code.newerposts'/}} »>>$services.rendering.escape($doc.documentReference.name,$doc.syntax)||queryString="page=${currentPageNumber}&ipp=${itemsPerPage}$queryString" class="button"]]**(%%) | ||
896 | #set($currentPageNumber = $currentPageNumber + 1) | ||
897 | #end | ||
898 | (% class="clear" %)(%%) | ||
899 | )))## pagingLinks | ||
900 | #end | ||
901 | #end | ||
902 | #end | ||
903 | ## | ||
904 | ## | ||
905 | ## | ||
906 | #** | ||
907 | * Displays a message box with "publish" icon. | ||
908 | * | ||
909 | * @param message A text message concerning blog article publishing | ||
910 | *### | ||
911 | #macro(publishMessageBox $message) | ||
912 | (% class="plainmessage publish-message" %)((($services.icon.render('world') $message))) | ||
913 | #end | ||
914 | #** | ||
915 | * Displays a message box with "show/hide" icon. | ||
916 | * | ||
917 | * @param message A text message concerning blog article hiding | ||
918 | *### | ||
919 | #macro(hideMessageBox $message) | ||
920 | (% class="plainmessage hide-message" %)((($services.icon.render('unlock') $message))) | ||
921 | #end | ||
922 | ## | ||
923 | ## | ||
924 | ## | ||
925 | #** | ||
926 | * Determine the requested week, for using in a weekly-indexed blog. The relevant request parameters are | ||
927 | * <tt>year</tt> and <tt>week</tt>. By default, the current week is used. | ||
928 | * | ||
929 | * @param monthDate The resulting week, a JODATime MutableDateTime. | ||
930 | *### | ||
931 | #macro(getRequestedWeek $weekDate) | ||
932 | #set ($weekDate = $NULL) | ||
933 | #setVariable ("$weekDate" $xwiki.jodatime.mutableDateTime) | ||
934 | #if("$!{request.year}" != '') | ||
935 | #set ($discard = $weekDate.setYear($numbertool.toNumber($request.year).intValue())) | ||
936 | #end | ||
937 | #if("$!{request.week}" != '') | ||
938 | #set ($discard = $weekDate.setWeekOfWeekyear($numbertool.toNumber($request.week).intValue())) | ||
939 | #end | ||
940 | #end | ||
941 | ## | ||
942 | ## | ||
943 | ## | ||
944 | #** | ||
945 | * Determine the requested month, for using in a monthly-indexed blog. The relevant request parameters are | ||
946 | * <tt>year</tt> and <tt>month</tt>. By default, the current month is used. | ||
947 | * | ||
948 | * @param monthDate The resulting month, a JODATime MutableDateTime. | ||
949 | *### | ||
950 | #macro(getRequestedMonth $monthDate) | ||
951 | #set ($monthDate = $NULL) | ||
952 | #setVariable ("$monthDate" $xwiki.jodatime.mutableDateTime) | ||
953 | #if("$!{request.year}" != '') | ||
954 | #set ($discard = $monthDate.setYear($numbertool.toNumber($request.year).intValue())) | ||
955 | #end | ||
956 | #if("$!{request.month}" != '') | ||
957 | #set ($discard = $monthDate.setMonthOfYear($numbertool.toNumber($request.month).intValue())) | ||
958 | #end | ||
959 | #end | ||
960 | ## | ||
961 | ## | ||
962 | ## | ||
963 | #** | ||
964 | * Retrieve a blog property (title, display type, etc). | ||
965 | * | ||
966 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object. | ||
967 | * @param propertyName The name of the property to be retrieved. One of the <tt>Blog.BlogClass</tt>'s properties. | ||
968 | * @param defaultValue The default value to use in case the blog object does not define one. | ||
969 | * @param propertyValue The resulting value. | ||
970 | *### | ||
971 | #macro(getBlogProperty $blogDoc $propertyName $defaultValue $propertyValue) | ||
972 | #set($result = "$!{blogDoc.getObject(${blogClassname}).getProperty($propertyName).value}") | ||
973 | #if($result == '') | ||
974 | #set($result = $defaultValue) | ||
975 | #end | ||
976 | #set ($propertyValue = $NULL) | ||
977 | #setVariable ("$propertyValue" $result) | ||
978 | #end | ||
979 | |||
980 | #** | ||
981 | * If an error occurs when executing an action, set a specific response status and display an error message. | ||
982 | * | ||
983 | * @param status The response status. | ||
984 | * @param text The user readable error to be displayed. Can be a translation key. | ||
985 | * @param parameters The parameters to use when decoding the translation key. | ||
986 | *### | ||
987 | #macro(blog__actionResponseError $status $text $parameters) | ||
988 | $response.setStatus($status) | ||
989 | #if($request.ajax) | ||
990 | $services.localization.render($text, $!parameters) | ||
991 | #else | ||
992 | {{error}}$services.localization.render($text, $!parameters){{/error}} | ||
993 | #end | ||
994 | #end | ||
995 | ## | ||
996 | ## | ||
997 | ## | ||
998 | #** | ||
999 | * Check if a blog is the Default blog (The one in the 'Blog' space). | ||
1000 | * | ||
1001 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object. | ||
1002 | * @param isDefault The resulting boolean. | ||
1003 | *### | ||
1004 | #macro(isDefaultBlog $blogDoc $isDefault) | ||
1005 | #set ($result = false) | ||
1006 | #if ($blogDoc.space == 'Blog') | ||
1007 | #set ($result = true) | ||
1008 | #end | ||
1009 | #setVariable("$isDefault" $result) | ||
1010 | #end | ||
1011 | ## | ||
1012 | ## | ||
1013 | ## | ||
1014 | #** | ||
1015 | * Retrieve the blog posts location (space). | ||
1016 | * | ||
1017 | * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object | ||
1018 | * @param postsLocation The resulting location. | ||
1019 | *### | ||
1020 | #macro(getBlogPostsLocation $blogSpace $postsLocation) | ||
1021 | #getBlogDocument($blogSpace $blogDoc) | ||
1022 | #getBlogProperty($blogDoc 'postsLocation' $blogDoc.space $result) | ||
1023 | #set ($postsLocation = $NULL) | ||
1024 | #setVariable ("$postsLocation" $result) | ||
1025 | #end | ||
1026 | ## | ||
1027 | ## | ||
1028 | ## | ||
1029 | #** | ||
1030 | * Retrieve the blog categories location (space). | ||
1031 | * | ||
1032 | * @param blogSpace The blog space. It should contain a document with a <tt>Blog.BlogClass</tt> object | ||
1033 | * @param categoriesLocation The resulting location. | ||
1034 | *### | ||
1035 | #macro(getBlogCategoriesLocation $blogSpace $categoriesLocation) | ||
1036 | #getBlogDocument($blogSpace $blogDoc) | ||
1037 | #getBlogProperty($blogDoc 'categoriesLocation' 'Blog' $result) | ||
1038 | #set ($postsLocation = $NULL) | ||
1039 | #setVariable ("$categoriesLocation" $result) | ||
1040 | #end | ||
1041 | ###** | ||
1042 | * Return the Query for selecting the blog posts based on the context where the posts are displayed. | ||
1043 | * for example there is 4 different panel contexts: | ||
1044 | * aBlog.aPost or aBlog.WebHome | ||
1045 | * aCategorySpace.aCategory | ||
1046 | * aCategorySpace.WebHome | ||
1047 | * Blog.aPost or Blog.WebHome | ||
1048 | * | ||
1049 | * @param query The query for selecting blog entries. | ||
1050 | * @param queryParams The parameters to bind with the generated query. | ||
1051 | * @param targetDoc The document in which the articles will be displayed. | ||
1052 | *### | ||
1053 | #macro(getAllBlogPostsQueryBasedOnDisplayContext $targetDoc $query $queryParams) | ||
1054 | #set ($query = $NULL) | ||
1055 | #set ($queryParams = $NULL) | ||
1056 | #getCategoryAllBlogPostsQuery($resultQuery) | ||
1057 | #set ($resultQueryParams = {}) | ||
1058 | #set($sanitizedSpace = $targetDoc.space.replaceAll('([%_!])', '!$1').concat('.%')) | ||
1059 | #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname)) | ||
1060 | ## Get all posts that are in the default blog space('Blog') or in category 'Blog.%' | ||
1061 | #set ($discard = $resultQueryParams.put('space', $targetDoc.space)) | ||
1062 | #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace)) | ||
1063 | #set($resultQuery = "${resultQuery} and (doc.space = :space or catList like :catList escape '!')") | ||
1064 | #elseif($targetDoc.getObject($blogCategoryClassname)) | ||
1065 | ## Get all posts that are in a category aCategorySpace.aCategory | ||
1066 | #set ($discard = $resultQueryParams.put('catList', $targetDoc.fullName)) | ||
1067 | #set($resultQuery = "${resultQuery} and (catList=:catList)") | ||
1068 | #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet') | ||
1069 | ## Get all posts that are in a category aCategorySpace.% | ||
1070 | #set ($discard = $resultQueryParams.put('catList', $sanitizedSpace)) | ||
1071 | ## Exclude incategorized posts | ||
1072 | #set ($excludedCategory = "${targetDoc.space}.WebHome") | ||
1073 | #if ($targetDoc.space == $defaultBlogSpace) | ||
1074 | #set ($excludedCategory = "Blog.Categories.WebHome") | ||
1075 | #end | ||
1076 | #set ($discard = $resultQueryParams.put('excludedCategory', $excludedCategory)) | ||
1077 | #set($resultQuery = "${resultQuery} and (catList<>:excludedCategory) and (catList like :catList escape '!')") | ||
1078 | #else | ||
1079 | ## Get all posts in blog space aBlog | ||
1080 | #getAllBlogPostsQuery($resultQuery) | ||
1081 | #getBlogPostsLocation($targetDoc.space $postsLocation) | ||
1082 | #set ($discard = $resultQueryParams.put('space', $postsLocation)) | ||
1083 | #set($resultQuery = "${resultQuery} and doc.space = :space") | ||
1084 | #end | ||
1085 | #setVariable("$query" $resultQuery) | ||
1086 | #setVariable("$queryParams" $resultQueryParams) | ||
1087 | #end | ||
1088 | ## | ||
1089 | ## | ||
1090 | ## | ||
1091 | ###** | ||
1092 | * Display blog posts based on the context where the posts are displayed. | ||
1093 | * for example there is 4 different panel contexts: | ||
1094 | * aBlog.aPost or aBlog.WebHome | ||
1095 | * aCategorySpace.aCategory | ||
1096 | * aCategorySpace.WebHome | ||
1097 | * Blog.aPost or Blog.WebHome | ||
1098 | * | ||
1099 | * @param targetDoc The document in which the articles will be displayed. | ||
1100 | * @param postsVisiblity The visibility of the posts to display: recent, unpublished, ... | ||
1101 | * @param layout Layout of the the posts to display | ||
1102 | * @param layoutParams additional layout parameters, it is a string like 'param1=val1|...|paramN=valueN' | ||
1103 | * @param limit the number of posts to display | ||
1104 | *### | ||
1105 | #macro(displayBlogPostsBasedOnContext $targetDoc $postsVisiblity $layout $layoutParams $limit) | ||
1106 | #if ($postLayout == 'full') | ||
1107 | #set ($macro.paginated = 'yes') | ||
1108 | #end | ||
1109 | #if ($targetDoc.space == $defaultBlogSpace && !$targetDoc.getObject($blogCategoryClassname)) | ||
1110 | ## Display all posts that are in the default blog space('Blog') or in category 'Blog.%' | ||
1111 | #getBlogPostsLayout($xwiki.getDocument("${defaultBlogSpace}.WebHome") $postsLayout) | ||
1112 | #if ("$!layout" == '') | ||
1113 | #set ($layout = $postsLayout) | ||
1114 | #end | ||
1115 | #if ($postsVisiblity == 'recent') | ||
1116 | {{blogpostlist blog="${defaultBlogSpace.replaceAll('~', '~~').replaceAll('"', '~"')}.WebHome" published='yes' hidden='no' layout="$!layout.replaceAll('~', '~~').replaceAll('"', '~"')" layoutParams="$!layoutParams.replaceAll('~', '~~').replaceAll('"', '~"')" limit="$limit" /}} | ||
1117 | #elseif($postsVisiblity == 'unpublished') | ||
1118 | {{blogpostlist blog="${defaultBlogSpace.replaceAll('~', '~~').replaceAll('"', '~"')}.WebHome" published='no' layout="$!layout.replaceAll('~', '~~').replaceAll('"', '~"')" layoutParams="$!layoutParams.replaceAll('~', '~~').replaceAll('"', '~"')" paginated="$!macro.paginated" limit="$limit" /}} | ||
1119 | #end | ||
1120 | #elseif($targetDoc.getObject($blogCategoryClassname)) | ||
1121 | ## Display all posts that are in a category aCategorySpace.aCategory | ||
1122 | #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc) | ||
1123 | #getBlogPostsLayout($blogDoc $postsLayout) | ||
1124 | #if ("$!layout" == '') | ||
1125 | #set ($layout = $postsLayout) | ||
1126 | #end | ||
1127 | #if ($postsVisiblity == 'recent') | ||
1128 | {{blogpostlist category="$targetDoc.fullName.replaceAll('~', '~~').replaceAll('"', '~"')" published='yes' hidden='no' layout="$!layout.replaceAll('~', '~~').replaceAll('"', '~"')" layoutParams="$!layoutParams.replaceAll('~', '~~').replaceAll('"', '~"')" limit="$limit" /}} | ||
1129 | #elseif($postsVisiblity == 'unpublished') | ||
1130 | {{blogpostlist category="$targetDoc.fullName.replaceAll('~', '~~').replaceAll('"', '~"')" published='no' layout="$!layout.replaceAll('~', '~~').replaceAll('"', '~"')" layoutParams="$!layoutParams.replaceAll('~', '~~').replaceAll('"', '~"')" paginated="$!macro.paginated" limit="$limit" /}} | ||
1131 | #end | ||
1132 | #elseif($targetDoc.getObject('XWiki.DocumentSheetBinding').sheet == 'Blog.CategoriesSheet') | ||
1133 | ## Display all posts that are in a category aCategorySpace.% | ||
1134 | #getBlogDocumentForCategoriesSpace($targetDoc.space $blogDoc) | ||
1135 | #getBlogPostsLayout($blogDoc $postsLayout) | ||
1136 | #if ("$!layout" == '') | ||
1137 | #set ($layout = $postsLayout) | ||
1138 | #end | ||
1139 | #if ($postsVisiblity == 'recent') | ||
1140 | {{blogpostlist category="$targetDoc.space.replaceAll('~', '~~').replaceAll('"', '~"')" published='yes' hidden='no' layout="$!layout.replaceAll('~', '~~').replaceAll('"', '~"')" layoutParams="$!layoutParams.replaceAll('~', '~~').replaceAll('"', '~"')" limit="$limit" /}} | ||
1141 | #elseif($postsVisiblity == 'unpublished') | ||
1142 | {{blogpostlist category="$targetDoc.space.replaceAll('~', '~~').replaceAll('"', '~"')" published='no' layout="$!layout.replaceAll('~', '~~').replaceAll('"', '~"')" layoutParams="$!layoutParams.replaceAll('~', '~~').replaceAll('"', '~"')" paginated="$!macro.paginated" limit="$limit" /}} | ||
1143 | #end | ||
1144 | #else | ||
1145 | ## Display all posts in blog space aBlog | ||
1146 | #getBlogDocument($targetDoc.space $blogDoc) | ||
1147 | #getBlogPostsLayout($blogDoc $postsLayout) | ||
1148 | #if ("$!layout" == '') | ||
1149 | #set ($layout = $postsLayout) | ||
1150 | #end | ||
1151 | #if ($postsVisiblity == 'recent') | ||
1152 | {{blogpostlist blog="$blogDoc.fullName.replaceAll('~', '~~').replaceAll('"', '~"')" published='yes' hidden='no' layout="$!layout.replaceAll('~', '~~').replaceAll('"', '~"')" limit="$limit" /}} | ||
1153 | #elseif($postsVisiblity == 'unpublished') | ||
1154 | {{blogpostlist blog="$blogDoc.fullName.replaceAll('~', '~~').replaceAll('"', '~"')" published='no' layout="$!layout.replaceAll('~', '~~').replaceAll('"', '~"')" layoutParams="$!layoutParams.replaceAll('~', '~~').replaceAll('"', '~"')" paginated="$!macro.paginated" limit="$limit" /}} | ||
1155 | #end | ||
1156 | #end | ||
1157 | #end | ||
1158 | ## | ||
1159 | ## | ||
1160 | ## | ||
1161 | #** | ||
1162 | * Bind parameters to a query object. | ||
1163 | * | ||
1164 | * @param queryObj The query object (org.xwiki.query.internal.ScriptQuery object) | ||
1165 | * @param queryParams the query parameters. | ||
1166 | *### | ||
1167 | #macro(bindQueryParameters $queryObj $queryParams) | ||
1168 | #set ($output = $queryObj) | ||
1169 | #foreach( $key in $queryParams.keySet() ) | ||
1170 | #set($output = $queryObj.bindValue($key, $queryParams.get($key))) | ||
1171 | #end | ||
1172 | #setVariable("$queryObj" $output) | ||
1173 | #end | ||
1174 | ## | ||
1175 | ## | ||
1176 | ## | ||
1177 | #** | ||
1178 | * Determines the blogposts layout: Default layout (Calendar), Image thumbnail | ||
1179 | * | ||
1180 | * @param blogDoc The blog document. It should contain a <tt>Blog.BlogClass</tt> object with the <tt>postsLayout</tt> | ||
1181 | * property set. | ||
1182 | * @param postsLayout The resulting string. If the blog object does not define anything, it is considered full (default). | ||
1183 | *### | ||
1184 | #macro(getBlogPostsLayout $blogDoc $postsLayout) | ||
1185 | #getBlogProperty($blogDoc 'postsLayout' 'full' $res) | ||
1186 | #set ($postsLayout = $NULL) | ||
1187 | #setVariable ("$postsLayout" $res) | ||
1188 | #end | ||
1189 | ## | ||
1190 | ## | ||
1191 | ## | ||
1192 | #** | ||
1193 | * Retrieve the blog document of a categories space, which is the blog descriptor that have its categoriesLocation property set to the categories space | ||
1194 | * | ||
1195 | * @param categoriesSpace A <tt>String</tt>, the name of the space. | ||
1196 | * @param blogDoc The resulting XDocument. | ||
1197 | *### | ||
1198 | #macro(getBlogDocumentForCategoriesSpace $categoriesSpace $blogDoc) | ||
1199 | #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()) | ||
1200 | #if($macro.blogDocs.size() > 0 && $categoriesSpace != $defaultBlogSpace) | ||
1201 | #set($macro.result = $xwiki.getDocument($macro.blogDocs.get(0))) | ||
1202 | #else | ||
1203 | ## Fallback to Blog.WebHome, the default blog | ||
1204 | #set($macro.result = $xwiki.getDocument('Blog.WebHome')) | ||
1205 | #end | ||
1206 | #set ($blogDoc = $NULL) | ||
1207 | #setVariable ("$blogDoc" $macro.result) | ||
1208 | #end | ||
1209 | {{/velocity}} |