diff --git a/services/pom.xml b/services/pom.xml
index 6bb25f18f6..e81c2aab66 100644
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -36,7 +36,7 @@
1.0
News addon used Rest endpoints
- 0.41
+ 0.43
diff --git a/services/src/main/java/org/exoplatform/news/queryBuilder/NewsQueryBuilder.java b/services/src/main/java/org/exoplatform/news/queryBuilder/NewsQueryBuilder.java
index 7939aa8d7e..f6cd8f82e7 100644
--- a/services/src/main/java/org/exoplatform/news/queryBuilder/NewsQueryBuilder.java
+++ b/services/src/main/java/org/exoplatform/news/queryBuilder/NewsQueryBuilder.java
@@ -60,16 +60,17 @@ public StringBuilder buildQuery(NewsFilter filter) throws Exception {
String escapedQuoteFuzzyText = fuzzyText.replace("'", "''").replace("\"", "\"\"");
String escapedQuoteSearchText = filter.getSearchText().replace("'", "''").replace("\"", "\"\"");
sqlQuery.append("(CONTAINS(.,'").append(escapedQuoteFuzzyText).append("') OR (exo:body LIKE '%").append(escapedQuoteSearchText).append("%'))");
- if (filter.getTagNames() != null && !filter.getTagNames().isEmpty()){
- sqlQuery.append(" OR (");
+ sqlQuery.append("AND ");
+ } else {
+ if (filter.getTagNames() != null && !filter.getTagNames().isEmpty()) {
for (String tagName : filter.getTagNames()) {
sqlQuery.append(" exo:body LIKE '%#").append(tagName).append("%'");
- if (filter.getTagNames().indexOf(tagName) != filter.getTagNames().size() -1) {
+ if (filter.getTagNames().indexOf(tagName) != filter.getTagNames().size() - 1) {
sqlQuery.append(" OR");
}
}
- sqlQuery.append(" ) AND ");
- } else sqlQuery.append("AND ");
+ sqlQuery.append(" AND ");
+ }
}
if (filter.isPublishedNews()) {
sqlQuery.append("exo:pinned = 'true' AND ");
diff --git a/services/src/main/java/org/exoplatform/news/rest/NewsRestResourcesV1.java b/services/src/main/java/org/exoplatform/news/rest/NewsRestResourcesV1.java
index 8a5d5ba6ed..71a4bd421b 100644
--- a/services/src/main/java/org/exoplatform/news/rest/NewsRestResourcesV1.java
+++ b/services/src/main/java/org/exoplatform/news/rest/NewsRestResourcesV1.java
@@ -483,8 +483,12 @@ public Response getNews(@Context HttpServletRequest request,
String lang = request.getLocale().getLanguage();
TagService tagService = CommonsUtils.getService(TagService.class);
long userIdentityId = RestUtils.getCurrentUserIdentityId();
- List tagNames = tagService.findTags(new TagFilter(text, 0), userIdentityId);
- if (tagNames != null && !tagNames.isEmpty()) newsFilter.setTagNames(tagNames.stream().map(e -> e.getName()).toList());
+ if (text.indexOf("#") == 0) {
+ String tagName = text.replace("#","");
+ List tagNames = tagService.findTags(new TagFilter(tagName, 0), userIdentityId);
+ if (tagNames != null && !tagNames.isEmpty()) newsFilter.setTagNames(tagNames.stream().map(e -> e.getName()).toList());
+ }
+
news = newsService.searchNews(newsFilter, lang);
} else {
org.exoplatform.services.security.Identity currentIdentity = ConversationState.getCurrent().getIdentity();
@@ -1008,7 +1012,7 @@ private NewsFilter buildFilter(List spaces, String filter, String text,
}
}
// Set text to search news with
- if (StringUtils.isNotEmpty(text)) {
+ if (StringUtils.isNotEmpty(text) && text.indexOf("#") != 0) {
newsFilter.setSearchText(text);
}
diff --git a/services/src/test/java/org/exoplatform/news/queryBuilder/NewsQueryBuilderTest.java b/services/src/test/java/org/exoplatform/news/queryBuilder/NewsQueryBuilderTest.java
index 09e137b2b7..ce5bcfac54 100644
--- a/services/src/test/java/org/exoplatform/news/queryBuilder/NewsQueryBuilderTest.java
+++ b/services/src/test/java/org/exoplatform/news/queryBuilder/NewsQueryBuilderTest.java
@@ -2,16 +2,19 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import org.exoplatform.commons.utils.CommonsUtils;
+import org.exoplatform.social.core.identity.model.Identity;
+import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider;
+import org.exoplatform.social.core.manager.IdentityManager;
import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.MockitoJUnitRunner;
@@ -20,19 +23,17 @@
import org.exoplatform.services.security.ConversationState;
import org.exoplatform.services.security.MembershipEntry;
import org.exoplatform.social.core.space.model.Space;
-import org.exoplatform.social.core.space.spi.SpaceService;
@RunWith(MockitoJUnitRunner.class)
public class NewsQueryBuilderTest {
private static final MockedStatic NEWS_UTILS = mockStatic(NewsUtils.class);
-
- @Mock
- SpaceService spaceService;
+ private static final MockedStatic COMMONS_UTILS = mockStatic(CommonsUtils.class);
@AfterClass
public static void afterRunBare() throws Exception { // NOSONAR
NEWS_UTILS.close();
+ COMMONS_UTILS.close();
}
@Test
@@ -48,6 +49,14 @@ public void shouldCreateQueryWithPinnedStateAndSearchTextAndAuthorAndOneSpaceAnd
List spaces = new ArrayList<>();
spaces.add("1");
filter.setSpaces(spaces);
+ filter.setDraftNews(true);
+ Space space1 = new Space();
+ space1.setId("1");
+ List allowedDraftNewsSpaces = new ArrayList<>();
+ allowedDraftNewsSpaces.add(space1);
+ NEWS_UTILS.when(() -> NewsUtils.getAllowedDraftNewsSpaces(any())).thenReturn(allowedDraftNewsSpaces);
+ Identity identity = new Identity(OrganizationIdentityProvider.NAME, "jean");
+ identity.setRemoteId("jean");
org.exoplatform.services.security.Identity currentIdentity = new org.exoplatform.services.security.Identity("john");
MembershipEntry membershipentry = new MembershipEntry("/platform/web-contributors", "redactor");
List memberships = new ArrayList();
@@ -55,13 +64,16 @@ public void shouldCreateQueryWithPinnedStateAndSearchTextAndAuthorAndOneSpaceAnd
currentIdentity.setMemberships(memberships);
ConversationState state = new ConversationState(currentIdentity);
ConversationState.setCurrent(state);
+ IdentityManager identityMock = mock(IdentityManager.class);
+ COMMONS_UTILS.when(() -> CommonsUtils.getService(IdentityManager.class)).thenReturn(identityMock);
+ when(identityMock.getOrCreateIdentity(anyString(), anyString())).thenReturn(identity);
// when
StringBuilder query = queryBuilder.buildQuery(filter);
// then
assertNotNull(query);
- assertEquals("SELECT * FROM exo:news WHERE ( exo:archived IS NULL OR exo:archived = 'false' OR ( exo:archived = 'true' AND exo:author = 'john')) AND (CONTAINS(.,'text~0.6') OR (exo:body LIKE '%text%')) OR ( exo:body LIKE '%#text%' OR exo:body LIKE '%#tex%' ) AND exo:pinned = 'true' AND ( exo:spaceId = '1') AND exo:author = 'john' AND (publication:currentState = 'published' OR (publication:currentState = 'draft' AND exo:activities <> '' )) AND jcr:path LIKE '/Groups/spaces/%' ORDER BY jcr:score DESC",
+ assertEquals("SELECT * FROM exo:news WHERE ( exo:archived IS NULL OR exo:archived = 'false' OR ( exo:archived = 'true' AND exo:author = 'john')) AND (CONTAINS(.,'text~0.6') OR (exo:body LIKE '%text%'))AND exo:pinned = 'true' AND ( exo:spaceId = '1') AND publication:currentState = 'draft' AND (('null' IN exo:newsModifiersIds AND exo:activities <> '') OR ( exo:author = 'john' AND exo:activities = '')OR (exo:spaceId = '1') AND exo:draftVisible = 'true') AND jcr:path LIKE '/Groups/spaces/%' ORDER BY jcr:score DESC",
query.toString());
}
@@ -221,6 +233,27 @@ public void shouldCreateQueryWithNoFilter() throws Exception {
assertNotNull(query);
assertEquals("SELECT * FROM exo:news WHERE ", query.toString());
}
+
+ @Test
+ public void testBuildQueryWithTagNames() throws Exception {
+ // Given
+ NewsQueryBuilder queryBuilder = new NewsQueryBuilder();
+ org.exoplatform.services.security.Identity currentIdentity = new org.exoplatform.services.security.Identity("john");
+ ConversationState state = new ConversationState(currentIdentity);
+ ConversationState.setCurrent(state);
+ NewsFilter filter = new NewsFilter();
+ filter.setAuthor("john");
+ filter.setTagNames(Arrays.asList(new String[]{"text"}));
+
+ // when
+ StringBuilder query = queryBuilder.buildQuery(filter);
+
+ // then
+ assertNotNull(query);
+ assertEquals("SELECT * FROM exo:news WHERE ( exo:archived IS NULL OR exo:archived = 'false' OR ( exo:archived = 'true' AND exo:author = 'john')) AND exo:body LIKE '%#text%' AND exo:author = 'john' AND (publication:currentState = 'published' OR (publication:currentState = 'draft' AND exo:activities <> '' )) AND jcr:path LIKE '/Groups/spaces/%' ORDER BY null DESC",
+ query.toString());
+ }
+
@Test
public void shouldAddFuzzySyntaxWhitQuotedWord() throws Exception {
// Given
@@ -232,7 +265,7 @@ public void shouldAddFuzzySyntaxWhitQuotedWord() throws Exception {
// Then
assertNotNull(result);
- assertEquals(result, "\"quoted\"~0.6");
+ assertEquals("\"quoted\"~0.6", result);
}
@Test
@@ -246,7 +279,7 @@ public void shouldAddFuzzySyntaxWhenTextContainsMultiWords() throws Exception {
// Then
assertNotNull(result);
- assertEquals(result, "search~0.6 OR text~0.6");
+ assertEquals("search~0.6 OR text~0.6", result);
}
@Test
@@ -260,7 +293,7 @@ public void shouldAddFuzzySyntaxWhenTextContainsQuotedMultiWords() throws Except
// Then
assertNotNull(result);
- assertEquals(result, "\"search text\"~0.6");
+ assertEquals("\"search text\"~0.6", result);
}
@Test
public void shouldAddFuzzySyntaxWhenTextContainsMultiWordsAndQuotedOne() throws Exception {
@@ -273,6 +306,19 @@ public void shouldAddFuzzySyntaxWhenTextContainsMultiWordsAndQuotedOne() throws
// Then
assertNotNull(result);
- assertEquals(result, "this~0.6 OR is~0.6 OR a~0.6 OR \"search text\"~0.6");
+ assertEquals("this~0.6 OR is~0.6 OR a~0.6 OR \"search text\"~0.6", result);
+ }
+
+ @Test
+ public void testAddFuzzySyntaxAndORQuoteInsideQuote() {
+ // Given
+ NewsQueryBuilder queryBuilder = new NewsQueryBuilder();
+ String text = "This \"quoted\" text.";
+
+ // when
+ String result = queryBuilder.addFuzzySyntaxAndOR(text);
+
+ // then
+ assertEquals("This~0.6 OR \"quoted\"~0.6 OR text.~0.6", result);
}
}
diff --git a/services/src/test/java/org/exoplatform/news/rest/NewsRestResourcesV1Test.java b/services/src/test/java/org/exoplatform/news/rest/NewsRestResourcesV1Test.java
index cc7b4d5c3f..a0ef7611cb 100644
--- a/services/src/test/java/org/exoplatform/news/rest/NewsRestResourcesV1Test.java
+++ b/services/src/test/java/org/exoplatform/news/rest/NewsRestResourcesV1Test.java
@@ -1576,7 +1576,6 @@ public void shouldGetAllNewsWhenSearchingWithTextInTheGivenSpaces() throws Excep
allNews.add(news3);
COMMONS_UTILS.when(()-> CommonsUtils.getService(TagService.class)).thenReturn(tagService);
REST_UTILS.when(()-> RestUtils.getCurrentUserIdentityId()).thenReturn(1L);
- when(tagService.findTags(new TagFilter(text, 0), 1L)).thenReturn(new ArrayList<>());
lenient().when(newsService.searchNews(any(), any())).thenReturn(allNews);
lenient().when(spaceService.isMember(any(Space.class), any())).thenReturn(true);
lenient().when(spaceService.getSpaceById(anyString())).thenReturn(new Space());
@@ -1632,7 +1631,6 @@ public void shouldGetAllNewsWhenSearchingWithTextInTheGivenSpace() throws Except
allNews.add(news3);
COMMONS_UTILS.when(()-> CommonsUtils.getService(TagService.class)).thenReturn(tagService);
REST_UTILS.when(()-> RestUtils.getCurrentUserIdentityId()).thenReturn(1L);
- when(tagService.findTags(new TagFilter(text, 0), 1L)).thenReturn(new ArrayList<>());
lenient().when(newsService.searchNews(any(), any())).thenReturn(allNews);
lenient().when(spaceService.isMember(any(Space.class), any())).thenReturn(true);
lenient().when(spaceService.getSpaceById(anyString())).thenReturn(new Space());
@@ -1681,7 +1679,6 @@ public void shouldGetAllNewsWhenSearchingWithTagTextInTheGivenSpace() throws Exc
allNews.add(news2);
COMMONS_UTILS.when(()-> CommonsUtils.getService(TagService.class)).thenReturn(tagService);
REST_UTILS.when(()-> RestUtils.getCurrentUserIdentityId()).thenReturn(1L);
- when(tagService.findTags(new TagFilter(tagText, 0), 1L)).thenReturn(Arrays.asList(new TagName("tagText")));
lenient().when(newsService.searchNews(any(), any())).thenReturn(allNews);
lenient().when(spaceService.isMember(any(Space.class), any())).thenReturn(true);
lenient().when(spaceService.getSpaceById(anyString())).thenReturn(new Space());
@@ -1733,7 +1730,6 @@ public void shouldGetPinnedNewsWhenSearchingWithTextInTheGivenSpaces() throws Ex
allNews.add(news3);
COMMONS_UTILS.when(()-> CommonsUtils.getService(TagService.class)).thenReturn(tagService);
REST_UTILS.when(()-> RestUtils.getCurrentUserIdentityId()).thenReturn(1L);
- when(tagService.findTags(new TagFilter(text, 0), 1L)).thenReturn(new ArrayList<>());
lenient().when(newsService.searchNews(any(), any())).thenReturn(allNews);
lenient().when(spaceService.isMember(any(Space.class), any())).thenReturn(true);
lenient().when(spaceService.getSpaceById(anyString())).thenReturn(new Space());
@@ -1918,7 +1914,6 @@ public void shouldGetMyPostedNewsWhenSearchingWithTheGivenSpaces() throws Except
allNews.add(news3);
COMMONS_UTILS.when(()-> CommonsUtils.getService(TagService.class)).thenReturn(tagService);
REST_UTILS.when(()-> RestUtils.getCurrentUserIdentityId()).thenReturn(1L);
- when(tagService.findTags(new TagFilter(text, 0), 1L)).thenReturn(new ArrayList<>());
lenient().when(newsService.searchNews(any(), any())).thenReturn(allNews);
lenient().when(spaceService.isMember(any(Space.class), any())).thenReturn(true);
lenient().when(spaceService.getSpaceById(anyString())).thenReturn(new Space());
diff --git a/webapp/src/main/webapp/services/newsServices.js b/webapp/src/main/webapp/services/newsServices.js
index e897991cce..72e84e1c83 100644
--- a/webapp/src/main/webapp/services/newsServices.js
+++ b/webapp/src/main/webapp/services/newsServices.js
@@ -55,6 +55,9 @@ export function markNewsAsRead(newsId){
export function getNews(filter, spaces, searchText, offset, limit, returnSize) {
let url = `${newsConstants.NEWS_API}?author=${newsConstants.userName}&publicationState=published&filter=${filter}`;
if (searchText) {
+ if (searchText.indexOf('#') === 0) {
+ searchText = searchText.replace('#', '%23');
+ }
url += `&text=${searchText}`;
}
if (spaces) {