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