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