001: /**
002: * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a copy
005: * of this software and associated documentation files (the "Software"), to deal
006: * in the Software without restriction, including without limitation the rights
007: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is
009: * furnished to do so, subject to the following conditions:
010: *
011: * The above copyright notice and this permission notice shall be included in
012: * all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
020: * SOFTWARE.
021: */package com.liferay.portlet.journal.action;
022:
023: import com.liferay.portal.kernel.util.Constants;
024: import com.liferay.portal.kernel.util.GetterUtil;
025: import com.liferay.portal.kernel.util.ParamUtil;
026: import com.liferay.portal.kernel.util.StringPool;
027: import com.liferay.portal.kernel.util.StringUtil;
028: import com.liferay.portal.kernel.util.Validator;
029: import com.liferay.portal.model.Layout;
030: import com.liferay.portal.security.auth.PrincipalException;
031: import com.liferay.portal.struts.PortletAction;
032: import com.liferay.portal.theme.ThemeDisplay;
033: import com.liferay.portal.util.PortalUtil;
034: import com.liferay.portal.util.WebKeys;
035: import com.liferay.portlet.ActionRequestImpl;
036: import com.liferay.portlet.PortletPreferencesFactoryUtil;
037: import com.liferay.portlet.PortletURLImpl;
038: import com.liferay.portlet.journal.ArticleContentException;
039: import com.liferay.portlet.journal.ArticleDisplayDateException;
040: import com.liferay.portlet.journal.ArticleExpirationDateException;
041: import com.liferay.portlet.journal.ArticleIdException;
042: import com.liferay.portlet.journal.ArticleSmallImageNameException;
043: import com.liferay.portlet.journal.ArticleSmallImageSizeException;
044: import com.liferay.portlet.journal.ArticleTitleException;
045: import com.liferay.portlet.journal.ArticleTypeException;
046: import com.liferay.portlet.journal.DuplicateArticleIdException;
047: import com.liferay.portlet.journal.NoSuchArticleException;
048: import com.liferay.portlet.journal.NoSuchStructureException;
049: import com.liferay.portlet.journal.NoSuchTemplateException;
050: import com.liferay.portlet.journal.model.JournalArticle;
051: import com.liferay.portlet.journal.model.JournalStructure;
052: import com.liferay.portlet.journal.service.JournalArticleServiceUtil;
053: import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
054: import com.liferay.portlet.journal.service.JournalStructureLocalServiceUtil;
055: import com.liferay.portlet.journal.util.JournalUtil;
056: import com.liferay.portlet.taggedcontent.util.AssetPublisherUtil;
057: import com.liferay.portlet.tags.TagsEntryException;
058: import com.liferay.util.FileUtil;
059: import com.liferay.util.LocalizationUtil;
060: import com.liferay.util.servlet.SessionErrors;
061: import com.liferay.util.servlet.UploadPortletRequest;
062:
063: import java.io.File;
064:
065: import java.util.Calendar;
066: import java.util.Enumeration;
067: import java.util.HashMap;
068: import java.util.Map;
069:
070: import javax.portlet.ActionRequest;
071: import javax.portlet.ActionResponse;
072: import javax.portlet.PortletConfig;
073: import javax.portlet.PortletPreferences;
074: import javax.portlet.RenderRequest;
075: import javax.portlet.RenderResponse;
076: import javax.portlet.WindowState;
077:
078: import org.apache.struts.action.ActionForm;
079: import org.apache.struts.action.ActionForward;
080: import org.apache.struts.action.ActionMapping;
081:
082: /**
083: * <a href="EditArticleAction.java.html"><b><i>View Source</i></b></a>
084: *
085: * @author Brian Wing Shun Chan
086: *
087: */
088: public class EditArticleAction extends PortletAction {
089:
090: public static final String VERSION_SEPARATOR = "_version_";
091:
092: public void processAction(ActionMapping mapping, ActionForm form,
093: PortletConfig config, ActionRequest req, ActionResponse res)
094: throws Exception {
095:
096: String cmd = ParamUtil.getString(req, Constants.CMD);
097:
098: JournalArticle article = null;
099:
100: try {
101: if (cmd.equals(Constants.ADD)
102: || cmd.equals(Constants.UPDATE)) {
103: article = updateArticle(req);
104: } else if (cmd.equals(Constants.APPROVE)) {
105: approveArticle(req);
106: } else if (cmd.equals(Constants.DELETE)) {
107: deleteArticles(req);
108: } else if (cmd.equals(Constants.EXPIRE)) {
109: expireArticles(req);
110: } else if (cmd.equals("removeArticlesLocale")) {
111: removeArticlesLocale(req);
112: }
113:
114: if (Validator.isNotNull(cmd)) {
115: String redirect = ParamUtil.getString(req, "redirect");
116:
117: if (article != null) {
118: boolean saveAndContinue = ParamUtil.getBoolean(req,
119: "saveAndContinue");
120:
121: if (saveAndContinue) {
122: redirect = getSaveAndContinueRedirect(config,
123: req, article, redirect);
124: }
125: }
126:
127: sendRedirect(req, res, redirect);
128: }
129: } catch (Exception e) {
130: if (e instanceof NoSuchArticleException
131: || e instanceof NoSuchStructureException
132: || e instanceof NoSuchTemplateException
133: || e instanceof PrincipalException) {
134:
135: SessionErrors.add(req, e.getClass().getName());
136:
137: setForward(req, "portlet.journal.error");
138: } else if (e instanceof ArticleContentException
139: || e instanceof ArticleDisplayDateException
140: || e instanceof ArticleExpirationDateException
141: || e instanceof ArticleIdException
142: || e instanceof ArticleSmallImageNameException
143: || e instanceof ArticleSmallImageSizeException
144: || e instanceof ArticleTitleException
145: || e instanceof ArticleTypeException
146: || e instanceof DuplicateArticleIdException) {
147:
148: SessionErrors.add(req, e.getClass().getName());
149: } else if (e instanceof TagsEntryException) {
150: SessionErrors.add(req, e.getClass().getName(), e);
151: } else {
152: throw e;
153: }
154: }
155: }
156:
157: public ActionForward render(ActionMapping mapping, ActionForm form,
158: PortletConfig config, RenderRequest req, RenderResponse res)
159: throws Exception {
160:
161: try {
162: String cmd = ParamUtil.getString(req, Constants.CMD);
163:
164: if (!cmd.equals(Constants.ADD)) {
165: ActionUtil.getArticle(req);
166: }
167: } catch (NoSuchArticleException nsse) {
168:
169: // Let this slide because the user can manually input a article id
170: // for a new article that does not yet exist.
171:
172: } catch (Exception e) {
173: if (//e instanceof NoSuchArticleException ||
174: e instanceof PrincipalException) {
175:
176: SessionErrors.add(req, e.getClass().getName());
177:
178: return mapping.findForward("portlet.journal.error");
179: } else {
180: throw e;
181: }
182: }
183:
184: return mapping.findForward(getForward(req,
185: "portlet.journal.edit_article"));
186: }
187:
188: protected void approveArticle(ActionRequest req) throws Exception {
189: Layout layout = (Layout) req.getAttribute(WebKeys.LAYOUT);
190:
191: long groupId = ParamUtil.getLong(req, "groupId");
192: String articleId = ParamUtil.getString(req, "articleId");
193: double version = ParamUtil.getDouble(req, "version");
194:
195: String articleURL = ParamUtil.getString(req, "articleURL");
196:
197: JournalArticleServiceUtil.approveArticle(groupId, articleId,
198: version, layout.getPlid(), articleURL, req
199: .getPreferences());
200: }
201:
202: protected void deleteArticles(ActionRequest req) throws Exception {
203: long groupId = ParamUtil.getLong(req, "groupId");
204:
205: String[] deleteArticleIds = StringUtil.split(ParamUtil
206: .getString(req, "deleteArticleIds"));
207:
208: for (int i = 0; i < deleteArticleIds.length; i++) {
209: int pos = deleteArticleIds[i]
210: .lastIndexOf(VERSION_SEPARATOR);
211:
212: String articleId = deleteArticleIds[i].substring(0, pos);
213: double version = GetterUtil.getDouble(deleteArticleIds[i]
214: .substring(pos + VERSION_SEPARATOR.length()));
215:
216: JournalArticleServiceUtil.deleteArticle(groupId, articleId,
217: version, null, null);
218:
219: JournalUtil.removeRecentArticle(req, deleteArticleIds[i]);
220: }
221: }
222:
223: protected void expireArticles(ActionRequest req) throws Exception {
224: long groupId = ParamUtil.getLong(req, "groupId");
225:
226: String[] expireArticleIds = StringUtil.split(ParamUtil
227: .getString(req, "expireArticleIds"));
228:
229: for (int i = 0; i < expireArticleIds.length; i++) {
230: int pos = expireArticleIds[i]
231: .lastIndexOf(VERSION_SEPARATOR);
232:
233: String articleId = expireArticleIds[i].substring(0, pos);
234: double version = GetterUtil.getDouble(expireArticleIds[i]
235: .substring(pos + VERSION_SEPARATOR.length()));
236:
237: JournalArticleServiceUtil.expireArticle(groupId, articleId,
238: version, null, null);
239: }
240: }
241:
242: protected Map getImages(UploadPortletRequest uploadReq)
243: throws Exception {
244: Map images = new HashMap();
245:
246: String imagePrefix = "structure_image_";
247:
248: Enumeration enu = uploadReq.getParameterNames();
249:
250: while (enu.hasMoreElements()) {
251: String name = (String) enu.nextElement();
252:
253: if (name.startsWith(imagePrefix)) {
254: File file = uploadReq.getFile(name);
255: byte[] bytes = FileUtil.getBytes(file);
256:
257: if ((bytes != null) && (bytes.length > 0)) {
258: name = name.substring(imagePrefix.length(), name
259: .length());
260:
261: images.put(name, bytes);
262: }
263: }
264: }
265:
266: return images;
267: }
268:
269: protected String getSaveAndContinueRedirect(PortletConfig config,
270: ActionRequest req, JournalArticle article, String redirect)
271: throws Exception {
272:
273: ThemeDisplay themeDisplay = (ThemeDisplay) req
274: .getAttribute(WebKeys.THEME_DISPLAY);
275:
276: String originalRedirect = ParamUtil.getString(req,
277: "originalRedirect");
278:
279: PortletURLImpl portletURL = new PortletURLImpl(
280: (ActionRequestImpl) req, config.getPortletName(),
281: themeDisplay.getPlid(), false);
282:
283: portletURL.setWindowState(WindowState.MAXIMIZED);
284:
285: portletURL.setParameter("struts_action",
286: "/journal/edit_article");
287: portletURL.setParameter(Constants.CMD, Constants.UPDATE, false);
288: portletURL.setParameter("redirect", redirect, false);
289: portletURL.setParameter("originalRedirect", originalRedirect,
290: false);
291: portletURL.setParameter("groupId", String.valueOf(article
292: .getGroupId()), false);
293: portletURL.setParameter("articleId", article.getArticleId(),
294: false);
295: portletURL.setParameter("version", String.valueOf(article
296: .getVersion()), false);
297:
298: return portletURL.toString();
299: }
300:
301: protected void removeArticlesLocale(ActionRequest req)
302: throws Exception {
303: long groupId = ParamUtil.getLong(req, "groupId");
304:
305: String[] removeArticleLocaleIds = StringUtil.split(ParamUtil
306: .getString(req, "deleteArticleIds"));
307:
308: for (int i = 0; i < removeArticleLocaleIds.length; i++) {
309: int pos = removeArticleLocaleIds[i]
310: .lastIndexOf(VERSION_SEPARATOR);
311:
312: String articleId = removeArticleLocaleIds[i].substring(0,
313: pos);
314: double version = GetterUtil
315: .getDouble(removeArticleLocaleIds[i].substring(pos
316: + VERSION_SEPARATOR.length()));
317: String languageId = ParamUtil.getString(req, "languageId");
318:
319: JournalArticleServiceUtil.removeArticleLocale(groupId,
320: articleId, version, languageId);
321: }
322: }
323:
324: protected JournalArticle updateArticle(ActionRequest req)
325: throws Exception {
326: UploadPortletRequest uploadReq = PortalUtil
327: .getUploadPortletRequest(req);
328:
329: String cmd = ParamUtil.getString(uploadReq, Constants.CMD);
330:
331: Layout layout = (Layout) uploadReq.getAttribute(WebKeys.LAYOUT);
332:
333: long groupId = ParamUtil.getLong(uploadReq, "groupId");
334:
335: String articleId = ParamUtil.getString(uploadReq, "articleId");
336: boolean autoArticleId = ParamUtil.getBoolean(uploadReq,
337: "autoArticleId");
338:
339: double version = ParamUtil.getDouble(uploadReq, "version");
340: boolean incrementVersion = ParamUtil.getBoolean(uploadReq,
341: "incrementVersion");
342:
343: String title = ParamUtil.getString(uploadReq, "title");
344: String description = ParamUtil.getString(uploadReq,
345: "description");
346: String content = ParamUtil.getString(uploadReq, "content");
347: String type = ParamUtil.getString(uploadReq, "type");
348: String structureId = ParamUtil.getString(uploadReq,
349: "structureId");
350: String templateId = ParamUtil
351: .getString(uploadReq, "templateId");
352:
353: String lastLanguageId = ParamUtil.getString(uploadReq,
354: "lastLanguageId");
355: String defaultLanguageId = ParamUtil.getString(uploadReq,
356: "defaultLanguageId");
357:
358: int displayDateMonth = ParamUtil.getInteger(uploadReq,
359: "displayDateMonth");
360: int displayDateDay = ParamUtil.getInteger(uploadReq,
361: "displayDateDay");
362: int displayDateYear = ParamUtil.getInteger(uploadReq,
363: "displayDateYear");
364: int displayDateHour = ParamUtil.getInteger(uploadReq,
365: "displayDateHour");
366: int displayDateMinute = ParamUtil.getInteger(uploadReq,
367: "displayDateMinute");
368: int displayDateAmPm = ParamUtil.getInteger(uploadReq,
369: "displayDateAmPm");
370:
371: if (displayDateAmPm == Calendar.PM) {
372: displayDateHour += 12;
373: }
374:
375: int expirationDateMonth = ParamUtil.getInteger(uploadReq,
376: "expirationDateMonth");
377: int expirationDateDay = ParamUtil.getInteger(uploadReq,
378: "expirationDateDay");
379: int expirationDateYear = ParamUtil.getInteger(uploadReq,
380: "expirationDateYear");
381: int expirationDateHour = ParamUtil.getInteger(uploadReq,
382: "expirationDateHour");
383: int expirationDateMinute = ParamUtil.getInteger(uploadReq,
384: "expirationDateMinute");
385: int expirationDateAmPm = ParamUtil.getInteger(uploadReq,
386: "expirationDateAmPm");
387: boolean neverExpire = ParamUtil.getBoolean(uploadReq,
388: "neverExpire");
389:
390: if (expirationDateAmPm == Calendar.PM) {
391: expirationDateHour += 12;
392: }
393:
394: int reviewDateMonth = ParamUtil.getInteger(uploadReq,
395: "reviewDateMonth");
396: int reviewDateDay = ParamUtil.getInteger(uploadReq,
397: "reviewDateDay");
398: int reviewDateYear = ParamUtil.getInteger(uploadReq,
399: "reviewDateYear");
400: int reviewDateHour = ParamUtil.getInteger(uploadReq,
401: "reviewDateHour");
402: int reviewDateMinute = ParamUtil.getInteger(uploadReq,
403: "reviewDateMinute");
404: int reviewDateAmPm = ParamUtil.getInteger(uploadReq,
405: "reviewDateAmPm");
406: boolean neverReview = ParamUtil.getBoolean(uploadReq,
407: "neverReview");
408:
409: if (reviewDateAmPm == Calendar.PM) {
410: reviewDateHour += 12;
411: }
412:
413: boolean indexable = ParamUtil
414: .getBoolean(uploadReq, "indexable");
415:
416: boolean smallImage = ParamUtil.getBoolean(uploadReq,
417: "smallImage");
418: String smallImageURL = ParamUtil.getString(uploadReq,
419: "smallImageURL");
420: File smallFile = uploadReq.getFile("smallFile");
421:
422: Map images = getImages(uploadReq);
423:
424: String articleURL = ParamUtil
425: .getString(uploadReq, "articleURL");
426:
427: String[] tagsEntries = StringUtil.split(ParamUtil.getString(
428: uploadReq, "tagsEntries"));
429:
430: String[] communityPermissions = uploadReq
431: .getParameterValues("communityPermissions");
432: String[] guestPermissions = uploadReq
433: .getParameterValues("guestPermissions");
434:
435: boolean approve = ParamUtil.getBoolean(uploadReq, "approve");
436:
437: JournalArticle article = null;
438:
439: if (cmd.equals(Constants.ADD)) {
440: if (Validator.isNull(structureId)) {
441: content = LocalizationUtil.updateLocalization(
442: StringPool.BLANK, "static-content", content,
443: lastLanguageId, defaultLanguageId, true);
444: }
445:
446: // Add article
447:
448: article = JournalArticleServiceUtil.addArticle(articleId,
449: autoArticleId, layout.getPlid(), title,
450: description, content, type, structureId,
451: templateId, displayDateMonth, displayDateDay,
452: displayDateYear, displayDateHour,
453: displayDateMinute, expirationDateMonth,
454: expirationDateDay, expirationDateYear,
455: expirationDateHour, expirationDateMinute,
456: neverExpire, reviewDateMonth, reviewDateDay,
457: reviewDateYear, reviewDateHour, reviewDateMinute,
458: neverReview, indexable, smallImage, smallImageURL,
459: smallFile, images, articleURL,
460: req.getPreferences(), tagsEntries,
461: communityPermissions, guestPermissions);
462:
463: AssetPublisherUtil.addAndStoreSelection(req,
464: JournalArticle.class.getName(), article
465: .getPrimaryKey(), -1);
466: } else {
467:
468: // Merge current content with new content
469:
470: JournalArticle curArticle = JournalArticleServiceUtil
471: .getArticle(groupId, articleId, version);
472:
473: if (Validator.isNull(structureId)) {
474: if (!curArticle.isTemplateDriven()) {
475: content = LocalizationUtil.updateLocalization(
476: curArticle.getContent(), "static-content",
477: content, lastLanguageId, defaultLanguageId,
478: true);
479: }
480: } else {
481: if (curArticle.isTemplateDriven()) {
482: JournalStructure structure = JournalStructureLocalServiceUtil
483: .getStructure(groupId, structureId);
484:
485: content = JournalUtil.mergeLocaleContent(curArticle
486: .getContent(), content, structure.getXsd());
487: content = JournalUtil.removeOldContent(content,
488: structure.getXsd());
489: }
490: }
491:
492: // Update article
493:
494: article = JournalArticleServiceUtil.updateArticle(groupId,
495: articleId, version, incrementVersion, title,
496: description, content, type, structureId,
497: templateId, displayDateMonth, displayDateDay,
498: displayDateYear, displayDateHour,
499: displayDateMinute, expirationDateMonth,
500: expirationDateDay, expirationDateYear,
501: expirationDateHour, expirationDateMinute,
502: neverExpire, reviewDateMonth, reviewDateDay,
503: reviewDateYear, reviewDateHour, reviewDateMinute,
504: neverReview, indexable, smallImage, smallImageURL,
505: smallFile, images, articleURL,
506: req.getPreferences(), tagsEntries);
507: }
508:
509: if (approve) {
510: article = JournalArticleServiceUtil.approveArticle(article
511: .getGroupId(), article.getArticleId(), article
512: .getVersion(), layout.getPlid(), articleURL, req
513: .getPreferences());
514: }
515:
516: // Recent articles
517:
518: JournalUtil.addRecentArticle(req, article);
519:
520: // Journal content
521:
522: String portletResource = ParamUtil.getString(uploadReq,
523: "portletResource");
524:
525: if (Validator.isNotNull(portletResource)) {
526: PortletPreferences prefs = PortletPreferencesFactoryUtil
527: .getPortletSetup(uploadReq, portletResource, true,
528: true);
529:
530: prefs.setValue("group-id", String.valueOf(article
531: .getGroupId()));
532: prefs.setValue("article-id", article.getArticleId());
533:
534: prefs.store();
535:
536: updateContentSearch(req, portletResource, article
537: .getArticleId());
538: }
539:
540: return article;
541: }
542:
543: protected void updateContentSearch(ActionRequest req,
544: String portletResource, String articleId) throws Exception {
545:
546: ThemeDisplay themeDisplay = (ThemeDisplay) req
547: .getAttribute(WebKeys.THEME_DISPLAY);
548:
549: Layout layout = themeDisplay.getLayout();
550:
551: JournalContentSearchLocalServiceUtil.updateContentSearch(layout
552: .getGroupId(), layout.isPrivateLayout(), layout
553: .getLayoutId(), portletResource, articleId);
554: }
555:
556: }
|