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(), page.getPageId());
421
422
424 socialActivityLocalService.deleteActivities(
425 WikiPage.class.getName(), page.getResourcePrimKey());
426
427
429 mbMessageLocalService.deleteDiscussionMessages(
430 WikiPage.class.getName(), page.getResourcePrimKey());
431
432
434 resourceLocalService.deleteResource(
435 page.getCompanyId(), WikiPage.class.getName(),
436 ResourceConstants.SCOPE_INDIVIDUAL, page.getResourcePrimKey());
437
438
440 try {
441 wikiPageResourceLocalService.deletePageResource(
442 page.getNodeId(), page.getTitle());
443 }
444 catch (NoSuchPageResourceException nspre) {
445 }
446
447
449 wikiPagePersistence.removeByN_T(page.getNodeId(), page.getTitle());
450
451
453 wikiPagePersistence.removeByN_R(page.getNodeId(), page.getTitle());
454
455
457 clearPageCache(page);
458 clearReferralsCache(page);
459 }
460
461 public void deletePageAttachment(long nodeId, String title, String fileName)
462 throws PortalException, SystemException {
463
464 if (Validator.isNull(fileName)) {
465 return;
466 }
467
468 WikiPage page = getPage(nodeId, title);
469
470 long companyId = page.getCompanyId();
471 String portletId = CompanyConstants.SYSTEM_STRING;
472 long repositoryId = CompanyConstants.SYSTEM;
473
474 try {
475 dlService.deleteFile(companyId, portletId, repositoryId, fileName);
476 }
477 catch (NoSuchFileException nsfe) {
478 }
479 }
480
481 public void deletePages(long nodeId)
482 throws PortalException, SystemException {
483
484 Iterator<WikiPage> itr = wikiPagePersistence.findByN_H_P(
485 nodeId, true, StringPool.BLANK).iterator();
486
487 while (itr.hasNext()) {
488 WikiPage page = itr.next();
489
490 deletePage(page);
491 }
492 }
493
494 public List<WikiPage> getChildren(
495 long nodeId, boolean head, String parentTitle)
496 throws SystemException {
497
498 return wikiPagePersistence.findByN_H_P(nodeId, head, parentTitle);
499 }
500
501 public List<WikiPage> getIncomingLinks(long nodeId, String title)
502 throws PortalException, SystemException {
503
504 List<WikiPage> links = new UniqueList<WikiPage>();
505
506 List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
507
508 for (WikiPage page : pages) {
509 if (isLinkedTo(page, title)) {
510 links.add(page);
511 }
512 }
513
514 List<WikiPage> referrals = wikiPagePersistence.findByN_R(nodeId, title);
515
516 for (WikiPage referral : referrals) {
517 for (WikiPage page : pages) {
518 if (isLinkedTo(page, referral.getTitle())) {
519 links.add(page);
520 }
521 }
522 }
523
524 return ListUtil.sort(links);
525 }
526
527 public List<WikiPage> getNoAssetPages() throws SystemException {
528 return wikiPageFinder.findByNoAssets();
529 }
530
531 public List<WikiPage> getOrphans(long nodeId)
532 throws PortalException, SystemException {
533
534 List<Map<String, Boolean>> pageTitles =
535 new ArrayList<Map<String, Boolean>>();
536
537 List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
538
539 for (WikiPage page : pages) {
540 pageTitles.add(WikiCacheUtil.getOutgoingLinks(page));
541 }
542
543 Set<WikiPage> notOrphans = new HashSet<WikiPage>();
544
545 for (WikiPage page : pages) {
546 for (Map<String, Boolean> pageTitle : pageTitles) {
547 if (pageTitle.get(page.getTitle().toLowerCase()) != null) {
548 notOrphans.add(page);
549
550 break;
551 }
552 }
553 }
554
555 List<WikiPage> orphans = new ArrayList<WikiPage>();
556
557 for (WikiPage page : pages) {
558 if (!notOrphans.contains(page)) {
559 orphans.add(page);
560 }
561 }
562
563 orphans = ListUtil.sort(orphans);
564
565 return orphans;
566 }
567
568 public List<WikiPage> getOutgoingLinks(long nodeId, String title)
569 throws PortalException, SystemException {
570
571 WikiPage page = getPage(nodeId, title);
572
573 Map<String, WikiPage> pages = new LinkedHashMap<String, WikiPage>();
574
575 Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
576
577 for (String curTitle : links.keySet()) {
578 Boolean exists = links.get(curTitle);
579
580 if (exists) {
581 if (!pages.containsKey(curTitle)) {
582 pages.put(curTitle, getPage(nodeId, curTitle));
583 }
584 }
585 else {
586 WikiPageImpl newPage = new WikiPageImpl();
587
588 newPage.setNew(true);
589 newPage.setNodeId(nodeId);
590 newPage.setTitle(curTitle);
591
592 if (!pages.containsKey(curTitle)) {
593 pages.put(curTitle, newPage);
594 }
595 }
596 }
597
598 return ListUtil.fromCollection(pages.values());
599 }
600
601 public WikiPage getPage(long resourcePrimKey)
602 throws PortalException, SystemException {
603
604 WikiPageResource wikiPageResource =
605 wikiPageResourceLocalService.getPageResource(resourcePrimKey);
606
607 return getPage(
608 wikiPageResource.getNodeId(), wikiPageResource.getTitle());
609 }
610
611 public WikiPage getPage(long nodeId, String title)
612 throws PortalException, SystemException {
613
614 List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
615 nodeId, title, true, 0, 1);
616
617 if (pages.size() > 0) {
618 return pages.get(0);
619 }
620 else {
621 throw new NoSuchPageException();
622 }
623 }
624
625 public WikiPage getPage(long nodeId, String title, double version)
626 throws PortalException, SystemException {
627
628 WikiPage page = null;
629
630 if (version == 0) {
631 page = getPage(nodeId, title);
632 }
633 else {
634 page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
635 }
636
637 return page;
638 }
639
640 public WikiPageDisplay getPageDisplay(
641 long nodeId, String title, PortletURL viewPageURL,
642 PortletURL editPageURL, String attachmentURLPrefix)
643 throws PortalException, SystemException {
644
645 WikiPage page = getPage(nodeId, title);
646
647 String formattedContent = WikiUtil.convert(
648 page, viewPageURL, editPageURL, attachmentURLPrefix);
649
650 return new WikiPageDisplayImpl(
651 page.getUserId(), page.getNodeId(), page.getTitle(),
652 page.getVersion(), page.getContent(), formattedContent,
653 page.getFormat(), page.getHead(), page.getAttachmentsFiles());
654 }
655
656 public List<WikiPage> getPages(long nodeId, int start, int end)
657 throws SystemException {
658
659 return wikiPagePersistence.findByNodeId(
660 nodeId, start, end, new PageCreateDateComparator(false));
661 }
662
663 public List<WikiPage> getPages(String format) throws SystemException {
664 return wikiPagePersistence.findByFormat(format);
665 }
666
667 public List<WikiPage> getPages(
668 long nodeId, String title, int start, int end)
669 throws SystemException {
670
671 return wikiPagePersistence.findByN_T(
672 nodeId, title, start, end, new PageCreateDateComparator(false));
673 }
674
675 public List<WikiPage> getPages(
676 long nodeId, String title, int start, int end,
677 OrderByComparator obc)
678 throws SystemException {
679
680 return wikiPagePersistence.findByN_T(nodeId, title, start, end, obc);
681 }
682
683 public List<WikiPage> getPages(
684 long nodeId, boolean head, int start, int end)
685 throws SystemException {
686
687 return wikiPagePersistence.findByN_H(
688 nodeId, head, start, end, new PageCreateDateComparator(false));
689 }
690
691 public List<WikiPage> getPages(
692 long nodeId, String title, boolean head, int start, int end)
693 throws SystemException {
694
695 return wikiPagePersistence.findByN_T_H(
696 nodeId, title, head, start, end,
697 new PageCreateDateComparator(false));
698 }
699
700 public int getPagesCount(long nodeId) throws SystemException {
701 return wikiPagePersistence.countByNodeId(nodeId);
702 }
703
704 public int getPagesCount(long nodeId, String title)
705 throws SystemException {
706
707 return wikiPagePersistence.countByN_T(nodeId, title);
708 }
709
710 public int getPagesCount(long nodeId, boolean head)
711 throws SystemException {
712
713 return wikiPagePersistence.countByN_H(nodeId, head);
714 }
715
716 public int getPagesCount(long nodeId, String title, boolean head)
717 throws SystemException {
718
719 return wikiPagePersistence.countByN_T_H(nodeId, title, head);
720 }
721
722 public int getPagesCount(String format) throws SystemException {
723 return wikiPagePersistence.countByFormat(format);
724 }
725
726 public List<WikiPage> getRecentChanges(long nodeId, int start, int end)
727 throws SystemException {
728
729 Calendar cal = CalendarFactoryUtil.getCalendar();
730
731 cal.add(Calendar.WEEK_OF_YEAR, -1);
732
733 return wikiPageFinder.findByCreateDate(
734 nodeId, cal.getTime(), false, start, end);
735 }
736
737 public int getRecentChangesCount(long nodeId) throws SystemException {
738 Calendar cal = CalendarFactoryUtil.getCalendar();
739
740 cal.add(Calendar.WEEK_OF_YEAR, -1);
741
742 return wikiPageFinder.countByCreateDate(nodeId, cal.getTime(), false);
743 }
744
745 public void movePage(
746 long userId, long nodeId, String title, String newTitle,
747 ServiceContext serviceContext)
748 throws PortalException, SystemException {
749
750 movePage(userId, nodeId, title, newTitle, true, serviceContext);
751 }
752
753 public void movePage(
754 long userId, long nodeId, String title, String newTitle,
755 boolean strict, ServiceContext serviceContext)
756 throws PortalException, SystemException {
757
758 validateTitle(newTitle);
759
760
762 if (title.equalsIgnoreCase(newTitle)) {
763 throw new DuplicatePageException(newTitle);
764 }
765
766 if (isUsedTitle(nodeId, newTitle)) {
767 WikiPage page = getPage(nodeId, newTitle);
768
769
771 if (((page.getVersion() == WikiPageImpl.DEFAULT_VERSION) &&
772 (page.getContent().length() < 200)) ||
773 !strict) {
774
775 deletePage(nodeId, newTitle);
776 }
777 else {
778 throw new DuplicatePageException(newTitle);
779 }
780 }
781
782
784 List<WikiPage> pageVersions = wikiPagePersistence.findByN_T(
785 nodeId, title);
786
787 if (pageVersions.size() == 0) {
788 return;
789 }
790
791 for (WikiPage page : pageVersions) {
792 page.setTitle(newTitle);
793
794 wikiPagePersistence.update(page, false);
795 }
796
797
799 List<WikiPage> children = wikiPagePersistence.findByN_P(nodeId, title);
800
801 for (WikiPage page : children) {
802 page.setParentTitle(newTitle);
803
804 wikiPagePersistence.update(page, false);
805 }
806
807 WikiPage page = pageVersions.get(pageVersions.size() - 1);
808
809 long resourcePrimKey = page.getResourcePrimKey();
810
811
813 WikiPageResource wikiPageResource =
814 wikiPageResourcePersistence.findByPrimaryKey(resourcePrimKey);
815
816 wikiPageResource.setTitle(newTitle);
817
818 wikiPageResourcePersistence.update(wikiPageResource, false);
819
820
822 String uuid = null;
823 double version = WikiPageImpl.DEFAULT_VERSION;
824 String summary = WikiPageImpl.MOVED + " to " + title;
825 String format = page.getFormat();
826 boolean head = true;
827 String parentTitle = page.getParentTitle();
828 String redirectTitle = page.getTitle();
829 String content =
830 StringPool.DOUBLE_OPEN_BRACKET + redirectTitle +
831 StringPool.DOUBLE_CLOSE_BRACKET;
832
833 addPage(
834 uuid, userId, nodeId, title, version, content, summary, false,
835 format, head, parentTitle, redirectTitle, serviceContext);
836
837
839 List<WikiPage> redirectedPages = wikiPagePersistence.findByN_R(
840 nodeId, title);
841
842 for (WikiPage redirectedPage : redirectedPages) {
843 redirectedPage.setRedirectTitle(newTitle);
844
845 wikiPagePersistence.update(redirectedPage, false);
846 }
847
848
850 String[] tagsCategories = tagsEntryLocalService.getEntryNames(
851 WikiPage.class.getName(), resourcePrimKey,
852 TagsEntryConstants.FOLKSONOMY_CATEGORY);
853 String[] tagsEntries = tagsEntryLocalService.getEntryNames(
854 WikiPage.class.getName(), resourcePrimKey,
855 TagsEntryConstants.FOLKSONOMY_TAG);
856
857 updateTagsAsset(userId, page, tagsCategories, tagsEntries);
858
859
861 try {
862 Indexer.deletePage(page.getCompanyId(), page.getNodeId(), title);
863 }
864 catch (SearchException se) {
865 _log.error("Indexing " + title, se);
866 }
867
868 reIndex(page);
869 }
870
871 public void reIndex(long resourcePrimKey) throws SystemException {
872 if (SearchEngineUtil.isIndexReadOnly()) {
873 return;
874 }
875
876 WikiPage page = null;
877
878 try {
879 page = wikiPageFinder.findByResourcePrimKey(resourcePrimKey);
880 }
881 catch (NoSuchPageException nspe) {
882 return;
883 }
884
885 reIndex(page);
886 }
887
888 public void reIndex(WikiPage page) throws SystemException {
889 if (Validator.isNotNull(page.getRedirectTitle())) {
890 return;
891 }
892
893 long companyId = page.getCompanyId();
894 long groupId = page.getGroupId();
895 long userId = page.getUserId();
896 long resourcePrimKey = page.getResourcePrimKey();
897 long nodeId = page.getNodeId();
898 String title = page.getTitle();
899 String content = page.getContent();
900 Date modifiedDate = page.getModifiedDate();
901
902 String[] tagsCategories = tagsEntryLocalService.getEntryNames(
903 WikiPage.class.getName(), resourcePrimKey,
904 TagsEntryConstants.FOLKSONOMY_CATEGORY);
905 String[] tagsEntries = tagsEntryLocalService.getEntryNames(
906 WikiPage.class.getName(), resourcePrimKey);
907
908 ExpandoBridge expandoBridge = page.getExpandoBridge();
909
910 try {
911 Indexer.updatePage(
912 companyId, groupId, userId, resourcePrimKey, nodeId, title,
913 content, modifiedDate, tagsCategories, tagsEntries,
914 expandoBridge);
915 }
916 catch (SearchException se) {
917 _log.error("Reindexing " + page.getPrimaryKey(), se);
918 }
919 }
920
921 public WikiPage revertPage(
922 long userId, long nodeId, String title, double version,
923 ServiceContext serviceContext)
924 throws PortalException, SystemException {
925
926 WikiPage oldPage = getPage(nodeId, title, version);
927
928 return updatePage(
929 userId, nodeId, title, 0, oldPage.getContent(),
930 WikiPageImpl.REVERTED + " to " + version, false,
931 oldPage.getFormat(), getParentPageTitle(oldPage),
932 oldPage.getRedirectTitle(), serviceContext);
933 }
934
935 public void subscribePage(long userId, long nodeId, String title)
936 throws PortalException, SystemException {
937
938 WikiPage page = getPage(nodeId, title);
939
940 subscriptionLocalService.addSubscription(
941 userId, WikiPage.class.getName(), page.getResourcePrimKey());
942 }
943
944 public void unsubscribePage(long userId, long nodeId, String title)
945 throws PortalException, SystemException {
946
947 WikiPage page = getPage(nodeId, title);
948
949 subscriptionLocalService.deleteSubscription(
950 userId, WikiPage.class.getName(), page.getResourcePrimKey());
951 }
952
953 public WikiPage updatePage(
954 long userId, long nodeId, String title, double version,
955 String content, String summary, boolean minorEdit, String format,
956 String parentTitle, String redirectTitle,
957 ServiceContext serviceContext)
958 throws PortalException, SystemException {
959
960
962 User user = userPersistence.findByPrimaryKey(userId);
963 Date now = new Date();
964
965 validate(nodeId, content, format);
966
967 WikiPage page = null;
968
969 try {
970 page = getPage(nodeId, title);
971 }
972 catch (NoSuchPageException nspe) {
973 return addPage(
974 null, userId, nodeId, title, WikiPageImpl.DEFAULT_VERSION,
975 content, summary, minorEdit, format, true, parentTitle,
976 redirectTitle, serviceContext);
977 }
978
979 double oldVersion = page.getVersion();
980
981 if ((version > 0) && (version != oldVersion)) {
982 throw new PageVersionException();
983 }
984
985 long resourcePrimKey = page.getResourcePrimKey();
986 long groupId = page.getGroupId();
987
988 page.setHead(false);
989 page.setModifiedDate(serviceContext.getModifiedDate(now));
990
991 wikiPagePersistence.update(page, false);
992
993 double newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
994
995 long pageId = counterLocalService.increment();
996
997 page = wikiPagePersistence.create(pageId);
998
999 page.setResourcePrimKey(resourcePrimKey);
1000 page.setGroupId(groupId);
1001 page.setCompanyId(user.getCompanyId());
1002 page.setUserId(user.getUserId());
1003 page.setUserName(user.getFullName());
1004 page.setCreateDate(serviceContext.getModifiedDate(now));
1005 page.setModifiedDate(serviceContext.getModifiedDate(now));
1006 page.setNodeId(nodeId);
1007 page.setTitle(title);
1008 page.setVersion(newVersion);
1009 page.setMinorEdit(minorEdit);
1010 page.setContent(content);
1011 page.setSummary(summary);
1012 page.setFormat(format);
1013 page.setHead(true);
1014
1015 if (Validator.isNotNull(parentTitle)) {
1016 page.setParentTitle(parentTitle);
1017 }
1018
1019 if (Validator.isNotNull(redirectTitle)) {
1020 page.setRedirectTitle(redirectTitle);
1021 }
1022
1023 wikiPagePersistence.update(page, false);
1024
1025
1027 WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
1028
1029 node.setLastPostDate(serviceContext.getModifiedDate(now));
1030
1031 wikiNodePersistence.update(node, false);
1032
1033
1035 socialActivityLocalService.addActivity(
1036 userId, page.getGroupId(), WikiPage.class.getName(),
1037 page.getResourcePrimKey(), WikiActivityKeys.UPDATE_PAGE,
1038 StringPool.BLANK, 0);
1039
1040
1042 if (!minorEdit && NotificationThreadLocal.isEnabled()) {
1043 notifySubscribers(node, page, serviceContext, true);
1044 }
1045
1046
1048 updateTagsAsset(
1049 userId, page, serviceContext.getTagsCategories(),
1050 serviceContext.getTagsEntries());
1051
1052
1054 reIndex(page);
1055
1056
1058 clearPageCache(page);
1059
1060 return page;
1061 }
1062
1063 public void updateTagsAsset(
1064 long userId, WikiPage page, String[] tagsCategories,
1065 String[] tagsEntries)
1066 throws PortalException, SystemException {
1067
1068 tagsAssetLocalService.updateAsset(
1069 userId, page.getGroupId(), WikiPage.class.getName(),
1070 page.getResourcePrimKey(), tagsCategories, tagsEntries, true, null,
1071 null, null, null, ContentTypes.TEXT_HTML, page.getTitle(), null,
1072 null, null, 0, 0, null, false);
1073 }
1074
1075 public void validateTitle(String title) throws PortalException {
1076 if (title.equals("all_pages") || title.equals("orphan_pages") ||
1077 title.equals("recent_changes")) {
1078
1079 throw new PageTitleException(title + " is reserved");
1080 }
1081
1082 if (Validator.isNotNull(PropsValues.WIKI_PAGE_TITLES_REGEXP)) {
1083 Pattern pattern = Pattern.compile(
1084 PropsValues.WIKI_PAGE_TITLES_REGEXP);
1085
1086 Matcher matcher = pattern.matcher(title);
1087
1088 if (!matcher.matches()) {
1089 throw new PageTitleException();
1090 }
1091 }
1092 }
1093
1094 protected void clearPageCache(WikiPage page) {
1095 if (!WikiCacheThreadLocal.isClearCache()) {
1096 return;
1097 }
1098
1099 WikiCacheUtil.clearCache(page.getNodeId(), page.getTitle());
1100 }
1101
1102 protected void clearReferralsCache(WikiPage page)
1103 throws PortalException, SystemException {
1104
1105 if (!WikiCacheThreadLocal.isClearCache()) {
1106 return;
1107 }
1108
1109 List<WikiPage> links = getIncomingLinks(
1110 page.getNodeId(), page.getTitle());
1111
1112 for (WikiPage curPage : links) {
1113 WikiCacheUtil.clearCache(curPage.getNodeId(), curPage.getTitle());
1114 }
1115 }
1116
1117 protected String getParentPageTitle(WikiPage page) {
1118
1119
1121 try {
1122 WikiPage parentPage = getPage(
1123 page.getNodeId(), page.getParentTitle());
1124
1125 return parentPage.getTitle();
1126 }
1127 catch (Exception e) {
1128 return null;
1129 }
1130 }
1131
1132 protected WikiPage getPreviousVersionPage(WikiPage page)
1133 throws PortalException, SystemException {
1134
1135 double previousVersion = MathUtil.format(page.getVersion() - 0.1, 1, 1);
1136
1137 if (previousVersion < 1) {
1138 return null;
1139 }
1140
1141 return getPage(page.getNodeId(), page.getTitle(), previousVersion);
1142 }
1143
1144 protected boolean isLinkedTo(WikiPage page, String targetTitle)
1145 throws PortalException {
1146
1147 Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
1148
1149 Boolean link = links.get(targetTitle.toLowerCase());
1150
1151 if (link != null) {
1152 return true;
1153 }
1154 else {
1155 return false;
1156 }
1157 }
1158
1159 protected boolean isUsedTitle(long nodeId, String title)
1160 throws SystemException {
1161
1162 if (getPagesCount(nodeId, title, true) > 0) {
1163 return true;
1164 }
1165 else {
1166 return false;
1167 }
1168 }
1169
1170 protected void notifySubscribers(
1171 WikiNode node, WikiPage page, ServiceContext serviceContext,
1172 boolean update)
1173 throws PortalException, SystemException {
1174
1175 PortletPreferences preferences =
1176 ServiceContextUtil.getPortletPreferences(serviceContext);
1177
1178 if (preferences == null) {
1179 long ownerId = node.getGroupId();
1180 int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
1181 long plid = PortletKeys.PREFS_PLID_SHARED;
1182 String portletId = PortletKeys.WIKI;
1183 String defaultPreferences = null;
1184
1185 preferences = portletPreferencesLocalService.getPreferences(
1186 node.getCompanyId(), ownerId, ownerType, plid, portletId,
1187 defaultPreferences);
1188 }
1189
1190 if (!update && WikiUtil.getEmailPageAddedEnabled(preferences)) {
1191 }
1192 else if (update && WikiUtil.getEmailPageUpdatedEnabled(preferences)) {
1193 }
1194 else {
1195 return;
1196 }
1197
1198 Company company = companyPersistence.findByPrimaryKey(
1199 page.getCompanyId());
1200
1201 Group group = groupPersistence.findByPrimaryKey(node.getGroupId());
1202
1203 User user = userPersistence.findByPrimaryKey(page.getUserId());
1204
1205 String portalURL = serviceContext.getPortalURL();
1206 String layoutFullURL = serviceContext.getLayoutFullURL();
1207
1208 WikiPage previousVersionPage = getPreviousVersionPage(page);
1209
1210 String attachmentURLPrefix =
1211 portalURL + serviceContext.getPathMain() +
1212 "/wiki/get_page_attachment?p_l_id=" + serviceContext.getPlid() +
1213 "&nodeId=" + page.getNodeId() + "&title=" +
1214 HttpUtil.encodeURL(page.getTitle()) + "&fileName=";
1215
1216 String pageDiffs = StringPool.BLANK;
1217
1218 try {
1219 pageDiffs = WikiUtil.diffHtml(
1220 previousVersionPage, page, null, null, attachmentURLPrefix);
1221 }
1222 catch (Exception e) {
1223 }
1224
1225 String pageContent = null;
1226
1227 if (Validator.equals(page.getFormat(), "creole")) {
1228 pageContent = WikiUtil.convert(
1229 page, null, null, attachmentURLPrefix);
1230 }
1231 else {
1232 pageContent = page.getContent();
1233 pageContent = WikiUtil.processContent(pageContent);
1234 }
1235
1236 String pageURL = StringPool.BLANK;
1237 String diffsURL = StringPool.BLANK;
1238
1239 if (Validator.isNotNull(layoutFullURL)) {
1240 pageURL =
1241 layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "wiki/" +
1242 node.getNodeId() + StringPool.SLASH +
1243 HttpUtil.encodeURL(page.getTitle());
1244
1245 if (previousVersionPage != null) {
1246 StringBundler sb = new StringBundler(16);
1247
1248 sb.append(layoutFullURL);
1249 sb.append("?p_p_id=");
1250 sb.append(PortletKeys.WIKI);
1251 sb.append("&p_p_state=");
1252 sb.append(WindowState.MAXIMIZED);
1253 sb.append("&struts_action=");
1254 sb.append(HttpUtil.encodeURL("/wiki/compare_versions"));
1255 sb.append("&nodeId=");
1256 sb.append(node.getNodeId());
1257 sb.append("&title=");
1258 sb.append(HttpUtil.encodeURL(page.getTitle()));
1259 sb.append("&sourceVersion=");
1260 sb.append(previousVersionPage.getVersion());
1261 sb.append("&targetVersion=");
1262 sb.append(page.getVersion());
1263 sb.append("&type=html");
1264
1265 diffsURL = sb.toString();
1266 }
1267 }
1268
1269 String portletName = PortalUtil.getPortletTitle(PortletKeys.WIKI, user);
1270
1271 String fromName = WikiUtil.getEmailFromName(preferences);
1272 String fromAddress = WikiUtil.getEmailFromAddress(preferences);
1273
1274 String replyToAddress = fromAddress;
1275 String mailId = WikiUtil.getMailId(
1276 company.getMx(), page.getNodeId(), page.getPageId());
1277
1278 fromName = StringUtil.replace(
1279 fromName,
1280 new String[] {
1281 "[$COMPANY_ID$]",
1282 "[$COMPANY_MX$]",
1283 "[$COMPANY_NAME$]",
1284 "[$COMMUNITY_NAME$]",
1285 "[$PAGE_USER_ADDRESS$]",
1286 "[$PAGE_USER_NAME$]",
1287 "[$PORTLET_NAME$]"
1288 },
1289 new String[] {
1290 String.valueOf(company.getCompanyId()),
1291 company.getMx(),
1292 company.getName(),
1293 group.getName(),
1294 user.getEmailAddress(),
1295 user.getFullName(),
1296 portletName
1297 });
1298
1299 fromAddress = StringUtil.replace(
1300 fromAddress,
1301 new String[] {
1302 "[$COMPANY_ID$]",
1303 "[$COMPANY_MX$]",
1304 "[$COMPANY_NAME$]",
1305 "[$COMMUNITY_NAME$]",
1306 "[$PAGE_USER_ADDRESS$]",
1307 "[$PAGE_USER_NAME$]",
1308 "[$PORTLET_NAME$]"
1309 },
1310 new String[] {
1311 String.valueOf(company.getCompanyId()),
1312 company.getMx(),
1313 company.getName(),
1314 group.getName(),
1315 user.getEmailAddress(),
1316 user.getFullName(),
1317 portletName
1318 });
1319
1320 String subjectPrefix = null;
1321 String body = null;
1322 String signature = null;
1323
1324 if (update) {
1325 subjectPrefix = WikiUtil.getEmailPageUpdatedSubjectPrefix(
1326 preferences);
1327 body = WikiUtil.getEmailPageUpdatedBody(preferences);
1328 signature = WikiUtil.getEmailPageUpdatedSignature(preferences);
1329 }
1330 else {
1331 subjectPrefix = WikiUtil.getEmailPageAddedSubjectPrefix(
1332 preferences);
1333 body = WikiUtil.getEmailPageAddedBody(preferences);
1334 signature = WikiUtil.getEmailPageAddedSignature(preferences);
1335 }
1336
1337 if (Validator.isNotNull(signature)) {
1338 body += "\n" + signature;
1339 }
1340
1341 subjectPrefix = StringUtil.replace(
1342 subjectPrefix,
1343 new String[] {
1344 "[$COMPANY_ID$]",
1345 "[$COMPANY_MX$]",
1346 "[$COMPANY_NAME$]",
1347 "[$COMMUNITY_NAME$]",
1348 "[$FROM_ADDRESS$]",
1349 "[$FROM_NAME$]",
1350 "[$NODE_NAME$]",
1351 "[$PAGE_CONTENT$]",
1352 "[$PAGE_ID$]",
1353 "[$PAGE_TITLE$]",
1354 "[$PAGE_USER_ADDRESS$]",
1355 "[$PAGE_USER_NAME$]",
1356 "[$PORTAL_URL$]",
1357 "[$PORTLET_NAME$]"
1358 },
1359 new String[] {
1360 String.valueOf(company.getCompanyId()),
1361 company.getMx(),
1362 company.getName(),
1363 group.getName(),
1364 fromAddress,
1365 fromName,
1366 node.getName(),
1367 pageContent,
1368 String.valueOf(page.getPageId()),
1369 page.getTitle(),
1370 user.getEmailAddress(),
1371 user.getFullName(),
1372 company.getVirtualHost(),
1373 portletName
1374 });
1375
1376 body = StringUtil.replace(
1377 body,
1378 new String[] {
1379 "[$COMPANY_ID$]",
1380 "[$COMPANY_MX$]",
1381 "[$COMPANY_NAME$]",
1382 "[$COMMUNITY_NAME$]",
1383 "[$DIFFS_URL$]",
1384 "[$FROM_ADDRESS$]",
1385 "[$FROM_NAME$]",
1386 "[$NODE_NAME$]",
1387 "[$PAGE_CONTENT$]",
1388 "[$PAGE_DATE_UPDATE$]",
1389 "[$PAGE_DIFFS$]",
1390 "[$PAGE_ID$]",
1391 "[$PAGE_SUMMARY$]",
1392 "[$PAGE_TITLE$]",
1393 "[$PAGE_URL$]",
1394 "[$PAGE_USER_ADDRESS$]",
1395 "[$PAGE_USER_NAME$]",
1396 "[$PORTAL_URL$]",
1397 "[$PORTLET_NAME$]"
1398 },
1399 new String[] {
1400 String.valueOf(company.getCompanyId()),
1401 company.getMx(),
1402 company.getName(),
1403 group.getName(),
1404 diffsURL,
1405 fromAddress,
1406 fromName,
1407 node.getName(),
1408 pageContent,
1409 String.valueOf(page.getModifiedDate()),
1410 replaceStyles(pageDiffs),
1411 String.valueOf(page.getPageId()),
1412 page.getSummary(),
1413 page.getTitle(),
1414 pageURL,
1415 user.getEmailAddress(),
1416 user.getFullName(),
1417 company.getVirtualHost(),
1418 portletName
1419 });
1420
1421 String subject = page.getTitle();
1422
1423 if (subject.indexOf(subjectPrefix) == -1) {
1424 subject = subjectPrefix + StringPool.SPACE + subject;
1425 }
1426
1427 Message message = new Message();
1428
1429 message.put("companyId", node.getCompanyId());
1430 message.put("userId", node.getUserId());
1431 message.put("nodeId", node.getNodeId());
1432 message.put("pageResourcePrimKey", page.getResourcePrimKey());
1433 message.put("fromName", fromName);
1434 message.put("fromAddress", fromAddress);
1435 message.put("subject", subject);
1436 message.put("body", body);
1437 message.put("replyToAddress", replyToAddress);
1438 message.put("mailId", mailId);
1439 message.put("htmlFormat", Boolean.TRUE);
1440
1441 MessageBusUtil.sendMessage(DestinationNames.WIKI, message);
1442 }
1443
1444 protected String replaceStyles(String html) {
1445 return StringUtil.replace(
1446 html,
1447 new String[] {
1448 "class=\"diff-html-added\"",
1449 "class=\"diff-html-removed\"",
1450 "class=\"diff-html-changed\"",
1451 "changeType=\"diff-added-image\"",
1452 "changeType=\"diff-removed-image\"",
1453 "changeType=\"diff-changed-image\""
1454 },
1455 new String[] {
1456 "style=\"background-color: #CFC;\"",
1457 "style=\"background-color: #FDC6C6; text-decoration: " +
1458 "line-through;\"",
1459 "style=\"border-bottom: 2px dotted blue;\"",
1460 "style=\"border: 10px solid #CFC;\"",
1461 "style=\"border: 10px solid #FDC6C6;\"",
1462 "style=\"border: 10px solid blue;\""
1463 }
1464 );
1465 }
1466
1467 protected void validate(long nodeId, String content, String format)
1468 throws PortalException {
1469
1470 if (!WikiUtil.validate(nodeId, content, format)) {
1471 throw new PageContentException();
1472 }
1473 }
1474
1475 protected void validate(
1476 String title, long nodeId, String content, String format)
1477 throws PortalException, SystemException {
1478
1479 if (Validator.isNull(title)) {
1480 throw new PageTitleException();
1481 }
1482
1483 if (isUsedTitle(nodeId, title)) {
1484 throw new DuplicatePageException();
1485 }
1486
1487 validateTitle(title);
1488
1489 validate(nodeId, content, format);
1490 }
1491
1492 private static Log _log = LogFactoryUtil.getLog(
1493 WikiPageLocalServiceImpl.class);
1494
1495}