1
22
23 package com.liferay.portlet.wiki.service.impl;
24
25 import com.liferay.documentlibrary.DuplicateDirectoryException;
26 import com.liferay.documentlibrary.DuplicateFileException;
27 import com.liferay.documentlibrary.NoSuchDirectoryException;
28 import com.liferay.documentlibrary.NoSuchFileException;
29 import com.liferay.portal.PortalException;
30 import com.liferay.portal.SystemException;
31 import com.liferay.portal.kernel.messaging.DestinationNames;
32 import com.liferay.portal.kernel.messaging.Message;
33 import com.liferay.portal.kernel.messaging.MessageBusUtil;
34 import com.liferay.portal.kernel.search.SearchException;
35 import com.liferay.portal.kernel.util.CalendarFactoryUtil;
36 import com.liferay.portal.kernel.util.ContentTypes;
37 import com.liferay.portal.kernel.util.ListUtil;
38 import com.liferay.portal.kernel.util.NotificationThreadLocal;
39 import com.liferay.portal.kernel.util.ObjectValuePair;
40 import com.liferay.portal.kernel.util.OrderByComparator;
41 import com.liferay.portal.kernel.util.StringPool;
42 import com.liferay.portal.kernel.util.StringUtil;
43 import com.liferay.portal.kernel.util.Validator;
44 import com.liferay.portal.model.Company;
45 import com.liferay.portal.model.CompanyConstants;
46 import com.liferay.portal.model.Group;
47 import com.liferay.portal.model.GroupConstants;
48 import com.liferay.portal.model.ResourceConstants;
49 import com.liferay.portal.model.User;
50 import com.liferay.portal.theme.ThemeDisplay;
51 import com.liferay.portal.util.PortalUtil;
52 import com.liferay.portal.util.PortletKeys;
53 import com.liferay.portal.util.PropsValues;
54 import com.liferay.portlet.wiki.DuplicatePageException;
55 import com.liferay.portlet.wiki.NoSuchPageException;
56 import com.liferay.portlet.wiki.PageContentException;
57 import com.liferay.portlet.wiki.PageTitleException;
58 import com.liferay.portlet.wiki.PageVersionException;
59 import com.liferay.portlet.wiki.model.WikiNode;
60 import com.liferay.portlet.wiki.model.WikiPage;
61 import com.liferay.portlet.wiki.model.WikiPageDisplay;
62 import com.liferay.portlet.wiki.model.WikiPageResource;
63 import com.liferay.portlet.wiki.model.impl.WikiPageDisplayImpl;
64 import com.liferay.portlet.wiki.model.impl.WikiPageImpl;
65 import com.liferay.portlet.wiki.service.base.WikiPageLocalServiceBaseImpl;
66 import com.liferay.portlet.wiki.social.WikiActivityKeys;
67 import com.liferay.portlet.wiki.util.Indexer;
68 import com.liferay.portlet.wiki.util.WikiCacheThreadLocal;
69 import com.liferay.portlet.wiki.util.WikiCacheUtil;
70 import com.liferay.portlet.wiki.util.WikiUtil;
71 import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
72 import com.liferay.util.MathUtil;
73 import com.liferay.util.UniqueList;
74
75 import java.rmi.RemoteException;
76
77 import java.util.ArrayList;
78 import java.util.Calendar;
79 import java.util.Collections;
80 import java.util.Date;
81 import java.util.HashSet;
82 import java.util.Iterator;
83 import java.util.LinkedHashMap;
84 import java.util.List;
85 import java.util.Map;
86 import java.util.Set;
87 import java.util.regex.Matcher;
88 import java.util.regex.Pattern;
89
90 import javax.portlet.PortletPreferences;
91 import javax.portlet.PortletURL;
92
93 import org.apache.commons.logging.Log;
94 import org.apache.commons.logging.LogFactory;
95
96
103 public class WikiPageLocalServiceImpl extends WikiPageLocalServiceBaseImpl {
104
105 public WikiPage addPage(
106 long userId, long nodeId, String title, String content,
107 String summary, boolean minorEdit, PortletPreferences prefs,
108 ThemeDisplay themeDisplay)
109 throws PortalException, SystemException {
110
111 String uuid = null;
112 double version = WikiPageImpl.DEFAULT_VERSION;
113 String format = WikiPageImpl.DEFAULT_FORMAT;
114 boolean head = true;
115 String parentTitle = null;
116 String redirectTitle = null;
117 String[] tagsEntries = null;
118
119 return addPage(
120 uuid, userId, nodeId, title, version, content, summary, minorEdit,
121 format, head, parentTitle, redirectTitle, tagsEntries, prefs,
122 themeDisplay);
123 }
124
125 public WikiPage addPage(
126 String uuid, long userId, long nodeId, String title, double version,
127 String content, String summary, boolean minorEdit, String format,
128 boolean head, String parentTitle, String redirectTitle,
129 String[] tagsEntries, PortletPreferences prefs,
130 ThemeDisplay themeDisplay)
131 throws PortalException, SystemException {
132
133
135 User user = userPersistence.findByPrimaryKey(userId);
136 WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
137
138 Date now = new Date();
139
140 validate(title, nodeId, content, format);
141
142 long pageId = counterLocalService.increment();
143
144 long resourcePrimKey =
145 wikiPageResourceLocalService.getPageResourcePrimKey(nodeId, title);
146
147 WikiPage page = wikiPagePersistence.create(pageId);
148
149 page.setUuid(uuid);
150 page.setResourcePrimKey(resourcePrimKey);
151 page.setCompanyId(user.getCompanyId());
152 page.setUserId(user.getUserId());
153 page.setUserName(user.getFullName());
154 page.setCreateDate(now);
155 page.setModifiedDate(now);
156 page.setNodeId(nodeId);
157 page.setTitle(title);
158 page.setVersion(version);
159 page.setMinorEdit(minorEdit);
160 page.setContent(content);
161 page.setSummary(summary);
162 page.setFormat(format);
163 page.setHead(head);
164 page.setParentTitle(parentTitle);
165 page.setRedirectTitle(redirectTitle);
166
167 wikiPagePersistence.update(page, false);
168
169
171 addPageResources(page.getNode(), page, true, true);
172
173
175 node.setLastPostDate(now);
176
177 wikiNodePersistence.update(node, false);
178
179
181 socialActivityLocalService.addActivity(
182 userId, node.getGroupId(), WikiPage.class.getName(),
183 page.getResourcePrimKey(), WikiActivityKeys.ADD_PAGE,
184 StringPool.BLANK, 0);
185
186
188 if (!minorEdit && NotificationThreadLocal.isNotificationEnabled()) {
189 notifySubscribers(node, page, prefs, themeDisplay, false);
190 }
191
192
194 updateTagsAsset(userId, page, tagsEntries);
195
196
198 try {
199 Indexer.addPage(
200 page.getCompanyId(), node.getGroupId(), nodeId, title,
201 content, tagsEntries);
202 }
203 catch (SearchException se) {
204 _log.error("Indexing " + pageId, se);
205 }
206
207
209 clearReferralsCache(page);
210 clearPageCache(page);
211
212 return page;
213 }
214
215 public void addPageAttachments(
216 long nodeId, String title,
217 List<ObjectValuePair<String, byte[]>> files)
218 throws PortalException, SystemException {
219
220 if (files.size() == 0) {
221 return;
222 }
223
224 WikiPage page = getPage(nodeId, title);
225
226 long companyId = page.getCompanyId();
227 String portletId = CompanyConstants.SYSTEM_STRING;
228 long groupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
229 long repositoryId = CompanyConstants.SYSTEM;
230 String dirName = page.getAttachmentsDir();
231
232 try {
233 try {
234 dlService.addDirectory(companyId, repositoryId, dirName);
235 }
236 catch (DuplicateDirectoryException dde) {
237 }
238
239 for (int i = 0; i < files.size(); i++) {
240 ObjectValuePair<String, byte[]> ovp = files.get(i);
241
242 String fileName = ovp.getKey();
243 byte[] bytes = ovp.getValue();
244
245 if (Validator.isNull(fileName)) {
246 continue;
247 }
248
249 try {
250 dlService.addFile(
251 companyId, portletId, groupId, repositoryId,
252 dirName + "/" + fileName, StringPool.BLANK,
253 new String[0], bytes);
254 }
255 catch (DuplicateFileException dfe) {
256 }
257 }
258 }
259 catch (RemoteException re) {
260 throw new SystemException(re);
261 }
262 }
263
264 public void addPageResources(
265 long nodeId, String title, boolean addCommunityPermissions,
266 boolean addGuestPermissions)
267 throws PortalException, SystemException {
268
269 WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
270 WikiPage page = getPage(nodeId, title);
271
272 addPageResources(
273 node, page, addCommunityPermissions, addGuestPermissions);
274 }
275
276 public void addPageResources(
277 WikiNode node, WikiPage page, boolean addCommunityPermissions,
278 boolean addGuestPermissions)
279 throws PortalException, SystemException {
280
281 resourceLocalService.addResources(
282 page.getCompanyId(), node.getGroupId(), page.getUserId(),
283 WikiPage.class.getName(), page.getResourcePrimKey(), false,
284 addCommunityPermissions, addGuestPermissions);
285 }
286
287 public void addPageResources(
288 long nodeId, String title, String[] communityPermissions,
289 String[] guestPermissions)
290 throws PortalException, SystemException {
291
292 WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
293 WikiPage page = getPage(nodeId, title);
294
295 addPageResources(node, page, communityPermissions, guestPermissions);
296 }
297
298 public void addPageResources(
299 WikiNode node, WikiPage page, String[] communityPermissions,
300 String[] guestPermissions)
301 throws PortalException, SystemException {
302
303 resourceLocalService.addModelResources(
304 page.getCompanyId(), node.getGroupId(), page.getUserId(),
305 WikiPage.class.getName(), page.getResourcePrimKey(),
306 communityPermissions, guestPermissions);
307 }
308
309 public void changeParent(
310 long userId, long nodeId, String title, String newParentTitle,
311 PortletPreferences prefs, ThemeDisplay themeDisplay)
312 throws PortalException, SystemException {
313
314 WikiPage page = getPage(nodeId, title);
315
316 String originalParentTitle = page.getParentTitle();
317
318 double version = page.getVersion();
319 String content = page.getContent();
320 String summary = themeDisplay.translate(
321 "changed-parent-from-x", originalParentTitle);
322 boolean minorEdit = false;
323 String format = page.getFormat();
324 String redirectTitle = page.getRedirectTitle();
325 String[] tagsEntries = tagsEntryLocalService.getEntryNames(
326 WikiPage.class.getName(), page.getResourcePrimKey());
327
328 updatePage(
329 userId, nodeId, title, version, content, summary, minorEdit,
330 format, newParentTitle, redirectTitle, tagsEntries, prefs,
331 themeDisplay);
332
333 List<WikiPage> oldPages = wikiPagePersistence.findByN_T_H(
334 nodeId, title, false);
335
336 for (WikiPage oldPage : oldPages) {
337 oldPage.setParentTitle(originalParentTitle);
338
339 wikiPagePersistence.update(oldPage, false);
340 }
341 }
342
343 public void deletePage(long nodeId, String title)
344 throws PortalException, SystemException {
345
346 List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
347 nodeId, title, true, 0, 1);
348
349 if (pages.size() > 0) {
350 WikiPage page = pages.iterator().next();
351
352 deletePage(page);
353 }
354 }
355
356 public void deletePage(WikiPage page)
357 throws PortalException, SystemException {
358
359
361 List<WikiPage> children = wikiPagePersistence.findByN_P(
362 page.getNodeId(), page.getTitle());
363
364 for (WikiPage curPage : children) {
365 deletePage(curPage);
366 }
367
368
370 try {
371 Indexer.deletePage(
372 page.getCompanyId(), page.getNodeId(), page.getTitle());
373 }
374 catch (SearchException se) {
375 _log.error("Deleting index " + page.getPrimaryKey(), se);
376 }
377
378
380 long companyId = page.getCompanyId();
381 String portletId = CompanyConstants.SYSTEM_STRING;
382 long repositoryId = CompanyConstants.SYSTEM;
383 String dirName = page.getAttachmentsDir();
384
385 try {
386 dlService.deleteDirectory(
387 companyId, portletId, repositoryId, dirName);
388 }
389 catch (NoSuchDirectoryException nsde) {
390 }
391 catch (RemoteException re) {
392 throw new SystemException(re);
393 }
394
395
397 tagsAssetLocalService.deleteAsset(
398 WikiPage.class.getName(), page.getResourcePrimKey());
399
400
402 subscriptionLocalService.deleteSubscriptions(
403 page.getCompanyId(), WikiPage.class.getName(), page.getPageId());
404
405
407 socialActivityLocalService.deleteActivities(
408 WikiPage.class.getName(), page.getResourcePrimKey());
409
410
412 mbMessageLocalService.deleteDiscussionMessages(
413 WikiPage.class.getName(), page.getResourcePrimKey());
414
415
417 resourceLocalService.deleteResource(
418 page.getCompanyId(), WikiPage.class.getName(),
419 ResourceConstants.SCOPE_INDIVIDUAL, page.getResourcePrimKey());
420
421
423 wikiPageResourceLocalService.deletePageResource(
424 page.getNodeId(), page.getTitle());
425
426
428 wikiPagePersistence.removeByN_T(page.getNodeId(), page.getTitle());
429
430
432 wikiPagePersistence.removeByN_R(page.getNodeId(), page.getTitle());
433
434
436 clearReferralsCache(page);
437 }
438
439 public void deletePageAttachment(long nodeId, String title, String fileName)
440 throws PortalException, SystemException {
441
442 if (Validator.isNull(fileName)) {
443 return;
444 }
445
446 WikiPage page = getPage(nodeId, title);
447
448 long companyId = page.getCompanyId();
449 String portletId = CompanyConstants.SYSTEM_STRING;
450 long repositoryId = CompanyConstants.SYSTEM;
451
452 try {
453 dlService.deleteFile(companyId, portletId, repositoryId, fileName);
454 }
455 catch (NoSuchFileException nsfe) {
456 }
457 catch (RemoteException re) {
458 throw new SystemException(re);
459 }
460 }
461
462 public void deletePages(long nodeId)
463 throws PortalException, SystemException {
464
465 Iterator<WikiPage> itr = wikiPagePersistence.findByN_H(
466 nodeId, true).iterator();
467
468 while (itr.hasNext()) {
469 WikiPage page = itr.next();
470
471 deletePage(page);
472 }
473 }
474
475 public List<WikiPage> getChildren(
476 long nodeId, boolean head, String parentTitle)
477 throws SystemException {
478
479 return wikiPagePersistence.findByN_H_P(nodeId, head, parentTitle);
480 }
481
482 public List<WikiPage> getIncomingLinks(long nodeId, String title)
483 throws PortalException, SystemException {
484
485 List<WikiPage> links = new UniqueList<WikiPage>();
486
487 List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
488
489 for (WikiPage page : pages) {
490 if (isLinkedTo(page, title)) {
491 links.add(page);
492 }
493 }
494
495 List<WikiPage> referrals = wikiPagePersistence.findByN_R(nodeId, title);
496
497 for (WikiPage referral : referrals) {
498 for (WikiPage page : pages) {
499 if (isLinkedTo(page, referral.getTitle())) {
500 links.add(page);
501 }
502 }
503 }
504
505 Collections.sort(links);
506
507 return links;
508 }
509
510 public List<WikiPage> getNoAssetPages() throws SystemException {
511 return wikiPageFinder.findByNoAssets();
512 }
513
514 public List<WikiPage> getOrphans(long nodeId)
515 throws PortalException, SystemException {
516
517 List<Map<String, Boolean>> pageTitles =
518 new ArrayList<Map<String, Boolean>>();
519
520 List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
521
522 for (WikiPage page : pages) {
523 pageTitles.add(WikiCacheUtil.getOutgoingLinks(page));
524 }
525
526 Set<WikiPage> notOrphans = new HashSet<WikiPage>();
527
528 for (WikiPage page : pages) {
529 for (Map<String, Boolean> pageTitle : pageTitles) {
530 if (pageTitle.get(page.getTitle()) != null) {
531 notOrphans.add(page);
532
533 break;
534 }
535 }
536 }
537
538 List<WikiPage> orphans = new ArrayList<WikiPage>();
539
540 for (WikiPage page : pages) {
541 if (!notOrphans.contains(page)) {
542 orphans.add(page);
543 }
544 }
545
546 Collections.sort(orphans);
547
548 return orphans;
549 }
550
551 public List<WikiPage> getOutgoingLinks(long nodeId, String title)
552 throws PortalException, SystemException {
553
554 WikiPage page = getPage(nodeId, title);
555
556 Map<String, WikiPage> pages = new LinkedHashMap<String, WikiPage>();
557
558 Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
559
560 for (String curTitle : links.keySet()) {
561 Boolean exists = links.get(curTitle);
562
563 if (exists) {
564 if (!pages.containsKey(curTitle)) {
565 pages.put(curTitle, getPage(nodeId, curTitle));
566 }
567 }
568 else {
569 WikiPageImpl newPage = new WikiPageImpl();
570
571 newPage.setNew(true);
572 newPage.setNodeId(nodeId);
573 newPage.setTitle(curTitle);
574
575 if (!pages.containsKey(curTitle)) {
576 pages.put(curTitle, newPage);
577 }
578 }
579 }
580
581 return ListUtil.fromCollection(pages.values());
582 }
583
584 public WikiPage getPage(long nodeId, String title)
585 throws PortalException, SystemException {
586
587 List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
588 nodeId, title, true, 0, 1);
589
590 if (pages.size() > 0) {
591 return pages.get(0);
592 }
593 else {
594 throw new NoSuchPageException();
595 }
596 }
597
598 public WikiPage getPage(long nodeId, String title, double version)
599 throws PortalException, SystemException {
600
601 WikiPage page = null;
602
603 if (version == 0) {
604 page = getPage(nodeId, title);
605 }
606 else {
607 page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
608 }
609
610 return page;
611 }
612
613 public WikiPageDisplay getPageDisplay(
614 long nodeId, String title, PortletURL viewPageURL,
615 PortletURL editPageURL, String attachmentURLPrefix)
616 throws PortalException, SystemException {
617
618 WikiPage page = getPage(nodeId, title);
619
620 String formattedContent = WikiUtil.convert(
621 page, viewPageURL, editPageURL, attachmentURLPrefix);
622
623 return new WikiPageDisplayImpl(
624 page.getUserId(), page.getNodeId(), page.getTitle(),
625 page.getVersion(), page.getContent(), formattedContent,
626 page.getFormat(), page.getHead(), page.getAttachmentsFiles());
627 }
628
629 public List<WikiPage> getPages(long nodeId, int start, int end)
630 throws SystemException {
631
632 return wikiPagePersistence.findByNodeId(
633 nodeId, start, end, new PageCreateDateComparator(false));
634 }
635
636 public List<WikiPage> getPages(String format) throws SystemException {
637 return wikiPagePersistence.findByFormat(format);
638 }
639
640 public List<WikiPage> getPages(
641 long nodeId, String title, int start, int end)
642 throws SystemException {
643
644 return wikiPagePersistence.findByN_T(
645 nodeId, title, start, end, new PageCreateDateComparator(false));
646 }
647
648 public List<WikiPage> getPages(
649 long nodeId, String title, int start, int end,
650 OrderByComparator obc)
651 throws SystemException {
652
653 return wikiPagePersistence.findByN_T(nodeId, title, start, end, obc);
654 }
655
656 public List<WikiPage> getPages(
657 long nodeId, boolean head, int start, int end)
658 throws SystemException {
659
660 return wikiPagePersistence.findByN_H(
661 nodeId, head, start, end, new PageCreateDateComparator(false));
662 }
663
664 public List<WikiPage> getPages(
665 long nodeId, String title, boolean head, int start, int end)
666 throws SystemException {
667
668 return wikiPagePersistence.findByN_T_H(
669 nodeId, title, head, start, end,
670 new PageCreateDateComparator(false));
671 }
672
673 public int getPagesCount(long nodeId) throws SystemException {
674 return wikiPagePersistence.countByNodeId(nodeId);
675 }
676
677 public int getPagesCount(long nodeId, String title)
678 throws SystemException {
679
680 return wikiPagePersistence.countByN_T(nodeId, title);
681 }
682
683 public int getPagesCount(long nodeId, boolean head)
684 throws SystemException {
685
686 return wikiPagePersistence.countByN_H(nodeId, head);
687 }
688
689 public int getPagesCount(long nodeId, String title, boolean head)
690 throws SystemException {
691
692 return wikiPagePersistence.countByN_T_H(nodeId, title, head);
693 }
694
695 public List<WikiPage> getRecentChanges(long nodeId, int start, int end)
696 throws SystemException {
697
698 Calendar cal = CalendarFactoryUtil.getCalendar();
699
700 cal.add(Calendar.WEEK_OF_YEAR, -1);
701
702 return wikiPageFinder.findByCreateDate(
703 nodeId, cal.getTime(), false, start, end);
704 }
705
706 public int getRecentChangesCount(long nodeId) throws SystemException {
707 Calendar cal = CalendarFactoryUtil.getCalendar();
708
709 cal.add(Calendar.WEEK_OF_YEAR, -1);
710
711 return wikiPageFinder.countByCreateDate(nodeId, cal.getTime(), false);
712 }
713
714 public void movePage(
715 long userId, long nodeId, String title, String newTitle,
716 PortletPreferences prefs, ThemeDisplay themeDisplay)
717 throws PortalException, SystemException {
718
719 movePage(userId, nodeId, title, newTitle, true, prefs, themeDisplay);
720 }
721
722 public void movePage(
723 long userId, long nodeId, String title, String newTitle,
724 boolean strict, PortletPreferences prefs, ThemeDisplay themeDisplay)
725 throws PortalException, SystemException {
726
727 validateTitle(newTitle);
728
729
731 if (isUsedTitle(nodeId, newTitle)) {
732 WikiPage page = getPage(nodeId, newTitle);
733
734
736 if (((page.getVersion() == WikiPageImpl.DEFAULT_VERSION) &&
737 (page.getContent().equals(WikiPageImpl.MOVED))) ||
738 !strict) {
739
740 deletePage(nodeId, newTitle);
741 }
742 else {
743 throw new DuplicatePageException(newTitle);
744 }
745 }
746
747
749 List<WikiPage> pageVersions = wikiPagePersistence.findByN_T(
750 nodeId, title);
751
752 if (pageVersions.size() == 0) {
753 return;
754 }
755
756 for (WikiPage page : pageVersions) {
757 page.setTitle(newTitle);
758
759 wikiPagePersistence.update(page, false);
760 }
761
762
764 List<WikiPage> children = wikiPagePersistence.findByN_P(nodeId, title);
765
766 for (WikiPage page : children) {
767 page.setParentTitle(newTitle);
768
769 wikiPagePersistence.update(page, false);
770 }
771
772 WikiPage page = pageVersions.get(pageVersions.size() - 1);
773
774
776 WikiPageResource wikiPageResource =
777 wikiPageResourcePersistence.findByPrimaryKey(
778 page.getResourcePrimKey());
779
780 wikiPageResource.setTitle(newTitle);
781
782 wikiPageResourcePersistence.update(wikiPageResource, false);
783
784
786 String uuid = null;
787 double version = WikiPageImpl.DEFAULT_VERSION;
788 String format = page.getFormat();
789 boolean head = true;
790 String parentTitle = page.getParentTitle();
791 String redirectTitle = page.getTitle();
792 String content =
793 StringPool.DOUBLE_OPEN_BRACKET + redirectTitle +
794 StringPool.DOUBLE_CLOSE_BRACKET;
795 String summary = WikiPageImpl.MOVED + " to " + title;
796
797 addPage(
798 uuid, userId, nodeId, title, version, content, summary, false,
799 format, head, parentTitle, redirectTitle, null, prefs,
800 themeDisplay);
801
802
804 List<WikiPage> redirectedPages = wikiPagePersistence.findByN_R(
805 nodeId, title);
806
807 for (WikiPage redirectedPage : redirectedPages) {
808 redirectedPage.setRedirectTitle(newTitle);
809
810 wikiPagePersistence.update(redirectedPage, false);
811 }
812
813
815 String[] tagsEntries = tagsEntryLocalService.getEntryNames(
816 WikiPage.class.getName(), page.getResourcePrimKey());
817
818 updateTagsAsset(userId, page, tagsEntries);
819
820
822 try {
823 Indexer.updatePage(
824 page.getCompanyId(), page.getNode().getGroupId(), nodeId,
825 newTitle, content, tagsEntries);
826 }
827 catch (SearchException se) {
828 _log.error("Indexing " + newTitle, se);
829 }
830 }
831
832 public WikiPage revertPage(
833 long userId, long nodeId, String title, double version,
834 PortletPreferences prefs, ThemeDisplay themeDisplay)
835 throws PortalException, SystemException {
836
837 WikiPage oldPage = getPage(nodeId, title, version);
838
839 return updatePage(
840 userId, nodeId, title, 0, oldPage.getContent(),
841 WikiPageImpl.REVERTED + " to " + version, false,
842 oldPage.getFormat(), null, oldPage.getRedirectTitle(), null, prefs,
843 themeDisplay);
844 }
845
846 public void subscribePage(long userId, long nodeId, String title)
847 throws PortalException, SystemException {
848
849 WikiPage page = getPage(nodeId, title);
850
851 subscriptionLocalService.addSubscription(
852 userId, WikiPage.class.getName(), page.getResourcePrimKey());
853 }
854
855 public void unsubscribePage(long userId, long nodeId, String title)
856 throws PortalException, SystemException {
857
858 WikiPage page = getPage(nodeId, title);
859
860 subscriptionLocalService.deleteSubscription(
861 userId, WikiPage.class.getName(), page.getResourcePrimKey());
862 }
863
864 public WikiPage updatePage(
865 long userId, long nodeId, String title, double version,
866 String content, String summary, boolean minorEdit, String format,
867 String parentTitle, String redirectTitle, String[] tagsEntries,
868 PortletPreferences prefs, ThemeDisplay themeDisplay)
869 throws PortalException, SystemException {
870
871
873 User user = userPersistence.findByPrimaryKey(userId);
874 Date now = new Date();
875
876 validate(nodeId, content, format);
877
878 WikiPage page = null;
879
880 try {
881 page = getPage(nodeId, title);
882 }
883 catch (NoSuchPageException nspe) {
884 return addPage(
885 null, userId, nodeId, title, WikiPageImpl.DEFAULT_VERSION,
886 content, summary, minorEdit, format, true, parentTitle,
887 redirectTitle, tagsEntries, prefs, themeDisplay);
888 }
889
890 double oldVersion = page.getVersion();
891
892 if ((version > 0) && (version != oldVersion)) {
893 throw new PageVersionException();
894 }
895
896 long resourcePrimKey = page.getResourcePrimKey();
897
898 page.setHead(false);
899 page.setModifiedDate(now);
900
901 wikiPagePersistence.update(page, false);
902
903 double newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
904
905 long pageId = counterLocalService.increment();
906
907 page = wikiPagePersistence.create(pageId);
908
909 page.setResourcePrimKey(resourcePrimKey);
910 page.setCompanyId(user.getCompanyId());
911 page.setUserId(user.getUserId());
912 page.setUserName(user.getFullName());
913 page.setCreateDate(now);
914 page.setModifiedDate(now);
915 page.setNodeId(nodeId);
916 page.setTitle(title);
917 page.setVersion(newVersion);
918 page.setMinorEdit(minorEdit);
919 page.setContent(content);
920 page.setSummary(summary);
921 page.setFormat(format);
922 page.setHead(true);
923
924 if (Validator.isNotNull(parentTitle)) {
925 page.setParentTitle(parentTitle);
926 }
927
928 if (Validator.isNotNull(redirectTitle)) {
929 page.setRedirectTitle(redirectTitle);
930 }
931
932 wikiPagePersistence.update(page, false);
933
934
936 WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
937
938 node.setLastPostDate(now);
939
940 wikiNodePersistence.update(node, false);
941
942
944 socialActivityLocalService.addActivity(
945 userId, node.getGroupId(), WikiPage.class.getName(),
946 page.getResourcePrimKey(), WikiActivityKeys.UPDATE_PAGE,
947 StringPool.BLANK, 0);
948
949
951 if (!minorEdit && NotificationThreadLocal.isNotificationEnabled()) {
952 notifySubscribers(node, page, prefs, themeDisplay, true);
953 }
954
955
957 updateTagsAsset(userId, page, tagsEntries);
958
959
961 try {
962 Indexer.updatePage(
963 node.getCompanyId(), node.getGroupId(), nodeId, title, content,
964 tagsEntries);
965 }
966 catch (SearchException se) {
967 _log.error("Indexing " + page.getPrimaryKey(), se);
968 }
969
970
972 clearPageCache(page);
973
974 return page;
975 }
976
977 public void updateTagsAsset(
978 long userId, WikiPage page, String[] tagsEntries)
979 throws PortalException, SystemException {
980
981 tagsAssetLocalService.updateAsset(
982 userId, page.getNode().getGroupId(), WikiPage.class.getName(),
983 page.getResourcePrimKey(), tagsEntries, null, null, null, null,
984 ContentTypes.TEXT_HTML, page.getTitle(), null, null, null, 0, 0,
985 null, false);
986 }
987
988 public void validateTitle(String title) throws PortalException {
989 if (title.equals("all_pages") || title.equals("orphan_pages") ||
990 title.equals("recent_changes")) {
991
992 throw new PageTitleException(title + " is reserved");
993 }
994
995 if (Validator.isNotNull(PropsValues.WIKI_PAGE_TITLES_REGEXP)) {
996 Pattern pattern = Pattern.compile(
997 PropsValues.WIKI_PAGE_TITLES_REGEXP);
998
999 Matcher matcher = pattern.matcher(title);
1000
1001 if (!matcher.matches()) {
1002 throw new PageTitleException();
1003 }
1004 }
1005 }
1006
1007 protected void clearPageCache(WikiPage page) {
1008 if (!WikiCacheThreadLocal.isClearCache()) {
1009 return;
1010 }
1011
1012 WikiCacheUtil.clearCache(page.getNodeId(), page.getTitle());
1013 }
1014
1015 protected void clearReferralsCache(WikiPage page)
1016 throws PortalException, SystemException {
1017
1018 if (!WikiCacheThreadLocal.isClearCache()) {
1019 return;
1020 }
1021
1022 List<WikiPage> links = getIncomingLinks(
1023 page.getNodeId(), page.getTitle());
1024
1025 for (WikiPage curPage : links) {
1026 WikiCacheUtil.clearCache(curPage.getNodeId(), curPage.getTitle());
1027 }
1028 }
1029
1030 protected boolean isLinkedTo(WikiPage page, String targetTitle)
1031 throws PortalException {
1032
1033 Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
1034
1035 Boolean link = links.get(targetTitle);
1036
1037 if (link != null) {
1038 return true;
1039 }
1040 else {
1041 return false;
1042 }
1043 }
1044
1045 protected boolean isUsedTitle(long nodeId, String title)
1046 throws SystemException {
1047
1048 if (getPagesCount(nodeId, title, true) > 0) {
1049 return true;
1050 }
1051 else {
1052 return false;
1053 }
1054 }
1055
1056 protected void notifySubscribers(
1057 WikiNode node, WikiPage page, PortletPreferences prefs,
1058 ThemeDisplay themeDisplay, boolean update)
1059 throws PortalException, SystemException {
1060
1061 if (prefs == null) {
1062 long ownerId = node.getGroupId();
1063 int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
1064 long plid = PortletKeys.PREFS_PLID_SHARED;
1065 String portletId = PortletKeys.WIKI;
1066 String defaultPreferences = null;
1067
1068 prefs = portletPreferencesLocalService.getPreferences(
1069 node.getCompanyId(), ownerId, ownerType, plid, portletId,
1070 defaultPreferences);
1071 }
1072
1073 if (!update && WikiUtil.getEmailPageAddedEnabled(prefs)) {
1074 }
1075 else if (update && WikiUtil.getEmailPageUpdatedEnabled(prefs)) {
1076 }
1077 else {
1078 return;
1079 }
1080
1081 Company company = companyPersistence.findByPrimaryKey(
1082 page.getCompanyId());
1083
1084 Group group = groupPersistence.findByPrimaryKey(node.getGroupId());
1085
1086 User user = userPersistence.findByPrimaryKey(page.getUserId());
1087
1088 String pageURL = StringPool.BLANK;
1089
1090 if (themeDisplay != null) {
1091 String portalURL = PortalUtil.getPortalURL(themeDisplay);
1092 String layoutURL = PortalUtil.getLayoutURL(themeDisplay);
1093
1094 pageURL =
1095 portalURL + layoutURL + "/wiki/" + node.getNodeId() + "/" +
1096 page.getTitle();
1097 }
1098
1099 String portletName = PortalUtil.getPortletTitle(
1100 PortletKeys.WIKI, user);
1101
1102 String fromName = WikiUtil.getEmailFromName(prefs);
1103 String fromAddress = WikiUtil.getEmailFromAddress(prefs);
1104
1105 String replyToAddress = fromAddress;
1106 String mailId = WikiUtil.getMailId(
1107 company.getMx(), page.getNodeId(), page.getPageId());
1108
1109 fromName = StringUtil.replace(
1110 fromName,
1111 new String[] {
1112 "[$COMPANY_ID$]",
1113 "[$COMPANY_MX$]",
1114 "[$COMPANY_NAME$]",
1115 "[$COMMUNITY_NAME$]",
1116 "[$PAGE_USER_ADDRESS$]",
1117 "[$PAGE_USER_NAME$]",
1118 "[$PORTLET_NAME$]"
1119 },
1120 new String[] {
1121 String.valueOf(company.getCompanyId()),
1122 company.getMx(),
1123 company.getName(),
1124 group.getName(),
1125 user.getEmailAddress(),
1126 user.getFullName(),
1127 portletName
1128 });
1129
1130 fromAddress = StringUtil.replace(
1131 fromAddress,
1132 new String[] {
1133 "[$COMPANY_ID$]",
1134 "[$COMPANY_MX$]",
1135 "[$COMPANY_NAME$]",
1136 "[$COMMUNITY_NAME$]",
1137 "[$PAGE_USER_ADDRESS$]",
1138 "[$PAGE_USER_NAME$]",
1139 "[$PORTLET_NAME$]"
1140 },
1141 new String[] {
1142 String.valueOf(company.getCompanyId()),
1143 company.getMx(),
1144 company.getName(),
1145 group.getName(),
1146 user.getEmailAddress(),
1147 user.getFullName(),
1148 portletName
1149 });
1150
1151 String subjectPrefix = null;
1152 String body = null;
1153 String signature = null;
1154
1155 if (update) {
1156 subjectPrefix = WikiUtil.getEmailPageUpdatedSubjectPrefix(prefs);
1157 body = WikiUtil.getEmailPageUpdatedBody(prefs);
1158 signature = WikiUtil.getEmailPageUpdatedSignature(prefs);
1159 }
1160 else {
1161 subjectPrefix = WikiUtil.getEmailPageAddedSubjectPrefix(prefs);
1162 body = WikiUtil.getEmailPageAddedBody(prefs);
1163 signature = WikiUtil.getEmailPageAddedSignature(prefs);
1164 }
1165
1166 if (Validator.isNotNull(signature)) {
1167 body += "\n--\n" + signature;
1168 }
1169
1170 subjectPrefix = StringUtil.replace(
1171 subjectPrefix,
1172 new String[] {
1173 "[$COMPANY_ID$]",
1174 "[$COMPANY_MX$]",
1175 "[$COMPANY_NAME$]",
1176 "[$COMMUNITY_NAME$]",
1177 "[$FROM_ADDRESS$]",
1178 "[$FROM_NAME$]",
1179 "[$NODE_NAME$]",
1180 "[$PAGE_CONTENT$]",
1181 "[$PAGE_ID$]",
1182 "[$PAGE_TITLE$]",
1183 "[$PAGE_USER_ADDRESS$]",
1184 "[$PAGE_USER_NAME$]",
1185 "[$PORTAL_URL$]",
1186 "[$PORTLET_NAME$]"
1187 },
1188 new String[] {
1189 String.valueOf(company.getCompanyId()),
1190 company.getMx(),
1191 company.getName(),
1192 group.getName(),
1193 fromAddress,
1194 fromName,
1195 node.getName(),
1196 page.getContent(),
1197 String.valueOf(page.getPageId()),
1198 page.getTitle(),
1199 user.getEmailAddress(),
1200 user.getFullName(),
1201 company.getVirtualHost(),
1202 portletName
1203 });
1204
1205 body = StringUtil.replace(
1206 body,
1207 new String[] {
1208 "[$COMPANY_ID$]",
1209 "[$COMPANY_MX$]",
1210 "[$COMPANY_NAME$]",
1211 "[$COMMUNITY_NAME$]",
1212 "[$FROM_ADDRESS$]",
1213 "[$FROM_NAME$]",
1214 "[$NODE_NAME$]",
1215 "[$PAGE_CONTENT$]",
1216 "[$PAGE_ID$]",
1217 "[$PAGE_TITLE$]",
1218 "[$PAGE_URL$]",
1219 "[$PAGE_USER_ADDRESS$]",
1220 "[$PAGE_USER_NAME$]",
1221 "[$PORTAL_URL$]",
1222 "[$PORTLET_NAME$]"
1223 },
1224 new String[] {
1225 String.valueOf(company.getCompanyId()),
1226 company.getMx(),
1227 company.getName(),
1228 group.getName(),
1229 fromAddress,
1230 fromName,
1231 node.getName(),
1232 page.getContent(),
1233 String.valueOf(page.getPageId()),
1234 page.getTitle(),
1235 pageURL,
1236 user.getEmailAddress(),
1237 user.getFullName(),
1238 company.getVirtualHost(),
1239 portletName
1240 });
1241
1242 String subject = page.getTitle();
1243
1244 if (subject.indexOf(subjectPrefix) == -1) {
1245 subject = subjectPrefix + subject;
1246 }
1247
1248 Message message = new Message();
1249
1250 message.put("companyId", node.getCompanyId());
1251 message.put("userId", node.getUserId());
1252 message.put("nodeId", node.getNodeId());
1253 message.put("pageResourcePrimKey", page.getResourcePrimKey());
1254 message.put("fromName", fromName);
1255 message.put("fromAddress", fromAddress);
1256 message.put("subject", subject);
1257 message.put("body", body);
1258 message.put("replyToAddress", replyToAddress);
1259 message.put("mailId", mailId);
1260
1261 MessageBusUtil.sendMessage(DestinationNames.WIKI, message);
1262 }
1263
1264 protected void validate(long nodeId, String content, String format)
1265 throws PortalException {
1266
1267 if (!WikiUtil.validate(nodeId, content, format)) {
1268 throw new PageContentException();
1269 }
1270 }
1271
1272 protected void validate(
1273 String title, long nodeId, String content, String format)
1274 throws PortalException {
1275
1276 if (Validator.isNull(title)) {
1277 throw new PageTitleException();
1278 }
1279
1280 validateTitle(title);
1281
1282 validate(nodeId, content, format);
1283 }
1284
1285 private static Log _log = LogFactory.getLog(WikiPageLocalServiceImpl.class);
1286
1287}