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 List<WikiPage> getNodePages(long nodeId, int max)
146 throws PortalException, SystemException {
147
148 List<WikiPage> pages = new ArrayList<WikiPage>();
149
150 int lastIntervalStart = 0;
151 boolean listNotExhausted = true;
152
153 while ((pages.size() < max) && listNotExhausted) {
154 List<WikiPage> pageList = wikiPageLocalService.getPages(
155 nodeId, true, lastIntervalStart, lastIntervalStart + max);
156
157 Iterator<WikiPage> itr = pageList.iterator();
158
159 lastIntervalStart += max;
160 listNotExhausted = (pageList.size() == max);
161
162 while (itr.hasNext() && (pages.size() < max)) {
163 WikiPage page = itr.next();
164
165 if (WikiPagePermission.contains(getPermissionChecker(), page,
166 ActionKeys.VIEW)) {
167
168 pages.add(page);
169 }
170 }
171 }
172
173 return pages;
174 }
175
176 public String getNodePagesRSS(
177 long nodeId, int max, String type, double version,
178 String displayStyle, String feedURL, String entryURL)
179 throws PortalException, SystemException {
180
181 WikiNodePermission.check(
182 getPermissionChecker(), nodeId, ActionKeys.VIEW);
183
184 WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
185
186 long companyId = node.getCompanyId();
187 String name = node.getName();
188 String description = node.getDescription();
189 List<WikiPage> pages = getNodePages(nodeId, max);
190 boolean diff = false;
191 Locale locale = null;
192
193 return exportToRSS(
194 companyId, name, description, type, version, displayStyle,
195 feedURL, entryURL, pages, diff, locale);
196 }
197
198 public WikiPage getPage(long nodeId, String title)
199 throws PortalException, SystemException {
200
201 WikiPagePermission.check(
202 getPermissionChecker(), nodeId, title, ActionKeys.VIEW);
203
204 return wikiPageLocalService.getPage(nodeId, title);
205 }
206
207 public WikiPage getPage(long nodeId, String title, double version)
208 throws PortalException, SystemException {
209
210 WikiPagePermission.check(
211 getPermissionChecker(), nodeId, title, ActionKeys.VIEW);
212
213 return wikiPageLocalService.getPage(nodeId, title, version);
214 }
215
216 public String getPagesRSS(
217 long companyId, long nodeId, String title, int max, String type,
218 double version, String displayStyle, String feedURL,
219 String entryURL, Locale locale)
220 throws PortalException, SystemException {
221
222 WikiPagePermission.check(
223 getPermissionChecker(), nodeId, title, ActionKeys.VIEW);
224
225 String description = title;
226 List<WikiPage> pages = wikiPageLocalService.getPages(
227 nodeId, title, 0, max, new PageCreateDateComparator(true));
228 boolean diff = true;
229
230 return exportToRSS(
231 companyId, title, description, type, version, displayStyle, feedURL,
232 entryURL, pages, diff, locale);
233 }
234
235 public void movePage(
236 long nodeId, String title, String newTitle,
237 ServiceContext serviceContext)
238 throws PortalException, SystemException {
239
240 WikiPagePermission.check(
241 getPermissionChecker(), nodeId, title, ActionKeys.DELETE);
242
243 WikiNodePermission.check(
244 getPermissionChecker(), nodeId, ActionKeys.ADD_PAGE);
245
246 wikiPageLocalService.movePage(
247 getUserId(), nodeId, title, newTitle, serviceContext);
248 }
249
250 public WikiPage revertPage(
251 long nodeId, String title, double version,
252 ServiceContext serviceContext)
253 throws PortalException, SystemException {
254
255 WikiPagePermission.check(
256 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
257
258 return wikiPageLocalService.revertPage(
259 getUserId(), nodeId, title, version, serviceContext);
260 }
261
262 public void subscribePage(long nodeId, String title)
263 throws PortalException, SystemException {
264
265 WikiPagePermission.check(
266 getPermissionChecker(), nodeId, title, ActionKeys.SUBSCRIBE);
267
268 wikiPageLocalService.subscribePage(getUserId(), nodeId, title);
269 }
270
271 public void unsubscribePage(long nodeId, String title)
272 throws PortalException, SystemException {
273
274 WikiPagePermission.check(
275 getPermissionChecker(), nodeId, title, ActionKeys.SUBSCRIBE);
276
277 wikiPageLocalService.unsubscribePage(getUserId(), nodeId, title);
278 }
279
280 public WikiPage updatePage(
281 long nodeId, String title, double version, String content,
282 String summary, boolean minorEdit, String format,
283 String parentTitle, String redirectTitle,
284 ServiceContext serviceContext)
285 throws PortalException, SystemException {
286
287 WikiPagePermission.check(
288 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
289
290 return wikiPageLocalService.updatePage(
291 getUserId(), nodeId, title, version, content, summary, minorEdit,
292 format, parentTitle, redirectTitle, serviceContext);
293 }
294
295 protected String exportToRSS(
296 long companyId, String name, String description, String type,
297 double version, String displayStyle, String feedURL,
298 String entryURL, List<WikiPage> pages, boolean diff, Locale locale)
299 throws SystemException {
300
301 SyndFeed syndFeed = new SyndFeedImpl();
302
303 syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
304 syndFeed.setTitle(name);
305 syndFeed.setLink(feedURL);
306 syndFeed.setDescription(description);
307
308 List<SyndEntry> entries = new ArrayList<SyndEntry>();
309
310 syndFeed.setEntries(entries);
311
312 WikiPage latestPage = null;
313
314 StringBundler link = new StringBundler(7);
315
316 for (WikiPage page : pages) {
317 String author = PortalUtil.getUserName(
318 page.getUserId(), page.getUserName());
319
320 String title =
321 page.getTitle() + StringPool.SPACE + page.getVersion();
322
323 if (page.isMinorEdit()) {
324 title +=
325 StringPool.SPACE + StringPool.OPEN_PARENTHESIS +
326 LanguageUtil.get(locale, "minor-edit") +
327 StringPool.CLOSE_PARENTHESIS;
328 }
329
330 link.setIndex(0);
331
332 link.append(entryURL);
333 link.append(StringPool.AMPERSAND);
334 link.append(HttpUtil.encodeURL(page.getTitle()));
335
336 SyndEntry syndEntry = new SyndEntryImpl();
337
338 syndEntry.setAuthor(author);
339 syndEntry.setTitle(title);
340 syndEntry.setPublishedDate(page.getCreateDate());
341 syndEntry.setUpdatedDate(page.getModifiedDate());
342
343 SyndContent syndContent = new SyndContentImpl();
344
345 syndContent.setType(RSSUtil.DEFAULT_ENTRY_TYPE);
346
347 if (diff) {
348 if (latestPage != null) {
349 link.append(StringPool.QUESTION);
350 link.append(
351 PortalUtil.getPortletNamespace(PortletKeys.WIKI));
352 link.append("version=");
353 link.append(page.getVersion());
354
355 String value = getPageDiff(
356 companyId, latestPage, page, locale);
357
358 syndContent.setValue(value);
359
360 syndEntry.setDescription(syndContent);
361
362 entries.add(syndEntry);
363 }
364 }
365 else {
366 String value = null;
367
368 if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
369 value = StringUtil.shorten(
370 HtmlUtil.extractText(page.getContent()),
371 _RSS_ABSTRACT_LENGTH, StringPool.BLANK);
372 }
373 else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
374 value = StringPool.BLANK;
375 }
376 else {
377 value = page.getContent();
378 }
379
380 syndContent.setValue(value);
381
382 syndEntry.setDescription(syndContent);
383
384 entries.add(syndEntry);
385 }
386
387 syndEntry.setLink(link.toString());
388 syndEntry.setUri(syndEntry.getLink());
389
390 latestPage = page;
391 }
392
393 try {
394 return RSSUtil.export(syndFeed);
395 }
396 catch (FeedException fe) {
397 throw new SystemException(fe);
398 }
399 }
400
401 protected String getPageDiff(
402 long companyId, WikiPage latestPage, WikiPage page,
403 Locale locale)
404 throws SystemException {
405
406 String sourceContent = WikiUtil.processContent(latestPage.getContent());
407 String targetContent = WikiUtil.processContent(page.getContent());
408
409 sourceContent = HtmlUtil.escape(sourceContent);
410 targetContent = HtmlUtil.escape(targetContent);
411
412 List<DiffResult>[] diffResults = DiffUtil.diff(
413 new UnsyncStringReader(sourceContent),
414 new UnsyncStringReader(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 UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter(
433 true);
434
435 VelocityEngineUtil.mergeTemplate(
436 velocityTemplateId, velocityTemplateContent, velocityContext,
437 unsyncStringWriter);
438
439 return unsyncStringWriter.toString();
440 }
441 catch (Exception e) {
442 throw new SystemException(e);
443 }
444 }
445
446 private static final int _RSS_ABSTRACT_LENGTH = GetterUtil.getInteger(
447 PropsUtil.get(PropsKeys.WIKI_RSS_ABSTRACT_LENGTH));
448
449 }