Skip to content

Commit

Permalink
feat: Implement an upgrade plugin for content articles attachments mi…
Browse files Browse the repository at this point in the history
…gration and adapt the NewsArticleUpgradePlugin - EXO-74446
  • Loading branch information
sofyenne authored Oct 29, 2024
1 parent 7fe058f commit ad19b68
Show file tree
Hide file tree
Showing 6 changed files with 347 additions and 21 deletions.
5 changes: 5 additions & 0 deletions data-upgrade-news/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
<artifactId>ecms-ext-authoring-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.ecms</groupId>
<artifactId>ecms-core-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.meeds.content</groupId>
<artifactId>content-service</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.exoplatform.news.upgrade;

import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import org.apache.commons.lang3.StringUtils;
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.persistence.impl.EntityManagerService;
import org.exoplatform.commons.upgrade.UpgradeProductPlugin;
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.container.component.RequestLifeCycle;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.services.attachments.storage.AttachmentStorage;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.wiki.model.PageVersion;
import org.exoplatform.wiki.service.NoteService;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class ArticleAttachmentsUpgradePlugin extends UpgradeProductPlugin {

private static final Log LOG = ExoLogger.getLogger(ArticleAttachmentsUpgradePlugin.class);

private SettingService settingService;

private NoteService noteService;

private EntityManagerService entityManagerService;

private AttachmentStorage attachmentStorage;

private final PortalContainer container;

private static final String ARTICLES_UPGRADE_EXECUTED_KEY = "articlesUpgradeExecuted";

private static final String ARTICLES_UPGRADE_PLUGIN_NAME = "NewsArticlesUpgradePlugin";

public ArticleAttachmentsUpgradePlugin(InitParams initParams,
EntityManagerService entityManagerService,
SettingService settingService,
NoteService noteService,
AttachmentStorage attachmentStorage, PortalContainer container) {
super(initParams);
this.settingService = settingService;
this.entityManagerService = entityManagerService;
this.noteService = noteService;
this.attachmentStorage = attachmentStorage;
this.container = container;
}

@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);
}

@Override
public void processUpgrade(String oldVersion, String newVersion) {
ExoContainerContext.setCurrentContainer(container);
long startupTime = System.currentTimeMillis();
int attachmentCount = 0;
int articleCount = 0;
boolean transactionStarted = false;
RequestLifeCycle.begin(this.entityManagerService);
EntityManager entityManager = this.entityManagerService.getEntityManager();
try {
if (!entityManager.getTransaction().isActive()) {
entityManager.getTransaction().begin();
transactionStarted = true;
}

List<Object[]> results = getAttachments(entityManager);
if (results.isEmpty()) {
return;
}
LOG.info("Start updating article attachments, {} articles should be updated", results.size());
for (Object[] result : results) {
String versionId = (String) result[0];
String originalVersionId = versionId;
String propertyValue = (String) result[1]; // get the value
PageVersion pageVersion = noteService.getPageVersionById(Long.valueOf(versionId));
if (pageVersion != null && pageVersion.getParent() != null && StringUtils.isNotEmpty(pageVersion.getParent().getId())) {
PageVersion latestVersion =
noteService.getPublishedVersionByPageIdAndLang(Long.valueOf(pageVersion.getParent().getId()),
null);
versionId = latestVersion.getId();
}
String[] attachmentIds = propertyValue.split(";");
attachmentCount += linkAttachmentsToEntity(versionId, attachmentIds);
articleCount += 1;
LOG.info("{} attachments linked to {} articles", attachmentCount, articleCount);

removeAttachmentProperty(originalVersionId, entityManager, transactionStarted);
}
if (transactionStarted && entityManager.getTransaction().isActive()) {
entityManager.getTransaction().commit();
}
LOG.info("Updating article attachments done it took {} ms", System.currentTimeMillis() - startupTime);
} catch (Exception e) {
if (transactionStarted && entityManager.getTransaction().isActive() && entityManager.getTransaction().getRollbackOnly()) {
entityManager.getTransaction().rollback();
}
LOG.error("Error when processing article attachments upgrade plugin", e);
} finally {
RequestLifeCycle.end();
}
}

private int linkAttachmentsToEntity(String articleId, String[] attachmentIds) {
AtomicInteger linkedAttachments = new AtomicInteger(0);

Arrays.stream(attachmentIds).forEach(id -> {
try {
// Link the attachment to the entity
this.attachmentStorage.linkAttachmentToEntity(Long.parseLong(articleId), "WIKI_PAGE_VERSIONS", id);
linkedAttachments.incrementAndGet();
} catch (Exception e) {
LOG.error("Error when linking attachment with id {} to entity with id {}", id, articleId, e);
}
});

return linkedAttachments.get();
}

private void removeAttachmentProperty(String articleId, EntityManager entityManager, boolean transactionStarted) {

String deleteQuery = "DELETE FROM SOC_METADATA_ITEMS_PROPERTIES "
+ "WHERE metadata_item_id IN (SELECT metadata_item_id FROM SOC_METADATA_ITEMS WHERE object_id = '" + articleId + "')"
+ " AND name = 'attachmentsIds'";

Query query = entityManager.createNativeQuery(deleteQuery);
query.executeUpdate();
}

private List<Object[]> getAttachments(EntityManager entityManager) {
String selectQuery = "SELECT mi.object_id, p.value " + "FROM SOC_METADATA_ITEMS mi " + "JOIN SOC_METADATA_ITEMS_PROPERTIES p "
+ "ON mi.metadata_item_id = p.metadata_item_id " + "WHERE mi.object_type = 'newsPageVersion' "
+ "AND p.name = 'attachmentsIds' " + "AND mi.object_id IS NOT NULL " + "AND mi.object_id != '' "
+ "AND p.value IS NOT NULL " + "AND p.value != '';";
Query nativeQuery = entityManager.createNativeQuery(selectQuery);
return nativeQuery.getResultList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.apache.commons.collections4.ListUtils;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.exoplatform.commons.api.settings.SettingService;
import org.exoplatform.commons.api.settings.SettingValue;
import org.exoplatform.commons.api.settings.data.Context;
Expand All @@ -52,6 +53,7 @@
import org.exoplatform.commons.utils.CommonsUtils;
import org.exoplatform.commons.utils.HTMLSanitizer;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.services.attachments.storage.AttachmentStorage;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.ext.app.SessionProviderService;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
Expand Down Expand Up @@ -110,6 +112,8 @@ public class NewsArticlesUpgrade extends UpgradeProductPlugin {

private SettingService settingService;

private AttachmentStorage attachmentStorage;

private int migratedNewsArticlesCount = 0;

public static final MetadataType NEWS_METADATA_TYPE = new MetadataType(1000, "news");
Expand Down Expand Up @@ -138,6 +142,7 @@ public NewsArticlesUpgrade(InitParams initParams,
NoteService noteService,
IdentityManager identityManager,
IndexingService indexingService,
AttachmentStorage attachmentStorage,
SettingService settingService) {
super(initParams);
this.repositoryService = repositoryService;
Expand All @@ -151,6 +156,7 @@ public NewsArticlesUpgrade(InitParams initParams,
this.identityManager = identityManager;
this.indexingService = indexingService;
this.settingService = settingService;
this.attachmentStorage = attachmentStorage;
}

@Override
Expand Down Expand Up @@ -279,7 +285,7 @@ public int manageNewsArticles(List<Node> newsArticlesNodes, Session session) thr
}
PageVersion pageVersion = noteService.getPublishedVersionByPageIdAndLang(Long.parseLong(article.getId()), null);
setArticleIllustration(pageVersion.getParent(), article.getSpaceId(), newsArticleNode, "notePage");
setArticleAttachments(pageVersion.getId(), article.getSpaceId(), newsArticleNode, "newsPageVersion");
setArticleAttachments(pageVersion.getId(), newsArticleNode);
/* upgrade news id for news targets and favorite metadatata items */
setArticleMetadatasItems(article.getId(), newsArticleNode.getUUID());
if (getStringProperty(newsArticleNode, "publication:currentState").equals("published")) {
Expand Down Expand Up @@ -330,7 +336,7 @@ public int manageNewsArticles(List<Node> newsArticlesNodes, Session session) thr
}
PageVersion pageVersion = noteService.getPublishedVersionByPageIdAndLang(Long.parseLong(article.getId()), null);
setArticleIllustration(pageVersion.getParent(), article.getSpaceId(), publishedNode, "notePage");
setArticleAttachments(pageVersion.getId(), article.getSpaceId(), publishedNode, "newsPageVersion");
setArticleAttachments(pageVersion.getId(), publishedNode);
/* upgrade news id for news targets and favorite metadatata items */
setArticleMetadatasItems(article.getId(), newsArticleNode.getUUID());
setArticleActivities(article, publishedNode);
Expand Down Expand Up @@ -544,28 +550,14 @@ private void setArticleViews(News article, Node newsNode) throws RepositoryExcep
}

private void setArticleAttachments(String articleId,
String spaceId,
Node newsNode,
String articleObjectType) throws RepositoryException {
Node newsNode) throws RepositoryException {
if (newsNode.hasProperty("exo:attachmentsIds")) {
Property attachmentsIdsProperty = newsNode.getProperty("exo:attachmentsIds");
String attachmentsIds = "";
for (Value value : attachmentsIdsProperty.getValues()) {
String attachmentId = value.getString();
attachmentsIds += attachmentId + ";";
}
MetadataObject articleMetaDataObject = new MetadataObject(articleObjectType, articleId, null, Long.parseLong(spaceId));
MetadataItem articleMetadataItem = metadataService.getMetadataItemsByMetadataAndObject(NEWS_METADATA_KEY,
articleMetaDataObject)
.get(0);
if (articleMetadataItem != null) {
Map<String, String> articleMetadataItemProperties = articleMetadataItem.getProperties();
if (articleMetadataItemProperties == null) {
articleMetadataItemProperties = new HashMap<>();
if (StringUtils.isNotEmpty(attachmentId) && StringUtils.isNotEmpty(articleId)) {
attachmentStorage.linkAttachmentToEntity(Long.valueOf(articleId), "WIKI_PAGE_VERSIONS", attachmentId);
}
articleMetadataItemProperties.put("attachmentsIds", attachmentsIds);
articleMetadataItem.setProperties(articleMetadataItemProperties);
metadataService.updateMetadataItem(articleMetadataItem, articleMetadataItem.getCreatorId());
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions data-upgrade-news/src/main/resources/conf/portal/configuration.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,39 @@
</value-param>
</init-params>
</component-plugin>
<component-plugin profiles="content">
<name>ContentArticleAttachmentsUpgrade</name>
<set-method>addUpgradePlugin</set-method>
<type>org.exoplatform.news.upgrade.ArticleAttachmentsUpgradePlugin</type>
<description>Migrate content attachments from metadata properties to attachments context</description>
<init-params>
<value-param>
<name>product.group.id</name>
<description>The groupId of the product</description>
<value>org.exoplatform.platform</value>
</value-param>
<value-param>
<name>plugin.execution.order</name>
<description>The plugin execution order</description>
<value>1</value>
</value-param>
<value-param>
<name>plugin.upgrade.execute.once</name>
<description>Execute this upgrade plugin only once</description>
<value>true</value>
</value-param>
<value-param>
<name>plugin.upgrade.async.execution</name>
<description>The plugin will be executed in an asynchronous mode</description>
<value>true</value>
</value-param>
<value-param>
<name>plugin.upgrade.target.version</name>
<description>Target version of the plugin</description>
<value>7.0.0</value>
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>

</configuration>
Loading

0 comments on commit ad19b68

Please sign in to comment.