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