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
parent
aacdbc8e31
commit
eb80bfdd9c
@ -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 |
||||
); |
||||
} |
||||
} |
||||
@ -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(); |
||||
@ -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
@ -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,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(); |
||||
Loading…
Reference in new issue