From 9d781652b2e6b5e316a91ffd6aadb2ff4457a737 Mon Sep 17 00:00:00 2001
From: Helmi Akermi <70575401+hakermi@users.noreply.github.com>
Date: Mon, 5 Aug 2024 16:46:14 +0100
Subject: [PATCH] feat: Add an upgrade plugin for content pages properties
migration and update NewsArticlesUpgradeplugin - EXO-73181 -
Meeds-io/MIPs#128 (#242)
Add an upgrade plugin for content pages properties(summary/illustrationId) migration and update the NewsArticlesUpgradePlugin to cover different target version context
---
.../ContentArticlePropertiesUpgrade.java | 234 ++++++++++++++++++
.../news/upgrade/jcr/NewsArticlesUpgrade.java | 134 +++++++---
.../resources/conf/portal/configuration.xml | 33 +++
.../ContentArticlePropertiesUpgradeTest.java | 164 ++++++++++++
.../upgrade/jcr/NewsArticlesUpgradeTest.java | 47 +++-
5 files changed, 570 insertions(+), 42 deletions(-)
create mode 100644 data-upgrade-news/src/main/java/org/exoplatform/news/upgrade/ContentArticlePropertiesUpgrade.java
create mode 100644 data-upgrade-news/src/test/java/org/exoplatform/news/upgrade/ContentArticlePropertiesUpgradeTest.java
diff --git a/data-upgrade-news/src/main/java/org/exoplatform/news/upgrade/ContentArticlePropertiesUpgrade.java b/data-upgrade-news/src/main/java/org/exoplatform/news/upgrade/ContentArticlePropertiesUpgrade.java
new file mode 100644
index 000000000..631a68471
--- /dev/null
+++ b/data-upgrade-news/src/main/java/org/exoplatform/news/upgrade/ContentArticlePropertiesUpgrade.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2024 eXo Platform SAS.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+package org.exoplatform.news.upgrade;
+
+import io.meeds.notes.model.NoteMetadataObject;
+import org.apache.commons.collections4.MapUtils;
+import org.exoplatform.commons.api.settings.SettingService;
+import org.exoplatform.commons.api.settings.SettingValue;
+import org.exoplatform.commons.api.settings.data.Context;
+import org.exoplatform.commons.api.settings.data.Scope;
+import org.exoplatform.commons.upgrade.UpgradeProductPlugin;
+import org.exoplatform.container.xml.InitParams;
+import org.exoplatform.portal.config.UserACL;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.exoplatform.social.core.manager.IdentityManager;
+import org.exoplatform.social.core.space.model.Space;
+import org.exoplatform.social.core.space.spi.SpaceService;
+import org.exoplatform.social.metadata.MetadataFilter;
+import org.exoplatform.social.metadata.MetadataService;
+import org.exoplatform.social.metadata.model.MetadataItem;
+import org.exoplatform.social.metadata.model.MetadataKey;
+import org.exoplatform.wiki.model.Page;
+import org.exoplatform.wiki.model.PageVersion;
+import org.exoplatform.wiki.service.NoteService;
+import org.exoplatform.wiki.utils.Utils;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ContentArticlePropertiesUpgrade extends UpgradeProductPlugin {
+
+ private static final Log LOG =
+ ExoLogger.getLogger(ContentArticlePropertiesUpgrade.class);
+
+ private final NoteService noteService;
+
+ private final MetadataService metadataService;
+
+ private final IdentityManager identityManager;
+
+ private final SpaceService spaceService;
+
+ private final UserACL userACL;
+
+ private final SettingService settingService;
+
+ private static final MetadataKey NOTES_METADATA_KEY =
+ new MetadataKey("notes", Utils.NOTES_METADATA_OBJECT_TYPE, 0);
+
+ public static final String NEWS_METADATA_NAME = "news";
+
+ public static final String NEWS_METADATA_DRAFT_OBJECT_TYPE = "newsDraftPage";
+
+ public static final String NOTE_METADATA_PAGE_OBJECT_TYPE = "notePage";
+
+ public static final String NOTE_METADATA_DRAFT_PAGE_OBJECT_TYPE = "noteDraftPage";
+
+ public static final String NEWS_METADATA_PAGE_VERSION_OBJECT_TYPE = "newsPageVersion";
+
+ public static final String NEWS_METADATA_LATEST_DRAFT_OBJECT_TYPE = "newsLatestDraftPage";
+
+ public static final String CONTENT_ILLUSTRATION_ID = "illustrationId";
+
+ public static final String SUMMARY = "summary";
+
+ public static final String FEATURED_IMAGE_ID = "featuredImageId";
+
+ private static final String FEATURED_IMAGE_UPDATED_DATE = "featuredImageUpdatedDate";
+
+ private static final String ARTICLES_UPGRADE_PLUGIN_NAME = "NewsArticlesUpgradePlugin";
+
+ private static final String ARTICLES_UPGRADE_EXECUTED_KEY = "articlesUpgradeExecuted";
+
+ public ContentArticlePropertiesUpgrade(InitParams initParams,
+ NoteService noteService,
+ MetadataService metadataService,
+ IdentityManager identityManager,
+ SpaceService spaceService,
+ UserACL userACL,
+ SettingService settingService) {
+ super(initParams);
+ this.noteService = noteService;
+ this.metadataService = metadataService;
+ this.identityManager = identityManager;
+ this.spaceService = spaceService;
+ this.userACL = userACL;
+ this.settingService = settingService;
+ }
+
+ @Override
+ public void processUpgrade(String oldVersion, String newVersion) {
+ long startupTime = System.currentTimeMillis();
+ LOG.info("Start upgrade of content page properties");
+ int notMigratedContentPagesPropertiesCount;
+ int processedContentPagesPropertiesCount = 0;
+ int totalContentPagesPropertiesCount = 0;
+ int ignoredContentPagesPropertiesCount = 0;
+ try {
+ MetadataFilter metadataFilter = getMetadataFilter();
+ metadataFilter.setMetadataObjectTypes(List.of(NEWS_METADATA_PAGE_VERSION_OBJECT_TYPE,
+ NEWS_METADATA_DRAFT_OBJECT_TYPE,
+ NEWS_METADATA_LATEST_DRAFT_OBJECT_TYPE));
+ List metadataItems = metadataService.getMetadataItemsByFilter(metadataFilter, 0, 0);
+ totalContentPagesPropertiesCount = metadataItems.size();
+ for (MetadataItem metadataItem : metadataItems) {
+ if (metadataItem != null && !MapUtils.isEmpty(metadataItem.getProperties())) {
+ Map contentProperties = metadataItem.getProperties();
+ Page page = null;
+ String objectType = NOTE_METADATA_PAGE_OBJECT_TYPE;
+ if (metadataItem.getObjectType().equals(NEWS_METADATA_PAGE_VERSION_OBJECT_TYPE)) {
+ PageVersion pageVersion = noteService.getPageVersionById(Long.valueOf(metadataItem.getObjectId()));
+ if (pageVersion != null && pageVersion.getParent() != null) {
+ page = pageVersion.getParent();
+ }
+ } else {
+ page = noteService.getDraftNoteById(metadataItem.getObjectId(), userACL.getSuperUser());
+ objectType = NOTE_METADATA_DRAFT_PAGE_OBJECT_TYPE;
+ }
+ if (page != null && page.getAuthor() != null) {
+ NoteMetadataObject noteMetadataObject = buildNoteMetadataObject(page, null, objectType);
+ MetadataItem noteMetadataItem = getNoteMetadataItem(page, null, objectType);
+
+ if (noteMetadataItem != null) {
+ LOG.info("ContentArticlePropertiesUpgrade: Ignore : Content page properties already migrated");
+ ignoredContentPagesPropertiesCount++;
+ } else {
+ Map noteProperties = new HashMap<>();
+ long creatorId = Long.parseLong(identityManager.getOrCreateUserIdentity(page.getAuthor()).getId());
+
+ if (contentProperties.getOrDefault(CONTENT_ILLUSTRATION_ID, null) != null) {
+ noteProperties.put(FEATURED_IMAGE_ID, contentProperties.get(CONTENT_ILLUSTRATION_ID));
+ noteProperties.put(FEATURED_IMAGE_UPDATED_DATE, String.valueOf(new Date().getTime()));
+ }
+ noteProperties.put(SUMMARY, contentProperties.get(SUMMARY));
+ metadataService.createMetadataItem(noteMetadataObject, NOTES_METADATA_KEY, noteProperties, creatorId);
+ processedContentPagesPropertiesCount++;
+ LOG.info("ContentArticlePropertiesUpgrade: Processed content page properties: {}/{}",
+ processedContentPagesPropertiesCount,
+ totalContentPagesPropertiesCount);
+ }
+ } else {
+ ignoredContentPagesPropertiesCount++;
+ LOG.warn("ContentArticlePropertiesUpgrade: Content page properties ignored due to data inconsistency: "
+ + "page exists: {}, page name: {}",
+ "ObjectType: {}",
+ "Page Id: {}",
+ "Page author: {}",
+ page != null,
+ page != null ? page.getName() : null,
+ objectType,
+ page != null ? page.getId() : null,
+ null);
+ }
+ } else {
+ LOG.info("ContentArticlePropertiesUpgrade: Ignore : Content page properties are empty");
+ ignoredContentPagesPropertiesCount++;
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("An error occurred while Migrating content pages properties:", e);
+ }
+ notMigratedContentPagesPropertiesCount = totalContentPagesPropertiesCount
+ - (processedContentPagesPropertiesCount + ignoredContentPagesPropertiesCount);
+ if (notMigratedContentPagesPropertiesCount == 0) {
+ LOG.info("End ContentArticlePropertiesUpgrade successful migration: total={} processed={} ignored={} error={}. It took {} ms.",
+ totalContentPagesPropertiesCount,
+ processedContentPagesPropertiesCount,
+ ignoredContentPagesPropertiesCount,
+ notMigratedContentPagesPropertiesCount,
+ (System.currentTimeMillis() - startupTime));
+ } else {
+ LOG.warn("End ContentArticlePropertiesUpgrade with some errors: total={} processed={} ignored={} error={}. It took {} ms."
+ + " The not migrated news articles will be processed again next startup.",
+ totalContentPagesPropertiesCount,
+ processedContentPagesPropertiesCount,
+ ignoredContentPagesPropertiesCount,
+ notMigratedContentPagesPropertiesCount,
+ (System.currentTimeMillis() - startupTime));
+ throw new IllegalStateException("Some content page properties weren't migrated successfully. It will be re-attempted next startup");
+ }
+ }
+
+ @Override
+ public boolean shouldProceedToUpgrade(String newVersion, String previousGroupVersion) {
+ SettingValue> settingValue = settingService.get(Context.GLOBAL.id(ARTICLES_UPGRADE_PLUGIN_NAME),
+ Scope.APPLICATION.id(ARTICLES_UPGRADE_PLUGIN_NAME),
+ ARTICLES_UPGRADE_EXECUTED_KEY);
+ if (settingValue == null || settingValue.getValue().equals("false")) {
+ return false;
+ }
+ return super.shouldProceedToUpgrade(newVersion, previousGroupVersion);
+ }
+
+ private MetadataFilter getMetadataFilter() {
+ MetadataFilter metadataFilter = new MetadataFilter();
+ metadataFilter.setMetadataName(NEWS_METADATA_NAME);
+ metadataFilter.setMetadataTypeName(NEWS_METADATA_NAME);
+ return metadataFilter;
+ }
+
+ private NoteMetadataObject buildNoteMetadataObject(Page note, String lang, String objectType) {
+ Space space = spaceService.getSpaceByGroupId(note.getWikiOwner());
+ long spaceId = space != null ? Long.parseLong(space.getId()) : 0L;
+ String noteId = String.valueOf(note.getId());
+ noteId = lang != null ? noteId + "-" + lang : noteId;
+ return new NoteMetadataObject(objectType, noteId, note.getParentPageId(), spaceId);
+ }
+
+ private MetadataItem getNoteMetadataItem(Page note, String lang, String objectType) {
+ NoteMetadataObject noteMetadataObject = buildNoteMetadataObject(note, lang, objectType);
+ return metadataService.getMetadataItemsByMetadataAndObject(NOTES_METADATA_KEY, noteMetadataObject)
+ .stream()
+ .findFirst()
+ .orElse(null);
+ }
+
+}
diff --git a/data-upgrade-news/src/main/java/org/exoplatform/news/upgrade/jcr/NewsArticlesUpgrade.java b/data-upgrade-news/src/main/java/org/exoplatform/news/upgrade/jcr/NewsArticlesUpgrade.java
index 59604bf11..804cb77f4 100644
--- a/data-upgrade-news/src/main/java/org/exoplatform/news/upgrade/jcr/NewsArticlesUpgrade.java
+++ b/data-upgrade-news/src/main/java/org/exoplatform/news/upgrade/jcr/NewsArticlesUpgrade.java
@@ -39,9 +39,15 @@
import io.meeds.notes.model.NotePageProperties;
import org.apache.commons.collections4.ListUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.exoplatform.commons.api.settings.SettingService;
+import org.exoplatform.commons.api.settings.SettingValue;
+import org.exoplatform.commons.api.settings.data.Context;
+import org.exoplatform.commons.api.settings.data.Scope;
import org.exoplatform.commons.file.model.FileItem;
import org.exoplatform.commons.file.services.FileService;
import org.exoplatform.commons.search.index.IndexingService;
+import org.exoplatform.commons.upgrade.UpgradePluginExecutionContext;
import org.exoplatform.commons.upgrade.UpgradeProductPlugin;
import org.exoplatform.commons.utils.CommonsUtils;
import org.exoplatform.commons.utils.HTMLSanitizer;
@@ -66,6 +72,7 @@
import org.exoplatform.social.metadata.model.MetadataKey;
import org.exoplatform.social.metadata.model.MetadataObject;
import org.exoplatform.social.metadata.model.MetadataType;
+import org.exoplatform.wiki.model.DraftPage;
import org.exoplatform.wiki.model.Page;
import org.exoplatform.wiki.model.PageVersion;
import org.exoplatform.wiki.service.NoteService;
@@ -75,6 +82,7 @@
import io.meeds.news.search.NewsIndexingServiceConnector;
import io.meeds.news.service.NewsService;
import io.meeds.news.utils.NewsUtils;
+import org.exoplatform.wiki.utils.Utils;
public class NewsArticlesUpgrade extends UpgradeProductPlugin {
@@ -97,8 +105,10 @@ public class NewsArticlesUpgrade extends UpgradeProductPlugin {
private NoteService noteService;
private IndexingService indexingService;
-
+
private IdentityManager identityManager;
+
+ private SettingService settingService;
private int migratedNewsArticlesCount = 0;
@@ -109,6 +119,14 @@ public class NewsArticlesUpgrade extends UpgradeProductPlugin {
private static final MetadataKey NEWS_METADATA_KEY =
new MetadataKey(NEWS_METADATA_TYPE.getName(), NEWS_METADATA_NAME, 0);
+ private static final MetadataKey NOTES_METADATA_KEY = new MetadataKey("notes", Utils.NOTES_METADATA_OBJECT_TYPE, 0);
+
+ private static final String PLUGIN_NAME = "NewsArticlesUpgradePlugin";
+
+ private static final String PLUGIN_EXECUTED_KEY = "articlesUpgradeExecuted";
+
+ private boolean upgradeFailed = false;
+
public NewsArticlesUpgrade(InitParams initParams,
RepositoryService repositoryService,
SessionProviderService sessionProviderService,
@@ -119,7 +137,8 @@ public NewsArticlesUpgrade(InitParams initParams,
FileService fileService,
NoteService noteService,
IdentityManager identityManager,
- IndexingService indexingService) {
+ IndexingService indexingService,
+ SettingService settingService) {
super(initParams);
this.repositoryService = repositoryService;
this.sessionProviderService = sessionProviderService;
@@ -131,6 +150,7 @@ public NewsArticlesUpgrade(InitParams initParams,
this.noteService = noteService;
this.identityManager = identityManager;
this.indexingService = indexingService;
+ this.settingService = settingService;
}
@Override
@@ -202,10 +222,36 @@ public void processUpgrade(String oldVersion, String newVersion) {
migratedNewsArticlesCount,
notMigratedNewsArticlesCount,
(System.currentTimeMillis() - startupTime));
+ this.upgradeFailed = true;
throw new IllegalStateException("Some news articles wasn't executed successfully. It will be re-attempted next startup");
}
}
+ @Override
+ public void afterUpgrade() {
+ if (!upgradeFailed) {
+ settingService.set(Context.GLOBAL.id(PLUGIN_NAME),
+ Scope.APPLICATION.id(PLUGIN_NAME),
+ PLUGIN_EXECUTED_KEY,
+ SettingValue.create(true));
+ }
+ }
+
+ @Override
+ public boolean shouldProceedToUpgrade(String newVersion, String previousGroupVersion, UpgradePluginExecutionContext upgradePluginExecutionContext) {
+ SettingValue> settingValue = settingService.get(Context.GLOBAL.id(PLUGIN_NAME),
+ Scope.APPLICATION.id(PLUGIN_NAME),
+ PLUGIN_EXECUTED_KEY);
+ boolean shouldUpgrade = super.shouldProceedToUpgrade(newVersion, previousGroupVersion, upgradePluginExecutionContext);
+ if (!shouldUpgrade && settingValue == null) {
+ settingService.set(Context.GLOBAL.id(PLUGIN_NAME),
+ Scope.APPLICATION.id(PLUGIN_NAME),
+ PLUGIN_EXECUTED_KEY,
+ SettingValue.create(true));
+ }
+ return shouldUpgrade;
+ }
+
public int manageNewsArticles(List newsArticlesNodes, Session session) throws Exception {
int notMigratedNewsArticlesCount = 0;
for (Node newsArticleNode : newsArticlesNodes) {
@@ -214,6 +260,7 @@ public int manageNewsArticles(List newsArticlesNodes, Session session) thr
News draftArticle = null;
try {
News news = convertNewsNodeToNewEntity(newsArticleNode, null);
+ NotePageProperties properties = news.getProperties();
LOG.info("Migrating news article with id '{}' and title '{}'", newsArticleNode.getUUID(), news.getTitle());
Space space = spaceService.getSpaceById(news.getSpaceId());
@@ -222,15 +269,14 @@ public int manageNewsArticles(List newsArticlesNodes, Session session) thr
|| getStringProperty(newsArticleNode, "publication:currentState").equals("published")) {
article = newsService.createNewsArticlePage(news, news.getAuthor());
- if (news.getProperties() != null && news.getAuthor() != null) {
- NotePageProperties properties = news.getProperties();
- properties.setNoteId(Long.parseLong(article.getId()));
+ properties.setNoteId(Long.parseLong(article.getId()));
+ if (news.getAuthor() != null) {
noteService.saveNoteMetadata(properties,
article.getLang(),
Long.valueOf(identityManager.getOrCreateUserIdentity(news.getAuthor()).getId()));
}
PageVersion pageVersion = noteService.getPublishedVersionByPageIdAndLang(Long.parseLong(article.getId()), null);
- setArticleIllustration(pageVersion.getId(), article.getSpaceId(), newsArticleNode, "newsPageVersion");
+ setArticleIllustration(pageVersion.getParent(), article.getSpaceId(), newsArticleNode, "notePage");
setArticleAttachments(pageVersion.getId(), article.getSpaceId(), newsArticleNode, "newsPageVersion");
/* upgrade news id for news targets and favorite metadatata items */
setArticleMetadatasItems(article.getId(), newsArticleNode.getUUID());
@@ -254,7 +300,15 @@ public int manageNewsArticles(List newsArticlesNodes, Session session) thr
space.getGroupId(),
news.getAuthor(),
news.getCreationDate().getTime());
- setArticleIllustration(draftArticle.getId(), draftArticle.getSpaceId(), newsArticleNode, "newsDraftPage");
+ DraftPage draftPage = noteService.getDraftNoteById(draftArticle.getId(), draftArticle.getAuthor());
+ properties.setNoteId(Long.parseLong(draftPage.getId()));
+ properties.setDraft(true);
+ if (news.getAuthor() != null) {
+ noteService.saveNoteMetadata(properties,
+ draftPage.getLang(),
+ Long.valueOf(identityManager.getOrCreateUserIdentity(news.getAuthor()).getId()));
+ }
+ setArticleIllustration(draftPage, draftArticle.getSpaceId(), newsArticleNode, "noteDraftPage");
} else {// drafts of existing articles
// upgrade existing articles
@@ -262,17 +316,17 @@ public int manageNewsArticles(List newsArticlesNodes, Session session) thr
Node versionNode = newsArticleNode.getVersionHistory().getSession().getNodeByUUID(versionNodeUUID);
Node publishedNode = versionNode.getNode("jcr:frozenNode");
News publishedNews = convertNewsNodeToNewEntity(newsArticleNode, publishedNode);
-
article = newsService.createNewsArticlePage(publishedNews, publishedNews.getAuthor());
- if (publishedNews.getProperties() != null && publishedNews.getAuthor() != null) {
- NotePageProperties properties = publishedNews.getProperties();
- properties.setNoteId(Long.parseLong(article.getId()));
- noteService.saveNoteMetadata(properties,
+ properties = publishedNews.getProperties();
+ properties.setNoteId(Long.parseLong(article.getId()));
+ if (publishedNews.getAuthor() != null) {
+ properties = noteService.saveNoteMetadata(properties,
article.getLang(),
- Long.valueOf(identityManager.getOrCreateUserIdentity(publishedNews.getAuthor()).getId()));
+ Long.valueOf(identityManager.getOrCreateUserIdentity(publishedNews.getAuthor())
+ .getId()));
}
PageVersion pageVersion = noteService.getPublishedVersionByPageIdAndLang(Long.parseLong(article.getId()), null);
- setArticleIllustration(pageVersion.getId(), article.getSpaceId(), publishedNode, "newsPageVersion");
+ setArticleIllustration(pageVersion.getParent(), article.getSpaceId(), publishedNode, "notePage");
setArticleAttachments(pageVersion.getId(), article.getSpaceId(), publishedNode, "newsPageVersion");
/* upgrade news id for news targets and favorite metadatata items */
setArticleMetadatasItems(article.getId(), newsArticleNode.getUUID());
@@ -282,14 +336,15 @@ public int manageNewsArticles(List newsArticlesNodes, Session session) thr
// upgrade the drafts of existing articles
/* attachments will not be migrated for drafts */
+ properties.setDraft(true);
+ news.setProperties(properties);
News draftForExistingArticle = newsService.createDraftForExistingPage(news,
news.getAuthor(),
publishedPage,
news.getCreationDate().getTime());
- setArticleIllustration(draftForExistingArticle.getId(),
- draftForExistingArticle.getSpaceId(),
- newsArticleNode,
- "newsLatestDraftPage");
+ DraftPage draftPage = noteService.getDraftNoteById(draftForExistingArticle.getId(),
+ draftForExistingArticle.getAuthor());
+ setArticleIllustration(draftPage, draftForExistingArticle.getSpaceId(), newsArticleNode, "noteDraftPage");
// set the update and the created date
setArticleCreateAndUpdateDate(article.getId(), article.getSpaceId(), newsArticleNode);
}
@@ -372,7 +427,7 @@ private Long saveArticleIllustration(InputStream articleIllustrationFileInputStr
FileItem articleIllustrationFileItem = new FileItem(null,
fileName,
mimeType,
- "news",
+ "wiki",
uploadSize,
new Date(),
IdentityConstants.SYSTEM,
@@ -386,10 +441,10 @@ private Long saveArticleIllustration(InputStream articleIllustrationFileInputStr
}
}
- private void setArticleIllustration(String articleId,
+ private void setArticleIllustration(Page article,
String spaceId,
Node newsNode,
- String articleObjectType) throws RepositoryException {
+ String articleObjectType) throws Exception {
if (newsNode.hasNode("illustration")) {
Node illustrationNode = newsNode.getNode("illustration");
Node illustrationContentNode = illustrationNode.getNode("jcr:content");
@@ -397,19 +452,32 @@ private void setArticleIllustration(String articleId,
String mimetype = illustrationContentNode.getProperty("jcr:mimeType").getString();
String illustrationNodeName = illustrationNode.getProperty("exo:title").getString();
Long articleIllustrationId = saveArticleIllustration(illustrationNodeInputStream, illustrationNodeName, mimetype, 0);
- MetadataObject articleMetaDataObject = new MetadataObject(articleObjectType, articleId, null, Long.parseLong(spaceId));
-
- MetadataItem articleMetadataItem = metadataService.getMetadataItemsByMetadataAndObject(NEWS_METADATA_KEY,
- articleMetaDataObject)
- .get(0);
- if (articleMetadataItem != null) {
- Map articleMetadataItemProperties = articleMetadataItem.getProperties();
- if (articleMetadataItemProperties == null) {
- articleMetadataItemProperties = new HashMap<>();
+ if (article != null && article.getAuthor() != null) {
+ long creatorId = Long.parseLong(identityManager.getOrCreateUserIdentity(article.getAuthor()).getId());
+ MetadataObject articleMetaDataObject = new MetadataObject(articleObjectType,
+ article.getId(),
+ article.getParentPageId(),
+ Long.parseLong(spaceId));
+
+ MetadataItem articleMetadataItem = metadataService
+ .getMetadataItemsByMetadataAndObject(NOTES_METADATA_KEY,
+ articleMetaDataObject)
+ .stream()
+ .findFirst()
+ .orElse(null);
+ Map articleMetadataItemProperties = new HashMap<>();
+ if (articleMetadataItem != null && !MapUtils.isEmpty(articleMetadataItem.getProperties())) {
+ articleMetadataItemProperties = articleMetadataItem.getProperties();
+ }
+ articleMetadataItemProperties.put("featuredImageId", String.valueOf(articleIllustrationId));
+ articleMetadataItemProperties.put("featuredImageUpdatedDate", String.valueOf(new Date().getTime()));
+
+ if (articleMetadataItem != null) {
+ articleMetadataItem.setProperties(articleMetadataItemProperties);
+ metadataService.updateMetadataItem(articleMetadataItem, creatorId);
+ } else {
+ metadataService.createMetadataItem(articleMetaDataObject, NOTES_METADATA_KEY, articleMetadataItemProperties, creatorId);
}
- articleMetadataItemProperties.put("illustrationId", String.valueOf(articleIllustrationId));
- articleMetadataItem.setProperties(articleMetadataItemProperties);
- metadataService.updateMetadataItem(articleMetadataItem, articleMetadataItem.getCreatorId());
}
}
}
diff --git a/data-upgrade-news/src/main/resources/conf/portal/configuration.xml b/data-upgrade-news/src/main/resources/conf/portal/configuration.xml
index a47efa764..53de8dd9e 100644
--- a/data-upgrade-news/src/main/resources/conf/portal/configuration.xml
+++ b/data-upgrade-news/src/main/resources/conf/portal/configuration.xml
@@ -48,6 +48,39 @@
+
+ ContentArticlePropertiesUpgrade
+ addUpgradePlugin
+ org.exoplatform.news.upgrade.ContentArticlePropertiesUpgrade
+ Migrate content properties from content to note
+
+
+ product.group.id
+ The groupId of the product
+ org.exoplatform.platform
+
+
+ plugin.execution.order
+ The plugin execution order
+ 1
+
+
+ plugin.upgrade.execute.once
+ Execute this upgrade plugin only once
+ true
+
+
+ plugin.upgrade.async.execution
+ The plugin will be executed in an asynchronous mode
+ true
+
+
+ plugin.upgrade.target.version
+ Target version of the plugin
+ 7.0.0
+
+
+
diff --git a/data-upgrade-news/src/test/java/org/exoplatform/news/upgrade/ContentArticlePropertiesUpgradeTest.java b/data-upgrade-news/src/test/java/org/exoplatform/news/upgrade/ContentArticlePropertiesUpgradeTest.java
new file mode 100644
index 000000000..60f4b4471
--- /dev/null
+++ b/data-upgrade-news/src/test/java/org/exoplatform/news/upgrade/ContentArticlePropertiesUpgradeTest.java
@@ -0,0 +1,164 @@
+package org.exoplatform.news.upgrade;
+
+import io.meeds.notes.model.NoteMetadataObject;
+import org.exoplatform.commons.api.settings.SettingService;
+import org.exoplatform.commons.api.settings.SettingValue;
+import org.exoplatform.container.xml.InitParams;
+import org.exoplatform.container.xml.ValueParam;
+import org.exoplatform.portal.config.UserACL;
+import org.exoplatform.social.core.identity.model.Identity;
+import org.exoplatform.social.core.manager.IdentityManager;
+import org.exoplatform.social.core.space.spi.SpaceService;
+import org.exoplatform.social.metadata.MetadataService;
+import org.exoplatform.social.metadata.model.MetadataItem;
+import org.exoplatform.social.metadata.model.MetadataKey;
+import org.exoplatform.wiki.model.DraftPage;
+import org.exoplatform.wiki.model.Page;
+import org.exoplatform.wiki.model.PageVersion;
+import org.exoplatform.wiki.service.NoteService;
+import org.exoplatform.wiki.utils.Utils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.data.elasticsearch.annotations.Setting;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ContentArticlePropertiesUpgradeTest {
+
+ @Mock
+ private NoteService noteService;
+
+ @Mock
+ private MetadataService metadataService;
+
+ @Mock
+ private IdentityManager identityManager;
+
+ @Mock
+ private SpaceService spaceService;
+
+ @Mock
+ private UserACL userACL;
+
+ @Mock
+ private SettingService settingService;
+
+ private ContentArticlePropertiesUpgrade contentArticlePropertiesUpgrade;
+
+ private static final MetadataKey NOTES_METADATA_KEY = new MetadataKey("notes", Utils.NOTES_METADATA_OBJECT_TYPE, 0);
+
+ private static final String ILLUSTRATION_ID = "illustrationId";
+
+ private static final String SUMMARY = "summary";
+
+ @Before
+ public void setUp() {
+ InitParams initParams = new InitParams();
+ ValueParam valueParam = new ValueParam();
+ valueParam.setName("product.group.id");
+ valueParam.setValue("org.exoplatform.platform");
+ initParams.addParameter(valueParam);
+ this.contentArticlePropertiesUpgrade = new ContentArticlePropertiesUpgrade(initParams,
+ noteService,
+ metadataService,
+ identityManager,
+ spaceService,
+ userACL,
+ settingService);
+ }
+
+ @Test
+ public void processUpgrade() throws Exception {
+ MetadataItem page = new MetadataItem();
+ MetadataItem draftOfPage = new MetadataItem();
+ MetadataItem draftOfPage2 = new MetadataItem();
+ MetadataItem draft = new MetadataItem();
+ page.setId(1L);
+ page.setObjectType("newsPageVersion");
+ page.setObjectId("1");
+ page.setProperties(Map.of(ILLUSTRATION_ID, "1", SUMMARY, "test summary"));
+
+ draftOfPage.setId(2L);
+ draftOfPage.setObjectType("newsLatestDraftPage");
+ draftOfPage.setObjectId("2");
+ draftOfPage.setProperties(Map.of(ILLUSTRATION_ID, "2", SUMMARY, "test summary"));
+
+ draftOfPage2.setId(4L);
+ draftOfPage2.setObjectType("newsLatestDraftPage");
+ draftOfPage2.setObjectId("6");
+ draftOfPage2.setProperties(Map.of(ILLUSTRATION_ID, "4", SUMMARY, "test summary"));
+
+ draft.setId(1L);
+ draft.setObjectId("3");
+ draft.setObjectType("newsDraftPage");
+ draft.setProperties(Map.of(ILLUSTRATION_ID, "3", SUMMARY, "test summary"));
+
+ Page parentPage = new Page();
+ parentPage.setId("2");
+ parentPage.setAuthor("user");
+ PageVersion pageVersion = new PageVersion();
+ pageVersion.setId("1");
+ pageVersion.setParent(parentPage);
+ pageVersion.setAuthor("user");
+
+ DraftPage draftOfExistingPage = new DraftPage();
+ draftOfExistingPage.setId("2");
+ draftOfExistingPage.setAuthor("user");
+
+ DraftPage draftOfExistingPage2 = new DraftPage();
+ draftOfExistingPage2.setId("6");
+
+ DraftPage draftPage = new DraftPage();
+ draftPage.setId("3");
+ draftPage.setAuthor("user");
+
+ MetadataItem notePage = new MetadataItem();
+ notePage.setId(5L);
+ notePage.setObjectType("notePage");
+ notePage.setObjectId("2");
+
+ List metadataItems = List.of(page, draftOfPage, draftOfPage2, draft);
+ Identity identity = mock(Identity.class);
+ when(metadataService.getMetadataItemsByFilter(any(), anyLong(), anyLong())).thenReturn(metadataItems);
+ when(noteService.getPageVersionById(anyLong())).thenReturn(pageVersion);
+ when(noteService.getDraftNoteById(anyString(), anyString())).thenReturn(draftOfExistingPage, draftOfExistingPage2, draftPage);
+ when(identityManager.getOrCreateUserIdentity(anyString())).thenReturn(identity);
+ when(metadataService.getMetadataItemsByMetadataAndObject(NOTES_METADATA_KEY,
+ new NoteMetadataObject("noteDraftPage", "3", null, 0L)))
+ .thenReturn(new ArrayList<>());
+ when(metadataService.getMetadataItemsByMetadataAndObject(NOTES_METADATA_KEY,
+ new NoteMetadataObject("noteDraftPage", "2", null, 0L)))
+ .thenReturn(new ArrayList<>());
+ when(metadataService.getMetadataItemsByMetadataAndObject(NOTES_METADATA_KEY,
+ new NoteMetadataObject("notePage", "2", null, 0L)))
+ .thenReturn(List.of(notePage));
+
+ when(userACL.getSuperUser()).thenReturn("root");
+ when(identity.getId()).thenReturn("1");
+ contentArticlePropertiesUpgrade.processUpgrade(null, null);
+
+ verify(metadataService, times(2)).createMetadataItem(any(), any(), any(), anyLong());
+ }
+
+ @Test
+ public void shouldProceedToUpgrade() {
+ SettingValue settingValue = mock(SettingValue.class);
+ when(settingValue.getValue()).thenReturn("false");
+ when(settingService.get(any(), any(), anyString())).thenReturn(null, settingValue);
+ assertFalse(contentArticlePropertiesUpgrade.shouldProceedToUpgrade("1.0", "1.2"));
+ assertFalse(contentArticlePropertiesUpgrade.shouldProceedToUpgrade("1.0", "1.2"));
+ when(settingValue.getValue()).thenReturn("true");
+ assertTrue(contentArticlePropertiesUpgrade.shouldProceedToUpgrade("1.0", "1.2"));
+ }
+}
diff --git a/data-upgrade-news/src/test/java/org/exoplatform/news/upgrade/jcr/NewsArticlesUpgradeTest.java b/data-upgrade-news/src/test/java/org/exoplatform/news/upgrade/jcr/NewsArticlesUpgradeTest.java
index 6bfa9a14c..d9c489cf1 100644
--- a/data-upgrade-news/src/test/java/org/exoplatform/news/upgrade/jcr/NewsArticlesUpgradeTest.java
+++ b/data-upgrade-news/src/test/java/org/exoplatform/news/upgrade/jcr/NewsArticlesUpgradeTest.java
@@ -16,18 +16,16 @@
*/
package org.exoplatform.news.upgrade.jcr;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Mockito.lenient;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.mockStatic;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
@@ -45,6 +43,10 @@
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
+import io.meeds.notes.model.NotePageProperties;
+import org.exoplatform.commons.api.settings.SettingService;
+import org.exoplatform.commons.api.settings.SettingValue;
+import org.exoplatform.commons.upgrade.UpgradePluginExecutionContext;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.manager.IdentityManager;
import org.junit.AfterClass;
@@ -124,6 +126,9 @@ public class NewsArticlesUpgradeTest {
@Mock
private IndexingService indexingService;
+ @Mock
+ private SettingService settingService;
+
private NewsArticlesUpgrade newsArticlesUpgrade;
@AfterClass
@@ -150,7 +155,8 @@ public void setUp() {
fileService,
noteService,
identityManager,
- indexingService);
+ indexingService,
+ settingService);
}
@Test
@@ -216,9 +222,12 @@ public void testProcessUpgrade() throws Exception {
News article = mock(News.class);
when(article.getId()).thenReturn("1");
when(article.getSpaceId()).thenReturn("1");
- when(newsService.createNewsArticlePage(any(News.class), anyString())).thenReturn(article);
-
+ Page page = new Page();
+ page.setId("1");
+ page.setAuthor("user");
+ when(identityManager.getOrCreateUserIdentity("user")).thenReturn(identity);
PageVersion pageVersion = mock(PageVersion.class);
+ when(pageVersion.getParent()).thenReturn(page);
when(noteService.getPublishedVersionByPageIdAndLang(anyLong(), nullable(String.class))).thenReturn(pageVersion);
when(noteService.getNoteById(anyString())).thenReturn(mock(Page.class));
when(pageVersion.getId()).thenReturn("1");
@@ -276,6 +285,12 @@ public void testProcessUpgrade() throws Exception {
when(startTimeProperty.getDate()).thenReturn(startTimePropertyCalendar);
when(startTimePropertyCalendar.getTime()).thenReturn(mock(Date.class));
+ Method method = newsArticlesUpgrade.getClass().getDeclaredMethod("convertNewsNodeToNewEntity", Node.class, Node.class);
+ method.setAccessible(true);
+ News news1 = (News) method.invoke(newsArticlesUpgrade, node1, null);
+ News news2 = (News) method.invoke(newsArticlesUpgrade, node2, null);
+ when(newsService.createNewsArticlePage(news1, "")).thenReturn(article);
+ when(newsService.createNewsArticlePage(news2, "")).thenReturn(article);
// Run the processUpgrade method
newsArticlesUpgrade.processUpgrade("1.0", "2.0");
@@ -286,4 +301,18 @@ public void testProcessUpgrade() throws Exception {
verify(activityManager, times(1)).getActivity(any());
verify(activityManager, times(1)).updateActivity(any(ExoSocialActivity.class), eq(false));
}
+
+ @Test
+ public void shouldProceedToUpgrade() {
+ SettingValue settingValue = mock(SettingValue.class);
+ UpgradePluginExecutionContext context = new UpgradePluginExecutionContext("0.9", 1);
+ when(settingService.get(any(), any(), anyString())).thenReturn(null);
+ newsArticlesUpgrade.shouldProceedToUpgrade("0.9", "1.0", context);
+ verify(settingService, times(1)).set(any(), any(), anyString(), any());
+ reset(settingService);
+ when(settingService.get(any(), any(), anyString())).thenReturn(settingValue);
+ context.setVersion("1.2");
+ newsArticlesUpgrade.shouldProceedToUpgrade("1.2", "1.0", context);
+ verify(settingService, times(0)).set(any(), any(), anyString(), any());
+ }
}