Skip to content

Commit

Permalink
Merge pull request #335 from opentok/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
SecondeJK committed Jun 14, 2023
2 parents 2701a37 + 398f722 commit f1e40f8
Show file tree
Hide file tree
Showing 9 changed files with 285 additions and 39 deletions.
17 changes: 16 additions & 1 deletion src/OpenTok/Archive.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,17 @@ class Archive
private $client;
/** @internal */
private $multiArchiveTag;

/**
* @var mixed|null
*/
private const PERMITTED_AUTO_RESOLUTIONS = [
'480x640',
"640x480",
"720x1280",
"1280x720",
"1080x1920",
"1920x1080"
];

/** @internal */
public function __construct($archiveData, $options = array())
Expand Down Expand Up @@ -141,6 +151,11 @@ public function __construct($archiveData, $options = array())
}
}

public static function getPermittedResolutions()
{
return self::PERMITTED_AUTO_RESOLUTIONS;
}

/** @internal */
public function __get($name)
{
Expand Down
17 changes: 15 additions & 2 deletions src/OpenTok/Broadcast.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ class Broadcast
private $multiBroadcastTag;
/** @ignore */
private $resolution;

/** @ignore */
private $hasAudio;
/** @ignore */
private $hasVideo;

public function __construct($broadcastData, $options = array())
{
// unpack optional arguments (merging with default values) into named variables
Expand All @@ -98,9 +102,12 @@ public function __construct($broadcastData, $options = array())
'isHls' => true,
'isLowLatency' => false,
'isDvr' => false,
'hasAudio' => true,
'hasVideo' => true
);

$options = array_merge($defaults, array_intersect_key($options, $defaults));
list($apiKey, $apiSecret, $apiUrl, $client, $isStopped, $streamMode) = array_values($options);
list($apiKey, $apiSecret, $apiUrl, $client, $isStopped, $streamMode, $hasAudio, $hasVideo) = array_values($options);

// validate params
Validators::validateBroadcastData($broadcastData);
Expand All @@ -118,6 +125,8 @@ public function __construct($broadcastData, $options = array())
$this->isHls = isset($this->data['settings']['hls']);
$this->isLowLatency = $this->data['settings']['hls']['lowLatency'] ?? false;
$this->isDvr = $this->data['settings']['hls']['dvr'] ?? false;
$this->hasAudio = $hasAudio;
$this->hasVideo = $hasVideo;

$this->client = isset($client) ? $client : new Client();
if (!$this->client->isConfigured()) {
Expand Down Expand Up @@ -157,6 +166,10 @@ public function __get($name)
return $this->isDvr;
case 'multiBroadcastTag':
return $this->multiBroadcastTag;
case 'hasAudio':
return $this->hasAudio;
case 'hasVideo':
return $this->hasVideo;
default:
return null;
}
Expand Down
41 changes: 34 additions & 7 deletions src/OpenTok/OpenTok.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ public function generateToken($sessionId, $options = array())
* <a href="https://tokbox.com/developer/guides/end-to-end-encryption">end-to-end encryption</a>
* for a routed session.</li>
*
* <li><code>archiveName</code> (String) &mdash; Name of the archives in auto archived sessions</li>
*
* <li><code>archiveResolution</code> (Enum) &mdash; Resolution of the archives in
* auto archived sessions. Can be one of "480x640", "640x480", "720x1280", "1280x720", "1080x1920", "1920x1080"</li>
*
* <li><code>'location'</code> (String) &mdash; An IP address that the OpenTok servers
* will use to situate the session in its global network. If you do not set a location hint,
* the OpenTok servers will be based on the first client connecting to the session.</li>
Expand Down Expand Up @@ -250,14 +255,34 @@ public function createSession($options = array())
'archiveMode' => ArchiveMode::MANUAL,
'location' => null,
'e2ee' => 'false',
'archiveName' => null,
'archiveResolution' => null
);

// Have to hack this because the default system in these classes needs total refactor
$resolvedArchiveMode = array_merge($defaults, array_intersect_key($options, $defaults));

if ($resolvedArchiveMode['archiveMode'] === ArchiveMode::ALWAYS) {
$defaults['archiveResolution'] = '640x480';
}

$options = array_merge($defaults, array_intersect_key($options, $defaults));

// Have to hack this because the default system in these classes needs total refactor
if ($options['archiveName'] === null) {
unset($options['archiveName']);
}

if ($options['archiveResolution'] === null) {
unset($options['archiveResolution']);
}

list($mediaMode, $archiveMode, $location, $e2ee) = array_values($options);

// validate arguments
Validators::validateMediaMode($mediaMode);
Validators::validateArchiveMode($archiveMode);
Validators::validateAutoArchiveMode($archiveMode, $options);
Validators::validateLocation($location);

// make API call
Expand Down Expand Up @@ -843,19 +868,21 @@ public function startBroadcast(string $sessionId, array $options = []): Broadcas
Validators::validateResolution($options['resolution']);
}

if (isset($options['output']['hls'])) {
Validators::validateBroadcastOutputOptions($options['output']['hls']);
if (isset($options['outputs']['hls'])) {
Validators::validateBroadcastOutputOptions($options['outputs']['hls']);
}

if (isset($options['output']['rtmp'])) {
Validators::validateRtmpStreams($options['output']['rtmp']);
if (isset($options['outputs']['rtmp'])) {
Validators::validateRtmpStreams($options['outputs']['rtmp']);
}

$defaults = [
'layout' => Layout::getBestFit(),
'hasAudio' => true,
'hasVideo' => true,
'streamMode' => 'auto',
'resolution' => '640x480',
'output' => [
'outputs' => [
'hls' => [
'dvr' => false,
'lowLatency' => false
Expand All @@ -865,7 +892,7 @@ public function startBroadcast(string $sessionId, array $options = []): Broadcas

$options = array_merge($defaults, $options);

list($layout, $streamMode) = array_values($options);
list($layout, $hasAudio, $hasVideo, $streamMode) = array_values($options);

// validate arguments
Validators::validateSessionId($sessionId);
Expand Down Expand Up @@ -1010,7 +1037,7 @@ public function getStream($sessionId, $streamId)
}

/**
* Returns a StreamList Object for the given session ID.
* Returns a StreamList Object for the given session ID.
*
* @param String $sessionId The session ID.
*
Expand Down
25 changes: 25 additions & 0 deletions src/OpenTok/Util/Validators.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace OpenTok\Util;

use OpenTok\Archive;
use OpenTok\Util\Client;
use OpenTok\Layout;
use OpenTok\Role;
Expand Down Expand Up @@ -266,6 +267,7 @@ public static function validateMediaMode($mediaMode)
);
}
}

public static function validateArchiveMode($archiveMode)
{
if (!ArchiveMode::isValidValue($archiveMode)) {
Expand All @@ -274,6 +276,22 @@ public static function validateArchiveMode($archiveMode)
);
}
}

public static function validateAutoArchiveMode($archiveMode, $options)
{
if ($archiveMode === ArchiveMode::MANUAL) {
foreach (['archiveName', 'archiveResolution'] as $key) {
if (array_key_exists($key, $options)) {
throw new InvalidArgumentException('Cannot set ' . $key . ' when Archive mode is Manual');
}
}
}

if (array_key_exists('archiveResolution', $options)) {
self::validateAutoArchiveResolution($options['archiveResolution']);
}
}

public static function validateLocation($location)
{
if ($location != null && !filter_var($location, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
Expand Down Expand Up @@ -394,6 +412,13 @@ public static function validateWebsocketOptions(array $websocketOptions)
}
}

public static function validateAutoArchiveResolution($archiveResolution)
{
if (! in_array($archiveResolution, Archive::getPermittedResolutions(), true)) {
throw new InvalidArgumentException($archiveResolution . ' is not a valid resolution');
}
}

public static function validateLayoutClassListItem($layoutClassList)
{
if (!is_string($layoutClassList['id'])) {
Expand Down
94 changes: 76 additions & 18 deletions tests/OpenTokTest/BroadcastTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use OpenTok\Archive;
use OpenTok\Broadcast;
use OpenTok\Exception\InvalidArgumentException;
use OpenTok\StreamMode;
Expand All @@ -14,26 +13,22 @@

class BroadcastTest extends TestCase
{

// Fixtures
protected $broadcastData;
protected $API_KEY;
protected $API_SECRET;

protected $broadcast;
protected $broadcastData;
protected $client;

protected static $mockBasePath;
/**
* @var array
*/
private $historyContainer;

public static function setUpBeforeClass(): void
{
self::$mockBasePath = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR;
}

public function setupBroadcasts($streamMode)
public function setUp(): void
{
// Set up fixtures
$this->broadcastData = array(
$this->broadcastData = [
'id' => '063e72a4-64b4-43c8-9da5-eca071daab89',
'createdAt' => 1394394801000,
'updatedAt' => 1394394801000,
Expand All @@ -42,14 +37,27 @@ public function setupBroadcasts($streamMode)
'layout' => [
'type' => 'custom',
'stylesheet' => 'a layout stylesheet',
'streenshareType' => 'some options'
'screenshareType' => 'some options'
],
'maxDuration' => 5400,
'resolution' => '640x480',
'streamMode' => $streamMode
);
'streamMode' => StreamMode::AUTO,
'isAudio' => true,
'isVideo' => true
];
}

$this->broadcast = new Broadcast($this->broadcastData, array(
public static function setUpBeforeClass(): void
{
self::$mockBasePath = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'mock' . DIRECTORY_SEPARATOR;
}

public function setupBroadcasts($streamMode)
{
$data = $this->broadcastData;
$data['streamMode'] = $streamMode;

$this->broadcast = new Broadcast($data, array(
'apiKey' => $this->API_KEY,
'apiSecret' => $this->API_SECRET,
'client' => $this->client
Expand Down Expand Up @@ -88,6 +96,39 @@ private function setupOTWithMocks($mocks)
$handlerStack->push($history);
}

public function testCannotCreateBroadcastWithAddInvalidApiKey(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('The apiKey was not a string nor an integer: ');

$broadcastObject = new Broadcast($this->broadcastData, [
'apiKey' => new Client()
]);
}

public function testCannotCreateBroadcastWithInvalidApiSecret(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('The apiSecret was not a string: OpenTok\Util\Client Object');

$broadcastObject = new Broadcast($this->broadcastData, [
'apiKey' => 'test',
'apiSecret' => new Client()
]);
}

public function testCannotCreateBroadcastWithInvalidApiUrl(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('The optional apiUrl was not a string: ');

$broadcastObject = new Broadcast($this->broadcastData, [
'apiKey' => 'validKey',
'apiSecret' => 'validSecret',
'apiUrl' => 'test'
]);
}

private function setupOT()
{
return $this->setupOTWithMocks([]);
Expand All @@ -98,8 +139,6 @@ public function testInitializes()
// Arrange
$this->setupOT();
$this->setupBroadcasts(StreamMode::AUTO);
// Act
// Assert
$this->assertInstanceOf(Broadcast::class, $this->broadcast);
}

Expand Down Expand Up @@ -180,5 +219,24 @@ public function testCanRemoveStreamFromBroadcast(): void
);
$this->assertTrue($return);
}

public function testCannotRemoveStreamFromBroadcastOnAuto(): void
{
$this->expectException(InvalidArgumentException::class);

$this->setupOTWithMocks([[
'code' => 200,
'headers' => [
'Content-Type' => 'application/json'
],
'path' => 'v2/project/APIKEY/broadcast/BROADCASTID/get'
]]);

$this->setupBroadcasts(StreamMode::AUTO);

$return = $this->broadcast->removeStreamFromBroadcast(
'5dfds4-asdda4asf4'
);
}
}

0 comments on commit f1e40f8

Please sign in to comment.