From e3bcf4c8b3ddeb3d35048e6297a4f6e72671b919 Mon Sep 17 00:00:00 2001 From: christianbeeznst Date: Fri, 1 Mar 2024 13:36:48 -0500 Subject: [PATCH 1/6] System template: Improve asset file naming and directory structure - refs #3804 --- config/packages/vich_uploader.yaml | 2 +- .../Component/Utils/AssetDirectoryNamer.php | 14 +++++- .../Component/Utils/AssetFileNameNamer.php | 48 +++++++++++++++++++ src/CoreBundle/Resources/config/services.yml | 14 +++++- 4 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/CoreBundle/Component/Utils/AssetFileNameNamer.php diff --git a/config/packages/vich_uploader.yaml b/config/packages/vich_uploader.yaml index c883003a0d..bb815c2cfe 100644 --- a/config/packages/vich_uploader.yaml +++ b/config/packages/vich_uploader.yaml @@ -16,7 +16,7 @@ vich_uploader: assets: uri_prefix: '' upload_destination: oneup_flysystem.asset_filesystem - namer: Vich\UploaderBundle\Naming\SmartUniqueNamer + namer: Chamilo\CoreBundle\Component\Utils\AssetFileNameNamer directory_namer: service: Chamilo\CoreBundle\Component\Utils\AssetDirectoryNamer options: {property: 'category'} diff --git a/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php b/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php index aa869d8cbd..4e89df784a 100644 --- a/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php +++ b/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php @@ -7,7 +7,9 @@ declare(strict_types=1); namespace Chamilo\CoreBundle\Component\Utils; use Chamilo\CoreBundle\Entity\Asset; +use Chamilo\CoreBundle\Repository\AssetRepository; use InvalidArgumentException; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Vich\UploaderBundle\Mapping\PropertyMapping; @@ -17,13 +19,17 @@ use Vich\UploaderBundle\Naming\DirectoryNamerInterface; class AssetDirectoryNamer implements DirectoryNamerInterface, ConfigurableInterface { protected PropertyAccessorInterface $propertyAccessor; + private ?AssetRepository $assetRepository = null; + private ?RequestStack $requestStack = null; private string $propertyPath; private int $charsPerDir = 2; private int $dirs = 1; - public function __construct(?PropertyAccessorInterface $propertyAccessor) + public function __construct(?PropertyAccessorInterface $propertyAccessor, ?AssetRepository $assetRepository = null, ?RequestStack $requestStack= null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); + $this->assetRepository = $assetRepository; + $this->requestStack = $requestStack; } /** @@ -53,6 +59,12 @@ class AssetDirectoryNamer implements DirectoryNamerInterface, ConfigurableInterf $fileName = $mapping->getFileName($object); $category = $this->propertyAccessor->getValue($object, $this->propertyPath); + if ($object->getCategory() === Asset::SYSTEM_TEMPLATE) { + return 'system_templates'; + } elseif ($object->getCategory() === Asset::TEMPLATE) { + return 'doc_templates'; + } + $parts[] = $category; if (Asset::EXTRA_FIELD === $category) { diff --git a/src/CoreBundle/Component/Utils/AssetFileNameNamer.php b/src/CoreBundle/Component/Utils/AssetFileNameNamer.php new file mode 100644 index 0000000000..0762fc4676 --- /dev/null +++ b/src/CoreBundle/Component/Utils/AssetFileNameNamer.php @@ -0,0 +1,48 @@ +requestStack = $requestStack; + $this->translator = $translator; + } + + public function name($object, PropertyMapping $mapping): string + { + $category = $object->getCategory(); + + if (in_array($category, [Asset::TEMPLATE, Asset::SYSTEM_TEMPLATE])) { + $request = $this->requestStack->getCurrentRequest(); + if ($request) { + $templateId = $object->getId(); + $templateTitle = $request->get('title', 'default-title'); + $titleSlug = $this->slugify($templateTitle); + $extension = pathinfo($mapping->getFileName($object), PATHINFO_EXTENSION); + return sprintf('%s-%s.%s', $templateId, $titleSlug, $extension); + } + } + + return $mapping->getFileName($object); + } + + private function slugify(string $text): string + { + return strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $text), '-')); + } +} diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index c7a97f8ffe..5527af0a51 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -45,7 +45,19 @@ services: Chamilo\CoreBundle\Component\Editor\CkEditor\CkEditor: arguments: ['@translator', '@router'] - Chamilo\CoreBundle\Component\Utils\AssetDirectoryNamer: ~ + Chamilo\CoreBundle\Component\Utils\AssetDirectoryNamer: + arguments: + - '@property_accessor' + - '@Chamilo\CoreBundle\Repository\AssetRepository' + - '@request_stack' + + Chamilo\CoreBundle\Component\Utils\AssetFileNameNamer: + arguments: + - '@request_stack' + - '@translator' + tags: + - { name: vich_uploader.namer, mapping: assets } + Chamilo\CoreBundle\Component\Utils\CreateDefaultPages: ~ Chamilo\CoreBundle\Component\Utils\NameConvention: ~ Chamilo\CoreBundle\Component\Utils\Glide: From 625f2971084dbef6a3df4a7a7cd56c117f68fa97 Mon Sep 17 00:00:00 2001 From: Yannick Warnier Date: Sat, 2 Mar 2024 01:43:27 +0100 Subject: [PATCH 2/6] Internal: Fix parameter types for CourseManager::get_user_list_from_course_code() calls + remove unneeded algorithmic complexity --- public/main/inc/ajax/course.ajax.php | 42 +++++++++++++--------------- public/main/inc/lib/course.lib.php | 2 +- public/main/user/user.php | 14 +++++++++- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/public/main/inc/ajax/course.ajax.php b/public/main/inc/ajax/course.ajax.php index 6c2cec8a7e..d397f3983a 100644 --- a/public/main/inc/ajax/course.ajax.php +++ b/public/main/inc/ajax/course.ajax.php @@ -67,32 +67,30 @@ switch ($action) { } $courseList = []; - if (!empty($list)) { - foreach ($list as $course) { - $courseInfo = api_get_course_info_by_id($course['real_id']); - $sessionId = 0; - if (isset($course['session_id']) && !empty($course['session_id'])) { - $sessionId = $course['session_id']; - } - - $sessionName = ''; - if (isset($course['session_name']) && !empty($course['session_name'])) { - $sessionName = ' ('.$course['session_name'].')'; - } + foreach ($list as $course) { + $courseInfo = api_get_course_info_by_id($course['real_id']); + $sessionId = 0; + if (!empty($course['session_id'])) { + $sessionId = $course['session_id']; + } - // Skip current course/course session - if ($currentCourseId == $courseInfo['real_id'] && $sessionId == $currentSessionId) { - continue; - } + $sessionName = ''; + if (!empty($course['session_name'])) { + $sessionName = ' ('.$course['session_name'].')'; + } - $courseList['items'][] = [ - 'id' => $courseInfo['real_id'].'_'.$sessionId, - 'text' => $courseInfo['title'].$sessionName, - ]; + // Skip current course/course session + if ($currentCourseId == $courseInfo['real_id'] && $sessionId == $currentSessionId) { + continue; } - echo json_encode($courseList); + $courseList['items'][] = [ + 'id' => $courseInfo['real_id'].'_'.$sessionId, + 'text' => $courseInfo['title'].$sessionName, + ]; } + + echo json_encode($courseList); } break; case 'search_category': @@ -125,7 +123,7 @@ switch ($action) { break; case 'search_course': if (api_is_teacher() || api_is_platform_admin()) { - if (isset($_GET['session_id']) && !empty($_GET['session_id'])) { + if (!empty($_GET['session_id'])) { //if session is defined, lets find only courses of this session $courseList = SessionManager::get_course_list_by_session_id( $_GET['session_id'], diff --git a/public/main/inc/lib/course.lib.php b/public/main/inc/lib/course.lib.php index 1b1b868f62..1f4d7fcf47 100644 --- a/public/main/inc/lib/course.lib.php +++ b/public/main/inc/lib/course.lib.php @@ -1253,7 +1253,7 @@ class CourseManager * @param array $extra_field * @param array $courseCodeList * @param array $userIdList - * @param string $filterByActive + * @param bool $filterByActive * @param array $sessionIdList * @param string $searchByKeyword * diff --git a/public/main/user/user.php b/public/main/user/user.php index c772583e89..0a073d1116 100644 --- a/public/main/user/user.php +++ b/public/main/user/user.php @@ -673,6 +673,11 @@ function get_number_of_users() $sessionId = api_get_session_id(); $courseCode = api_get_course_id(); $active = isset($_GET['active']) ? $_GET['active'] : null; + if ($active) { + $active = true; + } else { + $active = false; + } $type = isset($_REQUEST['type']) ? (int) $_REQUEST['type'] : STUDENT; if (empty($sessionId)) { @@ -821,6 +826,13 @@ function get_user_data($from, $number_of_items, $column, $direction) } $active = $_GET['active'] ?? null; + if (isset($active)) { + if ($active) { + $active = true; + } else { + $active = false; + } + } if (empty($sessionId)) { $status = $type; @@ -840,7 +852,7 @@ function get_user_data($from, $number_of_items, $column, $direction) null, false, false, - null, + [], [], [], $active From 16309d661f6548ee4af7a10e2c5ab228e5063982 Mon Sep 17 00:00:00 2001 From: christianbeeznst Date: Sat, 2 Mar 2024 22:10:35 -0500 Subject: [PATCH 3/6] Minor: Code Cleanup: Template param and styling fixes --- .../Component/Utils/AssetDirectoryNamer.php | 6 +++--- .../Component/Utils/AssetFileNameNamer.php | 12 +++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php b/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php index 4e89df784a..6df33c9855 100644 --- a/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php +++ b/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php @@ -25,7 +25,7 @@ class AssetDirectoryNamer implements DirectoryNamerInterface, ConfigurableInterf private int $charsPerDir = 2; private int $dirs = 1; - public function __construct(?PropertyAccessorInterface $propertyAccessor, ?AssetRepository $assetRepository = null, ?RequestStack $requestStack= null) + public function __construct(?PropertyAccessorInterface $propertyAccessor, ?AssetRepository $assetRepository = null, ?RequestStack $requestStack = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); $this->assetRepository = $assetRepository; @@ -59,9 +59,9 @@ class AssetDirectoryNamer implements DirectoryNamerInterface, ConfigurableInterf $fileName = $mapping->getFileName($object); $category = $this->propertyAccessor->getValue($object, $this->propertyPath); - if ($object->getCategory() === Asset::SYSTEM_TEMPLATE) { + if (Asset::SYSTEM_TEMPLATE === $object->getCategory()) { return 'system_templates'; - } elseif ($object->getCategory() === Asset::TEMPLATE) { + } elseif (Asset::TEMPLATE === $object->getCategory()) { return 'doc_templates'; } diff --git a/src/CoreBundle/Component/Utils/AssetFileNameNamer.php b/src/CoreBundle/Component/Utils/AssetFileNameNamer.php index 0762fc4676..f8853a3be1 100644 --- a/src/CoreBundle/Component/Utils/AssetFileNameNamer.php +++ b/src/CoreBundle/Component/Utils/AssetFileNameNamer.php @@ -12,6 +12,11 @@ use Symfony\Contracts\Translation\TranslatorInterface; use Vich\UploaderBundle\Mapping\PropertyMapping; use Vich\UploaderBundle\Naming\NamerInterface; +use const PATHINFO_EXTENSION; + +/** + * @implements NamerInterface + */ class AssetFileNameNamer implements NamerInterface { private RequestStack $requestStack; @@ -25,15 +30,20 @@ class AssetFileNameNamer implements NamerInterface public function name($object, PropertyMapping $mapping): string { + if (!$object instanceof Asset) { + throw new \InvalidArgumentException('Expected object of type Asset.'); + } + $category = $object->getCategory(); - if (in_array($category, [Asset::TEMPLATE, Asset::SYSTEM_TEMPLATE])) { + if (\in_array($category, [Asset::TEMPLATE, Asset::SYSTEM_TEMPLATE])) { $request = $this->requestStack->getCurrentRequest(); if ($request) { $templateId = $object->getId(); $templateTitle = $request->get('title', 'default-title'); $titleSlug = $this->slugify($templateTitle); $extension = pathinfo($mapping->getFileName($object), PATHINFO_EXTENSION); + return sprintf('%s-%s.%s', $templateId, $titleSlug, $extension); } } From b97bdf4b665576076c9d255c5494e57bdfde1a84 Mon Sep 17 00:00:00 2001 From: christianbeeznst Date: Sat, 2 Mar 2024 22:24:27 -0500 Subject: [PATCH 4/6] Minor: Code Cleanup: Template param and styling fixes --- src/CoreBundle/Component/Utils/AssetDirectoryNamer.php | 3 ++- src/CoreBundle/Component/Utils/AssetFileNameNamer.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php b/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php index 6df33c9855..a8bf1c0958 100644 --- a/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php +++ b/src/CoreBundle/Component/Utils/AssetDirectoryNamer.php @@ -61,7 +61,8 @@ class AssetDirectoryNamer implements DirectoryNamerInterface, ConfigurableInterf if (Asset::SYSTEM_TEMPLATE === $object->getCategory()) { return 'system_templates'; - } elseif (Asset::TEMPLATE === $object->getCategory()) { + } + if (Asset::TEMPLATE === $object->getCategory()) { return 'doc_templates'; } diff --git a/src/CoreBundle/Component/Utils/AssetFileNameNamer.php b/src/CoreBundle/Component/Utils/AssetFileNameNamer.php index f8853a3be1..ff456e7c59 100644 --- a/src/CoreBundle/Component/Utils/AssetFileNameNamer.php +++ b/src/CoreBundle/Component/Utils/AssetFileNameNamer.php @@ -7,6 +7,7 @@ declare(strict_types=1); namespace Chamilo\CoreBundle\Component\Utils; use Chamilo\CoreBundle\Entity\Asset; +use InvalidArgumentException; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Contracts\Translation\TranslatorInterface; use Vich\UploaderBundle\Mapping\PropertyMapping; @@ -31,7 +32,7 @@ class AssetFileNameNamer implements NamerInterface public function name($object, PropertyMapping $mapping): string { if (!$object instanceof Asset) { - throw new \InvalidArgumentException('Expected object of type Asset.'); + throw new InvalidArgumentException('Expected object of type Asset.'); } $category = $object->getCategory(); From c90861574d6b1dc98719ff87c27482798c01b834 Mon Sep 17 00:00:00 2001 From: Yannick Warnier Date: Tue, 5 Mar 2024 00:27:42 +0100 Subject: [PATCH 5/6] Display: Improve scale of grays in tailwind.config.js --- tailwind.config.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tailwind.config.js b/tailwind.config.js index e8061ff0b4..991a09d025 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -36,14 +36,14 @@ module.exports = { gradient: colorWithOpacity("--color-tertiary-gradient"), }, gray: { - 5: "#fcfcfc", - 10: "#fafafa", - 15: "#f7f8f9", - 20: "#edf0f2", - 25: "#e4e9ed", - 30: "rgba(0, 0, 0, 0.12)", - 50: "#a2a6b0", - 90: "#333333", + 5: "#ccc", + 10: "#bbb", + 15: "#aaa", + 20: "#999", + 25: "#888", + 30: "#777", + 50: "#555", + 90: "#444", }, support: { 1: "rgba(46, 117, 163, 0.08)", From 5e947fff98b9dd09506010677bfb49daef2feae0 Mon Sep 17 00:00:00 2001 From: Yannick Warnier Date: Tue, 5 Mar 2024 01:01:28 +0100 Subject: [PATCH 6/6] Internal: Fix name/title naming in certificate_report.php --- public/main/gradebook/certificate_report.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/main/gradebook/certificate_report.php b/public/main/gradebook/certificate_report.php index 637c3563ce..3749086b5c 100644 --- a/public/main/gradebook/certificate_report.php +++ b/public/main/gradebook/certificate_report.php @@ -47,7 +47,7 @@ if (api_is_student_boss()) { } foreach ($sessionsList as $session) { - $sessions[$session['id']] = $session['name']; + $sessions[$session['id']] = $session['title']; } $selfUrl = api_get_self(); @@ -233,7 +233,7 @@ if ($searchSessionAndCourse || $searchCourseOnly) { } if (!is_null($gradebook)) { - $sessionName = $session['name']; + $sessionName = $session['title']; $courseName = $sessionCourse['title']; $certificateStudent = [