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