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