001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.expando.util.ExpandoBridgeUtil;
067    import com.liferay.portlet.social.model.SocialActivity;
068    import com.liferay.portlet.social.model.SocialActivityConstants;
069    import com.liferay.portlet.trash.model.TrashEntry;
070    import com.liferay.portlet.trash.model.TrashVersion;
071    import com.liferay.portlet.trash.util.TrashUtil;
072    import com.liferay.portlet.wiki.DuplicatePageException;
073    import com.liferay.portlet.wiki.NoSuchPageException;
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, send = false,
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                    List<WikiPage> versionPages = wikiPagePersistence.findByN_T(
527                            page.getNodeId(), page.getTitle());
528    
529                    wikiPagePersistence.removeByN_T(page.getNodeId(), page.getTitle());
530    
531                    // References
532    
533                    wikiPagePersistence.removeByN_R(page.getNodeId(), page.getTitle());
534    
535                    // Resources
536    
537                    resourceLocalService.deleteResource(
538                            page.getCompanyId(), WikiPage.class.getName(),
539                            ResourceConstants.SCOPE_INDIVIDUAL, page.getResourcePrimKey());
540    
541                    // Resource
542    
543                    WikiPageResource pageResource =
544                            wikiPageResourceLocalService.fetchPageResource(
545                                    page.getNodeId(), page.getTitle());
546    
547                    if (pageResource != null) {
548                            wikiPageResourceLocalService.deleteWikiPageResource(pageResource);
549                    }
550    
551                    // Attachments
552    
553                    long folderId = page.getAttachmentsFolderId();
554    
555                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
556                            PortletFileRepositoryUtil.deleteFolder(folderId);
557                    }
558    
559                    // Subscriptions
560    
561                    subscriptionLocalService.deleteSubscriptions(
562                            page.getCompanyId(), WikiPage.class.getName(),
563                            page.getResourcePrimKey());
564    
565                    // Asset
566    
567                    SystemEventHierarchyEntryThreadLocal.pop(
568                            page.getModelClass(), page.getPageId());
569    
570                    try {
571                            for (WikiPage versionPage : versionPages) {
572                                    assetEntryLocalService.deleteEntry(
573                                            WikiPage.class.getName(), versionPage.getPrimaryKey());
574                            }
575                    }
576                    finally {
577                            SystemEventHierarchyEntryThreadLocal.push(
578                                    page.getModelClass(), page.getPageId());
579                    }
580    
581                    assetEntryLocalService.deleteEntry(
582                            WikiPage.class.getName(), page.getResourcePrimKey());
583    
584                    // Expando
585    
586                    expandoRowLocalService.deleteRows(page.getPrimaryKey());
587    
588                    // Message boards
589    
590                    mbMessageLocalService.deleteDiscussionMessages(
591                            WikiPage.class.getName(), page.getResourcePrimKey());
592    
593                    // Trash
594    
595                    if (page.isInTrash()) {
596                            page.setTitle(TrashUtil.getOriginalTitle(page.getTitle()));
597    
598                            trashEntryLocalService.deleteEntry(
599                                    WikiPage.class.getName(), page.getResourcePrimKey());
600                    }
601    
602                    // Indexer
603    
604                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
605                            WikiPage.class);
606    
607                    indexer.delete(page);
608    
609                    // Cache
610    
611                    clearPageCache(page);
612    
613                    // All versions
614    
615                    for (WikiPage versionPage : versionPages) {
616    
617                            // Workflow
618    
619                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
620                                    versionPage.getCompanyId(), versionPage.getGroupId(),
621                                    WikiPage.class.getName(), versionPage.getPageId());
622                    }
623    
624                    if (pageResource != null) {
625                            JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
626    
627                            extraDataJSONObject.put("version", page.getVersion());
628    
629                            systemEventLocalService.addSystemEvent(
630                                    0, page.getGroupId(), page.getModelClassName(),
631                                    page.getPrimaryKey(), pageResource.getUuid(), null,
632                                    SystemEventConstants.TYPE_DELETE,
633                                    extraDataJSONObject.toString());
634                    }
635            }
636    
637            @Override
638            public void deletePageAttachment(long nodeId, String title, String fileName)
639                    throws PortalException, SystemException {
640    
641                    WikiPage page = getPage(nodeId, title);
642    
643                    long folderId = page.getAttachmentsFolderId();
644    
645                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
646                            return;
647                    }
648    
649                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
650                            page.getGroupId(), folderId, fileName);
651    
652                    deletePageAttachment(fileEntry.getFileEntryId());
653            }
654    
655            @Override
656            public void deletePageAttachments(long nodeId, String title)
657                    throws PortalException, SystemException {
658    
659                    WikiPage page = getPage(nodeId, title);
660    
661                    long folderId = page.getAttachmentsFolderId();
662    
663                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
664                            return;
665                    }
666    
667                    PortletFileRepositoryUtil.deletePortletFileEntries(
668                            page.getGroupId(), folderId);
669            }
670    
671            @Override
672            public void deletePages(long nodeId)
673                    throws PortalException, SystemException {
674    
675                    List<WikiPage> pages = wikiPagePersistence.findByN_H_P(
676                            nodeId, true, StringPool.BLANK);
677    
678                    for (WikiPage page : pages) {
679                            wikiPageLocalService.deletePage(page);
680                    }
681    
682                    pages = wikiPagePersistence.findByN_H_P(
683                            nodeId, false, StringPool.BLANK);
684    
685                    for (WikiPage page : pages) {
686                            wikiPageLocalService.deletePage(page);
687                    }
688            }
689    
690            @Override
691            public void deleteTempPageAttachment(
692                            long groupId, long userId, String fileName, String tempFolderName)
693                    throws PortalException, SystemException {
694    
695                    TempFileUtil.deleteTempFile(groupId, userId, fileName, tempFolderName);
696            }
697    
698            @Override
699            public void deleteTrashPageAttachments(long nodeId, String title)
700                    throws PortalException, SystemException {
701    
702                    WikiPage page = getPage(nodeId, title);
703    
704                    long folderId = page.getAttachmentsFolderId();
705    
706                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
707                            return;
708                    }
709    
710                    PortletFileRepositoryUtil.deletePortletFileEntries(
711                            page.getGroupId(), folderId, WorkflowConstants.STATUS_IN_TRASH);
712            }
713    
714            @Override
715            public void discardDraft(long nodeId, String title, double version)
716                    throws PortalException, SystemException {
717    
718                    wikiPagePersistence.removeByN_T_V(nodeId, title, version);
719            }
720    
721            @Override
722            public WikiPage fetchLatestPage(
723                            long resourcePrimKey, int status, boolean preferApproved)
724                    throws SystemException {
725    
726                    WikiPage page = null;
727    
728                    OrderByComparator orderByComparator = new PageVersionComparator();
729    
730                    if (status == WorkflowConstants.STATUS_ANY) {
731                            if (preferApproved) {
732                                    page = wikiPagePersistence.fetchByR_S_First(
733                                            resourcePrimKey, WorkflowConstants.STATUS_APPROVED,
734                                            orderByComparator);
735                            }
736    
737                            if (page == null) {
738                                    page = wikiPagePersistence.fetchByResourcePrimKey_First(
739                                            resourcePrimKey, orderByComparator);
740                            }
741                    }
742                    else {
743                            page = wikiPagePersistence.fetchByR_S_First(
744                                    resourcePrimKey, status, orderByComparator);
745                    }
746    
747                    return page;
748            }
749    
750            @Override
751            public WikiPage fetchLatestPage(
752                            long resourcePrimKey, long nodeId, int status,
753                            boolean preferApproved)
754                    throws SystemException {
755    
756                    WikiPage page = null;
757    
758                    OrderByComparator orderByComparator = new PageVersionComparator();
759    
760                    if (status == WorkflowConstants.STATUS_ANY) {
761                            if (preferApproved) {
762                                    page = wikiPagePersistence.fetchByR_N_S_First(
763                                            resourcePrimKey, nodeId, WorkflowConstants.STATUS_APPROVED,
764                                            orderByComparator);
765                            }
766    
767                            if (page == null) {
768                                    page = wikiPagePersistence.fetchByR_N_First(
769                                            resourcePrimKey, nodeId, orderByComparator);
770                            }
771                    }
772                    else {
773                            page = wikiPagePersistence.fetchByR_N_S_First(
774                                    resourcePrimKey, nodeId, status, orderByComparator);
775                    }
776    
777                    return page;
778            }
779    
780            @Override
781            public WikiPage fetchLatestPage(
782                            long nodeId, String title, int status, boolean preferApproved)
783                    throws SystemException {
784    
785                    WikiPage page = null;
786    
787                    OrderByComparator orderByComparator = new PageVersionComparator();
788    
789                    if (status == WorkflowConstants.STATUS_ANY) {
790                            if (preferApproved) {
791                                    page = wikiPagePersistence.fetchByN_T_S_First(
792                                            nodeId, title, WorkflowConstants.STATUS_APPROVED,
793                                            orderByComparator);
794                            }
795    
796                            if (page == null) {
797                                    page = wikiPagePersistence.fetchByN_T_First(
798                                            nodeId, title, orderByComparator);
799                            }
800                    }
801                    else {
802                            page = wikiPagePersistence.fetchByN_T_S_First(
803                                    nodeId, title, status, orderByComparator);
804                    }
805    
806                    return page;
807            }
808    
809            @Override
810            public WikiPage fetchPage(long nodeId, String title)
811                    throws SystemException {
812    
813                    return wikiPagePersistence.fetchByN_T_H_First(
814                            nodeId, title, true, null);
815            }
816    
817            @Override
818            public WikiPage fetchPage(long nodeId, String title, double version)
819                    throws SystemException {
820    
821                    if (version == 0) {
822                            return fetchPage(nodeId, title);
823                    }
824                    else {
825                            return wikiPagePersistence.fetchByN_T_V(nodeId, title, version);
826                    }
827            }
828    
829            @Override
830            public List<WikiPage> getChildren(
831                            long nodeId, boolean head, String parentTitle)
832                    throws SystemException {
833    
834                    return wikiPagePersistence.findByN_H_P_S(
835                            nodeId, head, parentTitle, WorkflowConstants.STATUS_APPROVED);
836            }
837    
838            @Override
839            public WikiPage getDraftPage(long nodeId, String title)
840                    throws PortalException, SystemException {
841    
842                    List<WikiPage> pages = wikiPagePersistence.findByN_T_S(
843                            nodeId, title, WorkflowConstants.STATUS_DRAFT, 0, 1);
844    
845                    if (!pages.isEmpty()) {
846                            return pages.get(0);
847                    }
848    
849                    pages = wikiPagePersistence.findByN_T_S(
850                            nodeId, title, WorkflowConstants.STATUS_PENDING, 0, 1);
851    
852                    if (!pages.isEmpty()) {
853                            return pages.get(0);
854                    }
855                    else {
856                            StringBundler sb = new StringBundler(5);
857    
858                            sb.append("{nodeId=");
859                            sb.append(nodeId);
860                            sb.append(", title=");
861                            sb.append(title);
862                            sb.append("}");
863    
864                            throw new NoSuchPageException(sb.toString());
865                    }
866            }
867    
868            @Override
869            public List<WikiPage> getIncomingLinks(long nodeId, String title)
870                    throws PortalException, SystemException {
871    
872                    List<WikiPage> links = new UniqueList<WikiPage>();
873    
874                    List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
875    
876                    for (WikiPage page : pages) {
877                            if (isLinkedTo(page, title)) {
878                                    links.add(page);
879                            }
880                    }
881    
882                    List<WikiPage> referrals = wikiPagePersistence.findByN_R(nodeId, title);
883    
884                    for (WikiPage referral : referrals) {
885                            for (WikiPage page : pages) {
886                                    if (isLinkedTo(page, referral.getTitle())) {
887                                            links.add(page);
888                                    }
889                            }
890                    }
891    
892                    return ListUtil.sort(links);
893            }
894    
895            @Override
896            public WikiPage getLatestPage(
897                            long resourcePrimKey, int status, boolean preferApproved)
898                    throws PortalException, SystemException {
899    
900                    WikiPage page = fetchLatestPage(
901                            resourcePrimKey, status, preferApproved);
902    
903                    if (page == null) {
904                            StringBundler sb = new StringBundler(5);
905    
906                            sb.append("{resourcePrimKey=");
907                            sb.append(resourcePrimKey);
908                            sb.append(", status=");
909                            sb.append(status);
910                            sb.append("}");
911    
912                            throw new NoSuchPageException(sb.toString());
913                    }
914    
915                    return page;
916            }
917    
918            @Override
919            public WikiPage getLatestPage(
920                            long resourcePrimKey, long nodeId, int status,
921                            boolean preferApproved)
922                    throws PortalException, SystemException {
923    
924                    WikiPage page = fetchLatestPage(
925                            resourcePrimKey, nodeId, status, preferApproved);
926    
927                    if (page == null) {
928                            StringBundler sb = new StringBundler(7);
929    
930                            sb.append("{resourcePrimKey=");
931                            sb.append(resourcePrimKey);
932                            sb.append(", nodeId=");
933                            sb.append(nodeId);
934                            sb.append(", status=");
935                            sb.append(status);
936                            sb.append("}");
937    
938                            throw new NoSuchPageException(sb.toString());
939                    }
940    
941                    return page;
942            }
943    
944            @Override
945            public WikiPage getLatestPage(
946                            long nodeId, String title, int status, boolean preferApproved)
947                    throws PortalException, SystemException {
948    
949                    WikiPage page = fetchLatestPage(nodeId, title, status, preferApproved);
950    
951                    if (page == null) {
952                            StringBundler sb = new StringBundler(7);
953    
954                            sb.append("{nodeId=");
955                            sb.append(nodeId);
956                            sb.append(", title=");
957                            sb.append(title);
958                            sb.append(", status=");
959                            sb.append(status);
960                            sb.append("}");
961    
962                            throw new NoSuchPageException(sb.toString());
963                    }
964    
965                    return page;
966            }
967    
968            @Override
969            public List<WikiPage> getNoAssetPages() throws SystemException {
970                    return wikiPageFinder.findByNoAssets();
971            }
972    
973            @Override
974            public List<WikiPage> getOrphans(long nodeId)
975                    throws PortalException, SystemException {
976    
977                    List<WikiPage> pages = wikiPagePersistence.findByN_H_S(
978                            nodeId, true, WorkflowConstants.STATUS_APPROVED);
979    
980                    return WikiUtil.filterOrphans(pages);
981            }
982    
983            @Override
984            public List<WikiPage> getOutgoingLinks(long nodeId, String title)
985                    throws PortalException, SystemException {
986    
987                    WikiPage page = getPage(nodeId, title);
988    
989                    Map<String, WikiPage> pages = new LinkedHashMap<String, WikiPage>();
990    
991                    Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
992    
993                    for (Map.Entry<String, Boolean> entry : links.entrySet()) {
994                            String curTitle = entry.getKey();
995                            Boolean exists = entry.getValue();
996    
997                            if (exists) {
998                                    WikiPage curPage = getPage(nodeId, curTitle);
999    
1000                                    if (!pages.containsKey(curPage.getTitle())) {
1001                                            pages.put(curPage.getTitle(), curPage);
1002                                    }
1003                            }
1004                            else {
1005                                    WikiPageImpl newPage = new WikiPageImpl();
1006    
1007                                    newPage.setNew(true);
1008                                    newPage.setNodeId(nodeId);
1009                                    newPage.setTitle(curTitle);
1010    
1011                                    if (!pages.containsKey(curTitle)) {
1012                                            pages.put(curTitle, newPage);
1013                                    }
1014                            }
1015                    }
1016    
1017                    return ListUtil.fromMapValues(pages);
1018            }
1019    
1020            @Override
1021            public WikiPage getPage(long resourcePrimKey)
1022                    throws PortalException, SystemException {
1023    
1024                    return getPage(resourcePrimKey, Boolean.TRUE);
1025            }
1026    
1027            @Override
1028            public WikiPage getPage(long resourcePrimKey, Boolean head)
1029                    throws PortalException, SystemException {
1030    
1031                    WikiPageResource pageResource =
1032                            wikiPageResourceLocalService.getPageResource(resourcePrimKey);
1033    
1034                    return getPage(pageResource.getNodeId(), pageResource.getTitle(), head);
1035            }
1036    
1037            @Override
1038            public WikiPage getPage(long nodeId, String title)
1039                    throws PortalException, SystemException {
1040    
1041                    WikiPage page = fetchPage(nodeId, title);
1042    
1043                    if (page != null) {
1044                            return page;
1045                    }
1046                    else {
1047                            StringBundler sb = new StringBundler(5);
1048    
1049                            sb.append("{nodeId=");
1050                            sb.append(nodeId);
1051                            sb.append(", title=");
1052                            sb.append(title);
1053                            sb.append("}");
1054    
1055                            throw new NoSuchPageException(sb.toString());
1056                    }
1057            }
1058    
1059            @Override
1060            public WikiPage getPage(long nodeId, String title, Boolean head)
1061                    throws PortalException, SystemException {
1062    
1063                    List<WikiPage> pages;
1064    
1065                    if (head == null) {
1066                            pages = wikiPagePersistence.findByN_T(nodeId, title, 0, 1);
1067                    }
1068                    else {
1069                            pages = wikiPagePersistence.findByN_T_H(nodeId, title, head, 0, 1);
1070                    }
1071    
1072                    if (!pages.isEmpty()) {
1073                            return pages.get(0);
1074                    }
1075                    else {
1076                            StringBundler sb = new StringBundler(7);
1077    
1078                            sb.append("{nodeId=");
1079                            sb.append(nodeId);
1080                            sb.append(", title=");
1081                            sb.append(title);
1082                            sb.append(", head=");
1083                            sb.append(head);
1084                            sb.append("}");
1085    
1086                            throw new NoSuchPageException(sb.toString());
1087                    }
1088            }
1089    
1090            @Override
1091            public WikiPage getPage(long nodeId, String title, double version)
1092                    throws PortalException, SystemException {
1093    
1094                    WikiPage page = null;
1095    
1096                    if (version == 0) {
1097                            page = getPage(nodeId, title);
1098                    }
1099                    else {
1100                            page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
1101                    }
1102    
1103                    return page;
1104            }
1105    
1106            @Override
1107            public WikiPage getPageByPageId(long pageId)
1108                    throws PortalException, SystemException {
1109    
1110                    return wikiPagePersistence.findByPrimaryKey(pageId);
1111            }
1112    
1113            @Override
1114            public WikiPageDisplay getPageDisplay(
1115                            long nodeId, String title, PortletURL viewPageURL,
1116                            PortletURL editPageURL, String attachmentURLPrefix)
1117                    throws PortalException, SystemException {
1118    
1119                    WikiPage page = getPage(nodeId, title);
1120    
1121                    return getPageDisplay(
1122                            page, viewPageURL, editPageURL, attachmentURLPrefix);
1123            }
1124    
1125            @Override
1126            public WikiPageDisplay getPageDisplay(
1127                            WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
1128                            String attachmentURLPrefix)
1129                    throws PortalException, SystemException {
1130    
1131                    String formattedContent = WikiUtil.convert(
1132                            page, viewPageURL, editPageURL, attachmentURLPrefix);
1133    
1134                    return new WikiPageDisplayImpl(
1135                            page.getUserId(), page.getNodeId(), page.getTitle(),
1136                            page.getVersion(), page.getContent(), formattedContent,
1137                            page.getFormat(), page.getHead(), page.getAttachmentsFileEntries());
1138            }
1139    
1140            @Override
1141            public List<WikiPage> getPages(
1142                            long nodeId, boolean head, int start, int end)
1143                    throws SystemException {
1144    
1145                    return getPages(
1146                            nodeId, head, start, end, new PageCreateDateComparator(false));
1147            }
1148    
1149            @Override
1150            public List<WikiPage> getPages(
1151                            long nodeId, boolean head, int status, int start, int end)
1152                    throws SystemException {
1153    
1154                    return getPages(
1155                            nodeId, head, status, start, end,
1156                            new PageCreateDateComparator(false));
1157            }
1158    
1159            @Override
1160            public List<WikiPage> getPages(
1161                            long nodeId, boolean head, int status, int start, int end,
1162                            OrderByComparator obc)
1163                    throws SystemException {
1164    
1165                    if (status == WorkflowConstants.STATUS_ANY) {
1166                            return wikiPagePersistence.findByN_H(nodeId, head, start, end, obc);
1167                    }
1168                    else {
1169                            return wikiPagePersistence.findByN_H_S(
1170                                    nodeId, head, status, start, end, obc);
1171                    }
1172            }
1173    
1174            @Override
1175            public List<WikiPage> getPages(
1176                            long nodeId, boolean head, int start, int end,
1177                            OrderByComparator obc)
1178                    throws SystemException {
1179    
1180                    return getPages(
1181                            nodeId, head, WorkflowConstants.STATUS_APPROVED, start, end, obc);
1182            }
1183    
1184            @Override
1185            public List<WikiPage> getPages(long nodeId, int start, int end)
1186                    throws SystemException {
1187    
1188                    return getPages(
1189                            nodeId, start, end, new PageCreateDateComparator(false));
1190            }
1191    
1192            @Override
1193            public List<WikiPage> getPages(
1194                            long nodeId, int start, int end, OrderByComparator obc)
1195                    throws SystemException {
1196    
1197                    return wikiPagePersistence.findByNodeId(nodeId, start, end, obc);
1198            }
1199    
1200            @Override
1201            public List<WikiPage> getPages(
1202                            long resourcePrimKey, long nodeId, int status)
1203                    throws SystemException {
1204    
1205                    return wikiPagePersistence.findByR_N_S(resourcePrimKey, nodeId, status);
1206            }
1207    
1208            @Override
1209            public List<WikiPage> getPages(
1210                            long userId, long nodeId, int status, int start, int end)
1211                    throws SystemException {
1212    
1213                    if (userId > 0) {
1214                            return wikiPagePersistence.findByU_N_S(
1215                                    userId, nodeId, status, start, end,
1216                                    new PageCreateDateComparator(false));
1217                    }
1218                    else {
1219                            return wikiPagePersistence.findByN_S(
1220                                    nodeId, status, start, end,
1221                                    new PageCreateDateComparator(false));
1222                    }
1223            }
1224    
1225            @Override
1226            public List<WikiPage> getPages(
1227                            long nodeId, String title, boolean head, int start, int end)
1228                    throws SystemException {
1229    
1230                    return wikiPagePersistence.findByN_T_H(
1231                            nodeId, title, head, start, end,
1232                            new PageCreateDateComparator(false));
1233            }
1234    
1235            @Override
1236            public List<WikiPage> getPages(
1237                            long nodeId, String title, int start, int end)
1238                    throws SystemException {
1239    
1240                    return wikiPagePersistence.findByN_T(
1241                            nodeId, title, start, end, new PageCreateDateComparator(false));
1242            }
1243    
1244            @Override
1245            public List<WikiPage> getPages(
1246                            long nodeId, String title, int start, int end,
1247                            OrderByComparator obc)
1248                    throws SystemException {
1249    
1250                    return wikiPagePersistence.findByN_T(nodeId, title, start, end, obc);
1251            }
1252    
1253            @Override
1254            public List<WikiPage> getPages(String format) throws SystemException {
1255                    return wikiPagePersistence.findByFormat(format);
1256            }
1257    
1258            @Override
1259            public int getPagesCount(long nodeId) throws SystemException {
1260                    return wikiPagePersistence.countByNodeId(nodeId);
1261            }
1262    
1263            @Override
1264            public int getPagesCount(long nodeId, boolean head) throws SystemException {
1265                    return wikiPagePersistence.countByN_H_S(
1266                            nodeId, head, WorkflowConstants.STATUS_APPROVED);
1267            }
1268    
1269            @Override
1270            public int getPagesCount(long nodeId, boolean head, int status)
1271                    throws SystemException {
1272    
1273                    if (status == WorkflowConstants.STATUS_ANY) {
1274                            return wikiPagePersistence.countByN_H_NotS(
1275                                    nodeId, head, WorkflowConstants.STATUS_IN_TRASH);
1276                    }
1277                    else {
1278                            return wikiPagePersistence.countByN_H_S(nodeId, head, status);
1279                    }
1280            }
1281    
1282            @Override
1283            public int getPagesCount(long nodeId, int status) throws SystemException {
1284                    return wikiPagePersistence.countByN_S(nodeId, status);
1285            }
1286    
1287            @Override
1288            public int getPagesCount(long userId, long nodeId, int status)
1289                    throws SystemException {
1290    
1291                    if (userId > 0) {
1292                            return wikiPagePersistence.countByU_N_S(userId, nodeId, status);
1293                    }
1294                    else {
1295                            return wikiPagePersistence.countByN_S(nodeId, status);
1296                    }
1297            }
1298    
1299            @Override
1300            public int getPagesCount(long nodeId, String title) throws SystemException {
1301                    return wikiPagePersistence.countByN_T(nodeId, title);
1302            }
1303    
1304            @Override
1305            public int getPagesCount(long nodeId, String title, boolean head)
1306                    throws SystemException {
1307    
1308                    return wikiPagePersistence.countByN_T_H(nodeId, title, head);
1309            }
1310    
1311            @Override
1312            public int getPagesCount(String format) throws SystemException {
1313                    return wikiPagePersistence.countByFormat(format);
1314            }
1315    
1316            /**
1317             * @deprecated As of 6.2.0, replaced by {@link #getRecentChanges(long, long,
1318             *             int, int)}
1319             */
1320            @Override
1321            public List<WikiPage> getRecentChanges(long nodeId, int start, int end)
1322                    throws PortalException, SystemException {
1323    
1324                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
1325    
1326                    return getRecentChanges(node.getGroupId(), nodeId, start, end);
1327            }
1328    
1329            @Override
1330            public List<WikiPage> getRecentChanges(
1331                            long groupId, long nodeId, int start, int end)
1332                    throws SystemException {
1333    
1334                    Calendar cal = CalendarFactoryUtil.getCalendar();
1335    
1336                    cal.add(Calendar.WEEK_OF_YEAR, -1);
1337    
1338                    return wikiPageFinder.findByCreateDate(
1339                            groupId, nodeId, cal.getTime(), false, start, end);
1340            }
1341    
1342            /**
1343             * @deprecated As of 6.2.0, replaced by {@link #getRecentChangesCount(long,
1344             *             long)}
1345             */
1346            @Override
1347            public int getRecentChangesCount(long nodeId)
1348                    throws PortalException, SystemException {
1349    
1350                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
1351    
1352                    return getRecentChangesCount(node.getGroupId(), nodeId);
1353            }
1354    
1355            @Override
1356            public int getRecentChangesCount(long groupId, long nodeId)
1357                    throws SystemException {
1358    
1359                    Calendar cal = CalendarFactoryUtil.getCalendar();
1360    
1361                    cal.add(Calendar.WEEK_OF_YEAR, -1);
1362    
1363                    return wikiPageFinder.countByCreateDate(
1364                            groupId, nodeId, cal.getTime(), false);
1365            }
1366    
1367            @Override
1368            public String[] getTempPageAttachmentNames(
1369                            long groupId, long userId, String tempFolderName)
1370                    throws PortalException, SystemException {
1371    
1372                    return TempFileUtil.getTempFileEntryNames(
1373                            groupId, userId, tempFolderName);
1374            }
1375    
1376            @Override
1377            public boolean hasDraftPage(long nodeId, String title)
1378                    throws SystemException {
1379    
1380                    int count = wikiPagePersistence.countByN_T_S(
1381                            nodeId, title, WorkflowConstants.STATUS_DRAFT);
1382    
1383                    if (count > 0) {
1384                            return true;
1385                    }
1386                    else {
1387                            return false;
1388                    }
1389            }
1390    
1391            @Override
1392            public void movePage(
1393                            long userId, long nodeId, String title, String newTitle,
1394                            boolean strict, ServiceContext serviceContext)
1395                    throws PortalException, SystemException {
1396    
1397                    validateTitle(newTitle);
1398    
1399                    // Check if the new title already exists
1400    
1401                    if (StringUtil.equalsIgnoreCase(title, newTitle)) {
1402                            throw new DuplicatePageException(newTitle);
1403                    }
1404    
1405                    if (isUsedTitle(nodeId, newTitle)) {
1406                            WikiPage page = getPage(nodeId, newTitle);
1407    
1408                            // Support moving back to a previously moved title
1409    
1410                            if (((page.getVersion() == WikiPageConstants.VERSION_DEFAULT) &&
1411                                     (page.getContent().length() < 200)) ||
1412                                    !strict) {
1413    
1414                                    deletePage(nodeId, newTitle);
1415                            }
1416                            else {
1417                                    throw new DuplicatePageException(newTitle);
1418                            }
1419                    }
1420    
1421                    // All versions
1422    
1423                    List<WikiPage> versionPages = wikiPagePersistence.findByN_T(
1424                            nodeId, title);
1425    
1426                    if (versionPages.size() == 0) {
1427                            return;
1428                    }
1429    
1430                    for (WikiPage page : versionPages) {
1431                            page.setTitle(newTitle);
1432    
1433                            wikiPagePersistence.update(page);
1434                    }
1435    
1436                    // Children
1437    
1438                    List<WikiPage> children = wikiPagePersistence.findByN_P(nodeId, title);
1439    
1440                    for (WikiPage page : children) {
1441                            page.setParentTitle(newTitle);
1442    
1443                            wikiPagePersistence.update(page);
1444                    }
1445    
1446                    WikiPage page = versionPages.get(versionPages.size() - 1);
1447    
1448                    long resourcePrimKey = page.getResourcePrimKey();
1449    
1450                    // Page resource
1451    
1452                    WikiPageResource pageResource =
1453                            wikiPageResourcePersistence.findByPrimaryKey(resourcePrimKey);
1454    
1455                    pageResource.setTitle(newTitle);
1456    
1457                    wikiPageResourcePersistence.update(pageResource);
1458    
1459                    // Create stub page at the old location
1460    
1461                    double version = WikiPageConstants.VERSION_DEFAULT;
1462                    String summary = WikiPageConstants.MOVED + " to " + newTitle;
1463                    String format = page.getFormat();
1464                    boolean head = true;
1465                    String parentTitle = page.getParentTitle();
1466                    String redirectTitle = page.getTitle();
1467                    String content =
1468                            StringPool.DOUBLE_OPEN_BRACKET + redirectTitle +
1469                                    StringPool.DOUBLE_CLOSE_BRACKET;
1470    
1471                    serviceContext.setAddGroupPermissions(true);
1472                    serviceContext.setAddGuestPermissions(true);
1473    
1474                    populateServiceContext(serviceContext, page);
1475    
1476                    addPage(
1477                            userId, nodeId, title, version, content, summary, false, format,
1478                            head, parentTitle, redirectTitle, serviceContext);
1479    
1480                    // Move redirects to point to the page with the new title
1481    
1482                    List<WikiPage> redirectedPages = wikiPagePersistence.findByN_R(
1483                            nodeId, title);
1484    
1485                    for (WikiPage redirectedPage : redirectedPages) {
1486                            redirectedPage.setRedirectTitle(newTitle);
1487    
1488                            wikiPagePersistence.update(redirectedPage);
1489                    }
1490    
1491                    // Asset
1492    
1493                    updateAsset(
1494                            userId, page, serviceContext.getAssetCategoryIds(),
1495                            serviceContext.getAssetTagNames(),
1496                            serviceContext.getAssetLinkEntryIds());
1497    
1498                    // Indexer
1499    
1500                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1501                            WikiPage.class);
1502    
1503                    indexer.delete(
1504                            new Object[] {page.getCompanyId(), page.getNodeId(), title});
1505    
1506                    indexer.reindex(page);
1507            }
1508    
1509            @Override
1510            public void movePage(
1511                            long userId, long nodeId, String title, String newTitle,
1512                            ServiceContext serviceContext)
1513                    throws PortalException, SystemException {
1514    
1515                    movePage(userId, nodeId, title, newTitle, true, serviceContext);
1516            }
1517    
1518            @Override
1519            public FileEntry movePageAttachmentToTrash(
1520                            long userId, long nodeId, String title, String fileName)
1521                    throws PortalException, SystemException {
1522    
1523                    WikiPage page = getPage(nodeId, title);
1524    
1525                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1526                            page.getGroupId(), page.getAttachmentsFolderId(), fileName);
1527    
1528                    fileEntry = PortletFileRepositoryUtil.movePortletFileEntryToTrash(
1529                            userId, fileEntry.getFileEntryId());
1530    
1531                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1532    
1533                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
1534                    extraDataJSONObject.put(
1535                            "fileEntryTitle", TrashUtil.getOriginalTitle(fileEntry.getTitle()));
1536                    extraDataJSONObject.put("title", page.getTitle());
1537                    extraDataJSONObject.put("version", page.getVersion());
1538    
1539                    socialActivityLocalService.addActivity(
1540                            userId, page.getGroupId(), WikiPage.class.getName(),
1541                            page.getResourcePrimKey(),
1542                            SocialActivityConstants.TYPE_MOVE_ATTACHMENT_TO_TRASH,
1543                            extraDataJSONObject.toString(), 0);
1544    
1545                    return fileEntry;
1546            }
1547    
1548            @Override
1549            public WikiPage movePageToTrash(long userId, long nodeId, String title)
1550                    throws PortalException, SystemException {
1551    
1552                    List<WikiPage> wikiPages = wikiPagePersistence.findByN_T_H(
1553                            nodeId, title, true, 0, 1);
1554    
1555                    if (!wikiPages.isEmpty()) {
1556                            return movePageToTrash(userId, wikiPages.get(0));
1557                    }
1558    
1559                    return null;
1560            }
1561    
1562            @Override
1563            public WikiPage movePageToTrash(
1564                            long userId, long nodeId, String title, double version)
1565                    throws PortalException, SystemException {
1566    
1567                    WikiPage page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
1568    
1569                    return movePageToTrash(userId, page);
1570            }
1571    
1572            @Override
1573            public WikiPage movePageToTrash(long userId, WikiPage page)
1574                    throws PortalException, SystemException {
1575    
1576                    // Page
1577    
1578                    int oldStatus = page.getStatus();
1579                    String oldTitle = page.getTitle();
1580    
1581                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
1582                            page.setStatus(WorkflowConstants.STATUS_DRAFT);
1583    
1584                            wikiPagePersistence.update(page);
1585                    }
1586    
1587                    List<WikiPage> pageVersions = wikiPagePersistence.findByR_N_H(
1588                            page.getResourcePrimKey(), page.getNodeId(), false);
1589    
1590                    pageVersions = ListUtil.sort(pageVersions, new PageVersionComparator());
1591    
1592                    List<ObjectValuePair<Long, Integer>> pageVersionStatusOVPs =
1593                            new ArrayList<ObjectValuePair<Long, Integer>>();
1594    
1595                    if ((pageVersions != null) && !pageVersions.isEmpty()) {
1596                            pageVersionStatusOVPs = getPageVersionStatuses(pageVersions);
1597                    }
1598    
1599                    page = updateStatus(
1600                            userId, page, WorkflowConstants.STATUS_IN_TRASH,
1601                            new ServiceContext());
1602    
1603                    // Trash
1604    
1605                    WikiPageResource pageResource =
1606                            wikiPageResourcePersistence.fetchByPrimaryKey(
1607                                    page.getResourcePrimKey());
1608    
1609                    UnicodeProperties typeSettingsProperties = new UnicodeProperties();
1610    
1611                    typeSettingsProperties.put("title", page.getTitle());
1612    
1613                    TrashEntry trashEntry = trashEntryLocalService.addTrashEntry(
1614                            userId, page.getGroupId(), WikiPage.class.getName(),
1615                            page.getResourcePrimKey(), pageResource.getUuid(), null, oldStatus,
1616                            pageVersionStatusOVPs, typeSettingsProperties);
1617    
1618                    String trashTitle = TrashUtil.getTrashTitle(trashEntry.getEntryId());
1619    
1620                    for (WikiPage pageVersion : pageVersions) {
1621                            pageVersion.setTitle(trashTitle);
1622                            pageVersion.setStatus(WorkflowConstants.STATUS_IN_TRASH);
1623    
1624                            wikiPagePersistence.update(pageVersion);
1625                    }
1626    
1627                    pageResource.setTitle(trashTitle);
1628    
1629                    wikiPageResourcePersistence.update(pageResource);
1630    
1631                    page.setTitle(trashTitle);
1632    
1633                    wikiPagePersistence.update(page);
1634    
1635                    // Children
1636    
1637                    List<WikiPage> children = wikiPagePersistence.findByN_H_P(
1638                            page.getNodeId(), true, oldTitle);
1639    
1640                    for (WikiPage curPage : children) {
1641                            curPage.setParentTitle(trashTitle);
1642    
1643                            wikiPagePersistence.update(curPage);
1644    
1645                            if (!curPage.isInTrash()) {
1646                                    movePageToTrash(userId, curPage);
1647                            }
1648                    }
1649    
1650                    // Redirect Pages
1651    
1652                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_H_R(
1653                            page.getNodeId(), true, oldTitle);
1654    
1655                    for (WikiPage curPage : redirectPages) {
1656                            curPage.setRedirectTitle(trashTitle);
1657    
1658                            wikiPagePersistence.update(curPage);
1659    
1660                            if (!curPage.isInTrash()) {
1661                                    movePageToTrash(userId, curPage);
1662                            }
1663                    }
1664    
1665                    // Asset
1666    
1667                    assetEntryLocalService.updateVisible(
1668                            WikiPage.class.getName(), page.getResourcePrimKey(), false);
1669    
1670                    // Attachments
1671    
1672                    for (FileEntry fileEntry : page.getAttachmentsFileEntries()) {
1673                            PortletFileRepositoryUtil.movePortletFileEntryToTrash(
1674                                    userId, fileEntry.getFileEntryId());
1675                    }
1676    
1677                    // Comment
1678    
1679                    mbMessageLocalService.moveDiscussionToTrash(
1680                            WikiPage.class.getName(), page.getResourcePrimKey());
1681    
1682                    // Social
1683    
1684                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1685    
1686                    extraDataJSONObject.put(
1687                            "title", TrashUtil.getOriginalTitle(page.getTitle()));
1688                    extraDataJSONObject.put("version", page.getVersion());
1689    
1690                    socialActivityLocalService.addActivity(
1691                            userId, page.getGroupId(), WikiPage.class.getName(),
1692                            page.getResourcePrimKey(),
1693                            SocialActivityConstants.TYPE_MOVE_TO_TRASH,
1694                            extraDataJSONObject.toString(), 0);
1695    
1696                    // Indexer
1697    
1698                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1699                            WikiPage.class);
1700    
1701                    indexer.reindex(page);
1702    
1703                    // Workflow
1704    
1705                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
1706                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
1707                                    page.getCompanyId(), page.getGroupId(),
1708                                    WikiPage.class.getName(), page.getPageId());
1709                    }
1710    
1711                    return page;
1712            }
1713    
1714            @Override
1715            public void restorePageAttachmentFromTrash(
1716                            long userId, long nodeId, String title, String fileName)
1717                    throws PortalException, SystemException {
1718    
1719                    WikiPage page = getPage(nodeId, title);
1720    
1721                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1722                            page.getGroupId(), page.getAttachmentsFolderId(), fileName);
1723    
1724                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1725    
1726                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
1727                    extraDataJSONObject.put("fileEntryTitle", TrashUtil.getOriginalTitle(
1728                            fileEntry.getTitle()));
1729                    extraDataJSONObject.put("title", page.getTitle());
1730                    extraDataJSONObject.put("version", page.getVersion());
1731    
1732                    PortletFileRepositoryUtil.restorePortletFileEntryFromTrash(
1733                            userId, fileEntry.getFileEntryId());
1734    
1735                    socialActivityLocalService.addActivity(
1736                            userId, page.getGroupId(), WikiPage.class.getName(),
1737                            page.getResourcePrimKey(),
1738                            SocialActivityConstants.TYPE_RESTORE_ATTACHMENT_FROM_TRASH,
1739                            extraDataJSONObject.toString(), 0);
1740            }
1741    
1742            @Override
1743            public void restorePageFromTrash(long userId, WikiPage page)
1744                    throws PortalException, SystemException {
1745    
1746                    String title = page.getTitle();
1747    
1748                    String originalTitle = TrashUtil.getOriginalTitle(title);
1749    
1750                    List<WikiPage> pageVersions = wikiPagePersistence.findByR_N_H(
1751                            page.getResourcePrimKey(), page.getNodeId(), false);
1752    
1753                    for (WikiPage pageVersion : pageVersions) {
1754                            pageVersion.setTitle(originalTitle);
1755    
1756                            wikiPagePersistence.update(pageVersion);
1757                    }
1758    
1759                    WikiPageResource pageResource =
1760                            wikiPageResourcePersistence.fetchByPrimaryKey(
1761                                    page.getResourcePrimKey());
1762    
1763                    pageResource.setTitle(originalTitle);
1764    
1765                    wikiPageResourcePersistence.update(pageResource);
1766    
1767                    page.setTitle(originalTitle);
1768    
1769                    WikiPage parentPage = page.getParentPage();
1770    
1771                    if ((parentPage != null) && parentPage.isInTrash()) {
1772                            page.setParentTitle(StringPool.BLANK);
1773                    }
1774    
1775                    WikiPage redirectPage = page.getRedirectPage();
1776    
1777                    if ((redirectPage != null) && redirectPage.isInTrash()) {
1778                            page.setRedirectTitle(StringPool.BLANK);
1779                    }
1780    
1781                    wikiPagePersistence.update(page);
1782    
1783                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
1784                            WikiPage.class.getName(), page.getResourcePrimKey());
1785    
1786                    updateStatus(
1787                            userId, page, trashEntry.getStatus(), new ServiceContext());
1788    
1789                    // Children
1790    
1791                    List<WikiPage> children = wikiPagePersistence.findByN_H_P_S(
1792                            page.getNodeId(), true, title, WorkflowConstants.STATUS_IN_TRASH);
1793    
1794                    for (WikiPage curPage : children) {
1795                            curPage.setParentTitle(originalTitle);
1796    
1797                            wikiPagePersistence.update(curPage);
1798    
1799                            if (curPage.isInTrash()) {
1800                                    restorePageFromTrash(userId, curPage);
1801                            }
1802                    }
1803    
1804                    // Redirect Pages
1805    
1806                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_H_R(
1807                            page.getNodeId(), true, title);
1808    
1809                    for (WikiPage curPage : redirectPages) {
1810                            curPage.setRedirectTitle(originalTitle);
1811    
1812                            wikiPagePersistence.update(curPage);
1813    
1814                            if (curPage.isInTrash()) {
1815                                    restorePageFromTrash(userId, curPage);
1816                            }
1817                    }
1818    
1819                    // Attachments
1820    
1821                    for (FileEntry fileEntry : page.getDeletedAttachmentsFileEntries()) {
1822                            PortletFileRepositoryUtil.restorePortletFileEntryFromTrash(
1823                                    userId, fileEntry.getFileEntryId());
1824                    }
1825    
1826                    // Comment
1827    
1828                    mbMessageLocalService.restoreDiscussionFromTrash(
1829                            WikiPage.class.getName(), page.getResourcePrimKey());
1830    
1831                    // Trash
1832    
1833                    List<TrashVersion> trashVersions = trashVersionLocalService.getVersions(
1834                            trashEntry.getEntryId());
1835    
1836                    for (TrashVersion trashVersion : trashVersions) {
1837                            WikiPage trashArticleVersion = wikiPagePersistence.findByPrimaryKey(
1838                                    trashVersion.getClassPK());
1839    
1840                            trashArticleVersion.setStatus(trashVersion.getStatus());
1841    
1842                            wikiPagePersistence.update(trashArticleVersion);
1843                    }
1844    
1845                    trashEntryLocalService.deleteEntry(
1846                            WikiPage.class.getName(), page.getResourcePrimKey());
1847    
1848                    // Social
1849    
1850                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1851    
1852                    extraDataJSONObject.put("title", page.getTitle());
1853                    extraDataJSONObject.put("version", page.getVersion());
1854    
1855                    socialActivityLocalService.addActivity(
1856                            userId, page.getGroupId(), WikiPage.class.getName(),
1857                            page.getResourcePrimKey(),
1858                            SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
1859                            extraDataJSONObject.toString(), 0);
1860    
1861                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1862                            WikiPage.class);
1863    
1864                    indexer.reindex(page);
1865            }
1866    
1867            @Override
1868            public WikiPage revertPage(
1869                            long userId, long nodeId, String title, double version,
1870                            ServiceContext serviceContext)
1871                    throws PortalException, SystemException {
1872    
1873                    WikiPage oldPage = getPage(nodeId, title, version);
1874    
1875                    populateServiceContext(serviceContext, oldPage);
1876    
1877                    return updatePage(
1878                            userId, nodeId, title, 0, oldPage.getContent(),
1879                            WikiPageConstants.REVERTED + " to " + version, false,
1880                            oldPage.getFormat(), getParentPageTitle(oldPage),
1881                            oldPage.getRedirectTitle(), serviceContext);
1882            }
1883    
1884            @Override
1885            public void subscribePage(long userId, long nodeId, String title)
1886                    throws PortalException, SystemException {
1887    
1888                    WikiPage page = getPage(nodeId, title);
1889    
1890                    subscriptionLocalService.addSubscription(
1891                            userId, page.getGroupId(), WikiPage.class.getName(),
1892                            page.getResourcePrimKey());
1893            }
1894    
1895            @Override
1896            public void unsubscribePage(long userId, long nodeId, String title)
1897                    throws PortalException, SystemException {
1898    
1899                    WikiPage page = getPage(nodeId, title);
1900    
1901                    subscriptionLocalService.deleteSubscription(
1902                            userId, WikiPage.class.getName(), page.getResourcePrimKey());
1903            }
1904    
1905            @Override
1906            public void updateAsset(
1907                            long userId, WikiPage page, long[] assetCategoryIds,
1908                            String[] assetTagNames, long[] assetLinkEntryIds)
1909                    throws PortalException, SystemException {
1910    
1911                    boolean addDraftAssetEntry = false;
1912    
1913                    if (!page.isApproved() &&
1914                            (page.getVersion() != WikiPageConstants.VERSION_DEFAULT)) {
1915    
1916                            int approvedPagesCount = wikiPagePersistence.countByN_T_S(
1917                                    page.getNodeId(), page.getTitle(),
1918                                    WorkflowConstants.STATUS_APPROVED);
1919    
1920                            if (approvedPagesCount > 0) {
1921                                    addDraftAssetEntry = true;
1922                            }
1923                    }
1924    
1925                    AssetEntry assetEntry = null;
1926    
1927                    if (addDraftAssetEntry) {
1928                            assetEntry = assetEntryLocalService.updateEntry(
1929                                    userId, page.getGroupId(), page.getCreateDate(),
1930                                    page.getModifiedDate(), WikiPage.class.getName(),
1931                                    page.getPrimaryKey(), page.getUuid(), 0, assetCategoryIds,
1932                                    assetTagNames, false, null, null, null, ContentTypes.TEXT_HTML,
1933                                    page.getTitle(), null, null, null, null, 0, 0, null, false);
1934                    }
1935                    else {
1936                            assetEntry = assetEntryLocalService.updateEntry(
1937                                    userId, page.getGroupId(), page.getCreateDate(),
1938                                    page.getModifiedDate(), WikiPage.class.getName(),
1939                                    page.getResourcePrimKey(), page.getUuid(), 0, assetCategoryIds,
1940                                    assetTagNames, page.isApproved(), null, null, null,
1941                                    ContentTypes.TEXT_HTML, page.getTitle(), null, null, null, null,
1942                                    0, 0, null, false);
1943                    }
1944    
1945                    assetLinkLocalService.updateLinks(
1946                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
1947                            AssetLinkConstants.TYPE_RELATED);
1948            }
1949    
1950            @Override
1951            public WikiPage updatePage(
1952                            long userId, long nodeId, String title, double version,
1953                            String content, String summary, boolean minorEdit, String format,
1954                            String parentTitle, String redirectTitle,
1955                            ServiceContext serviceContext)
1956                    throws PortalException, SystemException {
1957    
1958                    // Page
1959    
1960                    User user = userPersistence.findByPrimaryKey(userId);
1961                    Date now = new Date();
1962    
1963                    WikiPage oldPage = null;
1964    
1965                    try {
1966                            oldPage = wikiPagePersistence.findByN_T_First(nodeId, title, null);
1967                    }
1968                    catch (NoSuchPageException nspe) {
1969                            return addPage(
1970                                    userId, nodeId, title, WikiPageConstants.VERSION_DEFAULT,
1971                                    content, summary, minorEdit, format, true, parentTitle,
1972                                    redirectTitle, serviceContext);
1973                    }
1974    
1975                    long pageId = 0;
1976    
1977                    if (oldPage.isApproved()) {
1978                            pageId = counterLocalService.increment();
1979                    }
1980                    else {
1981                            pageId = oldPage.getPageId();
1982                    }
1983    
1984                    content = SanitizerUtil.sanitize(
1985                            user.getCompanyId(), oldPage.getGroupId(), userId,
1986                            WikiPage.class.getName(), pageId, "text/" + format, content);
1987    
1988                    validate(nodeId, content, format);
1989    
1990                    double oldVersion = oldPage.getVersion();
1991    
1992                    if ((version > 0) && (version != oldVersion)) {
1993                            throw new PageVersionException();
1994                    }
1995    
1996                    serviceContext.validateModifiedDate(
1997                            oldPage, PageVersionException.class);
1998    
1999                    long resourcePrimKey =
2000                            wikiPageResourceLocalService.getPageResourcePrimKey(nodeId, title);
2001                    long groupId = oldPage.getGroupId();
2002    
2003                    WikiPage page = oldPage;
2004    
2005                    double newVersion = oldVersion;
2006    
2007                    if (oldPage.isApproved()) {
2008                            newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
2009    
2010                            page = wikiPagePersistence.create(pageId);
2011    
2012                            page.setUuid(serviceContext.getUuid());
2013                    }
2014    
2015                    page.setResourcePrimKey(resourcePrimKey);
2016                    page.setGroupId(groupId);
2017                    page.setCompanyId(user.getCompanyId());
2018                    page.setUserId(user.getUserId());
2019                    page.setUserName(user.getFullName());
2020                    page.setCreateDate(serviceContext.getModifiedDate(now));
2021                    page.setModifiedDate(serviceContext.getModifiedDate(now));
2022                    page.setNodeId(nodeId);
2023                    page.setTitle(title);
2024                    page.setVersion(newVersion);
2025                    page.setMinorEdit(minorEdit);
2026                    page.setContent(content);
2027    
2028                    if (oldPage.isPending()) {
2029                            page.setStatus(oldPage.getStatus());
2030                    }
2031                    else {
2032                            page.setStatus(WorkflowConstants.STATUS_DRAFT);
2033                    }
2034    
2035                    page.setSummary(summary);
2036                    page.setFormat(format);
2037    
2038                    if (Validator.isNotNull(parentTitle)) {
2039                            page.setParentTitle(parentTitle);
2040                    }
2041    
2042                    if (Validator.isNotNull(redirectTitle)) {
2043                            page.setRedirectTitle(redirectTitle);
2044                    }
2045    
2046                    ExpandoBridgeUtil.setExpandoBridgeAttributes(
2047                            oldPage.getExpandoBridge(), page.getExpandoBridge(),
2048                            serviceContext);
2049    
2050                    wikiPagePersistence.update(page);
2051    
2052                    // Node
2053    
2054                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
2055    
2056                    node.setLastPostDate(serviceContext.getModifiedDate(now));
2057    
2058                    wikiNodePersistence.update(node);
2059    
2060                    // Asset
2061    
2062                    updateAsset(
2063                            userId, page, serviceContext.getAssetCategoryIds(),
2064                            serviceContext.getAssetTagNames(),
2065                            serviceContext.getAssetLinkEntryIds());
2066    
2067                    // Social
2068    
2069                    if (!page.isMinorEdit() ||
2070                            PropsValues.WIKI_PAGE_MINOR_EDIT_ADD_SOCIAL_ACTIVITY) {
2071    
2072                            if (oldVersion == newVersion) {
2073                                    SocialActivity lastSocialActivity =
2074                                            socialActivityLocalService.fetchFirstActivity(
2075                                                    WikiPage.class.getName(), page.getResourcePrimKey(),
2076                                                    WikiActivityKeys.UPDATE_PAGE);
2077    
2078                                    if (lastSocialActivity != null) {
2079                                            lastSocialActivity.setCreateDate(now.getTime() + 1);
2080                                            lastSocialActivity.setUserId(serviceContext.getUserId());
2081    
2082                                            socialActivityPersistence.update(lastSocialActivity);
2083                                    }
2084                            }
2085                            else {
2086                                    JSONObject extraDataJSONObject =
2087                                            JSONFactoryUtil.createJSONObject();
2088    
2089                                    extraDataJSONObject.put("title", page.getTitle());
2090                                    extraDataJSONObject.put("version", page.getVersion());
2091    
2092                                    socialActivityLocalService.addActivity(
2093                                            userId, page.getGroupId(), WikiPage.class.getName(),
2094                                            page.getResourcePrimKey(), WikiActivityKeys.UPDATE_PAGE,
2095                                            extraDataJSONObject.toString(), 0);
2096                            }
2097                    }
2098    
2099                    // Workflow
2100    
2101                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
2102                            user.getCompanyId(), page.getGroupId(), userId,
2103                            WikiPage.class.getName(), page.getPageId(), page, serviceContext);
2104    
2105                    return page;
2106            }
2107    
2108            @Override
2109            public WikiPage updateStatus(
2110                            long userId, long resourcePrimKey, int status,
2111                            ServiceContext serviceContext)
2112                    throws PortalException, SystemException {
2113    
2114                    WikiPageResource pageResource =
2115                            wikiPageResourceLocalService.getPageResource(resourcePrimKey);
2116    
2117                    List<WikiPage> pages = wikiPagePersistence.findByN_T(
2118                            pageResource.getNodeId(), pageResource.getTitle(), 0, 1,
2119                            new PageVersionComparator());
2120    
2121                    WikiPage page = null;
2122    
2123                    if (!pages.isEmpty()) {
2124                            page = pages.get(0);
2125                    }
2126                    else {
2127                            throw new NoSuchPageException(
2128                                    "{resourcePrimKey=" + resourcePrimKey + "}");
2129                    }
2130    
2131                    return updateStatus(userId, page, status, serviceContext);
2132            }
2133    
2134            @Override
2135            public WikiPage updateStatus(
2136                            long userId, WikiPage page, int status,
2137                            ServiceContext serviceContext)
2138                    throws PortalException, SystemException {
2139    
2140                    // Page
2141    
2142                    User user = userPersistence.findByPrimaryKey(userId);
2143                    WikiNode node = wikiNodePersistence.findByPrimaryKey(page.getNodeId());
2144    
2145                    Date now = new Date();
2146    
2147                    int oldStatus = page.getStatus();
2148    
2149                    page.setStatus(status);
2150                    page.setStatusByUserId(userId);
2151                    page.setStatusByUserName(user.getFullName());
2152                    page.setStatusDate(now);
2153    
2154                    wikiPagePersistence.update(page);
2155    
2156                    if (status == WorkflowConstants.STATUS_APPROVED) {
2157    
2158                            // Asset
2159    
2160                            if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
2161                                    (page.getVersion() != WikiPageConstants.VERSION_DEFAULT)) {
2162    
2163                                    AssetEntry draftAssetEntry = assetEntryLocalService.fetchEntry(
2164                                            WikiPage.class.getName(), page.getPrimaryKey());
2165    
2166                                    if (draftAssetEntry != null) {
2167                                            long[] assetCategoryIds = draftAssetEntry.getCategoryIds();
2168                                            String[] assetTagNames = draftAssetEntry.getTagNames();
2169    
2170                                            List<AssetLink> assetLinks =
2171                                                    assetLinkLocalService.getDirectLinks(
2172                                                            draftAssetEntry.getEntryId(),
2173                                                            AssetLinkConstants.TYPE_RELATED, false);
2174    
2175                                            long[] assetLinkEntryIds = StringUtil.split(
2176                                                    ListUtil.toString(
2177                                                            assetLinks, AssetLink.ENTRY_ID2_ACCESSOR), 0L);
2178    
2179                                            AssetEntry assetEntry = assetEntryLocalService.updateEntry(
2180                                                    userId, page.getGroupId(), page.getCreateDate(),
2181                                                    page.getModifiedDate(), WikiPage.class.getName(),
2182                                                    page.getResourcePrimKey(), page.getUuid(), 0,
2183                                                    assetCategoryIds, assetTagNames, true, null, null, null,
2184                                                    ContentTypes.TEXT_HTML, page.getTitle(), null, null,
2185                                                    null, null, 0, 0, null, false);
2186    
2187                                            // Asset Links
2188    
2189                                            assetLinkLocalService.updateLinks(
2190                                                    userId, assetEntry.getEntryId(), assetLinkEntryIds,
2191                                                    AssetLinkConstants.TYPE_RELATED);
2192    
2193                                            SystemEventHierarchyEntryThreadLocal.push(WikiPage.class);
2194    
2195                                            try {
2196                                                    assetEntryLocalService.deleteEntry(
2197                                                            draftAssetEntry.getEntryId());
2198                                            }
2199                                            finally {
2200                                                    SystemEventHierarchyEntryThreadLocal.pop(
2201                                                            WikiPage.class);
2202                                            }
2203                                    }
2204                            }
2205    
2206                            assetEntryLocalService.updateVisible(
2207                                    WikiPage.class.getName(), page.getResourcePrimKey(), true);
2208    
2209                            // Social
2210    
2211                            if ((oldStatus != WorkflowConstants.STATUS_IN_TRASH) &&
2212                                    (page.getVersion() == WikiPageConstants.VERSION_DEFAULT) &&
2213                                    (!page.isMinorEdit() ||
2214                                     PropsValues.WIKI_PAGE_MINOR_EDIT_ADD_SOCIAL_ACTIVITY)) {
2215    
2216                                    JSONObject extraDataJSONObject =
2217                                            JSONFactoryUtil.createJSONObject();
2218    
2219                                    extraDataJSONObject.put("title", page.getTitle());
2220                                    extraDataJSONObject.put("version", page.getVersion());
2221    
2222                                    socialActivityLocalService.addActivity(
2223                                            userId, page.getGroupId(), WikiPage.class.getName(),
2224                                            page.getResourcePrimKey(), WikiActivityKeys.ADD_PAGE,
2225                                            extraDataJSONObject.toString(), 0);
2226                            }
2227    
2228                            // Subscriptions
2229    
2230                            if (NotificationThreadLocal.isEnabled() &&
2231                                    (!page.isMinorEdit() ||
2232                                     PropsValues.WIKI_PAGE_MINOR_EDIT_SEND_EMAIL)) {
2233    
2234                                    boolean update = false;
2235    
2236                                    if (page.getVersion() > WikiPageConstants.VERSION_DEFAULT) {
2237                                            update = true;
2238                                    }
2239    
2240                                    notifySubscribers(node, page, serviceContext, update);
2241                            }
2242    
2243                            // Cache
2244    
2245                            clearPageCache(page);
2246                    }
2247    
2248                    // Head
2249    
2250                    if (status == WorkflowConstants.STATUS_APPROVED) {
2251                            page.setHead(true);
2252    
2253                            List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
2254                                    page.getNodeId(), page.getTitle(), true);
2255    
2256                            for (WikiPage curPage : pages) {
2257                                    if (!curPage.equals(page)) {
2258                                            curPage.setHead(false);
2259    
2260                                            wikiPagePersistence.update(curPage);
2261                                    }
2262                            }
2263                    }
2264                    else if (status != WorkflowConstants.STATUS_IN_TRASH) {
2265                            page.setHead(false);
2266    
2267                            List<WikiPage> pages = wikiPagePersistence.findByN_T_S(
2268                                    page.getNodeId(), page.getTitle(),
2269                                    WorkflowConstants.STATUS_APPROVED);
2270    
2271                            for (WikiPage curPage : pages) {
2272                                    if (!curPage.equals(page)) {
2273                                            curPage.setHead(true);
2274    
2275                                            wikiPagePersistence.update(curPage);
2276    
2277                                            break;
2278                                    }
2279                            }
2280                    }
2281    
2282                    // Indexer
2283    
2284                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2285                            WikiPage.class);
2286    
2287                    indexer.reindex(page);
2288    
2289                    return wikiPagePersistence.update(page);
2290            }
2291    
2292            @Override
2293            public void validateTitle(String title) throws PortalException {
2294                    if (title.equals("all_pages") || title.equals("orphan_pages") ||
2295                            title.equals("recent_changes")) {
2296    
2297                            throw new PageTitleException(title + " is reserved");
2298                    }
2299    
2300                    if (Validator.isNotNull(PropsValues.WIKI_PAGE_TITLES_REGEXP)) {
2301                            Pattern pattern = Pattern.compile(
2302                                    PropsValues.WIKI_PAGE_TITLES_REGEXP);
2303    
2304                            Matcher matcher = pattern.matcher(title);
2305    
2306                            if (!matcher.matches()) {
2307                                    throw new PageTitleException();
2308                            }
2309                    }
2310            }
2311    
2312            protected void clearPageCache(WikiPage page) {
2313                    if (!WikiCacheThreadLocal.isClearCache()) {
2314                            return;
2315                    }
2316    
2317                    WikiCacheUtil.clearCache(page.getNodeId());
2318            }
2319    
2320            protected void deletePageAttachment(long fileEntryId)
2321                    throws PortalException, SystemException {
2322    
2323                    PortletFileRepositoryUtil.deletePortletFileEntry(fileEntryId);
2324            }
2325    
2326            protected String getDiffsURL(
2327                            WikiNode node, WikiPage page, WikiPage previousVersionPage,
2328                            ServiceContext serviceContext)
2329                    throws PortalException, SystemException {
2330    
2331                    if (previousVersionPage == null) {
2332                            return StringPool.BLANK;
2333                    }
2334    
2335                    HttpServletRequest request = serviceContext.getRequest();
2336    
2337                    if (request == null) {
2338                            return StringPool.BLANK;
2339                    }
2340    
2341                    String portletId = null;
2342                    long plid = LayoutConstants.DEFAULT_PLID;
2343                    String strutsAction = null;
2344    
2345                    if (serviceContext.getPlid() != LayoutConstants.DEFAULT_PLID) {
2346                            portletId = PortletKeys.WIKI;
2347                            plid = serviceContext.getPlid();
2348                            strutsAction = "/wiki/compare_versions";
2349                    }
2350                    else {
2351                            portletId = PortletKeys.WIKI_ADMIN;
2352                            plid = PortalUtil.getControlPanelPlid(
2353                                    serviceContext.getCompanyId());
2354                            strutsAction = "/wiki_admin/compare_versions";
2355                    }
2356    
2357                    PortletURL portletURL = PortletURLFactoryUtil.create(
2358                            request, portletId, plid, PortletRequest.RENDER_PHASE);
2359    
2360                    portletURL.setParameter("struts_action", strutsAction);
2361                    portletURL.setParameter("nodeId", String.valueOf(node.getNodeId()));
2362                    portletURL.setParameter("title", page.getTitle());
2363                    portletURL.setParameter(
2364                            "sourceVersion", String.valueOf(previousVersionPage.getVersion()));
2365                    portletURL.setParameter(
2366                            "targetVersion", String.valueOf(page.getVersion()));
2367                    portletURL.setParameter("type", "html");
2368    
2369                    return portletURL.toString();
2370            }
2371    
2372            protected String getPageURL(
2373                            WikiNode node, WikiPage page, ServiceContext serviceContext)
2374                    throws PortalException, SystemException {
2375    
2376                    HttpServletRequest request = serviceContext.getRequest();
2377    
2378                    if (request == null) {
2379                            return StringPool.BLANK;
2380                    }
2381    
2382                    String layoutFullURL = getLayoutURL(
2383                            node.getGroupId(), PortletKeys.WIKI, serviceContext);
2384    
2385                    if (Validator.isNotNull(layoutFullURL)) {
2386                            return layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "wiki/" +
2387                                    node.getNodeId() + StringPool.SLASH +
2388                                            HttpUtil.encodeURL(WikiUtil.escapeName(page.getTitle()));
2389                    }
2390                    else {
2391                            long controlPanelPlid = PortalUtil.getControlPanelPlid(
2392                                    serviceContext.getCompanyId());
2393    
2394                            PortletURL portletURL = PortletURLFactoryUtil.create(
2395                                    request, PortletKeys.WIKI_ADMIN, controlPanelPlid,
2396                                    PortletRequest.RENDER_PHASE);
2397    
2398                            portletURL.setParameter(
2399                                    "struts_action", "/wiki_admin/view_page_activities");
2400                            portletURL.setParameter("nodeId", String.valueOf(node.getNodeId()));
2401                            portletURL.setParameter("title", page.getTitle());
2402    
2403                            return portletURL.toString();
2404                    }
2405            }
2406    
2407            protected List<ObjectValuePair<Long, Integer>> getPageVersionStatuses(
2408                    List<WikiPage> pages) {
2409    
2410                    List<ObjectValuePair<Long, Integer>> pageVersionStatusOVPs =
2411                            new ArrayList<ObjectValuePair<Long, Integer>>(pages.size());
2412    
2413                    for (WikiPage page : pages) {
2414                            int status = page.getStatus();
2415    
2416                            if (status == WorkflowConstants.STATUS_PENDING) {
2417                                    status = WorkflowConstants.STATUS_DRAFT;
2418                            }
2419    
2420                            ObjectValuePair<Long, Integer> pageVersionStatusOVP =
2421                                    new ObjectValuePair<Long, Integer>(page.getPageId(), status);
2422    
2423                            pageVersionStatusOVPs.add(pageVersionStatusOVP);
2424                    }
2425    
2426                    return pageVersionStatusOVPs;
2427            }
2428    
2429            protected String getParentPageTitle(WikiPage page) {
2430    
2431                    // LPS-4586
2432    
2433                    try {
2434                            WikiPage parentPage = getPage(
2435                                    page.getNodeId(), page.getParentTitle());
2436    
2437                            return parentPage.getTitle();
2438                    }
2439                    catch (Exception e) {
2440                            return null;
2441                    }
2442            }
2443    
2444            protected WikiPage getPreviousVersionPage(WikiPage page)
2445                    throws PortalException, SystemException {
2446    
2447                    double previousVersion = MathUtil.format(page.getVersion() - 0.1, 1, 1);
2448    
2449                    if (previousVersion < 1) {
2450                            return null;
2451                    }
2452    
2453                    return getPage(page.getNodeId(), page.getTitle(), previousVersion);
2454            }
2455    
2456            protected boolean isLinkedTo(WikiPage page, String targetTitle)
2457                    throws PortalException {
2458    
2459                    Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
2460    
2461                    Boolean link = links.get(StringUtil.toLowerCase(targetTitle));
2462    
2463                    if (link != null) {
2464                            return true;
2465                    }
2466                    else {
2467                            return false;
2468                    }
2469            }
2470    
2471            protected boolean isUsedTitle(long nodeId, String title)
2472                    throws SystemException {
2473    
2474                    if (getPagesCount(nodeId, title, true) > 0) {
2475                            return true;
2476                    }
2477                    else {
2478                            return false;
2479                    }
2480            }
2481    
2482            protected void notifySubscribers(
2483                            WikiNode node, WikiPage page, ServiceContext serviceContext,
2484                            boolean update)
2485                    throws PortalException, SystemException {
2486    
2487                    String layoutFullURL = serviceContext.getLayoutFullURL();
2488    
2489                    if (!page.isApproved() || Validator.isNull(layoutFullURL)) {
2490                            return;
2491                    }
2492    
2493                    PortletPreferences preferences = null;
2494    
2495                    String rootPortletId = serviceContext.getRootPortletId();
2496    
2497                    if (Validator.isNull(rootPortletId) ||
2498                            !rootPortletId.equals(PortletKeys.WIKI_DISPLAY)) {
2499    
2500                            preferences = ServiceContextUtil.getPortletPreferences(
2501                                    serviceContext);
2502                    }
2503    
2504                    if (preferences == null) {
2505                            preferences = portletPreferencesLocalService.getPreferences(
2506                                    node.getCompanyId(), node.getGroupId(),
2507                                    PortletKeys.PREFS_OWNER_TYPE_GROUP,
2508                                    PortletKeys.PREFS_PLID_SHARED, PortletKeys.WIKI_ADMIN, null);
2509                    }
2510    
2511                    if (!update && WikiUtil.getEmailPageAddedEnabled(preferences)) {
2512                    }
2513                    else if (update && WikiUtil.getEmailPageUpdatedEnabled(preferences)) {
2514                    }
2515                    else {
2516                            return;
2517                    }
2518    
2519                    String portalURL = serviceContext.getPortalURL();
2520    
2521                    WikiPage previousVersionPage = getPreviousVersionPage(page);
2522    
2523                    String attachmentURLPrefix = WikiUtil.getAttachmentURLPrefix(
2524                            serviceContext.getPathMain(), serviceContext.getPlid(),
2525                            page.getNodeId(), page.getTitle());
2526    
2527                    attachmentURLPrefix = portalURL + attachmentURLPrefix;
2528    
2529                    String pageDiffs = StringPool.BLANK;
2530    
2531                    try {
2532                            pageDiffs = WikiUtil.diffHtml(
2533                                    previousVersionPage, page, null, null, attachmentURLPrefix);
2534                    }
2535                    catch (Exception e) {
2536                    }
2537    
2538                    String pageContent = null;
2539    
2540                    if (Validator.equals(page.getFormat(), "creole")) {
2541                            pageContent = WikiUtil.convert(
2542                                    page, null, null, attachmentURLPrefix);
2543                    }
2544                    else {
2545                            pageContent = page.getContent();
2546                            pageContent = WikiUtil.processContent(pageContent);
2547                    }
2548    
2549                    String fromName = WikiUtil.getEmailFromName(
2550                            preferences, page.getCompanyId());
2551                    String fromAddress = WikiUtil.getEmailFromAddress(
2552                            preferences, page.getCompanyId());
2553    
2554                    String subject = null;
2555                    String body = null;
2556                    String signature = null;
2557    
2558                    if (update) {
2559                            subject = WikiUtil.getEmailPageUpdatedSubject(preferences);
2560                            body = WikiUtil.getEmailPageUpdatedBody(preferences);
2561                            signature = WikiUtil.getEmailPageUpdatedSignature(preferences);
2562                    }
2563                    else {
2564                            subject = WikiUtil.getEmailPageAddedSubject(preferences);
2565                            body = WikiUtil.getEmailPageAddedBody(preferences);
2566                            signature = WikiUtil.getEmailPageAddedSignature(preferences);
2567                    }
2568    
2569                    if (Validator.isNotNull(signature)) {
2570                            body += "\n" + signature;
2571                    }
2572    
2573                    SubscriptionSender subscriptionSender = new SubscriptionSender();
2574    
2575                    subscriptionSender.setBody(body);
2576                    subscriptionSender.setCompanyId(page.getCompanyId());
2577                    subscriptionSender.setContextAttributes(
2578                            "[$DIFFS_URL$]",
2579                            getDiffsURL(node, page, previousVersionPage, serviceContext),
2580                            "[$NODE_NAME$]", node.getName(), "[$PAGE_DATE_UPDATE$]",
2581                            page.getModifiedDate(), "[$PAGE_ID$]", page.getPageId(),
2582                            "[$PAGE_SUMMARY$]", page.getSummary(), "[$PAGE_TITLE$]",
2583                            page.getTitle(), "[$PAGE_URL$]",
2584                            getPageURL(node, page, serviceContext));
2585                    subscriptionSender.setContextAttribute(
2586                            "[$PAGE_CONTENT$]", pageContent, false);
2587                    subscriptionSender.setContextAttribute(
2588                            "[$PAGE_DIFFS$]", replaceStyles(pageDiffs), false);
2589                    subscriptionSender.setContextUserPrefix("PAGE");
2590                    subscriptionSender.setFrom(fromAddress, fromName);
2591                    subscriptionSender.setHtmlFormat(true);
2592                    subscriptionSender.setMailId(
2593                            "wiki_page", page.getNodeId(), page.getPageId());
2594                    subscriptionSender.setPortletId(PortletKeys.WIKI);
2595                    subscriptionSender.setReplyToAddress(fromAddress);
2596                    subscriptionSender.setScopeGroupId(node.getGroupId());
2597                    subscriptionSender.setServiceContext(serviceContext);
2598                    subscriptionSender.setSubject(subject);
2599                    subscriptionSender.setUserId(page.getUserId());
2600    
2601                    subscriptionSender.addPersistedSubscribers(
2602                            WikiNode.class.getName(), node.getNodeId());
2603                    subscriptionSender.addPersistedSubscribers(
2604                            WikiPage.class.getName(), page.getResourcePrimKey());
2605    
2606                    subscriptionSender.flushNotificationsAsync();
2607            }
2608    
2609            protected void populateServiceContext(
2610                            ServiceContext serviceContext, WikiPage page)
2611                    throws PortalException, SystemException {
2612    
2613                    long[] assetCategoryIds = assetCategoryLocalService.getCategoryIds(
2614                            WikiPage.class.getName(), page.getResourcePrimKey());
2615    
2616                    serviceContext.setAssetCategoryIds(assetCategoryIds);
2617    
2618                    AssetEntry assetEntry = assetEntryLocalService.getEntry(
2619                            WikiPage.class.getName(), page.getResourcePrimKey());
2620    
2621                    List<AssetLink> assetLinks = assetLinkLocalService.getLinks(
2622                            assetEntry.getEntryId());
2623    
2624                    long[] assetLinkEntryIds = StringUtil.split(
2625                            ListUtil.toString(assetLinks, AssetLink.ENTRY_ID2_ACCESSOR), 0L);
2626    
2627                    serviceContext.setAssetLinkEntryIds(assetLinkEntryIds);
2628    
2629                    String[] assetTagNames = assetTagLocalService.getTagNames(
2630                            WikiPage.class.getName(), page.getResourcePrimKey());
2631    
2632                    serviceContext.setAssetTagNames(assetTagNames);
2633    
2634                    ExpandoBridge expandoBridge = page.getExpandoBridge();
2635    
2636                    serviceContext.setExpandoBridgeAttributes(
2637                            expandoBridge.getAttributes());
2638            }
2639    
2640            protected String replaceStyles(String html) {
2641                    return StringUtil.replace(
2642                            html,
2643                            new String[] {
2644                                    "class=\"diff-html-added\"", "class=\"diff-html-removed\"",
2645                                    "class=\"diff-html-changed\"",
2646                                    "changeType=\"diff-added-image\"",
2647                                    "changeType=\"diff-removed-image\"",
2648                                    "changeType=\"diff-changed-image\""
2649                            },
2650                            new String[] {
2651                                    "style=\"background-color: #CFC;\"",
2652                                    "style=\"background-color: #FDC6C6; text-decoration: " +
2653                                            "line-through;\"",
2654                                    "style=\"border-bottom: 2px dotted blue;\"",
2655                                    "style=\"border: 10px solid #CFC;\"",
2656                                    "style=\"border: 10px solid #FDC6C6;\"",
2657                                    "style=\"border: 10px solid blue;\""
2658                            }
2659                    );
2660            }
2661    
2662            protected void validate(long nodeId, String content, String format)
2663                    throws PortalException {
2664    
2665                    if (!WikiUtil.validate(nodeId, content, format)) {
2666                            throw new PageContentException();
2667                    }
2668            }
2669    
2670            protected void validate(
2671                            String title, long nodeId, String content, String format)
2672                    throws PortalException, SystemException {
2673    
2674                    if (Validator.isNull(title)) {
2675                            throw new PageTitleException();
2676                    }
2677    
2678                    if (isUsedTitle(nodeId, title)) {
2679                            throw new DuplicatePageException("{nodeId=" + nodeId + "}");
2680                    }
2681    
2682                    validateTitle(title);
2683    
2684                    validate(nodeId, content, format);
2685            }
2686    
2687    }