1
22
23 package com.liferay.portlet.wiki.service.impl;
24
25 import com.liferay.portal.PortalException;
26 import com.liferay.portal.SystemException;
27 import com.liferay.portal.kernel.language.LanguageUtil;
28 import com.liferay.portal.kernel.util.Diff;
29 import com.liferay.portal.kernel.util.DiffResult;
30 import com.liferay.portal.kernel.util.DiffUtil;
31 import com.liferay.portal.kernel.util.GetterUtil;
32 import com.liferay.portal.kernel.util.HtmlUtil;
33 import com.liferay.portal.kernel.util.ObjectValuePair;
34 import com.liferay.portal.kernel.util.StringPool;
35 import com.liferay.portal.kernel.util.StringUtil;
36 import com.liferay.portal.security.permission.ActionKeys;
37 import com.liferay.portal.theme.ThemeDisplay;
38 import com.liferay.portal.util.ContentUtil;
39 import com.liferay.portal.util.PortalUtil;
40 import com.liferay.portal.util.PortletKeys;
41 import com.liferay.portal.util.PropsKeys;
42 import com.liferay.portal.util.PropsUtil;
43 import com.liferay.portal.velocity.VelocityUtil;
44 import com.liferay.portlet.wiki.model.WikiNode;
45 import com.liferay.portlet.wiki.model.WikiPage;
46 import com.liferay.portlet.wiki.service.base.WikiPageServiceBaseImpl;
47 import com.liferay.portlet.wiki.service.permission.WikiNodePermission;
48 import com.liferay.portlet.wiki.service.permission.WikiPagePermission;
49 import com.liferay.portlet.wiki.util.WikiUtil;
50 import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
51 import com.liferay.util.RSSUtil;
52
53 import com.sun.syndication.feed.synd.SyndContent;
54 import com.sun.syndication.feed.synd.SyndContentImpl;
55 import com.sun.syndication.feed.synd.SyndEntry;
56 import com.sun.syndication.feed.synd.SyndEntryImpl;
57 import com.sun.syndication.feed.synd.SyndFeed;
58 import com.sun.syndication.feed.synd.SyndFeedImpl;
59 import com.sun.syndication.io.FeedException;
60
61 import java.io.StringReader;
62
63 import java.util.ArrayList;
64 import java.util.HashMap;
65 import java.util.Iterator;
66 import java.util.List;
67 import java.util.Locale;
68 import java.util.Map;
69
70 import javax.portlet.PortletPreferences;
71
72
79 public class WikiPageServiceImpl extends WikiPageServiceBaseImpl {
80
81 public WikiPage addPage(
82 long nodeId, String title, String content, String summary,
83 boolean minorEdit, PortletPreferences prefs,
84 ThemeDisplay themeDisplay)
85 throws PortalException, SystemException {
86
87 WikiNodePermission.check(
88 getPermissionChecker(), nodeId, ActionKeys.ADD_PAGE);
89
90 return wikiPageLocalService.addPage(
91 getUserId(), nodeId, title, content, summary, minorEdit, prefs,
92 themeDisplay);
93 }
94
95 public void addPageAttachments(
96 long nodeId, String title,
97 List<ObjectValuePair<String, byte[]>> files)
98 throws PortalException, SystemException {
99
100 WikiNodePermission.check(
101 getPermissionChecker(), nodeId, ActionKeys.ADD_ATTACHMENT);
102
103 wikiPageLocalService.addPageAttachments(nodeId, title, files);
104 }
105
106 public void changeParent(
107 long nodeId, String title, String newParentTitle,
108 PortletPreferences prefs, ThemeDisplay themeDisplay)
109 throws PortalException, SystemException {
110
111 WikiNodePermission.check(
112 getPermissionChecker(), nodeId, ActionKeys.ADD_PAGE);
113
114 WikiPagePermission.check(
115 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
116
117 wikiPageLocalService.changeParent(
118 getUserId(), nodeId, title, newParentTitle, prefs, themeDisplay);
119 }
120
121 public void deletePage(long nodeId, String title)
122 throws PortalException, SystemException {
123
124 WikiPagePermission.check(
125 getPermissionChecker(), nodeId, title, ActionKeys.DELETE);
126
127 wikiPageLocalService.deletePage(nodeId, title);
128 }
129
130 public void deletePageAttachment(long nodeId, String title, String fileName)
131 throws PortalException, SystemException {
132
133 WikiPagePermission.check(
134 getPermissionChecker(), nodeId, title, ActionKeys.DELETE);
135
136 wikiPageLocalService.deletePageAttachment(nodeId, title, fileName);
137 }
138
139 public List<WikiPage> getNodePages(long nodeId, int max)
140 throws PortalException, SystemException {
141
142 List<WikiPage> pages = new ArrayList<WikiPage>();
143
144 int lastIntervalStart = 0;
145 boolean listNotExhausted = true;
146
147 while ((pages.size() < max) && listNotExhausted) {
148 List<WikiPage> pageList = wikiPageLocalService.getPages(
149 nodeId, true, lastIntervalStart, lastIntervalStart + max);
150
151 Iterator<WikiPage> itr = pageList.iterator();
152
153 lastIntervalStart += max;
154 listNotExhausted = (pageList.size() == max);
155
156 while (itr.hasNext() && (pages.size() < max)) {
157 WikiPage page = itr.next();
158
159 if (WikiPagePermission.contains(getPermissionChecker(), page,
160 ActionKeys.VIEW)) {
161
162 pages.add(page);
163 }
164 }
165 }
166
167 return pages;
168 }
169
170 public String getNodePagesRSS(
171 long nodeId, int max, String type, double version,
172 String displayStyle, String feedURL, String entryURL)
173 throws PortalException, SystemException {
174
175 WikiNodePermission.check(
176 getPermissionChecker(), nodeId, ActionKeys.VIEW);
177
178 WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
179
180 long companyId = node.getCompanyId();
181 String name = node.getName();
182 String description = node.getDescription();
183 List<WikiPage> pages = getNodePages(nodeId, max);
184 boolean diff = false;
185 Locale locale = null;
186
187 return exportToRSS(
188 companyId, name, description, type, version, displayStyle,
189 feedURL, entryURL, pages, diff, locale);
190 }
191
192 public WikiPage getPage(long nodeId, String title)
193 throws PortalException, SystemException {
194
195 WikiPagePermission.check(
196 getPermissionChecker(), nodeId, title, ActionKeys.VIEW);
197
198 return wikiPageLocalService.getPage(nodeId, title);
199 }
200
201 public WikiPage getPage(long nodeId, String title, double version)
202 throws PortalException, SystemException {
203
204 WikiPagePermission.check(
205 getPermissionChecker(), nodeId, title, ActionKeys.VIEW);
206
207 return wikiPageLocalService.getPage(nodeId, title, version);
208 }
209
210 public String getPagesRSS(
211 long companyId, long nodeId, String title, int max, String type,
212 double version, String displayStyle, String feedURL,
213 String entryURL, Locale locale)
214 throws PortalException, SystemException {
215
216 WikiPagePermission.check(
217 getPermissionChecker(), nodeId, title, ActionKeys.VIEW);
218
219 String description = title;
220 List<WikiPage> pages = wikiPageLocalService.getPages(
221 nodeId, title, 0, max, new PageCreateDateComparator(true));
222 boolean diff = true;
223
224 return exportToRSS(
225 companyId, title, description, type, version, displayStyle, feedURL,
226 entryURL, pages, diff, locale);
227 }
228
229 public void movePage(
230 long nodeId, String title, String newTitle,
231 PortletPreferences prefs, ThemeDisplay themeDisplay)
232 throws PortalException, SystemException {
233
234 WikiNodePermission.check(
235 getPermissionChecker(), nodeId, ActionKeys.ADD_PAGE);
236
237 WikiPagePermission.check(
238 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
239
240 wikiPageLocalService.movePage(
241 getUserId(), nodeId, title, newTitle, prefs, themeDisplay);
242 }
243
244 public WikiPage revertPage(
245 long nodeId, String title, double version, PortletPreferences prefs,
246 ThemeDisplay themeDisplay)
247 throws PortalException, SystemException {
248
249 WikiPagePermission.check(
250 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
251
252 return wikiPageLocalService.revertPage(
253 getUserId(), nodeId, title, version, prefs, themeDisplay);
254 }
255
256 public void subscribePage(long nodeId, String title)
257 throws PortalException, SystemException {
258
259 WikiPagePermission.check(
260 getPermissionChecker(), nodeId, title, ActionKeys.SUBSCRIBE);
261
262 wikiPageLocalService.subscribePage(getUserId(), nodeId, title);
263 }
264
265 public void unsubscribePage(long nodeId, String title)
266 throws PortalException, SystemException {
267
268 WikiPagePermission.check(
269 getPermissionChecker(), nodeId, title, ActionKeys.SUBSCRIBE);
270
271 wikiPageLocalService.unsubscribePage(getUserId(), nodeId, title);
272 }
273
274 public WikiPage updatePage(
275 long nodeId, String title, double version, String content,
276 String summary, boolean minorEdit, String format,
277 String parentTitle, String redirectTitle, String[] tagsEntries,
278 PortletPreferences prefs, ThemeDisplay themeDisplay)
279 throws PortalException, SystemException {
280
281 WikiPagePermission.check(
282 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
283
284 return wikiPageLocalService.updatePage(
285 getUserId(), nodeId, title, version, content, summary, minorEdit,
286 format, parentTitle, redirectTitle, tagsEntries, prefs,
287 themeDisplay);
288 }
289
290 protected String exportToRSS(
291 long companyId, String name, String description, String type,
292 double version, String displayStyle, String feedURL,
293 String entryURL, List<WikiPage> pages, boolean diff, Locale locale)
294 throws SystemException {
295
296 SyndFeed syndFeed = new SyndFeedImpl();
297
298 syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
299 syndFeed.setTitle(name);
300 syndFeed.setLink(feedURL);
301 syndFeed.setDescription(description);
302
303 List<SyndEntry> entries = new ArrayList<SyndEntry>();
304
305 syndFeed.setEntries(entries);
306
307 WikiPage latestPage = null;
308
309 for (WikiPage page : pages) {
310 String author = PortalUtil.getUserName(
311 page.getUserId(), page.getUserName());
312
313 String title =
314 page.getTitle() + StringPool.SPACE + page.getVersion();
315
316 if (page.isMinorEdit()) {
317 title +=
318 StringPool.SPACE + StringPool.OPEN_PARENTHESIS +
319 LanguageUtil.get(locale, "minor-edit") +
320 StringPool.CLOSE_PARENTHESIS;
321 }
322
323 String link = entryURL;
324
325 SyndEntry syndEntry = new SyndEntryImpl();
326
327 syndEntry.setAuthor(author);
328 syndEntry.setTitle(title);
329 syndEntry.setPublishedDate(page.getCreateDate());
330
331 SyndContent syndContent = new SyndContentImpl();
332
333 syndContent.setType(RSSUtil.DEFAULT_ENTRY_TYPE);
334
335 if (diff) {
336 if (latestPage != null) {
337 link +=
338 "?" + PortalUtil.getPortletNamespace(PortletKeys.WIKI) +
339 "version=" + page.getVersion();
340
341 String value = getPageDiff(
342 companyId, latestPage, page, locale);
343
344 syndContent.setValue(value);
345
346 syndEntry.setDescription(syndContent);
347
348 entries.add(syndEntry);
349 }
350 }
351 else {
352 String value = null;
353
354 if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
355 value = StringUtil.shorten(
356 HtmlUtil.extractText(page.getContent()),
357 _RSS_ABSTRACT_LENGTH, StringPool.BLANK);
358 }
359 else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
360 value = StringPool.BLANK;
361 }
362 else {
363 value = page.getContent();
364 }
365
366 syndContent.setValue(value);
367
368 syndEntry.setDescription(syndContent);
369
370 entries.add(syndEntry);
371 }
372
373 syndEntry.setLink(link);
374
375 latestPage = page;
376 }
377
378 try {
379 return RSSUtil.export(syndFeed);
380 }
381 catch (FeedException fe) {
382 throw new SystemException(fe);
383 }
384 }
385
386 protected String getPageDiff(
387 long companyId, WikiPage latestPage, WikiPage page,
388 Locale locale)
389 throws SystemException {
390
391 String sourceContent = WikiUtil.processContent(latestPage.getContent());
392 String targetContent = WikiUtil.processContent(page.getContent());
393
394 sourceContent = HtmlUtil.escape(sourceContent);
395 targetContent = HtmlUtil.escape(targetContent);
396
397 List<DiffResult>[] diffResults = DiffUtil.diff(
398 new StringReader(sourceContent), new StringReader(targetContent));
399
400 String template = ContentUtil.get(
401 "com/liferay/portlet/wiki/dependencies/rss.vm");
402
403 Map<String, Object> variables = new HashMap<String, Object>();
404
405 variables.put("companyId", companyId);
406 variables.put("contextLine", Diff.CONTEXT_LINE);
407 variables.put("diffUtil", new DiffUtil());
408 variables.put("languageUtil", LanguageUtil.getLanguage());
409 variables.put("locale", locale);
410 variables.put("sourceResults", diffResults[0]);
411 variables.put("targetResults", diffResults[1]);
412
413 try {
414 return VelocityUtil.evaluate(template, variables);
415 }
416 catch (Exception e) {
417 throw new SystemException(e);
418 }
419 }
420
421 private static final int _RSS_ABSTRACT_LENGTH = GetterUtil.getInteger(
422 PropsUtil.get(PropsKeys.WIKI_RSS_ABSTRACT_LENGTH));
423
424 }