Skip to content

Commit

Permalink
feat: Delete published note should delete its related activity and ar…
Browse files Browse the repository at this point in the history
…ticle properties - EXO-75617 - Meeds-io/MIPs#161 (#338)

Ensure delete article properties of externally deleted published note
  • Loading branch information
hakermi authored Dec 9, 2024
1 parent f9ae72b commit ae6a701
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,29 @@
import org.exoplatform.services.listener.Event;
import org.exoplatform.services.listener.Listener;
import org.exoplatform.services.listener.ListenerService;
import org.exoplatform.services.security.Identity;
import org.exoplatform.social.core.storage.api.ActivityStorage;
import org.exoplatform.social.core.storage.cache.CachedActivityStorage;
import org.exoplatform.wiki.model.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ExternalArticlePageListener extends Listener<String, Page> {
public class ExternalArticlePageListener extends Listener<Object, Page> {

private final ListenerService listenerService;

private final NewsService newsService;

private CachedActivityStorage cachedActivityStorage;

private static final String[] LISTENER_EVENTS = { "note.updated" };
private static final String NOTE_DELETED = "note.deleted";

private static final String NOTE_UPDATED = "note.updated";

private static final String ARTICLE = "article";

private static final String[] LISTENER_EVENTS = { NOTE_DELETED, NOTE_UPDATED };

@Autowired
public ExternalArticlePageListener(ListenerService listenerService, NewsService newsService, ActivityStorage activityStorage) {
Expand All @@ -54,18 +61,23 @@ public ExternalArticlePageListener(ListenerService listenerService, NewsService

@PostConstruct
public void init() {
for (String listener : LISTENER_EVENTS) {
listenerService.addListener(listener, this);
for (String event : LISTENER_EVENTS) {
listenerService.addListener(event, this);
}
}

@Override
public void onEvent(Event<String, Page> event) throws Exception {
public void onEvent(Event<Object, Page> event) throws Exception {
Page page = event.getData();
if (page != null) {
News news = newsService.getNewsArticleById(page.getId());
if (news != null && news.getActivityId() != null) {
cachedActivityStorage.clearActivityCached(news.getActivityId());
if (event.getEventName().equals(NOTE_UPDATED)) {
News news = newsService.getNewsArticleById(page.getId());
if (news != null && news.getActivityId() != null) {
cachedActivityStorage.clearActivityCached(news.getActivityId());
}
} else if (event.getEventName().equals(NOTE_DELETED) && newsService.getNewsArticleById(page.getId()) != null) {
Identity identity = (Identity) event.getSource();
newsService.deleteNews(page.getId(), identity, ARTICLE);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1118,37 +1118,17 @@ public News createDraftForExistingPage(News draftArticle,
@Override
public void deleteArticle(News news, String articleCreator) throws Exception {
Page articlePage = noteService.getNoteById(news.getId());
if (articlePage != null && !articlePage.isDeleted()) {
boolean hasDraft = true;
while (hasDraft) {
try {
DraftPage latestDraftPage = noteService.getLatestDraftOfPage(articlePage, articleCreator);
if (latestDraftPage != null) {
deleteDraftArticle(latestDraftPage.getId(), articleCreator);
} else {
hasDraft = false;
}
} catch (Exception exception) {
hasDraft = false;
}
}
boolean isDeleted = noteService.deleteNote(articlePage.getWikiType(), articlePage.getWikiOwner(), articlePage.getName());
if (isDeleted) {
NewsPageObject newsPageMetadataObject = new NewsPageObject(NEWS_METADATA_PAGE_OBJECT_TYPE,
news.getId(),
null,
Long.parseLong(news.getSpaceId()));
MetadataItem metadataItem = metadataService.getMetadataItemsByMetadataAndObject(NEWS_METADATA_KEY, newsPageMetadataObject)
.stream()
.findFirst()
.orElse(null);
if (metadataItem != null) {
Map<String, String> properties = metadataItem.getProperties();
properties.put(NEWS_DELETED, String.valueOf(true));
metadataItem.setProperties(properties);
String currentIdentityId = identityManager.getOrCreateUserIdentity(articleCreator).getId();
metadataService.updateMetadataItem(metadataItem, Long.parseLong(currentIdentityId), false);

if (articlePage != null) {
if (!articlePage.isDeleted()) {
deleteAllDrafts(articlePage, articleCreator);
if (noteService.deleteNote(articlePage.getWikiType(), articlePage.getWikiOwner(), articlePage.getName())) {
updateDeletedArticleMetadata(news, articleCreator);
}
} else {
// If the article is already deleted,
// case of external publish, still update metadata
updateDeletedArticleMetadata(news, articleCreator);
}
}
}
Expand Down Expand Up @@ -1180,6 +1160,44 @@ public List<String> getArticleLanguages(String articleId, boolean withDrafts) th
return noteService.getPageAvailableTranslationLanguages(Long.parseLong(articleId), withDrafts);
}

private void deleteAllDrafts(Page articlePage, String articleCreator) {
boolean hasDraft = true;
while (hasDraft) {
try {
DraftPage latestDraft = noteService.getLatestDraftOfPage(articlePage);

if (latestDraft != null) {
deleteDraftArticle(latestDraft.getId(), articleCreator);
} else {
hasDraft = false;
}
} catch (Exception e) {
LOG.error("Error while deleting draft", e.getMessage());
hasDraft = false;
}
}
}

private void updateDeletedArticleMetadata(News news, String articleCreator) {
NewsPageObject newsPageObject = new NewsPageObject(NEWS_METADATA_PAGE_OBJECT_TYPE,
news.getId(),
null,
Long.parseLong(news.getSpaceId()));

MetadataItem metadataItem = metadataService.getMetadataItemsByMetadataAndObject(NEWS_METADATA_KEY, newsPageObject)
.stream()
.findFirst()
.orElse(null);

if (metadataItem != null) {
Map<String, String> properties = metadataItem.getProperties();
properties.put(NEWS_DELETED, String.valueOf(true));
metadataItem.setProperties(properties);
String currentIdentityId = identityManager.getOrCreateUserIdentity(articleCreator).getId();
metadataService.updateMetadataItem(metadataItem, Long.parseLong(currentIdentityId), false);
}
}

private void postProcessing(News news, String poster) throws Exception {
if (news.getAuthor() == null) {
news.setAuthor(poster);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import io.meeds.news.service.NewsService;
import org.exoplatform.services.listener.Event;
import org.exoplatform.services.listener.ListenerService;
import org.exoplatform.services.security.Identity;
import org.exoplatform.services.security.IdentityRegistry;
import org.exoplatform.social.core.storage.api.ActivityStorage;
import org.exoplatform.social.core.storage.cache.CachedActivityStorage;
import org.exoplatform.wiki.model.Page;
Expand All @@ -16,6 +18,7 @@
import java.lang.reflect.Field;

import static org.mockito.Mockito.*;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class ExternalArticlePageListenerTest {
Expand All @@ -26,6 +29,9 @@ public class ExternalArticlePageListenerTest {
@Mock
private NewsService newsService;

@Mock
private IdentityRegistry identityRegistry;

@Mock
private ActivityStorage activityStorage;

Expand All @@ -51,9 +57,15 @@ public void onEvent() throws Exception {
note.setId("1");
note.setWikiOwner("/spaces/space");
note.setContent("tes");
Event<String, Page> event = new Event<>("note.updated", "user", note);
Identity identity = mock(Identity.class);

Event<Object, Page> event = new Event<>("note.updated", "user", note);
when(newsService.getNewsArticleById("1")).thenReturn(article);
externalArticlePageListener.onEvent(event);
verify(cachedActivityStorage, times(1)).clearActivityCached("1");

event = new Event<>("note.deleted", identity, note);
externalArticlePageListener.onEvent(event);
verify(newsService, times(1)).deleteNews("1", identity, "article");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -844,18 +844,29 @@ public void testDeleteNewsArticle() throws Exception {
draftProperties.setFeaturedImage(noteFeaturedImage);
when(draftPage.getId()).thenReturn("1");
when(draftPage.getProperties()).thenReturn(draftProperties);
when(noteService.getLatestDraftOfPage(existingPage, identity.getUserId())).thenReturn(draftPage);
when(noteService.getLatestDraftOfPage(existingPage)).thenReturn(draftPage);
when(noteService.getDraftNoteById(anyString(), anyString())).thenReturn(draftPage);
when(identityManager.getOrCreateUserIdentity(anyString())).thenReturn(new org.exoplatform.social.core.identity.model.Identity("1"));
doNothing().when(noteService).removeNoteFeaturedImage(anyLong(), anyLong(), anyString(), anyBoolean(), anyLong());

when(existingPage.isDeleted()).thenReturn(false);
newsService.deleteNews(existingPage.getId(), identity, ARTICLE.name().toLowerCase());

//Then
verify(noteService, times(1)).deleteNote(existingPage.getWikiType(), existingPage.getWikiOwner(), existingPage.getName());
verify(noteService, times(1)).removeDraftById("1");
verify(activityManager, times(1)).deleteActivity("1");
verify(metadataService, times(1)).updateMetadataItem(any(MetadataItem.class), anyLong(), anyBoolean());

clearInvocations(noteService, activityManager, metadataService);
when(existingPage.isDeleted()).thenReturn(true);

newsService.deleteNews(existingPage.getId(), identity, ARTICLE.name().toLowerCase());

verify(noteService, times(0)).deleteNote(existingPage.getWikiType(), existingPage.getWikiOwner(), existingPage.getName());
verify(noteService, times(0)).removeDraftById("1");
verify(activityManager, times(1)).deleteActivity("1");
verify(metadataService, times(1)).updateMetadataItem(any(MetadataItem.class), anyLong(), anyBoolean());
}

@Test
Expand Down

0 comments on commit ae6a701

Please sign in to comment.