closedquestion-8.x-3.x-dev/src/Controller/ClosedQuestionController.php

src/Controller/ClosedQuestionController.php
<?php

namespace Drupal\closedquestion\Controller;

use Drupal\closedquestion\Entity\ClosedQuestionInterface;
use Drupal\closedquestion\Question\CqQuestionSequence;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Database\Connection;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\file\Entity\File;
use Drupal\file\FileInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;

/**
 * Class ClosedQuestionController.
 *
 * @package Drupal\closedquestion\Controller
 */
class ClosedQuestionController extends ControllerBase {

  /**
   * Database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $databaseConnection;

  /**
   * ClosedQuestionController constructor.
   *
   * @param \Drupal\Core\Database\Connection $database
   *   Database connection.
   */
  public function __construct(Connection $database) {
    $this->databaseConnection = $database;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('database')
    );
  }

  /**
   * Displays a view with scoreboard.
   *
   * @param \Drupal\closedquestion\Entity\ClosedQuestionInterface $closedquestion
   *   A question to display scores for.
   *
   * @return array
   *   Render array.
   */
  public function scoreboard(ClosedQuestionInterface $closedquestion) {

    return [
      '#type' => 'container',
      '#cache' => [
        'tags' => [
          'closedquestion_scoreboard:' . $closedquestion->id(),
        ],
        'contexts' => [
          'url.path',
        ],
      ],
      'heading' => [
        '#type' => 'html_tag',
        '#tag' => 'h2',
        '#value' => t('Users that answered question %question', array('%question' => $closedquestion->label())),
      ],
      'view' => views_embed_view('closed_question_scoreboard', 'default', $closedquestion->id()),
    ];
  }

  /**
   * Generates age title for the tabs.
   *
   * @param \Drupal\closedquestion\Entity\ClosedQuestionInterface $closedquestion
   *   A closed question being viewed.
   *
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
   *   Page title.
   */
  public function tabTitle(ClosedQuestionInterface $closedquestion) {
    return $closedquestion->label();
  }

  /**
   * Displays answers list.
   *
   * @param \Drupal\closedquestion\Entity\ClosedQuestionInterface $closedquestion
   *   A question to display answers for.
   * @param bool $asData
   *   If method should return data instead of HTML.
   *
   * @return array|string
   *   HTML | data array.
   */
  public function answers(ClosedQuestionInterface $closedquestion, $asData = FALSE) {
    /* summary table */

    // Set the table headers.
    $summaryTableHeaders = array(
      array('data' => t('User'), 'field' => 'name'),
      array('data' => t('Correct?'), 'field' => 'correct'),
    );
    $summaryTableHeadersKeys = array_keys($summaryTableHeaders[0]);

    $langcode = $this->languageManager()->getCurrentLanguage()->getId();

    // Get results from db.
    $query = $this->databaseConnection->select('cq__field_data', 'cq');
    $query->leftJoin('cq_answer', 'cqa', 'cqa.qid = cq.id');
    $query->join('users_field_data', 'u', 'cqa.uid = u.uid');
    $query->condition('cq.id', $closedquestion->id());
    $query->condition('cq.langcode', $langcode);
    $query->condition('u.langcode', $langcode);
    $query->addExpression('SUM(IF(correct_past>0, 1, 0))', 'total_correct');
    $query->addField('u', 'uid');
    $query->addField('u', 'name');
    $query->addField('cq', 'id');
    $query->addField('cq', 'title');
    $query->addField('cqa', 'answer__value');
    $query->addField('cqa', 'correct_past');
    $query->addField('cqa', 'correct');
    $query->addExpression("IF(correct=1, 'yes', 'no')", 'correct');
    $query->addExpression("DATE_FORMAT(FROM_UNIXTIME(cqa.changed), '%Y-%m-%d, %H:%i')", 'timestamp');

    $query = $query->extend('Drupal\Core\Database\Query\TableSortExtender');
    $query->groupBy('u.uid');
    $query->groupBy('cqa.id');
    $query->orderByHeader($summaryTableHeaders);

    $result = $query->execute();

    // Put db results in table.
    $summaryTableData = array();
    $summaryTableHeadersResultsAdded = FALSE;
    while ($row = $result->fetchAssoc()) {

      $summaryTableRowData = array();
      $summaryTableRowData[0] = $row['name'];
      $summaryTableRowData[1] = $row['correct'];

      /* add answer */
      $answerAsArray = unserialize($row['answer__value']);

      if (is_array($answerAsArray)) {
        ksort($answerAsArray);
        // Sequence questions require special handling.
        if ($closedquestion->question instanceof CqQuestionSequence) {
          $answerValueCombined = '';
          foreach ($answerAsArray as $key => $answerValue) {
            if (is_numeric($key)) {
              $answerValueCombined .= $answerValue['sa'];
            }
          }

          if ($summaryTableHeadersResultsAdded === FALSE) {
            $summaryTableHeaders[] = array('data' => t('Answer'), 'field' => 'answer__value');
            $summaryTableHeadersResultsAdded = TRUE;
          }

          $summaryTableRowData[count($summaryTableHeaders) - 1] = $answerValueCombined;
        }
        else {
          foreach ($answerAsArray as $key => $answerValue) {
            $columnIndex = array_search($key, $summaryTableHeadersKeys);
            if ($columnIndex === FALSE) {
              $columnIndex = count($summaryTableHeaders);
              $summaryTableHeaders[] = array(
                'data' => t('@key', ['@key' => $key]),
                'field' => 'answer__value',
              );
              $summaryTableHeadersKeys[] = $key;
            }

            $summaryTableRowData[$columnIndex] = Xss::filterAdmin($answerValue);
          }
        }
      }
      else {
        if ($summaryTableHeadersResultsAdded === FALSE) {
          $summaryTableHeaders[] = array('data' => t('Answer'), 'field' => 'answer__value');
          $summaryTableHeadersResultsAdded = TRUE;
        }

        $summaryTableRowData[count($summaryTableHeaders) - 1] = $answerAsArray;
      }

      $summaryTableRowData[] = $row['timestamp'];
      $summaryTableData[] = $summaryTableRowData;
    }

    $summaryTableHeaders[] = array('data' => t('Timestamp'), 'field' => 'changed');

    $tableData = array(
      'header' => $summaryTableHeaders,
      'rows' => $summaryTableData,
    );

    // Theme table.
    if ($asData === FALSE) {
      $retval = [
        '#type' => 'container',
        '#cache' => [
          'tags' => [
            'closedquestion_answers:' . $closedquestion->id(),
          ],
          'contexts' => [
            'url.path',
          ],
        ],
        'heading' => [
          '#type' => 'html_tag',
          '#tag' => 'h2',
          '#value' => t('User answers'),
        ],
        'results' => [
          '#type' => 'table',
          '#prefix' => '<div style="overflow: auto;">',
          '#suffix' => '</div>',
          '#header' => $summaryTableHeaders,
          '#rows' => $summaryTableData,
        ],
        'csv' => [
          '#type' => 'link',
          '#title' => t('Export to CSV'),
          '#url' => Url::fromRoute(
            'closedquestion.answers.csv',
            ['closedquestion' => $closedquestion->id()]
          ),
        ],
      ];
    }
    else {
      $retval = $tableData;
    }
    return $retval;
  }

  /**
   * Returns a CSV file with answers.
   *
   * @param \Drupal\closedquestion\Entity\ClosedQuestionInterface $closedquestion
   *   A question to generate report for.
   *
   * @return \Symfony\Component\HttpFoundation\Response
   *   Response with exported CSV file.
   */
  public function answersCsv(ClosedQuestionInterface $closedquestion) {
    $csvExport = '';
    $csvExportAsArray = array();

    $answers = $this->answers($closedquestion, TRUE);

    /* convert answers data to csv string */
    if (is_array($answers['header']) && is_array($answers['rows'])) {
      foreach ($answers['header'] as $columnData) {
        $csvExportAsArray[] = '"' . addslashes($columnData['data']) . '"';
      }
      $csvExport .= implode(';', $csvExportAsArray) . "\n";

      foreach ($answers['rows'] as &$rowData) {
        array_walk($rowData, function (&$value) {
          $value = '"' . addslashes($value) . '"';
        });

        $csvExport .= implode(';', $rowData) . "\n";
      }
    }

    /* output */
    $filename = 'cq_' . $closedquestion->id() . '_answers_' . date('YmdHis') . '.csv';
    $response = new Response();
    $response->headers->add([
      'Content-type' => 'text/csv',
      'Content-Disposition' => "attachment; filename=$filename",
      'Pragma' => 'no-cache',
      'Expires' => '0',
    ]);
    $response->setContent($csvExport);

    return $response;
  }

  /**
   * Displays user's history of answering the question.
   *
   * @param \Drupal\closedquestion\Entity\ClosedQuestionInterface $closedquestion
   *   A question to display log for.
   * @param \Drupal\Core\Session\AccountInterface $user
   *   A user to display log for.
   *
   * @return array
   *   Render array.
   */
  public function userLog(ClosedQuestionInterface $closedquestion, AccountInterface $user) {

    return [
      '#type' => 'container',
      '#cache' => [
        'tags' => [
          'closedquestion_user_log:' . $closedquestion->id(),
        ],
        'contexts' => [
          'url.path',
        ],
      ],
      'heading' => [
        '#type' => 'html_tag',
        '#tag' => 'h2',
        '#value' => t('The log of how user %name answered question %question', array('%name' => $user->getAccountName(), '%question' => $closedquestion->label())),
      ],
      'view' => views_embed_view('closed_question_user_log', 'default', $closedquestion->id(), $user->id()),
    ];
  }

  /**
   * Returns text representation of a question.
   *
   * @param \Drupal\closedquestion\Entity\ClosedQuestionInterface $closedquestion
   *   Closed question entity.
   *
   * @return array
   *   Text representation of the question.
   */
  public function text(ClosedQuestionInterface $closedquestion) {
    $retval = $closedquestion->question->getAllText();

    $retval['#cache'] = [
      'tags' => [
        'closedquestion_text:' . $closedquestion->id(),
      ],
      'contexts' => [
        'url.path',
      ],
    ];

    return $retval;
  }

  /**
   * Returns file as stream.
   *
   * @param \Drupal\file\FileInterface $file
   *   Id of a file to return.
   *
   * @return \Symfony\Component\HttpFoundation\Response|null
   *   File response if available.
   */
  public function getFile(FileInterface $file) {
    $uri = \Drupal::service('file_system')->realpath($file->getFileUri());

    if (file_exists($uri)) {
      $mimetype = mime_content_type($uri);

      $response = new Response();
      $response->headers->add([
        'Content-Description' => 'File Transfer',
        'Content-Type' => $mimetype != '' ? $mimetype : 'application/octet-stream',
      ]);
      $response->setContent(file_get_contents($uri));
      return $response;
    }

    return NULL;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc