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