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