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