Newer
Older
/**
* @file
* A simple n-star voting widget, usable in other forms.
*/
Ezra Barnett Gildesgame
committed
include_once dirname(__FILE__) . '/includes/fivestar.field.inc';
/**
* Implementation of hook_help().
*/
Nate Lampton
committed
function fivestar_help($path, $arg) {
Nate Lampton
committed
switch ($path) {
Ezra Barnett Gildesgame
committed
case 'admin/config/content/fivestar':
Nate Lampton
committed
$output = t('This page is used to configure site-wide features of the Fivestar module. To setup Fivestar to rate content:');
Nate Lampton
committed
t('Configure site-wide settings for Fivestar below.'),
Ezra Barnett Gildesgame
committed
t('Go to <a href="!types">admin/structure/types</a> and edit the type you would like to rate.', array('!types' => url('admin/structure/types'))),
t('On the settings page for the content type, a set of options is available for fivestar, where you can enable rating for that type and set rating options.'),
Ezra Barnett Gildesgame
committed
$output .= theme('item_list', array('items' => $steps, 'type' => 'ol'));
break;
Nate Lampton
committed
case 'admin/content/node-type/'. $arg[3] .'/fivestar':
$arg[5] = 'vote';
case 'admin/content/node-type/'. $arg[3] .'/fivestar/'. $arg[5]:
Ezra Barnett Gildesgame
committed
$output = t('Use the settings on this page to set up Fivestar rating for the %type content type. These settings specifically affect the %axis rating axis. If needing to set up different criteria for voting, see the main <a href="@url">Fivestar settings page</a>.', array('%type' => node_get_types('name', $arg[3]), '%axis' => $arg[5], '@url' => url('admin/config/content/fivestar')));
break;
}
return $output;
}
* Implementation of hook_menu().
Nate Lampton
committed
function fivestar_menu() {
$items = array();
Ezra Barnett Gildesgame
committed
$items['admin/config/content/fivestar'] = array(
Nate Lampton
committed
'title' => 'Fivestar',
'description' => 'Configure site-wide widgets used for Fivestar rating.',
Nate Lampton
committed
'page callback' => 'drupal_get_form',
'page arguments' => array('fivestar_settings'),
'access callback' => 'user_access',
'access arguments' => array('administer site configuration'),
'type' => MENU_NORMAL_ITEM,
'file' => 'includes/fivestar.admin.inc',
Nate Lampton
committed
);
$items['fivestar/preview/node'] = array(
'page callback' => 'fivestar_preview',
'access callback' => 'user_access',
'access arguments' => array('administer content types'),
'type' => MENU_CALLBACK,
'file' => 'includes/fivestar.admin.inc',
);
$items['fivestar/preview/color'] = array(
'page callback' => 'fivestar_preview_color',
'access callback' => 'user_access',
'access arguments' => array('administer site configuration'),
'type' => MENU_CALLBACK,
'file' => 'includes/fivestar.color.inc',
Nate Lampton
committed
);
$items['fivestar/vote'] = array(
'page callback' => 'fivestar_vote',
'access callback' => 'user_access',
'access arguments' => array('rate content'),
'type' => MENU_CALLBACK,
);
// Add a "fivestar" tab to each content type.
// We can't yet add it to the "operations" column in content types, due to a TODO in CCK
// (content.admin.inc line 32)
Ezra Barnett Gildesgame
committed
$items['admin/structure/types/manage/%node_type/fivestar'] = array(
'title' => 'Fivestar voting',
'page callback' => 'drupal_get_form',
'page arguments' => array('fivestar_node_type_tag_form', 4),
'access arguments' => array('administer content types'),
'type' => MENU_LOCAL_TASK,
'weight' => 5,
'file' => 'includes/fivestar.admin.inc',
);
foreach (fivestar_get_tags() as $tag) {
$items['admin/structure/types/manage/%node_type/fivestar/' . urlencode($tag)] = array(
'title' => $tag,
'page callback' => 'drupal_get_form',
Ezra Barnett Gildesgame
committed
'page arguments' => array('fivestar_node_type_tag_form', 4, $tag),
'access arguments' => array('administer content types'),
Ezra Barnett Gildesgame
committed
'type' => $tag == 'vote' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
'weight' => $tag == 'vote' ? 0 : 1,
Nate Lampton
committed
'file' => 'includes/fivestar.admin.inc',
);
}
return $items;
}
/**
* Implementation of hook_init().
Nate Lampton
committed
* These includes do not need to be loaded for cached pages.
*/
function fivestar_init() {
Ezra Barnett Gildesgame
committed
module_load_include('inc', 'fivestar', 'includes/fivestar.field');
// Add necessary CSS and JS.
// TODO: These shouldn't be loaded on every page, but block caching omits
// CSS and JS files that would be otherwise added.
fivestar_add_js();
fivestar_add_css();
Ezra Barnett Gildesgame
committed
* Implementation of hook_permission().
* Exposes permissions for rating content, viewing aggregate ratings, and using PHP
* snippets when configuring fivestar CCK fields.
*/
Ezra Barnett Gildesgame
committed
function fivestar_permission() {
return array(
'rate content' => array(
'title' => t('rate content'),
'description' => 'TODO: write description for rate content',
),
'use PHP for fivestar target' => array(
'title' => t('use PHP for fivestar target'),
'description' => 'TODO: write description for use PHP for fivestar target',
),
);
Nate Lampton
committed
/**
* Implementation of hook_theme().
*/
function fivestar_theme() {
return array(
// Fivestar theme functions.
'fivestar' => array(
Ezra Barnett Gildesgame
committed
'render element' => 'element',
Nate Lampton
committed
),
Nate Lampton
committed
'fivestar_select' => array(
Ezra Barnett Gildesgame
committed
'render element' => 'element',
Nate Lampton
committed
),
'fivestar_static' => array(
Ezra Barnett Gildesgame
committed
'variables' => array('rating' => NULL, 'stars' => 5, 'tag' => 'vote'),
Nate Lampton
committed
),
'fivestar_static_element' => array(
Ezra Barnett Gildesgame
committed
'variables' => array('star_display' => NULL, 'title' => NULL, 'description' => NULL),
Nate Lampton
committed
),
'fivestar_summary' => array(
Ezra Barnett Gildesgame
committed
'variables' => array('user_rating' => NULL, 'average_rating' => NULL, 'votes' => 0, 'stars' => 5, 'feedback_enable' => TRUE),
Nate Lampton
committed
),
'fivestar_widget' => array(
Ezra Barnett Gildesgame
committed
'render element' => 'form',
Nate Lampton
committed
),
Nate Lampton
committed
// fivestar.admin.inc.
Nate Lampton
committed
'fivestar_preview' => array(
Ezra Barnett Gildesgame
committed
'variables' => array('style' => NULL, 'text' => NULL, 'stars' => NULL, 'unvote' => NULL, 'title' => NULL, 'feedback_enable' => TRUE, 'labels_enable' => TRUE, 'labels' => array()),
Nate Lampton
committed
'file' => 'includes/fivestar.admin.inc',
Nate Lampton
committed
),
'fivestar_preview_widget' => array(
Ezra Barnett Gildesgame
committed
'variables' => array('css_file' => NULL),
Nate Lampton
committed
'file' => 'includes/fivestar.admin.inc',
Nate Lampton
committed
),
'fivestar_preview_wrapper' => array(
Ezra Barnett Gildesgame
committed
'variables' => array('content' => NULL, 'type' => 'direct'),
Nate Lampton
committed
'file' => 'includes/fivestar.admin.inc',
Nate Lampton
committed
),
'fivestar_settings' => array(
Ezra Barnett Gildesgame
committed
'render element' => 'form',
Nate Lampton
committed
'file' => 'includes/fivestar.admin.inc',
Nate Lampton
committed
),
Nate Lampton
committed
'fivestar_node_type_tag_form' => array(
Ezra Barnett Gildesgame
committed
'render element' => 'form',
Nate Lampton
committed
'file' => 'includes/fivestar.admin.inc',
Nate Lampton
committed
),
// fivestar.color.inc.
'fivestar_color_form' => array(
Ezra Barnett Gildesgame
committed
'render element' => 'form',
// fivestar.field.inc.
'fivestar_formatter_default' => array(
Ezra Barnett Gildesgame
committed
'render element' => 'element',
'file' => 'includes/fivestar.field.inc',
),
'fivestar_formatter_rating' => array(
Ezra Barnett Gildesgame
committed
'render element' => 'element',
'file' => 'includes/fivestar.field.inc',
),
'fivestar_formatter_percentage' => array(
Ezra Barnett Gildesgame
committed
'render element' => 'element',
'file' => 'includes/fivestar.field.inc',
Nate Lampton
committed
);
}
Ezra Barnett Gildesgame
committed
* Implementation of hook_node_type_delete().
Ezra Barnett Gildesgame
committed
function fivestar_node_type_delete($info) {
$type = $info->type;
// Be responsible and cleanup unneeded variables.
Ezra Barnett Gildesgame
committed
foreach (_fivestar_variables() as $variable) {
foreach (fivestar_get_tags() as $tag) {
$suffix = fivestar_get_suffix($type, $tag);
variable_del($variable . '_' . $suffix);
}
Ezra Barnett Gildesgame
committed
}
/**
* Implementation of hook_node_type_update().
*/
function fivestar_node_type_update($info) {
// When changing the type name, update the variables.
Ezra Barnett Gildesgame
committed
if (!empty($info->old_type) && $info->old_type != $info->type) {
foreach (_fivestar_variables() as $variable) {
foreach (fivestar_get_tags() as $tag) {
Nate Lampton
committed
$oldvarname = $variable . '_' . fivestar_get_suffix($info->old_type, $tag);
$newvarname = $variable . '_' . fivestar_get_suffix($info->type, $tag);
$value = variable_get($oldvarname, -1);
if ($value != -1) {
variable_del($oldvarname);
variable_set($newvarname, $value);
}
}
}
}
}
Ezra Barnett Gildesgame
committed
function _fivestar_variables() {
return array('fivestar', 'fivestar_unvote', 'fivestar_style', 'fivestar_stars', 'fivestar_comment', 'fivestar_position', 'fivestar_position_teaser', 'fivestar_labels_enable', 'fivestar_labels', 'fivestar_text', 'fivestar_title', 'fivestar_feedback');
}
* Callback function for fivestar/vote.
*
* @param type
* A content-type to log the vote to. 'node' is the most common.
* @param cid
* A content id to log the vote to. This would be a node ID, a comment ID, etc.
* @param tag
* Multi-axis tag to allow multiple votes per node. 'vote' is the most common.
* @param value
* A value from 1-100, representing the vote cast for the content.
* @return
* An XML chunk containing the results of the vote, for use by the client-side
* javascript code.
*/
function fivestar_vote($type, $cid, $tag, $value) {
Ezra Barnett Gildesgame
committed
drupal_add_http_header("Content-Type", "text/xml");
$output = '';
$output .= '<?xml version="1.0" encoding="UTF-8"?>';
// Rebuild the #auto_submit_path that was used as the token seed.
$path = preg_replace('/\/'. $value .'$/', '', $_GET['q']);
if (!isset($_GET['token']) || !fivestar_check_token($_GET['token'], $path)) {
$output .= '<xml><error>'. t('Invalid token') .'</error></xml>';
Ezra Barnett Gildesgame
committed
echo $output;
drupal_exit();
}
$result = _fivestar_cast_vote($type, $cid, $value, $tag, NULL, TRUE);
votingapi_recalculate_results($type, $cid);
if ($type == 'node') {
$node = node_load($cid);
}
Nate Lampton
committed
$suffix = fivestar_get_suffix((!isset($node) ? 'default' : $node->type), $tag);
Eric J. Duran
committed
$stars = variable_get('fivestar_stars_' . $suffix, 5);
$feedback_enable = variable_get('fivestar_feedback_' . $suffix, 1);
$output .= '<xml><result>';
if (count($result)) {
foreach ($result as $data) {
if (isset($data['tag']) && $data['tag'] == $tag) {
Nate Lampton
committed
$output .= '<'. $data['function'] .'>'. $data['value'] .'</'. $data['function'] .'>';
$summary[$data['tag']][$data['function']] = $data['value'];
Ezra Barnett Gildesgame
committed
$arguments = array(
'user_rating' => $value,
'average_rating' => $summary[$tag]['average'],
'votes' => $summary[$tag]['count'],
'stars' => $stars,
'feedback_enable' => $feedback_enable,
);
$skip_map = array(
'average' => array('user_rating', 'votes'),
'average_count' => array('user_rating'),
'user' => array('average_rating', 'votes'),
'user_count' => array('average_rating'),
'combo' => array(),
'count' => array('user_rating', 'average_rating'),
);
$output .= '<summary>';
Ezra Barnett Gildesgame
committed
foreach ($skip_map as $tag => $skip) {
$output .= "<$tag><![CDATA[". theme('fivestar_summary', array_diff_key($arguments, array_flip($skip))) . "]]></$tag>";
Ezra Barnett Gildesgame
committed
}
$output .= '</summary>';
$output .= '</result>';
$output .= '<vote>';
$output .= '<value>'. $value .'</value>';
$output .= '<type>'. $type .'</type>';
$output .= '<id>'. $cid .'</id>';
$output .= '<tag>'. $tag .'</tag>';
$output .= '</vote></xml>';
Ezra Barnett Gildesgame
committed
drupal_add_http_header("Content-Type", "text/xml");
echo $output;
drupal_exit();
}
/**
* Internal function to handle vote casting, flood control, XSS, IP based
* voting, etc...
*/
Eric J. Duran
committed
function _fivestar_cast_vote($entity_type, $id, $value, $tag = NULL, $uid = NULL, $result = FALSE, $skip_validation = FALSE) {
global $user;
$tag = empty($tag) ? 'vote' : $tag;
Nate Lampton
committed
$uid = empty($uid) ? $user->uid : $uid;
// Bail out if the user's trying to vote on an invalid object.
if (!$skip_validation && !fivestar_validate_target($entity_type, $id, $tag, $uid)) {
return array();
}
Nate Lampton
committed
// Sanity-check the incoming values.
if (is_numeric($id) && is_numeric($value)) {
if ($value > 100) {
$value = 100;
}
Nate Lampton
committed
// Get the user's current vote.
$criteria = array('entity_type' => $entity_type, 'entity_id' => $id, 'tag' => $tag, 'uid' => $uid);
// Get the unique identifier for the user (IP Address if anonymous).
$user_criteria = votingapi_current_user_identifier();
$user_votes = votingapi_select_votes($criteria + $user_criteria);
Nate Lampton
committed
if ($value == 0) {
Nate Lampton
committed
votingapi_delete_votes($user_votes);
}
else {
$votes = $criteria += array('value' => $value);
votingapi_set_votes($votes, $user_votes);
}
return fivestar_get_votes($entity_type, $id, $tag, $uid);
}
}
Eric J. Duran
committed
* Utility function to retrieve VotingAPI votes.
Eric J. Duran
committed
* Note that this should not be used for general vote retrieval, instead the
* VotingAPI function votingapi_select_results() should be used, which is more
* efficient when retrieving multiple votes.
*
Eric J. Duran
committed
* @param $entity_type
* The Entity type for which to retrieve votes.
* @param $id
* The ID for which to retrieve votes.
Eric J. Duran
committed
* The VotingAPI tag for which to retrieve votes.
Eric J. Duran
committed
* Optional. A user ID for which to retrieve votes.
* @return
* An array of the following keys:
* - average: An array of VotingAPI results, including the average 'value'.
* - count: An array of VotingAPI results, including the count 'value'.
* - user: An array of VotingAPI results, including the user's vote 'value'.
*/
Eric J. Duran
committed
function fivestar_get_votes($entity_type, $id, $tag = 'vote', $uid = NULL) {
Nate Lampton
committed
global $user;
if (!isset($uid)) {
Nate Lampton
committed
$uid = $user->uid;
}
$criteria = array(
Eric J. Duran
committed
'entity_type' => $entity_type,
'entity_id' => $id,
Nate Lampton
committed
'value_type' => 'percent',
'tag' => $tag,
);
$votes = array(
'average' => array(),
'count' => array(),
'user' => array(),
);
$results = votingapi_select_results($criteria);
foreach ($results as $result) {
if ($result['function'] == 'average') {
$votes['average'] = $result;
}
if ($result['function'] == 'count') {
$votes['count'] = $result;
}
}
if ($uid) {
$user_vote = votingapi_select_votes($criteria += array('uid' => $uid));
if ($user_vote) {
$votes['user'] = $user_vote[0];
$votes['user']['function'] = 'user';
}
Nate Lampton
committed
}
else {
// If the user is anonymous, we never bother loading their existing votes.
// Not only would it be hit-or-miss, it would break page caching. Safer to always
// show the 'fresh' version to anon users.
$votes['user'] = array('value' => 0);
}
return $votes;
}
* Check that an item being voted upon is a valid vote.
*
* Type of target (currently only node is supported).
* @param $id
* Identifier within the type (in this case nid).
* @param $tag
* The VotingAPI tag string.
* @param $uid
* The user trying to cast the vote.
*
* @return boolean
*/
function fivestar_validate_target($entity_type, $id, $tag, $uid = NULL) {
if (!isset($uid)) {
$uid = $GLOBALS['user']->uid;
}
$access = module_invoke_all('fivestar_access', $entity_type, $id, $tag, $uid);
foreach ($access as $result) {
if ($result == TRUE) {
return TRUE;
}
if ($result === FALSE) {
return FALSE;
}
}
/**
* Implementation of hook_fivestar_access().
*
* This hook is called before every vote is cast through Fivestar. It allows
* modules to allow voting on any type of content, such as nodes, users, or
* comments, even though only nodes are supported by Fivestar directly.
*
* Type of target (currently only node is supported).
* @param $id
* Identifier within the type (in this case nid).
* @param $tag
* The VotingAPI tag string.
* @param $uid
* The user ID trying to cast the vote.
*
* @return boolean or NULL
* Returns TRUE if voting is supported on this object.
* Returns NULL if voting is not supported on this object by this module.
* If needing to absolutely deny all voting on this object, regardless
* of permissions defined in other modules, return FALSE. Note if all
* modules return NULL, stating no preference, then access will be denied.
*/
function fivestar_fivestar_access($entity_type, $id, $tag, $uid) {
if ($entity_type == 'node' && $node = node_load($id)) {
Nate Lampton
committed
if (variable_get('fivestar_'. fivestar_get_suffix($node->type, $tag), 0)) {
return TRUE;
}
}
}
* Implementation of hook_fivestar_widgets().
*
* This hook allows other modules to create additional custom widgets for
* the fivestar module.
* @return array
* An array of key => value pairs suitable for inclusion as the #options in a
* select or radios form element. Each key must be the location of a css
* file for a fivestar widget. Each value should be the name of the widget.
*/
function fivestar_fivestar_widgets() {
$widgets_directory = drupal_get_path('module', 'fivestar') .'/widgets';
Ezra Barnett Gildesgame
committed
$files = file_scan_directory($widgets_directory, '/\.css$/');
$widgets = array();
foreach ($files as $file) {
if (strpos($file->filename, '-rtl.css') === FALSE) {
Ezra Barnett Gildesgame
committed
$widgets[$file->uri] = drupal_ucfirst(str_replace('-color', '', $file->name));
}
return $widgets;
}
/**
Eric J. Duran
committed
* Implementation of hook_entity_view().
Eric J. Duran
committed
* Adds the fivestar widget to the entity.
Eric J. Duran
committed
function fivestar_entity_view($entity, $type, $view_mode, $langcode) {
Ezra Barnett Gildesgame
committed
$exclude_modes = array(
'preview',
'search_index',
'search_result',
'rss',
);
Eric J. Duran
committed
if ($type == 'node') {
if (!in_array($view_mode, $exclude_modes) && !isset($entity->modr8_form_teaser) && variable_get('fivestar_'. $entity->type, 0)) {
if ($view_mode == 'teaser') {
$position = variable_get('fivestar_position_teaser_'. $entity->type, 'above');
}
else {
$position = variable_get('fivestar_position_'. $entity->type, 'above');
}
Nate Lampton
committed
Eric J. Duran
committed
switch ($position) {
case 'above':
case 'below':
if (user_access('rate content')) {
$content = '';
foreach (fivestar_get_tags() as $tag) {
if (fivestar_validate_target('node', $entity->nid, $tag)) {
$entity->content['fivestar_widget_' . $tag]['form'] = fivestar_widget_form($entity, $tag);
$entity->content['fivestar_widget_' . $tag]['#weight'] = ($position == 'above') ? -10 : 50;
}
}
break;
} // Fall through to static if not allowed to rate.
$position .= '_static';
case 'above_static':
case 'below_static':
Ezra Barnett Gildesgame
committed
$content = '';
foreach (fivestar_get_tags() as $tag) {
Eric J. Duran
committed
if (fivestar_validate_target('node', $entity->nid, $tag)) {
$content .= fivestar_static('node', $entity->nid, $entity->type, $tag);
Ezra Barnett Gildesgame
committed
}
Eric J. Duran
committed
if ($content) {
$entity->content['fivestar_widget'] = array(
'#markup' => $content,
'#weight' => strpos($position, 'above') === 0 ? -10 : 50,
);
Ezra Barnett Gildesgame
committed
}
Eric J. Duran
committed
break;
case 'link':
$entity->content['links']['fivestar_widget'] = array(
'#links' => array(
'fivestar-rate' => array(
'title' => t('Rate'),
'href' => 'node/'. $entity->nid,
'fragment' => 'fivestar-form-node-'. $entity->nid,
'attributes' => array('title' => t('Rate this @type', array('@type' => _node_types_build()->types[$entity->type]->name))),
),
Eric J. Duran
committed
);
break;
}
Ezra Barnett Gildesgame
committed
}
}
}
Ezra Barnett Gildesgame
committed
function fivestar_block_info() {
$blocks[0]['info'] = t('Fivestar: Rate this node');
return $blocks;
}
Ezra Barnett Gildesgame
committed
function fivestar_block_view($delta = 0) {
if (user_access('access content') && user_access('rate content') && (arg(2) == '' || arg(2) == 'view') && ($node = menu_get_object())) {
$block = array('subject' => t('Rate This'));
foreach (fivestar_get_tags() as $tag) {
if (fivestar_validate_target('node', $node->nid, $tag)) {
$block['content'][$tag] = fivestar_widget_form($node, $tag);
Ezra Barnett Gildesgame
committed
}
return $block;
}
function fivestar_widget_form($node, $tag = 'vote') {
return drupal_get_form('fivestar_form_node_'. $node->nid .'_'. $tag, 'node', $node->nid, $tag);
}
* Get a private token used to protect links from CSRF attacks.
function fivestar_get_token($value) {
global $user;
// Anonymous users don't get a session ID, which breaks page caching.
$session_id = $user->uid ? session_id() : '';
$private_key = drupal_get_private_key();
return md5($session_id . $value . $private_key);
}
/**
* Check to see if a token value matches the specified node.
*/
function fivestar_check_token($token, $value) {
return fivestar_get_token($value) == $token;
}
/**
* Implementation of hook_forms().
*
* This is necessary when multiple fivestar forms appear on the same page, each
* requiring a separate form_id, but all using the same underlying callbacks.
function fivestar_forms($form_id, $args) {
if (strpos($form_id, 'fivestar_form') !== FALSE) {
if ($form_id == 'fivestar_form_'. $args[0] .'_'. $args[1] .'_'. $args[2]) {
$forms[$form_id] = array('callback' => 'fivestar_form');
return $forms;
}
}
}
/**
* Create the fivestar form for the current item.
* Note that this is not an implementation of hook_form(). We should probably
* change the function to reflect that.
*/
Ezra Barnett Gildesgame
committed
function fivestar_form($form, &$form_state, $content_type, $content_id, $tag) {
global $user;
if ($content_type == 'node') {
if (is_numeric($content_id)) {
$node = node_load($content_id);
}
else {
return array();
}
}
Nate Lampton
committed
$suffix = fivestar_get_suffix($node->type, $tag);
$star_display = variable_get('fivestar_style_' . $suffix, 'average');
$text_display = variable_get('fivestar_text_' . $suffix, 'dual');
Nate Lampton
committed
if ($star_display == 'average' && ($text_display == 'average' || $text_display == 'none')) {
// Save a query and don't retrieve the user vote unnecessarily.
$votes = fivestar_get_votes($content_type, $content_id, $tag, 0);
}
else {
$votes = fivestar_get_votes($content_type, $content_id, $tag);
}
'user' => isset($votes['user']['value']) ? $votes['user']['value'] : 0,
'average' => isset($votes['average']['value']) ? $votes['average']['value'] : 0,
'count' => isset($votes['count']['value']) ? $votes['count']['value'] : 0,
$settings = array(
Eric J. Duran
committed
'stars' => variable_get('fivestar_stars_' . $suffix, 5),
'allow_clear' => variable_get('fivestar_unvote_' . $suffix, FALSE),
'style' => $star_display,
'text' => $text_display,
'content_type' => $content_type,
'content_id' => $content_id,
'autosubmit' => TRUE,
Eric J. Duran
committed
'title' => variable_get('fivestar_title_' . $suffix, 1) ? NULL : FALSE,
'feedback_enable' => variable_get('fivestar_feedback_' . $suffix, 1),
'labels_enable' => variable_get('fivestar_labels_enable_' . $suffix, 1),
'labels' => variable_get('fivestar_labels_' . $suffix, array()),
'tag' => $tag,
);
Ezra Barnett Gildesgame
committed
return fivestar_custom_widget(array(), $form_state, $values, $settings);
/**
* Retreive and print out a static display of stars for a piece of content.
*
* @param $content_type
* The type of content that will have its vote retreived. i.e. "node".
* @param $content_id
* The ID of the content that will have its vote retreived.
* @param $node_type
* Optional. If retreiving a node's rating, passing in the node type will
* prevent Fivestar from doing an additional query to find it.
* @param $tag
* Optional. The voting tag that will be retreived. Defaults to "vote" if none
* is specified.
*/
function fivestar_static($content_type, $content_id, $node_type = NULL, $tag = 'vote') {
Nate Lampton
committed
$criteria = array(
'content_type' => $content_type,
'content_id' => $content_id,
'value_type' => 'percent',
'tag' => 'vote',
);
$votes = fivestar_get_votes($content_type, $content_id, $tag);
if ($content_type == 'node') {
// Content type should always be passed to avoid this node load.
if (!isset($node_type)) {
$node = node_load($content_id);
$node_type = $node->type;
}
Nate Lampton
committed
$settings = fivestar_get_settings($node_type, $tag);
$stars = $settings['stars'];
switch ($settings['star_display']) {
case 'average':
case 'dual':
Eric J. Duran
committed
$star_value = (isset($votes['average']['value'])) ? $votes['average']['value']: '';
Nate Lampton
committed
$title = $settings['title_display'] ? t('Average') : NULL;
break;
case 'user':
Eric J. Duran
committed
$star_value = (isset($votes['user']['value'])) ? $votes['user']['value'] : '';
Nate Lampton
committed
$title = $settings['title_display'] ? t('Your rating') : NULL;
break;
case 'smart':
Eric J. Duran
committed
$star_value = (isset($votes['user']['value'])) ? $votes['user']['value'] : $votes['average']['value'];
Nate Lampton
committed
$title = $settings['title_display'] ? $votes['user']['value'] ? t('Your rating') : t('Average') : NULL;
if ($tag != 'vote') {
$title .= ' (' . ucfirst($tag) . ')';
}
// Set all text values, then unset the unnecessary ones.
Eric J. Duran
committed
$user_value = (isset($votes['user']['value'])) ? $votes['user']['value'] : NULL;
Eric J. Duran
committed
$average_value = (isset($votes['average']['value'])) ? $votes['average']['value'] : NULL;
$count_value = (isset($votes['count']['value'])) ? $votes['count']['value'] : NULL;
Nate Lampton
committed
switch ($settings['text_display']) {
case 'average':
$user_value = NULL;
break;
case 'user':
$average_value = NULL;
break;
case 'smart':
Nate Lampton
committed
if ($votes['user']['value']) {
$average_value = NULL;
}
else {
$user_value = NULL;
}
break;
}
}
// Possibly add other content types here (comment, user, etc).
else {
$stars = 5;
Nate Lampton
committed
$star_value = $votes['average']['value'];
$user_value = $votes['user']['value'];
$average_value = $votes['average']['value'];
$count_value = $votes['count']['value'];
Ezra Barnett Gildesgame
committed
$star_display = theme('fivestar_static', array(
'rating' => $star_value,
'stars' => $stars,
));
$text_display = $settings['text_display'] == 'none' ? NULL : theme('fivestar_summary', array(
'user_rating' => $user_value,
'average_rating' => $average_value,
'votes' => $count_value,
'stars'=> $stars,
'feedback_enable' =>FALSE,
));
Eric J. Duran
committed
return theme('fivestar_static_element', array('star_display' => $star_display, 'title' => $title, 'description' => $text_display));
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
/**
* Form builder; Build a custom Fivestar rating widget with arbitrary settings.
*
* This function is usually not called directly, instead call
* drupal_get_form('fivestar_custom_widget', $values, $settings) when wanting
* to display a widget.
*
* @param $form_state
* The form state provided by Form API.
* @param $values
* An array of current vote values from 0 to 100, with the following array
* keys:
* - user: The user's current vote.
* - average: The average vote value.
* - count: The total number of votes so far on this content.
* @param $settings
* An array of settings that configure the properties of the rating widget.
* Available keys for the settings include:
* - content_type: The type of content which will be voted upon.
* - content_id: The content ID which will be voted upon.
* - stars: The number of stars to display in this widget, from 2 to 10.
* Defaults to 5.
* - autosubmit: Whether the form should be submitted upon star selection.
* Defaults to TRUE.
* - allow_clear: Whether or not to show the "Clear current vote" icon when
* showing the widget. Defaults to FALSE.
* - required: Whether this field is required before the form can be
* submitted. Defaults to FALSE.
* - feedback_enable: Toggles the option to show the "Vote is being saved"
* text while a vote is being registered through AJAX. Defaults to TRUE.
* - labels_enable: Toggles the option to show the "Give it 2/5 stars" text
* while hovering over the stars with the mouse.
* - labels: An array of labels to be used. The number of labels should match
* the number of stars.
* - tag: The VotingAPI tag that will be registered by this widget. Defaults
* to "vote".
*/
Ezra Barnett Gildesgame
committed
function fivestar_custom_widget($form, &$form_state, $values, $settings) {
Ezra Barnett Gildesgame
committed
'#attributes' => array('class' => array('fivestar-widget')),
'#redirect' => FALSE,
'#theme' => 'fivestar_widget',
);
$form['#submit'][] = 'fivestar_form_submit';
if (isset($settings['content_type'])) {
$form['content_type'] = array(
'#type' => 'hidden',
'#value' => $settings['content_type'],
);
}
if (isset($settings['content_id'])) {
$form['content_id'] = array(
'#type' => 'hidden',
'#value' => $settings['content_id'],
);
}
if (isset($settings['tag'])) {
$form['tag'] = array(
'#type' => 'hidden',
'#value' => $settings['tag'],
);
}
$form['vote'] = array(
'#type' => 'fivestar',
'#stars' => $settings['stars'],
'#vote_count' => $values['count'],
'#vote_average' => $values['average'],
'#auto_submit' => isset($settings['autosubmit']) ? $settings['autosubmit'] : TRUE,
'#auto_submit_path' => (!isset($settings['autosubmit']) || $settings['autosubmit']) ? 'fivestar/vote/'. $settings['content_type'] .'/'. $settings['content_id'] .'/' . $settings['tag'] : NULL,
'#allow_clear' => $settings['allow_clear'],
'#content_id' => isset($settings['content_id']) ? $settings['content_id'] : NULL,
'#required' => isset($settings['required']) ? $settings['required'] : FALSE,
'#feedback_enable' => isset($settings['feedback_enable']) ? $settings['feedback_enable'] : TRUE,
'#labels_enable' => isset($settings['labels_enable']) ? $settings['labels_enable'] : TRUE,
'#labels' => isset($settings['labels']) ? $settings['labels'] : NULL,
'#tag' => isset($settings['tag']) ? $settings['tag'] : 'vote',
);
$form['destination'] = array(
'#type' => 'hidden',
'#value' => $_GET['q'],
);
$form['fivestar_submit'] = array(
'#type' => 'submit',
'#value' => t('Rate'),
Ezra Barnett Gildesgame
committed
'#attributes' => array('class' => array('fivestar-submit')),
);
Ezra Barnett Gildesgame
committed
$form['vote']['#attributes']['class'] = isset($form['vote']['#attributes']['class']) ? $form['vote']['#attributes']['class'] : array();
$settings['feedback_enable'] = isset($settings['feedback_enable']) ? $settings['feedback_enable'] : TRUE;
switch ($settings['text']) {
case 'user':
Ezra Barnett Gildesgame
committed
$form['vote']['#description'] = theme('fivestar_summary', array(
'user_rating' => $values['user'],
'votes' => $settings['style'] == 'dual' ? NULL : $values['count'],
'stars' => $settings['stars'],
'feedback_enable' => $settings['feedback_enable'],
));
$form['vote']['#attributes']['class'][] = 'fivestar-user-text';
break;
case 'average':
Ezra Barnett Gildesgame
committed
$form['vote']['#description'] = $settings['style'] == 'dual' ? NULL : theme('fivestar_summary', array(
'average_rating' => $values['average'],
'votes' => $values['count'],
'stars' => $settings['stars'],
'feedback_enable' => $settings['feedback_enable'],
));
$form['vote']['#attributes']['class'][] = 'fivestar-average-text';
break;
case 'smart':
Ezra Barnett Gildesgame
committed
$form['vote']['#description'] = ($settings['style'] == 'dual' && !$values['user']) ? NULL : theme('fivestar_summary', array(
'user_rating' => $values['user'],
'average_rating' => $values['user'] ? NULL : $values['average'],
'votes' => $settings['style'] == 'dual' ? NULL : $values['count'],
'stars' => $settings['stars'],
'feedback_enable' => $settings['feedback_enable'],
));
$form['vote']['#attributes']['class'][] = 'fivestar-smart-text';
$form['vote']['#attributes']['class'][] = $values['user'] ? 'fivestar-user-text' : 'fivestar-average-text';
break;
case 'dual':
Ezra Barnett Gildesgame
committed
$form['vote']['#description'] = theme('fivestar_summary', array(
'user_rating' => $values['user'],
'average_rating' => $settings['style'] == 'dual' ? NULL : $values['average'],
'votes' => $settings['style'] == 'dual' ? NULL : $values['count'],
'stars' => $settings['stars'],
'feedback_enable' => $settings['feedback_enable'],
));
$form['vote']['#attributes']['class'][] = ' fivestar-combo-text';
break;
}
switch ($settings['style']) {
case 'average':
$form['vote']['#title'] = t('Average');
$form['vote']['#default_value'] = $values['average'];
Ezra Barnett Gildesgame
committed
$form['vote']['#attributes']['class'][] = 'fivestar-average-stars';
break;
case 'user':
$form['vote']['#title'] = t('Your rating');
$form['vote']['#default_value'] = $values['user'];
Ezra Barnett Gildesgame
committed
$form['vote']['#attributes']['class'][] = 'fivestar-user-stars';
break;
case 'smart':
$form['vote']['#title'] = $values['user'] ? t('Your rating') : t('Average');
$form['vote']['#default_value'] = $values['user'] ? $values['user'] : $values['average'];
Ezra Barnett Gildesgame
committed
$form['vote']['#attributes']['class'][] = 'fivestar-smart-stars '. ($values['user'] ? 'fivestar-user-stars' : 'fivestar-average-stars');
break;
case 'dual':
$form['vote']['#title'] = t('Your rating');
$form['vote']['#default_value'] = $values['user'];
Ezra Barnett Gildesgame
committed
$form['vote']['#attributes']['class'][] = 'fivestar-combo-stars';
$form['#attributes']['class'][] = 'fivestar-combo-stars';
$static_average = theme('fivestar_static', array(
'rating' => $values['average'],
'stars' => $settings['stars'],
'tag' => $settings['tag'],
));
if ($settings['text'] == 'none' && !$settings['labels_enable'] && !$settings['feedback_enable']) {
$static_description = NULL;
}
elseif ($settings['text'] != 'none') {
Ezra Barnett Gildesgame
committed
$static_description = theme('fivestar_summary', array(
'averrage_rating' => $settings['text'] == 'user' ? NULL : (isset($values['average']) ? $values['average'] : 0),
'votes' => isset($values['count']) ? $values['count'] : 0,
'stars' => $settings['stars'],
'feedback_enable' => FALSE
));
}
else {
$static_description = ' ';
}
$form['average'] = array(
'#type' => 'markup',
'#markup' => theme('fivestar_static_element', array(
Ezra Barnett Gildesgame
committed
'star_display' => $static_average,
'title' => $settings['title'] !== FALSE ? t('Average') : NULL,
'description' => $static_description,
)),
'#weight' => -1,
);
break;
}
// Set an over-ridding title if passed in.
// An empty title won't change the default, a string will set a new title,
// and title === FALSE will unset the title entirely.
if (isset($settings['title'])) {
if ($settings['title'] !== FALSE) {
$form['vote']['#title'] = $settings['title'];
}
else {
unset($form['vote']['#title']);
unset($form['average']['#title']);
}
}
elseif ($settings['tag'] && $settings['tag'] != 'vote') {
$form['vote']['#title'] .= ' (' . ucfirst($settings['tag']) . ')';
}
return $form;
}
/**
* Submit handler for the above form (non-javascript version).
*/
Nate Lampton
committed
function fivestar_form_submit($form, &$form_state) {
if ($form_state['values']['form_id'] == 'fivestar_form_'. $form_state['values']['content_type'] .'_'. $form_state['values']['content_id'] . '_' . $form_state['values']['tag']) {
_fivestar_cast_vote($form_state['values']['content_type'], $form_state['values']['content_id'], $form_state['values']['vote'], $form_state['values']['tag']);
votingapi_recalculate_results($form_state['values']['content_type'], $form_state['values']['content_id']);
// Set a message that the vote was received.
Nate Lampton
committed
if ($form_state['values']['vote'] === '0') {