Ratings API

Last modified by Admin on 2024/10/28 16:31

cogAPI to rate wiki pages
TypeJAR
Category
Developed by

XWiki Development Team

Rating
1 Votes
LicenseGNU Lesser General Public License 2.1
Bundled With

XWiki Standard

Compatibility

XWiki Enterprise and Enterprise Manager 4.1+

Installable with the Extension Manager

Description

The following documentation is about Ratings API since XWiki 12.9RC1. The documentation prior to that version is still available there but it's heavily recommended to migrate to the new API.

The Ratings API allows to store and retrieve various kind of Ratings on different elements of XWiki. The API have been designed in order to allow using different RatingsManagers for different purpose on the wiki, and with different meanings: e.g. Ratings pages on a scale [0,5], liking pages on a scale [0,1], Ratings xobjects on a scale [0,3], etc. 

Instantiate a RatingsManager

 

You need to use the dedicated RatingsManagerFactory in order to instantiate a RatingsManager with the proper initialization. You only need to specify the name of the manager you would like to use. You can provide a RatingsConfiguration component with the same name as hint: this configuration will be used for the initialization, else a default configuration will be used. 

Storage

 

The Ratings API manipulate and store two kind of entities: 

  • Ratings: the votes performed by people
  • Average Ratings: an average vote computed on all ratings performed on the same entity

Storage of Ratings

 

Ratings are always stored in a Solr Core. By default, all ratings for any manager are stored in the same Solr Core, however it's possible to specify in the configuration to store the Ratings of a specific manager in a dedicated core. 

Storage of Average Ratings

Average Ratings can be stored in two places: in Solr Core, or as xobjects in the parent document of the rated entity. The default storage is as xobject.

Configuration

The RatingsConfiguration is used to initialize each RatingsManager and can be adapted uniquely to each usecase.

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.xwiki.ratings;

import java.util.Set;

import org.xwiki.component.annotation.Role;
import org.xwiki.model.reference.EntityReference;

/**
 * Configuration of {@link RatingsManager}.
 *
 * @version $Id$
 * @since 12.9RC1
 */

@Role
public interface RatingsConfiguration
{
   /**
     * @return {@code false} if a rating set to 0 shoud lead to the deletion of a previously made vote.
     *         {@code true} means that all ratings noted to 0 are stored. Note that this option will impact the
     *         average rating.
     */

   boolean isZeroStored();

   /**
     * @return the upper bound of the scale. The lower bound is always 0.
     */

   int getScaleUpperBound();

   /**
     * @return {@code true} to create - if possible, depending on the storage implementation - a dedicated store.
     *         {@code false} means that all ratings from any applications will be stored on the same storage.
     */

   boolean hasDedicatedCore();

   /**
     * @return {@code true} to store the average rating. {@code false} means that the average rating is never stored
     * nor computed.
     */

   boolean isAverageStored();

   /**
     * @return the storage hint to be used for Ratings data (e.g. solr).
     */

    String getRatingsStorageHint();

   /**
     * @return the storage hint to be used for Average Ratings data (e.g. solr or xobject)
     */

    String getAverageRatingStorageHint();

   /**
     * Allow to define a set of references that cannot be rated.
     * This list is mainly used in the UI and in the script service. Note that the provided references are actually
     * also excluding their children, so excluding a wiki reference will excludes all elements from this wiki to be
     * rated.
     *
     * @return the set of references to be excluded from ratings.
     */

    Set<EntityReference> getExcludedReferencesFromRatings();

   /**
     * @return {@code true} if the ratings is enabled. This configuration is only used to control the UI.
     */

   boolean isEnabled();
}

Events

The following events are automatically sent when using RatingsManager API. 

Ratings Events

CreatedRatingEvent

Sent when an event is created:

  • source: the name of the RatingsManager which is responsible of sending the event
  • data: the Rating object created

UpdatedRatingEvent

Sent when an event is updated:

  • source: the name of the RatingsManager which is responsible of sending the event
  • data: the Rating object updated

The event also contain the old vote before the Rating object has been updated.

DeletedRatingEvent

Sent when an event is deleted:

  • source: the name of the RatingsManager which is responsible of sending the event
  • data: the Rating object deleted

Average Ratings Events

UpdatingAverageRatingEvent

A begin event sent when an AverageRating is about to be updated:

  • source: the name of the RatingsManager which is responsible of sending the event
  • data: the AverageRating object updated

The event contains the data about the old average before the update, and the old total number of votes. 

UpdatedAverageRatingEvent

An end event sent when an AverageRating is successfully updated:

  • source: the name of the RatingsManager which is responsible of sending the event
  • data: the AverageRating object updated

The event contains the data about the old average before the update, and the old total number of votes. 

UpdateAverageRatingFailedEvent

An end event sent when an AverageRating failed to update:

  • source: the name of the RatingsManager which is responsible of sending the event
  • data: the AverageRating object updated

The event contains the data about the old average before the update, and the old total number of votes. 

Scripting

The Ratings Script Service allows to use the defined API for any RatingsManager by specifying its name on the form: $services.ratings.RatingsManagerName.
So if you have a dedicated RatingsManager named foobar, you'll be able to write velocity scripts such as:

#set ($myReference = ...)
#set ($ratings = $services.ratings.foobar.getRatings($myReference, 0, 10))

Note that if you don't specify any RatingsManager name, the script service will use by default the Ratings Application name.

The whole Script Service API is defined in AbstractScriptRatingsManager

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.xwiki.ratings.script;

import java.util.List;
import java.util.Optional;

import org.xwiki.model.reference.EntityReference;
import org.xwiki.ratings.AverageRating;
import org.xwiki.ratings.Rating;
import org.xwiki.ratings.RatingsConfiguration;
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}
 * should be replaced with the proper name of the {@link org.xwiki.ratings.RatingsManager} to use. Note that using
 * {@code $services.ratings} without a specific {@code RatingsManagerName} will automatically rely to the default
 * {@link org.xwiki.ratings.RatingsManagerFactory#DEFAULT_APP_HINT}.
 *
 * @version $Id$
 * @since 12.9RC1
 */

public interface RatingsScriptServiceAPI
{
   /**
     * Allows to save a rating for the given reference, with the current user reference.
     *
     * @param reference the reference for which to save a rating.
     * @param vote the rating to save.
     * @return an optional containing the {@link Rating} value, or empty in case of problem or if the rating is 0 and
     *      the configuration doesn't allow to save 0 values (see {@link RatingsConfiguration#isZeroStored()}).
     */

    Optional<Rating> setRating(EntityReference reference, int vote);

   /**
     * Allows to save a rating for the given reference, with the given user reference.
     *
     * @param reference the reference for which to save a rating.
     * @param userReference the reference of the user who performs the rating.
     * @param vote the rating to save.
     * @return an optional containing the {@link Rating} value, or empty in case of problem or if the rating is 0 and
     *      the configuration doesn't allow to save 0 values (see {@link RatingsConfiguration#isZeroStored()}).
     */

    Optional<Rating> setRating(EntityReference reference, UserReference userReference, int vote);

   /**
     * Retrieve ratings information for the given reference on the given manager.
     *
     * @param reference the reference for which to retrieve rating information.
     * @param offset the offset at which to start for retrieving information.
     * @param limit the limit number of information to retrieve.
     * @return a list of ratings containing a maximum of {@code limit} values sorted by
     *         updated date in descending order.
     */

    List<Rating> getRatings(EntityReference reference, int offset, int limit);

   /**
     * Retrieve ratings information for the given reference on the given manager.
     *
     * @param reference the reference for which to retrieve rating information.
     * @param offset the offset at which to start for retrieving information.
     * @param limit the limit number of information to retrieve.
     * @param asc if {@code true} return the results sorted by updated date in ascending order, else in descending order
     * @return a list of ratings containing a maximum of {@code limit} values.
     */

    List<Rating> getRatings(EntityReference reference, int offset, int limit, boolean asc);

   /**
     * Retrieve the average rating of a specific reference.
     *
     * @param reference the reference for which to retrieve the average rating information.
     * @return the average rating in an optional or an empty optional in case of error.
     */

    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
     */

   @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.
     *
     * @param reference the entity being rated
     * @param author the author of the rate
     * @return an optional containing the rating object or being empty if it cannot be found or in case of error.
     */

    Optional<Rating> getRating(EntityReference reference, UserReference author);

   /**
     * Retrieve all the ratings of the current user.
     * @param offset offset of ratings to start retrieve.
     * @param limit maximum number of ratings to retrieve.
     * @param asc if the results should be ordered in updated date ascending or descending order.
     * @return a list of ratings.
     */

    List<Rating> getCurrentUserRatings(int offset, int limit, boolean asc);

   /**
     * @return the current configuration.
     */

    RatingsConfiguration getConfiguration();

   /**
     * Define if the given reference is excluded from ratings.
     *
     * @param entityReference the reference to check.
     * @return {@code true} only if the given reference is excluded from ratings.
     */

   boolean isExcludedFromRatings(EntityReference entityReference);
}

Migration from old Ratings API (before 12.9RC1)

It has been decided to break the backward compatibility of the Ratings API of versions before 12.9RC1 in order to provide a better designed API and the ability to use this API for more use-cases. By default a migration of the existing Ratings data before 12.9RC1 are automatically performed when you upgrade your wiki. However if you used the Ratings API for some custom changes in your wiki, you might see some problems since some APIs have been broken: we will sum up here some of the breaking changes and how to fix them. 

User Reputation is missing

It has been decided to remove the User Reputation methods and classes: it is not clear for us what was the usecases for it, and the work was only partially done. If you're actually a user of such feature, please open a JIRA issue and we'll see how to introduce it back properly. 

Documents are now containing multiple Average Ratings xobjects

If you were manipulating directly the Average Ratings xobjects stored in the document, you now have to be a bit more careful: we store as many Average Ratings xobjects as they are RatingsManagers usecases. For example, if you have a wiki in which there is the standard Ratings Application and another extension using a RatingsManager for ratings comments, you might see two Average Ratings in your pages: one for the page ratings, and another one for the comments ratings. 

Note that you can easily distinguish them, by checking the dedicated managerId field.

RatingAPI class is missing and Script Service are returning optionals

The old Script Service API used to return RatingAPI class because the Rating class was actually doing too many things. We simplified this and now we only rely on the Rating class everywhere even in the Script Service. As much as possible we kept the same method names between RatingAPI and Rating classes: so Rating#getAuthor() and Rating#getVote() are still available. However note that Rating#getDate() doesn't exist another since we distinguish the creation date and the updated date, you can have look at Rating#getUpdatedAt() and Rating#getCreatedAt()

Finally note that we modernized the ScriptService API to use Java Optionals when needed instead of returning null: you might need to adapt your scripts to take it into account.

Prerequisites & Installation Instructions

We recommend using the Extension Manager to install this extension (Make sure that the text "Installable with the Extension Manager" is displayed at the top right location on this page to know if this extension can be installed with the Extension Manager).

You can also use the manual method which involves dropping the JAR file and all its dependencies into the WEB-INF/lib folder and restarting XWiki.

Dependencies

Dependencies for this extension (org.xwiki.platform:xwiki-platform-ratings-api 16.9.0):

Get Connected