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.HttpUtil;
38 import com.liferay.portal.kernel.util.ListUtil;
39 import com.liferay.portal.kernel.util.NotificationThreadLocal;
40 import com.liferay.portal.kernel.util.ObjectValuePair;
41 import com.liferay.portal.kernel.util.OrderByComparator;
42 import com.liferay.portal.kernel.util.StringPool;
43 import com.liferay.portal.kernel.util.StringUtil;
44 import com.liferay.portal.kernel.util.Validator;
45 import com.liferay.portal.model.Company;
46 import com.liferay.portal.model.CompanyConstants;
47 import com.liferay.portal.model.Group;
48 import com.liferay.portal.model.GroupConstants;
49 import com.liferay.portal.model.ResourceConstants;
50 import com.liferay.portal.model.User;
51 import com.liferay.portal.theme.ThemeDisplay;
52 import com.liferay.portal.util.PortalUtil;
53 import com.liferay.portal.util.PortletKeys;
54 import com.liferay.portal.util.PropsValues;
55 import com.liferay.portlet.wiki.DuplicatePageException;
56 import com.liferay.portlet.wiki.NoSuchPageException;
57 import com.liferay.portlet.wiki.PageContentException;
58 import com.liferay.portlet.wiki.PageTitleException;
59 import com.liferay.portlet.wiki.PageVersionException;
60 import com.liferay.portlet.wiki.model.WikiNode;
61 import com.liferay.portlet.wiki.model.WikiPage;
62 import com.liferay.portlet.wiki.model.WikiPageDisplay;
63 import com.liferay.portlet.wiki.model.WikiPageResource;
64 import com.liferay.portlet.wiki.model.impl.WikiPageDisplayImpl;
65 import com.liferay.portlet.wiki.model.impl.WikiPageImpl;
66 import com.liferay.portlet.wiki.service.base.WikiPageLocalServiceBaseImpl;
67 import com.liferay.portlet.wiki.social.WikiActivityKeys;
68 import com.liferay.portlet.wiki.util.Indexer;
69 import com.liferay.portlet.wiki.util.WikiCacheThreadLocal;
70 import com.liferay.portlet.wiki.util.WikiCacheUtil;
71 import com.liferay.portlet.wiki.util.WikiUtil;
72 import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
73 import com.liferay.util.MathUtil;
74 import com.liferay.util.UniqueList;
75
76 import java.rmi.RemoteException;
77
78 import java.util.ArrayList;
79 import java.util.Calendar;
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 return ListUtil.sort(links);
506 }
507
508 public List<WikiPage> getNoAssetPages() throws SystemException {
509 return wikiPageFinder.findByNoAssets();
510 }
511
512 public List<WikiPage> getOrphans(long nodeId)
513 throws PortalException, SystemException {
514
515 List<Map<String, Boolean>> pageTitles =
516 new ArrayList<Map<String, Boolean>>();
517
518 List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
519
520 for (WikiPage page : pages) {
521 pageTitles.add(WikiCacheUtil.getOutgoingLinks(page));
522 }
523
524 Set<WikiPage> notOrphans = new HashSet<WikiPage>();
525
526 for (WikiPage page : pages) {
527 for (Map<String, Boolean> pageTitle : pageTitles) {
528 if (pageTitle.get(page.getTitle()) != null) {
529 notOrphans.add(page);
530
531 break;
532 }
533 }
534 }
535
536 List<WikiPage> orphans = new ArrayList<WikiPage>();
537
538 for (WikiPage page : pages) {
539 if (!notOrphans.contains(page)) {
540 orphans.add(page);
541 }
542 }
543
544 orphans = ListUtil.sort(orphans);
545
546 return orphans;
547 }
548
549 public List<WikiPage> getOutgoingLinks(long nodeId, String title)
550 throws PortalException, SystemException {
551
552 WikiPage page = getPage(nodeId, title);
553
554 Map<String, WikiPage> pages = new LinkedHashMap<String, WikiPage>();
555
556 Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
557
558 for (String curTitle : links.keySet()) {
559 Boolean exists = links.get(curTitle);
560
561 if (exists) {
562 if (!pages.containsKey(curTitle)) {
563 pages.put(curTitle, getPage(nodeId, curTitle));
564 }
565 }
566 else {
567 WikiPageImpl newPage = new WikiPageImpl();
568
569 newPage.setNew(true);
570 newPage.setNodeId(nodeId);
571 newPage.setTitle(curTitle);
572
573 if (!pages.containsKey(curTitle)) {
574 pages.put(curTitle, newPage);
575 }
576 }
577 }
578
579 return ListUtil.fromCollection(pages.values());
580 }
581
582 public WikiPage getPage(long nodeId, String title)
583 throws PortalException, SystemException {
584
585 List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
586 nodeId, title, true, 0, 1);
587
588 if (pages.size() > 0) {
589 return pages.get(0);
590 }
591 else {
592 throw new NoSuchPageException();
593 }
594 }
595
596 public WikiPage getPage(long nodeId, String title, double version)
597 throws PortalException, SystemException {
598
599 WikiPage page = null;
600
601 if (version == 0) {
602 page = getPage(nodeId, title);
603 }
604 else {
605 page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
606 }
607
608 return page;
609 }
610
611 public WikiPageDisplay getPageDisplay(
612 long nodeId, String title, PortletURL viewPageURL,
613 PortletURL editPageURL, String attachmentURLPrefix)
614 throws PortalException, SystemException {
615
616 WikiPage page = getPage(nodeId, title);
617
618 String formattedContent = WikiUtil.convert(
619 page, viewPageURL, editPageURL, attachmentURLPrefix);
620
621 return new WikiPageDisplayImpl(
622 page.getUserId(), page.getNodeId(), page.getTitle(),
623 page.getVersion(), page.getContent(), formattedContent,
624 page.getFormat(), page.getHead(), page.getAttachmentsFiles());
625 }
626
627 public List<WikiPage> getPages(long nodeId, int start, int end)
628 throws SystemException {
629
630 return wikiPagePersistence.findByNodeId(
631 nodeId, start, end, new PageCreateDateComparator(false));
632 }
633
634 public List<WikiPage> getPages(String format) throws SystemException {
635 return wikiPagePersistence.findByFormat(format);
636 }
637
638 public List<WikiPage> getPages(
639 long nodeId, String title, int start, int end)
640 throws SystemException {
641
642 return wikiPagePersistence.findByN_T(
643 nodeId, title, start, end, new PageCreateDateComparator(false));
644 }
645
646 public List<WikiPage> getPages(
647 long nodeId, String title, int start, int end,
648 OrderByComparator obc)
649 throws SystemException {
650
651 return wikiPagePersistence.findByN_T(nodeId, title, start, end, obc);
652 }
653
654 public List<WikiPage> getPages(
655 long nodeId, boolean head, int start, int end)
656 throws SystemException {
657
658 return wikiPagePersistence.findByN_H(
659 nodeId, head, start, end, new PageCreateDateComparator(false));
660 }
661
662 public List<WikiPage> getPages(
663 long nodeId, String title, boolean head, int start, int end)
664 throws SystemException {
665
666 return wikiPagePersistence.findByN_T_H(
667 nodeId, title, head, start, end,
668 new PageCreateDateComparator(false));
669 }
670
671 public int getPagesCount(long nodeId) throws SystemException {
672 return wikiPagePersistence.countByNodeId(nodeId);
673 }
674
675 public int getPagesCount(long nodeId, String title)
676 throws SystemException {
677
678 return wikiPagePersistence.countByN_T(nodeId, title);
679 }
680
681 public int getPagesCount(long nodeId, boolean head)
682 throws SystemException {
683
684 return wikiPagePersistence.countByN_H(nodeId, head);
685 }
686
687 public int getPagesCount(long nodeId, String title, boolean head)
688 throws SystemException {
689
690 return wikiPagePersistence.countByN_T_H(nodeId, title, head);
691 }
692
693 public List<WikiPage> getRecentChanges(long nodeId, int start, int end)
694 throws SystemException {
695
696 Calendar cal = CalendarFactoryUtil.getCalendar();
697
698 cal.add(Calendar.WEEK_OF_YEAR, -1);
699
700 return wikiPageFinder.findByCreateDate(
701 nodeId, cal.getTime(), false, start, end);
702 }
703
704 public int getRecentChangesCount(long nodeId) throws SystemException {
705 Calendar cal = CalendarFactoryUtil.getCalendar();
706
707 cal.add(Calendar.WEEK_OF_YEAR, -1);
708
709 return wikiPageFinder.countByCreateDate(nodeId, cal.getTime(), false);
710 }
711
712 public void movePage(
713 long userId, long nodeId, String title, String newTitle,
714 PortletPreferences prefs, ThemeDisplay themeDisplay)
715 throws PortalException, SystemException {
716
717 movePage(userId, nodeId, title, newTitle, true, prefs, themeDisplay);
718 }
719
720 public void movePage(
721 long userId, long nodeId, String title, String newTitle,
722 boolean strict, PortletPreferences prefs, ThemeDisplay themeDisplay)
723 throws PortalException, SystemException {
724
725 validateTitle(newTitle);
726
727
729 if (isUsedTitle(nodeId, newTitle)) {
730 WikiPage page = getPage(nodeId, newTitle);
731
732
734 if (((page.getVersion() == WikiPageImpl.DEFAULT_VERSION) &&
735 (page.getContent().length() < 200)) ||
736 !strict) {
737
738 deletePage(nodeId, newTitle);
739 }
740 else {
741 throw new DuplicatePageException(newTitle);
742 }
743 }
744
745
747 List<WikiPage> pageVersions = wikiPagePersistence.findByN_T(
748 nodeId, title);
749
750 if (pageVersions.size() == 0) {
751 return;
752 }
753
754 for (WikiPage page : pageVersions) {
755 page.setTitle(newTitle);
756
757 wikiPagePersistence.update(page, false);
758 }
759
760
762 List<WikiPage> children = wikiPagePersistence.findByN_P(nodeId, title);
763
764 for (WikiPage page : children) {
765 page.setParentTitle(newTitle);
766
767 wikiPagePersistence.update(page, false);
768 }
769
770 WikiPage page = pageVersions.get(pageVersions.size() - 1);
771
772
774 WikiPageResource wikiPageResource =
775 wikiPageResourcePersistence.findByPrimaryKey(
776 page.getResourcePrimKey());
777
778 wikiPageResource.setTitle(newTitle);
779
780 wikiPageResourcePersistence.update(wikiPageResource, false);
781
782
784 String uuid = null;
785 double version = WikiPageImpl.DEFAULT_VERSION;
786 String format = page.getFormat();
787 boolean head = true;
788 String parentTitle = page.getParentTitle();
789 String redirectTitle = page.getTitle();
790 String content =
791 StringPool.DOUBLE_OPEN_BRACKET + redirectTitle +
792 StringPool.DOUBLE_CLOSE_BRACKET;
793 String summary = WikiPageImpl.MOVED + " to " + title;
794
795 addPage(
796 uuid, userId, nodeId, title, version, content, summary, false,
797 format, head, parentTitle, redirectTitle, null, prefs,
798 themeDisplay);
799
800
802 List<WikiPage> redirectedPages = wikiPagePersistence.findByN_R(
803 nodeId, title);
804
805 for (WikiPage redirectedPage : redirectedPages) {
806 redirectedPage.setRedirectTitle(newTitle);
807
808 wikiPagePersistence.update(redirectedPage, false);
809 }
810
811
813 String[] tagsEntries = tagsEntryLocalService.getEntryNames(
814 WikiPage.class.getName(), page.getResourcePrimKey());
815
816 updateTagsAsset(userId, page, tagsEntries);
817
818
820 try {
821 Indexer.updatePage(
822 page.getCompanyId(), page.getNode().getGroupId(), nodeId,
823 newTitle, content, tagsEntries);
824 }
825 catch (SearchException se) {
826 _log.error("Indexing " + newTitle, se);
827 }
828 }
829
830 public WikiPage revertPage(
831 long userId, long nodeId, String title, double version,
832 PortletPreferences prefs, ThemeDisplay themeDisplay)
833 throws PortalException, SystemException {
834
835 WikiPage oldPage = getPage(nodeId, title, version);
836
837 return updatePage(
838 userId, nodeId, title, 0, oldPage.getContent(),
839 WikiPageImpl.REVERTED + " to " + version, false,
840 oldPage.getFormat(), null, oldPage.getRedirectTitle(), null, prefs,
841 themeDisplay);
842 }
843
844 public void subscribePage(long userId, long nodeId, String title)
845 throws PortalException, SystemException {
846
847 WikiPage page = getPage(nodeId, title);
848
849 subscriptionLocalService.addSubscription(
850 userId, WikiPage.class.getName(), page.getResourcePrimKey());
851 }
852
853 public void unsubscribePage(long userId, long nodeId, String title)
854 throws PortalException, SystemException {
855
856 WikiPage page = getPage(nodeId, title);
857
858 subscriptionLocalService.deleteSubscription(
859 userId, WikiPage.class.getName(), page.getResourcePrimKey());
860 }
861
862 public WikiPage updatePage(
863 long userId, long nodeId, String title, double version,
864 String content, String summary, boolean minorEdit, String format,
865 String parentTitle, String redirectTitle, String[] tagsEntries,
866 PortletPreferences prefs, ThemeDisplay themeDisplay)
867 throws PortalException, SystemException {
868
869
871 User user = userPersistence.findByPrimaryKey(userId);
872 Date now = new Date();
873
874 validate(nodeId, content, format);
875
876 WikiPage page = null;
877
878 try {
879 page = getPage(nodeId, title);
880 }
881 catch (NoSuchPageException nspe) {
882 return addPage(
883 null, userId, nodeId, title, WikiPageImpl.DEFAULT_VERSION,
884 content, summary, minorEdit, format, true, parentTitle,
885 redirectTitle, tagsEntries, prefs, themeDisplay);
886 }
887
888 double oldVersion = page.getVersion();
889
890 if ((version > 0) && (version != oldVersion)) {
891 throw new PageVersionException();
892 }
893
894 long resourcePrimKey = page.getResourcePrimKey();
895
896 page.setHead(false);
897 page.setModifiedDate(now);
898
899 wikiPagePersistence.update(page, false);
900
901 double newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
902
903 long pageId = counterLocalService.increment();
904
905 page = wikiPagePersistence.create(pageId);
906
907 page.setResourcePrimKey(resourcePrimKey);
908 page.setCompanyId(user.getCompanyId());
909 page.setUserId(user.getUserId());
910 page.setUserName(user.getFullName());
911 page.setCreateDate(now);
912 page.setModifiedDate(now);
913 page.setNodeId(nodeId);
914 page.setTitle(title);
915 page.setVersion(newVersion);
916 page.setMinorEdit(minorEdit);
917 page.setContent(content);
918 page.setSummary(summary);
919 page.setFormat(format);
920 page.setHead(true);
921
922 if (Validator.isNotNull(parentTitle)) {
923 page.setParentTitle(parentTitle);
924 }
925
926 if (Validator.isNotNull(redirectTitle)) {
927 page.setRedirectTitle(redirectTitle);
928 }
929
930 wikiPagePersistence.update(page, false);
931
932
934 WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
935
936 node.setLastPostDate(now);
937
938 wikiNodePersistence.update(node, false);
939
940
942 socialActivityLocalService.addActivity(
943 userId, node.getGroupId(), WikiPage.class.getName(),
944 page.getResourcePrimKey(), WikiActivityKeys.UPDATE_PAGE,
945 StringPool.BLANK, 0);
946
947
949 if (!minorEdit && NotificationThreadLocal.isNotificationEnabled()) {
950 notifySubscribers(node, page, prefs, themeDisplay, true);
951 }
952
953
955 updateTagsAsset(userId, page, tagsEntries);
956
957
959 try {
960 Indexer.updatePage(
961 node.getCompanyId(), node.getGroupId(), nodeId, title, content,
962 tagsEntries);
963 }
964 catch (SearchException se) {
965 _log.error("Indexing " + page.getPrimaryKey(), se);
966 }
967
968
970 clearPageCache(page);
971
972 return page;
973 }
974
975 public void updateTagsAsset(
976 long userId, WikiPage page, String[] tagsEntries)
977 throws PortalException, SystemException {
978
979 tagsAssetLocalService.updateAsset(
980 userId, page.getNode().getGroupId(), WikiPage.class.getName(),
981 page.getResourcePrimKey(), tagsEntries, null, null, null, null,
982 ContentTypes.TEXT_HTML, page.getTitle(), null, null, null, 0, 0,
983 null, false);
984 }
985
986 public void validateTitle(String title) throws PortalException {
987 if (title.equals("all_pages") || title.equals("orphan_pages") ||
988 title.equals("recent_changes")) {
989
990 throw new PageTitleException(title + " is reserved");
991 }
992
993 if (Validator.isNotNull(PropsValues.WIKI_PAGE_TITLES_REGEXP)) {
994 Pattern pattern = Pattern.compile(
995 PropsValues.WIKI_PAGE_TITLES_REGEXP);
996
997 Matcher matcher = pattern.matcher(title);
998
999 if (!matcher.matches()) {
1000 throw new PageTitleException();
1001 }
1002 }
1003 }
1004
1005 protected void clearPageCache(WikiPage page) {
1006 if (!WikiCacheThreadLocal.isClearCache()) {
1007 return;
1008 }
1009
1010 WikiCacheUtil.clearCache(page.getNodeId(), page.getTitle());
1011 }
1012
1013 protected void clearReferralsCache(WikiPage page)
1014 throws PortalException, SystemException {
1015
1016 if (!WikiCacheThreadLocal.isClearCache()) {
1017 return;
1018 }
1019
1020 List<WikiPage> links = getIncomingLinks(
1021 page.getNodeId(), page.getTitle());
1022
1023 for (WikiPage curPage : links) {
1024 WikiCacheUtil.clearCache(curPage.getNodeId(), curPage.getTitle());
1025 }
1026 }
1027
1028 protected boolean isLinkedTo(WikiPage page, String targetTitle)
1029 throws PortalException {
1030
1031 Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
1032
1033 Boolean link = links.get(targetTitle);
1034
1035 if (link != null) {
1036 return true;
1037 }
1038 else {
1039 return false;
1040 }
1041 }
1042
1043 protected boolean isUsedTitle(long nodeId, String title)
1044 throws SystemException {
1045
1046 if (getPagesCount(nodeId, title, true) > 0) {
1047 return true;
1048 }
1049 else {
1050 return false;
1051 }
1052 }
1053
1054 protected void notifySubscribers(
1055 WikiNode node, WikiPage page, PortletPreferences prefs,
1056 ThemeDisplay themeDisplay, boolean update)
1057 throws PortalException, SystemException {
1058
1059 if (prefs == null) {
1060 long ownerId = node.getGroupId();
1061 int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
1062 long plid = PortletKeys.PREFS_PLID_SHARED;
1063 String portletId = PortletKeys.WIKI;
1064 String defaultPreferences = null;
1065
1066 prefs = portletPreferencesLocalService.getPreferences(
1067 node.getCompanyId(), ownerId, ownerType, plid, portletId,
1068 defaultPreferences);
1069 }
1070
1071 if (!update && WikiUtil.getEmailPageAddedEnabled(prefs)) {
1072 }
1073 else if (update && WikiUtil.getEmailPageUpdatedEnabled(prefs)) {
1074 }
1075 else {
1076 return;
1077 }
1078
1079 Company company = companyPersistence.findByPrimaryKey(
1080 page.getCompanyId());
1081
1082 Group group = groupPersistence.findByPrimaryKey(node.getGroupId());
1083
1084 User user = userPersistence.findByPrimaryKey(page.getUserId());
1085
1086 String pageURL = StringPool.BLANK;
1087
1088 if (themeDisplay != null) {
1089 String portalURL = PortalUtil.getPortalURL(themeDisplay);
1090 String layoutURL = PortalUtil.getLayoutURL(themeDisplay);
1091
1092 pageURL =
1093 portalURL + layoutURL + "/-/wiki/" + node.getNodeId() + "/" +
1094 HttpUtil.encodeURL(page.getTitle());
1095 }
1096
1097 String portletName = PortalUtil.getPortletTitle(
1098 PortletKeys.WIKI, user);
1099
1100 String fromName = WikiUtil.getEmailFromName(prefs);
1101 String fromAddress = WikiUtil.getEmailFromAddress(prefs);
1102
1103 String replyToAddress = fromAddress;
1104 String mailId = WikiUtil.getMailId(
1105 company.getMx(), page.getNodeId(), page.getPageId());
1106
1107 fromName = StringUtil.replace(
1108 fromName,
1109 new String[] {
1110 "[$COMPANY_ID$]",
1111 "[$COMPANY_MX$]",
1112 "[$COMPANY_NAME$]",
1113 "[$COMMUNITY_NAME$]",
1114 "[$PAGE_USER_ADDRESS$]",
1115 "[$PAGE_USER_NAME$]",
1116 "[$PORTLET_NAME$]"
1117 },
1118 new String[] {
1119 String.valueOf(company.getCompanyId()),
1120 company.getMx(),
1121 company.getName(),
1122 group.getName(),
1123 user.getEmailAddress(),
1124 user.getFullName(),
1125 portletName
1126 });
1127
1128 fromAddress = StringUtil.replace(
1129 fromAddress,
1130 new String[] {
1131 "[$COMPANY_ID$]",
1132 "[$COMPANY_MX$]",
1133 "[$COMPANY_NAME$]",
1134 "[$COMMUNITY_NAME$]",
1135 "[$PAGE_USER_ADDRESS$]",
1136 "[$PAGE_USER_NAME$]",
1137 "[$PORTLET_NAME$]"
1138 },
1139 new String[] {
1140 String.valueOf(company.getCompanyId()),
1141 company.getMx(),
1142 company.getName(),
1143 group.getName(),
1144 user.getEmailAddress(),
1145 user.getFullName(),
1146 portletName
1147 });
1148
1149 String subjectPrefix = null;
1150 String body = null;
1151 String signature = null;
1152
1153 if (update) {
1154 subjectPrefix = WikiUtil.getEmailPageUpdatedSubjectPrefix(prefs);
1155 body = WikiUtil.getEmailPageUpdatedBody(prefs);
1156 signature = WikiUtil.getEmailPageUpdatedSignature(prefs);
1157 }
1158 else {
1159 subjectPrefix = WikiUtil.getEmailPageAddedSubjectPrefix(prefs);
1160 body = WikiUtil.getEmailPageAddedBody(prefs);
1161 signature = WikiUtil.getEmailPageAddedSignature(prefs);
1162 }
1163
1164 if (Validator.isNotNull(signature)) {
1165 body += "\n--\n" + signature;
1166 }
1167
1168 subjectPrefix = StringUtil.replace(
1169 subjectPrefix,
1170 new String[] {
1171 "[$COMPANY_ID$]",
1172 "[$COMPANY_MX$]",
1173 "[$COMPANY_NAME$]",
1174 "[$COMMUNITY_NAME$]",
1175 "[$FROM_ADDRESS$]",
1176 "[$FROM_NAME$]",
1177 "[$NODE_NAME$]",
1178 "[$PAGE_CONTENT$]",
1179 "[$PAGE_ID$]",
1180 "[$PAGE_TITLE$]",
1181 "[$PAGE_USER_ADDRESS$]",
1182 "[$PAGE_USER_NAME$]",
1183 "[$PORTAL_URL$]",
1184 "[$PORTLET_NAME$]"
1185 },
1186 new String[] {
1187 String.valueOf(company.getCompanyId()),
1188 company.getMx(),
1189 company.getName(),
1190 group.getName(),
1191 fromAddress,
1192 fromName,
1193 node.getName(),
1194 page.getContent(),
1195 String.valueOf(page.getPageId()),
1196 page.getTitle(),
1197 user.getEmailAddress(),
1198 user.getFullName(),
1199 company.getVirtualHost(),
1200 portletName
1201 });
1202
1203 body = StringUtil.replace(
1204 body,
1205 new String[] {
1206 "[$COMPANY_ID$]",
1207 "[$COMPANY_MX$]",
1208 "[$COMPANY_NAME$]",
1209 "[$COMMUNITY_NAME$]",
1210 "[$FROM_ADDRESS$]",
1211 "[$FROM_NAME$]",
1212 "[$NODE_NAME$]",
1213 "[$PAGE_CONTENT$]",
1214 "[$PAGE_ID$]",
1215 "[$PAGE_TITLE$]",
1216 "[$PAGE_URL$]",
1217 "[$PAGE_USER_ADDRESS$]",
1218 "[$PAGE_USER_NAME$]",
1219 "[$PORTAL_URL$]",
1220 "[$PORTLET_NAME$]"
1221 },
1222 new String[] {
1223 String.valueOf(company.getCompanyId()),
1224 company.getMx(),
1225 company.getName(),
1226 group.getName(),
1227 fromAddress,
1228 fromName,
1229 node.getName(),
1230 page.getContent(),
1231 String.valueOf(page.getPageId()),
1232 page.getTitle(),
1233 pageURL,
1234 user.getEmailAddress(),
1235 user.getFullName(),
1236 company.getVirtualHost(),
1237 portletName
1238 });
1239
1240 String subject = page.getTitle();
1241
1242 if (subject.indexOf(subjectPrefix) == -1) {
1243 subject = subjectPrefix + subject;
1244 }
1245
1246 Message message = new Message();
1247
1248 message.put("companyId", node.getCompanyId());
1249 message.put("userId", node.getUserId());
1250 message.put("nodeId", node.getNodeId());
1251 message.put("pageResourcePrimKey", page.getResourcePrimKey());
1252 message.put("fromName", fromName);
1253 message.put("fromAddress", fromAddress);
1254 message.put("subject", subject);
1255 message.put("body", body);
1256 message.put("replyToAddress", replyToAddress);
1257 message.put("mailId", mailId);
1258
1259 MessageBusUtil.sendMessage(DestinationNames.WIKI, message);
1260 }
1261
1262 protected void validate(long nodeId, String content, String format)
1263 throws PortalException {
1264
1265 if (!WikiUtil.validate(nodeId, content, format)) {
1266 throw new PageContentException();
1267 }
1268 }
1269
1270 protected void validate(
1271 String title, long nodeId, String content, String format)
1272 throws PortalException {
1273
1274 if (Validator.isNull(title)) {
1275 throw new PageTitleException();
1276 }
1277
1278 validateTitle(title);
1279
1280 validate(nodeId, content, format);
1281 }
1282
1283 private static Log _log = LogFactory.getLog(WikiPageLocalServiceImpl.class);
1284
1285}