001    /**
002     * Copyright (c) 2000-present 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.dao.orm.QueryUtil;
018    import com.liferay.portal.kernel.diff.DiffHtmlUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.json.JSONFactoryUtil;
022    import com.liferay.portal.kernel.json.JSONObject;
023    import com.liferay.portal.kernel.language.LanguageUtil;
024    import com.liferay.portal.kernel.notifications.UserNotificationDefinition;
025    import com.liferay.portal.kernel.repository.model.FileEntry;
026    import com.liferay.portal.kernel.repository.model.Folder;
027    import com.liferay.portal.kernel.sanitizer.SanitizerUtil;
028    import com.liferay.portal.kernel.search.Indexer;
029    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
030    import com.liferay.portal.kernel.settings.LocalizedValuesMap;
031    import com.liferay.portal.kernel.systemevent.SystemEvent;
032    import com.liferay.portal.kernel.systemevent.SystemEventHierarchyEntryThreadLocal;
033    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
034    import com.liferay.portal.kernel.util.Constants;
035    import com.liferay.portal.kernel.util.ContentTypes;
036    import com.liferay.portal.kernel.util.FileUtil;
037    import com.liferay.portal.kernel.util.GetterUtil;
038    import com.liferay.portal.kernel.util.HttpUtil;
039    import com.liferay.portal.kernel.util.ListUtil;
040    import com.liferay.portal.kernel.util.MathUtil;
041    import com.liferay.portal.kernel.util.MimeTypesUtil;
042    import com.liferay.portal.kernel.util.NotificationThreadLocal;
043    import com.liferay.portal.kernel.util.ObjectValuePair;
044    import com.liferay.portal.kernel.util.OrderByComparator;
045    import com.liferay.portal.kernel.util.StringBundler;
046    import com.liferay.portal.kernel.util.StringPool;
047    import com.liferay.portal.kernel.util.StringUtil;
048    import com.liferay.portal.kernel.util.TempFileEntryUtil;
049    import com.liferay.portal.kernel.util.UnicodeProperties;
050    import com.liferay.portal.kernel.util.Validator;
051    import com.liferay.portal.kernel.workflow.WorkflowConstants;
052    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
053    import com.liferay.portal.kernel.workflow.WorkflowThreadLocal;
054    import com.liferay.portal.model.LayoutConstants;
055    import com.liferay.portal.model.ResourceConstants;
056    import com.liferay.portal.model.SystemEventConstants;
057    import com.liferay.portal.model.User;
058    import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
059    import com.liferay.portal.service.ServiceContext;
060    import com.liferay.portal.util.LayoutURLUtil;
061    import com.liferay.portal.util.Portal;
062    import com.liferay.portal.util.PortalUtil;
063    import com.liferay.portal.util.PortletKeys;
064    import com.liferay.portal.util.PropsValues;
065    import com.liferay.portal.util.SubscriptionSender;
066    import com.liferay.portlet.PortletURLFactoryUtil;
067    import com.liferay.portlet.asset.model.AssetEntry;
068    import com.liferay.portlet.asset.model.AssetLink;
069    import com.liferay.portlet.asset.model.AssetLinkConstants;
070    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
071    import com.liferay.portlet.expando.model.ExpandoBridge;
072    import com.liferay.portlet.social.model.SocialActivity;
073    import com.liferay.portlet.social.model.SocialActivityConstants;
074    import com.liferay.portlet.trash.model.TrashEntry;
075    import com.liferay.portlet.trash.model.TrashVersion;
076    import com.liferay.portlet.trash.util.TrashUtil;
077    import com.liferay.portlet.wiki.DuplicatePageException;
078    import com.liferay.portlet.wiki.NoSuchPageException;
079    import com.liferay.portlet.wiki.NodeChangeException;
080    import com.liferay.portlet.wiki.PageContentException;
081    import com.liferay.portlet.wiki.PageTitleException;
082    import com.liferay.portlet.wiki.PageVersionException;
083    import com.liferay.portlet.wiki.WikiSettings;
084    import com.liferay.portlet.wiki.model.WikiNode;
085    import com.liferay.portlet.wiki.model.WikiPage;
086    import com.liferay.portlet.wiki.model.WikiPageConstants;
087    import com.liferay.portlet.wiki.model.WikiPageDisplay;
088    import com.liferay.portlet.wiki.model.WikiPageResource;
089    import com.liferay.portlet.wiki.model.impl.WikiPageDisplayImpl;
090    import com.liferay.portlet.wiki.model.impl.WikiPageImpl;
091    import com.liferay.portlet.wiki.service.base.WikiPageLocalServiceBaseImpl;
092    import com.liferay.portlet.wiki.social.WikiActivityKeys;
093    import com.liferay.portlet.wiki.util.WikiCacheThreadLocal;
094    import com.liferay.portlet.wiki.util.WikiCacheUtil;
095    import com.liferay.portlet.wiki.util.WikiUtil;
096    import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
097    import com.liferay.portlet.wiki.util.comparator.PageVersionComparator;
098    
099    import java.io.File;
100    import java.io.IOException;
101    import java.io.InputStream;
102    import java.io.Serializable;
103    
104    import java.util.ArrayList;
105    import java.util.Calendar;
106    import java.util.Date;
107    import java.util.HashMap;
108    import java.util.HashSet;
109    import java.util.LinkedHashMap;
110    import java.util.List;
111    import java.util.Map;
112    import java.util.Set;
113    import java.util.regex.Matcher;
114    import java.util.regex.Pattern;
115    
116    import javax.portlet.PortletRequest;
117    import javax.portlet.PortletURL;
118    
119    import javax.servlet.http.HttpServletRequest;
120    
121    /**
122     * Provides the local service for accessing, adding, deleting, moving,
123     * subscription handling of, trash handling of, updating, and validating wiki
124     * pages.
125     *
126     * @author Brian Wing Shun Chan
127     * @author Jorge Ferrer
128     * @author Raymond Aug??
129     * @author Bruno Farache
130     * @author Julio Camarero
131     * @author Wesley Gong
132     * @author Marcellus Tavares
133     * @author Zsigmond Rab
134     * @author Zsolt Berentey
135     * @author Roberto D??az
136     */
137    public class WikiPageLocalServiceImpl extends WikiPageLocalServiceBaseImpl {
138    
139            @Override
140            public WikiPage addPage(
141                            long userId, long nodeId, String title, double version,
142                            String content, String summary, boolean minorEdit, String format,
143                            boolean head, String parentTitle, String redirectTitle,
144                            ServiceContext serviceContext)
145                    throws PortalException {
146    
147                    // Page
148    
149                    User user = userPersistence.findByPrimaryKey(userId);
150                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
151                    Date now = new Date();
152    
153                    long pageId = counterLocalService.increment();
154    
155                    content = SanitizerUtil.sanitize(
156                            user.getCompanyId(), node.getGroupId(), userId,
157                            WikiPage.class.getName(), pageId, "text/" + format, content);
158    
159                    validate(title, nodeId, content, format);
160    
161                    long resourcePrimKey =
162                            wikiPageResourceLocalService.getPageResourcePrimKey(nodeId, title);
163    
164                    WikiPage page = wikiPagePersistence.create(pageId);
165    
166                    page.setUuid(serviceContext.getUuid());
167                    page.setResourcePrimKey(resourcePrimKey);
168                    page.setGroupId(node.getGroupId());
169                    page.setCompanyId(user.getCompanyId());
170                    page.setUserId(user.getUserId());
171                    page.setUserName(user.getFullName());
172                    page.setCreateDate(serviceContext.getCreateDate(now));
173                    page.setModifiedDate(serviceContext.getModifiedDate(now));
174                    page.setNodeId(nodeId);
175                    page.setTitle(title);
176                    page.setVersion(version);
177                    page.setMinorEdit(minorEdit);
178                    page.setContent(content);
179                    page.setSummary(summary);
180                    page.setFormat(format);
181                    page.setHead(head);
182                    page.setParentTitle(parentTitle);
183                    page.setRedirectTitle(redirectTitle);
184                    page.setStatus(WorkflowConstants.STATUS_DRAFT);
185                    page.setStatusByUserId(userId);
186                    page.setStatusDate(serviceContext.getModifiedDate(now));
187                    page.setExpandoBridgeAttributes(serviceContext);
188    
189                    wikiPagePersistence.update(page);
190    
191                    // Resources
192    
193                    if (serviceContext.isAddGroupPermissions() ||
194                            serviceContext.isAddGuestPermissions()) {
195    
196                            addPageResources(
197                                    page, serviceContext.isAddGroupPermissions(),
198                                    serviceContext.isAddGuestPermissions());
199                    }
200                    else {
201                            addPageResources(
202                                    page, serviceContext.getGroupPermissions(),
203                                    serviceContext.getGuestPermissions());
204                    }
205    
206                    // Node
207    
208                    node.setLastPostDate(serviceContext.getModifiedDate(now));
209    
210                    wikiNodePersistence.update(node);
211    
212                    // Asset
213    
214                    updateAsset(
215                            userId, page, serviceContext.getAssetCategoryIds(),
216                            serviceContext.getAssetTagNames(),
217                            serviceContext.getAssetLinkEntryIds());
218    
219                    // Message boards
220    
221                    if (PropsValues.WIKI_PAGE_COMMENTS_ENABLED) {
222                            mbMessageLocalService.addDiscussionMessage(
223                                    userId, page.getUserName(), page.getGroupId(),
224                                    WikiPage.class.getName(), resourcePrimKey,
225                                    WorkflowConstants.ACTION_PUBLISH);
226                    }
227    
228                    // Workflow
229    
230                    startWorkflowInstance(userId, page, serviceContext);
231    
232                    return page;
233            }
234    
235            @Override
236            public WikiPage addPage(
237                            long userId, long nodeId, String title, String content,
238                            String summary, boolean minorEdit, ServiceContext serviceContext)
239                    throws PortalException {
240    
241                    double version = WikiPageConstants.VERSION_DEFAULT;
242                    String format = WikiPageConstants.DEFAULT_FORMAT;
243                    boolean head = false;
244                    String parentTitle = null;
245                    String redirectTitle = null;
246    
247                    return addPage(
248                            userId, nodeId, title, version, content, summary, minorEdit, format,
249                            head, parentTitle, redirectTitle, serviceContext);
250            }
251    
252            @Override
253            public void addPageAttachment(
254                            long userId, long nodeId, String title, String fileName, File file,
255                            String mimeType)
256                    throws PortalException {
257    
258                    WikiPage page = getPage(nodeId, title);
259    
260                    Folder folder = page.addAttachmentsFolder();
261    
262                    FileEntry fileEntry = PortletFileRepositoryUtil.addPortletFileEntry(
263                            page.getGroupId(), userId, WikiPage.class.getName(),
264                            page.getResourcePrimKey(), PortletKeys.WIKI, folder.getFolderId(),
265                            file, fileName, mimeType, true);
266    
267                    if (userId == 0) {
268                            userId = page.getUserId();
269                    }
270    
271                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
272    
273                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
274                    extraDataJSONObject.put("fileEntryTitle", fileEntry.getTitle());
275                    extraDataJSONObject.put("title", page.getTitle());
276                    extraDataJSONObject.put("version", page.getVersion());
277    
278                    socialActivityLocalService.addActivity(
279                            userId, page.getGroupId(), WikiPage.class.getName(),
280                            page.getResourcePrimKey(),
281                            SocialActivityConstants.TYPE_ADD_ATTACHMENT,
282                            extraDataJSONObject.toString(), 0);
283            }
284    
285            @Override
286            public void addPageAttachment(
287                            long userId, long nodeId, String title, String fileName,
288                            InputStream inputStream, String mimeType)
289                    throws PortalException {
290    
291                    WikiPage page = getPage(nodeId, title);
292    
293                    Folder folder = page.addAttachmentsFolder();
294    
295                    FileEntry fileEntry = PortletFileRepositoryUtil.addPortletFileEntry(
296                            page.getGroupId(), userId, WikiPage.class.getName(),
297                            page.getResourcePrimKey(), PortletKeys.WIKI, folder.getFolderId(),
298                            inputStream, fileName, mimeType, true);
299    
300                    if (userId == 0) {
301                            userId = page.getUserId();
302                    }
303    
304                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
305    
306                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
307                    extraDataJSONObject.put("fileEntryTitle", fileEntry.getTitle());
308                    extraDataJSONObject.put("title", page.getTitle());
309                    extraDataJSONObject.put("version", page.getVersion());
310    
311                    socialActivityLocalService.addActivity(
312                            userId, page.getGroupId(), WikiPage.class.getName(),
313                            page.getResourcePrimKey(),
314                            SocialActivityConstants.TYPE_ADD_ATTACHMENT,
315                            extraDataJSONObject.toString(), 0);
316            }
317    
318            @Override
319            public void addPageAttachments(
320                            long userId, long nodeId, String title,
321                            List<ObjectValuePair<String, InputStream>> inputStreamOVPs)
322                    throws PortalException {
323    
324                    if (inputStreamOVPs.isEmpty()) {
325                            return;
326                    }
327    
328                    for (int i = 0; i < inputStreamOVPs.size(); i++) {
329                            ObjectValuePair<String, InputStream> inputStreamOVP =
330                                    inputStreamOVPs.get(i);
331    
332                            String fileName = inputStreamOVP.getKey();
333                            InputStream inputStream = inputStreamOVP.getValue();
334    
335                            File file = null;
336    
337                            try {
338                                    file = FileUtil.createTempFile(inputStream);
339    
340                                    String mimeType = MimeTypesUtil.getContentType(file, fileName);
341    
342                                    addPageAttachment(
343                                            userId, nodeId, title, fileName, file, mimeType);
344                            }
345                            catch (IOException ioe) {
346                                    throw new SystemException(
347                                            "Unable to write temporary file", ioe);
348                            }
349                            finally {
350                                    FileUtil.delete(file);
351                            }
352                    }
353            }
354    
355            @Override
356            public void addPageResources(
357                            long nodeId, String title, boolean addGroupPermissions,
358                            boolean addGuestPermissions)
359                    throws PortalException {
360    
361                    WikiPage page = getPage(nodeId, title);
362    
363                    addPageResources(page, addGroupPermissions, addGuestPermissions);
364            }
365    
366            @Override
367            public void addPageResources(
368                            long nodeId, String title, String[] groupPermissions,
369                            String[] guestPermissions)
370                    throws PortalException {
371    
372                    WikiPage page = getPage(nodeId, title);
373    
374                    addPageResources(page, groupPermissions, guestPermissions);
375            }
376    
377            @Override
378            public void addPageResources(
379                            WikiPage page, boolean addGroupPermissions,
380                            boolean addGuestPermissions)
381                    throws PortalException {
382    
383                    resourceLocalService.addResources(
384                            page.getCompanyId(), page.getGroupId(), page.getUserId(),
385                            WikiPage.class.getName(), page.getResourcePrimKey(), false,
386                            addGroupPermissions, addGuestPermissions);
387            }
388    
389            @Override
390            public void addPageResources(
391                            WikiPage page, String[] groupPermissions, String[] guestPermissions)
392                    throws PortalException {
393    
394                    resourceLocalService.addModelResources(
395                            page.getCompanyId(), page.getGroupId(), page.getUserId(),
396                            WikiPage.class.getName(), page.getResourcePrimKey(),
397                            groupPermissions, guestPermissions);
398            }
399    
400            @Override
401            public void addTempFileEntry(
402                            long groupId, long userId, String folderName, String fileName,
403                            InputStream inputStream, String mimeType)
404                    throws PortalException {
405    
406                    TempFileEntryUtil.addTempFileEntry(
407                            groupId, userId, folderName, fileName, inputStream, mimeType);
408            }
409    
410            /**
411             * @deprecated As of 7.0.0 replaced by {@link #addTempFileEntry(long, long,
412             *             String, String, InputStream, String)}
413             */
414            @Deprecated
415            @Override
416            public void addTempPageAttachment(
417                            long groupId, long userId, String fileName, String tempFolderName,
418                            InputStream inputStream, String mimeType)
419                    throws PortalException {
420    
421                    addTempFileEntry(
422                            groupId, userId, tempFolderName, fileName, inputStream, mimeType);
423            }
424    
425            @Override
426            public void changeNode(
427                            long userId, long nodeId, String title, long newNodeId,
428                            ServiceContext serviceContext)
429                    throws PortalException {
430    
431                    if (nodeId == newNodeId) {
432                            return;
433                    }
434    
435                    checkNodeChange(nodeId, title, newNodeId);
436    
437                    WikiPage oldPage = getPage(nodeId, title);
438    
439                    oldPage.setParentTitle(StringPool.BLANK);
440    
441                    serviceContext.setCommand(Constants.MOVE);
442    
443                    updatePage(
444                            userId, oldPage, newNodeId, oldPage.getTitle(),
445                            oldPage.getContent(), oldPage.getSummary(), oldPage.getMinorEdit(),
446                            oldPage.getFormat(), oldPage.getParentTitle(),
447                            oldPage.getRedirectTitle(), serviceContext);
448            }
449    
450            @Override
451            public WikiPage changeParent(
452                            long userId, long nodeId, String title, String newParentTitle,
453                            ServiceContext serviceContext)
454                    throws PortalException {
455    
456                    if (Validator.isNotNull(newParentTitle)) {
457                            WikiPage parentPage = getPage(nodeId, newParentTitle);
458    
459                            if (Validator.isNotNull(parentPage.getRedirectTitle())) {
460                                    newParentTitle = parentPage.getRedirectTitle();
461                            }
462                    }
463    
464                    WikiPage page = getPage(nodeId, title);
465    
466                    String originalParentTitle = page.getParentTitle();
467    
468                    double version = page.getVersion();
469                    String content = page.getContent();
470                    String summary = serviceContext.translate(
471                            "changed-parent-from-x", originalParentTitle);
472                    boolean minorEdit = false;
473                    String format = page.getFormat();
474                    String redirectTitle = page.getRedirectTitle();
475    
476                    populateServiceContext(serviceContext, page);
477    
478                    page = updatePage(
479                            userId, nodeId, title, version, content, summary, minorEdit, format,
480                            newParentTitle, redirectTitle, serviceContext);
481    
482                    List<WikiPage> oldPages = wikiPagePersistence.findByN_T_H(
483                            nodeId, title, false);
484    
485                    for (WikiPage oldPage : oldPages) {
486                            if (!WorkflowThreadLocal.isEnabled()) {
487                                    oldPage.setParentTitle(originalParentTitle);
488    
489                                    wikiPagePersistence.update(oldPage);
490                            }
491                    }
492    
493                    return page;
494            }
495    
496            @Override
497            public void copyPageAttachments(
498                            long userId, long templateNodeId, String templateTitle, long nodeId,
499                            String title)
500                    throws PortalException {
501    
502                    WikiPage templatePage = getPage(templateNodeId, templateTitle);
503    
504                    List<FileEntry> templateFileEntries =
505                            templatePage.getAttachmentsFileEntries();
506    
507                    for (FileEntry templateFileEntry : templateFileEntries) {
508                            addPageAttachment(
509                                    userId, nodeId, title, templateFileEntry.getTitle(),
510                                    templateFileEntry.getContentStream(),
511                                    templateFileEntry.getMimeType());
512                    }
513            }
514    
515            @Override
516            public void deletePage(long nodeId, String title) throws PortalException {
517                    List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
518                            nodeId, title, true, 0, 1);
519    
520                    if (!pages.isEmpty()) {
521                            wikiPageLocalService.deletePage(pages.get(0));
522                    }
523            }
524    
525            /**
526             * @deprecated As of 6.2.0 replaced by {@link #discardDraft(long, String,
527             *             double)}
528             */
529            @Deprecated
530            @Override
531            public void deletePage(long nodeId, String title, double version)
532                    throws PortalException {
533    
534                    discardDraft(nodeId, title, version);
535            }
536    
537            @Override
538            @SystemEvent(
539                    action = SystemEventConstants.ACTION_SKIP, send = false,
540                    type = SystemEventConstants.TYPE_DELETE)
541            public void deletePage(WikiPage page) throws PortalException {
542    
543                    // Child pages
544    
545                    List<WikiPage> childPages = wikiPagePersistence.findByN_P(
546                            page.getNodeId(), page.getTitle());
547    
548                    for (WikiPage childPage : childPages) {
549                            if (childPage.isApproved() || childPage.isInTrashImplicitly()) {
550                                    wikiPageLocalService.deletePage(childPage);
551                            }
552                            else {
553                                    childPage.setParentTitle(StringPool.BLANK);
554    
555                                    wikiPagePersistence.update(childPage);
556                            }
557                    }
558    
559                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_R(
560                            page.getNodeId(), page.getTitle());
561    
562                    for (WikiPage redirectPage : redirectPages) {
563                            if (redirectPage.isApproved() ||
564                                    redirectPage.isInTrashImplicitly()) {
565    
566                                    wikiPageLocalService.deletePage(redirectPage);
567                            }
568                            else {
569                                    redirectPage.setRedirectTitle(StringPool.BLANK);
570    
571                                    wikiPagePersistence.update(redirectPage);
572                            }
573                    }
574    
575                    List<WikiPage> versionPages = wikiPagePersistence.findByN_T(
576                            page.getNodeId(), page.getTitle());
577    
578                    wikiPagePersistence.removeByN_T(page.getNodeId(), page.getTitle());
579    
580                    // References
581    
582                    wikiPagePersistence.removeByN_R(page.getNodeId(), page.getTitle());
583    
584                    // Resources
585    
586                    resourceLocalService.deleteResource(
587                            page.getCompanyId(), WikiPage.class.getName(),
588                            ResourceConstants.SCOPE_INDIVIDUAL, page.getResourcePrimKey());
589    
590                    // Resource
591    
592                    WikiPageResource pageResource =
593                            wikiPageResourceLocalService.fetchPageResource(
594                                    page.getNodeId(), page.getTitle());
595    
596                    if (pageResource != null) {
597                            wikiPageResourceLocalService.deleteWikiPageResource(pageResource);
598                    }
599    
600                    // Attachments
601    
602                    long folderId = page.getAttachmentsFolderId();
603    
604                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
605                            PortletFileRepositoryUtil.deletePortletFolder(folderId);
606                    }
607    
608                    // Subscriptions
609    
610                    subscriptionLocalService.deleteSubscriptions(
611                            page.getCompanyId(), WikiPage.class.getName(),
612                            page.getResourcePrimKey());
613    
614                    // Asset
615    
616                    SystemEventHierarchyEntryThreadLocal.pop(
617                            page.getModelClass(), page.getPageId());
618    
619                    try {
620                            for (WikiPage versionPage : versionPages) {
621                                    assetEntryLocalService.deleteEntry(
622                                            WikiPage.class.getName(), versionPage.getPrimaryKey());
623                            }
624                    }
625                    finally {
626                            SystemEventHierarchyEntryThreadLocal.push(
627                                    page.getModelClass(), page.getPageId());
628                    }
629    
630                    assetEntryLocalService.deleteEntry(
631                            WikiPage.class.getName(), page.getResourcePrimKey());
632    
633                    // Expando
634    
635                    expandoRowLocalService.deleteRows(page.getPrimaryKey());
636    
637                    // Message boards
638    
639                    mbMessageLocalService.deleteDiscussionMessages(
640                            WikiPage.class.getName(), page.getResourcePrimKey());
641    
642                    // Trash
643    
644                    if (page.isInTrash()) {
645                            if (page.isInTrashExplicitly()) {
646                                    page.setTitle(TrashUtil.getOriginalTitle(page.getTitle()));
647    
648                                    trashEntryLocalService.deleteEntry(
649                                            WikiPage.class.getName(), page.getResourcePrimKey());
650                            }
651                            else {
652                                    for (WikiPage versionPage : versionPages) {
653                                            trashVersionLocalService.deleteTrashVersion(
654                                                    WikiPage.class.getName(), versionPage.getPageId());
655                                    }
656                            }
657                    }
658    
659                    // Indexer
660    
661                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
662                            WikiPage.class);
663    
664                    indexer.delete(page);
665    
666                    // Cache
667    
668                    clearPageCache(page);
669    
670                    // Version pages
671    
672                    for (WikiPage versionPage : versionPages) {
673    
674                            // Workflow
675    
676                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
677                                    versionPage.getCompanyId(), versionPage.getGroupId(),
678                                    WikiPage.class.getName(), versionPage.getPageId());
679                    }
680    
681                    if (pageResource != null) {
682                            JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
683    
684                            extraDataJSONObject.put("version", page.getVersion());
685    
686                            systemEventLocalService.addSystemEvent(
687                                    0, page.getGroupId(), page.getModelClassName(),
688                                    page.getPrimaryKey(), pageResource.getUuid(), null,
689                                    SystemEventConstants.TYPE_DELETE,
690                                    extraDataJSONObject.toString());
691                    }
692            }
693    
694            @Override
695            public void deletePageAttachment(long nodeId, String title, String fileName)
696                    throws PortalException {
697    
698                    WikiPage page = getPage(nodeId, title);
699    
700                    long folderId = page.getAttachmentsFolderId();
701    
702                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
703                            return;
704                    }
705    
706                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
707                            page.getGroupId(), folderId, fileName);
708    
709                    deletePageAttachment(fileEntry.getFileEntryId());
710            }
711    
712            @Override
713            public void deletePageAttachments(long nodeId, String title)
714                    throws PortalException {
715    
716                    WikiPage page = getPage(nodeId, title);
717    
718                    long folderId = page.getAttachmentsFolderId();
719    
720                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
721                            return;
722                    }
723    
724                    PortletFileRepositoryUtil.deletePortletFileEntries(
725                            page.getGroupId(), folderId);
726            }
727    
728            @Override
729            public void deletePages(long nodeId) throws PortalException {
730                    List<WikiPage> pages = wikiPagePersistence.findByN_H_P(
731                            nodeId, true, StringPool.BLANK);
732    
733                    for (WikiPage page : pages) {
734                            wikiPageLocalService.deletePage(page);
735                    }
736    
737                    pages = wikiPagePersistence.findByN_H_P(
738                            nodeId, false, StringPool.BLANK);
739    
740                    for (WikiPage page : pages) {
741                            wikiPageLocalService.deletePage(page);
742                    }
743            }
744    
745            @Override
746            public void deleteTempFileEntry(
747                            long groupId, long userId, String folderName, String fileName)
748                    throws PortalException {
749    
750                    TempFileEntryUtil.deleteTempFileEntry(
751                            groupId, userId, folderName, fileName);
752            }
753    
754            @Override
755            public void deleteTrashPageAttachments(long nodeId, String title)
756                    throws PortalException {
757    
758                    WikiPage page = getPage(nodeId, title);
759    
760                    long folderId = page.getAttachmentsFolderId();
761    
762                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
763                            return;
764                    }
765    
766                    PortletFileRepositoryUtil.deletePortletFileEntries(
767                            page.getGroupId(), folderId, WorkflowConstants.STATUS_IN_TRASH);
768            }
769    
770            @Override
771            public void discardDraft(long nodeId, String title, double version)
772                    throws PortalException {
773    
774                    wikiPagePersistence.removeByN_T_V(nodeId, title, version);
775            }
776    
777            @Override
778            public WikiPage fetchLatestPage(
779                    long resourcePrimKey, int status, boolean preferApproved) {
780    
781                    WikiPage page = null;
782    
783                    OrderByComparator<WikiPage> orderByComparator =
784                            new PageVersionComparator();
785    
786                    if (status == WorkflowConstants.STATUS_ANY) {
787                            if (preferApproved) {
788                                    page = wikiPagePersistence.fetchByR_S_First(
789                                            resourcePrimKey, WorkflowConstants.STATUS_APPROVED,
790                                            orderByComparator);
791                            }
792    
793                            if (page == null) {
794                                    page = wikiPagePersistence.fetchByResourcePrimKey_First(
795                                            resourcePrimKey, orderByComparator);
796                            }
797                    }
798                    else {
799                            page = wikiPagePersistence.fetchByR_S_First(
800                                    resourcePrimKey, status, orderByComparator);
801                    }
802    
803                    return page;
804            }
805    
806            @Override
807            public WikiPage fetchLatestPage(
808                    long resourcePrimKey, long nodeId, int status, boolean preferApproved) {
809    
810                    WikiPage page = null;
811    
812                    OrderByComparator<WikiPage> orderByComparator =
813                            new PageVersionComparator();
814    
815                    if (status == WorkflowConstants.STATUS_ANY) {
816                            if (preferApproved) {
817                                    page = wikiPagePersistence.fetchByR_N_S_First(
818                                            resourcePrimKey, nodeId, WorkflowConstants.STATUS_APPROVED,
819                                            orderByComparator);
820                            }
821    
822                            if (page == null) {
823                                    page = wikiPagePersistence.fetchByR_N_First(
824                                            resourcePrimKey, nodeId, orderByComparator);
825                            }
826                    }
827                    else {
828                            page = wikiPagePersistence.fetchByR_N_S_First(
829                                    resourcePrimKey, nodeId, status, orderByComparator);
830                    }
831    
832                    return page;
833            }
834    
835            @Override
836            public WikiPage fetchLatestPage(
837                    long nodeId, String title, int status, boolean preferApproved) {
838    
839                    WikiPage page = null;
840    
841                    OrderByComparator<WikiPage> orderByComparator =
842                            new PageVersionComparator();
843    
844                    if (status == WorkflowConstants.STATUS_ANY) {
845                            if (preferApproved) {
846                                    page = wikiPagePersistence.fetchByN_T_S_First(
847                                            nodeId, title, WorkflowConstants.STATUS_APPROVED,
848                                            orderByComparator);
849                            }
850    
851                            if (page == null) {
852                                    page = wikiPagePersistence.fetchByN_T_First(
853                                            nodeId, title, orderByComparator);
854                            }
855                    }
856                    else {
857                            page = wikiPagePersistence.fetchByN_T_S_First(
858                                    nodeId, title, status, orderByComparator);
859                    }
860    
861                    return page;
862            }
863    
864            @Override
865            public WikiPage fetchPage(long resourcePrimKey) {
866                    WikiPageResource pageResource =
867                            wikiPageResourceLocalService.fetchWikiPageResource(resourcePrimKey);
868    
869                    if (pageResource == null) {
870                            return null;
871                    }
872    
873                    return fetchPage(pageResource.getNodeId(), pageResource.getTitle());
874            }
875    
876            @Override
877            public WikiPage fetchPage(long nodeId, String title) {
878                    return wikiPagePersistence.fetchByN_T_H_First(
879                            nodeId, title, true, null);
880            }
881    
882            @Override
883            public WikiPage fetchPage(long nodeId, String title, double version) {
884                    WikiPage page = null;
885    
886                    if (version == 0) {
887                            page = fetchPage(nodeId, title);
888                    }
889                    else {
890                            page = wikiPagePersistence.fetchByN_T_V(nodeId, title, version);
891                    }
892    
893                    return page;
894            }
895    
896            @Override
897            public List<WikiPage> getChildren(
898                    long nodeId, boolean head, String parentTitle) {
899    
900                    return getChildren(
901                            nodeId, head, parentTitle, WorkflowConstants.STATUS_APPROVED);
902            }
903    
904            @Override
905            public List<WikiPage> getChildren(
906                    long nodeId, boolean head, String parentTitle, int status) {
907    
908                    return wikiPagePersistence.findByN_H_P_S(
909                            nodeId, head, parentTitle, status);
910            }
911    
912            @Override
913            public List<WikiPage> getChildren(
914                    long nodeId, boolean head, String parentTitle, int start, int end) {
915    
916                    return wikiPagePersistence.findByN_H_P_S(
917                            nodeId, head, parentTitle, WorkflowConstants.STATUS_APPROVED, start,
918                            end);
919            }
920    
921            @Override
922            public int getChildrenCount(long nodeId, boolean head, String parentTitle) {
923                    return getChildrenCount(
924                            nodeId, head, parentTitle, WorkflowConstants.STATUS_APPROVED);
925            }
926    
927            @Override
928            public int getChildrenCount(
929                    long nodeId, boolean head, String parentTitle, int status) {
930    
931                    return wikiPagePersistence.countByN_H_P_S(
932                            nodeId, head, parentTitle, status);
933            }
934    
935            @Override
936            public List<WikiPage> getDependentPages(
937                    long nodeId, boolean head, String title, int status) {
938    
939                    List<WikiPage> dependentPages = new ArrayList<>();
940    
941                    List<WikiPage> childPages = getChildren(nodeId, head, title, status);
942    
943                    dependentPages.addAll(childPages);
944    
945                    List<WikiPage> redirectPages = getRedirectPages(
946                            nodeId, head, title, status);
947    
948                    dependentPages.addAll(redirectPages);
949    
950                    return dependentPages;
951            }
952    
953            @Override
954            public WikiPage getDraftPage(long nodeId, String title)
955                    throws PortalException {
956    
957                    List<WikiPage> pages = wikiPagePersistence.findByN_T_S(
958                            nodeId, title, WorkflowConstants.STATUS_DRAFT, 0, 1);
959    
960                    if (!pages.isEmpty()) {
961                            return pages.get(0);
962                    }
963    
964                    pages = wikiPagePersistence.findByN_T_S(
965                            nodeId, title, WorkflowConstants.STATUS_PENDING, 0, 1);
966    
967                    if (!pages.isEmpty()) {
968                            return pages.get(0);
969                    }
970                    else {
971                            StringBundler sb = new StringBundler(5);
972    
973                            sb.append("{nodeId=");
974                            sb.append(nodeId);
975                            sb.append(", title=");
976                            sb.append(title);
977                            sb.append("}");
978    
979                            throw new NoSuchPageException(sb.toString());
980                    }
981            }
982    
983            @Override
984            public List<WikiPage> getIncomingLinks(long nodeId, String title)
985                    throws PortalException {
986    
987                    Set<WikiPage> links = new HashSet<WikiPage>();
988    
989                    List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
990    
991                    for (WikiPage page : pages) {
992                            if (isLinkedTo(page, title)) {
993                                    links.add(page);
994                            }
995                    }
996    
997                    List<WikiPage> referrals = wikiPagePersistence.findByN_R(nodeId, title);
998    
999                    for (WikiPage referral : referrals) {
1000                            for (WikiPage page : pages) {
1001                                    if (isLinkedTo(page, referral.getTitle())) {
1002                                            links.add(page);
1003                                    }
1004                            }
1005                    }
1006    
1007                    return ListUtil.sort(new ArrayList<WikiPage>(links));
1008            }
1009    
1010            @Override
1011            public WikiPage getLatestPage(
1012                            long resourcePrimKey, int status, boolean preferApproved)
1013                    throws PortalException {
1014    
1015                    WikiPage page = fetchLatestPage(
1016                            resourcePrimKey, status, preferApproved);
1017    
1018                    if (page == null) {
1019                            StringBundler sb = new StringBundler(5);
1020    
1021                            sb.append("{resourcePrimKey=");
1022                            sb.append(resourcePrimKey);
1023                            sb.append(", status=");
1024                            sb.append(status);
1025                            sb.append("}");
1026    
1027                            throw new NoSuchPageException(sb.toString());
1028                    }
1029    
1030                    return page;
1031            }
1032    
1033            @Override
1034            public WikiPage getLatestPage(
1035                            long resourcePrimKey, long nodeId, int status,
1036                            boolean preferApproved)
1037                    throws PortalException {
1038    
1039                    WikiPage page = fetchLatestPage(
1040                            resourcePrimKey, nodeId, status, preferApproved);
1041    
1042                    if (page == null) {
1043                            StringBundler sb = new StringBundler(7);
1044    
1045                            sb.append("{resourcePrimKey=");
1046                            sb.append(resourcePrimKey);
1047                            sb.append(", nodeId=");
1048                            sb.append(nodeId);
1049                            sb.append(", status=");
1050                            sb.append(status);
1051                            sb.append("}");
1052    
1053                            throw new NoSuchPageException(sb.toString());
1054                    }
1055    
1056                    return page;
1057            }
1058    
1059            @Override
1060            public WikiPage getLatestPage(
1061                            long nodeId, String title, int status, boolean preferApproved)
1062                    throws PortalException {
1063    
1064                    WikiPage page = fetchLatestPage(nodeId, title, status, preferApproved);
1065    
1066                    if (page == null) {
1067                            StringBundler sb = new StringBundler(7);
1068    
1069                            sb.append("{nodeId=");
1070                            sb.append(nodeId);
1071                            sb.append(", title=");
1072                            sb.append(title);
1073                            sb.append(", status=");
1074                            sb.append(status);
1075                            sb.append("}");
1076    
1077                            throw new NoSuchPageException(sb.toString());
1078                    }
1079    
1080                    return page;
1081            }
1082    
1083            @Override
1084            public List<WikiPage> getNoAssetPages() {
1085                    return wikiPageFinder.findByNoAssets();
1086            }
1087    
1088            @Override
1089            public List<WikiPage> getOrphans(long nodeId) throws PortalException {
1090                    List<WikiPage> pages = wikiPagePersistence.findByN_H_S(
1091                            nodeId, true, WorkflowConstants.STATUS_APPROVED);
1092    
1093                    return WikiUtil.filterOrphans(pages);
1094            }
1095    
1096            @Override
1097            public List<WikiPage> getOutgoingLinks(long nodeId, String title)
1098                    throws PortalException {
1099    
1100                    WikiPage page = getPage(nodeId, title);
1101    
1102                    Map<String, WikiPage> pages = new LinkedHashMap<String, WikiPage>();
1103    
1104                    Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
1105    
1106                    for (Map.Entry<String, Boolean> entry : links.entrySet()) {
1107                            String curTitle = entry.getKey();
1108                            Boolean exists = entry.getValue();
1109    
1110                            if (exists) {
1111                                    WikiPage curPage = getPage(nodeId, curTitle);
1112    
1113                                    if (!pages.containsKey(curPage.getTitle())) {
1114                                            pages.put(curPage.getTitle(), curPage);
1115                                    }
1116                            }
1117                            else {
1118                                    WikiPageImpl newPage = new WikiPageImpl();
1119    
1120                                    newPage.setNew(true);
1121                                    newPage.setNodeId(nodeId);
1122                                    newPage.setTitle(curTitle);
1123    
1124                                    if (!pages.containsKey(curTitle)) {
1125                                            pages.put(curTitle, newPage);
1126                                    }
1127                            }
1128                    }
1129    
1130                    return ListUtil.fromMapValues(pages);
1131            }
1132    
1133            @Override
1134            public WikiPage getPage(long resourcePrimKey) throws PortalException {
1135                    return getPage(resourcePrimKey, Boolean.TRUE);
1136            }
1137    
1138            @Override
1139            public WikiPage getPage(long resourcePrimKey, Boolean head)
1140                    throws PortalException {
1141    
1142                    WikiPageResource pageResource =
1143                            wikiPageResourceLocalService.getPageResource(resourcePrimKey);
1144    
1145                    return getPage(pageResource.getNodeId(), pageResource.getTitle(), head);
1146            }
1147    
1148            @Override
1149            public WikiPage getPage(long nodeId, String title) throws PortalException {
1150                    WikiPage page = fetchPage(nodeId, title);
1151    
1152                    if (page != null) {
1153                            return page;
1154                    }
1155                    else {
1156                            StringBundler sb = new StringBundler(5);
1157    
1158                            sb.append("{nodeId=");
1159                            sb.append(nodeId);
1160                            sb.append(", title=");
1161                            sb.append(title);
1162                            sb.append("}");
1163    
1164                            throw new NoSuchPageException(sb.toString());
1165                    }
1166            }
1167    
1168            @Override
1169            public WikiPage getPage(long nodeId, String title, Boolean head)
1170                    throws PortalException {
1171    
1172                    List<WikiPage> pages;
1173    
1174                    if (head == null) {
1175                            pages = wikiPagePersistence.findByN_T(nodeId, title, 0, 1);
1176                    }
1177                    else {
1178                            pages = wikiPagePersistence.findByN_T_H(nodeId, title, head, 0, 1);
1179                    }
1180    
1181                    if (!pages.isEmpty()) {
1182                            return pages.get(0);
1183                    }
1184                    else {
1185                            StringBundler sb = new StringBundler(7);
1186    
1187                            sb.append("{nodeId=");
1188                            sb.append(nodeId);
1189                            sb.append(", title=");
1190                            sb.append(title);
1191                            sb.append(", head=");
1192                            sb.append(head);
1193                            sb.append("}");
1194    
1195                            throw new NoSuchPageException(sb.toString());
1196                    }
1197            }
1198    
1199            @Override
1200            public WikiPage getPage(long nodeId, String title, double version)
1201                    throws PortalException {
1202    
1203                    WikiPage page = null;
1204    
1205                    if (version == 0) {
1206                            page = getPage(nodeId, title);
1207                    }
1208                    else {
1209                            page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
1210                    }
1211    
1212                    return page;
1213            }
1214    
1215            @Override
1216            public WikiPage getPageByPageId(long pageId) throws PortalException {
1217                    return wikiPagePersistence.findByPrimaryKey(pageId);
1218            }
1219    
1220            @Override
1221            public WikiPageDisplay getPageDisplay(
1222                            long nodeId, String title, PortletURL viewPageURL,
1223                            PortletURL editPageURL, String attachmentURLPrefix)
1224                    throws PortalException {
1225    
1226                    WikiPage page = getPage(nodeId, title);
1227    
1228                    return getPageDisplay(
1229                            page, viewPageURL, editPageURL, attachmentURLPrefix);
1230            }
1231    
1232            @Override
1233            public WikiPageDisplay getPageDisplay(
1234                            WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
1235                            String attachmentURLPrefix)
1236                    throws PortalException {
1237    
1238                    String formattedContent = WikiUtil.convert(
1239                            page, viewPageURL, editPageURL, attachmentURLPrefix);
1240    
1241                    return new WikiPageDisplayImpl(
1242                            page.getUserId(), page.getNodeId(), page.getTitle(),
1243                            page.getVersion(), page.getContent(), formattedContent,
1244                            page.getFormat(), page.getHead(), page.getAttachmentsFileEntries());
1245            }
1246    
1247            @Override
1248            public List<WikiPage> getPages(
1249                    long nodeId, boolean head, int start, int end) {
1250    
1251                    return getPages(
1252                            nodeId, head, start, end, new PageCreateDateComparator(false));
1253            }
1254    
1255            @Override
1256            public List<WikiPage> getPages(
1257                    long nodeId, boolean head, int status, int start, int end) {
1258    
1259                    return getPages(
1260                            nodeId, head, status, start, end,
1261                            new PageCreateDateComparator(false));
1262            }
1263    
1264            @Override
1265            public List<WikiPage> getPages(
1266                    long nodeId, boolean head, int status, int start, int end,
1267                    OrderByComparator<WikiPage> obc) {
1268    
1269                    if (status == WorkflowConstants.STATUS_ANY) {
1270                            return wikiPagePersistence.findByN_H(nodeId, head, start, end, obc);
1271                    }
1272                    else {
1273                            return wikiPagePersistence.findByN_H_S(
1274                                    nodeId, head, status, start, end, obc);
1275                    }
1276            }
1277    
1278            @Override
1279            public List<WikiPage> getPages(
1280                    long nodeId, boolean head, int start, int end,
1281                    OrderByComparator<WikiPage> obc) {
1282    
1283                    return getPages(
1284                            nodeId, head, WorkflowConstants.STATUS_APPROVED, start, end, obc);
1285            }
1286    
1287            @Override
1288            public List<WikiPage> getPages(long nodeId, int start, int end) {
1289                    return getPages(
1290                            nodeId, start, end, new PageCreateDateComparator(false));
1291            }
1292    
1293            @Override
1294            public List<WikiPage> getPages(
1295                    long nodeId, int start, int end, OrderByComparator<WikiPage> obc) {
1296    
1297                    return wikiPagePersistence.findByNodeId(nodeId, start, end, obc);
1298            }
1299    
1300            @Override
1301            public List<WikiPage> getPages(
1302                    long resourcePrimKey, long nodeId, int status) {
1303    
1304                    return wikiPagePersistence.findByR_N_S(resourcePrimKey, nodeId, status);
1305            }
1306    
1307            @Override
1308            public List<WikiPage> getPages(
1309                    long userId, long nodeId, int status, int start, int end) {
1310    
1311                    if (userId > 0) {
1312                            return wikiPagePersistence.findByU_N_S(
1313                                    userId, nodeId, status, start, end,
1314                                    new PageCreateDateComparator(false));
1315                    }
1316                    else {
1317                            return wikiPagePersistence.findByN_S(
1318                                    nodeId, status, start, end,
1319                                    new PageCreateDateComparator(false));
1320                    }
1321            }
1322    
1323            @Override
1324            public List<WikiPage> getPages(
1325                    long nodeId, String title, boolean head, int start, int end) {
1326    
1327                    return wikiPagePersistence.findByN_T_H(
1328                            nodeId, title, head, start, end,
1329                            new PageCreateDateComparator(false));
1330            }
1331    
1332            @Override
1333            public List<WikiPage> getPages(
1334                    long nodeId, String title, int start, int end) {
1335    
1336                    return wikiPagePersistence.findByN_T(
1337                            nodeId, title, start, end, new PageCreateDateComparator(false));
1338            }
1339    
1340            @Override
1341            public List<WikiPage> getPages(
1342                    long nodeId, String title, int start, int end,
1343                    OrderByComparator<WikiPage> obc) {
1344    
1345                    return wikiPagePersistence.findByN_T(nodeId, title, start, end, obc);
1346            }
1347    
1348            @Override
1349            public List<WikiPage> getPages(String format) {
1350                    return wikiPagePersistence.findByFormat(format);
1351            }
1352    
1353            @Override
1354            public int getPagesCount(long nodeId) {
1355                    return wikiPagePersistence.countByNodeId(nodeId);
1356            }
1357    
1358            @Override
1359            public int getPagesCount(long nodeId, boolean head) {
1360                    return wikiPagePersistence.countByN_H_S(
1361                            nodeId, head, WorkflowConstants.STATUS_APPROVED);
1362            }
1363    
1364            @Override
1365            public int getPagesCount(long nodeId, boolean head, int status) {
1366                    if (status == WorkflowConstants.STATUS_ANY) {
1367                            return wikiPagePersistence.countByN_H_NotS(
1368                                    nodeId, head, WorkflowConstants.STATUS_IN_TRASH);
1369                    }
1370                    else {
1371                            return wikiPagePersistence.countByN_H_S(nodeId, head, status);
1372                    }
1373            }
1374    
1375            @Override
1376            public int getPagesCount(long nodeId, int status) {
1377                    return wikiPagePersistence.countByN_S(nodeId, status);
1378            }
1379    
1380            @Override
1381            public int getPagesCount(long userId, long nodeId, int status) {
1382                    if (userId > 0) {
1383                            return wikiPagePersistence.countByU_N_S(userId, nodeId, status);
1384                    }
1385                    else {
1386                            return wikiPagePersistence.countByN_S(nodeId, status);
1387                    }
1388            }
1389    
1390            @Override
1391            public int getPagesCount(long nodeId, String title) {
1392                    return wikiPagePersistence.countByN_T(nodeId, title);
1393            }
1394    
1395            @Override
1396            public int getPagesCount(long nodeId, String title, boolean head) {
1397                    return wikiPagePersistence.countByN_T_H(nodeId, title, head);
1398            }
1399    
1400            @Override
1401            public int getPagesCount(String format) {
1402                    return wikiPagePersistence.countByFormat(format);
1403            }
1404    
1405            @Override
1406            public WikiPage getPreviousVersionPage(WikiPage page)
1407                    throws PortalException {
1408    
1409                    double previousVersion = MathUtil.format(page.getVersion() - 0.1, 1, 1);
1410    
1411                    if (previousVersion < 1) {
1412                            return null;
1413                    }
1414    
1415                    return getPage(page.getNodeId(), page.getTitle(), previousVersion);
1416            }
1417    
1418            /**
1419             * @deprecated As of 6.2.0, replaced by {@link #getRecentChanges(long, long,
1420             *             int, int)}
1421             */
1422            @Deprecated
1423            @Override
1424            public List<WikiPage> getRecentChanges(long nodeId, int start, int end)
1425                    throws PortalException {
1426    
1427                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
1428    
1429                    return getRecentChanges(node.getGroupId(), nodeId, start, end);
1430            }
1431    
1432            @Override
1433            public List<WikiPage> getRecentChanges(
1434                    long groupId, long nodeId, int start, int end) {
1435    
1436                    Calendar cal = CalendarFactoryUtil.getCalendar();
1437    
1438                    cal.add(Calendar.WEEK_OF_YEAR, -1);
1439    
1440                    return wikiPageFinder.findByCreateDate(
1441                            groupId, nodeId, cal.getTime(), false, start, end);
1442            }
1443    
1444            /**
1445             * @deprecated As of 6.2.0, replaced by {@link #getRecentChangesCount(long,
1446             *             long)}
1447             */
1448            @Deprecated
1449            @Override
1450            public int getRecentChangesCount(long nodeId) throws PortalException {
1451                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
1452    
1453                    return getRecentChangesCount(node.getGroupId(), nodeId);
1454            }
1455    
1456            @Override
1457            public int getRecentChangesCount(long groupId, long nodeId) {
1458                    Calendar cal = CalendarFactoryUtil.getCalendar();
1459    
1460                    cal.add(Calendar.WEEK_OF_YEAR, -1);
1461    
1462                    return wikiPageFinder.countByCreateDate(
1463                            groupId, nodeId, cal.getTime(), false);
1464            }
1465    
1466            @Override
1467            public List<WikiPage> getRedirectPages(
1468                    long nodeId, boolean head, String redirectTitle, int status) {
1469    
1470                    return wikiPagePersistence.findByN_H_R_S(
1471                            nodeId, head, redirectTitle, status);
1472            }
1473    
1474            @Override
1475            public String[] getTempFileNames(
1476                            long groupId, long userId, String folderName)
1477                    throws PortalException {
1478    
1479                    return TempFileEntryUtil.getTempFileNames(groupId, userId, folderName);
1480            }
1481    
1482            @Override
1483            public boolean hasDraftPage(long nodeId, String title) {
1484                    int count = wikiPagePersistence.countByN_T_S(
1485                            nodeId, title, WorkflowConstants.STATUS_DRAFT);
1486    
1487                    if (count > 0) {
1488                            return true;
1489                    }
1490                    else {
1491                            return false;
1492                    }
1493            }
1494    
1495            @Override
1496            public void moveDependentToTrash(WikiPage page, long trashEntryId)
1497                    throws PortalException {
1498    
1499                    moveDependentToTrash(page, trashEntryId, false);
1500            }
1501    
1502            /**
1503             * @deprecated As of 6.2.0, replaced by {@link #renamePage(long, long,
1504             *             String, String, boolean, ServiceContext)}
1505             */
1506            @Deprecated
1507            @Override
1508            public void movePage(
1509                            long userId, long nodeId, String title, String newTitle,
1510                            boolean strict, ServiceContext serviceContext)
1511                    throws PortalException {
1512    
1513                    renamePage(userId, nodeId, title, newTitle, strict, serviceContext);
1514            }
1515    
1516            /**
1517             * @deprecated As of 7.0.0, replaced by {@link #renamePage(long, long,
1518             *             String, String, ServiceContext)}
1519             */
1520            @Deprecated
1521            @Override
1522            public void movePage(
1523                            long userId, long nodeId, String title, String newTitle,
1524                            ServiceContext serviceContext)
1525                    throws PortalException {
1526    
1527                    renamePage(userId, nodeId, title, newTitle, true, serviceContext);
1528            }
1529    
1530            @Override
1531            public FileEntry movePageAttachmentToTrash(
1532                            long userId, long nodeId, String title, String fileName)
1533                    throws PortalException {
1534    
1535                    WikiPage page = getPage(nodeId, title);
1536    
1537                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1538                            page.getGroupId(), page.getAttachmentsFolderId(), fileName);
1539    
1540                    fileEntry = PortletFileRepositoryUtil.movePortletFileEntryToTrash(
1541                            userId, fileEntry.getFileEntryId());
1542    
1543                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1544    
1545                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
1546                    extraDataJSONObject.put(
1547                            "fileEntryTitle", TrashUtil.getOriginalTitle(fileEntry.getTitle()));
1548                    extraDataJSONObject.put("title", page.getTitle());
1549                    extraDataJSONObject.put("version", page.getVersion());
1550    
1551                    socialActivityLocalService.addActivity(
1552                            userId, page.getGroupId(), WikiPage.class.getName(),
1553                            page.getResourcePrimKey(),
1554                            SocialActivityConstants.TYPE_MOVE_ATTACHMENT_TO_TRASH,
1555                            extraDataJSONObject.toString(), 0);
1556    
1557                    return fileEntry;
1558            }
1559    
1560            @Override
1561            public WikiPage movePageFromTrash(
1562                            long userId, long nodeId, String title, long newNodeId,
1563                            String newParentTitle)
1564                    throws PortalException {
1565    
1566                    WikiPage page = getPage(nodeId, title);
1567    
1568                    if (page.isInTrashExplicitly()) {
1569                            movePageFromTrash(userId, page, newNodeId, newParentTitle);
1570                    }
1571                    else {
1572                            moveDependentFromTrash(page, newNodeId, newParentTitle);
1573                    }
1574    
1575                    return page;
1576            }
1577    
1578            /**
1579             * @deprecated As of 7.0.0, replaced by {@link #movePageFromTrash(long,
1580             *             long, String, long, String)} *
1581             */
1582            @Deprecated
1583            @Override
1584            public WikiPage movePageFromTrash(
1585                            long userId, long nodeId, String title, String newParentTitle,
1586                            ServiceContext serviceContext)
1587                    throws PortalException {
1588    
1589                    return movePageFromTrash(userId, nodeId, title, nodeId, newParentTitle);
1590            }
1591    
1592            @Override
1593            public WikiPage movePageToTrash(long userId, long nodeId, String title)
1594                    throws PortalException {
1595    
1596                    List<WikiPage> wikiPages = wikiPagePersistence.findByN_T_H(
1597                            nodeId, title, true, 0, 1);
1598    
1599                    if (!wikiPages.isEmpty()) {
1600                            return movePageToTrash(userId, wikiPages.get(0));
1601                    }
1602    
1603                    return null;
1604            }
1605    
1606            @Override
1607            public WikiPage movePageToTrash(
1608                            long userId, long nodeId, String title, double version)
1609                    throws PortalException {
1610    
1611                    WikiPage page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
1612    
1613                    return movePageToTrash(userId, page);
1614            }
1615    
1616            @Override
1617            public WikiPage movePageToTrash(long userId, WikiPage page)
1618                    throws PortalException {
1619    
1620                    // Page
1621    
1622                    int oldStatus = page.getStatus();
1623                    String oldTitle = page.getTitle();
1624    
1625                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
1626                            page.setStatus(WorkflowConstants.STATUS_DRAFT);
1627    
1628                            wikiPagePersistence.update(page);
1629                    }
1630    
1631                    List<WikiPage> pageVersions = wikiPagePersistence.findByR_N_H(
1632                            page.getResourcePrimKey(), page.getNodeId(), false);
1633    
1634                    pageVersions = ListUtil.sort(pageVersions, new PageVersionComparator());
1635    
1636                    List<ObjectValuePair<Long, Integer>> pageVersionStatusOVPs =
1637                            new ArrayList<ObjectValuePair<Long, Integer>>();
1638    
1639                    if ((pageVersions != null) && !pageVersions.isEmpty()) {
1640                            pageVersionStatusOVPs = getPageVersionStatuses(pageVersions);
1641                    }
1642    
1643                    page = updateStatus(
1644                            userId, page, WorkflowConstants.STATUS_IN_TRASH,
1645                            new ServiceContext(), new HashMap<String, Serializable>());
1646    
1647                    // Trash
1648    
1649                    WikiPageResource pageResource =
1650                            wikiPageResourcePersistence.fetchByPrimaryKey(
1651                                    page.getResourcePrimKey());
1652    
1653                    UnicodeProperties typeSettingsProperties = new UnicodeProperties();
1654    
1655                    typeSettingsProperties.put("title", page.getTitle());
1656    
1657                    TrashEntry trashEntry = trashEntryLocalService.addTrashEntry(
1658                            userId, page.getGroupId(), WikiPage.class.getName(),
1659                            page.getResourcePrimKey(), pageResource.getUuid(), null, oldStatus,
1660                            pageVersionStatusOVPs, typeSettingsProperties);
1661    
1662                    String trashTitle = TrashUtil.getTrashTitle(trashEntry.getEntryId());
1663    
1664                    for (WikiPage pageVersion : pageVersions) {
1665                            pageVersion.setTitle(trashTitle);
1666                            pageVersion.setStatus(WorkflowConstants.STATUS_IN_TRASH);
1667    
1668                            wikiPagePersistence.update(pageVersion);
1669                    }
1670    
1671                    pageResource.setTitle(trashTitle);
1672    
1673                    wikiPageResourcePersistence.update(pageResource);
1674    
1675                    page.setTitle(trashTitle);
1676    
1677                    wikiPagePersistence.update(page);
1678    
1679                    // Child pages
1680    
1681                    moveDependentChildPagesToTrash(
1682                            page, oldTitle, trashTitle, trashEntry.getEntryId(), true);
1683    
1684                    // Redirect pages
1685    
1686                    moveDependentRedirectPagesToTrash(
1687                            page, oldTitle, trashTitle, trashEntry.getEntryId(), true);
1688    
1689                    // Asset
1690    
1691                    assetEntryLocalService.updateVisible(
1692                            WikiPage.class.getName(), page.getResourcePrimKey(), false);
1693    
1694                    // Social
1695    
1696                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1697    
1698                    extraDataJSONObject.put(
1699                            "title", TrashUtil.getOriginalTitle(page.getTitle()));
1700                    extraDataJSONObject.put("version", page.getVersion());
1701    
1702                    socialActivityLocalService.addActivity(
1703                            userId, page.getGroupId(), WikiPage.class.getName(),
1704                            page.getResourcePrimKey(),
1705                            SocialActivityConstants.TYPE_MOVE_TO_TRASH,
1706                            extraDataJSONObject.toString(), 0);
1707    
1708                    if (!pageVersions.isEmpty()) {
1709                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1710                                    WikiPage.class);
1711    
1712                            for (WikiPage pageVersion : pageVersions) {
1713                                    indexer.reindex(pageVersion);
1714                            }
1715                    }
1716    
1717                    // Workflow
1718    
1719                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
1720                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
1721                                    page.getCompanyId(), page.getGroupId(),
1722                                    WikiPage.class.getName(), page.getPageId());
1723                    }
1724    
1725                    return page;
1726            }
1727    
1728            @Override
1729            public void renamePage(
1730                            long userId, long nodeId, String title, String newTitle,
1731                            boolean strict, ServiceContext serviceContext)
1732                    throws PortalException {
1733    
1734                    validateTitle(newTitle);
1735    
1736                    if (StringUtil.equalsIgnoreCase(title, newTitle)) {
1737                            throw new DuplicatePageException(newTitle);
1738                    }
1739    
1740                    if (isUsedTitle(nodeId, newTitle)) {
1741    
1742                            // Support moving back to a previously moved title
1743    
1744                            WikiPage page = getPage(nodeId, newTitle);
1745    
1746                            if (((page.getVersion() == WikiPageConstants.VERSION_DEFAULT) &&
1747                                     (page.getContent().length() < 200)) ||
1748                                    !strict) {
1749    
1750                                    deletePage(nodeId, newTitle);
1751                            }
1752                            else {
1753                                    throw new DuplicatePageException(newTitle);
1754                            }
1755                    }
1756    
1757                    WikiPage page = getPage(nodeId, title);
1758    
1759                    String summary = page.getSummary();
1760    
1761                    if (Validator.isNotNull(page.getRedirectTitle())) {
1762                            page.setRedirectTitle(StringPool.BLANK);
1763    
1764                            summary = StringPool.BLANK;
1765                    }
1766    
1767                    serviceContext.setCommand(Constants.RENAME);
1768    
1769                    updatePage(
1770                            userId, page, 0, newTitle, page.getContent(), summary,
1771                            page.getMinorEdit(), page.getFormat(), page.getParentTitle(),
1772                            page.getRedirectTitle(), serviceContext);
1773            }
1774    
1775            @Override
1776            public void renamePage(
1777                            long userId, long nodeId, String title, String newTitle,
1778                            ServiceContext serviceContext)
1779                    throws PortalException {
1780    
1781                    renamePage(userId, nodeId, title, newTitle, true, serviceContext);
1782            }
1783    
1784            @Override
1785            public void restorePageAttachmentFromTrash(
1786                            long userId, long nodeId, String title, String fileName)
1787                    throws PortalException {
1788    
1789                    WikiPage page = getPage(nodeId, title);
1790    
1791                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1792                            page.getGroupId(), page.getAttachmentsFolderId(), fileName);
1793    
1794                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1795    
1796                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
1797                    extraDataJSONObject.put(
1798                            "fileEntryTitle", TrashUtil.getOriginalTitle(fileEntry.getTitle()));
1799                    extraDataJSONObject.put("title", page.getTitle());
1800                    extraDataJSONObject.put("version", page.getVersion());
1801    
1802                    PortletFileRepositoryUtil.restorePortletFileEntryFromTrash(
1803                            userId, fileEntry.getFileEntryId());
1804    
1805                    socialActivityLocalService.addActivity(
1806                            userId, page.getGroupId(), WikiPage.class.getName(),
1807                            page.getResourcePrimKey(),
1808                            SocialActivityConstants.TYPE_RESTORE_ATTACHMENT_FROM_TRASH,
1809                            extraDataJSONObject.toString(), 0);
1810            }
1811    
1812            @Override
1813            public void restorePageFromTrash(long userId, WikiPage page)
1814                    throws PortalException {
1815    
1816                    if (page.isInTrashExplicitly()) {
1817                            movePageFromTrash(
1818                                    userId, page, page.getNodeId(), page.getParentTitle());
1819                    }
1820                    else {
1821                            moveDependentFromTrash(
1822                                    page, page.getNodeId(), page.getParentTitle());
1823                    }
1824            }
1825    
1826            @Override
1827            public WikiPage revertPage(
1828                            long userId, long nodeId, String title, double version,
1829                            ServiceContext serviceContext)
1830                    throws PortalException {
1831    
1832                    WikiPage oldPage = getPage(nodeId, title, version);
1833    
1834                    populateServiceContext(serviceContext, oldPage);
1835    
1836                    return updatePage(
1837                            userId, nodeId, title, 0, oldPage.getContent(),
1838                            WikiPageConstants.REVERTED + " to " + version, false,
1839                            oldPage.getFormat(), getParentPageTitle(oldPage),
1840                            oldPage.getRedirectTitle(), serviceContext);
1841            }
1842    
1843            @Override
1844            public void subscribePage(long userId, long nodeId, String title)
1845                    throws PortalException {
1846    
1847                    WikiPage page = getPage(nodeId, title);
1848    
1849                    subscriptionLocalService.addSubscription(
1850                            userId, page.getGroupId(), WikiPage.class.getName(),
1851                            page.getResourcePrimKey());
1852            }
1853    
1854            @Override
1855            public void unsubscribePage(long userId, long nodeId, String title)
1856                    throws PortalException {
1857    
1858                    WikiPage page = getPage(nodeId, title);
1859    
1860                    subscriptionLocalService.deleteSubscription(
1861                            userId, WikiPage.class.getName(), page.getResourcePrimKey());
1862            }
1863    
1864            @Override
1865            public void updateAsset(
1866                            long userId, WikiPage page, long[] assetCategoryIds,
1867                            String[] assetTagNames, long[] assetLinkEntryIds)
1868                    throws PortalException {
1869    
1870                    boolean addDraftAssetEntry = false;
1871    
1872                    if (!page.isApproved() &&
1873                            (page.getVersion() != WikiPageConstants.VERSION_DEFAULT)) {
1874    
1875                            int approvedPagesCount = wikiPagePersistence.countByN_T_S(
1876                                    page.getNodeId(), page.getTitle(),
1877                                    WorkflowConstants.STATUS_APPROVED);
1878    
1879                            if (approvedPagesCount > 0) {
1880                                    addDraftAssetEntry = true;
1881                            }
1882                    }
1883    
1884                    AssetEntry assetEntry = null;
1885    
1886                    if (addDraftAssetEntry) {
1887                            assetEntry = assetEntryLocalService.updateEntry(
1888                                    userId, page.getGroupId(), page.getCreateDate(),
1889                                    page.getModifiedDate(), WikiPage.class.getName(),
1890                                    page.getPrimaryKey(), page.getUuid(), 0, assetCategoryIds,
1891                                    assetTagNames, false, null, null, null, ContentTypes.TEXT_HTML,
1892                                    page.getTitle(), null, null, null, null, 0, 0, null, false);
1893                    }
1894                    else {
1895                            assetEntry = assetEntryLocalService.updateEntry(
1896                                    userId, page.getGroupId(), page.getCreateDate(),
1897                                    page.getModifiedDate(), WikiPage.class.getName(),
1898                                    page.getResourcePrimKey(), page.getUuid(), 0, assetCategoryIds,
1899                                    assetTagNames, page.isApproved(), null, null, null,
1900                                    ContentTypes.TEXT_HTML, page.getTitle(), null, null, null, null,
1901                                    0, 0, null, false);
1902                    }
1903    
1904                    assetLinkLocalService.updateLinks(
1905                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
1906                            AssetLinkConstants.TYPE_RELATED);
1907            }
1908    
1909            @Override
1910            public WikiPage updatePage(
1911                            long userId, long nodeId, String title, double version,
1912                            String content, String summary, boolean minorEdit, String format,
1913                            String parentTitle, String redirectTitle,
1914                            ServiceContext serviceContext)
1915                    throws PortalException {
1916    
1917                    // Page
1918    
1919                    WikiPage oldPage = null;
1920    
1921                    try {
1922                            oldPage = wikiPagePersistence.findByN_T_First(nodeId, title, null);
1923    
1924                            if ((version > 0) && (version != oldPage.getVersion())) {
1925                                    throw new PageVersionException();
1926                            }
1927    
1928                            return updatePage(
1929                                    userId, oldPage, 0, StringPool.BLANK, content, summary,
1930                                    minorEdit, format, parentTitle, redirectTitle, serviceContext);
1931                    }
1932                    catch (NoSuchPageException nspe) {
1933                            return addPage(
1934                                    userId, nodeId, title, WikiPageConstants.VERSION_DEFAULT,
1935                                    content, summary, minorEdit, format, true, parentTitle,
1936                                    redirectTitle, serviceContext);
1937                    }
1938            }
1939    
1940            @Override
1941            public WikiPage updateStatus(
1942                            long userId, long resourcePrimKey, int status,
1943                            ServiceContext serviceContext)
1944                    throws PortalException {
1945    
1946                    WikiPageResource pageResource =
1947                            wikiPageResourceLocalService.getPageResource(resourcePrimKey);
1948    
1949                    List<WikiPage> pages = wikiPagePersistence.findByN_T(
1950                            pageResource.getNodeId(), pageResource.getTitle(), 0, 1,
1951                            new PageVersionComparator());
1952    
1953                    WikiPage page = null;
1954    
1955                    if (!pages.isEmpty()) {
1956                            page = pages.get(0);
1957                    }
1958                    else {
1959                            throw new NoSuchPageException(
1960                                    "{resourcePrimKey=" + resourcePrimKey + "}");
1961                    }
1962    
1963                    return updateStatus(
1964                            userId, page, status, serviceContext,
1965                            new HashMap<String, Serializable>());
1966            }
1967    
1968            /**
1969             * @deprecated As of 7.0.0, replaced by {@link #updateStatus(long, WikiPage,
1970             *             int, ServiceContext, Map)}
1971             */
1972            @Deprecated
1973            @Override
1974            public WikiPage updateStatus(
1975                            long userId, WikiPage page, int status,
1976                            ServiceContext serviceContext)
1977                    throws PortalException {
1978    
1979                    return updateStatus(
1980                            userId, page, status, serviceContext,
1981                            new HashMap<String, Serializable>());
1982            }
1983    
1984            @Override
1985            public WikiPage updateStatus(
1986                            long userId, WikiPage page, int status,
1987                            ServiceContext serviceContext,
1988                            Map<String, Serializable> workflowContext)
1989                    throws PortalException {
1990    
1991                    // Page
1992    
1993                    User user = userPersistence.findByPrimaryKey(userId);
1994    
1995                    Date now = new Date();
1996    
1997                    int oldStatus = page.getStatus();
1998    
1999                    page.setStatus(status);
2000                    page.setStatusByUserId(userId);
2001                    page.setStatusByUserName(user.getFullName());
2002                    page.setStatusDate(now);
2003    
2004                    wikiPagePersistence.update(page);
2005    
2006                    if (status == WorkflowConstants.STATUS_APPROVED) {
2007                            String cmd = GetterUtil.getString(
2008                                    workflowContext.get(WorkflowConstants.CONTEXT_COMMAND));
2009    
2010                            if (cmd.equals(Constants.MOVE)) {
2011                                    long resourcePrimKey = page.getResourcePrimKey();
2012    
2013                                    WikiPageResource pageResource =
2014                                            wikiPageResourceLocalService.getPageResource(
2015                                                    resourcePrimKey);
2016    
2017                                    page = doChangeNode(
2018                                            userId, pageResource.getNodeId(), page.getTitle(),
2019                                            page.getNodeId(), serviceContext);
2020                            }
2021                            else if (cmd.equals(Constants.RENAME)) {
2022                                    long resourcePrimKey = page.getResourcePrimKey();
2023    
2024                                    WikiPage oldPage = getPage(resourcePrimKey, true);
2025    
2026                                    page = doRenamePage(
2027                                            userId, page.getNodeId(), oldPage.getTitle(),
2028                                            page.getTitle(), serviceContext);
2029                            }
2030    
2031                            // Asset
2032    
2033                            if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
2034                                    (page.getVersion() != WikiPageConstants.VERSION_DEFAULT)) {
2035    
2036                                    AssetEntry draftAssetEntry = assetEntryLocalService.fetchEntry(
2037                                            WikiPage.class.getName(), page.getPrimaryKey());
2038    
2039                                    if (draftAssetEntry != null) {
2040                                            long[] assetCategoryIds = draftAssetEntry.getCategoryIds();
2041                                            String[] assetTagNames = draftAssetEntry.getTagNames();
2042    
2043                                            List<AssetLink> assetLinks =
2044                                                    assetLinkLocalService.getDirectLinks(
2045                                                            draftAssetEntry.getEntryId(),
2046                                                            AssetLinkConstants.TYPE_RELATED);
2047    
2048                                            long[] assetLinkEntryIds = ListUtil.toLongArray(
2049                                                    assetLinks, AssetLink.ENTRY_ID2_ACCESSOR);
2050    
2051                                            AssetEntry assetEntry = assetEntryLocalService.updateEntry(
2052                                                    userId, page.getGroupId(), page.getCreateDate(),
2053                                                    page.getModifiedDate(), WikiPage.class.getName(),
2054                                                    page.getResourcePrimKey(), page.getUuid(), 0,
2055                                                    assetCategoryIds, assetTagNames, true, null, null, null,
2056                                                    ContentTypes.TEXT_HTML, page.getTitle(), null, null,
2057                                                    null, null, 0, 0, null, false);
2058    
2059                                            // Asset Links
2060    
2061                                            assetLinkLocalService.updateLinks(
2062                                                    userId, assetEntry.getEntryId(), assetLinkEntryIds,
2063                                                    AssetLinkConstants.TYPE_RELATED);
2064    
2065                                            SystemEventHierarchyEntryThreadLocal.push(WikiPage.class);
2066    
2067                                            try {
2068                                                    assetEntryLocalService.deleteEntry(
2069                                                            draftAssetEntry.getEntryId());
2070                                            }
2071                                            finally {
2072                                                    SystemEventHierarchyEntryThreadLocal.pop(
2073                                                            WikiPage.class);
2074                                            }
2075                                    }
2076                            }
2077    
2078                            assetEntryLocalService.updateVisible(
2079                                    WikiPage.class.getName(), page.getResourcePrimKey(), true);
2080    
2081                            // Social
2082    
2083                            if ((oldStatus != WorkflowConstants.STATUS_IN_TRASH) &&
2084                                    (page.getVersion() == WikiPageConstants.VERSION_DEFAULT) &&
2085                                    (!page.isMinorEdit() ||
2086                                     PropsValues.WIKI_PAGE_MINOR_EDIT_ADD_SOCIAL_ACTIVITY)) {
2087    
2088                                    JSONObject extraDataJSONObject =
2089                                            JSONFactoryUtil.createJSONObject();
2090    
2091                                    extraDataJSONObject.put("title", page.getTitle());
2092                                    extraDataJSONObject.put("version", page.getVersion());
2093    
2094                                    socialActivityLocalService.addActivity(
2095                                            userId, page.getGroupId(), WikiPage.class.getName(),
2096                                            page.getResourcePrimKey(), WikiActivityKeys.ADD_PAGE,
2097                                            extraDataJSONObject.toString(), 0);
2098                            }
2099    
2100                            // Subscriptions
2101    
2102                            if (NotificationThreadLocal.isEnabled() &&
2103                                    (!page.isMinorEdit() ||
2104                                     PropsValues.WIKI_PAGE_MINOR_EDIT_SEND_EMAIL)) {
2105    
2106                                    notifySubscribers(
2107                                            page,
2108                                            (String)workflowContext.get(WorkflowConstants.CONTEXT_URL),
2109                                            serviceContext);
2110                            }
2111    
2112                            // Cache
2113    
2114                            clearPageCache(page);
2115                    }
2116    
2117                    // Head
2118    
2119                    if (status == WorkflowConstants.STATUS_APPROVED) {
2120                            page.setHead(true);
2121    
2122                            List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
2123                                    page.getNodeId(), page.getTitle(), true);
2124    
2125                            for (WikiPage curPage : pages) {
2126                                    if (!curPage.equals(page)) {
2127                                            curPage.setHead(false);
2128    
2129                                            wikiPagePersistence.update(curPage);
2130                                    }
2131                            }
2132                    }
2133                    else if (status != WorkflowConstants.STATUS_IN_TRASH) {
2134                            page.setHead(false);
2135    
2136                            List<WikiPage> pages = wikiPagePersistence.findByN_T_S(
2137                                    page.getNodeId(), page.getTitle(),
2138                                    WorkflowConstants.STATUS_APPROVED);
2139    
2140                            for (WikiPage curPage : pages) {
2141                                    if (!curPage.equals(page)) {
2142                                            curPage.setHead(true);
2143    
2144                                            wikiPagePersistence.update(curPage);
2145    
2146                                            break;
2147                                    }
2148                            }
2149                    }
2150    
2151                    // Indexer
2152    
2153                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2154                            WikiPage.class);
2155    
2156                    indexer.reindex(page);
2157    
2158                    return wikiPagePersistence.update(page);
2159            }
2160    
2161            @Override
2162            public void validateTitle(String title) throws PortalException {
2163                    if (title.equals("all_pages") || title.equals("orphan_pages") ||
2164                            title.equals("recent_changes")) {
2165    
2166                            throw new PageTitleException(title + " is reserved");
2167                    }
2168    
2169                    if (Validator.isNotNull(PropsValues.WIKI_PAGE_TITLES_REGEXP)) {
2170                            Pattern pattern = Pattern.compile(
2171                                    PropsValues.WIKI_PAGE_TITLES_REGEXP);
2172    
2173                            Matcher matcher = pattern.matcher(title);
2174    
2175                            if (!matcher.matches()) {
2176                                    throw new PageTitleException();
2177                            }
2178                    }
2179            }
2180    
2181            protected void changeChildPagesNode(
2182                            long userId, long nodeId, String title, long newNodeId,
2183                            ServiceContext serviceContext)
2184                    throws PortalException {
2185    
2186                    List<WikiPage> childPages = wikiPagePersistence.findByN_P(
2187                            nodeId, title);
2188    
2189                    for (WikiPage childPage : childPages) {
2190                            childPage = doChangeNode(
2191                                    userId, nodeId, childPage.getTitle(), newNodeId,
2192                                    serviceContext);
2193    
2194                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2195                                    WikiPage.class);
2196    
2197                            indexer.reindex(childPage);
2198                    }
2199            }
2200    
2201            protected void changeRedirectPagesNode(
2202                            long userId, long nodeId, String title, long newNodeId,
2203                            ServiceContext serviceContext)
2204                    throws PortalException {
2205    
2206                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_R(
2207                            nodeId, title);
2208    
2209                    for (WikiPage redirectPage : redirectPages) {
2210                            redirectPage = doChangeNode(
2211                                    userId, nodeId, redirectPage.getTitle(), newNodeId,
2212                                    serviceContext);
2213    
2214                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2215                                    WikiPage.class);
2216    
2217                            indexer.reindex(redirectPage);
2218                    }
2219            }
2220    
2221            protected void checkDuplicationOnNodeChange(
2222                            long nodeId, String title, long newNodeId)
2223                    throws PortalException {
2224    
2225                    WikiPage page = fetchPage(newNodeId, title);
2226    
2227                    if (page != null) {
2228                            WikiNode node = page.getNode();
2229    
2230                            throw new NodeChangeException(
2231                                    node.getName(), page. getTitle(),
2232                                    NodeChangeException.DUPLICATE_PAGE);
2233                    }
2234    
2235                    List<WikiPage> childPages = wikiPagePersistence.findByN_P(
2236                            nodeId, title);
2237    
2238                    for (WikiPage childPage : childPages) {
2239                            checkDuplicationOnNodeChange(
2240                                    nodeId, childPage.getTitle(), newNodeId);
2241                    }
2242    
2243                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_R(
2244                            nodeId, title);
2245    
2246                    for (WikiPage redirectPage : redirectPages) {
2247                            checkDuplicationOnNodeChange(
2248                                    nodeId, redirectPage.getTitle(), newNodeId);
2249                    }
2250            }
2251    
2252            protected void checkNodeChange(long nodeId, String title, long newNodeId)
2253                    throws PortalException {
2254    
2255                    WikiPage page = getPage(nodeId, title);
2256    
2257                    if (Validator.isNotNull(page.getRedirectTitle())) {
2258                            WikiNode node = page.getNode();
2259    
2260                            throw new NodeChangeException(
2261                                    node.getName(), page. getTitle(),
2262                                    NodeChangeException.REDIRECT_PAGE);
2263                    }
2264    
2265                    checkDuplicationOnNodeChange(nodeId, title, newNodeId);
2266            }
2267    
2268            protected void clearPageCache(WikiPage page) {
2269                    if (!WikiCacheThreadLocal.isClearCache()) {
2270                            return;
2271                    }
2272    
2273                    WikiCacheUtil.clearCache(page.getNodeId());
2274            }
2275    
2276            protected void deletePageAttachment(long fileEntryId)
2277                    throws PortalException {
2278    
2279                    PortletFileRepositoryUtil.deletePortletFileEntry(fileEntryId);
2280            }
2281    
2282            protected WikiPage doChangeNode(
2283                            long userId, long nodeId, String title, long newNodeId,
2284                            ServiceContext serviceContext)
2285                    throws PortalException {
2286    
2287                    // Version pages
2288    
2289                    List<WikiPage> versionPages = wikiPagePersistence.findByN_T(
2290                            nodeId, title, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
2291                            new PageVersionComparator());
2292    
2293                    WikiPage page = fetchLatestPage(
2294                            newNodeId, title, WorkflowConstants.STATUS_ANY, false);
2295    
2296                    if (page == null) {
2297                            page = getLatestPage(
2298                                    nodeId, title, WorkflowConstants.STATUS_ANY, false);
2299                    }
2300    
2301                    for (WikiPage versionPage : versionPages) {
2302                            versionPage.setParentTitle(page.getParentTitle());
2303                            versionPage.setNodeId(newNodeId);
2304    
2305                            wikiPagePersistence.update(versionPage);
2306                    }
2307    
2308                    // Page resource
2309    
2310                    long resourcePrimKey = page.getResourcePrimKey();
2311    
2312                    WikiPageResource pageResource =
2313                            wikiPageResourcePersistence.findByPrimaryKey(resourcePrimKey);
2314    
2315                    pageResource.setNodeId(newNodeId);
2316    
2317                    wikiPageResourcePersistence.update(pageResource);
2318    
2319                    // Child pages
2320    
2321                    changeChildPagesNode(userId, nodeId, title, newNodeId, serviceContext);
2322    
2323                    // Redirect pages
2324    
2325                    changeRedirectPagesNode(
2326                            userId, nodeId, title, newNodeId, serviceContext);
2327    
2328                    // Asset
2329    
2330                    updateAsset(
2331                            userId, page, serviceContext.getAssetCategoryIds(),
2332                            serviceContext.getAssetTagNames(),
2333                            serviceContext.getAssetLinkEntryIds());
2334    
2335                    return page;
2336            }
2337    
2338            protected WikiPage doRenamePage(
2339                            long userId, long nodeId, String title, String newTitle,
2340                            ServiceContext serviceContext)
2341                    throws PortalException {
2342    
2343                    // Version pages
2344    
2345                    List<WikiPage> versionPages = wikiPagePersistence.findByN_T(
2346                            nodeId, title, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
2347                            new PageVersionComparator());
2348    
2349                    WikiPage page = fetchLatestPage(
2350                            nodeId, newTitle, WorkflowConstants.STATUS_ANY, false);
2351    
2352                    if (page == null) {
2353                            page = getLatestPage(
2354                                    nodeId, title, WorkflowConstants.STATUS_ANY, false);
2355                    }
2356    
2357                    for (WikiPage versionPage : versionPages) {
2358                            versionPage.setRedirectTitle(page.getRedirectTitle());
2359                            versionPage.setTitle(newTitle);
2360    
2361                            wikiPagePersistence.update(versionPage);
2362                    }
2363    
2364                    // Page resource
2365    
2366                    long resourcePrimKey = page.getResourcePrimKey();
2367    
2368                    WikiPageResource pageResource =
2369                            wikiPageResourcePersistence.findByPrimaryKey(resourcePrimKey);
2370    
2371                    pageResource.setTitle(newTitle);
2372    
2373                    wikiPageResourcePersistence.update(pageResource);
2374    
2375                    // Create stub page at the old location
2376    
2377                    double version = WikiPageConstants.VERSION_DEFAULT;
2378                    String summary = LanguageUtil.format(
2379                            serviceContext.getLocale(), "renamed-as-x", newTitle);
2380                    String format = page.getFormat();
2381                    boolean head = true;
2382                    String parentTitle = page.getParentTitle();
2383                    String redirectTitle = page.getTitle();
2384                    String content =
2385                            StringPool.DOUBLE_OPEN_BRACKET + redirectTitle +
2386                                    StringPool.DOUBLE_CLOSE_BRACKET;
2387    
2388                    serviceContext.setAddGroupPermissions(true);
2389                    serviceContext.setAddGuestPermissions(true);
2390    
2391                    populateServiceContext(serviceContext, page);
2392    
2393                    boolean workflowEnabled = WorkflowThreadLocal.isEnabled();
2394    
2395                    WorkflowThreadLocal.setEnabled(false);
2396    
2397                    serviceContext.setCommand(Constants.ADD);
2398    
2399                    addPage(
2400                            userId, nodeId, title, version, content, summary, false, format,
2401                            head, parentTitle, redirectTitle, serviceContext);
2402    
2403                    WorkflowThreadLocal.setEnabled(workflowEnabled);
2404    
2405                    // Child pages
2406    
2407                    List<WikiPage> childPages = wikiPagePersistence.findByN_P(
2408                            nodeId, title);
2409    
2410                    for (WikiPage childPage : childPages) {
2411                            childPage.setParentTitle(newTitle);
2412    
2413                            wikiPagePersistence.update(childPage);
2414                    }
2415    
2416                    // Redirect pages
2417    
2418                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_R(
2419                            nodeId, title);
2420    
2421                    for (WikiPage redirectPage : redirectPages) {
2422                            redirectPage.setRedirectTitle(newTitle);
2423    
2424                            wikiPagePersistence.update(redirectPage);
2425                    }
2426    
2427                    // Asset
2428    
2429                    updateAsset(
2430                            userId, page, serviceContext.getAssetCategoryIds(),
2431                            serviceContext.getAssetTagNames(),
2432                            serviceContext.getAssetLinkEntryIds());
2433    
2434                    return page;
2435            }
2436    
2437            protected String getDiffsURL(
2438                            WikiPage page, WikiPage previousVersionPage,
2439                            ServiceContext serviceContext)
2440                    throws PortalException {
2441    
2442                    if (previousVersionPage == null) {
2443                            return StringPool.BLANK;
2444                    }
2445    
2446                    HttpServletRequest request = serviceContext.getRequest();
2447    
2448                    if (request == null) {
2449                            return StringPool.BLANK;
2450                    }
2451    
2452                    String portletId = null;
2453                    long plid = LayoutConstants.DEFAULT_PLID;
2454                    String strutsAction = null;
2455    
2456                    if (serviceContext.getPlid() != LayoutConstants.DEFAULT_PLID) {
2457                            portletId = PortletKeys.WIKI;
2458                            plid = serviceContext.getPlid();
2459                            strutsAction = "/wiki/compare_versions";
2460                    }
2461                    else {
2462                            portletId = PortletKeys.WIKI_ADMIN;
2463                            plid = PortalUtil.getControlPanelPlid(
2464                                    serviceContext.getCompanyId());
2465                            strutsAction = "/wiki_admin/compare_versions";
2466                    }
2467    
2468                    PortletURL portletURL = PortletURLFactoryUtil.create(
2469                            request, portletId, plid, PortletRequest.RENDER_PHASE);
2470    
2471                    portletURL.setParameter("struts_action", strutsAction);
2472                    portletURL.setParameter("nodeId", String.valueOf(page.getNodeId()));
2473                    portletURL.setParameter("title", page.getTitle());
2474                    portletURL.setParameter(
2475                            "sourceVersion", String.valueOf(previousVersionPage.getVersion()));
2476                    portletURL.setParameter(
2477                            "targetVersion", String.valueOf(page.getVersion()));
2478                    portletURL.setParameter("type", "html");
2479    
2480                    return portletURL.toString();
2481            }
2482    
2483            protected String getPageURL(WikiPage page, ServiceContext serviceContext)
2484                    throws PortalException {
2485    
2486                    HttpServletRequest request = serviceContext.getRequest();
2487    
2488                    if (request == null) {
2489                            return StringPool.BLANK;
2490                    }
2491    
2492                    String layoutFullURL = LayoutURLUtil.getLayoutURL(
2493                            page.getGroupId(), PortletKeys.WIKI, serviceContext);
2494    
2495                    if (Validator.isNotNull(layoutFullURL)) {
2496                            return layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "wiki/" +
2497                                    page.getNodeId() + StringPool.SLASH +
2498                                            HttpUtil.encodeURL(WikiUtil.escapeName(page.getTitle()));
2499                    }
2500                    else {
2501                            long controlPanelPlid = PortalUtil.getControlPanelPlid(
2502                                    serviceContext.getCompanyId());
2503    
2504                            PortletURL portletURL = PortletURLFactoryUtil.create(
2505                                    request, PortletKeys.WIKI_ADMIN, controlPanelPlid,
2506                                    PortletRequest.RENDER_PHASE);
2507    
2508                            portletURL.setParameter(
2509                                    "struts_action", "/wiki_admin/view_page_activities");
2510                            portletURL.setParameter("nodeId", String.valueOf(page.getNodeId()));
2511                            portletURL.setParameter("title", page.getTitle());
2512    
2513                            return portletURL.toString();
2514                    }
2515            }
2516    
2517            protected List<ObjectValuePair<Long, Integer>> getPageVersionStatuses(
2518                    List<WikiPage> pages) {
2519    
2520                    List<ObjectValuePair<Long, Integer>> pageVersionStatusOVPs =
2521                            new ArrayList<ObjectValuePair<Long, Integer>>(pages.size());
2522    
2523                    for (WikiPage page : pages) {
2524                            int status = page.getStatus();
2525    
2526                            if (status == WorkflowConstants.STATUS_PENDING) {
2527                                    status = WorkflowConstants.STATUS_DRAFT;
2528                            }
2529    
2530                            ObjectValuePair<Long, Integer> pageVersionStatusOVP =
2531                                    new ObjectValuePair<Long, Integer>(page.getPageId(), status);
2532    
2533                            pageVersionStatusOVPs.add(pageVersionStatusOVP);
2534                    }
2535    
2536                    return pageVersionStatusOVPs;
2537            }
2538    
2539            protected String getParentPageTitle(WikiPage page) {
2540    
2541                    // LPS-4586
2542    
2543                    try {
2544                            WikiPage parentPage = getPage(
2545                                    page.getNodeId(), page.getParentTitle());
2546    
2547                            return parentPage.getTitle();
2548                    }
2549                    catch (Exception e) {
2550                            return null;
2551                    }
2552            }
2553    
2554            protected boolean isLinkedTo(WikiPage page, String targetTitle)
2555                    throws PortalException {
2556    
2557                    Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
2558    
2559                    Boolean link = links.get(StringUtil.toLowerCase(targetTitle));
2560    
2561                    if (link != null) {
2562                            return true;
2563                    }
2564                    else {
2565                            return false;
2566                    }
2567            }
2568    
2569            protected boolean isUsedTitle(long nodeId, String title) {
2570                    if (getPagesCount(nodeId, title, true) > 0) {
2571                            return true;
2572                    }
2573                    else {
2574                            return false;
2575                    }
2576            }
2577    
2578            protected void moveDependentChildPagesFromTrash(
2579                            WikiPage page, long nodeId, String title, String trashTitle)
2580                    throws PortalException {
2581    
2582                    List<WikiPage> childPages = getChildren(
2583                            nodeId, true, trashTitle, WorkflowConstants.STATUS_IN_TRASH);
2584    
2585                    for (WikiPage childPage : childPages) {
2586                            childPage.setParentTitle(title);
2587    
2588                            wikiPagePersistence.update(childPage);
2589    
2590                            if (!childPage.isInTrashExplicitly()) {
2591                                    moveDependentFromTrash(childPage, page.getNodeId(), title);
2592                            }
2593                    }
2594            }
2595    
2596            protected void moveDependentChildPagesToTrash(
2597                            WikiPage page, String title, String trashTitle, long trashEntryId,
2598                            boolean createTrashVersion)
2599                    throws PortalException {
2600    
2601                    List<WikiPage> childPages = wikiPagePersistence.findByN_H_P(
2602                            page.getNodeId(), true, title);
2603    
2604                    for (WikiPage childPage : childPages) {
2605                            childPage.setParentTitle(trashTitle);
2606    
2607                            wikiPagePersistence.update(childPage);
2608    
2609                            if (!childPage.isInTrashExplicitly()) {
2610                                    moveDependentToTrash(
2611                                            childPage, trashEntryId, createTrashVersion);
2612                            }
2613                    }
2614            }
2615    
2616            protected void moveDependentFromTrash(
2617                            WikiPage page, long newNodeId, String newParentTitle)
2618                    throws PortalException {
2619    
2620                    // Page
2621    
2622                    String trashTitle = page.getTitle();
2623    
2624                    TrashVersion trashVersion = trashVersionLocalService.fetchVersion(
2625                            WikiPage.class.getName(), page.getPageId());
2626    
2627                    long oldNodeId = page.getNodeId();
2628    
2629                    if (newNodeId == 0) {
2630                            newNodeId = oldNodeId;
2631                    }
2632    
2633                    page.setNodeId(newNodeId);
2634    
2635                    WikiPageResource pageResource =
2636                            wikiPageResourcePersistence.findByPrimaryKey(
2637                                    page.getResourcePrimKey());
2638    
2639                    pageResource.setNodeId(newNodeId);
2640    
2641                    if (trashVersion != null) {
2642                            String originalTitle = TrashUtil.getOriginalTitle(page.getTitle());
2643    
2644                            pageResource.setTitle(originalTitle);
2645    
2646                            page.setTitle(originalTitle);
2647                    }
2648    
2649                    wikiPageResourcePersistence.update(pageResource);
2650    
2651                    page.setParentTitle(newParentTitle);
2652    
2653                    wikiPagePersistence.update(page);
2654    
2655                    int oldStatus = WorkflowConstants.STATUS_APPROVED;
2656    
2657                    if (trashVersion != null) {
2658                            oldStatus = trashVersion.getStatus();
2659                    }
2660    
2661                    // Version pages
2662    
2663                    List<WikiPage> versionPages = wikiPagePersistence.findByR_N(
2664                            page.getResourcePrimKey(), page.getNodeId());
2665    
2666                    for (WikiPage versionPage : versionPages) {
2667    
2668                            // Version page
2669    
2670                            versionPage.setParentTitle(newParentTitle);
2671                            versionPage.setNodeId(newNodeId);
2672                            versionPage.setTitle(page.getTitle());
2673    
2674                            trashVersion = trashVersionLocalService.fetchVersion(
2675                                    WikiPage.class.getName(), versionPage.getPageId());
2676    
2677                            int versionPageOldStatus = WorkflowConstants.STATUS_APPROVED;
2678    
2679                            if (trashVersion != null) {
2680                                    versionPageOldStatus = trashVersion.getStatus();
2681                            }
2682    
2683                            versionPage.setStatus(versionPageOldStatus);
2684    
2685                            wikiPagePersistence.update(versionPage);
2686    
2687                            // Trash
2688    
2689                            if (trashVersion != null) {
2690                                    trashVersionLocalService.deleteTrashVersion(trashVersion);
2691                            }
2692                    }
2693    
2694                    // Asset
2695    
2696                    if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
2697                            assetEntryLocalService.updateVisible(
2698                                    WikiPage.class.getName(), page.getResourcePrimKey(), true);
2699                    }
2700    
2701                    // Index
2702    
2703                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2704                            WikiPage.class);
2705    
2706                    indexer.reindex(page);
2707    
2708                    // Child pages
2709    
2710                    moveDependentChildPagesFromTrash(
2711                            page, oldNodeId, page.getTitle(), trashTitle);
2712    
2713                    // Redirect pages
2714    
2715                    moveDependentRedirectPagesFromTrash(
2716                            page, oldNodeId, page.getTitle(), trashTitle);
2717            }
2718    
2719            protected void moveDependentRedirectPagesFromTrash(
2720                            WikiPage page, long nodeId, String title, String trashTitle)
2721                    throws PortalException {
2722    
2723                    List<WikiPage> redirectPages = getRedirectPages(
2724                            nodeId, true, trashTitle, WorkflowConstants.STATUS_IN_TRASH);
2725    
2726                    for (WikiPage curPage : redirectPages) {
2727                            curPage.setRedirectTitle(title);
2728    
2729                            wikiPagePersistence.update(curPage);
2730    
2731                            if (!curPage.isInTrash()) {
2732                                    moveDependentFromTrash(
2733                                            curPage, page.getNodeId(), curPage.getParentTitle());
2734                            }
2735                    }
2736            }
2737    
2738            protected void moveDependentRedirectPagesToTrash(
2739                            WikiPage page, String title, String trashTitle, long trashEntryId,
2740                            boolean createTrashVersion)
2741                    throws PortalException {
2742    
2743                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_H_R(
2744                            page.getNodeId(), true, title);
2745    
2746                    for (WikiPage redirectPage : redirectPages) {
2747                            redirectPage.setRedirectTitle(trashTitle);
2748    
2749                            wikiPagePersistence.update(redirectPage);
2750    
2751                            if (!redirectPage.isInTrash()) {
2752                                    moveDependentToTrash(
2753                                            redirectPage, trashEntryId, createTrashVersion);
2754                            }
2755                    }
2756            }
2757    
2758            protected void moveDependentToTrash(
2759                            WikiPage page, long trashEntryId, boolean createTrashVersion)
2760                    throws PortalException {
2761    
2762                    // Page
2763    
2764                    String title = page.getTitle();
2765    
2766                    String trashTitle = title;
2767    
2768                    if (createTrashVersion) {
2769                            UnicodeProperties typeSettingsProperties = new UnicodeProperties();
2770    
2771                            typeSettingsProperties.put("title", page.getTitle());
2772    
2773                            TrashVersion trashVersion =
2774                                    trashVersionLocalService.addTrashVersion(
2775                                            trashEntryId, WikiPage.class.getName(), page.getPageId(),
2776                                            page.getStatus(), typeSettingsProperties);
2777    
2778                            trashTitle = TrashUtil.getTrashTitle(trashVersion.getVersionId());
2779    
2780                            WikiPageResource pageResource =
2781                                    wikiPageResourcePersistence.findByPrimaryKey(
2782                                            page.getResourcePrimKey());
2783    
2784                            pageResource.setTitle(trashTitle);
2785    
2786                            wikiPageResourcePersistence.update(pageResource);
2787    
2788                            page.setTitle(trashTitle);
2789    
2790                            wikiPagePersistence.update(page);
2791                    }
2792    
2793                    int oldStatus = page.getStatus();
2794    
2795                    if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
2796                            return;
2797                    }
2798    
2799                    // Version pages
2800    
2801                    List<WikiPage> versionPages = wikiPagePersistence.findByR_N(
2802                            page.getResourcePrimKey(), page.getNodeId());
2803    
2804                    for (WikiPage versionPage : versionPages) {
2805    
2806                            // Version page
2807    
2808                            versionPage.setTitle(page.getTitle());
2809    
2810                            int versionPageOldStatus = versionPage.getStatus();
2811    
2812                            versionPage.setStatus(WorkflowConstants.STATUS_IN_TRASH);
2813    
2814                            wikiPagePersistence.update(versionPage);
2815    
2816                            // Trash
2817    
2818                            int status = versionPageOldStatus;
2819    
2820                            if (versionPageOldStatus == WorkflowConstants.STATUS_PENDING) {
2821                                    status = WorkflowConstants.STATUS_DRAFT;
2822                            }
2823    
2824                            if (versionPageOldStatus != WorkflowConstants.STATUS_APPROVED) {
2825                                    trashVersionLocalService.addTrashVersion(
2826                                            trashEntryId, WikiPage.class.getName(),
2827                                            versionPage.getPageId(), status, null);
2828                            }
2829                    }
2830    
2831                    // Asset
2832    
2833                    if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
2834                            assetEntryLocalService.updateVisible(
2835                                    WikiPage.class.getName(), page.getResourcePrimKey(), false);
2836                    }
2837    
2838                    // Indexer
2839    
2840                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2841                            WikiPage.class);
2842    
2843                    indexer.reindex(page);
2844    
2845                    // Cache
2846    
2847                    if (WikiCacheThreadLocal.isClearCache()) {
2848                            WikiCacheUtil.clearCache(page.getNodeId());
2849                    }
2850    
2851                    // Workflow
2852    
2853                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
2854                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
2855                                    page.getCompanyId(), page.getGroupId(),
2856                                    WikiPage.class.getName(), page.getResourcePrimKey());
2857                    }
2858    
2859                    // Child pages
2860    
2861                    moveDependentChildPagesToTrash(
2862                            page, title, trashTitle, trashEntryId, createTrashVersion);
2863    
2864                    // Redirect pages
2865    
2866                    moveDependentRedirectPagesToTrash(
2867                            page, title, trashTitle, trashEntryId, createTrashVersion);
2868            }
2869    
2870            protected void movePageFromTrash(
2871                            long userId, WikiPage page, long newNodeId, String newParentTitle)
2872                    throws PortalException {
2873    
2874                    // Page
2875    
2876                    String trashTitle = page.getTitle();
2877    
2878                    String originalTitle = TrashUtil.getOriginalTitle(trashTitle);
2879    
2880                    long oldNodeId = page.getNodeId();
2881    
2882                    if (newNodeId == 0) {
2883                            newNodeId = oldNodeId;
2884                    }
2885    
2886                    List<WikiPage> pageVersions = wikiPagePersistence.findByR_N_H(
2887                            page.getResourcePrimKey(), oldNodeId, false);
2888    
2889                    for (WikiPage pageVersion : pageVersions) {
2890                            pageVersion.setParentTitle(newParentTitle);
2891                            pageVersion.setNodeId(newNodeId);
2892                            pageVersion.setTitle(originalTitle);
2893    
2894                            wikiPagePersistence.update(pageVersion);
2895                    }
2896    
2897                    WikiPageResource pageResource =
2898                            wikiPageResourcePersistence.fetchByPrimaryKey(
2899                                    page.getResourcePrimKey());
2900    
2901                    pageResource.setNodeId(newNodeId);
2902                    pageResource.setTitle(originalTitle);
2903    
2904                    wikiPageResourcePersistence.update(pageResource);
2905    
2906                    page.setNodeId(newNodeId);
2907                    page.setTitle(originalTitle);
2908    
2909                    WikiPage parentPage = page.getParentPage();
2910    
2911                    if ((parentPage != null) && parentPage.isInTrash()) {
2912                            page.setParentTitle(StringPool.BLANK);
2913                    }
2914    
2915                    if (Validator.isNotNull(newParentTitle)) {
2916                            WikiPage newParentPage = getPage(newNodeId, newParentTitle);
2917    
2918                            if (!newParentPage.isInTrash()) {
2919                                    page.setParentTitle(newParentTitle);
2920                            }
2921                    }
2922    
2923                    WikiPage redirectPage = page.getRedirectPage();
2924    
2925                    if ((redirectPage != null) && redirectPage.isInTrash()) {
2926                            page.setRedirectTitle(StringPool.BLANK);
2927                    }
2928    
2929                    wikiPagePersistence.update(page);
2930    
2931                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
2932                            WikiPage.class.getName(), page.getResourcePrimKey());
2933    
2934                    updateStatus(
2935                            userId, page, trashEntry.getStatus(), new ServiceContext(),
2936                            new HashMap<String, Serializable>());
2937    
2938                    // Child pages
2939    
2940                    moveDependentChildPagesFromTrash(
2941                            page, oldNodeId, originalTitle, trashTitle);
2942    
2943                    // Redirect pages
2944    
2945                    moveDependentRedirectPagesFromTrash(
2946                            page, oldNodeId, originalTitle, trashTitle);
2947    
2948                    // Trash
2949    
2950                    List<TrashVersion> trashVersions = trashVersionLocalService.getVersions(
2951                            trashEntry.getEntryId());
2952    
2953                    for (TrashVersion trashVersion : trashVersions) {
2954                            WikiPage trashArticleVersion = wikiPagePersistence.findByPrimaryKey(
2955                                    trashVersion.getClassPK());
2956    
2957                            trashArticleVersion.setStatus(trashVersion.getStatus());
2958    
2959                            wikiPagePersistence.update(trashArticleVersion);
2960                    }
2961    
2962                    trashEntryLocalService.deleteEntry(
2963                            WikiPage.class.getName(), page.getResourcePrimKey());
2964    
2965                    // Social
2966    
2967                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
2968    
2969                    extraDataJSONObject.put("title", page.getTitle());
2970                    extraDataJSONObject.put("version", page.getVersion());
2971    
2972                    socialActivityLocalService.addActivity(
2973                            userId, page.getGroupId(), WikiPage.class.getName(),
2974                            page.getResourcePrimKey(),
2975                            SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
2976                            extraDataJSONObject.toString(), 0);
2977    
2978                    if (!pageVersions.isEmpty()) {
2979                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2980                                    WikiPage.class);
2981    
2982                            for (WikiPage pageVersion : pageVersions) {
2983                                    indexer.reindex(pageVersion);
2984                            }
2985                    }
2986            }
2987    
2988            protected void notifySubscribers(
2989                            WikiPage page, String pageURL, ServiceContext serviceContext)
2990                    throws PortalException {
2991    
2992                    if (!page.isApproved() || Validator.isNull(pageURL)) {
2993                            return;
2994                    }
2995    
2996                    WikiSettings wikiSettings = WikiSettings.getInstance(page.getGroupId());
2997    
2998                    boolean update = false;
2999    
3000                    if (page.getVersion() > WikiPageConstants.VERSION_DEFAULT) {
3001                            update = true;
3002                    }
3003    
3004                    if (!update && wikiSettings.isEmailPageAddedEnabled()) {
3005                    }
3006                    else if (update && wikiSettings.isEmailPageUpdatedEnabled()) {
3007                    }
3008                    else {
3009                            return;
3010                    }
3011    
3012                    String portalURL = serviceContext.getPortalURL();
3013    
3014                    WikiPage previousVersionPage = getPreviousVersionPage(page);
3015    
3016                    String attachmentURLPrefix = WikiUtil.getAttachmentURLPrefix(
3017                            serviceContext.getPathMain(), serviceContext.getPlid(),
3018                            page.getNodeId(), page.getTitle());
3019    
3020                    attachmentURLPrefix = portalURL + attachmentURLPrefix;
3021    
3022                    String pageDiffs = StringPool.BLANK;
3023    
3024                    try {
3025                            pageDiffs = WikiUtil.diffHtml(
3026                                    previousVersionPage, page, null, null, attachmentURLPrefix);
3027                    }
3028                    catch (Exception e) {
3029                    }
3030    
3031                    String pageContent = null;
3032    
3033                    if (Validator.equals(page.getFormat(), "creole")) {
3034                            pageContent = WikiUtil.convert(
3035                                    page, null, null, attachmentURLPrefix);
3036                    }
3037                    else {
3038                            pageContent = page.getContent();
3039                            pageContent = WikiUtil.processContent(pageContent);
3040                    }
3041    
3042                    String pageTitle = page.getTitle();
3043    
3044                    String fromName = wikiSettings.getEmailFromName();
3045                    String fromAddress = wikiSettings.getEmailFromAddress();
3046    
3047                    LocalizedValuesMap subjectLocalizedValuesMap = null;
3048                    LocalizedValuesMap bodyLocalizedValuesMap = null;
3049    
3050                    if (update) {
3051                            subjectLocalizedValuesMap =
3052                                    wikiSettings.getEmailPageUpdatedSubject();
3053                            bodyLocalizedValuesMap = wikiSettings.getEmailPageUpdatedBody();
3054                    }
3055                    else {
3056                            subjectLocalizedValuesMap = wikiSettings.getEmailPageAddedSubject();
3057                            bodyLocalizedValuesMap = wikiSettings.getEmailPageAddedBody();
3058                    }
3059    
3060                    SubscriptionSender subscriptionSender = new SubscriptionSender();
3061    
3062                    subscriptionSender.setClassName(page.getModelClassName());
3063                    subscriptionSender.setClassPK(page.getPageId());
3064                    subscriptionSender.setCompanyId(page.getCompanyId());
3065                    subscriptionSender.setContextAttribute(
3066                            "[$PAGE_CONTENT$]", pageContent, false);
3067                    subscriptionSender.setContextAttribute(
3068                            "[$PAGE_DIFFS$]", DiffHtmlUtil.replaceStyles(pageDiffs), false);
3069    
3070                    WikiNode node = page.getNode();
3071    
3072                    subscriptionSender.setContextAttributes(
3073                            "[$DIFFS_URL$]",
3074                            getDiffsURL(page, previousVersionPage, serviceContext),
3075                            "[$NODE_NAME$]", node.getName(), "[$PAGE_DATE_UPDATE$]",
3076                            page.getModifiedDate(), "[$PAGE_ID$]", page.getPageId(),
3077                            "[$PAGE_SUMMARY$]", page.getSummary(), "[$PAGE_TITLE$]", pageTitle,
3078                            "[$PAGE_URL$]", pageURL);
3079    
3080                    subscriptionSender.setContextUserPrefix("PAGE");
3081                    subscriptionSender.setEntryTitle(pageTitle);
3082                    subscriptionSender.setEntryURL(pageURL);
3083                    subscriptionSender.setFrom(fromAddress, fromName);
3084                    subscriptionSender.setHtmlFormat(true);
3085                    subscriptionSender.setLocalizedBodyMap(bodyLocalizedValuesMap);
3086                    subscriptionSender.setLocalizedSubjectMap(subjectLocalizedValuesMap);
3087                    subscriptionSender.setMailId(
3088                            "wiki_page", page.getNodeId(), page.getPageId());
3089    
3090                    int notificationType =
3091                            UserNotificationDefinition.NOTIFICATION_TYPE_ADD_ENTRY;
3092    
3093                    if (serviceContext.isCommandUpdate()) {
3094                            notificationType =
3095                                    UserNotificationDefinition.NOTIFICATION_TYPE_UPDATE_ENTRY;
3096                    }
3097    
3098                    subscriptionSender.setNotificationType(notificationType);
3099    
3100                    subscriptionSender.setPortletId(PortletKeys.WIKI);
3101                    subscriptionSender.setReplyToAddress(fromAddress);
3102                    subscriptionSender.setScopeGroupId(page.getGroupId());
3103                    subscriptionSender.setServiceContext(serviceContext);
3104                    subscriptionSender.setUserId(page.getUserId());
3105    
3106                    subscriptionSender.addPersistedSubscribers(
3107                            WikiNode.class.getName(), page.getNodeId());
3108    
3109                    subscriptionSender.addPersistedSubscribers(
3110                            WikiPage.class.getName(), page.getResourcePrimKey());
3111    
3112                    subscriptionSender.flushNotificationsAsync();
3113            }
3114    
3115            protected void populateServiceContext(
3116                            ServiceContext serviceContext, WikiPage page)
3117                    throws PortalException {
3118    
3119                    long[] assetCategoryIds = assetCategoryLocalService.getCategoryIds(
3120                            WikiPage.class.getName(), page.getResourcePrimKey());
3121    
3122                    serviceContext.setAssetCategoryIds(assetCategoryIds);
3123    
3124                    AssetEntry assetEntry = assetEntryLocalService.getEntry(
3125                            WikiPage.class.getName(), page.getResourcePrimKey());
3126    
3127                    List<AssetLink> assetLinks = assetLinkLocalService.getLinks(
3128                            assetEntry.getEntryId());
3129    
3130                    long[] assetLinkEntryIds = ListUtil.toLongArray(
3131                            assetLinks, AssetLink.ENTRY_ID2_ACCESSOR);
3132    
3133                    serviceContext.setAssetLinkEntryIds(assetLinkEntryIds);
3134    
3135                    String[] assetTagNames = assetTagLocalService.getTagNames(
3136                            WikiPage.class.getName(), page.getResourcePrimKey());
3137    
3138                    serviceContext.setAssetTagNames(assetTagNames);
3139    
3140                    ExpandoBridge expandoBridge = page.getExpandoBridge();
3141    
3142                    serviceContext.setExpandoBridgeAttributes(
3143                            expandoBridge.getAttributes());
3144            }
3145    
3146            protected void startWorkflowInstance(
3147                            long userId, WikiPage page, ServiceContext serviceContext)
3148                    throws PortalException {
3149    
3150                    Map<String, Serializable> workflowContext =
3151                            new HashMap<String, Serializable>();
3152    
3153                    workflowContext.put(
3154                            WorkflowConstants.CONTEXT_COMMAND, serviceContext.getCommand());
3155                    workflowContext.put(
3156                            WorkflowConstants.CONTEXT_URL, getPageURL(page, serviceContext));
3157    
3158                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
3159                            page.getCompanyId(), page.getGroupId(), userId,
3160                            WikiPage.class.getName(), page.getPageId(), page, serviceContext,
3161                            workflowContext);
3162            }
3163    
3164            protected WikiPage updatePage(
3165                            long userId, WikiPage oldPage, long newNodeId, String newTitle,
3166                            String content, String summary, boolean minorEdit, String format,
3167                            String parentTitle, String redirectTitle,
3168                            ServiceContext serviceContext)
3169                    throws PortalException {
3170    
3171                    User user = userPersistence.findByPrimaryKey(userId);
3172    
3173                    long pageId = 0;
3174    
3175                    if (oldPage.isApproved()) {
3176                            pageId = counterLocalService.increment();
3177                    }
3178                    else {
3179                            pageId = oldPage.getPageId();
3180                    }
3181    
3182                    content = SanitizerUtil.sanitize(
3183                            user.getCompanyId(), oldPage.getGroupId(), userId,
3184                            WikiPage.class.getName(), pageId, "text/" + format, content);
3185    
3186                    long nodeId = oldPage.getNodeId();
3187    
3188                    if (newNodeId != 0) {
3189                            nodeId = newNodeId;
3190                    }
3191    
3192                    validate(nodeId, content, format);
3193    
3194                    serviceContext.validateModifiedDate(
3195                            oldPage, PageVersionException.class);
3196    
3197                    long resourcePrimKey =
3198                            wikiPageResourceLocalService.getPageResourcePrimKey(
3199                                    oldPage.getNodeId(), oldPage.getTitle());
3200    
3201                    Date now = new Date();
3202    
3203                    WikiPage page = oldPage;
3204    
3205                    double newVersion = oldPage.getVersion();
3206    
3207                    if (oldPage.isApproved()) {
3208                            newVersion = MathUtil.format(oldPage.getVersion() + 0.1, 1, 1);
3209    
3210                            page = wikiPagePersistence.create(pageId);
3211    
3212                            page.setUuid(serviceContext.getUuid());
3213                    }
3214    
3215                    page.setResourcePrimKey(resourcePrimKey);
3216                    page.setGroupId(oldPage.getGroupId());
3217                    page.setCompanyId(user.getCompanyId());
3218                    page.setUserId(user.getUserId());
3219                    page.setUserName(user.getFullName());
3220                    page.setCreateDate(oldPage.getCreateDate());
3221                    page.setModifiedDate(serviceContext.getModifiedDate(now));
3222                    page.setNodeId(nodeId);
3223                    page.setTitle(
3224                            Validator.isNull(newTitle) ? oldPage.getTitle() : newTitle);
3225                    page.setVersion(newVersion);
3226                    page.setMinorEdit(minorEdit);
3227                    page.setContent(content);
3228    
3229                    if (oldPage.isPending()) {
3230                            page.setStatus(oldPage.getStatus());
3231                    }
3232                    else {
3233                            page.setStatus(WorkflowConstants.STATUS_DRAFT);
3234                    }
3235    
3236                    page.setSummary(summary);
3237                    page.setFormat(format);
3238    
3239                    if (Validator.isNotNull(parentTitle)) {
3240                            page.setParentTitle(parentTitle);
3241                    }
3242    
3243                    if (Validator.isNotNull(redirectTitle)) {
3244                            page.setRedirectTitle(redirectTitle);
3245                    }
3246    
3247                    page.setExpandoBridgeAttributes(serviceContext);
3248    
3249                    wikiPagePersistence.update(page);
3250    
3251                    // Node
3252    
3253                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
3254    
3255                    node.setLastPostDate(serviceContext.getModifiedDate(now));
3256    
3257                    wikiNodePersistence.update(node);
3258    
3259                    // Asset
3260    
3261                    updateAsset(
3262                            userId, page, serviceContext.getAssetCategoryIds(),
3263                            serviceContext.getAssetTagNames(),
3264                            serviceContext.getAssetLinkEntryIds());
3265    
3266                    // Social
3267    
3268                    if (!page.isMinorEdit() ||
3269                            PropsValues.WIKI_PAGE_MINOR_EDIT_ADD_SOCIAL_ACTIVITY) {
3270    
3271                            if (oldPage.getVersion() == newVersion) {
3272                                    SocialActivity lastSocialActivity =
3273                                            socialActivityLocalService.fetchFirstActivity(
3274                                                    WikiPage.class.getName(), page.getResourcePrimKey(),
3275                                                    WikiActivityKeys.UPDATE_PAGE);
3276    
3277                                    if (lastSocialActivity != null) {
3278                                            lastSocialActivity.setCreateDate(now.getTime() + 1);
3279                                            lastSocialActivity.setUserId(serviceContext.getUserId());
3280    
3281                                            socialActivityPersistence.update(lastSocialActivity);
3282                                    }
3283                            }
3284                            else {
3285                                    JSONObject extraDataJSONObject =
3286                                            JSONFactoryUtil.createJSONObject();
3287    
3288                                    extraDataJSONObject.put("title", page.getTitle());
3289                                    extraDataJSONObject.put("version", page.getVersion());
3290    
3291                                    socialActivityLocalService.addActivity(
3292                                            userId, page.getGroupId(), WikiPage.class.getName(),
3293                                            page.getResourcePrimKey(), WikiActivityKeys.UPDATE_PAGE,
3294                                            extraDataJSONObject.toString(), 0);
3295                            }
3296                    }
3297    
3298                    // Workflow
3299    
3300                    startWorkflowInstance(userId, page, serviceContext);
3301    
3302                    return page;
3303            }
3304    
3305            protected void validate(long nodeId, String content, String format)
3306                    throws PortalException {
3307    
3308                    if (!WikiUtil.validate(nodeId, content, format)) {
3309                            throw new PageContentException();
3310                    }
3311            }
3312    
3313            protected void validate(
3314                            String title, long nodeId, String content, String format)
3315                    throws PortalException {
3316    
3317                    if (Validator.isNull(title)) {
3318                            throw new PageTitleException();
3319                    }
3320    
3321                    if (isUsedTitle(nodeId, title)) {
3322                            throw new DuplicatePageException("{nodeId=" + nodeId + "}");
3323                    }
3324    
3325                    validateTitle(title);
3326    
3327                    validate(nodeId, content, format);
3328            }
3329    
3330    }