pull/6058/merge
christianbeeznest 7 months ago committed by GitHub
commit 2f95cd6117
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 62
      public/main/gradebook/lib/be/category.class.php
  2. 12
      public/main/gradebook/lib/gradebook_data_generator.class.php
  3. 15
      src/CoreBundle/Entity/GradebookEvaluation.php
  4. 15
      src/CoreBundle/Entity/GradebookLink.php
  5. 6
      src/CoreBundle/Framework/Container.php
  6. 37
      src/CoreBundle/Migrations/Schema/V200/Version20250120103800.php
  7. 19
      src/CoreBundle/Repository/GradebookResultRepository.php

@ -4,6 +4,7 @@
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\GradebookCategory;
use Chamilo\CoreBundle\Framework\Container;
use ChamiloSession as Session;
use Chamilo\CoreBundle\Component\Utils\ActionIcon;
@ -2002,26 +2003,21 @@ class Category implements GradebookItem
/**
* Generates a certificate for this user if everything matches.
*
* @param int $user_id
* @param bool $sendNotification
* @param bool $skipGenerationIfExists
*
* @return array
*/
public static function generateUserCertificate(
GradebookCategory $category,
$user_id,
$sendNotification = false,
$skipGenerationIfExists = false
int $user_id,
bool $sendNotification = false,
bool $skipGenerationIfExists = false
) {
$user_id = (int) $user_id;
$categoryId = $category->getId();
$sessionId = $category->getSession() ? $category->getSession()->getId() : 0;
$courseId = $category->getCourse()->getId();
$userFinishedCourse = self::userFinishedCourse($user_id, $category, true);
if (!$userFinishedCourse) {
return false;
// check if all min_score requirements are met
if (!self::userMeetsMinimumScores($user_id, $category)) {
return false; // Do not generate certificate if the user does not meet all min_score criteria
}
$skillToolEnabled = SkillModel::hasAccessToUserSkill(api_get_user_id(), $user_id);
@ -2034,7 +2030,7 @@ class Category implements GradebookItem
$userHasSkills = !empty($userSkills);
}
// Block certification links depending on gradebook configuration (generate certifications)
// If certificate generation is disabled, return only badge link (if available)
if (empty($category->getGenerateCertificates())) {
if ($userHasSkills) {
return [
@ -2050,6 +2046,7 @@ class Category implements GradebookItem
}
$my_certificate = GradebookUtils::get_certificate_by_user_id($categoryId, $user_id);
// If certificate already exists and we should skip regeneration, return false
if ($skipGenerationIfExists && !empty($my_certificate)) {
return false;
}
@ -2089,7 +2086,7 @@ class Category implements GradebookItem
$fileWasGenerated = $certificate_obj->isHtmlFileGenerated();
// Fix when using custom certificate BT#15937
// Fix when using a custom certificate plugin
if ('true' === api_get_plugin_setting('customcertificate', 'enable_plugin_customcertificate')) {
$infoCertificate = CustomCertificatePlugin::getCertificateData($my_certificate['id'], $user_id);
if (!empty($infoCertificate)) {
@ -2135,6 +2132,43 @@ class Category implements GradebookItem
return $html;
}
return false;
}
/**
* Checks whether the user has met the minimum score (`min_score`) in all required evaluations.
*/
public static function userMeetsMinimumScores(int $userId, GradebookCategory $category): bool
{
$evaluations = $category->getEvaluations();
foreach ($evaluations as $evaluation) {
$minScore = $evaluation->getMinScore();
if ($minScore !== null) {
$userScore = self::getUserScoreForEvaluation($userId, $evaluation->getId());
if ($userScore === null || $userScore < $minScore) {
return false; // If at least one evaluation is below `min_score`, return false
}
}
}
return true;
}
/**
* Retrieves the score of a user for a specific evaluation using the GradebookResult repository.
*/
public static function getUserScoreForEvaluation(int $userId, int $evaluationId): ?float
{
$gradebookResultRepo = Container::getGradebookResultRepository();
$gradebookResult = $gradebookResultRepo->findOneBy([
'user' => $userId,
'evaluation' => $evaluationId,
]);
return $gradebookResult ? $gradebookResult->getScore() : null;
}
/**

@ -714,6 +714,13 @@ class GradebookDataGenerator
$scoreDisplay = ScoreDisplay::instance();
$score = $item->calc_score($userId);
$model = ExerciseLib::getCourseScoreModel();
// Get min_score from entity (only if available)
$minScore = null;
if (isset($item->entity) && method_exists($item->entity, 'getMinScore')) {
$minScore = $item->entity->getMinScore();
}
if (!empty($score)) {
switch ($item->get_item_type()) {
// category
@ -799,6 +806,11 @@ class GradebookDataGenerator
);
}
// If minScore exists and user score is lower, mark in red
if (!is_null($minScore) && $score[0] < $minScore) {
$display = "<span class='text-danger font-bold'>$display</span>";
}
return [
'display' => $display,
'score' => $score,

@ -75,6 +75,9 @@ class GradebookEvaluation
#[ORM\Column(name: 'user_score_list', type: 'array', nullable: true)]
protected ?array $userScoreList = null;
#[ORM\Column(name: 'min_score', type: 'float', precision: 6, scale: 2, nullable: true)]
protected ?float $minScore = null;
public function __construct()
{
$this->locked = 0;
@ -308,4 +311,16 @@ class GradebookEvaluation
return $this;
}
public function getMinScore(): ?float
{
return $this->minScore;
}
public function setMinScore(?float $minScore): self
{
$this->minScore = $minScore;
return $this;
}
}

@ -67,6 +67,9 @@ class GradebookLink
#[ORM\Column(name: 'user_score_list', type: 'array', nullable: true)]
protected ?array $userScoreList = null;
#[ORM\Column(name: 'min_score', type: 'float', precision: 6, scale: 2, nullable: true)]
protected ?float $minScore = null;
public function __construct()
{
$this->locked = 0;
@ -260,4 +263,16 @@ class GradebookLink
return $this;
}
public function getMinScore(): ?float
{
return $this->minScore;
}
public function setMinScore(?float $minScore): self
{
$this->minScore = $minScore;
return $this;
}
}

@ -15,6 +15,7 @@ use Chamilo\CoreBundle\Repository\ExtraFieldOptionsRepository;
use Chamilo\CoreBundle\Repository\ExtraFieldRepository;
use Chamilo\CoreBundle\Repository\GradeBookCategoryRepository;
use Chamilo\CoreBundle\Repository\GradebookCertificateRepository;
use Chamilo\CoreBundle\Repository\GradebookResultRepository;
use Chamilo\CoreBundle\Repository\LanguageRepository;
use Chamilo\CoreBundle\Repository\LegalRepository;
use Chamilo\CoreBundle\Repository\MessageRepository;
@ -363,6 +364,11 @@ class Container
return self::$container->get(GradebookCertificateRepository::class);
}
public static function getGradebookResultRepository(): GradebookResultRepository
{
return self::$container->get(GradebookResultRepository::class);
}
public static function getGroupRepository(): CGroupRepository
{
return self::$container->get(CGroupRepository::class);

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
use Doctrine\DBAL\Schema\Schema;
final class Version20250120103800 extends AbstractMigrationChamilo
{
public function getDescription(): string
{
return 'Add min_score column to gradebook_evaluation and gradebook_link tables';
}
public function up(Schema $schema): void
{
$this->addSql('
ALTER TABLE gradebook_evaluation
ADD COLUMN min_score FLOAT DEFAULT NULL
');
$this->addSql('
ALTER TABLE gradebook_link
ADD COLUMN min_score FLOAT DEFAULT NULL
');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE gradebook_evaluation DROP COLUMN min_score');
$this->addSql('ALTER TABLE gradebook_link DROP COLUMN min_score');
}
}

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Repository;
use Chamilo\CoreBundle\Entity\GradebookResult;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class GradebookResultRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, GradebookResult::class);
}
}
Loading…
Cancel
Save