' . t('About') . ''; $output .= '

' . t('VotingAPI helps developers who want to use a standardized API and schema for storing, retrieving and tabulating votes for Drupal content.') . '

'; $output .= '

' . t('Please view the %url page for more details.', [ '%url' => Link::fromTextAndUrl(t('Voting API'), Url::fromUri('https://www.drupal.org/project/votingapi')) ->toString(), ] ) . '

'; $output .= '

' . t('Uses') . '

'; $output .= '
'; $output .= '
' . t('General') . '
'; $output .= '
' . t('VotingAPI uses a flexible, easy-to-use framework for rating, voting, moderation, and consensus-gathering modules in Drupal. Module developers use it to focus on their ideas (say, providing a "rate this thread" widget at the bottom of each forum post) without worrying about the grunt work of storing votes, preventing ballot-stuffing, calculating the results, and so on.') . '
'; $output .= '
' . t('Basic Concepts and Features') . '
'; $output .= '
' . t('VotingAPI does NOT directly expose any voting mechanisms to end users. It is a framework designed to make life easier for other developers, and to standardize voting data for consumption by other modules (like Views).') . '
'; $output .= '
' . t('Two kinds of records are stored: individual votes by each user on each piece of content, and cached "result" records. The cached records aggregate calculated values like the average vote for a piece of content, how many people voted on it, etc. Each time a user votes, the cached result records are automatically recalculated. This means that no "on-the-fly" calculations have to be done when displaying content ratings.') . '
'; $output .= '
'; return $output; default: } } /** * Implements hook_entity_delete(). */ function votingapi_entity_delete(EntityInterface $entity) { // Only act on content entities. if (!($entity instanceof FieldableEntityInterface)) { return; } // Delete all votes and result entries for the deleted entities. if (!($entity instanceof VoteInterface)) { $vote_storage = \Drupal::entityTypeManager()->getStorage('vote'); $vote_storage->deleteVotesForDeletedEntity( $entity->getEntityTypeId(), $entity->id() ); } } /** * Implements hook_cron(). * * Recalculate results for any entities that have gotten votes since the last * run. */ function votingapi_cron() { if (Drupal::config('votingapi.settings') ->get('calculation_schedule') == 'cron' ) { $vote_storage = \Drupal::entityTypeManager()->getStorage('vote'); $results = $vote_storage->getVotesSinceMoment(); $manager = \Drupal::service('plugin.manager.votingapi.resultfunction'); foreach ($results as $entity) { $manager->recalculateResults( $entity['entity_type'], $entity['entity_id'], $entity['type'] ); } \Drupal::state()->set('votingapi.last_cron', \Drupal::time() ->getRequestTime()); } } /** * Implements hook_views_query_alter(). */ function votingapi_views_query_alter(ViewExecutable $view, QueryPluginBase $query) { // The code below allows sorting by voting results // so that no result (when no one voted) means zero. $base_table = $view->storage->get('base_table'); if ($query->getBaseId() != 'views_query') { return; } $vr_aliases = []; foreach ($query->tables[$base_table] as $alias => $table_d) { $table_info = $query->getTableInfo($alias); if ($table_info['table'] == 'votingapi_result') { $vr_aliases[$alias] = TRUE; } } $va_fields = []; foreach ($query->fields as $f_name => &$f_data) { if (isset($vr_aliases[$f_data['table']]) && $f_data['field'] == 'value') { $va_fields[$f_name] = $f_data; } } foreach ($va_fields as $va_field) { $query->addField(NULL, 'COALESCE(' . $va_field['table'] . '.value, 0)', $va_field['alias'] . '__coa'); } foreach ($query->orderby as &$order) { if (isset($va_fields[$order['field']])) { $order['field'] = $va_fields[$order['field']]['alias'] . '__coa'; } } }