global and user Zoom meetings - refs BT#17288

Introducing 3 local tables to link remote Zoom API meetings to local
user, course and sessions and remote registrants to local users.
Better than using remote storage. Opens new possibilities but would
work better with "webhooks" to maintain local copies of Zoom object.
pull/3383/head
Sébastien Ducoulombier 5 years ago
parent aacdbc8e31
commit eb80bfdd9c
  1. 6
      main/inc/lib/userportal.lib.php
  2. 468
      plugin/zoom/Entity/MeetingEntity.php
  3. 184
      plugin/zoom/Entity/RecordingEntity.php
  4. 258
      plugin/zoom/Entity/RegistrantEntity.php
  5. 13
      plugin/zoom/admin.php
  6. 30
      plugin/zoom/global.php
  7. 42
      plugin/zoom/join_meeting.php
  8. 7
      plugin/zoom/lang/english.php
  9. 7
      plugin/zoom/lang/french.php
  10. 7
      plugin/zoom/lang/spanish.php
  11. 27
      plugin/zoom/lib/API/Client.php
  12. 3
      plugin/zoom/lib/API/JWTClient.php
  13. 10
      plugin/zoom/lib/API/Meeting.php
  14. 45
      plugin/zoom/lib/API/MeetingInfoGet.php
  15. 14
      plugin/zoom/lib/API/MeetingInstance.php
  16. 5
      plugin/zoom/lib/API/MeetingInstances.php
  17. 5
      plugin/zoom/lib/API/MeetingList.php
  18. 7
      plugin/zoom/lib/API/MeetingRegistrant.php
  19. 5
      plugin/zoom/lib/API/MeetingRegistrantList.php
  20. 5
      plugin/zoom/lib/API/Pagination.php
  21. 5
      plugin/zoom/lib/API/PaginationToken.php
  22. 4
      plugin/zoom/lib/API/ParticipantList.php
  23. 11
      plugin/zoom/lib/API/PastMeeting.php
  24. 6
      plugin/zoom/lib/API/RecordingFile.php
  25. 4
      plugin/zoom/lib/API/RecordingList.php
  26. 10
      plugin/zoom/lib/API/RecordingMeeting.php
  27. 69
      plugin/zoom/lib/CourseMeeting.php
  28. 57
      plugin/zoom/lib/CourseMeetingInfoGet.php
  29. 26
      plugin/zoom/lib/CourseMeetingList.php
  30. 31
      plugin/zoom/lib/CourseMeetingListItem.php
  31. 142
      plugin/zoom/lib/CourseMeetingTrait.php
  32. 74
      plugin/zoom/lib/DisplayableMeetingTrait.php
  33. 28
      plugin/zoom/lib/File.php
  34. 141
      plugin/zoom/lib/MeetingEntityRepository.php
  35. 65
      plugin/zoom/lib/Recording.php
  36. 66
      plugin/zoom/lib/RecordingEntityRepository.php
  37. 51
      plugin/zoom/lib/RecordingList.php
  38. 33
      plugin/zoom/lib/RegistrantEntityRepository.php
  39. 51
      plugin/zoom/lib/UserMeetingRegistrant.php
  40. 43
      plugin/zoom/lib/UserMeetingRegistrantList.php
  41. 30
      plugin/zoom/lib/UserMeetingRegistrantListItem.php
  42. 89
      plugin/zoom/lib/UserMeetingRegistrantTrait.php
  43. 1177
      plugin/zoom/lib/zoom_plugin.class.php
  44. 31
      plugin/zoom/meeting.php
  45. 13
      plugin/zoom/meeting_from_user.php
  46. 22
      plugin/zoom/start.php
  47. 36
      plugin/zoom/user.php
  48. 18
      plugin/zoom/view/admin.tpl
  49. 18
      plugin/zoom/view/meeting.tpl
  50. 6
      plugin/zoom/view/start.tpl

@ -952,6 +952,12 @@ class IndexManager
];
}
if ('true' === api_get_plugin_setting('zoom', 'tool_enable')) {
foreach (ZoomPlugin::getProfileBlockItems() as $item) {
$items[] = $item;
}
}
if (
true === api_get_configuration_value('whispeak_auth_enabled') &&
!WhispeakAuthPlugin::checkUserIsEnrolled($userId)

@ -0,0 +1,468 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
use Chamilo\PluginBundle\Zoom\API\MeetingInfoGet;
use Chamilo\PluginBundle\Zoom\API\MeetingListItem;
use Chamilo\PluginBundle\Zoom\API\MeetingSettings;
use Chamilo\UserBundle\Entity\User;
use Database;
use DateInterval;
use DateTime;
use DateTimeZone;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Exception;
/**
* Class MeetingEntity.
* @package Chamilo\PluginBundle\Zoom
* @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\MeetingEntityRepository")
* @ORM\Table(
* name="plugin_zoom_meeting",
* indexes={
* @ORM\Index(name="user_id_index", columns={"user_id"}),
* @ORM\Index(name="course_id_index", columns={"course_id"}),
* @ORM\Index(name="session_id_index", columns={"session_id"})
* }
* )
* @ORM\HasLifecycleCallbacks
*/
class MeetingEntity
{
/**
* @var int the remote zoom meeting identifier
* @ORM\Column(type="bigint")
* @ORM\Id
*/
private $id;
/**
* @var User
* @ORM\ManyToOne(
* targetEntity="Chamilo\UserBundle\Entity\User",
* )
* @ORM\JoinColumn(name="user_id", nullable=true)
*/
private $user;
/**
* @var Course
* @ORM\ManyToOne(
* targetEntity="Chamilo\CoreBundle\Entity\Course",
* )
* @ORM\JoinColumn(name="course_id", nullable=true)
*/
private $course;
/**
* @var Session
* @ORM\ManyToOne(
* targetEntity="Chamilo\CoreBundle\Entity\Session",
* )
* @ORM\JoinColumn(name="session_id", nullable=true)
*/
private $session;
/**
* @var string
* @ORM\Column(type="text", name="meeting_list_item_json", nullable=true)
*/
private $meetingListItemJson;
/** @var MeetingListItem */
private $meetingListItem;
/**
* @var string
* @ORM\Column(type="text", name="meeting_info_get_json", nullable=true)
*/
private $meetingInfoGetJson;
/** @var MeetingInfoGet */
private $meetingInfoGet;
/**
* @var RegistrantEntity[]|ArrayCollection
* @ORM\OneToMany(
* targetEntity="RegistrantEntity",
* mappedBy="meeting",
* cascade={"persist", "remove"}
* )
*/
private $registrants;
/**
* @var RecordingEntity[]|ArrayCollection
* @ORM\OneToMany(
* targetEntity="RecordingEntity",
* mappedBy="meeting",
* )
*/
private $recordings;
// Displayable properties
/** @var string meeting type name */
public $typeName;
/** @var DateTime meeting start time as a DateTime instance */
public $startDateTime;
/** @var string meeting formatted start time */
public $formattedStartTime;
/** @var DateInterval meeting duration as a DateInterval instance */
public $durationInterval;
/** @var string meeting formatted duration */
public $formattedDuration;
/** @var string */
public $statusName;
public function __construct()
{
$this->registrants = new ArrayCollection();
$this->recordings = new ArrayCollection();
}
/**
* @return string
*/
public function __toString()
{
return sprintf('Meeting %d', $this->id);
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* @return Course
*/
public function getCourse()
{
return $this->course;
}
/**
* @return Session
*/
public function getSession()
{
return $this->session;
}
/**
* @return RegistrantEntity[]|ArrayCollection
*/
public function getRegistrants()
{
return $this->registrants;
}
/**
* @return RecordingEntity[]|ArrayCollection
*/
public function getRecordings()
{
return $this->recordings;
}
/**
* @ORM\PostLoad
*
* @throws Exception
*/
public function postLoad()
{
if (!is_null($this->meetingListItemJson)) {
$this->meetingListItem = MeetingListItem::fromJson($this->meetingListItemJson);
}
if (!is_null($this->meetingInfoGetJson)) {
$this->meetingInfoGet = MeetingInfoGet::fromJson($this->meetingInfoGetJson);
}
$this->initializeDisplayableProperties();
}
/**
* @ORM\PostUpdate
* @throws Exception
*/
public function postUpdate()
{
$this->initializeDisplayableProperties();
}
/**
* @ORM\PreFlush
*/
public function preFlush()
{
if (!is_null($this->meetingListItem)) {
$this->meetingListItemJson = json_encode($this->meetingListItem);
}
if (!is_null($this->meetingInfoGet)) {
$this->meetingInfoGetJson = json_encode($this->meetingInfoGet);
}
}
/**
* @return MeetingListItem
*/
public function getMeetingListItem()
{
return $this->meetingListItem;
}
/**
* @return MeetingInfoGet
*/
public function getMeetingInfoGet()
{
return $this->meetingInfoGet;
}
/**
* @param User $user
*
* @return $this
*/
public function setUser($user)
{
$this->user = $user;
return $this;
}
/**
* @param Course $course
*
* @return $this
*/
public function setCourse($course)
{
$this->course = $course;
return $this;
}
/**
* @param Session $session
*
* @return $this
*/
public function setSession($session)
{
$this->session = $session;
return $this;
}
/**
* @param MeetingListItem $meetingListItem
*
* @throws Exception
*
* @return MeetingEntity
*/
public function setMeetingListItem($meetingListItem)
{
if (is_null($this->id)) {
$this->id = $meetingListItem->id;
} elseif ($this->id != $meetingListItem->id) {
throw new Exception('the MeetingEntity identifier differs from the MeetingListItem identifier');
}
$this->meetingListItem = $meetingListItem;
return $this;
}
/**
* @param MeetingInfoGet $meetingInfoGet
*
* @throws Exception
*
* @return MeetingEntity
*/
public function setMeetingInfoGet($meetingInfoGet)
{
if (is_null($this->id)) {
$this->id = $meetingInfoGet->id;
} elseif ($this->id != $meetingInfoGet->id) {
throw new Exception('the MeetingEntity identifier differs from the MeetingInfoGet identifier');
}
$this->meetingInfoGet = $meetingInfoGet;
$this->initializeDisplayableProperties();
return $this;
}
/**
* @return bool
*/
public function isCourseMeeting()
{
return !is_null($this->course);
}
/**
* @return bool
*/
public function isUserMeeting()
{
return !is_null($this->user) && is_null($this->course);
}
/**
* @return bool
*/
public function isGlobalMeeting()
{
return is_null($this->user) && is_null($this->course);
}
/**
* Builds the list of users that can register into this meeting.
* Zoom requires an email address, therefore users without an email address are excluded from the list.
*
* @return User[] the list of users
*/
public function getRegistrableUsers()
{
$users = [];
if (!$this->isCourseMeeting()) {
$users = Database::getManager()->getRepository('ChamiloUserBundle:User')->findBy(['active' => true]);
}
if (is_null($this->session)) {
if (!is_null($this->course)) {
$users = $this->course->getUsers()->matching(
Criteria::create()->where(Criteria::expr()->isNull('email'))
);
}
} else {
if (!is_null($this->course)) {
$subscriptions = $this->session->getUserCourseSubscriptionsByStatus($this->course, Session::STUDENT);
if ($subscriptions) {
/** @var SessionRelCourseRelUser $sessionCourseUser */
foreach ($subscriptions as $sessionCourseUser) {
$users[] = $sessionCourseUser->getUser();
}
}
}
}
return $users;
}
/**
* @return bool
*/
public function requiresDateAndDuration()
{
return MeetingInfoGet::TYPE_SCHEDULED === $this->meetingInfoGet->type
|| MeetingInfoGet::TYPE_RECURRING_WITH_FIXED_TIME === $this->meetingInfoGet->type;
}
/**
* @return bool
*/
public function requiresRegistration()
{
return
MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED != $this->meetingInfoGet->settings->approval_type;
}
/**
* @return bool
*/
public function hasCloudAutoRecordingEnabled()
{
return 'cloud' === $this->meetingInfoGet->settings->auto_recording;
}
/**
* @param User $user
*
* @return bool
*/
public function hasRegisteredUser(User $user)
{
return $this->getRegistrants()->exists(
function (RegistrantEntity $registrantEntity) use (&$user) {
return $registrantEntity->getUser() === $user;
}
);
}
/**
* @param User $user
*
* @return RegistrantEntity|null
*/
public function getRegistrant(User $user)
{
foreach ($this->getRegistrants() as $registrant) {
if ($registrant->getUser() === $user) {
return $registrant;
}
}
return null;
}
/**
* @throws Exception on unexpected start_time or duration
*/
private function initializeDisplayableProperties()
{
$this->typeName = [
API\Meeting::TYPE_INSTANT => get_lang('InstantMeeting'),
API\Meeting::TYPE_SCHEDULED => get_lang('ScheduledMeeting'),
API\Meeting::TYPE_RECURRING_WITH_NO_FIXED_TIME => get_lang('RecurringWithNoFixedTime'),
API\Meeting::TYPE_RECURRING_WITH_FIXED_TIME => get_lang('RecurringWithFixedTime'),
][$this->meetingInfoGet->type];
if (property_exists($this, 'status')) {
$this->statusName = [
'waiting' => get_lang('Waiting'),
'started' => get_lang('Started'),
'finished' => get_lang('Finished'),
][$this->meetingInfoGet->status];
}
$this->startDateTime = null;
$this->formattedStartTime = '';
$this->durationInterval = null;
$this->formattedDuration = '';
if (!empty($this->meetingInfoGet->start_time)) {
$this->startDateTime = new DateTime($this->meetingInfoGet->start_time);
$this->startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get()));
$this->formattedStartTime = $this->startDateTime->format(get_lang('Y-m-d H:i'));
}
if (!empty($this->meetingInfoGet->duration)) {
$now = new DateTime();
$later = new DateTime();
$later->add(new DateInterval('PT'.$this->meetingInfoGet->duration.'M'));
$this->durationInterval = $later->diff($now);
$this->formattedDuration = $this->durationInterval->format(get_lang('DurationFormat'));
}
}
}

@ -0,0 +1,184 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Chamilo\PluginBundle\Zoom\API\RecordingMeeting;
use Database;
use DateInterval;
use DateTime;
use DateTimeZone;
use Doctrine\ORM\Mapping as ORM;
use Exception;
/**
* Class RecordingEntity.
* @package Chamilo\PluginBundle\Zoom
* @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\RecordingEntityRepository")
* @ORM\Table(
* name="plugin_zoom_recording",
* indexes={
* @ORM\Index(name="meeting_id_index", columns={"meeting_id"}),
* }
* )
* @ORM\HasLifecycleCallbacks
*/
class RecordingEntity
{
/**
* @var string
* @ORM\Column(type="string")
* @ORM\Id
*/
private $uuid;
/**
* @var MeetingEntity
* @ORM\ManyToOne(
* targetEntity="MeetingEntity",
* inversedBy="recordings",
* )
* @ORM\JoinColumn(name="meeting_id")
*/
private $meeting;
/**
* @var string
* @ORM\Column(type="text", name="recording_meeting_json", nullable=true)
*/
private $recordingMeetingJson;
/** @var RecordingMeeting */
private $recordingMeeting;
/** @var DateTime */
public $startDateTime;
/** @var string */
public $formattedStartTime;
/** @var DateInterval */
public $durationInterval;
/** @var string */
public $formattedDuration;
/**
* @param $name
*
* @throws Exception
*
* @return mixed
*/
public function __get($name)
{
$object = $this->getRecordingMeeting();
if (property_exists($object, $name)) {
return $object->$name;
}
throw new Exception(sprintf('%s does not know property %s', $this, $name));
}
/**
* @return string
*/
public function __toString()
{
return sprintf('Recording %d', $this->uuid);
}
/**
* @return MeetingEntity
*/
public function getMeeting()
{
return $this->meeting;
}
/**
* @return RecordingMeeting
*
* @throws Exception
*/
public function getRecordingMeeting()
{
return $this->recordingMeeting;
}
/**
* @param MeetingEntity $meeting
*
* @return $this
*/
public function setMeeting($meeting)
{
$this->meeting = $meeting;
$this->meeting->getRecordings()->add($this);
return $this;
}
/**
* @param RecordingMeeting $recordingMeeting
*
* @throws Exception
*
* @return RecordingEntity
*/
public function setRecordingMeeting($recordingMeeting)
{
if (is_null($this->uuid)) {
$this->uuid = $recordingMeeting->uuid;
} elseif ($this->uuid !== $recordingMeeting->uuid) {
throw new Exception('the RecordingEntity identifier differs from the RecordingMeeting identifier');
}
if (is_null($this->meeting)) {
$this->meeting = Database::getManager()->getRepository(MeetingEntity::class)->find($recordingMeeting->id);
// $this->meeting remains null when the remote RecordingMeeting refers to a deleted meeting
} elseif ($this->meeting->getId() != $recordingMeeting->id) {
throw new Exception('The RecordingEntity meeting id differs from the RecordingMeeting meeting id');
}
$this->recordingMeeting = $recordingMeeting;
return $this;
}
/**
* @ORM\PostLoad
*
* @throws Exception
*/
public function postLoad()
{
if (!is_null($this->recordingMeetingJson)) {
$this->recordingMeeting = RecordingMeeting::fromJson($this->recordingMeetingJson);
}
$this->initializeExtraProperties();
}
/**
* @ORM\PreFlush
*/
public function preFlush()
{
if (!is_null($this->recordingMeeting)) {
$this->recordingMeetingJson = json_encode($this->recordingMeeting);
}
}
/**
* @throws Exception
*/
public function initializeExtraProperties()
{
$this->startDateTime = new DateTime($this->recordingMeeting->start_time);
$this->startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get()));
$this->formattedStartTime = $this->startDateTime->format(get_lang('Y-m-d H:i'));
$now = new DateTime();
$later = new DateTime();
$later->add(new DateInterval('PT'.$this->recordingMeeting->duration.'M'));
$this->durationInterval = $later->diff($now);
$this->formattedDuration = $this->durationInterval->format(get_lang('DurationFormat'));
}
}

@ -0,0 +1,258 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Chamilo\PluginBundle\Zoom\API\CreatedRegistration;
use Chamilo\PluginBundle\Zoom\API\MeetingRegistrant;
use Chamilo\PluginBundle\Zoom\API\MeetingRegistrantListItem;
use Chamilo\UserBundle\Entity\User;
use Doctrine\ORM\Mapping as ORM;
use Exception;
/**
* Class RegistrantEntity.
* @package Chamilo\PluginBundle\Zoom
* @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\RegistrantEntityRepository")
* @ORM\Table(
* name="plugin_zoom_registrant",
* indexes={
* @ORM\Index(name="user_id_index", columns={"user_id"}),
* @ORM\Index(name="meeting_id_index", columns={"meeting_id"}),
* }
* )
* @ORM\HasLifecycleCallbacks
*/
class RegistrantEntity
{
/**
* @var string
* @ORM\Column(type="string")
* @ORM\Id
*/
private $id;
/**
* @var User
* @ORM\ManyToOne(
* targetEntity="Chamilo\UserBundle\Entity\User",
* )
* @ORM\JoinColumn(name="user_id", nullable=false)
*/
private $user;
/**
* @var MeetingEntity
* @ORM\ManyToOne(
* targetEntity="MeetingEntity",
* inversedBy="registrants",
* )
* @ORM\JoinColumn(name="meeting_id")
*/
private $meeting;
/**
* @var string
* @ORM\Column(type="text", name="created_registration_json", nullable=true)
*/
private $createdRegistrationJson;
/**
* @var string
* @ORM\Column(type="text", name="meeting_registrant_list_item_json", nullable=true)
*/
private $meetingRegistrantListItemJson;
/**
* @var string
* @ORM\Column(type="text", name="meeting_registrant_json", nullable=true)
*/
private $meetingRegistrantJson;
/** @var CreatedRegistration */
private $createdRegistration;
/** @var MeetingRegistrant */
private $meetingRegistrant;
/** @var MeetingRegistrantListItem */
private $meetingRegistrantListItem;
/** @var string */
public $fullName;
/**
* @return string
*/
public function __toString()
{
return sprintf('Registrant %d', $this->id);
}
/**
* @return MeetingEntity
*/
public function getMeeting()
{
return $this->meeting;
}
/**
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* @return MeetingRegistrantListItem
*
* @throws Exception
*/
public function getMeetingRegistrantListItem()
{
return $this->meetingRegistrantListItem;
}
/**
* @return CreatedRegistration
*
* @throws Exception
*/
public function getCreatedRegistration()
{
return $this->createdRegistration;
}
/**
* @return MeetingRegistrant
*
* @throws Exception
*/
public function getMeetingRegistrant()
{
return $this->meetingRegistrant;
}
/**
* @param MeetingEntity $meeting
*
* @return $this
*/
public function setMeeting($meeting)
{
$this->meeting = $meeting;
$this->meeting->getRegistrants()->add($this);
return $this;
}
/**
* @param User $user
*
* @return $this
*/
public function setUser($user)
{
$this->user = $user;
return $this;
}
/**
* @param MeetingRegistrantListItem $meetingRegistrantListItem
*
* @throws Exception
*
* @return $this
*/
public function setMeetingRegistrantListItem($meetingRegistrantListItem)
{
if (!is_null($this->meeting) && $this->meeting->getId() != $meetingRegistrantListItem->id) {
throw new Exception('RegistrantEntity meeting id differs from MeetingRegistrantListItem id');
}
$this->meetingRegistrantListItem = $meetingRegistrantListItem;
$this->computeFullName();
return $this;
}
/**
* @param CreatedRegistration $createdRegistration
*
* @throws Exception
*
* @return $this
*/
public function setCreatedRegistration($createdRegistration)
{
if (is_null($this->id)) {
$this->id = $createdRegistration->registrant_id;
} elseif ($this->id != $createdRegistration->registrant_id) {
throw new Exception('RegistrantEntity id differs from CreatedRegistration identifier');
}
$this->createdRegistration = $createdRegistration;
return $this;
}
/**
* @param MeetingRegistrant $meetingRegistrant
*
* @throws Exception
*
* @return $this
*/
public function setMeetingRegistrant($meetingRegistrant)
{
$this->meetingRegistrant = $meetingRegistrant;
$this->computeFullName();
return $this;
}
/**
* @ORM\PostLoad
* @throws Exception
*/
public function postLoad()
{
if (!is_null($this->meetingRegistrantJson)) {
$this->meetingRegistrant = MeetingRegistrant::fromJson($this->meetingRegistrantJson);
}
if (!is_null($this->createdRegistrationJson)) {
$this->createdRegistration = CreatedRegistration::fromJson($this->createdRegistrationJson);
}
if (!is_null($this->meetingRegistrantListItemJson)) {
$this->meetingRegistrantListItem = MeetingRegistrantListItem::fromJson(
$this->meetingRegistrantListItemJson
);
}
$this->computeFullName();
}
/**
* @ORM\PreFlush
*/
public function preFlush()
{
if (!is_null($this->meetingRegistrant)) {
$this->meetingRegistrantJson = json_encode($this->meetingRegistrant);
}
if (!is_null($this->createdRegistration)) {
$this->createdRegistrationJson = json_encode($this->createdRegistration);
}
if (!is_null($this->meetingRegistrantListItem)) {
$this->meetingRegistrantListItemJson = json_encode($this->meetingRegistrantListItem);
}
}
public function computeFullName()
{
$this->fullName = api_get_person_name(
$this->meetingRegistrant->first_name,
$this->meetingRegistrant->last_name
);
}
}

@ -16,14 +16,17 @@ $plugin = ZoomPlugin::create();
$this_section = SECTION_PLATFORM_ADMIN;
$form = $plugin->getAdminSearchForm();
$startDate = new DateTime($form->getElement('start')->getValue());
$endDate = new DateTime($form->getElement('end')->getValue());
$type = $form->getElement('type')->getValue();
$startDate = new DateTime($form->getSubmitValue('start'));
$endDate = new DateTime($form->getSubmitValue('end'));
$reloadRecordingLists = $form->getSubmitValue('reloadRecordingLists');
if ($reloadRecordingLists) {
$plugin->reloadPeriodRecordings($startDate, $endDate);
}
$tpl = new Template($tool_name);
$tpl->assign('meetings', $plugin->getPeriodMeetings($type, $startDate, $endDate));
$tpl->assign('meetings', $plugin->getMeetingRepository()->periodMeetings($startDate, $endDate));
if ($plugin->get('enableCloudRecording')) {
$tpl->assign('recordings', $plugin->getRecordings($startDate, $endDate));
$tpl->assign('recordings', $plugin->getRecordingRepository()->getPeriodRecordings($startDate, $endDate));
}
$tpl->assign('search_form', $form->returnForm());
$tpl->assign('content', $tpl->fetch('zoom/view/admin.tpl'));

@ -0,0 +1,30 @@
<?php
/* For license terms, see /license.txt */
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables
require_once __DIR__.'/config.php';
if (!api_user_is_login()) {
api_not_allowed(true);
}
$plugin = ZoomPlugin::create();
Display::display_header($plugin->get_title());
try {
printf(
'<div class="embed-responsive embed-responsive-16by9">
<a class="embed-responsive-item" href="%s" target="_blank">%s</a>
</div>',
$plugin->getGlobalMeetingURL(),
get_lang('JoinGlobalVideoConference')
);
} catch (Exception $exception) {
Display::addFlash(
Display::return_message($exception->getMessage(), 'error')
);
}
Display::display_footer();

@ -0,0 +1,42 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\PluginBundle\Zoom\MeetingEntity;
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables
require_once __DIR__.'/config.php';
if (!api_user_is_login()) {
api_not_allowed(true);
exit(); // just in case
}
$plugin = ZoomPlugin::create();
Display::display_header($plugin->get_title());
if (array_key_exists('meetingId', $_REQUEST)) {
/** @var MeetingEntity $meeting */
$meeting = $plugin->getMeetingRepository()->find($_REQUEST['meetingId']);
try {
if (is_null($meeting)) {
throw new Exception('Meeting not found');
}
// TODO introduce the meeting
printf(
'<div class="embed-responsive embed-responsive-16by9">
<a class="embed-responsive-item" href="%s" target="_blank">%s</a>
</div>',
$plugin->getUserMeetingURL($meeting),
get_lang('JoinMeetingAsMyself')
);
} catch (Exception $exception) {
Display::addFlash(
Display::return_message($exception->getMessage(), 'error')
);
}
}
Display::display_footer();

@ -46,6 +46,7 @@ Will not work for a <em>basic</em> profile.";
// please keep these lines alphabetically sorted
$strings['AllCourseUsersWereRegistered'] = "All course students were registered";
$strings['Agenda'] = "Agenda";
$strings['CannotRegisterWithoutEmailAddress'] = "Cannot register without email address";
$strings['CopyingJoinURL'] = "Copying join URL";
$strings['CopyJoinAsURL'] = "Copy 'join as' URL";
$strings['CopyToCourse'] = "Copy to course";
@ -53,6 +54,8 @@ $strings['CouldNotCopyJoinURL'] = "Could not copy join URL";
$strings['Course'] = "Cours";
$strings['CreatedAt'] = "Created at";
$strings['CreateLinkInCourse'] = "Create link(s) in course";
$strings['CreateUserVideoConference'] = "Create user conferences";
$strings['DateMeetingTitle'] = "%s: %s";
$strings['DeleteMeeting'] = "Delete meeting";
$strings['DeleteFile'] = "Delete file(s)";
$strings['Details'] = "Details";
@ -65,8 +68,11 @@ $strings['Files'] = "Files";
$strings['Finished'] = "finished";
$strings['FileWasCopiedToCourse'] = "The file was copied to the course";
$strings['FileWasDeleted'] = "The file was deleted";
$strings['GlobalMeeting'] = "Global meeting";
$strings['GroupUsersWereRegistered'] = "Group members were registered";
$strings['InstantMeeting'] = "Instant meeting";
$strings['Join'] = "Join";
$strings['JoinGlobalVideoConference'] = "Join global conference";
$strings['JoinMeetingAsMyself'] = "Join meeting as myself";
$strings['JoinURLCopied'] = "Join URL copied";
$strings['JoinURLToSendToParticipants'] = "Join URL to send to participants";
@ -105,4 +111,5 @@ $strings['UserRegistration'] = "User registration";
$strings['Y-m-d H:i'] = "Y-m-d H:i";
$strings['Waiting'] = "waiting";
$strings['XRecordingOfMeetingXFromXDurationXDotX'] = "%s recording of meeting %s from %s (%s).%s";
$strings['YouAreNotRegisteredToThisMeeting'] = "You are not registered to this meeting";
$strings['ZoomVideoConferences'] = "Zoom Video Conferences";

@ -45,6 +45,7 @@ Ne fonctionnera pas pour un profil <em>de base</em>.";
// please keep these lines alphabetically sorted
$strings['AllCourseUsersWereRegistered'] = "Tous les étudiants du cours sont inscrits";
$strings['Agenda'] = "Ordre du jour";
$strings['CannotRegisterWithoutEmailAddress'] = "Impossible d'inscrire un utilisateur sans adresse de courriel";
$strings['CopyingJoinURL'] = "Copie de l'URL pour rejoindre en cours";
$strings['CopyJoinAsURL'] = "Copier l'URL pour 'rejoindre en tant que'";
$strings['CopyToCourse'] = "Copier dans le cours";
@ -52,6 +53,8 @@ $strings['CouldNotCopyJoinURL'] = "Échec de la copie de l'URL pour rejoindre";
$strings['Course'] = "Cours";
$strings['CreatedAt'] = "Créé à";
$strings['CreateLinkInCourse'] = "Créer dans le cours un ou des lien(s) vers le(s) fichier(s)";
$strings['CreateUserVideoConference'] = "Créer des conferences par utilisateur";
$strings['DateMeetingTitle'] = "%s : %s";
$strings['DeleteMeeting'] = "Effacer la conférence";
$strings['DeleteFile'] = "Supprimer ce(s) fichier(s)";
$strings['Details'] = "Détail";
@ -64,8 +67,11 @@ $strings['Files'] = "Fichiers";
$strings['Finished'] = "terminée";
$strings['FileWasCopiedToCourse'] = "Le fichier a été copié dans le cours";
$strings['FileWasDeleted'] = "Le fichier a été effacé";
$strings['GlobalMeeting'] = "Conférence globale";
$strings['GroupUsersWereRegistered'] = "Les membres des groupes ont été inscrits";
$strings['InstantMeeting'] = "Conférence instantanée";
$strings['Join'] = "Rejoindre";
$strings['JoinGlobalVideoConference'] = "Rejoindre la conférence globale";
$strings['JoinMeetingAsMyself'] = "Rejoindre la conférence en tant que moi-même";
$strings['JoinURLCopied'] = "URL pour rejoindre copiée";
$strings['JoinURLToSendToParticipants'] = "URL pour assister à la conférence (à envoyer aux participants)";
@ -104,4 +110,5 @@ $strings['UserRegistration'] = "Inscription des utilisateurs";
$strings['Y-m-d H:i'] = "d/m/Y à H\hi";
$strings['Waiting'] = "en attente";
$strings['XRecordingOfMeetingXFromXDurationXDotX'] = "Enregistrement (%s) de la conférence %s de %s (%s).%s";
$strings['YouAreNotRegisteredToThisMeeting'] = "Vous n'êtes pas inscrit à cette conférence";
$strings['ZoomVideoConferences'] = "Conférences vidéo Zoom";

@ -44,6 +44,7 @@ No funcionará para un perfil <em>base/gratuito</em>.";
// please keep these lines alphabetically sorted
$strings['AllCourseUsersWereRegistered'] = "Todos los alumnos del curso están inscritos";
$strings['Agenda'] = "Orden del día";
$strings['CannotRegisterWithoutEmailAddress'] = "No se puede registrar usuario sin dirección de correo electrónico";
$strings['CopyingJoinURL'] = "Copia de la URL para ingresar";
$strings['CopyJoinAsURL'] = "Copiar la URL para 'ingresar como'";
$strings['CopyToCourse'] = "Copiar en el curso";
@ -51,6 +52,8 @@ $strings['CouldNotCopyJoinURL'] = "Falló la copia de la URL de ingreso";
$strings['Course'] = "Curso";
$strings['CreatedAt'] = "Creado el";
$strings['CreateLinkInCourse'] = "Crear en el curso uno o más vínculos hacia el/los archivo(s)";
$strings['CreateUserVideoConference'] = "Crear conferencias de usario";
$strings['DateMeetingTitle'] = "%s: %s";
$strings['DeleteMeeting'] = "Borrar la conferencia";
$strings['DeleteFile'] = "Borrar este/estos archivo(s)";
$strings['Details'] = "Detalle";
@ -63,8 +66,11 @@ $strings['Files'] = "Archivos";
$strings['Finished'] = "terminada";
$strings['FileWasCopiedToCourse'] = "El archivo ha sido copiado en el curso";
$strings['FileWasDeleted'] = "El archivo ha sido borrado";
$strings['GlobalMeeting'] = "Conferencia global";
$strings['GroupUsersWereRegistered'] = "Miembros de los grupos han sido registrados";
$strings['InstantMeeting'] = "Conferencia instantánea";
$strings['Join'] = "Ingresar";
$strings['JoinGlobalVideoConference'] = "Ingresar la conrencia global";
$strings['JoinMeetingAsMyself'] = "Ingresar la conferencia como yo mismo";
$strings['JoinURLCopied'] = "URL para juntarse copiada";
$strings['JoinURLToSendToParticipants'] = "URL para asistir a la conferencia (para enviar a los participantes)";
@ -103,4 +109,5 @@ $strings['UserRegistration'] = "Inscripción de los usuarios";
$strings['Y-m-d H:i'] = "d/m/Y a las H\hi";
$strings['Waiting'] = "en espera";
$strings['XRecordingOfMeetingXFromXDurationXDotX'] = "Grabación (%s) de la conferencia %s de %s (%s).%s";
$strings['YouAreNotRegisteredToThisMeeting'] = "No estás registrado en esta reunión";
$strings['ZoomVideoConferences'] = "Videoconferencias Zoom";

@ -13,8 +13,31 @@ use Exception;
*
* @package Chamilo\PluginBundle\Zoom\API
*/
interface Client
abstract class Client
{
/** @var Client */
private static $instance;
/**
* Returns an initialized Client.
*
* @return Client
*/
public static function getInstance()
{
return self::$instance;
}
/**
* Registers an initialized Client.
*
* @param Client $instance
*/
protected static function register($instance)
{
self::$instance = $instance;
}
/**
* Sends a Zoom API-compliant HTTP request and retrieves the response.
*
@ -30,5 +53,5 @@ interface Client
*
* @return string response body (not json-decoded)
*/
public function send($httpMethod, $relativePath, $parameters = [], $requestBody = null);
abstract public function send($httpMethod, $relativePath, $parameters = [], $requestBody = null);
}

@ -13,7 +13,7 @@ use Firebase\JWT\JWT;
*
* @package Chamilo\PluginBundle\Zoom
*/
class JWTClient implements Client
class JWTClient extends Client
{
public $token;
@ -33,6 +33,7 @@ class JWTClient implements Client
],
$apiSecret
);
self::register($this);
}
/**

@ -57,15 +57,13 @@ class Meeting
/**
* Creates a meeting on the server and returns the resulting MeetingInfoGet.
*
* @param Client $client an API client
*
* @throws Exception describing the error (message and code)
*
* @return MeetingInfoGet meeting
*/
public function create($client)
public function create()
{
return MeetingInfoGet::fromJson($client->send('POST', 'users/me/meetings', [], $this));
return MeetingInfoGet::fromJson(Client::getInstance()->send('POST', 'users/me/meetings', [], $this));
}
/**
@ -74,11 +72,9 @@ class Meeting
* @param string $topic
* @param int $type
*
* @throws Exception
*
* @return static
*/
protected static function fromTopicAndType($topic, $type = self::TYPE_SCHEDULED)
public static function fromTopicAndType($topic, $type = self::TYPE_SCHEDULED)
{
$instance = new static();
$instance->topic = $topic;

@ -34,58 +34,50 @@ class MeetingInfoGet extends MeetingInfo
/**
* Retrieves a meeting from its numeric identifier.
*
* @param Client $client
* @param int $id
*
* @throws Exception
*
* @return static the meeting
*/
public static function fromId($client, $id)
public static function fromId($id)
{
return static::fromJson($client->send('GET', "meetings/$id"));
return static::fromJson(Client::getInstance()->send('GET', "meetings/$id"));
}
/**
* Updates the meeting on server.
*
* @param Client $client
*
* @throws Exception
*/
public function update($client)
public function update()
{
$client->send('PATCH', 'meetings/'.$this->id, [], $this);
Client::getInstance()->send('PATCH', 'meetings/'.$this->id, [], $this);
}
/**
* Ends the meeting on server.
*
* @param Client $client
*
* @throws Exception
*/
public function endNow($client)
public function endNow()
{
$client->send('PUT', "meetings/$this->id/status", [], (object) ['action' => 'end']);
Client::getInstance()->send('PUT', "meetings/$this->id/status", [], (object) ['action' => 'end']);
}
/**
* Deletes the meeting on server.
*
* @param Client $client
*
* @throws Exception
*/
public function delete($client)
public function delete()
{
$client->send('DELETE', "meetings/$this->id");
Client::getInstance()->send('DELETE', "meetings/$this->id");
}
/**
* Adds a registrant to the meeting.
*
* @param Client $client
* @param MeetingRegistrant $registrant with at least 'email' and 'first_name'.
* 'last_name' will also be recorded by Zoom.
* Other properties remain ignored, or not returned by Zoom
@ -96,10 +88,10 @@ class MeetingInfoGet extends MeetingInfo
*
* @return CreatedRegistration with unique join_url and registrant_id properties
*/
public function addRegistrant($client, $registrant, $occurrenceIds = '')
public function addRegistrant($registrant, $occurrenceIds = '')
{
return CreatedRegistration::fromJson(
$client->send(
Client::getInstance()->send(
'POST',
"meetings/$this->id/registrants",
empty($occurrenceIds) ? [] : ['occurrence_ids' => $occurrenceIds],
@ -111,16 +103,15 @@ class MeetingInfoGet extends MeetingInfo
/**
* Removes registrants from the meeting.
*
* @param Client $client
* @param MeetingRegistrant[] $registrants registrants to remove (id and email)
* @param string $occurrenceIds separated by comma
*
* @throws Exception
*/
public function removeRegistrants($client, $registrants, $occurrenceIds = '')
public function removeRegistrants($registrants, $occurrenceIds = '')
{
if (!empty($registrants)) {
$client->send(
Client::getInstance()->send(
'PUT',
"meetings/$this->id/registrants/status",
empty($occurrenceIds) ? [] : ['occurrence_ids' => $occurrenceIds],
@ -135,28 +126,24 @@ class MeetingInfoGet extends MeetingInfo
/**
* Retrieves meeting registrants.
*
* @param Client $client
*
* @throws Exception
*
* @return MeetingRegistrantListItem[] the meeting registrants
*/
public function getRegistrants($client)
public function getRegistrants()
{
return MeetingRegistrantList::loadMeetingRegistrants($client, $this->id);
return MeetingRegistrantList::loadMeetingRegistrants($this->id);
}
/**
* Retrieves the meeting's instances.
*
* @param Client $client
*
* @throws Exception
*
* @return MeetingInstance[]
*/
public function getInstances($client)
public function getInstances()
{
return MeetingInstances::fromMeetingId($client, $this->id)->meetings;
return MeetingInstances::fromMeetingId($this->id)->meetings;
}
}

@ -26,28 +26,26 @@ class MeetingInstance
/**
* Retrieves the recording of the instance.
*
* @param Client $client
*
* @throws Exception with code 404 when there is no recording for this meeting
*
* @return RecordingMeeting the recording
*/
public function getRecordings($client)
public function getRecordings()
{
return RecordingMeeting::fromJson($client->send('GET', 'meetings/'.htmlentities($this->uuid).'/recordings'));
return RecordingMeeting::fromJson(
Client::getInstance()->send('GET', 'meetings/'.htmlentities($this->uuid).'/recordings')
);
}
/**
* Retrieves the instance's participants.
*
* @param Client $client
*
* @throws Exception
*
* @return ParticipantListItem[]
*/
public function getParticipants($client)
public function getParticipants()
{
return ParticipantList::loadInstanceParticipants($client, $this->uuid);
return ParticipantList::loadInstanceParticipants($this->uuid);
}
}

@ -30,16 +30,15 @@ class MeetingInstances
/**
* Retrieves a meeting's instances.
*
* @param Client $client
* @param int $meetingId
*
* @throws Exception
*
* @return MeetingInstances the meeting's instances
*/
public static function fromMeetingId($client, $meetingId)
public static function fromMeetingId($meetingId)
{
return static::fromJson($client->send('GET', "past_meetings/$meetingId/instances"));
return static::fromJson(Client::getInstance()->send('GET', "past_meetings/$meetingId/instances"));
}
/**

@ -35,16 +35,15 @@ class MeetingList
/**
* Retrieves all meetings of a type.
*
* @param Client $client
* @param int $type TYPE_SCHEDULED, TYPE_LIVE or TYPE_UPCOMING
*
* @throws Exception
*
* @return MeetingListItem[] all meetings
*/
public static function loadMeetings($client, $type)
public static function loadMeetings($type)
{
return static::loadItems('meetings', $client, 'users/me/meetings', ['type' => $type]);
return static::loadItems('meetings', 'users/me/meetings', ['type' => $type]);
}
/**

@ -77,14 +77,19 @@ class MeetingRegistrant
/**
* @param string $email
* @param string $firstName
* @param string $lastName
*
* @return MeetingRegistrant
*/
public static function fromEmailAndFirstName($email, $firstName)
public static function fromEmailAndFirstName($email, $firstName, $lastName = null)
{
$instance = new static();
$instance->first_name = $firstName;
$instance->email = $email;
$instance->first_name = $firstName;
if (!is_null($lastName)) {
$instance->last_name = $lastName;
}
return $instance;
}

@ -30,16 +30,15 @@ class MeetingRegistrantList
/**
* Retrieves all registrant for a meeting.
*
* @param Client $client
* @param int $meetingId
*
* @throws Exception
*
* @return MeetingRegistrantListItem[] all registrants of the meeting
*/
public static function loadMeetingRegistrants($client, $meetingId)
public static function loadMeetingRegistrants($meetingId)
{
return static::loadItems('registrants', $client, "meetings/$meetingId/registrants");
return static::loadItems('registrants', "meetings/$meetingId/registrants");
}
/**

@ -32,7 +32,6 @@ trait Pagination
* Retrieves all items from the server, possibly generating several API calls.
*
* @param string $arrayPropertyName item array property name
* @param Client $client
* @param string $relativePath relative path to pass to Client::send
* @param array $parameters parameter array to pass to Client::send
*
@ -40,7 +39,7 @@ trait Pagination
*
* @return array united list of items
*/
protected static function loadItems($arrayPropertyName, $client, $relativePath, $parameters = [])
protected static function loadItems($arrayPropertyName, $relativePath, $parameters = [])
{
$items = [];
$pageCount = 1;
@ -48,7 +47,7 @@ trait Pagination
$totalRecords = 0;
for ($pageNumber = 1; $pageNumber <= $pageCount; $pageNumber++) {
$response = static::fromJson(
$client->send(
Client::getInstance()->send(
'GET',
$relativePath,
array_merge(['page_size' => $pageSize, 'page_number' => $pageNumber], $parameters)

@ -35,7 +35,6 @@ trait PaginationToken
* Retrieves all items from the server, possibly generating several API calls.
*
* @param string $arrayPropertyName item array property name
* @param Client $client
* @param string $relativePath relative path to pass to Client::send
* @param array $parameters parameter array to pass to Client::send
*
@ -43,7 +42,7 @@ trait PaginationToken
*
* @return array united list of items
*/
protected static function loadItems($arrayPropertyName, $client, $relativePath, $parameters = [])
protected static function loadItems($arrayPropertyName, $relativePath, $parameters = [])
{
$items = [];
$pageSize = 300;
@ -51,7 +50,7 @@ trait PaginationToken
$nextPageToken = '';
do {
$response = static::fromJson(
$client->send(
Client::getInstance()->send(
'GET',
$relativePath,
array_merge(['page_size' => $pageSize, 'next_page_token' => $nextPageToken], $parameters)

@ -31,18 +31,16 @@ class ParticipantList
/**
* Retrieves a meeting instance's participants.
*
* @param Client $client
* @param string $instanceUUID
*
* @throws Exception
*
* @return ParticipantListItem[] participants
*/
public static function loadInstanceParticipants($client, $instanceUUID)
public static function loadInstanceParticipants($instanceUUID)
{
return static::loadItems(
'participants',
$client,
'past_meetings/'.htmlentities($instanceUUID).'/participants'
);
}

@ -50,29 +50,26 @@ class PastMeeting extends Meeting
/**
* Retrieves a past meeting instance from its identifier.
*
* @param Client $client
* @param string $uuid
*
* @throws Exception
*
* @return PastMeeting the past meeting
*/
public static function fromUUID($client, $uuid)
public static function fromUUID($uuid)
{
return static::fromJson($client->send('GET', 'past_meetings/'.htmlentities($uuid)));
return static::fromJson(Client::getInstance()->send('GET', 'past_meetings/'.htmlentities($uuid)));
}
/**
* Retrieves information on participants from a past meeting instance.
*
* @param Client $client
*
* @throws Exception
*
* @return ParticipantListItem[] participants
*/
public function getParticipants($client)
public function getParticipants()
{
return ParticipantList::loadInstanceParticipants($client, $this->uuid);
return ParticipantList::loadInstanceParticipants($this->uuid);
}
}

@ -95,13 +95,11 @@ class RecordingFile
/**
* Deletes the file.
*
* @param Client $client
*
* @throws Exception
*/
public function delete($client)
public function delete()
{
$client->send(
Client::getInstance()->send(
'DELETE',
"/meetings/$this->meeting_id/recordings/$this->id",
['action' => 'delete']

@ -34,7 +34,6 @@ class RecordingList
/**
* Retrieves all recordings from a period of time.
*
* @param Client $client
* @param DateTime $startDate first day of the period
* @param DateTime $endDate last day of the period
*
@ -42,11 +41,10 @@ class RecordingList
*
* @return RecordingMeeting[] all recordings from that period
*/
public static function loadPeriodRecordings($client, $startDate, $endDate)
public static function loadPeriodRecordings($startDate, $endDate)
{
return static::loadItems(
'meetings',
$client,
'users/me/recordings',
[
'from' => $startDate->format('Y-m-d'),

@ -69,13 +69,15 @@ class RecordingMeeting
/**
* Deletes the recording on the server.
*
* @param Client $client
*
* @throws Exception
*/
public function delete($client)
public function delete()
{
$client->send('DELETE', 'meetings/'.htmlentities($this->uuid).'/recordings', ['action' => 'delete']);
Client::getInstance()->send(
'DELETE',
'meetings/'.htmlentities($this->uuid).'/recordings',
['action' => 'delete']
);
}
/**

@ -1,69 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Exception;
/**
* Class CourseMeeting. A remote Zoom meeting linked to a local course.
* An instance of this class is required to create a remote meeting from scratch.
*
* @package Chamilo\PluginBundle\Zoom
*/
class CourseMeeting extends API\Meeting
{
use CourseMeetingTrait;
use DisplayableMeetingTrait;
/**
* Creates a CourseMeeting instance from a topic.
*
* @param int $courseId
* @param int $sessionId
* @param string $topic
* @param int $type
*
* @throws Exception
*
* @return static
*/
public static function fromCourseSessionTopicAndType($courseId, $sessionId, $topic, $type)
{
$instance = static::fromTopicAndType($topic, $type);
$instance->setCourseAndSessionId($courseId, $sessionId);
$instance->initializeDisplayableProperties();
return $instance;
}
/**
* {@inheritdoc}
*
* @throws Exception
*/
public function initializeExtraProperties()
{
parent::initializeExtraProperties();
$this->decodeAndRemoveTag();
$this->initializeDisplayableProperties();
}
/**
* {@inheritdoc}
*
* Creates a tagged meeting
*
* @return CourseMeetingInfoGet
*/
public function create($client)
{
$new = new CourseMeetingInfoGet();
$this->tagAgenda();
static::recursivelyCopyObjectProperties(parent::create($client), $new);
$this->untagAgenda();
return $new;
}
}

@ -1,57 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Exception;
/**
* Class CourseMeetingInfoGet. A full Meeting as returned by the server and locally linked to a course.
*
* @package Chamilo\PluginBundle\Zoom
*/
class CourseMeetingInfoGet extends API\MeetingInfoGet
{
use CourseMeetingTrait;
use DisplayableMeetingTrait;
/**
* {@inheritdoc}
*
* @throws Exception
*/
public function initializeExtraProperties()
{
parent::initializeExtraProperties();
$this->decodeAndRemoveTag();
$this->initializeDisplayableProperties();
}
/**
* Updates the meeting on server, tagging it so to remember its course and session.
*
* @param API\Client $client
*
* @throws Exception
*/
public function update($client)
{
$this->tagAgenda();
parent::update($client);
$this->untagAgenda();
}
/**
* Retrieves meeting registrants.
*
* @param API\Client $client
*
* @throws Exception
*
* @return UserMeetingRegistrantListItem[]
*/
public function getUserRegistrants($client)
{
return UserMeetingRegistrantList::loadUserMeetingRegistrants($client, $this->id);
}
}

@ -1,26 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
/**
* Class CourseMeetingList. A List of course meetings.
*
* @see CourseMeetingListItem
*
* @package Chamilo\PluginBundle\Zoom
*/
class CourseMeetingList extends API\MeetingList
{
/**
* {@inheritdoc}
*/
public function itemClass($propertyName)
{
if ('meetings' === $propertyName) {
return CourseMeetingListItem::class;
}
return parent::itemClass($propertyName);
}
}

@ -1,31 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Exception;
/**
* Class CourseMeetingListItem. An item from a course meeting list.
*
* @see CourseMeetingList
*
* @package Chamilo\PluginBundle\Zoom
*/
class CourseMeetingListItem extends API\MeetingListItem
{
use CourseMeetingTrait;
use DisplayableMeetingTrait;
/**
* {@inheritdoc}
*
* @throws Exception
*/
public function initializeExtraProperties()
{
parent::initializeExtraProperties();
$this->decodeAndRemoveTag();
$this->initializeDisplayableProperties();
}
}

@ -1,142 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
use Chamilo\UserBundle\Entity\User;
use Database;
/**
* Trait CourseMeetingTrait.
* A Zoom meeting linked to a (course, session) pair.
* The course and session IDs are stored in the meeting agenda on write operations, read and removed on retrieval.
*
* @package Chamilo\PluginBundle\Zoom
*/
trait CourseMeetingTrait
{
use API\BaseMeetingTrait;
/** @var bool whether the agenda contains the course and session identifiers */
public $isTaggedWithCourseId;
/** @var int meeting course id as found in the agenda field */
public $courseId;
/** @var Course meeting course */
public $course;
/** @var int meeting session id as found in the agenda field */
public $sessionId;
/** @var Session meeting session */
public $session;
public function loadCourse()
{
$this->course = Database::getManager()->getRepository('ChamiloCoreBundle:Course')->find($this->courseId);
}
public function loadSession()
{
$this->session = $this->sessionId
? Database::getManager()->getRepository('ChamiloCoreBundle:Session')->find($this->sessionId)
: null;
}
public function setCourseAndSessionId($courseId, $sessionId)
{
$this->courseId = $courseId;
$this->sessionId = $sessionId;
}
public function tagAgenda()
{
$this->agenda = $this->getUntaggedAgenda().$this->getTag();
}
public function untagAgenda()
{
$this->agenda = $this->getUntaggedAgenda();
}
/**
* Builds the list of users that can register into this meeting.
*
* @return User[] the list of users
*/
public function getCourseAndSessionUsers()
{
if ($this->sessionId && is_null($this->session)) {
$this->loadSession();
}
if (is_null($this->course)) {
$this->loadCourse();
}
$users = [];
if (is_null($this->session)) {
$users = Database::getManager()->getRepository(
'ChamiloCoreBundle:Course'
)->getSubscribedUsers($this->course)->getQuery()->getResult();
} else {
$subscriptions = $this->session->getUserCourseSubscriptionsByStatus($this->course, Session::STUDENT);
if ($subscriptions) {
/** @var SessionRelCourseRelUser $sessionCourseUser */
foreach ($subscriptions as $sessionCourseUser) {
$users[$sessionCourseUser->getUser()->getUserId()] = $sessionCourseUser->getUser();
}
}
}
return $users;
}
/**
* @param int $courseId
* @param int $sessionId
*
* @return bool whether both values match this CourseMeeting
*/
public function matches($courseId, $sessionId)
{
return $courseId == $this->courseId && $sessionId == $this->sessionId;
}
protected function decodeAndRemoveTag()
{
$this->isTaggedWithCourseId = preg_match(self::getTagPattern(), $this->agenda, $matches);
if ($this->isTaggedWithCourseId) {
$this->setCourseAndSessionId($matches['courseId'], $matches['sessionId']);
$this->untagAgenda();
} else {
$this->setCourseAndSessionId(0, 0);
}
$this->course = null;
$this->session = null;
}
protected function getUntaggedAgenda()
{
return str_replace($this->getTag(), '', $this->agenda);
}
/**
* @return string a tag to append to a meeting agenda so to link it to a (course, session) tuple
*/
private function getTag()
{
return "\n(course $this->courseId, session $this->sessionId)";
}
private static function getTagPattern()
{
return '/course (?P<courseId>\d+), session (?P<sessionId>\d+)/m';
}
}

@ -1,74 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use DateInterval;
use DateTime;
use DateTimeZone;
use Exception;
/**
* Trait DisplayableMeetingTrait. Extra properties to help formatting web views and time operations.
*
* @package Chamilo\PluginBundle\Zoom
*/
trait DisplayableMeetingTrait
{
use API\BaseMeetingTrait;
/** @var string meeting type name */
public $typeName;
/** @var DateTime meeting start time as a DateTime instance */
public $startDateTime;
/** @var string meeting formatted start time */
public $formattedStartTime;
/** @var DateInterval meeting duration as a DateInterval instance */
public $durationInterval;
/** @var string meeting formatted duration */
public $formattedDuration;
/** @var string */
public $statusName;
/**
* @throws Exception on unexpected start_time or duration
*/
public function initializeDisplayableProperties()
{
$this->typeName = [
API\Meeting::TYPE_INSTANT => get_lang('InstantMeeting'),
API\Meeting::TYPE_SCHEDULED => get_lang('ScheduledMeeting'),
API\Meeting::TYPE_RECURRING_WITH_NO_FIXED_TIME => get_lang('RecurringWithNoFixedTime'),
API\Meeting::TYPE_RECURRING_WITH_FIXED_TIME => get_lang('RecurringWithFixedTime'),
][$this->type];
if (property_exists($this, 'status')) {
$this->statusName = [
'waiting' => get_lang('Waiting'),
'started' => get_lang('Started'),
'finished' => get_lang('Finished'),
][$this->status];
}
$this->startDateTime = null;
$this->formattedStartTime = '';
$this->durationInterval = null;
$this->formattedDuration = '';
if (!empty($this->start_time)) {
$this->startDateTime = new DateTime($this->start_time);
$this->startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get()));
$this->formattedStartTime = $this->startDateTime->format(get_lang('Y-m-d H:i'));
}
if (!empty($this->duration)) {
$now = new DateTime();
$later = new DateTime();
$later->add(new DateInterval('PT'.$this->duration.'M'));
$this->durationInterval = $later->diff($now);
$this->formattedDuration = $this->durationInterval->format(get_lang('DurationFormat'));
}
}
}

@ -1,28 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Exception;
/**
* Class File. A RecordingFile with extra help properties for the web view.
*
* @package Chamilo\PluginBundle\Zoom
*/
class File extends API\RecordingFile
{
/** @var string */
public $formattedFileSize;
/**
* {@inheritdoc}
*
* @throws Exception
*/
public function initializeExtraProperties()
{
parent::initializeExtraProperties();
$this->formattedFileSize = format_file_size($this->file_size);
}
}

@ -0,0 +1,141 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\PageBundle\Entity\User;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\EntityRepository;
/**
* Class MeetingEntityRepository
* @package Chamilo\PluginBundle\Zoom
*/
class MeetingEntityRepository extends EntityRepository
{
/**
* Retrieves information about meetings having a start_time between two dates.
*
* @param DateTime $startDate
* @param DateTime $endDate
*
* @return MeetingEntity[]
*/
public function periodMeetings($startDate, $endDate)
{
$matching = [];
foreach ($this->findAll() as $candidate) {
if ($candidate->startDateTime >= $startDate
&& $candidate->startDateTime <= $endDate
) {
$matching[] = $candidate;
}
}
return $matching;
}
/**
* @return ArrayCollection|Collection|MeetingEntity[]
*/
public function globalMeetings()
{
return $this->matching(
Criteria::create()->where(
Criteria::expr()->andX(
Criteria::expr()->eq('course', null),
Criteria::expr()->eq('user', null)
)
)
);
}
/**
* @return ArrayCollection|Collection|MeetingEntity[]
*/
public function unfinishedGlobalMeetings()
{
return $this->globalMeetings()->filter(
function ($meeting) {
return 'finished' !== $meeting->getMeetingInfoGet()->status;
}
);
}
/**
* Returns either a user's meetings or all user meetings.
*
* @param User|null $user
* @return ArrayCollection|Collection|MeetingEntity[]
*/
public function userMeetings($user = null)
{
return $this->matching(
Criteria::create()->where(
Criteria::expr()->andX(
Criteria::expr()->eq('course', null),
is_null($user)
? Criteria::expr()->neq('user', null)
: Criteria::expr()->eq('user', $user)
)
)
);
}
/**
* @param User|null $user
* @return ArrayCollection|Collection|MeetingEntity[]
*/
public function unfinishedUserMeetings($user = null)
{
return $this->userMeetings($user)->filter(
function ($meeting) {
return 'finished' !== $meeting->getMeetingInfoGet()->status;
}
);
}
/**
* @param DateTime $start
* @param DateTime $end
* @param User|null $user
* @return ArrayCollection|Collection|MeetingEntity[]
*/
public function periodUserMeetings($start, $end, $user = null)
{
return $this->userMeetings($user)->filter(
function ($meeting) use ($start, $end) {
return $meeting->startDateTime >= $start
&& $meeting->startDateTime <= $end;
}
);
}
/**
* Returns either a course's meetings or all course meetings.
*
* @param Course|null $course
* @param Session|null $session
*
* @return ArrayCollection|Collection|MeetingEntity[]
*/
public function courseMeetings($course = null, $session = null)
{
return $this->matching(
Criteria::create()->where(
is_null($course)
? Criteria::expr()->neq('course', null)
: Criteria::expr()->andX(
Criteria::expr()->eq('course', $course),
Criteria::expr()->eq('session', $session)
)
)
);
}
}

@ -1,65 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use DateInterval;
use DateTime;
use DateTimeZone;
use Exception;
/**
* Class Recording. A RecordingMeeting with extra help properties and a list of File instances
* (instead of RecordingFile instances).
*
* @package Chamilo\PluginBundle\Zoom
*/
class Recording extends API\RecordingMeeting
{
/** @var File[] List of recording file. */
public $recording_files;
/** @var DateTime */
public $startDateTime;
/** @var string */
public $formattedStartTime;
/** @var DateInterval */
public $durationInterval;
/** @var string */
public $formattedDuration;
/**
* {@inheritdoc}
*
* @throws Exception
*/
public function initializeExtraProperties()
{
parent::initializeExtraProperties();
$this->startDateTime = new DateTime($this->start_time);
$this->startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get()));
$this->formattedStartTime = $this->startDateTime->format(get_lang('Y-m-d H:i'));
$now = new DateTime();
$later = new DateTime();
$later->add(new DateInterval('PT'.$this->duration.'M'));
$this->durationInterval = $later->diff($now);
$this->formattedDuration = $this->durationInterval->format(get_lang('DurationFormat'));
}
/**
* {@inheritdoc}
*/
public function itemClass($propertyName)
{
if ('recording_files' === $propertyName) {
return File::class;
}
return parent::itemClass($propertyName);
}
}

@ -0,0 +1,66 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Chamilo\ClassificationBundle\Entity\Collection;
use Chamilo\UserBundle\Entity\User;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\EntityRepository;
/**
* Class RecordingEntityRepository
* @package Chamilo\PluginBundle\Zoom
*/
class RecordingEntityRepository extends EntityRepository
{
public function getPeriodRecordings($startDate, $endDate)
{
$matching = [];
foreach ($this->findAll() as $candidate) {
if ($candidate->startDateTime >= $startDate
&& $candidate->startDateTime <= $endDate
) {
$matching[] = $candidate;
}
}
return $matching;
}
/**
* Returns a user's meeting recordings.
*
* @param User $user
* @return ArrayCollection|Collection|RecordingEntity[]
*/
public function userRecordings($user)
{
return $this->matching(
Criteria::create()->where(
Criteria::expr()->in(
'meeting',
$this->getEntityManager()->getRepository(MeetingEntity::class)->userMeetings($user)->toArray()
)
)
);
}
/**
* @param DateTime $start
* @param DateTime $end
* @param User $user
*
* @return ArrayCollection|RecordingEntity[]
*/
public function getPeriodUserRecordings($start, $end, $user)
{
return $this->userRecordings($user)->filter(
function ($meeting) use ($start, $end) {
return $meeting->startDateTime >= $start
&& $meeting->startDateTime <= $end;
}
);
}
}

@ -1,51 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use DateTime;
use Exception;
/**
* Class RecordingList. A list of past meeting instance recordings generated between two dates.
*
* @package Chamilo\PluginBundle\Zoom
*/
class RecordingList extends API\RecordingList
{
/**
* {@inheritdoc}
*/
public function itemClass($propertyName)
{
if ('meetings' === $propertyName) {
return Recording::class;
}
return parent::itemClass($propertyName);
}
/**
* Retrieves all recordings from a period of time.
*
* @param API\Client $client
* @param DateTime $startDate first day of the period
* @param DateTime $endDate last day of the period
*
* @throws Exception
*
* @return Recording[] all recordings from that period
*/
public static function loadRecordings($client, $startDate, $endDate)
{
return static::loadItems(
'meetings',
$client,
'users/me/recordings',
[
'from' => $startDate->format('Y-m-d'),
'to' => $endDate->format('Y-m-d'),
]
);
}
}

@ -0,0 +1,33 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Chamilo\UserBundle\Entity\User;
use DateInterval;
use DateTime;
use Doctrine\ORM\EntityRepository;
/**
* Class RegistrantEntityRepository
* @package Chamilo\PluginBundle\Zoom
*/
class RegistrantEntityRepository extends EntityRepository
{
/**
* Returns the upcoming meeting registrations for the given user.
*
* @param User $user
*
* @return array|RegistrantEntity[]
*/
public function meetingsComingSoonRegistrationsForUser($user)
{
$start = new DateTime();
$end = new DateTime();
$end->add(new DateInterval('P7D'));
$meetings = $this->getEntityManager()->getRepository(MeetingEntity::class)->periodMeetings($start, $end);
return $this->findBy(['meeting' => $meetings, 'user' => $user]);
}
}

@ -1,51 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Chamilo\UserBundle\Entity\User;
use Exception;
/**
* Class UserMeetingRegistrant. Used to register a local user to a meeting.
*
* @package Chamilo\PluginBundle\Zoom
*/
class UserMeetingRegistrant extends API\MeetingRegistrant
{
use UserMeetingRegistrantTrait;
/**
* {@inheritdoc}
*
* @throws Exception
*/
public function initializeExtraProperties()
{
parent::initializeExtraProperties();
$this->decodeAndRemoveTag();
$this->computeFullName();
}
/**
* Creates a UserMeetingRegistrant instance from a user.
*
* @param User $user
*
* @throws Exception
*
* @return static
*/
public static function fromUser($user)
{
$instance = new static();
$instance->email = $user->getEmail();
$instance->first_name = $user->getFirstname();
$instance->last_name = $user->getLastname();
$instance->userId = $user->getId();
$instance->user = $user;
$instance->computeFullName();
return $instance;
}
}

@ -1,43 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Exception;
/**
* Class UserMeetingRegistrantList. A list of users registered to a meeting.
*
* @see UserMeetingRegistrantListItem
*
* @package Chamilo\PluginBundle\Zoom
*/
class UserMeetingRegistrantList extends API\MeetingRegistrantList
{
/**
* {@inheritdoc}
*/
public function itemClass($propertyName)
{
if ('registrants' === $propertyName) {
return UserMeetingRegistrantListItem::class;
}
return parent::itemClass($propertyName);
}
/**
* Retrieves all registrant for a meeting.
*
* @param API\Client $client
* @param int $meetingId
*
* @throws Exception
*
* @return UserMeetingRegistrantListItem[] all registrants of the meeting
*/
public static function loadUserMeetingRegistrants($client, $meetingId)
{
return static::loadItems('registrants', $client, "meetings/$meetingId/registrants");
}
}

@ -1,30 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Exception;
/**
* Class UserMeetingRegistrantListItem. An item of a user registrant list.
*
* @see UserMeetingRegistrantList
*
* @package Chamilo\PluginBundle\Zoom
*/
class UserMeetingRegistrantListItem extends API\MeetingRegistrantListItem
{
use UserMeetingRegistrantTrait;
/**
* {@inheritdoc}
*
* @throws Exception
*/
public function initializeExtraProperties()
{
parent::initializeExtraProperties();
$this->decodeAndRemoveTag();
$this->computeFullName();
}
}

@ -1,89 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Chamilo\UserBundle\Entity\User;
use Database;
/**
* Trait UserMeetingRegistrantTrait.
* A Zoom meeting registrant linked to a local user.
* The user id is stored in the registrant's email address on write operations, read and removed on retrieval.
*
* @package Chamilo\PluginBundle\Zoom
*/
trait UserMeetingRegistrantTrait
{
/** @var bool whether the remote zoom record contains a local user's identifier */
public $isTaggedWithUserId;
/** @var int */
public $userId;
/** @var User */
public $user;
/** @var string */
public $fullName;
public function loadUser()
{
$this->user = Database::getManager()->getRepository('ChamiloUserBundle:User')->find($this->userId);
}
public function setUserId($userId)
{
$this->userId = $userId;
}
public function tagEmail()
{
$this->email = str_replace('@', $this->getTag(), $this->getUntaggedEmail());
}
public function untagEmail()
{
$this->email = $this->getUntaggedEmail();
}
public function matches($userId)
{
return $userId == $this->userId;
}
public function computeFullName()
{
$this->fullName = api_get_person_name($this->first_name, $this->last_name);
}
protected function decodeAndRemoveTag()
{
$this->isTaggedWithUserId = preg_match(self::getTagPattern(), $this->email, $matches);
if ($this->isTaggedWithUserId) {
$this->setUserId($matches['userId']);
$this->untagEmail();
} else {
$this->setUserId(0);
}
$this->user = null;
}
protected function getUntaggedEmail()
{
return str_replace($this->getTag(), '@', $this->email);
}
/**
* @return string a tag to append to a registrant comments so to link it to a user
*/
private function getTag()
{
return "+user_$this->userId@";
}
private static function getTagPattern()
{
return '/\+user_(?P<userId>\d+)@/m';
}
}

File diff suppressed because it is too large Load Diff

@ -1,7 +1,7 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\PluginBundle\Zoom\API\MeetingSettings;
use Chamilo\PluginBundle\Zoom\MeetingEntity;
if (!isset($returnURL)) {
exit;
@ -25,33 +25,34 @@ if (!array_key_exists('meetingId', $_REQUEST)) {
}
$plugin = ZoomPlugin::create();
$meeting = $plugin->getMeeting($_REQUEST['meetingId']);
/** @var MeetingEntity $meeting */
$meeting = $plugin->getMeetingRepository()->find($_REQUEST['meetingId']);
if (is_null($meeting)) {
throw new Exception('MeetingNotFound');
}
$tpl = new Template($meeting->id);
$tpl = new Template($meeting->getId());
if ($plugin->userIsConferenceManager()) {
if ($plugin->userIsConferenceManager($meeting)) {
// user can edit, start and delete meeting
$tpl->assign('isConferenceManager', true);
$tpl->assign('editMeetingForm', $plugin->getEditMeetingForm($meeting)->returnForm());
$tpl->assign('deleteMeetingForm', $plugin->getDeleteMeetingForm($meeting, $returnURL)->returnForm());
if ($plugin->get('enableParticipantRegistration')
&& MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED != $meeting->settings->approval_type) {
list($registerParticipantForm, $registrants) = $plugin->getRegisterParticipantForm($meeting);
$tpl->assign('registerParticipantForm', $registerParticipantForm->returnForm());
$tpl->assign('registrants', $registrants); // FIXME cache
if ($plugin->get('enableParticipantRegistration') && $meeting->requiresRegistration()) {
$tpl->assign('registerParticipantForm', $plugin->getRegisterParticipantForm($meeting)->returnForm());
$tpl->assign('registrants', $meeting->getRegistrants());
}
if ($plugin->get('enableCloudRecording')
&& 'cloud' === $meeting->settings->auto_recording
&& $meeting->hasCloudAutoRecordingEnabled()
// && 'finished' === $meeting->status
) {
list($fileForm, $recordings) = $plugin->getFileForm($meeting);
$tpl->assign('fileForm', $fileForm->returnForm());
$tpl->assign('recordings', $recordings);
$tpl->assign('fileForm', $plugin->getFileForm($meeting)->returnForm());
$tpl->assign('recordings', $meeting->getRecordings());
}
} elseif (MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED != $meeting->settings->approval_type) {
} elseif ($meeting->requiresRegistration()) {
$userId = api_get_user_id();
try {
foreach ($plugin->getRegistrants($meeting) as $registrant) {
foreach ($meeting->getRegistrants() as $registrant) {
if ($registrant->userId == $userId) {
$tpl->assign('currentUserJoinURL', $registrant->join_url);
break;

@ -0,0 +1,13 @@
<?php
/* For license terms, see /license.txt */
require_once __DIR__.'/config.php';
api_protect_admin_script();
$returnURL = 'user.php';
// the section (for the tabs)
$this_section = SECTION_MYPROFILE;
include "meeting.php";

@ -21,14 +21,28 @@ $tpl = new Template($tool_name);
$plugin = ZoomPlugin::create();
if ($plugin->userIsConferenceManager()) {
if ($plugin->userIsCourseConferenceManager(api_get_course_entity())) {
// user can create a new meeting
$tpl->assign('createInstantMeetingForm', $plugin->getCreateInstantMeetingForm()->returnForm());
$tpl->assign('scheduleMeetingForm', $plugin->getScheduleMeetingForm()->returnForm());
$tpl->assign(
'createInstantMeetingForm',
$plugin->getCreateInstantMeetingForm(
api_get_user_entity(api_get_user_id()),
api_get_course_entity(),
api_get_session_entity()
)->returnForm()
);
$tpl->assign('scheduleMeetingForm', $plugin->getScheduleMeetingForm(
api_get_user_entity(api_get_user_id()),
api_get_course_entity(),
api_get_session_entity()
)->returnForm());
}
try {
$tpl->assign('scheduledMeetings', $plugin->getScheduledMeetings());
$tpl->assign(
'scheduledMeetings',
$plugin->getMeetingRepository()->courseMeetings(api_get_course_entity(), api_get_session_entity())
);
} catch (Exception $exception) {
Display::addFlash(
Display::return_message('Could not retrieve scheduled meeting list: '.$exception->getMessage(), 'error')

@ -0,0 +1,36 @@
<?php
/* For license terms, see /license.txt */
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables
require_once __DIR__.'/config.php';
if (!ZoomPlugin::currentUserCanCreateUserMeeting()) {
api_not_allowed(true);
exit(); // just in case
}
$plugin = ZoomPlugin::create();
$user = api_get_user_entity(api_get_user_id());
$form = $plugin->getAdminSearchForm();
$startDate = new DateTime($form->getElement('start')->getValue());
$endDate = new DateTime($form->getElement('end')->getValue());
$reloadRecordingLists = $form->getElement('reloadRecordingLists')->getValue();
if ($reloadRecordingLists) {
$plugin->reloadPeriodRecordings($startDate, $endDate);
}
$tpl = new Template();
$tpl->assign('meetings', $plugin->getMeetingRepository()->periodUserMeetings($startDate, $endDate, $user));
if ($plugin->get('enableCloudRecording')) {
$tpl->assign(
'recordings',
$plugin->getRecordingRepository()->getPeriodUserRecordings($startDate, $endDate, $user)
);
}
$tpl->assign('search_form', $form->returnForm());
$tpl->assign('schedule_form', $plugin->getScheduleMeetingForm($user)->returnForm());
$tpl->assign('content', $tpl->fetch('zoom/view/admin.tpl'));
$tpl->display_one_col_template();

@ -4,6 +4,7 @@
<thead>
<tr>
<th>{{ 'StartTime'|get_lang }}</th>
<th>{{ 'User'|get_lang }}</th>
<th>{{ 'Course'|get_lang }}</th>
<th>{{ 'Session'|get_lang }}</th>
<th>{{ 'Topic'|get_lang }}</th>
@ -17,13 +18,14 @@
{% for meeting in meetings %}
<tr>
<td>{{ meeting.formattedStartTime }}</td>
<td>{{ meeting.course ? meeting.course.title : '-' }}</td>
<td>{{ meeting.session ? meeting.session.name : '-' }}</td>
<td>{{ meeting.topic }}</td>
<td>{{ meeting.user ? meeting.user : '-' }}</td>
<td>{{ meeting.course ? meeting.course : '-' }}</td>
<td>{{ meeting.session ? meeting.session : '-' }}</td>
<td>{{ meeting.meetingInfoGet.topic }}</td>
{% if recordings %}
<td>
{% for recording in recordings %}
{% if recording.id == meeting.id %}
{% if recording.recordingMeeting.id == meeting.id %}
<dl>
<dt>
{{ recording.formattedStartTime }}
@ -31,10 +33,10 @@
</dt>
<dd>
<ul>
{% for file in recording.recording_files %}
{% for file in recording.recordingMeeting.recording_files %}
<li>
{{ file.recording_type }}.{{ file.file_type }}
({{ file.formattedFileSize }})
({{ file.file_size }})
</li>
{% endfor %}
</ul>
@ -52,4 +54,6 @@
</tr>
{% endfor %}
</tbody>
</table>
</table>
{{ schedule_form }}

@ -1,8 +1,8 @@
<p>{{ meeting.typeName }} {{ meeting.id }} ({{ meeting.statusName }})</p>
<p>{{ meeting.typeName }} {{ meeting.id }} ({{ meeting.meetingInfoGet.status }})</p>
{% if isConferenceManager and meeting.status == 'waiting' %}
<p>
<a href="{{ meeting.start_url }}" target="_blank">
<a href="{{ meeting.meetingInfoGet.start_url }}" target="_blank">
{{ 'StartMeeting'|get_lang }}
</a>
</p>
@ -16,11 +16,11 @@
</p>
{% endif %}
{% if meeting.settings.approval_type == 2 %}
{% if meeting.meetingInfoGet.settings.approval_type == 2 %}
<p>
<label>
{{ 'JoinURLToSendToParticipants'|get_lang }}
<input readonly value="{{ meeting.join_url }}">
<input readonly value="{{ meeting.meetingInfoGet.join_url }}">
</label>
</p>
{% endif %}
@ -32,7 +32,7 @@
{{ deleteMeetingForm }}
{{ registerParticipantForm }}
{{ fileForm }}
{% if registrants and meeting.settings.approval_type != 2 %}
{% if registrants and meeting.meetingInfoGet.settings.approval_type != 2 %}
<script>
function copyJoinURL(event, url) {
event.target.textContent = '{{ 'CopyingJoinURL'|get_lang|escape }}';
@ -59,12 +59,12 @@
{% else %}
<h2>{{ meeting.topic }}</h2>
{% if meeting.agenda %}
<blockquote>{{ meeting.agenda| nl2br }}</blockquote>
<h2>{{ meeting.meetingInfoGet.topic }}</h2>
{% if meeting.meetingInfoGet.agenda %}
<blockquote>{{ meeting.meetingInfoGet.agenda| nl2br }}</blockquote>
{% endif %}
{% if meeting.type == 2 or meeting.type == 8 %}
{% if meeting.meetingInfoGet.type == 2 or meeting.meetingInfoGet.type == 8 %}
<dl class="meeting_properties">
<dt>{{ 'StartTime'|get_lang }}</dt>
<dd>{{ meeting.formattedStartTime }}</dd>

@ -21,14 +21,14 @@
<td>{{ meeting.formattedDuration }}</td>
<!-- td>{{ meeting.typeName }}</td -->
<td>
<strong>{{ meeting.topic }}</strong>
<p class="small">{{ meeting.agenda|nl2br }}</p>
<strong>{{ meeting.meetingInfoGet.topic }}</strong>
<p class="small">{{ meeting.meetingInfoGet.agenda|nl2br }}</p>
</td>
<td>
<a class="btn" href="meeting_from_start.php?meetingId={{ meeting.id }}">
{{ 'Details'|get_lang }}
</a>
<a class="btn" href="{{ meeting.join_url }}">
<a class="btn" href="{{ meeting.meetingInfoGet.join_url }}">
{{ 'Join'|get_lang }}
</a>
</td>

Loading…
Cancel
Save