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