parent
2a65680086
commit
caef076dcf
@ -0,0 +1,135 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom; |
||||
|
||||
use Chamilo\PluginBundle\Zoom\API\WebinarSchema; |
||||
use Chamilo\PluginBundle\Zoom\API\WebinarSettings; |
||||
use DateInterval; |
||||
use DateTime; |
||||
use Doctrine\ORM\Mapping as ORM; |
||||
use Exception; |
||||
use ZoomPlugin; |
||||
|
||||
/** |
||||
* @ORM\Entity() |
||||
* @ORM\HasLifecycleCallbacks |
||||
*/ |
||||
class Webinar extends Meeting |
||||
{ |
||||
/** |
||||
* @var string |
||||
* |
||||
* @ORM\Column(name="webinar_schema_json", type="text", nullable=true) |
||||
*/ |
||||
protected $webinarSchemaJson; |
||||
|
||||
/** |
||||
* @var WebinarSchema |
||||
*/ |
||||
protected $webinarSchema; |
||||
|
||||
public function preFlush() |
||||
{ |
||||
if (null !== $this->webinarSchema) { |
||||
$this->webinarSchemaJson = json_encode($this->webinarSchema); |
||||
} |
||||
} |
||||
|
||||
public function postLoad() |
||||
{ |
||||
if (null !== $this->webinarSchemaJson) { |
||||
$this->webinarSchema = WebinarSchema::fromJson($this->webinarSchemaJson); |
||||
} |
||||
|
||||
$this->initializeDisplayableProperties(); |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
*/ |
||||
public function setWebinarSchema(WebinarSchema $webinarSchema): Webinar |
||||
{ |
||||
if (null === $this->meetingId) { |
||||
$this->meetingId = $webinarSchema->id; |
||||
} elseif ($this->meetingId != $webinarSchema->id) { |
||||
throw new Exception('the Meeting identifier differs from the MeetingInfoGet identifier'); |
||||
} |
||||
|
||||
$this->webinarSchema = $webinarSchema; |
||||
|
||||
$this->initializeDisplayableProperties(); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getWebinarSchema(): WebinarSchema |
||||
{ |
||||
return $this->webinarSchema; |
||||
} |
||||
|
||||
public function hasCloudAutoRecordingEnabled(): bool |
||||
{ |
||||
return $this->webinarSchema->settings->auto_recording !== ZoomPlugin::RECORDING_TYPE_NONE; |
||||
} |
||||
|
||||
public function requiresDateAndDuration(): bool |
||||
{ |
||||
return WebinarSchema::TYPE_WEBINAR == $this->webinarSchema->type; |
||||
} |
||||
|
||||
public function requiresRegistration(): bool |
||||
{ |
||||
return in_array( |
||||
$this->webinarSchema->settings->approval_type, |
||||
[ |
||||
WebinarSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE, |
||||
WebinarSettings::APPROVAL_TYPE_MANUALLY_APPROVE, |
||||
] |
||||
); |
||||
} |
||||
|
||||
public function getTopic(): string |
||||
{ |
||||
return $this->webinarSchema->topic; |
||||
} |
||||
|
||||
public function getAgenda(): ?string |
||||
{ |
||||
return $this->webinarSchema->agenda; |
||||
} |
||||
|
||||
protected function initializeDisplayableProperties() |
||||
{ |
||||
$zoomPlugin = ZoomPlugin::create(); |
||||
|
||||
$namedTypes = [ |
||||
WebinarSchema::TYPE_WEBINAR => $zoomPlugin->get_lang('Webinar'), |
||||
WebinarSchema::TYPE_RECURRING_NO_FIXED_TIME => $zoomPlugin->get_lang('RecurringWithNoFixedTime'), |
||||
WebinarSchema::TYPE_RECURRING_FIXED_TIME => $zoomPlugin->get_lang('RecurringWithFixedTime'), |
||||
]; |
||||
|
||||
$this->typeName = $namedTypes[$this->webinarSchema->type]; |
||||
|
||||
if ($this->webinarSchema->start_time) { |
||||
$this->startDateTime = new DateTime( |
||||
$this->webinarSchema->start_time, |
||||
new \DateTimeZone(api_get_timezone()) |
||||
); |
||||
$this->formattedStartTime = $this->startDateTime->format('Y-m-d H:i'); |
||||
} |
||||
|
||||
if ($this->webinarSchema->duration) { |
||||
$now = new DateTime(); |
||||
$later = new DateTime(); |
||||
$later->add( |
||||
new DateInterval('PT'.$this->webinarSchema->duration.'M') |
||||
); |
||||
$this->durationInterval = $now->diff($later); |
||||
$this->formattedDuration = $this->durationInterval->format( |
||||
$zoomPlugin->get_lang('DurationFormat') |
||||
); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,61 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
use Chamilo\PluginBundle\Zoom\Meeting; |
||||
use Symfony\Component\HttpFoundation\JsonResponse; |
||||
use Symfony\Component\HttpFoundation\Request as HttpRequest; |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
|
||||
$cidReset = true; |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
api_protect_admin_script(); |
||||
|
||||
$request = HttpRequest::createFromGlobals(); |
||||
|
||||
$plugin = ZoomPlugin::create(); |
||||
$user = api_get_user_entity(api_get_user_id()); |
||||
|
||||
$action = $request->get('a'); |
||||
|
||||
if ($action == 'get_events') { |
||||
$startDate = $request->query->get('start'); |
||||
$endDate = $request->query->get('end'); |
||||
|
||||
$startDate = api_get_utc_datetime($startDate, true, true); |
||||
$endDate = api_get_utc_datetime($endDate, true, true); |
||||
|
||||
$meetings = $plugin |
||||
->getMeetingRepository() |
||||
->periodMeetings($startDate, $endDate); |
||||
|
||||
$meetingsAsEvents = array_map( |
||||
function (Meeting $meeting) { |
||||
$meetingInfo = $meeting->getMeetingInfoGet(); |
||||
|
||||
$endDate = new DateTime($meeting->formattedStartTime); |
||||
$endDate->sub($meeting->durationInterval); |
||||
|
||||
return [ |
||||
'id' => 'meeting_'.$meeting->getId(), |
||||
'title' => $meetingInfo->topic, |
||||
'editable' => false, |
||||
'start' => $meeting->formattedStartTime, |
||||
'start_date_localtime' => $meeting->formattedStartTime, |
||||
'end' => $endDate->format('Y-m-d H:i'), |
||||
'end_date_localtime' => $endDate->format('Y-m-d H:i'), |
||||
'duration' => $meeting->formattedDuration, |
||||
'description' => $meetingInfo->agenda, |
||||
'allDay' => false, |
||||
'accountEmail' => $meeting->getAccountEmail(), |
||||
]; |
||||
}, |
||||
$meetings |
||||
); |
||||
|
||||
$response = JsonResponse::create($meetingsAsEvents); |
||||
$response->send(); |
||||
} |
||||
@ -0,0 +1,47 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
|
||||
$cidReset = true; |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
api_protect_admin_script(); |
||||
|
||||
$plugin = ZoomPlugin::create(); |
||||
$toolName = $plugin->get_lang('ZoomVideoConferences'); |
||||
|
||||
$defaultView = api_get_setting('default_calendar_view'); |
||||
|
||||
if (empty($defaultView)) { |
||||
$defaultView = 'month'; |
||||
} |
||||
|
||||
$regionValue = api_get_language_isocode(); |
||||
|
||||
$htmlHeadXtra[] = api_get_asset('qtip2/jquery.qtip.min.js'); |
||||
$htmlHeadXtra[] = api_get_asset('fullcalendar/dist/fullcalendar.js'); |
||||
$htmlHeadXtra[] = api_get_asset('fullcalendar/dist/locale-all.js'); |
||||
$htmlHeadXtra[] = api_get_css_asset('fullcalendar/dist/fullcalendar.min.css'); |
||||
$htmlHeadXtra[] = api_get_css_asset('qtip2/jquery.qtip.min.css'); |
||||
|
||||
$tpl = new Template($toolName); |
||||
|
||||
$tpl->assign('web_agenda_ajax_url', 'calendar.ajax.php?sec_token='.Security::get_token()); |
||||
$tpl->assign('default_view', $defaultView); |
||||
$tpl->assign('region_value', 'en' === $regionValue ? 'en-GB' : $regionValue); |
||||
|
||||
$onHoverInfo = Agenda::returnOnHoverInfo(); |
||||
$tpl->assign('on_hover_info', $onHoverInfo); |
||||
|
||||
$extraSettings = Agenda::returnFullCalendarExtraSettings(); |
||||
|
||||
$tpl->assign('fullcalendar_settings', $extraSettings); |
||||
|
||||
$content = $tpl->fetch('zoom/view/calendar.tpl'); |
||||
|
||||
$tpl->assign('actions', $plugin->getToolbar()); |
||||
$tpl->assign('content', $content); |
||||
$tpl->display_one_col_template(); |
||||
@ -0,0 +1,26 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
class FollowUpUsers |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $enable; |
||||
/** |
||||
* @var |
||||
*/ |
||||
public $type; |
||||
|
||||
public function itemClass($propertyName) |
||||
{ |
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,22 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
class Ocurrence |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
public $occurrence_id; |
||||
public $start_time; |
||||
public $duration; |
||||
public $status; |
||||
|
||||
public function itemClass($propertyName) |
||||
{ |
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,23 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
class QuestionAndAnswer |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
public $enable; |
||||
public $allow_anonymous_questions; |
||||
public $answer_questions; |
||||
public $attendees_can_upvote; |
||||
public $attendees_can_comment; |
||||
|
||||
public function itemClass($propertyName) |
||||
{ |
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,103 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
abstract class RegistrantSchema |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
/** @var string */ |
||||
public $email; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $status; |
||||
|
||||
/** @var string */ |
||||
public $first_name; |
||||
|
||||
/** @var string */ |
||||
public $last_name; |
||||
|
||||
/** @var string */ |
||||
public $address; |
||||
|
||||
/** @var string */ |
||||
public $city; |
||||
|
||||
/** @var string */ |
||||
public $country; |
||||
|
||||
/** @var string */ |
||||
public $zip; |
||||
|
||||
/** @var string */ |
||||
public $state; |
||||
|
||||
/** @var string */ |
||||
public $phone; |
||||
|
||||
/** @var string */ |
||||
public $industry; |
||||
|
||||
/** @var string */ |
||||
public $org; |
||||
|
||||
/** @var string */ |
||||
public $job_title; |
||||
|
||||
/** @var string */ |
||||
public $purchasing_time_frame; |
||||
|
||||
/** @var string */ |
||||
public $role_in_purchase_process; |
||||
|
||||
/** @var string */ |
||||
public $no_of_employees; |
||||
|
||||
/** @var string */ |
||||
public $comments; |
||||
|
||||
/** @var object[] title => value */ |
||||
public $custom_questions; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $language; |
||||
|
||||
/** |
||||
* MeetingRegistrant constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->status = 'approved'; |
||||
$this->custom_questions = []; |
||||
} |
||||
|
||||
public static function fromEmailAndFirstName(string $email, string $firstName, string $lastName = null): RegistrantSchema |
||||
{ |
||||
$instance = new static(); |
||||
$instance->first_name = $firstName; |
||||
$instance->email = $email; |
||||
if (null !== $lastName) { |
||||
$instance->last_name = $lastName; |
||||
} |
||||
|
||||
return $instance; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function itemClass($propertyName): string |
||||
{ |
||||
if ('custom_questions' === $propertyName) { |
||||
return CustomQuestion::class; |
||||
} |
||||
throw new Exception("no such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,9 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
class WebinarRegistrantSchema extends RegistrantSchema |
||||
{ |
||||
} |
||||
@ -0,0 +1,143 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
use stdClass; |
||||
|
||||
class WebinarSchema |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
const TYPE_WEBINAR = 5; |
||||
const TYPE_RECURRING_NO_FIXED_TIME = 6; |
||||
const TYPE_RECURRING_FIXED_TIME = 9; |
||||
|
||||
public $uuid; |
||||
public $id; |
||||
public $host_id; |
||||
public $host_email; |
||||
public $topic; |
||||
public $type; |
||||
public $start_time; |
||||
public $duration; |
||||
public $timezone; |
||||
public $agenda; |
||||
public $created_at; |
||||
public $start_url; |
||||
public $join_url; |
||||
public $registration_url; |
||||
public $password; |
||||
/** |
||||
* @var WebinarSettings |
||||
*/ |
||||
public $settings; |
||||
public $registrants_confirmation_email; |
||||
/** |
||||
* @var array<int, TrackingField> |
||||
*/ |
||||
public $tracking_fields; |
||||
public $recurrence; |
||||
public $template_id; |
||||
/** |
||||
* @var array<int, Ocurrence> |
||||
*/ |
||||
public $ocurrences; |
||||
|
||||
protected function __construct() |
||||
{ |
||||
$this->tracking_fields = []; |
||||
$this->settings = new WebinarSettings(); |
||||
$this->ocurrences = []; |
||||
} |
||||
|
||||
public function itemClass($propertyName): string |
||||
{ |
||||
if ('tracking_fields' === $propertyName) { |
||||
return TrackingField::class; |
||||
} |
||||
|
||||
if ('ocurrences' === $propertyName) { |
||||
return Ocurrence::class; |
||||
} |
||||
|
||||
throw new Exception("no such array property $propertyName"); |
||||
} |
||||
|
||||
public static function fromTopicAndType($topic, $type = self::TYPE_WEBINAR): WebinarSchema |
||||
{ |
||||
$instance = new static(); |
||||
$instance->topic = $topic; |
||||
$instance->type = $type; |
||||
|
||||
return $instance; |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
*/ |
||||
public function create($userId = null): WebinarSchema |
||||
{ |
||||
$client = Client::getInstance(); |
||||
|
||||
$userId = empty($userId) ? 'me' : $userId; |
||||
|
||||
return self::fromJson( |
||||
$client->send('POST', "users/$userId/webinars", [], $this) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
*/ |
||||
public function update() |
||||
{ |
||||
Client::getInstance()->send('PATCH', 'webinars/'.$this->id, [], $this); |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
*/ |
||||
public function delete() |
||||
{ |
||||
Client::getInstance()->send('DELETE', "webinars/$this->id"); |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
*/ |
||||
public function addRegistrant(RegistrantSchema $registrant, string $ocurrenceIds = ''): CreatedRegistration |
||||
{ |
||||
return CreatedRegistration::fromJson( |
||||
Client::getInstance()->send( |
||||
'POST', |
||||
"webinars/$this->id/registrants", |
||||
empty($occurrenceIds) ? [] : ['occurrence_ids' => $occurrenceIds], |
||||
$registrant |
||||
) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
*/ |
||||
public function removeRegistrants(array $registrants, string $occurrenceIds = '') |
||||
{ |
||||
if (empty($registrants)) { |
||||
return; |
||||
} |
||||
|
||||
$requestBody = new stdClass(); |
||||
$requestBody->action = 'cancel'; |
||||
$requestBody->registrants = $registrants; |
||||
|
||||
Client::getInstance()->send( |
||||
'PUT', |
||||
"webinars/$this->id/registrants/status", |
||||
empty($occurrenceIds) ? [] : ['occurrence_ids' => $occurrenceIds], |
||||
$requestBody |
||||
); |
||||
} |
||||
} |
||||
@ -0,0 +1,201 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\PluginBundle\Zoom\API; |
||||
|
||||
use Exception; |
||||
|
||||
class WebinarSettings |
||||
{ |
||||
use JsonDeserializableTrait; |
||||
|
||||
const APPROVAL_TYPE_AUTOMATICALLY_APPROVE = 0; |
||||
const APPROVAL_TYPE_MANUALLY_APPROVE = 1; |
||||
const APPROVAL_TYPE_NO_REGISTRATION_REQUIRED = 2; |
||||
|
||||
const REGISTRATION_TYPE_REGISTER_ONCE_ATTEND_ANY = 1; |
||||
const REGISTRATION_TYPE_REGISTER_EACH = 2; |
||||
const REGISTRATION_TYPE_REGISTER_ONCE_CHOOSE = 3; |
||||
|
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $host_video; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $panelists_video; |
||||
/** |
||||
* @var int |
||||
*/ |
||||
public $approval_type; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $audio; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $auto_recording; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $enforce_login; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $enforce_login_domains; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $alternative_hosts; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $close_registration; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $show_share_button; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $allow_multiple_devices; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $practice_session; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $hd_video; |
||||
/** |
||||
* @var object |
||||
*/ |
||||
public $question_answer; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $registrants_confirmation_email; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $on_demand; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $request_permission_to_unmute_participants; |
||||
/** |
||||
* @var array<int,string> |
||||
*/ |
||||
public $global_dial_in_countries; |
||||
/** |
||||
* @var array<int,GlobalDialInNumber> |
||||
*/ |
||||
public $global_dial_in_numbers; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $contact_name; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $contact_email; |
||||
/** |
||||
* @var int |
||||
*/ |
||||
public $registrants_restrict_number; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $registrants_email_notification; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $post_webinar_survey; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $meeting_authentication; |
||||
/** |
||||
* @var QuestionAndAnswer |
||||
*/ |
||||
public $question_and_answer; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $hd_video_for_attendees; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $send_1080p_video_to_attendees; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $email_language; |
||||
/** |
||||
* @var bool |
||||
*/ |
||||
public $panelists_invitation_email_notification; |
||||
/** |
||||
* @var FollowUpUsers |
||||
*/ |
||||
public $attendees_and_panelists_reminder_email_notification; |
||||
/** |
||||
* @var FollowUpUsers |
||||
*/ |
||||
public $follow_up_attendees_email_notification; |
||||
/** |
||||
* @var FollowUpUsers |
||||
*/ |
||||
public $follow_up_absentees_email_notification; |
||||
|
||||
/** |
||||
* @var int |
||||
*/ |
||||
public $registration_type; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $auto; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $survey_url; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $authentication_option; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $authentication_domains; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $authentication_name; |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->global_dial_in_countries = []; |
||||
$this->global_dial_in_numbers = []; |
||||
$this->question_and_answer = new QuestionAndAnswer(); |
||||
$this->attendees_and_panelists_reminder_email_notification = new FollowUpUsers(); |
||||
$this->follow_up_absentees_email_notification = new FollowUpUsers(); |
||||
$this->follow_up_attendees_email_notification = new FollowUpUsers(); |
||||
} |
||||
|
||||
public function itemClass($propertyName): string |
||||
{ |
||||
if ('global_dial_in_countries' === $propertyName) { |
||||
return 'string'; |
||||
} |
||||
|
||||
if ('global_dial_in_numbers' === $propertyName) { |
||||
return GlobalDialInNumber::class; |
||||
} |
||||
|
||||
throw new Exception("No such array property $propertyName"); |
||||
} |
||||
} |
||||
@ -0,0 +1,117 @@ |
||||
<?php |
||||
|
||||
/* For license terms, see /license.txt */ |
||||
|
||||
use Chamilo\PluginBundle\Zoom\Meeting; |
||||
use Chamilo\UserBundle\Entity\User; |
||||
|
||||
require_once __DIR__.'/config.php'; |
||||
|
||||
api_block_anonymous_users(); |
||||
|
||||
$course_plugin = 'zoom'; // needed in order to load the plugin lang variables |
||||
|
||||
if (empty($_REQUEST['meetingId'])) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
$plugin = ZoomPlugin::create(); |
||||
|
||||
/** @var Meeting $meeting */ |
||||
$meeting = $plugin->getMeetingRepository()->findOneBy(['meetingId' => $_REQUEST['meetingId']]); |
||||
|
||||
if (null === $meeting) { |
||||
api_not_allowed(true, $plugin->get_lang('MeetingNotFound')); |
||||
} |
||||
|
||||
if (false !== $meeting->isGlobalMeeting() |
||||
|| false != $meeting->isCourseMeeting() |
||||
|| 'true' !== $plugin->get('enableParticipantRegistration') |
||||
|| !$meeting->requiresRegistration() |
||||
) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
$currentUser = api_get_user_entity(api_get_user_id()); |
||||
$userRegistrant = $meeting->getRegistrantByUser($currentUser); |
||||
|
||||
if ($meeting->isCourseMeeting()) { |
||||
api_protect_course_script(true); |
||||
|
||||
if (api_is_in_group()) { |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(), |
||||
'name' => get_lang('Groups'), |
||||
]; |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'group/group_space.php?'.api_get_cidreq(), |
||||
'name' => get_lang('GroupSpace').' '.$meeting->getGroup()->getName(), |
||||
]; |
||||
} |
||||
} |
||||
|
||||
$form = new FormValidator('subscription'); |
||||
$form->addHidden('meetingId', $meeting->getMeetingId()); |
||||
|
||||
if (!empty($userRegistrant)) { |
||||
$form->addButton( |
||||
'unregister', |
||||
$plugin->get_lang('UnregisterMeToConference'), |
||||
'user-times', |
||||
'warning' |
||||
); |
||||
|
||||
$form->addHtml( |
||||
'<div class="form-group"><div class="col-sm-8 col-sm-offset-2">' |
||||
.Display::url( |
||||
$plugin->get_lang('ViewMeeting'), |
||||
api_get_path(WEB_PLUGIN_PATH).'zoom/join_meeting.php?meetingId='.$meeting->getMeetingId(), |
||||
['class' => 'btn btn-primary'] |
||||
) |
||||
.'</div></div>' |
||||
); |
||||
} else { |
||||
$filtered = array_filter( |
||||
$meeting->getRegistrableUsers(), |
||||
function (User $registableUser) use ($currentUser) { |
||||
return $registableUser->getId() === $currentUser->getId(); |
||||
} |
||||
); |
||||
|
||||
if (empty($filtered)) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
$form->addButton( |
||||
'register', |
||||
$plugin->get_lang('RegisterMeToConference'), |
||||
'user-plus', |
||||
'success' |
||||
); |
||||
} |
||||
|
||||
if ($form->validate()) { |
||||
$values = $form->exportValues(); |
||||
|
||||
if (isset($values['unregister'])) { |
||||
$plugin->unregister($meeting, [$userRegistrant]); |
||||
} else { |
||||
$plugin->registerUsers($meeting, [$currentUser]); |
||||
} |
||||
|
||||
Display::addFlash( |
||||
Display::return_message($plugin->get_lang('RegisteredUserListWasUpdated'), 'success') |
||||
); |
||||
|
||||
api_location('?meetingId='.$meeting->getMeetingId()); |
||||
} else { |
||||
$form->protect(); |
||||
} |
||||
|
||||
$view = new Template(''); |
||||
$view->assign('meeting', $meeting); |
||||
$view->assign('frm_register_unregister', $form->returnForm()); |
||||
$content = $view->fetch('zoom/view/subscription.tpl'); |
||||
|
||||
$view->assign('content', $content); |
||||
$view->display_one_col_template(); |
||||
@ -0,0 +1,312 @@ |
||||
<div id="loading" style="margin-left:150px;position:absolute;display:none"> |
||||
{{ "Loading"|get_lang }} … |
||||
</div> |
||||
|
||||
<div id="calendar"></div> |
||||
|
||||
<div class="modal fade" tabindex="-1" role="dialog" id="simple-dialog-form"> |
||||
<div class="modal-dialog" role="document"> |
||||
<div class="modal-content"> |
||||
<div class="modal-header"> |
||||
<button type="button" class="close" data-dismiss="modal" aria-label="{{ 'Close'|get_lang }}"> |
||||
<span aria-hidden="true">×</span> |
||||
</button> |
||||
<h4 class="modal-title">{{ 'Details'|get_lang }}</h4> |
||||
</div> |
||||
<div class="modal-body"> |
||||
<form class="form-horizontal"> |
||||
<div class="form-group"> |
||||
<label class="col-sm-4 control-label">{{ "Date"|get_lang }}</label> |
||||
<div class="col-sm-8"> |
||||
<p class="form-static-control"> |
||||
<span id="simple_start_date"></span> |
||||
<span id="simple_end_date"></span> |
||||
</p> |
||||
</div> |
||||
</div> |
||||
<div class="form-group"> |
||||
<label class="col-sm-4 control-label">{{ "Title"|get_lang }}</label> |
||||
<div class="col-sm-8"> |
||||
<p class="form-static-control" id="simple_title"></p> |
||||
</div> |
||||
</div> |
||||
<div class="form-group"> |
||||
<label class="col-sm-4 control-label">{{ "Description"|get_lang }}</label> |
||||
<div class="col-sm-8"> |
||||
<p class="form-static-control" id="simple_content"></p> |
||||
</div> |
||||
</div> |
||||
<div class="form-group"> |
||||
<label class="col-sm-4 control-label">{{ "AccountEmail"|get_plugin_lang('ZoomPlugin') }}</label> |
||||
<div class="col-sm-8"> |
||||
<p class="form-static-control" id="simple_account"></p> |
||||
</div> |
||||
</div> |
||||
</form> |
||||
</div> |
||||
<div class="modal-footer"> |
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'Close'|get_lang }}</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<script> |
||||
$(function () { |
||||
var cookieData = Cookies.getJSON('agenda_cookies'); |
||||
var defaultView = (cookieData && cookieData.view) || '{{ default_view }}'; |
||||
var defaultStartDate = (cookieData && cookieData.start) || moment.now(); |
||||
|
||||
var CustomListViewGrid = ListViewGrid.extend({ |
||||
fgSegHtml: function (seg) { |
||||
var view = this.view; |
||||
var classes = ['fc-list-item'].concat(this.getSegCustomClasses(seg)); |
||||
var bgColor = this.getSegBackgroundColor(seg); |
||||
var event = seg.event; |
||||
var url = event.url; |
||||
var timeHtml; |
||||
|
||||
if (view.isMultiDayEvent(event)) { // if the event appears to span more than one day |
||||
if (seg.isStart || seg.isEnd) { // outer segment that probably lasts part of the day |
||||
timeHtml = htmlEscape(this.getEventTimeText(seg)); |
||||
} else { // inner segment that lasts the whole day |
||||
timeHtml = view.getAllDayHtml(); |
||||
} |
||||
} else { |
||||
// Display the normal time text for the *event's* times |
||||
timeHtml = htmlEscape(this.getEventTimeText(event)); |
||||
} |
||||
|
||||
if (url) { |
||||
classes.push('fc-has-url'); |
||||
} |
||||
|
||||
return '<tr class="' + classes.join(' ') + '">' + |
||||
(this.displayEventTime |
||||
? '<td class="fc-list-item-time ' + view.widgetContentClass + '">' + (timeHtml || '') + '</td>' |
||||
: '' |
||||
) + |
||||
'<td class="fc-list-item-marker ' + view.widgetContentClass + '">' + |
||||
'<span class="fc-event-dot"' + |
||||
(bgColor ? ' style="background-color:' + bgColor + '"' : '') + |
||||
'></span>' + |
||||
'</td>' + |
||||
'<td class="fc-list-item-title ' + view.widgetContentClass + '">' + |
||||
'<a' + (url ? ' href="' + htmlEscape(url) + '"' : '') + '>' + |
||||
htmlEscape(seg.event.title || '') + (seg.event.description || '') + |
||||
'</a>' + |
||||
'</td>' + |
||||
'</tr>'; |
||||
}, |
||||
|
||||
// render the event segments in the view |
||||
renderSegList: function (allSegs) { |
||||
var segsByDay = this.groupSegsByDay(allSegs); // sparse array |
||||
var dayIndex; |
||||
var daySegs; |
||||
var i; |
||||
var tableEl = $('<table class="fc-list-table"><tbody/></table>'); |
||||
var tbodyEl = tableEl.find('tbody'); |
||||
var eventList = []; |
||||
for (dayIndex = 0; dayIndex < segsByDay.length; dayIndex++) { |
||||
daySegs = segsByDay[dayIndex]; |
||||
if (daySegs) { // sparse array, so might be undefined |
||||
this.sortEventSegs(daySegs); |
||||
for (i = 0; i < daySegs.length; i++) { |
||||
var event = daySegs[i].event; |
||||
if (jQuery.inArray(event.id, eventList) !== -1) { |
||||
continue; |
||||
} |
||||
eventList.push(event.id); |
||||
// append a day header |
||||
tbodyEl.append(this.dayHeaderHtml( |
||||
this.view.start.clone().add(dayIndex, 'days'), |
||||
event |
||||
)); |
||||
|
||||
tbodyEl.append(daySegs[i].el); // append event row |
||||
} |
||||
} |
||||
} |
||||
|
||||
this.el.empty().append(tableEl); |
||||
}, |
||||
// generates the HTML for the day headers that live amongst the event rows |
||||
dayHeaderHtml: function (dayDate, event) { |
||||
var view = this.view; |
||||
var mainFormat = 'LL'; |
||||
var altFormat = 'dddd'; |
||||
var checkIfSame = true; |
||||
if (event.end) { |
||||
checkIfSame = event.end.format(mainFormat) === dayDate.format(mainFormat); |
||||
} |
||||
|
||||
return '<tr class="fc-list-heading" data-date="' + dayDate.format('YYYY-MM-DD') + '">' + |
||||
'<td class="' + view.widgetHeaderClass + '" colspan="3">' + |
||||
( |
||||
mainFormat |
||||
? view.buildGotoAnchorHtml( |
||||
dayDate, |
||||
{ 'class': 'fc-list-heading-main' }, |
||||
htmlEscape(dayDate.format(mainFormat)) // inner HTML |
||||
) |
||||
: '' |
||||
) + |
||||
( |
||||
(checkIfSame === false && mainFormat) |
||||
? view.buildGotoAnchorHtml( |
||||
dayDate, |
||||
{ 'class': 'fc-list-heading-main' }, |
||||
' - ' + htmlEscape(event.end.format(mainFormat)) // inner HTML |
||||
) |
||||
: '' |
||||
) + |
||||
( |
||||
altFormat |
||||
? view.buildGotoAnchorHtml( |
||||
dayDate, |
||||
{ 'class': 'fc-list-heading-alt' }, |
||||
htmlEscape(dayDate.format(altFormat)) // inner HTML |
||||
) |
||||
: '' |
||||
) + |
||||
'</td>' + |
||||
'</tr>' |
||||
} |
||||
}) |
||||
|
||||
var FC = $.fullCalendar; // a reference to FullCalendar's root namespace |
||||
var View = ListView; // the class that all views must inherit from |
||||
var CustomView; // our subclass |
||||
|
||||
CustomView = View.extend({ // make a subclass of View |
||||
initialize: function () { |
||||
this.grid = new CustomListViewGrid(this); |
||||
this.scroller = new Scroller({ |
||||
overflowX: 'hidden', |
||||
overflowY: 'auto' |
||||
}); |
||||
} |
||||
}) |
||||
|
||||
FC.views.CustomView = CustomView; // register our class with the view system |
||||
var height = ''; |
||||
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { |
||||
height = 'auto'; |
||||
} |
||||
|
||||
$('#calendar').fullCalendar({ |
||||
height: height, |
||||
header: { |
||||
left: 'today,prev,next', |
||||
center: 'title', |
||||
right: 'month,agendaWeek,agendaDay,CustomView' |
||||
}, |
||||
views: { |
||||
CustomView: { // name of view |
||||
type: 'list', |
||||
buttonText: '{{ 'AgendaList'|get_lang | escape('js') }}', |
||||
duration: { month: 1 }, |
||||
defaults: { |
||||
'listDayAltFormat': 'dddd' // day-of-week is nice-to-have |
||||
} |
||||
}, |
||||
month: { |
||||
'displayEventEnd': true |
||||
} |
||||
}, |
||||
locale: '{{ region_value }}', |
||||
defaultView: defaultView, |
||||
defaultDate: defaultStartDate, |
||||
firstHour: 8, |
||||
firstDay: 1, |
||||
{% if fullcalendar_settings %} |
||||
{{ fullcalendar_settings }} |
||||
{% endif %} |
||||
selectable: false, |
||||
selectHelper: true, |
||||
viewRender: function (view, element) { |
||||
var data = { |
||||
'view': view.name, |
||||
'start': view.intervalStart.format('YYYY-MM-DD') |
||||
}; |
||||
Cookies.set('agenda_cookies', data, 1); // Expires 1 day |
||||
}, |
||||
eventRender: function (event, element) { |
||||
{% if on_hover_info.description %} |
||||
if (event.description) { |
||||
element.qtip({ |
||||
content: event.description, |
||||
position: { |
||||
at: 'top center', |
||||
my: 'bottom center', |
||||
viewport: $(window) |
||||
} |
||||
}); |
||||
} |
||||
{% endif %} |
||||
}, |
||||
eventClick: function (calEvent, jsEvent, view) { |
||||
var start = calEvent.start; |
||||
var end = calEvent.end; |
||||
var diffDays = moment(end).diff(start, 'days'); |
||||
var endDateMinusOne = ''; |
||||
|
||||
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { |
||||
// If event is not editable then just return the qtip |
||||
{% if on_hover_info.description %} |
||||
if (calEvent.description) { |
||||
$(this).qtip({ |
||||
overwrite: false, |
||||
show: { ready: true }, |
||||
content: calEvent.description, |
||||
position: { |
||||
at: 'top center', |
||||
my: 'bottom center', |
||||
viewport: $(window) |
||||
} |
||||
}); |
||||
} |
||||
{% endif %} |
||||
|
||||
return; |
||||
} |
||||
|
||||
var clone = end.clone(); |
||||
endDateMinusOne = clone.subtract(1, 'days').format('{{ js_format_date }}'); |
||||
var startDateToString = start.format("{{ js_format_date }}"); |
||||
|
||||
// Simple form |
||||
$('#simple_start_date').html(startDateToString); |
||||
if (diffDays > 1) { |
||||
$('#simple_end_date').html(' - ' + endDateMinusOne); |
||||
} else if (diffDays == 0) { |
||||
var start_date_value = start.format('ll'); |
||||
var startTime = start.format('LT'); |
||||
var endTime = end.format('LT'); |
||||
$('#simple_start_date').html(''); |
||||
$('#simple_end_date').html(start_date_value + ' (' + startTime + ' - ' + endTime + ') '); |
||||
} else { |
||||
$('#simple_end_date').html(''); |
||||
} |
||||
|
||||
$('#simple_title').html(calEvent.title); |
||||
$('#simple_content').html(calEvent.description); |
||||
$('#simple_account').html(calEvent.accountEmail); |
||||
|
||||
$('#simple-dialog-form').modal('show'); |
||||
}, |
||||
editable: false, |
||||
events: "{{ web_agenda_ajax_url }}&a=get_events", |
||||
axisFormat: 'H(:mm)', // pm-am format -> h(:mm)a |
||||
timeFormat: 'H:mm', // pm-am format -> h:mm |
||||
loading: function (bool) { |
||||
if (bool) { |
||||
$('#loading').show(); |
||||
} else { |
||||
$('#loading').hide(); |
||||
} |
||||
} |
||||
}) |
||||
}) |
||||
</script> |
||||
@ -0,0 +1,39 @@ |
||||
{% if meeting.meetingInfoGet %} |
||||
<h2> |
||||
{{ meeting.meetingInfoGet.topic }} |
||||
<small>{{ meeting.typeName }}</small> |
||||
</h2> |
||||
|
||||
{% if meeting.meetingInfoGet.agenda %} |
||||
<p class="lead">{{ meeting.meetingInfoGet.agenda|nl2br }}</p> |
||||
{% endif %} |
||||
|
||||
{% if meeting.meetingInfoGet.type == 2 or meeting.meetingInfoGet.type == 8 %} |
||||
<dl class="meeting_properties dl-horizontal"> |
||||
<dt>{{ 'StartTime'|get_lang }}</dt> |
||||
<dd>{{ meeting.formattedStartTime }}</dd> |
||||
|
||||
<dt>{{ 'Duration'|get_lang }}</dt> |
||||
<dd>{{ meeting.formattedDuration }}</dd> |
||||
</dl> |
||||
{% endif %} |
||||
{% elseif meeting.webinarSchema %} |
||||
<h2> |
||||
{{ meeting.webinarSchema.topic }} |
||||
<small>{{ meeting.typeName }}</small> |
||||
</h2> |
||||
|
||||
{% if meeting.webinarSchema.agenda %} |
||||
<p class="lead">{{ meeting.webinarSchema.agenda|nl2br }}</p> |
||||
{% endif %} |
||||
|
||||
{% if meeting.webinarSchema.type == 5 or meeting.webinarSchema.type == 9 %} |
||||
<dl class="meeting_properties dl-horizontal"> |
||||
<dt>{{ 'StartTime'|get_lang }}</dt> |
||||
<dd>{{ meeting.formattedStartTime }}</dd> |
||||
|
||||
<dt>{{ 'Duration'|get_lang }}</dt> |
||||
<dd>{{ meeting.formattedDuration }}</dd> |
||||
</dl> |
||||
{% endif %} |
||||
{% endif %} |
||||
@ -0,0 +1,3 @@ |
||||
{% include 'zoom/view/meeting_details.tpl' %} |
||||
|
||||
{{ frm_register_unregister }} |
||||
Loading…
Reference in new issue