Internal: Move display_order from ResourceNode to ResourceLink (#5143)

* Internal: Move display_order from ResourceNode to ResourceLink #5137

* Internal: Use ResourceLink $displayOrder instead of ResourceNode $displayOrder #5137

* Internal: Remove ResourceNode $displayOrder #5137

* Vendor: Bump stof/doctrine-extensions-bundle version to 1.10 #5137

* Forum: Fix query to get forums in category ordered by resourceLink.displayOrder

* LP: Refactoring delete method to mark the resource link as deleted instead of remove the lp as resource

* LP: Fix query to set a custom order in lp list

* LP: Fix buttons to sort learn paths

* Rename ResourceNode::getResourceLinkByTypeGroup to ResourceNode::getResourceLinkByContext and change order or its params

* LP: Change display resource link display order when moving category position

* LP: Fix layout for old list view

* Forum: Fix sorting for forums and categories

* Course Progress: Fix sorting for sections

* Internal: Enable SoftDeleteable for ResourceLink entities

* Remove ResourceLink::VISIBILITY_DELETED in favor of soft delete

* Internal: Refactoring migration about display_order in course tools

* LP: Refactoring the category delete method to make a soft delete of the resource link

* LP: Refactoring the thematic delete method to make a soft delete of the resource link

* LP: Refactoring the forum delete methods to make a soft delete of the resource link

* Add shortcut method to remove resource link from its resource

* CI: Fix ResourceNodeRepositoryTest by adding a link to the resource node

* Internal: Migration: Drop display_order column from c_lp table

* Internal: Migration: Drop position column from c_lp_category table

* Internal: Migration: Drop cat_order column from c_forum_category table

* Internal: Migration: Drop forum_order column from c_forum_forum table

* Internal: Migration: Drop display_order column from c_thematic table

* Minor: Format code

* Announcement: Fix order of the course announcements

* Internal: Refactoring migration

* Internal: Migration: Drop display_order column from c_glossary table

* Refactoring method to move display order of resource links
pull/5244/head
Angel Fernando Quiroz Campos 2 years ago committed by GitHub
parent eb59045868
commit 054905286b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      composer.json
  2. 4
      config/packages/doctrine.yaml
  3. 1
      config/packages/stof_doctrine_extensions.yaml
  4. 18
      public/main/announcements/announcements.php
  5. 3
      public/main/course_progress/index.php
  6. 8
      public/main/exercise/exercise.class.php
  7. 44
      public/main/forum/forumfunction.inc.php
  8. 2
      public/main/inc/ajax/course_home.ajax.php
  9. 6
      public/main/inc/lib/AnnouncementManager.php
  10. 6
      public/main/inc/lib/document.lib.php
  11. 16
      public/main/inc/lib/groupmanager.lib.php
  12. 11
      public/main/inc/lib/message.lib.php
  13. 34
      public/main/inc/lib/thematic.lib.php
  14. 6
      public/main/inc/lib/tracking.lib.php
  15. 1
      public/main/inc/lib/webservices/Rest.php
  16. 136
      public/main/lp/learnpath.class.php
  17. 15
      public/main/lp/learnpathList.class.php
  18. 6
      public/main/lp/lp_controller.php
  19. 3
      public/main/lp/lp_list.php
  20. 2
      public/main/lp/scorm.class.php
  21. 1
      public/main/my_space/myStudents.php
  22. 2
      public/main/session/index.php
  23. 1
      public/plugin/customcertificate/src/export_pdf_all_in_one.php
  24. 1
      public/plugin/customcertificate/src/print_certificate.php
  25. 8
      src/CoreBundle/Controller/Api/GetLinksCollectionController.php
  26. 2
      src/CoreBundle/Controller/Api/UpdatePositionLink.php
  27. 3
      src/CoreBundle/DataProvider/Extension/CToolExtension.php
  28. 6
      src/CoreBundle/DataProvider/Extension/CourseLinkExtensionTrait.php
  29. 5
      src/CoreBundle/DataProvider/Extension/PersonalFileExtension.php
  30. 68
      src/CoreBundle/Entity/ResourceLink.php
  31. 77
      src/CoreBundle/Entity/ResourceNode.php
  32. 34
      src/CoreBundle/Migrations/AbstractMigrationChamilo.php
  33. 5
      src/CoreBundle/Migrations/Schema/V200/Version20170525122900.php
  34. 17
      src/CoreBundle/Migrations/Schema/V200/Version20230615213500.php
  35. 67
      src/CoreBundle/Migrations/Schema/V200/Version20240112191200.php
  36. 42
      src/CoreBundle/Migrations/Schema/V200/Version20240313111800.php
  37. 53
      src/CoreBundle/Repository/ResourceLinkRepository.php
  38. 3
      src/CoreBundle/Repository/ResourceNodeRepository.php
  39. 23
      src/CoreBundle/Repository/ResourceRepository.php
  40. 36
      src/CoreBundle/Resources/views/LearnPath/list.html.twig
  41. 5
      src/CoreBundle/Security/Authorization/Voter/ResourceNodeVoter.php
  42. 18
      src/CourseBundle/Entity/CForum.php
  43. 15
      src/CourseBundle/Entity/CForumCategory.php
  44. 16
      src/CourseBundle/Entity/CLp.php
  45. 17
      src/CourseBundle/Entity/CLpCategory.php
  46. 19
      src/CourseBundle/Entity/CThematic.php
  47. 3
      src/CourseBundle/Repository/CDocumentRepository.php
  48. 5
      tests/CoreBundle/Repository/ResourceNodeRepositoryTest.php
  49. 12
      tests/CourseBundle/Repository/CDocumentRepositoryTest.php
  50. 4
      tests/CourseBundle/Repository/CForumCategoryRepositoryTest.php
  51. 7
      tests/CourseBundle/Repository/CLpCategoryRepositoryTest.php
  52. 7
      tests/scripts/migrate_item_property.php

@ -114,7 +114,7 @@
"sensio/framework-extra-bundle": "~6.1",
"simpod/doctrine-utcdatetime": "^0.1.2",
"sonata-project/exporter": "^2.2",
"stof/doctrine-extensions-bundle": "~1.4",
"stof/doctrine-extensions-bundle": "^1.10",
"sunra/php-simple-html-dom-parser": "~1.5",
"symfony/apache-pack": "^1.0",
"symfony/asset": "5.4.*",

@ -59,3 +59,7 @@ doctrine:
string_functions:
MONTH: DoctrineExtensions\Query\Mysql\Month
YEAR: DoctrineExtensions\Query\Mysql\Year
filters:
softdeleteable:
class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
enabled: true

@ -8,5 +8,6 @@ stof_doctrine_extensions:
tree: true
timestampable: true
sluggable: true
softdeleteable: true
sortable: true
translatable: true

@ -26,9 +26,12 @@ api_protect_course_group(GroupManager::GROUP_TOOL_ANNOUNCEMENT);
$token = Security::get_existing_token();
$courseId = api_get_course_int_id();
$course = api_get_course_entity();
$_course = api_get_course_info_by_id($courseId);
$group_id = api_get_group_id();
$group = api_get_group_entity();
$sessionId = api_get_session_id();
$session = api_get_session_entity();
$current_course_tool = TOOL_ANNOUNCEMENT;
$this_section = SECTION_COURSES;
$nameTools = get_lang('Announcements');
@ -115,16 +118,21 @@ switch ($action) {
$sortDirection = 'up';
}
/** @var CAnnouncement $currentAnnouncement */
$currentAnnouncement = $repo->find($thisAnnouncementId);
if ($currentAnnouncement) {
$resourceNode = $currentAnnouncement->getResourceNode();
$currentDisplayOrder = $resourceNode->getDisplayOrder();
$link = $resourceNode->getResourceLinkByContext($course, $session, $group);
$newPosition = $currentDisplayOrder + ($sortDirection === 'down' ? 1 : -1);
$newPosition = max(0, $newPosition);
if ($link) {
if ('down' === $sortDirection) {
$link->moveDownPosition();
} else {
$link->moveUpPosition();
}
$resourceNode->setDisplayOrder($newPosition);
$em->flush();
$em->flush();
}
}
header('Location: '.$homeUrl);

@ -595,7 +595,8 @@ switch ($action) {
['class' => 'btn btn--plain']
);
if (0 == api_get_session_id()) {
$currentOrder = $thematic->getResourceNode()->getDisplayOrder();
$link = $thematic->getResourceNode()->getResourceLinkByContext($course, $session);
$currentOrder = $link ? $link->getDisplayOrder() : 0;
$moveButtons = $thematicManager->getMoveActions($id, $currentOrder, count($thematic_data));
$toolbarThematic .= $moveButtons;
}

@ -9,6 +9,7 @@ use Chamilo\CoreBundle\Entity\TrackEExercise;
use Chamilo\CoreBundle\Entity\TrackEExerciseConfirmation;
use Chamilo\CoreBundle\Entity\TrackEHotspot;
use Chamilo\CoreBundle\Framework\Container;
use Chamilo\CoreBundle\Repository\ResourceLinkRepository;
use Chamilo\CourseBundle\Entity\CExerciseCategory;
use Chamilo\CourseBundle\Entity\CQuiz;
use Chamilo\CourseBundle\Entity\CQuizRelQuestionCategory;
@ -1805,7 +1806,9 @@ class Exercise
$exerciseId = $this->iId;
$repo = Container::getQuizRepository();
/** @var CQuiz $exercise */
$exercise = $repo->find($exerciseId);
$linksRepo = Container::$container->get(ResourceLinkRepository::class);
if (null === $exercise) {
return false;
@ -1825,7 +1828,10 @@ class Exercise
WHERE iid = $exerciseId";
Database::query($sql);
$repo->softDelete($exercise);
$course = api_get_course_entity();
$session = api_get_session_entity();
$linksRepo->removeByResourceInContext($exercise, $course, $session);
SkillModel::deleteSkillsFromItem($exerciseId, ITEM_TYPE_EXERCISE);

@ -2,8 +2,10 @@
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\AbstractResource;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\GradebookLink;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\Session as SessionEntity;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Framework\Container;
@ -30,6 +32,10 @@ function handleForum($url)
$id = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : null;
if (api_is_allowed_to_edit(false, true)) {
$course = api_get_course_entity();
$session = api_get_session_entity();
$linksRepo = Database::getManager()->getRepository(ResourceLink::class);
//if is called from a learning path lp_id
$lp_id = isset($_REQUEST['lp_id']) ? (int) $_REQUEST['lp_id'] : null;
$content = $_REQUEST['content'] ?? '';
@ -47,6 +53,7 @@ function handleForum($url)
break;
}
/** @var AbstractResource|null $resource */
$resource = null;
if ($repo && $id) {
$resource = $repo->find($id);
@ -143,7 +150,7 @@ function handleForum($url)
break;
case 'delete_category':
if ($resource) {
$repo->delete($resource);
$linksRepo->removeByResourceInContext($resource, $course, $session);
Display::addFlash(
Display::return_message(get_lang('Forum category deleted'), 'confirmation', false)
@ -154,8 +161,8 @@ function handleForum($url)
break;
case 'delete_forum':
if ($resource) {
$resource = Container::getForumRepository()->find($id);
$repo->delete($resource);
$linksRepo->removeByResourceInContext($resource, $course, $session);
Display::addFlash(Display::return_message(get_lang('Forum deleted'), 'confirmation', false));
}
@ -165,7 +172,8 @@ function handleForum($url)
case 'delete_thread':
$locked = api_resource_is_locked_by_gradebook($id, LINK_FORUM_THREAD);
if ($resource && false === $locked) {
$repo->delete($resource);
$linksRepo->removeByResourceInContext($resource, $course, $session);
SkillModel::deleteSkillsFromItem($id, ITEM_TYPE_FORUM_THREAD);
$link_info = GradebookUtils::isResourceInCourseGradebook(
api_get_course_id(),
@ -576,7 +584,6 @@ function saveForumCategory(array $values, array $courseInfo = [], bool $showMess
{
$courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
$course_id = $courseInfo['real_id'];
$new_max = 1;
$session_id = api_get_session_id();
$clean_cat_title = $values['forum_category_title'];
$repo = Container::getForumCategoryRepository();
@ -609,7 +616,6 @@ function saveForumCategory(array $values, array $courseInfo = [], bool $showMess
$category
->setTitle($clean_cat_title)
->setCatComment($values['forum_category_comment'] ?? '')
->setCatOrder($new_max)
->setParent($course)
->addCourseLink($course, $session)
;
@ -666,8 +672,6 @@ function store_forum(array $values, array $courseInfo = [], bool $returnId = fal
$new_max = $row['sort_max'] + 1;*/
}
$new_max = 0;
// Forum images
$has_attachment = false;
$image_moved = true;
@ -714,7 +718,6 @@ function store_forum(array $values, array $courseInfo = [], bool $returnId = fal
if (!isset($values['forum_id'])) {
$forum = new CForum();
$forum->setForumOrder($new_max ?? null);
} else {
/** @var CForum $forum */
$forum = $repo->find($values['forum_id']);
@ -1025,7 +1028,6 @@ function moveUpDown(string $content, string $direction, int $id): string
{
$em = Database::getManager();
$entity = null;
if ('forumcategory' === $content) {
$entityRepo = $em->getRepository(CForumCategory::class);
} elseif ('forum' === $content) {
@ -1046,12 +1048,21 @@ function moveUpDown(string $content, string $direction, int $id): string
return false;
}
$currentDisplayOrder = $resourceNode->getDisplayOrder();
$course = api_get_course_entity();
$session = api_get_session_entity();
$link = $resourceNode->getResourceLinkByContext($course, $session);
$newPosition = $currentDisplayOrder + ($direction === 'down' ? 1 : -1);
$newPosition = max(0, $newPosition);
if (!$link) {
return false;
}
if ('down' === $direction) {
$link->moveDownPosition();
} else {
$link->moveUpPosition();
}
$resourceNode->setDisplayOrder($newPosition);
$em->flush();
Display::addFlash(Display::return_message(get_lang('Updated')));
@ -1083,6 +1094,8 @@ function get_forum_categories(int $courseId = 0, int $sessionId = 0): Array
/**
* This function retrieves all the fora in a given forum category.
*
* @todo: Fixes error if there forums with no category.
*
* @param int $categoryId the id of the forum category
* @param int $courseId Optional. The course ID
*
@ -1097,11 +1110,10 @@ function get_forums_in_category(int $categoryId, int $courseId = 0)
$repo = Container::getForumRepository();
$course = api_get_course_entity($courseId);
$qb = $repo->getResourcesByCourse($course, null);
$qb = $repo->getResourcesByCourse($course, null, null, null, true, true);
$qb
->andWhere('resource.forumCategory = :catId')
->setParameter('catId', $categoryId)
->orderBy('node.displayOrder')
;
return $qb->getQuery()->getResult();

@ -222,7 +222,7 @@ switch ($action) {
api_get_user_id(),
api_get_course_info($item['code']),
$session_id,
'lp.publishedOn DESC'
'resource.publishedOn DESC'
);
$flat_list = $list->get_flat_list();
$lps[$item['code']] = $flat_list;

@ -1394,7 +1394,7 @@ class AnnouncementManager
$announcements = $qb->getQuery()->getResult();
$iterator = 1;
$iterator = 0;
$bottomAnnouncement = $announcement_number;
$displayed = [];
@ -1582,7 +1582,7 @@ class AnnouncementManager
.$iconVisibility."</a>";
// Move up action
if ($iterator == 1) {
if ($iterator == 0 ) {
$move1 = $iconUpDisabled;
} else {
$move1 = "<a href=\"".$actionUrl."&action=move&up=".$announcementId."&sec_token=".$stok."\">".$iconUp."</a>";
@ -1590,7 +1590,7 @@ class AnnouncementManager
$modify_icons .= $move1;
// Move down action
if ($iterator == 4) {
if ($iterator === count($announcements) - 1) {
$move2 = $iconDownDisabled;
} else {
$move2 = "<a href=\"".$actionUrl."&action=move&down=".$announcementId."&sec_token=".$stok."\">".$iconDown."</a>";;

@ -581,7 +581,7 @@ class DocumentManager
docs.filetype = 'folder' AND
$groupCondition AND
n.path NOT LIKE '%shared_folder%' AND
l.visibility NOT IN ('".ResourceLink::VISIBILITY_DELETED."')
l.deleted_at IS NULL
$condition_session ";
if (0 != $groupIid) {
@ -681,7 +681,7 @@ class DocumentManager
WHERE
docs.filetype = 'folder' AND
$groupCondition AND
l.visibility NOT IN ('".ResourceLink::VISIBILITY_DELETED."')
l.deleted_at IS NULL
$condition_session AND
l.c_id = $courseId ";
$folder_in_invisible_result = Database::query($sql);
@ -3058,7 +3058,7 @@ class DocumentManager
l.c_id = $course_id AND
docs.filetype = 'folder' AND
n.path IN ('".$folder_sql."') AND
l.visibility NOT IN ('".ResourceLink::VISIBILITY_DELETED."')
l.deleted_at IS NULL
";
/*$sql = "SELECT path, title

@ -1068,6 +1068,9 @@ class GroupManager
{
$em = Database::getManager();
$course = api_get_course_entity();
$session = api_get_session_entity();
$groupCategoryRepo = $em->getRepository(CGroupCategory::class);
$cat1 = $groupCategoryRepo->find($id1);
$cat2 = $groupCategoryRepo->find($id2);
@ -1077,11 +1080,16 @@ class GroupManager
$node2 = $cat2->getResourceNode();
if ($node1 && $node2) {
$order1 = $node1->getDisplayOrder();
$order2 = $node2->getDisplayOrder();
$link1 = $node1->getResourceLinkByContext($course, $session);
$link2 = $node2->getResourceLinkByContext($course, $session);
if ($link1 && $link2) {
$order1 = $link1->getDisplayOrder();
$order2 = $link2->getDisplayOrder();
$node1->setDisplayOrder($order2);
$node2->setDisplayOrder($order1);
$link1->setDisplayOrder($order2);
$link2->setDisplayOrder($order1);
}
$em->flush();
}

@ -469,17 +469,6 @@ class MessageManager
return $result;
}
public static function softDeleteAttachments(Message $message): void
{
$attachments = $message->getAttachments();
if (!empty($attachments)) {
$repo = Container::getMessageAttachmentRepository();
foreach ($attachments as $file) {
$repo->softDelete($file);
}
}
}
/**
* Saves a message attachment files.
*

@ -5,6 +5,7 @@
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Framework\Container;
use Chamilo\CoreBundle\Repository\ResourceLinkRepository;
use Chamilo\CourseBundle\Entity\CAttendance;
use Chamilo\CourseBundle\Entity\CThematic;
use Chamilo\CourseBundle\Entity\CThematicAdvance;
@ -82,12 +83,18 @@ class Thematic
return false;
}
$currentDisplayOrder = $resourceNode->getDisplayOrder();
$link = $resourceNode->getResourceLinkByContext($course, $session);
$newPosition = $currentDisplayOrder + ($direction === 'down' ? 1 : -1);
$newPosition = max(0, $newPosition);
if (!$link) {
return false;
}
if ('down' === $direction) {
$link->moveDownPosition();
} else {
$link->moveUpPosition();
}
$resourceNode->setDisplayOrder($newPosition);
$em->flush();
// update done advances with de current thematic list
@ -151,8 +158,6 @@ class Thematic
$thematic
->setTitle($title)
->setContent($content)
//->setDisplayOrder($max_thematic_item + 1)
->setDisplayOrder(0)
->setParent($course)
->addCourseLink($course, $session)
;
@ -172,25 +177,24 @@ class Thematic
return $thematic;
}
/**
* Delete logically (set active field to 0) a thematic.
*
* @param int|array $thematicId One or many thematic ids
*
* @return void
*/
public function delete(int|array $thematicId): void
{
$repo = Container::getThematicRepository();
$linksRepo = Container::$container->get(ResourceLinkRepository::class);
$course = api_get_course_entity();
$session = api_get_session_entity();
if (is_array($thematicId)) {
foreach ($thematicId as $id) {
/** @var CThematic $resource */
$resource = $repo->find($id);
$repo->delete($resource);
$linksRepo->removeByResourceInContext($resource, $course, $session);
}
} else {
/** @var CThematic $resource */
$resource = $repo->find($thematicId);
$repo->delete($resource);
$linksRepo->removeByResourceInContext($resource, $course, $session);
};
}

@ -5690,7 +5690,7 @@ class Tracking
api_get_user_id(),
['real_id' => $courseId],
$sessionId,
'lp.publishedOn ASC',
'resource.publishedOn ASC',
true,
null,
true
@ -6931,7 +6931,7 @@ class Tracking
$userId,
$courseInfo,
0,
'lp.publishedOn ASC',
'resource.publishedOn ASC',
true,
null,
true
@ -7871,7 +7871,7 @@ class Tracking
api_get_user_id(),
$courseInfo,
$sessionId,
'lp.publishedOn ASC',
'resource.publishedOn ASC',
true,
null,
true

@ -821,7 +821,6 @@ class Rest extends WebService
$categoryNone = new CLpCategory();
$categoryNone->setTitle(get_lang('WithOutCategory'));
$categoryNone->setPosition(0);
$categories = array_merge([$categoryNone], $categoriesTempList);
$categoryData = [];

@ -3,6 +3,7 @@
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Entity\Session as SessionEntity;
use Chamilo\CourseBundle\Entity\CLpRelUser;
@ -603,7 +604,6 @@ class learnpath
$dsp = $row[0] + 1;
}*/
$dsp = 1;
$category = null;
if (!empty($categoryId)) {
$category = Container::getLpCategoryRepository()->find($categoryId);
@ -615,7 +615,6 @@ class learnpath
->setLpType($type)
->setTitle($name)
->setDescription($description)
->setDisplayOrder($dsp)
->setCategory($category)
->setPublishedOn($published_on)
->setExpiredOn($expired_on)
@ -787,39 +786,40 @@ class learnpath
return false;
}
$lp_item = Database::get_course_table(TABLE_LP_ITEM);
$lp_view = Database::get_course_table(TABLE_LP_VIEW);
$lp_item_view = Database::get_course_table(TABLE_LP_ITEM_VIEW);
$course = api_get_course_entity();
$session = api_get_session_entity();
//$lp_item = Database::get_course_table(TABLE_LP_ITEM);
//$lp_view = Database::get_course_table(TABLE_LP_VIEW);
//$lp_item_view = Database::get_course_table(TABLE_LP_ITEM_VIEW);
// Delete lp item id.
foreach ($this->items as $lpItemId => $dummy) {
$sql = "DELETE FROM $lp_item_view
WHERE lp_item_id = '".$lpItemId."'";
Database::query($sql);
}
//foreach ($this->items as $lpItemId => $dummy) {
// $sql = "DELETE FROM $lp_item_view
// WHERE lp_item_id = '".$lpItemId."'";
// Database::query($sql);
//}
// Proposed by Christophe (nickname: clefevre)
$sql = "DELETE FROM $lp_item
WHERE lp_id = ".$this->lp_id;
Database::query($sql);
//$sql = "DELETE FROM $lp_item
// WHERE lp_id = ".$this->lp_id;
//Database::query($sql);
$sql = "DELETE FROM $lp_view
WHERE lp_id = ".$this->lp_id;
Database::query($sql);
//$sql = "DELETE FROM $lp_view
// WHERE lp_id = ".$this->lp_id;
//Database::query($sql);
$table = Database::get_course_table(TABLE_LP_REL_USERGROUP);
$sql = "DELETE FROM $table
WHERE
lp_id = {$this->lp_id}";
Database::query($sql);
//$table = Database::get_course_table(TABLE_LP_REL_USERGROUP);
//$sql = "DELETE FROM $table
// WHERE
// lp_id = {$this->lp_id}";
//Database::query($sql);
$repo = Container::getLpRepository();
$lp = $repo->find($this->lp_id);
Database::getManager()->remove($lp);
Database::getManager()->flush();
$lp = Container::getLpRepository()->find($this->lp_id);
// Updates the display order of all lps.
$this->update_display_order();
Database::getManager()
->getRepository(ResourceLink::class)
->removeByResourceInContext($lp, $course, $session);
$link_info = GradebookUtils::isResourceInCourseGradebook(
api_get_course_id(),
@ -832,9 +832,9 @@ class learnpath
GradebookUtils::remove_resource_from_course_gradebook($link_info['id']);
}
if ('true' === api_get_setting('search_enabled')) {
delete_all_values_for_item($this->cc, TOOL_LEARNPATH, $this->lp_id);
}
//if ('true' === api_get_setting('search_enabled')) {
// delete_all_values_for_item($this->cc, TOOL_LEARNPATH, $this->lp_id);
//}
}
/**
@ -7138,37 +7138,41 @@ class learnpath
}
}
/**
* @param int $id
*/
public static function moveUpCategory($id)
public static function moveUpCategory(int $id): void
{
$id = (int) $id;
$em = Database::getManager();
/** @var CLpCategory $item */
$item = $em->find(CLpCategory::class, $id);
if ($item) {
$position = $item->getPosition() - 1;
$item->setPosition($position);
$em->persist($item);
$em->flush();
$course = api_get_course_entity();
$session = api_get_session_entity();
$link = $item->resourceNode->getResourceLinkByContext($course, $session);
if ($link) {
$link->moveUpPosition();
$em->flush();
}
}
}
/**
* @param int $id
*/
public static function moveDownCategory($id)
public static function moveDownCategory(int $id): void
{
$id = (int) $id;
$em = Database::getManager();
/** @var CLpCategory $item */
$item = $em->find(CLpCategory::class, $id);
if ($item) {
$position = $item->getPosition() + 1;
$item->setPosition($position);
$em->persist($item);
$em->flush();
$course = api_get_course_entity();
$session = api_get_session_entity();
$link = $item->resourceNode->getResourceLinkByContext($course, $session);
if ($link) {
$link->moveDownPosition();
$em->flush();
}
}
}
@ -7198,7 +7202,7 @@ class learnpath
{
// Using doctrine extensions
$repo = Container::getLpCategoryRepository();
$qb = $repo->getResourcesByCourse(api_get_course_entity($courseId), api_get_session_entity());
$qb = $repo->getResourcesByCourse(api_get_course_entity($courseId), api_get_session_entity(), null, null, true, true);
return $qb->getQuery()->getResult();
}
@ -7222,10 +7226,7 @@ class learnpath
return $sessionId;
}
/**
* @param int $id
*/
public static function deleteCategory($id): bool
public static function deleteCategory(int $id): bool
{
$repo = Container::getLpCategoryRepository();
/** @var CLpCategory $category */
@ -7236,12 +7237,14 @@ class learnpath
foreach ($lps as $lp) {
$lp->setCategory(null);
$em->persist($lp);
}
// Removing category.
$em->remove($category);
$em->flush();
$em->persist($lp);
$course = api_get_course_entity();
$session = api_get_session_entity();
$em->getRepository(ResourceLink::class)->removeByResourceInContext($category, $course, $session);
return true;
}
@ -8616,21 +8619,20 @@ class learnpath
/** @var CLp $lp */
$lp = Container::getLpRepository()->find($lpId);
if ($lp) {
$resourceNode = $lp->getResourceNode();
$position = $resourceNode->getDisplayOrder();
$resourceNodeId = $resourceNode->getId();
$course = api_get_course_entity();
$session = api_get_session_entity();
$group = api_get_group_entity();
$item = $em->find(ResourceNode::class, $resourceNodeId);
if ($item) {
$newPosition = 0;
$link = $lp->getResourceNode()->getResourceLinkByContext($course, $session, $group);
if ($link) {
if ('down' === $direction) {
$newPosition = $position + 1;
$link->moveDownPosition();
}
if ('up' === $direction) {
$newPosition = $position - 1;
$link->moveUpPosition();
}
$item->setDisplayOrder($newPosition);
$em->persist($item);
$em->flush();
}
}

@ -55,16 +55,15 @@ class LearnpathList
$course_id = $courseInfo['real_id'];
$this->user_id = $user_id;
$order = ' ORDER BY lp.displayOrder ASC, lp.title ASC';
if (isset($order_by)) {
$order = Database::parse_conditions(['order' => $order_by]);
}
$repo = Container::getLpRepository();
$course = api_get_course_entity($course_id);
$session = api_get_session_entity($session_id);
$qb = $repo->getResourcesByCourse($course, $session);
$qb = $repo->getResourcesByCourse($course, $session, null, null, true, true);
if (!empty($order_by)) {
$qb->addOrderBy($order_by);
}
$now = api_get_utc_datetime();
if ($check_publication_dates) {
@ -94,7 +93,6 @@ class LearnpathList
$order
";*/
//$learningPaths = Database::getManager()->createQuery($dql)->getResult();
$qb->addOrderBy('node.displayOrder', 'ASC');
$showBlockedPrerequisite = ('true' === api_get_setting('lp.show_prerequisite_as_blocked'));
$names = [];
@ -138,6 +136,8 @@ class LearnpathList
}
$link = $lp->getFirstResourceLink();
$resourceNode = $lp->getResourceNode();
$this->list[$lp->getIid()] = [
'lp_type' => $lp->getLpType(),
'lp_session' => $link && $link->getSession() ? (int) $link->getSession()->getId() : 0,
@ -154,7 +154,6 @@ class LearnpathList
'lp_prevent_reinit' => $lp->getPreventReinit(),
'seriousgame_mode' => $lp->getSeriousgameMode(),
'lp_scorm_debug' => $lp->getDebug(),
'lp_display_order' => $lp->getResourceNode()->getDisplayOrder() + 1,
'autolaunch' => $lp->getAutolaunch(),
'created_on' => $lp->getCreatedOn() ? $lp->getCreatedOn()->format('Y-m-d H:i:s') : null,
'modified_on' => $lp->getModifiedOn() ? $lp->getModifiedOn()->format('Y-m-d H:i:s') : null,

@ -440,7 +440,7 @@ switch ($action) {
api_not_allowed(true);
}
if (isset($_REQUEST['id'])) {
learnpath::moveUpCategory($_REQUEST['id']);
learnpath::moveUpCategory((int) $_REQUEST['id']);
}
require 'lp_list.php';
break;
@ -449,7 +449,7 @@ switch ($action) {
api_not_allowed(true);
}
if (isset($_REQUEST['id'])) {
learnpath::moveDownCategory($_REQUEST['id']);
learnpath::moveDownCategory((int) $_REQUEST['id']);
}
require 'lp_list.php';
break;
@ -458,7 +458,7 @@ switch ($action) {
api_not_allowed(true);
}
if (isset($_REQUEST['id'])) {
$result = learnpath::deleteCategory($_REQUEST['id']);
$result = learnpath::deleteCategory((int) $_REQUEST['id']);
if ($result) {
Display::addFlash(Display::return_message(get_lang('Deleted')));
}

@ -111,7 +111,6 @@ if ($allowCategory) {
$categoryTest = new CLpCategory();
$categoryTest->setTitle(get_lang('Without category'));
$categoryTest->setPosition(0);
$categories = [$categoryTest];
if (!empty($categoriesTempList)) {
@ -708,7 +707,7 @@ foreach ($categories as $category) {
/* COLUMN ORDER */
// Only active while session mode is not active
if (0 == $sessionId) {
if (1 == $details['lp_display_order'] && 1 != $max) {
if (0 == $current && 1 != $max) {
$dsp_order .= Display::url(
Display::getMdiIcon('arrow-down-bold', 'ch-tool-icon', '', 22),
"lp_controller.php?$cidReq&action=move_lp_down&lp_id=$id&category_id=$categoryId",

@ -267,7 +267,6 @@ class scorm extends learnpath
$row = Database::fetch_array($res_max);
$dsp = $row[0] + 1;
}*/
$dsp = 1;
$name = $oOrganization->get_name();
$lp = (new CLp())
@ -277,7 +276,6 @@ class scorm extends learnpath
->setPath($this->subdir)
->setDefaultEncoding($this->manifest_encoding)
->setJsLib('scorm_api.php')
->setDisplayOrder($dsp)
->setUseMaxScore($userMaxScore)
->setAsset($this->asset)
->setParent($course)

@ -1607,7 +1607,6 @@ if (empty($details)) {
$categoriesTempList = learnpath::getCategories($courseId);
$categoryTest = new CLpCategory();
$categoryTest->setTitle(get_lang('Without category'));
$categoryTest->setPosition(0);
$categories = [
$categoryTest,
];

@ -115,7 +115,7 @@ if (!empty($courseList)) {
api_get_user_id(),
api_get_course_info($course_data['code']),
$session_id,
'lp.publishedOn ASC',
'resource.publishedOn ASC',
true,
null,
true

@ -485,7 +485,6 @@ foreach ($userList as $userInfo) {
$categoryTest = new CLpCategory();
$categoryTest->setId(0);
$categoryTest->setTitle($plugin->get_lang('WithOutCategory'));
$categoryTest->setPosition(0);
$categories = [$categoryTest];
if (!empty($categoriesTempList)) {

@ -372,7 +372,6 @@ foreach ($userList as $userInfo) {
$categoryTest = new CLpCategory();
$categoryTest->setId(0);
$categoryTest->setTitle($plugin->get_lang('WithOutCategory'));
$categoryTest->setPosition(0);
$categories = [$categoryTest];
if (!empty($categoriesTempList)) {

@ -43,6 +43,8 @@ class GetLinksCollectionController extends BaseResourceFileAction
if ($links) {
/** @var CLink $link */
foreach ($links as $link) {
$resourceNode = $link->getResourceNode();
$dataResponse['linksWithoutCategory'][] =
[
'id' => $link->getIid(),
@ -51,7 +53,7 @@ class GetLinksCollectionController extends BaseResourceFileAction
'url' => $link->getUrl(),
'iid' => $link->getIid(),
'linkVisible' => $link->getFirstResourceLink()->getVisibility(),
'position' => $link->getResourceNode()->getDisplayOrder(),
'position' => $resourceNode->getResourceLinkByContext($course, $session)?->getDisplayOrder(),
];
}
}
@ -78,6 +80,8 @@ class GetLinksCollectionController extends BaseResourceFileAction
/** @var CLink $link */
foreach ($links as $link) {
$resourceNode = $link->getResourceNode();
$items[] = [
'id' => $link->getIid(),
'title' => $link->getTitle(),
@ -85,7 +89,7 @@ class GetLinksCollectionController extends BaseResourceFileAction
'url' => $link->getUrl(),
'iid' => $link->getIid(),
'linkVisible' => $link->getFirstResourceLink()->getVisibility(),
'position' => $link->getResourceNode()->getDisplayOrder(),
'position' => $resourceNode->getResourceLinkByContext($course, $session)?->getDisplayOrder(),
];
$dataResponse['categories'][$categoryId]['links'] = $items;

@ -23,7 +23,7 @@ class UpdatePositionLink extends AbstractController
$resourceNode = $link->getResourceNode();
if ($resourceNode) {
$resourceNode->setDisplayOrder($newPosition);
// $resourceNode->setDisplayOrder($newPosition);
$em->flush();
}

@ -9,7 +9,6 @@ namespace Chamilo\CoreBundle\DataProvider\Extension;
use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Traits\ControllerTrait;
use Chamilo\CoreBundle\Traits\CourseControllerTrait;
use Chamilo\CourseBundle\Entity\CTool;
@ -39,8 +38,6 @@ class CToolExtension implements QueryCollectionExtensionInterface
->andWhere(
$queryBuilder->expr()->notIn("$alias.title", ['course_tool', 'course_homepage'])
)
->andWhere('resource_links.visibility != :visibility_deleted')
->setParameter('visibility_deleted', ResourceLink::VISIBILITY_DELETED)
;
}
}

@ -37,12 +37,6 @@ trait CourseLinkExtensionTrait
protected function addVisibilityCondition(QueryBuilder $queryBuilder): void
{
// Do not show deleted resources.
$queryBuilder
->andWhere('links.visibility != :visibilityDeleted')
->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
;
$allowDraft =
$this->security->isGranted('ROLE_ADMIN')
|| $this->security->isGranted('ROLE_CURRENT_COURSE_TEACHER');

@ -71,11 +71,6 @@ final class PersonalFileExtension implements QueryCollectionExtensionInterface /
if ($isShared) {
$queryBuilder->leftJoin('node.resourceLinks', 'links');
/*$queryBuilder
->andWhere('links.visibility != :visibilityDeleted')
->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
;*/
$queryBuilder
->andWhere('links.visibility = :visibility')
->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)

@ -7,27 +7,31 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\Entity;
use ApiPlatform\Metadata\ApiResource;
use Chamilo\CoreBundle\Repository\ResourceLinkRepository;
use Chamilo\CoreBundle\Traits\TimestampableTypedEntity;
use Chamilo\CourseBundle\Entity\CGroup;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;
use LogicException;
use Stringable;
use Symfony\Component\Serializer\Annotation\Groups;
#[ApiResource]
#[ORM\Table(name: 'resource_link')]
#[ORM\Entity]
#[ORM\Entity(repositoryClass: ResourceLinkRepository::class)]
#[Gedmo\SoftDeleteable(fieldName: 'deletedAt', timeAware: false, hardDelete: true)]
class ResourceLink implements Stringable
{
use SoftDeleteableEntity;
use TimestampableTypedEntity;
public const VISIBILITY_DRAFT = 0;
public const VISIBILITY_PENDING = 1;
public const VISIBILITY_PUBLISHED = 2;
public const VISIBILITY_DELETED = 3;
#[ORM\Id]
#[ORM\Column(type: 'integer')]
@ -38,22 +42,27 @@ class ResourceLink implements Stringable
#[ORM\JoinColumn(name: 'resource_node_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
protected ResourceNode $resourceNode;
#[Gedmo\SortableGroup]
#[ORM\ManyToOne(targetEntity: Course::class)]
#[ORM\JoinColumn(name: 'c_id', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
protected ?Course $course = null;
#[Gedmo\SortableGroup]
#[ORM\ManyToOne(targetEntity: Session::class, inversedBy: 'resourceLinks')]
#[ORM\JoinColumn(name: 'session_id', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
protected ?Session $session = null;
#[ORM\ManyToOne(targetEntity: CGroup::class)]
#[ORM\JoinColumn(name: 'group_id', referencedColumnName: 'iid', nullable: true, onDelete: 'CASCADE')]
protected ?CGroup $group = null;
#[Gedmo\SortableGroup]
#[ORM\ManyToOne(targetEntity: Usergroup::class)]
#[ORM\JoinColumn(name: 'usergroup_id', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
protected ?Usergroup $userGroup = null;
#[Gedmo\SortableGroup]
#[ORM\ManyToOne(targetEntity: CGroup::class)]
#[ORM\JoinColumn(name: 'group_id', referencedColumnName: 'iid', nullable: true, onDelete: 'CASCADE')]
protected ?CGroup $group = null;
#[Gedmo\SortableGroup]
#[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
protected ?User $user = null;
@ -85,6 +94,14 @@ class ResourceLink implements Stringable
#[ORM\Column(name: 'end_visibility_at', type: 'datetime', nullable: true)]
protected ?DateTimeInterface $endVisibilityAt = null;
#[Gedmo\SortablePosition]
#[ORM\Column]
private int $displayOrder;
#[Gedmo\SortableGroup]
#[ORM\Column]
private ?int $resourceTypeGroup;
public function __construct()
{
$this->resourceRights = new ArrayCollection();
@ -277,7 +294,6 @@ class ResourceLink implements Stringable
'Draft' => self::VISIBILITY_DRAFT,
'Pending' => self::VISIBILITY_PENDING,
'Published' => self::VISIBILITY_PUBLISHED,
'Deleted' => self::VISIBILITY_DELETED,
];
}
@ -295,4 +311,42 @@ class ResourceLink implements Stringable
{
return array_flip(static::getVisibilityList())[$this->getVisibility()];
}
public function getDisplayOrder(): int
{
return $this->displayOrder;
}
public function setDisplayOrder(int $displayOrder): static
{
$this->displayOrder = $displayOrder;
return $this;
}
public function getResourceTypeGroup(): ?int
{
return $this->resourceTypeGroup;
}
public function setResourceTypeGroup(int $resourceTypeGroup): static
{
$this->resourceTypeGroup = $resourceTypeGroup;
return $this;
}
public function moveUpPosition(): static
{
$this->displayOrder--;
return $this;
}
public function moveDownPosition(): static
{
$this->displayOrder++;
return $this;
}
}

@ -20,10 +20,12 @@ use Chamilo\CoreBundle\Entity\Listener\ResourceNodeListener;
use Chamilo\CoreBundle\Repository\ResourceNodeRepository;
use Chamilo\CoreBundle\Traits\TimestampableAgoTrait;
use Chamilo\CoreBundle\Traits\TimestampableTypedEntity;
use Chamilo\CourseBundle\Entity\CGroup;
use Chamilo\CourseBundle\Entity\CShortcut;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use InvalidArgumentException;
@ -97,7 +99,6 @@ class ResourceNode implements Stringable
#[Assert\NotNull]
#[ORM\ManyToOne(targetEntity: ResourceType::class, inversedBy: 'resourceNodes')]
#[ORM\JoinColumn(name: 'resource_type_id', referencedColumnName: 'id', nullable: false)]
#[Gedmo\SortableGroup]
protected ResourceType $resourceType;
#[ORM\ManyToOne(targetEntity: ResourceFormat::class, inversedBy: 'resourceNodes')]
@ -130,7 +131,6 @@ class ResourceNode implements Stringable
#[ORM\JoinColumn(name: 'parent_id', onDelete: 'CASCADE')]
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
#[Gedmo\TreeParent]
#[Gedmo\SortableGroup]
protected ?ResourceNode $parent = null;
/**
@ -189,10 +189,6 @@ class ResourceNode implements Stringable
#[ORM\Column(type: 'uuid', unique: true)]
protected ?UuidV4 $uuid = null;
#[ORM\Column(name: 'display_order', type: 'integer', nullable: false)]
#[Gedmo\SortablePosition]
protected int $displayOrder;
public function __construct()
{
$this->public = false;
@ -202,7 +198,6 @@ class ResourceNode implements Stringable
$this->comments = new ArrayCollection();
$this->createdAt = new DateTime();
$this->fileEditableText = false;
$this->displayOrder = 0;
}
public function __toString(): string
@ -414,6 +409,57 @@ class ResourceNode implements Stringable
return $this->resourceLinks;
}
public function getResourceLinkByContext(
?Course $course = null,
?Session $session = null,
?CGroup $group = null,
?Usergroup $usergroup = null,
?User $user = null,
): ?ResourceLink {
$criteria = Criteria::create();
$criteria->where(
Criteria::expr()->eq('resourceTypeGroup', $this->resourceType->getId())
);
if ($course) {
$criteria->andWhere(
Criteria::expr()->eq('course', $course)
);
}
if ($session) {
$criteria->andWhere(
Criteria::expr()->eq('session', $session)
);
}
if ($usergroup) {
$criteria->andWhere(
Criteria::expr()->eq('userGroup', $usergroup)
);
}
if ($group) {
$criteria->andWhere(
Criteria::expr()->eq('group', $group)
);
}
if ($user) {
$criteria->andWhere(
Criteria::expr()->eq('user', $user)
);
}
$first = $this
->resourceLinks
->matching($criteria)
->first()
;
return $first ?: null;
}
public function setResourceLinks(Collection $resourceLinks): self
{
$this->resourceLinks = $resourceLinks;
@ -423,7 +469,10 @@ class ResourceNode implements Stringable
public function addResourceLink(ResourceLink $link): self
{
$link->setResourceNode($this);
$link
->setResourceNode($this)
->setResourceTypeGroup($this->resourceType->getId())
;
$this->resourceLinks->add($link);
return $this;
@ -582,16 +631,4 @@ class ResourceNode implements Stringable
return $this;
}
public function getDisplayOrder(): int
{
return $this->displayOrder;
}
public function setDisplayOrder(int $displayOrder): self
{
$this->displayOrder = $displayOrder;
return $this;
}
}

@ -9,8 +9,10 @@ namespace Chamilo\CoreBundle\Migrations;
use Chamilo\CoreBundle\Entity\AbstractResource;
use Chamilo\CoreBundle\Entity\AccessUrl;
use Chamilo\CoreBundle\Entity\Admin;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\ResourceInterface;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\SettingsCurrent;
use Chamilo\CoreBundle\Entity\SettingsOptions;
use Chamilo\CoreBundle\Entity\User;
@ -18,6 +20,8 @@ use Chamilo\CoreBundle\Repository\Node\UserRepository;
use Chamilo\CoreBundle\Repository\ResourceRepository;
use Chamilo\CoreBundle\Repository\SessionRepository;
use Chamilo\CourseBundle\Repository\CGroupRepository;
use DateTime;
use DateTimeZone;
use Doctrine\Migrations\AbstractMigration;
use Doctrine\ORM\EntityManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
@ -260,6 +264,7 @@ abstract class AbstractMigrationChamilo extends AbstractMigration implements Con
$userId = (int) $item['insert_user_id'];
$sessionId = $item['session_id'] ?? 0;
$groupId = $item['to_group_id'] ?? 0;
$lastUpdatedAt = new DateTime($item['lastedit_date'], new DateTimeZone('UTC'));
$newVisibility = ResourceLink::VISIBILITY_DRAFT;
@ -273,11 +278,6 @@ abstract class AbstractMigrationChamilo extends AbstractMigration implements Con
case 1:
$newVisibility = ResourceLink::VISIBILITY_PUBLISHED;
break;
case 2:
$newVisibility = ResourceLink::VISIBILITY_DELETED;
break;
}
@ -321,6 +321,12 @@ abstract class AbstractMigrationChamilo extends AbstractMigration implements Con
$em->persist($resourceNode);
}
$resource->addCourseLink($course, $session, $group, $newVisibility);
if (2 === $visibility) {
$link = $resource->getResourceNode()->getResourceLinkByContext($course, $session, $group);
$link->setDeletedAt($lastUpdatedAt);
}
$em->persist($resource);
}
@ -331,4 +337,22 @@ abstract class AbstractMigrationChamilo extends AbstractMigration implements Con
{
return file_exists($filePath) && !is_dir($filePath) && is_readable($filePath);
}
public function findCourse(int $id): ?Course
{
if (0 === $id) {
return null;
}
return $this->getEntityManager()->find(Course::class, $id);
}
public function findSession(int $id): ?Session
{
if (0 === $id) {
return null;
}
return $this->getEntityManager()->find(Session::class, $id);
}
}

@ -33,14 +33,11 @@ class Version20170525122900 extends AbstractMigrationChamilo
);
$this->addSql('CREATE UNIQUE INDEX UNIQ_8A5F48FFD17F50A6 ON resource_node (uuid)');
$this->addSql('ALTER TABLE resource_node ADD public TINYINT(1) NOT NULL');
$this->addSql(
'ALTER TABLE resource_node ADD display_order INT NOT NULL'
);
}
if (!$schema->hasTable('resource_link')) {
$this->addSql(
"CREATE TABLE resource_link (id INT AUTO_INCREMENT NOT NULL, resource_node_id INT DEFAULT NULL, session_id INT DEFAULT NULL, user_id INT DEFAULT NULL, c_id INT DEFAULT NULL, group_id INT DEFAULT NULL, usergroup_id INT DEFAULT NULL, visibility INT NOT NULL, start_visibility_at DATETIME DEFAULT NULL, end_visibility_at DATETIME DEFAULT NULL, created_at DATETIME NOT NULL COMMENT '(DC2Type:datetime)', updated_at DATETIME NOT NULL COMMENT '(DC2Type:datetime)', INDEX IDX_398C394B1BAD783F (resource_node_id), INDEX IDX_398C394B613FECDF (session_id), INDEX IDX_398C394BA76ED395 (user_id), INDEX IDX_398C394B91D79BD3 (c_id), INDEX IDX_398C394BFE54D947 (group_id), INDEX IDX_398C394BD2112630 (usergroup_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT = DYNAMIC;"
"CREATE TABLE resource_link (id INT AUTO_INCREMENT NOT NULL, resource_node_id INT DEFAULT NULL, c_id INT DEFAULT NULL, session_id INT DEFAULT NULL, usergroup_id INT DEFAULT NULL, group_id INT DEFAULT NULL, user_id INT DEFAULT NULL, visibility INT NOT NULL, start_visibility_at DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime)', end_visibility_at DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime)', display_order INT NOT NULL, resource_type_group INT NOT NULL, created_at DATETIME NOT NULL COMMENT '(DC2Type:datetime)', updated_at DATETIME NOT NULL COMMENT '(DC2Type:datetime)', deleted_at DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime)', INDEX IDX_398C394B1BAD783F (resource_node_id), INDEX IDX_398C394B91D79BD3 (c_id), INDEX IDX_398C394B613FECDF (session_id), INDEX IDX_398C394BD2112630 (usergroup_id), INDEX IDX_398C394BFE54D947 (group_id), INDEX IDX_398C394BA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC;"
);
}

@ -7,9 +7,7 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\ResourceNode;
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
use Chamilo\CoreBundle\Repository\Node\CourseRepository;
use Chamilo\CourseBundle\Entity\CLp;
use Chamilo\CourseBundle\Repository\CLpRepository;
use Doctrine\DBAL\Connection;
@ -32,7 +30,6 @@ final class Version20230615213500 extends AbstractMigrationChamilo
$connection = $em->getConnection();
$lpRepo = $container->get(CLpRepository::class);
$courseRepo = $container->get(CourseRepository::class);
$q = $em->createQuery('SELECT c FROM Chamilo\CoreBundle\Entity\Course c');
@ -52,13 +49,15 @@ final class Version20230615213500 extends AbstractMigrationChamilo
$resource = $lpRepo->find($lpId);
if ($resource->hasResourceNode()) {
$resourceNode = $resource->getResourceNode();
$resourceNodeId = $resourceNode->getId();
$item = $em->find(ResourceNode::class, $resourceNodeId);
if ($item) {
$item->setDisplayOrder($position);
$em->persist($item);
}
$course = $this->findCourse((int) $lp['c_id']);
$session = $this->findSession((int) ($lp['session_id'] ?? 0));
$link = $resourceNode->getResourceLinkByContext($course, $session);
$link?->setDisplayOrder(
$position > 0 ? $position - 1 : 0
);
}
}
}

@ -6,6 +6,7 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
use Chamilo\CoreBundle\Entity\AbstractResource;
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
use Chamilo\CourseBundle\Repository\CAnnouncementRepository;
use Chamilo\CourseBundle\Repository\CGlossaryRepository;
@ -14,7 +15,6 @@ use Chamilo\CourseBundle\Repository\CLinkCategoryRepository;
use Chamilo\CourseBundle\Repository\CLinkRepository;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Schema\Schema;
use Exception;
final class Version20240112191200 extends AbstractMigrationChamilo
{
@ -38,44 +38,53 @@ final class Version20240112191200 extends AbstractMigrationChamilo
$glossaryRepo = $container->get(CGlossaryRepository::class);
$announcementRepo = $container->get(CAnnouncementRepository::class);
$this->updateResourceNodeDisplayOrder($linkCategoryRepo, 'c_link_category', $em);
$this->updateResourceNodeDisplayOrder($linkRepo, 'c_link', $em);
$this->updateResourceNodeDisplayOrder($groupCategoryRepo, 'c_group_category', $em);
$this->updateResourceNodeDisplayOrder($glossaryRepo, 'c_glossary', $em);
$this->updateResourceNodeDisplayOrder($announcementRepo, 'c_announcement', $em);
$this->updateResourceNodeDisplayOrder($linkCategoryRepo, 'c_link_category', $em, $schema);
$this->updateResourceNodeDisplayOrder($linkRepo, 'c_link', $em, $schema);
$this->updateResourceNodeDisplayOrder($groupCategoryRepo, 'c_group_category', $em, $schema);
$this->updateResourceNodeDisplayOrder($glossaryRepo, 'c_glossary', $em, $schema);
$this->updateResourceNodeDisplayOrder($announcementRepo, 'c_announcement', $em, $schema);
}
private function updateResourceNodeDisplayOrder($resourceRepo, $tableName, $em): void
private function updateResourceNodeDisplayOrder($resourceRepo, $tableName, $em, Schema $schema): void
{
/** @var Connection $connection */
$connection = $em->getConnection();
try {
$testResult = $connection->executeQuery("SELECT display_order FROM $tableName LIMIT 1");
$columnExists = true;
} catch (Exception $e) {
$columnExists = false;
$table = $schema->getTable($tableName);
if (!$table->hasColumn('display_order')) {
return;
}
if ($columnExists) {
$sql = "SELECT * FROM $tableName ORDER BY display_order";
$result = $connection->executeQuery($sql);
$resources = $result->fetchAllAssociative();
foreach ($resources as $resourceData) {
$resourceId = (int) $resourceData['iid'];
$resourcePosition = (int) $resourceData['display_order'];
$resource = $resourceRepo->find($resourceId);
if ($resource && $resource->hasResourceNode()) {
$resourceNode = $resource->getResourceNode();
if ($resourceNode) {
$resourceNode->setDisplayOrder($resourcePosition);
}
}
$sql = "SELECT * FROM $tableName ORDER BY display_order";
$result = $connection->executeQuery($sql);
$resources = $result->fetchAllAssociative();
foreach ($resources as $resourceData) {
$resourceId = (int) $resourceData['iid'];
$resourcePosition = (int) $resourceData['display_order'];
/** @var AbstractResource $resource */
$resource = $resourceRepo->find($resourceId);
if (!$resource || !$resource->hasResourceNode()) {
continue;
}
$em->flush();
$resourceNode = $resource->getResourceNode();
if ($resourceNode) {
$course = $this->findCourse((int) $resourceData['c_id']);
$session = $this->findSession((int) ($resourceData['session_id'] ?? 0));
$link = $resourceNode->getResourceLinkByContext($course, $session);
$link?->setDisplayOrder(
$resourcePosition > 0 ? $resourcePosition - 1 : 0
);
}
}
$em->flush();
}
}

@ -0,0 +1,42 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
use Doctrine\DBAL\Schema\Schema;
class Version20240313111800 extends AbstractMigrationChamilo
{
private array $changes = [
'c_lp' => 'display_order',
'c_lp_category' => 'position',
'c_forum_category' => 'cat_order',
'c_forum_forum' => 'forum_order',
'c_thematic' => 'display_order',
'c_announcement' => 'display_order',
'c_glossary' => 'display_order',
];
public function getDescription(): string
{
$tables = array_keys($this->changes);
$columns = array_values($this->changes);
return sprintf(
'Removing %s columns from % tables',
implode(', ', $columns),
implode(', ', $tables)
);
}
public function up(Schema $schema): void
{
foreach ($this->changes as $table => $column) {
$this->addSql("ALTER TABLE $table DROP $column");
}
}
}

@ -0,0 +1,53 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\Repository;
use Chamilo\CoreBundle\Entity\AbstractResource;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Entity\Usergroup;
use Chamilo\CourseBundle\Entity\CGroup;
use Doctrine\ORM\EntityManagerInterface;
use Gedmo\Sortable\Entity\Repository\SortableRepository;
class ResourceLinkRepository extends SortableRepository
{
public function __construct(EntityManagerInterface $em)
{
parent::__construct($em, $em->getClassMetadata(ResourceLink::class));
}
public function remove(ResourceLink $resourceLink): void
{
$em = $this->getEntityManager();
// To move the resource link at the end to reorder the list
$resourceLink->setDisplayOrder(-1);
$em->flush();
// soft delete handled by Gedmo\SoftDeleteable
$em->remove($resourceLink);
$em->flush();
}
public function removeByResourceInContext(
AbstractResource $resource,
Course $course,
?Session $session = null,
?CGroup $group = null,
?Usergroup $usergroup = null,
?User $user = null,
): void {
$link = $resource->getResourceNode()->getResourceLinkByContext($course, $session, $group, $usergroup, $user);
if ($link) {
$this->remove($link);
}
}
}

@ -8,7 +8,6 @@ namespace Chamilo\CoreBundle\Repository;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\ResourceFile;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\ResourceNode;
use Chamilo\CoreBundle\Entity\ResourceType;
use Chamilo\CoreBundle\Entity\Session;
@ -145,7 +144,6 @@ class ResourceNodeRepository extends MaterializedPathRepository
->innerJoin('node.resourceLinks', 'l')
->where('node.resourceType = :type')
->andWhere('node.parent = :parentNode')
->andWhere('l.visibility <> :visibility')
->andWhere('file IS NOT NULL')
;
@ -154,7 +152,6 @@ class ResourceNodeRepository extends MaterializedPathRepository
$qb->andWhere('l.course = :course');
$params['course'] = $course;
}
$params['visibility'] = ResourceLink::VISIBILITY_DELETED;
$params['parentNode'] = $resourceNode;
$params['type'] = $type;

@ -282,12 +282,6 @@ abstract class ResourceRepository extends ServiceEntityRepository
$checker->isGranted('ROLE_ADMIN')
|| $checker->isGranted('ROLE_CURRENT_COURSE_TEACHER');
// Do not show deleted resources.
$qb
->andWhere('links.visibility != :visibilityDeleted')
->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED, Types::INTEGER)
;
if ($displayOnlyPublished) {
if (!$isAdminOrTeacher
|| ($checkStudentView && 'studentview' === $sessionStudentView)
@ -397,7 +391,7 @@ abstract class ResourceRepository extends ServiceEntityRepository
$this->addCourseSessionGroupQueryBuilder($course, $session, $group, $qb);
if ($displayOrder) {
$qb->orderBy('node.displayOrder', 'ASC');
$qb->orderBy('links.displayOrder', 'ASC');
}
return $qb;
@ -605,14 +599,6 @@ abstract class ResourceRepository extends ServiceEntityRepository
// }
}
/**
* Change all links visibility to DELETED.
*/
public function softDelete(AbstractResource $resource): void
{
$this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
}
public function toggleVisibilityPublishedDraft(AbstractResource $resource): void
{
$firstLink = $resource->getFirstResourceLink();
@ -638,11 +624,6 @@ abstract class ResourceRepository extends ServiceEntityRepository
$this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DRAFT);
}
public function setVisibilityDeleted(AbstractResource $resource): void
{
$this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
}
public function setVisibilityPending(AbstractResource $resource): void
{
$this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PENDING);
@ -729,12 +710,10 @@ abstract class ResourceRepository extends ServiceEntityRepository
->innerJoin('node.resourceLinks', 'l')
->innerJoin('node.resourceFile', 'file')
->where('l.course = :course')
->andWhere('l.visibility <> :visibility')
->andWhere('file IS NOT NULL')
->setParameters(
[
'course' => $course,
'visibility' => ResourceLink::VISIBILITY_DELETED,
]
)
;

@ -10,7 +10,6 @@
}
}
</script>
{% set configuration = 1 %}
<div class="panel-group my-8" role="tablist">
{% for lp_data in data %}
{% set show_category = true %}
@ -19,19 +18,20 @@
{% endif %}
{% if show_category %}
{% if configuration == 0 %}
{% if 'false' == chamilo_settings_get('lp.lp_category_accordion') %}
<!--- old view -->
{% if categories|length > 1 and lp_data.category.iid %}
{% if is_allowed_to_edit %}
<h3 class="page-header my-8
{% if lp_data.category_visibility == 0 %}
text-gray-400
{% else %}
text-gray-800
{% endif %}
">
{{ lp_data.category.getTitle() | trim }}
<div class="section-header section-header--h6">
{% if is_allowed_to_edit %}
<h6 class="section-header__title
{% if lp_data.category_visibility == 0 %}
text-gray-400
{% else %}
text-gray-800
{% endif %}
">
{{ lp_data.category.getTitle() | trim }}
</h6>
{% if lp_data.category.iid > 0 %}
{% if not session %}
<a href="{{ 'lp_controller.php?' ~ course_url_params ~ '&action=add_lp_category&id=' ~ lp_data.category.iid }}"
@ -88,8 +88,8 @@
</a>
{% else %}
<a
href="lp_controller.php?{{ course_url_params ~ '&' ~ {'action':'toggle_category_publish', 'id':lp_data.category.iid, 'new_status':0}|url_encode }}"
title="{{ 'Do not publish'|trans }}"
href="lp_controller.php?{{ course_url_params ~ '&' ~ {'action':'toggle_category_publish', 'id':lp_data.category.iid, 'new_status':0}|url_encode }}"
title="{{ 'Do not publish'|trans }}"
>
<i class="mdi-checkbox-multiple-blank mdi ch-tool-icon" style="font-size: 22px; width: 22px; height: 22px;" aria-hidden="true" title="{{ "Hide"|trans }}"></i>
</a>
@ -101,10 +101,10 @@
</a>
{% endif %}
{% endif %}
</h3>
{% elseif lp_data.lp_list is not empty %}
<h3 class="page-header">{{ lp_data.category.getTitle() }}</h3>
{% endif %}
{% elseif lp_data.lp_list is not empty %}
<h6 class="section-header__title">{{ lp_data.category.getTitle() }}</h6>
{% endif %}
</div>
{% endif %}
{% if lp_data.lp_list %}

@ -155,11 +155,6 @@ class ResourceNodeVoter extends Voter
// @todo implement view, edit, delete.
foreach ($links as $link) {
// Block access if visibility is deleted. Creator and admin have already access.
if (ResourceLink::VISIBILITY_DELETED === $link->getVisibility()) {
continue;
}
// Check if resource was sent to the current user.
$linkUser = $link->getUser();
if ($linkUser instanceof UserInterface

@ -13,7 +13,6 @@ use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Stringable;
use Symfony\Component\Validator\Constraints as Assert;
@ -46,7 +45,6 @@ class CForum extends AbstractResource implements ResourceInterface, Stringable
#[ORM\JoinColumn(name: 'forum_last_post', referencedColumnName: 'iid')]
protected ?CForumPost $forumLastPost = null;
#[Gedmo\SortableGroup]
#[ORM\ManyToOne(targetEntity: CForumCategory::class, inversedBy: 'forums')]
#[ORM\JoinColumn(name: 'forum_category', referencedColumnName: 'iid', nullable: true, onDelete: 'SET NULL')]
protected ?CForumCategory $forumCategory = null;
@ -75,10 +73,6 @@ class CForum extends AbstractResource implements ResourceInterface, Stringable
#[ORM\Column(name: 'forum_group_public_private', type: 'string', length: 20, nullable: true)]
protected ?string $forumGroupPublicPrivate;
#[Gedmo\SortablePosition]
#[ORM\Column(name: 'forum_order', type: 'integer', nullable: true)]
protected ?int $forumOrder = null;
#[ORM\Column(name: 'locked', type: 'integer', nullable: false)]
protected int $locked;
@ -289,18 +283,6 @@ class CForum extends AbstractResource implements ResourceInterface, Stringable
return $this;
}
public function setForumOrder(int $forumOrder): self
{
$this->forumOrder = $forumOrder;
return $this;
}
public function getForumOrder(): ?int
{
return $this->forumOrder;
}
public function setLocked(int $locked): self
{
$this->locked = $locked;

@ -32,9 +32,6 @@ class CForumCategory extends AbstractResource implements ResourceInterface, Stri
#[ORM\Column(name: 'cat_comment', type: 'text', nullable: true)]
protected ?string $catComment;
#[ORM\Column(name: 'cat_order', type: 'integer', nullable: false)]
protected int $catOrder;
#[ORM\Column(name: 'locked', type: 'integer', nullable: false)]
protected int $locked;
@ -89,18 +86,6 @@ class CForumCategory extends AbstractResource implements ResourceInterface, Stri
return $this->catComment;
}
public function setCatOrder(int $catOrder): self
{
$this->catOrder = $catOrder;
return $this;
}
public function getCatOrder(): int
{
return $this->catOrder;
}
public function setLocked(int $locked): self
{
$this->locked = $locked;

@ -62,9 +62,6 @@ class CLp extends AbstractResource implements ResourceInterface, ResourceShowCou
#[ORM\Column(name: 'default_encoding', type: 'string', length: 32, nullable: false, options: ['default' => 'UTF-8'])]
protected string $defaultEncoding;
#[ORM\Column(name: 'display_order', type: 'integer', nullable: false, options: ['default' => 0])]
protected int $displayOrder;
#[ORM\Column(name: 'content_maker', type: 'text', nullable: false)]
protected string $contentMaker;
@ -168,7 +165,6 @@ class CLp extends AbstractResource implements ResourceInterface, ResourceShowCou
$this->defaultEncoding = 'UTF-8';
$this->defaultViewMod = 'embedded';
$this->description = '';
$this->displayOrder = 0;
$this->debug = false;
$this->forceCommit = false;
$this->hideTocFrame = false;
@ -287,18 +283,6 @@ class CLp extends AbstractResource implements ResourceInterface, ResourceShowCou
return $this->defaultEncoding;
}
public function setDisplayOrder(int $displayOrder): self
{
$this->displayOrder = $displayOrder;
return $this;
}
public function getDisplayOrder(): int
{
return $this->displayOrder;
}
public function setContentMaker(string $contentMaker): self
{
$this->contentMaker = $contentMaker;

@ -13,7 +13,6 @@ use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Sortable\Entity\Repository\SortableRepository;
use Stringable;
use Symfony\Component\Validator\Constraints as Assert;
@ -34,10 +33,6 @@ class CLpCategory extends AbstractResource implements ResourceInterface, Stringa
#[ORM\Column(name: 'title', type: 'text')]
protected string $title;
#[Gedmo\SortablePosition]
#[ORM\Column(name: 'position', type: 'integer')]
protected int $position;
/**
* @var Collection<int, CLpCategoryRelUser>
*/
@ -81,18 +76,6 @@ class CLpCategory extends AbstractResource implements ResourceInterface, Stringa
return $this->title;
}
public function setPosition(int $position): self
{
$this->position = $position;
return $this;
}
public function getPosition(): int
{
return $this->position;
}
/**
* @return Collection<int, CLp>
*/

@ -33,9 +33,6 @@ class CThematic extends AbstractResource implements ResourceInterface, Stringabl
#[ORM\Column(name: 'content', type: 'text', nullable: true)]
protected ?string $content = null;
#[ORM\Column(name: 'display_order', type: 'integer', nullable: false)]
protected int $displayOrder;
#[ORM\Column(name: 'active', type: 'boolean', nullable: false)]
protected bool $active;
@ -57,7 +54,6 @@ class CThematic extends AbstractResource implements ResourceInterface, Stringabl
$this->plans = new ArrayCollection();
$this->advances = new ArrayCollection();
$this->active = true;
$this->displayOrder = 0;
}
public function __toString(): string
@ -92,21 +88,6 @@ class CThematic extends AbstractResource implements ResourceInterface, Stringabl
return $this->content;
}
public function setDisplayOrder(int $displayOrder): self
{
$this->displayOrder = $displayOrder;
return $this;
}
/**
* Get displayOrder.
*/
public function getDisplayOrder(): int
{
return $this->displayOrder;
}
public function setActive(bool $active): self
{
$this->active = $active;

@ -7,7 +7,6 @@ declare(strict_types=1);
namespace Chamilo\CourseBundle\Repository;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\ResourceNode;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\User;
@ -54,10 +53,8 @@ final class CDocumentRepository extends ResourceRepository
->innerJoin('d.resourceNode', 'node')
->innerJoin('node.resourceLinks', 'l')
->where('l.user = :user')
->andWhere('l.visibility <> :visibility')
->setParameters([
'user' => $userId,
'visibility' => ResourceLink::VISIBILITY_DELETED,
])
->getQuery()
;

@ -156,7 +156,6 @@ class ResourceNodeRepositoryTest extends AbstractApiTest
$link = (new ResourceLink())
->setVisibility(ResourceLink::VISIBILITY_PUBLISHED)
->setResourceNode($resourceNode)
->setUser($student)
->setCourse($course)
->setSession($session)
@ -167,7 +166,9 @@ class ResourceNodeRepositoryTest extends AbstractApiTest
->setStartVisibilityAt(new DateTime())
->setEndVisibilityAt(new DateTime())
;
$em->persist($link);
$resourceNode->addResourceLink($link);
$em->flush();
$em->clear();

@ -11,6 +11,7 @@ use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\ResourceNode;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Repository\Node\CourseRepository;
use Chamilo\CoreBundle\Repository\ResourceLinkRepository;
use Chamilo\CourseBundle\Entity\CDocument;
use Chamilo\CourseBundle\Entity\CGroup;
use Chamilo\CourseBundle\Repository\CDocumentRepository;
@ -982,6 +983,7 @@ class CDocumentRepositoryTest extends AbstractApiTest
{
$course = $this->createCourse('Test');
$documentRepo = self::getContainer()->get(CDocumentRepository::class);
$linksRepo = self::getContainer()->get(ResourceLinkRepository::class);
$admin = $this->getUser('admin');
$document = (new CDocument())
@ -1031,15 +1033,9 @@ class CDocumentRepositoryTest extends AbstractApiTest
$this->assertSame(ResourceLink::VISIBILITY_PENDING, $link->getVisibility());
$this->assertSame('Pending', $link->getVisibilityName());
$documentRepo->setVisibilityDeleted($document);
$link = $document->getFirstResourceLink();
$this->assertSame(ResourceLink::VISIBILITY_DELETED, $link->getVisibility());
$this->assertSame('Deleted', $link->getVisibilityName());
$documentRepo->softDelete($document);
$link = $document->getFirstResourceLink();
$this->assertSame(ResourceLink::VISIBILITY_DELETED, $link->getVisibility());
$this->assertSame('Deleted', $link->getVisibilityName());
$linksRepo->remove($link);
$this->assertTrue($link->isDeleted());
}
public function testGetTotalSpaceByCourse(): void

@ -34,18 +34,18 @@ class CForumCategoryRepositoryTest extends AbstractApiTest
$category = (new CForumCategory())
->setTitle('cat 1')
->setCatComment('comment')
->setCatOrder(1)
->setLocked(1)
->setParent($course)
->setCreator($teacher)
->addCourseLink($course)
;
$category->addCourseLink($course);
$this->assertHasNoEntityViolations($category);
$categoryRepo->create($category);
$this->assertSame($category->getIid(), $category->getResourceIdentifier());
$this->assertSame(1, $category->getLocked());
$this->assertSame(1, $category->getCatOrder());
$this->assertSame(0, $category->getResourceNode()->getResourceLinkByContext($course)?->getDisplayOrder());
$this->assertSame('comment', $category->getCatComment());
$this->assertSame('cat 1', (string) $category);

@ -26,16 +26,18 @@ class CLpCategoryRepositoryTest extends AbstractApiTest
$category = (new CLpCategory())
->setTitle('cat')
->setPosition(1)
->setParent($course)
->setCreator($teacher)
;
$category->addCourseLink($course);
$this->assertHasNoEntityViolations($category);
$em->persist($category);
$em->flush();
$link = $category->getResourceNode()->getResourceLinkByContext($course);
$this->assertSame($category->getResourceIdentifier(), $category->getIid());
$this->assertSame(1, $category->getPosition());
$this->assertSame(0, $link?->getDisplayOrder());
$this->assertSame('cat', (string) $category);
$this->assertSame(1, $repo->count([]));
@ -55,7 +57,6 @@ class CLpCategoryRepositoryTest extends AbstractApiTest
$category = (new CLpCategory())
->setTitle('cat')
->setPosition(1)
->setParent($course)
->setCreator($teacher)
;

@ -142,9 +142,6 @@ while ($row = Database::fetch_array($result, 'ASSOC')) {
case '1':
$newVisibility = ResourceLink::VISIBILITY_PUBLISHED;
break;
case '2':
$newVisibility = ResourceLink::VISIBILITY_DELETED;
break;
}
$link = new ResourceLink();
@ -157,6 +154,10 @@ while ($row = Database::fetch_array($result, 'ASSOC')) {
->setVisibility($newVisibility)
;
if (2 === (int) $row['visibility']) {
$link->setDeletedAt($lastUpdatedAt);
}
if (!empty($rights)) {
foreach ($rights as $right) {
$link->addResourceRight($right);

Loading…
Cancel
Save