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