001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.wiki.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.json.JSONFactoryUtil;
020    import com.liferay.portal.kernel.json.JSONObject;
021    import com.liferay.portal.kernel.repository.model.FileEntry;
022    import com.liferay.portal.kernel.repository.model.Folder;
023    import com.liferay.portal.kernel.sanitizer.SanitizerUtil;
024    import com.liferay.portal.kernel.search.Indexer;
025    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
026    import com.liferay.portal.kernel.systemevent.SystemEvent;
027    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
028    import com.liferay.portal.kernel.util.ContentTypes;
029    import com.liferay.portal.kernel.util.FileUtil;
030    import com.liferay.portal.kernel.util.HttpUtil;
031    import com.liferay.portal.kernel.util.ListUtil;
032    import com.liferay.portal.kernel.util.MathUtil;
033    import com.liferay.portal.kernel.util.MimeTypesUtil;
034    import com.liferay.portal.kernel.util.NotificationThreadLocal;
035    import com.liferay.portal.kernel.util.ObjectValuePair;
036    import com.liferay.portal.kernel.util.OrderByComparator;
037    import com.liferay.portal.kernel.util.StringPool;
038    import com.liferay.portal.kernel.util.StringUtil;
039    import com.liferay.portal.kernel.util.TempFileUtil;
040    import com.liferay.portal.kernel.util.UnicodeProperties;
041    import com.liferay.portal.kernel.util.UniqueList;
042    import com.liferay.portal.kernel.util.Validator;
043    import com.liferay.portal.kernel.workflow.WorkflowConstants;
044    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
045    import com.liferay.portal.kernel.workflow.WorkflowThreadLocal;
046    import com.liferay.portal.model.LayoutConstants;
047    import com.liferay.portal.model.ResourceConstants;
048    import com.liferay.portal.model.SystemEventConstants;
049    import com.liferay.portal.model.User;
050    import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
051    import com.liferay.portal.service.ServiceContext;
052    import com.liferay.portal.service.ServiceContextUtil;
053    import com.liferay.portal.util.Portal;
054    import com.liferay.portal.util.PortalUtil;
055    import com.liferay.portal.util.PortletKeys;
056    import com.liferay.portal.util.PropsValues;
057    import com.liferay.portal.util.SubscriptionSender;
058    import com.liferay.portlet.PortletURLFactoryUtil;
059    import com.liferay.portlet.asset.model.AssetEntry;
060    import com.liferay.portlet.asset.model.AssetLink;
061    import com.liferay.portlet.asset.model.AssetLinkConstants;
062    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
063    import com.liferay.portlet.expando.model.ExpandoBridge;
064    import com.liferay.portlet.social.model.SocialActivity;
065    import com.liferay.portlet.social.model.SocialActivityConstants;
066    import com.liferay.portlet.trash.model.TrashEntry;
067    import com.liferay.portlet.trash.util.TrashUtil;
068    import com.liferay.portlet.wiki.DuplicatePageException;
069    import com.liferay.portlet.wiki.NoSuchPageException;
070    import com.liferay.portlet.wiki.NoSuchPageResourceException;
071    import com.liferay.portlet.wiki.PageContentException;
072    import com.liferay.portlet.wiki.PageTitleException;
073    import com.liferay.portlet.wiki.PageVersionException;
074    import com.liferay.portlet.wiki.model.WikiNode;
075    import com.liferay.portlet.wiki.model.WikiPage;
076    import com.liferay.portlet.wiki.model.WikiPageConstants;
077    import com.liferay.portlet.wiki.model.WikiPageDisplay;
078    import com.liferay.portlet.wiki.model.WikiPageResource;
079    import com.liferay.portlet.wiki.model.impl.WikiPageDisplayImpl;
080    import com.liferay.portlet.wiki.model.impl.WikiPageImpl;
081    import com.liferay.portlet.wiki.service.base.WikiPageLocalServiceBaseImpl;
082    import com.liferay.portlet.wiki.social.WikiActivityKeys;
083    import com.liferay.portlet.wiki.util.WikiCacheThreadLocal;
084    import com.liferay.portlet.wiki.util.WikiCacheUtil;
085    import com.liferay.portlet.wiki.util.WikiUtil;
086    import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
087    import com.liferay.portlet.wiki.util.comparator.PageVersionComparator;
088    
089    import java.io.File;
090    import java.io.IOException;
091    import java.io.InputStream;
092    
093    import java.util.Calendar;
094    import java.util.Date;
095    import java.util.LinkedHashMap;
096    import java.util.List;
097    import java.util.Map;
098    import java.util.regex.Matcher;
099    import java.util.regex.Pattern;
100    
101    import javax.portlet.PortletPreferences;
102    import javax.portlet.PortletRequest;
103    import javax.portlet.PortletURL;
104    
105    import javax.servlet.http.HttpServletRequest;
106    
107    /**
108     * Provides the local service for accessing, adding, deleting, moving,
109     * subscription handling of, trash handling of, updating, and validating wiki
110     * pages.
111     *
112     * @author Brian Wing Shun Chan
113     * @author Jorge Ferrer
114     * @author Raymond Aug??
115     * @author Bruno Farache
116     * @author Julio Camarero
117     * @author Wesley Gong
118     * @author Marcellus Tavares
119     * @author Zsigmond Rab
120     * @author Zsolt Berentey
121     */
122    public class WikiPageLocalServiceImpl extends WikiPageLocalServiceBaseImpl {
123    
124            @Override
125            public WikiPage addPage(
126                            long userId, long nodeId, String title, double version,
127                            String content, String summary, boolean minorEdit, String format,
128                            boolean head, String parentTitle, String redirectTitle,
129                            ServiceContext serviceContext)
130                    throws PortalException, SystemException {
131    
132                    // Page
133    
134                    User user = userPersistence.findByPrimaryKey(userId);
135                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
136                    Date now = new Date();
137    
138                    long pageId = counterLocalService.increment();
139    
140                    content = SanitizerUtil.sanitize(
141                            user.getCompanyId(), node.getGroupId(), userId,
142                            WikiPage.class.getName(), pageId, "text/" + format, content);
143    
144                    validate(title, nodeId, content, format);
145    
146                    long resourcePrimKey =
147                            wikiPageResourceLocalService.getPageResourcePrimKey(nodeId, title);
148    
149                    WikiPage page = wikiPagePersistence.create(pageId);
150    
151                    page.setUuid(serviceContext.getUuid());
152                    page.setResourcePrimKey(resourcePrimKey);
153                    page.setGroupId(node.getGroupId());
154                    page.setCompanyId(user.getCompanyId());
155                    page.setUserId(user.getUserId());
156                    page.setUserName(user.getFullName());
157                    page.setCreateDate(serviceContext.getCreateDate(now));
158                    page.setModifiedDate(serviceContext.getModifiedDate(now));
159                    page.setNodeId(nodeId);
160                    page.setTitle(title);
161                    page.setVersion(version);
162                    page.setMinorEdit(minorEdit);
163                    page.setContent(content);
164                    page.setSummary(summary);
165                    page.setFormat(format);
166                    page.setHead(head);
167                    page.setParentTitle(parentTitle);
168                    page.setRedirectTitle(redirectTitle);
169                    page.setStatus(WorkflowConstants.STATUS_DRAFT);
170                    page.setStatusByUserId(userId);
171                    page.setStatusDate(serviceContext.getModifiedDate(now));
172                    page.setExpandoBridgeAttributes(serviceContext);
173    
174                    wikiPagePersistence.update(page);
175    
176                    // Resources
177    
178                    if (serviceContext.isAddGroupPermissions() ||
179                            serviceContext.isAddGuestPermissions()) {
180    
181                            addPageResources(
182                                    page, serviceContext.isAddGroupPermissions(),
183                                    serviceContext.isAddGuestPermissions());
184                    }
185                    else {
186                            addPageResources(
187                                    page, serviceContext.getGroupPermissions(),
188                                    serviceContext.getGuestPermissions());
189                    }
190    
191                    // Node
192    
193                    node.setLastPostDate(serviceContext.getModifiedDate(now));
194    
195                    wikiNodePersistence.update(node);
196    
197                    // Asset
198    
199                    updateAsset(
200                            userId, page, serviceContext.getAssetCategoryIds(),
201                            serviceContext.getAssetTagNames(),
202                            serviceContext.getAssetLinkEntryIds());
203    
204                    // Message boards
205    
206                    if (PropsValues.WIKI_PAGE_COMMENTS_ENABLED) {
207                            mbMessageLocalService.addDiscussionMessage(
208                                    userId, page.getUserName(), page.getGroupId(),
209                                    WikiPage.class.getName(), resourcePrimKey,
210                                    WorkflowConstants.ACTION_PUBLISH);
211                    }
212    
213                    // Workflow
214    
215                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
216                            user.getCompanyId(), page.getGroupId(), userId,
217                            WikiPage.class.getName(), page.getPageId(), page, serviceContext);
218    
219                    return page;
220            }
221    
222            @Override
223            public WikiPage addPage(
224                            long userId, long nodeId, String title, String content,
225                            String summary, boolean minorEdit, ServiceContext serviceContext)
226                    throws PortalException, SystemException {
227    
228                    double version = WikiPageConstants.VERSION_DEFAULT;
229                    String format = WikiPageConstants.DEFAULT_FORMAT;
230                    boolean head = false;
231                    String parentTitle = null;
232                    String redirectTitle = null;
233    
234                    return addPage(
235                            userId, nodeId, title, version, content, summary, minorEdit, format,
236                            head, parentTitle, redirectTitle, serviceContext);
237            }
238    
239            @Override
240            public void addPageAttachment(
241                            long userId, long nodeId, String title, String fileName, File file,
242                            String mimeType)
243                    throws PortalException, SystemException {
244    
245                    WikiPage page = getPage(nodeId, title);
246    
247                    Folder folder = page.addAttachmentsFolder();
248    
249                    FileEntry fileEntry = PortletFileRepositoryUtil.addPortletFileEntry(
250                            page.getGroupId(), userId, WikiPage.class.getName(),
251                            page.getResourcePrimKey(), PortletKeys.WIKI, folder.getFolderId(),
252                            file, fileName, mimeType, true);
253    
254                    if (userId == 0) {
255                            userId = page.getUserId();
256                    }
257    
258                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
259    
260                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
261                    extraDataJSONObject.put("fileEntryTitle", fileEntry.getTitle());
262                    extraDataJSONObject.put("title", page.getTitle());
263                    extraDataJSONObject.put("version", page.getVersion());
264    
265                    socialActivityLocalService.addActivity(
266                            userId, page.getGroupId(), WikiPage.class.getName(),
267                            page.getResourcePrimKey(),
268                            SocialActivityConstants.TYPE_ADD_ATTACHMENT,
269                            extraDataJSONObject.toString(), 0);
270            }
271    
272            @Override
273            public void addPageAttachment(
274                            long userId, long nodeId, String title, String fileName,
275                            InputStream inputStream, String mimeType)
276                    throws PortalException, SystemException {
277    
278                    WikiPage page = getPage(nodeId, title);
279    
280                    Folder folder = page.addAttachmentsFolder();
281    
282                    FileEntry fileEntry = PortletFileRepositoryUtil.addPortletFileEntry(
283                            page.getGroupId(), userId, WikiPage.class.getName(),
284                            page.getResourcePrimKey(), PortletKeys.WIKI, folder.getFolderId(),
285                            inputStream, fileName, mimeType, true);
286    
287                    if (userId == 0) {
288                            userId = page.getUserId();
289                    }
290    
291                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
292    
293                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
294                    extraDataJSONObject.put("fileEntryTitle", fileEntry.getTitle());
295                    extraDataJSONObject.put("title", page.getTitle());
296                    extraDataJSONObject.put("version", page.getVersion());
297    
298                    socialActivityLocalService.addActivity(
299                            userId, page.getGroupId(), WikiPage.class.getName(),
300                            page.getResourcePrimKey(),
301                            SocialActivityConstants.TYPE_ADD_ATTACHMENT,
302                            extraDataJSONObject.toString(), 0);
303            }
304    
305            @Override
306            public void addPageAttachments(
307                            long userId, long nodeId, String title,
308                            List<ObjectValuePair<String, InputStream>> inputStreamOVPs)
309                    throws PortalException, SystemException {
310    
311                    if (inputStreamOVPs.size() == 0) {
312                            return;
313                    }
314    
315                    for (int i = 0; i < inputStreamOVPs.size(); i++) {
316                            ObjectValuePair<String, InputStream> inputStreamOVP =
317                                    inputStreamOVPs.get(i);
318    
319                            String fileName = inputStreamOVP.getKey();
320                            InputStream inputStream = inputStreamOVP.getValue();
321    
322                            File file = null;
323    
324                            try {
325                                    file = FileUtil.createTempFile(inputStream);
326    
327                                    String mimeType = MimeTypesUtil.getContentType(file, fileName);
328    
329                                    addPageAttachment(
330                                            userId, nodeId, title, fileName, file, mimeType);
331                            }
332                            catch (IOException ioe) {
333                                    throw new SystemException(
334                                            "Unable to write temporary file", ioe);
335                            }
336                            finally {
337                                    FileUtil.delete(file);
338                            }
339                    }
340            }
341    
342            @Override
343            public void addPageResources(
344                            long nodeId, String title, boolean addGroupPermissions,
345                            boolean addGuestPermissions)
346                    throws PortalException, SystemException {
347    
348                    WikiPage page = getPage(nodeId, title);
349    
350                    addPageResources(page, addGroupPermissions, addGuestPermissions);
351            }
352    
353            @Override
354            public void addPageResources(
355                            long nodeId, String title, String[] groupPermissions,
356                            String[] guestPermissions)
357                    throws PortalException, SystemException {
358    
359                    WikiPage page = getPage(nodeId, title);
360    
361                    addPageResources(page, groupPermissions, guestPermissions);
362            }
363    
364            @Override
365            public void addPageResources(
366                            WikiPage page, boolean addGroupPermissions,
367                            boolean addGuestPermissions)
368                    throws PortalException, SystemException {
369    
370                    resourceLocalService.addResources(
371                            page.getCompanyId(), page.getGroupId(), page.getUserId(),
372                            WikiPage.class.getName(), page.getResourcePrimKey(), false,
373                            addGroupPermissions, addGuestPermissions);
374            }
375    
376            @Override
377            public void addPageResources(
378                            WikiPage page, String[] groupPermissions, String[] guestPermissions)
379                    throws PortalException, SystemException {
380    
381                    resourceLocalService.addModelResources(
382                            page.getCompanyId(), page.getGroupId(), page.getUserId(),
383                            WikiPage.class.getName(), page.getResourcePrimKey(),
384                            groupPermissions, guestPermissions);
385            }
386    
387            @Override
388            public void addTempPageAttachment(
389                            long groupId, long userId, String fileName, String tempFolderName,
390                            InputStream inputStream, String mimeType)
391                    throws PortalException, SystemException {
392    
393                    TempFileUtil.addTempFile(
394                            groupId, userId, fileName, tempFolderName, inputStream, mimeType);
395            }
396    
397            @Override
398            public void changeParent(
399                            long userId, long nodeId, String title, String newParentTitle,
400                            ServiceContext serviceContext)
401                    throws PortalException, SystemException {
402    
403                    if (Validator.isNotNull(newParentTitle)) {
404                            WikiPage parentPage = getPage(nodeId, newParentTitle);
405    
406                            if (Validator.isNotNull(parentPage.getRedirectTitle())) {
407                                    newParentTitle = parentPage.getRedirectTitle();
408                            }
409                    }
410    
411                    WikiPage page = getPage(nodeId, title);
412    
413                    String originalParentTitle = page.getParentTitle();
414    
415                    double version = page.getVersion();
416                    String content = page.getContent();
417                    String summary = serviceContext.translate(
418                            "changed-parent-from-x", originalParentTitle);
419                    boolean minorEdit = false;
420                    String format = page.getFormat();
421                    String redirectTitle = page.getRedirectTitle();
422    
423                    populateServiceContext(serviceContext, page);
424    
425                    updatePage(
426                            userId, nodeId, title, version, content, summary, minorEdit, format,
427                            newParentTitle, redirectTitle, serviceContext);
428    
429                    List<WikiPage> oldPages = wikiPagePersistence.findByN_T_H(
430                            nodeId, title, false);
431    
432                    for (WikiPage oldPage : oldPages) {
433                            if (!WorkflowThreadLocal.isEnabled()) {
434                                    oldPage.setParentTitle(originalParentTitle);
435    
436                                    wikiPagePersistence.update(oldPage);
437                            }
438                    }
439            }
440    
441            @Override
442            public void copyPageAttachments(
443                            long userId, long templateNodeId, String templateTitle, long nodeId,
444                            String title)
445                    throws PortalException, SystemException {
446    
447                    WikiPage templatePage = getPage(templateNodeId, templateTitle);
448    
449                    List<FileEntry> templateFileEntries =
450                            templatePage.getAttachmentsFileEntries();
451    
452                    for (FileEntry templateFileEntry : templateFileEntries) {
453                            addPageAttachment(
454                                    userId, nodeId, title, templateFileEntry.getTitle(),
455                                    templateFileEntry.getContentStream(),
456                                    templateFileEntry.getMimeType());
457                    }
458            }
459    
460            @Override
461            public void deletePage(long nodeId, String title)
462                    throws PortalException, SystemException {
463    
464                    List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
465                            nodeId, title, true, 0, 1);
466    
467                    if (!pages.isEmpty()) {
468                            wikiPageLocalService.deletePage(pages.get(0));
469                    }
470            }
471    
472            /**
473             * @deprecated As of 6.2.0 replaced by {@link #discardDraft(long, String,
474             *             double)}
475             */
476            @Override
477            public void deletePage(long nodeId, String title, double version)
478                    throws PortalException, SystemException {
479    
480                    discardDraft(nodeId, title, version);
481            }
482    
483            @Override
484            @SystemEvent(
485                    action = SystemEventConstants.ACTION_SKIP,
486                    type = SystemEventConstants.TYPE_DELETE)
487            public void deletePage(WikiPage page)
488                    throws PortalException, SystemException {
489    
490                    // Children
491    
492                    List<WikiPage> childrenPages = wikiPagePersistence.findByN_P(
493                            page.getNodeId(), page.getTitle());
494    
495                    for (WikiPage childrenPage : childrenPages) {
496                            if (!childrenPage.isApproved() ||
497                                    (!childrenPage.isInTrash() && page.isInTrash())) {
498    
499                                    childrenPage.setParentTitle(StringPool.BLANK);
500    
501                                    wikiPagePersistence.update(childrenPage);
502                            }
503                            else {
504                                    deletePage(childrenPage);
505                            }
506                    }
507    
508                    wikiPagePersistence.removeByN_T(page.getNodeId(), page.getTitle());
509    
510                    // References
511    
512                    wikiPagePersistence.removeByN_R(page.getNodeId(), page.getTitle());
513    
514                    // Resources
515    
516                    resourceLocalService.deleteResource(
517                            page.getCompanyId(), WikiPage.class.getName(),
518                            ResourceConstants.SCOPE_INDIVIDUAL, page.getResourcePrimKey());
519    
520                    // Resource
521    
522                    try {
523                            wikiPageResourceLocalService.deletePageResource(
524                                    page.getNodeId(), page.getTitle());
525                    }
526                    catch (NoSuchPageResourceException nspre) {
527                    }
528    
529                    // Attachments
530    
531                    long folderId = page.getAttachmentsFolderId();
532    
533                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
534                            PortletFileRepositoryUtil.deleteFolder(folderId);
535                    }
536    
537                    // Subscriptions
538    
539                    subscriptionLocalService.deleteSubscriptions(
540                            page.getCompanyId(), WikiPage.class.getName(),
541                            page.getResourcePrimKey());
542    
543                    // Asset
544    
545                    List<WikiPage> versionPages = wikiPagePersistence.findByN_T(
546                            page.getNodeId(), page.getTitle());
547    
548                    for (WikiPage versionPage : versionPages) {
549                            assetEntryLocalService.deleteEntry(
550                                    WikiPage.class.getName(), versionPage.getPrimaryKey());
551                    }
552    
553                    assetEntryLocalService.deleteEntry(
554                            WikiPage.class.getName(), page.getResourcePrimKey());
555    
556                    // Expando
557    
558                    expandoRowLocalService.deleteRows(page.getPrimaryKey());
559    
560                    // Message boards
561    
562                    mbMessageLocalService.deleteDiscussionMessages(
563                            WikiPage.class.getName(), page.getResourcePrimKey());
564    
565                    // Trash
566    
567                    if (page.isInTrash()) {
568                            page.setTitle(TrashUtil.getOriginalTitle(page.getTitle()));
569    
570                            trashEntryLocalService.deleteEntry(
571                                    WikiPage.class.getName(), page.getResourcePrimKey());
572                    }
573    
574                    // Indexer
575    
576                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
577                            WikiPage.class);
578    
579                    indexer.delete(page);
580    
581                    // Cache
582    
583                    clearPageCache(page);
584    
585                    // All versions
586    
587                    List<WikiPage> pages = wikiPagePersistence.findByN_T(
588                            page.getNodeId(), page.getTitle());
589    
590                    for (WikiPage curPage : pages) {
591    
592                            // Workflow
593    
594                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
595                                    curPage.getCompanyId(), curPage.getGroupId(),
596                                    WikiPage.class.getName(), curPage.getPageId());
597                    }
598            }
599    
600            @Override
601            public void deletePageAttachment(long nodeId, String title, String fileName)
602                    throws PortalException, SystemException {
603    
604                    WikiPage page = getPage(nodeId, title);
605    
606                    long folderId = page.getAttachmentsFolderId();
607    
608                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
609                            return;
610                    }
611    
612                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
613                            page.getGroupId(), folderId, fileName);
614    
615                    deletePageAttachment(fileEntry.getFileEntryId());
616            }
617    
618            @Override
619            public void deletePageAttachments(long nodeId, String title)
620                    throws PortalException, SystemException {
621    
622                    WikiPage page = getPage(nodeId, title);
623    
624                    long folderId = page.getAttachmentsFolderId();
625    
626                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
627                            return;
628                    }
629    
630                    PortletFileRepositoryUtil.deletePortletFileEntries(
631                            page.getGroupId(), folderId);
632            }
633    
634            @Override
635            public void deletePages(long nodeId)
636                    throws PortalException, SystemException {
637    
638                    List<WikiPage> pages = wikiPagePersistence.findByN_H_P(
639                            nodeId, true, StringPool.BLANK);
640    
641                    for (WikiPage page : pages) {
642                            deletePage(page);
643                    }
644    
645                    pages = wikiPagePersistence.findByN_H_P(
646                            nodeId, false, StringPool.BLANK);
647    
648                    for (WikiPage page : pages) {
649                            deletePage(page);
650                    }
651            }
652    
653            @Override
654            public void deleteTempPageAttachment(
655                            long groupId, long userId, String fileName, String tempFolderName)
656                    throws PortalException, SystemException {
657    
658                    TempFileUtil.deleteTempFile(groupId, userId, fileName, tempFolderName);
659            }
660    
661            @Override
662            public void deleteTrashPageAttachments(long nodeId, String title)
663                    throws PortalException, SystemException {
664    
665                    WikiPage page = getPage(nodeId, title);
666    
667                    long folderId = page.getAttachmentsFolderId();
668    
669                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
670                            return;
671                    }
672    
673                    PortletFileRepositoryUtil.deletePortletFileEntries(
674                            page.getGroupId(), folderId, WorkflowConstants.STATUS_IN_TRASH);
675            }
676    
677            @Override
678            public void discardDraft(long nodeId, String title, double version)
679                    throws PortalException, SystemException {
680    
681                    wikiPagePersistence.removeByN_T_V(nodeId, title, version);
682            }
683    
684            @Override
685            public WikiPage fetchPage(long nodeId, String title, double version)
686                    throws SystemException {
687    
688                    return wikiPagePersistence.fetchByN_T_V(nodeId, title, version);
689            }
690    
691            @Override
692            public List<WikiPage> getChildren(
693                            long nodeId, boolean head, String parentTitle)
694                    throws SystemException {
695    
696                    return wikiPagePersistence.findByN_H_P_S(
697                            nodeId, head, parentTitle, WorkflowConstants.STATUS_APPROVED);
698            }
699    
700            @Override
701            public WikiPage getDraftPage(long nodeId, String title)
702                    throws PortalException, SystemException {
703    
704                    List<WikiPage> pages = wikiPagePersistence.findByN_T_S(
705                            nodeId, title, WorkflowConstants.STATUS_DRAFT, 0, 1);
706    
707                    if (!pages.isEmpty()) {
708                            return pages.get(0);
709                    }
710                    else {
711                            pages = wikiPagePersistence.findByN_T_S(
712                                    nodeId, title, WorkflowConstants.STATUS_PENDING, 0, 1);
713    
714                            if (!pages.isEmpty()) {
715                                    return pages.get(0);
716                            }
717                            else {
718                                    throw new NoSuchPageException();
719                            }
720                    }
721    
722            }
723    
724            @Override
725            public List<WikiPage> getIncomingLinks(long nodeId, String title)
726                    throws PortalException, SystemException {
727    
728                    List<WikiPage> links = new UniqueList<WikiPage>();
729    
730                    List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
731    
732                    for (WikiPage page : pages) {
733                            if (isLinkedTo(page, title)) {
734                                    links.add(page);
735                            }
736                    }
737    
738                    List<WikiPage> referrals = wikiPagePersistence.findByN_R(nodeId, title);
739    
740                    for (WikiPage referral : referrals) {
741                            for (WikiPage page : pages) {
742                                    if (isLinkedTo(page, referral.getTitle())) {
743                                            links.add(page);
744                                    }
745                            }
746                    }
747    
748                    return ListUtil.sort(links);
749            }
750    
751            @Override
752            public List<WikiPage> getNoAssetPages() throws SystemException {
753                    return wikiPageFinder.findByNoAssets();
754            }
755    
756            @Override
757            public List<WikiPage> getOrphans(long nodeId)
758                    throws PortalException, SystemException {
759    
760                    List<WikiPage> pages = wikiPagePersistence.findByN_H_S(
761                            nodeId, true, WorkflowConstants.STATUS_APPROVED);
762    
763                    return WikiUtil.filterOrphans(pages);
764            }
765    
766            @Override
767            public List<WikiPage> getOutgoingLinks(long nodeId, String title)
768                    throws PortalException, SystemException {
769    
770                    WikiPage page = getPage(nodeId, title);
771    
772                    Map<String, WikiPage> pages = new LinkedHashMap<String, WikiPage>();
773    
774                    Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
775    
776                    for (Map.Entry<String, Boolean> entry : links.entrySet()) {
777                            String curTitle = entry.getKey();
778                            Boolean exists = entry.getValue();
779    
780                            if (exists) {
781                                    WikiPage curPage = getPage(nodeId, curTitle);
782    
783                                    if (!pages.containsKey(curPage.getTitle())) {
784                                            pages.put(curPage.getTitle(), curPage);
785                                    }
786                            }
787                            else {
788                                    WikiPageImpl newPage = new WikiPageImpl();
789    
790                                    newPage.setNew(true);
791                                    newPage.setNodeId(nodeId);
792                                    newPage.setTitle(curTitle);
793    
794                                    if (!pages.containsKey(curTitle)) {
795                                            pages.put(curTitle, newPage);
796                                    }
797                            }
798                    }
799    
800                    return ListUtil.fromMapValues(pages);
801            }
802    
803            @Override
804            public WikiPage getPage(long resourcePrimKey)
805                    throws PortalException, SystemException {
806    
807                    return getPage(resourcePrimKey, Boolean.TRUE);
808            }
809    
810            @Override
811            public WikiPage getPage(long resourcePrimKey, Boolean head)
812                    throws PortalException, SystemException {
813    
814                    WikiPageResource pageResource =
815                            wikiPageResourceLocalService.getPageResource(resourcePrimKey);
816    
817                    return getPage(pageResource.getNodeId(), pageResource.getTitle(), head);
818            }
819    
820            @Override
821            public WikiPage getPage(long nodeId, String title)
822                    throws PortalException, SystemException {
823    
824                    List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
825                            nodeId, title, true, 0, 1);
826    
827                    if (!pages.isEmpty()) {
828                            return pages.get(0);
829                    }
830                    else {
831                            throw new NoSuchPageException();
832                    }
833            }
834    
835            @Override
836            public WikiPage getPage(long nodeId, String title, Boolean head)
837                    throws PortalException, SystemException {
838    
839                    List<WikiPage> pages;
840    
841                    if (head == null) {
842                            pages = wikiPagePersistence.findByN_T(nodeId, title, 0, 1);
843                    }
844                    else {
845                            pages = wikiPagePersistence.findByN_T_H(nodeId, title, head, 0, 1);
846                    }
847    
848                    if (!pages.isEmpty()) {
849                            return pages.get(0);
850                    }
851                    else {
852                            throw new NoSuchPageException();
853                    }
854            }
855    
856            @Override
857            public WikiPage getPage(long nodeId, String title, double version)
858                    throws PortalException, SystemException {
859    
860                    WikiPage page = null;
861    
862                    if (version == 0) {
863                            page = getPage(nodeId, title);
864                    }
865                    else {
866                            page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
867                    }
868    
869                    return page;
870            }
871    
872            @Override
873            public WikiPage getPageByPageId(long pageId)
874                    throws PortalException, SystemException {
875    
876                    return wikiPagePersistence.findByPrimaryKey(pageId);
877            }
878    
879            @Override
880            public WikiPageDisplay getPageDisplay(
881                            long nodeId, String title, PortletURL viewPageURL,
882                            PortletURL editPageURL, String attachmentURLPrefix)
883                    throws PortalException, SystemException {
884    
885                    WikiPage page = getPage(nodeId, title);
886    
887                    return getPageDisplay(
888                            page, viewPageURL, editPageURL, attachmentURLPrefix);
889            }
890    
891            @Override
892            public WikiPageDisplay getPageDisplay(
893                            WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
894                            String attachmentURLPrefix)
895                    throws PortalException, SystemException {
896    
897                    String formattedContent = WikiUtil.convert(
898                            page, viewPageURL, editPageURL, attachmentURLPrefix);
899    
900                    return new WikiPageDisplayImpl(
901                            page.getUserId(), page.getNodeId(), page.getTitle(),
902                            page.getVersion(), page.getContent(), formattedContent,
903                            page.getFormat(), page.getHead(), page.getAttachmentsFileEntries());
904            }
905    
906            @Override
907            public List<WikiPage> getPages(
908                            long nodeId, boolean head, int start, int end)
909                    throws SystemException {
910    
911                    return getPages(
912                            nodeId, head, start, end, new PageCreateDateComparator(false));
913            }
914    
915            @Override
916            public List<WikiPage> getPages(
917                            long nodeId, boolean head, int status, int start, int end,
918                            OrderByComparator obc)
919                    throws SystemException {
920    
921                    if (status == WorkflowConstants.STATUS_ANY) {
922                            return wikiPagePersistence.findByN_H(nodeId, head, start, end, obc);
923                    }
924                    else {
925                            return wikiPagePersistence.findByN_H_S(
926                                    nodeId, head, status, start, end, obc);
927                    }
928            }
929    
930            @Override
931            public List<WikiPage> getPages(
932                            long nodeId, boolean head, int start, int end,
933                            OrderByComparator obc)
934                    throws SystemException {
935    
936                    return getPages(
937                            nodeId, head, WorkflowConstants.STATUS_APPROVED, start, end, obc);
938            }
939    
940            @Override
941            public List<WikiPage> getPages(long nodeId, int start, int end)
942                    throws SystemException {
943    
944                    return getPages(
945                            nodeId, start, end, new PageCreateDateComparator(false));
946            }
947    
948            @Override
949            public List<WikiPage> getPages(
950                            long nodeId, int start, int end, OrderByComparator obc)
951                    throws SystemException {
952    
953                    return wikiPagePersistence.findByNodeId(nodeId, start, end, obc);
954            }
955    
956            @Override
957            public List<WikiPage> getPages(
958                            long resourcePrimKey, long nodeId, int status)
959                    throws SystemException {
960    
961                    return wikiPagePersistence.findByR_N_S(resourcePrimKey, nodeId, status);
962            }
963    
964            @Override
965            public List<WikiPage> getPages(
966                            long userId, long nodeId, int status, int start, int end)
967                    throws SystemException {
968    
969                    if (userId > 0) {
970                            return wikiPagePersistence.findByU_N_S(
971                                    userId, nodeId, status, start, end,
972                                    new PageCreateDateComparator(false));
973                    }
974                    else {
975                            return wikiPagePersistence.findByN_S(
976                                    nodeId, status, start, end,
977                                    new PageCreateDateComparator(false));
978                    }
979            }
980    
981            @Override
982            public List<WikiPage> getPages(
983                            long nodeId, String title, boolean head, int start, int end)
984                    throws SystemException {
985    
986                    return wikiPagePersistence.findByN_T_H(
987                            nodeId, title, head, start, end,
988                            new PageCreateDateComparator(false));
989            }
990    
991            @Override
992            public List<WikiPage> getPages(
993                            long nodeId, String title, int start, int end)
994                    throws SystemException {
995    
996                    return wikiPagePersistence.findByN_T(
997                            nodeId, title, start, end, new PageCreateDateComparator(false));
998            }
999    
1000            @Override
1001            public List<WikiPage> getPages(
1002                            long nodeId, String title, int start, int end,
1003                            OrderByComparator obc)
1004                    throws SystemException {
1005    
1006                    return wikiPagePersistence.findByN_T(nodeId, title, start, end, obc);
1007            }
1008    
1009            @Override
1010            public List<WikiPage> getPages(String format) throws SystemException {
1011                    return wikiPagePersistence.findByFormat(format);
1012            }
1013    
1014            @Override
1015            public int getPagesCount(long nodeId) throws SystemException {
1016                    return wikiPagePersistence.countByNodeId(nodeId);
1017            }
1018    
1019            @Override
1020            public int getPagesCount(long nodeId, boolean head) throws SystemException {
1021                    return wikiPagePersistence.countByN_H_S(
1022                            nodeId, head, WorkflowConstants.STATUS_APPROVED);
1023            }
1024    
1025            @Override
1026            public int getPagesCount(long nodeId, boolean head, int status)
1027                    throws SystemException {
1028    
1029                    if (status == WorkflowConstants.STATUS_ANY) {
1030                            return wikiPagePersistence.countByN_H(nodeId, head);
1031                    }
1032                    else {
1033                            return wikiPagePersistence.countByN_H_S(nodeId, head, status);
1034                    }
1035            }
1036    
1037            @Override
1038            public int getPagesCount(long nodeId, int status) throws SystemException {
1039                    return wikiPagePersistence.countByN_S(nodeId, status);
1040            }
1041    
1042            @Override
1043            public int getPagesCount(long userId, long nodeId, int status)
1044                    throws SystemException {
1045    
1046                    if (userId > 0) {
1047                            return wikiPagePersistence.countByU_N_S(userId, nodeId, status);
1048                    }
1049                    else {
1050                            return wikiPagePersistence.countByN_S(nodeId, status);
1051                    }
1052            }
1053    
1054            @Override
1055            public int getPagesCount(long nodeId, String title) throws SystemException {
1056                    return wikiPagePersistence.countByN_T(nodeId, title);
1057            }
1058    
1059            @Override
1060            public int getPagesCount(long nodeId, String title, boolean head)
1061                    throws SystemException {
1062    
1063                    return wikiPagePersistence.countByN_T_H(nodeId, title, head);
1064            }
1065    
1066            @Override
1067            public int getPagesCount(String format) throws SystemException {
1068                    return wikiPagePersistence.countByFormat(format);
1069            }
1070    
1071            /**
1072             * @deprecated As of 6.2.0, replaced by {@link #getRecentChanges(long, long,
1073             *             int, int)}
1074             */
1075            @Override
1076            public List<WikiPage> getRecentChanges(long nodeId, int start, int end)
1077                    throws PortalException, SystemException {
1078    
1079                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
1080    
1081                    return getRecentChanges(node.getGroupId(), nodeId, start, end);
1082            }
1083    
1084            @Override
1085            public List<WikiPage> getRecentChanges(
1086                            long groupId, long nodeId, int start, int end)
1087                    throws SystemException {
1088    
1089                    Calendar cal = CalendarFactoryUtil.getCalendar();
1090    
1091                    cal.add(Calendar.WEEK_OF_YEAR, -1);
1092    
1093                    return wikiPageFinder.findByCreateDate(
1094                            groupId, nodeId, cal.getTime(), false, start, end);
1095            }
1096    
1097            /**
1098             * @deprecated As of 6.2.0, replaced by {@link #getRecentChangesCount(long,
1099             *             long)}
1100             */
1101            @Override
1102            public int getRecentChangesCount(long nodeId)
1103                    throws PortalException, SystemException {
1104    
1105                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
1106    
1107                    return getRecentChangesCount(node.getGroupId(), nodeId);
1108            }
1109    
1110            @Override
1111            public int getRecentChangesCount(long groupId, long nodeId)
1112                    throws SystemException {
1113    
1114                    Calendar cal = CalendarFactoryUtil.getCalendar();
1115    
1116                    cal.add(Calendar.WEEK_OF_YEAR, -1);
1117    
1118                    return wikiPageFinder.countByCreateDate(
1119                            groupId, nodeId, cal.getTime(), false);
1120            }
1121    
1122            @Override
1123            public String[] getTempPageAttachmentNames(
1124                            long groupId, long userId, String tempFolderName)
1125                    throws PortalException, SystemException {
1126    
1127                    return TempFileUtil.getTempFileEntryNames(
1128                            groupId, userId, tempFolderName);
1129            }
1130    
1131            @Override
1132            public boolean hasDraftPage(long nodeId, String title)
1133                    throws SystemException {
1134    
1135                    int count = wikiPagePersistence.countByN_T_S(
1136                            nodeId, title, WorkflowConstants.STATUS_DRAFT);
1137    
1138                    if (count > 0) {
1139                            return true;
1140                    }
1141                    else {
1142                            return false;
1143                    }
1144            }
1145    
1146            @Override
1147            public void movePage(
1148                            long userId, long nodeId, String title, String newTitle,
1149                            boolean strict, ServiceContext serviceContext)
1150                    throws PortalException, SystemException {
1151    
1152                    validateTitle(newTitle);
1153    
1154                    // Check if the new title already exists
1155    
1156                    if (title.equalsIgnoreCase(newTitle)) {
1157                            throw new DuplicatePageException(newTitle);
1158                    }
1159    
1160                    if (isUsedTitle(nodeId, newTitle)) {
1161                            WikiPage page = getPage(nodeId, newTitle);
1162    
1163                            // Support moving back to a previously moved title
1164    
1165                            if (((page.getVersion() == WikiPageConstants.VERSION_DEFAULT) &&
1166                                     (page.getContent().length() < 200)) ||
1167                                    !strict) {
1168    
1169                                    deletePage(nodeId, newTitle);
1170                            }
1171                            else {
1172                                    throw new DuplicatePageException(newTitle);
1173                            }
1174                    }
1175    
1176                    // All versions
1177    
1178                    List<WikiPage> versionPages = wikiPagePersistence.findByN_T(
1179                            nodeId, title);
1180    
1181                    if (versionPages.size() == 0) {
1182                            return;
1183                    }
1184    
1185                    for (WikiPage page : versionPages) {
1186                            page.setTitle(newTitle);
1187    
1188                            wikiPagePersistence.update(page);
1189                    }
1190    
1191                    // Children
1192    
1193                    List<WikiPage> children = wikiPagePersistence.findByN_P(nodeId, title);
1194    
1195                    for (WikiPage page : children) {
1196                            page.setParentTitle(newTitle);
1197    
1198                            wikiPagePersistence.update(page);
1199                    }
1200    
1201                    WikiPage page = versionPages.get(versionPages.size() - 1);
1202    
1203                    long resourcePrimKey = page.getResourcePrimKey();
1204    
1205                    // Page resource
1206    
1207                    WikiPageResource pageResource =
1208                            wikiPageResourcePersistence.findByPrimaryKey(resourcePrimKey);
1209    
1210                    pageResource.setTitle(newTitle);
1211    
1212                    wikiPageResourcePersistence.update(pageResource);
1213    
1214                    // Create stub page at the old location
1215    
1216                    double version = WikiPageConstants.VERSION_DEFAULT;
1217                    String summary = WikiPageConstants.MOVED + " to " + title;
1218                    String format = page.getFormat();
1219                    boolean head = true;
1220                    String parentTitle = page.getParentTitle();
1221                    String redirectTitle = page.getTitle();
1222                    String content =
1223                            StringPool.DOUBLE_OPEN_BRACKET + redirectTitle +
1224                                    StringPool.DOUBLE_CLOSE_BRACKET;
1225    
1226                    serviceContext.setAddGroupPermissions(true);
1227                    serviceContext.setAddGuestPermissions(true);
1228    
1229                    populateServiceContext(serviceContext, page);
1230    
1231                    addPage(
1232                            userId, nodeId, title, version, content, summary, false, format,
1233                            head, parentTitle, redirectTitle, serviceContext);
1234    
1235                    // Move redirects to point to the page with the new title
1236    
1237                    List<WikiPage> redirectedPages = wikiPagePersistence.findByN_R(
1238                            nodeId, title);
1239    
1240                    for (WikiPage redirectedPage : redirectedPages) {
1241                            redirectedPage.setRedirectTitle(newTitle);
1242    
1243                            wikiPagePersistence.update(redirectedPage);
1244                    }
1245    
1246                    // Asset
1247    
1248                    updateAsset(
1249                            userId, page, serviceContext.getAssetCategoryIds(),
1250                            serviceContext.getAssetTagNames(),
1251                            serviceContext.getAssetLinkEntryIds());
1252    
1253                    // Indexer
1254    
1255                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1256                            WikiPage.class);
1257    
1258                    indexer.delete(
1259                            new Object[] {page.getCompanyId(), page.getNodeId(), title});
1260    
1261                    indexer.reindex(page);
1262            }
1263    
1264            @Override
1265            public void movePage(
1266                            long userId, long nodeId, String title, String newTitle,
1267                            ServiceContext serviceContext)
1268                    throws PortalException, SystemException {
1269    
1270                    movePage(userId, nodeId, title, newTitle, true, serviceContext);
1271            }
1272    
1273            @Override
1274            public FileEntry movePageAttachmentToTrash(
1275                            long userId, long nodeId, String title, String fileName)
1276                    throws PortalException, SystemException {
1277    
1278                    WikiPage page = getPage(nodeId, title);
1279    
1280                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1281                            page.getGroupId(), page.getAttachmentsFolderId(), fileName);
1282    
1283                    fileEntry = PortletFileRepositoryUtil.movePortletFileEntryToTrash(
1284                            userId, fileEntry.getFileEntryId());
1285    
1286                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1287    
1288                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
1289                    extraDataJSONObject.put(
1290                            "fileEntryTitle", TrashUtil.getOriginalTitle(fileEntry.getTitle()));
1291                    extraDataJSONObject.put("title", page.getTitle());
1292                    extraDataJSONObject.put("version", page.getVersion());
1293    
1294                    socialActivityLocalService.addActivity(
1295                            userId, page.getGroupId(), WikiPage.class.getName(),
1296                            page.getResourcePrimKey(),
1297                            SocialActivityConstants.TYPE_MOVE_ATTACHMENT_TO_TRASH,
1298                            extraDataJSONObject.toString(), 0);
1299    
1300                    return fileEntry;
1301            }
1302    
1303            @Override
1304            public WikiPage movePageToTrash(long userId, long nodeId, String title)
1305                    throws PortalException, SystemException {
1306    
1307                    List<WikiPage> wikiPages = wikiPagePersistence.findByN_T_H(
1308                            nodeId, title, true, 0, 1);
1309    
1310                    if (!wikiPages.isEmpty()) {
1311                            return movePageToTrash(userId, wikiPages.get(0));
1312                    }
1313    
1314                    return null;
1315            }
1316    
1317            @Override
1318            public WikiPage movePageToTrash(
1319                            long userId, long nodeId, String title, double version)
1320                    throws PortalException, SystemException {
1321    
1322                    WikiPage page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
1323    
1324                    return movePageToTrash(userId, page);
1325            }
1326    
1327            @Override
1328            public WikiPage movePageToTrash(long userId, WikiPage page)
1329                    throws PortalException, SystemException {
1330    
1331                    // Page
1332    
1333                    int oldStatus = page.getStatus();
1334                    String oldTitle = page.getTitle();
1335    
1336                    page = updateStatus(
1337                            userId, page, WorkflowConstants.STATUS_IN_TRASH,
1338                            new ServiceContext());
1339    
1340                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
1341                            WikiPage.class.getName(), page.getResourcePrimKey());
1342    
1343                    String trashTitle = TrashUtil.getTrashTitle(trashEntry.getEntryId());
1344    
1345                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_R(
1346                            page.getNodeId(), page.getTitle());
1347    
1348                    for (WikiPage redirectPage : redirectPages) {
1349                            redirectPage.setRedirectTitle(trashTitle);
1350    
1351                            wikiPagePersistence.update(redirectPage);
1352                    }
1353    
1354                    List<WikiPage> versionPages = wikiPagePersistence.findByR_N_H(
1355                            page.getResourcePrimKey(), page.getNodeId(), false);
1356    
1357                    for (WikiPage versionPage : versionPages) {
1358                            versionPage.setTitle(trashTitle);
1359    
1360                            wikiPagePersistence.update(versionPage);
1361                    }
1362    
1363                    WikiPageResource pageResource =
1364                            wikiPageResourcePersistence.fetchByPrimaryKey(
1365                                    page.getResourcePrimKey());
1366    
1367                    pageResource.setTitle(trashTitle);
1368    
1369                    wikiPageResourcePersistence.update(pageResource);
1370    
1371                    page.setTitle(trashTitle);
1372    
1373                    wikiPagePersistence.update(page);
1374    
1375                    // Children
1376    
1377                    List<WikiPage> children = wikiPagePersistence.findByN_P(
1378                            page.getNodeId(), oldTitle);
1379    
1380                    for (WikiPage curPage : children) {
1381                            curPage.setParentTitle(trashTitle);
1382    
1383                            wikiPagePersistence.update(curPage);
1384    
1385                            if (curPage.isApproved()) {
1386                                    movePageToTrash(userId, curPage);
1387                            }
1388                    }
1389    
1390                    // Social
1391    
1392                    socialActivityCounterLocalService.disableActivityCounters(
1393                            WikiPage.class.getName(), page.getPageId());
1394    
1395                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1396    
1397                    extraDataJSONObject.put(
1398                            "title", TrashUtil.getOriginalTitle(page.getTitle()));
1399                    extraDataJSONObject.put("version", page.getVersion());
1400    
1401                    socialActivityLocalService.addActivity(
1402                            userId, page.getGroupId(), WikiPage.class.getName(),
1403                            page.getResourcePrimKey(),
1404                            SocialActivityConstants.TYPE_MOVE_TO_TRASH,
1405                            extraDataJSONObject.toString(), 0);
1406    
1407                    // Workflow
1408    
1409                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
1410                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
1411                                    page.getCompanyId(), page.getGroupId(),
1412                                    WikiPage.class.getName(), page.getPageId());
1413                    }
1414    
1415                    return page;
1416            }
1417    
1418            @Override
1419            public void restorePageAttachmentFromTrash(
1420                            long userId, long nodeId, String title, String fileName)
1421                    throws PortalException, SystemException {
1422    
1423                    WikiPage page = getPage(nodeId, title);
1424    
1425                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1426                            page.getGroupId(), page.getAttachmentsFolderId(), fileName);
1427    
1428                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1429    
1430                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
1431                    extraDataJSONObject.put("fileEntryTitle", TrashUtil.getOriginalTitle(
1432                            fileEntry.getTitle()));
1433                    extraDataJSONObject.put("title", page.getTitle());
1434                    extraDataJSONObject.put("version", page.getVersion());
1435    
1436                    PortletFileRepositoryUtil.restorePortletFileEntryFromTrash(
1437                            userId, fileEntry.getFileEntryId());
1438    
1439                    socialActivityLocalService.addActivity(
1440                            userId, page.getGroupId(), WikiPage.class.getName(),
1441                            page.getResourcePrimKey(),
1442                            SocialActivityConstants.TYPE_RESTORE_ATTACHMENT_FROM_TRASH,
1443                            extraDataJSONObject.toString(), 0);
1444            }
1445    
1446            @Override
1447            public void restorePageFromTrash(long userId, WikiPage page)
1448                    throws PortalException, SystemException {
1449    
1450                    String title = page.getTitle();
1451    
1452                    String originalTitle = TrashUtil.getOriginalTitle(title);
1453    
1454                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_R(
1455                            page.getNodeId(), page.getTitle());
1456    
1457                    for (WikiPage redirectPage : redirectPages) {
1458                            redirectPage.setRedirectTitle(originalTitle);
1459    
1460                            wikiPagePersistence.update(redirectPage);
1461                    }
1462    
1463                    List<WikiPage> versionPages = wikiPagePersistence.findByR_N_H(
1464                            page.getResourcePrimKey(), page.getNodeId(), false);
1465    
1466                    for (WikiPage versionPage : versionPages) {
1467                            versionPage.setTitle(originalTitle);
1468    
1469                            wikiPagePersistence.update(versionPage);
1470                    }
1471    
1472                    WikiPageResource pageResource =
1473                            wikiPageResourcePersistence.fetchByPrimaryKey(
1474                                    page.getResourcePrimKey());
1475    
1476                    pageResource.setTitle(originalTitle);
1477    
1478                    wikiPageResourcePersistence.update(pageResource);
1479    
1480                    page.setTitle(originalTitle);
1481    
1482                    wikiPagePersistence.update(page);
1483    
1484                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
1485                            WikiPage.class.getName(), page.getResourcePrimKey());
1486    
1487                    updateStatus(
1488                            userId, page, trashEntry.getStatus(), new ServiceContext());
1489    
1490                    // Children
1491    
1492                    List<WikiPage> children = wikiPagePersistence.findByN_P(
1493                            page.getNodeId(), title);
1494    
1495                    for (WikiPage curPage : children) {
1496                            curPage.setParentTitle(originalTitle);
1497    
1498                            wikiPagePersistence.update(curPage);
1499    
1500                            if (curPage.isInTrash()) {
1501                                    restorePageFromTrash(userId, curPage);
1502                            }
1503                    }
1504    
1505                    // Social
1506    
1507                    socialActivityCounterLocalService.enableActivityCounters(
1508                            WikiPage.class.getName(), page.getPageId());
1509    
1510                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1511    
1512                    extraDataJSONObject.put("title", page.getTitle());
1513                    extraDataJSONObject.put("version", page.getVersion());
1514    
1515                    socialActivityLocalService.addActivity(
1516                            userId, page.getGroupId(), WikiPage.class.getName(),
1517                            page.getResourcePrimKey(),
1518                            SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
1519                            extraDataJSONObject.toString(), 0);
1520            }
1521    
1522            @Override
1523            public WikiPage revertPage(
1524                            long userId, long nodeId, String title, double version,
1525                            ServiceContext serviceContext)
1526                    throws PortalException, SystemException {
1527    
1528                    WikiPage oldPage = getPage(nodeId, title, version);
1529    
1530                    populateServiceContext(serviceContext, oldPage);
1531    
1532                    return updatePage(
1533                            userId, nodeId, title, 0, oldPage.getContent(),
1534                            WikiPageConstants.REVERTED + " to " + version, false,
1535                            oldPage.getFormat(), getParentPageTitle(oldPage),
1536                            oldPage.getRedirectTitle(), serviceContext);
1537            }
1538    
1539            @Override
1540            public void subscribePage(long userId, long nodeId, String title)
1541                    throws PortalException, SystemException {
1542    
1543                    WikiPage page = getPage(nodeId, title);
1544    
1545                    subscriptionLocalService.addSubscription(
1546                            userId, page.getGroupId(), WikiPage.class.getName(),
1547                            page.getResourcePrimKey());
1548            }
1549    
1550            @Override
1551            public void unsubscribePage(long userId, long nodeId, String title)
1552                    throws PortalException, SystemException {
1553    
1554                    WikiPage page = getPage(nodeId, title);
1555    
1556                    subscriptionLocalService.deleteSubscription(
1557                            userId, WikiPage.class.getName(), page.getResourcePrimKey());
1558            }
1559    
1560            @Override
1561            public void updateAsset(
1562                            long userId, WikiPage page, long[] assetCategoryIds,
1563                            String[] assetTagNames, long[] assetLinkEntryIds)
1564                    throws PortalException, SystemException {
1565    
1566                    boolean addDraftAssetEntry = false;
1567    
1568                    if (!page.isApproved() &&
1569                            (page.getVersion() != WikiPageConstants.VERSION_DEFAULT)) {
1570    
1571                            int approvedPagesCount = wikiPagePersistence.countByN_T_S(
1572                                    page.getNodeId(), page.getTitle(),
1573                                    WorkflowConstants.STATUS_APPROVED);
1574    
1575                            if (approvedPagesCount > 0) {
1576                                    addDraftAssetEntry = true;
1577                            }
1578                    }
1579    
1580                    AssetEntry assetEntry = null;
1581    
1582                    if (addDraftAssetEntry) {
1583                            assetEntry = assetEntryLocalService.updateEntry(
1584                                    userId, page.getGroupId(), page.getCreateDate(),
1585                                    page.getModifiedDate(), WikiPage.class.getName(),
1586                                    page.getPrimaryKey(), page.getUuid(), 0, assetCategoryIds,
1587                                    assetTagNames, false, null, null, null, ContentTypes.TEXT_HTML,
1588                                    page.getTitle(), null, null, null, null, 0, 0, null, false);
1589                    }
1590                    else {
1591                            assetEntry = assetEntryLocalService.updateEntry(
1592                                    userId, page.getGroupId(), page.getCreateDate(),
1593                                    page.getModifiedDate(), WikiPage.class.getName(),
1594                                    page.getResourcePrimKey(), page.getUuid(), 0, assetCategoryIds,
1595                                    assetTagNames, page.isApproved(), null, null, null,
1596                                    ContentTypes.TEXT_HTML, page.getTitle(), null, null, null, null,
1597                                    0, 0, null, false);
1598                    }
1599    
1600                    assetLinkLocalService.updateLinks(
1601                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
1602                            AssetLinkConstants.TYPE_RELATED);
1603            }
1604    
1605            @Override
1606            public WikiPage updatePage(
1607                            long userId, long nodeId, String title, double version,
1608                            String content, String summary, boolean minorEdit, String format,
1609                            String parentTitle, String redirectTitle,
1610                            ServiceContext serviceContext)
1611                    throws PortalException, SystemException {
1612    
1613                    // Page
1614    
1615                    User user = userPersistence.findByPrimaryKey(userId);
1616                    Date now = new Date();
1617    
1618                    WikiPage oldPage = null;
1619    
1620                    try {
1621                            oldPage = wikiPagePersistence.findByN_T_First(nodeId, title, null);
1622                    }
1623                    catch (NoSuchPageException nspe) {
1624                            return addPage(
1625                                    userId, nodeId, title, WikiPageConstants.VERSION_DEFAULT,
1626                                    content, summary, minorEdit, format, true, parentTitle,
1627                                    redirectTitle, serviceContext);
1628                    }
1629    
1630                    long pageId = 0;
1631    
1632                    if (oldPage.isApproved()) {
1633                            pageId = counterLocalService.increment();
1634                    }
1635                    else {
1636                            pageId = oldPage.getPageId();
1637                    }
1638    
1639                    content = SanitizerUtil.sanitize(
1640                            user.getCompanyId(), oldPage.getGroupId(), userId,
1641                            WikiPage.class.getName(), pageId, "text/" + format, content);
1642    
1643                    validate(nodeId, content, format);
1644    
1645                    double oldVersion = oldPage.getVersion();
1646    
1647                    if ((version > 0) && (version != oldVersion)) {
1648                            throw new PageVersionException();
1649                    }
1650    
1651                    serviceContext.validateModifiedDate(
1652                            oldPage, PageVersionException.class);
1653    
1654                    long resourcePrimKey =
1655                            wikiPageResourceLocalService.getPageResourcePrimKey(nodeId, title);
1656                    long groupId = oldPage.getGroupId();
1657    
1658                    WikiPage page = oldPage;
1659    
1660                    double newVersion = oldVersion;
1661    
1662                    if (oldPage.isApproved()) {
1663                            newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
1664    
1665                            page = wikiPagePersistence.create(pageId);
1666                    }
1667    
1668                    page.setResourcePrimKey(resourcePrimKey);
1669                    page.setGroupId(groupId);
1670                    page.setCompanyId(user.getCompanyId());
1671                    page.setUserId(user.getUserId());
1672                    page.setUserName(user.getFullName());
1673                    page.setCreateDate(serviceContext.getModifiedDate(now));
1674                    page.setModifiedDate(serviceContext.getModifiedDate(now));
1675                    page.setNodeId(nodeId);
1676                    page.setTitle(title);
1677                    page.setVersion(newVersion);
1678                    page.setMinorEdit(minorEdit);
1679                    page.setContent(content);
1680    
1681                    if (oldPage.isPending()) {
1682                            page.setStatus(oldPage.getStatus());
1683                    }
1684                    else {
1685                            page.setStatus(WorkflowConstants.STATUS_DRAFT);
1686                    }
1687    
1688                    page.setSummary(summary);
1689                    page.setFormat(format);
1690    
1691                    if (Validator.isNotNull(parentTitle)) {
1692                            page.setParentTitle(parentTitle);
1693                    }
1694    
1695                    if (Validator.isNotNull(redirectTitle)) {
1696                            page.setRedirectTitle(redirectTitle);
1697                    }
1698    
1699                    page.setExpandoBridgeAttributes(serviceContext);
1700    
1701                    wikiPagePersistence.update(page);
1702    
1703                    // Node
1704    
1705                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
1706    
1707                    node.setLastPostDate(serviceContext.getModifiedDate(now));
1708    
1709                    wikiNodePersistence.update(node);
1710    
1711                    // Asset
1712    
1713                    updateAsset(
1714                            userId, page, serviceContext.getAssetCategoryIds(),
1715                            serviceContext.getAssetTagNames(),
1716                            serviceContext.getAssetLinkEntryIds());
1717    
1718                    // Social
1719    
1720                    if (!page.isMinorEdit() ||
1721                            PropsValues.WIKI_PAGE_MINOR_EDIT_ADD_SOCIAL_ACTIVITY) {
1722    
1723                            if (oldVersion == newVersion) {
1724                                    SocialActivity lastSocialActivity =
1725                                            socialActivityLocalService.fetchFirstActivity(
1726                                                    WikiPage.class.getName(), page.getResourcePrimKey(),
1727                                                    WikiActivityKeys.UPDATE_PAGE);
1728    
1729                                    if (lastSocialActivity != null) {
1730                                            lastSocialActivity.setCreateDate(now.getTime() + 1);
1731                                            lastSocialActivity.setUserId(serviceContext.getUserId());
1732    
1733                                            socialActivityPersistence.update(lastSocialActivity);
1734                                    }
1735                            }
1736                            else {
1737                                    JSONObject extraDataJSONObject =
1738                                            JSONFactoryUtil.createJSONObject();
1739    
1740                                    extraDataJSONObject.put("title", page.getTitle());
1741                                    extraDataJSONObject.put("version", page.getVersion());
1742    
1743                                    socialActivityLocalService.addActivity(
1744                                            userId, page.getGroupId(), WikiPage.class.getName(),
1745                                            page.getResourcePrimKey(), WikiActivityKeys.UPDATE_PAGE,
1746                                            extraDataJSONObject.toString(), 0);
1747                            }
1748                    }
1749    
1750                    // Workflow
1751    
1752                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
1753                            user.getCompanyId(), page.getGroupId(), userId,
1754                            WikiPage.class.getName(), page.getPageId(), page, serviceContext);
1755    
1756                    return page;
1757            }
1758    
1759            @Override
1760            public WikiPage updateStatus(
1761                            long userId, long resourcePrimKey, int status,
1762                            ServiceContext serviceContext)
1763                    throws PortalException, SystemException {
1764    
1765                    WikiPageResource pageResource =
1766                            wikiPageResourceLocalService.getPageResource(resourcePrimKey);
1767    
1768                    List<WikiPage> pages = wikiPagePersistence.findByN_T(
1769                            pageResource.getNodeId(), pageResource.getTitle(), 0, 1,
1770                            new PageVersionComparator());
1771    
1772                    WikiPage page = null;
1773    
1774                    if (!pages.isEmpty()) {
1775                            page = pages.get(0);
1776                    }
1777                    else {
1778                            throw new NoSuchPageException();
1779                    }
1780    
1781                    return updateStatus(userId, page, status, serviceContext);
1782            }
1783    
1784            @Override
1785            public WikiPage updateStatus(
1786                            long userId, WikiPage page, int status,
1787                            ServiceContext serviceContext)
1788                    throws PortalException, SystemException {
1789    
1790                    // Page
1791    
1792                    User user = userPersistence.findByPrimaryKey(userId);
1793                    WikiNode node = wikiNodePersistence.findByPrimaryKey(page.getNodeId());
1794    
1795                    Date now = new Date();
1796    
1797                    int oldStatus = page.getStatus();
1798    
1799                    page.setStatus(status);
1800                    page.setStatusByUserId(userId);
1801                    page.setStatusByUserName(user.getFullName());
1802                    page.setStatusDate(now);
1803    
1804                    if (status == WorkflowConstants.STATUS_APPROVED) {
1805    
1806                            // Asset
1807    
1808                            if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
1809                                    (page.getVersion() != WikiPageConstants.VERSION_DEFAULT)) {
1810    
1811                                    AssetEntry draftAssetEntry = assetEntryLocalService.fetchEntry(
1812                                            WikiPage.class.getName(), page.getPrimaryKey());
1813    
1814                                    if (draftAssetEntry != null) {
1815                                            long[] assetCategoryIds = draftAssetEntry.getCategoryIds();
1816                                            String[] assetTagNames = draftAssetEntry.getTagNames();
1817    
1818                                            List<AssetLink> assetLinks =
1819                                                    assetLinkLocalService.getDirectLinks(
1820                                                            draftAssetEntry.getEntryId(),
1821                                                            AssetLinkConstants.TYPE_RELATED);
1822    
1823                                            long[] assetLinkEntryIds = StringUtil.split(
1824                                                    ListUtil.toString(
1825                                                            assetLinks, AssetLink.ENTRY_ID2_ACCESSOR), 0L);
1826    
1827                                            AssetEntry assetEntry = assetEntryLocalService.updateEntry(
1828                                                    userId, page.getGroupId(), page.getCreateDate(),
1829                                                    page.getModifiedDate(), WikiPage.class.getName(),
1830                                                    page.getResourcePrimKey(), page.getUuid(), 0,
1831                                                    assetCategoryIds, assetTagNames, true, null, null, null,
1832                                                    ContentTypes.TEXT_HTML, page.getTitle(), null, null,
1833                                                    null, null, 0, 0, null, false);
1834    
1835                                            // Asset Links
1836    
1837                                            assetLinkLocalService.updateLinks(
1838                                                    userId, assetEntry.getEntryId(), assetLinkEntryIds,
1839                                                    AssetLinkConstants.TYPE_RELATED);
1840    
1841                                            assetEntryLocalService.deleteEntry(
1842                                                    draftAssetEntry.getEntryId());
1843                                    }
1844                            }
1845    
1846                            assetEntryLocalService.updateVisible(
1847                                    WikiPage.class.getName(), page.getResourcePrimKey(), true);
1848    
1849                            // Social
1850    
1851                            if ((oldStatus != WorkflowConstants.STATUS_IN_TRASH) &&
1852                                    (page.getVersion() == WikiPageConstants.VERSION_DEFAULT) &&
1853                                    (!page.isMinorEdit() ||
1854                                     PropsValues.WIKI_PAGE_MINOR_EDIT_ADD_SOCIAL_ACTIVITY)) {
1855    
1856                                    JSONObject extraDataJSONObject =
1857                                            JSONFactoryUtil.createJSONObject();
1858    
1859                                    extraDataJSONObject.put("title", page.getTitle());
1860                                    extraDataJSONObject.put("version", page.getVersion());
1861    
1862                                    socialActivityLocalService.addActivity(
1863                                            userId, page.getGroupId(), WikiPage.class.getName(),
1864                                            page.getResourcePrimKey(), WikiActivityKeys.ADD_PAGE,
1865                                            extraDataJSONObject.toString(), 0);
1866                            }
1867    
1868                            // Subscriptions
1869    
1870                            if (NotificationThreadLocal.isEnabled() &&
1871                                    (!page.isMinorEdit() ||
1872                                     PropsValues.WIKI_PAGE_MINOR_EDIT_SEND_EMAIL)) {
1873    
1874                                    boolean update = false;
1875    
1876                                    if (page.getVersion() > WikiPageConstants.VERSION_DEFAULT) {
1877                                            update = true;
1878                                    }
1879    
1880                                    notifySubscribers(node, page, serviceContext, update);
1881                            }
1882    
1883                            // Indexer
1884    
1885                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1886                                    WikiPage.class);
1887    
1888                            indexer.reindex(page);
1889    
1890                            // Cache
1891    
1892                            clearPageCache(page);
1893                    }
1894    
1895                    if ((oldStatus == WorkflowConstants.STATUS_IN_TRASH) &&
1896                            (status != WorkflowConstants.STATUS_IN_TRASH)) {
1897    
1898                            // Trash
1899    
1900                            trashEntryLocalService.deleteEntry(
1901                                    WikiPage.class.getName(), page.getResourcePrimKey());
1902                    }
1903                    else if (status == WorkflowConstants.STATUS_IN_TRASH) {
1904    
1905                            // Asset
1906    
1907                            assetEntryLocalService.updateVisible(
1908                                    WikiPage.class.getName(), page.getResourcePrimKey(), false);
1909    
1910                            // Trash
1911    
1912                            UnicodeProperties typeSettingsProperties = new UnicodeProperties();
1913    
1914                            typeSettingsProperties.put("title", page.getTitle());
1915    
1916                            trashEntryLocalService.addTrashEntry(
1917                                    userId, page.getGroupId(), WikiPage.class.getName(),
1918                                    page.getResourcePrimKey(), oldStatus, null,
1919                                    typeSettingsProperties);
1920    
1921                            // Indexer
1922    
1923                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1924                                    WikiPage.class);
1925    
1926                            indexer.reindex(page);
1927    
1928                            // Cache
1929    
1930                            clearPageCache(page);
1931                    }
1932    
1933                    // Head
1934    
1935                    if (status == WorkflowConstants.STATUS_APPROVED) {
1936                            page.setHead(true);
1937    
1938                            List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
1939                                    page.getNodeId(), page.getTitle(), true);
1940    
1941                            for (WikiPage curPage : pages) {
1942                                    if (!curPage.equals(page)) {
1943                                            curPage.setHead(false);
1944    
1945                                            wikiPagePersistence.update(curPage);
1946                                    }
1947                            }
1948                    }
1949                    else if (status != WorkflowConstants.STATUS_IN_TRASH) {
1950                            page.setHead(false);
1951    
1952                            List<WikiPage> pages = wikiPagePersistence.findByN_T_S(
1953                                    page.getNodeId(), page.getTitle(),
1954                                    WorkflowConstants.STATUS_APPROVED);
1955    
1956                            for (WikiPage curPage : pages) {
1957                                    if (!curPage.equals(page)) {
1958                                            curPage.setHead(true);
1959    
1960                                            wikiPagePersistence.update(curPage);
1961    
1962                                            break;
1963                                    }
1964                            }
1965                    }
1966    
1967                    return wikiPagePersistence.update(page);
1968            }
1969    
1970            @Override
1971            public void validateTitle(String title) throws PortalException {
1972                    if (title.equals("all_pages") || title.equals("orphan_pages") ||
1973                            title.equals("recent_changes")) {
1974    
1975                            throw new PageTitleException(title + " is reserved");
1976                    }
1977    
1978                    if (Validator.isNotNull(PropsValues.WIKI_PAGE_TITLES_REGEXP)) {
1979                            Pattern pattern = Pattern.compile(
1980                                    PropsValues.WIKI_PAGE_TITLES_REGEXP);
1981    
1982                            Matcher matcher = pattern.matcher(title);
1983    
1984                            if (!matcher.matches()) {
1985                                    throw new PageTitleException();
1986                            }
1987                    }
1988            }
1989    
1990            protected void clearPageCache(WikiPage page) {
1991                    if (!WikiCacheThreadLocal.isClearCache()) {
1992                            return;
1993                    }
1994    
1995                    WikiCacheUtil.clearCache(page.getNodeId());
1996            }
1997    
1998            protected void deletePageAttachment(long fileEntryId)
1999                    throws PortalException, SystemException {
2000    
2001                    PortletFileRepositoryUtil.deletePortletFileEntry(fileEntryId);
2002            }
2003    
2004            protected String getDiffsURL(
2005                            WikiNode node, WikiPage page, WikiPage previousVersionPage,
2006                            ServiceContext serviceContext)
2007                    throws PortalException, SystemException {
2008    
2009                    if (previousVersionPage == null) {
2010                            return StringPool.BLANK;
2011                    }
2012    
2013                    if (Validator.isNotNull(serviceContext.getLayoutFullURL())) {
2014                            return StringPool.BLANK;
2015                    }
2016    
2017                    HttpServletRequest request = serviceContext.getRequest();
2018    
2019                    if (request == null) {
2020                            return StringPool.BLANK;
2021                    }
2022    
2023                    String portletId = null;
2024                    long plid = LayoutConstants.DEFAULT_PLID;
2025                    String strutsAction = null;
2026    
2027                    if (serviceContext.getPlid() != LayoutConstants.DEFAULT_PLID) {
2028                            portletId = PortletKeys.WIKI;
2029                            plid = serviceContext.getPlid();
2030                            strutsAction = "/wiki/compare_versions";
2031                    }
2032                    else {
2033                            portletId = PortletKeys.WIKI_ADMIN;
2034                            plid = PortalUtil.getControlPanelPlid(
2035                                    serviceContext.getCompanyId());
2036                            strutsAction = "/wiki_admin/compare_versions";
2037                    }
2038    
2039                    PortletURL portletURL = PortletURLFactoryUtil.create(
2040                            request, portletId, plid, PortletRequest.RENDER_PHASE);
2041    
2042                    portletURL.setParameter("struts_action", strutsAction);
2043                    portletURL.setParameter("nodeId", String.valueOf(node.getNodeId()));
2044                    portletURL.setParameter("title", page.getTitle());
2045                    portletURL.setParameter(
2046                            "sourceVersion", String.valueOf(previousVersionPage.getVersion()));
2047                    portletURL.setParameter(
2048                            "targetVersion", String.valueOf(page.getVersion()));
2049                    portletURL.setParameter("type", "html");
2050    
2051                    return portletURL.toString();
2052            }
2053    
2054            protected String getPageURL(
2055                            WikiNode node, WikiPage page, ServiceContext serviceContext)
2056                    throws PortalException, SystemException {
2057    
2058                    if (Validator.isNotNull(serviceContext.getLayoutFullURL())) {
2059                            return StringPool.BLANK;
2060                    }
2061    
2062                    HttpServletRequest request = serviceContext.getRequest();
2063    
2064                    if (request == null) {
2065                            return StringPool.BLANK;
2066                    }
2067    
2068                    String layoutFullURL = getLayoutURL(
2069                            node.getGroupId(), PortletKeys.WIKI, serviceContext);
2070    
2071                    if (Validator.isNotNull(layoutFullURL)) {
2072                            return layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "wiki/" +
2073                                    node.getNodeId() + StringPool.SLASH +
2074                                            HttpUtil.encodeURL(page.getTitle());
2075                    }
2076                    else {
2077                            long controlPanelPlid = PortalUtil.getControlPanelPlid(
2078                                    serviceContext.getCompanyId());
2079    
2080                            PortletURL portletURL = PortletURLFactoryUtil.create(
2081                                    request, PortletKeys.WIKI_ADMIN, controlPanelPlid,
2082                                    PortletRequest.RENDER_PHASE);
2083    
2084                            portletURL.setParameter(
2085                                    "struts_action", "/wiki_admin/view_page_activities");
2086                            portletURL.setParameter("nodeId", String.valueOf(node.getNodeId()));
2087                            portletURL.setParameter("title", page.getTitle());
2088    
2089                            return portletURL.toString();
2090                    }
2091            }
2092    
2093            protected String getParentPageTitle(WikiPage page) {
2094    
2095                    // LPS-4586
2096    
2097                    try {
2098                            WikiPage parentPage = getPage(
2099                                    page.getNodeId(), page.getParentTitle());
2100    
2101                            return parentPage.getTitle();
2102                    }
2103                    catch (Exception e) {
2104                            return null;
2105                    }
2106            }
2107    
2108            protected WikiPage getPreviousVersionPage(WikiPage page)
2109                    throws PortalException, SystemException {
2110    
2111                    double previousVersion = MathUtil.format(page.getVersion() - 0.1, 1, 1);
2112    
2113                    if (previousVersion < 1) {
2114                            return null;
2115                    }
2116    
2117                    return getPage(page.getNodeId(), page.getTitle(), previousVersion);
2118            }
2119    
2120            protected boolean isLinkedTo(WikiPage page, String targetTitle)
2121                    throws PortalException {
2122    
2123                    Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
2124    
2125                    Boolean link = links.get(targetTitle.toLowerCase());
2126    
2127                    if (link != null) {
2128                            return true;
2129                    }
2130                    else {
2131                            return false;
2132                    }
2133            }
2134    
2135            protected boolean isUsedTitle(long nodeId, String title)
2136                    throws SystemException {
2137    
2138                    if (getPagesCount(nodeId, title, true) > 0) {
2139                            return true;
2140                    }
2141                    else {
2142                            return false;
2143                    }
2144            }
2145    
2146            protected void notifySubscribers(
2147                            WikiNode node, WikiPage page, ServiceContext serviceContext,
2148                            boolean update)
2149                    throws PortalException, SystemException {
2150    
2151                    PortletPreferences preferences = null;
2152    
2153                    String rootPortletId = serviceContext.getRootPortletId();
2154    
2155                    if (Validator.isNull(rootPortletId) ||
2156                            !rootPortletId.equals(PortletKeys.WIKI_DISPLAY)) {
2157    
2158                            preferences = ServiceContextUtil.getPortletPreferences(
2159                                    serviceContext);
2160                    }
2161    
2162                    if (preferences == null) {
2163                            preferences = portletPreferencesLocalService.getPreferences(
2164                                    node.getCompanyId(), node.getGroupId(),
2165                                    PortletKeys.PREFS_OWNER_TYPE_GROUP,
2166                                    PortletKeys.PREFS_PLID_SHARED, PortletKeys.WIKI_ADMIN, null);
2167                    }
2168    
2169                    if (!update && WikiUtil.getEmailPageAddedEnabled(preferences)) {
2170                    }
2171                    else if (update && WikiUtil.getEmailPageUpdatedEnabled(preferences)) {
2172                    }
2173                    else {
2174                            return;
2175                    }
2176    
2177                    String portalURL = serviceContext.getPortalURL();
2178    
2179                    WikiPage previousVersionPage = getPreviousVersionPage(page);
2180    
2181                    String attachmentURLPrefix = WikiUtil.getAttachmentURLPrefix(
2182                            serviceContext.getPathMain(), serviceContext.getPlid(),
2183                            page.getNodeId(), page.getTitle());
2184    
2185                    attachmentURLPrefix = portalURL + attachmentURLPrefix;
2186    
2187                    String pageDiffs = StringPool.BLANK;
2188    
2189                    try {
2190                            pageDiffs = WikiUtil.diffHtml(
2191                                    previousVersionPage, page, null, null, attachmentURLPrefix);
2192                    }
2193                    catch (Exception e) {
2194                    }
2195    
2196                    String pageContent = null;
2197    
2198                    if (Validator.equals(page.getFormat(), "creole")) {
2199                            pageContent = WikiUtil.convert(
2200                                    page, null, null, attachmentURLPrefix);
2201                    }
2202                    else {
2203                            pageContent = page.getContent();
2204                            pageContent = WikiUtil.processContent(pageContent);
2205                    }
2206    
2207                    String fromName = WikiUtil.getEmailFromName(
2208                            preferences, page.getCompanyId());
2209                    String fromAddress = WikiUtil.getEmailFromAddress(
2210                            preferences, page.getCompanyId());
2211    
2212                    String subject = null;
2213                    String body = null;
2214                    String signature = null;
2215    
2216                    if (update) {
2217                            subject = WikiUtil.getEmailPageUpdatedSubject(preferences);
2218                            body = WikiUtil.getEmailPageUpdatedBody(preferences);
2219                            signature = WikiUtil.getEmailPageUpdatedSignature(preferences);
2220                    }
2221                    else {
2222                            subject = WikiUtil.getEmailPageAddedSubject(preferences);
2223                            body = WikiUtil.getEmailPageAddedBody(preferences);
2224                            signature = WikiUtil.getEmailPageAddedSignature(preferences);
2225                    }
2226    
2227                    if (Validator.isNotNull(signature)) {
2228                            body += "\n" + signature;
2229                    }
2230    
2231                    SubscriptionSender subscriptionSender = new SubscriptionSender();
2232    
2233                    subscriptionSender.setBody(body);
2234                    subscriptionSender.setCompanyId(page.getCompanyId());
2235                    subscriptionSender.setContextAttributes(
2236                            "[$DIFFS_URL$]",
2237                            getDiffsURL(node, page, previousVersionPage, serviceContext),
2238                            "[$NODE_NAME$]", node.getName(), "[$PAGE_DATE_UPDATE$]",
2239                            page.getModifiedDate(), "[$PAGE_ID$]", page.getPageId(),
2240                            "[$PAGE_SUMMARY$]", page.getSummary(), "[$PAGE_TITLE$]",
2241                            page.getTitle(), "[$PAGE_URL$]",
2242                            getPageURL(node, page, serviceContext));
2243                    subscriptionSender.setContextAttribute(
2244                            "[$PAGE_CONTENT$]", pageContent, false);
2245                    subscriptionSender.setContextAttribute(
2246                            "[$PAGE_DIFFS$]", replaceStyles(pageDiffs), false);
2247                    subscriptionSender.setContextUserPrefix("PAGE");
2248                    subscriptionSender.setFrom(fromAddress, fromName);
2249                    subscriptionSender.setHtmlFormat(true);
2250                    subscriptionSender.setMailId(
2251                            "wiki_page", page.getNodeId(), page.getPageId());
2252                    subscriptionSender.setPortletId(PortletKeys.WIKI);
2253                    subscriptionSender.setReplyToAddress(fromAddress);
2254                    subscriptionSender.setScopeGroupId(node.getGroupId());
2255                    subscriptionSender.setServiceContext(serviceContext);
2256                    subscriptionSender.setSubject(subject);
2257                    subscriptionSender.setUserId(page.getUserId());
2258    
2259                    subscriptionSender.addPersistedSubscribers(
2260                            WikiNode.class.getName(), node.getNodeId());
2261                    subscriptionSender.addPersistedSubscribers(
2262                            WikiPage.class.getName(), page.getResourcePrimKey());
2263    
2264                    subscriptionSender.flushNotificationsAsync();
2265            }
2266    
2267            protected void populateServiceContext(
2268                            ServiceContext serviceContext, WikiPage page)
2269                    throws PortalException, SystemException {
2270    
2271                    long[] assetCategoryIds = assetCategoryLocalService.getCategoryIds(
2272                            WikiPage.class.getName(), page.getResourcePrimKey());
2273    
2274                    serviceContext.setAssetCategoryIds(assetCategoryIds);
2275    
2276                    AssetEntry assetEntry = assetEntryLocalService.getEntry(
2277                            WikiPage.class.getName(), page.getResourcePrimKey());
2278    
2279                    List<AssetLink> assetLinks = assetLinkLocalService.getLinks(
2280                            assetEntry.getEntryId());
2281    
2282                    long[] assetLinkEntryIds = StringUtil.split(
2283                            ListUtil.toString(assetLinks, AssetLink.ENTRY_ID2_ACCESSOR), 0L);
2284    
2285                    serviceContext.setAssetLinkEntryIds(assetLinkEntryIds);
2286    
2287                    String[] assetTagNames = assetTagLocalService.getTagNames(
2288                            WikiPage.class.getName(), page.getResourcePrimKey());
2289    
2290                    serviceContext.setAssetTagNames(assetTagNames);
2291    
2292                    ExpandoBridge expandoBridge = page.getExpandoBridge();
2293    
2294                    serviceContext.setExpandoBridgeAttributes(
2295                            expandoBridge.getAttributes());
2296            }
2297    
2298            protected String replaceStyles(String html) {
2299                    return StringUtil.replace(
2300                            html,
2301                            new String[] {
2302                                    "class=\"diff-html-added\"", "class=\"diff-html-removed\"",
2303                                    "class=\"diff-html-changed\"",
2304                                    "changeType=\"diff-added-image\"",
2305                                    "changeType=\"diff-removed-image\"",
2306                                    "changeType=\"diff-changed-image\""
2307                            },
2308                            new String[] {
2309                                    "style=\"background-color: #CFC;\"",
2310                                    "style=\"background-color: #FDC6C6; text-decoration: " +
2311                                            "line-through;\"",
2312                                    "style=\"border-bottom: 2px dotted blue;\"",
2313                                    "style=\"border: 10px solid #CFC;\"",
2314                                    "style=\"border: 10px solid #FDC6C6;\"",
2315                                    "style=\"border: 10px solid blue;\""
2316                            }
2317                    );
2318            }
2319    
2320            protected void validate(long nodeId, String content, String format)
2321                    throws PortalException {
2322    
2323                    if (!WikiUtil.validate(nodeId, content, format)) {
2324                            throw new PageContentException();
2325                    }
2326            }
2327    
2328            protected void validate(
2329                            String title, long nodeId, String content, String format)
2330                    throws PortalException, SystemException {
2331    
2332                    if (Validator.isNull(title)) {
2333                            throw new PageTitleException();
2334                    }
2335    
2336                    if (isUsedTitle(nodeId, title)) {
2337                            throw new DuplicatePageException();
2338                    }
2339    
2340                    validateTitle(title);
2341    
2342                    validate(nodeId, content, format);
2343            }
2344    
2345    }