Merge pull request #5291 from christianbeeznest/GH-5270-2

Platform: Refactor global events management - refs #5270
pull/5292/head
christianbeeznest 2 years ago committed by GitHub
commit 8d44d5e87e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      assets/vue/router/ccalendarevent.js
  2. 74
      assets/vue/views/ccalendarevent/CCalendarEventList.vue
  3. 20
      public/main/inc/ajax/agenda.ajax.php
  4. 85
      public/main/inc/lib/agenda.lib.php
  5. 13
      src/CoreBundle/ApiResource/CalendarEvent.php
  6. 2
      src/CoreBundle/Controller/Admin/IndexBlocksController.php
  7. 9
      src/CoreBundle/DataProvider/Extension/CCalendarEventExtension.php
  8. 8
      src/CoreBundle/DataTransformer/CalendarEventTransformer.php
  9. 49
      src/CoreBundle/Entity/Listener/ResourceListener.php
  10. 166
      src/CoreBundle/Entity/SysCalendar.php
  11. 65
      src/CoreBundle/Filter/GlobalEventFilter.php
  12. 102
      src/CoreBundle/Migrations/Schema/V200/Version20240323181500.php
  13. 29
      src/CoreBundle/Migrations/Schema/V200/Version20240323222700.php
  14. 19
      src/CoreBundle/Repository/SysCalendarRepository.php
  15. 2
      src/CourseBundle/Entity/CCalendarEvent.php
  16. 32
      src/CourseBundle/Repository/CCalendarEventRepository.php

@ -18,7 +18,8 @@ export default {
{
name: 'CCalendarEventList',
path: '',
component: () => import('../views/ccalendarevent/CCalendarEventList.vue')
component: () => import('../views/ccalendarevent/CCalendarEventList.vue'),
props: (route) => ({ type: route.query.type })
}
]
};

@ -1,10 +1,10 @@
<template>
<div class="flex flex-col gap-4">
<CalendarSectionHeader
<!--CalendarSectionHeader
@add-click="showAddEventDialog"
@my-students-schedule-click="goToMyStudentsSchedule"
@session-planning-click="goToSessionPanning"
/>
/-->
<FullCalendar
ref="cal"
@ -23,6 +23,7 @@
v-if="dialog"
ref="createForm"
:values="item"
:is-global="isGlobal"
/>
<template #footer>
<BaseButton
@ -72,17 +73,18 @@
/>
<BaseButton
v-if="showDeleteButton"
:label="t('Delete')"
icon="delete"
type="danger"
@click="confirmDelete"
/>
<BaseButton
v-if="allowToEdit"
v-if="allowToEdit && showEditButton"
:label="t('Edit')"
type="secondary"
@click="dialog = true"
/>
icon="delete"/>
</template>
</Dialog>
@ -128,6 +130,7 @@ import { useStore } from "vuex"
import { useI18n } from "vue-i18n"
import { useConfirm } from "primevue/useconfirm"
import { useFormatDate } from "../../composables/formatDate"
import { useRoute } from "vue-router"
import Loading from "../../components/Loading.vue"
import FullCalendar from "@fullcalendar/vue3"
@ -171,6 +174,8 @@ const allowToUnsubscribe = ref(false)
const currentUser = computed(() => store.getters["security/getUser"])
const { t } = useI18n()
const { appLocale } = useLocale()
const route = useRoute()
const isGlobal = ref(route.query.type === 'global')
let currentEvent = null
@ -203,13 +208,29 @@ async function getCalendarEvents({ startStr, endStr }) {
params.gid = group.value.id
}
if (route.query?.type === 'global') {
params.type = 'global'
}
const calendarEvents = await cCalendarEventService.findAll({ params }).then((response) => response.json())
return calendarEvents["hydra:member"].map((event) => ({
...event,
start: event.startDate,
end: event.endDate,
}))
return calendarEvents["hydra:member"].map((event) => {
let color = '#007BFF'
if (event.type === 'global') {
color = '#FF0000'
} else if (event.type === 'course') {
color = '#28a745'
} else if (event.type === 'session') {
color = '#800080'
}
return {
...event,
start: event.startDate,
end: event.endDate,
color,
}
})
}
const calendarLocale = allLocales.find(
@ -291,6 +312,32 @@ const calendarOptions = ref({
},
})
const currentContext = computed(() => {
if (route.query.type === 'global') {
return 'global'
} else if (course.value) {
return 'course'
} else if (session.value) {
return 'session'
} else {
return 'personal'
}
});
const allowAction = (eventType) => {
const contextRules = {
global: ['global'],
course: ['course'],
session: ['session'],
personal: ['personal']
};
return contextRules[currentContext.value].includes(eventType);
};
const showEditButton = computed(() => allowAction(item.value.type));
const showDeleteButton = computed(() => allowAction(item.value.type));
const cal = ref(null)
function reFetch() {
@ -359,6 +406,10 @@ function onCreateEventForm() {
let itemModel = createForm.value.v$.item.$model
if (isGlobal.value) {
itemModel.isGlobal = true
}
if (itemModel["@id"]) {
store.dispatch("ccalendarevent/update", itemModel)
} else {
@ -380,6 +431,11 @@ function onCreateEventForm() {
const toast = useToast()
watch(() => route.query.type, (newType) => {
isGlobal.value = newType === 'global'
reFetch()
})
watch(
() => store.state.ccalendarevent.created,
(created) => {

@ -177,26 +177,6 @@ switch ($action) {
$month,
$year
);
$agendaitems = Agenda::get_global_agenda_items(
$agendaitems,
$day,
$month,
$year,
$week,
"month_view"
);
if ('true' === api_get_setting('allow_personal_agenda')) {
/*$agendaitems = Agenda::get_personal_agenda_items(
$user_id,
$agendaitems,
$day,
$month,
$year,
$week,
"month_view"
);*/
}
Agenda::display_mymonthcalendar(
$user_id,
$agendaitems,

@ -3,8 +3,6 @@
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Course;
//use Chamilo\CoreBundle\Entity\PersonalAgenda;
use Chamilo\CoreBundle\Entity\SysCalendar;
use Chamilo\CoreBundle\Framework\Container;
use Chamilo\CourseBundle\Entity\CCalendarEvent;
use Chamilo\CourseBundle\Entity\CCalendarEventAttachment;
@ -57,8 +55,6 @@ class Agenda
$sessionId = 0
) {
// Table definitions
$this->tbl_global_agenda = Database::get_main_table(TABLE_MAIN_SYSTEM_CALENDAR);
//$this->tbl_personal_agenda = Database::get_main_table(TABLE_PERSONAL_AGENDA);
$this->tbl_course_agenda = Database::get_course_table(TABLE_AGENDA);
$this->table_repeat = Database::get_course_table(TABLE_AGENDA_REPEAT);
@ -365,24 +361,6 @@ class Agenda
}
}
break;
case 'admin':
if (api_is_platform_admin()) {
$event = new SysCalendar();
$color = SysCalendar::COLOR_SYSTEM_EVENT;
$event
->setTitle($title)
->setContent($content)
->setStartDate($start)
->setEndDate($end)
->setAllDay($allDay)
->setUrl(api_get_url_entity())
->setColor($color)
;
$em->persist($event);
$em->flush();
$id = $event->getId();
}
break;
}
return $id;
@ -811,26 +789,6 @@ class Agenda
return false;
break;
case 'admin':
case 'platform':
if (api_is_platform_admin()) {
$attributes = [
'title' => $title,
'start_date' => $start,
'end_date' => $end,
'all_day' => $allDay,
];
if ($updateContent) {
$attributes['content'] = $content;
}
Database::update(
$this->tbl_global_agenda,
$attributes,
['id = ?' => $id]
);
}
break;
}
}
@ -925,14 +883,6 @@ class Agenda
}
}
break;
case 'admin':
if (api_is_platform_admin()) {
Database::delete(
$this->tbl_global_agenda,
['id = ?' => $id]
);
}
break;
}
}
@ -957,9 +907,6 @@ class Agenda
$format = 'json'
) {
switch ($this->type) {
case 'admin':
$this->getPlatformEvents($start, $end);
break;
case 'course':
$course = api_get_course_entity($courseId);
@ -1001,14 +948,6 @@ class Agenda
$sessionFilterActive = true;
}
if (false == $sessionFilterActive) {
// Getting personal events
//$this->getPersonalEvents($start, $end);
// Getting platform/admin events
$this->getPlatformEvents($start, $end);
}
$ignoreVisibility = ('true' === api_get_setting('agenda.personal_agenda_show_all_session_events'));
// Getting course events
@ -1171,12 +1110,6 @@ class Agenda
id = ".$id;
Database::query($sql);
break;
case 'admin':
$sql = "UPDATE $this->tbl_global_agenda SET
end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
WHERE id = ".$id;
Database::query($sql);
break;
}
}
@ -1222,14 +1155,6 @@ class Agenda
id=".$id;
Database::query($sql);
break;
case 'admin':
$sql = "UPDATE $this->tbl_global_agenda SET
all_day = $allDay,
start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE),
end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
WHERE id=".$id;
Database::query($sql);
break;
}
}
@ -1291,16 +1216,6 @@ class Agenda
}
}
break;
case 'admin':
case 'platform':
$sql = "SELECT * FROM ".$this->tbl_global_agenda."
WHERE id = $id";
$result = Database::query($sql);
if (Database::num_rows($result)) {
$event = Database::fetch_array($result, 'ASSOC');
$event['description'] = $event['content'];
}
break;
}
return $event;

@ -43,7 +43,20 @@ class CalendarEvent extends AbstractResource
#[Groups(['calendar_event:read'])]
public ?ResourceNode $resourceNode = null,
?array $resourceLinkListFromEntity = null,
#[Groups(['calendar_event:read'])]
public ?string $type = null,
) {
$this->resourceLinkListFromEntity = $resourceLinkListFromEntity;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(?string $type): self
{
$this->type = $type;
return $this;
}
}

@ -339,7 +339,7 @@ class IndexBlocksController extends BaseController
];
$items[] = [
'class' => 'item-global-agenda',
'url' => $this->generateUrl('legacy_main', ['name' => 'calendar/agenda_js.php', 'type' => 'admin']),
'url' => '/resources/ccalendarevent?type=global',
'label' => $this->translator->trans('Global agenda'),
];

@ -35,15 +35,20 @@ final class CCalendarEventExtension implements QueryCollectionExtensionInterface
?Operation $operation = null,
array $context = []
): void {
$this->addWhere($queryBuilder, $resourceClass);
$this->addWhere($queryBuilder, $resourceClass, $context);
}
private function addWhere(QueryBuilder $qb, string $resourceClass): void
private function addWhere(QueryBuilder $qb, string $resourceClass, array $context): void
{
if (CCalendarEvent::class !== $resourceClass) {
return;
}
$isGlobalType = isset($context['filters']['type']) && $context['filters']['type'] === 'global';
if ($isGlobalType) {
return;
}
$courseId = $this->cidReqHelper->getCourseId();
$sessionId = $this->cidReqHelper->getSessionId();
$groupId = $this->cidReqHelper->getGroupId();

@ -12,6 +12,7 @@ use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\SessionRelCourse;
use Chamilo\CoreBundle\Repository\Node\UsergroupRepository;
use Chamilo\CourseBundle\Entity\CCalendarEvent;
use Chamilo\CourseBundle\Repository\CCalendarEventRepository;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
@ -20,6 +21,7 @@ class CalendarEventTransformer implements DataTransformerInterface
public function __construct(
private readonly RouterInterface $router,
private readonly UsergroupRepository $usergroupRepository,
private readonly CCalendarEventRepository $calendarEventRepository
) {}
public function transform($object, string $to, array $context = []): object
@ -48,7 +50,8 @@ class CalendarEventTransformer implements DataTransformerInterface
$subscriptionItemTitle = $this->usergroupRepository->find($object->getSubscriptionItemId())?->getTitle();
}
return new CalendarEvent(
$eventType = $this->calendarEventRepository->determineEventType($object);
$calendarEvent = new CalendarEvent(
'calendar_event_'.$object->getIid(),
$object->getTitle(),
$object->getContent(),
@ -65,6 +68,9 @@ class CalendarEventTransformer implements DataTransformerInterface
$object->getResourceNode(),
$object->getResourceLinkListFromEntity(),
);
$calendarEvent->setType($eventType);
return $calendarEvent;
}
private function mapSessionToDto(object $object): CalendarEvent

@ -13,6 +13,7 @@ use Chamilo\CoreBundle\Entity\EntityAccessUrlInterface;
use Chamilo\CoreBundle\Entity\PersonalFile;
use Chamilo\CoreBundle\Entity\ResourceFile;
use Chamilo\CoreBundle\Entity\ResourceFormat;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\ResourceNode;
use Chamilo\CoreBundle\Entity\ResourceToRootInterface;
use Chamilo\CoreBundle\Entity\ResourceType;
@ -20,6 +21,7 @@ use Chamilo\CoreBundle\Entity\ResourceWithAccessUrlInterface;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Tool\ToolChain;
use Chamilo\CoreBundle\Traits\AccessUrlListenerTrait;
use Chamilo\CourseBundle\Entity\CCalendarEvent;
use Cocur\Slugify\SlugifyInterface;
use Doctrine\ORM\Event\PostUpdateEventArgs;
use Doctrine\ORM\Event\PrePersistEventArgs;
@ -257,6 +259,10 @@ class ResourceListener
throw new InvalidArgumentException($message);
}
if ($resource instanceof CCalendarEvent) {
$this->addCCalendarEventGlobalLink($resource, $eventArgs);
}
}
/**
@ -299,4 +305,47 @@ class ResourceListener
$slug = sprintf('%s.%s', $this->slugify->slugify($originalBasename), $originalExtension);*/
$resource->getResourceNode()->setTitle($resourceName);
}
private function addCCalendarEventGlobalLink(CCalendarEvent $event, PrePersistEventArgs $eventArgs): void
{
$currentRequest = $this->request->getCurrentRequest();
if (null === $currentRequest) {
return;
}
$type = $currentRequest->query->get('type');
if (null === $type) {
$content = $currentRequest->getContent();
$params = json_decode($content, true);
if (isset($params['isGlobal']) && 1 === (int) $params['isGlobal']) {
$type = 'global';
}
}
if ('global' === $type) {
$em = $eventArgs->getObjectManager();
$resourceNode = $event->getResourceNode();
$globalLink = new ResourceLink();
$globalLink->setCourse(null)
->setSession(null)
->setGroup(null)
->setUser(null);
$alreadyHasGlobalLink = false;
foreach ($resourceNode->getResourceLinks() as $existingLink) {
if (null === $existingLink->getCourse() && null === $existingLink->getSession() &&
null === $existingLink->getGroup() && null === $existingLink->getUser()) {
$alreadyHasGlobalLink = true;
break;
}
}
if (!$alreadyHasGlobalLink) {
$resourceNode->addResourceLink($globalLink);
$em->persist($globalLink);
}
}
}
}

@ -1,166 +0,0 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Entity;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
/**
* SysCalendar.
*/
#[ORM\Table(name: 'sys_calendar')]
#[ORM\Entity]
class SysCalendar
{
public const COLOR_SYSTEM_EVENT = '#FF0000';
#[ORM\Column(name: 'id', type: 'integer')]
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'IDENTITY')]
protected ?int $id = null;
#[ORM\Column(name: 'title', type: 'string', length: 255, nullable: false)]
protected string $title;
#[ORM\Column(name: 'content', type: 'text', nullable: true)]
protected ?string $content = null;
#[ORM\Column(name: 'start_date', type: 'datetime', nullable: true)]
protected ?DateTime $startDate = null;
#[ORM\Column(name: 'end_date', type: 'datetime', nullable: true)]
protected ?DateTime $endDate = null;
#[ORM\ManyToOne(targetEntity: AccessUrl::class)]
#[ORM\JoinColumn(name: 'access_url_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
protected AccessUrl $url;
#[ORM\Column(name: 'all_day', type: 'integer', nullable: false)]
protected int $allDay;
#[ORM\Column(name: 'color', type: 'string', length: 20, nullable: true)]
protected ?string $color = null;
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
/**
* Get title.
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
/**
* Get content.
*
* @return string
*/
public function getContent()
{
return $this->content;
}
public function setStartDate(DateTime $startDate): self
{
$this->startDate = $startDate;
return $this;
}
/**
* Get startDate.
*
* @return DateTime
*/
public function getStartDate()
{
return $this->startDate;
}
public function setEndDate(DateTime $endDate): self
{
$this->endDate = $endDate;
return $this;
}
/**
* Get endDate.
*
* @return DateTime
*/
public function getEndDate()
{
return $this->endDate;
}
public function setAllDay(int $allDay): self
{
$this->allDay = $allDay;
return $this;
}
/**
* Get allDay.
*
* @return int
*/
public function getAllDay()
{
return $this->allDay;
}
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
public function getColor(): ?string
{
return $this->color;
}
public function setColor(string $color): self
{
$this->color = $color;
return $this;
}
public function getUrl(): AccessUrl
{
return $this->url;
}
public function setUrl(AccessUrl $url): self
{
$this->url = $url;
return $this;
}
}

@ -0,0 +1,65 @@
<?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\ResourceNode;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;
use Psr\Log\LoggerInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
class GlobalEventFilter extends AbstractFilter
{
public function __construct(
ManagerRegistry $managerRegistry,
?LoggerInterface $logger = null,
?array $properties = null,
?NameConverterInterface $nameConverter = null
) {
parent::__construct($managerRegistry, $logger, $properties, $nameConverter);
}
protected function filterProperty(
string $property,
$value,
QueryBuilder $queryBuilder,
QueryNameGeneratorInterface $queryNameGenerator,
string $resourceClass,
?Operation $operation = null,
array $context = []
): void {
$isGlobalType = isset($context['filters']['type']) && $context['filters']['type'] === 'global';
if (!$isGlobalType) {
return;
}
$rootAlias = $queryBuilder->getRootAliases()[0];
$resourceNodeAlias = $queryNameGenerator->generateJoinAlias('resourceNode');
$resourceLinkAlias = $queryNameGenerator->generateJoinAlias('resourceLink');
$queryBuilder
->innerJoin("$rootAlias.resourceNode", $resourceNodeAlias)
->innerJoin("$resourceNodeAlias.resourceLinks", $resourceLinkAlias)
->andWhere("$resourceLinkAlias.course IS NULL")
->andWhere("$resourceLinkAlias.session IS NULL")
->andWhere("$resourceLinkAlias.group IS NULL")
->andWhere("$resourceLinkAlias.user IS NULL");
}
public function getDescription(string $resourceClass): array
{
return [
'type' => [
'property' => 'type',
'type' => 'string',
'required' => false,
'description' => 'Filter events by type. Use "global" to get global events.',
],
];
}
}

@ -0,0 +1,102 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
use Chamilo\CourseBundle\Entity\CCalendarEvent;
use DateTime;
use DateTimeZone;
use Doctrine\DBAL\Schema\Schema;
class Version20240323181500 extends AbstractMigrationChamilo
{
public function getDescription(): string
{
return 'Migrate sys_calendar to c_calendar_event';
}
public function up(Schema $schema): void
{
$em = $this->getEntityManager();
$sysCalendars = $this->connection->fetchAllAssociative('SELECT * FROM sys_calendar');
$utc = new DateTimeZone('UTC');
$admin = $this->getAdmin();
foreach ($sysCalendars as $sysCalendar) {
$calendarEvent = $this->createCCalendarEvent(
$sysCalendar['title'] ?: '-',
$sysCalendar['content'],
$sysCalendar['start_date'] ? new DateTime($sysCalendar['start_date'], $utc) : null,
$sysCalendar['end_date'] ? new DateTime($sysCalendar['end_date'], $utc) : null,
(bool) $sysCalendar['all_day'],
$sysCalendar['color'] ?? '',
$admin
);
$em->persist($calendarEvent);
$this->addGlobalResourceLinkToNode($em, $calendarEvent->getResourceNode());
}
$em->flush();
}
private function createCCalendarEvent(
string $title,
string $content,
?DateTime $startDate,
?DateTime $endDate,
bool $allDay,
string $color,
User $creator
): CCalendarEvent {
$calendarEvent = new CCalendarEvent();
$calendarEvent
->setTitle($title)
->setContent($content)
->setStartDate($startDate)
->setEndDate($endDate)
->setAllDay($allDay)
->setColor($color)
->setCreator($creator)
->setResourceName($title)
->setParentResourceNode($creator->getResourceNode()->getId())
;
return $calendarEvent;
}
private function addGlobalResourceLinkToNode($em, $resourceNode): void
{
$globalLink = new ResourceLink();
$globalLink->setCourse(null)
->setSession(null)
->setGroup(null)
->setUser(null);
$alreadyHasGlobalLink = false;
foreach ($resourceNode->getResourceLinks() as $existingLink) {
if (null === $existingLink->getCourse() && null === $existingLink->getSession() &&
null === $existingLink->getGroup() && null === $existingLink->getUser()) {
$alreadyHasGlobalLink = true;
break;
}
}
if (!$alreadyHasGlobalLink) {
$resourceNode->addResourceLink($globalLink);
$em->persist($globalLink);
}
}
public function down(Schema $schema): void
{
// Down migration is not defined, as data migration cannot be easily reverted
}
}

@ -0,0 +1,29 @@
<?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;
final class Version20240323222700 extends AbstractMigrationChamilo
{
public function getDescription(): string
{
return 'Remove the sys_calendar table';
}
public function up(Schema $schema): void
{
$this->addSql('DROP TABLE IF EXISTS sys_calendar');
}
public function down(Schema $schema): void
{
if (!$schema->hasTable('sys_calendar')) {
$this->addSql('CREATE TABLE sys_calendar (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, content LONGTEXT DEFAULT NULL, start_date DATETIME DEFAULT NULL, end_date DATETIME DEFAULT NULL, access_url_id INT DEFAULT NULL, all_day INT NOT NULL, color VARCHAR(20) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
}
}
}

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

@ -21,6 +21,7 @@ use Chamilo\CoreBundle\Entity\AbstractResource;
use Chamilo\CoreBundle\Entity\ResourceInterface;
use Chamilo\CoreBundle\Entity\Room;
use Chamilo\CoreBundle\Filter\CidFilter;
use Chamilo\CoreBundle\Filter\GlobalEventFilter;
use Chamilo\CoreBundle\Filter\SidFilter;
use Chamilo\CoreBundle\State\CalendarEventProvider;
use Chamilo\CoreBundle\State\CCalendarEventProcessor;
@ -67,6 +68,7 @@ use Symfony\Component\Validator\Constraints as Assert;
#[ApiFilter(filterClass: DateFilter::class, strategy: 'exclude_null')]
#[ApiFilter(filterClass: CidFilter::class)]
#[ApiFilter(filterClass: SidFilter::class)]
#[ApiFilter(GlobalEventFilter::class, properties: ["type"])]
class CCalendarEvent extends AbstractResource implements ResourceInterface, Stringable
{
public const COLOR_STUDENT_PUBLICATION = '#FF8C00';

@ -8,6 +8,7 @@ namespace Chamilo\CourseBundle\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\Repository\ResourceRepository;
@ -76,4 +77,35 @@ final class CCalendarEventRepository extends ResourceRepository
return $event;
}
public function determineEventType(CCalendarEvent $event): string
{
$em = $this->getEntityManager();
$queryBuilder = $em->createQueryBuilder();
$queryBuilder
->select('rl')
->from(ResourceLink::class, 'rl')
->innerJoin('rl.resourceNode', 'rn')
->where('rn.id = :resourceNodeId')
->setParameter('resourceNodeId', $event->getResourceNode()->getId());
$resourceLinks = $queryBuilder->getQuery()->getResult();
foreach ($resourceLinks as $link) {
if (null === $link->getCourse() && null === $link->getSession() && null === $link->getGroup() && null === $link->getUser()) {
return 'global';
}
if (null !== $link->getCourse()) {
return 'course';
}
if (null !== $link->getSession()) {
return 'session';
}
}
return 'personal';
}
}

Loading…
Cancel
Save