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.wiki.action;
016    
017    import com.liferay.portal.kernel.sanitizer.SanitizerException;
018    import com.liferay.portal.kernel.servlet.SessionErrors;
019    import com.liferay.portal.kernel.util.Constants;
020    import com.liferay.portal.kernel.util.ParamUtil;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.portal.kernel.workflow.WorkflowConstants;
025    import com.liferay.portal.model.Layout;
026    import com.liferay.portal.security.auth.PrincipalException;
027    import com.liferay.portal.service.ServiceContext;
028    import com.liferay.portal.service.ServiceContextFactory;
029    import com.liferay.portal.struts.PortletAction;
030    import com.liferay.portal.struts.StrutsActionPortletURL;
031    import com.liferay.portal.theme.ThemeDisplay;
032    import com.liferay.portal.util.WebKeys;
033    import com.liferay.portlet.PortletResponseImpl;
034    import com.liferay.portlet.PortletURLImpl;
035    import com.liferay.portlet.asset.AssetCategoryException;
036    import com.liferay.portlet.asset.AssetTagException;
037    import com.liferay.portlet.trash.model.TrashEntry;
038    import com.liferay.portlet.trash.service.TrashEntryLocalServiceUtil;
039    import com.liferay.portlet.trash.service.TrashEntryServiceUtil;
040    import com.liferay.portlet.trash.util.TrashUtil;
041    import com.liferay.portlet.wiki.DuplicatePageException;
042    import com.liferay.portlet.wiki.NoSuchNodeException;
043    import com.liferay.portlet.wiki.NoSuchPageException;
044    import com.liferay.portlet.wiki.PageContentException;
045    import com.liferay.portlet.wiki.PageTitleException;
046    import com.liferay.portlet.wiki.PageVersionException;
047    import com.liferay.portlet.wiki.model.WikiNode;
048    import com.liferay.portlet.wiki.model.WikiPage;
049    import com.liferay.portlet.wiki.model.WikiPageConstants;
050    import com.liferay.portlet.wiki.model.WikiPageResource;
051    import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
052    import com.liferay.portlet.wiki.service.WikiPageResourceLocalServiceUtil;
053    import com.liferay.portlet.wiki.service.WikiPageServiceUtil;
054    
055    import javax.portlet.ActionRequest;
056    import javax.portlet.ActionResponse;
057    import javax.portlet.PortletConfig;
058    import javax.portlet.PortletRequest;
059    import javax.portlet.RenderRequest;
060    import javax.portlet.RenderResponse;
061    
062    import org.apache.struts.action.ActionForm;
063    import org.apache.struts.action.ActionForward;
064    import org.apache.struts.action.ActionMapping;
065    
066    /**
067     * @author Brian Wing Shun Chan
068     * @author Jorge Ferrer
069     */
070    public class EditPageAction extends PortletAction {
071    
072            @Override
073            public void processAction(
074                            ActionMapping actionMapping, ActionForm actionForm,
075                            PortletConfig portletConfig, ActionRequest actionRequest,
076                            ActionResponse actionResponse)
077                    throws Exception {
078    
079                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
080    
081                    WikiPage page = null;
082    
083                    try {
084                            if (cmd.equals(Constants.ADD) || cmd.equals(Constants.UPDATE)) {
085                                    page = updatePage(actionRequest);
086                            }
087                            else if (cmd.equals(Constants.DELETE)) {
088                                    deletePage(actionRequest, false);
089                            }
090                            else if (cmd.equals(Constants.MOVE_TO_TRASH)) {
091                                    deletePage(actionRequest, true);
092                            }
093                            else if (cmd.equals(Constants.RESTORE)) {
094                                    restorePage(actionRequest);
095                            }
096                            else if (cmd.equals(Constants.REVERT)) {
097                                    revertPage(actionRequest);
098                            }
099                            else if (cmd.equals(Constants.SUBSCRIBE)) {
100                                    subscribePage(actionRequest);
101                            }
102                            else if (cmd.equals(Constants.UNSUBSCRIBE)) {
103                                    unsubscribePage(actionRequest);
104                            }
105    
106                            if (Validator.isNotNull(cmd)) {
107                                    String redirect = ParamUtil.getString(
108                                            actionRequest, "redirect");
109    
110                                    int workflowAction = ParamUtil.getInteger(
111                                            actionRequest, "workflowAction",
112                                            WorkflowConstants.ACTION_PUBLISH);
113    
114                                    if (page != null) {
115                                            if (workflowAction == WorkflowConstants.ACTION_SAVE_DRAFT) {
116                                                    redirect = getSaveAndContinueRedirect(
117                                                            actionRequest, actionResponse, page, redirect);
118                                            }
119                                            else if (redirect.endsWith("title=")) {
120                                                    redirect += page.getTitle();
121                                            }
122                                    }
123    
124                                    sendRedirect(actionRequest, actionResponse, redirect);
125                            }
126                    }
127                    catch (Exception e) {
128                            if (e instanceof NoSuchNodeException ||
129                                    e instanceof NoSuchPageException ||
130                                    e instanceof PrincipalException) {
131    
132                                    SessionErrors.add(actionRequest, e.getClass());
133    
134                                    setForward(actionRequest, "portlet.wiki.error");
135                            }
136                            else if (e instanceof DuplicatePageException ||
137                                             e instanceof PageContentException ||
138                                             e instanceof PageVersionException ||
139                                             e instanceof PageTitleException ||
140                                             e instanceof SanitizerException) {
141    
142                                    SessionErrors.add(actionRequest, e.getClass());
143                            }
144                            else if (e instanceof AssetCategoryException ||
145                                             e instanceof AssetTagException) {
146    
147                                    SessionErrors.add(actionRequest, e.getClass(), e);
148                            }
149                            else {
150                                    Throwable cause = e.getCause();
151    
152                                    if (cause instanceof SanitizerException) {
153                                            SessionErrors.add(actionRequest, SanitizerException.class);
154                                    }
155                                    else {
156                                            throw e;
157                                    }
158                            }
159                    }
160            }
161    
162            @Override
163            public ActionForward render(
164                            ActionMapping actionMapping, ActionForm actionForm,
165                            PortletConfig portletConfig, RenderRequest renderRequest,
166                            RenderResponse renderResponse)
167                    throws Exception {
168    
169                    try {
170                            ActionUtil.getNode(renderRequest);
171    
172                            if (!SessionErrors.contains(
173                                            renderRequest, DuplicatePageException.class.getName())) {
174    
175                                    getPage(renderRequest);
176                            }
177                    }
178                    catch (Exception e) {
179                            if (e instanceof NoSuchNodeException ||
180                                    e instanceof PageTitleException ||
181                                    e instanceof PrincipalException) {
182    
183                                    SessionErrors.add(renderRequest, e.getClass());
184    
185                                    return actionMapping.findForward("portlet.wiki.error");
186                            }
187                            else if (e instanceof NoSuchPageException) {
188    
189                                    // Let edit_page.jsp handle this case
190    
191                            }
192                            else {
193                                    throw e;
194                            }
195                    }
196    
197                    return actionMapping.findForward(
198                            getForward(renderRequest, "portlet.wiki.edit_page"));
199            }
200    
201            protected void deletePage(ActionRequest actionRequest, boolean moveToTrash)
202                    throws Exception {
203    
204                    long nodeId = ParamUtil.getLong(actionRequest, "nodeId");
205                    String title = ParamUtil.getString(actionRequest, "title");
206                    double version = ParamUtil.getDouble(actionRequest, "version");
207    
208                    WikiPage wikiPage = null;
209    
210                    if (moveToTrash) {
211                            if (version > 0) {
212                                    wikiPage = WikiPageServiceUtil.movePageToTrash(
213                                            nodeId, title, version);
214                            }
215                            else {
216                                    wikiPage = WikiPageServiceUtil.movePageToTrash(nodeId, title);
217                            }
218                    }
219                    else {
220                            if (version > 0) {
221                                    WikiPageServiceUtil.discardDraft(nodeId, title, version);
222                            }
223                            else {
224                                    WikiPageServiceUtil.deletePage(nodeId, title);
225                            }
226                    }
227    
228                    if (moveToTrash && (wikiPage != null)) {
229                            TrashUtil.addTrashSessionMessages(actionRequest, wikiPage);
230    
231                            hideDefaultSuccessMessage(actionRequest);
232                    }
233            }
234    
235            protected void getPage(RenderRequest renderRequest) throws Exception {
236                    long nodeId = ParamUtil.getLong(renderRequest, "nodeId");
237                    String title = ParamUtil.getString(renderRequest, "title");
238                    double version = ParamUtil.getDouble(renderRequest, "version");
239                    boolean removeRedirect = ParamUtil.getBoolean(
240                            renderRequest, "removeRedirect");
241    
242                    if (nodeId == 0) {
243                            WikiNode node = (WikiNode)renderRequest.getAttribute(
244                                    WebKeys.WIKI_NODE);
245    
246                            if (node != null) {
247                                    nodeId = node.getNodeId();
248                            }
249                    }
250    
251                    WikiPage page = null;
252    
253                    if (Validator.isNull(title)) {
254                            renderRequest.setAttribute(WebKeys.WIKI_PAGE, page);
255    
256                            return;
257                    }
258    
259                    try {
260                            if (version == 0) {
261                                    page = WikiPageServiceUtil.getPage(nodeId, title, null);
262                            }
263                            else {
264                                    page = WikiPageServiceUtil.getPage(nodeId, title, version);
265                            }
266                    }
267                    catch (NoSuchPageException nspe1) {
268                            try {
269                                    page = WikiPageServiceUtil.getPage(nodeId, title, false);
270                            }
271                            catch (NoSuchPageException nspe2) {
272                                    if (title.equals(WikiPageConstants.FRONT_PAGE) &&
273                                            (version == 0)) {
274    
275                                            ServiceContext serviceContext = new ServiceContext();
276    
277                                            page = WikiPageServiceUtil.addPage(
278                                                    nodeId, title, null, WikiPageConstants.NEW, true,
279                                                    serviceContext);
280                                    }
281                                    else {
282                                            throw nspe2;
283                                    }
284                            }
285                    }
286    
287                    if (removeRedirect) {
288                            page.setContent(StringPool.BLANK);
289                            page.setRedirectTitle(StringPool.BLANK);
290                    }
291    
292                    renderRequest.setAttribute(WebKeys.WIKI_PAGE, page);
293            }
294    
295            protected String getSaveAndContinueRedirect(
296                            ActionRequest actionRequest, ActionResponse actionResponse,
297                            WikiPage page, String redirect)
298                    throws Exception {
299    
300                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
301                            WebKeys.THEME_DISPLAY);
302    
303                    Layout layout = themeDisplay.getLayout();
304    
305                    PortletURLImpl portletURL = new StrutsActionPortletURL(
306                            (PortletResponseImpl)actionResponse, themeDisplay.getPlid(),
307                            PortletRequest.RENDER_PHASE);
308    
309                    portletURL.setParameter("struts_action", "/wiki/edit_page");
310                    portletURL.setParameter(Constants.CMD, Constants.UPDATE, false);
311                    portletURL.setParameter("redirect", redirect, false);
312                    portletURL.setParameter(
313                            "groupId", String.valueOf(layout.getGroupId()), false);
314                    portletURL.setParameter(
315                            "nodeId", String.valueOf(page.getNodeId()), false);
316                    portletURL.setParameter("title", page.getTitle(), false);
317                    portletURL.setWindowState(actionRequest.getWindowState());
318    
319                    return portletURL.toString();
320            }
321    
322            @Override
323            protected boolean isCheckMethodOnProcessAction() {
324                    return _CHECK_METHOD_ON_PROCESS_ACTION;
325            }
326    
327            protected void restorePage(ActionRequest actionRequest) throws Exception {
328                    long[] restoreEntryIds = StringUtil.split(
329                            ParamUtil.getString(actionRequest, "restoreTrashEntryIds"), 0L);
330    
331                    for (long restoreEntryId : restoreEntryIds) {
332                            long overridePageResourcePrimKey = 0;
333    
334                            TrashEntry trashEntry = TrashEntryLocalServiceUtil.getTrashEntry(
335                                    restoreEntryId);
336    
337                            WikiPageResource pageResource =
338                                    WikiPageResourceLocalServiceUtil.getPageResource(
339                                            trashEntry.getClassPK());
340    
341                            String title = TrashUtil.getOriginalTitle(pageResource.getTitle());
342    
343                            if (title.equals(WikiPageConstants.FRONT_PAGE)) {
344                                    WikiPage overridePage = WikiPageLocalServiceUtil.fetchPage(
345                                            pageResource.getNodeId(), WikiPageConstants.FRONT_PAGE);
346    
347                                    if (overridePage != null) {
348                                            overridePageResourcePrimKey =
349                                                    overridePage.getResourcePrimKey();
350                                    }
351                            }
352    
353                            TrashEntryServiceUtil.restoreEntry(
354                                    restoreEntryId, overridePageResourcePrimKey, null);
355                    }
356            }
357    
358            protected void revertPage(ActionRequest actionRequest) throws Exception {
359                    long nodeId = ParamUtil.getLong(actionRequest, "nodeId");
360                    String title = ParamUtil.getString(actionRequest, "title");
361                    double version = ParamUtil.getDouble(actionRequest, "version");
362    
363                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
364                            WikiPage.class.getName(), actionRequest);
365    
366                    WikiPageServiceUtil.revertPage(nodeId, title, version, serviceContext);
367            }
368    
369            protected void subscribePage(ActionRequest actionRequest) throws Exception {
370                    long nodeId = ParamUtil.getLong(actionRequest, "nodeId");
371                    String title = ParamUtil.getString(actionRequest, "title");
372    
373                    WikiPageServiceUtil.subscribePage(nodeId, title);
374            }
375    
376            protected void unsubscribePage(ActionRequest actionRequest)
377                    throws Exception {
378    
379                    long nodeId = ParamUtil.getLong(actionRequest, "nodeId");
380                    String title = ParamUtil.getString(actionRequest, "title");
381    
382                    WikiPageServiceUtil.unsubscribePage(nodeId, title);
383            }
384    
385            protected WikiPage updatePage(ActionRequest actionRequest)
386                    throws Exception {
387    
388                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
389    
390                    long nodeId = ParamUtil.getLong(actionRequest, "nodeId");
391                    String title = ParamUtil.getString(actionRequest, "title");
392                    double version = ParamUtil.getDouble(actionRequest, "version");
393    
394                    String content = ParamUtil.getString(actionRequest, "content");
395                    String summary = ParamUtil.getString(actionRequest, "summary");
396                    boolean minorEdit = ParamUtil.getBoolean(actionRequest, "minorEdit");
397                    String format = ParamUtil.getString(actionRequest, "format");
398                    String parentTitle = ParamUtil.getString(actionRequest, "parentTitle");
399                    String redirectTitle = null;
400                    boolean copyPageAttachments = ParamUtil.getBoolean(
401                            actionRequest, "copyPageAttachments");
402    
403                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
404                            WikiPage.class.getName(), actionRequest);
405    
406                    WikiPage page = null;
407    
408                    if (cmd.equals(Constants.UPDATE)) {
409                            page = WikiPageServiceUtil.updatePage(
410                                    nodeId, title, version, content, summary, minorEdit, format,
411                                    parentTitle, redirectTitle, serviceContext);
412                    }
413                    else {
414                            page = WikiPageServiceUtil.addPage(
415                                    nodeId, title, content, summary, minorEdit, format, parentTitle,
416                                    redirectTitle, serviceContext);
417    
418                            if (copyPageAttachments) {
419                                    long templateNodeId = ParamUtil.getLong(
420                                            actionRequest, "templateNodeId");
421                                    String templateTitle = ParamUtil.getString(
422                                            actionRequest, "templateTitle");
423    
424                                    WikiPageServiceUtil.copyPageAttachments(
425                                            templateNodeId, templateTitle, page.getNodeId(),
426                                            page.getTitle());
427                            }
428                    }
429    
430                    return page;
431            }
432    
433            private static final boolean _CHECK_METHOD_ON_PROCESS_ACTION = false;
434    
435    }