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