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