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