openquestions-1.0.x-dev/src/Plugin/Block/OQScoreboardBlock.php
src/Plugin/Block/OQScoreboardBlock.php
<?php
namespace Drupal\openquestions\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\Core\Utility\LinkGeneratorInterface;
use Drupal\Core\Session\AccountProxy;
use Drupal\Component\Render\FormattableMarkup;
/**
* OpenQuestions Scoreboard block. Designed to show the current votes on
* OQ Item pages.
*
* "entity:oq_item" is available due to OQItemRouteContext.
*
* @Block(
* id = "oq_scoreboard_block",
* admin_label = @Translation("OQ Scoreboard"),
* category = @Translation("OpenQuestions"),
* context_definitions = {
* "oq_item" = @ContextDefinition("entity:oq_item", label = @Translation("OQ Item"))
* }
* )
*/
class OQScoreboardBlock extends BlockBase implements ContainerFactoryPluginInterface {
/**
* To generate links.
*
* @var \Drupal\Core\Utility\LinkGeneratorInterface
*/
protected $linkGenerator;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxy
*/
protected $currentUser;
/**
* Our logger.
*
* @var \Drupal\Core\Logger\LoggerChannelInterface
*/
protected $logger;
/**
* Constructs an OQScoreboardBlock.
*/
public function __construct(array $configuration,
$plugin_id,
$plugin_definition,
LinkGeneratorInterface $linkGenerator,
AccountProxy $currentUser,
LoggerChannelInterface $logger) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->linkGenerator = $linkGenerator;
$this->currentUser = $currentUser;
$this->logger = $logger;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('link_generator'),
$container->get('current_user'),
$container->get('openquestions.logger.channel.openquestions')
);
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'expand_all' => 1,
'expand_questions' => 1,
];
}
/**
* {@inheritdoc}
*/
public function blockForm($form, FormStateInterface $form_state) {
$form['expand_all'] = [
'#type' => 'checkbox',
'#title' => $this->t('Expand all'),
'#description' => $this->t('Expand all'),
'#default_value' => $this->configuration['expand_all'],
];
$form['expand_questions'] = [
'#type' => 'checkbox',
'#title' => $this->t('Expand questions'),
'#description' => $this->t('Expand questions'),
'#default_value' => $this->configuration['expand_questions'],
];
return $form;
}
/**
* {@inheritdoc}
*/
public function blockSubmit($form, FormStateInterface $form_state) {
$this->configuration['expand_all'] = $form_state->getValue('expand_all');
$this->configuration['expand_questions'] = $form_state->getValue('expand_questions');
}
/**
* {@inheritdoc}
*/
public function build() {
$item = $this->getContextValue('oq_item');
$voteData = $item->getVoteData();
$accounts = $voteData->getAccountsThatAreAllowedToVoteOnThisItem();
$ret = [];
$questions = $item->getQuestions();
foreach ($questions as $question) {
if ($question->get('status')->value) {
$ret[] = $this->buildQuestion($question, $voteData, $accounts);
$ret[] = $this->buildQuestionFooter($question, $voteData, $accounts);
}
}
$ret['#attached']['library'][] = 'openquestions/openquestions_voting';
return $ret;
}
/**
* Build a virtual table for the given question.
*/
protected function buildQuestion($question, $voteData, $accounts) {
$ret = [
'#theme' => 'table__openquestions_voting',
'#caption' => '',
'#question_id' => 0,
'#current_uid' => 0,
'#accounts' => [],
'#votes' => [],
];
$ret['#caption'] = $question->get('label')->value;
$ret['#question_id'] = $questionID = $question->id();
$ret['#current_uid'] = $currentUID = $this->currentUser->id();
foreach ($accounts as $account) {
$ret['#accounts'][] = [
'uid' => $account->id(),
'name' => $account->get('name')->value,
'url' => $account->toUrl()->toString(),
];
}
$itemID = $this->getContextValue('oq_item')->id();
foreach ($accounts as $account) {
$ary = $voteData->getVotesForQuestionIdAndAccountId($questionID, $account->id());
$vote = $ary ? array_shift($ary) : NULL;
$row = [
'type' => NULL,
'value' => NULL,
'vote_url' => NULL,
'uid' => $account->id(),
'item_id' => $itemID,
'question_id' => $questionID,
];
if (!$vote) {
if ($currentUID && $currentUID == $account->id()) {
$row['type'] = 'voteable';
$row['value'] = $this->t('Vote');
}
else {
$row['type'] = 'empty';
$row['value'] = '--';
}
}
else {
$row['vote_url'] = $vote->toUrl()->toString();
$row['value'] = $question->getOptionName($vote->get('vote_value')->value);
if (!$vote->get('status')->value) {
$row['type'] = 'canceled';
$row['value'] .= ' ' . $this->t('(X)');
}
else {
$row['type'] = 'voted';
}
}
$ret['#votes'][] = $row;
}
return $ret;
}
/**
* Build the info for the footer of a question table.
*/
protected function buildQuestionFooter($question, $voteData, $accounts) {
$ret = [
'#type' => 'item',
'#markup' => '',
];
$rangeInfo = $question->getOptionsRangeInfo();
if ($rangeInfo['type'] == 'binary') {
$ret['#markup'] = $this->t('Choices are @a or @b', ['@a' => $rangeInfo['first'], '@b' => $rangeInfo['last']]);
}
else {
$ret['#markup'] = $this->t('Choices range between @a and @b', ['@a' => $rangeInfo['first'], '@b' => $rangeInfo['last']]);
}
return $ret;
}
}
