You are here

rate.module in Rate 8

Same filename and directory in other branches
  1. 8.2 rate.module
  2. 6.2 rate.module
  3. 7.2 rate.module
  4. 7 rate.module

Hook implementation code for the Rate module.

File

rate.module
View source
<?php

/**
 * @file
 * Hook implementation code for the Rate module.
 */
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Link;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Url;
use Drupal\node\NodeInterface;

/**
 * Implements hook_entity_extra_field_info().
 */
function rate_entity_extra_field_info() {
  $extra = [];
  $config = \Drupal::config('rate.settings');
  $enabled_types_widgets = $config
    ->get('enabled_types_widgets');
  if (!empty($enabled_types_widgets)) {
    foreach ($enabled_types_widgets as $entity_type_id => $entities) {
      foreach ($entities as $bundle => $settings) {
        $extra[$entity_type_id][$bundle]['display']['rate_vote_widget'] = [
          'label' => t('Rate Vote Widget'),
          'description' => t('Displays the rate voting widget selected from the settings page.'),
          'weight' => 100,
          'visible' => TRUE,
        ];
      }
    }
  }
  return $extra;
}

/**
 * Implements hook_entity_view().
 */
function rate_entity_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if (($widget_config = $display
    ->getComponent('rate_vote_widget')) && $view_mode == 'full') {
    $vote_widget_service = \Drupal::service('rate.entity.vote_widget');
    $vote_widget = $vote_widget_service
      ->buildRateVotingWidget($entity
      ->id(), $entity
      ->getEntityTypeId(), $entity
      ->bundle());
    if (isset($vote_widget['rate_vote_widget'])) {
      $vote_widget['rate_vote_widget']['#weight'] = isset($widget_config['weight']) ? $widget_config['weight'] : 2;
    }
    $build = array_merge($build, $vote_widget);
  }
}

/**
 * Implements hook_menu_local_tasks_alter().
 *
 * This unsets Voting Results tab for non-voting-enabled node types.
 */
function rate_menu_local_tasks_alter(&$data, $route_name) {
  if (isset($data['tabs'][0]) && isset($data['tabs'][0]['entity.node.canonical'])) {
    $node = Drupal::request()->attributes
      ->get('node');
    if (!$node instanceof NodeInterface) {
      $node = Drupal::entityTypeManager()
        ->getStorage('node')
        ->load($node);
    }
    if ($node) {
      $config = \Drupal::config('rate.settings');
      $enabled_types_widgets = $config
        ->get('enabled_types_widgets');
      if (!empty($enabled_types_widgets)) {
        foreach ($enabled_types_widgets as $entity_type_id => $entity_types) {
          foreach ($entity_types as $bundle => $settings) {
            if ($entity_type_id !== 'node') {
              continue;
            }
            if (!in_array($node
              ->bundle(), array_keys($entity_types))) {
              unset($data['tabs'][0]['rate.results_page']);
              break;
            }
          }
        }
      }
      elseif (isset($data['tabs'][0]['rate.results_page'])) {
        unset($data['tabs'][0]['rate.results_page']);
      }
    }
  }
}

/**
 * Implements hook_theme().
 */
function rate_theme($existing, $type, $theme, $path) {
  return [
    // Templates for default widget types.
    'rate_template_info_description' => [
      'variables' => [
        'info' => '',
        'description' => '',
      ],
      'template' => 'rate-template-info-description',
    ],
    'rate_template_thumbs_up' => [
      'variables' => [
        'results' => 0,
        'use_ajax' => FALSE,
        'can_vote' => FALSE,
        'has_voted' => FALSE,
        'user_voted' => NULL,
        'entity_id' => NULL,
        'entity_type_id' => NULL,
        'widget_type' => NULL,
      ],
      'template' => 'rate-template-thumbs-up',
    ],
    'rate_template_thumbs_up_down' => [
      'variables' => [
        'results' => 0,
        'use_ajax' => FALSE,
        'can_vote' => FALSE,
        'has_voted' => FALSE,
        'user_voted' => NULL,
        'entity_id' => NULL,
        'entity_type_id' => NULL,
        'widget_type' => NULL,
      ],
      'template' => 'rate-template-thumbs-up-down',
    ],
    'rate_template_number_up_down' => [
      'variables' => [
        'results' => 0,
        'use_ajax' => FALSE,
        'can_vote' => FALSE,
        'has_voted' => FALSE,
        'user_voted' => NULL,
        'entity_id' => NULL,
        'entity_type_id' => NULL,
        'widget_type' => NULL,
      ],
      'template' => 'rate-template-number-up-down',
    ],
    'rate_template_fivestar' => [
      'variables' => [
        'results' => 0,
        'use_ajax' => FALSE,
        'can_vote' => FALSE,
        'has_voted' => FALSE,
        'user_voted' => NULL,
        'entity_id' => NULL,
        'entity_type_id' => NULL,
        'widget_type' => NULL,
      ],
      'template' => 'rate-template-fivestar',
    ],
    'rate_template_yesno' => [
      'variables' => [
        'results' => 0,
        'use_ajax' => FALSE,
        'can_vote' => FALSE,
        'has_voted' => FALSE,
        'user_voted' => NULL,
        'entity_id' => NULL,
        'entity_type_id' => NULL,
        'widget_type' => NULL,
      ],
      'template' => 'rate-template-yesno',
    ],
  ];
}

/**
 * Implements hook_preprocess_HOOK() for rate-template-number-up-down.html.twig.
 */
function template_preprocess_rate_template_number_up_down(&$variables) {
  $vote_types = [
    'up',
    'down',
  ];
  foreach ($vote_types as $vote_type) {
    $variables[$vote_type . '_attributes'] = new Attribute();
    $variables[$vote_type . '_attributes']['class'] = [];
    $variables[$vote_type . '_attributes']['class'][] = 'rate-number-up-down-btn-' . $vote_type;
    if ($variables['use_ajax'] && !$variables['has_voted'] && $variables['can_vote']) {
      $variables[$vote_type . '_attributes']['class'][] = 'use-ajax';
    }
  }
  $score = isset($variables['results']['updown']['vote_sum']) ? $variables['results']['updown']['vote_sum'] : 0;
  if ($score > 0) {
    $score = '+' . $score;
    $score_class = 'positive';
  }
  elseif ($score < 0) {
    $score_class = 'negative';
  }
  else {
    $score_class = 'neutral';
  }
  $variables['score'] = $score;
  $variables['score_attributes'] = new Attribute();
  $variables['score_attributes']['class'] = [];
  $variables['score_attributes']['class'][] = 'rate-number-up-down-rating';
  $variables['score_attributes']['class'][] = $score_class;
  $variables['up_votes'] = isset($variables['results']['updown']['rate_count_up']) ? $variables['results']['updown']['rate_count_up'] : 0;
  $variables['down_votes'] = isset($variables['results']['updown']['vote_count']) ? $variables['results']['updown']['vote_count'] - $variables['up_votes'] : 0;
  _rate_set_common_theme_variables($variables);
  _rate_get_undo_link($variables);
  $variables['#attached']['library'][] = 'rate/number-up-down';
}

/**
 * Implements hook_preprocess_HOOK() for rate-template-fivestar.html.twig.
 */
function template_preprocess_rate_template_fivestar(&$variables) {
  $variables['stars'] = [];

  // Calculate the score.
  $score = isset($variables['results']['fivestar']['vote_average']) ? $variables['results']['fivestar']['vote_average'] : 0;

  // Set up the links.
  for ($counter = 1; $counter < 6; $counter++) {
    $variables['stars'][$counter]['star_attributes'] = new Attribute();
    $variables['stars'][$counter]['star_attributes']['class'] = [];
    if ($counter <= $score) {
      $variables['stars'][$counter]['star_attributes']['class'][] = 'rate-fivestar-btn-filled';
    }
    else {
      $variables['stars'][$counter]['star_attributes']['class'][] = 'rate-fivestar-btn-empty';
    }
    $variables['stars'][$counter]['star_attributes']['class'][] = ' rate-fivestar-' . $counter;
    if ($variables['use_ajax'] && !$variables['has_voted'] && $variables['can_vote']) {
      $variables['stars'][$counter]['star_attributes']['class'][] = 'use-ajax';
    }
    if ($variables['entity_id']) {
      $variables['stars'][$counter]['star_link'] = Url::fromRoute('rate.vote', [
        'entity_type_id' => $variables['entity_type_id'],
        'vote_type_id' => 'fivestar',
        'value' => $counter,
        'entity_id' => $variables['entity_id'],
        'widget_type' => $variables['widget_type'],
        'destination' => \Drupal::destination()
          ->getAsArray()['destination'],
      ]);
    }
  }
  _rate_set_common_theme_variables($variables, FALSE);
  _rate_get_undo_link($variables);
  $variables['#attached']['library'][] = 'rate/fivestar';
}

/**
 * Implements hook_preprocess_HOOK() for rate-template-thumbs_up_down.html.twig.
 */
function template_preprocess_rate_template_thumbs_up_down(&$variables) {
  $vote_types = [
    'up' => '1',
    'down' => '-1',
  ];
  foreach ($vote_types as $vote_type => $value) {
    $variables[$vote_type . '_li_attributes'] = new Attribute();
    $variables[$vote_type . '_li_attributes']['class'] = [];
    $variables[$vote_type . '_li_attributes']['class'] = 'thumb-' . $vote_type;
    $variables[$vote_type . '_attributes'] = new Attribute();
    $variables[$vote_type . '_attributes']['class'] = [];
    $variables[$vote_type . '_attributes']['class'][] = 'rate-thumbs-up-down-btn-' . $vote_type;

    // Add a class if the current user has voted on this item.
    if ($variables['user_voted'] === $value) {
      $variables[$vote_type . '_li_attributes']['class'][] = 'rate-voted';
    }
    if ($variables['use_ajax'] && !$variables['has_voted'] && $variables['can_vote']) {
      $variables[$vote_type . '_attributes']['class'][] = 'use-ajax';
    }
  }
  $variables['percent_attributes'] = new Attribute();
  $variables['percent_attributes']['class'] = [];
  $variables['percent_attributes']['class'][] = 'percent';
  $total_votes = isset($variables['results']['updown']['vote_count']) ? $variables['results']['updown']['vote_count'] : 0;
  $variables['up_votes'] = isset($variables['results']['updown']['rate_count_up']) ? $variables['results']['updown']['rate_count_up'] : 0;
  $variables['down_votes'] = $total_votes - $variables['up_votes'];
  if (!empty($total_votes)) {
    $variables['up_percent'] = round($variables['up_votes'] / $total_votes * 100);
    $variables['down_percent'] = round($variables['down_votes'] / $total_votes * 100);
  }
  else {
    $variables['up_percent'] = 0;
    $variables['down_percent'] = 0;
  }
  _rate_set_common_theme_variables($variables);
  _rate_get_undo_link($variables);
  $variables['#attached']['library'][] = 'rate/thumbs-up-down';
}

/**
 * Implements hook_preprocess_HOOK() for rate-template-thumbs_up.html.twig.
 */
function template_preprocess_rate_template_thumbs_up(&$variables) {
  $variables['up_attributes'] = new Attribute();
  $variables['up_attributes']['class'] = [];
  $variables['up_attributes']['class'][] = 'rate-thumbs-up-btn-up';
  if ($variables['use_ajax'] && !$variables['has_voted'] && $variables['can_vote']) {
    $variables['up_attributes']['class'][] = 'use-ajax';
  }
  $variables['score_attributes'] = new Attribute();
  $variables['score_attributes']['class'] = [];
  $variables['score_attributes']['class'][] = 'rate-score';
  $variables['up_votes'] = isset($variables['results']['updown']['rate_count_up']) ? $variables['results']['updown']['rate_count_up'] : 0;
  _rate_set_common_theme_variables($variables);
  _rate_get_undo_link($variables);
  $variables['#attached']['library'][] = 'rate/thumbs-up';
}

/**
 * Implements hook_preprocess_HOOK() for rate-template-yes_no.html.twig.
 */
function template_preprocess_rate_template_yesno(&$variables) {
  $vote_types = [
    'yes' => '1',
    'no' => '-1',
  ];
  foreach ($vote_types as $vote_type => $value) {
    $variables[$vote_type . '_li_attributes'] = new Attribute();
    $variables[$vote_type . '_li_attributes']['class'] = [];
    $variables[$vote_type . '_li_attributes']['class'][] = 'rate-' . $vote_type;
    $variables[$vote_type . '_attributes'] = new Attribute();
    $variables[$vote_type . '_attributes']['class'] = [];
    $variables[$vote_type . '_attributes']['class'][] = 'rate-yesno-btn';
    $variables[$vote_type . '_attributes']['class'][] = 'rate-' . $vote_type . '-btn';

    // Add a class if the current user has voted on this item.
    if ($variables['user_voted'] === $value) {
      $variables[$vote_type . '_li_attributes']['class'][] = 'rate-voted';
    }
    if ($variables['use_ajax'] && !$variables['has_voted'] && $variables['can_vote']) {
      $variables[$vote_type . '_attributes']['class'][] = 'use-ajax';
    }
  }
  $variables['up_votes'] = isset($variables['results']['updown']['rate_count_up']) ? $variables['results']['updown']['rate_count_up'] : 0;
  $variables['down_votes'] = isset($variables['results']['updown']['vote_count']) ? $variables['results']['updown']['vote_count'] - $variables['up_votes'] : 0;
  $variables['score_attributes'] = new Attribute();
  $variables['score_attributes']['class'] = [];
  $variables['score_attributes']['class'][] = 'rate-yesno-votes';
  _rate_set_common_theme_variables($variables, TRUE);
  _rate_get_undo_link($variables);
  $variables['#attached']['library'][] = 'rate/yesno';
}

/**
 * Helper function to return an undo link.
 */
function _rate_get_undo_link(&$variables) {
  if (!$variables['entity_id']) {
    $variables['can_vote'] = FALSE;
    return;
  }
  $variables['undo'] = '';
  $variables['undo_attributes'] = new Attribute();
  $variables['undo_attributes']['class'] = [];
  $variables['undo_attributes']['class'][] = 'rate-undo-vote';
  $undo_link_class = 'rate-undo';
  if ($variables['use_ajax']) {
    $undo_link_class .= ' use-ajax';
  }
  if ($variables['has_voted']) {
    $variables['undo'] = Link::fromTextAndUrl(t('Undo'), Url::fromRoute('rate.undo_vote', [
      'entity_type_id' => $variables['entity_type_id'],
      'entity_id' => $variables['entity_id'],
      'widget_type' => $variables['widget_type'],
      'destination' => \Drupal::destination()
        ->getAsArray()['destination'],
    ], [
      'attributes' => [
        'class' => $undo_link_class,
      ],
    ]));
  }
}

/**
 * Helper function to set common themeing variables.
 */
function _rate_set_common_theme_variables(&$variables, $generate_links = TRUE) {
  $destination = \Drupal::destination()
    ->getAsArray();
  if (!$variables['entity_id']) {
    $variables['can_vote'] = FALSE;
    return;
  }
  if ($generate_links) {
    $variables['up_url'] = Url::fromRoute('rate.vote', [
      'entity_type_id' => $variables['entity_type_id'],
      'vote_type_id' => 'updown',
      'value' => 1,
      'entity_id' => $variables['entity_id'],
      'widget_type' => $variables['widget_type'],
      'destination' => $destination['destination'],
    ]);
    $variables['down_url'] = Url::fromRoute('rate.vote', [
      'entity_type_id' => $variables['entity_type_id'],
      'vote_type_id' => 'updown',
      'value' => -1,
      'entity_id' => $variables['entity_id'],
      'widget_type' => $variables['widget_type'],
      'destination' => $destination['destination'],
    ]);
  }
  $output['info_description'] = [
    // @Todo: Add info and description to to settings form.
    '#theme' => 'info_description',
    '#info' => '',
    '#description' => '',
  ];
  $variables['destination'] = $destination['destination'];
  $variables['widget_attributes'] = new Attribute();
  $variables['widget_attributes']['data-drupal-selector'] = 'rate-' . $variables['entity_type_id'] . '-' . $variables['entity_id'];
  $variables['widget_attributes']['class'] = [];
  $class = str_ireplace('rate_template_', '', $variables['theme_hook_original']);
  $variables['widget_attributes']['class'][] = 'rate-widget-' . str_ireplace('_', '-', $class);
}

/**
 * Implements hook_ENTITY_TYPE_access().
 */
function rate_vote_type_access(EntityInterface $vote_type, $operation, AccountInterface $account) {

  // If the user has the 'view rate results page' permission, we grant 'view'
  // access to all of the vote_type configuration entities defined
  // by the Rate module.
  $rate_types = [
    'updown',
    'fivestar',
  ];

  // Allow users with the permission 'view rate results page' to view metadata
  // about any of the vote types provided by this module.
  if (in_array($vote_type
    ->id(), $rate_types)) {
    switch ($operation) {
      case 'view':
        return AccessResult::allowedIf($account
          ->hasPermission('view rate results page'))
          ->cachePerPermissions()
          ->cachePerUser();
      default:
        return AccessResult::neutral();
    }
  }
  else {
    return AccessResult::neutral();
  }
}