View source
<?php
namespace Drupal\opigno_h5p\TypeProcessors;
use Drupal\Component\Utility\Xss;
class FillInProcessor extends TypeProcessor {
const FILL_IN_PLACEHOLDER = '__________';
const RESPONSES_SEPARATOR = '[,]';
const CRP_REPORT_SEPARATOR = ' / ';
public function generateHTML($description, $crp, $response, $extras, $scoreSettings = NULL) {
$this
->setStyle('opigno_h5p/opigno_h5p.fill-in');
$caseMatters = $this
->determineCaseMatters($crp[0]);
if (!empty($crp)) {
$processedCRPs = $this
->processCRPs($crp, $caseMatters['nextIndex']);
$processedResponse = $this
->processResponse($response);
$header = $this
->generateHeader($scoreSettings);
$report = $this
->buildReportOutput($description, $processedCRPs, $processedResponse, $caseMatters['caseSensitive']);
$footer = $this
->generateFooter();
}
else {
$header = '<div class="h5p-reporting-description">' . Xss::filter($description) . '</div>';
$report = '<div class="h5p-fill-in-user-response">' . Xss::filter($response) . '</div>';
$footer = NULL;
}
$container = '<div class="h5p-reporting-container h5p-fill-in-container">' . $header . $report . '</div>';
return $container . $footer;
}
private function generateHeader($scoreSettings) {
$scoreHtml = $this
->generateScoreHtml($scoreSettings);
return "<div class='h5p-fill-in-header'>" . $scoreHtml . "</div>";
}
public function generateFooter() {
return '<div class="h5p-fill-in-footer">' . '<span class="h5p-fill-in-correct-responses-pattern">' . t('Correct Answer') . '</span>' . '<span class="h5p-fill-in-user-response-correct">' . t('Your correct answer') . '</span>' . '<span class="h5p-fill-in-user-response-wrong">' . t('Your incorrect answer') . '</span>' . '</div>';
}
private function processCRPs(array $crp, $strStartIndex) {
$sortedCRP = [];
foreach ($crp as $crpString) {
$pattern = substr($crpString, $strStartIndex);
$answers = explode(self::RESPONSES_SEPARATOR, $pattern);
foreach ($answers as $index => $value) {
if (!isset($sortedCRP[$index])) {
$sortedCRP[$index] = [];
}
if (!in_array($value, $sortedCRP[$index])) {
$sortedCRP[$index][] = $value;
}
}
}
return $sortedCRP;
}
private function determineCaseMatters($singleCRP) {
$html = '';
$nextIndex = 0;
$caseSensitive = NULL;
if (strtolower(substr($singleCRP, 1, 13)) === 'case_matters=') {
if (strtolower(substr($singleCRP, 14, 5)) === 'false') {
$html = 'caseSensitive = false';
$nextIndex = 20;
$caseSensitive = FALSE;
}
elseif (strtolower(substr($singleCRP, 14, 4)) === 'true') {
$html = 'caseSensitive = true';
$nextIndex = 19;
$caseSensitive = TRUE;
}
}
return [
'html' => $html,
'nextIndex' => $nextIndex,
'caseSensitive' => $caseSensitive,
];
}
private function buildReportOutput($description, $crp, $response, $caseSensitive) {
$placeholderReplacements = $this
->getPlaceholderReplacements($crp, $response, $caseSensitive);
return $this
->replacePlaceholders($description, $placeholderReplacements);
}
private function getPlaceholderReplacements(array $crp, array $response, $caseSensitive) {
$placeholderReplacements = [];
foreach ($crp as $index => $value) {
$currentResponse = isset($response[$index]) ? $response[$index] : '';
$isCorrect = $this
->isResponseCorrect($currentResponse, $value, $caseSensitive);
$responseClass = $isCorrect ? 'h5p-fill-in-user-response-correct' : 'h5p-fill-in-user-response-wrong';
$userResponse = '<span class="h5p-fill-in-user-response ' . $responseClass . '">' . $currentResponse . '</span>';
$CRPhtml = $this
->getCRPHtml($value, $currentResponse, $caseSensitive);
$correctResponsePattern = '';
if (strlen($CRPhtml) > 0) {
$correctResponsePattern .= '<span class="h5p-fill-in-correct-responses-pattern">' . $CRPhtml . '</span>';
}
$placeholderReplacements[] = $userResponse . $correctResponsePattern;
}
return $placeholderReplacements;
}
private function getCRPHtml(array $singleCRP, $response, $caseSensitive) {
$html = [];
foreach ($singleCRP as $value) {
$comparisonCRP = $value;
$comparisonResponse = $response;
if (isset($caseSensitive) && $caseSensitive === FALSE) {
$comparisonCRP = strtolower($value);
$comparisonResponse = strtolower($response);
}
if ($comparisonCRP === $comparisonResponse) {
continue;
}
$html[] = $value;
}
return implode(self::CRP_REPORT_SEPARATOR, $html);
}
private function isResponseCorrect($response, array $crp, $caseSensitive) {
$userResponse = $response;
$matchingPattern = $crp;
if (isset($caseSensitive) && $caseSensitive === FALSE) {
$userResponse = strtolower($response);
$matchingPattern = array_map('strtolower', $crp);
}
return in_array($userResponse, $matchingPattern);
}
private function processResponse($response) {
return explode(self::RESPONSES_SEPARATOR, $response);
}
private function replacePlaceholders($description, array $placeholderReplacements) {
$replacedDescription = $description;
$index = 0;
$nextPos = strpos($replacedDescription, self::FILL_IN_PLACEHOLDER, 0);
while ($nextPos !== FALSE) {
$replacedDescription = substr_replace($replacedDescription, $placeholderReplacements[$index], $nextPos, strlen(self::FILL_IN_PLACEHOLDER));
$nextPos = strpos($replacedDescription, self::FILL_IN_PLACEHOLDER, $nextPos + strlen($placeholderReplacements[$index]));
$index += 1;
}
return $replacedDescription;
}
}