From e435f5220d05ce035afb434b44820690a7ee3df6 Mon Sep 17 00:00:00 2001 From: Julio Montoya Date: Thu, 6 Aug 2020 09:09:09 +0200 Subject: [PATCH] Plugins: Zoom - Add group add, meeting activity, refactor code BT#17288 --- main/inc/lib/api.lib.php | 9 + .../Entity/{MeetingEntity.php => Meeting.php} | 97 +- plugin/zoom/Entity/MeetingActivity.php | 176 +++ .../{RecordingEntity.php => Recording.php} | 18 +- .../{RegistrantEntity.php => Registrant.php} | 12 +- plugin/zoom/activity.php | 30 + plugin/zoom/admin.php | 30 - plugin/zoom/endpoint.php | 81 +- plugin/zoom/join_meeting.php | 21 +- ...tyRepository.php => MeetingRepository.php} | 29 +- ...Repository.php => RecordingRepository.php} | 13 +- ...epository.php => RegistrantRepository.php} | 6 +- plugin/zoom/lib/ZoomPlugin.php | 1084 +++++++++-------- plugin/zoom/meeting.php | 11 +- plugin/zoom/meetings.php | 2 +- plugin/zoom/start.php | 5 +- plugin/zoom/view/activity.tpl | 28 + plugin/zoom/view/list.tpl | 62 - plugin/zoom/view/meeting.tpl | 19 +- plugin/zoom/view/meetings.tpl | 62 + 20 files changed, 1064 insertions(+), 731 deletions(-) rename plugin/zoom/Entity/{MeetingEntity.php => Meeting.php} (86%) create mode 100644 plugin/zoom/Entity/MeetingActivity.php rename plugin/zoom/Entity/{RecordingEntity.php => Recording.php} (93%) rename plugin/zoom/Entity/{RegistrantEntity.php => Registrant.php} (95%) create mode 100644 plugin/zoom/activity.php delete mode 100644 plugin/zoom/admin.php rename plugin/zoom/lib/{MeetingEntityRepository.php => MeetingRepository.php} (88%) rename plugin/zoom/lib/{RecordingEntityRepository.php => RecordingRepository.php} (82%) rename plugin/zoom/lib/{RegistrantEntityRepository.php => RegistrantRepository.php} (82%) create mode 100644 plugin/zoom/view/activity.tpl delete mode 100644 plugin/zoom/view/list.tpl create mode 100644 plugin/zoom/view/meetings.tpl diff --git a/main/inc/lib/api.lib.php b/main/inc/lib/api.lib.php index dfbe047b72..2bab7f8907 100644 --- a/main/inc/lib/api.lib.php +++ b/main/inc/lib/api.lib.php @@ -2200,6 +2200,15 @@ function api_get_course_entity($courseId = 0) return Database::getManager()->getRepository('ChamiloCoreBundle:Course')->find($courseId); } +function api_get_group_entity($id = 0) +{ + if (empty($id)) { + $id = api_get_group_id(); + } + + return Database::getManager()->getRepository('ChamiloCourseBundle:CGroupInfo')->find($id); +} + /** * @param int $id * diff --git a/plugin/zoom/Entity/MeetingEntity.php b/plugin/zoom/Entity/Meeting.php similarity index 86% rename from plugin/zoom/Entity/MeetingEntity.php rename to plugin/zoom/Entity/Meeting.php index 3b6cdfac02..f030075d0e 100644 --- a/plugin/zoom/Entity/MeetingEntity.php +++ b/plugin/zoom/Entity/Meeting.php @@ -8,6 +8,7 @@ use Chamilo\CoreBundle\Entity\Course; use Chamilo\CoreBundle\Entity\CourseRelUser; use Chamilo\CoreBundle\Entity\Session; use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser; +use Chamilo\CourseBundle\Entity\CGroupInfo; use Chamilo\PluginBundle\Zoom\API\MeetingInfoGet; use Chamilo\PluginBundle\Zoom\API\MeetingListItem; use Chamilo\PluginBundle\Zoom\API\MeetingSettings; @@ -21,9 +22,9 @@ use Doctrine\ORM\Mapping as ORM; use Exception; /** - * Class MeetingEntity. + * Class Meeting. * - * @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\MeetingEntityRepository") + * @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\MeetingRepository") * @ORM\Table( * name="plugin_zoom_meeting", * indexes={ @@ -34,7 +35,7 @@ use Exception; * ) * @ORM\HasLifecycleCallbacks */ -class MeetingEntity +class Meeting { /** @var string meeting type name */ public $typeName; @@ -82,6 +83,13 @@ class MeetingEntity */ protected $course; + /** + * @var CGroupInfo + * @ORM\ManyToOne(targetEntity="Chamilo\CourseBundle\Entity\CGroupInfo") + * @ORM\JoinColumn(name="group_id", referencedColumnName="id", nullable=true) + */ + protected $group; + /** * @var Session * @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Session") @@ -108,16 +116,24 @@ class MeetingEntity protected $meetingInfoGet; /** - * @var RegistrantEntity[]|ArrayCollection + * @var MeetingActivity[]|ArrayCollection + * + * @ORM\OneToMany(targetEntity="MeetingActivity", mappedBy="meeting", cascade={"persist", "remove"}) + * + */ + protected $activities; + + /** + * @var Registrant[]|ArrayCollection + * + * @ORM\OneToMany(targetEntity="Registrant", mappedBy="meeting", cascade={"persist", "remove"}) * - * @ORM\OneToMany(targetEntity="RegistrantEntity", mappedBy="meeting", cascade={"persist", "remove"} - * ) */ protected $registrants; /** - * @var RecordingEntity[]|ArrayCollection - * @ORM\OneToMany(targetEntity="RecordingEntity", mappedBy="meeting", cascade={"persist"}, orphanRemoval=true) + * @var Recording[]|ArrayCollection + * @ORM\OneToMany(targetEntity="Recording", mappedBy="meeting", cascade={"persist"}, orphanRemoval=true) */ protected $recordings; @@ -125,6 +141,7 @@ class MeetingEntity { $this->registrants = new ArrayCollection(); $this->recordings = new ArrayCollection(); + $this->activities = new ArrayCollection(); } /** @@ -154,7 +171,7 @@ class MeetingEntity /** * @param int $meetingId * - * @return MeetingEntity + * @return Meeting */ public function setMeetingId($meetingId) { @@ -188,7 +205,7 @@ class MeetingEntity } /** - * @return RegistrantEntity[]|ArrayCollection + * @return Registrant[]|ArrayCollection */ public function getRegistrants() { @@ -196,13 +213,39 @@ class MeetingEntity } /** - * @return RecordingEntity[]|ArrayCollection + * @return Recording[]|ArrayCollection */ public function getRecordings() { return $this->recordings; } + /** + * @return MeetingActivity[]|ArrayCollection + */ + public function getActivities() + { + return $this->activities; + } + + public function addActivity(MeetingActivity $activity) + { + $activity->setMeeting($this); + $this->activities[] = $activity; + } + + /** + * @param MeetingActivity[]|ArrayCollection $activities + * + * @return Meeting + */ + public function setActivities($activities) + { + $this->activities = $activities; + + return $this; + } + /** * @ORM\PostLoad * @@ -294,19 +337,39 @@ class MeetingEntity return $this; } + /** + * @return CGroupInfo + */ + public function getGroup() + { + return $this->group; + } + + /** + * @param CGroupInfo $group + * + * @return Meeting + */ + public function setGroup($group) + { + $this->group = $group; + + return $this; + } + /** * @param MeetingListItem $meetingListItem * * @throws Exception * - * @return MeetingEntity + * @return Meeting */ public function setMeetingListItem($meetingListItem) { if (null === $this->meetingId) { $this->meetingId = $meetingListItem->id; } elseif ($this->meetingId != $meetingListItem->id) { - throw new Exception('the MeetingEntity identifier differs from the MeetingListItem identifier'); + throw new Exception('the Meeting identifier differs from the MeetingListItem identifier'); } $this->meetingListItem = $meetingListItem; @@ -318,14 +381,14 @@ class MeetingEntity * * @throws Exception * - * @return MeetingEntity + * @return Meeting */ public function setMeetingInfoGet($meetingInfoGet) { if (null === $this->meetingId) { $this->meetingId = $meetingInfoGet->id; } elseif ($this->meetingId != $meetingInfoGet->id) { - throw new Exception('the MeetingEntity identifier differs from the MeetingInfoGet identifier'); + throw new Exception('the Meeting identifier differs from the MeetingInfoGet identifier'); } $this->meetingInfoGet = $meetingInfoGet; $this->initializeDisplayableProperties(); @@ -439,7 +502,7 @@ class MeetingEntity public function hasRegisteredUser($user) { return $this->getRegistrants()->exists( - function (RegistrantEntity $registrantEntity) use (&$user) { + function (Registrant $registrantEntity) use (&$user) { return $registrantEntity->getUser() === $user; } ); @@ -448,7 +511,7 @@ class MeetingEntity /** * @param User $user * - * @return RegistrantEntity|null + * @return Registrant|null */ public function getRegistrant($user) { diff --git a/plugin/zoom/Entity/MeetingActivity.php b/plugin/zoom/Entity/MeetingActivity.php new file mode 100644 index 0000000000..f25bab979e --- /dev/null +++ b/plugin/zoom/Entity/MeetingActivity.php @@ -0,0 +1,176 @@ +id); + } + + /** + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * @return Meeting + */ + public function getMeeting() + { + return $this->meeting; + } + + /** + * @param Meeting $meeting + * + * @return MeetingActivity + */ + public function setMeeting($meeting) + { + $this->meeting = $meeting; + + return $this; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string $name + * + * @return MeetingActivity + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * @param string $type + * + * @return MeetingActivity + */ + public function setType($type) + { + $this->type = $type; + + return $this; + } + + /** + * @return string + */ + public function getEvent() + { + return $this->event; + } + + public function getEventDecoded() + { + if (!empty($this->event)) { + return json_decode($this->event); + } + + return ''; + } + + /** + * @param string $event + * + * @return MeetingActivity + */ + public function setEvent($event) + { + $this->event = $event; + + return $this; + } + + +} diff --git a/plugin/zoom/Entity/RecordingEntity.php b/plugin/zoom/Entity/Recording.php similarity index 93% rename from plugin/zoom/Entity/RecordingEntity.php rename to plugin/zoom/Entity/Recording.php index 64b8d7d28f..f39274c504 100644 --- a/plugin/zoom/Entity/RecordingEntity.php +++ b/plugin/zoom/Entity/Recording.php @@ -15,7 +15,7 @@ use Exception; /** * Class RecordingEntity. * - * @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\RecordingEntityRepository") + * @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\RecordingRepository") * @ORM\Table( * name="plugin_zoom_recording", * indexes={ @@ -24,7 +24,7 @@ use Exception; * ) * @ORM\HasLifecycleCallbacks */ -class RecordingEntity +class Recording { /** @var DateTime */ public $startDateTime; @@ -53,8 +53,8 @@ class RecordingEntity protected $uuid; /** - * @var MeetingEntity - * @ORM\ManyToOne(targetEntity="MeetingEntity", inversedBy="recordings") + * @var Meeting + * @ORM\ManyToOne(targetEntity="Meeting", inversedBy="recordings") * @ORM\JoinColumn(name="meeting_id") */ protected $meeting; @@ -93,7 +93,7 @@ class RecordingEntity } /** - * @return MeetingEntity + * @return Meeting */ public function getMeeting() { @@ -111,7 +111,7 @@ class RecordingEntity } /** - * @param MeetingEntity $meeting + * @param Meeting $meeting * * @return $this */ @@ -126,9 +126,9 @@ class RecordingEntity /** * @param RecordingMeeting $recordingMeeting * - * @throws Exception + * @return Recording + *@throws Exception * - * @return RecordingEntity */ public function setRecordingMeeting($recordingMeeting) { @@ -138,7 +138,7 @@ class RecordingEntity throw new Exception('the RecordingEntity identifier differs from the RecordingMeeting identifier'); } if (null === $this->meeting) { - $this->meeting = Database::getManager()->getRepository(MeetingEntity::class)->find($recordingMeeting->id); + $this->meeting = Database::getManager()->getRepository(Meeting::class)->find($recordingMeeting->id); } elseif ($this->meeting->getId() != $recordingMeeting->id) { // $this->meeting remains null when the remote RecordingMeeting refers to a deleted meeting. throw new Exception('The RecordingEntity meeting id differs from the RecordingMeeting meeting id'); diff --git a/plugin/zoom/Entity/RegistrantEntity.php b/plugin/zoom/Entity/Registrant.php similarity index 95% rename from plugin/zoom/Entity/RegistrantEntity.php rename to plugin/zoom/Entity/Registrant.php index 999a95ab82..ee9964644f 100644 --- a/plugin/zoom/Entity/RegistrantEntity.php +++ b/plugin/zoom/Entity/Registrant.php @@ -14,7 +14,7 @@ use Exception; /** * Class RegistrantEntity. * - * @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\RegistrantEntityRepository") + * @ORM\Entity(repositoryClass="RegistrantRepository") * @ORM\Table( * name="plugin_zoom_registrant", * indexes={ @@ -24,7 +24,7 @@ use Exception; * ) * @ORM\HasLifecycleCallbacks */ -class RegistrantEntity +class Registrant { /** @var string */ public $fullName; @@ -45,8 +45,8 @@ class RegistrantEntity protected $user; /** - * @var MeetingEntity - * @ORM\ManyToOne(targetEntity="MeetingEntity", inversedBy="registrants") + * @var Meeting + * @ORM\ManyToOne(targetEntity="Meeting", inversedBy="registrants") * @ORM\JoinColumn(name="meeting_id", referencedColumnName="id") */ protected $meeting; @@ -87,7 +87,7 @@ class RegistrantEntity } /** - * @return MeetingEntity + * @return Meeting */ public function getMeeting() { @@ -95,7 +95,7 @@ class RegistrantEntity } /** - * @param MeetingEntity $meeting + * @param Meeting $meeting * * @return $this */ diff --git a/plugin/zoom/activity.php b/plugin/zoom/activity.php new file mode 100644 index 0000000000..ab0ec67f20 --- /dev/null +++ b/plugin/zoom/activity.php @@ -0,0 +1,30 @@ +get_lang('ZoomVideoConferences'); +$tpl = new Template($plugin->get_lang('ZoomVideoConferences')); + +$meetingId = isset($_REQUEST['meetingId']) ? (int) $_REQUEST['meetingId'] : 0; +if (empty($meetingId)) { + api_not_allowed(true); +} + +$content = ''; +/** @var Meeting $meeting */ +$meeting = $plugin->getMeetingRepository()->findOneBy(['meetingId' => $meetingId]); +if (null === $meeting) { + api_not_allowed(true); +} + +$tpl->assign('actions', $plugin->getToolbar()); +$tpl->assign('meeting', $meeting); +$tpl->assign('content', $tpl->fetch('zoom/view/activity.tpl')); +$tpl->display_one_col_template(); diff --git a/plugin/zoom/admin.php b/plugin/zoom/admin.php deleted file mode 100644 index 65805c9ccd..0000000000 --- a/plugin/zoom/admin.php +++ /dev/null @@ -1,30 +0,0 @@ -get_lang('ZoomVideoConferences'); -$this_section = SECTION_PLATFORM_ADMIN; - -$form = $plugin->getAdminSearchForm(); -$startDate = new DateTime($form->getSubmitValue('start')); -$endDate = new DateTime($form->getSubmitValue('end')); - -$tpl = new Template($tool_name); - -$tpl->assign('meetings', $plugin->getMeetingRepository()->periodMeetings($startDate, $endDate)); -if ('true' === $plugin->get('enableCloudRecording')) { - $tpl->assign('recordings', $plugin->getRecordingRepository()->getPeriodRecordings($startDate, $endDate)); -} -$tpl->assign('actions', $plugin->getToolbar()); -$tpl->assign('search_form', $form->returnForm()); -$tpl->assign('type', 'admin'); -$tpl->assign('content', $tpl->fetch('zoom/view/list.tpl')); -$tpl->display_one_col_template(); diff --git a/plugin/zoom/endpoint.php b/plugin/zoom/endpoint.php index 503819809d..8740191f81 100644 --- a/plugin/zoom/endpoint.php +++ b/plugin/zoom/endpoint.php @@ -3,9 +3,10 @@ /* For license terms, see /license.txt */ use Chamilo\PluginBundle\Zoom\API\RecordingMeeting; -use Chamilo\PluginBundle\Zoom\MeetingEntity; -use Chamilo\PluginBundle\Zoom\RecordingEntity; -use Chamilo\PluginBundle\Zoom\RegistrantEntity; +use Chamilo\PluginBundle\Zoom\Meeting; +use Chamilo\PluginBundle\Zoom\MeetingActivity; +use Chamilo\PluginBundle\Zoom\Recording; +use Chamilo\PluginBundle\Zoom\Registrant; use Symfony\Component\HttpFoundation\Response; if ('POST' !== $_SERVER['REQUEST_METHOD']) { @@ -36,56 +37,63 @@ list($objectType, $action) = explode('.', $decoded->event); $em = Database::getManager(); -$meetingRepository = $em->getRepository(MeetingEntity::class); -$meetingEntity = null; +$meetingRepository = $em->getRepository(Meeting::class); +$meeting = null; if ($object->id) { - /** @var MeetingEntity $meetingEntity */ - $meetingEntity = $meetingRepository->findOneBy(['meetingId' => $object->id]); + /** @var Meeting $meeting */ + $meeting = $meetingRepository->findOneBy(['meetingId' => $object->id]); +} + +$activity = null; +if ($meeting) { + $activity = new MeetingActivity(); + $activity->setName($action); + $activity->setType($objectType); + $activity->setEvent(json_encode($object)); } switch ($objectType) { case 'meeting': - $registrantRepository = $em->getRepository(RegistrantEntity::class); + $registrantRepository = $em->getRepository(Registrant::class); - if (null === $meetingEntity) { + if (null === $meeting) { exit; } - error_log('Meeting '.$action.' - '.$meetingEntity->getId()); + error_log('Meeting '.$action.' - '.$meeting->getId()); error_log(print_r($object, 1)); switch ($action) { case 'deleted': - $em->remove($meetingEntity); + $em->remove($meeting); $em->flush(); break; case 'ended': case 'started': - $meetingEntity->setStatus($action); - $em->persist($meetingEntity); + $meeting->setStatus($action); + $meeting->addActivity($activity); + $em->persist($meeting); $em->flush(); break; case 'participant_joined': case 'participant_left': - error_log('Participant: #'.$object->participant->id); - error_log(print_r($object->participant, 1)); - /*$registrant = $registrantRepository->findOneBy(['meeting' => $meetingEntity, '' => $object->participant->id]); - if (null === $registrant) { - exit; - }*/ + $meeting->addActivity($activity); break; default: - error_log(sprintf('Event "%s" on %s was unhandled: %s', $action, $objectType, $body)); - - http_response_code(Response::HTTP_NOT_IMPLEMENTED); // Not Implemented + $meeting->addActivity($activity); + $em->persist($meeting); + $em->flush(); + //error_log(sprintf('Event "%s" on %s was unhandled: %s', $action, $objectType, $body)); + //http_response_code(Response::HTTP_NOT_IMPLEMENTED); // Not Implemented + break; } break; case 'recording': - $recordingRepository = $em->getRepository(RecordingEntity::class); + $recordingRepository = $em->getRepository(Recording::class); $recordingEntity = null; if ($object->uuid) { - $recordingEntity = $recordingRepository->findBy(['uuid' => $object->uuid, 'meeting' => $meetingEntity]); + $recordingEntity = $recordingRepository->findBy(['uuid' => $object->uuid, 'meeting' => $meeting]); } error_log("Recording: $action"); @@ -93,33 +101,42 @@ switch ($objectType) { switch ($action) { case 'completed': - $recording = new RecordingEntity(); + $recording = new Recording(); $recording->setRecordingMeeting(RecordingMeeting::fromObject($object)); - $recording->setMeeting($meetingEntity); + $recording->setMeeting($meeting); + $meeting->addActivity($activity); + $em->persist($meeting); $em->persist($recording); $em->flush(); break; case 'recovered': - if (null === $recordingEntity) { + /*if (null === $recordingEntity) { $em->persist( - (new RecordingEntity())->setRecordingMeeting(RecordingMeeting::fromObject($object)) + (new Recording())->setRecordingMeeting(RecordingMeeting::fromObject($object)) ); $em->flush(); - } + }*/ break; case 'trashed': case 'deleted': + $meeting->addActivity($activity); + $em->persist($meeting); if (null !== $recordingEntity) { $em->remove($recordingEntity); - $em->flush(); } + $em->flush(); break; default: - error_log(sprintf('Event "%s" on %s was unhandled: %s', $action, $objectType, $body)); - http_response_code(501); // Not Implemented + $meeting->addActivity($activity); + $em->persist($meeting); + $em->flush(); + //error_log(sprintf('Event "%s" on %s was unhandled: %s', $action, $objectType, $body)); + //http_response_code(501); // Not Implemented + break; } break; default: error_log(sprintf('Event "%s" on %s was unhandled: %s', $action, $objectType, $body)); http_response_code(501); // Not Implemented + break; } diff --git a/plugin/zoom/join_meeting.php b/plugin/zoom/join_meeting.php index 6c2909a5bc..746282fccb 100644 --- a/plugin/zoom/join_meeting.php +++ b/plugin/zoom/join_meeting.php @@ -2,7 +2,7 @@ /* For license terms, see /license.txt */ -use Chamilo\PluginBundle\Zoom\MeetingEntity; +use Chamilo\PluginBundle\Zoom\Meeting; require_once __DIR__.'/config.php'; @@ -15,26 +15,30 @@ if (empty($meetingId)) { } $plugin = ZoomPlugin::create(); -Display::display_header($plugin->get_title()); -echo $plugin->getToolbar(); -/** @var MeetingEntity $meeting */ +$content = ''; +/** @var Meeting $meeting */ $meeting = $plugin->getMeetingRepository()->findOneBy(['meetingId' => $meetingId]); + try { if (null === $meeting) { throw new Exception($plugin->get_lang('Meeting not found')); } + if ($meeting->isCourseMeeting()) { + api_protect_course_script(true); + } + $startJoinURL = $plugin->getStartOrJoinMeetingURL($meeting); - echo $meeting->getIntroduction(); + $content .= $meeting->getIntroduction(); if (!empty($startJoinURL)) { - echo Display::url($plugin->get_lang('EnterMeeting'), $startJoinURL, ['class' => 'btn btn-primary']); + $content .= Display::url($plugin->get_lang('EnterMeeting'), $startJoinURL, ['class' => 'btn btn-primary']); } else { //echo Display::return_message($plugin->get_lang('ConferenceNotStarted'), 'warning'); } if ($plugin->userIsConferenceManager($meeting)) { - echo ' '.Display::url( + $content .= ' '.Display::url( get_lang('Details'), api_get_path(WEB_PLUGIN_PATH).'zoom/meeting.php?meetingId='.$meeting->getMeetingId(), ['class' => 'btn btn-default'] @@ -46,4 +50,7 @@ try { ); } +Display::display_header($plugin->get_title()); +echo $plugin->getToolbar(); +echo $content; Display::display_footer(); diff --git a/plugin/zoom/lib/MeetingEntityRepository.php b/plugin/zoom/lib/MeetingRepository.php similarity index 88% rename from plugin/zoom/lib/MeetingEntityRepository.php rename to plugin/zoom/lib/MeetingRepository.php index 7f21bebda0..c5196ad486 100644 --- a/plugin/zoom/lib/MeetingEntityRepository.php +++ b/plugin/zoom/lib/MeetingRepository.php @@ -5,6 +5,7 @@ namespace Chamilo\PluginBundle\Zoom; use Chamilo\CoreBundle\Entity\Course; use Chamilo\CoreBundle\Entity\Session; +use Chamilo\CourseBundle\Entity\CGroupInfo; use Chamilo\PageBundle\Entity\User; use DateTime; use Doctrine\Common\Collections\ArrayCollection; @@ -14,9 +15,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; /** - * Class MeetingEntityRepository. + * Class MeetingRepository. */ -class MeetingEntityRepository extends EntityRepository +class MeetingRepository extends EntityRepository { /** * Retrieves information about meetings having a start_time between two dates. @@ -24,7 +25,7 @@ class MeetingEntityRepository extends EntityRepository * @param DateTime $startDate * @param DateTime $endDate * - * @return MeetingEntity[] + * @return Meeting[] */ public function periodMeetings($startDate, $endDate) { @@ -40,7 +41,7 @@ class MeetingEntityRepository extends EntityRepository } /** - * @return ArrayCollection|Collection|MeetingEntity[] + * @return ArrayCollection|Collection|Meeting[] */ public function globalMeetings() { @@ -55,7 +56,7 @@ class MeetingEntityRepository extends EntityRepository } /** - * @return ArrayCollection|Collection|MeetingEntity[] + * @return ArrayCollection|Collection|Meeting[] */ public function unfinishedGlobalMeetings() { @@ -134,7 +135,7 @@ class MeetingEntityRepository extends EntityRepository /** * @param User|null $user * - * @return MeetingEntity[] + * @return Meeting[] */ public function unfinishedUserMeetings($user = null) { @@ -160,7 +161,7 @@ class MeetingEntityRepository extends EntityRepository * @param DateTime $end * @param User $user * - * @return ArrayCollection|Collection|MeetingEntity[] + * @return ArrayCollection|Collection|Meeting[] */ public function periodUserMeetings($start, $end, $user = null) { @@ -186,18 +187,18 @@ class MeetingEntityRepository extends EntityRepository /** * Returns either a course's meetings or all course meetings. * - * @param Course|null $course - * @param Session|null $session + * @param Course|null $course + * @param Session|null $session + * @param CGroupInfo|null $group * - * @return ArrayCollection|Collection|MeetingEntity[] + * @return ArrayCollection|Collection|Meeting[] */ - public function courseMeetings($course = null, $session = null) + public function courseMeetings($course, $group = null, $session = null) { return $this->matching( Criteria::create()->where( - null === $course - ? Criteria::expr()->neq('course', null) - : Criteria::expr()->andX( + Criteria::expr()->andX( + Criteria::expr()->eq('group', $group), Criteria::expr()->eq('course', $course), Criteria::expr()->eq('session', $session) ) diff --git a/plugin/zoom/lib/RecordingEntityRepository.php b/plugin/zoom/lib/RecordingRepository.php similarity index 82% rename from plugin/zoom/lib/RecordingEntityRepository.php rename to plugin/zoom/lib/RecordingRepository.php index 4e64e5cb2a..959a70cbc9 100644 --- a/plugin/zoom/lib/RecordingEntityRepository.php +++ b/plugin/zoom/lib/RecordingRepository.php @@ -11,14 +11,15 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\EntityRepository; /** - * Class RecordingEntityRepository. + * Class RecordingRepository. */ -class RecordingEntityRepository extends EntityRepository +class RecordingRepository extends EntityRepository { public function getPeriodRecordings($startDate, $endDate) { $matching = []; - foreach ($this->findAll() as $candidate) { + $all = $this->findAll(); + foreach ($all as $candidate) { if ($candidate->startDateTime >= $startDate && $candidate->startDateTime <= $endDate) { $matching[] = $candidate; } @@ -32,7 +33,7 @@ class RecordingEntityRepository extends EntityRepository * * @param User $user * - * @return ArrayCollection|Collection|RecordingEntity[] + * @return ArrayCollection|Collection|Recording[] */ /*public function userRecordings($user) { @@ -40,7 +41,7 @@ class RecordingEntityRepository extends EntityRepository Criteria::create()->where( Criteria::expr()->in( 'meeting', - $this->getEntityManager()->getRepository(MeetingEntity::class)->userMeetings($user)->toArray() + $this->getEntityManager()->getRepository(Meeting::class)->userMeetings($user)->toArray() ) ) ); @@ -51,7 +52,7 @@ class RecordingEntityRepository extends EntityRepository * @param DateTime $end * @param User $user * - * @return ArrayCollection|RecordingEntity[] + * @return ArrayCollection|Recording[] */ /*public function getPeriodUserRecordings($start, $end, $user = null) { diff --git a/plugin/zoom/lib/RegistrantEntityRepository.php b/plugin/zoom/lib/RegistrantRepository.php similarity index 82% rename from plugin/zoom/lib/RegistrantEntityRepository.php rename to plugin/zoom/lib/RegistrantRepository.php index 9624e47215..66ba2aedb2 100644 --- a/plugin/zoom/lib/RegistrantEntityRepository.php +++ b/plugin/zoom/lib/RegistrantRepository.php @@ -12,21 +12,21 @@ use Doctrine\ORM\EntityRepository; /** * Class RegistrantEntityRepository. */ -class RegistrantEntityRepository extends EntityRepository +class RegistrantRepository extends EntityRepository { /** * Returns the upcoming meeting registrations for the given user. * * @param User $user * - * @return array|RegistrantEntity[] + * @return array|Registrant[] */ public function meetingsComingSoonRegistrationsForUser($user) { $start = new DateTime(); $end = new DateTime(); $end->add(new DateInterval('P7D')); - $meetings = $this->getEntityManager()->getRepository(MeetingEntity::class)->periodMeetings($start, $end); + $meetings = $this->getEntityManager()->getRepository(Meeting::class)->periodMeetings($start, $end); return $this->findBy(['meeting' => $meetings, 'user' => $user]); } diff --git a/plugin/zoom/lib/ZoomPlugin.php b/plugin/zoom/lib/ZoomPlugin.php index 5ebf7ef022..be9090c023 100644 --- a/plugin/zoom/lib/ZoomPlugin.php +++ b/plugin/zoom/lib/ZoomPlugin.php @@ -4,18 +4,20 @@ use Chamilo\CoreBundle\Entity\Course; use Chamilo\CoreBundle\Entity\Session; +use Chamilo\CourseBundle\Entity\CGroupInfo; use Chamilo\PluginBundle\Zoom\API\JWTClient; use Chamilo\PluginBundle\Zoom\API\MeetingInfoGet; use Chamilo\PluginBundle\Zoom\API\MeetingRegistrant; use Chamilo\PluginBundle\Zoom\API\MeetingSettings; use Chamilo\PluginBundle\Zoom\API\RecordingFile; use Chamilo\PluginBundle\Zoom\API\RecordingList; -use Chamilo\PluginBundle\Zoom\MeetingEntity; -use Chamilo\PluginBundle\Zoom\MeetingEntityRepository; -use Chamilo\PluginBundle\Zoom\RecordingEntity; -use Chamilo\PluginBundle\Zoom\RecordingEntityRepository; -use Chamilo\PluginBundle\Zoom\RegistrantEntity; -use Chamilo\PluginBundle\Zoom\RegistrantEntityRepository; +use Chamilo\PluginBundle\Zoom\Meeting; +use Chamilo\PluginBundle\Zoom\MeetingActivity; +use Chamilo\PluginBundle\Zoom\MeetingRepository; +use Chamilo\PluginBundle\Zoom\Recording; +use Chamilo\PluginBundle\Zoom\RecordingRepository; +use Chamilo\PluginBundle\Zoom\Registrant; +use Chamilo\PluginBundle\Zoom\RegistrantRepository; use Chamilo\UserBundle\Entity\User; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\OptimisticLockException; @@ -109,8 +111,7 @@ class ZoomPlugin extends Plugin && in_array( (api_is_platform_admin() ? PLATFORM_ADMIN : $user->getStatus()), (array) api_get_plugin_setting('zoom', 'globalConferenceAllowRoles') - ) - ; + ); } /** @@ -129,31 +130,7 @@ class ZoomPlugin extends Plugin && in_array( (api_is_platform_admin() ? PLATFORM_ADMIN : $user->getStatus()), (array) api_get_plugin_setting('zoom', 'globalConferencePerUserAllowRoles') - ) - ; - } - - /** - * @return array [ $title => $link ] - */ - public function meetingsToWhichCurrentUserIsRegisteredComingSoon() - { - $linkTemplate = api_get_path(WEB_PLUGIN_PATH).'zoom/join_meeting.php?meetingId=%s'; - $user = api_get_user_entity(api_get_user_id()); - $meetings = self::getRegistrantRepository()->meetingsComingSoonRegistrationsForUser($user); - $items = []; - foreach ($meetings as $registrant) { - $meeting = $registrant->getMeeting(); - $items[ - sprintf( - $this->get_lang('DateMeetingTitle'), - $meeting->formattedStartTime, - $meeting->getMeetingInfoGet()->topic - ) - ] = sprintf($linkTemplate, $meeting->getId()); - } - - return $items; + ); } /** @@ -189,27 +166,32 @@ class ZoomPlugin extends Plugin } /** - * @return MeetingEntityRepository|EntityRepository + * @return array [ $title => $link ] */ - public static function getMeetingRepository() + public function meetingsToWhichCurrentUserIsRegisteredComingSoon() { - return Database::getManager()->getRepository(MeetingEntity::class); - } + $linkTemplate = api_get_path(WEB_PLUGIN_PATH).'zoom/join_meeting.php?meetingId=%s'; + $user = api_get_user_entity(api_get_user_id()); + $meetings = self::getRegistrantRepository()->meetingsComingSoonRegistrationsForUser($user); + $items = []; + foreach ($meetings as $registrant) { + $meeting = $registrant->getMeeting(); + $items[sprintf( + $this->get_lang('DateMeetingTitle'), + $meeting->formattedStartTime, + $meeting->getMeetingInfoGet()->topic + )] = sprintf($linkTemplate, $meeting->getId()); + } - /** - * @return RecordingEntityRepository|EntityRepository - */ - public static function getRecordingRepository() - { - return Database::getManager()->getRepository(RecordingEntity::class); + return $items; } /** - * @return RegistrantEntityRepository|EntityRepository + * @return RegistrantRepository|EntityRepository */ public static function getRegistrantRepository() { - return Database::getManager()->getRepository(RegistrantEntity::class); + return Database::getManager()->getRepository(Registrant::class); } /** @@ -220,11 +202,14 @@ class ZoomPlugin extends Plugin */ public function install() { - (new SchemaTool(Database::getManager()))->createSchema([ - Database::getManager()->getClassMetadata(MeetingEntity::class), - Database::getManager()->getClassMetadata(RecordingEntity::class), - Database::getManager()->getClassMetadata(RegistrantEntity::class), - ]); + (new SchemaTool(Database::getManager()))->createSchema( + [ + Database::getManager()->getClassMetadata(Meeting::class), + Database::getManager()->getClassMetadata(MeetingActivity::class), + Database::getManager()->getClassMetadata(Recording::class), + Database::getManager()->getClassMetadata(Registrant::class), + ] + ); $this->install_course_fields_in_all_courses(); } @@ -234,11 +219,14 @@ class ZoomPlugin extends Plugin */ public function uninstall() { - (new SchemaTool(Database::getManager()))->dropSchema([ - Database::getManager()->getClassMetadata(MeetingEntity::class), - Database::getManager()->getClassMetadata(RecordingEntity::class), - Database::getManager()->getClassMetadata(RegistrantEntity::class), - ]); + (new SchemaTool(Database::getManager()))->dropSchema( + [ + Database::getManager()->getClassMetadata(Meeting::class), + Database::getManager()->getClassMetadata(MeetingActivity::class), + Database::getManager()->getClassMetadata(Recording::class), + Database::getManager()->getClassMetadata(Registrant::class), + ] + ); $this->uninstall_course_fields_in_all_courses(); } @@ -276,10 +264,12 @@ class ZoomPlugin extends Plugin $end->add($oneMonth); } try { - $form->setDefaults([ - 'start' => $start->format('Y-m-d'), - 'end' => $end->format('Y-m-d'), - ]); + $form->setDefaults( + [ + 'start' => $start->format('Y-m-d'), + 'end' => $end->format('Y-m-d'), + ] + ); } catch (Exception $exception) { error_log(join(':', [__FILE__, __LINE__, $exception])); } @@ -290,11 +280,11 @@ class ZoomPlugin extends Plugin /** * Generates a meeting edit form and updates the meeting on validation. * - * @param MeetingEntity $meeting the meeting + * @param Meeting $meeting the meeting * + * @return FormValidator * @throws Exception * - * @return FormValidator */ public function getEditMeetingForm($meeting) { @@ -352,40 +342,40 @@ class ZoomPlugin extends Plugin /** * Generates a meeting delete form and deletes the meeting on validation. * - * @param MeetingEntity $meetingEntity - * @param string $returnURL where to redirect to on successful deletion + * @param Meeting $meeting + * @param string $returnURL where to redirect to on successful deletion * + * @return FormValidator * @throws Exception * - * @return FormValidator */ - public function getDeleteMeetingForm($meetingEntity, $returnURL) + public function getDeleteMeetingForm($meeting, $returnURL) { - $id = $meetingEntity->getMeetingId(); + $id = $meeting->getMeetingId(); $form = new FormValidator('delete', 'post', api_get_self().'?meetingId='.$id); $form->addButtonDelete($this->get_lang('DeleteMeeting')); if ($form->validate()) { - $this->deleteMeeting($meetingEntity, $returnURL); + $this->deleteMeeting($meeting, $returnURL); } return $form; } /** - * @param MeetingEntity $meetingEntity - * @param string $returnURL + * @param Meeting $meeting + * @param string $returnURL * * @return false */ - public function deleteMeeting($meetingEntity, $returnURL) + public function deleteMeeting($meeting, $returnURL) { - if (null === $meetingEntity) { + if (null === $meeting) { return false; } $em = Database::getManager(); try { - $meetingEntity->getMeetingInfoGet()->delete(); - $em->remove($meetingEntity); + $meeting->getMeetingInfoGet()->delete(); + $em->remove($meeting); $em->flush(); Display::addFlash( @@ -397,24 +387,41 @@ class ZoomPlugin extends Plugin } } + /** + * @param Exception $exception + */ + public function handleException($exception) + { + if ($exception instanceof Exception) { + $error = json_decode($exception->getMessage()); + $message = $exception->getMessage(); + if ($error->message) { + $message = $error->message; + } + Display::addFlash( + Display::return_message($message, 'error') + ); + } + } + /** * Generates a registrant list update form listing course and session users. * Updates the list on validation. * - * @param MeetingEntity $meetingEntity + * @param Meeting $meeting * + * @return FormValidator * @throws Exception * - * @return FormValidator */ - public function getRegisterParticipantForm($meetingEntity) + public function getRegisterParticipantForm($meeting) { $form = new FormValidator('register', 'post', $_SERVER['REQUEST_URI']); $userIdSelect = $form->addSelect('userIds', $this->get_lang('RegisteredUsers')); $userIdSelect->setMultiple(true); $form->addButtonSend($this->get_lang('UpdateRegisteredUserList')); - $users = $meetingEntity->getRegistrableUsers(); + $users = $meeting->getRegistrableUsers(); foreach ($users as $user) { $userIdSelect->addOption( api_get_person_name($user->getFirstname(), $user->getLastname()), @@ -434,7 +441,7 @@ class ZoomPlugin extends Plugin } try { - $this->updateRegistrantList($meetingEntity, $selectedUsers); + $this->updateRegistrantList($meeting, $selectedUsers); Display::addFlash( Display::return_message($this->get_lang('RegisteredUserListWasUpdated'), 'confirm') ); @@ -445,7 +452,7 @@ class ZoomPlugin extends Plugin } } $registeredUserIds = []; - foreach ($meetingEntity->getRegistrants() as $registrant) { + foreach ($meeting->getRegistrants() as $registrant) { $registeredUserIds[] = $registrant->getUser()->getId(); } $userIdSelect->setSelected($registeredUserIds); @@ -454,31 +461,136 @@ class ZoomPlugin extends Plugin } /** - * @param Exception $exception + * Updates meeting registrants list. Adds the missing registrants and removes the extra. + * + * @param Meeting $meeting + * @param User[] $users list of users to be registered + * + * @throws Exception */ - public function handleException($exception) + private function updateRegistrantList($meeting, $users) { - if ($exception instanceof Exception) { - $error = json_decode($exception->getMessage()); - $message = $exception->getMessage(); - if ($error->message) { - $message = $error->message; + $usersToAdd = []; + foreach ($users as $user) { + $found = false; + foreach ($meeting->getRegistrants() as $registrant) { + if ($registrant->getUser() === $user) { + $found = true; + break; + } } - Display::addFlash( - Display::return_message($message, 'error') - ); + if (!$found) { + $usersToAdd[] = $user; + } + } + $registrantsToRemove = []; + foreach ($meeting->getRegistrants() as $registrant) { + $found = false; + foreach ($users as $user) { + if ($registrant->getUser() === $user) { + $found = true; + break; + } + } + if (!$found) { + $registrantsToRemove[] = $registrant; + } + } + $this->registerUsers($meeting, $usersToAdd); + $this->unregister($meeting, $registrantsToRemove); + } + + /** + * Register users to a meeting. + * + * @param Meeting $meeting + * @param User[] $users + * + * @return User[] failed registrations [ user id => errorMessage ] + * @throws OptimisticLockException + * + */ + private function registerUsers($meeting, $users) + { + $failedUsers = []; + foreach ($users as $user) { + try { + $this->registerUser($meeting, $user, false); + } catch (Exception $exception) { + $failedUsers[$user->getId()] = $exception->getMessage(); + } + } + Database::getManager()->flush(); + + return $failedUsers; + } + + /** + * @param Meeting $meeting + * @param User $user + * @param bool $andFlush + * + * @return Registrant + * @throws Exception + * + * @throws OptimisticLockException + */ + private function registerUser($meeting, $user, $andFlush = true) + { + if (empty($user->getEmail())) { + throw new Exception($this->get_lang('CannotRegisterWithoutEmailAddress')); + } + + $meetingRegistrant = MeetingRegistrant::fromEmailAndFirstName( + $user->getEmail(), + $user->getFirstname(), + $user->getLastname() + ); + + $registrantEntity = (new Registrant()) + ->setMeeting($meeting) + ->setUser($user) + ->setMeetingRegistrant($meetingRegistrant) + ->setCreatedRegistration($meeting->getMeetingInfoGet()->addRegistrant($meetingRegistrant)); + Database::getManager()->persist($registrantEntity); + if ($andFlush) { + Database::getManager()->flush($registrantEntity); + } + + return $registrantEntity; + } + + /** + * Removes registrants from a meeting. + * + * @param Meeting $meeting + * @param Registrant[] $registrants + * + * @throws Exception + */ + private function unregister($meeting, $registrants) + { + $meetingRegistrants = []; + foreach ($registrants as $registrant) { + $meetingRegistrants[] = $registrant->getMeetingRegistrant(); } + $meeting->getMeetingInfoGet()->removeRegistrants($meetingRegistrants); + $em = Database::getManager(); + foreach ($registrants as $registrant) { + $em->remove($registrant); + } + $em->flush(); } /** * Generates a meeting recording files management form. * Takes action on validation. * - * @param MeetingEntity $meeting + * @param Meeting $meeting * + * @return FormValidator * @throws Exception * - * @return FormValidator */ public function getFileForm($meeting) { @@ -577,81 +689,233 @@ class ZoomPlugin extends Plugin } /** - * Generates a form to fast and easily create and start an instant meeting. - * On validation, create it then redirect to it and exit. + * Adds to the meeting course documents a link to a meeting instance recording file. * - * @param User $user - * @param Course $course - * @param Session $session + * @param Meeting $meeting + * @param RecordingFile $file + * @param string $name * - * @return FormValidator + * @throws Exception */ - public function getCreateInstantMeetingForm($user, $course, $session) + public function createLinkToFileInCourse($meeting, $file, $name) { - $form = new FormValidator('createInstantMeetingForm', 'post', '', '_blank'); - $form->addButton('startButton', $this->get_lang('StartInstantMeeting'), 'video-camera', 'primary'); - if ($form->validate()) { - try { - $this->startInstantMeeting($this->get_lang('InstantMeeting'), $user, $course, $session); - } catch (Exception $exception) { - Display::addFlash( - Display::return_message($exception->getMessage(), 'error') - ); - } + $course = $meeting->getCourse(); + if (null === $course) { + throw new Exception('This meeting is not linked to a course'); + } + $courseInfo = api_get_course_info_by_id($course->getId()); + if (empty($courseInfo)) { + throw new Exception('This meeting is not linked to a valid course'); + } + $path = '/zoom_meeting_recording_file_'.$file->id.'.'.$file->file_type; + $docId = DocumentManager::addCloudLink($courseInfo, $path, $file->play_url, $name); + if (!$docId) { + throw new Exception( + get_lang( + DocumentManager::cloudLinkExists( + $courseInfo, + $path, + $file->play_url + ) ? 'UrlAlreadyExists' : 'ErrorAddCloudLink' + ) + ); } - - return $form; } /** - * Generates a form to schedule a meeting. - * On validation, creates it and redirects to its page. + * Copies a recording file to a meeting's course. * - * @param User|null $user - * @param Course|null $course - * @param Session|null $session + * @param Meeting $meeting + * @param RecordingFile $file + * @param string $name * * @throws Exception - * - * @return FormValidator */ - public function getScheduleMeetingForm($user, $course = null, $session = null) + public function copyFileToCourse($meeting, $file, $name) { - $form = new FormValidator('scheduleMeetingForm'); - $form->addHeader($this->get_lang('ScheduleAMeeting')); - $startTimeDatePicker = $form->addDateTimePicker('startTime', get_lang('StartTime')); - $form->setRequired($startTimeDatePicker); - - $form->addText('topic', $this->get_lang('Topic'), true); - $form->addTextarea('agenda', get_lang('Agenda'), ['maxlength' => 2000]); - - $durationNumeric = $form->addNumeric('duration', $this->get_lang('DurationInMinutes')); - $form->setRequired($durationNumeric); - + $course = $meeting->getCourse(); if (null === $course) { - $options = []; - if ('true' === $this->get('enableGlobalConference')) { - $options['everyone'] = $this->get_lang('ForEveryone'); - } - - if ('true' === $this->get('enableGlobalConferencePerUser')) { - $options['registered_users'] = $this->get_lang('SomeUsers'); - } - - if (!empty($options)) { - if (1 === count($options)) { - $form->addHidden('type', key($options)); - } else { - $form->addSelect('type', $this->get_lang('ConferenceType'), $options); - } - } - } else { - // To course - $form->addHidden('type', 'course'); + throw new Exception('This meeting is not linked to a course'); } - - // $passwordText = $form->addText('password', get_lang('Password'), false, ['maxlength' => '10']); - if (null !== $course) { + $courseInfo = api_get_course_info_by_id($course->getId()); + if (empty($courseInfo)) { + throw new Exception('This meeting is not linked to a valid course'); + } + $tmpFile = tmpfile(); + if (false === $tmpFile) { + throw new Exception('tmpfile() returned false'); + } + $curl = curl_init($file->getFullDownloadURL($this->jwtClient->token)); + if (false === $curl) { + throw new Exception('Could not init curl: '.curl_error($curl)); + } + if (!curl_setopt_array( + $curl, + [ + CURLOPT_FILE => $tmpFile, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 120, + ] + )) { + throw new Exception("Could not set curl options: ".curl_error($curl)); + } + if (false === curl_exec($curl)) { + throw new Exception("curl_exec failed: ".curl_error($curl)); + } + $newPath = handle_uploaded_document( + $courseInfo, + [ + 'name' => $name, + 'tmp_name' => stream_get_meta_data($tmpFile)['uri'], + 'size' => filesize(stream_get_meta_data($tmpFile)['uri']), + 'from_file' => true, + 'type' => $file->file_type, + ], + '/', + api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document', + api_get_user_id(), + 0, + null, + 0, + '', + true, + false, + null, + $meeting->getSession()->getId(), + true + ); + fclose($tmpFile); + if (false === $newPath) { + throw new Exception('could not handle uploaded document'); + } + } + + /** + * Generates a form to fast and easily create and start an instant meeting. + * On validation, create it then redirect to it and exit. + * + * @param User $user + * @param Course $course + * @param Session $session + * + * @return FormValidator + */ + public function getCreateInstantMeetingForm($user, $course, $group, $session) + { + $form = new FormValidator('createInstantMeetingForm', 'post', '', '_blank'); + $form->addButton('startButton', $this->get_lang('StartInstantMeeting'), 'video-camera', 'primary'); + if ($form->validate()) { + try { + $this->startInstantMeeting($this->get_lang('InstantMeeting'), $user, $course, $group, $session); + } catch (Exception $exception) { + Display::addFlash( + Display::return_message($exception->getMessage(), 'error') + ); + } + } + + return $form; + } + + /** + * Starts a new instant meeting and redirects to its start url. + * + * @param string $topic + * @param User|null $user + * @param Course|null $course + * @param CGroupInfo|null $group + * @param Session|null $session + * + * @throws Exception + */ + private function startInstantMeeting($topic, $user = null, $course = null, $group = null, $session = null) + { + $meeting = $this->createMeetingFromMeeting( + (new Meeting()) + ->setMeetingInfoGet(MeetingInfoGet::fromTopicAndType($topic, MeetingInfoGet::TYPE_INSTANT)) + ->setUser($user) + ->setGroup($group) + ->setCourse($course) + ->setSession($session) + ); + api_location($meeting->getMeetingInfoGet()->start_url); + } + + /** + * Creates a meeting on Zoom servers and stores it in the local database. + * + * @param Meeting $meeting a new, unsaved meeting with at least a type and a topic + * + * @return Meeting + * @throws Exception + * + */ + private function createMeetingFromMeeting($meeting) + { + $approvalType = $meeting->getMeetingInfoGet()->settings->approval_type; + $meeting->getMeetingInfoGet()->settings->auto_recording = 'true' === $this->get('enableCloudRecording') + ? 'cloud' + : 'local'; + $meeting->getMeetingInfoGet()->settings->registrants_email_notification = false; + $meeting->setMeetingInfoGet($meeting->getMeetingInfoGet()->create()); + $meeting->getMeetingInfoGet()->settings->approval_type = $approvalType; + + Database::getManager()->persist($meeting); + Database::getManager()->flush(); + + return $meeting; + } + + /** + * Generates a form to schedule a meeting. + * On validation, creates it and redirects to its page. + * + * @param User|null $user + * @param Course|null $course + * @param Session|null $session + * + * @return FormValidator + * @throws Exception + * + */ + public function getScheduleMeetingForm($user, $course = null, $group = null, $session = null) + { + $form = new FormValidator('scheduleMeetingForm'); + $form->addHeader($this->get_lang('ScheduleAMeeting')); + $startTimeDatePicker = $form->addDateTimePicker('startTime', get_lang('StartTime')); + $form->setRequired($startTimeDatePicker); + + $form->addText('topic', $this->get_lang('Topic'), true); + $form->addTextarea('agenda', get_lang('Agenda'), ['maxlength' => 2000]); + + $durationNumeric = $form->addNumeric('duration', $this->get_lang('DurationInMinutes')); + $form->setRequired($durationNumeric); + + /*if (null === $course) { + $options = []; + if ('true' === $this->get('enableGlobalConference')) { + $options['everyone'] = $this->get_lang('ForEveryone'); + } + + if ('true' === $this->get('enableGlobalConferencePerUser')) { + $options['registered_users'] = $this->get_lang('SomeUsers'); + } + + if (!empty($options)) { + if (1 === count($options)) { + $form->addHidden('type', key($options)); + } else { + $form->addSelect('type', $this->get_lang('ConferenceType'), $options); + } + } + } else { + // To course + $form->addHidden('type', 'course'); + } + + // $passwordText = $form->addText('password', get_lang('Password'), false, ['maxlength' => '10']); + if (null !== $course) { $registrationOptions = [ 'RegisterAllCourseUsers' => $this->get_lang('RegisterAllCourseUsers'), ]; @@ -684,7 +948,8 @@ class ZoomPlugin extends Plugin $form->setAttribute('onchange', $jsCode); } - } + }*/ + $form->addButtonCreate(get_lang('Save')); if ($form->validate()) { @@ -715,6 +980,7 @@ class ZoomPlugin extends Plugin $newMeeting = $this->scheduleMeeting( $user, $course, + $group, $session, new DateTime($form->getSubmitValue('startTime')), $form->getSubmitValue('duration'), @@ -766,166 +1032,124 @@ class ZoomPlugin extends Plugin } /** - * @param MeetingEntity $meeting + * Schedules a meeting and returns it. + * set $course, $session and $user to null in order to create a global meeting. + * + * @param User|null $user the current user, for a course meeting or a user meeting + * @param Course|null $course the course, for a course meeting + * @param Session|null $session the session, for a course meeting + * @param DateTime $startTime meeting local start date-time (configure local timezone on your Zoom account) + * @param int $duration in minutes + * @param string $topic short title of the meeting, required + * @param string $agenda ordre du jour + * @param string $password meeting password + * + * @return Meeting meeting + * @throws Exception * - * @return bool whether the logged-in user can manage conferences in this context, that is either - * the current course or session coach, the platform admin or the current course admin */ - public function userIsConferenceManager($meeting) - { - if (null === $meeting) { - return false; - } - - if (api_is_coach() || api_is_platform_admin()) { - return true; - } - - if ($meeting->isCourseMeeting() && api_get_course_id() && api_is_course_admin()) { - return true; + private function scheduleMeeting( + $user, + $course, + $group, + $session, + $startTime, + $duration, + $topic, + $agenda, + $password + ) { + $meetingInfoGet = MeetingInfoGet::fromTopicAndType($topic, MeetingInfoGet::TYPE_SCHEDULED); + $meetingInfoGet->duration = $duration; + $meetingInfoGet->start_time = $startTime->format(DateTimeInterface::ISO8601); + $meetingInfoGet->agenda = $agenda; + $meetingInfoGet->password = $password; + $meetingInfoGet->settings->approval_type = MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED; + if ('true' === $this->get('enableParticipantRegistration')) { + $meetingInfoGet->settings->approval_type = MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE; } - return $meeting->isUserMeeting() && $meeting->getUser()->getId() == api_get_user_id(); + return $this->createMeetingFromMeeting( + (new Meeting()) + ->setMeetingInfoGet($meetingInfoGet) + ->setUser($user) + ->setCourse($course) + ->setGroup($group) + ->setSession($session) + ); } /** - * @return bool whether the logged-in user can manage conferences in this context, that is either - * the current course or session coach, the platform admin or the current course admin + * Registers all the course users to a course meeting. + * + * @param Meeting $meeting + * + * @throws OptimisticLockException */ - public function userIsCourseConferenceManager() + private function registerAllCourseUsers($meeting) { - if (api_is_coach() || api_is_platform_admin()) { - return true; - } - - if (api_get_course_id() && api_is_course_admin()) { - return true; - } - - return false; + $this->registerUsers($meeting, $meeting->getRegistrableUsers()); } /** - * Adds to the meeting course documents a link to a meeting instance recording file. - * - * @param MeetingEntity $meeting - * @param RecordingFile $file - * @param string $name + * Return the current global meeting (create it if needed). * + * @return string * @throws Exception + * */ - public function createLinkToFileInCourse($meeting, $file, $name) + public function getGlobalMeeting() { - $course = $meeting->getCourse(); - if (null === $course) { - throw new Exception('This meeting is not linked to a course'); - } - $courseInfo = api_get_course_info_by_id($course->getId()); - if (empty($courseInfo)) { - throw new Exception('This meeting is not linked to a valid course'); - } - $path = '/zoom_meeting_recording_file_'.$file->id.'.'.$file->file_type; - $docId = DocumentManager::addCloudLink($courseInfo, $path, $file->play_url, $name); - if (!$docId) { - throw new Exception(get_lang(DocumentManager::cloudLinkExists($courseInfo, $path, $file->play_url) ? 'UrlAlreadyExists' : 'ErrorAddCloudLink')); + foreach ($this->getMeetingRepository()->unfinishedGlobalMeetings() as $meeting) { + return $meeting; } + + return $this->createGlobalMeeting(); } /** - * Copies a recording file to a meeting's course. - * - * @param MeetingEntity $meeting - * @param RecordingFile $file - * @param string $name - * - * @throws Exception + * @return MeetingRepository|EntityRepository */ - public function copyFileToCourse($meeting, $file, $name) + public static function getMeetingRepository() { - $course = $meeting->getCourse(); - if (null === $course) { - throw new Exception('This meeting is not linked to a course'); - } - $courseInfo = api_get_course_info_by_id($course->getId()); - if (empty($courseInfo)) { - throw new Exception('This meeting is not linked to a valid course'); - } - $tmpFile = tmpfile(); - if (false === $tmpFile) { - throw new Exception('tmpfile() returned false'); - } - $curl = curl_init($file->getFullDownloadURL($this->jwtClient->token)); - if (false === $curl) { - throw new Exception('Could not init curl: '.curl_error($curl)); - } - if (!curl_setopt_array( - $curl, - [ - CURLOPT_FILE => $tmpFile, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_MAXREDIRS => 10, - CURLOPT_TIMEOUT => 120, - ] - )) { - throw new Exception("Could not set curl options: ".curl_error($curl)); - } - if (false === curl_exec($curl)) { - throw new Exception("curl_exec failed: ".curl_error($curl)); - } - $newPath = handle_uploaded_document( - $courseInfo, - [ - 'name' => $name, - 'tmp_name' => stream_get_meta_data($tmpFile)['uri'], - 'size' => filesize(stream_get_meta_data($tmpFile)['uri']), - 'from_file' => true, - 'type' => $file->file_type, - ], - '/', - api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document', - api_get_user_id(), - 0, - null, - 0, - '', - true, - false, - null, - $meeting->getSession()->getId(), - true - ); - fclose($tmpFile); - if (false === $newPath) { - throw new Exception('could not handle uploaded document'); - } + return Database::getManager()->getRepository(Meeting::class); } /** - * Return the current global meeting (create it if needed). - * + * @return Meeting * @throws Exception * - * @return string */ - public function getGlobalMeeting() + private function createGlobalMeeting() { - foreach ($this->getMeetingRepository()->unfinishedGlobalMeetings() as $meeting) { - return $meeting; - } + $meetingInfoGet = MeetingInfoGet::fromTopicAndType( + $this->get_lang('GlobalMeeting'), + MeetingInfoGet::TYPE_SCHEDULED + ); + $meetingInfoGet->start_time = (new DateTime())->format(DateTimeInterface::ISO8601); + $meetingInfoGet->duration = 60; + $meetingInfoGet->settings->approval_type = + ('true' === $this->get('enableParticipantRegistration')) + ? MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE + : MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED; + // $meetingInfoGet->settings->host_video = true; + $meetingInfoGet->settings->participant_video = true; + $meetingInfoGet->settings->join_before_host = true; + $meetingInfoGet->settings->registrants_email_notification = false; - return $this->createGlobalMeeting(); + return $this->createMeetingFromMeeting((new Meeting())->setMeetingInfoGet($meetingInfoGet)); } /** * Returns the URL to enter (start or join) a meeting or null if not possible to enter the meeting, * The returned URL depends on the meeting current status (waiting, started or finished) and the current user. * - * @param MeetingEntity $meeting + * @param Meeting $meeting * - * @throws Exception + * @return string|null * @throws OptimisticLockException * - * @return string|null + * @throws Exception */ public function getStartOrJoinMeetingURL($meeting) { @@ -981,6 +1205,46 @@ class ZoomPlugin extends Plugin return null; } + /** + * @param Meeting $meeting + * + * @return bool whether the logged-in user can manage conferences in this context, that is either + * the current course or session coach, the platform admin or the current course admin + */ + public function userIsConferenceManager($meeting) + { + if (null === $meeting) { + return false; + } + + if (api_is_coach() || api_is_platform_admin()) { + return true; + } + + if ($meeting->isCourseMeeting() && api_get_course_id() && api_is_course_admin()) { + return true; + } + + return $meeting->isUserMeeting() && $meeting->getUser()->getId() == api_get_user_id(); + } + + /** + * @return bool whether the logged-in user can manage conferences in this context, that is either + * the current course or session coach, the platform admin or the current course admin + */ + public function userIsCourseConferenceManager() + { + if (api_is_coach() || api_is_platform_admin()) { + return true; + } + + if (api_get_course_id() && api_is_course_admin()) { + return true; + } + + return false; + } + /** * Update local recording list from remote Zoom server's version. * Kept to implement a future administration button ("import existing data from zoom server"). @@ -1001,23 +1265,23 @@ class ZoomPlugin extends Plugin foreach ($recordings as $recordingMeeting) { $recordingEntity = $recordingRepo->findOneBy(['uuid' => $recordingMeeting->uuid]); if (null === $recordingEntity) { - $recordingEntity = new RecordingEntity(); - $meetingEntity = $meetingRepo->findOneBy(['meetingId' => $recordingMeeting->id]); - if (null === $meetingEntity) { + $recordingEntity = new Recording(); + $meeting = $meetingRepo->findOneBy(['meetingId' => $recordingMeeting->id]); + if (null === $meeting) { try { $meetingInfoGet = MeetingInfoGet::fromId($recordingMeeting->id); } catch (Exception $exception) { $meetingInfoGet = null; // deleted meeting with recordings } if (null !== $meetingInfoGet) { - $meetingEntity = $this->createMeetingFromMeetingEntity( - (new MeetingEntity())->setMeetingInfoGet($meetingInfoGet) + $meeting = $this->createMeetingFromMeeting( + (new Meeting())->setMeetingInfoGet($meetingInfoGet) ); - $em->persist($meetingEntity); + $em->persist($meeting); } } - if (null !== $meetingEntity) { - $recordingEntity->setMeeting($meetingEntity); + if (null !== $meeting) { + $recordingEntity->setMeeting($meeting); } } $recordingEntity->setRecordingMeeting($recordingMeeting); @@ -1026,6 +1290,14 @@ class ZoomPlugin extends Plugin $em->flush(); } + /** + * @return RecordingRepository|EntityRepository + */ + public static function getRecordingRepository() + { + return Database::getManager()->getRepository(Recording::class); + } + public function getToolbar($returnUrl = '') { if (!api_is_platform_admin()) { @@ -1041,15 +1313,13 @@ class ZoomPlugin extends Plugin Display::url( Display::return_icon('bbb.png', $this->get_lang('Meetings'), null, ICON_SIZE_MEDIUM), api_get_path(WEB_PLUGIN_PATH).'zoom/meetings.php' - ) - ; + ); } else { $actionsLeft .= Display::url( Display::return_icon('bbb.png', $this->get_lang('Meetings'), null, ICON_SIZE_MEDIUM), api_get_path(WEB_PLUGIN_PATH).'zoom/start.php?'.api_get_cidreq() - ) - ; + ); } /*if ('true' === api_get_plugin_setting('zoom', 'enableGlobalConferencePerUser')) { @@ -1078,248 +1348,4 @@ class ZoomPlugin extends Plugin return Display::toolbarAction('toolbar', [$actionsLeft]); } - - /** - * Creates a meeting on Zoom servers and stores it in the local database. - * - * @param MeetingEntity $meeting a new, unsaved meeting with at least a type and a topic - * - * @throws Exception - * - * @return MeetingEntity - */ - private function createMeetingFromMeetingEntity($meeting) - { - $approvalType = $meeting->getMeetingInfoGet()->settings->approval_type; - $meeting->getMeetingInfoGet()->settings->auto_recording = 'true' === $this->get('enableCloudRecording') - ? 'cloud' - : 'local'; - $meeting->getMeetingInfoGet()->settings->registrants_email_notification = false; - $meeting->setMeetingInfoGet($meeting->getMeetingInfoGet()->create()); - $meeting->getMeetingInfoGet()->settings->approval_type = $approvalType; - - Database::getManager()->persist($meeting); - Database::getManager()->flush(); - - return $meeting; - } - - /** - * @throws Exception - * - * @return MeetingEntity - */ - private function createGlobalMeeting() - { - $meetingInfoGet = MeetingInfoGet::fromTopicAndType( - $this->get_lang('GlobalMeeting'), - MeetingInfoGet::TYPE_SCHEDULED - ); - $meetingInfoGet->start_time = (new DateTime())->format(DateTimeInterface::ISO8601); - $meetingInfoGet->duration = 60; - $meetingInfoGet->settings->approval_type = - ('true' === $this->get('enableParticipantRegistration')) - ? MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE - : MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED; - // $meetingInfoGet->settings->host_video = true; - $meetingInfoGet->settings->participant_video = true; - $meetingInfoGet->settings->join_before_host = true; - $meetingInfoGet->settings->registrants_email_notification = false; - - return $this->createMeetingFromMeetingEntity((new MeetingEntity())->setMeetingInfoGet($meetingInfoGet)); - } - - /** - * Schedules a meeting and returns it. - * set $course, $session and $user to null in order to create a global meeting. - * - * @param User|null $user the current user, for a course meeting or a user meeting - * @param Course|null $course the course, for a course meeting - * @param Session|null $session the session, for a course meeting - * @param DateTime $startTime meeting local start date-time (configure local timezone on your Zoom account) - * @param int $duration in minutes - * @param string $topic short title of the meeting, required - * @param string $agenda ordre du jour - * @param string $password meeting password - * - * @throws Exception - * - * @return MeetingEntity meeting - */ - private function scheduleMeeting($user, $course, $session, $startTime, $duration, $topic, $agenda, $password) - { - $meetingInfoGet = MeetingInfoGet::fromTopicAndType($topic, MeetingInfoGet::TYPE_SCHEDULED); - $meetingInfoGet->duration = $duration; - $meetingInfoGet->start_time = $startTime->format(DateTimeInterface::ISO8601); - $meetingInfoGet->agenda = $agenda; - $meetingInfoGet->password = $password; - $meetingInfoGet->settings->approval_type = MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED; - if ('true' === $this->get('enableParticipantRegistration')) { - $meetingInfoGet->settings->approval_type = MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE; - } - - return $this->createMeetingFromMeetingEntity( - (new MeetingEntity()) - ->setMeetingInfoGet($meetingInfoGet) - ->setUser($user) - ->setCourse($course) - ->setSession($session) - ); - } - - /** - * Starts a new instant meeting and redirects to its start url. - * - * @param string $topic - * @param User|null $user - * @param Course|null $course - * @param Session|null $session - * - * @throws Exception - */ - private function startInstantMeeting($topic, $user = null, $course = null, $session = null) - { - $meeting = $this->createMeetingFromMeetingEntity( - (new MeetingEntity()) - ->setMeetingInfoGet(MeetingInfoGet::fromTopicAndType($topic, MeetingInfoGet::TYPE_INSTANT)) - ->setUser($user) - ->setCourse($course) - ->setSession($session) - ); - api_location($meeting->getMeetingInfoGet()->start_url); - } - - /** - * @param MeetingEntity $meetingEntity - * @param User $user - * @param bool $andFlush - * - * @throws OptimisticLockException - * @throws Exception - * - * @return RegistrantEntity - */ - private function registerUser($meetingEntity, $user, $andFlush = true) - { - if (empty($user->getEmail())) { - throw new Exception($this->get_lang('CannotRegisterWithoutEmailAddress')); - } - - $meetingRegistrant = MeetingRegistrant::fromEmailAndFirstName( - $user->getEmail(), - $user->getFirstname(), - $user->getLastname() - ); - - $registrantEntity = (new RegistrantEntity()) - ->setMeeting($meetingEntity) - ->setUser($user) - ->setMeetingRegistrant($meetingRegistrant) - ->setCreatedRegistration($meetingEntity->getMeetingInfoGet()->addRegistrant($meetingRegistrant)); - Database::getManager()->persist($registrantEntity); - if ($andFlush) { - Database::getManager()->flush($registrantEntity); - } - - return $registrantEntity; - } - - /** - * Register users to a meeting. - * - * @param MeetingEntity $meetingEntity - * @param User[] $users - * - * @throws OptimisticLockException - * - * @return User[] failed registrations [ user id => errorMessage ] - */ - private function registerUsers($meetingEntity, $users) - { - $failedUsers = []; - foreach ($users as $user) { - try { - $this->registerUser($meetingEntity, $user, false); - } catch (Exception $exception) { - $failedUsers[$user->getId()] = $exception->getMessage(); - } - } - Database::getManager()->flush(); - - return $failedUsers; - } - - /** - * Registers all the course users to a course meeting. - * - * @param MeetingEntity $meetingEntity - * - * @throws OptimisticLockException - */ - private function registerAllCourseUsers($meetingEntity) - { - $this->registerUsers($meetingEntity, $meetingEntity->getRegistrableUsers()); - } - - /** - * Removes registrants from a meeting. - * - * @param MeetingEntity $meetingEntity - * @param RegistrantEntity[] $registrants - * - * @throws Exception - */ - private function unregister($meetingEntity, $registrants) - { - $meetingRegistrants = []; - foreach ($registrants as $registrant) { - $meetingRegistrants[] = $registrant->getMeetingRegistrant(); - } - $meetingEntity->getMeetingInfoGet()->removeRegistrants($meetingRegistrants); - $em = Database::getManager(); - foreach ($registrants as $registrant) { - $em->remove($registrant); - } - $em->flush(); - } - - /** - * Updates meeting registrants list. Adds the missing registrants and removes the extra. - * - * @param MeetingEntity $meetingEntity - * @param User[] $users list of users to be registered - * - * @throws Exception - */ - private function updateRegistrantList($meetingEntity, $users) - { - $usersToAdd = []; - foreach ($users as $user) { - $found = false; - foreach ($meetingEntity->getRegistrants() as $registrant) { - if ($registrant->getUser() === $user) { - $found = true; - break; - } - } - if (!$found) { - $usersToAdd[] = $user; - } - } - $registrantsToRemove = []; - foreach ($meetingEntity->getRegistrants() as $registrant) { - $found = false; - foreach ($users as $user) { - if ($registrant->getUser() === $user) { - $found = true; - break; - } - } - if (!$found) { - $registrantsToRemove[] = $registrant; - } - } - $this->registerUsers($meetingEntity, $usersToAdd); - $this->unregister($meetingEntity, $registrantsToRemove); - } } diff --git a/plugin/zoom/meeting.php b/plugin/zoom/meeting.php index cf4b9eea32..2691353970 100755 --- a/plugin/zoom/meeting.php +++ b/plugin/zoom/meeting.php @@ -2,7 +2,7 @@ /* For license terms, see /license.txt */ -use Chamilo\PluginBundle\Zoom\MeetingEntity; +use Chamilo\PluginBundle\Zoom\Meeting; require_once __DIR__.'/config.php'; @@ -12,7 +12,7 @@ if (empty($meetingId)) { } $plugin = ZoomPlugin::create(); -/** @var MeetingEntity $meeting */ +/** @var Meeting $meeting */ $meeting = $plugin->getMeetingRepository()->findOneBy(['meetingId' => $meetingId]); if (null === $meeting) { @@ -46,17 +46,14 @@ if ($plugin->userIsConferenceManager($meeting)) { $tpl->assign('editMeetingForm', $plugin->getEditMeetingForm($meeting)->returnForm()); $tpl->assign('deleteMeetingForm', $plugin->getDeleteMeetingForm($meeting, $returnURL)->returnForm()); - if (false === $meeting->isGlobalMeeting()) { + if (false === $meeting->isGlobalMeeting() && false == $meeting->isCourseMeeting()) { if ('true' === $plugin->get('enableParticipantRegistration') && $meeting->requiresRegistration()) { $tpl->assign('registerParticipantForm', $plugin->getRegisterParticipantForm($meeting)->returnForm()); $tpl->assign('registrants', $meeting->getRegistrants()); } } - if ('true' === $plugin->get('enableCloudRecording') && - $meeting->hasCloudAutoRecordingEnabled() - // && 'finished' === $meeting->status - ) { + if ('true' === $plugin->get('enableCloudRecording') && $meeting->hasCloudAutoRecordingEnabled()) { $tpl->assign('fileForm', $plugin->getFileForm($meeting)->returnForm()); $tpl->assign('recordings', $meeting->getRecordings()); } diff --git a/plugin/zoom/meetings.php b/plugin/zoom/meetings.php index 5e39196610..c4567308fa 100644 --- a/plugin/zoom/meetings.php +++ b/plugin/zoom/meetings.php @@ -23,5 +23,5 @@ $tpl->assign('allow_recording', 'true' === $plugin->get('enableCloudRecording')) $tpl->assign('actions', $plugin->getToolbar()); $tpl->assign('search_form', $form->returnForm()); $tpl->assign('schedule_form', $scheduleForm->returnForm()); -$tpl->assign('content', $tpl->fetch('zoom/view/list.tpl')); +$tpl->assign('content', $tpl->fetch('zoom/view/meetings.tpl')); $tpl->display_one_col_template(); diff --git a/plugin/zoom/start.php b/plugin/zoom/start.php index d6d4caeeeb..6682f7552a 100755 --- a/plugin/zoom/start.php +++ b/plugin/zoom/start.php @@ -19,6 +19,7 @@ $plugin = ZoomPlugin::create(); $tool_name = $plugin->get_lang('ZoomVideoConferences'); $tpl = new Template($tool_name); $course = api_get_course_entity(); +$group = api_get_group_entity(); $session = api_get_session_entity(); $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : ''; @@ -39,12 +40,14 @@ if ($plugin->userIsCourseConferenceManager()) { $plugin->getCreateInstantMeetingForm( $user, $course, + $group, $session )->returnForm() ); $tpl->assign('scheduleMeetingForm', $plugin->getScheduleMeetingForm( $user, $course, + $group, $session )->returnForm()); } @@ -52,7 +55,7 @@ if ($plugin->userIsCourseConferenceManager()) { try { $tpl->assign( 'scheduledMeetings', - $plugin->getMeetingRepository()->courseMeetings($course, $session) + $plugin->getMeetingRepository()->courseMeetings($course, $group, $session) ); } catch (Exception $exception) { Display::addFlash( diff --git a/plugin/zoom/view/activity.tpl b/plugin/zoom/view/activity.tpl new file mode 100644 index 0000000000..38e8ae3175 --- /dev/null +++ b/plugin/zoom/view/activity.tpl @@ -0,0 +1,28 @@ +

+ {{ meeting.typeName }} {{ meeting.meetingId }} +

+ + + + + + + + + + + {% for activity in meeting.activities %} + + + + + + {% endfor %} + +
{{ 'Name'|get_plugin_lang('ZoomPlugin') }}{{ 'Type'|get_lang }}{{ 'Event'|get_lang }}
+ {{ activity.name }} + + {{ activity.type }} + + {{ activity.eventDecoded }} +
\ No newline at end of file diff --git a/plugin/zoom/view/list.tpl b/plugin/zoom/view/list.tpl deleted file mode 100644 index b0e825a3c4..0000000000 --- a/plugin/zoom/view/list.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{% import "default/document/recycle.tpl" as macro %} - -{{ schedule_form }} -{{ search_form }} - -{% if meetings %} -

{{ 'MeetingsFound'|get_plugin_lang('ZoomPlugin') }}:

- - - - - - -{# #} -{# #} - {% if allow_recording %} - - {% endif %} - - - - - {% for meeting in meetings %} - - - - -{# #} -{# #} - - - - {% endfor %} - -
{{ 'Topic'|get_plugin_lang('ZoomPlugin') }}{{ 'StartTime'|get_lang }}{{ 'ForEveryone'|get_plugin_lang('ZoomPlugin') }}{{ 'Course'|get_lang }}{{ 'Session'|get_lang }}{{ 'Recordings'|get_plugin_lang('ZoomPlugin') }}
{{ meeting.meetingInfoGet.topic }}{{ meeting.formattedStartTime }}{{ meeting.user ? 'No' : 'Yes' }}{{ meeting.course ? meeting.course : '-' }}{{ meeting.session ? meeting.session : '-' }} - {% if allow_recording and meeting.recordings.count > 0 %} - {% for recording in meeting.recordings %} -
-
- {{ recording.formattedStartTime }} ({{ recording.formattedDuration }}) -
-
- -
-
- {% endfor %} - {% endif %} -
- - {{ 'Details'|get_lang }} - -
-{% endif %} \ No newline at end of file diff --git a/plugin/zoom/view/meeting.tpl b/plugin/zoom/view/meeting.tpl index 8f3fc34b25..ae0b74aae6 100644 --- a/plugin/zoom/view/meeting.tpl +++ b/plugin/zoom/view/meeting.tpl @@ -2,22 +2,27 @@ {{ meeting.typeName }} {{ meeting.meetingId }} ({{ meeting.meetingInfoGet.status }}) +
+ {% if meeting.meetingInfoGet.status != 'finished' %} -

{{ 'ViewMeeting'|get_plugin_lang('ZoomPlugin') }} -

{% endif %} -{% if isConferenceManager and meeting.status == 'waiting' %} -

- - {{ 'StartMeeting'|get_plugin_lang('ZoomPlugin') }} +{% if isConferenceManager %} + {% if meeting.status == 'waiting' %} + + {{ 'StartMeeting'|get_plugin_lang('ZoomPlugin') }} + + {% endif %} + + + {{ 'Activity'|get_plugin_lang('ZoomPlugin') }} -

{% endif %} +
{% if currentUserJoinURL %} {#

#} {# #} diff --git a/plugin/zoom/view/meetings.tpl b/plugin/zoom/view/meetings.tpl new file mode 100644 index 0000000000..fb45f3f084 --- /dev/null +++ b/plugin/zoom/view/meetings.tpl @@ -0,0 +1,62 @@ +{% import "default/document/recycle.tpl" as macro %} + +{{ schedule_form }} +{{ search_form }} + +{% if meetings %} +

{{ 'MeetingsFound'|get_plugin_lang('ZoomPlugin') }}:

+ + + + + + +{# #} +{# #} + {% if allow_recording %} + + {% endif %} + + + + + {% for meeting in meetings %} + + + + +{# #} +{# #} + + + + {% endfor %} + +
{{ 'Topic'|get_plugin_lang('ZoomPlugin') }}{{ 'StartTime'|get_lang }}{{ 'ForEveryone'|get_plugin_lang('ZoomPlugin') }}{{ 'Course'|get_lang }}{{ 'Session'|get_lang }}{{ 'Recordings'|get_plugin_lang('ZoomPlugin') }}
{{ meeting.meetingInfoGet.topic }}{{ meeting.formattedStartTime }}{{ meeting.user ? 'No' : 'Yes' }}{{ meeting.course ? meeting.course : '-' }}{{ meeting.session ? meeting.session : '-' }} + {% if allow_recording and meeting.recordings.count > 0 %} + {% for recording in meeting.recordings %} +
+
+ {{ recording.formattedStartTime }} ({{ recording.formattedDuration }}) +
+
+ +
+
+ {% endfor %} + {% endif %} +
+ + {{ 'Details'|get_lang }} + +
+{% endif %} \ No newline at end of file