Merge branch 'master' of github.com:chamilo/chamilo-lms

pull/4988/head
Yannick Warnier 1 year ago
commit 2de8ba667e
  1. 2
      public/main/inc/lib/certificate.lib.php
  2. 4
      public/main/inc/lib/tracking.lib.php
  3. 9
      public/main/my_space/myStudents.php
  4. 16
      public/main/template/default/gradebook/custom_certificate.html.twig
  5. 6
      src/CoreBundle/Command/UpdateVueTranslations.php
  6. 8
      src/CoreBundle/Controller/Api/CreateSocialPostAttachmentAction.php
  7. 2
      src/CoreBundle/Controller/Api/SocialPostAttachmentsController.php
  8. 4
      src/CoreBundle/Entity/SocialPost.php
  9. 2
      src/CoreBundle/Migrations/Schema/V200/Version20231022124700.php
  10. 4
      src/CoreBundle/Migrations/Schema/V200/Version20231026221100.php
  11. 12
      src/CoreBundle/Migrations/Schema/V200/Version20231026231100.php
  12. 8
      src/CoreBundle/Migrations/Schema/V200/Version20231031204300.php
  13. 28
      src/CoreBundle/State/CategorizedExerciseResultStateProvider.php
  14. 2
      src/CourseBundle/Entity/CLp.php
  15. 3
      translations/messages.fr.po

@ -803,7 +803,7 @@ class Certificate extends Model
$tplContent->assign(
'certificate_generated_date_no_time',
api_get_local_time(
$myCertificate['created_at'],
$myCertificate['created_at'] ?? null,
null,
null,
false,

@ -3265,13 +3265,13 @@ class Tracking
// Compose a filter based on optional learning paths list given
$condition_lp = '';
if (count($lp_ids) > 0) {
$condition_lp = " iid IN(".implode(',', $lp_ids).") ";
$condition_lp = " AND iid IN(".implode(',', $lp_ids).") ";
}
// Check the real number of LPs corresponding to the filter in the
// database (and if no list was given, get them all)
$sql = "SELECT DISTINCT(iid) FROM $lpTable
WHERE $condition_lp";
WHERE 1=1 $condition_lp";
$result = Database::query($sql);
$session_condition = api_get_session_condition($sessionId);

@ -550,12 +550,11 @@ switch ($action) {
if ($myCertificate) {
$certificate = new Certificate($myCertificate['id'], $studentId);
$certificate->deleteCertificate(true);
// Create new one
$certificate = new Certificate(0, $studentId);
$certificate->generatePdfFromCustomCertificate();
exit;
}
break;
// Create new one
$certificate = new Certificate(0, $studentId);
$certificate->generatePdfFromCustomCertificate();
exit;
case 'send_legal':
$isBoss = UserManager::userIsBossOfStudent(api_get_user_id(), $studentId);
if ($isBoss || api_is_platform_admin()) {

@ -7,11 +7,11 @@
<body>
<table border="0" bgcolor="#92c647" cellpadding="0" cellspacing="0" align="center" width="80%">
<tr>
<td bgcolor="#92c647"><img src="{{ _p.web_css_theme }}images/header_top.png" style="display: block;"></td>
<td bgcolor="#92c647"><img src="{{ url('index') ~ '/build/css/themes/chamilo/images/header_top.png' }}" style="display: block;"></td>
</tr>
<tr>
<td>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="#92c647" width=58 height=91>
<img src="{{ _p.web_css_theme }}images/lado-b.png" style="display:block;">
@ -20,7 +20,7 @@
{{ 'CertificateHeader' | get_lang }}
</td>
<td bgcolor="#92c647" width=58 height=91>
<img src="{{ _p.web_css_theme }}images/lado-header.png" style="display:block;">
<img src="{{ url('index') ~ '/build/css/themes/chamilo/images/lado-header.png' }}" style="display:block;">
</td>
</tr>
</table>
@ -30,13 +30,13 @@
<td>
<table bgcolor="#FFFFFF" border="0" cellspacing="0" cellpadding="0" width="100%" height=900>
<tr>
<td bgcolor="#92c647" height=755><img src="{{ _p.web_css_theme }}images/lado-a.png" style="display:block;"></td>
<td bgcolor="#92c647" height=755><img src="{{ url('index') ~ '/build/css/themes/chamilo/images/lado-a.png' }}" style="display:block;"></td>
<td height=755 style="font-family:CourierSans-Light; line-height: 22px; color:#40ad49; padding: 40px; font-size: 18px;" valign="top">
<h3 style="color: #672290; font-size: 24px;">
{{ complete_name }}
</h3>
<p style="font-size: 16px;">
{{ 'UserHasParticipateDansDePlatformeXTheContratDateXCertificateDateXTimeX' | get_lang | format(_s.site_name, certificate_generated_date_no_time, terms_validation_date_no_time, time_in_platform_in_hours)}}
{{ 'User has participate dans de platforme %s the contrat date %s certificate date %s time %s' | trans | format(_s.site_name, certificate_generated_date_no_time, terms_validation_date_no_time, time_in_platform_in_hours)}}
</p>
<br />
<p style="font-size: 16px;">{{ 'ThisTrainingHasXHours' | get_lang | format(time_in_platform_in_hours)}}</p><br />
@ -63,7 +63,7 @@
<br />
</td>
<td height=755 bgcolor="#92c647">
<img src="{{ _p.web_css_theme }}images/lado-b.png" style="display:block;">
<img src="{{ url('index') ~ '/build/css/themes/chamilo/images/lado-b.png' }}" style="display:block;">
</td>
</tr>
</table>
@ -73,11 +73,11 @@
<td>
<table border="0" cellspacing="0" cellpadding="0" width="100%" height=91>
<tr>
<td bgcolor="#92c647" width=58 height=91><img src="{{ _p.web_css_theme }}images/lado-b.png" style="display:block;"></td>
<td bgcolor="#92c647" width=58 height=91><img src="{{ url('index') ~ '/build/css/themes/chamilo/images/lado-b.png' }}" style="display:block;"></td>
<td bgcolor="#92c647" width=500 height=91 style="font-family:CourierSans-Light; line-height: 18px; color:#FFF;">
{{ 'CertificateFooter' | get_lang }}
</td>
<td bgcolor="#92c647" width=245 height=91><img src="{{ _p.web_css_theme }}images/lado-footer.png" style="display:block;"></td>
<td bgcolor="#92c647" width=245 height=91><img src="{{ url('index') ~ '/build/css/themes/chamilo/images/lado-footer.png' }}" style="display:block;"></td>
</tr>
</table>
</td>

@ -84,7 +84,7 @@ class UpdateVueTranslations extends Command
}
/**
* Replace specifiers in a string to allow rendering them by i18n
* Replace specifiers in a string to allow rendering them by i18n.
*
* <code>
* $txt = "Bonjour %s. Je m’appelle %s";
@ -99,12 +99,12 @@ class UpdateVueTranslations extends Command
$type = $matches[1];
return match ($type) {
"s", "d", "f" => "{".$count++."}",
's', 'd', 'f' => '{'.$count++.'}',
default => $matches[0],
};
};
$pattern = "/%([sdf])/";
$pattern = '/%([sdf])/';
return preg_replace_callback($pattern, $replace, $text);
}

@ -10,6 +10,8 @@ use Chamilo\CoreBundle\Entity\SocialPost;
use Chamilo\CoreBundle\Entity\SocialPostAttachment;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Repository\Node\SocialPostAttachmentRepository;
use DateTime;
use DateTimeZone;
use Doctrine\ORM\EntityManager;
use Exception;
use Symfony\Component\HttpFoundation\File\UploadedFile;
@ -28,12 +30,12 @@ class CreateSocialPostAttachmentAction extends BaseResourceFileAction
$socialPostId = $request->request->get('messageId');
if (!$uploadedFile instanceof UploadedFile) {
throw new \Exception('No file uploaded');
throw new Exception('No file uploaded');
}
$socialPost = $em->getRepository(SocialPost::class)->find($socialPostId);
if (!$socialPost) {
throw new \Exception('No social post found');
throw new Exception('No social post found');
}
/** @var User $currentUser */
@ -44,7 +46,7 @@ class CreateSocialPostAttachmentAction extends BaseResourceFileAction
$attachment->setFilename($uploadedFile->getClientOriginalName());
$attachment->setSize($uploadedFile->getSize());
$attachment->setInsertUserId($currentUser->getId());
$attachment->setInsertDateTime(new \DateTime('now', new \DateTimeZone('UTC')));
$attachment->setInsertDateTime(new DateTime('now', new DateTimeZone('UTC')));
$attachment->setParent($currentUser);
$attachment->addUserLink($currentUser);

@ -8,13 +8,11 @@ use Chamilo\CoreBundle\Entity\SocialPost;
use Chamilo\CoreBundle\Entity\SocialPostAttachment;
use Chamilo\CoreBundle\Repository\Node\SocialPostAttachmentRepository;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Security\Core\Security;
class SocialPostAttachmentsController extends BaseResourceFileAction
{
public function __invoke(SocialPost $socialPost, EntityManager $em, Security $security, SocialPostAttachmentRepository $attachmentRepo): JsonResponse
{
$attachments = $em->getRepository(SocialPostAttachment::class)->findBy(['socialPost' => $socialPost->getId()]);

@ -147,8 +147,8 @@ class SocialPost
#[ORM\OneToMany(
targetEntity: SocialPostAttachment::class,
mappedBy: "socialPost",
cascade: ["persist", "remove"],
mappedBy: 'socialPost',
cascade: ['persist', 'remove'],
orphanRemoval: true
)]
private Collection $attachments;

@ -453,7 +453,7 @@ final class Version20231022124700 extends AbstractMigrationChamilo
// Reconstructing the URL with the new courseId and adjusted parameters.
return $matches[1].'?cid='.$courseId.'&sid='.$matches[5].'&gid='.$matches[7].$remainingParams;
// Return the new URL.
// Return the new URL.
},
$htmlContent
);

@ -20,8 +20,8 @@ class Version20231026221100 extends AbstractMigrationChamilo
{
if (false === $schema->hasTable('social_post_attachments')) {
$this->addSql("CREATE TABLE social_post_attachments (id INT AUTO_INCREMENT NOT NULL, social_post_id BIGINT DEFAULT NULL, resource_node_id BIGINT DEFAULT NULL, path VARCHAR(255) NOT NULL, filename LONGTEXT NOT NULL, size INT NOT NULL, sys_insert_user_id INT NOT NULL, sys_insert_datetime DATETIME NOT NULL COMMENT '(DC2Type:datetime)', sys_lastedit_user_id INT DEFAULT NULL, sys_lastedit_datetime DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime)', INDEX IDX_DF2A8F34C4F2D6B1 (social_post_id), UNIQUE INDEX UNIQ_DF2A8F341BAD783F (resource_node_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC;");
$this->addSql("ALTER TABLE social_post_attachments ADD CONSTRAINT FK_DF2A8F34C4F2D6B1 FOREIGN KEY (social_post_id) REFERENCES social_post (id) ON DELETE CASCADE;");
$this->addSql("ALTER TABLE social_post_attachments ADD CONSTRAINT FK_DF2A8F341BAD783F FOREIGN KEY (resource_node_id) REFERENCES resource_node (id) ON DELETE CASCADE;");
$this->addSql('ALTER TABLE social_post_attachments ADD CONSTRAINT FK_DF2A8F34C4F2D6B1 FOREIGN KEY (social_post_id) REFERENCES social_post (id) ON DELETE CASCADE;');
$this->addSql('ALTER TABLE social_post_attachments ADD CONSTRAINT FK_DF2A8F341BAD783F FOREIGN KEY (resource_node_id) REFERENCES resource_node (id) ON DELETE CASCADE;');
}
}
}

@ -11,6 +11,8 @@ use Chamilo\CoreBundle\Entity\SocialPostAttachment;
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
use Chamilo\CoreBundle\Repository\Node\SocialPostAttachmentRepository;
use Chamilo\CoreBundle\Repository\Node\UserRepository;
use DateTime;
use DateTimeZone;
use DirectoryIterator;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Schema\Schema;
@ -39,12 +41,14 @@ final class Version20231026231100 extends AbstractMigrationChamilo
$sub = $em->createQueryBuilder();
$sub->select('sp.id')
->from('Chamilo\CoreBundle\Entity\SocialPost', 'sp');
->from('Chamilo\CoreBundle\Entity\SocialPost', 'sp')
;
$qb = $em->createQueryBuilder();
$qb->select('ma')
->from('Chamilo\CoreBundle\Entity\MessageAttachment', 'ma')
->where($qb->expr()->in('ma.message', $sub->getDQL()));
->where($qb->expr()->in('ma.message', $sub->getDQL()))
;
$query = $qb->getQuery();
$messageAttachments = $query->getResult();
@ -73,7 +77,7 @@ final class Version20231026231100 extends AbstractMigrationChamilo
$attachment->setFilename($uploadFile->getClientOriginalName());
$attachment->setSize($uploadFile->getSize());
$attachment->setInsertUserId($sender->getId());
$attachment->setInsertDateTime(new \DateTime('now', new \DateTimeZone('UTC')));
$attachment->setInsertDateTime(new DateTime('now', new DateTimeZone('UTC')));
$attachment->setParent($sender);
$attachment->addUserLink($sender);
$attachment->setCreator($sender);
@ -102,7 +106,7 @@ final class Version20231026231100 extends AbstractMigrationChamilo
if ($fileInfo->isDir()) {
$result = $this->findFileRecursively($filePath, $targetFile);
if ($result !== null) {
if (null !== $result) {
return $result;
}
} else {

@ -13,13 +13,13 @@ final class Version20231031204300 extends AbstractMigrationChamilo
{
public function getDescription(): string
{
return "Allow message sender to be null";
return 'Allow message sender to be null';
}
public function up(Schema $schema): void
{
$this->addSql("ALTER TABLE message DROP FOREIGN KEY FK_B6BD307FF6C43E79");
$this->addSql("ALTER TABLE message CHANGE user_sender_id user_sender_id INT DEFAULT NULL");
$this->addSql("ALTER TABLE message ADD CONSTRAINT FK_B6BD307FF6C43E79 FOREIGN KEY (user_sender_id) REFERENCES user (id) ON DELETE SET NULL");
$this->addSql('ALTER TABLE message DROP FOREIGN KEY FK_B6BD307FF6C43E79');
$this->addSql('ALTER TABLE message CHANGE user_sender_id user_sender_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE message ADD CONSTRAINT FK_B6BD307FF6C43E79 FOREIGN KEY (user_sender_id) REFERENCES user (id) ON DELETE SET NULL');
}
}

@ -21,6 +21,7 @@ use Question;
use QuestionOptionsEvaluationPlugin;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use TestCategory;
class CategorizedExerciseResultStateProvider implements ProviderInterface
@ -55,7 +56,7 @@ class CategorizedExerciseResultStateProvider implements ProviderInterface
ob_start();
$categoryList = self::displayQuestionListByAttempt(
$categoryList = $this->displayQuestionListByAttempt(
$objExercise,
$trackExercise
);
@ -70,7 +71,7 @@ class CategorizedExerciseResultStateProvider implements ProviderInterface
/**
* @throws Exception
*/
private static function displayQuestionListByAttempt(
private function displayQuestionListByAttempt(
Exercise $objExercise,
TrackEExercise $exerciseTracking
): array {
@ -317,8 +318,12 @@ class CategorizedExerciseResultStateProvider implements ProviderInterface
}
}
if ($this->isAllowedToSeeResults()) {
$show_results = true;
}
if (!$show_results && !$show_only_score && RESULT_DISABLE_RADAR !== $objExercise->results_disabled) {
throw new Exception(get_lang('Not allowed'));
throw new AccessDeniedException();
}
// Adding total
@ -332,6 +337,10 @@ class CategorizedExerciseResultStateProvider implements ProviderInterface
private static function getStatsTableByAttempt(Exercise $exercise, array $category_list = []): array
{
if (empty($category_list)) {
return [];
}
$hide = (int) $exercise->getPageConfigurationAttribute('hide_category_table');
if (1 === $hide) {
@ -375,7 +384,7 @@ class CategorizedExerciseResultStateProvider implements ProviderInterface
];
}
if ($category_list['none']['score'] > 0) {
if (isset($category_list['none']) && $category_list['none']['score'] > 0) {
$absolute = ExerciseLib::show_score(
$category_list['none']['score'],
$category_list['none']['total'],
@ -417,4 +426,15 @@ class CategorizedExerciseResultStateProvider implements ProviderInterface
return $stats;
}
private function isAllowedToSeeResults(): bool
{
$isStudentBoss = $this->security->isGranted('ROLE_STUDENT_BOSS');
$isHRM = $this->security->isGranted('ROLE_RRHH');
$isSessionAdmin = $this->security->isGranted('ROLE_SESSION_MANAGER');
$isCourseTutor = $this->security->isGranted('ROLE_CURRENT_COURSE_SESSION_TEACHER');
$isAllowedToEdit = api_is_allowed_to_edit(null, true);
return $isAllowedToEdit || $isCourseTutor || $isSessionAdmin || $isHRM || $isStudentBoss;
}
}

@ -199,8 +199,6 @@ class CLp extends AbstractResource implements ResourceInterface, ResourceShowCou
/**
* Get lpType.
*
* @return int
*/
public function getLpType(): int
{

@ -24160,3 +24160,6 @@ msgstr "À venir"
msgid "Past session tab"
msgstr "Terminées"
msgid "User has participate dans de platforme %s the contrat date %s certificate date %s time %s"
msgstr "a participé à une formation en ligne sur la plateforme %s de l’Office franco-allemand pour la Jeunesse. <br>Du <span style=\"color: #672290;\">%s</span> au <span style=\"color: #672290;\">%s</span>.<br><br>Cette formation avait pour objectif la préparation linguistique et interculturelle à une mobilité dans un cadre de formation professionnelle."

Loading…
Cancel
Save