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