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