Skip to content
Snippets Groups Projects
Commit c090cdf3 authored by Simon Urli's avatar Simon Urli
Browse files

XWIKI-18903: Allow to recompute average ratings from script service

  * Provide a new script service method to allow re-compute the average
    rating. Note that this method needs programming right since it can
be resource consuming.
parent c3c82ebb
No related branches found
No related tags found
No related merge requests found
......@@ -38,6 +38,8 @@
import org.xwiki.ratings.RatingsConfiguration;
import org.xwiki.ratings.RatingsException;
import org.xwiki.ratings.RatingsManager;
import org.xwiki.security.authorization.ContextualAuthorizationManager;
import org.xwiki.security.authorization.Right;
import org.xwiki.stability.Unstable;
import org.xwiki.user.UserReference;
import org.xwiki.user.UserReferenceResolver;
......@@ -64,6 +66,9 @@ public abstract class AbstractScriptRatingsManager implements RatingsScriptServi
@Named("document")
private UserReferenceResolver<DocumentReference> userReferenceResolver;
@Inject
private ContextualAuthorizationManager authorizationManager;
@Inject
private Logger logger;
......@@ -132,6 +137,24 @@ public Optional<AverageRating> getAverageRating(EntityReference reference)
return Optional.empty();
}
@Override
public Optional<AverageRating> recomputeAverageRating(EntityReference reference)
{
if (this.authorizationManager.hasAccess(Right.PROGRAM)) {
try {
return Optional.of(this.ratingsManager.recomputeAverageRating(reference));
} catch (RatingsException e) {
logger.error("Error when computing average rating for reference [{}]", reference,
ExceptionUtils.getRootCause(e));
}
} else {
logger.warn("Recomputation of average rating is not authorized for users without programming rights. "
+ "The script in [{}] cannot be executed properly.",
this.contextProvider.get().getDoc().getDocumentReference());
}
return Optional.empty();
}
@Override
public Optional<Rating> getRating(EntityReference reference, UserReference author)
{
......
......@@ -29,6 +29,8 @@
import org.xwiki.stability.Unstable;
import org.xwiki.user.UserReference;
import com.xpn.xwiki.util.Programming;
/**
* Defines the available methods for {@link RatingsScriptService}.
* Those methods are available when using {@code $services.ratings.RatingsManagerName} where {@code RatingsManagerName}
......@@ -93,6 +95,23 @@ public interface RatingsScriptServiceAPI
*/
Optional<AverageRating> getAverageRating(EntityReference reference);
/**
* Recompute the average rating of a reference.
* Note that this method can be resource consuming if the set of data is large.
*
* @param reference the reference for which to recompute the average ratings.
* @return the average rating in an optional or an empty optional in case of error.
* @since 13.7RC1
* @since 13.4.3
* @since 12.10.9
*/
@Unstable
@Programming
default Optional<AverageRating> recomputeAverageRating(EntityReference reference)
{
return Optional.empty();
}
/**
* Retrieve the rating performed by the given author on the given reference.
* The method returns an empty optional if the rating cannot be found.
......
......@@ -34,6 +34,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.mockito.Mock;
import org.xwiki.component.manager.ComponentLookupException;
import org.xwiki.component.manager.ComponentManager;
......@@ -47,7 +48,11 @@
import org.xwiki.ratings.RatingsException;
import org.xwiki.ratings.RatingsManager;
import org.xwiki.ratings.RatingsManagerFactory;
import org.xwiki.security.authorization.ContextualAuthorizationManager;
import org.xwiki.security.authorization.Right;
import org.xwiki.test.LogLevel;
import org.xwiki.test.annotation.BeforeComponent;
import org.xwiki.test.junit5.LogCaptureExtension;
import org.xwiki.test.junit5.mockito.ComponentTest;
import org.xwiki.test.junit5.mockito.InjectMockComponents;
import org.xwiki.test.junit5.mockito.MockComponent;
......@@ -55,11 +60,13 @@
import org.xwiki.user.UserReferenceResolver;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.doc.XWikiDocument;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
......@@ -94,6 +101,12 @@ public class RatingsScriptServiceTest
@Named("document")
private UserReferenceResolver<DocumentReference> userReferenceResolver;
@MockComponent
private ContextualAuthorizationManager authorizationManager;
@RegisterExtension
LogCaptureExtension logCapture = new LogCaptureExtension(LogLevel.WARN);
private RatingsConfiguration ratingsConfiguration;
private UserReference currentUser;
......@@ -299,4 +312,15 @@ void isExcludedFromRatings()
// Ensure that we stop the loop whenever we found a match.
verify(inputRef, never()).hasParent(lastExcludedRef);
}
@Test
void recomputeAverageRating() throws RatingsException
{
DocumentReference docRef = mock(DocumentReference.class);
when(this.authorizationManager.hasAccess(Right.PROGRAM)).thenReturn(true);
AverageRating averageRating = mock(AverageRating.class);
when(this.defaultManager.recomputeAverageRating(docRef)).thenReturn(averageRating);
assertEquals(Optional.of(averageRating), this.scriptService.recomputeAverageRating(docRef));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment