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