001    /**
002     * Copyright (c) 2000-2010 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.documentlibrary.DuplicateDirectoryException;
018    import com.liferay.documentlibrary.NoSuchDirectoryException;
019    import com.liferay.documentlibrary.NoSuchFileException;
020    import com.liferay.portal.kernel.exception.PortalException;
021    import com.liferay.portal.kernel.exception.SystemException;
022    import com.liferay.portal.kernel.language.LanguageUtil;
023    import com.liferay.portal.kernel.messaging.DestinationNames;
024    import com.liferay.portal.kernel.messaging.Message;
025    import com.liferay.portal.kernel.messaging.MessageBusUtil;
026    import com.liferay.portal.kernel.search.Indexer;
027    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
028    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
029    import com.liferay.portal.kernel.util.ContentTypes;
030    import com.liferay.portal.kernel.util.HttpUtil;
031    import com.liferay.portal.kernel.util.ListUtil;
032    import com.liferay.portal.kernel.util.MathUtil;
033    import com.liferay.portal.kernel.util.NotificationThreadLocal;
034    import com.liferay.portal.kernel.util.ObjectValuePair;
035    import com.liferay.portal.kernel.util.OrderByComparator;
036    import com.liferay.portal.kernel.util.StringBundler;
037    import com.liferay.portal.kernel.util.StringPool;
038    import com.liferay.portal.kernel.util.StringUtil;
039    import com.liferay.portal.kernel.util.Validator;
040    import com.liferay.portal.kernel.workflow.WorkflowConstants;
041    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
042    import com.liferay.portal.model.Company;
043    import com.liferay.portal.model.CompanyConstants;
044    import com.liferay.portal.model.Group;
045    import com.liferay.portal.model.GroupConstants;
046    import com.liferay.portal.model.ResourceConstants;
047    import com.liferay.portal.model.User;
048    import com.liferay.portal.security.permission.ActionKeys;
049    import com.liferay.portal.service.ServiceContext;
050    import com.liferay.portal.service.ServiceContextUtil;
051    import com.liferay.portal.util.Portal;
052    import com.liferay.portal.util.PortalUtil;
053    import com.liferay.portal.util.PortletKeys;
054    import com.liferay.portal.util.PropsValues;
055    import com.liferay.portlet.asset.NoSuchEntryException;
056    import com.liferay.portlet.asset.model.AssetEntry;
057    import com.liferay.portlet.expando.model.ExpandoBridge;
058    import com.liferay.portlet.wiki.DuplicatePageException;
059    import com.liferay.portlet.wiki.NoSuchPageException;
060    import com.liferay.portlet.wiki.NoSuchPageResourceException;
061    import com.liferay.portlet.wiki.PageContentException;
062    import com.liferay.portlet.wiki.PageTitleException;
063    import com.liferay.portlet.wiki.PageVersionException;
064    import com.liferay.portlet.wiki.model.WikiNode;
065    import com.liferay.portlet.wiki.model.WikiPage;
066    import com.liferay.portlet.wiki.model.WikiPageConstants;
067    import com.liferay.portlet.wiki.model.WikiPageDisplay;
068    import com.liferay.portlet.wiki.model.WikiPageResource;
069    import com.liferay.portlet.wiki.model.impl.WikiPageDisplayImpl;
070    import com.liferay.portlet.wiki.model.impl.WikiPageImpl;
071    import com.liferay.portlet.wiki.service.base.WikiPageLocalServiceBaseImpl;
072    import com.liferay.portlet.wiki.social.WikiActivityKeys;
073    import com.liferay.portlet.wiki.util.WikiCacheThreadLocal;
074    import com.liferay.portlet.wiki.util.WikiCacheUtil;
075    import com.liferay.portlet.wiki.util.WikiUtil;
076    import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
077    import com.liferay.portlet.wiki.util.comparator.PageVersionComparator;
078    import com.liferay.util.UniqueList;
079    
080    import java.io.InputStream;
081    
082    import java.util.ArrayList;
083    import java.util.Calendar;
084    import java.util.Date;
085    import java.util.HashSet;
086    import java.util.LinkedHashMap;
087    import java.util.List;
088    import java.util.Map;
089    import java.util.Set;
090    import java.util.regex.Matcher;
091    import java.util.regex.Pattern;
092    
093    import javax.portlet.PortletPreferences;
094    import javax.portlet.PortletURL;
095    import javax.portlet.WindowState;
096    
097    /**
098     * @author Brian Wing Shun Chan
099     * @author Jorge Ferrer
100     * @author Raymond Augé
101     * @author Bruno Farache
102     * @author Julio Camarero
103     * @author Wesley Gong
104     * @author Marcellus Tavares
105     * @author Zsigmond Rab
106     * @author Zsolt Berentey
107     */
108    public class WikiPageLocalServiceImpl extends WikiPageLocalServiceBaseImpl {
109    
110            public WikiPage addPage(
111                            long userId, long nodeId, String title, double version,
112                            String content, String summary, boolean minorEdit, String format,
113                            boolean head, String parentTitle, String redirectTitle,
114                            ServiceContext serviceContext)
115                    throws PortalException, SystemException {
116    
117                    // Page
118    
119                    User user = userPersistence.findByPrimaryKey(userId);
120                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
121    
122                    Date now = new Date();
123    
124                    validate(title, nodeId, content, format);
125    
126                    long pageId = counterLocalService.increment();
127    
128                    long resourcePrimKey =
129                            wikiPageResourceLocalService.getPageResourcePrimKey(nodeId, title);
130    
131                    WikiPage page = wikiPagePersistence.create(pageId);
132    
133                    page.setUuid(serviceContext.getUuid());
134                    page.setResourcePrimKey(resourcePrimKey);
135                    page.setGroupId(node.getGroupId());
136                    page.setCompanyId(user.getCompanyId());
137                    page.setUserId(user.getUserId());
138                    page.setUserName(user.getFullName());
139                    page.setCreateDate(serviceContext.getCreateDate(now));
140                    page.setModifiedDate(serviceContext.getModifiedDate(now));
141                    page.setNodeId(nodeId);
142                    page.setTitle(title);
143                    page.setVersion(version);
144                    page.setMinorEdit(minorEdit);
145                    page.setContent(content);
146                    page.setStatus(WorkflowConstants.STATUS_DRAFT);
147                    page.setSummary(summary);
148                    page.setFormat(format);
149                    page.setHead(head);
150                    page.setParentTitle(parentTitle);
151                    page.setRedirectTitle(redirectTitle);
152    
153                    wikiPagePersistence.update(page, false);
154    
155                    // Resources
156    
157                    if (serviceContext.getAddCommunityPermissions() ||
158                            serviceContext.getAddGuestPermissions()) {
159    
160                            addPageResources(
161                                    page, serviceContext.getAddCommunityPermissions(),
162                                    serviceContext.getAddGuestPermissions());
163                    }
164                    else {
165                            addPageResources(
166                                    page, serviceContext.getCommunityPermissions(),
167                                    serviceContext.getGuestPermissions());
168                    }
169    
170                    // Node
171    
172                    node.setLastPostDate(serviceContext.getModifiedDate(now));
173    
174                    wikiNodePersistence.update(node, false);
175    
176                    // Asset
177    
178                    updateAsset(
179                            userId, page, serviceContext.getAssetCategoryIds(),
180                            serviceContext.getAssetTagNames());
181    
182                    // Expando
183    
184                    ExpandoBridge expandoBridge = page.getExpandoBridge();
185    
186                    expandoBridge.setAttributes(serviceContext);
187    
188                    // Message boards
189    
190                    if (PropsValues.WIKI_PAGE_COMMENTS_ENABLED) {
191                            mbMessageLocalService.addDiscussionMessage(
192                                    userId, page.getUserName(), page.getGroupId(),
193                                    WikiPage.class.getName(), resourcePrimKey,
194                                    WorkflowConstants.ACTION_PUBLISH);
195                    }
196    
197                    // Workflow
198    
199                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
200                            user.getCompanyId(), page.getGroupId(), userId,
201                            WikiPage.class.getName(), page.getResourcePrimKey(), page,
202                            serviceContext);
203    
204                    return page;
205            }
206    
207            public WikiPage addPage(
208                            long userId, long nodeId, String title, String content,
209                            String summary, boolean minorEdit, ServiceContext serviceContext)
210                    throws PortalException, SystemException {
211    
212                    double version = WikiPageConstants.DEFAULT_VERSION;
213                    String format = WikiPageConstants.DEFAULT_FORMAT;
214                    boolean head = false;
215                    String parentTitle = null;
216                    String redirectTitle = null;
217    
218                    return addPage(
219                            userId, nodeId, title, version, content, summary, minorEdit, format,
220                            head, parentTitle, redirectTitle, serviceContext);
221            }
222    
223            public void addPageAttachment(
224                            long companyId, String dirName, Date modifiedDate, String fileName,
225                            InputStream inputStream)
226                    throws PortalException, SystemException {
227    
228                    if (inputStream == null) {
229                            return;
230                    }
231    
232                    String portletId = CompanyConstants.SYSTEM_STRING;
233                    long groupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
234                    long repositoryId = CompanyConstants.SYSTEM;
235    
236                    try {
237                            dlService.addDirectory(companyId, repositoryId, dirName);
238                    }
239                    catch (DuplicateDirectoryException dde) {
240                    }
241    
242                    dlLocalService.addFile(
243                            companyId, portletId, groupId, repositoryId,
244                            dirName + "/" + fileName, false, 0, StringPool.BLANK,
245                            modifiedDate, new ServiceContext(), inputStream);
246            }
247    
248            public void addPageAttachments(
249                            long nodeId, String title,
250                            List<ObjectValuePair<String, byte[]>> files)
251                    throws PortalException, SystemException {
252    
253                    if (files.size() == 0) {
254                            return;
255                    }
256    
257                    WikiPage page = getPage(nodeId, title);
258    
259                    long companyId = page.getCompanyId();
260                    String portletId = CompanyConstants.SYSTEM_STRING;
261                    long groupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
262                    long repositoryId = CompanyConstants.SYSTEM;
263                    String dirName = page.getAttachmentsDir();
264    
265                    try {
266                            dlService.addDirectory(companyId, repositoryId, dirName);
267                    }
268                    catch (DuplicateDirectoryException dde) {
269                    }
270    
271                    for (int i = 0; i < files.size(); i++) {
272                            ObjectValuePair<String, byte[]> ovp = files.get(i);
273    
274                            String fileName = ovp.getKey();
275                            byte[] bytes = ovp.getValue();
276    
277                            if (Validator.isNull(fileName)) {
278                                    continue;
279                            }
280    
281                            dlService.addFile(
282                                    companyId, portletId, groupId, repositoryId,
283                                    dirName + "/" + fileName, 0, StringPool.BLANK,
284                                    page.getModifiedDate(), new ServiceContext(), bytes);
285                    }
286            }
287    
288            public void addPageResources(
289                            long nodeId, String title, boolean addCommunityPermissions,
290                            boolean addGuestPermissions)
291                    throws PortalException, SystemException {
292    
293                    WikiPage page = getPage(nodeId, title);
294    
295                    addPageResources(page, addCommunityPermissions, addGuestPermissions);
296            }
297    
298            public void addPageResources(
299                            long nodeId, String title, String[] communityPermissions,
300                            String[] guestPermissions)
301                    throws PortalException, SystemException {
302    
303                    WikiPage page = getPage(nodeId, title);
304    
305                    addPageResources(page, communityPermissions, guestPermissions);
306            }
307    
308            public void addPageResources(
309                            WikiPage page, boolean addCommunityPermissions,
310                            boolean addGuestPermissions)
311                    throws PortalException, SystemException {
312    
313                    resourceLocalService.addResources(
314                            page.getCompanyId(), page.getGroupId(), page.getUserId(),
315                            WikiPage.class.getName(), page.getResourcePrimKey(), false,
316                            addCommunityPermissions, addGuestPermissions);
317            }
318    
319            public void addPageResources(
320                            WikiPage page, String[] communityPermissions,
321                            String[] guestPermissions)
322                    throws PortalException, SystemException {
323    
324                    resourceLocalService.addModelResources(
325                            page.getCompanyId(), page.getGroupId(), page.getUserId(),
326                            WikiPage.class.getName(), page.getResourcePrimKey(),
327                            communityPermissions, guestPermissions);
328            }
329    
330            public void changeParent(
331                            long userId, long nodeId, String title, String newParentTitle,
332                            ServiceContext serviceContext)
333                    throws PortalException, SystemException {
334    
335                    if (Validator.isNotNull(newParentTitle)) {
336                            WikiPage parentPage = getPage(nodeId, newParentTitle);
337    
338                            if (Validator.isNotNull(parentPage.getRedirectTitle())) {
339                                    newParentTitle = parentPage.getRedirectTitle();
340                            }
341                    }
342    
343                    WikiPage page = getPage(nodeId, title);
344    
345                    String originalParentTitle = page.getParentTitle();
346    
347                    double version = page.getVersion();
348                    String content = page.getContent();
349                    String summary = LanguageUtil.format(
350                            ServiceContextUtil.getLocale(serviceContext),
351                            "changed-parent-from-x", originalParentTitle);
352                    boolean minorEdit = false;
353                    String format = page.getFormat();
354                    String redirectTitle = page.getRedirectTitle();
355    
356                    long[] assetCategoryIds = assetCategoryLocalService.getCategoryIds(
357                            WikiPage.class.getName(), page.getResourcePrimKey());
358                    String[] assetTagNames = assetTagLocalService.getTagNames(
359                            WikiPage.class.getName(), page.getResourcePrimKey());
360    
361                    serviceContext.setAssetCategoryIds(assetCategoryIds);
362                    serviceContext.setAssetTagNames(assetTagNames);
363    
364                    updatePage(
365                            userId, nodeId, title, version, content, summary, minorEdit,
366                            format, newParentTitle, redirectTitle, serviceContext);
367    
368                    List<WikiPage> oldPages = wikiPagePersistence.findByN_T_H(
369                            nodeId, title, false);
370    
371                    for (WikiPage oldPage : oldPages) {
372                            oldPage.setParentTitle(originalParentTitle);
373    
374                            wikiPagePersistence.update(oldPage, false);
375                    }
376            }
377    
378            public void deletePage(long nodeId, String title)
379                    throws PortalException, SystemException {
380    
381                    List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
382                            nodeId, title, true, 0, 1);
383    
384                    if (!pages.isEmpty()) {
385                            WikiPage page = pages.iterator().next();
386    
387                            deletePage(page);
388                    }
389            }
390    
391            public void deletePage(long nodeId, String title, double version)
392                    throws PortalException, SystemException {
393    
394                    wikiPagePersistence.removeByN_T_V(nodeId, title, version);
395            }
396    
397            public void deletePage(WikiPage page)
398                    throws PortalException, SystemException {
399    
400                    // Children
401    
402                    List<WikiPage> children = wikiPagePersistence.findByN_H_P(
403                            page.getNodeId(), true, page.getTitle());
404    
405                    for (WikiPage curPage : children) {
406                            deletePage(curPage);
407                    }
408    
409                    // Indexer
410    
411                    Indexer indexer = IndexerRegistryUtil.getIndexer(WikiPage.class);
412    
413                    indexer.delete(page);
414    
415                    // Attachments
416    
417                    long companyId = page.getCompanyId();
418                    String portletId = CompanyConstants.SYSTEM_STRING;
419                    long repositoryId = CompanyConstants.SYSTEM;
420                    String dirName = page.getAttachmentsDir();
421    
422                    try {
423                            dlService.deleteDirectory(
424                                    companyId, portletId, repositoryId, dirName);
425                    }
426                    catch (NoSuchDirectoryException nsde) {
427                    }
428    
429                    // Subscriptions
430    
431                    subscriptionLocalService.deleteSubscriptions(
432                            page.getCompanyId(), WikiPage.class.getName(),
433                            page.getResourcePrimKey());
434    
435                    // Social
436    
437                    socialActivityLocalService.deleteActivities(
438                            WikiPage.class.getName(), page.getResourcePrimKey());
439    
440                    // Message boards
441    
442                    mbMessageLocalService.deleteDiscussionMessages(
443                            WikiPage.class.getName(), page.getResourcePrimKey());
444    
445                    // Expando
446    
447                    expandoValueLocalService.deleteValues(
448                            WikiPage.class.getName(), page.getResourcePrimKey());
449    
450                    // Asset
451    
452                    assetEntryLocalService.deleteEntry(
453                            WikiPage.class.getName(), page.getPrimaryKey());
454                    assetEntryLocalService.deleteEntry(
455                            WikiPage.class.getName(), page.getResourcePrimKey());
456    
457                    // Resources
458    
459                    resourceLocalService.deleteResource(
460                            page.getCompanyId(), WikiPage.class.getName(),
461                            ResourceConstants.SCOPE_INDIVIDUAL, page.getResourcePrimKey());
462    
463                    // Resource
464    
465                    try {
466                            wikiPageResourceLocalService.deletePageResource(
467                                    page.getNodeId(), page.getTitle());
468                    }
469                    catch (NoSuchPageResourceException nspre) {
470                    }
471    
472                    // All versions
473    
474                    wikiPagePersistence.removeByN_T(page.getNodeId(), page.getTitle());
475    
476                    // All referrals
477    
478                    wikiPagePersistence.removeByN_R(page.getNodeId(), page.getTitle());
479    
480                    // Workflow
481    
482                    workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
483                            page.getCompanyId(), page.getGroupId(),
484                            WikiPage.class.getName(), page.getResourcePrimKey());
485    
486                    // Cache
487    
488                    clearPageCache(page);
489            }
490    
491            public void deletePageAttachment(long nodeId, String title, String fileName)
492                    throws PortalException, SystemException {
493    
494                    if (Validator.isNull(fileName)) {
495                            return;
496                    }
497    
498                    WikiPage page = getPage(nodeId, title);
499    
500                    long companyId = page.getCompanyId();
501                    String portletId = CompanyConstants.SYSTEM_STRING;
502                    long repositoryId = CompanyConstants.SYSTEM;
503    
504                    try {
505                            dlService.deleteFile(companyId, portletId, repositoryId, fileName);
506                    }
507                    catch (NoSuchFileException nsfe) {
508                    }
509            }
510    
511            public void deletePages(long nodeId)
512                    throws PortalException, SystemException {
513    
514                    List<WikiPage> pages = wikiPagePersistence.findByN_H_P(
515                            nodeId, true, StringPool.BLANK);
516    
517                    for (WikiPage page : pages) {
518                            deletePage(page);
519                    }
520    
521                    pages = wikiPagePersistence.findByN_H_P(
522                            nodeId, false, StringPool.BLANK);
523    
524                    for (WikiPage page : pages) {
525                            deletePage(page);
526                    }
527            }
528    
529            public List<WikiPage> getChildren(
530                            long nodeId, boolean head, String parentTitle)
531                    throws SystemException {
532    
533                    return wikiPagePersistence.findByN_H_P_S(
534                            nodeId, head, parentTitle, WorkflowConstants.STATUS_APPROVED);
535            }
536    
537            public WikiPage getDraftPage(long nodeId, String title)
538                    throws PortalException, SystemException {
539    
540                    List<WikiPage> pages = wikiPagePersistence.findByN_T_S(
541                            nodeId, title, WorkflowConstants.STATUS_DRAFT, 0, 1);
542    
543                    if (!pages.isEmpty()) {
544                            return pages.get(0);
545                    }
546                    else {
547                            pages = wikiPagePersistence.findByN_T_S(
548                                    nodeId, title, WorkflowConstants.STATUS_PENDING, 0, 1);
549    
550                            if (!pages.isEmpty()) {
551                                    return pages.get(0);
552                            }
553                            else {
554                                    throw new NoSuchPageException();
555                            }
556                    }
557    
558            }
559    
560            public List<WikiPage> getIncomingLinks(long nodeId, String title)
561                    throws PortalException, SystemException {
562    
563                    List<WikiPage> links = new UniqueList<WikiPage>();
564    
565                    List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
566    
567                    for (WikiPage page : pages) {
568                            if (isLinkedTo(page, title)) {
569                                    links.add(page);
570                            }
571                    }
572    
573                    List<WikiPage> referrals = wikiPagePersistence.findByN_R(nodeId, title);
574    
575                    for (WikiPage referral : referrals) {
576                            for (WikiPage page : pages) {
577                                    if (isLinkedTo(page, referral.getTitle())) {
578                                            links.add(page);
579                                    }
580                            }
581                    }
582    
583                    return ListUtil.sort(links);
584            }
585    
586            public List<WikiPage> getNoAssetPages() throws SystemException {
587                    return wikiPageFinder.findByNoAssets();
588            }
589    
590            public List<WikiPage> getOrphans(long nodeId)
591                    throws PortalException, SystemException {
592    
593                    List<Map<String, Boolean>> pageTitles =
594                            new ArrayList<Map<String, Boolean>>();
595    
596                    List<WikiPage> pages = wikiPagePersistence.findByN_H_S(
597                            nodeId, true, WorkflowConstants.STATUS_APPROVED);
598    
599                    for (WikiPage page : pages) {
600                            pageTitles.add(WikiCacheUtil.getOutgoingLinks(page));
601                    }
602    
603                    Set<WikiPage> notOrphans = new HashSet<WikiPage>();
604    
605                    for (WikiPage page : pages) {
606                            for (Map<String, Boolean> pageTitle : pageTitles) {
607                                    if (pageTitle.get(page.getTitle().toLowerCase()) != null) {
608                                            notOrphans.add(page);
609    
610                                            break;
611                                    }
612                            }
613                    }
614    
615                    List<WikiPage> orphans = new ArrayList<WikiPage>();
616    
617                    for (WikiPage page : pages) {
618                            if (!notOrphans.contains(page)) {
619                                    orphans.add(page);
620                            }
621                    }
622    
623                    orphans = ListUtil.sort(orphans);
624    
625                    return orphans;
626            }
627    
628            public List<WikiPage> getOutgoingLinks(long nodeId, String title)
629                    throws PortalException, SystemException {
630    
631                    WikiPage page = getPage(nodeId, title);
632    
633                    Map<String, WikiPage> pages = new LinkedHashMap<String, WikiPage>();
634    
635                    Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
636    
637                    for (Map.Entry<String, Boolean> entry : links.entrySet()) {
638                            String curTitle = entry.getKey();
639                            Boolean exists = entry.getValue();
640    
641                            if (exists) {
642                                    if (!pages.containsKey(curTitle)) {
643                                            pages.put(curTitle, getPage(nodeId, curTitle));
644                                    }
645                            }
646                            else {
647                                    WikiPageImpl newPage = new WikiPageImpl();
648    
649                                    newPage.setNew(true);
650                                    newPage.setNodeId(nodeId);
651                                    newPage.setTitle(curTitle);
652    
653                                    if (!pages.containsKey(curTitle)) {
654                                            pages.put(curTitle, newPage);
655                                    }
656                            }
657                    }
658    
659                    return ListUtil.fromCollection(pages.values());
660            }
661    
662            public WikiPage getPage(long resourcePrimKey)
663                    throws PortalException, SystemException {
664    
665                    return getPage(resourcePrimKey, Boolean.TRUE);
666            }
667    
668            public WikiPage getPage(long resourcePrimKey, Boolean head)
669                    throws PortalException, SystemException {
670    
671                    WikiPageResource wikiPageResource =
672                            wikiPageResourceLocalService.getPageResource(resourcePrimKey);
673    
674                    return getPage(
675                            wikiPageResource.getNodeId(), wikiPageResource.getTitle(), head);
676            }
677    
678            public WikiPage getPage(long nodeId, String title)
679                    throws PortalException, SystemException {
680    
681                    List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
682                            nodeId, title, true, 0, 1);
683    
684                    if (!pages.isEmpty()) {
685                            return pages.get(0);
686                    }
687                    else {
688                            throw new NoSuchPageException();
689                    }
690            }
691    
692            public WikiPage getPage(long nodeId, String title, Boolean head)
693                    throws PortalException, SystemException {
694    
695                    List<WikiPage> pages;
696    
697                    if (head == null) {
698                            pages = wikiPagePersistence.findByN_T(nodeId, title, 0, 1);
699                    }
700                    else {
701                            pages = wikiPagePersistence.findByN_T_H(
702                                    nodeId, title, head, 0, 1);
703                    }
704    
705                    if (!pages.isEmpty()) {
706                            return pages.get(0);
707                    }
708                    else {
709                            throw new NoSuchPageException();
710                    }
711            }
712    
713            public WikiPage getPage(long nodeId, String title, double version)
714                    throws PortalException, SystemException {
715    
716                    WikiPage page = null;
717    
718                    if (version == 0) {
719                            page = getPage(nodeId, title);
720                    }
721                    else {
722                            page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
723                    }
724    
725                    return page;
726            }
727    
728            public WikiPageDisplay getPageDisplay(
729                            long nodeId, String title, PortletURL viewPageURL,
730                            PortletURL editPageURL, String attachmentURLPrefix)
731                    throws PortalException, SystemException {
732    
733                    WikiPage page = getPage(nodeId, title);
734    
735                    return getPageDisplay(
736                            page, viewPageURL, editPageURL, attachmentURLPrefix);
737            }
738    
739            public WikiPageDisplay getPageDisplay(
740                            WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
741                            String attachmentURLPrefix)
742                    throws PortalException, SystemException {
743    
744                    String formattedContent = WikiUtil.convert(
745                            page, viewPageURL, editPageURL, attachmentURLPrefix);
746    
747                    return new WikiPageDisplayImpl(
748                            page.getUserId(), page.getNodeId(), page.getTitle(),
749                            page.getVersion(), page.getContent(), formattedContent,
750                            page.getFormat(), page.getHead(), page.getAttachmentsFiles());
751            }
752    
753            public List<WikiPage> getPages(
754                            long nodeId, boolean head, int start, int end)
755                    throws SystemException {
756    
757                    return getPages(
758                            nodeId, head, start, end, new PageCreateDateComparator(false));
759            }
760    
761            public List<WikiPage> getPages(
762                            long nodeId, boolean head, int start, int end,
763                            OrderByComparator obc)
764                    throws SystemException {
765    
766                    return wikiPagePersistence.findByN_H_S(
767                            nodeId, head, WorkflowConstants.STATUS_APPROVED, start, end,
768                            obc);
769            }
770    
771            public List<WikiPage> getPages(long nodeId, int start, int end)
772                    throws SystemException {
773    
774                    return getPages(
775                            nodeId, start, end, new PageCreateDateComparator(false));
776            }
777    
778            public List<WikiPage> getPages(
779                            long nodeId, int start, int end, OrderByComparator obc)
780                    throws SystemException {
781    
782                    return wikiPagePersistence.findByNodeId(
783                            nodeId, start, end, obc);
784            }
785    
786            public List<WikiPage> getPages(
787                            long resourcePrimKey, long nodeId, int status)
788                    throws SystemException {
789    
790                    return wikiPagePersistence.findByR_N_S(resourcePrimKey, nodeId, status);
791            }
792    
793            public List<WikiPage> getPages(
794                            long userId, long nodeId, int status, int start, int end)
795                    throws SystemException {
796    
797                    if (userId > 0) {
798                            return wikiPagePersistence.findByU_N_S(
799                                    userId, nodeId, status, start, end,
800                                    new PageCreateDateComparator(false));
801                    }
802                    else {
803                            return wikiPagePersistence.findByN_S(
804                                    nodeId, status, start, end,
805                                    new PageCreateDateComparator(false));
806                    }
807            }
808    
809            public List<WikiPage> getPages(
810                            long nodeId, String title, boolean head, int start, int end)
811                    throws SystemException {
812    
813                    return wikiPagePersistence.findByN_T_H(
814                            nodeId, title, head, start, end,
815                            new PageCreateDateComparator(false));
816            }
817    
818            public List<WikiPage> getPages(
819                            long nodeId, String title, int start, int end)
820                    throws SystemException {
821    
822                    return wikiPagePersistence.findByN_T(
823                            nodeId, title, start, end, new PageCreateDateComparator(false));
824            }
825    
826            public List<WikiPage> getPages(
827                            long nodeId, String title, int start, int end,
828                            OrderByComparator obc)
829                    throws SystemException {
830    
831                    return wikiPagePersistence.findByN_T(nodeId, title, start, end, obc);
832            }
833    
834            public List<WikiPage> getPages(String format) throws SystemException {
835                    return wikiPagePersistence.findByFormat(format);
836            }
837    
838            public int getPagesCount(long nodeId) throws SystemException {
839                    return wikiPagePersistence.countByNodeId(nodeId);
840            }
841    
842            public int getPagesCount(long nodeId, boolean head)
843                    throws SystemException {
844    
845                    return wikiPagePersistence.countByN_H_S(
846                            nodeId, head, WorkflowConstants.STATUS_APPROVED);
847            }
848    
849            public int getPagesCount(long userId, long nodeId, int status)
850                    throws SystemException {
851    
852                    if (userId > 0) {
853                            return wikiPagePersistence.countByU_N_S(userId, nodeId, status);
854                    }
855                    else {
856                            return wikiPagePersistence.countByN_S(nodeId, status);
857                    }
858            }
859    
860            public int getPagesCount(long nodeId, String title)
861                    throws SystemException {
862    
863                    return wikiPagePersistence.countByN_T(nodeId, title);
864            }
865    
866            public int getPagesCount(long nodeId, String title, boolean head)
867                    throws SystemException {
868    
869                    return wikiPagePersistence.countByN_T_H(nodeId, title, head);
870            }
871    
872            public int getPagesCount(String format) throws SystemException {
873                    return wikiPagePersistence.countByFormat(format);
874            }
875    
876            public List<WikiPage> getRecentChanges(long nodeId, int start, int end)
877                    throws SystemException {
878    
879                    Calendar cal = CalendarFactoryUtil.getCalendar();
880    
881                    cal.add(Calendar.WEEK_OF_YEAR, -1);
882    
883                    return wikiPageFinder.findByCreateDate(
884                            nodeId, cal.getTime(), false, start, end);
885            }
886    
887            public int getRecentChangesCount(long nodeId) throws SystemException {
888                    Calendar cal = CalendarFactoryUtil.getCalendar();
889    
890                    cal.add(Calendar.WEEK_OF_YEAR, -1);
891    
892                    return wikiPageFinder.countByCreateDate(nodeId, cal.getTime(), false);
893            }
894    
895            public boolean hasDraftPage(long nodeId, String title)
896                    throws SystemException {
897    
898                    int count = wikiPagePersistence.countByN_T_S(
899                            nodeId, title, WorkflowConstants.STATUS_DRAFT);
900    
901                    if (count > 0) {
902                            return true;
903                    }
904                    else {
905                            return false;
906                    }
907            }
908    
909            public void movePage(
910                            long userId, long nodeId, String title, String newTitle,
911                            boolean strict, ServiceContext serviceContext)
912                    throws PortalException, SystemException {
913    
914                    validateTitle(newTitle);
915    
916                    // Check if the new title already exists
917    
918                    if (title.equalsIgnoreCase(newTitle)) {
919                            throw new DuplicatePageException(newTitle);
920                    }
921    
922                    if (isUsedTitle(nodeId, newTitle)) {
923                            WikiPage page = getPage(nodeId, newTitle);
924    
925                            // Support moving back to a previously moved title
926    
927                            if (((page.getVersion() == WikiPageConstants.DEFAULT_VERSION) &&
928                                     (page.getContent().length() < 200)) ||
929                                    !strict) {
930    
931                                    deletePage(nodeId, newTitle);
932                            }
933                            else {
934                                    throw new DuplicatePageException(newTitle);
935                            }
936                    }
937    
938                    // All versions
939    
940                    List<WikiPage> pageVersions = wikiPagePersistence.findByN_T(
941                            nodeId, title);
942    
943                    if (pageVersions.size() == 0) {
944                            return;
945                    }
946    
947                    for (WikiPage page : pageVersions) {
948                            page.setTitle(newTitle);
949    
950                            wikiPagePersistence.update(page, false);
951                    }
952    
953                    // Children
954    
955                    List<WikiPage> children = wikiPagePersistence.findByN_P(nodeId, title);
956    
957                    for (WikiPage page : children) {
958                            page.setParentTitle(newTitle);
959    
960                            wikiPagePersistence.update(page, false);
961                    }
962    
963                    WikiPage page = pageVersions.get(pageVersions.size() - 1);
964    
965                    long resourcePrimKey = page.getResourcePrimKey();
966    
967                    // Page resource
968    
969                    WikiPageResource wikiPageResource =
970                            wikiPageResourcePersistence.findByPrimaryKey(resourcePrimKey);
971    
972                    wikiPageResource.setTitle(newTitle);
973    
974                    wikiPageResourcePersistence.update(wikiPageResource, false);
975    
976                    // Create stub page at the old location
977    
978                    double version = WikiPageConstants.DEFAULT_VERSION;
979                    String summary = WikiPageConstants.MOVED + " to " + title;
980                    String format = page.getFormat();
981                    boolean head = true;
982                    String parentTitle = page.getParentTitle();
983                    String redirectTitle = page.getTitle();
984                    String content =
985                            StringPool.DOUBLE_OPEN_BRACKET + redirectTitle +
986                                    StringPool.DOUBLE_CLOSE_BRACKET;
987    
988                    serviceContext.setAddCommunityPermissions(true);
989                    serviceContext.setAddGuestPermissions(true);
990    
991                    addPage(
992                            userId, nodeId, title, version, content, summary, false, format,
993                            head, parentTitle, redirectTitle, serviceContext);
994    
995                    // Move redirects to point to the page with the new title
996    
997                    List<WikiPage> redirectedPages = wikiPagePersistence.findByN_R(
998                            nodeId, title);
999    
1000                    for (WikiPage redirectedPage : redirectedPages) {
1001                            redirectedPage.setRedirectTitle(newTitle);
1002    
1003                            wikiPagePersistence.update(redirectedPage, false);
1004                    }
1005    
1006                    // Asset
1007    
1008                    updateAsset(userId, page, null, null);
1009    
1010                    // Indexer
1011    
1012                    Indexer indexer = IndexerRegistryUtil.getIndexer(WikiPage.class);
1013    
1014                    indexer.delete(
1015                            new Object[] {page.getCompanyId(), page.getNodeId(), title});
1016    
1017                    indexer.reindex(page);
1018            }
1019    
1020            public void movePage(
1021                            long userId, long nodeId, String title, String newTitle,
1022                            ServiceContext serviceContext)
1023                    throws PortalException, SystemException {
1024    
1025                    movePage(userId, nodeId, title, newTitle, true, serviceContext);
1026            }
1027    
1028            public WikiPage revertPage(
1029                            long userId, long nodeId, String title, double version,
1030                            ServiceContext serviceContext)
1031                    throws PortalException, SystemException {
1032    
1033                    WikiPage oldPage = getPage(nodeId, title, version);
1034    
1035                    return updatePage(
1036                            userId, nodeId, title, 0, oldPage.getContent(),
1037                            WikiPageConstants.REVERTED + " to " + version, false,
1038                            oldPage.getFormat(), getParentPageTitle(oldPage),
1039                            oldPage.getRedirectTitle(), serviceContext);
1040            }
1041    
1042            public void subscribePage(long userId, long nodeId, String title)
1043                    throws PortalException, SystemException {
1044    
1045                    WikiPage page = getPage(nodeId, title);
1046    
1047                    subscriptionLocalService.addSubscription(
1048                            userId, WikiPage.class.getName(), page.getResourcePrimKey());
1049            }
1050    
1051            public void unsubscribePage(long userId, long nodeId, String title)
1052                    throws PortalException, SystemException {
1053    
1054                    WikiPage page = getPage(nodeId, title);
1055    
1056                    subscriptionLocalService.deleteSubscription(
1057                            userId, WikiPage.class.getName(), page.getResourcePrimKey());
1058            }
1059    
1060            public void updateAsset(
1061                            long userId, WikiPage page, long[] assetCategoryIds,
1062                            String[] assetTagNames)
1063                    throws PortalException, SystemException {
1064    
1065                    boolean addDraftAssetEntry = false;
1066    
1067                    if (!page.isApproved() &&
1068                            (page.getVersion() != WikiPageConstants.DEFAULT_VERSION)) {
1069    
1070                            int approvedPagesCount = wikiPagePersistence.countByN_T_S(
1071                                    page.getNodeId(), page.getTitle(),
1072                                    WorkflowConstants.STATUS_APPROVED);
1073    
1074                            if (approvedPagesCount > 0) {
1075                                    addDraftAssetEntry = true;
1076                            }
1077                    }
1078    
1079                    if (addDraftAssetEntry) {
1080                            assetEntryLocalService.updateEntry(
1081                                    userId, page.getGroupId(), WikiPage.class.getName(),
1082                                    page.getPrimaryKey(), page.getUuid(), assetCategoryIds,
1083                                    assetTagNames, false, null, null, null, null,
1084                                    ContentTypes.TEXT_HTML, page.getTitle(), null, null, null, 0, 0,
1085                                    null, false);
1086                    }
1087                    else {
1088                            assetEntryLocalService.updateEntry(
1089                                    userId, page.getGroupId(), WikiPage.class.getName(),
1090                                    page.getResourcePrimKey(), page.getUuid(), assetCategoryIds,
1091                                    assetTagNames, page.isApproved(), null, null, null, null,
1092                                    ContentTypes.TEXT_HTML, page.getTitle(), null, null, null, 0, 0,
1093                                    null, false);
1094                    }
1095            }
1096    
1097            public WikiPage updatePage(
1098                            long userId, long nodeId, String title, double version,
1099                            String content, String summary, boolean minorEdit, String format,
1100                            String parentTitle, String redirectTitle,
1101                            ServiceContext serviceContext)
1102                    throws PortalException, SystemException {
1103    
1104                    // Page
1105    
1106                    User user = userPersistence.findByPrimaryKey(userId);
1107                    Date now = new Date();
1108    
1109                    validate(nodeId, content, format);
1110    
1111                    WikiPage oldPage = null;
1112    
1113                    try {
1114                            oldPage = wikiPagePersistence.findByN_T_First(nodeId, title, null);
1115                    }
1116                    catch (NoSuchPageException nspe) {
1117                            return addPage(
1118                                    userId, nodeId, title, WikiPageConstants.DEFAULT_VERSION,
1119                                    content, summary, minorEdit, format, true, parentTitle,
1120                                    redirectTitle, serviceContext);
1121                    }
1122    
1123                    double oldVersion = oldPage.getVersion();
1124    
1125                    if ((version > 0) && (version != oldVersion)) {
1126                            throw new PageVersionException();
1127                    }
1128    
1129                    long resourcePrimKey =
1130                            wikiPageResourceLocalService.getPageResourcePrimKey(
1131                                    nodeId, title);
1132                    long groupId = oldPage.getGroupId();
1133    
1134                    WikiPage page = oldPage;
1135    
1136                    double newVersion = oldVersion;
1137    
1138                    if (oldPage.isApproved()) {
1139                            newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
1140    
1141                            long pageId = counterLocalService.increment();
1142    
1143                            page = wikiPagePersistence.create(pageId);
1144                    }
1145    
1146                    page.setResourcePrimKey(resourcePrimKey);
1147                    page.setGroupId(groupId);
1148                    page.setCompanyId(user.getCompanyId());
1149                    page.setUserId(user.getUserId());
1150                    page.setUserName(user.getFullName());
1151                    page.setCreateDate(serviceContext.getModifiedDate(now));
1152                    page.setModifiedDate(serviceContext.getModifiedDate(now));
1153                    page.setNodeId(nodeId);
1154                    page.setTitle(title);
1155                    page.setVersion(newVersion);
1156                    page.setMinorEdit(minorEdit);
1157                    page.setContent(content);
1158    
1159                    if (oldPage.isPending()) {
1160                            page.setStatus(oldPage.getStatus());
1161                    }
1162                    else {
1163                            page.setStatus(WorkflowConstants.STATUS_DRAFT);
1164                    }
1165    
1166                    page.setSummary(summary);
1167                    page.setFormat(format);
1168    
1169                    if (Validator.isNotNull(parentTitle)) {
1170                            page.setParentTitle(parentTitle);
1171                    }
1172    
1173                    if (Validator.isNotNull(redirectTitle)) {
1174                            page.setRedirectTitle(redirectTitle);
1175                    }
1176    
1177                    wikiPagePersistence.update(page, false);
1178    
1179                    // Expando
1180    
1181                    ExpandoBridge expandoBridge = page.getExpandoBridge();
1182    
1183                    expandoBridge.setAttributes(serviceContext);
1184    
1185                    // Node
1186    
1187                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
1188    
1189                    node.setLastPostDate(serviceContext.getModifiedDate(now));
1190    
1191                    wikiNodePersistence.update(node, false);
1192    
1193                    // Asset
1194    
1195                    updateAsset(
1196                            userId, page, serviceContext.getAssetCategoryIds(),
1197                            serviceContext.getAssetTagNames());
1198    
1199                    // Workflow
1200    
1201                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
1202                            user.getCompanyId(), page.getGroupId(), userId,
1203                            WikiPage.class.getName(), page.getResourcePrimKey(), page,
1204                            serviceContext);
1205    
1206                    return page;
1207            }
1208    
1209            public WikiPage updateStatus(
1210                            long userId, long resourcePrimKey, int status,
1211                            ServiceContext serviceContext)
1212                    throws PortalException, SystemException {
1213    
1214                    WikiPageResource wikiPageResource =
1215                            wikiPageResourceLocalService.getPageResource(resourcePrimKey);
1216    
1217                    List<WikiPage> pages = wikiPagePersistence.findByN_T(
1218                            wikiPageResource.getNodeId(), wikiPageResource.getTitle(), 0, 1,
1219                            new PageVersionComparator());
1220    
1221                    WikiPage page = null;
1222    
1223                    if (!pages.isEmpty()) {
1224                            page = pages.get(0);
1225                    }
1226                    else {
1227                            throw new NoSuchPageException();
1228                    }
1229    
1230                    return updateStatus(userId, page, status, serviceContext);
1231            }
1232    
1233            public WikiPage updateStatus(
1234                            long userId, WikiPage page, int status,
1235                            ServiceContext serviceContext)
1236                    throws PortalException, SystemException {
1237    
1238                    User user = userPersistence.findByPrimaryKey(userId);
1239                    WikiNode node = wikiNodePersistence.findByPrimaryKey(page.getNodeId());
1240    
1241                    Date now = new Date();
1242    
1243                    int oldStatus = page.getStatus();
1244    
1245                    page.setStatus(status);
1246                    page.setStatusByUserId(userId);
1247                    page.setStatusByUserName(user.getFullName());
1248                    page.setStatusDate(now);
1249    
1250                    if (status == WorkflowConstants.STATUS_APPROVED) {
1251    
1252                            // Asset
1253    
1254                            if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
1255                                    (page.getVersion() != WikiPageConstants.DEFAULT_VERSION)) {
1256    
1257                                    try {
1258                                            AssetEntry draftAssetEntry =
1259                                                    assetEntryLocalService.getEntry(
1260                                                            WikiPage.class.getName(), page.getPrimaryKey());
1261    
1262                                            long[] assetCategoryIds = draftAssetEntry.getCategoryIds();
1263                                            String[] assetTagNames = draftAssetEntry.getTagNames();
1264    
1265                                            assetEntryLocalService.updateEntry(
1266                                                    userId, page.getGroupId(), WikiPage.class.getName(),
1267                                                    page.getResourcePrimKey(), page.getUuid(),
1268                                                    assetCategoryIds, assetTagNames, true, null, null, null,
1269                                                    null, ContentTypes.TEXT_HTML, page.getTitle(), null,
1270                                                    null, null, 0, 0, null, false);
1271    
1272                                    }
1273                                    catch (NoSuchEntryException nsee) {
1274                                    }
1275                            }
1276    
1277                            assetEntryLocalService.updateVisible(
1278                                    WikiPage.class.getName(), page.getResourcePrimKey(), true);
1279    
1280                            // Social
1281    
1282                            int activity = WikiActivityKeys.ADD_PAGE;
1283                            String actionId = ActionKeys.ADD_PAGE;
1284    
1285                            if (page.getVersion() > 1.1) {
1286                                    activity = WikiActivityKeys.UPDATE_PAGE;
1287                                    actionId = ActionKeys.UPDATE;
1288                            }
1289    
1290                            socialActivityLocalService.addActivity(
1291                                    userId, page.getGroupId(), WikiPage.class.getName(),
1292                                    page.getResourcePrimKey(), activity, StringPool.BLANK, 0);
1293    
1294                            socialEquityLogLocalService.addEquityLogs(
1295                                    userId, WikiPage.class.getName(), page.getResourcePrimKey(),
1296                                    actionId);
1297    
1298                            // Subscriptions
1299    
1300                            if (!page.isMinorEdit() && NotificationThreadLocal.isEnabled()) {
1301                                    boolean update = false;
1302    
1303                                    if (page.getVersion() > 1.1) {
1304                                            update = true;
1305                                    }
1306    
1307                                    notifySubscribers(node, page, serviceContext, update);
1308                            }
1309    
1310                            // Indexer
1311    
1312                            Indexer indexer = IndexerRegistryUtil.getIndexer(WikiPage.class);
1313    
1314                            indexer.reindex(page);
1315    
1316                            // Cache
1317    
1318                            clearPageCache(page);
1319    
1320                            // Head
1321    
1322                            page.setHead(true);
1323    
1324                            List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
1325                                    page.getNodeId(), page.getTitle(), true);
1326    
1327                            for (WikiPage curPage : pages) {
1328                                    if (!curPage.equals(page)) {
1329                                            curPage.setHead(false);
1330    
1331                                            wikiPagePersistence.update(curPage, false);
1332                                    }
1333                            }
1334                    }
1335                    else {
1336    
1337                            // Head
1338    
1339                            page.setHead(false);
1340    
1341                            List<WikiPage> pages = wikiPagePersistence.findByN_T_S(
1342                                    page.getNodeId(), page.getTitle(),
1343                                    WorkflowConstants.STATUS_APPROVED);
1344    
1345                            for (WikiPage curPage : pages) {
1346                                    if (!curPage.equals(page)) {
1347                                            curPage.setHead(true);
1348    
1349                                            wikiPagePersistence.update(curPage, false);
1350    
1351                                            break;
1352                                    }
1353                            }
1354                    }
1355    
1356                    return wikiPagePersistence.update(page, false);
1357            }
1358    
1359            public void validateTitle(String title) throws PortalException {
1360                    if (title.equals("all_pages") || title.equals("orphan_pages") ||
1361                            title.equals("recent_changes")) {
1362    
1363                            throw new PageTitleException(title + " is reserved");
1364                    }
1365    
1366                    if (Validator.isNotNull(PropsValues.WIKI_PAGE_TITLES_REGEXP)) {
1367                            Pattern pattern = Pattern.compile(
1368                                    PropsValues.WIKI_PAGE_TITLES_REGEXP);
1369    
1370                            Matcher matcher = pattern.matcher(title);
1371    
1372                            if (!matcher.matches()) {
1373                                    throw new PageTitleException();
1374                            }
1375                    }
1376            }
1377    
1378            protected void clearPageCache(WikiPage page) {
1379                    if (!WikiCacheThreadLocal.isClearCache()) {
1380                            return;
1381                    }
1382    
1383                    WikiCacheUtil.clearCache(page.getNodeId());
1384            }
1385    
1386            protected String getParentPageTitle(WikiPage page) {
1387    
1388                    // LPS-4586
1389    
1390                    try {
1391                            WikiPage parentPage = getPage(
1392                                    page.getNodeId(), page.getParentTitle());
1393    
1394                            return parentPage.getTitle();
1395                    }
1396                    catch (Exception e) {
1397                            return null;
1398                    }
1399            }
1400    
1401            protected WikiPage getPreviousVersionPage(WikiPage page)
1402                    throws PortalException, SystemException {
1403    
1404                    double previousVersion = MathUtil.format(page.getVersion() - 0.1, 1, 1);
1405    
1406                    if (previousVersion < 1) {
1407                            return null;
1408                    }
1409    
1410                    return getPage(page.getNodeId(), page.getTitle(), previousVersion);
1411            }
1412    
1413            protected boolean isLinkedTo(WikiPage page, String targetTitle)
1414                    throws PortalException {
1415    
1416                    Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
1417    
1418                    Boolean link = links.get(targetTitle.toLowerCase());
1419    
1420                    if (link != null) {
1421                            return true;
1422                    }
1423                    else {
1424                            return false;
1425                    }
1426            }
1427    
1428            protected boolean isUsedTitle(long nodeId, String title)
1429                    throws SystemException {
1430    
1431                    if (getPagesCount(nodeId, title, true) > 0) {
1432                            return true;
1433                    }
1434                    else {
1435                            return false;
1436                    }
1437            }
1438    
1439            protected void notifySubscribers(
1440                            WikiNode node, WikiPage page, ServiceContext serviceContext,
1441                            boolean update)
1442                    throws PortalException, SystemException {
1443    
1444                    PortletPreferences preferences =
1445                            ServiceContextUtil.getPortletPreferences(serviceContext);
1446    
1447                    if (preferences == null) {
1448                            long ownerId = node.getGroupId();
1449                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
1450                            long plid = PortletKeys.PREFS_PLID_SHARED;
1451                            String portletId = PortletKeys.WIKI;
1452                            String defaultPreferences = null;
1453    
1454                            preferences = portletPreferencesLocalService.getPreferences(
1455                                    node.getCompanyId(), ownerId, ownerType, plid, portletId,
1456                                    defaultPreferences);
1457                    }
1458    
1459                    if (!update && WikiUtil.getEmailPageAddedEnabled(preferences)) {
1460                    }
1461                    else if (update && WikiUtil.getEmailPageUpdatedEnabled(preferences)) {
1462                    }
1463                    else {
1464                            return;
1465                    }
1466    
1467                    Company company = companyPersistence.findByPrimaryKey(
1468                            page.getCompanyId());
1469    
1470                    Group group = groupPersistence.findByPrimaryKey(node.getGroupId());
1471    
1472                    User user = userPersistence.findByPrimaryKey(page.getUserId());
1473    
1474                    String portalURL = serviceContext.getPortalURL();
1475                    String layoutFullURL = serviceContext.getLayoutFullURL();
1476    
1477                    WikiPage previousVersionPage = getPreviousVersionPage(page);
1478    
1479                    String attachmentURLPrefix =
1480                            portalURL + serviceContext.getPathMain() +
1481                                    "/wiki/get_page_attachment?p_l_id=" + serviceContext.getPlid() +
1482                                            "&nodeId=" + page.getNodeId() + "&title=" +
1483                                                    HttpUtil.encodeURL(page.getTitle()) + "&fileName=";
1484    
1485                    String pageDiffs = StringPool.BLANK;
1486    
1487                    try {
1488                            pageDiffs = WikiUtil.diffHtml(
1489                                    previousVersionPage, page, null, null, attachmentURLPrefix);
1490                    }
1491                    catch (Exception e) {
1492                    }
1493    
1494                    String pageContent = null;
1495    
1496                    if (Validator.equals(page.getFormat(), "creole")) {
1497                            pageContent = WikiUtil.convert(
1498                                    page, null, null, attachmentURLPrefix);
1499                    }
1500                    else {
1501                            pageContent = page.getContent();
1502                            pageContent = WikiUtil.processContent(pageContent);
1503                    }
1504    
1505                    String pageURL = StringPool.BLANK;
1506                    String diffsURL = StringPool.BLANK;
1507    
1508                    if (Validator.isNotNull(layoutFullURL)) {
1509                            pageURL =
1510                                    layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "wiki/" +
1511                                            node.getNodeId() + StringPool.SLASH +
1512                                                    HttpUtil.encodeURL(page.getTitle());
1513    
1514                            if (previousVersionPage != null) {
1515                                    StringBundler sb = new StringBundler(16);
1516    
1517                                    sb.append(layoutFullURL);
1518                                    sb.append("?p_p_id=");
1519                                    sb.append(PortletKeys.WIKI);
1520                                    sb.append("&p_p_state=");
1521                                    sb.append(WindowState.MAXIMIZED);
1522                                    sb.append("&struts_action=");
1523                                    sb.append(HttpUtil.encodeURL("/wiki/compare_versions"));
1524                                    sb.append("&nodeId=");
1525                                    sb.append(node.getNodeId());
1526                                    sb.append("&title=");
1527                                    sb.append(HttpUtil.encodeURL(page.getTitle()));
1528                                    sb.append("&sourceVersion=");
1529                                    sb.append(previousVersionPage.getVersion());
1530                                    sb.append("&targetVersion=");
1531                                    sb.append(page.getVersion());
1532                                    sb.append("&type=html");
1533    
1534                                    diffsURL = sb.toString();
1535                            }
1536                    }
1537    
1538                    String portletName = PortalUtil.getPortletTitle(PortletKeys.WIKI, user);
1539    
1540                    String fromName = WikiUtil.getEmailFromName(preferences);
1541                    String fromAddress = WikiUtil.getEmailFromAddress(preferences);
1542    
1543                    String replyToAddress = fromAddress;
1544                    String mailId = WikiUtil.getMailId(
1545                            company.getMx(), page.getNodeId(), page.getPageId());
1546    
1547                    fromName = StringUtil.replace(
1548                            fromName,
1549                            new String[] {
1550                                    "[$COMPANY_ID$]",
1551                                    "[$COMPANY_MX$]",
1552                                    "[$COMPANY_NAME$]",
1553                                    "[$COMMUNITY_NAME$]",
1554                                    "[$PAGE_USER_ADDRESS$]",
1555                                    "[$PAGE_USER_NAME$]",
1556                                    "[$PORTLET_NAME$]"
1557                            },
1558                            new String[] {
1559                                    String.valueOf(company.getCompanyId()),
1560                                    company.getMx(),
1561                                    company.getName(),
1562                                    group.getName(),
1563                                    user.getEmailAddress(),
1564                                    user.getFullName(),
1565                                    portletName
1566                            });
1567    
1568                    fromAddress = StringUtil.replace(
1569                            fromAddress,
1570                            new String[] {
1571                                    "[$COMPANY_ID$]",
1572                                    "[$COMPANY_MX$]",
1573                                    "[$COMPANY_NAME$]",
1574                                    "[$COMMUNITY_NAME$]",
1575                                    "[$PAGE_USER_ADDRESS$]",
1576                                    "[$PAGE_USER_NAME$]",
1577                                    "[$PORTLET_NAME$]"
1578                            },
1579                            new String[] {
1580                                    String.valueOf(company.getCompanyId()),
1581                                    company.getMx(),
1582                                    company.getName(),
1583                                    group.getName(),
1584                                    user.getEmailAddress(),
1585                                    user.getFullName(),
1586                                    portletName
1587                            });
1588    
1589                    String subjectPrefix = null;
1590                    String body = null;
1591                    String signature = null;
1592    
1593                    if (update) {
1594                            subjectPrefix = WikiUtil.getEmailPageUpdatedSubjectPrefix(
1595                                    preferences);
1596                            body = WikiUtil.getEmailPageUpdatedBody(preferences);
1597                            signature = WikiUtil.getEmailPageUpdatedSignature(preferences);
1598                    }
1599                    else {
1600                            subjectPrefix = WikiUtil.getEmailPageAddedSubjectPrefix(
1601                                    preferences);
1602                            body = WikiUtil.getEmailPageAddedBody(preferences);
1603                            signature = WikiUtil.getEmailPageAddedSignature(preferences);
1604                    }
1605    
1606                    if (Validator.isNotNull(signature)) {
1607                            body += "\n" + signature;
1608                    }
1609    
1610                    subjectPrefix = StringUtil.replace(
1611                            subjectPrefix,
1612                            new String[] {
1613                                    "[$COMPANY_ID$]",
1614                                    "[$COMPANY_MX$]",
1615                                    "[$COMPANY_NAME$]",
1616                                    "[$COMMUNITY_NAME$]",
1617                                    "[$FROM_ADDRESS$]",
1618                                    "[$FROM_NAME$]",
1619                                    "[$NODE_NAME$]",
1620                                    "[$PAGE_CONTENT$]",
1621                                    "[$PAGE_ID$]",
1622                                    "[$PAGE_TITLE$]",
1623                                    "[$PAGE_USER_ADDRESS$]",
1624                                    "[$PAGE_USER_NAME$]",
1625                                    "[$PORTAL_URL$]",
1626                                    "[$PORTLET_NAME$]"
1627                            },
1628                            new String[] {
1629                                    String.valueOf(company.getCompanyId()),
1630                                    company.getMx(),
1631                                    company.getName(),
1632                                    group.getName(),
1633                                    fromAddress,
1634                                    fromName,
1635                                    node.getName(),
1636                                    pageContent,
1637                                    String.valueOf(page.getPageId()),
1638                                    page.getTitle(),
1639                                    user.getEmailAddress(),
1640                                    user.getFullName(),
1641                                    company.getVirtualHost(),
1642                                    portletName
1643                            });
1644    
1645                    body = StringUtil.replace(
1646                            body,
1647                            new String[] {
1648                                    "[$COMPANY_ID$]",
1649                                    "[$COMPANY_MX$]",
1650                                    "[$COMPANY_NAME$]",
1651                                    "[$COMMUNITY_NAME$]",
1652                                    "[$DIFFS_URL$]",
1653                                    "[$FROM_ADDRESS$]",
1654                                    "[$FROM_NAME$]",
1655                                    "[$NODE_NAME$]",
1656                                    "[$PAGE_CONTENT$]",
1657                                    "[$PAGE_DATE_UPDATE$]",
1658                                    "[$PAGE_DIFFS$]",
1659                                    "[$PAGE_ID$]",
1660                                    "[$PAGE_SUMMARY$]",
1661                                    "[$PAGE_TITLE$]",
1662                                    "[$PAGE_URL$]",
1663                                    "[$PAGE_USER_ADDRESS$]",
1664                                    "[$PAGE_USER_NAME$]",
1665                                    "[$PORTAL_URL$]",
1666                                    "[$PORTLET_NAME$]"
1667                            },
1668                            new String[] {
1669                                    String.valueOf(company.getCompanyId()),
1670                                    company.getMx(),
1671                                    company.getName(),
1672                                    group.getName(),
1673                                    diffsURL,
1674                                    fromAddress,
1675                                    fromName,
1676                                    node.getName(),
1677                                    pageContent,
1678                                    String.valueOf(page.getModifiedDate()),
1679                                    replaceStyles(pageDiffs),
1680                                    String.valueOf(page.getPageId()),
1681                                    page.getSummary(),
1682                                    page.getTitle(),
1683                                    pageURL,
1684                                    user.getEmailAddress(),
1685                                    user.getFullName(),
1686                                    company.getVirtualHost(),
1687                                    portletName
1688                            });
1689    
1690                    String subject = page.getTitle();
1691    
1692                    if (subject.indexOf(subjectPrefix) == -1) {
1693                            subject = subjectPrefix + StringPool.SPACE + subject;
1694                    }
1695    
1696                    Message message = new Message();
1697    
1698                    message.put("companyId", node.getCompanyId());
1699                    message.put("userId", node.getUserId());
1700                    message.put("nodeId", node.getNodeId());
1701                    message.put("pageResourcePrimKey", page.getResourcePrimKey());
1702                    message.put("fromName", fromName);
1703                    message.put("fromAddress", fromAddress);
1704                    message.put("subject", subject);
1705                    message.put("body", body);
1706                    message.put("replyToAddress", replyToAddress);
1707                    message.put("mailId", mailId);
1708                    message.put("htmlFormat", Boolean.TRUE);
1709    
1710                    MessageBusUtil.sendMessage(DestinationNames.WIKI, message);
1711            }
1712    
1713            protected String replaceStyles(String html) {
1714                    return StringUtil.replace(
1715                            html,
1716                            new String[] {
1717                                    "class=\"diff-html-added\"",
1718                                    "class=\"diff-html-removed\"",
1719                                    "class=\"diff-html-changed\"",
1720                                    "changeType=\"diff-added-image\"",
1721                                    "changeType=\"diff-removed-image\"",
1722                                    "changeType=\"diff-changed-image\""
1723                            },
1724                            new String[] {
1725                                    "style=\"background-color: #CFC;\"",
1726                                    "style=\"background-color: #FDC6C6; text-decoration: " +
1727                                            "line-through;\"",
1728                                    "style=\"border-bottom: 2px dotted blue;\"",
1729                                    "style=\"border: 10px solid #CFC;\"",
1730                                    "style=\"border: 10px solid #FDC6C6;\"",
1731                                    "style=\"border: 10px solid blue;\""
1732                            }
1733                    );
1734            }
1735    
1736            protected void validate(long nodeId, String content, String format)
1737                    throws PortalException {
1738    
1739                    if (!WikiUtil.validate(nodeId, content, format)) {
1740                            throw new PageContentException();
1741                    }
1742            }
1743    
1744            protected void validate(
1745                            String title, long nodeId, String content, String format)
1746                    throws PortalException, SystemException {
1747    
1748                    if (Validator.isNull(title)) {
1749                            throw new PageTitleException();
1750                    }
1751    
1752                    if (isUsedTitle(nodeId, title)) {
1753                            throw new DuplicatePageException();
1754                    }
1755    
1756                    validateTitle(title);
1757    
1758                    validate(nodeId, content, format);
1759            }
1760    
1761    }