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