1
14
15 package com.liferay.portlet.journal.action;
16
17 import com.liferay.portal.kernel.servlet.SessionErrors;
18 import com.liferay.portal.kernel.upload.UploadPortletRequest;
19 import com.liferay.portal.kernel.util.Constants;
20 import com.liferay.portal.kernel.util.FileUtil;
21 import com.liferay.portal.kernel.util.GetterUtil;
22 import com.liferay.portal.kernel.util.LocalizationUtil;
23 import com.liferay.portal.kernel.util.ParamUtil;
24 import com.liferay.portal.kernel.util.StringPool;
25 import com.liferay.portal.kernel.util.StringUtil;
26 import com.liferay.portal.kernel.util.Validator;
27 import com.liferay.portal.kernel.workflow.WorkflowConstants;
28 import com.liferay.portal.model.Layout;
29 import com.liferay.portal.security.auth.PrincipalException;
30 import com.liferay.portal.security.permission.ActionKeys;
31 import com.liferay.portal.security.permission.PermissionChecker;
32 import com.liferay.portal.service.ServiceContext;
33 import com.liferay.portal.service.ServiceContextFactory;
34 import com.liferay.portal.service.SubscriptionLocalServiceUtil;
35 import com.liferay.portal.struts.PortletAction;
36 import com.liferay.portal.theme.ThemeDisplay;
37 import com.liferay.portal.util.PortalUtil;
38 import com.liferay.portal.util.PortletKeys;
39 import com.liferay.portal.util.WebKeys;
40 import com.liferay.portlet.ActionRequestImpl;
41 import com.liferay.portlet.PortletPreferencesFactoryUtil;
42 import com.liferay.portlet.PortletURLImpl;
43 import com.liferay.portlet.asset.AssetTagException;
44 import com.liferay.portlet.assetpublisher.util.AssetPublisherUtil;
45 import com.liferay.portlet.journal.ArticleContentException;
46 import com.liferay.portlet.journal.ArticleDisplayDateException;
47 import com.liferay.portlet.journal.ArticleExpirationDateException;
48 import com.liferay.portlet.journal.ArticleIdException;
49 import com.liferay.portlet.journal.ArticleSmallImageNameException;
50 import com.liferay.portlet.journal.ArticleSmallImageSizeException;
51 import com.liferay.portlet.journal.ArticleTitleException;
52 import com.liferay.portlet.journal.ArticleTypeException;
53 import com.liferay.portlet.journal.ArticleVersionException;
54 import com.liferay.portlet.journal.DuplicateArticleIdException;
55 import com.liferay.portlet.journal.NoSuchArticleException;
56 import com.liferay.portlet.journal.NoSuchStructureException;
57 import com.liferay.portlet.journal.NoSuchTemplateException;
58 import com.liferay.portlet.journal.model.JournalArticle;
59 import com.liferay.portlet.journal.model.JournalStructure;
60 import com.liferay.portlet.journal.service.JournalArticleServiceUtil;
61 import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
62 import com.liferay.portlet.journal.service.JournalStructureLocalServiceUtil;
63 import com.liferay.portlet.journal.service.permission.JournalPermission;
64 import com.liferay.portlet.journal.util.JournalUtil;
65
66 import java.io.File;
67
68 import java.util.Calendar;
69 import java.util.Enumeration;
70 import java.util.HashMap;
71 import java.util.Map;
72
73 import javax.portlet.ActionRequest;
74 import javax.portlet.ActionResponse;
75 import javax.portlet.PortletConfig;
76 import javax.portlet.PortletPreferences;
77 import javax.portlet.PortletRequest;
78 import javax.portlet.RenderRequest;
79 import javax.portlet.RenderResponse;
80 import javax.portlet.WindowState;
81
82 import org.apache.struts.action.ActionForm;
83 import org.apache.struts.action.ActionForward;
84 import org.apache.struts.action.ActionMapping;
85
86
92 public class EditArticleAction extends PortletAction {
93
94 public static final String VERSION_SEPARATOR = "_version_";
95
96 public void processAction(
97 ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
98 ActionRequest actionRequest, ActionResponse actionResponse)
99 throws Exception {
100
101 String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
102
103 JournalArticle article = null;
104
105 try {
106 if (cmd.equals(Constants.ADD) || cmd.equals(Constants.UPDATE)) {
107 article = updateArticle(actionRequest);
108 }
109 else if (cmd.equals(Constants.DELETE)) {
110 deleteArticles(actionRequest);
111 }
112 else if (cmd.equals(Constants.EXPIRE)) {
113 expireArticles(actionRequest);
114 }
115 else if (cmd.equals(Constants.SUBSCRIBE)) {
116 subscribeArticles(actionRequest);
117 }
118 else if (cmd.equals(Constants.UNSUBSCRIBE)) {
119 unsubscribeArticles(actionRequest);
120 }
121 else if (cmd.equals("removeArticlesLocale")) {
122 removeArticlesLocale(actionRequest);
123 }
124
125 if (Validator.isNotNull(cmd)) {
126 String redirect = ParamUtil.getString(
127 actionRequest, "redirect");
128
129 int workflowAction = ParamUtil.getInteger(
130 actionRequest, "workflowAction",
131 WorkflowConstants.ACTION_PUBLISH);
132
133 if ((article != null) &&
134 (workflowAction == WorkflowConstants.ACTION_SAVE_DRAFT)) {
135
136 redirect = getSaveAndContinueRedirect(
137 portletConfig, actionRequest, article, redirect);
138 }
139
140 String referringPortletResource = ParamUtil.getString(
141 actionRequest, "referringPortletResource");
142
143 if (referringPortletResource.equals(
144 PortletKeys.JOURNAL_CONTENT)) {
145
146 actionResponse.sendRedirect(redirect);
147 }
148 else {
149 sendRedirect(actionRequest, actionResponse, redirect);
150 }
151 }
152 }
153 catch (Exception e) {
154 if (e instanceof NoSuchArticleException ||
155 e instanceof NoSuchStructureException ||
156 e instanceof NoSuchTemplateException ||
157 e instanceof PrincipalException) {
158
159 SessionErrors.add(actionRequest, e.getClass().getName());
160
161 setForward(actionRequest, "portlet.journal.error");
162 }
163 else if (e instanceof ArticleContentException ||
164 e instanceof ArticleDisplayDateException ||
165 e instanceof ArticleExpirationDateException ||
166 e instanceof ArticleIdException ||
167 e instanceof ArticleSmallImageNameException ||
168 e instanceof ArticleSmallImageSizeException ||
169 e instanceof ArticleTitleException ||
170 e instanceof ArticleTypeException ||
171 e instanceof ArticleVersionException ||
172 e instanceof DuplicateArticleIdException) {
173
174 SessionErrors.add(actionRequest, e.getClass().getName());
175 }
176 else if (e instanceof AssetTagException) {
177 SessionErrors.add(actionRequest, e.getClass().getName(), e);
178 }
179 else {
180 throw e;
181 }
182 }
183 }
184
185 public ActionForward render(
186 ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
187 RenderRequest renderRequest, RenderResponse renderResponse)
188 throws Exception {
189
190 try {
191 String cmd = ParamUtil.getString(renderRequest, Constants.CMD);
192
193 if (!cmd.equals(Constants.ADD)) {
194 ActionUtil.getArticle(renderRequest);
195 }
196 }
197 catch (NoSuchArticleException nsse) {
198
199
202 }
203 catch (Exception e) {
204 if ( e instanceof PrincipalException) {
206
207 SessionErrors.add(renderRequest, e.getClass().getName());
208
209 return mapping.findForward("portlet.journal.error");
210 }
211 else {
212 throw e;
213 }
214 }
215
216 return mapping.findForward(
217 getForward(renderRequest, "portlet.journal.edit_article"));
218 }
219
220 protected void deleteArticles(ActionRequest actionRequest)
221 throws Exception {
222
223 long groupId = ParamUtil.getLong(actionRequest, "groupId");
224
225 String[] deleteArticleIds = StringUtil.split(
226 ParamUtil.getString(actionRequest, "deleteArticleIds"));
227
228 ServiceContext serviceContext = ServiceContextFactory.getInstance(
229 JournalArticle.class.getName(), actionRequest);
230
231 for (int i = 0; i < deleteArticleIds.length; i++) {
232 int pos = deleteArticleIds[i].lastIndexOf(VERSION_SEPARATOR);
233
234 String articleId = deleteArticleIds[i];
235
236 String articleURL = ParamUtil.getString(
237 actionRequest, "articleURL");
238
239 if (pos == -1) {
240 JournalArticleServiceUtil.deleteArticle(
241 groupId, articleId, articleURL, serviceContext);
242 }
243 else {
244 articleId = articleId.substring(0, pos);
245 double version = GetterUtil.getDouble(
246 deleteArticleIds[i].substring(
247 pos + VERSION_SEPARATOR.length()));
248
249 JournalArticleServiceUtil.deleteArticle(
250 groupId, articleId, version, articleURL, serviceContext);
251 }
252
253 JournalUtil.removeRecentArticle(actionRequest, deleteArticleIds[i]);
254 }
255 }
256
257 protected void expireArticles(ActionRequest actionRequest)
258 throws Exception {
259
260 long groupId = ParamUtil.getLong(actionRequest, "groupId");
261
262 String[] expireArticleIds = StringUtil.split(
263 ParamUtil.getString(actionRequest, "expireArticleIds"));
264
265 ServiceContext serviceContext = ServiceContextFactory.getInstance(
266 JournalArticle.class.getName(), actionRequest);
267
268 for (int i = 0; i < expireArticleIds.length; i++) {
269 int pos = expireArticleIds[i].lastIndexOf(VERSION_SEPARATOR);
270
271 String articleId = expireArticleIds[i].substring(0, pos);
272 double version = GetterUtil.getDouble(
273 expireArticleIds[i].substring(
274 pos + VERSION_SEPARATOR.length()));
275
276 String articleURL = ParamUtil.getString(
277 actionRequest, "articleURL");
278
279 JournalArticleServiceUtil.expireArticle(
280 groupId, articleId, version, articleURL, serviceContext);
281 }
282 }
283
284 protected Map<String, byte[]> getImages(UploadPortletRequest uploadRequest)
285 throws Exception {
286
287 Map<String, byte[]> images = new HashMap<String, byte[]>();
288
289 String imagePrefix = "structure_image_";
290
291 Enumeration<String> enu = uploadRequest.getParameterNames();
292
293 while (enu.hasMoreElements()) {
294 String name = enu.nextElement();
295
296 if (name.startsWith(imagePrefix)) {
297 File file = uploadRequest.getFile(name);
298 byte[] bytes = FileUtil.getBytes(file);
299
300 if ((bytes != null) && (bytes.length > 0)) {
301 name = name.substring(imagePrefix.length(), name.length());
302
303 images.put(name, bytes);
304 }
305 }
306 }
307
308 return images;
309 }
310
311 protected String getSaveAndContinueRedirect(
312 PortletConfig portletConfig, ActionRequest actionRequest,
313 JournalArticle article, String redirect)
314 throws Exception {
315
316 ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
317 WebKeys.THEME_DISPLAY);
318
319 String originalRedirect = ParamUtil.getString(
320 actionRequest, "originalRedirect");
321
322 PortletURLImpl portletURL = new PortletURLImpl(
323 (ActionRequestImpl)actionRequest, portletConfig.getPortletName(),
324 themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
325
326 portletURL.setWindowState(WindowState.MAXIMIZED);
327
328 portletURL.setParameter("struts_action", "/journal/edit_article");
329 portletURL.setParameter(Constants.CMD, Constants.UPDATE, false);
330 portletURL.setParameter("redirect", redirect, false);
331 portletURL.setParameter("originalRedirect", originalRedirect, false);
332 portletURL.setParameter(
333 "groupId", String.valueOf(article.getGroupId()), false);
334 portletURL.setParameter("articleId", article.getArticleId(), false);
335 portletURL.setParameter(
336 "version", String.valueOf(article.getVersion()), false);
337
338 return portletURL.toString();
339 }
340
341 protected void removeArticlesLocale(ActionRequest actionRequest)
342 throws Exception {
343
344 long groupId = ParamUtil.getLong(actionRequest, "groupId");
345
346 String[] removeArticleLocaleIds = StringUtil.split(
347 ParamUtil.getString(actionRequest, "deleteArticleIds"));
348
349 for (int i = 0; i < removeArticleLocaleIds.length; i++) {
350 int pos = removeArticleLocaleIds[i].lastIndexOf(VERSION_SEPARATOR);
351
352 String articleId = removeArticleLocaleIds[i].substring(0, pos);
353 double version = GetterUtil.getDouble(
354 removeArticleLocaleIds[i].substring(
355 pos + VERSION_SEPARATOR.length()));
356 String languageId = ParamUtil.getString(
357 actionRequest, "languageId");
358
359 JournalArticleServiceUtil.removeArticleLocale(
360 groupId, articleId, version, languageId);
361 }
362 }
363
364 protected void subscribeArticles(ActionRequest actionRequest)
365 throws Exception {
366
367 ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
368 WebKeys.THEME_DISPLAY);
369
370 PermissionChecker permissionChecker =
371 themeDisplay.getPermissionChecker();
372
373 if (JournalPermission.contains(
374 permissionChecker, themeDisplay.getScopeGroupId(),
375 ActionKeys.SUBSCRIBE)) {
376
377 SubscriptionLocalServiceUtil.addSubscription(
378 themeDisplay.getUserId(), JournalArticle.class.getName(),
379 themeDisplay.getScopeGroupId());
380 }
381 }
382
383 protected void unsubscribeArticles(ActionRequest actionRequest)
384 throws Exception {
385
386 ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
387 WebKeys.THEME_DISPLAY);
388
389 PermissionChecker permissionChecker =
390 themeDisplay.getPermissionChecker();
391
392 if (JournalPermission.contains(
393 permissionChecker, themeDisplay.getScopeGroupId(),
394 ActionKeys.SUBSCRIBE)) {
395
396 SubscriptionLocalServiceUtil.deleteSubscription(
397 themeDisplay.getUserId(), JournalArticle.class.getName(),
398 themeDisplay.getScopeGroupId());
399 }
400 }
401
402 protected JournalArticle updateArticle(ActionRequest actionRequest)
403 throws Exception {
404
405 UploadPortletRequest uploadRequest = PortalUtil.getUploadPortletRequest(
406 actionRequest);
407
408 String cmd = ParamUtil.getString(uploadRequest, Constants.CMD);
409
410 long groupId = ParamUtil.getLong(uploadRequest, "groupId");
411
412 String articleId = ParamUtil.getString(uploadRequest, "articleId");
413 boolean autoArticleId = ParamUtil.getBoolean(
414 uploadRequest, "autoArticleId");
415
416 double version = ParamUtil.getDouble(uploadRequest, "version");
417
418 String title = ParamUtil.getString(uploadRequest, "title");
419 String description = ParamUtil.getString(uploadRequest, "description");
420 String content = ParamUtil.getString(uploadRequest, "content");
421 String type = ParamUtil.getString(uploadRequest, "type");
422 String structureId = ParamUtil.getString(uploadRequest, "structureId");
423 String templateId = ParamUtil.getString(uploadRequest, "templateId");
424
425 String lastLanguageId = ParamUtil.getString(
426 uploadRequest, "lastLanguageId");
427 String defaultLanguageId = ParamUtil.getString(
428 uploadRequest, "defaultLanguageId");
429
430 int displayDateMonth = ParamUtil.getInteger(
431 uploadRequest, "displayDateMonth");
432 int displayDateDay = ParamUtil.getInteger(
433 uploadRequest, "displayDateDay");
434 int displayDateYear = ParamUtil.getInteger(
435 uploadRequest, "displayDateYear");
436 int displayDateHour = ParamUtil.getInteger(
437 uploadRequest, "displayDateHour");
438 int displayDateMinute = ParamUtil.getInteger(
439 uploadRequest, "displayDateMinute");
440 int displayDateAmPm = ParamUtil.getInteger(
441 uploadRequest, "displayDateAmPm");
442
443 if (displayDateAmPm == Calendar.PM) {
444 displayDateHour += 12;
445 }
446
447 int expirationDateMonth = ParamUtil.getInteger(
448 uploadRequest, "expirationDateMonth");
449 int expirationDateDay = ParamUtil.getInteger(
450 uploadRequest, "expirationDateDay");
451 int expirationDateYear = ParamUtil.getInteger(
452 uploadRequest, "expirationDateYear");
453 int expirationDateHour = ParamUtil.getInteger(
454 uploadRequest, "expirationDateHour");
455 int expirationDateMinute = ParamUtil.getInteger(
456 uploadRequest, "expirationDateMinute");
457 int expirationDateAmPm = ParamUtil.getInteger(
458 uploadRequest, "expirationDateAmPm");
459 boolean neverExpire = ParamUtil.getBoolean(
460 uploadRequest, "neverExpire");
461
462 if (expirationDateAmPm == Calendar.PM) {
463 expirationDateHour += 12;
464 }
465
466 int reviewDateMonth = ParamUtil.getInteger(
467 uploadRequest, "reviewDateMonth");
468 int reviewDateDay = ParamUtil.getInteger(
469 uploadRequest, "reviewDateDay");
470 int reviewDateYear = ParamUtil.getInteger(
471 uploadRequest, "reviewDateYear");
472 int reviewDateHour = ParamUtil.getInteger(
473 uploadRequest, "reviewDateHour");
474 int reviewDateMinute = ParamUtil.getInteger(
475 uploadRequest, "reviewDateMinute");
476 int reviewDateAmPm = ParamUtil.getInteger(
477 uploadRequest, "reviewDateAmPm");
478 boolean neverReview = ParamUtil.getBoolean(
479 uploadRequest, "neverReview");
480
481 if (reviewDateAmPm == Calendar.PM) {
482 reviewDateHour += 12;
483 }
484
485 boolean indexable = ParamUtil.getBoolean(uploadRequest, "indexable");
486
487 boolean smallImage = ParamUtil.getBoolean(uploadRequest, "smallImage");
488 String smallImageURL = ParamUtil.getString(
489 uploadRequest, "smallImageURL");
490 File smallFile = uploadRequest.getFile("smallFile");
491
492 Map<String, byte[]> images = getImages(uploadRequest);
493
494 String articleURL = ParamUtil.getString(uploadRequest, "articleURL");
495
496 ServiceContext serviceContext = ServiceContextFactory.getInstance(
497 JournalArticle.class.getName(), actionRequest);
498
499 JournalArticle article = null;
500
501 if (cmd.equals(Constants.ADD)) {
502 if (Validator.isNull(structureId)) {
503 content = LocalizationUtil.updateLocalization(
504 StringPool.BLANK, "static-content", content,
505 lastLanguageId, defaultLanguageId, true);
506 }
507
508
510 article = JournalArticleServiceUtil.addArticle(
511 groupId, articleId, autoArticleId, title, description,
512 content, type, structureId, templateId, displayDateMonth,
513 displayDateDay, displayDateYear, displayDateHour,
514 displayDateMinute, expirationDateMonth, expirationDateDay,
515 expirationDateYear, expirationDateHour, expirationDateMinute,
516 neverExpire, reviewDateMonth, reviewDateDay, reviewDateYear,
517 reviewDateHour, reviewDateMinute, neverReview, indexable,
518 smallImage, smallImageURL, smallFile, images, articleURL,
519 serviceContext);
520
521 AssetPublisherUtil.addAndStoreSelection(
522 actionRequest, JournalArticle.class.getName(),
523 article.getResourcePrimKey(), -1);
524 }
525 else {
526
527
529 JournalArticle curArticle = JournalArticleServiceUtil.getArticle(
530 groupId, articleId, version);
531
532 if (Validator.isNull(structureId)) {
533 if (!curArticle.isTemplateDriven()) {
534 content = LocalizationUtil.updateLocalization(
535 curArticle.getContent(), "static-content", content,
536 lastLanguageId, defaultLanguageId, true);
537 }
538 }
539 else {
540 if (curArticle.isTemplateDriven()) {
541 JournalStructure structure =
542 JournalStructureLocalServiceUtil.getStructure(
543 groupId, structureId);
544
545 content = JournalUtil.mergeArticleContent(
546 curArticle.getContent(), content);
547 content = JournalUtil.removeOldContent(
548 content, structure.getMergedXsd());
549 }
550 }
551
552
554 article = JournalArticleServiceUtil.updateArticle(
555 groupId, articleId, version, title, description, content, type,
556 structureId, templateId, displayDateMonth, displayDateDay,
557 displayDateYear, displayDateHour, displayDateMinute,
558 expirationDateMonth, expirationDateDay, expirationDateYear,
559 expirationDateHour, expirationDateMinute, neverExpire,
560 reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
561 reviewDateMinute, neverReview, indexable, smallImage,
562 smallImageURL, smallFile, images, articleURL, serviceContext);
563 }
564
565
567 JournalUtil.addRecentArticle(actionRequest, article);
568
569
571 String portletResource = ParamUtil.getString(
572 uploadRequest, "portletResource");
573
574 if (Validator.isNotNull(portletResource)) {
575 PortletPreferences preferences =
576 PortletPreferencesFactoryUtil.getPortletSetup(
577 uploadRequest, portletResource);
578
579 preferences.setValue(
580 "group-id", String.valueOf(article.getGroupId()));
581 preferences.setValue("article-id", article.getArticleId());
582
583 preferences.store();
584
585 updateContentSearch(
586 actionRequest, portletResource, article.getArticleId());
587 }
588
589 return article;
590 }
591
592 protected void updateContentSearch(
593 ActionRequest actionRequest, String portletResource,
594 String articleId)
595 throws Exception {
596
597 ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
598 WebKeys.THEME_DISPLAY);
599
600 Layout layout = themeDisplay.getLayout();
601
602 JournalContentSearchLocalServiceUtil.updateContentSearch(
603 layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
604 portletResource, articleId);
605 }
606
607 }