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