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