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.service.ServiceContext;
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
80 public class WikiPageServiceImpl extends WikiPageServiceBaseImpl {
81
82 public WikiPage addPage(
83 long nodeId, String title, String content, String summary,
84 boolean minorEdit, ServiceContext serviceContext)
85 throws PortalException, SystemException {
86
87 WikiNodePermission.check(
88 getPermissionChecker(), nodeId, ActionKeys.ADD_PAGE);
89
90 return wikiPageLocalService.addPage(
91 getUserId(), nodeId, title, content, summary, minorEdit,
92 serviceContext);
93 }
94
95 public WikiPage addPage(
96 long nodeId, String title, String content, String summary,
97 boolean minorEdit, String format, String parentTitle,
98 String redirectTitle, ServiceContext serviceContext)
99 throws PortalException, SystemException {
100
101 WikiNodePermission.check(
102 getPermissionChecker(), nodeId, ActionKeys.ADD_PAGE);
103
104 return wikiPageLocalService.addPage(
105 null, getUserId(), nodeId, title, WikiPageImpl.DEFAULT_VERSION,
106 content, summary, minorEdit, format, true, parentTitle,
107 redirectTitle, serviceContext);
108 }
109
110 public void addPageAttachments(
111 long nodeId, String title,
112 List<ObjectValuePair<String, byte[]>> files)
113 throws PortalException, SystemException {
114
115 WikiNodePermission.check(
116 getPermissionChecker(), nodeId, ActionKeys.ADD_ATTACHMENT);
117
118 wikiPageLocalService.addPageAttachments(nodeId, title, files);
119 }
120
121 public void changeParent(
122 long nodeId, String title, String newParentTitle,
123 ServiceContext serviceContext)
124 throws PortalException, SystemException {
125
126 WikiPagePermission.check(
127 getPermissionChecker(), nodeId, title, ActionKeys.DELETE);
128
129 WikiNodePermission.check(
130 getPermissionChecker(), nodeId, ActionKeys.ADD_PAGE);
131
132 wikiPageLocalService.changeParent(
133 getUserId(), nodeId, title, newParentTitle, serviceContext);
134 }
135
136 public void deletePage(long nodeId, String title)
137 throws PortalException, SystemException {
138
139 WikiPagePermission.check(
140 getPermissionChecker(), nodeId, title, ActionKeys.DELETE);
141
142 wikiPageLocalService.deletePage(nodeId, title);
143 }
144
145 public void deletePageAttachment(long nodeId, String title, String fileName)
146 throws PortalException, SystemException {
147
148 WikiPagePermission.check(
149 getPermissionChecker(), nodeId, title, ActionKeys.DELETE);
150
151 wikiPageLocalService.deletePageAttachment(nodeId, title, fileName);
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, double version)
217 throws PortalException, SystemException {
218
219 WikiPagePermission.check(
220 getPermissionChecker(), nodeId, title, ActionKeys.VIEW);
221
222 return wikiPageLocalService.getPage(nodeId, title, version);
223 }
224
225 public String getPagesRSS(
226 long companyId, long nodeId, String title, int max, String type,
227 double version, String displayStyle, String feedURL,
228 String entryURL, Locale locale)
229 throws PortalException, SystemException {
230
231 WikiPagePermission.check(
232 getPermissionChecker(), nodeId, title, ActionKeys.VIEW);
233
234 String description = title;
235 List<WikiPage> pages = wikiPageLocalService.getPages(
236 nodeId, title, 0, max, new PageCreateDateComparator(true));
237 boolean diff = true;
238
239 return exportToRSS(
240 companyId, title, description, type, version, displayStyle, feedURL,
241 entryURL, pages, diff, locale);
242 }
243
244 public void movePage(
245 long nodeId, String title, String newTitle,
246 ServiceContext serviceContext)
247 throws PortalException, SystemException {
248
249 WikiPagePermission.check(
250 getPermissionChecker(), nodeId, title, ActionKeys.DELETE);
251
252 WikiNodePermission.check(
253 getPermissionChecker(), nodeId, ActionKeys.ADD_PAGE);
254
255 wikiPageLocalService.movePage(
256 getUserId(), nodeId, title, newTitle, serviceContext);
257 }
258
259 public WikiPage revertPage(
260 long nodeId, String title, double version,
261 ServiceContext serviceContext)
262 throws PortalException, SystemException {
263
264 WikiPagePermission.check(
265 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
266
267 return wikiPageLocalService.revertPage(
268 getUserId(), nodeId, title, version, serviceContext);
269 }
270
271 public void subscribePage(long nodeId, String title)
272 throws PortalException, SystemException {
273
274 WikiPagePermission.check(
275 getPermissionChecker(), nodeId, title, ActionKeys.SUBSCRIBE);
276
277 wikiPageLocalService.subscribePage(getUserId(), nodeId, title);
278 }
279
280 public void unsubscribePage(long nodeId, String title)
281 throws PortalException, SystemException {
282
283 WikiPagePermission.check(
284 getPermissionChecker(), nodeId, title, ActionKeys.SUBSCRIBE);
285
286 wikiPageLocalService.unsubscribePage(getUserId(), nodeId, title);
287 }
288
289 public WikiPage updatePage(
290 long nodeId, String title, double version, String content,
291 String summary, boolean minorEdit, String format,
292 String parentTitle, String redirectTitle,
293 ServiceContext serviceContext)
294 throws PortalException, SystemException {
295
296 WikiPagePermission.check(
297 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
298
299 return wikiPageLocalService.updatePage(
300 getUserId(), nodeId, title, version, content, summary, minorEdit,
301 format, parentTitle, redirectTitle, serviceContext);
302 }
303
304 protected String exportToRSS(
305 long companyId, String name, String description, String type,
306 double version, String displayStyle, String feedURL,
307 String entryURL, List<WikiPage> pages, boolean diff, Locale locale)
308 throws SystemException {
309
310 SyndFeed syndFeed = new SyndFeedImpl();
311
312 syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
313 syndFeed.setTitle(name);
314 syndFeed.setLink(feedURL);
315 syndFeed.setDescription(description);
316
317 List<SyndEntry> entries = new ArrayList<SyndEntry>();
318
319 syndFeed.setEntries(entries);
320
321 WikiPage latestPage = null;
322
323 for (WikiPage page : pages) {
324 String author = PortalUtil.getUserName(
325 page.getUserId(), page.getUserName());
326
327 String title =
328 page.getTitle() + StringPool.SPACE + page.getVersion();
329
330 if (page.isMinorEdit()) {
331 title +=
332 StringPool.SPACE + StringPool.OPEN_PARENTHESIS +
333 LanguageUtil.get(locale, "minor-edit") +
334 StringPool.CLOSE_PARENTHESIS;
335 }
336
337 String link = entryURL + HttpUtil.encodeURL(page.getTitle());
338
339 SyndEntry syndEntry = new SyndEntryImpl();
340
341 syndEntry.setAuthor(author);
342 syndEntry.setTitle(title);
343 syndEntry.setPublishedDate(page.getCreateDate());
344 syndEntry.setUpdatedDate(page.getModifiedDate());
345
346 SyndContent syndContent = new SyndContentImpl();
347
348 syndContent.setType(RSSUtil.DEFAULT_ENTRY_TYPE);
349
350 if (diff) {
351 if (latestPage != null) {
352 link +=
353 "?" + PortalUtil.getPortletNamespace(PortletKeys.WIKI) +
354 "version=" + page.getVersion();
355
356 String value = getPageDiff(
357 companyId, latestPage, page, locale);
358
359 syndContent.setValue(value);
360
361 syndEntry.setDescription(syndContent);
362
363 entries.add(syndEntry);
364 }
365 }
366 else {
367 String value = null;
368
369 if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
370 value = StringUtil.shorten(
371 HtmlUtil.extractText(page.getContent()),
372 _RSS_ABSTRACT_LENGTH, StringPool.BLANK);
373 }
374 else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
375 value = StringPool.BLANK;
376 }
377 else {
378 value = page.getContent();
379 }
380
381 syndContent.setValue(value);
382
383 syndEntry.setDescription(syndContent);
384
385 entries.add(syndEntry);
386 }
387
388 syndEntry.setLink(link);
389 syndEntry.setUri(syndEntry.getLink());
390
391 latestPage = page;
392 }
393
394 try {
395 return RSSUtil.export(syndFeed);
396 }
397 catch (FeedException fe) {
398 throw new SystemException(fe);
399 }
400 }
401
402 protected String getPageDiff(
403 long companyId, WikiPage latestPage, WikiPage page,
404 Locale locale)
405 throws SystemException {
406
407 String sourceContent = WikiUtil.processContent(latestPage.getContent());
408 String targetContent = WikiUtil.processContent(page.getContent());
409
410 sourceContent = HtmlUtil.escape(sourceContent);
411 targetContent = HtmlUtil.escape(targetContent);
412
413 List<DiffResult>[] diffResults = DiffUtil.diff(
414 new StringReader(sourceContent), new StringReader(targetContent));
415
416 String velocityTemplateId =
417 "com/liferay/portlet/wiki/dependencies/rss.vm";
418 String velocityTemplateContent = ContentUtil.get(velocityTemplateId);
419
420 VelocityContext velocityContext =
421 VelocityEngineUtil.getWrappedStandardToolsContext();
422
423 velocityContext.put("companyId", companyId);
424 velocityContext.put("contextLine", Diff.CONTEXT_LINE);
425 velocityContext.put("diffUtil", new DiffUtil());
426 velocityContext.put("languageUtil", LanguageUtil.getLanguage());
427 velocityContext.put("locale", locale);
428 velocityContext.put("sourceResults", diffResults[0]);
429 velocityContext.put("targetResults", diffResults[1]);
430
431 try {
432 StringWriter stringWriter = new StringWriter();
433
434 VelocityEngineUtil.mergeTemplate(
435 velocityTemplateId, velocityTemplateContent, velocityContext,
436 stringWriter);
437
438 return stringWriter.toString();
439 }
440 catch (Exception e) {
441 throw new SystemException(e);
442 }
443 }
444
445 private static final int _RSS_ABSTRACT_LENGTH = GetterUtil.getInteger(
446 PropsUtil.get(PropsKeys.WIKI_RSS_ABSTRACT_LENGTH));
447
448 }