001
014
015 package com.liferay.portlet.journal.service.impl;
016
017 import com.liferay.portal.LocaleException;
018 import com.liferay.portal.NoSuchImageException;
019 import com.liferay.portal.kernel.dao.orm.QueryDefinition;
020 import com.liferay.portal.kernel.dao.orm.QueryUtil;
021 import com.liferay.portal.kernel.exception.PortalException;
022 import com.liferay.portal.kernel.exception.SystemException;
023 import com.liferay.portal.kernel.json.JSONFactoryUtil;
024 import com.liferay.portal.kernel.json.JSONObject;
025 import com.liferay.portal.kernel.language.LanguageUtil;
026 import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
027 import com.liferay.portal.kernel.log.Log;
028 import com.liferay.portal.kernel.log.LogFactoryUtil;
029 import com.liferay.portal.kernel.sanitizer.SanitizerUtil;
030 import com.liferay.portal.kernel.search.Field;
031 import com.liferay.portal.kernel.search.Hits;
032 import com.liferay.portal.kernel.search.Indexer;
033 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
034 import com.liferay.portal.kernel.search.QueryConfig;
035 import com.liferay.portal.kernel.search.SearchContext;
036 import com.liferay.portal.kernel.search.SearchException;
037 import com.liferay.portal.kernel.search.Sort;
038 import com.liferay.portal.kernel.util.ArrayUtil;
039 import com.liferay.portal.kernel.util.CalendarFactoryUtil;
040 import com.liferay.portal.kernel.util.CharPool;
041 import com.liferay.portal.kernel.util.ContentTypes;
042 import com.liferay.portal.kernel.util.FileUtil;
043 import com.liferay.portal.kernel.util.GetterUtil;
044 import com.liferay.portal.kernel.util.HtmlUtil;
045 import com.liferay.portal.kernel.util.HttpUtil;
046 import com.liferay.portal.kernel.util.ListUtil;
047 import com.liferay.portal.kernel.util.LocaleUtil;
048 import com.liferay.portal.kernel.util.LocalizationUtil;
049 import com.liferay.portal.kernel.util.MathUtil;
050 import com.liferay.portal.kernel.util.ObjectValuePair;
051 import com.liferay.portal.kernel.util.OrderByComparator;
052 import com.liferay.portal.kernel.util.ParamUtil;
053 import com.liferay.portal.kernel.util.PropsKeys;
054 import com.liferay.portal.kernel.util.StringPool;
055 import com.liferay.portal.kernel.util.StringUtil;
056 import com.liferay.portal.kernel.util.Time;
057 import com.liferay.portal.kernel.util.UnicodeProperties;
058 import com.liferay.portal.kernel.util.Validator;
059 import com.liferay.portal.kernel.workflow.WorkflowConstants;
060 import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
061 import com.liferay.portal.kernel.xml.Document;
062 import com.liferay.portal.kernel.xml.DocumentException;
063 import com.liferay.portal.kernel.xml.Element;
064 import com.liferay.portal.kernel.xml.Node;
065 import com.liferay.portal.kernel.xml.SAXReaderUtil;
066 import com.liferay.portal.kernel.xml.XPath;
067 import com.liferay.portal.model.Company;
068 import com.liferay.portal.model.Group;
069 import com.liferay.portal.model.Image;
070 import com.liferay.portal.model.ResourceConstants;
071 import com.liferay.portal.model.User;
072 import com.liferay.portal.service.ServiceContext;
073 import com.liferay.portal.service.ServiceContextUtil;
074 import com.liferay.portal.servlet.filters.cache.CacheUtil;
075 import com.liferay.portal.theme.ThemeDisplay;
076 import com.liferay.portal.util.PortalUtil;
077 import com.liferay.portal.util.PortletKeys;
078 import com.liferay.portal.util.PrefsPropsUtil;
079 import com.liferay.portal.util.PropsValues;
080 import com.liferay.portal.util.SubscriptionSender;
081 import com.liferay.portal.webserver.WebServerServletTokenUtil;
082 import com.liferay.portlet.asset.NoSuchEntryException;
083 import com.liferay.portlet.asset.model.AssetEntry;
084 import com.liferay.portlet.asset.model.AssetLink;
085 import com.liferay.portlet.asset.model.AssetLinkConstants;
086 import com.liferay.portlet.dynamicdatamapping.NoSuchStructureException;
087 import com.liferay.portlet.dynamicdatamapping.NoSuchTemplateException;
088 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
089 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
090 import com.liferay.portlet.dynamicdatamapping.storage.FieldConstants;
091 import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
092 import com.liferay.portlet.expando.model.ExpandoBridge;
093 import com.liferay.portlet.journal.ArticleContentException;
094 import com.liferay.portlet.journal.ArticleDisplayDateException;
095 import com.liferay.portlet.journal.ArticleExpirationDateException;
096 import com.liferay.portlet.journal.ArticleIdException;
097 import com.liferay.portlet.journal.ArticleReviewDateException;
098 import com.liferay.portlet.journal.ArticleSmallImageNameException;
099 import com.liferay.portlet.journal.ArticleSmallImageSizeException;
100 import com.liferay.portlet.journal.ArticleTitleException;
101 import com.liferay.portlet.journal.ArticleTypeException;
102 import com.liferay.portlet.journal.ArticleVersionException;
103 import com.liferay.portlet.journal.DuplicateArticleIdException;
104 import com.liferay.portlet.journal.NoSuchArticleException;
105 import com.liferay.portlet.journal.NoSuchArticleResourceException;
106 import com.liferay.portlet.journal.StructureXsdException;
107 import com.liferay.portlet.journal.model.JournalArticle;
108 import com.liferay.portlet.journal.model.JournalArticleConstants;
109 import com.liferay.portlet.journal.model.JournalArticleDisplay;
110 import com.liferay.portlet.journal.model.JournalArticleResource;
111 import com.liferay.portlet.journal.model.impl.JournalArticleDisplayImpl;
112 import com.liferay.portlet.journal.service.base.JournalArticleLocalServiceBaseImpl;
113 import com.liferay.portlet.journal.social.JournalActivityKeys;
114 import com.liferay.portlet.journal.util.JournalUtil;
115 import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
116 import com.liferay.portlet.journal.util.comparator.ArticleVersionComparator;
117 import com.liferay.portlet.journalcontent.util.JournalContentUtil;
118 import com.liferay.portlet.trash.model.TrashEntry;
119 import com.liferay.portlet.trash.model.TrashVersion;
120 import com.liferay.portlet.trash.util.TrashUtil;
121
122 import java.io.File;
123 import java.io.IOException;
124 import java.io.Serializable;
125
126 import java.util.ArrayList;
127 import java.util.Calendar;
128 import java.util.Date;
129 import java.util.HashMap;
130 import java.util.HashSet;
131 import java.util.LinkedHashMap;
132 import java.util.List;
133 import java.util.Locale;
134 import java.util.Map;
135 import java.util.Set;
136
137 import javax.portlet.PortletPreferences;
138
139
146 public class JournalArticleLocalServiceImpl
147 extends JournalArticleLocalServiceBaseImpl {
148
149 public JournalArticle addArticle(
150 long userId, long groupId, long folderId, long classNameId,
151 long classPK, String articleId, boolean autoArticleId,
152 double version, Map<Locale, String> titleMap,
153 Map<Locale, String> descriptionMap, String content, String type,
154 String structureId, String templateId, String layoutUuid,
155 int displayDateMonth, int displayDateDay, int displayDateYear,
156 int displayDateHour, int displayDateMinute, int expirationDateMonth,
157 int expirationDateDay, int expirationDateYear,
158 int expirationDateHour, int expirationDateMinute,
159 boolean neverExpire, int reviewDateMonth, int reviewDateDay,
160 int reviewDateYear, int reviewDateHour, int reviewDateMinute,
161 boolean neverReview, boolean indexable, boolean smallImage,
162 String smallImageURL, File smallImageFile,
163 Map<String, byte[]> images, String articleURL,
164 ServiceContext serviceContext)
165 throws PortalException, SystemException {
166
167
168
169 User user = userPersistence.findByPrimaryKey(userId);
170 articleId = articleId.trim().toUpperCase();
171
172 Date displayDate = null;
173 Date expirationDate = null;
174 Date reviewDate = null;
175
176 if (classNameId == JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
177 displayDate = PortalUtil.getDate(
178 displayDateMonth, displayDateDay, displayDateYear,
179 displayDateHour, displayDateMinute, user.getTimeZone(),
180 ArticleDisplayDateException.class);
181
182 if (!neverExpire) {
183 expirationDate = PortalUtil.getDate(
184 expirationDateMonth, expirationDateDay, expirationDateYear,
185 expirationDateHour, expirationDateMinute,
186 user.getTimeZone(), ArticleExpirationDateException.class);
187 }
188
189 if (!neverReview) {
190 reviewDate = PortalUtil.getDate(
191 reviewDateMonth, reviewDateDay, reviewDateYear,
192 reviewDateHour, reviewDateMinute, user.getTimeZone(),
193 ArticleReviewDateException.class);
194 }
195 }
196
197 byte[] smallImageBytes = null;
198
199 try {
200 smallImageBytes = FileUtil.getBytes(smallImageFile);
201 }
202 catch (IOException ioe) {
203 }
204
205 Date now = new Date();
206
207 validate(
208 user.getCompanyId(), groupId, classNameId, articleId, autoArticleId,
209 version, titleMap, content, type, structureId, templateId,
210 expirationDate, smallImage, smallImageURL, smallImageFile,
211 smallImageBytes);
212
213 if (autoArticleId) {
214 articleId = String.valueOf(counterLocalService.increment());
215 }
216
217 long id = counterLocalService.increment();
218
219 long resourcePrimKey =
220 journalArticleResourceLocalService.getArticleResourcePrimKey(
221 serviceContext.getUuid(), groupId, articleId);
222
223 JournalArticle article = journalArticlePersistence.create(id);
224
225 Locale locale = LocaleUtil.getDefault();
226
227 String defaultLanguageId = ParamUtil.getString(
228 serviceContext, "defaultLanguageId");
229
230 if (Validator.isNull(defaultLanguageId)) {
231 defaultLanguageId = LocalizationUtil.getDefaultLocale(content);
232 }
233
234 if (Validator.isNotNull(defaultLanguageId)) {
235 locale = LocaleUtil.fromLanguageId(defaultLanguageId);
236 }
237
238 String title = titleMap.get(locale);
239
240 content = format(
241 user, groupId, articleId, version, false, content, structureId,
242 images);
243
244 article.setResourcePrimKey(resourcePrimKey);
245 article.setGroupId(groupId);
246 article.setCompanyId(user.getCompanyId());
247 article.setUserId(user.getUserId());
248 article.setUserName(user.getFullName());
249 article.setCreateDate(serviceContext.getCreateDate(now));
250 article.setModifiedDate(serviceContext.getModifiedDate(now));
251 article.setFolderId(folderId);
252 article.setClassNameId(classNameId);
253 article.setClassPK(classPK);
254 article.setArticleId(articleId);
255 article.setVersion(version);
256 article.setTitleMap(titleMap, locale);
257 article.setUrlTitle(
258 getUniqueUrlTitle(id, articleId, title, null, serviceContext));
259 article.setDescriptionMap(descriptionMap, locale);
260 article.setContent(content);
261 article.setType(type);
262 article.setStructureId(structureId);
263 article.setTemplateId(templateId);
264 article.setLayoutUuid(layoutUuid);
265 article.setDisplayDate(displayDate);
266 article.setExpirationDate(expirationDate);
267 article.setReviewDate(reviewDate);
268 article.setIndexable(indexable);
269 article.setSmallImage(smallImage);
270 article.setSmallImageId(counterLocalService.increment());
271 article.setSmallImageURL(smallImageURL);
272
273 if ((expirationDate == null) || expirationDate.after(now)) {
274 article.setStatus(WorkflowConstants.STATUS_DRAFT);
275 }
276 else {
277 article.setStatus(WorkflowConstants.STATUS_EXPIRED);
278 }
279
280 journalArticlePersistence.update(article);
281
282
283
284 if (serviceContext.isAddGroupPermissions() ||
285 serviceContext.isAddGuestPermissions()) {
286
287 addArticleResources(
288 article, serviceContext.isAddGroupPermissions(),
289 serviceContext.isAddGuestPermissions());
290 }
291 else {
292 addArticleResources(
293 article, serviceContext.getGroupPermissions(),
294 serviceContext.getGuestPermissions());
295 }
296
297
298
299 ExpandoBridge expandoBridge = article.getExpandoBridge();
300
301 expandoBridge.setAttributes(serviceContext);
302
303
304
305 saveImages(
306 smallImage, article.getSmallImageId(), smallImageFile,
307 smallImageBytes);
308
309
310
311 updateAsset(
312 userId, article, serviceContext.getAssetCategoryIds(),
313 serviceContext.getAssetTagNames(),
314 serviceContext.getAssetLinkEntryIds());
315
316
317
318 if (PortalUtil.getClassNameId(DDMStructure.class) == classNameId) {
319 updateDDMStructureXSD(classPK, content, serviceContext);
320 }
321
322
323
324 if (PropsValues.JOURNAL_ARTICLE_COMMENTS_ENABLED) {
325 mbMessageLocalService.addDiscussionMessage(
326 userId, article.getUserName(), groupId,
327 JournalArticle.class.getName(), resourcePrimKey,
328 WorkflowConstants.ACTION_PUBLISH);
329 }
330
331
332
333 PortletPreferences preferences =
334 ServiceContextUtil.getPortletPreferences(serviceContext);
335
336 sendEmail(
337 article, articleURL, preferences, "requested", serviceContext);
338
339
340
341 if (classNameId == JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
342 WorkflowHandlerRegistryUtil.startWorkflowInstance(
343 user.getCompanyId(), groupId, userId,
344 JournalArticle.class.getName(), article.getId(), article,
345 serviceContext);
346
347 if (serviceContext.getWorkflowAction() !=
348 WorkflowConstants.ACTION_PUBLISH) {
349
350
351
352 reindex(article);
353 }
354 }
355 else {
356 updateStatus(
357 userId, article, WorkflowConstants.STATUS_APPROVED, null,
358 new HashMap<String, Serializable>(), serviceContext);
359 }
360
361 return article;
362 }
363
364 public JournalArticle addArticle(
365 long userId, long groupId, long folderId,
366 Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
367 String content, String structureId, String templateId,
368 ServiceContext serviceContext)
369 throws PortalException, SystemException {
370
371 Calendar calendar = CalendarFactoryUtil.getCalendar();
372
373 int displayDateMonth = calendar.get(Calendar.MONTH);
374 int displayDateDay = calendar.get(Calendar.DAY_OF_MONTH);
375 int displayDateYear = calendar.get(Calendar.YEAR);
376 int displayDateHour = calendar.get(Calendar.HOUR_OF_DAY);
377 int displayDateMinute = calendar.get(Calendar.MINUTE);
378
379 return addArticle(
380 userId, groupId, folderId,
381 JournalArticleConstants.CLASSNAME_ID_DEFAULT, 0, StringPool.BLANK,
382 true, 1, titleMap, descriptionMap, content, "general", structureId,
383 templateId, null, displayDateMonth, displayDateDay, displayDateYear,
384 displayDateHour, displayDateMinute, 0, 0, 0, 0, 0, true, 0, 0, 0, 0,
385 0, true, true, false, null, null, null, null, serviceContext);
386 }
387
388 public void addArticleResources(
389 JournalArticle article, boolean addGroupPermissions,
390 boolean addGuestPermissions)
391 throws PortalException, SystemException {
392
393 resourceLocalService.addResources(
394 article.getCompanyId(), article.getGroupId(), article.getUserId(),
395 JournalArticle.class.getName(), article.getResourcePrimKey(), false,
396 addGroupPermissions, addGuestPermissions);
397 }
398
399 public void addArticleResources(
400 JournalArticle article, String[] groupPermissions,
401 String[] guestPermissions)
402 throws PortalException, SystemException {
403
404 resourceLocalService.addModelResources(
405 article.getCompanyId(), article.getGroupId(), article.getUserId(),
406 JournalArticle.class.getName(), article.getResourcePrimKey(),
407 groupPermissions, guestPermissions);
408 }
409
410 public void addArticleResources(
411 long groupId, String articleId, boolean addGroupPermissions,
412 boolean addGuestPermissions)
413 throws PortalException, SystemException {
414
415 JournalArticle article = getLatestArticle(groupId, articleId);
416
417 addArticleResources(article, addGroupPermissions, addGuestPermissions);
418 }
419
420 public void addArticleResources(
421 long groupId, String articleId, String[] groupPermissions,
422 String[] guestPermissions)
423 throws PortalException, SystemException {
424
425 JournalArticle article = getLatestArticle(groupId, articleId);
426
427 addArticleResources(article, groupPermissions, guestPermissions);
428 }
429
430 public JournalArticle checkArticleResourcePrimKey(
431 long groupId, String articleId, double version)
432 throws PortalException, SystemException {
433
434 JournalArticle article = journalArticlePersistence.findByG_A_V(
435 groupId, articleId, version);
436
437 if (article.getResourcePrimKey() > 0) {
438 return article;
439 }
440
441 long resourcePrimKey =
442 journalArticleResourceLocalService.getArticleResourcePrimKey(
443 groupId, articleId);
444
445 article.setResourcePrimKey(resourcePrimKey);
446
447 journalArticlePersistence.update(article);
448
449 return article;
450 }
451
452 public void checkArticles() throws PortalException, SystemException {
453 Date now = new Date();
454
455 List<JournalArticle> articles =
456 journalArticleFinder.findByExpirationDate(
457 JournalArticleConstants.CLASSNAME_ID_DEFAULT,
458 WorkflowConstants.STATUS_APPROVED,
459 new Date(now.getTime() + _JOURNAL_ARTICLE_CHECK_INTERVAL));
460
461 if (_log.isDebugEnabled()) {
462 _log.debug("Expiring " + articles.size() + " articles");
463 }
464
465 Set<Long> companyIds = new HashSet<Long>();
466
467 for (JournalArticle article : articles) {
468 if (PropsValues.JOURNAL_ARTICLE_EXPIRE_ALL_VERSIONS) {
469 List<JournalArticle> currentArticles =
470 journalArticlePersistence.findByG_A(
471 article.getGroupId(), article.getArticleId(),
472 QueryUtil.ALL_POS, QueryUtil.ALL_POS,
473 new ArticleVersionComparator(true));
474
475 for (JournalArticle currentArticle : currentArticles) {
476 currentArticle.setExpirationDate(
477 article.getExpirationDate());
478 currentArticle.setStatus(WorkflowConstants.STATUS_EXPIRED);
479
480 journalArticlePersistence.update(currentArticle);
481 }
482 }
483 else {
484 article.setStatus(WorkflowConstants.STATUS_EXPIRED);
485
486 journalArticlePersistence.update(article);
487 }
488
489 updatePreviousApprovedArticle(article);
490
491 JournalContentUtil.clearCache(
492 article.getGroupId(), article.getArticleId(),
493 article.getTemplateId());
494
495 companyIds.add(article.getCompanyId());
496 }
497
498 for (long companyId : companyIds) {
499 CacheUtil.clearCache(companyId);
500 }
501
502 if (_previousCheckDate == null) {
503 _previousCheckDate = new Date(
504 now.getTime() - _JOURNAL_ARTICLE_CHECK_INTERVAL);
505 }
506
507 articles = journalArticleFinder.findByReviewDate(
508 JournalArticleConstants.CLASSNAME_ID_DEFAULT, now,
509 _previousCheckDate);
510
511 if (_log.isDebugEnabled()) {
512 _log.debug(
513 "Sending review notifications for " + articles.size() +
514 " articles");
515 }
516
517 for (JournalArticle article : articles) {
518 String articleURL = StringPool.BLANK;
519
520 long ownerId = article.getGroupId();
521 int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
522 long plid = PortletKeys.PREFS_PLID_SHARED;
523 String portletId = PortletKeys.JOURNAL;
524
525 PortletPreferences preferences =
526 portletPreferencesLocalService.getPreferences(
527 article.getCompanyId(), ownerId, ownerType, plid,
528 portletId);
529
530 sendEmail(
531 article, articleURL, preferences, "review",
532 new ServiceContext());
533 }
534
535 _previousCheckDate = now;
536 }
537
538 public void checkNewLine(long groupId, String articleId, double version)
539 throws PortalException, SystemException {
540
541 JournalArticle article = journalArticlePersistence.findByG_A_V(
542 groupId, articleId, version);
543
544 String content = GetterUtil.getString(article.getContent());
545
546 if (content.contains("\\n")) {
547 content = StringUtil.replace(
548 content, new String[] {"\\n", "\\r"},
549 new String[] {"\n", "\r"});
550
551 article.setContent(content);
552
553 journalArticlePersistence.update(article);
554 }
555 }
556
557 public void checkStructure(long groupId, String articleId, double version)
558 throws PortalException, SystemException {
559
560 JournalArticle article = journalArticlePersistence.findByG_A_V(
561 groupId, articleId, version);
562
563 if (Validator.isNull(article.getStructureId())) {
564 return;
565 }
566
567 checkStructure(article);
568 }
569
570 public JournalArticle copyArticle(
571 long userId, long groupId, String oldArticleId, String newArticleId,
572 boolean autoArticleId, double version)
573 throws PortalException, SystemException {
574
575
576
577 User user = userPersistence.findByPrimaryKey(userId);
578 oldArticleId = oldArticleId.trim().toUpperCase();
579 newArticleId = newArticleId.trim().toUpperCase();
580 Date now = new Date();
581
582 JournalArticle oldArticle = journalArticlePersistence.findByG_A_V(
583 groupId, oldArticleId, version);
584
585 if (autoArticleId) {
586 newArticleId = String.valueOf(counterLocalService.increment());
587 }
588 else {
589 validate(newArticleId);
590
591 if (journalArticlePersistence.countByG_A(
592 groupId, newArticleId) > 0) {
593
594 throw new DuplicateArticleIdException();
595 }
596 }
597
598 long id = counterLocalService.increment();
599
600 long resourcePrimKey =
601 journalArticleResourceLocalService.getArticleResourcePrimKey(
602 groupId, newArticleId);
603
604 JournalArticle newArticle = journalArticlePersistence.create(id);
605
606 newArticle.setResourcePrimKey(resourcePrimKey);
607 newArticle.setGroupId(groupId);
608 newArticle.setCompanyId(user.getCompanyId());
609 newArticle.setUserId(user.getUserId());
610 newArticle.setUserName(user.getFullName());
611 newArticle.setCreateDate(now);
612 newArticle.setModifiedDate(now);
613 newArticle.setArticleId(newArticleId);
614 newArticle.setVersion(JournalArticleConstants.VERSION_DEFAULT);
615 newArticle.setTitle(oldArticle.getTitle());
616 newArticle.setDescription(oldArticle.getDescription());
617
618 try {
619 copyArticleImages(oldArticle, newArticle);
620 }
621 catch (Exception e) {
622 newArticle.setContent(oldArticle.getContent());
623 }
624
625 newArticle.setType(oldArticle.getType());
626 newArticle.setStructureId(oldArticle.getStructureId());
627 newArticle.setTemplateId(oldArticle.getTemplateId());
628 newArticle.setLayoutUuid(oldArticle.getLayoutUuid());
629 newArticle.setDisplayDate(oldArticle.getDisplayDate());
630 newArticle.setExpirationDate(oldArticle.getExpirationDate());
631 newArticle.setReviewDate(oldArticle.getReviewDate());
632 newArticle.setIndexable(oldArticle.isIndexable());
633 newArticle.setSmallImage(oldArticle.isSmallImage());
634 newArticle.setSmallImageId(counterLocalService.increment());
635 newArticle.setSmallImageURL(oldArticle.getSmallImageURL());
636 newArticle.setStatus(oldArticle.getStatus());
637
638 journalArticlePersistence.update(newArticle);
639
640
641
642 addArticleResources(newArticle, true, true);
643
644
645
646 if (oldArticle.getSmallImage()) {
647 Image image = imageLocalService.getImage(
648 oldArticle.getSmallImageId());
649
650 byte[] smallImageBytes = image.getTextObj();
651
652 imageLocalService.updateImage(
653 newArticle.getSmallImageId(), smallImageBytes);
654 }
655
656
657
658 long[] assetCategoryIds = assetCategoryLocalService.getCategoryIds(
659 JournalArticle.class.getName(), oldArticle.getResourcePrimKey());
660 String[] assetTagNames = assetTagLocalService.getTagNames(
661 JournalArticle.class.getName(), oldArticle.getResourcePrimKey());
662
663 updateAsset(userId, newArticle, assetCategoryIds, assetTagNames, null);
664
665 return newArticle;
666 }
667
668 public void deleteArticle(JournalArticle article)
669 throws PortalException, SystemException {
670
671 deleteArticle(article, StringPool.BLANK, null);
672 }
673
674 public void deleteArticle(
675 JournalArticle article, String articleURL,
676 ServiceContext serviceContext)
677 throws PortalException, SystemException {
678
679 if (article.isApproved() &&
680 isLatestVersion(
681 article.getGroupId(), article.getArticleId(),
682 article.getVersion(), WorkflowConstants.STATUS_APPROVED)) {
683
684 updatePreviousApprovedArticle(article);
685 }
686 else if (article.isInTrash()) {
687 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
688 JournalArticle.class);
689
690 indexer.delete(article);
691 }
692
693
694
695 if ((serviceContext != null) && Validator.isNotNull(articleURL)) {
696 PortletPreferences preferences =
697 ServiceContextUtil.getPortletPreferences(serviceContext);
698
699 if ((preferences != null) && !article.isApproved() &&
700 isLatestVersion(
701 article.getGroupId(), article.getArticleId(),
702 article.getVersion())) {
703
704 sendEmail(
705 article, articleURL, preferences, "denied", serviceContext);
706 }
707 }
708
709
710
711 journalArticleImageLocalService.deleteImages(
712 article.getGroupId(), article.getArticleId(), article.getVersion());
713
714
715
716 if (!article.isDraft()) {
717 workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
718 article.getCompanyId(), article.getGroupId(),
719 JournalArticle.class.getName(), article.getId());
720 }
721
722 int articlesCount = journalArticlePersistence.countByG_A(
723 article.getGroupId(), article.getArticleId());
724
725 if (articlesCount == 1) {
726
727
728
729 subscriptionLocalService.deleteSubscriptions(
730 article.getCompanyId(), JournalArticle.class.getName(),
731 article.getResourcePrimKey());
732
733
734
735 ratingsStatsLocalService.deleteStats(
736 JournalArticle.class.getName(), article.getResourcePrimKey());
737
738
739
740 mbMessageLocalService.deleteDiscussionMessages(
741 JournalArticle.class.getName(), article.getResourcePrimKey());
742
743
744
745 assetEntryLocalService.deleteEntry(
746 JournalArticle.class.getName(), article.getResourcePrimKey());
747
748
749
750 journalContentSearchLocalService.deleteArticleContentSearches(
751 article.getGroupId(), article.getArticleId());
752
753
754
755 imageLocalService.deleteImage(article.getSmallImageId());
756
757
758
759 expandoValueLocalService.deleteValues(
760 JournalArticle.class.getName(), article.getId());
761
762
763
764 trashEntryLocalService.deleteEntry(
765 JournalArticle.class.getName(), article.getResourcePrimKey());
766
767
768
769 resourceLocalService.deleteResource(
770 article.getCompanyId(), JournalArticle.class.getName(),
771 ResourceConstants.SCOPE_INDIVIDUAL,
772 article.getResourcePrimKey());
773
774
775
776 try {
777 journalArticleResourceLocalService.deleteArticleResource(
778 article.getGroupId(), article.getArticleId());
779 }
780 catch (NoSuchArticleResourceException nsare) {
781 }
782 }
783
784
785
786 journalArticlePersistence.remove(article);
787 }
788
789 public void deleteArticle(
790 long groupId, String articleId, double version, String articleURL,
791 ServiceContext serviceContext)
792 throws PortalException, SystemException {
793
794 JournalArticle article = journalArticlePersistence.findByG_A_V(
795 groupId, articleId, version);
796
797 deleteArticle(article, articleURL, serviceContext);
798 }
799
800 public void deleteArticle(
801 long groupId, String articleId, ServiceContext serviceContext)
802 throws PortalException, SystemException {
803
804 List<JournalArticle> articles = journalArticlePersistence.findByG_A(
805 groupId, articleId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
806 new ArticleVersionComparator(true));
807
808 for (JournalArticle article : articles) {
809 deleteArticle(article, null, serviceContext);
810 }
811 }
812
813 public void deleteArticles(long groupId)
814 throws PortalException, SystemException {
815
816 for (JournalArticle article :
817 journalArticlePersistence.findByGroupId(groupId)) {
818
819 deleteArticle(article, null, null);
820 }
821 }
822
823 public void deleteArticles(long groupId, long folderId)
824 throws PortalException, SystemException {
825
826 for (JournalArticle article :
827 journalArticlePersistence.findByG_F(groupId, folderId)) {
828
829 deleteArticle(article, null, null);
830 }
831 }
832
833 public void deleteLayoutArticleReferences(long groupId, String layoutUuid)
834 throws SystemException {
835
836 List<JournalArticle> articles = journalArticlePersistence.findByG_L(
837 groupId, layoutUuid);
838
839 for (JournalArticle article : articles) {
840 article.setLayoutUuid(StringPool.BLANK);
841
842 journalArticlePersistence.update(article);
843 }
844 }
845
846 public JournalArticle expireArticle(
847 long userId, long groupId, String articleId, double version,
848 String articleURL, ServiceContext serviceContext)
849 throws PortalException, SystemException {
850
851 return updateStatus(
852 userId, groupId, articleId, version,
853 WorkflowConstants.STATUS_EXPIRED, articleURL,
854 new HashMap<String, Serializable>(), serviceContext);
855 }
856
857 public void expireArticle(
858 long userId, long groupId, String articleId, String articleURL,
859 ServiceContext serviceContext)
860 throws PortalException, SystemException {
861
862 if (PropsValues.JOURNAL_ARTICLE_EXPIRE_ALL_VERSIONS) {
863 List<JournalArticle> articles = journalArticlePersistence.findByG_A(
864 groupId, articleId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
865 new ArticleVersionComparator(true));
866
867 for (JournalArticle article : articles) {
868 expireArticle(
869 userId, groupId, article.getArticleId(),
870 article.getVersion(), articleURL, serviceContext);
871 }
872 }
873 else {
874 JournalArticle article = getLatestArticle(
875 groupId, articleId, WorkflowConstants.STATUS_APPROVED);
876
877 expireArticle(
878 userId, groupId, article.getArticleId(), article.getVersion(),
879 articleURL, serviceContext);
880 }
881 }
882
883 public JournalArticle fetchArticle(String uuid, long groupId)
884 throws SystemException {
885
886 return journalArticlePersistence.fetchByUUID_G(uuid, groupId);
887 }
888
889 public JournalArticle getArticle(long id)
890 throws PortalException, SystemException {
891
892 return journalArticlePersistence.findByPrimaryKey(id);
893 }
894
895 public JournalArticle getArticle(long groupId, String articleId)
896 throws PortalException, SystemException {
897
898
899
900
901 try {
902 return getLatestArticle(
903 groupId, articleId, WorkflowConstants.STATUS_APPROVED);
904 }
905 catch (NoSuchArticleException nsae) {
906 return getLatestArticle(
907 groupId, articleId, WorkflowConstants.STATUS_ANY);
908 }
909 }
910
911 public JournalArticle getArticle(
912 long groupId, String articleId, double version)
913 throws PortalException, SystemException {
914
915 return journalArticlePersistence.findByG_A_V(
916 groupId, articleId, version);
917 }
918
919 public JournalArticle getArticle(
920 long groupId, String className, long classPK)
921 throws PortalException, SystemException {
922
923 long classNameId = PortalUtil.getClassNameId(className);
924
925 List<JournalArticle> articles = journalArticlePersistence.findByG_C_C(
926 groupId, classNameId, classPK);
927
928 if (articles.isEmpty()) {
929 throw new NoSuchArticleException(
930 "No approved JournalArticle exists with the key {groupId=" +
931 groupId + ", className=" + className + ", classPK=" +
932 classPK + "}");
933 }
934
935 return articles.get(0);
936 }
937
938 public JournalArticle getArticleByUrlTitle(long groupId, String urlTitle)
939 throws PortalException, SystemException {
940
941
942
943
944 try {
945 return getLatestArticleByUrlTitle(
946 groupId, urlTitle, WorkflowConstants.STATUS_APPROVED);
947 }
948 catch (NoSuchArticleException nsae) {
949 return getLatestArticleByUrlTitle(
950 groupId, urlTitle, WorkflowConstants.STATUS_PENDING);
951 }
952 }
953
954 public String getArticleContent(
955 JournalArticle article, String templateId, String viewMode,
956 String languageId, ThemeDisplay themeDisplay)
957 throws PortalException, SystemException {
958
959 JournalArticleDisplay articleDisplay = getArticleDisplay(
960 article, templateId, viewMode, languageId, 1, null, themeDisplay);
961
962 if (articleDisplay == null) {
963 return StringPool.BLANK;
964 }
965 else {
966 return articleDisplay.getContent();
967 }
968 }
969
970 public String getArticleContent(
971 long groupId, String articleId, double version, String viewMode,
972 String templateId, String languageId, ThemeDisplay themeDisplay)
973 throws PortalException, SystemException {
974
975 JournalArticleDisplay articleDisplay = getArticleDisplay(
976 groupId, articleId, version, templateId, viewMode, languageId,
977 themeDisplay);
978
979 if (articleDisplay == null) {
980 return StringPool.BLANK;
981 }
982 else {
983 return articleDisplay.getContent();
984 }
985 }
986
987 public String getArticleContent(
988 long groupId, String articleId, double version, String viewMode,
989 String languageId, ThemeDisplay themeDisplay)
990 throws PortalException, SystemException {
991
992 return getArticleContent(
993 groupId, articleId, version, viewMode, null, languageId,
994 themeDisplay);
995 }
996
997 public String getArticleContent(
998 long groupId, String articleId, String viewMode, String templateId,
999 String languageId, ThemeDisplay themeDisplay)
1000 throws PortalException, SystemException {
1001
1002 JournalArticleDisplay articleDisplay = getArticleDisplay(
1003 groupId, articleId, templateId, viewMode, languageId, themeDisplay);
1004
1005 return articleDisplay.getContent();
1006 }
1007
1008 public String getArticleContent(
1009 long groupId, String articleId, String viewMode, String languageId,
1010 ThemeDisplay themeDisplay)
1011 throws PortalException, SystemException {
1012
1013 return getArticleContent(
1014 groupId, articleId, viewMode, null, languageId, themeDisplay);
1015 }
1016
1017 public JournalArticleDisplay getArticleDisplay(
1018 JournalArticle article, String templateId, String viewMode,
1019 String languageId, int page, String xmlRequest,
1020 ThemeDisplay themeDisplay)
1021 throws PortalException, SystemException {
1022
1023 String content = null;
1024
1025 if (page < 1) {
1026 page = 1;
1027 }
1028
1029 int numberOfPages = 1;
1030 boolean paginate = false;
1031 boolean pageFlow = false;
1032
1033 boolean cacheable = true;
1034
1035 if (Validator.isNull(xmlRequest)) {
1036 xmlRequest = "<request />";
1037 }
1038
1039 Map<String, String> tokens = JournalUtil.getTokens(
1040 article.getGroupId(), themeDisplay, xmlRequest);
1041
1042 tokens.put(
1043 "article_resource_pk",
1044 String.valueOf(article.getResourcePrimKey()));
1045
1046 String defaultTemplateId = article.getTemplateId();
1047
1048 if (article.isTemplateDriven()) {
1049 if (Validator.isNull(templateId)) {
1050 templateId = defaultTemplateId;
1051 }
1052
1053 tokens.put("structure_id", article.getStructureId());
1054 tokens.put("template_id", templateId);
1055 }
1056
1057 String xml = article.getContent();
1058
1059 try {
1060 Document document = null;
1061
1062 Element rootElement = null;
1063
1064 if (article.isTemplateDriven()) {
1065 document = SAXReaderUtil.read(xml);
1066
1067 rootElement = document.getRootElement();
1068
1069 Document requestDocument = SAXReaderUtil.read(xmlRequest);
1070
1071 List<Element> pages = rootElement.elements("page");
1072
1073 if (!pages.isEmpty()) {
1074 pageFlow = true;
1075
1076 String targetPage = requestDocument.valueOf(
1077 "/request/parameters/parameter[name='targetPage']/" +
1078 "value");
1079
1080 Element pageElement = null;
1081
1082 if (Validator.isNotNull(targetPage)) {
1083 targetPage = HtmlUtil.escapeXPathAttribute(targetPage);
1084
1085 XPath xPathSelector = SAXReaderUtil.createXPath(
1086 "/root/page[@id = " + targetPage + "]");
1087
1088 pageElement = (Element)xPathSelector.selectSingleNode(
1089 document);
1090 }
1091
1092 if (pageElement != null) {
1093 document = SAXReaderUtil.createDocument(pageElement);
1094
1095 rootElement = document.getRootElement();
1096
1097 numberOfPages = pages.size();
1098 }
1099 else {
1100 if (page > pages.size()) {
1101 page = 1;
1102 }
1103
1104 pageElement = pages.get(page - 1);
1105
1106 document = SAXReaderUtil.createDocument(pageElement);
1107
1108 rootElement = document.getRootElement();
1109
1110 numberOfPages = pages.size();
1111 paginate = true;
1112 }
1113 }
1114
1115 rootElement.add(requestDocument.getRootElement().createCopy());
1116
1117 JournalUtil.addAllReservedEls(
1118 rootElement, tokens, article, languageId, themeDisplay);
1119
1120 xml = DDMXMLUtil.formatXML(document);
1121 }
1122 }
1123 catch (DocumentException de) {
1124 throw new SystemException(de);
1125 }
1126
1127 try {
1128 if (_log.isDebugEnabled()) {
1129 _log.debug(
1130 "Transforming " + article.getArticleId() + " " +
1131 article.getVersion() + " " + languageId);
1132 }
1133
1134 String script = null;
1135 String langType = null;
1136
1137 if (article.isTemplateDriven()) {
1138
1139
1140
1141
1142
1143
1144
1145 DDMTemplate ddmTemplate = null;
1146
1147 try {
1148 ddmTemplate = ddmTemplatePersistence.findByG_C_T(
1149 article.getGroupId(),
1150 PortalUtil.getClassNameId(DDMStructure.class),
1151 templateId);
1152 }
1153 catch (NoSuchTemplateException nste1) {
1154 try {
1155 Group companyGroup = groupLocalService.getCompanyGroup(
1156 article.getCompanyId());
1157
1158 ddmTemplate = ddmTemplatePersistence.findByG_C_T(
1159 companyGroup.getGroupId(),
1160 PortalUtil.getClassNameId(DDMStructure.class),
1161 templateId);
1162
1163 tokens.put(
1164 "company_group_id",
1165 String.valueOf(companyGroup.getGroupId()));
1166 }
1167 catch (NoSuchTemplateException nste2) {
1168 if (!defaultTemplateId.equals(templateId)) {
1169 ddmTemplate = ddmTemplatePersistence.findByG_C_T(
1170 article.getGroupId(),
1171 PortalUtil.getClassNameId(DDMStructure.class),
1172 defaultTemplateId);
1173 }
1174 else {
1175 throw nste1;
1176 }
1177 }
1178 }
1179
1180 script = ddmTemplate.getScript();
1181 langType = ddmTemplate.getLanguage();
1182 cacheable = ddmTemplate.isCacheable();
1183 }
1184
1185 content = JournalUtil.transform(
1186 themeDisplay, tokens, viewMode, languageId, xml, script,
1187 langType);
1188
1189 if (!pageFlow) {
1190 String[] pieces = StringUtil.split(
1191 content, PropsValues.JOURNAL_ARTICLE_TOKEN_PAGE_BREAK);
1192
1193 if (pieces.length > 1) {
1194 if (page > pieces.length) {
1195 page = 1;
1196 }
1197
1198 content = pieces[page - 1];
1199 numberOfPages = pieces.length;
1200 paginate = true;
1201 }
1202 }
1203 }
1204 catch (Exception e) {
1205 throw new SystemException(e);
1206 }
1207
1208 return new JournalArticleDisplayImpl(
1209 article.getCompanyId(), article.getId(),
1210 article.getResourcePrimKey(), article.getGroupId(),
1211 article.getUserId(), article.getArticleId(), article.getVersion(),
1212 article.getTitle(languageId), article.getUrlTitle(),
1213 article.getDescription(languageId), article.getAvailableLocales(),
1214 content, article.getType(), article.getStructureId(), templateId,
1215 article.isSmallImage(), article.getSmallImageId(),
1216 article.getSmallImageURL(), numberOfPages, page, paginate,
1217 cacheable);
1218 }
1219
1220 public JournalArticleDisplay getArticleDisplay(
1221 long groupId, String articleId, double version, String templateId,
1222 String viewMode, String languageId, int page, String xmlRequest,
1223 ThemeDisplay themeDisplay)
1224 throws PortalException, SystemException {
1225
1226 Date now = new Date();
1227
1228 JournalArticle article = journalArticlePersistence.findByG_A_V(
1229 groupId, articleId, version);
1230
1231 if (article.isExpired()) {
1232 Date expirationDate = article.getExpirationDate();
1233
1234 if ((expirationDate != null) && expirationDate.before(now)) {
1235 return null;
1236 }
1237 }
1238
1239 if (article.getDisplayDate().after(now)) {
1240 return null;
1241 }
1242
1243 return getArticleDisplay(
1244 article, templateId, viewMode, languageId, page, xmlRequest,
1245 themeDisplay);
1246 }
1247
1248 public JournalArticleDisplay getArticleDisplay(
1249 long groupId, String articleId, double version, String templateId,
1250 String viewMode, String languageId, ThemeDisplay themeDisplay)
1251 throws PortalException, SystemException {
1252
1253 return getArticleDisplay(
1254 groupId, articleId, version, templateId, viewMode, languageId, 1,
1255 null, themeDisplay);
1256 }
1257
1258 public JournalArticleDisplay getArticleDisplay(
1259 long groupId, String articleId, String viewMode, String languageId,
1260 int page, String xmlRequest, ThemeDisplay themeDisplay)
1261 throws PortalException, SystemException {
1262
1263 return getArticleDisplay(
1264 groupId, articleId, null, viewMode, languageId, page, xmlRequest,
1265 themeDisplay);
1266 }
1267
1268 public JournalArticleDisplay getArticleDisplay(
1269 long groupId, String articleId, String templateId, String viewMode,
1270 String languageId, int page, String xmlRequest,
1271 ThemeDisplay themeDisplay)
1272 throws PortalException, SystemException {
1273
1274 JournalArticle article = getDisplayArticle(groupId, articleId);
1275
1276 return getArticleDisplay(
1277 groupId, articleId, article.getVersion(), templateId, viewMode,
1278 languageId, page, xmlRequest, themeDisplay);
1279 }
1280
1281 public JournalArticleDisplay getArticleDisplay(
1282 long groupId, String articleId, String templateId, String viewMode,
1283 String languageId, ThemeDisplay themeDisplay)
1284 throws PortalException, SystemException {
1285
1286 JournalArticle article = getDisplayArticle(groupId, articleId);
1287
1288 return getArticleDisplay(
1289 groupId, articleId, article.getVersion(), templateId, viewMode,
1290 languageId, themeDisplay);
1291 }
1292
1293 public JournalArticleDisplay getArticleDisplay(
1294 long groupId, String articleId, String viewMode, String languageId,
1295 ThemeDisplay themeDisplay)
1296 throws PortalException, SystemException {
1297
1298 return getArticleDisplay(
1299 groupId, articleId, null, viewMode, languageId, themeDisplay);
1300 }
1301
1302 public List<JournalArticle> getArticles() throws SystemException {
1303 return journalArticlePersistence.findAll();
1304 }
1305
1306 public List<JournalArticle> getArticles(long groupId)
1307 throws SystemException {
1308
1309 return journalArticlePersistence.findByGroupId(groupId);
1310 }
1311
1312 public List<JournalArticle> getArticles(long groupId, int start, int end)
1313 throws SystemException {
1314
1315 return journalArticlePersistence.findByGroupId(groupId, start, end);
1316 }
1317
1318 public List<JournalArticle> getArticles(
1319 long groupId, int start, int end, OrderByComparator obc)
1320 throws SystemException {
1321
1322 return journalArticlePersistence.findByGroupId(
1323 groupId, start, end, obc);
1324 }
1325
1326 public List<JournalArticle> getArticles(long groupId, long folderId)
1327 throws SystemException {
1328
1329 return journalArticlePersistence.findByG_F(groupId, folderId);
1330 }
1331
1332 public List<JournalArticle> getArticles(
1333 long groupId, long folderId, int start, int end)
1334 throws SystemException {
1335
1336 return journalArticlePersistence.findByG_F(
1337 groupId, folderId, start, end);
1338 }
1339
1340 public List<JournalArticle> getArticles(
1341 long groupId, long folderId, int start, int end,
1342 OrderByComparator orderByComparator)
1343 throws SystemException {
1344
1345 return journalArticlePersistence.findByG_F(
1346 groupId, folderId, start, end, orderByComparator);
1347 }
1348
1349 public List<JournalArticle> getArticles(long groupId, String articleId)
1350 throws SystemException {
1351
1352 return journalArticlePersistence.findByG_A(groupId, articleId);
1353 }
1354
1355 public List<JournalArticle> getArticlesBySmallImageId(long smallImageId)
1356 throws SystemException {
1357
1358 return journalArticlePersistence.findBySmallImageId(smallImageId);
1359 }
1360
1361 public int getArticlesCount(long groupId) throws SystemException {
1362 return journalArticlePersistence.countByGroupId(groupId);
1363 }
1364
1365 public int getArticlesCount(long groupId, long folderId)
1366 throws SystemException {
1367
1368 return journalArticlePersistence.countByG_F(groupId, folderId);
1369 }
1370
1371 public List<JournalArticle> getCompanyArticles(
1372 long companyId, double version, int status, int start, int end)
1373 throws SystemException {
1374
1375 if (status == WorkflowConstants.STATUS_ANY) {
1376 return journalArticlePersistence.findByC_V(
1377 companyId, version, start, end, new ArticleIDComparator(true));
1378 }
1379 else {
1380 return journalArticlePersistence.findByC_V_ST(
1381 companyId, version, status, start, end,
1382 new ArticleIDComparator(true));
1383 }
1384 }
1385
1386 public List<JournalArticle> getCompanyArticles(
1387 long companyId, int status, int start, int end)
1388 throws SystemException {
1389
1390 if (status == WorkflowConstants.STATUS_ANY) {
1391 return journalArticlePersistence.findByCompanyId(
1392 companyId, start, end, new ArticleIDComparator(true));
1393 }
1394 else {
1395 return journalArticlePersistence.findByC_ST(
1396 companyId, status, start, end, new ArticleIDComparator(true));
1397 }
1398 }
1399
1400 public int getCompanyArticlesCount(
1401 long companyId, double version, int status, int start, int end)
1402 throws SystemException {
1403
1404 if (status == WorkflowConstants.STATUS_ANY) {
1405 return journalArticlePersistence.countByC_V(companyId, version);
1406 }
1407 else {
1408 return journalArticlePersistence.countByC_V_ST(
1409 companyId, version, status);
1410 }
1411 }
1412
1413 public int getCompanyArticlesCount(long companyId, int status)
1414 throws SystemException {
1415
1416 if (status == WorkflowConstants.STATUS_ANY) {
1417 return journalArticlePersistence.countByCompanyId(companyId);
1418 }
1419 else {
1420 return journalArticlePersistence.countByC_ST(companyId, status);
1421 }
1422 }
1423
1424 public JournalArticle getDisplayArticle(long groupId, String articleId)
1425 throws PortalException, SystemException {
1426
1427 List<JournalArticle> articles = journalArticlePersistence.findByG_A_ST(
1428 groupId, articleId, WorkflowConstants.STATUS_APPROVED);
1429
1430 if (articles.isEmpty()) {
1431 throw new NoSuchArticleException(
1432 "No approved JournalArticle exists with the key {groupId=" +
1433 groupId + ", " + "articleId=" + articleId + "}");
1434
1435 }
1436
1437 Date now = new Date();
1438
1439 for (int i = 0; i < articles.size(); i++) {
1440 JournalArticle article = articles.get(i);
1441
1442 Date expirationDate = article.getExpirationDate();
1443
1444 if (article.getDisplayDate().before(now) &&
1445 ((expirationDate == null) || expirationDate.after(now))) {
1446
1447 return article;
1448 }
1449 }
1450
1451 return articles.get(0);
1452 }
1453
1454 public JournalArticle getDisplayArticleByUrlTitle(
1455 long groupId, String urlTitle)
1456 throws PortalException, SystemException {
1457
1458 List<JournalArticle> articles = null;
1459
1460 OrderByComparator orderByComparator = new ArticleVersionComparator();
1461
1462 articles = journalArticlePersistence.findByG_UT_ST(
1463 groupId, urlTitle, WorkflowConstants.STATUS_APPROVED,
1464 QueryUtil.ALL_POS, QueryUtil.ALL_POS, orderByComparator);
1465
1466 if (articles.isEmpty()) {
1467 throw new NoSuchArticleException(
1468 "No JournalArticle exists with the key {groupId=" + groupId +
1469 ", urlTitle=" + urlTitle + "}");
1470 }
1471
1472 Date now = new Date();
1473
1474 for (JournalArticle article : articles) {
1475 Date expirationDate = article.getExpirationDate();
1476
1477 if (article.getDisplayDate().before(now) &&
1478 ((expirationDate == null) || expirationDate.after(now))) {
1479
1480 return article;
1481 }
1482 }
1483
1484 return articles.get(0);
1485 }
1486
1487 public JournalArticle getLatestArticle(long resourcePrimKey)
1488 throws PortalException, SystemException {
1489
1490 return getLatestArticle(resourcePrimKey, WorkflowConstants.STATUS_ANY);
1491 }
1492
1493 public JournalArticle getLatestArticle(long resourcePrimKey, int status)
1494 throws PortalException, SystemException {
1495
1496 return getLatestArticle(resourcePrimKey, status, true);
1497 }
1498
1499 public JournalArticle getLatestArticle(
1500 long resourcePrimKey, int status, boolean preferApproved)
1501 throws PortalException, SystemException {
1502
1503 List<JournalArticle> articles = null;
1504
1505 OrderByComparator orderByComparator = new ArticleVersionComparator();
1506
1507 if (status == WorkflowConstants.STATUS_ANY) {
1508 if (preferApproved) {
1509 articles = journalArticlePersistence.findByR_ST(
1510 resourcePrimKey, WorkflowConstants.STATUS_APPROVED, 0, 1,
1511 orderByComparator);
1512 }
1513
1514 if ((articles == null) || (articles.size() == 0)) {
1515 articles = journalArticlePersistence.findByResourcePrimKey(
1516 resourcePrimKey, 0, 1, orderByComparator);
1517 }
1518 }
1519 else {
1520 articles = journalArticlePersistence.findByR_ST(
1521 resourcePrimKey, status, 0, 1, orderByComparator);
1522 }
1523
1524 if (articles.isEmpty()) {
1525 throw new NoSuchArticleException(
1526 "No JournalArticle exists with the key {resourcePrimKey=" +
1527 resourcePrimKey + "}");
1528 }
1529
1530 return articles.get(0);
1531 }
1532
1533 public JournalArticle getLatestArticle(long groupId, String articleId)
1534 throws PortalException, SystemException {
1535
1536 return getLatestArticle(
1537 groupId, articleId, WorkflowConstants.STATUS_ANY);
1538 }
1539
1540 public JournalArticle getLatestArticle(
1541 long groupId, String articleId, int status)
1542 throws PortalException, SystemException {
1543
1544 List<JournalArticle> articles = null;
1545
1546 OrderByComparator orderByComparator = new ArticleVersionComparator();
1547
1548 if (status == WorkflowConstants.STATUS_ANY) {
1549 articles = journalArticlePersistence.findByG_A(
1550 groupId, articleId, 0, 1, orderByComparator);
1551 }
1552 else {
1553 articles = journalArticlePersistence.findByG_A_ST(
1554 groupId, articleId, status, 0, 1, orderByComparator);
1555 }
1556
1557 if (articles.isEmpty()) {
1558 throw new NoSuchArticleException(
1559 "No JournalArticle exists with the key {groupId=" + groupId +
1560 ", articleId=" + articleId + ", status=" + status + "}");
1561 }
1562
1563 return articles.get(0);
1564 }
1565
1566 public JournalArticle getLatestArticle(
1567 long groupId, String className, long classPK)
1568 throws PortalException, SystemException {
1569
1570 long classNameId = PortalUtil.getClassNameId(className);
1571
1572 List<JournalArticle> articles = journalArticlePersistence.findByG_C_C(
1573 groupId, classNameId, classPK, 0, 1,
1574 new ArticleVersionComparator());
1575
1576 if (articles.isEmpty()) {
1577 throw new NoSuchArticleException(
1578 "No JournalArticle exists with the key {groupId=" + groupId +
1579 ", className=" + className + ", classPK =" + classPK + "}");
1580 }
1581
1582 return articles.get(0);
1583 }
1584
1585 public JournalArticle getLatestArticleByUrlTitle(
1586 long groupId, String urlTitle, int status)
1587 throws PortalException, SystemException {
1588
1589 List<JournalArticle> articles = null;
1590
1591 OrderByComparator orderByComparator = new ArticleVersionComparator();
1592
1593 if (status == WorkflowConstants.STATUS_ANY) {
1594 articles = journalArticlePersistence.findByG_UT(
1595 groupId, urlTitle, 0, 1, orderByComparator);
1596 }
1597 else {
1598 articles = journalArticlePersistence.findByG_UT_ST(
1599 groupId, urlTitle, status, 0, 1, orderByComparator);
1600 }
1601
1602 if (articles.isEmpty()) {
1603 throw new NoSuchArticleException(
1604 "No JournalArticle exists with the key {groupId=" + groupId +
1605 ", urlTitle=" + urlTitle + ", status=" + status + "}");
1606 }
1607
1608 return articles.get(0);
1609 }
1610
1611 public double getLatestVersion(long groupId, String articleId)
1612 throws PortalException, SystemException {
1613
1614 JournalArticle article = getLatestArticle(groupId, articleId);
1615
1616 return article.getVersion();
1617 }
1618
1619 public double getLatestVersion(long groupId, String articleId, int status)
1620 throws PortalException, SystemException {
1621
1622 JournalArticle article = getLatestArticle(groupId, articleId, status);
1623
1624 return article.getVersion();
1625 }
1626
1627 public int getNotInTrashArticlesCount(long groupId, long folderId)
1628 throws SystemException {
1629
1630 return journalArticlePersistence.countByG_F_NotST(
1631 groupId, folderId, WorkflowConstants.STATUS_IN_TRASH);
1632 }
1633
1634 public List<JournalArticle> getStructureArticles(
1635 long groupId, String structureId)
1636 throws SystemException {
1637
1638 return journalArticlePersistence.findByG_S(groupId, structureId);
1639 }
1640
1641 public List<JournalArticle> getStructureArticles(
1642 long groupId, String structureId, int start, int end,
1643 OrderByComparator obc)
1644 throws SystemException {
1645
1646 return journalArticlePersistence.findByG_S(
1647 groupId, structureId, start, end, obc);
1648 }
1649
1650 public int getStructureArticlesCount(long groupId, String structureId)
1651 throws SystemException {
1652
1653 return journalArticlePersistence.countByG_S(groupId, structureId);
1654 }
1655
1656 public List<JournalArticle> getTemplateArticles(
1657 long groupId, String templateId)
1658 throws SystemException {
1659
1660 return journalArticlePersistence.findByG_T(groupId, templateId);
1661 }
1662
1663 public List<JournalArticle> getTemplateArticles(
1664 long groupId, String templateId, int start, int end,
1665 OrderByComparator obc)
1666 throws SystemException {
1667
1668 return journalArticlePersistence.findByG_T(
1669 groupId, templateId, start, end, obc);
1670 }
1671
1672 public int getTemplateArticlesCount(long groupId, String templateId)
1673 throws SystemException {
1674
1675 return journalArticlePersistence.countByG_T(groupId, templateId);
1676 }
1677
1678 public boolean hasArticle(long groupId, String articleId)
1679 throws SystemException {
1680
1681 try {
1682 getArticle(groupId, articleId);
1683
1684 return true;
1685 }
1686 catch (PortalException pe) {
1687 return false;
1688 }
1689 }
1690
1691 public boolean isLatestVersion(
1692 long groupId, String articleId, double version)
1693 throws PortalException, SystemException {
1694
1695 if (getLatestVersion(groupId, articleId) == version) {
1696 return true;
1697 }
1698 else {
1699 return false;
1700 }
1701 }
1702
1703 public boolean isLatestVersion(
1704 long groupId, String articleId, double version, int status)
1705 throws PortalException, SystemException {
1706
1707 if (getLatestVersion(groupId, articleId, status) == version) {
1708 return true;
1709 }
1710 else {
1711 return false;
1712 }
1713 }
1714
1715 public void moveArticle(long groupId, String articleId, long newFolderId)
1716 throws SystemException {
1717
1718 List<JournalArticle> articles = journalArticlePersistence.findByG_A(
1719 groupId, articleId);
1720
1721 for (JournalArticle article : articles) {
1722 article.setFolderId(newFolderId);
1723
1724 journalArticlePersistence.update(article);
1725 }
1726 }
1727
1728 public JournalArticle moveArticleToTrash(
1729 long userId, JournalArticle article)
1730 throws PortalException, SystemException {
1731
1732 List<JournalArticle> articleVersions =
1733 journalArticlePersistence.findByG_A(
1734 article.getGroupId(), article.getArticleId());
1735
1736 articleVersions = ListUtil.sort(
1737 articleVersions, new ArticleVersionComparator());
1738
1739 Map<String, Serializable> workflowContext =
1740 new HashMap<String, Serializable>();
1741
1742 workflowContext.put("articleVersions", (Serializable)articleVersions);
1743
1744 article = updateStatus(
1745 userId, article.getId(), WorkflowConstants.STATUS_IN_TRASH,
1746 workflowContext, new ServiceContext());
1747
1748
1749
1750 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1751 JournalArticle.class);
1752
1753 indexer.delete(article);
1754
1755 TrashEntry trashEntry = trashEntryLocalService.getEntry(
1756 JournalArticle.class.getName(), article.getResourcePrimKey());
1757
1758 String trashArticleId = TrashUtil.getTrashTitle(
1759 trashEntry.getEntryId());
1760
1761 if (!articleVersions.isEmpty()) {
1762 for (JournalArticle curArticleVersion : articleVersions) {
1763 curArticleVersion.setArticleId(trashArticleId);
1764
1765 journalArticlePersistence.update(curArticleVersion);
1766 }
1767 }
1768
1769 JournalArticleResource articleResource =
1770 journalArticleResourcePersistence.fetchByPrimaryKey(
1771 article.getResourcePrimKey());
1772
1773 articleResource.setArticleId(trashArticleId);
1774
1775 journalArticleResourcePersistence.update(articleResource);
1776
1777 article.setArticleId(trashArticleId);
1778
1779 reindex(article);
1780
1781 return journalArticlePersistence.update(article);
1782 }
1783
1784 public JournalArticle moveArticleToTrash(
1785 long userId, long groupId, String articleId)
1786 throws PortalException, SystemException {
1787
1788 List<JournalArticle> articles = journalArticlePersistence.findByG_A(
1789 groupId, articleId, 0, 1, new ArticleVersionComparator());
1790
1791 if (!articles.isEmpty()) {
1792 return moveArticleToTrash(userId, articles.get(0));
1793 }
1794
1795 return null;
1796 }
1797
1798 public JournalArticle removeArticleLocale(
1799 long groupId, String articleId, double version, String languageId)
1800 throws PortalException, SystemException {
1801
1802 JournalArticle article = journalArticlePersistence.findByG_A_V(
1803 groupId, articleId, version);
1804
1805 String title = article.getTitle();
1806
1807 title = LocalizationUtil.removeLocalization(
1808 title, "static-content", languageId, true);
1809
1810 article.setTitle(title);
1811
1812 String description = article.getDescription();
1813
1814 description = LocalizationUtil.removeLocalization(
1815 description, "static-content", languageId, true);
1816
1817 article.setDescription(description);
1818
1819 String content = article.getContent();
1820
1821 if (article.isTemplateDriven()) {
1822 content = JournalUtil.removeArticleLocale(content, languageId);
1823 }
1824 else {
1825 content = LocalizationUtil.removeLocalization(
1826 content, "static-content", languageId, true);
1827 }
1828
1829 article.setContent(content);
1830
1831 journalArticlePersistence.update(article);
1832
1833 return article;
1834 }
1835
1836 public void restoreArticleFromTrash(long userId, JournalArticle article)
1837 throws PortalException, SystemException {
1838
1839
1840
1841 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1842 JournalArticle.class);
1843
1844 indexer.delete(article);
1845
1846 String trashArticleId = TrashUtil.getOriginalTitle(
1847 article.getArticleId());
1848
1849 List<JournalArticle> articleVersions =
1850 journalArticlePersistence.findByG_A(
1851 article.getGroupId(), article.getArticleId());
1852
1853 if (!articleVersions.isEmpty()) {
1854 for (JournalArticle curArticleVersion : articleVersions) {
1855 curArticleVersion.setArticleId(trashArticleId);
1856
1857 journalArticlePersistence.update(curArticleVersion);
1858 }
1859 }
1860
1861 article.setArticleId(trashArticleId);
1862
1863 journalArticlePersistence.update(article);
1864
1865 JournalArticleResource articleResource =
1866 journalArticleResourcePersistence.fetchByPrimaryKey(
1867 article.getResourcePrimKey());
1868
1869 articleResource.setArticleId(trashArticleId);
1870
1871 journalArticleResourcePersistence.update(articleResource);
1872
1873 TrashEntry trashEntry = trashEntryLocalService.getEntry(
1874 JournalArticle.class.getName(), article.getResourcePrimKey());
1875
1876 Map<String, Serializable> workflowContext =
1877 new HashMap<String, Serializable>();
1878
1879 List<TrashVersion> trashVersions = trashEntryLocalService.getVersions(
1880 trashEntry.getEntryId());
1881
1882 workflowContext.put("trashVersions", (Serializable)trashVersions);
1883
1884 ServiceContext serviceContext = new ServiceContext();
1885
1886 serviceContext.setScopeGroupId(article.getGroupId());
1887
1888 updateStatus(
1889 userId, article, trashEntry.getStatus(), null, workflowContext,
1890 serviceContext);
1891 }
1892
1893 public List<JournalArticle> search(
1894 long companyId, long groupId, List<Long> folderIds,
1895 long classNameId, String keywords, Double version, String type,
1896 String structureId, String templateId, Date displayDateGT,
1897 Date displayDateLT, int status, Date reviewDate, int start, int end,
1898 OrderByComparator obc)
1899 throws SystemException {
1900
1901 return journalArticleFinder.findByKeywords(
1902 companyId, groupId, folderIds, classNameId, keywords, version, type,
1903 structureId, templateId, displayDateGT, displayDateLT, status,
1904 reviewDate, start, end, obc);
1905 }
1906
1907 public List<JournalArticle> search(
1908 long companyId, long groupId, List<Long> folderIds,
1909 long classNameId, String articleId, Double version, String title,
1910 String description, String content, String type, String structureId,
1911 String templateId, Date displayDateGT, Date displayDateLT,
1912 int status, Date reviewDate, boolean andOperator, int start,
1913 int end, OrderByComparator obc)
1914 throws SystemException {
1915
1916 QueryDefinition queryDefinition = new QueryDefinition(
1917 status, start, end, obc);
1918
1919 return journalArticleFinder.findByC_G_F_C_A_V_T_D_C_T_S_T_D_R(
1920 companyId, groupId, folderIds, classNameId, articleId, version,
1921 title, description, content, type, structureId, templateId,
1922 displayDateGT, displayDateLT, reviewDate, andOperator,
1923 queryDefinition);
1924 }
1925
1926 public List<JournalArticle> search(
1927 long companyId, long groupId, List<Long> folderIds,
1928 long classNameId, String articleId, Double version, String title,
1929 String description, String content, String type,
1930 String[] structureIds, String[] templateIds, Date displayDateGT,
1931 Date displayDateLT, int status, Date reviewDate,
1932 boolean andOperator, int start, int end, OrderByComparator obc)
1933 throws SystemException {
1934
1935 QueryDefinition queryDefinition = new QueryDefinition(
1936 status, start, end, obc);
1937
1938 return journalArticleFinder.findByC_G_F_C_A_V_T_D_C_T_S_T_D_R(
1939 companyId, groupId, folderIds, classNameId, articleId, version,
1940 title, description, content, type, structureIds, templateIds,
1941 displayDateGT, displayDateLT, reviewDate, andOperator,
1942 queryDefinition);
1943 }
1944
1945 public Hits search(
1946 long companyId, long groupId, List<Long> folderIds,
1947 long classNameId, String structureId, String templateId,
1948 String keywords, LinkedHashMap<String, Object> params, int start,
1949 int end, Sort sort)
1950 throws SystemException {
1951
1952 String articleId = null;
1953 String title = null;
1954 String description = null;
1955 String content = null;
1956 boolean andOperator = false;
1957
1958 if (Validator.isNotNull(keywords)) {
1959 articleId = keywords;
1960 title = keywords;
1961 description = keywords;
1962 content = keywords;
1963 }
1964 else {
1965 andOperator = true;
1966 }
1967
1968 String status = String.valueOf(WorkflowConstants.STATUS_ANY);
1969
1970 if (params != null) {
1971 params.put("keywords", keywords);
1972 }
1973
1974 return search(
1975 companyId, groupId, folderIds, classNameId, articleId, title,
1976 description, content, null, status, structureId, templateId, params,
1977 andOperator, start, end, sort);
1978 }
1979
1980 public Hits search(
1981 long companyId, long groupId, List<Long> folderIds,
1982 long classNameId, String articleId, String title,
1983 String description, String content, String type, String status,
1984 String structureId, String templateId,
1985 LinkedHashMap<String, Object> params, boolean andSearch, int start,
1986 int end, Sort sort)
1987 throws SystemException {
1988
1989 try {
1990 SearchContext searchContext = new SearchContext();
1991
1992 searchContext.setAndSearch(andSearch);
1993
1994 Map<String, Serializable> attributes =
1995 new HashMap<String, Serializable>();
1996
1997 attributes.put(Field.CLASS_NAME_ID, classNameId);
1998 attributes.put(Field.CONTENT, content);
1999 attributes.put(Field.DESCRIPTION, description);
2000 attributes.put(Field.STATUS, status);
2001 attributes.put(Field.TITLE, title);
2002 attributes.put(Field.TYPE, type);
2003 attributes.put("articleId", articleId);
2004 attributes.put("ddmStructureKey", structureId);
2005 attributes.put("ddmTemplateKey", templateId);
2006 attributes.put("params", params);
2007
2008 searchContext.setAttributes(attributes);
2009
2010 searchContext.setCompanyId(companyId);
2011 searchContext.setEnd(end);
2012 searchContext.setFolderIds(folderIds);
2013 searchContext.setGroupIds(new long[] {groupId});
2014 searchContext.setIncludeDiscussions(
2015 GetterUtil.getBoolean(params.get("includeDiscussions")));
2016
2017 if (params != null) {
2018 String keywords = (String)params.remove("keywords");
2019
2020 if (Validator.isNotNull(keywords)) {
2021 searchContext.setKeywords(keywords);
2022 }
2023 }
2024
2025 QueryConfig queryConfig = new QueryConfig();
2026
2027 queryConfig.setHighlightEnabled(false);
2028 queryConfig.setScoreEnabled(false);
2029
2030 searchContext.setQueryConfig(queryConfig);
2031
2032 if (sort != null) {
2033 searchContext.setSorts(new Sort[] {sort});
2034 }
2035
2036 searchContext.setStart(start);
2037
2038 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2039 JournalArticle.class);
2040
2041 return indexer.search(searchContext);
2042 }
2043 catch (Exception e) {
2044 throw new SystemException(e);
2045 }
2046 }
2047
2048 public int searchCount(
2049 long companyId, long groupId, List<Long> folderIds,
2050 long classNameId, String keywords, Double version, String type,
2051 String structureId, String templateId, Date displayDateGT,
2052 Date displayDateLT, int status, Date reviewDate)
2053 throws SystemException {
2054
2055 return journalArticleFinder.countByKeywords(
2056 companyId, groupId, folderIds, classNameId, keywords, version, type,
2057 structureId, templateId, displayDateGT, displayDateLT, status,
2058 reviewDate);
2059 }
2060
2061 public int searchCount(
2062 long companyId, long groupId, List<Long> folderIds,
2063 long classNameId, String articleId, Double version, String title,
2064 String description, String content, String type, String structureId,
2065 String templateId, Date displayDateGT, Date displayDateLT,
2066 int status, Date reviewDate, boolean andOperator)
2067 throws SystemException {
2068
2069 return journalArticleFinder.countByC_G_F_C_A_V_T_D_C_T_S_T_D_R(
2070 companyId, groupId, folderIds, classNameId, articleId, version,
2071 title, description, content, type, structureId, templateId,
2072 displayDateGT, displayDateLT, reviewDate, andOperator,
2073 new QueryDefinition(status));
2074 }
2075
2076 public int searchCount(
2077 long companyId, long groupId, List<Long> folderIds,
2078 long classNameId, String articleId, Double version, String title,
2079 String description, String content, String type,
2080 String[] structureIds, String[] templateIds, Date displayDateGT,
2081 Date displayDateLT, int status, Date reviewDate,
2082 boolean andOperator)
2083 throws SystemException {
2084
2085 return journalArticleFinder.countByC_G_F_C_A_V_T_D_C_T_S_T_D_R(
2086 companyId, groupId, folderIds, classNameId, articleId, version,
2087 title, description, content, type, structureIds, templateIds,
2088 displayDateGT, displayDateLT, reviewDate, andOperator,
2089 new QueryDefinition(status));
2090 }
2091
2092 public void subscribe(long userId, long groupId)
2093 throws PortalException, SystemException {
2094
2095 subscriptionLocalService.addSubscription(
2096 userId, groupId, JournalArticle.class.getName(), groupId);
2097 }
2098
2099 public void unsubscribe(long userId, long groupId)
2100 throws PortalException, SystemException {
2101
2102 subscriptionLocalService.deleteSubscription(
2103 userId, JournalArticle.class.getName(), groupId);
2104 }
2105
2106 public JournalArticle updateArticle(
2107 long userId, long groupId, long folderId, String articleId,
2108 double version, Map<Locale, String> titleMap,
2109 Map<Locale, String> descriptionMap, String content,
2110 String layoutUuid, ServiceContext serviceContext)
2111 throws PortalException, SystemException {
2112
2113 User user = userPersistence.findByPrimaryKey(userId);
2114
2115 JournalArticle article = journalArticlePersistence.findByG_A_V(
2116 groupId, articleId, version);
2117
2118 Date displayDate = article.getDisplayDate();
2119
2120 int displayDateMonth = 0;
2121 int displayDateDay = 0;
2122 int displayDateYear = 0;
2123 int displayDateHour = 0;
2124 int displayDateMinute = 0;
2125
2126 if (displayDate != null) {
2127 Calendar displayCal = CalendarFactoryUtil.getCalendar(
2128 user.getTimeZone());
2129
2130 displayCal.setTime(displayDate);
2131
2132 displayDateMonth = displayCal.get(Calendar.MONTH);
2133 displayDateDay = displayCal.get(Calendar.DATE);
2134 displayDateYear = displayCal.get(Calendar.YEAR);
2135 displayDateHour = displayCal.get(Calendar.HOUR);
2136 displayDateMinute = displayCal.get(Calendar.MINUTE);
2137
2138 if (displayCal.get(Calendar.AM_PM) == Calendar.PM) {
2139 displayDateHour += 12;
2140 }
2141 }
2142
2143 Date expirationDate = article.getExpirationDate();
2144
2145 int expirationDateMonth = 0;
2146 int expirationDateDay = 0;
2147 int expirationDateYear = 0;
2148 int expirationDateHour = 0;
2149 int expirationDateMinute = 0;
2150 boolean neverExpire = true;
2151
2152 if (expirationDate != null) {
2153 Calendar expirationCal = CalendarFactoryUtil.getCalendar(
2154 user.getTimeZone());
2155
2156 expirationCal.setTime(expirationDate);
2157
2158 expirationDateMonth = expirationCal.get(Calendar.MONTH);
2159 expirationDateDay = expirationCal.get(Calendar.DATE);
2160 expirationDateYear = expirationCal.get(Calendar.YEAR);
2161 expirationDateHour = expirationCal.get(Calendar.HOUR);
2162 expirationDateMinute = expirationCal.get(Calendar.MINUTE);
2163 neverExpire = false;
2164
2165 if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
2166 expirationDateHour += 12;
2167 }
2168 }
2169
2170 Date reviewDate = article.getReviewDate();
2171
2172 int reviewDateMonth = 0;
2173 int reviewDateDay = 0;
2174 int reviewDateYear = 0;
2175 int reviewDateHour = 0;
2176 int reviewDateMinute = 0;
2177 boolean neverReview = true;
2178
2179 if (reviewDate != null) {
2180 Calendar reviewCal = CalendarFactoryUtil.getCalendar(
2181 user.getTimeZone());
2182
2183 reviewCal.setTime(reviewDate);
2184
2185 reviewDateMonth = reviewCal.get(Calendar.MONTH);
2186 reviewDateDay = reviewCal.get(Calendar.DATE);
2187 reviewDateYear = reviewCal.get(Calendar.YEAR);
2188 reviewDateHour = reviewCal.get(Calendar.HOUR);
2189 reviewDateMinute = reviewCal.get(Calendar.MINUTE);
2190 neverReview = false;
2191
2192 if (reviewCal.get(Calendar.AM_PM) == Calendar.PM) {
2193 reviewDateHour += 12;
2194 }
2195 }
2196
2197 return updateArticle(
2198 userId, groupId, folderId, articleId, version, titleMap,
2199 descriptionMap, content, article.getType(),
2200 article.getStructureId(), article.getTemplateId(), layoutUuid,
2201 displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
2202 displayDateMinute, expirationDateMonth, expirationDateDay,
2203 expirationDateYear, expirationDateHour, expirationDateMinute,
2204 neverExpire, reviewDateMonth, reviewDateDay, reviewDateYear,
2205 reviewDateHour, reviewDateMinute, neverReview,
2206 article.getIndexable(), article.isSmallImage(),
2207 article.getSmallImageURL(), null, null, null, serviceContext);
2208 }
2209
2210 public JournalArticle updateArticle(
2211 long userId, long groupId, long folderId, String articleId,
2212 double version, Map<Locale, String> titleMap,
2213 Map<Locale, String> descriptionMap, String content, String type,
2214 String structureId, String templateId, String layoutUuid,
2215 int displayDateMonth, int displayDateDay, int displayDateYear,
2216 int displayDateHour, int displayDateMinute, int expirationDateMonth,
2217 int expirationDateDay, int expirationDateYear,
2218 int expirationDateHour, int expirationDateMinute,
2219 boolean neverExpire, int reviewDateMonth, int reviewDateDay,
2220 int reviewDateYear, int reviewDateHour, int reviewDateMinute,
2221 boolean neverReview, boolean indexable, boolean smallImage,
2222 String smallImageURL, File smallImageFile,
2223 Map<String, byte[]> images, String articleURL,
2224 ServiceContext serviceContext)
2225 throws PortalException, SystemException {
2226
2227
2228
2229 User user = userPersistence.findByPrimaryKey(userId);
2230 articleId = articleId.trim().toUpperCase();
2231
2232 byte[] smallImageBytes = null;
2233
2234 try {
2235 smallImageBytes = FileUtil.getBytes(smallImageFile);
2236 }
2237 catch (IOException ioe) {
2238 }
2239
2240 JournalArticle latestArticle = getLatestArticle(
2241 groupId, articleId, WorkflowConstants.STATUS_ANY);
2242
2243 JournalArticle article = latestArticle;
2244
2245 boolean imported = ExportImportThreadLocal.isImportInProcess();
2246
2247 double latestVersion = latestArticle.getVersion();
2248
2249 boolean addNewVersion = false;
2250
2251 if (imported) {
2252 if (latestVersion > version) {
2253 JournalArticle existingArticle =
2254 journalArticlePersistence.fetchByG_A_V(
2255 groupId, articleId, version);
2256
2257 if (existingArticle != null) {
2258 article = existingArticle;
2259 }
2260 else {
2261 addNewVersion = true;
2262 }
2263 }
2264 else if (latestVersion < version) {
2265 addNewVersion = true;
2266 }
2267 }
2268 else {
2269 if ((version > 0) && (version != latestVersion)) {
2270 throw new ArticleVersionException();
2271 }
2272
2273 serviceContext.validateModifiedDate(
2274 latestArticle, ArticleVersionException.class);
2275
2276 if (latestArticle.isApproved() || latestArticle.isExpired()) {
2277 addNewVersion = true;
2278
2279 version = MathUtil.format(latestVersion + 0.1, 1, 1);
2280 }
2281 }
2282
2283 Date displayDate = null;
2284 Date expirationDate = null;
2285 Date reviewDate = null;
2286
2287 if (article.getClassNameId() ==
2288 JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
2289
2290 displayDate = PortalUtil.getDate(
2291 displayDateMonth, displayDateDay, displayDateYear,
2292 displayDateHour, displayDateMinute, user.getTimeZone(),
2293 ArticleDisplayDateException.class);
2294
2295 if (!neverExpire) {
2296 expirationDate = PortalUtil.getDate(
2297 expirationDateMonth, expirationDateDay, expirationDateYear,
2298 expirationDateHour, expirationDateMinute,
2299 user.getTimeZone(), ArticleExpirationDateException.class);
2300 }
2301
2302 if (!neverReview) {
2303 reviewDate = PortalUtil.getDate(
2304 reviewDateMonth, reviewDateDay, reviewDateYear,
2305 reviewDateHour, reviewDateMinute, user.getTimeZone(),
2306 ArticleReviewDateException.class);
2307 }
2308 }
2309
2310 Date now = new Date();
2311
2312 boolean expired = false;
2313
2314 if ((expirationDate != null) && expirationDate.before(now)) {
2315 expired = true;
2316 }
2317
2318 validate(
2319 user.getCompanyId(), groupId, latestArticle.getClassNameId(),
2320 titleMap, content, type, structureId, templateId, expirationDate,
2321 smallImage, smallImageURL, smallImageFile, smallImageBytes);
2322
2323 if (addNewVersion) {
2324 long id = counterLocalService.increment();
2325
2326 article = journalArticlePersistence.create(id);
2327
2328 article.setResourcePrimKey(latestArticle.getResourcePrimKey());
2329 article.setGroupId(latestArticle.getGroupId());
2330 article.setCompanyId(latestArticle.getCompanyId());
2331 article.setUserId(user.getUserId());
2332 article.setUserName(user.getFullName());
2333 article.setCreateDate(serviceContext.getModifiedDate(now));
2334 article.setClassNameId(latestArticle.getClassNameId());
2335 article.setClassPK(latestArticle.getClassPK());
2336 article.setArticleId(articleId);
2337 article.setVersion(version);
2338 article.setSmallImageId(latestArticle.getSmallImageId());
2339 }
2340
2341 Locale locale = LocaleUtil.getDefault();
2342
2343 String defaultLanguageId = ParamUtil.getString(
2344 serviceContext, "defaultLanguageId");
2345
2346 if (Validator.isNull(defaultLanguageId)) {
2347 defaultLanguageId = LocalizationUtil.getDefaultLocale(content);
2348 }
2349
2350 if (Validator.isNotNull(defaultLanguageId)) {
2351 locale = LocaleUtil.fromLanguageId(defaultLanguageId);
2352 }
2353
2354 String title = titleMap.get(locale);
2355
2356 content = format(
2357 user, groupId, articleId, article.getVersion(), addNewVersion,
2358 content, structureId, images);
2359
2360 article.setModifiedDate(serviceContext.getModifiedDate(now));
2361 article.setFolderId(folderId);
2362 article.setTitleMap(titleMap, locale);
2363 article.setUrlTitle(
2364 getUniqueUrlTitle(
2365 article.getId(), article.getArticleId(), title,
2366 latestArticle.getUrlTitle(), serviceContext));
2367 article.setDescriptionMap(descriptionMap, locale);
2368 article.setContent(content);
2369 article.setType(type);
2370 article.setStructureId(structureId);
2371 article.setTemplateId(templateId);
2372 article.setLayoutUuid(layoutUuid);
2373 article.setDisplayDate(displayDate);
2374 article.setExpirationDate(expirationDate);
2375 article.setReviewDate(reviewDate);
2376 article.setIndexable(indexable);
2377 article.setSmallImage(smallImage);
2378
2379 if (smallImage) {
2380 if ((smallImageFile != null) && (smallImageBytes != null)) {
2381 article.setSmallImageId(counterLocalService.increment());
2382 }
2383 }
2384 else {
2385 article.setSmallImageId(0);
2386 }
2387
2388 article.setSmallImageURL(smallImageURL);
2389
2390 if (latestArticle.isPending()) {
2391 article.setStatus(latestArticle.getStatus());
2392 }
2393 else if (!expired) {
2394 article.setStatus(WorkflowConstants.STATUS_DRAFT);
2395 }
2396 else {
2397 article.setStatus(WorkflowConstants.STATUS_EXPIRED);
2398 }
2399
2400 journalArticlePersistence.update(article);
2401
2402
2403
2404 updateAsset(
2405 userId, article, serviceContext.getAssetCategoryIds(),
2406 serviceContext.getAssetTagNames(),
2407 serviceContext.getAssetLinkEntryIds());
2408
2409
2410
2411 if (PortalUtil.getClassNameId(DDMStructure.class) ==
2412 article.getClassNameId()) {
2413
2414 updateDDMStructureXSD(
2415 article.getClassPK(), content, serviceContext);
2416 }
2417
2418
2419
2420 ExpandoBridge expandoBridge = article.getExpandoBridge();
2421
2422 expandoBridge.setAttributes(serviceContext);
2423
2424
2425
2426 saveImages(
2427 smallImage, article.getSmallImageId(), smallImageFile,
2428 smallImageBytes);
2429
2430
2431
2432 PortletPreferences preferences =
2433 ServiceContextUtil.getPortletPreferences(serviceContext);
2434
2435
2436
2437 if (expired && imported) {
2438 updateStatus(
2439 userId, article, article.getStatus(), articleURL,
2440 new HashMap<String, Serializable>(), serviceContext);
2441 }
2442
2443 if (serviceContext.getWorkflowAction() ==
2444 WorkflowConstants.ACTION_PUBLISH) {
2445
2446 sendEmail(
2447 article, articleURL, preferences, "requested", serviceContext);
2448
2449 WorkflowHandlerRegistryUtil.startWorkflowInstance(
2450 user.getCompanyId(), groupId, userId,
2451 JournalArticle.class.getName(), article.getId(), article,
2452 serviceContext);
2453 }
2454 else if (article.getVersion() ==
2455 JournalArticleConstants.VERSION_DEFAULT) {
2456
2457
2458
2459 reindex(article);
2460 }
2461
2462 return article;
2463 }
2464
2465 public JournalArticle updateArticle(
2466 long userId, long groupId, long folderId, String articleId,
2467 double version, String content, ServiceContext serviceContext)
2468 throws PortalException, SystemException {
2469
2470 JournalArticle article = journalArticlePersistence.findByG_A_V(
2471 groupId, articleId, version);
2472
2473 return updateArticle(
2474 userId, groupId, folderId, articleId, version,
2475 article.getTitleMap(), article.getDescriptionMap(), content,
2476 article.getLayoutUuid(), serviceContext);
2477 }
2478
2479
2483 public JournalArticle updateArticleTranslation(
2484 long groupId, String articleId, double version, Locale locale,
2485 String title, String description, String content,
2486 Map<String, byte[]> images)
2487 throws PortalException, SystemException {
2488
2489 return updateArticleTranslation(
2490 groupId, articleId, version, locale, title, description, content,
2491 images, null);
2492 }
2493
2494 public JournalArticle updateArticleTranslation(
2495 long groupId, String articleId, double version, Locale locale,
2496 String title, String description, String content,
2497 Map<String, byte[]> images, ServiceContext serviceContext)
2498 throws PortalException, SystemException {
2499
2500 validateContent(content);
2501
2502 JournalArticle oldArticle = getLatestArticle(
2503 groupId, articleId, WorkflowConstants.STATUS_ANY);
2504
2505 double oldVersion = oldArticle.getVersion();
2506
2507 if ((version > 0) && (version != oldVersion)) {
2508 throw new ArticleVersionException();
2509 }
2510
2511 boolean incrementVersion = false;
2512
2513 if (oldArticle.isApproved() || oldArticle.isExpired()) {
2514 incrementVersion = true;
2515 }
2516
2517 if (serviceContext != null) {
2518 serviceContext.validateModifiedDate(
2519 oldArticle, ArticleVersionException.class);
2520 }
2521
2522 JournalArticle article = null;
2523
2524 User user = userPersistence.findByPrimaryKey(oldArticle.getUserId());
2525
2526 if (incrementVersion) {
2527 double newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
2528
2529 long id = counterLocalService.increment();
2530
2531 article = journalArticlePersistence.create(id);
2532
2533 article.setResourcePrimKey(oldArticle.getResourcePrimKey());
2534 article.setGroupId(oldArticle.getGroupId());
2535 article.setCompanyId(oldArticle.getCompanyId());
2536 article.setUserId(oldArticle.getUserId());
2537 article.setUserName(user.getFullName());
2538 article.setCreateDate(new Date());
2539 article.setModifiedDate(new Date());
2540 article.setClassNameId(oldArticle.getClassNameId());
2541 article.setClassPK(oldArticle.getClassPK());
2542 article.setArticleId(articleId);
2543 article.setVersion(newVersion);
2544 article.setTitleMap(oldArticle.getTitleMap());
2545 article.setUrlTitle(
2546 getUniqueUrlTitle(
2547 id, articleId, title, oldArticle.getUrlTitle(),
2548 serviceContext));
2549 article.setDescriptionMap(oldArticle.getDescriptionMap());
2550 article.setType(oldArticle.getType());
2551 article.setStructureId(oldArticle.getStructureId());
2552 article.setTemplateId(oldArticle.getTemplateId());
2553 article.setLayoutUuid(oldArticle.getLayoutUuid());
2554 article.setDisplayDate(oldArticle.getDisplayDate());
2555 article.setExpirationDate(oldArticle.getExpirationDate());
2556 article.setReviewDate(oldArticle.getReviewDate());
2557 article.setIndexable(oldArticle.getIndexable());
2558 article.setSmallImage(oldArticle.getSmallImage());
2559 article.setSmallImageId(oldArticle.getSmallImageId());
2560
2561 if (article.getSmallImageId() == 0) {
2562 article.setSmallImageId(counterLocalService.increment());
2563 }
2564
2565 article.setSmallImageURL(oldArticle.getSmallImageURL());
2566
2567 article.setStatus(WorkflowConstants.STATUS_DRAFT);
2568 article.setStatusDate(new Date());
2569 }
2570 else {
2571 article = oldArticle;
2572 }
2573
2574 Map<Locale, String> titleMap = article.getTitleMap();
2575
2576 titleMap.put(locale, title);
2577
2578 article.setTitleMap(titleMap);
2579
2580 Map<Locale, String> descriptionMap = article.getDescriptionMap();
2581
2582 descriptionMap.put(locale, description);
2583
2584 article.setDescriptionMap(descriptionMap);
2585
2586 content = format(
2587 user, groupId, articleId, article.getVersion(),
2588 !oldArticle.isDraft(), content, oldArticle.getStructureId(),
2589 images);
2590
2591 article.setContent(content);
2592
2593 journalArticlePersistence.update(article);
2594
2595 return article;
2596 }
2597
2598 public void updateAsset(
2599 long userId, JournalArticle article, long[] assetCategoryIds,
2600 String[] assetTagNames, long[] assetLinkEntryIds)
2601 throws PortalException, SystemException {
2602
2603 boolean visible = article.isApproved();
2604
2605 if (article.getClassNameId() !=
2606 JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
2607
2608 visible = false;
2609 }
2610
2611 boolean addDraftAssetEntry = false;
2612
2613 if (!article.isApproved() &&
2614 (article.getVersion() != JournalArticleConstants.VERSION_DEFAULT)) {
2615
2616 int approvedArticlesCount = journalArticlePersistence.countByG_A_ST(
2617 article.getGroupId(), article.getArticleId(),
2618 JournalArticleConstants.ASSET_ENTRY_CREATION_STATUSES);
2619
2620 if (approvedArticlesCount > 0) {
2621 addDraftAssetEntry = true;
2622 }
2623 }
2624
2625 AssetEntry assetEntry = null;
2626
2627 if (addDraftAssetEntry) {
2628 assetEntry = assetEntryLocalService.updateEntry(
2629 userId, article.getGroupId(), article.getCreateDate(),
2630 article.getModifiedDate(), JournalArticle.class.getName(),
2631 article.getPrimaryKey(), article.getUuid(),
2632 getClassTypeId(article), assetCategoryIds, assetTagNames, false,
2633 null, null, null, ContentTypes.TEXT_HTML, article.getTitle(),
2634 article.getDescription(), article.getDescription(), null,
2635 article.getLayoutUuid(), 0, 0, null, false);
2636 }
2637 else {
2638 JournalArticleResource journalArticleResource =
2639 journalArticleResourceLocalService.getArticleResource(
2640 article.getResourcePrimKey());
2641
2642 assetEntry = assetEntryLocalService.updateEntry(
2643 userId, article.getGroupId(), article.getCreateDate(),
2644 article.getModifiedDate(), JournalArticle.class.getName(),
2645 journalArticleResource.getResourcePrimKey(),
2646 journalArticleResource.getUuid(), getClassTypeId(article),
2647 assetCategoryIds, assetTagNames, visible, null, null, null,
2648 ContentTypes.TEXT_HTML, article.getTitle(),
2649 article.getDescription(), article.getDescription(), null,
2650 article.getLayoutUuid(), 0, 0, null, false);
2651 }
2652
2653 assetLinkLocalService.updateLinks(
2654 userId, assetEntry.getEntryId(), assetLinkEntryIds,
2655 AssetLinkConstants.TYPE_RELATED);
2656 }
2657
2658 public JournalArticle updateContent(
2659 long groupId, String articleId, double version, String content)
2660 throws PortalException, SystemException {
2661
2662 JournalArticle article = journalArticlePersistence.findByG_A_V(
2663 groupId, articleId, version);
2664
2665 article.setContent(content);
2666
2667 journalArticlePersistence.update(article);
2668
2669 return article;
2670 }
2671
2672 public JournalArticle updateStatus(
2673 long userId, JournalArticle article, int status, String articleURL,
2674 Map<String, Serializable> workflowContext,
2675 ServiceContext serviceContext)
2676 throws PortalException, SystemException {
2677
2678
2679
2680 User user = userPersistence.findByPrimaryKey(userId);
2681 Date now = new Date();
2682
2683 int oldStatus = article.getStatus();
2684
2685 int oldArticleVersionStatus = WorkflowConstants.STATUS_ANY;
2686
2687 List<ObjectValuePair<Long, Integer>> articleVersionStatusOVPs =
2688 new ArrayList<ObjectValuePair<Long, Integer>>();
2689
2690 List<JournalArticle> articleVersions =
2691 (List<JournalArticle>)workflowContext.get("articleVersions");
2692
2693 if ((articleVersions != null) && !articleVersions.isEmpty()) {
2694 JournalArticle oldArticleVersion = articleVersions.get(0);
2695
2696 oldArticleVersionStatus = oldArticleVersion.getStatus();
2697
2698 articleVersionStatusOVPs = getArticleVersionStatuses(
2699 articleVersions);
2700 }
2701
2702 article.setModifiedDate(serviceContext.getModifiedDate(now));
2703
2704 boolean neverExpire = false;
2705
2706 if (status == WorkflowConstants.STATUS_APPROVED) {
2707 Date expirationDate = article.getExpirationDate();
2708
2709 if ((expirationDate != null) && expirationDate.before(now)) {
2710 neverExpire = true;
2711
2712 article.setExpirationDate(null);
2713 }
2714 }
2715
2716 if (status == WorkflowConstants.STATUS_EXPIRED) {
2717 article.setExpirationDate(now);
2718 }
2719
2720 article.setStatus(status);
2721 article.setStatusByUserId(user.getUserId());
2722 article.setStatusByUserName(user.getFullName());
2723 article.setStatusDate(serviceContext.getModifiedDate(now));
2724
2725 journalArticlePersistence.update(article);
2726
2727 if (hasModifiedLatestApprovedVersion(
2728 article.getGroupId(), article.getArticleId(),
2729 article.getVersion())) {
2730
2731 if (status == WorkflowConstants.STATUS_APPROVED) {
2732 updateUrlTitles(
2733 article.getGroupId(), article.getArticleId(),
2734 article.getUrlTitle());
2735
2736
2737
2738 if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
2739 (article.getVersion() !=
2740 JournalArticleConstants.VERSION_DEFAULT)) {
2741
2742 AssetEntry draftAssetEntry = null;
2743
2744 try {
2745 draftAssetEntry = assetEntryLocalService.getEntry(
2746 JournalArticle.class.getName(),
2747 article.getPrimaryKey());
2748
2749 long[] assetCategoryIds =
2750 draftAssetEntry.getCategoryIds();
2751 String[] assetTagNames = draftAssetEntry.getTagNames();
2752
2753 List<AssetLink> assetLinks =
2754 assetLinkLocalService.getDirectLinks(
2755 draftAssetEntry.getEntryId(),
2756 AssetLinkConstants.TYPE_RELATED);
2757
2758 long[] assetLinkEntryIds = StringUtil.split(
2759 ListUtil.toString(
2760 assetLinks, AssetLink.ENTRY_ID2_ACCESSOR), 0L);
2761
2762 AssetEntry assetEntry =
2763 assetEntryLocalService.updateEntry(
2764 userId, article.getGroupId(),
2765 article.getCreateDate(),
2766 article.getModifiedDate(),
2767 JournalArticle.class.getName(),
2768 article.getResourcePrimKey(), article.getUuid(),
2769 getClassTypeId(article), assetCategoryIds,
2770 assetTagNames, false, null, null, null,
2771 ContentTypes.TEXT_HTML, article.getTitle(),
2772 article.getDescription(),
2773 article.getDescription(), null,
2774 article.getLayoutUuid(), 0, 0, null, false);
2775
2776 assetLinkLocalService.updateLinks(
2777 userId, assetEntry.getEntryId(), assetLinkEntryIds,
2778 AssetLinkConstants.TYPE_RELATED);
2779
2780 assetEntryLocalService.deleteEntry(
2781 JournalArticle.class.getName(),
2782 article.getPrimaryKey());
2783 }
2784 catch (NoSuchEntryException nsee) {
2785 }
2786 }
2787
2788 if (article.getClassNameId() ==
2789 JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
2790
2791
2792
2793
2794 Date[] dateInterval = getDateInterval(
2795 article.getGroupId(), article.getArticleId(),
2796 article.getDisplayDate(), article.getExpirationDate());
2797
2798 Date displayDate = dateInterval[0];
2799 Date expirationDate = dateInterval[1];
2800
2801 if (neverExpire) {
2802 expirationDate = null;
2803 }
2804
2805 assetEntryLocalService.updateEntry(
2806 JournalArticle.class.getName(),
2807 article.getResourcePrimKey(), displayDate,
2808 expirationDate, true);
2809 }
2810
2811
2812
2813 if (serviceContext.isCommandUpdate()) {
2814 socialActivityLocalService.addActivity(
2815 user.getUserId(), article.getGroupId(),
2816 JournalArticle.class.getName(), article.getId(),
2817 JournalActivityKeys.UPDATE_ARTICLE,
2818 getExtraDataJSON(article, serviceContext), 0);
2819 }
2820 else {
2821 socialActivityLocalService.addUniqueActivity(
2822 user.getUserId(), article.getGroupId(),
2823 JournalArticle.class.getName(), article.getId(),
2824 JournalActivityKeys.ADD_ARTICLE,
2825 getExtraDataJSON(article, serviceContext), 0);
2826 }
2827
2828
2829
2830 reindex(article);
2831 }
2832 else if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
2833 updatePreviousApprovedArticle(article);
2834 }
2835 }
2836
2837 if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
2838
2839
2840
2841 if (serviceContext.isCommandUpdate()) {
2842 socialActivityLocalService.addActivity(
2843 user.getUserId(), article.getGroupId(),
2844 JournalArticle.class.getName(), article.getId(),
2845 JournalActivityKeys.UPDATE_ARTICLE,
2846 getExtraDataJSON(article, serviceContext), 0);
2847 }
2848 else {
2849 socialActivityLocalService.addUniqueActivity(
2850 user.getUserId(), article.getGroupId(),
2851 JournalArticle.class.getName(), article.getId(),
2852 JournalActivityKeys.ADD_ARTICLE,
2853 getExtraDataJSON(article, serviceContext), 0);
2854 }
2855
2856
2857
2858 List<TrashVersion> trashVersions =
2859 (List<TrashVersion>)workflowContext.get("trashVersions");
2860
2861 for (TrashVersion trashVersion : trashVersions) {
2862 JournalArticle trashArticleVersion =
2863 journalArticlePersistence.findByPrimaryKey(
2864 trashVersion.getClassPK());
2865
2866 trashArticleVersion.setStatus(trashVersion.getStatus());
2867
2868 journalArticlePersistence.update(trashArticleVersion);
2869 }
2870
2871 trashEntryLocalService.deleteEntry(
2872 JournalArticle.class.getName(), article.getResourcePrimKey());
2873
2874
2875
2876 if (status == WorkflowConstants.STATUS_APPROVED) {
2877 reindex(article);
2878 }
2879 else {
2880 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2881 JournalArticle.class);
2882
2883 indexer.delete(article);
2884 }
2885
2886 }
2887 else if (status == WorkflowConstants.STATUS_IN_TRASH) {
2888 assetEntryLocalService.updateVisible(
2889 JournalArticle.class.getName(), article.getResourcePrimKey(),
2890 false);
2891
2892
2893
2894 for (JournalArticle curArticleVersion : articleVersions) {
2895 curArticleVersion.setStatus(WorkflowConstants.STATUS_IN_TRASH);
2896
2897 journalArticlePersistence.update(curArticleVersion);
2898 }
2899
2900 UnicodeProperties typeSettingsProperties = new UnicodeProperties();
2901
2902 typeSettingsProperties.put("title", article.getArticleId());
2903
2904 trashEntryLocalService.addTrashEntry(
2905 userId, article.getGroupId(), JournalArticle.class.getName(),
2906 article.getResourcePrimKey(), oldArticleVersionStatus,
2907 articleVersionStatusOVPs, typeSettingsProperties);
2908
2909
2910
2911 reindex(article);
2912 }
2913
2914 if ((article.getClassNameId() ==
2915 JournalArticleConstants.CLASSNAME_ID_DEFAULT) &&
2916 (oldStatus != WorkflowConstants.STATUS_IN_TRASH) &&
2917 (status != WorkflowConstants.STATUS_IN_TRASH)) {
2918
2919
2920
2921 if ((oldStatus == WorkflowConstants.STATUS_PENDING) &&
2922 ((status == WorkflowConstants.STATUS_APPROVED) ||
2923 (status == WorkflowConstants.STATUS_DENIED))) {
2924
2925 String msg = "granted";
2926
2927 if (status == WorkflowConstants.STATUS_DENIED) {
2928 msg = "denied";
2929 }
2930
2931 try {
2932 PortletPreferences preferences =
2933 ServiceContextUtil.getPortletPreferences(
2934 serviceContext);
2935
2936 sendEmail(
2937 article, articleURL, preferences, msg, serviceContext);
2938 }
2939 catch (Exception e) {
2940 _log.error(
2941 "Unable to send email to notify the change of status " +
2942 " to " + msg + " for article " + article.getId() +
2943 ": " + e.getMessage());
2944 }
2945 }
2946
2947
2948
2949 notifySubscribers(article, serviceContext);
2950 }
2951
2952 return article;
2953 }
2954
2955 public JournalArticle updateStatus(
2956 long userId, long classPK, int status,
2957 Map<String, Serializable> workflowContext,
2958 ServiceContext serviceContext)
2959 throws PortalException, SystemException {
2960
2961 JournalArticle article = getArticle(classPK);
2962
2963 return updateStatus(
2964 userId, article, status, null, workflowContext, serviceContext);
2965 }
2966
2967 public JournalArticle updateStatus(
2968 long userId, long groupId, String articleId, double version,
2969 int status, String articleURL,
2970 Map<String, Serializable> workflowContext,
2971 ServiceContext serviceContext)
2972 throws PortalException, SystemException {
2973
2974 JournalArticle article = journalArticlePersistence.findByG_A_V(
2975 groupId, articleId, version);
2976
2977 return updateStatus(
2978 userId, article, status, articleURL, workflowContext,
2979 serviceContext);
2980 }
2981
2982 public void updateTemplateId(
2983 long groupId, long classNameId, String oldTemplateId,
2984 String newTemplateId)
2985 throws SystemException {
2986
2987 List<JournalArticle> articles = journalArticlePersistence.findByG_C_T(
2988 groupId, classNameId, oldTemplateId);
2989
2990 for (JournalArticle article : articles) {
2991 article.setTemplateId(newTemplateId);
2992
2993 journalArticlePersistence.update(article);
2994 }
2995 }
2996
2997 protected void checkStructure(Document contentDoc, Element root)
2998 throws PortalException {
2999
3000 for (Element el : root.elements()) {
3001 checkStructureField(el, contentDoc);
3002
3003 checkStructure(contentDoc, el);
3004 }
3005 }
3006
3007 protected void checkStructure(JournalArticle article)
3008 throws PortalException, SystemException {
3009
3010 Group companyGroup = groupLocalService.getCompanyGroup(
3011 article.getCompanyId());
3012
3013 DDMStructure structure = null;
3014
3015 try {
3016 structure = ddmStructurePersistence.findByG_C_S(
3017 article.getGroupId(),
3018 PortalUtil.getClassNameId(JournalArticle.class),
3019 article.getStructureId());
3020 }
3021 catch (NoSuchStructureException nsse) {
3022 structure = ddmStructurePersistence.findByG_C_S(
3023 companyGroup.getGroupId(),
3024 PortalUtil.getClassNameId(JournalArticle.class),
3025 article.getStructureId());
3026 }
3027
3028 String content = GetterUtil.getString(article.getContent());
3029
3030 try {
3031 Document contentDocument = SAXReaderUtil.read(content);
3032 Document xsdDocument = SAXReaderUtil.read(structure.getXsd());
3033
3034 checkStructure(contentDocument, xsdDocument.getRootElement());
3035 }
3036 catch (DocumentException de) {
3037 throw new SystemException(de);
3038 }
3039 catch (StructureXsdException sxsde) {
3040 long groupId = article.getGroupId();
3041 String articleId = article.getArticleId();
3042 double version = article.getVersion();
3043
3044 if (_log.isWarnEnabled()) {
3045 _log.warn(
3046 "Article {groupId=" + groupId + ", articleId=" +
3047 articleId + ", version=" + version +
3048 "} has content that does not match its " +
3049 "structure: " + sxsde.getMessage());
3050 }
3051 }
3052 }
3053
3054 protected void checkStructureField(Element el, Document contentDoc)
3055 throws PortalException {
3056
3057 StringBuilder elPath = new StringBuilder();
3058
3059 elPath.append(el.attributeValue("name"));
3060
3061 Element elParent = el.getParent();
3062
3063 for (;;) {
3064 if ((elParent == null) || elParent.getName().equals("root")) {
3065 break;
3066 }
3067
3068 elPath.insert(
3069 0, elParent.attributeValue("name") + StringPool.COMMA);
3070
3071 elParent = elParent.getParent();
3072 }
3073
3074 String[] elPathNames = StringUtil.split(elPath.toString());
3075
3076 Element contentEl = contentDoc.getRootElement();
3077
3078 for (String _elPathName : elPathNames) {
3079 boolean foundEl = false;
3080
3081 for (Element tempEl : contentEl.elements()) {
3082 if (_elPathName.equals(
3083 tempEl.attributeValue("name", StringPool.BLANK))) {
3084
3085 contentEl = tempEl;
3086 foundEl = true;
3087
3088 break;
3089 }
3090 }
3091
3092 if (!foundEl) {
3093 String elType = contentEl.attributeValue(
3094 "type", StringPool.BLANK);
3095
3096 if (!elType.equals("list") && !elType.equals("multi-list")) {
3097 throw new StructureXsdException(elPath.toString());
3098 }
3099
3100 break;
3101 }
3102 }
3103 }
3104
3105 protected void copyArticleImages(
3106 JournalArticle oldArticle, JournalArticle newArticle)
3107 throws Exception {
3108
3109 Document contentDoc = SAXReaderUtil.read(oldArticle.getContent());
3110
3111 XPath xPathSelector = SAXReaderUtil.createXPath(
3112 "
3113
3114 List<Node> imageNodes = xPathSelector.selectNodes(contentDoc);
3115
3116 for (Node imageNode : imageNodes) {
3117 Element imageEl = (Element)imageNode;
3118
3119 String instanceId = imageEl.attributeValue("instance-id");
3120 String name = imageEl.attributeValue("name");
3121
3122 List<Element> dynamicContentEls = imageEl.elements(
3123 "dynamic-content");
3124
3125 for (Element dynamicContentEl : dynamicContentEls) {
3126 long imageId = GetterUtil.getLong(
3127 dynamicContentEl.attributeValue("id"));
3128 String languageId = dynamicContentEl.attributeValue(
3129 "language-id");
3130
3131 Image oldImage = null;
3132
3133 try {
3134 oldImage = imageLocalService.getImage(imageId);
3135 }
3136 catch (NoSuchImageException nsie) {
3137 continue;
3138 }
3139
3140 imageId = journalArticleImageLocalService.getArticleImageId(
3141 newArticle.getGroupId(), newArticle.getArticleId(),
3142 newArticle.getVersion(), instanceId, name, languageId);
3143
3144 imageLocalService.updateImage(imageId, oldImage.getTextObj());
3145
3146 String elContent =
3147 "/image/journal/article?img_id=" + imageId + "&t=" +
3148 WebServerServletTokenUtil.getToken(imageId);
3149
3150 dynamicContentEl.setText(elContent);
3151 dynamicContentEl.addAttribute("id", String.valueOf(imageId));
3152 }
3153 }
3154
3155 newArticle.setContent(contentDoc.formattedString());
3156 }
3157
3158 protected void format(
3159 User user, long groupId, String articleId, double version,
3160 boolean incrementVersion, Element root, Map<String, byte[]> images)
3161 throws PortalException, SystemException {
3162
3163 for (Element element : root.elements()) {
3164 String elInstanceId = element.attributeValue(
3165 "instance-id", StringPool.BLANK);
3166 String elName = element.attributeValue("name", StringPool.BLANK);
3167 String elType = element.attributeValue("type", StringPool.BLANK);
3168
3169 if (elType.equals("image")) {
3170 formatImage(
3171 groupId, articleId, version, incrementVersion, element,
3172 elInstanceId, elName, images);
3173 }
3174 else if (elType.equals("text_area") || elType.equals("text") ||
3175 elType.equals("text_box")) {
3176
3177 List<Element> dynamicContentElements = element.elements(
3178 "dynamic-content");
3179
3180 for (Element dynamicContentElement : dynamicContentElements) {
3181 String dynamicContent = dynamicContentElement.getText();
3182
3183 if (Validator.isNotNull(dynamicContent)) {
3184 dynamicContent = SanitizerUtil.sanitize(
3185 user.getCompanyId(), groupId, user.getUserId(),
3186 JournalArticle.class.getName(), 0,
3187 ContentTypes.TEXT_HTML, dynamicContent);
3188
3189 dynamicContentElement.clearContent();
3190
3191 dynamicContentElement.addCDATA(dynamicContent);
3192 }
3193 }
3194 }
3195
3196 format(
3197 user, groupId, articleId, version, incrementVersion, element,
3198 images);
3199 }
3200 }
3201
3202 protected String format(
3203 User user, long groupId, String articleId, double version,
3204 boolean incrementVersion, String content, String structureId,
3205 Map<String, byte[]> images)
3206 throws PortalException, SystemException {
3207
3208 Document document = null;
3209
3210 try {
3211 document = SAXReaderUtil.read(content);
3212
3213 Element rootElement = document.getRootElement();
3214
3215 if (Validator.isNotNull(structureId)) {
3216 format(
3217 user, groupId, articleId, version, incrementVersion,
3218 rootElement, images);
3219 }
3220 else {
3221 List<Element> staticContentElements = rootElement.elements(
3222 "static-content");
3223
3224 for (Element staticContentElement : staticContentElements) {
3225 String staticContent = staticContentElement.getText();
3226
3227 staticContent = SanitizerUtil.sanitize(
3228 user.getCompanyId(), groupId, user.getUserId(),
3229 JournalArticle.class.getName(), 0,
3230 ContentTypes.TEXT_HTML, staticContent);
3231
3232 staticContentElement.clearContent();
3233
3234 staticContentElement.addCDATA(staticContent);
3235 }
3236 }
3237
3238 content = DDMXMLUtil.formatXML(document);
3239 }
3240 catch (DocumentException de) {
3241 _log.error(de, de);
3242 }
3243
3244 content = HtmlUtil.replaceMsWordCharacters(content);
3245
3246 return content;
3247 }
3248
3249 protected void formatImage(
3250 long groupId, String articleId, double version,
3251 boolean incrementVersion, Element el, String elInstanceId,
3252 String elName, Map<String, byte[]> images)
3253 throws PortalException, SystemException {
3254
3255 List<Element> imageContents = el.elements("dynamic-content");
3256
3257 for (Element dynamicContent : imageContents) {
3258 String elLanguage = dynamicContent.attributeValue(
3259 "language-id", StringPool.BLANK);
3260
3261 if (!elLanguage.equals(StringPool.BLANK)) {
3262 elLanguage = "_" + elLanguage;
3263 }
3264
3265 long imageId = journalArticleImageLocalService.getArticleImageId(
3266 groupId, articleId, version, elInstanceId, elName, elLanguage);
3267
3268 double oldVersion = MathUtil.format(version - 0.1, 1, 1);
3269
3270 long oldImageId = 0;
3271
3272 if ((oldVersion >= 1) && incrementVersion) {
3273 oldImageId = journalArticleImageLocalService.getArticleImageId(
3274 groupId, articleId, oldVersion, elInstanceId, elName,
3275 elLanguage);
3276 }
3277
3278 String elContent =
3279 "/image/journal/article?img_id=" + imageId + "&t=" +
3280 WebServerServletTokenUtil.getToken(imageId);
3281
3282 if (dynamicContent.getText().equals("delete")) {
3283 dynamicContent.setText(StringPool.BLANK);
3284
3285 imageLocalService.deleteImage(imageId);
3286
3287 String defaultElLanguage = "";
3288
3289 if (!Validator.isNotNull(elLanguage)) {
3290 defaultElLanguage =
3291 "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
3292 }
3293
3294 long defaultImageId =
3295 journalArticleImageLocalService.getArticleImageId(
3296 groupId, articleId, version, elInstanceId, elName,
3297 defaultElLanguage);
3298
3299 imageLocalService.deleteImage(defaultImageId);
3300
3301 continue;
3302 }
3303
3304 byte[] bytes = images.get(elInstanceId + "_" + elName + elLanguage);
3305
3306 if ((bytes != null) && (bytes.length > 0)) {
3307 dynamicContent.setText(elContent);
3308 dynamicContent.addAttribute("id", String.valueOf(imageId));
3309
3310 imageLocalService.updateImage(imageId, bytes);
3311
3312 continue;
3313 }
3314
3315 if ((version > JournalArticleConstants.VERSION_DEFAULT) &&
3316 incrementVersion) {
3317
3318 Image oldImage = null;
3319
3320 if (oldImageId > 0) {
3321 oldImage = imageLocalService.getImage(oldImageId);
3322 }
3323
3324 if (oldImage != null) {
3325 dynamicContent.setText(elContent);
3326 dynamicContent.addAttribute("id", String.valueOf(imageId));
3327
3328 bytes = oldImage.getTextObj();
3329
3330 imageLocalService.updateImage(imageId, bytes);
3331 }
3332
3333 continue;
3334 }
3335
3336 Image image = imageLocalService.getImage(imageId);
3337
3338 if (image != null) {
3339 dynamicContent.setText(elContent);
3340 dynamicContent.addAttribute("id", String.valueOf(imageId));
3341
3342 continue;
3343 }
3344
3345 long contentImageId = GetterUtil.getLong(
3346 HttpUtil.getParameter(dynamicContent.getText(), "img_id"));
3347
3348 if (contentImageId <= 0) {
3349 contentImageId = GetterUtil.getLong(
3350 HttpUtil.getParameter(
3351 dynamicContent.getText(), "img_id", false));
3352 }
3353
3354 if (contentImageId > 0) {
3355 image = imageLocalService.getImage(contentImageId);
3356
3357 if (image != null) {
3358 dynamicContent.addAttribute(
3359 "id", String.valueOf(contentImageId));
3360
3361 continue;
3362 }
3363 }
3364
3365 String defaultElLanguage = "";
3366
3367 if (!Validator.isNotNull(elLanguage)) {
3368 defaultElLanguage =
3369 "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
3370 }
3371
3372 long defaultImageId =
3373 journalArticleImageLocalService.getArticleImageId(
3374 groupId, articleId, version, elInstanceId, elName,
3375 defaultElLanguage);
3376
3377 Image defaultImage = imageLocalService.getImage(defaultImageId);
3378
3379 if (defaultImage != null) {
3380 dynamicContent.setText(elContent);
3381 dynamicContent.addAttribute(
3382 "id", String.valueOf(defaultImageId));
3383
3384 bytes = defaultImage.getTextObj();
3385
3386 imageLocalService.updateImage(defaultImageId, bytes);
3387
3388 continue;
3389 }
3390
3391 if (Validator.isNotNull(elLanguage)) {
3392 dynamicContent.setText(StringPool.BLANK);
3393 }
3394 }
3395 }
3396
3397 protected List<ObjectValuePair<Long, Integer>> getArticleVersionStatuses(
3398 List<JournalArticle> articles) {
3399
3400 List<ObjectValuePair<Long, Integer>> dlArticleVersionStatusOVPs =
3401 new ArrayList<ObjectValuePair<Long, Integer>>(articles.size());
3402
3403 for (JournalArticle article : articles) {
3404 int status = article.getStatus();
3405
3406 if (status == WorkflowConstants.STATUS_PENDING) {
3407 status = WorkflowConstants.STATUS_DRAFT;
3408 }
3409
3410 ObjectValuePair<Long, Integer> dlFileVersionStatusOVP =
3411 new ObjectValuePair<Long, Integer>(article.getId(), status);
3412
3413 dlArticleVersionStatusOVPs.add(dlFileVersionStatusOVP);
3414 }
3415
3416 return dlArticleVersionStatusOVPs;
3417 }
3418
3419 protected long getClassTypeId(JournalArticle article) {
3420 long classTypeId = 0;
3421
3422 try {
3423 long classNameId = PortalUtil.getClassNameId(JournalArticle.class);
3424
3425 DDMStructure ddmStructure = ddmStructurePersistence.fetchByG_C_S(
3426 article.getGroupId(), classNameId, article.getStructureId());
3427
3428 if (ddmStructure == null) {
3429 Group companyGroup = groupLocalService.getCompanyGroup(
3430 article.getCompanyId());
3431
3432 ddmStructure = ddmStructurePersistence.fetchByG_C_S(
3433 companyGroup.getGroupId(), classNameId,
3434 article.getStructureId());
3435 }
3436
3437 if (ddmStructure != null) {
3438 classTypeId = ddmStructure.getStructureId();
3439 }
3440 }
3441 catch (Exception e) {
3442 _log.error(e, e);
3443 }
3444
3445 return classTypeId;
3446 }
3447
3448 protected Date[] getDateInterval(
3449 long groupId, String articleId, Date earliestDisplayDate,
3450 Date latestExpirationDate)
3451 throws SystemException {
3452
3453 Date[] dateInterval = new Date[2];
3454
3455 List<JournalArticle> articles = journalArticlePersistence.findByG_A_ST(
3456 groupId, articleId, WorkflowConstants.STATUS_APPROVED);
3457
3458 boolean expiringArticle = true;
3459
3460 if (latestExpirationDate == null) {
3461 expiringArticle = false;
3462 }
3463
3464 for (JournalArticle article : articles) {
3465 if ((earliestDisplayDate == null) ||
3466 ((article.getDisplayDate() != null) &&
3467 earliestDisplayDate.after(article.getDisplayDate()))) {
3468
3469 earliestDisplayDate = article.getDisplayDate();
3470 }
3471
3472 if (expiringArticle &&
3473 ((latestExpirationDate == null) ||
3474 ((article.getExpirationDate() != null) &&
3475 latestExpirationDate.before(article.getExpirationDate())))) {
3476
3477 latestExpirationDate = article.getExpirationDate();
3478 }
3479
3480 if (expiringArticle && (article.getExpirationDate() == null) &&
3481 (latestExpirationDate != null)) {
3482
3483 expiringArticle = false;
3484 }
3485 }
3486
3487 dateInterval[0] = earliestDisplayDate;
3488 dateInterval[1] = latestExpirationDate;
3489
3490 return dateInterval;
3491 }
3492
3493 protected String getExtraDataJSON(
3494 JournalArticle article, ServiceContext serviceContext) {
3495
3496 JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
3497
3498 jsonObject.put("title", article.getTitle(serviceContext.getLocale()));
3499
3500 return jsonObject.toString();
3501 }
3502
3503 protected String getUniqueUrlTitle(
3504 long id, long groupId, String articleId, String title)
3505 throws PortalException, SystemException {
3506
3507 String urlTitle = JournalUtil.getUrlTitle(id, title);
3508
3509 for (int i = 1;; i++) {
3510 JournalArticle article = null;
3511
3512 try {
3513 article = getArticleByUrlTitle(groupId, urlTitle);
3514 }
3515 catch (NoSuchArticleException nsae) {
3516 }
3517
3518 if ((article == null) || articleId.equals(article.getArticleId())) {
3519 break;
3520 }
3521 else {
3522 String suffix = StringPool.DASH + i;
3523
3524 String prefix = urlTitle;
3525
3526 if (urlTitle.length() > suffix.length()) {
3527 prefix = urlTitle.substring(
3528 0, urlTitle.length() - suffix.length());
3529 }
3530
3531 urlTitle = prefix + suffix;
3532 }
3533 }
3534
3535 return urlTitle;
3536 }
3537
3538 protected String getUniqueUrlTitle(
3539 long id, String articleId, String title, String oldUrlTitle,
3540 ServiceContext serviceContext)
3541 throws PortalException, SystemException {
3542
3543 String serviceContextUrlTitle = ParamUtil.getString(
3544 serviceContext, "urlTitle");
3545
3546 String urlTitle = null;
3547
3548 if (Validator.isNotNull(serviceContextUrlTitle)) {
3549 urlTitle = JournalUtil.getUrlTitle(id, serviceContextUrlTitle);
3550 }
3551 else if (Validator.isNotNull(oldUrlTitle)) {
3552 return oldUrlTitle;
3553 }
3554 else {
3555 urlTitle = getUniqueUrlTitle(
3556 id, serviceContext.getScopeGroupId(), articleId, title);
3557 }
3558
3559 JournalArticle urlTitleArticle = null;
3560
3561 try {
3562 urlTitleArticle = getArticleByUrlTitle(
3563 serviceContext.getScopeGroupId(), urlTitle);
3564 }
3565 catch (NoSuchArticleException nsae) {
3566 }
3567
3568 if ((urlTitleArticle != null) &&
3569 !Validator.equals(
3570 urlTitleArticle.getArticleId(), articleId)) {
3571
3572 urlTitle = getUniqueUrlTitle(
3573 id, serviceContext.getScopeGroupId(), articleId, urlTitle);
3574 }
3575
3576 return urlTitle;
3577 }
3578
3579 protected boolean hasModifiedLatestApprovedVersion(
3580 long groupId, String articleId, double version)
3581 throws PortalException, SystemException {
3582
3583 double latestApprovedVersion;
3584
3585 try {
3586 latestApprovedVersion = getLatestVersion(
3587 groupId, articleId, WorkflowConstants.STATUS_APPROVED);
3588
3589 if (version >= latestApprovedVersion) {
3590 return true;
3591 }
3592 else {
3593 return false;
3594 }
3595 }
3596 catch (NoSuchArticleException nsae) {
3597 return true;
3598 }
3599 }
3600
3601 protected void notifySubscribers(
3602 JournalArticle article, ServiceContext serviceContext)
3603 throws PortalException, SystemException {
3604
3605 if (!article.isApproved()) {
3606 return;
3607 }
3608
3609 String articleURL = PortalUtil.getControlPanelFullURL(
3610 serviceContext.getScopeGroupId(), PortletKeys.JOURNAL, null);
3611
3612 if (Validator.isNull(articleURL)) {
3613 return;
3614 }
3615
3616 PortletPreferences preferences =
3617 ServiceContextUtil.getPortletPreferences(serviceContext);
3618
3619 if (preferences == null) {
3620 long ownerId = article.getGroupId();
3621 int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
3622 long plid = PortletKeys.PREFS_PLID_SHARED;
3623 String portletId = PortletKeys.JOURNAL;
3624 String defaultPreferences = null;
3625
3626 preferences = portletPreferencesLocalService.getPreferences(
3627 article.getCompanyId(), ownerId, ownerType, plid, portletId,
3628 defaultPreferences);
3629 }
3630
3631 if ((article.getVersion() == 1.0) &&
3632 JournalUtil.getEmailArticleAddedEnabled(preferences)) {
3633 }
3634 else if ((article.getVersion() != 1.0) &&
3635 JournalUtil.getEmailArticleUpdatedEnabled(preferences)) {
3636 }
3637 else {
3638 return;
3639 }
3640
3641 String fromName = JournalUtil.getEmailFromName(
3642 preferences, article.getCompanyId());
3643 String fromAddress = JournalUtil.getEmailFromAddress(
3644 preferences, article.getCompanyId());
3645
3646 String subject = null;
3647 String body = null;
3648
3649 if (article.getVersion() == 1.0) {
3650 subject = JournalUtil.getEmailArticleAddedSubject(preferences);
3651 body = JournalUtil.getEmailArticleAddedBody(preferences);
3652 }
3653 else {
3654 subject = JournalUtil.getEmailArticleUpdatedSubject(preferences);
3655 body = JournalUtil.getEmailArticleUpdatedBody(preferences);
3656 }
3657
3658 SubscriptionSender subscriptionSender = new SubscriptionSender();
3659
3660 subscriptionSender.setBody(body);
3661 subscriptionSender.setCompanyId(article.getCompanyId());
3662 subscriptionSender.setContextAttributes(
3663 "[$ARTICLE_ID$]", article.getArticleId(), "[$ARTICLE_TITLE$]",
3664 article.getTitle(serviceContext.getLanguageId()), "[$ARTICLE_URL$]",
3665 articleURL, "[$ARTICLE_VERSION$]", article.getVersion());
3666 subscriptionSender.setContextUserPrefix("ARTICLE");
3667 subscriptionSender.setFrom(fromAddress, fromName);
3668 subscriptionSender.setHtmlFormat(true);
3669 subscriptionSender.setMailId("journal_article", article.getId());
3670 subscriptionSender.setPortletId(PortletKeys.JOURNAL);
3671 subscriptionSender.setReplyToAddress(fromAddress);
3672 subscriptionSender.setScopeGroupId(article.getGroupId());
3673 subscriptionSender.setServiceContext(serviceContext);
3674 subscriptionSender.setSubject(subject);
3675 subscriptionSender.setUserId(article.getUserId());
3676
3677 subscriptionSender.addPersistedSubscribers(
3678 JournalArticle.class.getName(), article.getGroupId());
3679
3680 subscriptionSender.flushNotificationsAsync();
3681 }
3682
3683 protected void reindex(JournalArticle article) throws SearchException {
3684 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3685 JournalArticle.class);
3686
3687 indexer.reindex(article);
3688 }
3689
3690 protected void saveImages(
3691 boolean smallImage, long smallImageId, File smallImageFile,
3692 byte[] smallImageBytes)
3693 throws PortalException, SystemException {
3694
3695 if (smallImage) {
3696 if ((smallImageFile != null) && (smallImageBytes != null)) {
3697 imageLocalService.updateImage(smallImageId, smallImageBytes);
3698 }
3699 }
3700 else {
3701 imageLocalService.deleteImage(smallImageId);
3702 }
3703 }
3704
3705 protected void sendEmail(
3706 JournalArticle article, String articleURL,
3707 PortletPreferences preferences, String emailType,
3708 ServiceContext serviceContext)
3709 throws PortalException, SystemException {
3710
3711 if (preferences == null) {
3712 return;
3713 }
3714 else if (emailType.equals("denied") &&
3715 JournalUtil.getEmailArticleApprovalDeniedEnabled(
3716 preferences)) {
3717 }
3718 else if (emailType.equals("granted") &&
3719 JournalUtil.getEmailArticleApprovalGrantedEnabled(
3720 preferences)) {
3721 }
3722 else if (emailType.equals("requested") &&
3723 JournalUtil.getEmailArticleApprovalRequestedEnabled(
3724 preferences)) {
3725 }
3726 else if (emailType.equals("review") &&
3727 JournalUtil.getEmailArticleReviewEnabled(preferences)) {
3728 }
3729 else {
3730 return;
3731 }
3732
3733 Company company = companyPersistence.findByPrimaryKey(
3734 article.getCompanyId());
3735
3736 User user = userPersistence.findByPrimaryKey(article.getUserId());
3737
3738 articleURL +=
3739 "&groupId=" + article.getGroupId() + "&articleId=" +
3740 article.getArticleId() + "&version=" + article.getVersion();
3741
3742 String fromName = JournalUtil.getEmailFromName(
3743 preferences, article.getCompanyId());
3744 String fromAddress = JournalUtil.getEmailFromAddress(
3745 preferences, article.getCompanyId());
3746
3747 String toName = user.getFullName();
3748 String toAddress = user.getEmailAddress();
3749
3750 if (emailType.equals("requested") || emailType.equals("review")) {
3751 String tempToName = fromName;
3752 String tempToAddress = fromAddress;
3753
3754 fromName = toName;
3755 fromAddress = toAddress;
3756
3757 toName = tempToName;
3758 toAddress = tempToAddress;
3759 }
3760
3761 String subject = null;
3762 String body = null;
3763
3764 if (emailType.equals("denied")) {
3765 subject = JournalUtil.getEmailArticleApprovalDeniedSubject(
3766 preferences);
3767 body = JournalUtil.getEmailArticleApprovalDeniedBody(preferences);
3768 }
3769 else if (emailType.equals("granted")) {
3770 subject = JournalUtil.getEmailArticleApprovalGrantedSubject(
3771 preferences);
3772 body = JournalUtil.getEmailArticleApprovalGrantedBody(preferences);
3773 }
3774 else if (emailType.equals("requested")) {
3775 subject = JournalUtil.getEmailArticleApprovalRequestedSubject(
3776 preferences);
3777 body = JournalUtil.getEmailArticleApprovalRequestedBody(
3778 preferences);
3779 }
3780 else if (emailType.equals("review")) {
3781 subject = JournalUtil.getEmailArticleReviewSubject(preferences);
3782 body = JournalUtil.getEmailArticleReviewBody(preferences);
3783 }
3784
3785 SubscriptionSender subscriptionSender = new SubscriptionSender();
3786
3787 subscriptionSender.setBody(body);
3788 subscriptionSender.setCompanyId(company.getCompanyId());
3789 subscriptionSender.setContextAttributes(
3790 "[$ARTICLE_ID$]", article.getArticleId(), "[$ARTICLE_TITLE$]",
3791 article.getTitle(serviceContext.getLanguageId()), "[$ARTICLE_URL$]",
3792 articleURL, "[$ARTICLE_USER_NAME$]", article.getUserName(),
3793 "[$ARTICLE_VERSION$]", article.getVersion());
3794 subscriptionSender.setContextUserPrefix("ARTICLE");
3795 subscriptionSender.setFrom(fromAddress, fromName);
3796 subscriptionSender.setHtmlFormat(true);
3797 subscriptionSender.setMailId("journal_article", article.getId());
3798 subscriptionSender.setPortletId(PortletKeys.JOURNAL);
3799 subscriptionSender.setScopeGroupId(article.getGroupId());
3800 subscriptionSender.setServiceContext(serviceContext);
3801 subscriptionSender.setSubject(subject);
3802 subscriptionSender.setUserId(article.getUserId());
3803
3804 subscriptionSender.addRuntimeSubscribers(toAddress, toName);
3805
3806 subscriptionSender.flushNotificationsAsync();
3807 }
3808
3809 protected void updateDDMStructureXSD(
3810 long ddmStructureId, String content, ServiceContext serviceContext)
3811 throws PortalException, SystemException {
3812
3813 try {
3814 Document document = SAXReaderUtil.read(content);
3815
3816 Element rootElement = document.getRootElement();
3817
3818 List<Element> elements = rootElement.elements();
3819
3820 for (Element element : elements) {
3821 String fieldName = element.attributeValue(
3822 "name", StringPool.BLANK);
3823
3824 List<Element> dynamicContentElements = element.elements(
3825 "dynamic-content");
3826
3827 for (Element dynamicContentElement : dynamicContentElements) {
3828 String value = dynamicContentElement.getText();
3829
3830 ddmStructureLocalService.updateXSDFieldMetadata(
3831 ddmStructureId, fieldName,
3832 FieldConstants.PREDEFINED_VALUE, value, serviceContext);
3833 }
3834 }
3835 }
3836 catch (DocumentException de) {
3837 throw new SystemException(de);
3838 }
3839 }
3840
3841 protected void updatePreviousApprovedArticle(JournalArticle article)
3842 throws PortalException, SystemException {
3843
3844 List<JournalArticle> approvedArticles =
3845 journalArticlePersistence.findByG_A_ST(
3846 article.getGroupId(), article.getArticleId(),
3847 WorkflowConstants.STATUS_APPROVED, 0, 2);
3848
3849 if (approvedArticles.isEmpty() ||
3850 ((approvedArticles.size() == 1) &&
3851 (article.getStatus() == WorkflowConstants.STATUS_APPROVED))) {
3852
3853 if (article.isIndexable()) {
3854 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3855 JournalArticle.class);
3856
3857 indexer.delete(article);
3858 }
3859
3860 assetEntryLocalService.updateVisible(
3861 JournalArticle.class.getName(), article.getResourcePrimKey(),
3862 false);
3863 }
3864 else {
3865 JournalArticle previousApprovedArticle = approvedArticles.get(0);
3866
3867 if (article.getStatus() == WorkflowConstants.STATUS_APPROVED) {
3868 previousApprovedArticle = approvedArticles.get(1);
3869 }
3870
3871 Date[] dateInterval = getDateInterval(
3872 previousApprovedArticle.getGroupId(),
3873 previousApprovedArticle.getArticleId(),
3874 previousApprovedArticle.getDisplayDate(),
3875 previousApprovedArticle.getExpirationDate());
3876
3877 Date displayDate = dateInterval[0];
3878 Date expirationDate = dateInterval[1];
3879
3880 AssetEntry assetEntry = assetEntryLocalService.updateEntry(
3881 JournalArticle.class.getName(), article.getResourcePrimKey(),
3882 displayDate, expirationDate, true);
3883
3884 assetEntry.setModifiedDate(
3885 previousApprovedArticle.getModifiedDate());
3886
3887 assetEntryPersistence.update(assetEntry);
3888
3889 if (article.isIndexable()) {
3890 reindex(previousApprovedArticle);
3891 }
3892 }
3893 }
3894
3895 protected void updateUrlTitles(
3896 long groupId, String articleId, String urlTitle)
3897 throws SystemException {
3898
3899 List<JournalArticle> articles = journalArticlePersistence.findByG_A(
3900 groupId, articleId);
3901
3902 for (JournalArticle article : articles) {
3903 if (!article.getUrlTitle().equals(urlTitle)) {
3904 article.setUrlTitle(urlTitle);
3905
3906 journalArticlePersistence.update(article);
3907 }
3908 }
3909 }
3910
3911 protected void validate(
3912 long companyId, long groupId, long classNameId,
3913 Map<Locale, String> titleMap, String content, String type,
3914 String structureId, String templateId, Date expirationDate,
3915 boolean smallImage, String smallImageURL, File smallImageFile,
3916 byte[] smallImageBytes)
3917 throws PortalException, SystemException {
3918
3919 Locale articleDefaultLocale = LocaleUtil.fromLanguageId(
3920 LocalizationUtil.getDefaultLocale(content));
3921
3922 Locale[] availableLocales = LanguageUtil.getAvailableLocales();
3923
3924 if (!ArrayUtil.contains(availableLocales, articleDefaultLocale)) {
3925 LocaleException le = new LocaleException(
3926 "The locale " + articleDefaultLocale +
3927 " is not available in company " + companyId);
3928
3929 Locale[] sourceAvailableLocales = {articleDefaultLocale};
3930
3931 le.setSourceAvailableLocales(sourceAvailableLocales);
3932 le.setTargetAvailableLocales(availableLocales);
3933
3934 throw le;
3935 }
3936
3937 if ((classNameId == JournalArticleConstants.CLASSNAME_ID_DEFAULT) &&
3938 (titleMap.isEmpty() ||
3939 Validator.isNull(titleMap.get(articleDefaultLocale)))) {
3940
3941 throw new ArticleTitleException();
3942 }
3943 else if (Validator.isNull(type)) {
3944 throw new ArticleTypeException();
3945 }
3946
3947 validateContent(content);
3948
3949 if (Validator.isNotNull(structureId)) {
3950 Group companyGroup = groupLocalService.getCompanyGroup(companyId);
3951
3952 DDMStructure ddmStructure = null;
3953
3954 try {
3955 ddmStructure = ddmStructurePersistence.findByG_C_S(
3956 groupId, PortalUtil.getClassNameId(JournalArticle.class),
3957 structureId);
3958 }
3959 catch (NoSuchStructureException nsse) {
3960 ddmStructure = ddmStructurePersistence.findByG_C_S(
3961 companyGroup.getGroupId(),
3962 PortalUtil.getClassNameId(JournalArticle.class),
3963 structureId);
3964 }
3965
3966 DDMTemplate ddmTemplate = null;
3967
3968 if (Validator.isNotNull(templateId)) {
3969 ddmTemplate = ddmTemplateService.getTemplate(
3970 groupId, PortalUtil.getClassNameId(DDMStructure.class),
3971 templateId);
3972
3973 if (ddmTemplate.getClassPK() != ddmStructure.getStructureId()) {
3974 throw new NoSuchTemplateException();
3975 }
3976 }
3977 else if (classNameId ==
3978 JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
3979
3980 throw new NoSuchTemplateException();
3981 }
3982 }
3983
3984 if ((expirationDate != null) && expirationDate.before(new Date()) &&
3985 !ExportImportThreadLocal.isImportInProcess()) {
3986
3987 throw new ArticleExpirationDateException();
3988 }
3989
3990 String[] imageExtensions = PrefsPropsUtil.getStringArray(
3991 PropsKeys.JOURNAL_IMAGE_EXTENSIONS, StringPool.COMMA);
3992
3993 if (smallImage && Validator.isNull(smallImageURL) &&
3994 (smallImageFile != null) && (smallImageBytes != null)) {
3995
3996 String smallImageName = smallImageFile.getName();
3997
3998 if (smallImageName != null) {
3999 boolean validSmallImageExtension = false;
4000
4001 for (String _imageExtension : imageExtensions) {
4002 if (StringPool.STAR.equals(_imageExtension) ||
4003 StringUtil.endsWith(smallImageName, _imageExtension)) {
4004
4005 validSmallImageExtension = true;
4006
4007 break;
4008 }
4009 }
4010
4011 if (!validSmallImageExtension) {
4012 throw new ArticleSmallImageNameException(smallImageName);
4013 }
4014 }
4015
4016 long smallImageMaxSize = PrefsPropsUtil.getLong(
4017 PropsKeys.JOURNAL_IMAGE_SMALL_MAX_SIZE);
4018
4019 if ((smallImageMaxSize > 0) &&
4020 ((smallImageBytes == null) ||
4021 (smallImageBytes.length > smallImageMaxSize))) {
4022
4023 throw new ArticleSmallImageSizeException();
4024 }
4025 }
4026 }
4027
4028 protected void validate(
4029 long companyId, long groupId, long classNameId, String articleId,
4030 boolean autoArticleId, double version, Map<Locale, String> titleMap,
4031 String content, String type, String structureId, String templateId,
4032 Date expirationDate, boolean smallImage, String smallImageURL,
4033 File smallImageFile, byte[] smallImageBytes)
4034 throws PortalException, SystemException {
4035
4036 if (!autoArticleId) {
4037 validate(articleId);
4038 }
4039
4040 JournalArticle article = journalArticlePersistence.fetchByG_A_V(
4041 groupId, articleId, version);
4042
4043 if (article != null) {
4044 throw new DuplicateArticleIdException();
4045 }
4046
4047 validate(
4048 companyId, groupId, classNameId, titleMap, content, type,
4049 structureId, templateId, expirationDate, smallImage, smallImageURL,
4050 smallImageFile, smallImageBytes);
4051 }
4052
4053 protected void validate(String articleId) throws PortalException {
4054 if (Validator.isNull(articleId) ||
4055 (articleId.indexOf(CharPool.SPACE) != -1)) {
4056
4057 throw new ArticleIdException();
4058 }
4059 }
4060
4061 protected void validateContent(String content) throws PortalException {
4062 if (Validator.isNull(content)) {
4063 throw new ArticleContentException("Content is null");
4064 }
4065
4066 try {
4067 SAXReaderUtil.read(content);
4068 }
4069 catch (DocumentException de) {
4070 if (_log.isDebugEnabled()) {
4071 _log.debug("Invalid content:\n" + content);
4072 }
4073
4074 throw new ArticleContentException(
4075 "Unable to read content with an XML parser", de);
4076 }
4077 }
4078
4079 private static final long _JOURNAL_ARTICLE_CHECK_INTERVAL =
4080 PropsValues.JOURNAL_ARTICLE_CHECK_INTERVAL * Time.MINUTE;
4081
4082 private static Log _log = LogFactoryUtil.getLog(
4083 JournalArticleLocalServiceImpl.class);
4084
4085 private Date _previousCheckDate;
4086
4087 }