Merge pull request #4272 from AngelFQC/BT19898

Exercise: Add exercise_embeddable_extra_types configuration setting
pull/4275/head
Nicolas Ducoulombier 4 years ago committed by GitHub
commit dd92bc9866
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 84
      main/inc/lib/exercise.lib.php
  2. 25
      main/install/configuration.dist.php
  3. 2
      src/Chamilo/CourseBundle/Entity/CQuizQuestion.php
  4. 53
      src/Chamilo/CourseBundle/Entity/Repository/CQuizQuestionRepository.php

@ -4,6 +4,7 @@
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
use Chamilo\CoreBundle\Entity\TrackEExercises;
use Chamilo\CourseBundle\Entity\CQuizQuestion;
use ChamiloSession as Session;
/**
@ -5999,20 +6000,57 @@ EOT;
return ($answeredQuestionsCount + $numberOfQuestions) > $questionsLimitPerDay;
}
/**
* By default, allowed types are unique-answer (and image) or multiple-answer questions.
* Types can be extended by the configuration setting "exercise_embeddable_extra_types".
*/
public static function getEmbeddableTypes(): array
{
$allowedTypes = [
UNIQUE_ANSWER,
MULTIPLE_ANSWER,
FILL_IN_BLANKS,
MATCHING,
FREE_ANSWER,
MULTIPLE_ANSWER_COMBINATION,
UNIQUE_ANSWER_NO_OPTION,
MULTIPLE_ANSWER_TRUE_FALSE,
MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE,
ORAL_EXPRESSION,
GLOBAL_MULTIPLE_ANSWER,
CALCULATED_ANSWER,
UNIQUE_ANSWER_IMAGE,
READING_COMPREHENSION,
MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY,
UPLOAD_ANSWER,
];
$defaultTypes = [UNIQUE_ANSWER, MULTIPLE_ANSWER, UNIQUE_ANSWER_IMAGE];
$types = $defaultTypes;
$extraTypes = api_get_configuration_value('exercise_embeddable_extra_types');
if (false !== $extraTypes && !empty($extraTypes['types'])) {
$types = array_merge($defaultTypes, $extraTypes['types']);
}
return array_filter(
array_unique($types),
function ($type) use ($allowedTypes) {
return in_array($type, $allowedTypes);
}
);
}
/**
* Check if an exercise complies with the requirements to be embedded in the mobile app or a video.
* By making sure it is set on one question per page and it only contains unique-answer or multiple-answer questions
* or unique-answer image. And that the exam does not have immediate feedback.
* By making sure it is set on one question per page, and that the exam does not have immediate feedback,
* and it only contains allowed types.
*
* @param array $exercise Exercise info
*
* @throws \Doctrine\ORM\Query\QueryException
*
* @return bool
* @see Exercise::getEmbeddableTypes()
*/
public static function isQuizEmbeddable(array $exercise)
public static function isQuizEmbeddable(array $exercise): bool
{
$em = Database::getManager();
$exercise['iid'] = isset($exercise['iid']) ? (int) $exercise['iid'] : 0;
if (ONE_PER_PAGE != $exercise['type'] ||
in_array($exercise['feedback_type'], [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP])
@ -6020,32 +6058,12 @@ EOT;
return false;
}
$countAll = $em
->createQuery('SELECT COUNT(qq)
FROM ChamiloCourseBundle:CQuizQuestion qq
INNER JOIN ChamiloCourseBundle:CQuizRelQuestion qrq
WITH qq.iid = qrq.questionId
WHERE qrq.exerciceId = :id'
)
->setParameter('id', $exercise['iid'])
->getSingleScalarResult();
$questionRepository = Database::getManager()->getRepository(CQuizQuestion::class);
$countOfAllowed = $em
->createQuery('SELECT COUNT(qq)
FROM ChamiloCourseBundle:CQuizQuestion qq
INNER JOIN ChamiloCourseBundle:CQuizRelQuestion qrq
WITH qq.iid = qrq.questionId
WHERE qrq.exerciceId = :id AND qq.type IN (:types)'
)
->setParameters(
[
'id' => $exercise['iid'],
'types' => [UNIQUE_ANSWER, MULTIPLE_ANSWER, UNIQUE_ANSWER_IMAGE],
]
)
->getSingleScalarResult();
$countAll = $questionRepository->countQuestionsInExercise($exercise['iid']);
$countAllowed = $questionRepository->countEmbeddableQuestionsInExercise($exercise['iid']);
return $countAll === $countOfAllowed;
return $countAll === $countAllowed;
}
/**

@ -729,6 +729,31 @@ $_configuration['send_all_emails_to'] = [
//$_configuration['hide_user_info_in_quiz_result'] = false;
// Show the username field in exercise results report
//$_configuration['exercise_attempts_report_show_username'] = false;
// Allow extends allowed question types for embeddable exercises.
/* By default, only the following question types are allowed: 1, 2, 17
Add this types to allow them in embeddable exercises:
1 = Multiple choice
2 = Multiple answers
3 = Fill blanks or form
4 = Matching
5 = Open question
9 = Exact Selection
10 = Unique answer with unknown
11 = Multiple answer true/false/don't know
12 = Combination true/false/don't know
13 = Oral expression
14 = Global multiple answer
16 = Calculated question
17 = Unique answer image
21 = Reading comprehension
22 = Multiple answer true/false/degree of certainty
23 = Upload answer
*/
/*
$_configuration['exercise_embeddable_extra_types'] = [
'types' => [],
];
*/
// Score model
// Allow to convert a score into a text/color label

@ -15,7 +15,7 @@ use Doctrine\ORM\Mapping as ORM;
* @ORM\Index(name="position", columns={"position"})
* }
* )
* @ORM\Entity()
* @ORM\Entity(repositoryClass="Chamilo\CourseBundle\Entity\Repository\CQuizQuestionRepository")
*/
class CQuizQuestion
{

@ -0,0 +1,53 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\CourseBundle\Entity\Repository;
use Chamilo\CourseBundle\Entity\CQuizRelQuestion;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Doctrine\ORM\Query\Expr\Join;
class CQuizQuestionRepository extends EntityRepository
{
/**
* @throws NonUniqueResultException
* @throws NoResultException
*/
public function countQuestionsInExercise(int $exerciseId): int
{
$query = $this->createQueryBuilder('qq')
->select('COUNT(qq)')
->innerJoin(CQuizRelQuestion::class, 'qrq', Join::WITH, 'qq.iid = qrq.questionId')
->where('qrq.exerciceId = :id')
->setParameters(['id' => $exerciseId])
->getQuery()
;
return (int) $query->getSingleScalarResult();
}
/**
* @throws NonUniqueResultException
* @throws NoResultException
*/
public function countEmbeddableQuestionsInExercise(int $exerciseId): int
{
$query = $this->createQueryBuilder('qq')
->select('COUNT(qq)')
->innerJoin(CQuizRelQuestion::class, 'qrq', Join::WITH, 'qq.iid = qrq.questionId')
->where('qrq.exerciceId = :id AND qq.type IN (:types)')
->setParameters(
[
'id' => $exerciseId,
'types' => \ExerciseLib::getEmbeddableTypes(),
]
)
->getQuery()
;
return (int) $query->getSingleScalarResult();
}
}
Loading…
Cancel
Save