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