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