Merge pull request #3383 from sebastiendu/17288-plugin-zoom-global-user-meetings
Plugin: Zoom: global and user Zoom meetings - refs BT#17288pull/3393/head
commit
1cd9918920
@ -0,0 +1,508 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Chamilo\CoreBundle\Entity\Course; |
||||
use Chamilo\CoreBundle\Entity\CourseRelUser; |
||||
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\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 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; |
||||
|
||||
/** |
||||
* @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; |
||||
|
||||
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); |
||||
} |
||||
|
||||
public function setStatus($status) |
||||
{ |
||||
$this->meetingInfoGet->status = $status; |
||||
} |
||||
|
||||
/** |
||||
* 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() |
||||
{ |
||||
/** @var User[] $users */ |
||||
$users = []; |
||||
if (!$this->isCourseMeeting()) { |
||||
$users = Database::getManager()->getRepository('ChamiloUserBundle:User')->findBy(['active' => true]); |
||||
} elseif (is_null($this->session)) { |
||||
if (!is_null($this->course)) { |
||||
/** @var CourseRelUser $courseRelUser */ |
||||
foreach ($this->course->getUsers() as $courseRelUser) { |
||||
$users[] = $courseRelUser->getUser(); |
||||
} |
||||
} |
||||
} 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(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
$activeUsersWithEmail = []; |
||||
foreach ($users as $user) { |
||||
if ($user->isActive() && !empty($user->getEmail())) { |
||||
$activeUsersWithEmail[] = $user; |
||||
} |
||||
} |
||||
|
||||
return $activeUsersWithEmail; |
||||
} |
||||
|
||||
/** |
||||
* @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) |
||||
{ |
||||
return $this->getRegistrants()->exists( |
||||
function (RegistrantEntity $registrantEntity) use (&$user) { |
||||
return $registrantEntity->getUser() === $user; |
||||
} |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @param User $user |
||||
* |
||||
* @return RegistrantEntity|null |
||||
*/ |
||||
public function getRegistrant($user) |
||||
{ |
||||
foreach ($this->getRegistrants() as $registrant) { |
||||
if ($registrant->getUser() === $user) { |
||||
return $registrant; |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Generates a short presentation of the meeting for the future participant. |
||||
* To be displayed above the "Enter meeting" link. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function getIntroduction() |
||||
{ |
||||
$introduction = sprintf('<h1>%s</h1>', $this->meetingInfoGet->topic); |
||||
if (!$this->isGlobalMeeting()) { |
||||
$introduction .= sprintf('<p>%s (%s)</p>', $this->formattedStartTime, $this->formattedDuration); |
||||
} |
||||
if ($this->user) { |
||||
$introduction .= sprintf('<p>%s</p>', $this->user->getFullname()); |
||||
} elseif ($this->isCourseMeeting()) { |
||||
if (is_null($this->session)) { |
||||
$introduction .= sprintf('<p class="main">%s</p>', $this->course); |
||||
} else { |
||||
$introduction .= sprintf('<p class="main">%s (%s)</p>', $this->course, $this->session); |
||||
} |
||||
} |
||||
if (!empty($this->meetingInfoGet->agenda)) { |
||||
$introduction .= sprintf('<p>%s</p>', $this->meetingInfoGet->agenda); |
||||
} |
||||
|
||||
return $introduction; |
||||
} |
||||
|
||||
/** |
||||
* @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,185 @@ |
||||
<?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 DateTime */ |
||||
public $startDateTime; |
||||
|
||||
/** @var string */ |
||||
public $formattedStartTime; |
||||
|
||||
/** @var DateInterval */ |
||||
public $durationInterval; |
||||
|
||||
/** @var string */ |
||||
public $formattedDuration; |
||||
|
||||
/** |
||||
* @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; |
||||
|
||||
/** |
||||
* @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; |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
* |
||||
* @return RecordingMeeting |
||||
*/ |
||||
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,260 @@ |
||||
<?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 */ |
||||
public $fullName; |
||||
|
||||
/** |
||||
* @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; |
||||
|
||||
/** |
||||
* @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; |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingRegistrantListItem |
||||
*/ |
||||
public function getMeetingRegistrantListItem() |
||||
{ |
||||
return $this->meetingRegistrantListItem; |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
* |
||||
* @return CreatedRegistration |
||||
*/ |
||||
public function getCreatedRegistration() |
||||
{ |
||||
return $this->createdRegistration; |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
* |
||||
* @return MeetingRegistrant |
||||
*/ |
||||
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 |
||||
); |
||||
} |
||||
} |
||||
@ -0,0 +1,70 @@ |
||||
The Chamilo Zoom plugin class itself is defined in _plugin/zoom/lib/zoom_plugin.class.php_ |
||||
|
||||
It manipulates both **remote Zoom server objects** and **local database entities**: |
||||
|
||||
# Local database entities |
||||
|
||||
The local entities map the remote objects to Chamilo courses/sessions and users. |
||||
|
||||
They also maintain a cache of the matching remote objects. |
||||
|
||||
_Entity/*Entity.php_ are the local database entity classes. |
||||
|
||||
Doctrine entity manager repository classes are in _lib/*EntityRepository.php_. |
||||
|
||||
# Remote Zoom server objets |
||||
|
||||
_lib/API/*.php_ contains the Zoom API data structure definition classes, |
||||
based on Zoom's own API specification: |
||||
|
||||
* https://marketplace.zoom.us/docs/api-reference/zoom-api |
||||
* https://marketplace.zoom.us/docs/api-reference/zoom-api/Zoom%20API.oas2.json |
||||
|
||||
These classes provide methods to list, create, update and delete the remote objects. |
||||
|
||||
# JWT Client |
||||
|
||||
API class methods use a JWT client implemented in _lib/API/JWTClient.php_. |
||||
|
||||
The plugin constructor initializes the JWT Client, giving it required API key and secret. |
||||
|
||||
# Event notification handler |
||||
|
||||
_endpoint.php_ is the Zoom API event notification web hook end point. |
||||
|
||||
It handles notifications sent by Zoom servers on useful events : |
||||
|
||||
* meeting start and end, |
||||
* registrant join and leave, |
||||
* recordings created and deleted |
||||
|
||||
# Administrative interface |
||||
|
||||
_admin.php_ is the administrative interface. |
||||
It lists all meetings and recordings. |
||||
|
||||
# Course tool |
||||
|
||||
_start.php_ is the **course** tool target: |
||||
|
||||
* to the course teacher, it shows a course meeting management interface; |
||||
* to the course learners, it shows the list of scheduled course meetings. |
||||
|
||||
# Home page's profile block (also on "My Courses" page) |
||||
|
||||
This plugin can add 3 kinds of links to "profile block" : |
||||
|
||||
1. _join_meeting.php?meetingId=…_ links to upcoming meetings accessible to the current user. |
||||
_join_meeting.php_ presents the meeting and shows a link to enter the meeting. |
||||
2. _user.php_ is the **user**'s own meeting management interface. |
||||
3. _global.php_ directs the user to _join_meeting.php_ with the **global** meeting. |
||||
|
||||
# Meeting management page |
||||
|
||||
_admin.php_, _start.php_ and _user.php_ link to _meeting.php_. |
||||
|
||||
_meeting.php_ is the meeting management page, where one can manage |
||||
|
||||
* the meeting properties, |
||||
* the list of its registrants and |
||||
* its recordings. |
||||
@ -1 +1,35 @@ |
||||
This plugin allows teachers to launch a Zoom conference at any time and students to join it. |
||||
This plugin adds Zoom meetings, user registration to meetings and meeting recordings. |
||||
|
||||
## Meetings |
||||
|
||||
A **meeting** can be linked to a local **user** and/or a local **course**/**session**: |
||||
|
||||
* a meeting with a course is a _course meeting_; |
||||
* a meeting with a user and no course is a _user meeting_; |
||||
* a meeting with no course nor user is a _global meeting_. |
||||
|
||||
## Registrants |
||||
|
||||
A **registrant** is the registration of a local user to a meeting. |
||||
|
||||
Users do not register themselves to meetings. |
||||
|
||||
* They are registered to a course meeting by the course manager. |
||||
* They are registered to a user meeting by that user. |
||||
* They are registered automatically to the global meeting, when they enter it. |
||||
|
||||
## Recordings |
||||
|
||||
A **recording** is the list of files created during a past meeting instance. |
||||
|
||||
Course meeting files can be copied to the course by the course manager. |
||||
|
||||
# Required Zoom user account |
||||
|
||||
Recordings and user registration are only available to paying Zoom customers. |
||||
|
||||
For a non-paying Zoom user, this plugin still works but participants will join anonymously. |
||||
|
||||
# Contributing |
||||
|
||||
Read README.code.md for an introduction to the plugin's code. |
||||
@ -0,0 +1,100 @@ |
||||
<?php |
||||
/* For license terms, see /license.txt */ |
||||
|
||||
use Chamilo\PluginBundle\Zoom\API\MeetingInfoGet; |
||||
use Chamilo\PluginBundle\Zoom\API\RecordingMeeting; |
||||
use Chamilo\PluginBundle\Zoom\MeetingEntity; |
||||
use Chamilo\PluginBundle\Zoom\RecordingEntity; |
||||
use Chamilo\PluginBundle\Zoom\RegistrantEntity; |
||||
|
||||
if ('POST' !== $_SERVER['REQUEST_METHOD']) { |
||||
http_response_code(404); // Not found |
||||
exit; |
||||
} |
||||
|
||||
$authorizationHeaderValue = apache_request_headers()['authorization']; // TODO handle non-apache installations |
||||
|
||||
require __DIR__.'/config.php'; |
||||
|
||||
if (api_get_plugin_setting('zoom', 'verificationToken') !== $authorizationHeaderValue) { |
||||
http_response_code(401); // Unauthorized |
||||
exit; |
||||
} |
||||
|
||||
$body = file_get_contents('php://input'); |
||||
$decoded = json_decode($body); |
||||
if (is_null($decoded) || !is_object($decoded) || !isset($decoded->event) || !isset($decoded->payload->object)) { |
||||
error_log(sprintf('Did not recognize event notification: %s', $body)); |
||||
http_response_code(422); // Unprocessable Entity |
||||
exit; |
||||
} |
||||
$object = $decoded->payload->object; |
||||
list($objectType, $action) = explode('.', $decoded->event); |
||||
switch ($objectType) { |
||||
case 'meeting': |
||||
$meetingRepository = $entityManager->getRepository(MeetingEntity::class); |
||||
$registrantRepository = $entityManager->getRepository(RegistrantEntity::class); |
||||
switch ($action) { |
||||
case 'deleted': |
||||
$meetingEntity = $meetingRepository->find($object->id); |
||||
if (!is_null($meetingEntity)) { |
||||
$entityManager->remove($meetingEntity); |
||||
} |
||||
break; |
||||
case 'ended': |
||||
case 'started': |
||||
$entityManager->persist( |
||||
( |
||||
$meetingRepository->find($object->id)->setStatus($action) |
||||
?: (new MeetingEntity())->setMeetingInfoGet(MeetingInfoGet::fromObject($object)) |
||||
) |
||||
); |
||||
$entityManager->flush(); |
||||
break; |
||||
case 'participant_joined': |
||||
case 'participant_left': |
||||
$registrant = $registrantRepository->find($object->participant->id); |
||||
if (!is_null($registrant)) { |
||||
// TODO log attendance |
||||
} |
||||
break; |
||||
case 'alert': |
||||
default: |
||||
error_log(sprintf('Event "%s" on %s was unhandled: %s', $action, $objectType, $body)); |
||||
http_response_code(501); // Not Implemented |
||||
} |
||||
break; |
||||
case 'recording': |
||||
$recordingRepository = $entityManager->getRepository(RecordingEntity::class); |
||||
switch ($action) { |
||||
case 'completed': |
||||
$entityManager->persist( |
||||
(new RecordingEntity())->setRecordingMeeting(RecordingMeeting::fromObject($object)) |
||||
); |
||||
$entityManager->flush(); |
||||
break; |
||||
case 'recovered': |
||||
if (is_null($recordingRepository->find($object->uuid))) { |
||||
$entityManager->persist( |
||||
(new RecordingEntity())->setRecordingMeeting(RecordingMeeting::fromObject($object)) |
||||
); |
||||
$entityManager->flush(); |
||||
} |
||||
break; |
||||
case 'trashed': |
||||
case 'deleted': |
||||
$recordingEntity = $recordingRepository->find($object->uuid); |
||||
if (!is_null($recordingEntity)) { |
||||
$entityManager->remove($recordingEntity); |
||||
$entityManager->flush(); |
||||
} |
||||
break; |
||||
default: |
||||
error_log(sprintf('Event "%s" on %s was unhandled: %s', $action, $objectType, $body)); |
||||
http_response_code(501); // Not Implemented |
||||
} |
||||
break; |
||||
default: |
||||
error_log(sprintf('Event "%s" on %s was unhandled: %s', $action, $objectType, $body)); |
||||
http_response_code(501); // Not Implemented |
||||
} |
||||
@ -0,0 +1,12 @@ |
||||
<?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::currentUserCanJoinGlobalMeeting()) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
location('join_meeting.php?meetingId='.ZoomPlugin::create()->getGlobalMeeting()->getId()); |
||||
@ -0,0 +1,39 @@ |
||||
<?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'); |
||||
} |
||||
printf( |
||||
'%s<p><a href="%s" target="_blank">%s</a></p>', |
||||
$meeting->getIntroduction(), |
||||
$plugin->getStartOrJoinMeetingURL($meeting), |
||||
get_lang('EnterMeeting') |
||||
); |
||||
} catch (Exception $exception) { |
||||
Display::addFlash( |
||||
Display::return_message($exception->getMessage(), 'error') |
||||
); |
||||
} |
||||
} |
||||
|
||||
Display::display_footer(); |
||||
@ -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,144 @@ |
||||
<?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,69 @@ |
||||
<?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,34 @@ |
||||
<?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
@ -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"; |
||||
@ -0,0 +1,32 @@ |
||||
<?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()); |
||||
|
||||
$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(); |
||||
Loading…
Reference in new issue