Refactoring tools visibility in course home - refs BT#21219

See https://github.com/chamilo/chamilo-lms/pull/5045
pull/5064/head
Angel Fernando Quiroz Campos 2 years ago
parent 770d043943
commit 3ebefc6ca9
  1. 36
      assets/vue/components/course/CourseTool.vue
  2. 14
      assets/vue/services/courseService.js
  3. 57
      assets/vue/views/course/CourseHome.vue
  4. 17
      src/CoreBundle/ApiResource/AbstractResource.php
  5. 41
      src/CoreBundle/ApiResource/CourseTool.php
  6. 73
      src/CoreBundle/Controller/CourseController.php
  7. 46
      src/CoreBundle/DataProvider/Extension/CToolExtension.php
  8. 74
      src/CoreBundle/DataTransformer/CourseToolDataTranformer.php
  9. 69
      src/CoreBundle/Filter/CidFilter.php
  10. 105
      src/CoreBundle/Filter/SidFilter.php
  11. 101
      src/CoreBundle/State/CToolProvider.php
  12. 2
      src/CoreBundle/Tool/AbstractTool.php
  13. 6
      src/CoreBundle/Traits/CourseControllerTrait.php
  14. 54
      src/CoreBundle/Traits/CourseFromRequestTrait.php
  15. 29
      src/CourseBundle/Entity/CTool.php

@ -1,9 +1,9 @@
<template>
<div class="course-tool">
<router-link
v-if="to"
:aria-labelledby="`course-tool-${tool.ctool.iid}`"
:to="to"
v-if="tool.to"
:aria-labelledby="`course-tool-${tool.iid}`"
:to="tool.to"
class="course-tool__link hover:primary-gradient"
:class="cardCustomClass"
>
@ -15,8 +15,8 @@
</router-link>
<a
v-else
:aria-labelledby="`course-tool-${tool.ctool.iid}`"
:href="url"
:aria-labelledby="`course-tool-${tool.iid}`"
:href="tool.url"
class="course-tool__link"
:class="cardCustomClass"
>
@ -28,19 +28,19 @@
</a>
<router-link
v-if="to"
:id="`course-tool-${tool.ctool.iid}`"
v-if="tool.to"
:id="`course-tool-${tool.iid}`"
:class="titleCustomClass"
:to="to"
:to="tool.to"
class="course-tool__title"
>
{{ tool.tool.nameToShow }}
</router-link>
<a
v-else
:id="`course-tool-${tool.ctool.iid}`"
:id="`course-tool-${tool.iid}`"
v-t="tool.tool.nameToShow"
:href="url"
:href="tool.url"
class="course-tool__title"
:class="titleCustomClass"
/>
@ -104,24 +104,10 @@ const isCustomizing = inject("isCustomizing")
// eslint-disable-next-line no-undef
const props = defineProps({
course: {
type: Object,
required: true,
},
tool: {
type: Object,
required: true,
},
url: {
type: String,
required: false,
default: () => null,
},
to: {
type: String,
required: false,
default: () => null,
},
changeVisibility: {
type: Function,
required: true,
@ -153,5 +139,5 @@ const titleCustomClass = computed(() => {
}
return ""
})
const isVisible = computed(() => props.tool.ctool.resourceNode.resourceLinks[0].visibility === 2)
const isVisible = computed(() => props.tool.resourceNode.resourceLinks[0].visibility === 2)
</script>

@ -13,6 +13,20 @@ const courseService = {
return data
},
loadCTools: async (courseId, sessionId = 0) => {
const { data } = await axios.get(ENTRYPOINT + 'c_tools', {
params: {
cid: courseId,
sid: sessionId,
order: {
position: 'asc'
}
},
})
return data["hydra:member"]
},
/**
* @param {Object} tool
* @param {number} newIndex

@ -184,13 +184,10 @@
v-for="(tool, index) in tools"
:key="'tool-' + index.toString()"
:change-visibility="changeVisibility"
:course="course"
:data-index="index"
:data-tool="tool.ctool.name"
:data-tool="tool.name"
:go-to-setting-course-tool="goToSettingCourseTool"
:to="tool.to"
:tool="tool"
:url="tool.url"
/>
<ShortCutList
@ -222,9 +219,9 @@ import StudentViewButton from "../../components/StudentViewButton.vue"
import Sortable from "sortablejs"
import { checkIsAllowedToEdit } from "../../composables/userPermissions"
import { useCidReqStore } from "../../store/cidReq"
import {storeToRefs} from "pinia";
import courseService from "../../services/courseService";
import CourseIntroduction from "../../components/course/CourseIntroduction.vue";
import { storeToRefs } from "pinia"
import courseService from "../../services/courseService"
import CourseIntroduction from "../../components/course/CourseIntroduction.vue"
import { usePlatformConfig } from "../../store/platformConfig"
const store = useStore()
@ -238,7 +235,7 @@ const { getSetting } = storeToRefs(platformConfigStore)
const tools = ref([])
const shortcuts = ref([])
const courseIntroEl = ref(null);
const courseIntroEl = ref(null)
const isCourseLoading = ref(true)
@ -254,29 +251,43 @@ const courseItems = ref([])
const routerTools = ["document", "link", "glossary", "agenda", "student_publication", "course_homepage"]
courseService.loadTools(course.value.id, session.value?.id)
.then((data) => {
tools.value = data.tools.map((element) => {
if (routerTools.includes(element.ctool.name)) {
courseService.loadCTools(course.value.id, session.value?.id)
.then((cTools) => {
tools.value = cTools.map(element => {
if (routerTools.includes(element.name)) {
element.to = element.url
}
return element
})
shortcuts.value = data.shortcuts
const noAdminToolsIndex = []
courseItems.value = tools.value
.filter((element, index) => {
if ("admin" === element.tool.category) {
noAdminToolsIndex.push(index)
return true
}
let adminTool = tools.value.filter((element) => element.category === "admin")
return false
})
.map(adminTool => ({
label: adminTool.tool.nameToShow,
url: adminTool.url,
}))
if (Array.isArray(adminTool)) {
courseItems.value = adminTool.map((tool) => ({
label: tool.tool.nameToShow,
url: tool.url,
}))
}
noAdminToolsIndex.reverse().forEach((element) => tools.value.splice(element, 1))
isCourseLoading.value = false
})
courseService
.loadTools(course.value.id, session.value?.id)
.then((data) => {
shortcuts.value = data.shortcuts
})
.catch((error) => console.log(error))
const courseTMenu = ref(null)
@ -299,12 +310,12 @@ function goToShortCut(shortcut) {
}
const setToolVisibility = (tool, visibility) => {
tool.ctool.resourceNode.resourceLinks[0].visibility = visibility
tool.resourceNode.resourceLinks[0].visibility = visibility
}
function changeVisibility(tool) {
axios
.post(ENTRYPOINT + "../r/course_tool/links/" + tool.ctool.resourceNode.id + "/change_visibility?cid=" + course.value.id + "&sid=" + session.value?.id)
.post(ENTRYPOINT + "../r/course_tool/links/" + tool.resourceNode.id + "/change_visibility?cid=" + course.value.id + "&sid=" + session.value?.id)
.then((response) => setToolVisibility(tool, response.data.visibility))
.catch((error) => console.log(error))
}
@ -353,7 +364,7 @@ async function updateDisplayOrder(htmlItem, newIndex) {
if (typeof tools !== "undefined" && Array.isArray(tools.value)) {
const toolList = tools.value
toolItem = toolList.find((element) => element.tool.name === tool)
toolItem = toolList.find((element) => element.name === tool)
} else {
console.error("Error: tools.value is undefined")
return

@ -0,0 +1,17 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;
abstract class AbstractResource
{
#[Groups([
'ctool:read',
])]
public ?string $illustrationUrl = null;
}

@ -0,0 +1,41 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\ApiResource;
use Chamilo\CoreBundle\Entity\ResourceNode;
use Chamilo\CoreBundle\Tool\AbstractTool;
use Symfony\Component\Serializer\Annotation\Groups;
class CourseTool extends AbstractResource
{
#[Groups(['ctool:read'])]
public ?int $iid = null;
#[Groups(['ctool:read'])]
public string $name;
#[Groups(['ctool:read'])]
public ?bool $visibility = null;
#[Groups(['ctool:read'])]
public AbstractTool $tool;
#[Groups(['ctool:read'])]
public ?ResourceNode $resourceNode = null;
#[Groups(['ctool:read'])]
public string $url;
#[Groups(['ctool:read'])]
public string $category = '';
#[Groups(['ctool:read'])]
public function getNameToTranslate(): string
{
return ucfirst(str_replace('_', ' ', $this->name));
}
}

@ -9,7 +9,6 @@ namespace Chamilo\CoreBundle\Controller;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\CourseRelUser;
use Chamilo\CoreBundle\Entity\ExtraField;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\SessionRelUser;
use Chamilo\CoreBundle\Entity\Tag;
@ -140,7 +139,7 @@ class CourseController extends ToolBaseController
if (!empty($requestData) && isset($requestData['toolItem'])) {
$index = $requestData['index'];
$toolItem = $requestData['toolItem'];
$toolId = (int) $toolItem['ctool']['iid'];
$toolId = (int) $toolItem['iid'];
/** @var CTool $cTool */
$cTool = $em->find(CTool::class, $toolId);
@ -203,75 +202,6 @@ class CourseController extends ToolBaseController
];
Event::registerLog($logInfo);
$qb = $toolRepository->getResourcesByCourse($course, $this->getSession(), null, null, false);
$qb->addSelect('tool');
$qb->innerJoin('resource.tool', 'tool');
$skipTools = ['course_tool', 'chat', 'notebook', 'wiki', 'course_homepage'];
$qb->andWhere($qb->expr()->notIn('resource.name', $skipTools));
$qb->addOrderBy('resource.position', 'ASC');
$result = $qb->getQuery()->getResult();
$tools = [];
$toolsToDisplay = [];
$isAdmin = ($user->hasRole('ROLE_SUPER_ADMIN') || $user->hasRole('ROLE_ADMIN'));
$isCourseTeacher = ($user->hasRole('ROLE_CURRENT_COURSE_TEACHER') || $user->hasRole('ROLE_CURRENT_COURSE_SESSION_TEACHER'));
$currentSessionId = (int) $sessionId;
/** @var CTool $item */
foreach ($result as $item) {
$toolModel = $toolChain->getToolFromName($item->getTool()->getName());
if (!($isCourseTeacher || $isAdmin) && 'admin' === $toolModel->getCategory()) {
continue;
}
$resourceNodeId = $item->getResourceNode()->getId();
$selectedLink = null;
$linkSessionId = null;
$hasNullSessionIdDraftLink = false;
foreach ($item->getResourceNode()->getResourceLinks() as $link) {
$linkSessionId = $link->getSession() ? $link->getSession()->getId() : null;
if ($isInASession && null === $linkSessionId && ResourceLink::VISIBILITY_DRAFT === $link->getVisibility()) {
$hasNullSessionIdDraftLink = true;
$selectedLink = $link;
break;
}
if ($linkSessionId === $currentSessionId) {
$selectedLink = $link;
break;
}
if (null === $linkSessionId && !$selectedLink) {
$selectedLink = $link;
}
}
if ($hasNullSessionIdDraftLink || ($isInASession && (null === $linkSessionId && ResourceLink::VISIBILITY_DRAFT === $selectedLink->getVisibility()))) {
continue;
}
if ($selectedLink) {
if (!($isCourseTeacher || $isAdmin) && ResourceLink::VISIBILITY_DRAFT === $selectedLink->getVisibility()) {
continue;
}
$item->getResourceNode()->getResourceLinks()->first()->setVisibility($selectedLink->getVisibility());
$toolsToDisplay[$resourceNodeId] = [
'ctool' => $item,
'tool' => $toolModel,
'url' => $this->generateToolUrl($toolModel),
'category' => $toolModel->getCategory(),
];
}
}
foreach ($toolsToDisplay as $toolData) {
$tools[] = $toolData;
}
// Deleting the objects
$sessionHandler->remove('toolgroup');
$sessionHandler->remove('_gid');
@ -289,7 +219,6 @@ class CourseController extends ToolBaseController
$responseData = [
'shortcuts' => $shortcuts,
'diagram' => '',
'tools' => $tools,
];
$json = $this->serializer->serialize(

@ -0,0 +1,46 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
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;
use Doctrine\ORM\QueryBuilder;
class CToolExtension implements QueryCollectionExtensionInterface
{
use ControllerTrait;
use CourseControllerTrait;
public function applyToCollection(
QueryBuilder $queryBuilder,
QueryNameGeneratorInterface $queryNameGenerator,
string $resourceClass,
Operation $operation = null,
array $context = []
): void {
if (CTool::class !== $resourceClass) {
return;
}
$alias = $queryBuilder->getRootAliases()[0];
$queryBuilder
->innerJoin("$alias.resourceNode", 'resource_node')
->innerJoin('resource_node.resourceLinks', 'resource_links')
->andWhere(
$queryBuilder->expr()->notIn("$alias.name", ['course_tool', 'course_homepage'])
)
->andWhere('resource_links.visibility != :visibility_deleted')
->setParameter('visibility_deleted', ResourceLink::VISIBILITY_DELETED)
;
}
}

@ -0,0 +1,74 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\DataTransformer;
use ApiPlatform\Core\DataTransformer\DataTransformerInterface;
use Chamilo\CoreBundle\ApiResource\CourseTool;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Tool\AbstractTool;
use Chamilo\CoreBundle\Tool\ToolChain;
use Chamilo\CoreBundle\Traits\CourseFromRequestTrait;
use Chamilo\CourseBundle\Entity\CTool;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class CourseToolDataTranformer implements DataTransformerInterface
{
use CourseFromRequestTrait;
public function __construct(
protected RequestStack $requestStack,
protected EntityManagerInterface $entityManager,
protected readonly ToolChain $toolChain,
) {}
public function transform($object, string $to, array $context = [])
{
\assert($object instanceof CTool);
$tool = $object->getTool();
$toolModel = $this->toolChain->getToolFromName(
$tool->getName()
);
$course = $this->getCourse();
$cTool = new CourseTool();
$cTool->iid = $object->getIid();
$cTool->name = $object->getName();
$cTool->visibility = $object->getVisibility();
$cTool->resourceNode = $object->resourceNode;
$cTool->illustrationUrl = $object->illustrationUrl;
$cTool->url = $this->generateToolUrl($toolModel, $course);
$cTool->tool = $toolModel;
return $cTool;
}
private function generateToolUrl(AbstractTool $tool, Course $course): string
{
$link = $tool->getLink();
if (strpos($link, 'nodeId')) {
$nodeId = (string) $course->getResourceNode()->getId();
$link = str_replace(':nodeId', $nodeId, $link);
}
return $link.'?'
.http_build_query([
'cid' => $this->getCourse()->getId(),
'sid' => $this->getSession()?->getId(),
'gid' => 0,
]);
}
public function supportsTransformation($data, string $to, array $context = []): bool
{
return $data instanceof CTool && CourseTool::class === $to;
}
}

@ -0,0 +1,69 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\Filter;
use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use Chamilo\CoreBundle\Traits\CourseFromRequestTrait;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
class CidFilter extends AbstractFilter
{
use CourseFromRequestTrait;
public function __construct(
protected RequestStack $requestStack,
protected EntityManagerInterface $entityManager,
ManagerRegistry $managerRegistry,
LoggerInterface $logger = null,
array $properties = null,
NameConverterInterface $nameConverter = null,
) {
parent::__construct($managerRegistry, $logger, $properties, $nameConverter);
}
public function getDescription(string $resourceClass): array
{
return [
'cid' => [
'property' => null,
'type' => 'int',
'required' => true,
'description' => 'Course identifier',
],
];
}
protected function filterProperty(
string $property,
$value,
QueryBuilder $queryBuilder,
QueryNameGeneratorInterface $queryNameGenerator,
string $resourceClass,
Operation $operation = null,
array $context = []
): void {
if ('cid' !== $property) {
return;
}
$course = $this->getCourse();
$queryBuilder
->andWhere(
$queryBuilder->expr()->eq('resource_links.course', ':course')
)
->setParameter('course', $course->getId())
;
}
}

@ -0,0 +1,105 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\Filter;
use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use Chamilo\CoreBundle\Entity\ResourceShowCourseResourcesInSessionInterface;
use Chamilo\CoreBundle\Traits\CourseFromRequestTrait;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;
use Psr\Log\LoggerInterface;
use ReflectionClass;
use ReflectionException;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
class SidFilter extends AbstractFilter
{
use CourseFromRequestTrait;
public function __construct(
protected RequestStack $requestStack,
protected EntityManagerInterface $entityManager,
ManagerRegistry $managerRegistry,
LoggerInterface $logger = null,
array $properties = null,
NameConverterInterface $nameConverter = null
) {
parent::__construct($managerRegistry, $logger, $properties, $nameConverter);
}
public function getDescription(string $resourceClass): array
{
return [
'sid' => [
'property' => null,
'type' => 'string',
'required' => false,
'description' => 'Course identifier',
],
];
}
/**
* @param mixed $value
*
* @throws ReflectionException
*/
protected function filterProperty(
string $property,
$value,
QueryBuilder $queryBuilder,
QueryNameGeneratorInterface $queryNameGenerator,
string $resourceClass,
Operation $operation = null,
array $context = []
): void {
if ('sid' !== $property) {
return;
}
$reflection = new ReflectionClass($resourceClass);
$loadBaseSessionContent = \in_array(
ResourceShowCourseResourcesInSessionInterface::class,
$reflection->getInterfaceNames(),
true
);
// Session was set with a kernel request from CoreBundle\EventListener\CourseListener class
$session = $this->getSession();
if (null === $session) {
$queryBuilder->andWhere(
$queryBuilder->expr()->orX(
$queryBuilder->expr()->isNull('resource_links.session'),
$queryBuilder->expr()->eq('resource_links.session', 0)
)
);
} elseif ($loadBaseSessionContent) {
$queryBuilder
->andWhere(
$queryBuilder->expr()->orX(
$queryBuilder->expr()->eq('resource_links.session', ':session'),
$queryBuilder->expr()->isNull('resource_links.session')
)
)
->setParameter('session', $session?->getId())
;
} else {
$queryBuilder
->andWhere(
$queryBuilder->expr()->eq('resource_links.session', ':session')
)
->setParameter('session', $session?->getId())
;
}
}
}

@ -0,0 +1,101 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\State;
use ApiPlatform\Doctrine\Orm\State\CollectionProvider;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\Pagination\PartialPaginatorInterface;
use ApiPlatform\State\ProviderInterface;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Settings\SettingsManager;
use Chamilo\CoreBundle\Tool\ToolChain;
use Chamilo\CoreBundle\Traits\CourseFromRequestTrait;
use Chamilo\CourseBundle\Entity\CTool;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Security;
/**
* @template-implements ProviderInterface<CTool>
*/
class CToolProvider implements ProviderInterface
{
use CourseFromRequestTrait;
public function __construct(
private readonly CollectionProvider $provider,
protected EntityManagerInterface $entityManager,
private readonly SettingsManager $settingsManager,
private readonly Security $security,
private readonly ToolChain $toolChain,
protected RequestStack $requestStack,
) {}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): array
{
/** @var PartialPaginatorInterface $result */
$result = $this->provider->provide($operation, $uriVariables, $context);
$request = $this->requestStack->getMainRequest();
$studentView = $request ? $request->getSession()->get('studentview') : 'studentview';
/** @var User|null $user */
$user = $this->security->getUser();
$isAllowToEdit = $user && ($user->hasRole('ROLE_ADMIN') || $user->hasRole('ROLE_CURRENT_COURSE_TEACHER'));
$isAllowToEditBack = $user && ($user->hasRole('ROLE_ADMIN') || $user->hasRole('ROLE_CURRENT_COURSE_TEACHER'));
$isAllowToSessionEdit = $user && ($user->hasRole('ROLE_ADMIN') || $user->hasRole('ROLE_CURRENT_COURSE_TEACHER') || $user->hasRole('ROLE_CURRENT_COURSE_SESSION_TEACHER'));
$allowVisibilityInSession = $this->settingsManager->getSetting('course.allow_edit_tool_visibility_in_session');
$session = $this->getSession();
$results = [];
/** @var CTool $cTool */
foreach ($result as $cTool) {
$toolModel = $this->toolChain->getToolFromName(
$cTool->getTool()->getName()
);
if (!$isAllowToEdit && 'admin' === $toolModel->getCategory()) {
continue;
}
$resourceLinks = $cTool->getResourceNode()->getResourceLinks();
if ($session && $allowVisibilityInSession) {
$sessionLink = $resourceLinks->findFirst(
fn (int $key, ResourceLink $resourceLink): bool => $resourceLink->getSession()?->getId() === $session->getId()
);
if ($sessionLink) {
// Set the session link as unique to include in repsonse
$resourceLinks->clear();
$resourceLinks->add($sessionLink);
$isAllowToEdit = $isAllowToSessionEdit;
} else {
$isAllowToEdit = $isAllowToEditBack;
}
}
if (!$isAllowToEdit || 'studentview' === $studentView) {
$notPublishedLink = ResourceLink::VISIBILITY_PUBLISHED !== $resourceLinks->first()->getVisibility();
if ($notPublishedLink) {
continue;
}
}
$results[] = $cTool;
}
return $results;
}
}

@ -19,6 +19,8 @@ abstract class AbstractTool
#[Groups(['ctool:read'])]
protected string $icon = '';
#[Groups(['ctool:read'])]
protected string $category = '';
protected string $link;
protected string $image;

@ -27,8 +27,6 @@ trait CourseControllerTrait
/**
* Gets the current Chamilo course based in the "_real_cid" session variable.
*
* @return Course
*/
/*public function getCourse()
{
@ -60,10 +58,8 @@ trait CourseControllerTrait
/**
* Gets the current Chamilo session based in the "sid" $_SESSION variable.
*
* @return Session|null
*/
public function getCourseSession()
public function getCourseSession(): ?Session
{
$request = $this->getRequest();

@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Traits;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\Session;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
trait CourseFromRequestTrait
{
protected RequestStack $requestStack;
protected EntityManagerInterface $entityManager;
public function getRequest(): ?Request
{
return $this->requestStack->getMainRequest();
}
public function getCourse(): ?Course
{
$request = $this->getRequest();
if ($request) {
$courseId = $request->getSession()->get('cid', 0);
}
if (empty($courseId)) {
return null;
}
return $this->entityManager->find(Course::class, $courseId);
}
public function getSession(): ?Session
{
$request = $this->getRequest();
if ($request) {
$sessionId = $request->getSession()->get('sid', 0);
}
if (empty($sessionId)) {
return null;
}
return $this->entityManager->find(Session::class, $sessionId);
}
}

@ -6,44 +6,53 @@ declare(strict_types=1);
namespace Chamilo\CourseBundle\Entity;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;
use Chamilo\CoreBundle\ApiResource\CourseTool;
use Chamilo\CoreBundle\Entity\AbstractResource;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\ResourceInterface;
use Chamilo\CoreBundle\Entity\ResourceShowCourseResourcesInSessionInterface;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\Tool;
use Chamilo\CoreBundle\Filter\CidFilter;
use Chamilo\CoreBundle\Filter\SidFilter;
use Chamilo\CoreBundle\State\CToolProvider;
use Chamilo\CourseBundle\Repository\CToolRepository;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Stringable;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
#[ApiResource(
operations: [
new GetCollection(),
],
normalizationContext: ['groups' => ['ctool:read']],
denormalizationContext: ['groups' => ['ctool:write']],
security: "is_granted('ROLE_ADMIN') or is_granted('ROLE_CURRENT_COURSE_TEACHER')"
output: CourseTool::class,
provider: CToolProvider::class,
)]
#[ORM\Table(name: 'c_tool')]
#[ORM\Index(columns: ['c_id'], name: 'course')]
#[ORM\Index(columns: ['session_id'], name: 'session_id')]
#[ORM\HasLifecycleCallbacks]
#[ORM\Entity(repositoryClass: CToolRepository::class)]
#[ApiFilter(CidFilter::class)]
#[ApiFilter(SidFilter::class)]
#[ApiFilter(OrderFilter::class, properties: ['position' => 'ASC'])]
class CTool extends AbstractResource implements ResourceInterface, ResourceShowCourseResourcesInSessionInterface, Stringable
{
#[Groups(['ctool:read'])]
#[ORM\Column(name: 'iid', type: 'integer')]
#[ORM\Id]
#[ORM\GeneratedValue]
protected ?int $iid = null;
#[Assert\NotBlank]
#[Groups(['ctool:read'])]
#[ORM\Column(name: 'name', type: 'text', nullable: false)]
protected string $name;
#[Groups(['ctool:read'])]
#[ORM\Column(name: 'visibility', type: 'boolean', nullable: true)]
protected ?bool $visibility = null;
@ -65,9 +74,6 @@ class CTool extends AbstractResource implements ResourceInterface, ResourceShowC
#[ORM\Column(name: 'position', type: 'integer')]
protected int $position;
#[Groups(['ctool:read'])]
protected string $nameToTranslate;
public function __construct()
{
$this->visibility = true;
@ -91,11 +97,6 @@ class CTool extends AbstractResource implements ResourceInterface, ResourceShowC
return $this;
}
public function getNameToTranslate(): string
{
return ucfirst(str_replace('_', ' ', $this->name));
}
public function getIid(): ?int
{
return $this->iid;

Loading…
Cancel
Save