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