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.blogs.action;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.json.JSONFactoryUtil;
020    import com.liferay.portal.kernel.json.JSONObject;
021    import com.liferay.portal.kernel.portlet.LiferayWindowState;
022    import com.liferay.portal.kernel.sanitizer.SanitizerException;
023    import com.liferay.portal.kernel.servlet.SessionErrors;
024    import com.liferay.portal.kernel.servlet.SessionMessages;
025    import com.liferay.portal.kernel.upload.LiferayFileItemException;
026    import com.liferay.portal.kernel.upload.UploadException;
027    import com.liferay.portal.kernel.upload.UploadPortletRequest;
028    import com.liferay.portal.kernel.util.ArrayUtil;
029    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
030    import com.liferay.portal.kernel.util.Constants;
031    import com.liferay.portal.kernel.util.HttpUtil;
032    import com.liferay.portal.kernel.util.ParamUtil;
033    import com.liferay.portal.kernel.util.StreamUtil;
034    import com.liferay.portal.kernel.util.StringPool;
035    import com.liferay.portal.kernel.util.StringUtil;
036    import com.liferay.portal.kernel.util.Validator;
037    import com.liferay.portal.kernel.workflow.WorkflowConstants;
038    import com.liferay.portal.security.auth.PrincipalException;
039    import com.liferay.portal.service.ServiceContext;
040    import com.liferay.portal.service.ServiceContextFactory;
041    import com.liferay.portal.struts.PortletAction;
042    import com.liferay.portal.theme.ThemeDisplay;
043    import com.liferay.portal.util.PortalUtil;
044    import com.liferay.portal.util.PortletKeys;
045    import com.liferay.portal.util.PropsValues;
046    import com.liferay.portal.util.WebKeys;
047    import com.liferay.portlet.PortletURLImpl;
048    import com.liferay.portlet.asset.AssetCategoryException;
049    import com.liferay.portlet.asset.AssetTagException;
050    import com.liferay.portlet.assetpublisher.util.AssetPublisherUtil;
051    import com.liferay.portlet.blogs.EntryContentException;
052    import com.liferay.portlet.blogs.EntryDisplayDateException;
053    import com.liferay.portlet.blogs.EntrySmallImageNameException;
054    import com.liferay.portlet.blogs.EntrySmallImageSizeException;
055    import com.liferay.portlet.blogs.EntryTitleException;
056    import com.liferay.portlet.blogs.NoSuchEntryException;
057    import com.liferay.portlet.blogs.model.BlogsEntry;
058    import com.liferay.portlet.blogs.service.BlogsEntryLocalServiceUtil;
059    import com.liferay.portlet.blogs.service.BlogsEntryServiceUtil;
060    import com.liferay.portlet.documentlibrary.FileSizeException;
061    
062    import java.io.InputStream;
063    
064    import java.util.Calendar;
065    import java.util.HashMap;
066    import java.util.Map;
067    
068    import javax.portlet.ActionRequest;
069    import javax.portlet.ActionResponse;
070    import javax.portlet.PortletConfig;
071    import javax.portlet.PortletRequest;
072    import javax.portlet.RenderRequest;
073    import javax.portlet.RenderResponse;
074    import javax.portlet.WindowState;
075    
076    import javax.servlet.http.HttpServletResponse;
077    
078    import org.apache.struts.action.ActionForm;
079    import org.apache.struts.action.ActionForward;
080    import org.apache.struts.action.ActionMapping;
081    
082    /**
083     * @author Brian Wing Shun Chan
084     * @author Wilson S. Man
085     * @author Thiago Moreira
086     * @author Juan Fern??ndez
087     * @author Zsolt Berentey
088     * @author Levente Hud??k
089     */
090    public class EditEntryAction extends PortletAction {
091    
092            @Override
093            public void processAction(
094                            ActionMapping actionMapping, ActionForm actionForm,
095                            PortletConfig portletConfig, ActionRequest actionRequest,
096                            ActionResponse actionResponse)
097                    throws Exception {
098    
099                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
100    
101                    try {
102                            BlogsEntry entry = null;
103                            String oldUrlTitle = StringPool.BLANK;
104    
105                            UploadException uploadException =
106                                    (UploadException)actionRequest.getAttribute(
107                                            WebKeys.UPLOAD_EXCEPTION);
108    
109                            if (uploadException != null) {
110                                    if (uploadException.isExceededLiferayFileItemSizeLimit()) {
111                                            throw new LiferayFileItemException();
112                                    }
113                                    else if (uploadException.isExceededSizeLimit()) {
114                                            throw new FileSizeException(uploadException.getCause());
115                                    }
116    
117                                    throw new PortalException(uploadException.getCause());
118                            }
119                            else if (cmd.equals(Constants.ADD) ||
120                                             cmd.equals(Constants.UPDATE)) {
121    
122                                    Object[] returnValue = updateEntry(actionRequest);
123    
124                                    entry = (BlogsEntry)returnValue[0];
125                                    oldUrlTitle = ((String)returnValue[1]);
126                            }
127                            else if (cmd.equals(Constants.DELETE)) {
128                                    deleteEntries(actionRequest, false);
129                            }
130                            else if (cmd.equals(Constants.MOVE_TO_TRASH)) {
131                                    deleteEntries(actionRequest, true);
132                            }
133                            else if (cmd.equals(Constants.SUBSCRIBE)) {
134                                    subscribe(actionRequest);
135                            }
136                            else if (cmd.equals(Constants.RESTORE)) {
137                                    restoreEntries(actionRequest);
138                            }
139                            else if (cmd.equals(Constants.UNSUBSCRIBE)) {
140                                    unsubscribe(actionRequest);
141                            }
142                            else if (cmd.equals(Constants.UPDATE_CONTENT)) {
143                                    updateContent(actionRequest, actionResponse);
144    
145                                    return;
146                            }
147    
148                            String redirect = ParamUtil.getString(actionRequest, "redirect");
149                            boolean updateRedirect = false;
150    
151                            String portletId = HttpUtil.getParameter(redirect, "p_p_id", false);
152    
153                            if (Validator.isNotNull(oldUrlTitle)) {
154                                    String oldRedirectParam =
155                                            PortalUtil.getPortletNamespace(portletId) + "redirect";
156    
157                                    String oldRedirect = HttpUtil.getParameter(
158                                            redirect, oldRedirectParam, false);
159    
160                                    if (Validator.isNotNull(oldRedirect)) {
161                                            String newRedirect = HttpUtil.decodeURL(oldRedirect);
162    
163                                            newRedirect = StringUtil.replace(
164                                                    newRedirect, oldUrlTitle, entry.getUrlTitle());
165                                            newRedirect = StringUtil.replace(
166                                                    newRedirect, oldRedirectParam, "redirect");
167    
168                                            redirect = StringUtil.replace(
169                                                    redirect, oldRedirect, newRedirect);
170                                    }
171                                    else if (redirect.endsWith("/blogs/" + oldUrlTitle) ||
172                                                     redirect.contains("/blogs/" + oldUrlTitle + "?") ||
173                                                     redirect.contains("/blog/" + oldUrlTitle + "?")) {
174    
175                                            redirect = StringUtil.replace(
176                                                    redirect, oldUrlTitle, entry.getUrlTitle());
177                                    }
178    
179                                    updateRedirect = true;
180                            }
181    
182                            int workflowAction = ParamUtil.getInteger(
183                                    actionRequest, "workflowAction",
184                                    WorkflowConstants.ACTION_SAVE_DRAFT);
185    
186                            boolean ajax = ParamUtil.getBoolean(actionRequest, "ajax");
187    
188                            if (ajax) {
189                                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
190    
191                                    jsonObject.put("entryId", entry.getEntryId());
192                                    jsonObject.put("redirect", redirect);
193                                    jsonObject.put("updateRedirect", updateRedirect);
194    
195                                    writeJSON(actionRequest, actionResponse, jsonObject);
196    
197                                    return;
198                            }
199    
200                            if ((entry != null) &&
201                                    (workflowAction == WorkflowConstants.ACTION_SAVE_DRAFT)) {
202    
203                                    redirect = getSaveAndContinueRedirect(
204                                            portletConfig, actionRequest, entry, redirect);
205    
206                                    sendRedirect(actionRequest, actionResponse, redirect);
207                            }
208                            else {
209                                    WindowState windowState = actionRequest.getWindowState();
210    
211                                    if (!windowState.equals(LiferayWindowState.POP_UP)) {
212                                            sendRedirect(actionRequest, actionResponse, redirect);
213                                    }
214                                    else {
215                                            redirect = PortalUtil.escapeRedirect(redirect);
216    
217                                            if (Validator.isNotNull(redirect)) {
218                                                    if (cmd.equals(Constants.ADD) && (entry != null)) {
219                                                            String namespace = PortalUtil.getPortletNamespace(
220                                                                    portletId);
221    
222                                                            redirect = HttpUtil.addParameter(
223                                                                    redirect, namespace + "className",
224                                                                    BlogsEntry.class.getName());
225                                                            redirect = HttpUtil.addParameter(
226                                                                    redirect, namespace + "classPK",
227                                                                    entry.getEntryId());
228                                                    }
229    
230                                                    actionResponse.sendRedirect(redirect);
231                                            }
232                                    }
233                            }
234                    }
235                    catch (Exception e) {
236                            if (e instanceof NoSuchEntryException ||
237                                    e instanceof PrincipalException) {
238    
239                                    SessionErrors.add(actionRequest, e.getClass());
240    
241                                    setForward(actionRequest, "portlet.blogs.error");
242                            }
243                            else if (e instanceof EntryContentException ||
244                                             e instanceof EntryDisplayDateException ||
245                                             e instanceof EntrySmallImageNameException ||
246                                             e instanceof EntrySmallImageSizeException ||
247                                             e instanceof EntryTitleException ||
248                                             e instanceof LiferayFileItemException ||
249                                             e instanceof FileSizeException ||
250                                             e instanceof SanitizerException) {
251    
252                                    SessionErrors.add(actionRequest, e.getClass());
253                            }
254                            else if (e instanceof AssetCategoryException ||
255                                             e instanceof AssetTagException) {
256    
257                                    SessionErrors.add(actionRequest, e.getClass(), e);
258                            }
259                            else {
260                                    Throwable cause = e.getCause();
261    
262                                    if (cause instanceof SanitizerException) {
263                                            SessionErrors.add(actionRequest, SanitizerException.class);
264                                    }
265                                    else {
266                                            throw e;
267                                    }
268                            }
269                    }
270            }
271    
272            @Override
273            public ActionForward render(
274                            ActionMapping actionMapping, ActionForm actionForm,
275                            PortletConfig portletConfig, RenderRequest renderRequest,
276                            RenderResponse renderResponse)
277                    throws Exception {
278    
279                    try {
280                            ActionUtil.getEntry(renderRequest);
281    
282                            if (PropsValues.BLOGS_PINGBACK_ENABLED) {
283                                    BlogsEntry entry = (BlogsEntry)renderRequest.getAttribute(
284                                            WebKeys.BLOGS_ENTRY);
285    
286                                    if ((entry != null) && entry.isAllowPingbacks()) {
287                                            HttpServletResponse response =
288                                                    PortalUtil.getHttpServletResponse(renderResponse);
289    
290                                            response.addHeader(
291                                                    "X-Pingback",
292                                                    PortalUtil.getPortalURL(renderRequest) +
293                                                            "/xmlrpc/pingback");
294                                    }
295                            }
296                    }
297                    catch (Exception e) {
298                            if (e instanceof NoSuchEntryException ||
299                                    e instanceof PrincipalException) {
300    
301                                    SessionErrors.add(renderRequest, e.getClass());
302    
303                                    return actionMapping.findForward("portlet.blogs.error");
304                            }
305                            else {
306                                    throw e;
307                            }
308                    }
309    
310                    return actionMapping.findForward(
311                            getForward(renderRequest, "portlet.blogs.edit_entry"));
312            }
313    
314            protected void deleteEntries(
315                            ActionRequest actionRequest, boolean moveToTrash)
316                    throws Exception {
317    
318                    long[] deleteEntryIds = null;
319    
320                    long entryId = ParamUtil.getLong(actionRequest, "entryId");
321    
322                    if (entryId > 0) {
323                            deleteEntryIds = new long[] {entryId};
324                    }
325                    else {
326                            deleteEntryIds = StringUtil.split(
327                                    ParamUtil.getString(actionRequest, "deleteEntryIds"), 0L);
328                    }
329    
330                    String deleteEntryTitle = null;
331    
332                    for (int i = 0; i < deleteEntryIds.length; i++) {
333                            long deleteEntryId = deleteEntryIds[i];
334    
335                            if (moveToTrash) {
336                                    BlogsEntry entry = BlogsEntryServiceUtil.moveEntryToTrash(
337                                            deleteEntryId);
338    
339                                    if (i == 0) {
340                                            deleteEntryTitle = entry.getTitle();
341                                    }
342                            }
343                            else {
344                                    BlogsEntryServiceUtil.deleteEntry(deleteEntryId);
345                            }
346                    }
347    
348                    if (moveToTrash && (deleteEntryIds.length > 0)) {
349                            Map<String, String[]> data = new HashMap<String, String[]>();
350    
351                            data.put(
352                                    "deleteEntryClassName",
353                                    new String[] {BlogsEntry.class.getName()});
354    
355                            if (Validator.isNotNull(deleteEntryTitle)) {
356                                    data.put("deleteEntryTitle", new String[] {deleteEntryTitle});
357                            }
358    
359                            data.put(
360                                    "restoreEntryIds", ArrayUtil.toStringArray(deleteEntryIds));
361    
362                            SessionMessages.add(
363                                    actionRequest,
364                                    PortalUtil.getPortletId(actionRequest) +
365                                            SessionMessages.KEY_SUFFIX_DELETE_SUCCESS_DATA, data);
366    
367                            hideDefaultSuccessMessage(actionRequest);
368                    }
369            }
370    
371            protected String getSaveAndContinueRedirect(
372                            PortletConfig portletConfig, ActionRequest actionRequest,
373                            BlogsEntry entry, String redirect)
374                    throws Exception {
375    
376                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
377                            WebKeys.THEME_DISPLAY);
378    
379                    String backURL = ParamUtil.getString(actionRequest, "backURL");
380    
381                    boolean preview = ParamUtil.getBoolean(actionRequest, "preview");
382    
383                    PortletURLImpl portletURL = new PortletURLImpl(
384                            actionRequest, portletConfig.getPortletName(),
385                            themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
386    
387                    String portletName = portletConfig.getPortletName();
388    
389                    if (portletName.equals(PortletKeys.BLOGS_ADMIN)) {
390                            portletURL.setParameter("struts_action", "/blogs_admin/edit_entry");
391                    }
392                    else {
393                            portletURL.setParameter("struts_action", "/blogs/edit_entry");
394                    }
395    
396                    portletURL.setParameter(Constants.CMD, Constants.UPDATE, false);
397                    portletURL.setParameter("redirect", redirect, false);
398                    portletURL.setParameter("backURL", backURL, false);
399                    portletURL.setParameter(
400                            "groupId", String.valueOf(entry.getGroupId()), false);
401                    portletURL.setParameter(
402                            "entryId", String.valueOf(entry.getEntryId()), false);
403                    portletURL.setParameter("preview", String.valueOf(preview), false);
404                    portletURL.setWindowState(actionRequest.getWindowState());
405    
406                    return portletURL.toString();
407            }
408    
409            protected void restoreEntries(ActionRequest actionRequest)
410                    throws PortalException, SystemException {
411    
412                    long[] restoreEntryIds = StringUtil.split(
413                            ParamUtil.getString(actionRequest, "restoreEntryIds"), 0L);
414    
415                    for (long restoreEntryId : restoreEntryIds) {
416                            BlogsEntryServiceUtil.restoreEntryFromTrash(restoreEntryId);
417                    }
418            }
419    
420            protected void subscribe(ActionRequest actionRequest) throws Exception {
421                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
422                            WebKeys.THEME_DISPLAY);
423    
424                    BlogsEntryServiceUtil.subscribe(themeDisplay.getScopeGroupId());
425            }
426    
427            protected void unsubscribe(ActionRequest actionRequest) throws Exception {
428                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
429                            WebKeys.THEME_DISPLAY);
430    
431                    BlogsEntryServiceUtil.unsubscribe(themeDisplay.getScopeGroupId());
432            }
433    
434            protected void updateContent(
435                            ActionRequest actionRequest, ActionResponse actionResponse)
436                    throws Exception {
437    
438                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
439                            WebKeys.THEME_DISPLAY);
440    
441                    long entryId = ParamUtil.getLong(actionRequest, "entryId");
442    
443                    BlogsEntry entry = BlogsEntryLocalServiceUtil.getEntry(entryId);
444    
445                    String content = ParamUtil.getString(actionRequest, "content");
446    
447                    Calendar displayDateCal = CalendarFactoryUtil.getCalendar(
448                            themeDisplay.getTimeZone());
449    
450                    displayDateCal.setTime(entry.getDisplayDate());
451    
452                    int displayDateMonth = displayDateCal.get(Calendar.MONTH);
453                    int displayDateDay = displayDateCal.get(Calendar.DATE);
454                    int displayDateYear = displayDateCal.get(Calendar.YEAR);
455                    int displayDateHour = displayDateCal.get(Calendar.HOUR);
456                    int displayDateMinute = displayDateCal.get(Calendar.MINUTE);
457    
458                    if (displayDateCal.get(Calendar.AM_PM) == Calendar.PM) {
459                            displayDateHour += 12;
460                    }
461    
462                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
463                            actionRequest);
464    
465                    serviceContext.setCommand(Constants.UPDATE);
466    
467                    try {
468                            BlogsEntryServiceUtil.updateEntry(
469                                    entryId, entry.getTitle(), entry.getDescription(), content,
470                                    displayDateMonth, displayDateDay, displayDateYear,
471                                    displayDateHour, displayDateMinute, entry.getAllowPingbacks(),
472                                    entry.getAllowTrackbacks(), null, entry.getSmallImage(),
473                                    entry.getSmallImageURL(), null, null, serviceContext);
474    
475                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
476    
477                            jsonObject.put("success", Boolean.TRUE);
478    
479                            writeJSON(actionRequest, actionResponse, jsonObject);
480                    }
481                    catch (Exception e) {
482                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
483    
484                            jsonObject.put("success", Boolean.FALSE);
485    
486                            jsonObject.putException(e);
487    
488                            writeJSON(actionRequest, actionResponse, jsonObject);
489                    }
490            }
491    
492            protected Object[] updateEntry(ActionRequest actionRequest)
493                    throws Exception {
494    
495                    long entryId = ParamUtil.getLong(actionRequest, "entryId");
496    
497                    String title = ParamUtil.getString(actionRequest, "title");
498                    String description = ParamUtil.getString(actionRequest, "description");
499                    String content = ParamUtil.getString(actionRequest, "content");
500    
501                    int displayDateMonth = ParamUtil.getInteger(
502                            actionRequest, "displayDateMonth");
503                    int displayDateDay = ParamUtil.getInteger(
504                            actionRequest, "displayDateDay");
505                    int displayDateYear = ParamUtil.getInteger(
506                            actionRequest, "displayDateYear");
507                    int displayDateHour = ParamUtil.getInteger(
508                            actionRequest, "displayDateHour");
509                    int displayDateMinute = ParamUtil.getInteger(
510                            actionRequest, "displayDateMinute");
511                    int displayDateAmPm = ParamUtil.getInteger(
512                            actionRequest, "displayDateAmPm");
513    
514                    if (displayDateAmPm == Calendar.PM) {
515                            displayDateHour += 12;
516                    }
517    
518                    boolean allowPingbacks = ParamUtil.getBoolean(
519                            actionRequest, "allowPingbacks");
520                    boolean allowTrackbacks = ParamUtil.getBoolean(
521                            actionRequest, "allowTrackbacks");
522                    String[] trackbacks = StringUtil.split(
523                            ParamUtil.getString(actionRequest, "trackbacks"));
524    
525                    boolean smallImage = false;
526                    String smallImageURL = null;
527                    String smallImageFileName = null;
528                    InputStream smallImageInputStream = null;
529    
530                    BlogsEntry entry = null;
531                    String oldUrlTitle = null;
532    
533                    try {
534                            boolean ajax = ParamUtil.getBoolean(actionRequest, "ajax");
535    
536                            if (!ajax) {
537                                    smallImage = ParamUtil.getBoolean(actionRequest, "smallImage");
538                                    smallImageURL = ParamUtil.getString(
539                                            actionRequest, "smallImageURL");
540    
541                                    if (smallImage && Validator.isNull(smallImageURL)) {
542                                            UploadPortletRequest uploadPortletRequest =
543                                                    PortalUtil.getUploadPortletRequest(actionRequest);
544    
545                                            smallImageFileName = uploadPortletRequest.getFileName(
546                                                    "smallFile");
547                                            smallImageInputStream =
548                                                    uploadPortletRequest.getFileAsStream("smallFile");
549                                    }
550                            }
551    
552                            ServiceContext serviceContext = ServiceContextFactory.getInstance(
553                                    BlogsEntry.class.getName(), actionRequest);
554    
555                            entry = null;
556                            oldUrlTitle = StringPool.BLANK;
557    
558                            if (entryId <= 0) {
559    
560                                    // Add entry
561    
562                                    entry = BlogsEntryServiceUtil.addEntry(
563                                            title, description, content, displayDateMonth,
564                                            displayDateDay, displayDateYear, displayDateHour,
565                                            displayDateMinute, allowPingbacks, allowTrackbacks,
566                                            trackbacks, smallImage, smallImageURL, smallImageFileName,
567                                            smallImageInputStream, serviceContext);
568    
569                                    AssetPublisherUtil.addAndStoreSelection(
570                                            actionRequest, BlogsEntry.class.getName(),
571                                            entry.getEntryId(), -1);
572                            }
573                            else {
574    
575                                    // Update entry
576    
577                                    entry = BlogsEntryLocalServiceUtil.getEntry(entryId);
578    
579                                    String tempOldUrlTitle = entry.getUrlTitle();
580    
581                                    entry = BlogsEntryServiceUtil.updateEntry(
582                                            entryId, title, description, content, displayDateMonth,
583                                            displayDateDay, displayDateYear, displayDateHour,
584                                            displayDateMinute, allowPingbacks, allowTrackbacks,
585                                            trackbacks, smallImage, smallImageURL, smallImageFileName,
586                                            smallImageInputStream, serviceContext);
587    
588                                    if (!tempOldUrlTitle.equals(entry.getUrlTitle())) {
589                                            oldUrlTitle = tempOldUrlTitle;
590                                    }
591    
592                                    AssetPublisherUtil.addAndStoreSelection(
593                                            actionRequest, BlogsEntry.class.getName(),
594                                            entry.getEntryId(), -1);
595                            }
596                    }
597                    finally {
598                            StreamUtil.cleanUp(smallImageInputStream);
599                    }
600    
601                    return new Object[] {entry, oldUrlTitle};
602            }
603    
604    }