* @package Wombat */ WBClass::load('WBWebinar' ); /** * Webinar BigBlueButton * * @version 0.2.0 * @package Wombat */ class WBWebinar_BigBlueButton extends WBWebinar { protected $config = array( 'secret' => '', 'url' => '[[PROTOCOL]]://[[SERVER]][[SELF]]bigbluebutton', 'api' => '%s/api/%s?%s&checksum=%s', 'logouturl' => '[[PROTOCOL]]://[[SERVER]][[SELF]]', 'welcome' => 'Welcome!', 'bannertext' => 'Big Blue Button Webinar' ); /** * @var array */ private $meetings = array(); /** * @var WBRest_Serializer_Xml */ private $ser = null; /** * 2nd Constructor */ protected function init() { $this->ser = WBClass::create('WBRest_Serializer_Xml'); $this->config['url'] = rtrim($this->config['url'], ' /'); } /** * Create Meeting * * @param array */ protected function addMeeting($data) { if (empty($data['title'])) { $data['title'] = 'Webinar'; } if (empty($data['welcome'])) { $data['welcome'] = $this->config['welcome']; } if (empty($data['bannertext'])) { $data['bannertext'] = $this->config['bannertext']; } if (empty($data['maxparticipants'])) { $data['maxparticipants'] = 0; } $data['maxparticipants'] = intval($data['maxparticipants']); $data['maxparticipants'] = max(2, $data['maxparticipants']); $id = $this->getMeetingId(); if (empty($id)) { if (empty($data['salt'])) { $salt = time(); } $id = $data['salt'] . '-' . gmdate('Y-m-d'); $id = str_replace(array(' ', '_'), array('-', '-'), $id); } $param = array( 'name' => $data['title'], 'meetingID' => $id, 'maxParticipants' => $data['maxparticipants'], 'logoutURL' => WBString::replaceSuperPlaceholders($this->config['logouturl']), 'welcome' => $data['welcome'], 'bannerText' => $data['bannertext'], 'muteOnStart' => true, 'allowModsToUnmuteUsers' => true, 'endWhenNoModerator' => true, 'endWhenNoModeratorDelayInMinutes' => 2, 'record' => true ); $res = $this->request('create', $param); if (is_array($res)) { $this->setMeetingId($id); $this->setMeetingMeta($res); return; } switch (strtoupper($res)) { case 'idNotUnique': $this->setMeetingId($id); return $this->loadMeeting(); break; default: break; } } /** * Load Meeting * */ protected function loadMeeting() { $id = $this->getMeetingId(); if (empty($id)) { return; } $res = $this->getMeetingInfo($id); if (is_array($res) && !empty($res)) { $this->setMeetingId($id); $this->setMeetingMeta($res); return; } $this->setMeetingId(''); } /** * Get Meeting's Join URL for Moderator or Attendee * * @param string person's name * @param bool is moderator */ protected function getMeetingJoinUrl($name = '', $moderator = false) { $mid = $this->getMeetingId(); if (empty($mid)) { return ''; } $data = $this->getMeetingInfo($mid); if (empty($data)) { return ''; } $pw = $data['attendeePW']; if ($moderator) { $pw = $data['moderatorPW']; } $param = array( 'meetingID' => $mid, 'password' => $pw ); if (!empty($name)) { $param['fullName'] = $name; } return $this->getURL('join', $param); } /** * End Meeting * */ protected function endMeeting() { $id = trim($this->getMeetingId()); if (empty($id)) { return; } $data = $this->getMeetingInfo($id); if (!is_array($data)) { return; } $pw = $data['moderatorPW']; $param = array( 'meetingID' => $id, 'password' => $data['moderatorPW'], ); $data = $this->request('end', $param); } private function getMeetings() { $params = array(); $data = $this->request('getMeetings', $params); $this->meetings = array(); if (empty($data['meetings'])) { return $this->meetings; } $this->meetings = $data['meetings']; return $this->meetings; } /** * Get Recordings of Meeting - Implementation * * @todo improve values of returned list * @return array list */ protected function getMeetingRecorings() { $mid = $this->getMeetingId(); $param = array( 'meetingID' => $mid, ); $data = $this->request('getRecordings', $param); if (!is_array($data)) { return array(); } $list = array(); if (!isset($data['recordings']) || empty($data['recordings'])) { return $list; } if (!isset($data['recordings']['recording']['playback']['format'][0])) { $data['recordings']['recording']['playback']['format'] = array($data['recordings']['recording']['playback']['format']); } foreach ($data['recordings']['recording']['playback']['format'] as $f) { $list[] = array( 'type' => $f['type'], 'url' => $f['url'] ); } return $list; } private function getMeetingInfo($mid) { foreach ($this->meetings as $m) { if ($id == $m['meetingID']) { return $m; } } $param = array( 'meetingID' => $mid, ); $data = $this->request('getMeetingInfo', $param); if (!is_array($data)) { return array(); } $this->meetings[] = $data; return $data; } private function getURL($name, $param = array()) { // convert to strings foreach ($param as &$v) { if (is_bool($v)) { if ($v) { $v = 'true'; } else { $v = 'false'; } } } $get = http_build_query($param); $cs = $this->getChecksum($name, $get); $url = sprintf($this->config['api'], WBString::replaceSuperPlaceholders($this->config['url']), $name, $get, $cs); return $url; } private function request($name, $param = array()) { $url = $this->getURL($name, $param); // use key 'http' even if you send the request to 'https' $header = array(); $method = 'GET'; $options = array( 'http' => array( 'method' => $method, 'header' => implode("\r\n", $header), 'ignore_errors' => false, 'max_redirects' => 1, 'follow_location' => 1 ) ); // magic variable $http_response_header = array(); $context = stream_context_create($options); $res = file_get_contents($url, false, $context); $data = array(); if (empty($res)) { return $data; } $data = $this->ser->unserialize($res, null); if (empty($data['returncode'])) { return array(); } switch (strtoupper($data['returncode'])) { case 'SUCCESS': break; case 'FAILED': default: return $data['messageKey']; break; } return $data; } /** * * callName + queryString + sharedSecret * @return string */ private function getChecksum($name, $query) { $str = $name . $query . $this->config['secret']; return sha1($str); } }