001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.journal.action;
016    
017    import com.liferay.portal.LocaleException;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.portlet.LiferayWindowState;
020    import com.liferay.portal.kernel.servlet.SessionErrors;
021    import com.liferay.portal.kernel.servlet.SessionMessages;
022    import com.liferay.portal.kernel.upload.UploadException;
023    import com.liferay.portal.kernel.upload.UploadPortletRequest;
024    import com.liferay.portal.kernel.util.ArrayUtil;
025    import com.liferay.portal.kernel.util.Constants;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.HttpUtil;
028    import com.liferay.portal.kernel.util.LocaleUtil;
029    import com.liferay.portal.kernel.util.LocalizationUtil;
030    import com.liferay.portal.kernel.util.ParamUtil;
031    import com.liferay.portal.kernel.util.StringPool;
032    import com.liferay.portal.kernel.util.StringUtil;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.kernel.workflow.WorkflowConstants;
035    import com.liferay.portal.model.Layout;
036    import com.liferay.portal.security.auth.PrincipalException;
037    import com.liferay.portal.service.LayoutLocalServiceUtil;
038    import com.liferay.portal.service.ServiceContext;
039    import com.liferay.portal.service.ServiceContextFactory;
040    import com.liferay.portal.struts.PortletAction;
041    import com.liferay.portal.theme.ThemeDisplay;
042    import com.liferay.portal.util.PortalUtil;
043    import com.liferay.portal.util.WebKeys;
044    import com.liferay.portlet.PortletURLFactoryUtil;
045    import com.liferay.portlet.PortletURLImpl;
046    import com.liferay.portlet.asset.AssetCategoryException;
047    import com.liferay.portlet.asset.AssetTagException;
048    import com.liferay.portlet.assetpublisher.util.AssetPublisherUtil;
049    import com.liferay.portlet.dynamicdatamapping.NoSuchStructureException;
050    import com.liferay.portlet.dynamicdatamapping.NoSuchTemplateException;
051    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
052    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
053    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
054    import com.liferay.portlet.dynamicdatamapping.util.DDMUtil;
055    import com.liferay.portlet.journal.ArticleContentException;
056    import com.liferay.portlet.journal.ArticleContentSizeException;
057    import com.liferay.portlet.journal.ArticleDisplayDateException;
058    import com.liferay.portlet.journal.ArticleExpirationDateException;
059    import com.liferay.portlet.journal.ArticleIdException;
060    import com.liferay.portlet.journal.ArticleSmallImageNameException;
061    import com.liferay.portlet.journal.ArticleSmallImageSizeException;
062    import com.liferay.portlet.journal.ArticleTitleException;
063    import com.liferay.portlet.journal.ArticleTypeException;
064    import com.liferay.portlet.journal.ArticleVersionException;
065    import com.liferay.portlet.journal.DuplicateArticleIdException;
066    import com.liferay.portlet.journal.NoSuchArticleException;
067    import com.liferay.portlet.journal.asset.JournalArticleAssetRenderer;
068    import com.liferay.portlet.journal.model.JournalArticle;
069    import com.liferay.portlet.journal.service.JournalArticleServiceUtil;
070    import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
071    import com.liferay.portlet.journal.util.JournalConverterUtil;
072    import com.liferay.portlet.journal.util.JournalUtil;
073    
074    import java.io.File;
075    
076    import java.util.Calendar;
077    import java.util.HashMap;
078    import java.util.Locale;
079    import java.util.Map;
080    
081    import javax.portlet.ActionRequest;
082    import javax.portlet.ActionResponse;
083    import javax.portlet.PortletConfig;
084    import javax.portlet.PortletPreferences;
085    import javax.portlet.PortletRequest;
086    import javax.portlet.PortletURL;
087    import javax.portlet.RenderRequest;
088    import javax.portlet.RenderResponse;
089    import javax.portlet.WindowState;
090    
091    import org.apache.struts.action.ActionForm;
092    import org.apache.struts.action.ActionForward;
093    import org.apache.struts.action.ActionMapping;
094    
095    /**
096     * @author Brian Wing Shun Chan
097     * @author Raymond Aug??
098     * @author Eduardo Lundgren
099     * @author Juan Fern??ndez
100     * @author Levente Hud??k
101     */
102    public class EditArticleAction extends PortletAction {
103    
104            public static final String VERSION_SEPARATOR = "_version_";
105    
106            @Override
107            public void processAction(
108                            ActionMapping actionMapping, ActionForm actionForm,
109                            PortletConfig portletConfig, ActionRequest actionRequest,
110                            ActionResponse actionResponse)
111                    throws Exception {
112    
113                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
114    
115                    JournalArticle article = null;
116                    String oldUrlTitle = StringPool.BLANK;
117    
118                    try {
119                            if (Validator.isNull(cmd)) {
120                                    UploadException uploadException =
121                                            (UploadException)actionRequest.getAttribute(
122                                                    WebKeys.UPLOAD_EXCEPTION);
123    
124                                    if (uploadException != null) {
125                                            if (uploadException.isExceededSizeLimit()) {
126                                                    throw new ArticleContentSizeException();
127                                            }
128    
129                                            throw new PortalException(uploadException.getCause());
130                                    }
131    
132                                    return;
133                            }
134                            else if (cmd.equals(Constants.ADD) ||
135                                             cmd.equals(Constants.PREVIEW) ||
136                                             cmd.equals(Constants.TRANSLATE) ||
137                                             cmd.equals(Constants.UPDATE)) {
138    
139                                    Object[] contentAndImages = updateArticle(actionRequest);
140    
141                                    article = (JournalArticle)contentAndImages[0];
142                                    oldUrlTitle = ((String)contentAndImages[1]);
143                            }
144                            else if (cmd.equals(Constants.DELETE)) {
145                                    deleteArticles(actionRequest, false);
146                            }
147                            else if (cmd.equals(Constants.DELETE_TRANSLATION)) {
148                                    removeArticlesLocale(actionRequest);
149                            }
150                            else if (cmd.equals(Constants.EXPIRE)) {
151                                    expireArticles(actionRequest);
152                            }
153                            else if (cmd.equals(Constants.MOVE)) {
154                                    moveArticles(actionRequest);
155                            }
156                            else if (cmd.equals(Constants.MOVE_TO_TRASH)) {
157                                    deleteArticles(actionRequest, true);
158                            }
159                            else if (cmd.equals(Constants.RESTORE)) {
160                                    restoreArticles(actionRequest);
161                            }
162                            else if (cmd.equals(Constants.SUBSCRIBE)) {
163                                    subscribeArticles(actionRequest);
164                            }
165                            else if (cmd.equals(Constants.UNSUBSCRIBE)) {
166                                    unsubscribeArticles(actionRequest);
167                            }
168    
169                            String redirect = ParamUtil.getString(actionRequest, "redirect");
170    
171                            int workflowAction = ParamUtil.getInteger(
172                                    actionRequest, "workflowAction",
173                                    WorkflowConstants.ACTION_PUBLISH);
174    
175                            String portletId = HttpUtil.getParameter(redirect, "p_p_id", false);
176    
177                            String namespace = PortalUtil.getPortletNamespace(portletId);
178    
179                            if (Validator.isNotNull(oldUrlTitle)) {
180                                    String oldRedirectParam = namespace + "redirect";
181    
182                                    String oldRedirect = HttpUtil.getParameter(
183                                            redirect, oldRedirectParam, false);
184    
185                                    if (Validator.isNotNull(oldRedirect)) {
186                                            String newRedirect = HttpUtil.decodeURL(oldRedirect);
187    
188                                            newRedirect = StringUtil.replace(
189                                                    newRedirect, oldUrlTitle, article.getUrlTitle());
190                                            newRedirect = StringUtil.replace(
191                                                    newRedirect, oldRedirectParam, "redirect");
192    
193                                            redirect = StringUtil.replace(
194                                                    redirect, oldRedirect, newRedirect);
195                                    }
196                            }
197    
198                            ThemeDisplay themeDisplay =
199                                    (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
200    
201                            if (cmd.equals(Constants.DELETE) &&
202                                    !ActionUtil.hasArticle(actionRequest)) {
203    
204                                    String referringPortletResource = ParamUtil.getString(
205                                            actionRequest, "referringPortletResource");
206    
207                                    if (Validator.isNotNull(referringPortletResource)) {
208                                            setForward(
209                                                    actionRequest,
210                                                    "portlet.journal.asset.add_asset_redirect");
211    
212                                            return;
213                                    }
214                                    else {
215                                            PortletURL portletURL = PortletURLFactoryUtil.create(
216                                                    actionRequest, portletConfig.getPortletName(),
217                                                    themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
218    
219                                            redirect = portletURL.toString();
220                                    }
221                            }
222    
223                            if (cmd.equals(Constants.DELETE_TRANSLATION) ||
224                                    cmd.equals(Constants.TRANSLATE)) {
225    
226                                    setForward(
227                                            actionRequest,
228                                            "portlet.journal.update_translation_redirect");
229                            }
230                            else if ((article != null) &&
231                                             (workflowAction == WorkflowConstants.ACTION_SAVE_DRAFT)) {
232    
233                                    redirect = getSaveAndContinueRedirect(
234                                            portletConfig, actionRequest, article, redirect);
235    
236                                    sendRedirect(actionRequest, actionResponse, redirect);
237                            }
238                            else {
239                                    WindowState windowState = actionRequest.getWindowState();
240    
241                                    Layout layout = themeDisplay.getLayout();
242    
243                                    if (!windowState.equals(LiferayWindowState.POP_UP) &&
244                                            layout.isTypeControlPanel()) {
245    
246                                            sendRedirect(actionRequest, actionResponse, redirect);
247                                    }
248                                    else {
249                                            redirect = PortalUtil.escapeRedirect(redirect);
250    
251                                            if (Validator.isNotNull(redirect)) {
252                                                    if (cmd.equals(Constants.ADD) && (article != null)) {
253                                                            redirect = HttpUtil.addParameter(
254                                                                    redirect, namespace + "className",
255                                                                    JournalArticle.class.getName());
256                                                            redirect = HttpUtil.addParameter(
257                                                                    redirect, namespace + "classPK",
258                                                                    JournalArticleAssetRenderer.getClassPK(
259                                                                            article));
260                                                    }
261    
262                                                    actionResponse.sendRedirect(redirect);
263                                            }
264                                    }
265                            }
266                    }
267                    catch (Exception e) {
268                            if (e instanceof NoSuchArticleException ||
269                                    e instanceof NoSuchStructureException ||
270                                    e instanceof NoSuchTemplateException ||
271                                    e instanceof PrincipalException) {
272    
273                                    SessionErrors.add(actionRequest, e.getClass());
274    
275                                    setForward(actionRequest, "portlet.journal.error");
276                            }
277                            else if (e instanceof ArticleContentException ||
278                                             e instanceof ArticleContentSizeException ||
279                                             e instanceof ArticleDisplayDateException ||
280                                             e instanceof ArticleExpirationDateException ||
281                                             e instanceof ArticleIdException ||
282                                             e instanceof ArticleSmallImageNameException ||
283                                             e instanceof ArticleSmallImageSizeException ||
284                                             e instanceof ArticleTitleException ||
285                                             e instanceof ArticleTypeException ||
286                                             e instanceof ArticleVersionException ||
287                                             e instanceof DuplicateArticleIdException) {
288    
289                                    SessionErrors.add(actionRequest, e.getClass());
290                            }
291                            else if (e instanceof AssetCategoryException ||
292                                             e instanceof AssetTagException ||
293                                             e instanceof LocaleException) {
294    
295                                    SessionErrors.add(actionRequest, e.getClass(), e);
296                            }
297                            else {
298                                    throw e;
299                            }
300                    }
301            }
302    
303            @Override
304            public ActionForward render(
305                            ActionMapping actionMapping, ActionForm actionForm,
306                            PortletConfig portletConfig, RenderRequest renderRequest,
307                            RenderResponse renderResponse)
308                    throws Exception {
309    
310                    try {
311                            ActionUtil.getArticle(renderRequest);
312                    }
313                    catch (NoSuchArticleException nsae) {
314    
315                            // Let this slide because the user can manually input a article id
316                            // for a new article that does not yet exist.
317    
318                    }
319                    catch (Exception e) {
320                            if (//e instanceof NoSuchArticleException ||
321                                    e instanceof PrincipalException) {
322    
323                                    SessionErrors.add(renderRequest, e.getClass());
324    
325                                    return actionMapping.findForward("portlet.journal.error");
326                            }
327                            else {
328                                    throw e;
329                            }
330                    }
331    
332                    return actionMapping.findForward(
333                            getForward(renderRequest, "portlet.journal.edit_article"));
334            }
335    
336            protected void deleteArticles(
337                            ActionRequest actionRequest, boolean moveToTrash)
338                    throws Exception {
339    
340                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
341                            WebKeys.THEME_DISPLAY);
342    
343                    String deleteEntryTitle = null;
344    
345                    String[] deleteArticleIds = null;
346    
347                    String articleId = ParamUtil.getString(actionRequest, "articleId");
348    
349                    if (Validator.isNotNull(articleId)) {
350                            deleteArticleIds = new String[] {articleId};
351                    }
352                    else {
353                            deleteArticleIds = StringUtil.split(
354                                    ParamUtil.getString(actionRequest, "articleIds"));
355                    }
356    
357                    long[] restoreArticleIds = new long[deleteArticleIds.length];
358    
359                    for (int i = 0; i < deleteArticleIds.length; i++) {
360                            String deleteArticleId = deleteArticleIds[i];
361    
362                            if (moveToTrash) {
363                                    JournalArticle article =
364                                            JournalArticleServiceUtil.moveArticleToTrash(
365                                                    themeDisplay.getScopeGroupId(), deleteArticleId);
366    
367                                    if (i == 0) {
368                                            deleteEntryTitle = article.getTitle(
369                                                    themeDisplay.getLocale());
370                                    }
371    
372                                    restoreArticleIds[i] = article.getResourcePrimKey();
373                            }
374                            else {
375                                    ActionUtil.deleteArticle(actionRequest, deleteArticleId);
376                            }
377                    }
378    
379                    if (moveToTrash && (deleteArticleIds.length > 0)) {
380                            Map<String, String[]> data = new HashMap<String, String[]>();
381    
382                            data.put(
383                                    "deleteEntryClassName",
384                                    new String[] {JournalArticle.class.getName()});
385    
386                            if (Validator.isNotNull(deleteEntryTitle)) {
387                                    data.put("deleteEntryTitle", new String[] {deleteEntryTitle});
388                            }
389    
390                            data.put(
391                                    "restoreArticleIds",
392                                    ArrayUtil.toStringArray(restoreArticleIds));
393    
394                            SessionMessages.add(
395                                    actionRequest,
396                                    PortalUtil.getPortletId(actionRequest) +
397                                            SessionMessages.KEY_SUFFIX_DELETE_SUCCESS_DATA, data);
398    
399                            hideDefaultSuccessMessage(actionRequest);
400                    }
401            }
402    
403            protected void expireArticles(ActionRequest actionRequest)
404                    throws Exception {
405    
406                    String articleId = ParamUtil.getString(actionRequest, "articleId");
407    
408                    if (Validator.isNotNull(articleId)) {
409                            ActionUtil.expireArticle(actionRequest, articleId);
410                    }
411                    else {
412                            String[] expireArticleIds = StringUtil.split(
413                                    ParamUtil.getString(actionRequest, "expireArticleIds"));
414    
415                            for (String expireArticleId : expireArticleIds) {
416                                    ActionUtil.expireArticle(actionRequest, expireArticleId);
417                            }
418                    }
419            }
420    
421            protected String getSaveAndContinueRedirect(
422                            PortletConfig portletConfig, ActionRequest actionRequest,
423                            JournalArticle article, String redirect)
424                    throws Exception {
425    
426                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
427                            WebKeys.THEME_DISPLAY);
428    
429                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
430    
431                    String referringPortletResource = ParamUtil.getString(
432                            actionRequest, "referringPortletResource");
433    
434                    String languageId = ParamUtil.getString(actionRequest, "languageId");
435    
436                    PortletURLImpl portletURL = new PortletURLImpl(
437                            actionRequest, portletConfig.getPortletName(),
438                            themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
439    
440                    portletURL.setParameter("struts_action", "/journal/edit_article");
441                    portletURL.setParameter(Constants.CMD, cmd, false);
442                    portletURL.setParameter("redirect", redirect, false);
443                    portletURL.setParameter(
444                            "referringPortletResource", referringPortletResource, false);
445                    portletURL.setParameter(
446                            "resourcePrimKey", String.valueOf(article.getResourcePrimKey()),
447                            false);
448                    portletURL.setParameter(
449                            "groupId", String.valueOf(article.getGroupId()), false);
450                    portletURL.setParameter("articleId", article.getArticleId(), false);
451                    portletURL.setParameter(
452                            "version", String.valueOf(article.getVersion()), false);
453                    portletURL.setParameter("languageId", languageId, false);
454                    portletURL.setWindowState(actionRequest.getWindowState());
455    
456                    return portletURL.toString();
457            }
458    
459            protected void moveArticles(ActionRequest actionRequest) throws Exception {
460                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
461                            WebKeys.THEME_DISPLAY);
462    
463                    String articleId = ParamUtil.getString(actionRequest, "articleId");
464                    long newFolderId = ParamUtil.getLong(actionRequest, "newFolderId");
465    
466                    if (Validator.isNotNull(articleId)) {
467                            JournalArticleServiceUtil.moveArticle(
468                                    themeDisplay.getScopeGroupId(), articleId, newFolderId);
469                    }
470                    else {
471                            String[] articleIds = StringUtil.split(
472                                    ParamUtil.getString(actionRequest, "articleIds"));
473    
474                            for (int i = 0; i < articleIds.length; i++) {
475                                    JournalArticleServiceUtil.moveArticle(
476                                            themeDisplay.getScopeGroupId(), articleIds[i], newFolderId);
477                            }
478                    }
479            }
480    
481            protected void removeArticlesLocale(ActionRequest actionRequest)
482                    throws Exception {
483    
484                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
485    
486                    String[] removeArticleLocaleIds = StringUtil.split(
487                            ParamUtil.getString(actionRequest, "articleIds"));
488    
489                    for (String removeArticleLocaleId : removeArticleLocaleIds) {
490                            int pos = removeArticleLocaleId.lastIndexOf(VERSION_SEPARATOR);
491    
492                            String articleId = removeArticleLocaleId.substring(0, pos);
493                            double version = GetterUtil.getDouble(
494                                    removeArticleLocaleId.substring(
495                                            pos + VERSION_SEPARATOR.length()));
496                            String languageId = ParamUtil.getString(
497                                    actionRequest, "languageId");
498    
499                            JournalArticleServiceUtil.removeArticleLocale(
500                                    groupId, articleId, version, languageId);
501                    }
502            }
503    
504            protected void restoreArticles(ActionRequest actionRequest)
505                    throws Exception {
506    
507                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
508                            WebKeys.THEME_DISPLAY);
509    
510                    String[] restoreEntryIds = StringUtil.split(
511                            ParamUtil.getString(actionRequest, "restoreEntryIds"));
512    
513                    for (String restoreEntryId : restoreEntryIds) {
514                            JournalArticleServiceUtil.restoreArticleFromTrash(
515                                    themeDisplay.getScopeGroupId(), restoreEntryId);
516                    }
517            }
518    
519            protected void subscribeArticles(ActionRequest actionRequest)
520                    throws Exception {
521    
522                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
523                            WebKeys.THEME_DISPLAY);
524    
525                    JournalArticleServiceUtil.subscribe(themeDisplay.getScopeGroupId());
526            }
527    
528            protected void unsubscribeArticles(ActionRequest actionRequest)
529                    throws Exception {
530    
531                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
532                            WebKeys.THEME_DISPLAY);
533    
534                    JournalArticleServiceUtil.unsubscribe(themeDisplay.getScopeGroupId());
535            }
536    
537            protected Object[] updateArticle(ActionRequest actionRequest)
538                    throws Exception {
539    
540                    UploadPortletRequest uploadPortletRequest =
541                            PortalUtil.getUploadPortletRequest(actionRequest);
542    
543                    String cmd = ParamUtil.getString(uploadPortletRequest, Constants.CMD);
544    
545                    long groupId = ParamUtil.getLong(uploadPortletRequest, "groupId");
546                    long folderId = ParamUtil.getLong(uploadPortletRequest, "folderId");
547                    long classNameId = ParamUtil.getLong(
548                            uploadPortletRequest, "classNameId");
549                    long classPK = ParamUtil.getLong(uploadPortletRequest, "classPK");
550    
551                    String articleId = ParamUtil.getString(
552                            uploadPortletRequest, "articleId");
553    
554                    boolean autoArticleId = ParamUtil.getBoolean(
555                            uploadPortletRequest, "autoArticleId");
556                    double version = ParamUtil.getDouble(uploadPortletRequest, "version");
557                    boolean localized = ParamUtil.getBoolean(
558                            uploadPortletRequest, "localized");
559    
560                    String defaultLanguageId = ParamUtil.getString(
561                            uploadPortletRequest, "defaultLanguageId");
562    
563                    Locale defaultLocale = LocaleUtil.fromLanguageId(defaultLanguageId);
564    
565                    String toLanguageId = ParamUtil.getString(
566                            uploadPortletRequest, "toLanguageId");
567    
568                    Locale toLocale = null;
569    
570                    String title = StringPool.BLANK;
571                    String description = StringPool.BLANK;
572    
573                    if (Validator.isNull(toLanguageId)) {
574                            title = ParamUtil.getString(
575                                    uploadPortletRequest, "title_" + defaultLanguageId);
576                            description = ParamUtil.getString(
577                                    uploadPortletRequest, "description_" + defaultLanguageId);
578                    }
579                    else {
580                            toLocale = LocaleUtil.fromLanguageId(toLanguageId);
581    
582                            title = ParamUtil.getString(
583                                    uploadPortletRequest, "title_" + toLanguageId);
584                            description = ParamUtil.getString(
585                                    uploadPortletRequest, "description_" + toLanguageId);
586                    }
587    
588                    String content = ParamUtil.getString(
589                            uploadPortletRequest, "articleContent");
590    
591                    Map<String, byte[]> images = new HashMap<String, byte[]>();
592    
593                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
594                            JournalArticle.class.getName(), uploadPortletRequest);
595    
596                    String structureId = ParamUtil.getString(
597                            uploadPortletRequest, "structureId");
598    
599                    DDMStructure ddmStructure = null;
600    
601                    if (Validator.isNotNull(structureId)) {
602                            try {
603                                    ddmStructure =
604                                            DDMStructureLocalServiceUtil.getStructure(
605                                                    PortalUtil.getSiteGroupId(groupId),
606                                                    PortalUtil.getClassNameId(JournalArticle.class),
607                                                    structureId);
608                            }
609                            catch (NoSuchStructureException nsse) {
610                                    ThemeDisplay themeDisplay =
611                                            (ThemeDisplay)uploadPortletRequest.getAttribute(
612                                                    WebKeys.THEME_DISPLAY);
613    
614                                    ddmStructure =
615                                            DDMStructureLocalServiceUtil.getStructure(
616                                                    themeDisplay.getCompanyGroupId(),
617                                                    PortalUtil.getClassNameId(JournalArticle.class),
618                                                    structureId);
619                            }
620    
621                            String languageId = toLanguageId;
622    
623                            if (Validator.isNull(languageId)) {
624                                    languageId = defaultLanguageId;
625                            }
626    
627                            Locale locale = LocaleUtil.fromLanguageId(languageId);
628    
629                            Object[] contentAndImages = ActionUtil.getContentAndImages(
630                                    ddmStructure, locale, serviceContext);
631    
632                            content = (String)contentAndImages[0];
633                            images = (HashMap<String, byte[]>)contentAndImages[1];
634                    }
635    
636                    Boolean fileItemThresholdSizeExceeded =
637                            (Boolean)uploadPortletRequest.getAttribute(
638                                    WebKeys.FILE_ITEM_THRESHOLD_SIZE_EXCEEDED);
639    
640                    if ((fileItemThresholdSizeExceeded != null) &&
641                            fileItemThresholdSizeExceeded.booleanValue()) {
642    
643                            throw new ArticleContentSizeException();
644                    }
645    
646                    String type = ParamUtil.getString(uploadPortletRequest, "type");
647                    String templateId = ParamUtil.getString(
648                            uploadPortletRequest, "templateId");
649                    String layoutUuid = ParamUtil.getString(
650                            uploadPortletRequest, "layoutUuid");
651    
652                    // The target page and the article must belong to the same group
653    
654                    Layout targetLayout =
655                            LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
656                                    layoutUuid, groupId, false);
657    
658                    if (targetLayout == null) {
659                            targetLayout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
660                                    layoutUuid, groupId, true);
661                    }
662    
663                    if (targetLayout == null) {
664                            layoutUuid = null;
665                    }
666    
667                    int displayDateMonth = ParamUtil.getInteger(
668                            uploadPortletRequest, "displayDateMonth");
669                    int displayDateDay = ParamUtil.getInteger(
670                            uploadPortletRequest, "displayDateDay");
671                    int displayDateYear = ParamUtil.getInteger(
672                            uploadPortletRequest, "displayDateYear");
673                    int displayDateHour = ParamUtil.getInteger(
674                            uploadPortletRequest, "displayDateHour");
675                    int displayDateMinute = ParamUtil.getInteger(
676                            uploadPortletRequest, "displayDateMinute");
677                    int displayDateAmPm = ParamUtil.getInteger(
678                            uploadPortletRequest, "displayDateAmPm");
679    
680                    if (displayDateAmPm == Calendar.PM) {
681                            displayDateHour += 12;
682                    }
683    
684                    int expirationDateMonth = ParamUtil.getInteger(
685                            uploadPortletRequest, "expirationDateMonth");
686                    int expirationDateDay = ParamUtil.getInteger(
687                            uploadPortletRequest, "expirationDateDay");
688                    int expirationDateYear = ParamUtil.getInteger(
689                            uploadPortletRequest, "expirationDateYear");
690                    int expirationDateHour = ParamUtil.getInteger(
691                            uploadPortletRequest, "expirationDateHour");
692                    int expirationDateMinute = ParamUtil.getInteger(
693                            uploadPortletRequest, "expirationDateMinute");
694                    int expirationDateAmPm = ParamUtil.getInteger(
695                            uploadPortletRequest, "expirationDateAmPm");
696                    boolean neverExpire = ParamUtil.getBoolean(
697                            uploadPortletRequest, "neverExpire");
698    
699                    if (expirationDateAmPm == Calendar.PM) {
700                            expirationDateHour += 12;
701                    }
702    
703                    int reviewDateMonth = ParamUtil.getInteger(
704                            uploadPortletRequest, "reviewDateMonth");
705                    int reviewDateDay = ParamUtil.getInteger(
706                            uploadPortletRequest, "reviewDateDay");
707                    int reviewDateYear = ParamUtil.getInteger(
708                            uploadPortletRequest, "reviewDateYear");
709                    int reviewDateHour = ParamUtil.getInteger(
710                            uploadPortletRequest, "reviewDateHour");
711                    int reviewDateMinute = ParamUtil.getInteger(
712                            uploadPortletRequest, "reviewDateMinute");
713                    int reviewDateAmPm = ParamUtil.getInteger(
714                            uploadPortletRequest, "reviewDateAmPm");
715                    boolean neverReview = ParamUtil.getBoolean(
716                            uploadPortletRequest, "neverReview");
717    
718                    if (reviewDateAmPm == Calendar.PM) {
719                            reviewDateHour += 12;
720                    }
721    
722                    boolean indexable = ParamUtil.getBoolean(
723                            uploadPortletRequest, "indexable");
724    
725                    boolean smallImage = ParamUtil.getBoolean(
726                            uploadPortletRequest, "smallImage");
727                    String smallImageURL = ParamUtil.getString(
728                            uploadPortletRequest, "smallImageURL");
729                    File smallFile = uploadPortletRequest.getFile("smallFile");
730    
731                    String articleURL = ParamUtil.getString(
732                            uploadPortletRequest, "articleURL");
733    
734                    serviceContext.setAttribute("defaultLanguageId", defaultLanguageId);
735    
736                    JournalArticle article = null;
737                    String oldUrlTitle = StringPool.BLANK;
738    
739                    if (cmd.equals(Constants.ADD)) {
740                            Map<Locale, String> titleMap = new HashMap<Locale, String>();
741    
742                            titleMap.put(defaultLocale, title);
743    
744                            Map<Locale, String> descriptionMap = new HashMap<Locale, String>();
745    
746                            descriptionMap.put(defaultLocale, description);
747    
748                            if (Validator.isNull(structureId)) {
749                                    content = LocalizationUtil.updateLocalization(
750                                            StringPool.BLANK, "static-content", content,
751                                            defaultLanguageId, defaultLanguageId, true, localized);
752                            }
753    
754                            // Add article
755    
756                            article = JournalArticleServiceUtil.addArticle(
757                                    groupId, folderId, classNameId, classPK, articleId,
758                                    autoArticleId, titleMap, descriptionMap, content, type,
759                                    structureId, templateId, layoutUuid, displayDateMonth,
760                                    displayDateDay, displayDateYear, displayDateHour,
761                                    displayDateMinute, expirationDateMonth, expirationDateDay,
762                                    expirationDateYear, expirationDateHour, expirationDateMinute,
763                                    neverExpire, reviewDateMonth, reviewDateDay, reviewDateYear,
764                                    reviewDateHour, reviewDateMinute, neverReview, indexable,
765                                    smallImage, smallImageURL, smallFile, images, articleURL,
766                                    serviceContext);
767    
768                            AssetPublisherUtil.addAndStoreSelection(
769                                    actionRequest, JournalArticle.class.getName(),
770                                    article.getResourcePrimKey(), -1);
771                    }
772                    else {
773    
774                            // Merge current content with new content
775    
776                            JournalArticle curArticle = JournalArticleServiceUtil.getArticle(
777                                    groupId, articleId, version);
778    
779                            if (Validator.isNull(structureId)) {
780                                    if (!curArticle.isTemplateDriven()) {
781                                            String curContent = StringPool.BLANK;
782    
783                                            curContent = curArticle.getContent();
784    
785                                            if (cmd.equals(Constants.TRANSLATE)) {
786                                                    content = LocalizationUtil.updateLocalization(
787                                                            curContent, "static-content", content, toLanguageId,
788                                                            defaultLanguageId, true, true);
789                                            }
790                                            else {
791                                                    content = LocalizationUtil.updateLocalization(
792                                                            curContent, "static-content", content,
793                                                            defaultLanguageId, defaultLanguageId, true,
794                                                            localized);
795                                            }
796                                    }
797                            }
798                            else {
799                                    if (curArticle.isTemplateDriven()) {
800                                            Fields newFields = DDMUtil.getFields(
801                                                    ddmStructure.getStructureId(), serviceContext);
802    
803                                            Fields existingFields = JournalConverterUtil.getDDMFields(
804                                                    ddmStructure, curArticle.getContent());
805    
806                                            Fields mergedFields = DDMUtil.mergeFields(
807                                                    newFields, existingFields);
808    
809                                            content = JournalConverterUtil.getContent(
810                                                    ddmStructure, mergedFields);
811                                    }
812                            }
813    
814                            // Update article
815    
816                            article = JournalArticleServiceUtil.getArticle(
817                                    groupId, articleId, version);
818    
819                            Map<Locale, String> titleMap = article.getTitleMap();
820                            Map<Locale, String> descriptionMap = article.getDescriptionMap();
821    
822                            String tempOldUrlTitle = article.getUrlTitle();
823    
824                            if (cmd.equals(Constants.PREVIEW) || cmd.equals(Constants.UPDATE)) {
825                                    titleMap.put(defaultLocale, title);
826                                    descriptionMap.put(defaultLocale, description);
827    
828                                    article = JournalArticleServiceUtil.updateArticle(
829                                            groupId, folderId, articleId, version, titleMap,
830                                            descriptionMap, content, type, structureId, templateId,
831                                            layoutUuid, displayDateMonth, displayDateDay,
832                                            displayDateYear, displayDateHour, displayDateMinute,
833                                            expirationDateMonth, expirationDateDay, expirationDateYear,
834                                            expirationDateHour, expirationDateMinute, neverExpire,
835                                            reviewDateMonth, reviewDateDay, reviewDateYear,
836                                            reviewDateHour, reviewDateMinute, neverReview, indexable,
837                                            smallImage, smallImageURL, smallFile, images, articleURL,
838                                            serviceContext);
839                            }
840                            else if (cmd.equals(Constants.TRANSLATE)) {
841                                    article = JournalArticleServiceUtil.updateArticleTranslation(
842                                            groupId, articleId, version, toLocale, title, description,
843                                            content, images, serviceContext);
844                            }
845    
846                            if (!tempOldUrlTitle.equals(article.getUrlTitle())) {
847                                    oldUrlTitle = tempOldUrlTitle;
848                            }
849                    }
850    
851                    // Recent articles
852    
853                    JournalUtil.addRecentArticle(actionRequest, article);
854    
855                    // Journal content
856    
857                    PortletPreferences portletPreferences = getStrictPortletSetup(
858                            actionRequest);
859    
860                    if (portletPreferences != null) {
861                            portletPreferences.setValue(
862                                    "groupId", String.valueOf(article.getGroupId()));
863                            portletPreferences.setValue("articleId", article.getArticleId());
864    
865                            portletPreferences.store();
866    
867                            String portletResource = ParamUtil.getString(
868                                    actionRequest, "portletResource");
869    
870                            updateContentSearch(
871                                    actionRequest, portletResource, article.getArticleId());
872                    }
873    
874                    return new Object[] {article, oldUrlTitle};
875            }
876    
877            protected void updateContentSearch(
878                            ActionRequest actionRequest, String portletResource,
879                            String articleId)
880                    throws Exception {
881    
882                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
883                            WebKeys.THEME_DISPLAY);
884    
885                    Layout layout = themeDisplay.getLayout();
886    
887                    JournalContentSearchLocalServiceUtil.updateContentSearch(
888                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
889                            portletResource, articleId, true);
890            }
891    
892    }