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