From d7099ed4e15b5d0c4791199618efeaf00a2778a4 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Wed, 30 Aug 2023 17:32:57 +0200 Subject: [PATCH 01/68] Deprecate configToken --- src/Parameters/CreateMeetingParameters.php | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index 0afa4b0d..c1b3fa04 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -163,6 +163,11 @@ class CreateMeetingParameters extends MetaParameters */ protected $webVoice; + /** + * @var string + */ + protected $configToken; + /** * @var int */ @@ -476,6 +481,28 @@ public function setGuestPolicyAlwaysAccept(): self return $this; } + /** + * @deprecated old flash client parameter, not used anymore + * @return string + */ + public function getConfigToken(): ?string + { + return $this->configToken; + } + + /** + * @deprecated old flash client parameter, not used anymore + * @param string $configToken + * + * @return JoinMeetingParameters + */ + public function setConfigToken(string $configToken): self + { + $this->configToken = $configToken; + + return $this; + } + public function addPresentation(string $nameOrUrl, ?string $content = null, ?string $filename = null): self { if (!$filename) { From 519529dc9cf1661749a5f9939a96119918c85612 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Wed, 30 Aug 2023 17:35:32 +0200 Subject: [PATCH 02/68] Fix code style --- .php-cs-fixer.php | 2 ++ src/BigBlueButton.php | 7 +++---- src/Exceptions/BaseException.php | 4 +--- .../Bridge/PsrHttpClient/PsrHttpClientTransport.php | 3 --- .../SymfonyHttpClient/SymfonyHttpClientTransport.php | 3 --- src/Http/Transport/CurlTransport.php | 3 --- src/Parameters/BaseParameters.php | 3 --- src/Parameters/CreateMeetingParameters.php | 5 +---- src/Parameters/InsertDocumentParameters.php | 5 +---- src/Parameters/PutRecordingTextTrackParameters.php | 5 ----- src/Responses/BaseResponseAsJson.php | 3 --- tests/TestCase.php | 7 ------- tests/functional/BigBlueButtonWithCurlTransportTest.php | 3 --- .../BigBlueButtonWithPsrHttpClientTransport.php | 3 --- .../BigBlueButtonWithSymfonyHttpClientTransportTest.php | 3 --- tests/integration/Http/Transport/CurlTransportTest.php | 9 +++------ .../Bridge/PsrHttpClient/PsrHttpClientTransportTest.php | 3 --- tests/unit/Http/Transport/HeaderTest.php | 2 -- 18 files changed, 11 insertions(+), 62 deletions(-) diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index a1e6c9dd..a714f742 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -18,6 +18,8 @@ 'yoda_style' => false, 'single_line_throw' => false, 'increment_style' => false, + 'modernize_strpos' => false, + 'get_class_to_class_keyword' => false, ]) ->setRiskyAllowed(true) ->setFinder($finder); diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index 402a9a2a..ffe6c1d8 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -59,7 +59,6 @@ use BigBlueButton\Responses\PutRecordingTextTrackResponse; use BigBlueButton\Responses\UpdateRecordingsResponse; use BigBlueButton\Util\UrlBuilder; -use SimpleXMLElement; /** * Class BigBlueButton. @@ -108,7 +107,7 @@ class BigBlueButton * * @throws ConfigException */ - public function __construct(?string $baseUrl = null, ?string $secret = null, ?TransportInterface $transport = null) + public function __construct(string $baseUrl = null, string $secret = null, TransportInterface $transport = null) { // Keeping backward compatibility with older deployed versions $this->securitySecret = $secret ?: getenv('BBB_SECURITY_SALT') ?: getenv('BBB_SECRET'); @@ -478,10 +477,10 @@ public function setJSessionId(string $jSessionId): void * @throws ParsingException * @throws RuntimeException */ - private function processXmlResponse(string $url, string $payload = '', string $contentType = 'application/xml'): SimpleXMLElement + private function processXmlResponse(string $url, string $payload = '', string $contentType = 'application/xml'): \SimpleXMLElement { try { - return new SimpleXMLElement($this->requestUrl($url, $payload, $contentType)); + return new \SimpleXMLElement($this->requestUrl($url, $payload, $contentType)); } catch (NetworkException|RuntimeException $e) { throw $e; } catch (\Throwable $e) { diff --git a/src/Exceptions/BaseException.php b/src/Exceptions/BaseException.php index bd6e8576..68f42be0 100644 --- a/src/Exceptions/BaseException.php +++ b/src/Exceptions/BaseException.php @@ -21,11 +21,9 @@ namespace BigBlueButton\Exceptions; -use Exception; - /** * @abstract since 4.0. */ -class BaseException extends Exception +class BaseException extends \Exception { } diff --git a/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php b/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php index a8b10278..9c76ce50 100644 --- a/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php +++ b/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php @@ -104,9 +104,6 @@ public function __construct( $this->defaultHeaders = $defaultHeaders; } - /** - * {@inheritDoc} - */ public function request(TransportRequest $request): TransportResponse { if ('' !== $payload = $request->getPayload()) { diff --git a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php index 943ac80e..3c91cc5c 100644 --- a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php +++ b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php @@ -101,9 +101,6 @@ public static function create(array $defaultHeaders = [], array $defaultOptions // @codeCoverageIgnoreEnd } - /** - * {@inheritDoc} - */ public function request(TransportRequest $request): TransportResponse { $headers = $this->defaultHeaders; diff --git a/src/Http/Transport/CurlTransport.php b/src/Http/Transport/CurlTransport.php index 40d0b7eb..4a7980d6 100644 --- a/src/Http/Transport/CurlTransport.php +++ b/src/Http/Transport/CurlTransport.php @@ -84,9 +84,6 @@ public static function createWithDefaultOptions(array $additionalCurlOptions = [ // @codeCoverageIgnoreEnd } - /** - * {@inheritDoc} - */ public function request(TransportRequest $request): TransportResponse { // @codeCoverageIgnoreStart diff --git a/src/Parameters/BaseParameters.php b/src/Parameters/BaseParameters.php index f87e95c5..36252a56 100644 --- a/src/Parameters/BaseParameters.php +++ b/src/Parameters/BaseParameters.php @@ -45,9 +45,6 @@ public function __call(string $name, array $arguments) return null; } - /** - * @return mixed - */ protected function getter(string $name) { if (property_exists($this, $name)) { diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index 0afa4b0d..750566a8 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -476,7 +476,7 @@ public function setGuestPolicyAlwaysAccept(): self return $this; } - public function addPresentation(string $nameOrUrl, ?string $content = null, ?string $filename = null): self + public function addPresentation(string $nameOrUrl, string $content = null, string $filename = null): self { if (!$filename) { $this->presentations[$nameOrUrl] = !$content ?: base64_encode($content); @@ -492,9 +492,6 @@ public function getPresentations(): array return $this->presentations; } - /** - * @return mixed - */ public function getPresentationsAsXML() { $result = ''; diff --git a/src/Parameters/InsertDocumentParameters.php b/src/Parameters/InsertDocumentParameters.php index 3542dd9b..7140c447 100644 --- a/src/Parameters/InsertDocumentParameters.php +++ b/src/Parameters/InsertDocumentParameters.php @@ -42,7 +42,7 @@ public function __construct(string $meetingID) $this->meetingID = $meetingID; } - public function addPresentation(string $url, string $filename, ?bool $downloadable = null, ?bool $removable = null): self + public function addPresentation(string $url, string $filename, bool $downloadable = null, bool $removable = null): self { $this->presentations[$url] = [ 'filename' => $filename, @@ -60,9 +60,6 @@ public function removePresentation(string $url): self return $this; } - /** - * @return mixed - */ public function getPresentationsAsXML() { $result = ''; diff --git a/src/Parameters/PutRecordingTextTrackParameters.php b/src/Parameters/PutRecordingTextTrackParameters.php index 728ac032..b8fb2fc9 100644 --- a/src/Parameters/PutRecordingTextTrackParameters.php +++ b/src/Parameters/PutRecordingTextTrackParameters.php @@ -62,15 +62,10 @@ class PutRecordingTextTrackParameters extends BaseParameters */ protected $contentType; - /** - * @var mixed - */ protected $file; /** * GetRecordingTextTracksParameters constructor. - * - * @param $recordID */ public function __construct(string $recordID, string $kind, string $lang, string $label) { diff --git a/src/Responses/BaseResponseAsJson.php b/src/Responses/BaseResponseAsJson.php index 7d45bba9..66cb6746 100644 --- a/src/Responses/BaseResponseAsJson.php +++ b/src/Responses/BaseResponseAsJson.php @@ -28,9 +28,6 @@ abstract class BaseResponseAsJson public const FAILED = 'FAILED'; public const CHECKSUM_ERROR = 'checksumError'; - /** - * @var mixed - */ protected $data; /** diff --git a/tests/TestCase.php b/tests/TestCase.php index d66e4bb0..1b66cf1c 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -40,9 +40,6 @@ class TestCase extends \PHPUnit\Framework\TestCase */ protected $faker; - /** - * {@inheritdoc} - */ protected function setUp(): void { parent::setUp(); @@ -127,8 +124,6 @@ protected function generateCreateParams() } /** - * @param $createParams - * * @return array */ protected function generateBreakoutCreateParams($createParams) @@ -202,8 +197,6 @@ protected function getCreateMock($params) } /** - * @param $params - * * @return CreateMeetingParameters */ protected function getBreakoutCreateMock($params) diff --git a/tests/functional/BigBlueButtonWithCurlTransportTest.php b/tests/functional/BigBlueButtonWithCurlTransportTest.php index 9bfc9a0f..61d40766 100644 --- a/tests/functional/BigBlueButtonWithCurlTransportTest.php +++ b/tests/functional/BigBlueButtonWithCurlTransportTest.php @@ -26,9 +26,6 @@ final class BigBlueButtonWithCurlTransportTest extends AbstractBigBlueButtonFunctionalTest { - /** - * {@inheritDoc} - */ protected static function createTransport(): TransportInterface { return CurlTransport::createWithDefaultOptions(); diff --git a/tests/functional/BigBlueButtonWithPsrHttpClientTransport.php b/tests/functional/BigBlueButtonWithPsrHttpClientTransport.php index 3bebccef..cd5bd19c 100644 --- a/tests/functional/BigBlueButtonWithPsrHttpClientTransport.php +++ b/tests/functional/BigBlueButtonWithPsrHttpClientTransport.php @@ -29,9 +29,6 @@ final class BigBlueButtonWithPsrHttpClientTransport extends AbstractBigBlueButtonFunctionalTest { - /** - * {@inheritDoc} - */ protected static function createTransport(): TransportInterface { $psr17Factory = new Psr17Factory(); diff --git a/tests/functional/BigBlueButtonWithSymfonyHttpClientTransportTest.php b/tests/functional/BigBlueButtonWithSymfonyHttpClientTransportTest.php index 0dc733b8..3f75ce6f 100644 --- a/tests/functional/BigBlueButtonWithSymfonyHttpClientTransportTest.php +++ b/tests/functional/BigBlueButtonWithSymfonyHttpClientTransportTest.php @@ -26,9 +26,6 @@ final class BigBlueButtonWithSymfonyHttpClientTransportTest extends AbstractBigBlueButtonFunctionalTest { - /** - * {@inheritDoc} - */ protected static function createTransport(): TransportInterface { return SymfonyHttpClientTransport::create(); diff --git a/tests/integration/Http/Transport/CurlTransportTest.php b/tests/integration/Http/Transport/CurlTransportTest.php index 8517e011..6f79185a 100644 --- a/tests/integration/Http/Transport/CurlTransportTest.php +++ b/tests/integration/Http/Transport/CurlTransportTest.php @@ -34,9 +34,6 @@ */ final class CurlTransportTest extends TestCase { - /** - * {@inheritDoc} - */ public static function setUpBeforeClass(): void { TestHttpServer::start(); @@ -45,9 +42,9 @@ public static function setUpBeforeClass(): void public function provideBadResponseCodes(): iterable { // cURL does not understand codes below 200 properly. -// foreach (range(100, 199) as $badCode) { -// yield 'HTTP code ' . $badCode => [$badCode]; -// } + // foreach (range(100, 199) as $badCode) { + // yield 'HTTP code ' . $badCode => [$badCode]; + // } foreach (range(300, 599) as $badCode) { yield 'HTTP code '.$badCode => [$badCode]; diff --git a/tests/unit/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransportTest.php b/tests/unit/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransportTest.php index 73d97637..dc7fa204 100644 --- a/tests/unit/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransportTest.php +++ b/tests/unit/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransportTest.php @@ -62,9 +62,6 @@ final class PsrHttpClientTransportTest extends TestCase */ private $streamFactoryMock; - /** - * {@inheritDoc} - */ protected function setUp(): void { $this->transport = $this->createTransport(); diff --git a/tests/unit/Http/Transport/HeaderTest.php b/tests/unit/Http/Transport/HeaderTest.php index 70abb5d5..c7217f4f 100644 --- a/tests/unit/Http/Transport/HeaderTest.php +++ b/tests/unit/Http/Transport/HeaderTest.php @@ -78,8 +78,6 @@ public function provideNonStringHeaders(): iterable /** * @dataProvider provideNonStringHeaders - * - * @param mixed $badHeader */ public function testMergeCurlHeadersWithNonStringHeaders($badHeader): void { From 7efb21c2c50ebf945572b3687929d014edee97ae Mon Sep 17 00:00:00 2001 From: Felix Jacobi Date: Sat, 7 Oct 2023 13:30:15 +0200 Subject: [PATCH 03/68] Updated PHPUnit to version 9 (fixes #89) (#158) * Updated PHPUnit to version 9 (fixes #89) * Extended tests --- composer.json | 4 +- phpunit.xml.dist | 48 +++++------- src/Parameters/CreateMeetingParameters.php | 2 +- tests/unit/BigBlueButtonTest.php | 75 +++++++++++++++++++ .../CreateMeetingParametersTest.php | 3 +- tools/.phpunit/composer.json | 4 +- 6 files changed, 98 insertions(+), 38 deletions(-) diff --git a/composer.json b/composer.json index 0ad3d191..32c5b509 100644 --- a/composer.json +++ b/composer.json @@ -124,12 +124,12 @@ "brainmaestro/composer-git-hooks": "^2.8", "extensions": { "phpunit/phpunit": { - "fakerphp/faker": "^1.14" + "fakerphp/faker": "1.20.*" } }, "friendsofphp/php-cs-fixer": "^3.3", "php-coveralls/php-coveralls": "^2.4", - "phpunit/phpunit": "^8", + "phpunit/phpunit": "^9", "vimeo/psalm": "^4.22" } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 627dd0e5..ccc8bc0e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,33 +1,19 @@ - - - - - - - ./src/ - - - - - - ./tests/unit/ - - - ./tests/integration/ - - - ./tests/functional/ - - - + + + + ./src/ + + + + + ./tests/unit/ + + + ./tests/integration/ + + + ./tests/functional/ + + diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index 750566a8..9320dff5 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -526,7 +526,7 @@ public function getHTTPQuery(): string if ($this->isBreakout()) { if ($this->parentMeetingID === null || $this->sequence === null) { - trigger_error('Breakout rooms require a parentMeetingID and sequence number.', \E_USER_WARNING); + throw new \RuntimeException('Breakout rooms require a parentMeetingID and sequence number.'); } } else { $queries = $this->filterBreakoutRelatedQueries($queries); diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index 045cb7fb..7a1ad1aa 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -27,8 +27,10 @@ use BigBlueButton\Http\Transport\TransportResponse; use BigBlueButton\Parameters\DeleteRecordingsParameters; use BigBlueButton\Parameters\GetRecordingsParameters; +use BigBlueButton\Parameters\GetRecordingTextTracksParameters; use BigBlueButton\Parameters\InsertDocumentParameters; use BigBlueButton\Parameters\PublishRecordingsParameters; +use BigBlueButton\Parameters\PutRecordingTextTrackParameters; use PHPUnit\Framework\MockObject\MockObject; /** @@ -372,4 +374,77 @@ public function testGetInsertDocument(): void $this->assertTrue($response->success()); } + + public function testGetRecordingTextTracks(): void + { + $params = new GetRecordingTextTracksParameters('foobar'); + + $json = '{ + "response": { + "returncode": "SUCCESS", + "tracks": [ + { + "href": "https://captions.example.com/textTrack/0ab39e419c9bcb63233168daefe390f232c71343/183f0bf3a0982a127bdb8161e0c44eb696b3e75c-1554230749920/subtitles_en-US.vtt", + "kind": "subtitles", + "label": "English", + "lang": "en-US", + "source": "upload" + }, + { + "href": "https://captions.example.com/textTrack/95b62d1b762700b9d5366a9e71d5fcc5086f2723/183f0bf3a0982a127bdb8161e0c44eb696b3e75c-1554230749920/subtitles_pt-BR.vtt", + "kind": "subtitles", + "label": "Brazil", + "lang": "pt-BR", + "source": "upload" + } + ] + } + }'; + $this->transport->method('request')->willReturn(new TransportResponse($json, null)); + + $response = $this->bbb->getRecordingTextTracks($params); + + $this->assertTrue($response->success()); + $this->assertSame('SUCCESS', $response->getReturnCode()); + + $tracks = $response->getTracks(); + $this->assertCount(2, $tracks); + $this->assertArrayHasKey(0, $tracks); + $this->assertArrayHasKey(1, $tracks); + + $this->assertSame('https://captions.example.com/textTrack/0ab39e419c9bcb63233168daefe390f232c71343/183f0bf3a0982a127bdb8161e0c44eb696b3e75c-1554230749920/subtitles_en-US.vtt', $tracks[0]->getHref()); + $this->assertSame('subtitles', $tracks[0]->getKind()); + $this->assertSame('English', $tracks[0]->getLabel()); + $this->assertSame('en-US', $tracks[0]->getLang()); + $this->assertSame('upload', $tracks[0]->getSource()); + + $this->assertSame('https://captions.example.com/textTrack/95b62d1b762700b9d5366a9e71d5fcc5086f2723/183f0bf3a0982a127bdb8161e0c44eb696b3e75c-1554230749920/subtitles_pt-BR.vtt', $tracks[1]->getHref()); + $this->assertSame('subtitles', $tracks[1]->getKind()); + $this->assertSame('Brazil', $tracks[1]->getLabel()); + $this->assertSame('pt-BR', $tracks[1]->getLang()); + $this->assertSame('upload', $tracks[1]->getSource()); + } + + public function testPutRecordingTextTrack(): void + { + $params = new PutRecordingTextTrackParameters('foobar', 'subtitles', 'en-US', 'English'); + + $json = '{ + "response": { + "messageKey": "upload_text_track_success", + "message": "Text track uploaded successfully", + "recordId": "baz", + "returncode": "SUCCESS" + } + }'; + $this->transport->method('request')->willReturn(new TransportResponse($json, null)); + + $response = $this->bbb->putRecordingTextTrack($params); + + $this->assertTrue($response->success()); + $this->assertNull($response->getMessageKey()); + $this->assertNull($response->getMessage()); + $this->assertSame('baz', $response->getRecordID()); + $this->assertSame('SUCCESS', $response->getReturnCode()); + } } diff --git a/tests/unit/Parameters/CreateMeetingParametersTest.php b/tests/unit/Parameters/CreateMeetingParametersTest.php index e951e777..86be17e3 100644 --- a/tests/unit/Parameters/CreateMeetingParametersTest.php +++ b/tests/unit/Parameters/CreateMeetingParametersTest.php @@ -21,7 +21,6 @@ use BigBlueButton\Core\GuestPolicy; use BigBlueButton\TestCase; -use PHPUnit\Framework\Error\Warning; /** * Class CreateMeetingParametersTest. @@ -123,7 +122,7 @@ public function testCreateBreakoutMeeting() public function testCreateBreakoutMeetingWithMissingParams() { - $this->expectException(Warning::class); + $this->expectException(\RuntimeException::class); $params = new CreateMeetingParameters($this->faker->uuid, $this->faker->name); $params->setBreakout(true); diff --git a/tools/.phpunit/composer.json b/tools/.phpunit/composer.json index 18a43fc8..4db33099 100644 --- a/tools/.phpunit/composer.json +++ b/tools/.phpunit/composer.json @@ -1,6 +1,6 @@ { "require": { - "phpunit/phpunit": "^8", - "fakerphp/faker": "^1.14" + "phpunit/phpunit": "^9.0", + "fakerphp/faker": "1.20.*" } } From eaafe113df6d6fd292d857978ebb6437d135b766 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sat, 7 Oct 2023 17:26:28 +0200 Subject: [PATCH 04/68] Fix functional tests (#160) * Fix voiceBridge too short * End meeting after each test, enforce guest policy on joinMeeting test --- tests/TestCase.php | 2 +- .../AbstractBigBlueButtonFunctionalTest.php | 37 +++++++++++++++++-- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index 1b66cf1c..e88de813 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -72,7 +72,7 @@ protected function generateCreateParams() 'moderatorPW' => $this->faker->password, 'autoStartRecording' => $this->faker->boolean(50), 'dialNumber' => $this->faker->phoneNumber, - 'voiceBridge' => $this->faker->randomNumber(5), + 'voiceBridge' => $this->faker->randomNumber(5, true), 'webVoice' => $this->faker->word, 'logoutURL' => $this->faker->url, 'maxParticipants' => $this->faker->numberBetween(2, 100), diff --git a/tests/functional/AbstractBigBlueButtonFunctionalTest.php b/tests/functional/AbstractBigBlueButtonFunctionalTest.php index fdceead1..3ee5be4f 100644 --- a/tests/functional/AbstractBigBlueButtonFunctionalTest.php +++ b/tests/functional/AbstractBigBlueButtonFunctionalTest.php @@ -119,10 +119,12 @@ public function testCreateMeetingUrl(): void */ public function testCreateMeeting() { - $params = $this->generateCreateParams(); - $result = $this->bbb->createMeeting($this->getCreateMock($params)); + $result = $this->createRealMeeting($this->bbb); $this->assertEquals('SUCCESS', $result->getReturnCode()); $this->assertTrue($result->success()); + + // Cleanup + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); } /** @@ -138,6 +140,9 @@ public function testCreateMeetingWithDocumentUrl() $this->assertCount(1, $params->getPresentations()); $this->assertEquals('SUCCESS', $result->getReturnCode()); $this->assertTrue($result->success()); + + // Cleanup + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); } /** @@ -153,6 +158,9 @@ public function testCreateMeetingWithDocumentUrlAndFileName() $this->assertCount(1, $params->getPresentations()); $this->assertEquals('SUCCESS', $result->getReturnCode()); $this->assertTrue($result->success()); + + // Cleanup + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); } /** @@ -168,6 +176,9 @@ public function testCreateMeetingWithDocumentEmbedded() $this->assertCount(1, $params->getPresentations()); $this->assertEquals('SUCCESS', $result->getReturnCode()); $this->assertTrue($result->success()); + + // Cleanup + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); } /** @@ -184,6 +195,9 @@ public function testCreateMeetingWithMultiDocument() $this->assertCount(2, $params->getPresentations()); $this->assertEquals('SUCCESS', $result->getReturnCode()); $this->assertTrue($result->success()); + + // Cleanup + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); } /* Join Meeting */ @@ -208,8 +222,9 @@ public function testCreateJoinMeetingUrl(): void public function testJoinMeeting() { - $params = $this->generateCreateParams(); - $result = $this->bbb->createMeeting($this->getCreateMock($params)); + $params = $this->getCreateMock($this->generateCreateParams()); + $params->setGuestPolicy('ALWAYS_ACCEPT'); + $result = $this->bbb->createMeeting($params); $this->assertEquals('SUCCESS', $result->getReturnCode(), 'Create meeting'); $creationTime = $result->getCreationTime(); @@ -226,6 +241,9 @@ public function testJoinMeeting() $this->assertNotEmpty($joinMeeting->getSessionToken()); $this->assertNotEmpty($joinMeeting->getGuestStatus()); $this->assertNotEmpty($joinMeeting->getUrl()); + + // Cleanup + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); } /* End Meeting */ @@ -283,8 +301,13 @@ public function testGetMeetingsUrl(): void public function testGetMeetings() { + $meeting = $this->createRealMeeting($this->bbb); + $result = $this->bbb->getMeetings(); $this->assertNotEmpty($result->getMeetings()); + + // Cleanup + $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId(), $meeting->getModeratorPassword())); } /* Get meeting info */ @@ -295,6 +318,9 @@ public function testGetMeetingInfoUrl(): void $url = $this->bbb->getMeetingInfoUrl(new GetMeetingInfoParameters($meeting->getMeetingId())); $this->assertStringContainsString('='.rawurlencode($meeting->getMeetingId()), $url); + + // Cleanup + $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId(), $meeting->getModeratorPassword())); } public function testGetMeetingInfo() @@ -304,6 +330,9 @@ public function testGetMeetingInfo() $result = $this->bbb->getMeetingInfo(new GetMeetingInfoParameters($meeting->getMeetingId(), $meeting->getModeratorPassword())); $this->assertEquals('SUCCESS', $result->getReturnCode()); $this->assertTrue($result->success()); + + // Cleanup + $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId(), $meeting->getModeratorPassword())); } public function testGetRecordingsUrl(): void From e231d4b32a2227fdbec053b6eca58a19292a2b0c Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sat, 7 Oct 2023 17:41:31 +0200 Subject: [PATCH 05/68] Implement breakout rooms groups in create API (#155) * Implement breakout rooms groups in create API * Code cleanup, add comments, type hints * Fix cs * Fixed missing type hints * Fixed CS --------- Co-authored-by: Felix Jacobi --- src/Core/Meeting.php | 4 +-- src/Parameters/CreateMeetingParameters.php | 30 ++++++++++++++++ tests/TestCase.php | 34 +++++++++++++++++++ tests/unit/BigBlueButtonTest.php | 8 ++--- .../CreateMeetingParametersTest.php | 1 + 5 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/Core/Meeting.php b/src/Core/Meeting.php index 3d1dbc64..49f41acb 100644 --- a/src/Core/Meeting.php +++ b/src/Core/Meeting.php @@ -61,12 +61,12 @@ class Meeting private $dialNumber; /** - * @var string + * @var string|null */ private $attendeePassword; /** - * @var string + * @var string|null */ private $moderatorPassword; diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index 9320dff5..9b6e6b01 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -373,6 +373,11 @@ class CreateMeetingParameters extends MetaParameters */ protected $userCameraCap; + /** + * @var array + */ + private $breakoutRoomsGroups = []; + /** * @var array */ @@ -487,6 +492,24 @@ public function addPresentation(string $nameOrUrl, string $content = null, strin return $this; } + /** + * @return array + */ + public function getBreakoutRoomsGroups(): array + { + return $this->breakoutRoomsGroups; + } + + /** + * @return $this + */ + public function addBreakoutRoomsGroup(string $id, ?string $name, array $roster): self + { + $this->breakoutRoomsGroups[] = ['id' => $id, 'name' => $name, 'roster' => $roster]; + + return $this; + } + public function getPresentations(): array { return $this->presentations; @@ -524,6 +547,13 @@ public function getHTTPQuery(): string { $queries = $this->getHTTPQueryArray(); + // Pre-defined groups to automatically assign the students to a given breakout room + if (!empty($this->breakoutRoomsGroups)) { + $queries = array_merge($queries, [ + 'groups' => json_encode($this->breakoutRoomsGroups), + ]); + } + if ($this->isBreakout()) { if ($this->parentMeetingID === null || $this->sequence === null) { throw new \RuntimeException('Breakout rooms require a parentMeetingID and sequence number.'); diff --git a/tests/TestCase.php b/tests/TestCase.php index e88de813..a2a656bb 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -120,9 +120,24 @@ protected function generateCreateParams() 'allowRequestsWithoutSession' => $this->faker->boolean(50), 'virtualBackgroundsDisabled' => $this->faker->boolean(50), 'userCameraCap' => $this->faker->numberBetween(1, 5), + 'groups' => $this->generateBreakoutRoomsGroups(), ]; } + /** + * @return array + */ + protected function generateBreakoutRoomsGroups(): array + { + $br = $this->faker->numberBetween(0, 8); + $groups = []; + for ($i = 0; $i <= $br; ++$i) { + $groups[] = ['id' => $this->faker->uuid, 'name' => $this->faker->name, 'roster' => $this->faker->randomElements]; + } + + return $groups; + } + /** * @return array */ @@ -145,6 +160,10 @@ protected function getCreateMock($params) { $createMeetingParams = new CreateMeetingParameters($params['meetingID'], $params['name']); + foreach ($params['groups'] as $group) { + $createMeetingParams->addBreakoutRoomsGroup($group['id'], $group['name'], $group['roster']); + } + return $createMeetingParams->setAttendeePW($params['attendeePW']) ->setModeratorPW($params['moderatorPW']) ->setDialNumber($params['dialNumber']) @@ -339,4 +358,19 @@ public function assertEachGetterValueIsBoolean($obj, $getters) $this->assertIsBool($obj->$getterName(), 'Got a '.\gettype($obj->$getterName()).' instead of a boolean for property -> '.$getterName); } } + + public function assertUrlContainsAllRequestParameters(string $url, array $parameters): void + { + foreach ($parameters as $parameter) { + if (\is_bool($parameter)) { + $parameter = $parameter ? 'true' : 'false'; + } + + if (!\is_array($parameter)) { + $this->assertStringContainsString($parameter, urldecode($url)); + } else { + $this->assertUrlContainsAllRequestParameters($url, $parameter); + } + } + } } diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index 7a1ad1aa..67b3dae5 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -163,12 +163,8 @@ public function testCreateMeetingUrl() { $params = $this->generateCreateParams(); $url = $this->bbb->getCreateMeetingUrl($this->getCreateMock($params)); - foreach ($params as $key => $value) { - if (\is_bool($value)) { - $value = $value ? 'true' : 'false'; - } - $this->assertStringContainsString(rawurlencode($key).'='.rawurlencode($value), $url); - } + + $this->assertUrlContainsAllRequestParameters($url, $params); } /* Join Meeting */ diff --git a/tests/unit/Parameters/CreateMeetingParametersTest.php b/tests/unit/Parameters/CreateMeetingParametersTest.php index 86be17e3..ea17c16e 100644 --- a/tests/unit/Parameters/CreateMeetingParametersTest.php +++ b/tests/unit/Parameters/CreateMeetingParametersTest.php @@ -89,6 +89,7 @@ public function testCreateMeetingParameters() $this->assertEquals($params['breakoutRoomsRecord'], $createMeetingParams->isBreakoutRoomsRecord()); $this->assertEquals($params['allowRequestsWithoutSession'], $createMeetingParams->isAllowRequestsWithoutSession()); $this->assertEquals($params['virtualBackgroundsDisabled'], $createMeetingParams->isVirtualBackgroundsDisabled()); + $this->assertEquals(json_encode($params['groups']), json_encode($createMeetingParams->getBreakoutRoomsGroups())); // Check values are empty of this is not a breakout room $this->assertNull($createMeetingParams->isBreakout()); From b55171bb165d5cf739ab3dd3c8dfa6c3928e4819 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sat, 7 Oct 2023 17:44:07 +0200 Subject: [PATCH 06/68] Support multiple checksum algorithms (#147) * Add custom hash algorithm * Adjust tests * Fix cs * Update src/BigBlueButton.php Co-authored-by: Felix Jacobi * Refactor to be compliant with upstream * Fix cs * Remove setHashingAlgorithm, add hashing algorithm as constructor arg. * Revert changes to construct param type hints * Fix cs * Fix test --------- Co-authored-by: Felix Jacobi --- composer.json | 3 ++- src/BigBlueButton.php | 12 ++++++++++-- src/Enum/HashingAlgorithm.php | 31 ++++++++++++++++++++++++++++++ src/Util/UrlBuilder.php | 10 ++++++++-- tests/unit/BigBlueButtonTest.php | 13 ++++++++++++- tests/unit/Util/UrlBuilderTest.php | 21 +++++++++++++++----- 6 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 src/Enum/HashingAlgorithm.php diff --git a/composer.json b/composer.json index 32c5b509..4384457e 100644 --- a/composer.json +++ b/composer.json @@ -62,7 +62,8 @@ "ext-curl": "*", "ext-simplexml": "*", "ext-mbstring": "*", - "ext-json": "*" + "ext-json": "*", + "marc-mabe/php-enum": "^4.7" }, "suggest": { "psr/http-client-implementation": "To use the PsrHttpClientTransport.", diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index ffe6c1d8..28a58434 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -20,6 +20,7 @@ namespace BigBlueButton; use BigBlueButton\Core\ApiMethod; +use BigBlueButton\Enum\HashingAlgorithm; use BigBlueButton\Exceptions\ConfigException; use BigBlueButton\Exceptions\NetworkException; use BigBlueButton\Exceptions\ParsingException; @@ -80,6 +81,11 @@ class BigBlueButton */ protected $bbbServerBaseUrl; + /** + * @var string + */ + protected $hashingAlgorithm; + /** * @var UrlBuilder */ @@ -107,17 +113,19 @@ class BigBlueButton * * @throws ConfigException */ - public function __construct(string $baseUrl = null, string $secret = null, TransportInterface $transport = null) + public function __construct(string $baseUrl = null, string $secret = null, TransportInterface $transport = null, string $hashingAlgorithm = HashingAlgorithm::SHA_1) { // Keeping backward compatibility with older deployed versions $this->securitySecret = $secret ?: getenv('BBB_SECURITY_SALT') ?: getenv('BBB_SECRET'); $this->bbbServerBaseUrl = $baseUrl ?: getenv('BBB_SERVER_BASE_URL'); + $this->hashingAlgorithm = $hashingAlgorithm; + if (empty($this->bbbServerBaseUrl)) { throw new ConfigException('Base url required'); } - $this->urlBuilder = new UrlBuilder($this->securitySecret, $this->bbbServerBaseUrl); + $this->urlBuilder = new UrlBuilder($this->securitySecret, $this->bbbServerBaseUrl, $this->hashingAlgorithm); $this->transport = $transport ?? CurlTransport::createWithDefaultOptions(); } diff --git a/src/Enum/HashingAlgorithm.php b/src/Enum/HashingAlgorithm.php new file mode 100644 index 00000000..bf74376a --- /dev/null +++ b/src/Enum/HashingAlgorithm.php @@ -0,0 +1,31 @@ +. + */ + +namespace BigBlueButton\Enum; + +use MabeEnum\Enum; + +class HashingAlgorithm extends Enum +{ + public const SHA_1 = 'sha1'; + public const SHA_256 = 'sha256'; + public const SHA_512 = 'sha512'; + public const SHA_384 = 'sha384'; +} diff --git a/src/Util/UrlBuilder.php b/src/Util/UrlBuilder.php index f2b58b8c..3b15aafe 100644 --- a/src/Util/UrlBuilder.php +++ b/src/Util/UrlBuilder.php @@ -35,10 +35,16 @@ final class UrlBuilder */ private $bbbServerBaseUrl; - public function __construct(string $secret, string $serverBaseUrl) + /** + * @var string + */ + private $hashingAlgorithm; + + public function __construct(string $secret, string $serverBaseUrl, string $hashingAlgorithm) { $this->securitySalt = $secret; $this->bbbServerBaseUrl = $serverBaseUrl; + $this->hashingAlgorithm = $hashingAlgorithm; } /** @@ -61,6 +67,6 @@ public function buildQs(string $method = '', string $params = ''): string $checksumParam = 'checksum='; } - return $params.$checksumParam.sha1($method.$params.$this->securitySalt); + return $params.$checksumParam.hash($this->hashingAlgorithm, $method.$params.$this->securitySalt); } } diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index 67b3dae5..b2c0c549 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -20,6 +20,7 @@ namespace BigBlueButton; use BigBlueButton\Core\ApiMethod; +use BigBlueButton\Enum\HashingAlgorithm; use BigBlueButton\Exceptions\ConfigException; use BigBlueButton\Exceptions\NetworkException; use BigBlueButton\Exceptions\ParsingException; @@ -349,13 +350,23 @@ public function testUpdateRecordingsUrl() public function testBuildUrl(): void { - $bigBlueButton = new BigBlueButton('https://bbb.example/bigbluebutton/', 'S3cr3t'); + // Test with default hash algorithm (sha1) + $bigBlueButton = new BigBlueButton('https://bbb.example/bigbluebutton/', 'S3cr3t', null, HashingAlgorithm::SHA_1); $this->assertSame( 'https://bbb.example/bigbluebutton/api/foo?foo=bar&baz=bazinga&checksum=694ad46bc5a79a572bab6c8b9a939527c39ac7f6', $bigBlueButton->buildUrl('foo', 'foo=bar&baz=bazinga'), 'URL is not ok' ); + + // Test with different hash algorithm (sha256) + $bigBlueButton = new BigBlueButton('https://bbb.example/bigbluebutton/', 'S3cr3t', null, HashingAlgorithm::SHA_256); + + $this->assertSame( + 'https://bbb.example/bigbluebutton/api/foo?foo=bar&baz=bazinga&checksum=0ce0d779a8220be9824c7eab055b36b59ac504ba899a76d7c528b8473960025e', + $bigBlueButton->buildUrl('foo', 'foo=bar&baz=bazinga'), + 'URL is not ok' + ); } public function testGetInsertDocument(): void diff --git a/tests/unit/Util/UrlBuilderTest.php b/tests/unit/Util/UrlBuilderTest.php index facce75d..64b71187 100644 --- a/tests/unit/Util/UrlBuilderTest.php +++ b/tests/unit/Util/UrlBuilderTest.php @@ -30,7 +30,8 @@ final class UrlBuilderTest extends TestCase { public function testBuildUrl(): void { - $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/'); + // Test with sha1 hash algorithm + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha1'); // echo sha1('getMeetings' . 'foo=bar&baz=bazinga' . 'AFFE'); $this->assertSame( @@ -38,11 +39,21 @@ public function testBuildUrl(): void $urlBuilder->buildUrl('getMeetings', 'foo=bar&baz=bazinga'), 'signed URL is OK' ); + + // Test with sha256 hash algorithm + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha256'); + + // echo hash('sha256', 'getMeetings' . 'foo=bar&baz=bazinga' . 'AFFE'); + $this->assertSame( + 'https://bbb.example/bigbluebutton/api/getMeetings?foo=bar&baz=bazinga&checksum=e93a022a742425259bf3acec803ad8b4e428e7653b66bfecfa60d935a04bcc3b', + $urlBuilder->buildUrl('getMeetings', 'foo=bar&baz=bazinga'), + 'signed URL is OK' + ); } public function testBuildUrlWithEmptyParams(): void { - $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/'); + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha1'); // echo sha1('getMeetings' . '' . 'AFFE'); $this->assertSame( @@ -54,7 +65,7 @@ public function testBuildUrlWithEmptyParams(): void public function testBuildUrlWithoutAppend(): void { - $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/'); + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha1'); $this->assertSame( 'https://bbb.example/bigbluebutton/api/getMeetings', @@ -65,7 +76,7 @@ public function testBuildUrlWithoutAppend(): void public function testBuildQs(): void { - $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/'); + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha1'); // echo sha1('getMeetings' . 'foo=bar&baz=bazinga' . 'AFFE'); $this->assertSame( @@ -77,7 +88,7 @@ public function testBuildQs(): void public function testBuildQsWithEmptyParams(): void { - $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/'); + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha1'); // echo sha1('getMeetings' . '' . 'AFFE'); $this->assertSame( From 87e761a1f6e9995098febb9073c308f29ac8bffb Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:09:21 +0200 Subject: [PATCH 07/68] Fix methods in wrong class --- src/Parameters/CreateMeetingParameters.php | 25 ---------------------- src/Parameters/JoinMeetingParameters.php | 22 +++++++++++++++++-- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index 08a80f05..9b6e6b01 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -163,11 +163,6 @@ class CreateMeetingParameters extends MetaParameters */ protected $webVoice; - /** - * @var string - */ - protected $configToken; - /** * @var int */ @@ -486,26 +481,6 @@ public function setGuestPolicyAlwaysAccept(): self return $this; } - /** - * @deprecated old flash client parameter, not used anymore - */ - public function getConfigToken(): ?string - { - return $this->configToken; - } - - /** - * @deprecated old flash client parameter, not used anymore - * - * @return JoinMeetingParameters - */ - public function setConfigToken(string $configToken): self - { - $this->configToken = $configToken; - - return $this; - } - public function addPresentation(string $nameOrUrl, string $content = null, string $filename = null): self { if (!$filename) { diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index 4a9dbc4a..ce988328 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -34,8 +34,6 @@ * @method $this setUserID(string $userID) * @method string getWebVoiceConf() * @method $this setWebVoiceConf(string $webVoiceConf) - * @method string getConfigToken() - * @method $this setConfigToken(string $configToken) * @method string getDefaultLayout() * @method $this setDefaultLayout(string $defaultLayout) * @method string getAvatarURL() @@ -137,4 +135,24 @@ public function __construct(string $meetingID, string $fullName, string $passwor $this->fullName = $fullName; $this->password = $password; } + + /** + * @deprecated old flash client parameter, not used anymore + */ + public function getConfigToken(): ?string + { + return $this->configToken; + } + + /** + * @deprecated old flash client parameter, not used anymore + * + * @return JoinMeetingParameters + */ + public function setConfigToken(string $configToken): self + { + $this->configToken = $configToken; + + return $this; + } } From 5ce2e64d98167efc1cd55793cca12971ae3ef442 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:09:28 +0200 Subject: [PATCH 08/68] Add tests for config token --- tests/TestCase.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index a2a656bb..da641181 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -237,6 +237,7 @@ protected function generateJoinMeetingParams() 'userID' => $this->faker->numberBetween(1, 1000), 'webVoiceConf' => $this->faker->word, 'createTime' => $this->faker->unixTime, + 'configToken' => $this->faker->word, 'userdata-countrycode' => $this->faker->countryCode, 'userdata-email' => $this->faker->email, 'userdata-commercial' => false, @@ -252,9 +253,14 @@ protected function getJoinMeetingMock($params) { $joinMeetingParams = new JoinMeetingParameters($params['meetingID'], $params['fullName'], $params['password']); - return $joinMeetingParams->setUserID($params['userID'])->setWebVoiceConf($params['webVoiceConf']) - ->setCreateTime($params['createTime'])->addUserData('countrycode', $params['userdata-countrycode']) - ->addUserData('email', $params['userdata-email'])->addUserData('commercial', $params['userdata-commercial']); + return $joinMeetingParams + ->setUserID($params['userID']) + ->setWebVoiceConf($params['webVoiceConf']) + ->setCreateTime($params['createTime']) + ->setConfigToken($params['configToken']) + ->addUserData('countrycode', $params['userdata-countrycode']) + ->addUserData('email', $params['userdata-email']) + ->addUserData('commercial', $params['userdata-commercial']); } /** From 3652993139d3cc0d1d20045d54fed2aca5234a7b Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:11:01 +0200 Subject: [PATCH 09/68] Fix psalm error --- src/Enum/HashingAlgorithm.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Enum/HashingAlgorithm.php b/src/Enum/HashingAlgorithm.php index bf74376a..a2e1a02b 100644 --- a/src/Enum/HashingAlgorithm.php +++ b/src/Enum/HashingAlgorithm.php @@ -22,6 +22,9 @@ use MabeEnum\Enum; +/** + * @psalm-immutable + */ class HashingAlgorithm extends Enum { public const SHA_1 = 'sha1'; From aaa2ff5a16de229811f3d96c75adebe0165bcd47 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:17:29 +0200 Subject: [PATCH 10/68] Fix cs --- src/Parameters/JoinMeetingParameters.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index ce988328..e8ca4ddf 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -146,8 +146,6 @@ public function getConfigToken(): ?string /** * @deprecated old flash client parameter, not used anymore - * - * @return JoinMeetingParameters */ public function setConfigToken(string $configToken): self { From 11bf11b89f6e372af6c554946dce3f2c3a3ad474 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:31:36 +0200 Subject: [PATCH 11/68] Add psalm immutable annotation --- src/Enum/HashingAlgorithm.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Enum/HashingAlgorithm.php b/src/Enum/HashingAlgorithm.php index bf74376a..a2e1a02b 100644 --- a/src/Enum/HashingAlgorithm.php +++ b/src/Enum/HashingAlgorithm.php @@ -22,6 +22,9 @@ use MabeEnum\Enum; +/** + * @psalm-immutable + */ class HashingAlgorithm extends Enum { public const SHA_1 = 'sha1'; From f1b66bef9b44fa19385cbbc5b6a4e11831843e4e Mon Sep 17 00:00:00 2001 From: Felix Jacobi Date: Mon, 23 Oct 2023 12:58:35 +0200 Subject: [PATCH 12/68] Deprecated password parameters (fixes #142) (#159) * Deprecated password parameters (fixes #142) * Improved deprecation notices --------- Co-authored-by: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> --- src/Core/Meeting.php | 6 ++ src/Parameters/CreateMeetingParameters.php | 60 +++++++++++++++++-- src/Parameters/EndMeetingParameters.php | 34 +++++++++-- src/Parameters/JoinMeetingParameters.php | 45 ++++++++++---- tests/TestCase.php | 28 ++++++--- .../CreateMeetingParametersTest.php | 40 ++++++++++--- .../Parameters/EndMeetingParametersTest.php | 27 ++++++++- .../Parameters/JoinMeetingParametersTest.php | 33 ++++++++-- 8 files changed, 231 insertions(+), 42 deletions(-) diff --git a/src/Core/Meeting.php b/src/Core/Meeting.php index 49f41acb..027c2baa 100644 --- a/src/Core/Meeting.php +++ b/src/Core/Meeting.php @@ -213,11 +213,17 @@ public function getDialNumber(): string return $this->dialNumber; } + /** + * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. + */ public function getAttendeePassword(): string { return $this->attendeePassword; } + /** + * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. + */ public function getModeratorPassword(): string { return $this->moderatorPassword; diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index 9b6e6b01..d28b1b45 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -26,10 +26,6 @@ * @method $this setName(string $name) * @method string getMeetingID() * @method $this setMeetingID(string $id) - * @method string getAttendeePW() - * @method $this setAttendeePW(string $password) - * @method string getModeratorPW() - * @method $this setModeratorPW(string $password) * @method string getWelcome() * @method $this setWelcome(string $welcome) * @method string getDialNumber() @@ -134,12 +130,12 @@ class CreateMeetingParameters extends MetaParameters protected $meetingID; /** - * @var string + * @var string|null */ protected $attendeePW; /** - * @var string + * @var string|null */ protected $moderatorPW; @@ -543,6 +539,58 @@ public function getPresentationsAsXML() return $result; } + /** + * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. + */ + public function getAttendeePW(): string + { + if (null === $this->attendeePW) { + throw new \RuntimeException(sprintf('Attendee password was not passed to "%s".', self::class)); + } + + return $this->attendeePW; + } + + /** + * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. + * + * @return $this + */ + public function setAttendeePW(string $attendeePW): self + { + @trigger_error(sprintf('Passing a attendee password to "%s::setAttendeePW()" is deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the attendee password to create a meeting.', self::class), \E_USER_DEPRECATED); + + $this->attendeePW = $attendeePW; + + return $this; + } + + /** + * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. + */ + public function getModeratorPW(): string + { + if (null === $this->moderatorPW) { + throw new \RuntimeException(sprintf('Moderator password was not passed to "%s".', self::class)); + } + + return $this->moderatorPW; + } + + /** + * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. + * + * @return $this + */ + public function setModeratorPW(string $moderatorPW): self + { + @trigger_error(sprintf('Passing a moderator password to "%s::setModeratorPW()" is deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the moderator password to create a meeting.', self::class), \E_USER_DEPRECATED); + + $this->moderatorPW = $moderatorPW; + + return $this; + } + public function getHTTPQuery(): string { $queries = $this->getHTTPQueryArray(); diff --git a/src/Parameters/EndMeetingParameters.php b/src/Parameters/EndMeetingParameters.php index 82b19f31..ed71c605 100644 --- a/src/Parameters/EndMeetingParameters.php +++ b/src/Parameters/EndMeetingParameters.php @@ -24,8 +24,6 @@ * * @method string getMeetingID() * @method $this setMeetingID(string $id) - * @method string getPassword() - * @method $this setPassword(string $password) */ class EndMeetingParameters extends BaseParameters { @@ -35,13 +33,41 @@ class EndMeetingParameters extends BaseParameters protected $meetingID; /** - * @var string + * @var string|null */ protected $password; - public function __construct(string $meetingID, string $password) + public function __construct(string $meetingID, string $password = null) { + if (\func_num_args() === 2) { + @trigger_error(sprintf('Passing $password parameter to constructor of "%s" is deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter to end a meeting.', self::class), \E_USER_DEPRECATED); + } + $this->password = $password; $this->meetingID = $meetingID; } + + /** + * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. + */ + public function getPassword(): string + { + if (null === $this->password) { + throw new \RuntimeException(sprintf('Password was not passed to "%s".', self::class)); + } + + return $this->password; + } + + /** + * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. + * + * @return $this + */ + public function setPassword(string $password): self + { + $this->password = $password; + + return $this; + } } diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index e8ca4ddf..71a1d1d8 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -26,8 +26,6 @@ * @method $this setFullName(string $fullName) * @method string getMeetingID() * @method $this setMeetingID(string $id) - * @method string getPassword() - * @method $this setPassword(string $password) * @method string getCreateTime() * @method $this setCreateTime(string $createTime) * @method string getUserID() @@ -65,7 +63,7 @@ class JoinMeetingParameters extends UserDataParameters protected $meetingID; /** - * @var string + * @var string|null */ protected $password; @@ -109,11 +107,6 @@ class JoinMeetingParameters extends UserDataParameters */ protected $clientURL; - /** - * @var bool - */ - protected $joinViaHtml5; - /** * @var bool */ @@ -129,15 +122,43 @@ class JoinMeetingParameters extends UserDataParameters */ protected $excludeFromDashboard; - public function __construct(string $meetingID, string $fullName, string $password) + public function __construct(string $meetingID, string $fullName, string $password = null) { + if (\func_num_args() === 3) { + @trigger_error(sprintf('Passing $password parameter to constructor of "%s" is deprecated since 5.1 and will be removed in 6.0. Use "%s::setRole()" to set the designated role for the joining user instead.', self::class, self::class), \E_USER_DEPRECATED); + } + $this->meetingID = $meetingID; $this->fullName = $fullName; $this->password = $password; } /** - * @deprecated old flash client parameter, not used anymore + * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. + */ + public function getPassword(): string + { + if (null === $this->password) { + throw new \RuntimeException(sprintf('Password was not passed to "%s".', self::class)); + } + + return $this->password; + } + + /** + * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. + * + * @return $this + */ + public function setPassword(string $password): self + { + $this->password = $password; + + return $this; + } + + /** + * @deprecated since 5.1 and will be removed in 6.0. Old BigBlueButton flash client parameter. */ public function getConfigToken(): ?string { @@ -145,7 +166,9 @@ public function getConfigToken(): ?string } /** - * @deprecated old flash client parameter, not used anymore + * @deprecated since 5.1 and will be removed in 6.0. Old BigBlueButton flash client parameter. + * + * @return $this */ public function setConfigToken(string $configToken): self { diff --git a/tests/TestCase.php b/tests/TestCase.php index da641181..8bc75909 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -160,13 +160,7 @@ protected function getCreateMock($params) { $createMeetingParams = new CreateMeetingParameters($params['meetingID'], $params['name']); - foreach ($params['groups'] as $group) { - $createMeetingParams->addBreakoutRoomsGroup($group['id'], $group['name'], $group['roster']); - } - - return $createMeetingParams->setAttendeePW($params['attendeePW']) - ->setModeratorPW($params['moderatorPW']) - ->setDialNumber($params['dialNumber']) + $createMeetingParams->setDialNumber($params['dialNumber']) ->setVoiceBridge($params['voiceBridge']) ->setWebVoice($params['webVoice']) ->setLogoutURL($params['logoutURL']) @@ -213,6 +207,20 @@ protected function getCreateMock($params) ->setAllowRequestsWithoutSession($params['allowRequestsWithoutSession']) ->setVirtualBackgroundsDisabled($params['virtualBackgroundsDisabled']) ->setUserCameraCap($params['userCameraCap']); + + if (isset($params['moderatorPW'])) { + $createMeetingParams->setModeratorPW($params['moderatorPW']); + } + + if (isset($params['attendeePW'])) { + $createMeetingParams->setAttendeePW($params['attendeePW']); + } + + foreach ($params['groups'] as $group) { + $createMeetingParams->addBreakoutRoomsGroup($group['id'], $group['name'], $group['roster']); + } + + return $createMeetingParams; } /** @@ -251,7 +259,11 @@ protected function generateJoinMeetingParams() */ protected function getJoinMeetingMock($params) { - $joinMeetingParams = new JoinMeetingParameters($params['meetingID'], $params['fullName'], $params['password']); + if (isset($params['password'])) { + $joinMeetingParams = new JoinMeetingParameters($params['meetingID'], $params['fullName'], $params['password']); + } else { + $joinMeetingParams = new JoinMeetingParameters($params['meetingID'], $params['fullName']); + } return $joinMeetingParams ->setUserID($params['userID']) diff --git a/tests/unit/Parameters/CreateMeetingParametersTest.php b/tests/unit/Parameters/CreateMeetingParametersTest.php index ea17c16e..f20cab99 100644 --- a/tests/unit/Parameters/CreateMeetingParametersTest.php +++ b/tests/unit/Parameters/CreateMeetingParametersTest.php @@ -25,7 +25,7 @@ /** * Class CreateMeetingParametersTest. */ -class CreateMeetingParametersTest extends TestCase +final class CreateMeetingParametersTest extends TestCase { public function testCreateMeetingParameters() { @@ -121,7 +121,7 @@ public function testCreateBreakoutMeeting() $this->assertStringContainsString('freeJoin='.rawurlencode($createBreakoutMeetingParams->isFreeJoin() ? 'true' : 'false'), $params); } - public function testCreateBreakoutMeetingWithMissingParams() + public function testCreateBreakoutMeetingWithMissingParams(): void { $this->expectException(\RuntimeException::class); @@ -130,7 +130,7 @@ public function testCreateBreakoutMeetingWithMissingParams() $params->getHTTPQuery(); } - public function testNonExistingProperty() + public function testNonExistingProperty(): void { $this->expectException(\BadFunctionCallException::class); @@ -138,7 +138,7 @@ public function testNonExistingProperty() $params->getFoobar(); } - public function testWrongMethodName() + public function testWrongMethodName(): void { $this->expectException(\BadFunctionCallException::class); @@ -146,7 +146,7 @@ public function testWrongMethodName() $params->getname(); } - public function testGetPresentationsAsXMLWithUrl() + public function testGetPresentationsAsXMLWithUrl(): void { $params = $this->generateCreateParams(); $createMeetingParams = $this->getCreateMock($params); @@ -154,7 +154,7 @@ public function testGetPresentationsAsXMLWithUrl() $this->assertXmlStringEqualsXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'presentation_with_url.xml', $createMeetingParams->getPresentationsAsXML()); } - public function testGetPresentationsAsXMLWithUrlAndFilename() + public function testGetPresentationsAsXMLWithUrlAndFilename(): void { $params = $this->generateCreateParams(); $createMeetingParams = $this->getCreateMock($params); @@ -162,7 +162,7 @@ public function testGetPresentationsAsXMLWithUrlAndFilename() $this->assertXmlStringEqualsXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'presentation_with_filename.xml', $createMeetingParams->getPresentationsAsXML()); } - public function testGetPresentationsAsXMLWithFile() + public function testGetPresentationsAsXMLWithFile(): void { $params = $this->generateCreateParams(); $createMeetingParams = $this->getCreateMock($params); @@ -221,4 +221,30 @@ public function testGuestPolicyAskModerator(): void $this->assertSame(GuestPolicy::ASK_MODERATOR, $createMeetingParams->getGuestPolicy()); $this->assertTrue($createMeetingParams->isGuestPolicyAskModerator()); } + + /** + * @group legacy + */ + public function testCreateMeetingParametersWithoutAttendeePassword(): void + { + $params = $this->generateCreateParams(); + unset($params['attendeePW']); + $createMeetingParams = $this->getCreateMock($params); + + $this->expectException(\RuntimeException::class); + $createMeetingParams->getAttendeePW(); + } + + /** + * @group legacy + */ + public function testCreateMeetingParametersWithoutModeratorPassword(): void + { + $params = $this->generateCreateParams(); + unset($params['moderatorPW']); + $createMeetingParams = $this->getCreateMock($params); + + $this->expectException(\RuntimeException::class); + $createMeetingParams->getModeratorPW(); + } } diff --git a/tests/unit/Parameters/EndMeetingParametersTest.php b/tests/unit/Parameters/EndMeetingParametersTest.php index 2873bb0a..45e0d12b 100644 --- a/tests/unit/Parameters/EndMeetingParametersTest.php +++ b/tests/unit/Parameters/EndMeetingParametersTest.php @@ -21,9 +21,9 @@ use BigBlueButton\TestCase; -class EndMeetingParametersTest extends TestCase +final class EndMeetingParametersTest extends TestCase { - public function testEndMeetingParameters() + public function testEndMeetingParameters(): void { $endMeetingParams = new EndMeetingParameters($meetingId = $this->faker->uuid, $password = $this->faker->password()); @@ -36,4 +36,27 @@ public function testEndMeetingParameters() $this->assertEquals($newId, $endMeetingParams->getMeetingID()); $this->assertEquals($newPassword, $endMeetingParams->getPassword()); } + + /** + * @group legacy + */ + public function testEndMeetingParametersWithoutPassword(): void + { + $endMeetingParams = new EndMeetingParameters($this->faker->uuid); + + $this->expectException(\RuntimeException::class); + + $endMeetingParams->getPassword(); + } + + /** + * @group legacy + */ + public function testEndMeetingParametersWithSetPassword(): void + { + $endMeetingParams = new EndMeetingParameters($this->faker->uuid); + + $endMeetingParams->setPassword($password = $this->faker->password); + $this->assertSame($password, $endMeetingParams->getPassword()); + } } diff --git a/tests/unit/Parameters/JoinMeetingParametersTest.php b/tests/unit/Parameters/JoinMeetingParametersTest.php index 924ba035..e8e29632 100644 --- a/tests/unit/Parameters/JoinMeetingParametersTest.php +++ b/tests/unit/Parameters/JoinMeetingParametersTest.php @@ -21,9 +21,9 @@ use BigBlueButton\TestCase; -class JoinMeetingParametersTest extends TestCase +final class JoinMeetingParametersTest extends TestCase { - public function testJoinMeetingParameters() + public function testJoinMeetingParameters(): void { $params = $this->generateJoinMeetingParams(); $joinMeetingParams = $this->getJoinMeetingMock($params); @@ -46,7 +46,6 @@ public function testJoinMeetingParameters() $joinMeetingParams->setAvatarURL($avatarUrl = $this->faker->url); $joinMeetingParams->setRedirect($redirect = $this->faker->boolean(50)); $joinMeetingParams->setClientURL($clientUrl = $this->faker->url); - $joinMeetingParams->setJoinViaHtml5($joinViaHtml5 = $this->faker->boolean(50)); $joinMeetingParams->setGuest($guest = $this->faker->boolean(50)); $this->assertEquals($newId, $joinMeetingParams->getMeetingID()); $this->assertEquals($newName, $joinMeetingParams->getFullName()); @@ -55,7 +54,33 @@ public function testJoinMeetingParameters() $this->assertEquals($avatarUrl, $joinMeetingParams->getAvatarURL()); $this->assertEquals($redirect, $joinMeetingParams->isRedirect()); $this->assertEquals($clientUrl, $joinMeetingParams->getClientURL()); - $this->assertEquals($joinViaHtml5, $joinMeetingParams->isJoinViaHtml5()); $this->assertEquals($guest, $joinMeetingParams->isGuest()); } + + /** + * @group legacy + */ + public function testJoinMeetingParametersWithoutPassword(): void + { + $params = $this->generateJoinMeetingParams(); + unset($params['password']); + $joinMeetingParams = $this->getJoinMeetingMock($params); + + $this->expectException(\RuntimeException::class); + + $joinMeetingParams->getPassword(); + } + + /** + * @group legacy + */ + public function testJoinMeetingParametersWithSetPassword(): void + { + $params = $this->generateJoinMeetingParams(); + unset($params['password']); + $joinMeetingParams = $this->getJoinMeetingMock($params); + + $joinMeetingParams->setPassword($password = $this->faker->password); + $this->assertSame($password, $joinMeetingParams->getPassword()); + } } From 3d45f2af6c21a1aae8b7fb7913804358d78bb1bb Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 13 Nov 2023 04:34:25 +0100 Subject: [PATCH 13/68] Implement disabledFeatures in create API (#152) * Implement disabledFeatures in create API * Refactor * Implement disabled features exclude, update features enum * Add return type --------- Co-authored-by: Felix Jacobi --- src/Enum/Feature.php | 46 +++++++++++++++++++ src/Parameters/CreateMeetingParameters.php | 30 ++++++++++++ tests/TestCase.php | 7 ++- .../AbstractBigBlueButtonFunctionalTest.php | 23 ++-------- .../CreateMeetingParametersTest.php | 29 ++++++++++++ 5 files changed, 116 insertions(+), 19 deletions(-) create mode 100644 src/Enum/Feature.php diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php new file mode 100644 index 00000000..f3cbc6c2 --- /dev/null +++ b/src/Enum/Feature.php @@ -0,0 +1,46 @@ +. + */ + +namespace BigBlueButton\Enum; + +use MabeEnum\Enum; + +/** + * @psalm-immutable + */ +class Feature extends Enum +{ + public const BREAKOUT_ROOMS = 'breakoutRooms'; + public const CAPTIONS = 'captions'; + public const CHAT = 'chat'; + public const DOWNLOAD_PRESENTATION_WITH_ANNOTATIONS = 'downloadPresentationWithAnnotations'; + public const EXTERNAL_VIDEOS = 'externalVideos'; + public const IMPORT_PRESENTATION_WITHANNOTATIONS_FROM_BREAKOUTROOMS = 'importPresentationWithAnnotationsFromBreakoutRooms'; + public const IMPORT_SHARED_NOTES_FROM_BREAKOUTROOMS = 'importSharedNotesFromBreakoutRooms'; + public const LAYOUTS = 'layouts'; + public const LEARNING_DASHBOARD = 'learningDashboard'; + public const POLLS = 'polls'; + public const SCREENSHARE = 'screenshare'; + public const SHARED_NOTES = 'sharedNotes'; + public const VIRTUAL_BACKGROUNDS = 'virtualBackgrounds'; + public const CUSTOM_VIRTUAL_BACKGROUNDS = 'customVirtualBackgrounds'; + public const LIVE_TRANSCRIPTION = 'liveTranscription'; + public const PRESENTATION = 'presentation'; +} diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index d28b1b45..8a1530db 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -116,6 +116,10 @@ * @method $this setVirtualBackgroundsDisabled(bool $isVirtualBackgroundsDisabled) * @method int getUserCameraCap() * @method $this setUserCameraCap(int $cap) + * @method array getDisabledFeatures() + * @method $this setDisabledFeatures(array $disabledFeatures) + * @method array getDisabledFeaturesExclude() + * @method $this setDisabledFeaturesExclude(array $disabledFeaturesExclude) */ class CreateMeetingParameters extends MetaParameters { @@ -374,6 +378,16 @@ class CreateMeetingParameters extends MetaParameters */ private $breakoutRoomsGroups = []; + /** + * @var array + */ + protected $disabledFeatures = []; + + /** + * @var array + */ + protected $disabledFeaturesExclude = []; + /** * @var array */ @@ -381,6 +395,8 @@ class CreateMeetingParameters extends MetaParameters public function __construct(string $meetingID, string $name) { + $this->ignoreProperties = ['disabledFeatures', 'disabledFeaturesExclude']; + $this->meetingID = $meetingID; $this->name = $name; } @@ -595,6 +611,20 @@ public function getHTTPQuery(): string { $queries = $this->getHTTPQueryArray(); + // Add disabled features if any are set + if (!empty($this->disabledFeatures)) { + $queries = array_merge($queries, [ + 'disabledFeatures' => implode(',', $this->disabledFeatures), + ]); + } + + // Add disabled features exclude if any are set + if (!empty($this->disabledFeaturesExclude)) { + $queries = array_merge($queries, [ + 'disabledFeaturesExclude' => implode(',', $this->disabledFeaturesExclude), + ]); + } + // Pre-defined groups to automatically assign the students to a given breakout room if (!empty($this->breakoutRoomsGroups)) { $queries = array_merge($queries, [ diff --git a/tests/TestCase.php b/tests/TestCase.php index 8bc75909..406eb573 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -21,6 +21,7 @@ use BigBlueButton\Core\GuestPolicy; use BigBlueButton\Core\MeetingLayout; +use BigBlueButton\Enum\Feature; use BigBlueButton\Parameters\CreateMeetingParameters; use BigBlueButton\Parameters\EndMeetingParameters; use BigBlueButton\Parameters\JoinMeetingParameters; @@ -97,6 +98,8 @@ protected function generateCreateParams() 'lockSettingsLockOnJoinConfigurable' => $this->faker->boolean(50), 'allowModsToUnmuteUsers' => $this->faker->boolean(50), 'allowModsToEjectCameras' => $this->faker->boolean(50), + 'disabledFeatures' => $this->faker->randomElements(Feature::getValues(), 3), + 'disabledFeaturesExclude' => $this->faker->randomElements(Feature::getValues(), 2), 'meta_presenter' => $this->faker->name, 'meta_endCallbackUrl' => $this->faker->url, 'meta_bbb-recording-ready-url' => $this->faker->url, @@ -206,7 +209,9 @@ protected function getCreateMock($params) ->setBreakoutRoomsRecord($params['breakoutRoomsRecord']) ->setAllowRequestsWithoutSession($params['allowRequestsWithoutSession']) ->setVirtualBackgroundsDisabled($params['virtualBackgroundsDisabled']) - ->setUserCameraCap($params['userCameraCap']); + ->setUserCameraCap($params['userCameraCap']) + ->setDisabledFeatures($params['disabledFeatures']) + ->setDisabledFeaturesExclude($params['disabledFeaturesExclude']); if (isset($params['moderatorPW'])) { $createMeetingParams->setModeratorPW($params['moderatorPW']); diff --git a/tests/functional/AbstractBigBlueButtonFunctionalTest.php b/tests/functional/AbstractBigBlueButtonFunctionalTest.php index 3ee5be4f..3d2deafc 100644 --- a/tests/functional/AbstractBigBlueButtonFunctionalTest.php +++ b/tests/functional/AbstractBigBlueButtonFunctionalTest.php @@ -106,12 +106,8 @@ public function testCreateMeetingUrl(): void { $params = $this->generateCreateParams(); $url = $this->bbb->getCreateMeetingUrl($this->getCreateMock($params)); - foreach ($params as $key => $value) { - if (\is_bool($value)) { - $value = $value ? 'true' : 'false'; - } - $this->assertStringContainsString($key.'='.rawurlencode($value), $url); - } + + $this->assertUrlContainsAllRequestParameters($url, $params); } /** @@ -212,12 +208,7 @@ public function testCreateJoinMeetingUrl(): void $url = $this->bbb->getJoinMeetingURL($joinMeetingMock); - foreach ($joinMeetingParams as $key => $value) { - if (\is_bool($value)) { - $value = $value ? 'true' : 'false'; - } - $this->assertStringContainsString('='.rawurlencode($value), $url); - } + $this->assertUrlContainsAllRequestParameters($url, $joinMeetingParams); } public function testJoinMeeting() @@ -255,12 +246,8 @@ public function testCreateEndMeetingUrl(): void { $params = $this->generateEndMeetingParams(); $url = $this->bbb->getEndMeetingURL($this->getEndMeetingMock($params)); - foreach ($params as $key => $value) { - if (\is_bool($value)) { - $value = $value ? 'true' : 'false'; - } - $this->assertStringContainsString('='.rawurlencode($value), $url); - } + + $this->assertUrlContainsAllRequestParameters($url, $params); } public function testEndMeeting() diff --git a/tests/unit/Parameters/CreateMeetingParametersTest.php b/tests/unit/Parameters/CreateMeetingParametersTest.php index f20cab99..ea970d45 100644 --- a/tests/unit/Parameters/CreateMeetingParametersTest.php +++ b/tests/unit/Parameters/CreateMeetingParametersTest.php @@ -20,6 +20,7 @@ namespace BigBlueButton\Parameters; use BigBlueButton\Core\GuestPolicy; +use BigBlueButton\Enum\Feature; use BigBlueButton\TestCase; /** @@ -90,6 +91,8 @@ public function testCreateMeetingParameters() $this->assertEquals($params['allowRequestsWithoutSession'], $createMeetingParams->isAllowRequestsWithoutSession()); $this->assertEquals($params['virtualBackgroundsDisabled'], $createMeetingParams->isVirtualBackgroundsDisabled()); $this->assertEquals(json_encode($params['groups']), json_encode($createMeetingParams->getBreakoutRoomsGroups())); + $this->assertEquals($params['disabledFeatures'], $createMeetingParams->getDisabledFeatures()); + $this->assertEquals($params['disabledFeaturesExclude'], $createMeetingParams->getDisabledFeaturesExclude()); // Check values are empty of this is not a breakout room $this->assertNull($createMeetingParams->isBreakout()); @@ -104,6 +107,32 @@ public function testCreateMeetingParameters() $this->assertEquals($newId, $createMeetingParams->getMeetingID()); } + public function testDisabledFeatures(): void + { + $params = $this->generateCreateParams(); + $createMeetingParams = $this->getCreateMock($params); + + // Test empty disabled features + $createMeetingParams->setDisabledFeatures([]); + $params = urldecode($createMeetingParams->getHTTPQuery()); + $this->assertStringNotContainsString('disabledFeatures=', $params); + + // Test with multiple disabled features + $createMeetingParams->setDisabledFeatures([Feature::CHAT, Feature::POLLS, Feature::CAPTIONS]); + $params = urldecode($createMeetingParams->getHTTPQuery()); + $this->assertStringContainsString('disabledFeatures=chat,polls,captions', $params); + + // Test empty disabled features exclude + $createMeetingParams->setDisabledFeaturesExclude([]); + $params = urldecode($createMeetingParams->getHTTPQuery()); + $this->assertStringNotContainsString('disabledFeaturesExclude=', $params); + + // Test with multiple disabled features exclude + $createMeetingParams->setDisabledFeaturesExclude([Feature::CHAT, Feature::POLLS]); + $params = urldecode($createMeetingParams->getHTTPQuery()); + $this->assertStringContainsString('disabledFeaturesExclude=chat,polls', $params); + } + public function testCreateBreakoutMeeting() { $params = $this->generateBreakoutCreateParams($this->generateCreateParams()); From 9c8f3b79fa8d31699d830e46e9c5ab4cddd5981e Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Fri, 9 Feb 2024 11:16:52 +0100 Subject: [PATCH 14/68] Implement API changes in BBB 2.4-2.6 (#156) * Implement API changes in BBB 2.4-2.6 * Add backwards compatibility for the old method setLockSettingsDisableNote and isLockSettingsDisableNote * Fix CS and composer scripts * CS Fixer * Adjust tests * Add errorRedirectUrl join parameter * Add final to test classes --- composer.json | 6 +- src/BigBlueButton.php | 2 +- src/Core/Meeting.php | 6 +- src/Enum/Role.php | 32 ++++ src/Parameters/CreateMeetingParameters.php | 138 ++++++++++++++++-- src/Parameters/EndMeetingParameters.php | 2 +- src/Parameters/InsertDocumentParameters.php | 2 +- src/Parameters/JoinMeetingParameters.php | 22 ++- tests/TestCase.php | 11 +- .../Http/Transport/Fixtures/web/cookie.php | 2 +- .../Transport/Fixtures/web/double-newline.php | 2 +- .../Http/Transport/Fixtures/web/dump.php | 2 +- .../Http/Transport/Fixtures/web/no-cookie.php | 2 +- .../Transport/Fixtures/web/response-code.php | 2 +- tests/unit/BigBlueButtonTest.php | 2 +- .../DeleteRecordingsParametersTest.php | 2 +- .../GetMeetingInfoParametersTest.php | 2 +- .../GetRecordingTextTracksParametersTest.php | 2 +- .../GetRecordingsParametersTest.php | 2 +- .../Parameters/HooksCreateParametersTest.php | 2 +- .../Parameters/HooksDestroyParametersTest.php | 2 +- .../IsMeetingRunningParametersTest.php | 2 +- .../Parameters/JoinMeetingParametersTest.php | 31 +++- .../PublishRecordingsParametersTest.php | 2 +- .../PutRecordingTextTracksParametersTest.php | 2 +- .../UpdateRecordingsParametersTest.php | 2 +- .../unit/Responses/ApiVersionResponseTest.php | 4 +- .../Responses/CreateMeetingResponseTest.php | 4 +- .../DeleteRecordingsResponseTest.php | 4 +- .../unit/Responses/EndMeetingResponseTest.php | 4 +- .../Responses/GetMeetingInfoResponseTest.php | 6 +- .../Responses/GetMeetingsResponseTest.php | 4 +- .../Responses/GetRecordingsResponseTest.php | 4 +- .../GetRecordingsTextTracksResponseTest.php | 2 +- .../Responses/HooksCreateResponseTest.php | 4 +- .../Responses/HooksDestroyResponseTest.php | 4 +- .../unit/Responses/HooksListResponseTest.php | 4 +- .../Responses/InsertDocumentResponseTest.php | 2 +- .../IsMeetingRunningResponseTest.php | 4 +- .../Responses/JoinMeetingResponseTest.php | 4 +- .../PublishRecordingsResponseTest.php | 4 +- .../UpdateRecordingsResponseTest.php | 4 +- 42 files changed, 266 insertions(+), 80 deletions(-) create mode 100644 src/Enum/Role.php diff --git a/composer.json b/composer.json index 4384457e..699ef910 100644 --- a/composer.json +++ b/composer.json @@ -103,9 +103,9 @@ "test-functional": "tools/phpunit --testsuite=\"BigBlueButton functional test suite\" --exclude-group=functional-legacy", "cs-fix": "tools/php-cs-fixer fix --allow-risky=yes", "cs-test": "tools/php-cs-fixer fix --dry-run --allow-risky=yes", - "psalm": "psalm --threads=1", - "psalm-clear": "psalm --clear-cache && psalm --clear-global-cache", - "psalm-fix": "psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType", + "psalm": "tools/psalm --threads=1", + "psalm-clear": "tools/psalm --clear-cache && psalm --clear-global-cache", + "psalm-fix": "tools/psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType", "post-install-cmd": "tools/composer-git-hooks add --ignore-lock", "post-update-cmd": "tools/composer-git-hooks update" }, diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index 28a58434..f8c21a97 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -113,7 +113,7 @@ class BigBlueButton * * @throws ConfigException */ - public function __construct(string $baseUrl = null, string $secret = null, TransportInterface $transport = null, string $hashingAlgorithm = HashingAlgorithm::SHA_1) + public function __construct(?string $baseUrl = null, ?string $secret = null, ?TransportInterface $transport = null, string $hashingAlgorithm = HashingAlgorithm::SHA_1) { // Keeping backward compatibility with older deployed versions $this->securitySecret = $secret ?: getenv('BBB_SECURITY_SALT') ?: getenv('BBB_SECRET'); diff --git a/src/Core/Meeting.php b/src/Core/Meeting.php index 027c2baa..24a98cf7 100644 --- a/src/Core/Meeting.php +++ b/src/Core/Meeting.php @@ -20,6 +20,8 @@ namespace BigBlueButton\Core; +use BigBlueButton\Enum\Role; + /** * Class Meeting. */ @@ -324,7 +326,7 @@ public function getModerators(): array $attendees = $this->getAttendees(); $moderators = array_filter($attendees, function ($attendee) { - return $attendee->getRole() === 'MODERATOR'; + return $attendee->getRole() === Role::MODERATOR; }); return array_values($moderators); @@ -340,7 +342,7 @@ public function getViewers(): array $attendees = $this->getAttendees(); $viewers = array_filter($attendees, function ($attendee) { - return $attendee->getRole() === 'VIEWER'; + return $attendee->getRole() === Role::VIEWER; }); return array_values($viewers); diff --git a/src/Enum/Role.php b/src/Enum/Role.php new file mode 100644 index 00000000..3c3cbfb0 --- /dev/null +++ b/src/Enum/Role.php @@ -0,0 +1,32 @@ +. + */ + +namespace BigBlueButton\Enum; + +use MabeEnum\Enum; + +/** + * @psalm-immutable + */ +class Role extends Enum +{ + public const MODERATOR = 'MODERATOR'; + public const VIEWER = 'VIEWER'; +} diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index 8a1530db..bc074583 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -48,8 +48,6 @@ * @method $this setSequence(int $sequence) * @method bool|null isFreeJoin() * @method $this setFreeJoin(bool $isFreeJoin) - * @method bool|null isBreakoutRoomsEnabled() - * @method $this setBreakoutRoomsEnabled(bool $isBreakoutRoomsEnabled) * @method bool|null isBreakoutRoomsPrivateChatEnabled() * @method $this setBreakoutRoomsPrivateChatEnabled(bool $isBreakoutRoomsPrivateChatEnabled) * @method bool|null isBreakoutRoomsRecord() @@ -82,8 +80,8 @@ * @method $this setLockSettingsDisablePrivateChat(bool $isLockSettingsDisablePrivateChat) * @method bool|null isLockSettingsDisablePublicChat() * @method $this setLockSettingsDisablePublicChat(bool $isLockSettingsDisablePublicChat) - * @method bool|null isLockSettingsDisableNote() - * @method $this setLockSettingsDisableNote(bool $isLockSettingsDisableNote) + * @method bool|null isLockSettingsDisableNotes() + * @method $this setLockSettingsDisableNotes(bool $isLockSettingsDisableNotes) * @method bool|null isLockSettingsLockedLayout() * @method $this setLockSettingsLockedLayout(bool $isLockSettingsLockedLayout) * @method bool|null isLockSettingsHideUserList() @@ -104,16 +102,12 @@ * @method $this setMeetingLayout(string $meetingLayout) * @method string getMeetingEndedURL() * @method $this setMeetingEndedURL(string $meetingEndedURL) - * @method bool|null isLearningDashboardEnabled() - * @method $this setLearningDashboardEnabled(bool $isLearningDashboardEnabled) * @method int getLearningDashboardCleanupDelayInMinutes() * @method $this setLearningDashboardCleanupDelayInMinutes(int $learningDashboardCleanupDelayInMinutes) * @method bool|null isAllowModsToEjectCameras() * @method $this setAllowModsToEjectCameras(bool $isAllowModsToEjectCameras) * @method bool|null isAllowRequestsWithoutSession() * @method $this setAllowRequestsWithoutSession(bool $isAllowRequestsWithoutSession) - * @method bool|null isVirtualBackgroundsDisabled() - * @method $this setVirtualBackgroundsDisabled(bool $isVirtualBackgroundsDisabled) * @method int getUserCameraCap() * @method $this setUserCameraCap(int $cap) * @method array getDisabledFeatures() @@ -291,7 +285,7 @@ class CreateMeetingParameters extends MetaParameters /** * @var bool */ - protected $lockSettingsDisableNote; + protected $lockSettingsDisableNotes; /** * @var bool @@ -313,6 +307,11 @@ class CreateMeetingParameters extends MetaParameters */ protected $lockSettingsLockOnJoinConfigurable; + /** + * @var bool + */ + protected $lockSettingsHideViewersCursor; + /** * @var string */ @@ -388,6 +387,51 @@ class CreateMeetingParameters extends MetaParameters */ protected $disabledFeaturesExclude = []; + /** + * @var int + */ + protected $meetingCameraCap; + + /** + * @var int + */ + protected $meetingExpireIfNoUserJoinedInMinutes; + + /** + * @var int + */ + protected $meetingExpireWhenLastUserLeftInMinutes; + + /** + * @var bool + */ + protected $preUploadedPresentationOverrideDefault; + + /** + * @var bool + */ + protected $notifyRecordingIsOn; + + /** + * @var bool + */ + protected $remindRecordingIsOn; + + /** + * @var bool + */ + protected $recordFullDurationMedia; + + /** + * @var string + */ + protected $presentationUploadExternalUrl; + + /** + * @var string + */ + protected $presentationUploadExternalDescription; + /** * @var array */ @@ -427,6 +471,80 @@ public function isBreakout(): ?bool return $this->isBreakout; } + /** + * @deprecated use disabledFeatures instead + * Backwards compatibility for the old method name with the missing 's' at the end + */ + public function setLockSettingsDisableNote(bool $isLockSettingsDisableNote): self + { + $this->isLockSettingsDisableNotes = $isLockSettingsDisableNote; + + return $this; + } + + /** + * @deprecated use disabledFeatures instead + * Backwards compatibility for the old method name with the missing 's' at the end + */ + public function isLockSettingsDisableNote(): bool + { + return $this->isLockSettingsDisableNotes; + } + + /** + * @deprecated Use disabledFeatures instead + */ + public function setLearningDashboardEnabled(bool $learningDashboardEnabled): self + { + $this->learningDashboardEnabled = $learningDashboardEnabled; + + return $this; + } + + /** + * @deprecated Use disabledFeatures instead + */ + public function isLearningDashboardEnabled(): bool + { + return $this->learningDashboardEnabled; + } + + /** + * @deprecated Use disabledFeatures instead + */ + public function setVirtualBackgroundsDisabled(bool $virtualBackgroundsDisabled): self + { + $this->virtualBackgroundsDisabled = $virtualBackgroundsDisabled; + + return $this; + } + + /** + * @deprecated Use disabledFeatures instead + */ + public function isVirtualBackgroundsDisabled(): bool + { + return $this->virtualBackgroundsDisabled; + } + + /** + * @deprecated Use disabledFeatures instead + */ + public function setBreakoutRoomsEnabled(bool $breakoutRoomsEnabled): self + { + $this->breakoutRoomsEnabled = $breakoutRoomsEnabled; + + return $this; + } + + /** + * @deprecated Use disabledFeatures instead + */ + public function isBreakoutRoomsEnabled(): bool + { + return $this->breakoutRoomsEnabled; + } + public function isUserCameraCapDisabled(): bool { return $this->userCameraCap === 0; @@ -493,7 +611,7 @@ public function setGuestPolicyAlwaysAccept(): self return $this; } - public function addPresentation(string $nameOrUrl, string $content = null, string $filename = null): self + public function addPresentation(string $nameOrUrl, ?string $content = null, ?string $filename = null): self { if (!$filename) { $this->presentations[$nameOrUrl] = !$content ?: base64_encode($content); diff --git a/src/Parameters/EndMeetingParameters.php b/src/Parameters/EndMeetingParameters.php index ed71c605..c2e23366 100644 --- a/src/Parameters/EndMeetingParameters.php +++ b/src/Parameters/EndMeetingParameters.php @@ -37,7 +37,7 @@ class EndMeetingParameters extends BaseParameters */ protected $password; - public function __construct(string $meetingID, string $password = null) + public function __construct(string $meetingID, ?string $password = null) { if (\func_num_args() === 2) { @trigger_error(sprintf('Passing $password parameter to constructor of "%s" is deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter to end a meeting.', self::class), \E_USER_DEPRECATED); diff --git a/src/Parameters/InsertDocumentParameters.php b/src/Parameters/InsertDocumentParameters.php index 7140c447..cf3c894b 100644 --- a/src/Parameters/InsertDocumentParameters.php +++ b/src/Parameters/InsertDocumentParameters.php @@ -42,7 +42,7 @@ public function __construct(string $meetingID) $this->meetingID = $meetingID; } - public function addPresentation(string $url, string $filename, bool $downloadable = null, bool $removable = null): self + public function addPresentation(string $url, string $filename, ?bool $downloadable = null, ?bool $removable = null): self { $this->presentations[$url] = [ 'filename' => $filename, diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index 71a1d1d8..6417f22f 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -19,6 +19,8 @@ namespace BigBlueButton\Parameters; +use BigBlueButton\Enum\Role; + /** * Class JoinMeetingParametersTest. * @@ -38,6 +40,8 @@ * @method $this setAvatarURL(string $avatarURL) * @method bool|null isRedirect() * @method $this setRedirect(bool $redirect) + * @method string getErrorRedirectUrl() + * @method $this setErrorRedirectUrl(string $errorRedirectUrl) * @method string getClientURL() * @method $this setClientURL(string $clientURL) * @method bool|null isGuest() @@ -102,6 +106,11 @@ class JoinMeetingParameters extends UserDataParameters */ protected $redirect; + /** + * @var string + */ + protected $errorRedirectUrl; + /** * @var string */ @@ -122,15 +131,20 @@ class JoinMeetingParameters extends UserDataParameters */ protected $excludeFromDashboard; - public function __construct(string $meetingID, string $fullName, string $password = null) + public function __construct(string $meetingID, string $fullName, $passwordOrRole) { - if (\func_num_args() === 3) { - @trigger_error(sprintf('Passing $password parameter to constructor of "%s" is deprecated since 5.1 and will be removed in 6.0. Use "%s::setRole()" to set the designated role for the joining user instead.', self::class, self::class), \E_USER_DEPRECATED); + if (!$passwordOrRole instanceof Role) { + @trigger_error(sprintf('Passing a password as the third parameter to constructor of "%s" is deprecated since 5.1 and will be removed in 6.0. Pass the role for the joining user instead.', self::class, self::class), \E_USER_DEPRECATED); } $this->meetingID = $meetingID; $this->fullName = $fullName; - $this->password = $password; + + if (Role::MODERATOR === $passwordOrRole || Role::VIEWER === $passwordOrRole) { + $this->role = $passwordOrRole; + } else { + $this->password = $passwordOrRole; + } } /** diff --git a/tests/TestCase.php b/tests/TestCase.php index 406eb573..9696c4c4 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -22,6 +22,7 @@ use BigBlueButton\Core\GuestPolicy; use BigBlueButton\Core\MeetingLayout; use BigBlueButton\Enum\Feature; +use BigBlueButton\Enum\Role; use BigBlueButton\Parameters\CreateMeetingParameters; use BigBlueButton\Parameters\EndMeetingParameters; use BigBlueButton\Parameters\JoinMeetingParameters; @@ -246,11 +247,12 @@ protected function generateJoinMeetingParams() { return ['meetingID' => $this->faker->uuid, 'fullName' => $this->faker->name, - 'password' => $this->faker->password, + 'role' => $this->faker->randomElement(Role::getValues()), 'userID' => $this->faker->numberBetween(1, 1000), 'webVoiceConf' => $this->faker->word, 'createTime' => $this->faker->unixTime, 'configToken' => $this->faker->word, + 'errorRedirectUrl' => $this->faker->url, 'userdata-countrycode' => $this->faker->countryCode, 'userdata-email' => $this->faker->email, 'userdata-commercial' => false, @@ -264,16 +266,13 @@ protected function generateJoinMeetingParams() */ protected function getJoinMeetingMock($params) { - if (isset($params['password'])) { - $joinMeetingParams = new JoinMeetingParameters($params['meetingID'], $params['fullName'], $params['password']); - } else { - $joinMeetingParams = new JoinMeetingParameters($params['meetingID'], $params['fullName']); - } + $joinMeetingParams = new JoinMeetingParameters($params['meetingID'], $params['fullName'], $params['role']); return $joinMeetingParams ->setUserID($params['userID']) ->setWebVoiceConf($params['webVoiceConf']) ->setCreateTime($params['createTime']) + ->setErrorRedirectUrl($params['errorRedirectUrl']) ->setConfigToken($params['configToken']) ->addUserData('countrycode', $params['userdata-countrycode']) ->addUserData('email', $params['userdata-email']) diff --git a/tests/integration/Http/Transport/Fixtures/web/cookie.php b/tests/integration/Http/Transport/Fixtures/web/cookie.php index 51858fc3..d808ab0b 100644 --- a/tests/integration/Http/Transport/Fixtures/web/cookie.php +++ b/tests/integration/Http/Transport/Fixtures/web/cookie.php @@ -20,7 +20,7 @@ */ if ('cli-server' !== \PHP_SAPI) { // safe guard against unwanted execution - throw new \Exception("You cannot run this script directly, it's a fixture for TestHttpServer."); + throw new Exception("You cannot run this script directly, it's a fixture for TestHttpServer."); } setcookie('JSESSIONID', 'Monkey'); diff --git a/tests/integration/Http/Transport/Fixtures/web/double-newline.php b/tests/integration/Http/Transport/Fixtures/web/double-newline.php index 2a1e4999..bbc5f7fa 100644 --- a/tests/integration/Http/Transport/Fixtures/web/double-newline.php +++ b/tests/integration/Http/Transport/Fixtures/web/double-newline.php @@ -20,7 +20,7 @@ */ if ('cli-server' !== \PHP_SAPI) { // safe guard against unwanted execution - throw new \Exception("You cannot run this script directly, it's a fixture for TestHttpServer."); + throw new Exception("You cannot run this script directly, it's a fixture for TestHttpServer."); } echo "Foo\r\n\r\n"; diff --git a/tests/integration/Http/Transport/Fixtures/web/dump.php b/tests/integration/Http/Transport/Fixtures/web/dump.php index a74efeaa..19be4420 100644 --- a/tests/integration/Http/Transport/Fixtures/web/dump.php +++ b/tests/integration/Http/Transport/Fixtures/web/dump.php @@ -29,7 +29,7 @@ if ('cli-server' !== \PHP_SAPI) { // safe guard against unwanted execution - throw new \Exception("You cannot run this script directly, it's a fixture for TestHttpServer."); + throw new Exception("You cannot run this script directly, it's a fixture for TestHttpServer."); } $vars = []; diff --git a/tests/integration/Http/Transport/Fixtures/web/no-cookie.php b/tests/integration/Http/Transport/Fixtures/web/no-cookie.php index 553afb62..6dae060f 100644 --- a/tests/integration/Http/Transport/Fixtures/web/no-cookie.php +++ b/tests/integration/Http/Transport/Fixtures/web/no-cookie.php @@ -20,7 +20,7 @@ */ if ('cli-server' !== \PHP_SAPI) { // safe guard against unwanted execution - throw new \Exception("You cannot run this script directly, it's a fixture for TestHttpServer."); + throw new Exception("You cannot run this script directly, it's a fixture for TestHttpServer."); } echo 'Hello from the other side!'; diff --git a/tests/integration/Http/Transport/Fixtures/web/response-code.php b/tests/integration/Http/Transport/Fixtures/web/response-code.php index e09e412d..bfc48b46 100644 --- a/tests/integration/Http/Transport/Fixtures/web/response-code.php +++ b/tests/integration/Http/Transport/Fixtures/web/response-code.php @@ -20,7 +20,7 @@ */ if ('cli-server' !== \PHP_SAPI) { // safe guard against unwanted execution - throw new \Exception("You cannot run this script directly, it's a fixture for TestHttpServer."); + throw new Exception("You cannot run this script directly, it's a fixture for TestHttpServer."); } http_response_code((int) ($_GET['code'] ?? 200)); diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index b2c0c549..e1381f5d 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -37,7 +37,7 @@ /** * Class BigBlueButtonTest. */ -class BigBlueButtonTest extends TestCase +final class BigBlueButtonTest extends TestCase { /** @var MockObject */ private $transport; diff --git a/tests/unit/Parameters/DeleteRecordingsParametersTest.php b/tests/unit/Parameters/DeleteRecordingsParametersTest.php index b183b1af..449ddea9 100644 --- a/tests/unit/Parameters/DeleteRecordingsParametersTest.php +++ b/tests/unit/Parameters/DeleteRecordingsParametersTest.php @@ -21,7 +21,7 @@ use BigBlueButton\TestCase; -class DeleteRecordingsParametersTest extends TestCase +final class DeleteRecordingsParametersTest extends TestCase { public function testDeleteRecordingParameter() { diff --git a/tests/unit/Parameters/GetMeetingInfoParametersTest.php b/tests/unit/Parameters/GetMeetingInfoParametersTest.php index 192f3205..16ada01a 100644 --- a/tests/unit/Parameters/GetMeetingInfoParametersTest.php +++ b/tests/unit/Parameters/GetMeetingInfoParametersTest.php @@ -21,7 +21,7 @@ use BigBlueButton\TestCase; -class GetMeetingInfoParametersTest extends TestCase +final class GetMeetingInfoParametersTest extends TestCase { public function testGetMeetingInfoParameters() { diff --git a/tests/unit/Parameters/GetRecordingTextTracksParametersTest.php b/tests/unit/Parameters/GetRecordingTextTracksParametersTest.php index ae46c8d5..c230b8ac 100644 --- a/tests/unit/Parameters/GetRecordingTextTracksParametersTest.php +++ b/tests/unit/Parameters/GetRecordingTextTracksParametersTest.php @@ -22,7 +22,7 @@ use BigBlueButton\TestCase; -class GetRecordingTextTracksParametersTest extends TestCase +final class GetRecordingTextTracksParametersTest extends TestCase { public function testGetRecordingTextTracksParameters() { diff --git a/tests/unit/Parameters/GetRecordingsParametersTest.php b/tests/unit/Parameters/GetRecordingsParametersTest.php index 355c5500..21cfa985 100644 --- a/tests/unit/Parameters/GetRecordingsParametersTest.php +++ b/tests/unit/Parameters/GetRecordingsParametersTest.php @@ -21,7 +21,7 @@ use BigBlueButton\TestCase; -class GetRecordingsParametersTest extends TestCase +final class GetRecordingsParametersTest extends TestCase { public function testGetRecordingsParameters() { diff --git a/tests/unit/Parameters/HooksCreateParametersTest.php b/tests/unit/Parameters/HooksCreateParametersTest.php index 97769273..fb194cca 100644 --- a/tests/unit/Parameters/HooksCreateParametersTest.php +++ b/tests/unit/Parameters/HooksCreateParametersTest.php @@ -21,7 +21,7 @@ use BigBlueButton\TestCase; -class HooksCreateParametersTest extends TestCase +final class HooksCreateParametersTest extends TestCase { public function testHooksCreateParameters() { diff --git a/tests/unit/Parameters/HooksDestroyParametersTest.php b/tests/unit/Parameters/HooksDestroyParametersTest.php index c3e5eddb..b1907721 100644 --- a/tests/unit/Parameters/HooksDestroyParametersTest.php +++ b/tests/unit/Parameters/HooksDestroyParametersTest.php @@ -21,7 +21,7 @@ use BigBlueButton\TestCase; -class HooksDestroyParametersTest extends TestCase +final class HooksDestroyParametersTest extends TestCase { public function testHooksDestroyParameters(): void { diff --git a/tests/unit/Parameters/IsMeetingRunningParametersTest.php b/tests/unit/Parameters/IsMeetingRunningParametersTest.php index 9e89b286..90f28352 100644 --- a/tests/unit/Parameters/IsMeetingRunningParametersTest.php +++ b/tests/unit/Parameters/IsMeetingRunningParametersTest.php @@ -24,7 +24,7 @@ /** * Class IsMeetingRunningParametersTest. */ -class IsMeetingRunningParametersTest extends TestCase +final class IsMeetingRunningParametersTest extends TestCase { public function testIsMeetingRunningParameters() { diff --git a/tests/unit/Parameters/JoinMeetingParametersTest.php b/tests/unit/Parameters/JoinMeetingParametersTest.php index e8e29632..b91aeb4f 100644 --- a/tests/unit/Parameters/JoinMeetingParametersTest.php +++ b/tests/unit/Parameters/JoinMeetingParametersTest.php @@ -19,6 +19,7 @@ namespace BigBlueButton\Parameters; +use BigBlueButton\Enum\Role; use BigBlueButton\TestCase; final class JoinMeetingParametersTest extends TestCase @@ -26,14 +27,16 @@ final class JoinMeetingParametersTest extends TestCase public function testJoinMeetingParameters(): void { $params = $this->generateJoinMeetingParams(); + $params['role'] = Role::MODERATOR; $joinMeetingParams = $this->getJoinMeetingMock($params); $this->assertEquals($params['meetingID'], $joinMeetingParams->getMeetingID()); $this->assertEquals($params['fullName'], $joinMeetingParams->getFullName()); - $this->assertEquals($params['password'], $joinMeetingParams->getPassword()); + $this->assertEquals($params['role'], $joinMeetingParams->getRole()); $this->assertEquals($params['userID'], $joinMeetingParams->getUserID()); $this->assertEquals($params['webVoiceConf'], $joinMeetingParams->getWebVoiceConf()); $this->assertEquals($params['createTime'], $joinMeetingParams->getCreateTime()); + $this->assertEquals($params['errorRedirectUrl'], $joinMeetingParams->getErrorRedirectUrl()); $this->assertEquals($params['userdata-countrycode'], $joinMeetingParams->getUserData('countrycode')); $this->assertEquals($params['userdata-email'], $joinMeetingParams->getUserData('email')); $this->assertEquals($params['userdata-commercial'], $joinMeetingParams->getUserData('commercial')); @@ -41,29 +44,31 @@ public function testJoinMeetingParameters(): void // Test setters that are ignored by the constructor $joinMeetingParams->setMeetingID($newId = $this->faker->uuid); $joinMeetingParams->setFullName($newName = $this->faker->name); - $joinMeetingParams->setPassword($newPassword = $this->faker->password); + $joinMeetingParams->setRole($newRole = Role::VIEWER); $joinMeetingParams->setConfigToken($configToken = $this->faker->md5); $joinMeetingParams->setAvatarURL($avatarUrl = $this->faker->url); $joinMeetingParams->setRedirect($redirect = $this->faker->boolean(50)); $joinMeetingParams->setClientURL($clientUrl = $this->faker->url); + $joinMeetingParams->setErrorRedirectUrl($newErrorRedirectUrl = $this->faker->url); $joinMeetingParams->setGuest($guest = $this->faker->boolean(50)); $this->assertEquals($newId, $joinMeetingParams->getMeetingID()); $this->assertEquals($newName, $joinMeetingParams->getFullName()); - $this->assertEquals($newPassword, $joinMeetingParams->getPassword()); + $this->assertEquals($newRole, $joinMeetingParams->getRole()); $this->assertEquals($configToken, $joinMeetingParams->getConfigToken()); $this->assertEquals($avatarUrl, $joinMeetingParams->getAvatarURL()); $this->assertEquals($redirect, $joinMeetingParams->isRedirect()); $this->assertEquals($clientUrl, $joinMeetingParams->getClientURL()); + $this->assertEquals($newErrorRedirectUrl, $joinMeetingParams->getErrorRedirectUrl()); $this->assertEquals($guest, $joinMeetingParams->isGuest()); } /** * @group legacy + * Using the deprecated getPassword method, without setting the password in the constructor or using the setPassword method */ public function testJoinMeetingParametersWithoutPassword(): void { $params = $this->generateJoinMeetingParams(); - unset($params['password']); $joinMeetingParams = $this->getJoinMeetingMock($params); $this->expectException(\RuntimeException::class); @@ -73,11 +78,27 @@ public function testJoinMeetingParametersWithoutPassword(): void /** * @group legacy + * Using the deprecated getPassword method, with passing the password in the constructor + */ + public function testJoinMeetingParametersWithPassword(): void + { + $params = $this->generateJoinMeetingParams(); + // Legacy, allow users to pass a password as the third constructor parameter + $params['role'] = $this->faker->password; + $joinMeetingParams = $this->getJoinMeetingMock($params); + + // Check if the password is set and the role is null + $this->assertSame($params['role'], $joinMeetingParams->getPassword()); + $this->assertNull($joinMeetingParams->getRole()); + } + + /** + * @group legacy + * Using the deprecated getPassword method, with using the setPassword method */ public function testJoinMeetingParametersWithSetPassword(): void { $params = $this->generateJoinMeetingParams(); - unset($params['password']); $joinMeetingParams = $this->getJoinMeetingMock($params); $joinMeetingParams->setPassword($password = $this->faker->password); diff --git a/tests/unit/Parameters/PublishRecordingsParametersTest.php b/tests/unit/Parameters/PublishRecordingsParametersTest.php index 3abfdf13..c9fde0f4 100644 --- a/tests/unit/Parameters/PublishRecordingsParametersTest.php +++ b/tests/unit/Parameters/PublishRecordingsParametersTest.php @@ -21,7 +21,7 @@ use BigBlueButton\TestCase; -class PublishRecordingsParametersTest extends TestCase +final class PublishRecordingsParametersTest extends TestCase { public function testPublishRecordingsParameters() { diff --git a/tests/unit/Parameters/PutRecordingTextTracksParametersTest.php b/tests/unit/Parameters/PutRecordingTextTracksParametersTest.php index 454cdffb..a43edf17 100644 --- a/tests/unit/Parameters/PutRecordingTextTracksParametersTest.php +++ b/tests/unit/Parameters/PutRecordingTextTracksParametersTest.php @@ -22,7 +22,7 @@ use BigBlueButton\TestCase; -class PutRecordingTextTracksParametersTest extends TestCase +final class PutRecordingTextTracksParametersTest extends TestCase { public function testPutRecordingTextTracksParameters() { diff --git a/tests/unit/Parameters/UpdateRecordingsParametersTest.php b/tests/unit/Parameters/UpdateRecordingsParametersTest.php index ad36c198..e9baf7a0 100644 --- a/tests/unit/Parameters/UpdateRecordingsParametersTest.php +++ b/tests/unit/Parameters/UpdateRecordingsParametersTest.php @@ -21,7 +21,7 @@ use BigBlueButton\TestCase; -class UpdateRecordingsParametersTest extends TestCase +final class UpdateRecordingsParametersTest extends TestCase { public function testUpdateRecordingsParameters() { diff --git a/tests/unit/Responses/ApiVersionResponseTest.php b/tests/unit/Responses/ApiVersionResponseTest.php index 7f59a122..ec0ac72f 100644 --- a/tests/unit/Responses/ApiVersionResponseTest.php +++ b/tests/unit/Responses/ApiVersionResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\ApiVersionResponse; use BigBlueButton\TestCase; -class ApiVersionResponseTest extends TestCase +final class ApiVersionResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\ApiVersionResponse + * @var ApiVersionResponse */ private $version; diff --git a/tests/unit/Responses/CreateMeetingResponseTest.php b/tests/unit/Responses/CreateMeetingResponseTest.php index 84198494..5c7369ab 100644 --- a/tests/unit/Responses/CreateMeetingResponseTest.php +++ b/tests/unit/Responses/CreateMeetingResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\CreateMeetingResponse; use BigBlueButton\TestCase; -class CreateMeetingResponseTest extends TestCase +final class CreateMeetingResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\CreateMeetingResponse + * @var CreateMeetingResponse */ private $meeting; diff --git a/tests/unit/Responses/DeleteRecordingsResponseTest.php b/tests/unit/Responses/DeleteRecordingsResponseTest.php index ae7416f5..b7594fc2 100644 --- a/tests/unit/Responses/DeleteRecordingsResponseTest.php +++ b/tests/unit/Responses/DeleteRecordingsResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\DeleteRecordingsResponse; use BigBlueButton\TestCase; -class DeleteRecordingsResponseTest extends TestCase +final class DeleteRecordingsResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\DeleteRecordingsResponse + * @var DeleteRecordingsResponse */ private $delete; diff --git a/tests/unit/Responses/EndMeetingResponseTest.php b/tests/unit/Responses/EndMeetingResponseTest.php index 37ecefb9..16a72a27 100644 --- a/tests/unit/Responses/EndMeetingResponseTest.php +++ b/tests/unit/Responses/EndMeetingResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\EndMeetingResponse; use BigBlueButton\TestCase; -class EndMeetingResponseTest extends TestCase +final class EndMeetingResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\EndMeetingResponse + * @var EndMeetingResponse */ private $end; diff --git a/tests/unit/Responses/GetMeetingInfoResponseTest.php b/tests/unit/Responses/GetMeetingInfoResponseTest.php index c6cf2696..daae09c6 100644 --- a/tests/unit/Responses/GetMeetingInfoResponseTest.php +++ b/tests/unit/Responses/GetMeetingInfoResponseTest.php @@ -17,10 +17,10 @@ * You should have received a copy of the GNU Lesser General Public License along * with BigBlueButton; if not, see . */ -class GetMeetingInfoResponseTest extends \BigBlueButton\TestCase +final class GetMeetingInfoResponseTest extends BigBlueButton\TestCase { /** - * @var \BigBlueButton\Responses\GetMeetingInfoResponse + * @var BigBlueButton\Responses\GetMeetingInfoResponse */ private $meetingInfo; @@ -30,7 +30,7 @@ protected function setUp(): void $xml = $this->loadXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'get_meeting_info.xml'); - $this->meetingInfo = new \BigBlueButton\Responses\GetMeetingInfoResponse($xml); + $this->meetingInfo = new BigBlueButton\Responses\GetMeetingInfoResponse($xml); } public function testGetMeetingInfoResponseContent() diff --git a/tests/unit/Responses/GetMeetingsResponseTest.php b/tests/unit/Responses/GetMeetingsResponseTest.php index 2f77ce3d..8787b794 100644 --- a/tests/unit/Responses/GetMeetingsResponseTest.php +++ b/tests/unit/Responses/GetMeetingsResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\GetMeetingsResponse; use BigBlueButton\TestCase; -class GetMeetingsResponseTest extends TestCase +final class GetMeetingsResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\GetMeetingsResponse + * @var GetMeetingsResponse */ private $meetings; diff --git a/tests/unit/Responses/GetRecordingsResponseTest.php b/tests/unit/Responses/GetRecordingsResponseTest.php index 85dfcd4e..7e069168 100644 --- a/tests/unit/Responses/GetRecordingsResponseTest.php +++ b/tests/unit/Responses/GetRecordingsResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\GetRecordingsResponse; use BigBlueButton\TestCase; -class GetRecordingsResponseTest extends TestCase +final class GetRecordingsResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\GetRecordingsResponse + * @var GetRecordingsResponse */ private $records; diff --git a/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php b/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php index eb660884..7d9fd526 100644 --- a/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php +++ b/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php @@ -5,7 +5,7 @@ use BigBlueButton\Responses\GetRecordingTextTracksResponse; use BigBlueButton\TestCase; -class GetRecordingsTextTracksResponseTest extends TestCase +final class GetRecordingsTextTracksResponseTest extends TestCase { /** * @var GetRecordingTextTracksResponse diff --git a/tests/unit/Responses/HooksCreateResponseTest.php b/tests/unit/Responses/HooksCreateResponseTest.php index 440e5965..97de3944 100644 --- a/tests/unit/Responses/HooksCreateResponseTest.php +++ b/tests/unit/Responses/HooksCreateResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\HooksCreateResponse; use BigBlueButton\TestCase; -class HooksCreateResponseTest extends TestCase +final class HooksCreateResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\HooksCreateResponse + * @var HooksCreateResponse */ private $createResponse; diff --git a/tests/unit/Responses/HooksDestroyResponseTest.php b/tests/unit/Responses/HooksDestroyResponseTest.php index 0e0eb047..3e1d252d 100644 --- a/tests/unit/Responses/HooksDestroyResponseTest.php +++ b/tests/unit/Responses/HooksDestroyResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\HooksDestroyResponse; use BigBlueButton\TestCase; -class HooksDestroyResponseTest extends TestCase +final class HooksDestroyResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\HooksDestroyResponse + * @var HooksDestroyResponse */ private $destroyResponse; diff --git a/tests/unit/Responses/HooksListResponseTest.php b/tests/unit/Responses/HooksListResponseTest.php index ea3d2745..0ea9a572 100644 --- a/tests/unit/Responses/HooksListResponseTest.php +++ b/tests/unit/Responses/HooksListResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\HooksListResponse; use BigBlueButton\TestCase; -class HooksListResponseTest extends TestCase +final class HooksListResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\HooksListResponse + * @var HooksListResponse */ private $listResponse; diff --git a/tests/unit/Responses/InsertDocumentResponseTest.php b/tests/unit/Responses/InsertDocumentResponseTest.php index bf9dc225..da69dbd4 100644 --- a/tests/unit/Responses/InsertDocumentResponseTest.php +++ b/tests/unit/Responses/InsertDocumentResponseTest.php @@ -24,7 +24,7 @@ use BigBlueButton\Responses\InsertDocumentResponse; use BigBlueButton\TestCase; -class InsertDocumentResponseTest extends TestCase +final class InsertDocumentResponseTest extends TestCase { /** * @var \BigBlueButton\Responses\IsMeetingRunningResponse diff --git a/tests/unit/Responses/IsMeetingRunningResponseTest.php b/tests/unit/Responses/IsMeetingRunningResponseTest.php index 5e4a2f89..874964f4 100644 --- a/tests/unit/Responses/IsMeetingRunningResponseTest.php +++ b/tests/unit/Responses/IsMeetingRunningResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\IsMeetingRunningResponse; use BigBlueButton\TestCase; -class IsMeetingRunningResponseTest extends TestCase +final class IsMeetingRunningResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\IsMeetingRunningResponse + * @var IsMeetingRunningResponse */ private $running; diff --git a/tests/unit/Responses/JoinMeetingResponseTest.php b/tests/unit/Responses/JoinMeetingResponseTest.php index 0178dd55..3ad928ff 100644 --- a/tests/unit/Responses/JoinMeetingResponseTest.php +++ b/tests/unit/Responses/JoinMeetingResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\JoinMeetingResponse; use BigBlueButton\TestCase; -class JoinMeetingResponseTest extends TestCase +final class JoinMeetingResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\JoinMeetingResponse + * @var JoinMeetingResponse */ private $joinMeeting; diff --git a/tests/unit/Responses/PublishRecordingsResponseTest.php b/tests/unit/Responses/PublishRecordingsResponseTest.php index 105a6792..6155ea52 100644 --- a/tests/unit/Responses/PublishRecordingsResponseTest.php +++ b/tests/unit/Responses/PublishRecordingsResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\PublishRecordingsResponse; use BigBlueButton\TestCase; -class PublishRecordingsResponseTest extends TestCase +final class PublishRecordingsResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\PublishRecordingsResponse + * @var PublishRecordingsResponse */ private $publish; diff --git a/tests/unit/Responses/UpdateRecordingsResponseTest.php b/tests/unit/Responses/UpdateRecordingsResponseTest.php index 76e61026..b45bc570 100644 --- a/tests/unit/Responses/UpdateRecordingsResponseTest.php +++ b/tests/unit/Responses/UpdateRecordingsResponseTest.php @@ -22,10 +22,10 @@ use BigBlueButton\Responses\UpdateRecordingsResponse; use BigBlueButton\TestCase; -class UpdateRecordingsResponseTest extends TestCase +final class UpdateRecordingsResponseTest extends TestCase { /** - * @var \BigBlueButton\Responses\UpdateRecordingsResponse + * @var UpdateRecordingsResponse */ private $update; From c0ae493d58b3beb2d19274c7f7beb54633d8413f Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Fri, 9 Feb 2024 11:19:09 +0100 Subject: [PATCH 15/68] Fix CI not running for experimental versions (#165) * Fix CI not running for experimental versions * Add latest PHP Versions * Fix syntax --------- Co-authored-by: Felix Jacobi --- .github/workflows/ci.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b7a907fb..4ba2bd9d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: run: composer install --dev --no-interaction - name: Execute tests without coverage run: tools/phpunit --testsuite="BigBlueButton unit test suite,BigBlueButton integration test suite" - + PHP: name: PHP ${{ matrix.php-versions }} runs-on: ubuntu-latest @@ -42,7 +42,10 @@ jobs: include: - php-versions: '8.1' experimental: true - + - php-versions: '8.2' + experimental: true + - php-versions: '8.3' + experimental: true steps: - name: Checkout uses: actions/checkout@v2 @@ -65,7 +68,7 @@ jobs: tools/phpunit --coverage-clover=build/logs/coverage.xml --testsuite="BigBlueButton unit test suite,BigBlueButton integration test suite" - name: Execute tests without coverage if: ${{ matrix.experimental }} - run: tools/phpunit --testsuite="BigBlueButton test suite" + run: tools/phpunit --testsuite="BigBlueButton unit test suite,BigBlueButton integration test suite" continue-on-error: true - name: Coveralls env: From 9b2af356f6fd5f368673da278725acd79a52e57c Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Fri, 9 Feb 2024 14:42:15 +0100 Subject: [PATCH 16/68] Fix missing docs for new methods (#167) --- src/Parameters/CreateMeetingParameters.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index bc074583..32212db1 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -40,6 +40,12 @@ * @method $this setLogoutURL(string $logoutURL) * @method bool|null isRecord() * @method $this setRecord(bool $isRecord) + * @method bool|null isNotifyRecordingIsOn() + * @method $this setNotifyRecordingIsOn(bool $isNotifyRecordingIsOn) + * @method bool|null isRemindRecordingIsOn() + * @method $this setRemindRecordingIsOn(bool $remindRecordingIsOn) + * @method bool|null isRecordFullDurationMedia() + * @method $this setRecordFullDurationMedia(bool $recordFullDurationMedia) * @method int getDuration() * @method $this setDuration(int $duration) * @method string getParentMeetingID() @@ -90,6 +96,8 @@ * @method $this setLockSettingsLockOnJoin(bool $isLockSettingsLockOnJoin) * @method bool|null isLockSettingsLockOnJoinConfigurable() * @method $this setLockSettingsLockOnJoinConfigurable(bool $isLockSettingsLockOnJoinConfigurable) + * @method $this setLockSettingsHideViewersCursor(bool $isLockSettingsHideViewersCursor) + * @method bool|null isLockSettingsHideViewersCursor() * @method string getGuestPolicy() * @method $this setGuestPolicy(string $guestPolicy) * @method bool|null isMeetingKeepEvents() @@ -98,6 +106,10 @@ * @method $this setEndWhenNoModerator(bool $isEndWhenNoModerator) * @method int getEndWhenNoModeratorDelayInMinutes() * @method $this setEndWhenNoModeratorDelayInMinutes(int $endWhenNoModeratorDelayInMinutes) + * @method int getMeetingExpireIfNoUserJoinedInMinutes() + * @method $this setMeetingExpireIfNoUserJoinedInMinutes(int $meetingExpireIfNoUserJoinedInMinutes) + * @method int getMeetingExpireWhenLastUserLeftInMinutes() + * @method $this setMeetingExpireWhenLastUserLeftInMinutes(int $meetingExpireWhenLastUserLeftInMinutes) * @method string getMeetingLayout() * @method $this setMeetingLayout(string $meetingLayout) * @method string getMeetingEndedURL() @@ -110,10 +122,18 @@ * @method $this setAllowRequestsWithoutSession(bool $isAllowRequestsWithoutSession) * @method int getUserCameraCap() * @method $this setUserCameraCap(int $cap) + * @method int getMeetingCameraCap() + * @method $this setMeetingCameraCap(int $cap) * @method array getDisabledFeatures() * @method $this setDisabledFeatures(array $disabledFeatures) * @method array getDisabledFeaturesExclude() * @method $this setDisabledFeaturesExclude(array $disabledFeaturesExclude) + * @method string getPreUploadedPresentationOverrideDefault() + * @method $this setPreUploadedPresentationOverrideDefault(string $preUploadedPresentationOverrideDefault) + * @method string getPresentationUploadExternalUrl() + * @method $this setPresentationUploadExternalUrl(string $presentationUploadExternalUrl) + * @method string getPresentationUploadExternalDescription() + * @method $this setPresentationUploadExternalDescription(string $presentationUploadExternalDescription) */ class CreateMeetingParameters extends MetaParameters { From acb0b42da199ba24479fd62f8c67cbf4d3988888 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:49:19 +0100 Subject: [PATCH 17/68] Add new 2.7 features (#169) * Add new features * Fix casing, deprecate old consts * Fix wrong docs type * Add new 2.7 parameters * Revert casing changes and deprecations --- src/Enum/Feature.php | 5 +++++ src/Parameters/CreateMeetingParameters.php | 18 ++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php index f3cbc6c2..13ec6113 100644 --- a/src/Enum/Feature.php +++ b/src/Enum/Feature.php @@ -43,4 +43,9 @@ class Feature extends Enum public const CUSTOM_VIRTUAL_BACKGROUNDS = 'customVirtualBackgrounds'; public const LIVE_TRANSCRIPTION = 'liveTranscription'; public const PRESENTATION = 'presentation'; + public const CAMERA_AS_CONTENT = 'cameraAsContent'; + public const SNAPSHOT_OF_CURRENT_SLIDE = 'snapshotOfCurrentSlide'; + public const DOWNLOAD_PRESENTATION_ORIGINAL_FILE = 'downloadPresentationOriginalFile'; + public const DOWNLOAD_PRESENTATION_CONVERTED_TO_PDF = 'downloadPresentationConvertedToPdf'; + public const TIMER = 'timer'; } diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index 32212db1..ab87f1e2 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -128,12 +128,16 @@ * @method $this setDisabledFeatures(array $disabledFeatures) * @method array getDisabledFeaturesExclude() * @method $this setDisabledFeaturesExclude(array $disabledFeaturesExclude) - * @method string getPreUploadedPresentationOverrideDefault() - * @method $this setPreUploadedPresentationOverrideDefault(string $preUploadedPresentationOverrideDefault) + * @method bool|null isPreUploadedPresentationOverrideDefault() + * @method $this setPreUploadedPresentationOverrideDefault(bool $preUploadedPresentationOverrideDefault) * @method string getPresentationUploadExternalUrl() * @method $this setPresentationUploadExternalUrl(string $presentationUploadExternalUrl) * @method string getPresentationUploadExternalDescription() * @method $this setPresentationUploadExternalDescription(string $presentationUploadExternalDescription) + * @method string getPreUploadedPresentation() + * @method $this setPreUploadedPresentation(string $preUploadedPresentation) + * @method string getPreUploadedPresentationName() + * @method $this setPreUploadedPresentationName(string $preUploadedPresentationName) */ class CreateMeetingParameters extends MetaParameters { @@ -427,6 +431,16 @@ class CreateMeetingParameters extends MetaParameters */ protected $preUploadedPresentationOverrideDefault; + /** + * @var string + */ + protected $preUploadedPresentation; + + /** + * @var string + */ + protected $preUploadedPresentationName; + /** * @var bool */ From 0ae92a0f86859bb51aaa023c096b26c9089bf5c9 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 12 Feb 2024 08:41:47 +0100 Subject: [PATCH 18/68] Fix psalm composer script --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 699ef910..551db99f 100644 --- a/composer.json +++ b/composer.json @@ -104,7 +104,7 @@ "cs-fix": "tools/php-cs-fixer fix --allow-risky=yes", "cs-test": "tools/php-cs-fixer fix --dry-run --allow-risky=yes", "psalm": "tools/psalm --threads=1", - "psalm-clear": "tools/psalm --clear-cache && psalm --clear-global-cache", + "psalm-clear": "tools/psalm --clear-cache && tools/psalm --clear-global-cache", "psalm-fix": "tools/psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType", "post-install-cmd": "tools/composer-git-hooks add --ignore-lock", "post-update-cmd": "tools/composer-git-hooks update" From 38f655412158410c9257aae504f4a87b373cb05e Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 12 Feb 2024 13:16:25 +0100 Subject: [PATCH 19/68] Fix inconsistent features const casing (#170) Remove marc-mabe/php-enum dependency --- composer.json | 3 +-- src/Enum/Enum.php | 34 ++++++++++++++++++++++++++++++++++ src/Enum/Feature.php | 16 ++++++++++++---- src/Enum/HashingAlgorithm.php | 2 -- src/Enum/Role.php | 2 -- 5 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 src/Enum/Enum.php diff --git a/composer.json b/composer.json index 551db99f..4f2df47c 100644 --- a/composer.json +++ b/composer.json @@ -62,8 +62,7 @@ "ext-curl": "*", "ext-simplexml": "*", "ext-mbstring": "*", - "ext-json": "*", - "marc-mabe/php-enum": "^4.7" + "ext-json": "*" }, "suggest": { "psr/http-client-implementation": "To use the PsrHttpClientTransport.", diff --git a/src/Enum/Enum.php b/src/Enum/Enum.php new file mode 100644 index 00000000..a4ae350e --- /dev/null +++ b/src/Enum/Enum.php @@ -0,0 +1,34 @@ +. + */ + +namespace BigBlueButton\Enum; + +/** + * @psalm-immutable + */ +abstract class Enum +{ + public static function getValues(): array + { + $reflection = new \ReflectionClass(static::class); + + return $reflection->getConstants(); + } +} diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php index 13ec6113..7b811bcb 100644 --- a/src/Enum/Feature.php +++ b/src/Enum/Feature.php @@ -20,8 +20,6 @@ namespace BigBlueButton\Enum; -use MabeEnum\Enum; - /** * @psalm-immutable */ @@ -32,8 +30,8 @@ class Feature extends Enum public const CHAT = 'chat'; public const DOWNLOAD_PRESENTATION_WITH_ANNOTATIONS = 'downloadPresentationWithAnnotations'; public const EXTERNAL_VIDEOS = 'externalVideos'; - public const IMPORT_PRESENTATION_WITHANNOTATIONS_FROM_BREAKOUTROOMS = 'importPresentationWithAnnotationsFromBreakoutRooms'; - public const IMPORT_SHARED_NOTES_FROM_BREAKOUTROOMS = 'importSharedNotesFromBreakoutRooms'; + public const IMPORT_PRESENTATION_WITH_ANNOTATIONS_FROM_BREAKOUT_ROOMS = 'importPresentationWithAnnotationsFromBreakoutRooms'; + public const IMPORT_SHARED_NOTES_FROM_BREAKOUT_ROOMS = 'importSharedNotesFromBreakoutRooms'; public const LAYOUTS = 'layouts'; public const LEARNING_DASHBOARD = 'learningDashboard'; public const POLLS = 'polls'; @@ -48,4 +46,14 @@ class Feature extends Enum public const DOWNLOAD_PRESENTATION_ORIGINAL_FILE = 'downloadPresentationOriginalFile'; public const DOWNLOAD_PRESENTATION_CONVERTED_TO_PDF = 'downloadPresentationConvertedToPdf'; public const TIMER = 'timer'; + + /** + * @deprecated Use Feature::IMPORT_PRESENTATION_WITH_ANNOTATIONS_FROM_BREAKOUT_ROOMS instead + */ + public const IMPORT_PRESENTATION_WITHANNOTATIONS_FROM_BREAKOUTROOMS = 'importPresentationWithAnnotationsFromBreakoutRooms'; + + /** + * @deprecated Use Feature::IMPORT_SHARED_NOTES_FROM_BREAKOUT_ROOMS instead + */ + public const IMPORT_SHARED_NOTES_FROM_BREAKOUTROOMS = 'importSharedNotesFromBreakoutRooms'; } diff --git a/src/Enum/HashingAlgorithm.php b/src/Enum/HashingAlgorithm.php index a2e1a02b..c5cd1545 100644 --- a/src/Enum/HashingAlgorithm.php +++ b/src/Enum/HashingAlgorithm.php @@ -20,8 +20,6 @@ namespace BigBlueButton\Enum; -use MabeEnum\Enum; - /** * @psalm-immutable */ diff --git a/src/Enum/Role.php b/src/Enum/Role.php index 3c3cbfb0..1766c666 100644 --- a/src/Enum/Role.php +++ b/src/Enum/Role.php @@ -20,8 +20,6 @@ namespace BigBlueButton\Enum; -use MabeEnum\Enum; - /** * @psalm-immutable */ From 19dede18613f05957f68ce87ac7b3ddce081b052 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 19 Feb 2024 19:37:24 +0100 Subject: [PATCH 20/68] Deprecate password methods (#174) --- src/Responses/CreateMeetingResponse.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Responses/CreateMeetingResponse.php b/src/Responses/CreateMeetingResponse.php index 89b063fb..46526b73 100644 --- a/src/Responses/CreateMeetingResponse.php +++ b/src/Responses/CreateMeetingResponse.php @@ -1,4 +1,5 @@ rawXml->parentMeetingID->__toString(); } + /** + * @deprecated and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter in api requests. + */ public function getAttendeePassword(): string { return $this->rawXml->attendeePW->__toString(); } + /** + * @deprecated and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter in api requests. + */ public function getModeratorPassword(): string { return $this->rawXml->moderatorPW->__toString(); From fc3e56864e1d5129b73dc0c4351d5d3fe0b6e29f Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sat, 24 Feb 2024 13:49:53 +0100 Subject: [PATCH 21/68] Bump minimum PHP version to 8.1 (#171) * Bump minimum PHP version to 8.1 --- .github/workflows/ci.yml | 10 +++------- README.md | 6 +++--- composer.json | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ba2bd9d..6528c1a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['7.4', '8.0'] + php-versions: ['8.1', '8.2'] experimental: [false] steps: @@ -37,13 +37,9 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['7.4','8.0'] + php-versions: ['8.1', '8.2'] experimental: [false] include: - - php-versions: '8.1' - experimental: true - - php-versions: '8.2' - experimental: true - php-versions: '8.3' experimental: true steps: @@ -73,5 +69,5 @@ jobs: - name: Coveralls env: COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - if: ${{ matrix.php-versions == '7.4' && env.COVERALLS_REPO_TOKEN != null }} + if: ${{ matrix.php-versions == '8.1' && env.COVERALLS_REPO_TOKEN != null }} run: tools/php-coveralls --coverage_clover=build/logs/coverage.xml -v diff --git a/README.md b/README.md index 16290b60..ff22d717 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # :tada: Best BigBlueButton API for PHP The unofficial and easiest to use **BigBlueButton API for PHP**, makes easy for -developers to use [BigBlueButton API] v2.2+ for **PHP 7.4+**. +developers to use [BigBlueButton API] v2.2+ for **PHP 8.1+**. ![Build Status](https://github.com/littleredbutton/bigbluebutton-api-php/workflows/CI/badge.svg) [![Coverage Status](https://coveralls.io/repos/github/littleredbutton/bigbluebutton-api-php/badge.svg?branch=master)](https://coveralls.io/github/littleredbutton/bigbluebutton-api-php?branch=master) @@ -56,7 +56,7 @@ following advantages: - Development is simplified through git hooks and contributor guidelines - Documentation is up-to-date and complete - API is fixed and extended to exploit the full potential -- Require at least PHP 7.4, which allows to make the code more efficient and +- Require at least PHP 8.1, which allows to make the code more efficient and readable ## :gear: Installation and usage @@ -64,7 +64,7 @@ following advantages: In order to use this library you have to make sure to meet the following requirements: -- PHP 7.4 or above. +- PHP 8.1 or above. - curl library installed. - mbstring library installed. - xml library installed. diff --git a/composer.json b/composer.json index 4f2df47c..77a998e6 100644 --- a/composer.json +++ b/composer.json @@ -58,7 +58,7 @@ "docs": "https://github.com/littleredbutton/bigbluebutton-api-php/blob/master/README.md" }, "require": { - "php": ">=7.4", + "php": ">=8.1", "ext-curl": "*", "ext-simplexml": "*", "ext-mbstring": "*", From d4cc0c3d6e16df2a0fd13a5c1948ba1a3d388bd1 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sun, 25 Feb 2024 12:38:41 +0100 Subject: [PATCH 22/68] Bump symfony dependencies, remove EOL versions (#176) --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 4f2df47c..1514873d 100644 --- a/composer.json +++ b/composer.json @@ -75,10 +75,10 @@ "psr/http-client": "^1.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0", - "symfony/dotenv": "^3.4|^4.0|^5.0", + "symfony/dotenv": "^5.4|^6.4|^7.0", "symfony/http-client-contracts": "^1.1|^2.0", - "symfony/http-client": "^4.4|^5.0", - "symfony/process": "^3.4|^4.0|^5.0", + "symfony/http-client": "^5.4|^6.4|^7.0", + "symfony/process": "^5.4|^6.4|^7.0", "nyholm/psr7": "^1.4" }, "autoload": { From bcd5208d902ec0f16a63ab1bcc33b1150a15b7c1 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 26 Feb 2024 09:12:01 +0100 Subject: [PATCH 23/68] Revert "Bump symfony dependencies, remove EOL versions (#176)" This reverts commit d4cc0c3d6e16df2a0fd13a5c1948ba1a3d388bd1. --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 1514873d..4f2df47c 100644 --- a/composer.json +++ b/composer.json @@ -75,10 +75,10 @@ "psr/http-client": "^1.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0", - "symfony/dotenv": "^5.4|^6.4|^7.0", + "symfony/dotenv": "^3.4|^4.0|^5.0", "symfony/http-client-contracts": "^1.1|^2.0", - "symfony/http-client": "^5.4|^6.4|^7.0", - "symfony/process": "^5.4|^6.4|^7.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", "nyholm/psr7": "^1.4" }, "autoload": { From dbca763068ff41343f5924ba0a7a930cbba2e04c Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 26 Feb 2024 09:13:02 +0100 Subject: [PATCH 24/68] Bump symfony dependencies, remove EOL versions (#179) --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 77a998e6..f070c3bb 100644 --- a/composer.json +++ b/composer.json @@ -75,10 +75,10 @@ "psr/http-client": "^1.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0", - "symfony/dotenv": "^3.4|^4.0|^5.0", + "symfony/dotenv": "^5.4|^6.4|^7.0", "symfony/http-client-contracts": "^1.1|^2.0", - "symfony/http-client": "^4.4|^5.0", - "symfony/process": "^3.4|^4.0|^5.0", + "symfony/http-client": "^5.4|^6.4|^7.0", + "symfony/process": "^5.4|^6.4|^7.0", "nyholm/psr7": "^1.4" }, "autoload": { From f217d821946139cf1f56f2efa78c076edf43a8a4 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Tue, 27 Feb 2024 01:42:59 +0100 Subject: [PATCH 25/68] Add missing tests (#182) * Add meta param tests * Add test for idNotUnique error * Add test for recording preview width/height and caching * Add test for remove presentation in insertDocuments * Add missing properties --- src/Core/Record.php | 3 +++ .../create_meeting_not_unique_error.xml | 5 +++++ .../CreateMeetingParametersTest.php | 21 +++++++++++++++++++ .../InsertDocumentParametersTest.php | 7 ++++++- .../Responses/CreateMeetingResponseTest.php | 19 +++++++++++++++++ .../Responses/GetRecordingsResponseTest.php | 6 ++++++ 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/create_meeting_not_unique_error.xml diff --git a/src/Core/Record.php b/src/Core/Record.php index dfa15b92..0cf21290 100644 --- a/src/Core/Record.php +++ b/src/Core/Record.php @@ -36,6 +36,9 @@ class Record /** @var PlaybackFormat[] */ private $playbackFormats = []; + private $playbackType; + private $playbackUrl; + private $playbackLength; public function __construct(\SimpleXMLElement $xml) { diff --git a/tests/fixtures/create_meeting_not_unique_error.xml b/tests/fixtures/create_meeting_not_unique_error.xml new file mode 100644 index 00000000..1575d544 --- /dev/null +++ b/tests/fixtures/create_meeting_not_unique_error.xml @@ -0,0 +1,5 @@ + + FAILED + idNotUnique + A meeting already exists with that meeting ID. Please use a different meeting ID. + diff --git a/tests/unit/Parameters/CreateMeetingParametersTest.php b/tests/unit/Parameters/CreateMeetingParametersTest.php index ea970d45..5ecfd611 100644 --- a/tests/unit/Parameters/CreateMeetingParametersTest.php +++ b/tests/unit/Parameters/CreateMeetingParametersTest.php @@ -107,6 +107,27 @@ public function testCreateMeetingParameters() $this->assertEquals($newId, $createMeetingParams->getMeetingID()); } + public function testMetaParameters(): void + { + $params = $this->generateCreateParams(); + $createMeetingParams = $this->getCreateMock($params); + $createMeetingParams->addMeta('userdata-bbb_hide_presentation_on_join', true); + $createMeetingParams->addMeta('userdata-bbb_show_participants_on_login', false); + $createMeetingParams->addMeta('userdata-bbb_fullaudio_bridge', 'fullaudio'); + + // Test getters + $this->assertTrue($createMeetingParams->getMeta('userdata-bbb_hide_presentation_on_join')); + $this->assertFalse($createMeetingParams->getMeta('userdata-bbb_show_participants_on_login')); + $this->assertEquals('fullaudio', $createMeetingParams->getMeta('userdata-bbb_fullaudio_bridge')); + + $params = urldecode($createMeetingParams->getHTTPQuery()); + + // Test HTTP query + $this->assertStringContainsString('meta_userdata-bbb_hide_presentation_on_join=true', $params); + $this->assertStringContainsString('meta_userdata-bbb_show_participants_on_login=false', $params); + $this->assertStringContainsString('meta_userdata-bbb_fullaudio_bridge=fullaudio', $params); + } + public function testDisabledFeatures(): void { $params = $this->generateCreateParams(); diff --git a/tests/unit/Parameters/InsertDocumentParametersTest.php b/tests/unit/Parameters/InsertDocumentParametersTest.php index d7acb3cd..05caa17c 100644 --- a/tests/unit/Parameters/InsertDocumentParametersTest.php +++ b/tests/unit/Parameters/InsertDocumentParametersTest.php @@ -25,14 +25,19 @@ final class InsertDocumentParametersTest extends TestCase { - public function testIsMeetingRunningParameters(): void + public function testInsertingDocuments(): void { $meetingId = $this->faker->uuid; $params = new InsertDocumentParameters($meetingId); + // Adding presentations $params->addPresentation('http://localhost/foobar.png', 'Foobar.png'); $params->addPresentation('http://localhost/foobar.pdf', 'Foobar.pdf', true); $params->addPresentation('http://localhost/foobar.svg', 'Foobar.svg', true, false); + $params->addPresentation('http://localhost/demo.pdf', 'Demo.pdf', true); + + // Removing presentation + $params->removePresentation('http://localhost/demo.pdf'); $this->assertEquals($meetingId, $params->getMeetingID()); diff --git a/tests/unit/Responses/CreateMeetingResponseTest.php b/tests/unit/Responses/CreateMeetingResponseTest.php index 5c7369ab..4780992e 100644 --- a/tests/unit/Responses/CreateMeetingResponseTest.php +++ b/tests/unit/Responses/CreateMeetingResponseTest.php @@ -40,7 +40,10 @@ protected function setUp(): void public function testCreateMeetingResponseContent() { + $this->assertTrue($this->meeting->success()); + $this->assertFalse($this->meeting->failed()); $this->assertEquals('SUCCESS', $this->meeting->getReturnCode()); + $this->assertEquals('random-1665177', $this->meeting->getMeetingId()); $this->assertEquals('1a6938c707cdf5d052958672d66c219c30690c47-1524212045514', $this->meeting->getInternalMeetingId()); $this->assertEquals('bbb-none', $this->meeting->getParentMeetingId()); @@ -54,7 +57,10 @@ public function testCreateMeetingResponseContent() $this->assertEquals(20, $this->meeting->getDuration()); $this->assertFalse($this->meeting->hasBeenForciblyEnded()); $this->assertEquals('duplicateWarning', $this->meeting->getMessageKey()); + $this->assertTrue($this->meeting->isDuplicate()); $this->assertEquals('This conference was already in existence and may currently be in progress.', $this->meeting->getMessage()); + + $this->assertFalse($this->meeting->isIdNotUnique()); } public function testCreateMeetingResponseTypes() @@ -65,4 +71,17 @@ public function testCreateMeetingResponseTypes() $this->assertEachGetterValueIsInteger($this->meeting, ['getDuration', 'getVoiceBridge']); $this->assertEachGetterValueIsBoolean($this->meeting, ['hasUserJoined', 'hasBeenForciblyEnded']); } + + public function testIdNotUnique() + { + $xml = $this->loadXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'create_meeting_not_unique_error.xml'); + + $meeting = new CreateMeetingResponse($xml); + + $this->assertFalse($meeting->success()); + $this->assertTrue($meeting->failed()); + $this->assertEquals('FAILED', $meeting->getReturnCode()); + + $this->assertTrue($meeting->isIdNotUnique()); + } } diff --git a/tests/unit/Responses/GetRecordingsResponseTest.php b/tests/unit/Responses/GetRecordingsResponseTest.php index 7e069168..d405ba12 100644 --- a/tests/unit/Responses/GetRecordingsResponseTest.php +++ b/tests/unit/Responses/GetRecordingsResponseTest.php @@ -111,5 +111,11 @@ public function testImagePreviews(): void $this->assertEquals('Welcome to', $previews[0]->getAlt()); $this->assertEquals('https://demo.bigbluebutton.org/presentation/ffbfc4cc24428694e8b53a4e144f414052431693-1530718721124/presentation/d2d9a672040fbde2a47a10bf6c37b6a4b5ae187f-1530718721134/thumbnails/thumb-1.png', $previews[0]->getUrl()); + $this->assertEquals(176, $previews[0]->getWidth()); + $this->assertEquals(136, $previews[0]->getHeight()); + + // Load previews again, check if same instance is returned (caching) + $newPreviews = $formats[1]->getImagePreviews(); + $this->assertTrue($previews[0] === $newPreviews[0]); } } From 2ee11409ed0b0a98d00b47ee5680a5ca1397db4f Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sun, 3 Mar 2024 01:28:22 +0100 Subject: [PATCH 26/68] Recording response errors (#181) * Add not found errors * Deprecate isInvalidId * Add tests * Add errors to PutRecordingTextTrackResponse * Make json responses behavior same as xml responses * Add/adjust tests * Added mssing return type hints --------- Co-authored-by: Felix Jacobi --- src/Responses/BaseResponseAsJson.php | 18 +-- src/Responses/DeleteRecordingsResponse.php | 9 ++ src/Responses/PublishRecordingsResponse.php | 7 + .../PutRecordingTextTrackResponse.php | 20 ++- src/Responses/UpdateRecordingsResponse.php | 7 + tests/fixtures/not_found_error.xml | 5 + tests/unit/BigBlueButtonTest.php | 4 +- .../DeleteRecordingsResponseTest.php | 10 ++ .../PublishRecordingsResponseTest.php | 10 ++ .../PutRecordingTextTrackResponseTest.php | 144 ++++++++++++++++++ .../UpdateRecordingsResponseTest.php | 10 ++ 11 files changed, 228 insertions(+), 16 deletions(-) create mode 100644 tests/fixtures/not_found_error.xml create mode 100644 tests/unit/Responses/PutRecordingTextTrackResponseTest.php diff --git a/src/Responses/BaseResponseAsJson.php b/src/Responses/BaseResponseAsJson.php index 66cb6746..420fef3c 100644 --- a/src/Responses/BaseResponseAsJson.php +++ b/src/Responses/BaseResponseAsJson.php @@ -50,27 +50,19 @@ public function getRawArray(): array return json_decode(json_encode($this->data), true); } - public function getMessage(): ?string + public function getMessage(): string { - if ($this->failed()) { - return $this->data->response->message; - } - - return null; + return $this->data->response->message ?? ''; } - public function getMessageKey(): ?string + public function getMessageKey(): string { - if ($this->failed()) { - return $this->data->response->messageKey; - } - - return null; + return $this->data->response->messageKey ?? ''; } public function getReturnCode(): string { - return $this->data->response->returncode; + return $this->data->response->returncode ?? ''; } public function success(): bool diff --git a/src/Responses/DeleteRecordingsResponse.php b/src/Responses/DeleteRecordingsResponse.php index 9cba904c..c46d7bb8 100644 --- a/src/Responses/DeleteRecordingsResponse.php +++ b/src/Responses/DeleteRecordingsResponse.php @@ -24,15 +24,24 @@ */ class DeleteRecordingsResponse extends BaseResponse { + /** @deprecated and will be removed in 6.0. Use KEY_NOT_FOUND instead */ public const KEY_INVALID_ID = 'InvalidRecordingId'; + public const KEY_NOT_FOUND = 'notFound'; + public function isDeleted(): bool { return $this->rawXml->deleted->__toString() == 'true'; } + /** @deprecated and will be removed in 6.0. Use isNotFound instead */ public function isInvalidId(): bool { return $this->getMessageKey() === self::KEY_INVALID_ID; } + + public function isNotFound(): bool + { + return $this->getMessageKey() === self::KEY_NOT_FOUND; + } } diff --git a/src/Responses/PublishRecordingsResponse.php b/src/Responses/PublishRecordingsResponse.php index 4a06e98e..e2814a16 100644 --- a/src/Responses/PublishRecordingsResponse.php +++ b/src/Responses/PublishRecordingsResponse.php @@ -24,8 +24,15 @@ */ class PublishRecordingsResponse extends BaseResponse { + public const KEY_NOT_FOUND = 'notFound'; + public function isPublished(): bool { return $this->rawXml->published->__toString() === 'true'; } + + public function isNotFound(): bool + { + return $this->getMessageKey() === self::KEY_NOT_FOUND; + } } diff --git a/src/Responses/PutRecordingTextTrackResponse.php b/src/Responses/PutRecordingTextTrackResponse.php index b512a635..f7c4e93e 100644 --- a/src/Responses/PutRecordingTextTrackResponse.php +++ b/src/Responses/PutRecordingTextTrackResponse.php @@ -27,11 +27,14 @@ class PutRecordingTextTrackResponse extends BaseResponseAsJson public const KEY_SUCCESS = 'upload_text_track_success'; public const KEY_FAILED = 'upload_text_track_failed'; public const KEY_EMPTY = 'empty_uploaded_text_track'; + public const KEY_NO_RECORDINGS = 'noRecordings'; + public const KEY_INVALID_KIND = 'invalidKind'; + public const KEY_INVALID_LANG = 'invalidLang'; public const KEY_PARAM_ERROR = 'paramError'; public function getRecordID(): string { - return $this->data->response->recordId; + return $this->data->response->recordId ?? ''; } public function isUploadTrackSuccess(): bool @@ -49,6 +52,21 @@ public function isUploadTrackEmpty(): bool return $this->getMessageKey() === self::KEY_EMPTY; } + public function isNoRecordings(): bool + { + return $this->getMessageKey() === self::KEY_NO_RECORDINGS; + } + + public function isInvalidLang(): bool + { + return $this->getMessageKey() === self::KEY_INVALID_LANG; + } + + public function isInvalidKind(): bool + { + return $this->getMessageKey() === self::KEY_INVALID_KIND; + } + public function isKeyParamError(): bool { return $this->getMessageKey() === self::KEY_PARAM_ERROR; diff --git a/src/Responses/UpdateRecordingsResponse.php b/src/Responses/UpdateRecordingsResponse.php index c30ceaef..0445d821 100644 --- a/src/Responses/UpdateRecordingsResponse.php +++ b/src/Responses/UpdateRecordingsResponse.php @@ -24,8 +24,15 @@ */ class UpdateRecordingsResponse extends BaseResponse { + public const KEY_NOT_FOUND = 'notFound'; + public function isUpdated(): bool { return $this->rawXml->updated->__toString() === 'true'; } + + public function isNotFound(): bool + { + return $this->getMessageKey() === self::KEY_NOT_FOUND; + } } diff --git a/tests/fixtures/not_found_error.xml b/tests/fixtures/not_found_error.xml new file mode 100644 index 00000000..4a5d46b7 --- /dev/null +++ b/tests/fixtures/not_found_error.xml @@ -0,0 +1,5 @@ + + FAILED + notFound + We could not find recordings + diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index e1381f5d..044f626b 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -449,8 +449,8 @@ public function testPutRecordingTextTrack(): void $response = $this->bbb->putRecordingTextTrack($params); $this->assertTrue($response->success()); - $this->assertNull($response->getMessageKey()); - $this->assertNull($response->getMessage()); + $this->assertEquals('upload_text_track_success', $response->getMessageKey()); + $this->assertEquals('Text track uploaded successfully', $response->getMessage()); $this->assertSame('baz', $response->getRecordID()); $this->assertSame('SUCCESS', $response->getReturnCode()); } diff --git a/tests/unit/Responses/DeleteRecordingsResponseTest.php b/tests/unit/Responses/DeleteRecordingsResponseTest.php index b7594fc2..38cf4cfc 100644 --- a/tests/unit/Responses/DeleteRecordingsResponseTest.php +++ b/tests/unit/Responses/DeleteRecordingsResponseTest.php @@ -49,4 +49,14 @@ public function testDeleteRecordingsResponseTypes() $this->assertEachGetterValueIsString($this->delete, ['getReturnCode']); $this->assertEachGetterValueIsBoolean($this->delete, ['isDeleted']); } + + public function testNotFoundError(): void + { + $xml = $this->loadXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'not_found_error.xml'); + + $delete = new DeleteRecordingsResponse($xml); + + $this->assertTrue($delete->failed()); + $this->assertTrue($delete->isNotFound()); + } } diff --git a/tests/unit/Responses/PublishRecordingsResponseTest.php b/tests/unit/Responses/PublishRecordingsResponseTest.php index 6155ea52..62d9979f 100644 --- a/tests/unit/Responses/PublishRecordingsResponseTest.php +++ b/tests/unit/Responses/PublishRecordingsResponseTest.php @@ -49,4 +49,14 @@ public function testPublishRecordingsResponseTypes() $this->assertEachGetterValueIsString($this->publish, ['getReturnCode']); $this->assertEachGetterValueIsBoolean($this->publish, ['isPublished']); } + + public function testNotFoundError(): void + { + $xml = $this->loadXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'not_found_error.xml'); + + $publish = new PublishRecordingsResponse($xml); + + $this->assertTrue($publish->failed()); + $this->assertTrue($publish->isNotFound()); + } } diff --git a/tests/unit/Responses/PutRecordingTextTrackResponseTest.php b/tests/unit/Responses/PutRecordingTextTrackResponseTest.php new file mode 100644 index 00000000..32b9bf04 --- /dev/null +++ b/tests/unit/Responses/PutRecordingTextTrackResponseTest.php @@ -0,0 +1,144 @@ +. + */ + +namespace BigBlueButton\Parameters; + +use BigBlueButton\Responses\PutRecordingTextTrackResponse; +use BigBlueButton\TestCase; + +final class PutRecordingTextTrackResponseTest extends TestCase +{ + public function testUploadSuccess(): void + { + $json = '{ + "response": { + "messageKey": "upload_text_track_success", + "message": "Text track uploaded successfully", + "recordId": "baz", + "returncode": "SUCCESS" + } + }'; + + $response = new PutRecordingTextTrackResponse($json); + + $this->assertTrue($response->success()); + $this->assertEquals('baz', $response->getRecordID()); + $this->assertTrue($response->isUploadTrackSuccess()); + } + + public function testUploadFailed(): void + { + $json = '{ + "response": { + "messageKey": "upload_text_track_failed", + "message": "Text track upload failed.", + "recordId": "baz", + "returncode": "FAILED" + } + }'; + + $response = new PutRecordingTextTrackResponse($json); + + $this->assertTrue($response->failed()); + $this->assertEquals('baz', $response->getRecordID()); + $this->assertTrue($response->isUploadTrackFailed()); + } + + public function testUploadEmpty(): void + { + $json = '{ + "response": { + "messageKey": "empty_uploaded_text_track", + "message": "Empty uploaded text track.", + "returncode": "FAILED" + } + }'; + + $response = new PutRecordingTextTrackResponse($json); + + $this->assertTrue($response->failed()); + $this->assertTrue($response->isUploadTrackEmpty()); + } + + public function testNoRecordings(): void + { + $json = '{ + "response": { + "messageKey": "noRecordings", + "message": "No recording was found for meeting-id-1234.", + "returncode": "FAILED" + } + }'; + + $response = new PutRecordingTextTrackResponse($json); + + $this->assertTrue($response->failed()); + $this->assertTrue($response->isNoRecordings()); + } + + public function testInvalidLang(): void + { + $json = '{ + "response": { + "messageKey": "invalidLang", + "message": "Malformed lang param, received=english", + "returncode": "FAILED" + } + }'; + + $response = new PutRecordingTextTrackResponse($json); + + $this->assertTrue($response->failed()); + $this->assertTrue($response->isInvalidLang()); + } + + public function testInvalidKind(): void + { + $json = '{ + "response": { + "messageKey": "invalidKind", + "message": "Invalid kind parameter, expected=\'subtitles|captions\' actual=somethingelse", + "returncode": "FAILED" + } + }'; + + $response = new PutRecordingTextTrackResponse($json); + + $this->assertTrue($response->failed()); + $this->assertTrue($response->isInvalidKind()); + } + + public function testHandleMissingJsonKeys(): void + { + $json = '{}'; + + $response = new PutRecordingTextTrackResponse($json); + + $this->assertFalse($response->success()); + $this->assertFalse($response->failed()); + $this->assertFalse($response->hasChecksumError()); + $this->assertEquals('', $response->getRecordID()); + $this->assertFalse($response->isUploadTrackSuccess()); + $this->assertFalse($response->isUploadTrackFailed()); + $this->assertFalse($response->isUploadTrackEmpty()); + $this->assertFalse($response->isNoRecordings()); + $this->assertFalse($response->isInvalidLang()); + $this->assertFalse($response->isInvalidKind()); + } +} diff --git a/tests/unit/Responses/UpdateRecordingsResponseTest.php b/tests/unit/Responses/UpdateRecordingsResponseTest.php index b45bc570..69b2759d 100644 --- a/tests/unit/Responses/UpdateRecordingsResponseTest.php +++ b/tests/unit/Responses/UpdateRecordingsResponseTest.php @@ -49,4 +49,14 @@ public function testUpdateRecordingsResponseTypes() $this->assertEachGetterValueIsString($this->update, ['getReturnCode']); $this->assertEachGetterValueIsBoolean($this->update, ['isUpdated']); } + + public function testNotFoundError(): void + { + $xml = $this->loadXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'not_found_error.xml'); + + $update = new UpdateRecordingsResponse($xml); + + $this->assertTrue($update->failed()); + $this->assertTrue($update->isNotFound()); + } } From 06574cf14daf3928617c7234d275adfccda47588 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sun, 3 Mar 2024 01:32:54 +0100 Subject: [PATCH 27/68] Update Webhook api calls (#184) * Add HooksListParameters * Add eventID to hooks create api * Add errors to HooksDestroyResponse * Add tests * Add backward compatibility * Change cs * Added mssing return type hints and made newly added class final --------- Co-authored-by: Felix Jacobi --- src/BigBlueButton.php | 19 ++- src/Parameters/HooksCreateParameters.php | 7 + src/Parameters/HooksListParameters.php | 34 ++++ src/Responses/HooksDestroyResponse.php | 13 ++ tests/unit/BigBlueButtonTest.php | 147 ++++++++++++++++++ .../Parameters/HooksListParametersTest.php | 36 +++++ .../Responses/HooksDestroyResponseTest.php | 18 +++ 7 files changed, 270 insertions(+), 4 deletions(-) create mode 100644 src/Parameters/HooksListParameters.php create mode 100644 tests/unit/Parameters/HooksListParametersTest.php diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index f8c21a97..b8993dfd 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -36,6 +36,7 @@ use BigBlueButton\Parameters\GetRecordingTextTracksParameters; use BigBlueButton\Parameters\HooksCreateParameters; use BigBlueButton\Parameters\HooksDestroyParameters; +use BigBlueButton\Parameters\HooksListParameters; use BigBlueButton\Parameters\InsertDocumentParameters; use BigBlueButton\Parameters\IsMeetingRunningParameters; use BigBlueButton\Parameters\JoinMeetingParameters; @@ -418,14 +419,24 @@ public function hooksCreate(HooksCreateParameters $hookCreateParams): HooksCreat return new HooksCreateResponse($xml); } - public function getHooksListUrl(): string + public function getHooksListUrl(?HooksListParameters $hooksListParameters = null): string { - return $this->urlBuilder->buildUrl(ApiMethod::HOOKS_LIST); + if ($hooksListParameters === null) { + @trigger_error(sprintf('Not passing the $hooksListParameters parameter to "%s::getHooksListUrl()" is deprecated since 5.4 and will be required in 6.0.', self::class), \E_USER_DEPRECATED); + $hooksListParameters = new HooksListParameters(); + } + + return $this->urlBuilder->buildUrl(ApiMethod::HOOKS_LIST, $hooksListParameters->getHTTPQuery()); } - public function hooksList(): HooksListResponse + public function hooksList(?HooksListParameters $hooksListParameters = null): HooksListResponse { - $xml = $this->processXmlResponse($this->getHooksListUrl()); + if ($hooksListParameters === null) { + @trigger_error(sprintf('Not passing the $hooksListParameters parameter to "%s::hooksList()" is deprecated since 5.4 and will be required in 6.0.', self::class), \E_USER_DEPRECATED); + $hooksListParameters = new HooksListParameters(); + } + + $xml = $this->processXmlResponse($this->getHooksListUrl($hooksListParameters)); return new HooksListResponse($xml); } diff --git a/src/Parameters/HooksCreateParameters.php b/src/Parameters/HooksCreateParameters.php index 59c96914..2e95b92e 100644 --- a/src/Parameters/HooksCreateParameters.php +++ b/src/Parameters/HooksCreateParameters.php @@ -24,6 +24,8 @@ * @method $this setCallbackURL(string $url) * @method string getMeetingID() * @method $this setMeetingID(string $id) + * @method string getEventID() + * @method $this setEventID(string $id) * @method bool|null isGetRaw() * @method $this setGetRaw(bool $getRaw) */ @@ -39,6 +41,11 @@ class HooksCreateParameters extends BaseParameters */ protected $meetingID; + /** + * @var string + */ + protected $eventID; + /** * @var bool */ diff --git a/src/Parameters/HooksListParameters.php b/src/Parameters/HooksListParameters.php new file mode 100644 index 00000000..7f5027e9 --- /dev/null +++ b/src/Parameters/HooksListParameters.php @@ -0,0 +1,34 @@ +. + */ + +namespace BigBlueButton\Parameters; + +/** + * Class HooksListParameters. + * + * @method string getMeetingID() + * @method $this setMeetingID(string $id) + */ +final class HooksListParameters extends MetaParameters +{ + /** + * @var string + */ + protected $meetingID; +} diff --git a/src/Responses/HooksDestroyResponse.php b/src/Responses/HooksDestroyResponse.php index b460a047..360139ab 100644 --- a/src/Responses/HooksDestroyResponse.php +++ b/src/Responses/HooksDestroyResponse.php @@ -24,8 +24,21 @@ */ class HooksDestroyResponse extends BaseResponse { + public const KEY_MISSING_HOOK = 'destroyMissingHook'; + public const KEY_HOOK_ERROR = 'destroyHookError'; + public function removed(): bool { return $this->rawXml->removed->__toString() === 'true'; } + + public function isMissingHook(): bool + { + return $this->getMessageKey() === self::KEY_MISSING_HOOK; + } + + public function isHookError(): bool + { + return $this->getMessageKey() === self::KEY_HOOK_ERROR; + } } diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index 044f626b..3373a54b 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -29,6 +29,9 @@ use BigBlueButton\Parameters\DeleteRecordingsParameters; use BigBlueButton\Parameters\GetRecordingsParameters; use BigBlueButton\Parameters\GetRecordingTextTracksParameters; +use BigBlueButton\Parameters\HooksCreateParameters; +use BigBlueButton\Parameters\HooksDestroyParameters; +use BigBlueButton\Parameters\HooksListParameters; use BigBlueButton\Parameters\InsertDocumentParameters; use BigBlueButton\Parameters\PublishRecordingsParameters; use BigBlueButton\Parameters\PutRecordingTextTrackParameters; @@ -454,4 +457,148 @@ public function testPutRecordingTextTrack(): void $this->assertSame('baz', $response->getRecordID()); $this->assertSame('SUCCESS', $response->getReturnCode()); } + + public function testHooksCreate(): void + { + $params = new HooksCreateParameters($this->faker->url); + + $xml = ' + SUCCESS + 1 + false + false + '; + + $this->transport->method('request')->willReturn(new TransportResponse($xml, null)); + + $response = $this->bbb->hooksCreate($params); + + $this->assertTrue($response->success()); + $this->assertSame(1, $response->getHookId()); + $this->assertFalse($response->isPermanentHook()); + $this->assertFalse($response->hasRawData()); + } + + public function testHooksList(): void + { + $params = new HooksListParameters(); + + $xml = ' + SUCCESS + + + 1 + + + false + false + + + 2 + + false + false + + + '; + + $this->transport->method('request')->willReturn(new TransportResponse($xml, null)); + + $response = $this->bbb->hooksList($params); + + $this->assertTrue($response->success()); + $this->assertCount(2, $response->getHooks()); + + // Hook for a single meeting + $meetingHook = $response->getHooks()[0]; + $this->assertSame(1, $meetingHook->getHookId()); + $this->assertSame('http://postcatcher.in/catchers/abcdefghijk', $meetingHook->getCallbackURL()); + $this->assertSame('my-meeting', $meetingHook->getMeetingID()); + $this->assertFalse($meetingHook->isPermanentHook()); + $this->assertFalse($meetingHook->hasRawData()); + + // Global hook + $globalHook = $response->getHooks()[1]; + $this->assertSame(2, $globalHook->getHookId()); + $this->assertSame('http://postcatcher.in/catchers/1234567890', $globalHook->getCallbackURL()); + $this->assertFalse($globalHook->isPermanentHook()); + $this->assertFalse($globalHook->hasRawData()); + } + + /** + * @group legacy + */ + public function testHooksListWithoutParameter(): void + { + $xml = ' + SUCCESS + + + 1 + + + false + false + + + 2 + + false + false + + + '; + + $this->transport->method('request')->willReturn(new TransportResponse($xml, null)); + + $response = $this->bbb->hooksList(); + + $this->assertTrue($response->success()); + $this->assertCount(2, $response->getHooks()); + } + + public function testHooksListUrl(): void + { + // Test without meeting ID + $params = new HooksListParameters(); + $url = $this->bbb->getHooksListUrl($params); + + $this->assertStringContainsString(ApiMethod::HOOKS_LIST, $url); + $this->assertStringNotContainsString('meetingID=', $url); + + // Test with meeting ID + $params = new HooksListParameters(); + $params->setMeetingID('foobar'); + $url = $this->bbb->getHooksListUrl($params); + + $this->assertStringContainsString('meetingID=foobar', $url); + } + + /** + * @group legacy + */ + public function testHooksListUrlWithoutParameter(): void + { + $url = $this->bbb->getHooksListUrl(); + + $this->assertStringContainsString(ApiMethod::HOOKS_LIST, $url); + $this->assertStringNotContainsString('meetingID=', $url); + } + + public function testHookDestroy(): void + { + $params = new HooksDestroyParameters(1); + + $xml = ' + SUCCESS + true + '; + + $this->transport->method('request')->willReturn(new TransportResponse($xml, null)); + + $response = $this->bbb->hooksDestroy($params); + + $this->assertTrue($response->success()); + $this->assertTrue($response->removed()); + } } diff --git a/tests/unit/Parameters/HooksListParametersTest.php b/tests/unit/Parameters/HooksListParametersTest.php new file mode 100644 index 00000000..f4c25822 --- /dev/null +++ b/tests/unit/Parameters/HooksListParametersTest.php @@ -0,0 +1,36 @@ +. + */ + +namespace BigBlueButton\Parameters; + +use BigBlueButton\TestCase; + +final class HooksListParametersTest extends TestCase +{ + public function testHooksListParameters(): void + { + $hooksListParameters = new HooksListParameters(); + + $this->assertNull($hooksListParameters->getMeetingID()); + + // Test setters that are ignored by the constructor + $hooksListParameters->setMeetingID($meetingId = $this->faker->uuid); + $this->assertEquals($meetingId, $hooksListParameters->getMeetingID()); + } +} diff --git a/tests/unit/Responses/HooksDestroyResponseTest.php b/tests/unit/Responses/HooksDestroyResponseTest.php index 3e1d252d..0454288c 100644 --- a/tests/unit/Responses/HooksDestroyResponseTest.php +++ b/tests/unit/Responses/HooksDestroyResponseTest.php @@ -49,4 +49,22 @@ public function testHooksDestroyResponseTypes() $this->assertEachGetterValueIsString($this->destroyResponse, ['getReturnCode']); $this->assertEachGetterValueIsBoolean($this->destroyResponse, ['removed']); } + + public function testHookDestroyMissingHook(): void + { + $xml = simplexml_load_string('FAILEDdestroyMissingHookThe hook informed was not found.'); + + $destroyResponse = new HooksDestroyResponse($xml); + $this->assertTrue($destroyResponse->failed()); + $this->assertTrue($destroyResponse->isMissingHook()); + } + + public function testHookDestroyHookError(): void + { + $xml = simplexml_load_string('FAILEDdestroyHookErrorAn error happened while removing your hook. Check the logs.'); + + $destroyResponse = new HooksDestroyResponse($xml); + $this->assertTrue($destroyResponse->failed()); + $this->assertTrue($destroyResponse->isHookError()); + } } From ebff0b3d96bd0709c64050e20354e12d69f921dd Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 11 Mar 2024 20:26:24 +0100 Subject: [PATCH 28/68] Change coveralls to codecov (#185) --- .github/workflows/ci.yml | 8 +++----- composer.json | 1 - tools/.php-coveralls/.gitignore | 2 -- tools/.php-coveralls/composer.json | 5 ----- tools/php-coveralls | 7 ------- 5 files changed, 3 insertions(+), 20 deletions(-) delete mode 100644 tools/.php-coveralls/.gitignore delete mode 100644 tools/.php-coveralls/composer.json delete mode 100755 tools/php-coveralls diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ba2bd9d..daf2e07b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,8 +70,6 @@ jobs: if: ${{ matrix.experimental }} run: tools/phpunit --testsuite="BigBlueButton unit test suite,BigBlueButton integration test suite" continue-on-error: true - - name: Coveralls - env: - COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - if: ${{ matrix.php-versions == '7.4' && env.COVERALLS_REPO_TOKEN != null }} - run: tools/php-coveralls --coverage_clover=build/logs/coverage.xml -v + - name: Upload coverage + if: ${{ matrix.php-versions == '7.4' }} + uses: codecov/codecov-action@v3 diff --git a/composer.json b/composer.json index 4f2df47c..22fc3ea0 100644 --- a/composer.json +++ b/composer.json @@ -128,7 +128,6 @@ } }, "friendsofphp/php-cs-fixer": "^3.3", - "php-coveralls/php-coveralls": "^2.4", "phpunit/phpunit": "^9", "vimeo/psalm": "^4.22" } diff --git a/tools/.php-coveralls/.gitignore b/tools/.php-coveralls/.gitignore deleted file mode 100644 index 4fbb073c..00000000 --- a/tools/.php-coveralls/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/vendor/ -/composer.lock diff --git a/tools/.php-coveralls/composer.json b/tools/.php-coveralls/composer.json deleted file mode 100644 index 79cd2252..00000000 --- a/tools/.php-coveralls/composer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require": { - "php-coveralls/php-coveralls": "^2.4.0" - } -} diff --git a/tools/php-coveralls b/tools/php-coveralls deleted file mode 100755 index 657546b6..00000000 --- a/tools/php-coveralls +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -# This file was created automatically by cotor as a tool wrapper. - -DIR=$(realpath "$(dirname "${BASH_SOURCE[0]}")") - -composer install --working-dir=$DIR/.php-coveralls --quiet -exec $DIR/.php-coveralls/vendor/bin/php-coveralls "$@" From 93c824db871620cbdcd8d18962e317a526fae0e0 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Thu, 14 Mar 2024 23:15:17 +0100 Subject: [PATCH 29/68] Add tests (#187) * Add getMeetingInfo, getRecordings tests * Add test hasNoRecordings * Cleanup * Add recording tests --- .../AbstractBigBlueButtonFunctionalTest.php | 83 ------- tests/unit/BigBlueButtonTest.php | 211 +++++++++++++++--- .../Responses/GetRecordingsResponseTest.php | 14 ++ 3 files changed, 189 insertions(+), 119 deletions(-) diff --git a/tests/functional/AbstractBigBlueButtonFunctionalTest.php b/tests/functional/AbstractBigBlueButtonFunctionalTest.php index 3d2deafc..582602d0 100644 --- a/tests/functional/AbstractBigBlueButtonFunctionalTest.php +++ b/tests/functional/AbstractBigBlueButtonFunctionalTest.php @@ -20,7 +20,6 @@ namespace BigBlueButton\Tests\Functional; use BigBlueButton\BigBlueButton; -use BigBlueButton\Core\ApiMethod; use BigBlueButton\Http\Transport\TransportInterface; use BigBlueButton\Parameters\DeleteRecordingsParameters; use BigBlueButton\Parameters\EndMeetingParameters; @@ -99,17 +98,6 @@ public function testApiVersion() /* Create Meeting */ - /** - * Test create meeting URL. - */ - public function testCreateMeetingUrl(): void - { - $params = $this->generateCreateParams(); - $url = $this->bbb->getCreateMeetingUrl($this->getCreateMock($params)); - - $this->assertUrlContainsAllRequestParameters($url, $params); - } - /** * Test create meeting. */ @@ -198,19 +186,6 @@ public function testCreateMeetingWithMultiDocument() /* Join Meeting */ - /** - * Test create join meeting URL. - */ - public function testCreateJoinMeetingUrl(): void - { - $joinMeetingParams = $this->generateJoinMeetingParams(); - $joinMeetingMock = $this->getJoinMeetingMock($joinMeetingParams); - - $url = $this->bbb->getJoinMeetingURL($joinMeetingMock); - - $this->assertUrlContainsAllRequestParameters($url, $joinMeetingParams); - } - public function testJoinMeeting() { $params = $this->getCreateMock($this->generateCreateParams()); @@ -239,17 +214,6 @@ public function testJoinMeeting() /* End Meeting */ - /** - * Test generate end meeting URL. - */ - public function testCreateEndMeetingUrl(): void - { - $params = $this->generateEndMeetingParams(); - $url = $this->bbb->getEndMeetingURL($this->getEndMeetingMock($params)); - - $this->assertUrlContainsAllRequestParameters($url, $params); - } - public function testEndMeeting() { $meeting = $this->createRealMeeting($this->bbb); @@ -280,12 +244,6 @@ public function testIsMeetingRunning() /* Get Meetings */ - public function testGetMeetingsUrl(): void - { - $url = $this->bbb->getMeetingsUrl(); - $this->assertStringContainsString(ApiMethod::GET_MEETINGS, $url); - } - public function testGetMeetings() { $meeting = $this->createRealMeeting($this->bbb); @@ -299,17 +257,6 @@ public function testGetMeetings() /* Get meeting info */ - public function testGetMeetingInfoUrl(): void - { - $meeting = $this->createRealMeeting($this->bbb); - - $url = $this->bbb->getMeetingInfoUrl(new GetMeetingInfoParameters($meeting->getMeetingId())); - $this->assertStringContainsString('='.rawurlencode($meeting->getMeetingId()), $url); - - // Cleanup - $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId(), $meeting->getModeratorPassword())); - } - public function testGetMeetingInfo() { $meeting = $this->createRealMeeting($this->bbb); @@ -322,12 +269,6 @@ public function testGetMeetingInfo() $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId(), $meeting->getModeratorPassword())); } - public function testGetRecordingsUrl(): void - { - $url = $this->bbb->getRecordingsUrl(new GetRecordingsParameters()); - $this->assertStringContainsString(ApiMethod::GET_RECORDINGS, $url); - } - public function testGetRecordings() { $result = $this->bbb->getRecordings(new GetRecordingsParameters()); @@ -335,12 +276,6 @@ public function testGetRecordings() $this->assertTrue($result->success()); } - public function testPublishRecordingsUrl(): void - { - $url = $this->bbb->getPublishRecordingsUrl(new PublishRecordingsParameters($this->faker->sha1, true)); - $this->assertStringContainsString(ApiMethod::PUBLISH_RECORDINGS, $url); - } - public function testPublishRecordings() { $result = $this->bbb->publishRecordings(new PublishRecordingsParameters('non-existing-id-'.$this->faker->sha1, true)); @@ -348,12 +283,6 @@ public function testPublishRecordings() $this->assertTrue($result->failed()); } - public function testDeleteRecordingsUrl(): void - { - $url = $this->bbb->getDeleteRecordingsUrl(new DeleteRecordingsParameters($this->faker->sha1)); - $this->assertStringContainsString(ApiMethod::DELETE_RECORDINGS, $url); - } - public function testDeleteRecordings() { $result = $this->bbb->deleteRecordings(new DeleteRecordingsParameters('non-existing-id-'.$this->faker->sha1)); @@ -361,18 +290,6 @@ public function testDeleteRecordings() $this->assertTrue($result->failed()); } - public function testUpdateRecordingsUrl(): void - { - $params = $this->generateUpdateRecordingsParams(); - $url = $this->bbb->getUpdateRecordingsUrl($this->getUpdateRecordingsParamsMock($params)); - foreach ($params as $key => $value) { - if (\is_bool($value)) { - $value = $value ? 'true' : 'false'; - } - $this->assertStringContainsString('='.rawurlencode($value), $url); - } - } - public function testUpdateRecordings() { $params = $this->generateUpdateRecordingsParams(); diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index 3373a54b..d2588608 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -27,6 +27,7 @@ use BigBlueButton\Http\Transport\TransportInterface; use BigBlueButton\Http\Transport\TransportResponse; use BigBlueButton\Parameters\DeleteRecordingsParameters; +use BigBlueButton\Parameters\GetMeetingInfoParameters; use BigBlueButton\Parameters\GetRecordingsParameters; use BigBlueButton\Parameters\GetRecordingTextTracksParameters; use BigBlueButton\Parameters\HooksCreateParameters; @@ -61,7 +62,7 @@ protected function setUp(): void $this->bbb = new BigBlueButton('http://localhost/', null, $this->transport); } - public function testMissingUrl() + public function testMissingUrl(): void { $this->expectException(ConfigException::class); @@ -75,7 +76,7 @@ public function testMissingUrl() } } - public function testNetworkFailure() + public function testNetworkFailure(): void { $this->expectException(NetworkException::class); @@ -86,7 +87,7 @@ public function testNetworkFailure() $this->bbb->createMeeting($this->getCreateMock($params)); } - public function testInvalidXMLResponse() + public function testInvalidXMLResponse(): void { $this->expectException(ParsingException::class); @@ -97,7 +98,7 @@ public function testInvalidXMLResponse() $this->bbb->createMeeting($this->getCreateMock($params)); } - public function testJSessionId() + public function testJSessionId(): void { $id = 'foobar'; $this->transport->method('request')->willReturn(new TransportResponse('', $id)); @@ -109,7 +110,7 @@ public function testJSessionId() $this->assertEquals($id, $this->bbb->getJSessionId()); } - public function testApiVersion() + public function testApiVersion(): void { $apiVersion = '2.0'; $xml = " @@ -125,7 +126,7 @@ public function testApiVersion() $this->assertEquals($apiVersion, $response->getVersion()); } - public function testIsConnectionWorking() + public function testIsConnectionWorking(): void { $xmlSuccess = ' SUCCESS @@ -158,12 +159,67 @@ public function testIsConnectionWorking() $this->assertEquals(BigBlueButton::CONNECTION_ERROR_BASEURL, $this->bbb->getConnectionError()); } + /* Get meeting info */ + + public function testGetMeetingInfoUrl(): void + { + $meetingId = $this->faker->uuid; + + $url = $this->bbb->getMeetingInfoUrl(new GetMeetingInfoParameters($meetingId)); + $this->assertStringContainsString('='.rawurlencode($meetingId), $url); + } + + public function testGetMeetingInfo(): void + { + $meetingId = $this->faker->uuid; + + $xml = ' + SUCCESS + Demo Meeting + '.$meetingId.' + 79fd9d83ffdfe7d1fcfb19feab08d283ad518e49-1710416871174 + 1710416871174 + Thu Mar 14 11:47:51 UTC 2024 + 180621383 + 18632080022 + ap + mp + false + 540 + false + false + false + 1710416871176 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + false + '; + + $this->transport->method('request')->willReturn(new TransportResponse($xml, null)); + + $result = $this->bbb->getMeetingInfo(new GetMeetingInfoParameters($meetingId)); + $this->assertEquals('SUCCESS', $result->getReturnCode()); + $this->assertTrue($result->success()); + + $meeting = $result->getMeeting(); + + $this->assertEquals($meetingId, $meeting->getMeetingId()); + $this->assertEquals('Demo Meeting', $meeting->getMeetingName()); + } + /* Create Meeting */ /** * Test create meeting URL. */ - public function testCreateMeetingUrl() + public function testCreateMeetingUrl(): void { $params = $this->generateCreateParams(); $url = $this->bbb->getCreateMeetingUrl($this->getCreateMock($params)); @@ -176,22 +232,17 @@ public function testCreateMeetingUrl() /** * Test create join meeting URL. */ - public function testCreateJoinMeetingUrl() + public function testCreateJoinMeetingUrl(): void { $joinMeetingParams = $this->generateJoinMeetingParams(); $joinMeetingMock = $this->getJoinMeetingMock($joinMeetingParams); $url = $this->bbb->getJoinMeetingURL($joinMeetingMock); - foreach ($joinMeetingParams as $key => $value) { - if (\is_bool($value)) { - $value = $value ? 'true' : 'false'; - } - $this->assertStringContainsString(rawurlencode($key).'='.rawurlencode($value), $url); - } + $this->assertUrlContainsAllRequestParameters($url, $joinMeetingParams); } - public function testJoinMeeting() + public function testJoinMeeting(): void { $joinMeetingParams = $this->generateJoinMeetingParams(); $params = $this->getJoinMeetingMock($joinMeetingParams); @@ -227,19 +278,15 @@ public function testJoinMeeting() /** * Test generate end meeting URL. */ - public function testCreateEndMeetingUrl() + public function testCreateEndMeetingUrl(): void { $params = $this->generateEndMeetingParams(); $url = $this->bbb->getEndMeetingURL($this->getEndMeetingMock($params)); - foreach ($params as $key => $value) { - if (\is_bool($value)) { - $value = $value ? 'true' : 'false'; - } - $this->assertStringContainsString(rawurlencode($key).'='.rawurlencode($value), $url); - } + + $this->assertUrlContainsAllRequestParameters($url, $params); } - public function testEndMeeting() + public function testEndMeeting(): void { $data = $this->generateEndMeetingParams(); $params = $this->getEndMeetingMock($data); @@ -259,13 +306,13 @@ public function testEndMeeting() /* Get Meetings */ - public function testGetMeetingsUrl() + public function testGetMeetingsUrl(): void { $url = $this->bbb->getMeetingsUrl(); $this->assertStringContainsString(ApiMethod::GET_MEETINGS, $url); } - public function testGetMeetings() + public function testGetMeetings(): void { $xml = ' SUCCESS @@ -319,36 +366,128 @@ public function testGetMeetings() $this->assertFalse($response->getMeetings()[0]->hasUserJoined()); } - /* Get meeting info */ + /* Get recordings */ - public function testGetRecordingsUrl() + public function testGetRecordingsUrl(): void { $url = $this->bbb->getRecordingsUrl(new GetRecordingsParameters()); $this->assertStringContainsString(ApiMethod::GET_RECORDINGS, $url); } - public function testPublishRecordingsUrl() + public function testGetRecordings(): void + { + $xml = ' + SUCCESS + + + f71d810b6e90a4a34ae02b8c7143e8733178578e-1462807897120 + 9d287cf50490ca856ca5273bd303a7e321df6051-4-119 + + true + published + 1462807897120 + 1462812873004 + + + + + + + + + + + + + + presentation + http://test-install.blindsidenetworks.com/playback/presentation/0.9.0/playback.html?meetingId=f71d810b6e90a4a34ae02b8c7143e8733178578e-1462807897120 + 44 + + + + + '; + + $this->transport->method('request')->willReturn(new TransportResponse($xml, null)); + + $response = $this->bbb->getRecordings(new GetRecordingsParameters()); + + $this->assertCount(1, $response->getRecords()); + $recording = $response->getRecords()[0]; + $this->assertEquals('f71d810b6e90a4a34ae02b8c7143e8733178578e-1462807897120', $recording->getRecordID()); + $this->assertEquals('9d287cf50490ca856ca5273bd303a7e321df6051-4-119', $recording->getMeetingID()); + $this->assertEquals('SAT- Writing-Humanities (All participants)', $recording->getName()); + } + + /* Publish recordings */ + + public function testPublishRecordingsUrl(): void { $url = $this->bbb->getPublishRecordingsUrl(new PublishRecordingsParameters($this->faker->sha1, true)); $this->assertStringContainsString(ApiMethod::PUBLISH_RECORDINGS, $url); } - public function testDeleteRecordingsUrl() + public function testPublishRecordings(): void + { + $xml = ' + SUCCESS + true + '; + + $this->transport->method('request')->willReturn(new TransportResponse($xml, null)); + + $result = $this->bbb->publishRecordings(new PublishRecordingsParameters($this->faker->sha1, true)); + + $this->assertTrue($result->isPublished()); + } + + /* Delete recordings */ + + public function testDeleteRecordingsUrl(): void { $url = $this->bbb->getDeleteRecordingsUrl(new DeleteRecordingsParameters($this->faker->sha1)); $this->assertStringContainsString(ApiMethod::DELETE_RECORDINGS, $url); } - public function testUpdateRecordingsUrl() + public function testDeleteRecordings(): void + { + $xml = ' + SUCCESS + true + '; + + $this->transport->method('request')->willReturn(new TransportResponse($xml, null)); + + $result = $this->bbb->deleteRecordings(new DeleteRecordingsParameters($this->faker->sha1)); + + $this->assertTrue($result->isDeleted()); + } + + /* Update recordings */ + + public function testUpdateRecordingsUrl(): void { $params = $this->generateUpdateRecordingsParams(); $url = $this->bbb->getUpdateRecordingsUrl($this->getUpdateRecordingsParamsMock($params)); - foreach ($params as $key => $value) { - if (\is_bool($value)) { - $value = $value ? 'true' : 'false'; - } - $this->assertStringContainsString(rawurlencode($key).'='.rawurlencode($value), $url); - } + + $this->assertUrlContainsAllRequestParameters($url, $params); + } + + public function testUpdateRecordings(): void + { + $params = $this->generateUpdateRecordingsParams(); + + $xml = ' + SUCCESS + true + '; + + $this->transport->method('request')->willReturn(new TransportResponse($xml, null)); + + $result = $this->bbb->updateRecordings($this->getUpdateRecordingsParamsMock($params)); + + $this->assertTrue($result->isUpdated()); } public function testBuildUrl(): void diff --git a/tests/unit/Responses/GetRecordingsResponseTest.php b/tests/unit/Responses/GetRecordingsResponseTest.php index d405ba12..7f79c393 100644 --- a/tests/unit/Responses/GetRecordingsResponseTest.php +++ b/tests/unit/Responses/GetRecordingsResponseTest.php @@ -118,4 +118,18 @@ public function testImagePreviews(): void $newPreviews = $formats[1]->getImagePreviews(); $this->assertTrue($previews[0] === $newPreviews[0]); } + + public function testHasNoRecordings(): void + { + $xml = ' + SUCCESS + + noRecordings + There are no recordings for the meeting(s). + '; + + $response = new GetRecordingsResponse(simplexml_load_string($xml)); + + $this->assertTrue($response->hasNoRecordings()); + } } From 1de69d773442bc933fa38a684260491f5441f968 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Thu, 14 Mar 2024 23:16:29 +0100 Subject: [PATCH 30/68] Remove deprecations (#172) * Remove deprecations * Remove passwords in CreateMeetingResponse * Remove deprecations --- README.md | 13 +- src/BigBlueButton.php | 14 +- src/Core/Meeting.php | 28 ---- src/Enum/Feature.php | 10 -- src/Parameters/CreateMeetingParameters.php | 152 +----------------- src/Parameters/EndMeetingParameters.php | 37 +---- src/Parameters/JoinMeetingParameters.php | 70 +------- src/Responses/CreateMeetingResponse.php | 16 -- src/Responses/DeleteRecordingsResponse.php | 9 -- tests/TestCase.php | 64 +++----- .../AbstractBigBlueButtonFunctionalTest.php | 27 ++-- tests/unit/BigBlueButtonTest.php | 46 +----- .../CreateMeetingParametersTest.php | 36 +---- .../Parameters/EndMeetingParametersTest.php | 29 +--- .../Parameters/JoinMeetingParametersTest.php | 46 +----- .../Responses/CreateMeetingResponseTest.php | 9 +- .../Responses/GetMeetingInfoResponseTest.php | 14 +- .../Responses/GetMeetingsResponseTest.php | 12 +- 18 files changed, 76 insertions(+), 556 deletions(-) diff --git a/README.md b/README.md index ff22d717..9b29b0ef 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ $bbb = new BigBlueButton($apiUrl, $apiSecret); If you didn't use composer before, make sure that you include `vendor/autoload.php`. -In general the usage is closly related to the official [API description](https://docs.bigbluebutton.org/dev/api.html). This means to create a room, you have to create a `CreateMeetingParameters` object and set all required parameters via the related setter method. This means to set the `attendeePW`, you have to call `setAttendeePW` and so on. +In general the usage is closly related to the official [API description](https://docs.bigbluebutton.org/dev/api.html). This means to create a room, you have to create a `CreateMeetingParameters` object and set all required parameters via the related setter method. #### Test if API url and secret are valid ```php @@ -126,8 +126,6 @@ $version = $bbb->getApiVersion()->getVersion(); use BigBlueButton\Parameters\CreateMeetingParameters; $createMeetingParams = new CreateMeetingParameters($meetingID, $meetingName); -$createMeetingParams->setAttendeePW($attendee_password); -$createMeetingParams->setModeratorPW($moderator_password); $createMeetingResponse = $bbb->createMeeting($createMeetingParams); @@ -155,10 +153,10 @@ $createMeetingParams->setGuestPolicyAlwaysAcceptAuth(); #### Join a meeting ```php use BigBlueButton\Parameters\JoinMeetingParameters; +use BigBlueButton\Enum\Role; -$joinMeetingParams = new JoinMeetingParameters($room->uid, $displayname, $password); +$joinMeetingParams = new JoinMeetingParameters($room->uid, $displayname, Role::VIEWER); $joinMeetingParams->setCreateTime($createMeetingResponse->getCreationTime()); -$joinMeetingParams->setJoinViaHtml5(true); $joinMeetingParams->setRedirect(true); $joinUrl = $bbb->getJoinMeetingURL($joinMeetingParams); @@ -170,7 +168,7 @@ $joinUrl = $bbb->getJoinMeetingURL($joinMeetingParams); ```php use BigBlueButton\Parameters\EndMeetingParameters; -$endMeetingParams = new EndMeetingParameters($meetingID, $moderator_password); +$endMeetingParams = new EndMeetingParameters($meetingID); $response = $bbb->endMeeting($endMeetingParams); ``` @@ -206,7 +204,7 @@ if ($response->success() && $response->isRunning()) { ```php use BigBlueButton\Parameters\GetMeetingInfoParameters; -$getMeetingInfoParams = new GetMeetingInfoParameters($meetingID, $moderator_password); +$getMeetingInfoParams = new GetMeetingInfoParameters($meetingID); $response = $bbb->getMeetingInfo($getMeetingInfoParams); @@ -483,4 +481,3 @@ composer test-integration Bugs and feature request are tracked on [GitHub](https://github.com/littleredbutton/bigbluebutton-api-php/issues) [BigBlueButton API]: https://docs.bigbluebutton.org/dev/api.html - diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index b8993dfd..177d5f1a 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -419,23 +419,13 @@ public function hooksCreate(HooksCreateParameters $hookCreateParams): HooksCreat return new HooksCreateResponse($xml); } - public function getHooksListUrl(?HooksListParameters $hooksListParameters = null): string + public function getHooksListUrl(HooksListParameters $hooksListParameters): string { - if ($hooksListParameters === null) { - @trigger_error(sprintf('Not passing the $hooksListParameters parameter to "%s::getHooksListUrl()" is deprecated since 5.4 and will be required in 6.0.', self::class), \E_USER_DEPRECATED); - $hooksListParameters = new HooksListParameters(); - } - return $this->urlBuilder->buildUrl(ApiMethod::HOOKS_LIST, $hooksListParameters->getHTTPQuery()); } - public function hooksList(?HooksListParameters $hooksListParameters = null): HooksListResponse + public function hooksList(HooksListParameters $hooksListParameters): HooksListResponse { - if ($hooksListParameters === null) { - @trigger_error(sprintf('Not passing the $hooksListParameters parameter to "%s::hooksList()" is deprecated since 5.4 and will be required in 6.0.', self::class), \E_USER_DEPRECATED); - $hooksListParameters = new HooksListParameters(); - } - $xml = $this->processXmlResponse($this->getHooksListUrl($hooksListParameters)); return new HooksListResponse($xml); diff --git a/src/Core/Meeting.php b/src/Core/Meeting.php index 24a98cf7..44af74bc 100644 --- a/src/Core/Meeting.php +++ b/src/Core/Meeting.php @@ -62,16 +62,6 @@ class Meeting */ private $dialNumber; - /** - * @var string|null - */ - private $attendeePassword; - - /** - * @var string|null - */ - private $moderatorPassword; - /** * @var bool */ @@ -166,8 +156,6 @@ public function __construct(\SimpleXMLElement $xml) $this->creationDate = $xml->createDate->__toString(); $this->voiceBridge = (int) $xml->voiceBridge; $this->dialNumber = $xml->dialNumber->__toString(); - $this->attendeePassword = $xml->attendeePW->__toString(); - $this->moderatorPassword = $xml->moderatorPW->__toString(); $this->hasBeenForciblyEnded = $xml->hasBeenForciblyEnded->__toString() === 'true'; $this->isRunning = $xml->running->__toString() === 'true'; $this->participantCount = (int) $xml->participantCount; @@ -215,22 +203,6 @@ public function getDialNumber(): string return $this->dialNumber; } - /** - * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. - */ - public function getAttendeePassword(): string - { - return $this->attendeePassword; - } - - /** - * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. - */ - public function getModeratorPassword(): string - { - return $this->moderatorPassword; - } - public function hasBeenForciblyEnded(): bool { return $this->hasBeenForciblyEnded; diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php index 7b811bcb..ecc9bde1 100644 --- a/src/Enum/Feature.php +++ b/src/Enum/Feature.php @@ -46,14 +46,4 @@ class Feature extends Enum public const DOWNLOAD_PRESENTATION_ORIGINAL_FILE = 'downloadPresentationOriginalFile'; public const DOWNLOAD_PRESENTATION_CONVERTED_TO_PDF = 'downloadPresentationConvertedToPdf'; public const TIMER = 'timer'; - - /** - * @deprecated Use Feature::IMPORT_PRESENTATION_WITH_ANNOTATIONS_FROM_BREAKOUT_ROOMS instead - */ - public const IMPORT_PRESENTATION_WITHANNOTATIONS_FROM_BREAKOUTROOMS = 'importPresentationWithAnnotationsFromBreakoutRooms'; - - /** - * @deprecated Use Feature::IMPORT_SHARED_NOTES_FROM_BREAKOUT_ROOMS instead - */ - public const IMPORT_SHARED_NOTES_FROM_BREAKOUTROOMS = 'importSharedNotesFromBreakoutRooms'; } diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index ab87f1e2..e27a5a63 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -1,4 +1,5 @@ isBreakout; } - /** - * @deprecated use disabledFeatures instead - * Backwards compatibility for the old method name with the missing 's' at the end - */ - public function setLockSettingsDisableNote(bool $isLockSettingsDisableNote): self - { - $this->isLockSettingsDisableNotes = $isLockSettingsDisableNote; - - return $this; - } - - /** - * @deprecated use disabledFeatures instead - * Backwards compatibility for the old method name with the missing 's' at the end - */ - public function isLockSettingsDisableNote(): bool - { - return $this->isLockSettingsDisableNotes; - } - - /** - * @deprecated Use disabledFeatures instead - */ - public function setLearningDashboardEnabled(bool $learningDashboardEnabled): self - { - $this->learningDashboardEnabled = $learningDashboardEnabled; - - return $this; - } - - /** - * @deprecated Use disabledFeatures instead - */ - public function isLearningDashboardEnabled(): bool - { - return $this->learningDashboardEnabled; - } - - /** - * @deprecated Use disabledFeatures instead - */ - public function setVirtualBackgroundsDisabled(bool $virtualBackgroundsDisabled): self - { - $this->virtualBackgroundsDisabled = $virtualBackgroundsDisabled; - - return $this; - } - - /** - * @deprecated Use disabledFeatures instead - */ - public function isVirtualBackgroundsDisabled(): bool - { - return $this->virtualBackgroundsDisabled; - } - - /** - * @deprecated Use disabledFeatures instead - */ - public function setBreakoutRoomsEnabled(bool $breakoutRoomsEnabled): self - { - $this->breakoutRoomsEnabled = $breakoutRoomsEnabled; - - return $this; - } - - /** - * @deprecated Use disabledFeatures instead - */ - public function isBreakoutRoomsEnabled(): bool - { - return $this->breakoutRoomsEnabled; - } - public function isUserCameraCapDisabled(): bool { return $this->userCameraCap === 0; @@ -707,58 +609,6 @@ public function getPresentationsAsXML() return $result; } - /** - * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. - */ - public function getAttendeePW(): string - { - if (null === $this->attendeePW) { - throw new \RuntimeException(sprintf('Attendee password was not passed to "%s".', self::class)); - } - - return $this->attendeePW; - } - - /** - * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. - * - * @return $this - */ - public function setAttendeePW(string $attendeePW): self - { - @trigger_error(sprintf('Passing a attendee password to "%s::setAttendeePW()" is deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the attendee password to create a meeting.', self::class), \E_USER_DEPRECATED); - - $this->attendeePW = $attendeePW; - - return $this; - } - - /** - * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. - */ - public function getModeratorPW(): string - { - if (null === $this->moderatorPW) { - throw new \RuntimeException(sprintf('Moderator password was not passed to "%s".', self::class)); - } - - return $this->moderatorPW; - } - - /** - * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. - * - * @return $this - */ - public function setModeratorPW(string $moderatorPW): self - { - @trigger_error(sprintf('Passing a moderator password to "%s::setModeratorPW()" is deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the moderator password to create a meeting.', self::class), \E_USER_DEPRECATED); - - $this->moderatorPW = $moderatorPW; - - return $this; - } - public function getHTTPQuery(): string { $queries = $this->getHTTPQueryArray(); diff --git a/src/Parameters/EndMeetingParameters.php b/src/Parameters/EndMeetingParameters.php index c2e23366..c1644075 100644 --- a/src/Parameters/EndMeetingParameters.php +++ b/src/Parameters/EndMeetingParameters.php @@ -1,4 +1,5 @@ password = $password; $this->meetingID = $meetingID; } - - /** - * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. - */ - public function getPassword(): string - { - if (null === $this->password) { - throw new \RuntimeException(sprintf('Password was not passed to "%s".', self::class)); - } - - return $this->password; - } - - /** - * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. - * - * @return $this - */ - public function setPassword(string $password): self - { - $this->password = $password; - - return $this; - } } diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index 6417f22f..39dd1891 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -1,4 +1,5 @@ meetingID = $meetingID; $this->fullName = $fullName; - - if (Role::MODERATOR === $passwordOrRole || Role::VIEWER === $passwordOrRole) { - $this->role = $passwordOrRole; - } else { - $this->password = $passwordOrRole; - } - } - - /** - * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. - */ - public function getPassword(): string - { - if (null === $this->password) { - throw new \RuntimeException(sprintf('Password was not passed to "%s".', self::class)); - } - - return $this->password; - } - - /** - * @deprecated since 5.1 and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter. - * - * @return $this - */ - public function setPassword(string $password): self - { - $this->password = $password; - - return $this; - } - - /** - * @deprecated since 5.1 and will be removed in 6.0. Old BigBlueButton flash client parameter. - */ - public function getConfigToken(): ?string - { - return $this->configToken; - } - - /** - * @deprecated since 5.1 and will be removed in 6.0. Old BigBlueButton flash client parameter. - * - * @return $this - */ - public function setConfigToken(string $configToken): self - { - $this->configToken = $configToken; - - return $this; + $this->role = $role; } } diff --git a/src/Responses/CreateMeetingResponse.php b/src/Responses/CreateMeetingResponse.php index 46526b73..c109e7e6 100644 --- a/src/Responses/CreateMeetingResponse.php +++ b/src/Responses/CreateMeetingResponse.php @@ -43,22 +43,6 @@ public function getParentMeetingId(): string return $this->rawXml->parentMeetingID->__toString(); } - /** - * @deprecated and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter in api requests. - */ - public function getAttendeePassword(): string - { - return $this->rawXml->attendeePW->__toString(); - } - - /** - * @deprecated and will be removed in 6.0. Recent BigBlueButton versions does not require the password parameter in api requests. - */ - public function getModeratorPassword(): string - { - return $this->rawXml->moderatorPW->__toString(); - } - /** * Creation timestamp. * diff --git a/src/Responses/DeleteRecordingsResponse.php b/src/Responses/DeleteRecordingsResponse.php index c46d7bb8..b7efd8f1 100644 --- a/src/Responses/DeleteRecordingsResponse.php +++ b/src/Responses/DeleteRecordingsResponse.php @@ -24,9 +24,6 @@ */ class DeleteRecordingsResponse extends BaseResponse { - /** @deprecated and will be removed in 6.0. Use KEY_NOT_FOUND instead */ - public const KEY_INVALID_ID = 'InvalidRecordingId'; - public const KEY_NOT_FOUND = 'notFound'; public function isDeleted(): bool @@ -34,12 +31,6 @@ public function isDeleted(): bool return $this->rawXml->deleted->__toString() == 'true'; } - /** @deprecated and will be removed in 6.0. Use isNotFound instead */ - public function isInvalidId(): bool - { - return $this->getMessageKey() === self::KEY_INVALID_ID; - } - public function isNotFound(): bool { return $this->getMessageKey() === self::KEY_NOT_FOUND; diff --git a/tests/TestCase.php b/tests/TestCase.php index 9696c4c4..f8322812 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,4 +1,5 @@ $this->faker->name, 'meetingID' => $this->faker->uuid, - 'attendeePW' => $this->faker->password, - 'moderatorPW' => $this->faker->password, 'autoStartRecording' => $this->faker->boolean(50), 'dialNumber' => $this->faker->phoneNumber, 'voiceBridge' => $this->faker->randomNumber(5, true), @@ -92,7 +91,7 @@ protected function generateCreateParams() 'lockSettingsDisableMic' => $this->faker->boolean(50), 'lockSettingsDisablePrivateChat' => $this->faker->boolean(50), 'lockSettingsDisablePublicChat' => $this->faker->boolean(50), - 'lockSettingsDisableNote' => $this->faker->boolean(50), + 'lockSettingsDisableNotes' => $this->faker->boolean(50), 'lockSettingsHideUserList' => $this->faker->boolean(50), 'lockSettingsLockedLayout' => $this->faker->boolean(50), 'lockSettingsLockOnJoin' => $this->faker->boolean(50), @@ -110,19 +109,16 @@ protected function generateCreateParams() 'endWhenNoModerator' => $this->faker->boolean(50), 'endWhenNoModeratorDelayInMinutes' => $this->faker->numberBetween(1, 100), 'meetingLayout' => $this->faker->randomElement([ - MeetingLayout::CUSTOM_LAYOUT, - MeetingLayout::SMART_LAYOUT, - MeetingLayout::PRESENTATION_FOCUS, - MeetingLayout::VIDEO_FOCUS, - ]), - 'learningDashboardEnabled' => $this->faker->boolean(50), + MeetingLayout::CUSTOM_LAYOUT, + MeetingLayout::SMART_LAYOUT, + MeetingLayout::PRESENTATION_FOCUS, + MeetingLayout::VIDEO_FOCUS, + ]), 'learningDashboardCleanupDelayInMinutes' => $this->faker->numberBetween(1, 100), - 'breakoutRoomsEnabled' => $this->faker->boolean(50), 'breakoutRoomsPrivateChatEnabled' => $this->faker->boolean(50), 'meetingEndedURL' => $this->faker->url, 'breakoutRoomsRecord' => $this->faker->boolean(50), 'allowRequestsWithoutSession' => $this->faker->boolean(50), - 'virtualBackgroundsDisabled' => $this->faker->boolean(50), 'userCameraCap' => $this->faker->numberBetween(1, 5), 'groups' => $this->generateBreakoutRoomsGroups(), ]; @@ -185,7 +181,7 @@ protected function getCreateMock($params) ->setLockSettingsDisableMic($params['lockSettingsDisableMic']) ->setLockSettingsDisablePrivateChat($params['lockSettingsDisablePrivateChat']) ->setLockSettingsDisablePublicChat($params['lockSettingsDisablePublicChat']) - ->setLockSettingsDisableNote($params['lockSettingsDisableNote']) + ->setLockSettingsDisableNotes($params['lockSettingsDisableNotes']) ->setLockSettingsHideUserList($params['lockSettingsHideUserList']) ->setLockSettingsLockedLayout($params['lockSettingsLockedLayout']) ->setLockSettingsLockOnJoin($params['lockSettingsLockOnJoin']) @@ -202,26 +198,15 @@ protected function getCreateMock($params) ->setMeetingEndedURL($params['meetingEndedURL']) ->setMeetingLayout($params['meetingLayout']) ->setMeetingKeepEvents($params['meetingKeepEvents']) - ->setLearningDashboardEnabled($params['learningDashboardEnabled']) ->setLearningDashboardCleanupDelayInMinutes($params['learningDashboardCleanupDelayInMinutes']) ->setAllowModsToEjectCameras($params['allowModsToEjectCameras']) - ->setBreakoutRoomsEnabled($params['breakoutRoomsEnabled']) ->setBreakoutRoomsPrivateChatEnabled($params['breakoutRoomsPrivateChatEnabled']) ->setBreakoutRoomsRecord($params['breakoutRoomsRecord']) ->setAllowRequestsWithoutSession($params['allowRequestsWithoutSession']) - ->setVirtualBackgroundsDisabled($params['virtualBackgroundsDisabled']) ->setUserCameraCap($params['userCameraCap']) ->setDisabledFeatures($params['disabledFeatures']) ->setDisabledFeaturesExclude($params['disabledFeaturesExclude']); - if (isset($params['moderatorPW'])) { - $createMeetingParams->setModeratorPW($params['moderatorPW']); - } - - if (isset($params['attendeePW'])) { - $createMeetingParams->setAttendeePW($params['attendeePW']); - } - foreach ($params['groups'] as $group) { $createMeetingParams->addBreakoutRoomsGroup($group['id'], $group['name'], $group['roster']); } @@ -236,8 +221,7 @@ protected function getBreakoutCreateMock($params) { $createMeetingParams = $this->getCreateMock($params); - return $createMeetingParams->setBreakout($params['isBreakout'])->setParentMeetingID($params['parentMeetingId'])-> - setSequence($params['sequence'])->setFreeJoin($params['freeJoin']); + return $createMeetingParams->setBreakout($params['isBreakout'])->setParentMeetingID($params['parentMeetingId'])->setSequence($params['sequence'])->setFreeJoin($params['freeJoin']); } /** @@ -245,17 +229,17 @@ protected function getBreakoutCreateMock($params) */ protected function generateJoinMeetingParams() { - return ['meetingID' => $this->faker->uuid, - 'fullName' => $this->faker->name, - 'role' => $this->faker->randomElement(Role::getValues()), - 'userID' => $this->faker->numberBetween(1, 1000), - 'webVoiceConf' => $this->faker->word, - 'createTime' => $this->faker->unixTime, - 'configToken' => $this->faker->word, - 'errorRedirectUrl' => $this->faker->url, - 'userdata-countrycode' => $this->faker->countryCode, - 'userdata-email' => $this->faker->email, - 'userdata-commercial' => false, + return [ + 'meetingID' => $this->faker->uuid, + 'fullName' => $this->faker->name, + 'role' => $this->faker->randomElement(Role::getValues()), + 'userID' => $this->faker->numberBetween(1, 1000), + 'webVoiceConf' => $this->faker->word, + 'createTime' => $this->faker->unixTime, + 'errorRedirectUrl' => $this->faker->url, + 'userdata-countrycode' => $this->faker->countryCode, + 'userdata-email' => $this->faker->email, + 'userdata-commercial' => false, ]; } @@ -273,7 +257,6 @@ protected function getJoinMeetingMock($params) ->setWebVoiceConf($params['webVoiceConf']) ->setCreateTime($params['createTime']) ->setErrorRedirectUrl($params['errorRedirectUrl']) - ->setConfigToken($params['configToken']) ->addUserData('countrycode', $params['userdata-countrycode']) ->addUserData('email', $params['userdata-email']) ->addUserData('commercial', $params['userdata-commercial']); @@ -284,8 +267,9 @@ protected function getJoinMeetingMock($params) */ protected function generateEndMeetingParams() { - return ['meetingID' => $this->faker->uuid, - 'password' => $this->faker->password, ]; + return [ + 'meetingID' => $this->faker->uuid, + ]; } /** @@ -295,7 +279,7 @@ protected function generateEndMeetingParams() */ protected function getEndMeetingMock($params) { - return new EndMeetingParameters($params['meetingID'], $params['password']); + return new EndMeetingParameters($params['meetingID']); } /** diff --git a/tests/functional/AbstractBigBlueButtonFunctionalTest.php b/tests/functional/AbstractBigBlueButtonFunctionalTest.php index 3d2deafc..c7493d3f 100644 --- a/tests/functional/AbstractBigBlueButtonFunctionalTest.php +++ b/tests/functional/AbstractBigBlueButtonFunctionalTest.php @@ -1,4 +1,5 @@ assertTrue($result->success()); // Cleanup - $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId())); } /** @@ -138,7 +139,7 @@ public function testCreateMeetingWithDocumentUrl() $this->assertTrue($result->success()); // Cleanup - $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId())); } /** @@ -156,7 +157,7 @@ public function testCreateMeetingWithDocumentUrlAndFileName() $this->assertTrue($result->success()); // Cleanup - $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId())); } /** @@ -174,7 +175,7 @@ public function testCreateMeetingWithDocumentEmbedded() $this->assertTrue($result->success()); // Cleanup - $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId())); } /** @@ -193,7 +194,7 @@ public function testCreateMeetingWithMultiDocument() $this->assertTrue($result->success()); // Cleanup - $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId())); } /* Join Meeting */ @@ -219,8 +220,8 @@ public function testJoinMeeting() $this->assertEquals('SUCCESS', $result->getReturnCode(), 'Create meeting'); $creationTime = $result->getCreationTime(); - $joinMeetingParams = $this->generateJoinMeetingParams(); - $joinMeetingParams = new JoinMeetingParameters($result->getMeetingId(), 'Foobar', $result->getAttendeePassword()); + $params = $this->generateJoinMeetingParams(); + $joinMeetingParams = new JoinMeetingParameters($result->getMeetingId(), $params['fullName'], $params['role']); $joinMeetingParams->setRedirect(false); $joinMeetingParams->setCreateTime(sprintf('%.0f', $creationTime)); @@ -234,7 +235,7 @@ public function testJoinMeeting() $this->assertNotEmpty($joinMeeting->getUrl()); // Cleanup - $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId(), $result->getModeratorPassword())); + $this->bbb->endMeeting(new EndMeetingParameters($result->getMeetingId())); } /* End Meeting */ @@ -254,7 +255,7 @@ public function testEndMeeting() { $meeting = $this->createRealMeeting($this->bbb); - $endMeeting = new EndMeetingParameters($meeting->getMeetingId(), $meeting->getModeratorPassword()); + $endMeeting = new EndMeetingParameters($meeting->getMeetingId()); $result = $this->bbb->endMeeting($endMeeting); $this->assertEquals('SUCCESS', $result->getReturnCode()); $this->assertTrue($result->success()); @@ -294,7 +295,7 @@ public function testGetMeetings() $this->assertNotEmpty($result->getMeetings()); // Cleanup - $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId(), $meeting->getModeratorPassword())); + $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId())); } /* Get meeting info */ @@ -307,19 +308,19 @@ public function testGetMeetingInfoUrl(): void $this->assertStringContainsString('='.rawurlencode($meeting->getMeetingId()), $url); // Cleanup - $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId(), $meeting->getModeratorPassword())); + $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId())); } public function testGetMeetingInfo() { $meeting = $this->createRealMeeting($this->bbb); - $result = $this->bbb->getMeetingInfo(new GetMeetingInfoParameters($meeting->getMeetingId(), $meeting->getModeratorPassword())); + $result = $this->bbb->getMeetingInfo(new GetMeetingInfoParameters($meeting->getMeetingId())); $this->assertEquals('SUCCESS', $result->getReturnCode()); $this->assertTrue($result->success()); // Cleanup - $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId(), $meeting->getModeratorPassword())); + $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId())); } public function testGetRecordingsUrl(): void diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index 3373a54b..1ad770dd 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -1,4 +1,5 @@ assertEquals('Tue Jul 10 16:47:38 UTC 2018', $response->getMeetings()[0]->getCreationDate()); $this->assertEquals('70066', $response->getMeetings()[0]->getVoiceBridge()); $this->assertEquals('613-555-1234', $response->getMeetings()[0]->getDialNumber()); - $this->assertEquals('ap', $response->getMeetings()[0]->getAttendeePassword()); - $this->assertEquals('mp', $response->getMeetings()[0]->getModeratorPassword()); $this->assertFalse($response->getMeetings()[0]->isRunning()); $this->assertEquals(0, $response->getMeetings()[0]->getDuration()); $this->assertFalse($response->getMeetings()[0]->hasUserJoined()); @@ -525,38 +524,6 @@ public function testHooksList(): void $this->assertFalse($globalHook->hasRawData()); } - /** - * @group legacy - */ - public function testHooksListWithoutParameter(): void - { - $xml = ' - SUCCESS - - - 1 - - - false - false - - - 2 - - false - false - - - '; - - $this->transport->method('request')->willReturn(new TransportResponse($xml, null)); - - $response = $this->bbb->hooksList(); - - $this->assertTrue($response->success()); - $this->assertCount(2, $response->getHooks()); - } - public function testHooksListUrl(): void { // Test without meeting ID @@ -574,17 +541,6 @@ public function testHooksListUrl(): void $this->assertStringContainsString('meetingID=foobar', $url); } - /** - * @group legacy - */ - public function testHooksListUrlWithoutParameter(): void - { - $url = $this->bbb->getHooksListUrl(); - - $this->assertStringContainsString(ApiMethod::HOOKS_LIST, $url); - $this->assertStringNotContainsString('meetingID=', $url); - } - public function testHookDestroy(): void { $params = new HooksDestroyParameters(1); diff --git a/tests/unit/Parameters/CreateMeetingParametersTest.php b/tests/unit/Parameters/CreateMeetingParametersTest.php index 5ecfd611..5a85387c 100644 --- a/tests/unit/Parameters/CreateMeetingParametersTest.php +++ b/tests/unit/Parameters/CreateMeetingParametersTest.php @@ -1,4 +1,5 @@ assertEquals($params['name'], $createMeetingParams->getName()); $this->assertEquals($params['meetingID'], $createMeetingParams->getMeetingID()); - $this->assertEquals($params['attendeePW'], $createMeetingParams->getAttendeePW()); - $this->assertEquals($params['moderatorPW'], $createMeetingParams->getModeratorPW()); $this->assertEquals($params['autoStartRecording'], $createMeetingParams->isAutoStartRecording()); $this->assertEquals($params['dialNumber'], $createMeetingParams->getDialNumber()); $this->assertEquals($params['voiceBridge'], $createMeetingParams->getVoiceBridge()); @@ -56,7 +55,7 @@ public function testCreateMeetingParameters() $this->assertEquals($params['lockSettingsDisableMic'], $createMeetingParams->isLockSettingsDisableMic()); $this->assertEquals($params['lockSettingsDisablePrivateChat'], $createMeetingParams->isLockSettingsDisablePrivateChat()); $this->assertEquals($params['lockSettingsDisablePublicChat'], $createMeetingParams->isLockSettingsDisablePublicChat()); - $this->assertEquals($params['lockSettingsDisableNote'], $createMeetingParams->isLockSettingsDisableNote()); + $this->assertEquals($params['lockSettingsDisableNotes'], $createMeetingParams->isLockSettingsDisableNotes()); $this->assertEquals($params['lockSettingsLockedLayout'], $createMeetingParams->isLockSettingsLockedLayout()); $this->assertEquals($params['lockSettingsHideUserList'], $createMeetingParams->isLockSettingsHideUserList()); $this->assertEquals($params['lockSettingsLockOnJoin'], $createMeetingParams->isLockSettingsLockOnJoin()); @@ -66,9 +65,7 @@ public function testCreateMeetingParameters() $this->assertEquals($params['guestPolicy'], $createMeetingParams->getGuestPolicy()); $this->assertEquals($params['endWhenNoModerator'], $createMeetingParams->isEndWhenNoModerator()); $this->assertEquals($params['endWhenNoModeratorDelayInMinutes'], $createMeetingParams->getEndWhenNoModeratorDelayInMinutes()); - $this->assertEquals($params['learningDashboardEnabled'], $createMeetingParams->isLearningDashboardEnabled()); $this->assertEquals($params['learningDashboardCleanupDelayInMinutes'], $createMeetingParams->getLearningDashboardCleanupDelayInMinutes()); - $this->assertEquals($params['breakoutRoomsEnabled'], $createMeetingParams->isBreakoutRoomsEnabled()); $this->assertEquals($params['breakoutRoomsRecord'], $createMeetingParams->isBreakoutRoomsRecord()); $this->assertEquals($params['breakoutRoomsPrivateChatEnabled'], $createMeetingParams->isBreakoutRoomsPrivateChatEnabled()); $this->assertEquals($params['meetingEndedURL'], $createMeetingParams->getMeetingEndedURL()); @@ -82,14 +79,11 @@ public function testCreateMeetingParameters() $this->assertEquals($params['endWhenNoModerator'], $createMeetingParams->isEndWhenNoModerator()); $this->assertEquals($params['endWhenNoModeratorDelayInMinutes'], $createMeetingParams->getEndWhenNoModeratorDelayInMinutes()); $this->assertEquals($params['meetingLayout'], $createMeetingParams->getMeetingLayout()); - $this->assertEquals($params['learningDashboardEnabled'], $createMeetingParams->isLearningDashboardEnabled()); $this->assertEquals($params['learningDashboardCleanupDelayInMinutes'], $createMeetingParams->getLearningDashboardCleanupDelayInMinutes()); $this->assertEquals($params['allowModsToEjectCameras'], $createMeetingParams->isAllowModsToEjectCameras()); - $this->assertEquals($params['breakoutRoomsEnabled'], $createMeetingParams->isBreakoutRoomsEnabled()); $this->assertEquals($params['breakoutRoomsPrivateChatEnabled'], $createMeetingParams->isBreakoutRoomsPrivateChatEnabled()); $this->assertEquals($params['breakoutRoomsRecord'], $createMeetingParams->isBreakoutRoomsRecord()); $this->assertEquals($params['allowRequestsWithoutSession'], $createMeetingParams->isAllowRequestsWithoutSession()); - $this->assertEquals($params['virtualBackgroundsDisabled'], $createMeetingParams->isVirtualBackgroundsDisabled()); $this->assertEquals(json_encode($params['groups']), json_encode($createMeetingParams->getBreakoutRoomsGroups())); $this->assertEquals($params['disabledFeatures'], $createMeetingParams->getDisabledFeatures()); $this->assertEquals($params['disabledFeaturesExclude'], $createMeetingParams->getDisabledFeaturesExclude()); @@ -271,30 +265,4 @@ public function testGuestPolicyAskModerator(): void $this->assertSame(GuestPolicy::ASK_MODERATOR, $createMeetingParams->getGuestPolicy()); $this->assertTrue($createMeetingParams->isGuestPolicyAskModerator()); } - - /** - * @group legacy - */ - public function testCreateMeetingParametersWithoutAttendeePassword(): void - { - $params = $this->generateCreateParams(); - unset($params['attendeePW']); - $createMeetingParams = $this->getCreateMock($params); - - $this->expectException(\RuntimeException::class); - $createMeetingParams->getAttendeePW(); - } - - /** - * @group legacy - */ - public function testCreateMeetingParametersWithoutModeratorPassword(): void - { - $params = $this->generateCreateParams(); - unset($params['moderatorPW']); - $createMeetingParams = $this->getCreateMock($params); - - $this->expectException(\RuntimeException::class); - $createMeetingParams->getModeratorPW(); - } } diff --git a/tests/unit/Parameters/EndMeetingParametersTest.php b/tests/unit/Parameters/EndMeetingParametersTest.php index 45e0d12b..45a6e2cf 100644 --- a/tests/unit/Parameters/EndMeetingParametersTest.php +++ b/tests/unit/Parameters/EndMeetingParametersTest.php @@ -1,4 +1,5 @@ faker->uuid, $password = $this->faker->password()); + $endMeetingParams = new EndMeetingParameters($meetingId = $this->faker->uuid); $this->assertEquals($meetingId, $endMeetingParams->getMeetingID()); - $this->assertEquals($password, $endMeetingParams->getPassword()); // Test setters that are ignored by the constructor $endMeetingParams->setMeetingID($newId = $this->faker->uuid); - $endMeetingParams->setPassword($newPassword = $this->faker->password); $this->assertEquals($newId, $endMeetingParams->getMeetingID()); - $this->assertEquals($newPassword, $endMeetingParams->getPassword()); - } - - /** - * @group legacy - */ - public function testEndMeetingParametersWithoutPassword(): void - { - $endMeetingParams = new EndMeetingParameters($this->faker->uuid); - - $this->expectException(\RuntimeException::class); - - $endMeetingParams->getPassword(); - } - - /** - * @group legacy - */ - public function testEndMeetingParametersWithSetPassword(): void - { - $endMeetingParams = new EndMeetingParameters($this->faker->uuid); - - $endMeetingParams->setPassword($password = $this->faker->password); - $this->assertSame($password, $endMeetingParams->getPassword()); } } diff --git a/tests/unit/Parameters/JoinMeetingParametersTest.php b/tests/unit/Parameters/JoinMeetingParametersTest.php index b91aeb4f..45f5dbef 100644 --- a/tests/unit/Parameters/JoinMeetingParametersTest.php +++ b/tests/unit/Parameters/JoinMeetingParametersTest.php @@ -1,4 +1,5 @@ setMeetingID($newId = $this->faker->uuid); $joinMeetingParams->setFullName($newName = $this->faker->name); $joinMeetingParams->setRole($newRole = Role::VIEWER); - $joinMeetingParams->setConfigToken($configToken = $this->faker->md5); $joinMeetingParams->setAvatarURL($avatarUrl = $this->faker->url); $joinMeetingParams->setRedirect($redirect = $this->faker->boolean(50)); $joinMeetingParams->setClientURL($clientUrl = $this->faker->url); @@ -54,54 +54,10 @@ public function testJoinMeetingParameters(): void $this->assertEquals($newId, $joinMeetingParams->getMeetingID()); $this->assertEquals($newName, $joinMeetingParams->getFullName()); $this->assertEquals($newRole, $joinMeetingParams->getRole()); - $this->assertEquals($configToken, $joinMeetingParams->getConfigToken()); $this->assertEquals($avatarUrl, $joinMeetingParams->getAvatarURL()); $this->assertEquals($redirect, $joinMeetingParams->isRedirect()); $this->assertEquals($clientUrl, $joinMeetingParams->getClientURL()); $this->assertEquals($newErrorRedirectUrl, $joinMeetingParams->getErrorRedirectUrl()); $this->assertEquals($guest, $joinMeetingParams->isGuest()); } - - /** - * @group legacy - * Using the deprecated getPassword method, without setting the password in the constructor or using the setPassword method - */ - public function testJoinMeetingParametersWithoutPassword(): void - { - $params = $this->generateJoinMeetingParams(); - $joinMeetingParams = $this->getJoinMeetingMock($params); - - $this->expectException(\RuntimeException::class); - - $joinMeetingParams->getPassword(); - } - - /** - * @group legacy - * Using the deprecated getPassword method, with passing the password in the constructor - */ - public function testJoinMeetingParametersWithPassword(): void - { - $params = $this->generateJoinMeetingParams(); - // Legacy, allow users to pass a password as the third constructor parameter - $params['role'] = $this->faker->password; - $joinMeetingParams = $this->getJoinMeetingMock($params); - - // Check if the password is set and the role is null - $this->assertSame($params['role'], $joinMeetingParams->getPassword()); - $this->assertNull($joinMeetingParams->getRole()); - } - - /** - * @group legacy - * Using the deprecated getPassword method, with using the setPassword method - */ - public function testJoinMeetingParametersWithSetPassword(): void - { - $params = $this->generateJoinMeetingParams(); - $joinMeetingParams = $this->getJoinMeetingMock($params); - - $joinMeetingParams->setPassword($password = $this->faker->password); - $this->assertSame($password, $joinMeetingParams->getPassword()); - } } diff --git a/tests/unit/Responses/CreateMeetingResponseTest.php b/tests/unit/Responses/CreateMeetingResponseTest.php index 4780992e..146fa02a 100644 --- a/tests/unit/Responses/CreateMeetingResponseTest.php +++ b/tests/unit/Responses/CreateMeetingResponseTest.php @@ -1,4 +1,5 @@ assertEquals('random-1665177', $this->meeting->getMeetingId()); $this->assertEquals('1a6938c707cdf5d052958672d66c219c30690c47-1524212045514', $this->meeting->getInternalMeetingId()); $this->assertEquals('bbb-none', $this->meeting->getParentMeetingId()); - $this->assertEquals('tK6J5cJv3hMLNx5IBePa', $this->meeting->getAttendeePassword()); - $this->assertEquals('34Heu0uiZYqCZXX9C4m2', $this->meeting->getModeratorPassword()); $this->assertEquals(1453283819419, $this->meeting->getCreationTime()); $this->assertEquals(76286, $this->meeting->getVoiceBridge()); $this->assertEquals('Wed Jan 20 04:56:59 EST 2016', $this->meeting->getCreationDate()); @@ -65,8 +64,10 @@ public function testCreateMeetingResponseContent() public function testCreateMeetingResponseTypes() { - $this->assertEachGetterValueIsString($this->meeting, ['getReturnCode', 'getInternalMeetingId', 'getParentMeetingId', - 'getAttendeePassword', 'getModeratorPassword', 'getDialNumber', 'getCreationDate', ]); + $this->assertEachGetterValueIsString($this->meeting, [ + 'getReturnCode', 'getInternalMeetingId', 'getParentMeetingId', + 'getDialNumber', 'getCreationDate', + ]); $this->assertEachGetterValueIsDouble($this->meeting, ['getCreationTime']); $this->assertEachGetterValueIsInteger($this->meeting, ['getDuration', 'getVoiceBridge']); $this->assertEachGetterValueIsBoolean($this->meeting, ['hasUserJoined', 'hasBeenForciblyEnded']); diff --git a/tests/unit/Responses/GetMeetingInfoResponseTest.php b/tests/unit/Responses/GetMeetingInfoResponseTest.php index daae09c6..96526538 100644 --- a/tests/unit/Responses/GetMeetingInfoResponseTest.php +++ b/tests/unit/Responses/GetMeetingInfoResponseTest.php @@ -47,8 +47,6 @@ public function testGetMeetingInfoResponseContent() $this->assertEquals('Tue Jan 19 07:25:17 EST 2016', $info->getCreationDate()); $this->assertEquals(70100, $info->getVoiceBridge()); $this->assertEquals('613-555-1234', $info->getDialNumber()); - $this->assertEquals('dbfc7207321527bbb870c82028', $info->getAttendeePassword()); - $this->assertEquals('4bfbbeeb4a65cacaefe3676633', $info->getModeratorPassword()); $this->assertTrue($info->isRunning()); $this->assertEquals(20, $info->getDuration()); $this->assertTrue($info->hasUserJoined()); @@ -122,11 +120,15 @@ public function testGetMeetingInfoResponseTypes() { $info = $this->meetingInfo->getMeeting(); - $this->assertEachGetterValueIsString($info, ['getMeetingName', 'getMeetingId', 'getInternalMeetingId', - 'getModeratorPassword', 'getAttendeePassword', 'getCreationDate', 'getDialNumber', ]); + $this->assertEachGetterValueIsString($info, [ + 'getMeetingName', 'getMeetingId', 'getInternalMeetingId', + 'getCreationDate', 'getDialNumber', + ]); - $this->assertEachGetterValueIsInteger($info, ['getVoiceBridge', 'getDuration', 'getParticipantCount', - 'getListenerCount', 'getVoiceParticipantCount', 'getVideoCount', 'getMaxUsers', 'getModeratorCount', ]); + $this->assertEachGetterValueIsInteger($info, [ + 'getVoiceBridge', 'getDuration', 'getParticipantCount', + 'getListenerCount', 'getVoiceParticipantCount', 'getVideoCount', 'getMaxUsers', 'getModeratorCount', + ]); $this->assertEachGetterValueIsDouble($info, ['getStartTime', 'getEndTime', 'getCreationTime']); diff --git a/tests/unit/Responses/GetMeetingsResponseTest.php b/tests/unit/Responses/GetMeetingsResponseTest.php index 8787b794..a89e8d31 100644 --- a/tests/unit/Responses/GetMeetingsResponseTest.php +++ b/tests/unit/Responses/GetMeetingsResponseTest.php @@ -1,4 +1,5 @@ assertEquals('Tue Jan 19 08:27:55 EST 2016', $aMeeting->getCreationDate()); $this->assertEquals(49518, $aMeeting->getVoiceBridge()); $this->assertEquals('580.124.3937x93615', $aMeeting->getDialNumber()); - $this->assertEquals('f~kxYJeAV~G?Jb+E:ggn', $aMeeting->getAttendeePassword()); - $this->assertEquals('n:"zWc##Bi.y,d^s,mMF', $aMeeting->getModeratorPassword()); $this->assertFalse($aMeeting->hasBeenForciblyEnded()); $this->assertTrue($aMeeting->isRunning()); $this->assertEquals(5, $aMeeting->getParticipantCount()); @@ -74,11 +73,12 @@ public function testGetMeetingsResponseTypes() $aMeeting = $this->meetings->getMeetings()[2]; - $this->assertEachGetterValueIsString($aMeeting, ['getMeetingId', 'getMeetingName', 'getCreationDate', 'getDialNumber', - 'getAttendeePassword', 'getModeratorPassword', ]); + $this->assertEachGetterValueIsString($aMeeting, ['getMeetingId', 'getMeetingName', 'getCreationDate', 'getDialNumber']); $this->assertEachGetterValueIsDouble($aMeeting, ['getCreationTime']); - $this->assertEachGetterValueIsInteger($aMeeting, ['getVoiceBridge', 'getParticipantCount', 'getListenerCount', - 'getVoiceParticipantCount', 'getVideoCount', 'getDuration', ]); + $this->assertEachGetterValueIsInteger($aMeeting, [ + 'getVoiceBridge', 'getParticipantCount', 'getListenerCount', + 'getVoiceParticipantCount', 'getVideoCount', 'getDuration', + ]); $this->assertEachGetterValueIsBoolean($aMeeting, ['hasBeenForciblyEnded', 'isRunning', 'hasUserJoined']); } From 40494d0c451babb1de58faec8f7a0331283c2206 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Thu, 14 Mar 2024 23:36:47 +0100 Subject: [PATCH 31/68] Refactor using native ones (#186) * Refactor to native enums * Code style --- src/BigBlueButton.php | 2 +- src/Core/Meeting.php | 4 +- src/Enum/Enum.php | 34 ----------------- src/Enum/Feature.php | 44 +++++++++++----------- src/Enum/HashingAlgorithm.php | 10 ++--- src/Enum/Role.php | 6 +-- src/Parameters/BaseParameters.php | 4 ++ src/Parameters/CreateMeetingParameters.php | 5 ++- src/Parameters/JoinMeetingParameters.php | 4 +- src/Util/UrlBuilder.php | 11 +++--- tests/TestCase.php | 29 +++++++------- tests/unit/Util/UrlBuilderTest.php | 13 ++++--- 12 files changed, 71 insertions(+), 95 deletions(-) delete mode 100644 src/Enum/Enum.php diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index 177d5f1a..098565f2 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -114,7 +114,7 @@ class BigBlueButton * * @throws ConfigException */ - public function __construct(?string $baseUrl = null, ?string $secret = null, ?TransportInterface $transport = null, string $hashingAlgorithm = HashingAlgorithm::SHA_1) + public function __construct(?string $baseUrl = null, ?string $secret = null, ?TransportInterface $transport = null, HashingAlgorithm $hashingAlgorithm = HashingAlgorithm::SHA_1) { // Keeping backward compatibility with older deployed versions $this->securitySecret = $secret ?: getenv('BBB_SECURITY_SALT') ?: getenv('BBB_SECRET'); diff --git a/src/Core/Meeting.php b/src/Core/Meeting.php index 44af74bc..80710c5f 100644 --- a/src/Core/Meeting.php +++ b/src/Core/Meeting.php @@ -298,7 +298,7 @@ public function getModerators(): array $attendees = $this->getAttendees(); $moderators = array_filter($attendees, function ($attendee) { - return $attendee->getRole() === Role::MODERATOR; + return $attendee->getRole() === Role::MODERATOR->value; }); return array_values($moderators); @@ -314,7 +314,7 @@ public function getViewers(): array $attendees = $this->getAttendees(); $viewers = array_filter($attendees, function ($attendee) { - return $attendee->getRole() === Role::VIEWER; + return $attendee->getRole() === Role::VIEWER->value; }); return array_values($viewers); diff --git a/src/Enum/Enum.php b/src/Enum/Enum.php deleted file mode 100644 index a4ae350e..00000000 --- a/src/Enum/Enum.php +++ /dev/null @@ -1,34 +0,0 @@ -. - */ - -namespace BigBlueButton\Enum; - -/** - * @psalm-immutable - */ -abstract class Enum -{ - public static function getValues(): array - { - $reflection = new \ReflectionClass(static::class); - - return $reflection->getConstants(); - } -} diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php index ecc9bde1..ef5eef82 100644 --- a/src/Enum/Feature.php +++ b/src/Enum/Feature.php @@ -23,27 +23,27 @@ /** * @psalm-immutable */ -class Feature extends Enum +enum Feature: string { - public const BREAKOUT_ROOMS = 'breakoutRooms'; - public const CAPTIONS = 'captions'; - public const CHAT = 'chat'; - public const DOWNLOAD_PRESENTATION_WITH_ANNOTATIONS = 'downloadPresentationWithAnnotations'; - public const EXTERNAL_VIDEOS = 'externalVideos'; - public const IMPORT_PRESENTATION_WITH_ANNOTATIONS_FROM_BREAKOUT_ROOMS = 'importPresentationWithAnnotationsFromBreakoutRooms'; - public const IMPORT_SHARED_NOTES_FROM_BREAKOUT_ROOMS = 'importSharedNotesFromBreakoutRooms'; - public const LAYOUTS = 'layouts'; - public const LEARNING_DASHBOARD = 'learningDashboard'; - public const POLLS = 'polls'; - public const SCREENSHARE = 'screenshare'; - public const SHARED_NOTES = 'sharedNotes'; - public const VIRTUAL_BACKGROUNDS = 'virtualBackgrounds'; - public const CUSTOM_VIRTUAL_BACKGROUNDS = 'customVirtualBackgrounds'; - public const LIVE_TRANSCRIPTION = 'liveTranscription'; - public const PRESENTATION = 'presentation'; - public const CAMERA_AS_CONTENT = 'cameraAsContent'; - public const SNAPSHOT_OF_CURRENT_SLIDE = 'snapshotOfCurrentSlide'; - public const DOWNLOAD_PRESENTATION_ORIGINAL_FILE = 'downloadPresentationOriginalFile'; - public const DOWNLOAD_PRESENTATION_CONVERTED_TO_PDF = 'downloadPresentationConvertedToPdf'; - public const TIMER = 'timer'; + case BREAKOUT_ROOMS = 'breakoutRooms'; + case CAPTIONS = 'captions'; + case CHAT = 'chat'; + case DOWNLOAD_PRESENTATION_WITH_ANNOTATIONS = 'downloadPresentationWithAnnotations'; + case EXTERNAL_VIDEOS = 'externalVideos'; + case IMPORT_PRESENTATION_WITH_ANNOTATIONS_FROM_BREAKOUT_ROOMS = 'importPresentationWithAnnotationsFromBreakoutRooms'; + case IMPORT_SHARED_NOTES_FROM_BREAKOUT_ROOMS = 'importSharedNotesFromBreakoutRooms'; + case LAYOUTS = 'layouts'; + case LEARNING_DASHBOARD = 'learningDashboard'; + case POLLS = 'polls'; + case SCREENSHARE = 'screenshare'; + case SHARED_NOTES = 'sharedNotes'; + case VIRTUAL_BACKGROUNDS = 'virtualBackgrounds'; + case CUSTOM_VIRTUAL_BACKGROUNDS = 'customVirtualBackgrounds'; + case LIVE_TRANSCRIPTION = 'liveTranscription'; + case PRESENTATION = 'presentation'; + case CAMERA_AS_CONTENT = 'cameraAsContent'; + case SNAPSHOT_OF_CURRENT_SLIDE = 'snapshotOfCurrentSlide'; + case DOWNLOAD_PRESENTATION_ORIGINAL_FILE = 'downloadPresentationOriginalFile'; + case DOWNLOAD_PRESENTATION_CONVERTED_TO_PDF = 'downloadPresentationConvertedToPdf'; + case TIMER = 'timer'; } diff --git a/src/Enum/HashingAlgorithm.php b/src/Enum/HashingAlgorithm.php index c5cd1545..52911756 100644 --- a/src/Enum/HashingAlgorithm.php +++ b/src/Enum/HashingAlgorithm.php @@ -23,10 +23,10 @@ /** * @psalm-immutable */ -class HashingAlgorithm extends Enum +enum HashingAlgorithm: string { - public const SHA_1 = 'sha1'; - public const SHA_256 = 'sha256'; - public const SHA_512 = 'sha512'; - public const SHA_384 = 'sha384'; + case SHA_1 = 'sha1'; + case SHA_256 = 'sha256'; + case SHA_512 = 'sha512'; + case SHA_384 = 'sha384'; } diff --git a/src/Enum/Role.php b/src/Enum/Role.php index 1766c666..bd6d1bb2 100644 --- a/src/Enum/Role.php +++ b/src/Enum/Role.php @@ -23,8 +23,8 @@ /** * @psalm-immutable */ -class Role extends Enum +enum Role: string { - public const MODERATOR = 'MODERATOR'; - public const VIEWER = 'VIEWER'; + case MODERATOR = 'MODERATOR'; + case VIEWER = 'VIEWER'; } diff --git a/src/Parameters/BaseParameters.php b/src/Parameters/BaseParameters.php index 36252a56..69588dad 100644 --- a/src/Parameters/BaseParameters.php +++ b/src/Parameters/BaseParameters.php @@ -95,6 +95,10 @@ protected function getHTTPQueryArray(): array return $value ? 'true' : 'false'; } + if ($value instanceof \BackedEnum) { + $value = $value->value; + } + return $value; }, $properties); } diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index e27a5a63..7aeee2bb 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -21,6 +21,7 @@ namespace BigBlueButton\Parameters; use BigBlueButton\Core\GuestPolicy; +use BigBlueButton\Enum\Feature; /** * @method string getName() @@ -616,14 +617,14 @@ public function getHTTPQuery(): string // Add disabled features if any are set if (!empty($this->disabledFeatures)) { $queries = array_merge($queries, [ - 'disabledFeatures' => implode(',', $this->disabledFeatures), + 'disabledFeatures' => implode(',', array_map(fn (Feature $disabledFeature): string => $disabledFeature->value, $this->disabledFeatures)), ]); } // Add disabled features exclude if any are set if (!empty($this->disabledFeaturesExclude)) { $queries = array_merge($queries, [ - 'disabledFeaturesExclude' => implode(',', $this->disabledFeaturesExclude), + 'disabledFeaturesExclude' => implode(',', array_map(fn (Feature $disabledFeatureExclude): string => $disabledFeatureExclude->value, $this->disabledFeaturesExclude)), ]); } diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index 39dd1891..f8e0281d 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -20,6 +20,8 @@ namespace BigBlueButton\Parameters; +use BigBlueButton\Enum\Role; + /** * Class JoinMeetingParametersTest. * @@ -120,7 +122,7 @@ class JoinMeetingParameters extends UserDataParameters */ protected $excludeFromDashboard; - public function __construct(string $meetingID, string $fullName, string $role) + public function __construct(string $meetingID, string $fullName, Role $role) { $this->meetingID = $meetingID; $this->fullName = $fullName; diff --git a/src/Util/UrlBuilder.php b/src/Util/UrlBuilder.php index 3b15aafe..81638b9c 100644 --- a/src/Util/UrlBuilder.php +++ b/src/Util/UrlBuilder.php @@ -19,6 +19,8 @@ namespace BigBlueButton\Util; +use BigBlueButton\Enum\HashingAlgorithm; + /** * Class UrlBuilder. * @@ -35,12 +37,9 @@ final class UrlBuilder */ private $bbbServerBaseUrl; - /** - * @var string - */ - private $hashingAlgorithm; + private HashingAlgorithm $hashingAlgorithm; - public function __construct(string $secret, string $serverBaseUrl, string $hashingAlgorithm) + public function __construct(string $secret, string $serverBaseUrl, HashingAlgorithm $hashingAlgorithm) { $this->securitySalt = $secret; $this->bbbServerBaseUrl = $serverBaseUrl; @@ -67,6 +66,6 @@ public function buildQs(string $method = '', string $params = ''): string $checksumParam = 'checksum='; } - return $params.$checksumParam.hash($this->hashingAlgorithm, $method.$params.$this->securitySalt); + return $params.$checksumParam.hash($this->hashingAlgorithm->value, $method.$params.$this->securitySalt); } } diff --git a/tests/TestCase.php b/tests/TestCase.php index f8322812..f5177a15 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -98,8 +98,8 @@ protected function generateCreateParams() 'lockSettingsLockOnJoinConfigurable' => $this->faker->boolean(50), 'allowModsToUnmuteUsers' => $this->faker->boolean(50), 'allowModsToEjectCameras' => $this->faker->boolean(50), - 'disabledFeatures' => $this->faker->randomElements(Feature::getValues(), 3), - 'disabledFeaturesExclude' => $this->faker->randomElements(Feature::getValues(), 2), + 'disabledFeatures' => $this->faker->randomElements(Feature::cases(), 3), + 'disabledFeaturesExclude' => $this->faker->randomElements(Feature::cases(), 2), 'meta_presenter' => $this->faker->name, 'meta_endCallbackUrl' => $this->faker->url, 'meta_bbb-recording-ready-url' => $this->faker->url, @@ -229,17 +229,16 @@ protected function getBreakoutCreateMock($params) */ protected function generateJoinMeetingParams() { - return [ - 'meetingID' => $this->faker->uuid, - 'fullName' => $this->faker->name, - 'role' => $this->faker->randomElement(Role::getValues()), - 'userID' => $this->faker->numberBetween(1, 1000), - 'webVoiceConf' => $this->faker->word, - 'createTime' => $this->faker->unixTime, - 'errorRedirectUrl' => $this->faker->url, - 'userdata-countrycode' => $this->faker->countryCode, - 'userdata-email' => $this->faker->email, - 'userdata-commercial' => false, + return ['meetingID' => $this->faker->uuid, + 'fullName' => $this->faker->name, + 'role' => $this->faker->randomElement(Role::cases()), + 'userID' => $this->faker->numberBetween(1, 1000), + 'webVoiceConf' => $this->faker->word, + 'createTime' => $this->faker->unixTime, + 'errorRedirectUrl' => $this->faker->url, + 'userdata-countrycode' => $this->faker->countryCode, + 'userdata-email' => $this->faker->email, + 'userdata-commercial' => false, ]; } @@ -372,6 +371,10 @@ public function assertUrlContainsAllRequestParameters(string $url, array $parame $parameter = $parameter ? 'true' : 'false'; } + if ($parameter instanceof \BackedEnum) { + $parameter = $parameter->value; + } + if (!\is_array($parameter)) { $this->assertStringContainsString($parameter, urldecode($url)); } else { diff --git a/tests/unit/Util/UrlBuilderTest.php b/tests/unit/Util/UrlBuilderTest.php index 64b71187..105dfebb 100644 --- a/tests/unit/Util/UrlBuilderTest.php +++ b/tests/unit/Util/UrlBuilderTest.php @@ -21,6 +21,7 @@ namespace BigBlueButton\Util; +use BigBlueButton\Enum\HashingAlgorithm; use PHPUnit\Framework\TestCase; /** @@ -31,7 +32,7 @@ final class UrlBuilderTest extends TestCase public function testBuildUrl(): void { // Test with sha1 hash algorithm - $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha1'); + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', HashingAlgorithm::SHA_1); // echo sha1('getMeetings' . 'foo=bar&baz=bazinga' . 'AFFE'); $this->assertSame( @@ -41,7 +42,7 @@ public function testBuildUrl(): void ); // Test with sha256 hash algorithm - $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha256'); + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', HashingAlgorithm::SHA_256); // echo hash('sha256', 'getMeetings' . 'foo=bar&baz=bazinga' . 'AFFE'); $this->assertSame( @@ -53,7 +54,7 @@ public function testBuildUrl(): void public function testBuildUrlWithEmptyParams(): void { - $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha1'); + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', HashingAlgorithm::SHA_1); // echo sha1('getMeetings' . '' . 'AFFE'); $this->assertSame( @@ -65,7 +66,7 @@ public function testBuildUrlWithEmptyParams(): void public function testBuildUrlWithoutAppend(): void { - $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha1'); + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', HashingAlgorithm::SHA_1); $this->assertSame( 'https://bbb.example/bigbluebutton/api/getMeetings', @@ -76,7 +77,7 @@ public function testBuildUrlWithoutAppend(): void public function testBuildQs(): void { - $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha1'); + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', HashingAlgorithm::SHA_1); // echo sha1('getMeetings' . 'foo=bar&baz=bazinga' . 'AFFE'); $this->assertSame( @@ -88,7 +89,7 @@ public function testBuildQs(): void public function testBuildQsWithEmptyParams(): void { - $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', 'sha1'); + $urlBuilder = new UrlBuilder('AFFE', 'https://bbb.example/bigbluebutton/', HashingAlgorithm::SHA_1); // echo sha1('getMeetings' . '' . 'AFFE'); $this->assertSame( From 027a140c2414124511517a1c8edb26df08fd7770 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 25 Mar 2024 11:05:57 +0100 Subject: [PATCH 32/68] Fix cs --- tests/TestCase.php | 32 +++++++++---------- .../Responses/CreateMeetingResponseTest.php | 2 +- .../GetRecordingsTextTracksResponseTest.php | 12 +++---- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index 9696c4c4..f78f85d9 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -110,11 +110,11 @@ protected function generateCreateParams() 'endWhenNoModerator' => $this->faker->boolean(50), 'endWhenNoModeratorDelayInMinutes' => $this->faker->numberBetween(1, 100), 'meetingLayout' => $this->faker->randomElement([ - MeetingLayout::CUSTOM_LAYOUT, - MeetingLayout::SMART_LAYOUT, - MeetingLayout::PRESENTATION_FOCUS, - MeetingLayout::VIDEO_FOCUS, - ]), + MeetingLayout::CUSTOM_LAYOUT, + MeetingLayout::SMART_LAYOUT, + MeetingLayout::PRESENTATION_FOCUS, + MeetingLayout::VIDEO_FOCUS, + ]), 'learningDashboardEnabled' => $this->faker->boolean(50), 'learningDashboardCleanupDelayInMinutes' => $this->faker->numberBetween(1, 100), 'breakoutRoomsEnabled' => $this->faker->boolean(50), @@ -246,16 +246,16 @@ protected function getBreakoutCreateMock($params) protected function generateJoinMeetingParams() { return ['meetingID' => $this->faker->uuid, - 'fullName' => $this->faker->name, - 'role' => $this->faker->randomElement(Role::getValues()), - 'userID' => $this->faker->numberBetween(1, 1000), - 'webVoiceConf' => $this->faker->word, - 'createTime' => $this->faker->unixTime, - 'configToken' => $this->faker->word, - 'errorRedirectUrl' => $this->faker->url, - 'userdata-countrycode' => $this->faker->countryCode, - 'userdata-email' => $this->faker->email, - 'userdata-commercial' => false, + 'fullName' => $this->faker->name, + 'role' => $this->faker->randomElement(Role::getValues()), + 'userID' => $this->faker->numberBetween(1, 1000), + 'webVoiceConf' => $this->faker->word, + 'createTime' => $this->faker->unixTime, + 'configToken' => $this->faker->word, + 'errorRedirectUrl' => $this->faker->url, + 'userdata-countrycode' => $this->faker->countryCode, + 'userdata-email' => $this->faker->email, + 'userdata-commercial' => false, ]; } @@ -285,7 +285,7 @@ protected function getJoinMeetingMock($params) protected function generateEndMeetingParams() { return ['meetingID' => $this->faker->uuid, - 'password' => $this->faker->password, ]; + 'password' => $this->faker->password, ]; } /** diff --git a/tests/unit/Responses/CreateMeetingResponseTest.php b/tests/unit/Responses/CreateMeetingResponseTest.php index 4780992e..941fce9f 100644 --- a/tests/unit/Responses/CreateMeetingResponseTest.php +++ b/tests/unit/Responses/CreateMeetingResponseTest.php @@ -66,7 +66,7 @@ public function testCreateMeetingResponseContent() public function testCreateMeetingResponseTypes() { $this->assertEachGetterValueIsString($this->meeting, ['getReturnCode', 'getInternalMeetingId', 'getParentMeetingId', - 'getAttendeePassword', 'getModeratorPassword', 'getDialNumber', 'getCreationDate', ]); + 'getAttendeePassword', 'getModeratorPassword', 'getDialNumber', 'getCreationDate', ]); $this->assertEachGetterValueIsDouble($this->meeting, ['getCreationTime']); $this->assertEachGetterValueIsInteger($this->meeting, ['getDuration', 'getVoiceBridge']); $this->assertEachGetterValueIsBoolean($this->meeting, ['hasUserJoined', 'hasBeenForciblyEnded']); diff --git a/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php b/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php index 7d9fd526..5eecf46c 100644 --- a/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php +++ b/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php @@ -41,12 +41,12 @@ public function testGetRecordingTextTracksResponseTypes() $secondTracks = $this->tracks->getTracks()[1]; $this->assertEachGetterValueIsString($secondTracks, [ - 'getHref', - 'getKind', - 'getLabel', - 'getLang', - 'getSource', - ] + 'getHref', + 'getKind', + 'getLabel', + 'getLang', + 'getSource', + ] ); } From 513a56ab0fbcf9f5fbc9f08ae33bebee24812613 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Thu, 28 Mar 2024 13:39:12 +0100 Subject: [PATCH 33/68] Create dependabot.yml --- .github/dependabot.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..51b18f29 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + # Maintain dependencies for Composer + - package-ecosystem: "composer" + directory: "/" + schedule: + interval: "daily" From e62790a4e5cc2499536e7dfe2ee8b53657c01a70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Apr 2024 20:18:08 +0200 Subject: [PATCH 34/68] Update psr/http-message requirement from ^1.0 to ^1.0 || ^2.0 (#196) Updates the requirements on [psr/http-message](https://github.com/php-fig/http-message) to permit the latest version. - [Release notes](https://github.com/php-fig/http-message/releases) - [Changelog](https://github.com/php-fig/http-message/blob/master/CHANGELOG.md) - [Commits](https://github.com/php-fig/http-message/compare/1.0...2.0) --- updated-dependencies: - dependency-name: psr/http-message dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 22fc3ea0..b36d8e8c 100644 --- a/composer.json +++ b/composer.json @@ -74,7 +74,7 @@ "require-dev": { "psr/http-client": "^1.0", "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", + "psr/http-message": "^1.0 || ^2.0", "symfony/dotenv": "^3.4|^4.0|^5.0", "symfony/http-client-contracts": "^1.1|^2.0", "symfony/http-client": "^4.4|^5.0", From 7e55854556f1b46a5dc056679b6d686442033632 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Thu, 4 Apr 2024 20:22:22 +0200 Subject: [PATCH 35/68] Deprecate clientURL (#194) * Deprecate clientURL * Fix cs --------- Co-authored-by: Felix Jacobi --- src/Parameters/JoinMeetingParameters.php | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index 6417f22f..863c10f6 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -42,8 +42,6 @@ * @method $this setRedirect(bool $redirect) * @method string getErrorRedirectUrl() * @method $this setErrorRedirectUrl(string $errorRedirectUrl) - * @method string getClientURL() - * @method $this setClientURL(string $clientURL) * @method bool|null isGuest() * @method $this setGuest(bool $guest) * @method string getRole() @@ -190,4 +188,24 @@ public function setConfigToken(string $configToken): self return $this; } + + /** + * @deprecated and will be removed in 6.0. Old BigBlueButton flash client parameter. + */ + public function getClientURL(): ?string + { + return $this->clientURL; + } + + /** + * @deprecated and will be removed in 6.0. Old BigBlueButton flash client parameter. + * + * @return $this + */ + public function setClientURL(string $clientURL): self + { + $this->clientURL = $clientURL; + + return $this; + } } From 7f7320fb0f84db9dfbb0f9e66fd95bb598519cce Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sun, 5 May 2024 21:26:08 +0200 Subject: [PATCH 36/68] Deprecate not passing server base url and secret (#195) * Deprecate not passing server base url and secret * Update src/BigBlueButton.php Co-authored-by: Felix Jacobi * Update src/BigBlueButton.php Co-authored-by: Felix Jacobi * Show deprecation when using environment variables --------- Co-authored-by: Felix Jacobi --- src/BigBlueButton.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index b8993dfd..805eb3b2 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -116,6 +116,22 @@ class BigBlueButton */ public function __construct(?string $baseUrl = null, ?string $secret = null, ?TransportInterface $transport = null, string $hashingAlgorithm = HashingAlgorithm::SHA_1) { + if (null === $baseUrl) { + @trigger_error(sprintf('Constructing "%s" without passing a server base URL is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); + } + + if (null === $secret) { + @trigger_error(sprintf('Constructing "%s" without passing a secret is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); + } + + if (getenv('BBB_SECURITY_SALT') !== false || getenv('BBB_SECRET') !== false) { + @trigger_error('Using BBB_SECURITY_SALT or BBB_SECRET environment variables is deprecated for security reasons and will be removed in 6.0. Use the constructor parameters instead.', \E_USER_DEPRECATED); + } + + if (getenv('BBB_SERVER_BASE_URL') !== false) { + @trigger_error('Using BBB_SERVER_BASE_URL environment variable is deprecated for security reasons and will be removed in 6.0. Use the constructor parameters instead.', \E_USER_DEPRECATED); + } + // Keeping backward compatibility with older deployed versions $this->securitySecret = $secret ?: getenv('BBB_SECURITY_SALT') ?: getenv('BBB_SECRET'); $this->bbbServerBaseUrl = $baseUrl ?: getenv('BBB_SERVER_BASE_URL'); From afee4cc2773bde7ca720eed0d3d04c088815046f Mon Sep 17 00:00:00 2001 From: Henning <105713989+marineusde@users.noreply.github.com> Date: Mon, 24 Jun 2024 17:33:27 +0200 Subject: [PATCH 37/68] Getting of the parentMeetingID in the class Meeting (#200) --- src/Core/Meeting.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Core/Meeting.php b/src/Core/Meeting.php index 24a98cf7..721454c5 100644 --- a/src/Core/Meeting.php +++ b/src/Core/Meeting.php @@ -117,6 +117,11 @@ class Meeting */ private $internalMeetingId; + /** + * @var string + */ + private $parentMeetingID; + /** * @var bool */ @@ -177,6 +182,7 @@ public function __construct(\SimpleXMLElement $xml) $this->duration = (int) $xml->duration; $this->hasUserJoined = $xml->hasUserJoined->__toString() === 'true'; $this->internalMeetingId = $xml->internalMeetingID->__toString(); + $this->parentMeetingID = $xml->parentMeetingID->__toString(); $this->isRecording = $xml->recording->__toString() === 'true'; $this->startTime = (float) $xml->startTime; $this->endTime = (float) $xml->endTime; @@ -276,6 +282,11 @@ public function getInternalMeetingId(): string return $this->internalMeetingId; } + public function getParentMeetingID(): string + { + return $this->parentMeetingID; + } + public function isRecording(): bool { return $this->isRecording; From 7761b10b1dc60532a70232f08d3d31658ee2f0a8 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 24 Jun 2024 18:09:59 +0200 Subject: [PATCH 38/68] Move all enums to BigBlueButton\Enum namespace (#197) --- src/BigBlueButton.php | 2 +- src/Core/ApiMethod.php | 35 +++++++------- src/Core/GuestPolicy.php | 9 ++-- src/Core/MeetingLayout.php | 9 ++-- src/Enum/ApiMethod.php | 46 +++++++++++++++++++ src/Enum/Feature.php | 4 +- src/Enum/GuestPolicy.php | 32 +++++++++++++ src/Enum/MeetingLayout.php | 32 +++++++++++++ src/Parameters/CreateMeetingParameters.php | 18 ++++---- src/Parameters/JoinMeetingParameters.php | 7 ++- tests/TestCase.php | 4 +- tests/unit/BigBlueButtonTest.php | 2 +- .../CreateMeetingParametersTest.php | 2 +- 13 files changed, 158 insertions(+), 44 deletions(-) create mode 100644 src/Enum/ApiMethod.php create mode 100644 src/Enum/GuestPolicy.php create mode 100644 src/Enum/MeetingLayout.php diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index 805eb3b2..8d94943d 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -19,7 +19,7 @@ namespace BigBlueButton; -use BigBlueButton\Core\ApiMethod; +use BigBlueButton\Enum\ApiMethod; use BigBlueButton\Enum\HashingAlgorithm; use BigBlueButton\Exceptions\ConfigException; use BigBlueButton\Exceptions\NetworkException; diff --git a/src/Core/ApiMethod.php b/src/Core/ApiMethod.php index ba4edf35..7d960eab 100644 --- a/src/Core/ApiMethod.php +++ b/src/Core/ApiMethod.php @@ -19,24 +19,23 @@ namespace BigBlueButton\Core; +/* @deprecated and will be removed in 6.0. Use \BigBlueButton\Enum\ApiMethod instead */ final class ApiMethod { - public const CREATE = 'create'; - public const JOIN = 'join'; - public const ENTER = 'enter'; - public const END = 'end'; - public const IS_MEETING_RUNNING = 'isMeetingRunning'; - public const GET_MEETING_INFO = 'getMeetingInfo'; - public const GET_MEETINGS = 'getMeetings'; - public const SIGN_OUT = 'signOut'; - public const GET_RECORDINGS = 'getRecordings'; - public const PUBLISH_RECORDINGS = 'publishRecordings'; - public const DELETE_RECORDINGS = 'deleteRecordings'; - public const UPDATE_RECORDINGS = 'updateRecordings'; - public const GET_RECORDING_TEXT_TRACKS = 'getRecordingTextTracks'; - public const PUT_RECORDING_TEXT_TRACK = 'putRecordingTextTrack'; - public const HOOKS_CREATE = 'hooks/create'; - public const HOOKS_LIST = 'hooks/list'; - public const HOOKS_DESTROY = 'hooks/destroy'; - public const INSERT_DOCUMENT = 'insertDocument'; + public const CREATE = \BigBlueButton\Enum\ApiMethod::CREATE; + public const JOIN = \BigBlueButton\Enum\ApiMethod::JOIN; + public const END = \BigBlueButton\Enum\ApiMethod::END; + public const IS_MEETING_RUNNING = \BigBlueButton\Enum\ApiMethod::IS_MEETING_RUNNING; + public const GET_MEETING_INFO = \BigBlueButton\Enum\ApiMethod::GET_MEETING_INFO; + public const GET_MEETINGS = \BigBlueButton\Enum\ApiMethod::GET_MEETINGS; + public const GET_RECORDINGS = \BigBlueButton\Enum\ApiMethod::GET_RECORDINGS; + public const PUBLISH_RECORDINGS = \BigBlueButton\Enum\ApiMethod::PUBLISH_RECORDINGS; + public const DELETE_RECORDINGS = \BigBlueButton\Enum\ApiMethod::DELETE_RECORDINGS; + public const UPDATE_RECORDINGS = \BigBlueButton\Enum\ApiMethod::UPDATE_RECORDINGS; + public const GET_RECORDING_TEXT_TRACKS = \BigBlueButton\Enum\ApiMethod::GET_RECORDING_TEXT_TRACKS; + public const PUT_RECORDING_TEXT_TRACK = \BigBlueButton\Enum\ApiMethod::PUT_RECORDING_TEXT_TRACK; + public const HOOKS_CREATE = \BigBlueButton\Enum\ApiMethod::HOOKS_CREATE; + public const HOOKS_LIST = \BigBlueButton\Enum\ApiMethod::HOOKS_LIST; + public const HOOKS_DESTROY = \BigBlueButton\Enum\ApiMethod::HOOKS_DESTROY; + public const INSERT_DOCUMENT = \BigBlueButton\Enum\ApiMethod::INSERT_DOCUMENT; } diff --git a/src/Core/GuestPolicy.php b/src/Core/GuestPolicy.php index a9177160..94d95060 100644 --- a/src/Core/GuestPolicy.php +++ b/src/Core/GuestPolicy.php @@ -22,10 +22,11 @@ namespace BigBlueButton\Core; +/* @deprecated and will be removed in 6.0. Use \BigBlueButton\Enum\GuestPolicy instead */ final class GuestPolicy { - public const ALWAYS_ACCEPT = 'ALWAYS_ACCEPT'; - public const ALWAYS_DENY = 'ALWAYS_DENY'; - public const ASK_MODERATOR = 'ASK_MODERATOR'; - public const ALWAYS_ACCEPT_AUTH = 'ALWAYS_ACCEPT_AUTH'; + public const ALWAYS_ACCEPT = \BigBlueButton\Enum\GuestPolicy::ALWAYS_ACCEPT; + public const ALWAYS_DENY = \BigBlueButton\Enum\GuestPolicy::ALWAYS_DENY; + public const ASK_MODERATOR = \BigBlueButton\Enum\GuestPolicy::ASK_MODERATOR; + public const ALWAYS_ACCEPT_AUTH = \BigBlueButton\Enum\GuestPolicy::ALWAYS_ACCEPT_AUTH; } diff --git a/src/Core/MeetingLayout.php b/src/Core/MeetingLayout.php index 0f499913..4691720c 100644 --- a/src/Core/MeetingLayout.php +++ b/src/Core/MeetingLayout.php @@ -22,10 +22,11 @@ namespace BigBlueButton\Core; +/* @deprecated Use \BigBlueButton\Enum\MeetingLayout instead */ final class MeetingLayout { - public const CUSTOM_LAYOUT = 'CUSTOM_LAYOUT'; - public const SMART_LAYOUT = 'SMART_LAYOUT'; - public const PRESENTATION_FOCUS = 'PRESENTATION_FOCUS'; - public const VIDEO_FOCUS = 'VIDEO_FOCUS'; + public const CUSTOM_LAYOUT = \BigBlueButton\Enum\MeetingLayout::CUSTOM_LAYOUT; + public const SMART_LAYOUT = \BigBlueButton\Enum\MeetingLayout::SMART_LAYOUT; + public const PRESENTATION_FOCUS = \BigBlueButton\Enum\MeetingLayout::PRESENTATION_FOCUS; + public const VIDEO_FOCUS = \BigBlueButton\Enum\MeetingLayout::VIDEO_FOCUS; } diff --git a/src/Enum/ApiMethod.php b/src/Enum/ApiMethod.php new file mode 100644 index 00000000..97bbc6e2 --- /dev/null +++ b/src/Enum/ApiMethod.php @@ -0,0 +1,46 @@ +. + */ + +namespace BigBlueButton\Enum; + +/** + * @psalm-immutable + */ +class ApiMethod extends Enum +{ + public const CREATE = 'create'; + public const JOIN = 'join'; + public const ENTER = 'enter'; + public const END = 'end'; + public const IS_MEETING_RUNNING = 'isMeetingRunning'; + public const GET_MEETING_INFO = 'getMeetingInfo'; + public const GET_MEETINGS = 'getMeetings'; + public const SIGN_OUT = 'signOut'; + public const GET_RECORDINGS = 'getRecordings'; + public const PUBLISH_RECORDINGS = 'publishRecordings'; + public const DELETE_RECORDINGS = 'deleteRecordings'; + public const UPDATE_RECORDINGS = 'updateRecordings'; + public const GET_RECORDING_TEXT_TRACKS = 'getRecordingTextTracks'; + public const PUT_RECORDING_TEXT_TRACK = 'putRecordingTextTrack'; + public const HOOKS_CREATE = 'hooks/create'; + public const HOOKS_LIST = 'hooks/list'; + public const HOOKS_DESTROY = 'hooks/destroy'; + public const INSERT_DOCUMENT = 'insertDocument'; +} diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php index 7b811bcb..76af14d0 100644 --- a/src/Enum/Feature.php +++ b/src/Enum/Feature.php @@ -48,12 +48,12 @@ class Feature extends Enum public const TIMER = 'timer'; /** - * @deprecated Use Feature::IMPORT_PRESENTATION_WITH_ANNOTATIONS_FROM_BREAKOUT_ROOMS instead + * @deprecated and will be removed in 6.0. Use Feature::IMPORT_PRESENTATION_WITH_ANNOTATIONS_FROM_BREAKOUT_ROOMS instead */ public const IMPORT_PRESENTATION_WITHANNOTATIONS_FROM_BREAKOUTROOMS = 'importPresentationWithAnnotationsFromBreakoutRooms'; /** - * @deprecated Use Feature::IMPORT_SHARED_NOTES_FROM_BREAKOUT_ROOMS instead + * @deprecated and will be removed in 6.0. Use Feature::IMPORT_SHARED_NOTES_FROM_BREAKOUT_ROOMS instead */ public const IMPORT_SHARED_NOTES_FROM_BREAKOUTROOMS = 'importSharedNotesFromBreakoutRooms'; } diff --git a/src/Enum/GuestPolicy.php b/src/Enum/GuestPolicy.php new file mode 100644 index 00000000..4bf90f49 --- /dev/null +++ b/src/Enum/GuestPolicy.php @@ -0,0 +1,32 @@ +. + */ + +namespace BigBlueButton\Enum; + +/** + * @psalm-immutable + */ +class GuestPolicy extends Enum +{ + public const ALWAYS_ACCEPT = 'ALWAYS_ACCEPT'; + public const ALWAYS_DENY = 'ALWAYS_DENY'; + public const ASK_MODERATOR = 'ASK_MODERATOR'; + public const ALWAYS_ACCEPT_AUTH = 'ALWAYS_ACCEPT_AUTH'; +} diff --git a/src/Enum/MeetingLayout.php b/src/Enum/MeetingLayout.php new file mode 100644 index 00000000..39f0b152 --- /dev/null +++ b/src/Enum/MeetingLayout.php @@ -0,0 +1,32 @@ +. + */ + +namespace BigBlueButton\Enum; + +/** + * @psalm-immutable + */ +class MeetingLayout extends Enum +{ + public const CUSTOM_LAYOUT = 'CUSTOM_LAYOUT'; + public const SMART_LAYOUT = 'SMART_LAYOUT'; + public const PRESENTATION_FOCUS = 'PRESENTATION_FOCUS'; + public const VIDEO_FOCUS = 'VIDEO_FOCUS'; +} diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index ab87f1e2..eb05612c 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -19,7 +19,7 @@ namespace BigBlueButton\Parameters; -use BigBlueButton\Core\GuestPolicy; +use BigBlueButton\Enum\GuestPolicy; /** * @method string getName() @@ -506,7 +506,7 @@ public function isBreakout(): ?bool } /** - * @deprecated use disabledFeatures instead + * @deprecated and will be removed in 6.0. Use disabledFeatures instead * Backwards compatibility for the old method name with the missing 's' at the end */ public function setLockSettingsDisableNote(bool $isLockSettingsDisableNote): self @@ -517,7 +517,7 @@ public function setLockSettingsDisableNote(bool $isLockSettingsDisableNote): sel } /** - * @deprecated use disabledFeatures instead + * @deprecated and will be removed in 6.0. Use disabledFeatures instead * Backwards compatibility for the old method name with the missing 's' at the end */ public function isLockSettingsDisableNote(): bool @@ -526,7 +526,7 @@ public function isLockSettingsDisableNote(): bool } /** - * @deprecated Use disabledFeatures instead + * @deprecated and will be removed in 6.0. Use disabledFeatures instead */ public function setLearningDashboardEnabled(bool $learningDashboardEnabled): self { @@ -536,7 +536,7 @@ public function setLearningDashboardEnabled(bool $learningDashboardEnabled): sel } /** - * @deprecated Use disabledFeatures instead + * @deprecated and will be removed in 6.0. Use disabledFeatures instead */ public function isLearningDashboardEnabled(): bool { @@ -544,7 +544,7 @@ public function isLearningDashboardEnabled(): bool } /** - * @deprecated Use disabledFeatures instead + * @deprecated and will be removed in 6.0. Use disabledFeatures instead */ public function setVirtualBackgroundsDisabled(bool $virtualBackgroundsDisabled): self { @@ -554,7 +554,7 @@ public function setVirtualBackgroundsDisabled(bool $virtualBackgroundsDisabled): } /** - * @deprecated Use disabledFeatures instead + * @deprecated and will be removed in 6.0. Use disabledFeatures instead */ public function isVirtualBackgroundsDisabled(): bool { @@ -562,7 +562,7 @@ public function isVirtualBackgroundsDisabled(): bool } /** - * @deprecated Use disabledFeatures instead + * @deprecated and will be removed in 6.0. Use disabledFeatures instead */ public function setBreakoutRoomsEnabled(bool $breakoutRoomsEnabled): self { @@ -572,7 +572,7 @@ public function setBreakoutRoomsEnabled(bool $breakoutRoomsEnabled): self } /** - * @deprecated Use disabledFeatures instead + * @deprecated and will be removed in 6.0. Use disabledFeatures instead */ public function isBreakoutRoomsEnabled(): bool { diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index 863c10f6..6e360081 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -51,8 +51,11 @@ */ class JoinMeetingParameters extends UserDataParameters { - public const MODERATOR = 'MODERATOR'; - public const VIEWER = 'VIEWER'; + /* @deprecated and will be removed in 6.0. Use BigBlueButton\Enum\Role::MODERATOR instead */ + public const MODERATOR = Role::MODERATOR; + + /* @deprecated and will be removed in 6.0. Use BigBlueButton\Enum\Role::VIEWER instead */ + public const VIEWER = Role::VIEWER; /** * @var string diff --git a/tests/TestCase.php b/tests/TestCase.php index f78f85d9..da68b216 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -19,9 +19,9 @@ namespace BigBlueButton; -use BigBlueButton\Core\GuestPolicy; -use BigBlueButton\Core\MeetingLayout; use BigBlueButton\Enum\Feature; +use BigBlueButton\Enum\GuestPolicy; +use BigBlueButton\Enum\MeetingLayout; use BigBlueButton\Enum\Role; use BigBlueButton\Parameters\CreateMeetingParameters; use BigBlueButton\Parameters\EndMeetingParameters; diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index d2588608..d50ab595 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -19,7 +19,7 @@ namespace BigBlueButton; -use BigBlueButton\Core\ApiMethod; +use BigBlueButton\Enum\ApiMethod; use BigBlueButton\Enum\HashingAlgorithm; use BigBlueButton\Exceptions\ConfigException; use BigBlueButton\Exceptions\NetworkException; diff --git a/tests/unit/Parameters/CreateMeetingParametersTest.php b/tests/unit/Parameters/CreateMeetingParametersTest.php index 5ecfd611..e4ebbe06 100644 --- a/tests/unit/Parameters/CreateMeetingParametersTest.php +++ b/tests/unit/Parameters/CreateMeetingParametersTest.php @@ -19,8 +19,8 @@ namespace BigBlueButton\Parameters; -use BigBlueButton\Core\GuestPolicy; use BigBlueButton\Enum\Feature; +use BigBlueButton\Enum\GuestPolicy; use BigBlueButton\TestCase; /** From 1d2f4231d778c9c248eee2650c276c319b5d3bb3 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Mon, 24 Jun 2024 18:22:00 +0200 Subject: [PATCH 39/68] Add new create meeting param allowPromoteGuestToModerator (#203) * Add allowPromoteGuestToModerator * Remove code duplication --------- Co-authored-by: Felix Jacobi --- src/Parameters/CreateMeetingParameters.php | 7 +++++++ tests/TestCase.php | 2 ++ tests/unit/Parameters/CreateMeetingParametersTest.php | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index eb05612c..20a3f303 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -120,6 +120,8 @@ * @method $this setAllowModsToEjectCameras(bool $isAllowModsToEjectCameras) * @method bool|null isAllowRequestsWithoutSession() * @method $this setAllowRequestsWithoutSession(bool $isAllowRequestsWithoutSession) + * @method bool|null isAllowPromoteGuestToModerator() + * @method $this setAllowPromoteGuestToModerator(bool $isAllowPromoteGuestToModerator) * @method int getUserCameraCap() * @method $this setUserCameraCap(int $cap) * @method int getMeetingCameraCap() @@ -386,6 +388,11 @@ class CreateMeetingParameters extends MetaParameters */ protected $allowRequestsWithoutSession; + /** + * @var bool + */ + protected $allowPromoteGuestToModerator; + /** * @var bool */ diff --git a/tests/TestCase.php b/tests/TestCase.php index da68b216..31155c68 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -99,6 +99,7 @@ protected function generateCreateParams() 'lockSettingsLockOnJoinConfigurable' => $this->faker->boolean(50), 'allowModsToUnmuteUsers' => $this->faker->boolean(50), 'allowModsToEjectCameras' => $this->faker->boolean(50), + 'allowPromoteGuestToModerator' => $this->faker->boolean(50), 'disabledFeatures' => $this->faker->randomElements(Feature::getValues(), 3), 'disabledFeaturesExclude' => $this->faker->randomElements(Feature::getValues(), 2), 'meta_presenter' => $this->faker->name, @@ -209,6 +210,7 @@ protected function getCreateMock($params) ->setBreakoutRoomsPrivateChatEnabled($params['breakoutRoomsPrivateChatEnabled']) ->setBreakoutRoomsRecord($params['breakoutRoomsRecord']) ->setAllowRequestsWithoutSession($params['allowRequestsWithoutSession']) + ->setAllowPromoteGuestToModerator($params['allowPromoteGuestToModerator']) ->setVirtualBackgroundsDisabled($params['virtualBackgroundsDisabled']) ->setUserCameraCap($params['userCameraCap']) ->setDisabledFeatures($params['disabledFeatures']) diff --git a/tests/unit/Parameters/CreateMeetingParametersTest.php b/tests/unit/Parameters/CreateMeetingParametersTest.php index e4ebbe06..99cc9cab 100644 --- a/tests/unit/Parameters/CreateMeetingParametersTest.php +++ b/tests/unit/Parameters/CreateMeetingParametersTest.php @@ -63,6 +63,7 @@ public function testCreateMeetingParameters() $this->assertEquals($params['lockSettingsLockOnJoinConfigurable'], $createMeetingParams->isLockSettingsLockOnJoinConfigurable()); $this->assertEquals($params['allowModsToUnmuteUsers'], $createMeetingParams->isAllowModsToUnmuteUsers()); $this->assertEquals($params['allowModsToEjectCameras'], $createMeetingParams->isAllowModsToEjectCameras()); + $this->assertEquals($params['allowPromoteGuestToModerator'], $createMeetingParams->isAllowPromoteGuestToModerator()); $this->assertEquals($params['guestPolicy'], $createMeetingParams->getGuestPolicy()); $this->assertEquals($params['endWhenNoModerator'], $createMeetingParams->isEndWhenNoModerator()); $this->assertEquals($params['endWhenNoModeratorDelayInMinutes'], $createMeetingParams->getEndWhenNoModeratorDelayInMinutes()); @@ -84,7 +85,6 @@ public function testCreateMeetingParameters() $this->assertEquals($params['meetingLayout'], $createMeetingParams->getMeetingLayout()); $this->assertEquals($params['learningDashboardEnabled'], $createMeetingParams->isLearningDashboardEnabled()); $this->assertEquals($params['learningDashboardCleanupDelayInMinutes'], $createMeetingParams->getLearningDashboardCleanupDelayInMinutes()); - $this->assertEquals($params['allowModsToEjectCameras'], $createMeetingParams->isAllowModsToEjectCameras()); $this->assertEquals($params['breakoutRoomsEnabled'], $createMeetingParams->isBreakoutRoomsEnabled()); $this->assertEquals($params['breakoutRoomsPrivateChatEnabled'], $createMeetingParams->isBreakoutRoomsPrivateChatEnabled()); $this->assertEquals($params['breakoutRoomsRecord'], $createMeetingParams->isBreakoutRoomsRecord()); From cf2ff2576f1a49ce426b4e278ebc8d8d5ff4c822 Mon Sep 17 00:00:00 2001 From: Felix Jacobi Date: Fri, 26 Jul 2024 17:46:08 +0200 Subject: [PATCH 40/68] Converted native enums --- src/BigBlueButton.php | 4 +- src/Enum/ApiMethod.php | 38 +++++++++---------- src/Enum/GuestPolicy.php | 10 ++--- src/Enum/MeetingLayout.php | 10 ++--- .../PsrHttpClient/PsrHttpClientTransport.php | 8 ++-- .../SymfonyHttpClientTransport.php | 6 +-- src/Http/Transport/CurlTransport.php | 6 +-- src/Http/Transport/Header.php | 6 +-- src/Parameters/CreateMeetingParameters.php | 2 +- .../AbstractBigBlueButtonFunctionalTest.php | 2 +- tests/unit/Http/Transport/HeaderTest.php | 4 +- .../GetRecordingsTextTracksResponseTest.php | 12 +++--- 12 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index 782a0a22..5bd73a71 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -117,11 +117,11 @@ class BigBlueButton public function __construct(?string $baseUrl = null, ?string $secret = null, ?TransportInterface $transport = null, HashingAlgorithm $hashingAlgorithm = HashingAlgorithm::SHA_1) { if (null === $baseUrl) { - @trigger_error(sprintf('Constructing "%s" without passing a server base URL is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); + @trigger_error(\sprintf('Constructing "%s" without passing a server base URL is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); } if (null === $secret) { - @trigger_error(sprintf('Constructing "%s" without passing a secret is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); + @trigger_error(\sprintf('Constructing "%s" without passing a secret is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); } if (getenv('BBB_SECURITY_SALT') !== false || getenv('BBB_SECRET') !== false) { diff --git a/src/Enum/ApiMethod.php b/src/Enum/ApiMethod.php index 97bbc6e2..307f524c 100644 --- a/src/Enum/ApiMethod.php +++ b/src/Enum/ApiMethod.php @@ -23,24 +23,24 @@ /** * @psalm-immutable */ -class ApiMethod extends Enum +enum ApiMethod: string { - public const CREATE = 'create'; - public const JOIN = 'join'; - public const ENTER = 'enter'; - public const END = 'end'; - public const IS_MEETING_RUNNING = 'isMeetingRunning'; - public const GET_MEETING_INFO = 'getMeetingInfo'; - public const GET_MEETINGS = 'getMeetings'; - public const SIGN_OUT = 'signOut'; - public const GET_RECORDINGS = 'getRecordings'; - public const PUBLISH_RECORDINGS = 'publishRecordings'; - public const DELETE_RECORDINGS = 'deleteRecordings'; - public const UPDATE_RECORDINGS = 'updateRecordings'; - public const GET_RECORDING_TEXT_TRACKS = 'getRecordingTextTracks'; - public const PUT_RECORDING_TEXT_TRACK = 'putRecordingTextTrack'; - public const HOOKS_CREATE = 'hooks/create'; - public const HOOKS_LIST = 'hooks/list'; - public const HOOKS_DESTROY = 'hooks/destroy'; - public const INSERT_DOCUMENT = 'insertDocument'; + case CREATE = 'create'; + case JOIN = 'join'; + case ENTER = 'enter'; + case END = 'end'; + case IS_MEETING_RUNNING = 'isMeetingRunning'; + case GET_MEETING_INFO = 'getMeetingInfo'; + case GET_MEETINGS = 'getMeetings'; + case SIGN_OUT = 'signOut'; + case GET_RECORDINGS = 'getRecordings'; + case PUBLISH_RECORDINGS = 'publishRecordings'; + case DELETE_RECORDINGS = 'deleteRecordings'; + case UPDATE_RECORDINGS = 'updateRecordings'; + case GET_RECORDING_TEXT_TRACKS = 'getRecordingTextTracks'; + case PUT_RECORDING_TEXT_TRACK = 'putRecordingTextTrack'; + case HOOKS_CREATE = 'hooks/create'; + case HOOKS_LIST = 'hooks/list'; + case HOOKS_DESTROY = 'hooks/destroy'; + case INSERT_DOCUMENT = 'insertDocument'; } diff --git a/src/Enum/GuestPolicy.php b/src/Enum/GuestPolicy.php index 4bf90f49..4449bd1c 100644 --- a/src/Enum/GuestPolicy.php +++ b/src/Enum/GuestPolicy.php @@ -23,10 +23,10 @@ /** * @psalm-immutable */ -class GuestPolicy extends Enum +enum GuestPolicy: string { - public const ALWAYS_ACCEPT = 'ALWAYS_ACCEPT'; - public const ALWAYS_DENY = 'ALWAYS_DENY'; - public const ASK_MODERATOR = 'ASK_MODERATOR'; - public const ALWAYS_ACCEPT_AUTH = 'ALWAYS_ACCEPT_AUTH'; + case ALWAYS_ACCEPT = 'ALWAYS_ACCEPT'; + case ALWAYS_DENY = 'ALWAYS_DENY'; + case ASK_MODERATOR = 'ASK_MODERATOR'; + case ALWAYS_ACCEPT_AUTH = 'ALWAYS_ACCEPT_AUTH'; } diff --git a/src/Enum/MeetingLayout.php b/src/Enum/MeetingLayout.php index 39f0b152..6c81ef1d 100644 --- a/src/Enum/MeetingLayout.php +++ b/src/Enum/MeetingLayout.php @@ -23,10 +23,10 @@ /** * @psalm-immutable */ -class MeetingLayout extends Enum +enum MeetingLayout: string { - public const CUSTOM_LAYOUT = 'CUSTOM_LAYOUT'; - public const SMART_LAYOUT = 'SMART_LAYOUT'; - public const PRESENTATION_FOCUS = 'PRESENTATION_FOCUS'; - public const VIDEO_FOCUS = 'VIDEO_FOCUS'; + case CUSTOM_LAYOUT = 'CUSTOM_LAYOUT'; + case SMART_LAYOUT = 'SMART_LAYOUT'; + case PRESENTATION_FOCUS = 'PRESENTATION_FOCUS'; + case VIDEO_FOCUS = 'VIDEO_FOCUS'; } diff --git a/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php b/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php index 9c76ce50..8dd1426a 100644 --- a/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php +++ b/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php @@ -34,7 +34,7 @@ // @codeCoverageIgnoreStart if (!interface_exists(ClientInterface::class)) { - throw new \LogicException(sprintf( + throw new \LogicException(\sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides psr/http-client-implementation.', @@ -44,7 +44,7 @@ } if (!interface_exists(RequestFactoryInterface::class)) { - throw new \LogicException(sprintf( + throw new \LogicException(\sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides psr/http-factory-implementation.', @@ -54,7 +54,7 @@ } if (!interface_exists(StreamFactoryInterface::class)) { - throw new \LogicException(sprintf( + throw new \LogicException(\sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides psr/http-factory-implementation.', @@ -121,7 +121,7 @@ public function request(TransportRequest $request): TransportResponse try { $psrResponse = $this->httpClient->sendRequest($psrRequest); } catch (ClientExceptionInterface $e) { - throw new RuntimeException(sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); + throw new RuntimeException(\sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); } if ($psrResponse->getStatusCode() < 200 || $psrResponse->getStatusCode() >= 300) { diff --git a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php index 3c91cc5c..b07f8ebe 100644 --- a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php +++ b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php @@ -38,7 +38,7 @@ // @codeCoverageIgnoreStart if (!interface_exists(HttpClientInterface::class)) { - throw new \LogicException(sprintf( + throw new \LogicException(\sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides symfony/http-client-implementation.', @@ -89,7 +89,7 @@ public static function create(array $defaultHeaders = [], array $defaultOptions { // @codeCoverageIgnoreStart if (!class_exists(HttpClient::class)) { - throw new \LogicException(sprintf( + throw new \LogicException(\sprintf( 'Cannot create an instance of "%s" when Symfony HttpClient is not installed. '. 'Either instantiate the class by yourself and pass a proper implementation or '. 'try to run "composer require symfony/http-client".', @@ -131,7 +131,7 @@ public function request(TransportRequest $request): TransportResponse return new TransportResponse($symfonyResponse->getContent(), self::extractJsessionCookie($symfonyResponse)); } catch (TransportExceptionInterface $e) { - throw new RuntimeException(sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); + throw new RuntimeException(\sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); } catch (ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface $e) { throw new NetworkException('Bad response.', $e->getCode(), $e); } diff --git a/src/Http/Transport/CurlTransport.php b/src/Http/Transport/CurlTransport.php index 4a7980d6..f0c4708d 100644 --- a/src/Http/Transport/CurlTransport.php +++ b/src/Http/Transport/CurlTransport.php @@ -197,9 +197,9 @@ private static function getHeadersAndContentFromCurlHandle($curlHandle): array // @codeCoverageIgnoreStart if (\PHP_VERSION_ID >= 80000 && !$curlHandle instanceof \CurlHandle) { /* @noinspection PhpElementIsNotAvailableInCurrentPhpVersionInspection */ - throw new \InvalidArgumentException(sprintf('$curlHandle must be "%s". "%s" given.', \CurlHandle::class, get_debug_type($curlHandle))); + throw new \InvalidArgumentException(\sprintf('$curlHandle must be "%s". "%s" given.', \CurlHandle::class, get_debug_type($curlHandle))); } elseif (\PHP_VERSION_ID < 80000 && !\is_resource($curlHandle)) { - throw new \InvalidArgumentException(sprintf('$curlHandle must be resource. "%s" given.', \is_object($curlHandle) ? \get_class($curlHandle) : \gettype($curlHandle))); + throw new \InvalidArgumentException(\sprintf('$curlHandle must be resource. "%s" given.', \is_object($curlHandle) ? \get_class($curlHandle) : \gettype($curlHandle))); } // @codeCoverageIgnoreEnd @@ -231,7 +231,7 @@ private static function getHeadersAndContentFromCurlHandle($curlHandle): array $splitHeader = explode(': ', $line, 2); // @codeCoverageIgnoreStart if (!isset($splitHeader[0], $splitHeader[1])) { - throw new \InvalidArgumentException(sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $line)); + throw new \InvalidArgumentException(\sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $line)); } // @codeCoverageIgnoreEnd diff --git a/src/Http/Transport/Header.php b/src/Http/Transport/Header.php index 1a38bf2a..1a3f71d1 100644 --- a/src/Http/Transport/Header.php +++ b/src/Http/Transport/Header.php @@ -43,7 +43,7 @@ public static function mergeCurlHeaders(array ...$headers): array foreach ($headers as $headerSet) { foreach ($headerSet as $header) { if (!\is_string($header)) { - throw new \InvalidArgumentException(sprintf( + throw new \InvalidArgumentException(\sprintf( 'Non-string header with type "%s" passed.', \is_object($header) ? \get_class($header) : \gettype($header) )); @@ -51,7 +51,7 @@ public static function mergeCurlHeaders(array ...$headers): array $splitHeader = explode(': ', $header, 2); if (!isset($splitHeader[0], $splitHeader[1])) { - throw new \InvalidArgumentException(sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $header)); + throw new \InvalidArgumentException(\sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $header)); } // Enforce lower case for header names to avoid duplicates in mixed case. The case of header names should @@ -62,7 +62,7 @@ public static function mergeCurlHeaders(array ...$headers): array $result = []; foreach ($mergedHeaders as $header => $value) { - $result[] = sprintf('%s: %s', $header, $value); + $result[] = \sprintf('%s: %s', $header, $value); } return $result; diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index ee11f0b0..c0a7c05d 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -20,8 +20,8 @@ namespace BigBlueButton\Parameters; -use BigBlueButton\Enum\GuestPolicy; use BigBlueButton\Enum\Feature; +use BigBlueButton\Enum\GuestPolicy; /** * @method string getName() diff --git a/tests/functional/AbstractBigBlueButtonFunctionalTest.php b/tests/functional/AbstractBigBlueButtonFunctionalTest.php index 648e1693..eb75b2f0 100644 --- a/tests/functional/AbstractBigBlueButtonFunctionalTest.php +++ b/tests/functional/AbstractBigBlueButtonFunctionalTest.php @@ -198,7 +198,7 @@ public function testJoinMeeting() $params = $this->generateJoinMeetingParams(); $joinMeetingParams = new JoinMeetingParameters($result->getMeetingId(), $params['fullName'], $params['role']); $joinMeetingParams->setRedirect(false); - $joinMeetingParams->setCreateTime(sprintf('%.0f', $creationTime)); + $joinMeetingParams->setCreateTime(\sprintf('%.0f', $creationTime)); $joinMeeting = $this->bbb->joinMeeting($joinMeetingParams); $this->assertEquals('SUCCESS', $joinMeeting->getReturnCode(), 'Join meeting'); diff --git a/tests/unit/Http/Transport/HeaderTest.php b/tests/unit/Http/Transport/HeaderTest.php index c7217f4f..fc34d692 100644 --- a/tests/unit/Http/Transport/HeaderTest.php +++ b/tests/unit/Http/Transport/HeaderTest.php @@ -61,7 +61,7 @@ public function provideBadlyFormattedHeaders(): iterable public function testMergeCurlHeadersWithBadHeaders(string $badHeader): void { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $badHeader)); + $this->expectExceptionMessage(\sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $badHeader)); Header::mergeCurlHeaders([$badHeader]); } @@ -82,7 +82,7 @@ public function provideNonStringHeaders(): iterable public function testMergeCurlHeadersWithNonStringHeaders($badHeader): void { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf( + $this->expectExceptionMessage(\sprintf( 'Non-string header with type "%s" passed.', \is_object($badHeader) ? \get_class($badHeader) : \gettype($badHeader) )); diff --git a/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php b/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php index 7d9fd526..5eecf46c 100644 --- a/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php +++ b/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php @@ -41,12 +41,12 @@ public function testGetRecordingTextTracksResponseTypes() $secondTracks = $this->tracks->getTracks()[1]; $this->assertEachGetterValueIsString($secondTracks, [ - 'getHref', - 'getKind', - 'getLabel', - 'getLang', - 'getSource', - ] + 'getHref', + 'getKind', + 'getLabel', + 'getLang', + 'getSource', + ] ); } From 7d6d7ed95b73b28213dbcc448dde168bc2d4d113 Mon Sep 17 00:00:00 2001 From: Felix Jacobi Date: Thu, 1 Aug 2024 09:19:14 +0200 Subject: [PATCH 41/68] Improved code quality (#188) * Installed rector * Applied Rector quality improvements * Fixed CS * Updated Psalm * Applied more typed property rules * Updated rector configs * Fixed CS * Added PHPStan and fixed issues to up to level 5 * Fixed symfony/process dependency * Fixed tests * Rector * Added enum test * Added strict_types * Fix workflow * Fixed strict types related errors * Fix CS * Added deprecation for not passing base URL and secret * Ignore deprecation * Fixed CS * Fixed unsafe comparison * Fix PHPStan for level 6 * Fixed typing issues * Updated rector config * Rectored after merge * Fixed deprecation message --- .github/workflows/ci.yml | 9 + .gitignore | 2 + .php-cs-fixer.php | 4 +- composer.json | 20 +- phpstan.neon | 17 + phpunit.xml.dist => phpunit.xml | 0 rector.php | 35 ++ src/BigBlueButton.php | 65 ++- src/Core/ApiMethod.php | 41 -- src/Core/Attendee.php | 66 +-- src/Core/GuestPolicy.php | 32 -- src/Core/Hook.php | 45 +- src/Core/ImagePreview.php | 24 +- src/Core/Meeting.php | 182 +++----- src/Core/MeetingLayout.php | 32 -- src/Core/PlaybackFormat.php | 17 +- src/Core/Record.php | 31 +- src/Core/Track.php | 28 +- src/Enum/ApiMethod.php | 2 + src/Enum/Feature.php | 2 + src/Enum/GuestPolicy.php | 2 + src/Enum/HashingAlgorithm.php | 2 + src/Enum/MeetingLayout.php | 2 + src/Enum/Role.php | 2 + src/Http/SetCookie.php | 49 +- .../PsrHttpClient/PsrHttpClientTransport.php | 32 +- .../SymfonyHttpClientTransport.php | 20 +- src/Http/Transport/CurlTransport.php | 33 +- src/Http/Transport/Header.php | 2 +- src/Http/Transport/TransportRequest.php | 20 +- src/Http/Transport/TransportResponse.php | 14 +- src/Parameters/BaseParameters.php | 51 ++- src/Parameters/CreateMeetingParameters.php | 430 ++++-------------- src/Parameters/DeleteRecordingsParameters.php | 11 +- src/Parameters/EndMeetingParameters.php | 10 +- src/Parameters/GetMeetingInfoParameters.php | 11 +- .../GetRecordingTextTracksParameters.php | 11 +- src/Parameters/GetRecordingsParameters.php | 20 +- src/Parameters/HooksCreateParameters.php | 28 +- src/Parameters/HooksDestroyParameters.php | 11 +- src/Parameters/HooksListParameters.php | 8 +- src/Parameters/InsertDocumentParameters.php | 16 +- src/Parameters/IsMeetingRunningParameters.php | 11 +- src/Parameters/JoinMeetingParameters.php | 89 +--- src/Parameters/MetaParameters.php | 19 +- .../PublishRecordingsParameters.php | 17 +- .../PutRecordingTextTrackParameters.php | 40 +- src/Parameters/UpdateRecordingsParameters.php | 11 +- src/Parameters/UserDataParameters.php | 19 +- src/Responses/ApiVersionResponse.php | 3 + src/Responses/BaseResponse.php | 17 +- src/Responses/BaseResponseAsJson.php | 8 +- src/Responses/CreateMeetingResponse.php | 2 + src/Responses/DeleteRecordingsResponse.php | 3 + src/Responses/EndMeetingResponse.php | 3 + src/Responses/GetMeetingInfoResponse.php | 8 +- src/Responses/GetMeetingsResponse.php | 5 +- .../GetRecordingTextTracksResponse.php | 5 +- src/Responses/GetRecordingsResponse.php | 5 +- src/Responses/HooksCreateResponse.php | 3 + src/Responses/HooksDestroyResponse.php | 3 + src/Responses/HooksListResponse.php | 5 +- src/Responses/InsertDocumentResponse.php | 2 + src/Responses/IsMeetingRunningResponse.php | 3 + src/Responses/JoinMeetingResponse.php | 3 + src/Responses/PublishRecordingsResponse.php | 3 + .../PutRecordingTextTrackResponse.php | 3 + src/Responses/UpdateRecordingsResponse.php | 3 + src/Util/ArrayHelper.php | 11 +- src/Util/UrlBuilder.php | 31 +- tests/bootstrap.php | 6 +- tests/{ => common}/TestCase.php | 147 +++--- .../AbstractBigBlueButtonFunctionalTest.php | 45 +- .../Http/Transport/CurlTransportTest.php | 25 +- .../Http/Transport/Fixtures/web/dump.php | 2 +- .../Http/Transport/TestHttpServer.php | 7 +- tests/unit/BigBlueButtonTest.php | 29 +- tests/unit/Http/SetCookieTest.php | 16 +- .../PsrHttpClientTransportTest.php | 15 +- .../SymfonyHttpClientTransportTest.php | 5 +- tests/unit/Http/Transport/CookieTest.php | 3 +- tests/unit/Http/Transport/HeaderTest.php | 8 +- .../Http/Transport/TransportRequestTest.php | 2 +- .../Http/Transport/TransportResponseTest.php | 3 +- tests/unit/Parameters/BaseParametersTest.php | 33 +- .../CreateMeetingParametersTest.php | 16 +- .../DeleteRecordingsParametersTest.php | 10 +- .../Parameters/EndMeetingParametersTest.php | 7 +- .../GetMeetingInfoParametersTest.php | 10 +- .../GetRecordingTextTracksParametersTest.php | 9 +- .../GetRecordingsParametersTest.php | 10 +- .../Parameters/HooksCreateParametersTest.php | 10 +- .../Parameters/HooksDestroyParametersTest.php | 10 +- .../Parameters/HooksListParametersTest.php | 8 +- .../InsertDocumentParametersTest.php | 5 +- .../IsMeetingRunningParametersTest.php | 10 +- .../Parameters/JoinMeetingParametersTest.php | 6 +- .../PublishRecordingsParametersTest.php | 12 +- .../PutRecordingTextTracksParametersTest.php | 9 +- .../UpdateRecordingsParametersTest.php | 9 +- .../unit/Responses/ApiVersionResponseTest.php | 16 +- .../Responses/CreateMeetingResponseTest.php | 17 +- .../DeleteRecordingsResponseTest.php | 16 +- .../unit/Responses/EndMeetingResponseTest.php | 16 +- .../Responses/GetMeetingInfoResponseTest.php | 25 +- .../Responses/GetMeetingsResponseTest.php | 17 +- .../Responses/GetRecordingsResponseTest.php | 18 +- .../GetRecordingsTextTracksResponseTest.php | 17 +- .../Responses/HooksCreateResponseTest.php | 16 +- .../Responses/HooksDestroyResponseTest.php | 16 +- .../unit/Responses/HooksListResponseTest.php | 16 +- .../Responses/InsertDocumentResponseTest.php | 9 +- .../IsMeetingRunningResponseTest.php | 16 +- .../Responses/JoinMeetingResponseTest.php | 16 +- .../PublishRecordingsResponseTest.php | 16 +- .../PutRecordingTextTrackResponseTest.php | 7 +- .../UpdateRecordingsResponseTest.php | 16 +- tests/unit/Util/ArrayHelperTest.php | 8 +- tests/unit/Util/UrlBuilderTest.php | 3 +- tools/.phpstan/.gitignore | 1 + tools/.phpstan/composer.json | 5 + tools/.phpstan/composer.lock | 81 ++++ tools/.psalm/composer.json | 2 +- tools/.rector/.gitignore | 2 + tools/.rector/composer.json | 5 + tools/README.md | 2 +- tools/bootstrap.php | 13 + tools/phpstan | 7 + tools/rector | 7 + 129 files changed, 1157 insertions(+), 1510 deletions(-) create mode 100644 phpstan.neon rename phpunit.xml.dist => phpunit.xml (100%) create mode 100644 rector.php delete mode 100644 src/Core/ApiMethod.php delete mode 100644 src/Core/GuestPolicy.php delete mode 100644 src/Core/MeetingLayout.php rename tests/{ => common}/TestCase.php (82%) create mode 100644 tools/.phpstan/.gitignore create mode 100644 tools/.phpstan/composer.json create mode 100644 tools/.phpstan/composer.lock create mode 100644 tools/.rector/.gitignore create mode 100644 tools/.rector/composer.json create mode 100644 tools/bootstrap.php create mode 100755 tools/phpstan create mode 100755 tools/rector diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2049ebc6..8693cf9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,3 +69,12 @@ jobs: - name: Upload coverage if: ${{ matrix.php-versions == '8.1' }} uses: codecov/codecov-action@v3 + - name: Run rector + if: ${{ matrix.php-versions == '8.1' }} + run: tools/rector process --dry-run + - name: Run psalm + if: ${{ matrix.php-versions == '8.1' }} + run: tools/psalm + - name: Run phpstan + if: ${{ matrix.php-versions == '8.1' }} + run: tools/phpstan diff --git a/.gitignore b/.gitignore index d6bdc7e4..3fdf8edd 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ reports # # See https://github.com/littleredbutton/bigbluebutton-api-php/pull/115 for the discussion. /composer.lock + +/Makefile.iservmake diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index a714f742..ccd311ce 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -5,8 +5,8 @@ $finder = \PhpCsFixer\Finder::create() ->files() ->name('*.php') - ->in(__DIR__ . '/src') - ->in(__DIR__ . '/tests'); + ->in(__DIR__.'/src') + ->in(__DIR__.'/tests'); $config = new PhpCsFixer\Config(); diff --git a/composer.json b/composer.json index 2c59e6c8..c79ab95a 100644 --- a/composer.json +++ b/composer.json @@ -91,8 +91,17 @@ }, "autoload-dev": { "psr-4": { + "BigBlueButton\\Tests\\Common\\": [ + "tests/common" + ], "BigBlueButton\\Tests\\Functional\\": [ "tests/functional" + ], + "BigBlueButton\\Tests\\Integration\\": [ + "tests/integration" + ], + "BigBlueButton\\Tests\\Unit\\": [ + "tests/unit" ] } }, @@ -105,6 +114,9 @@ "psalm": "tools/psalm --threads=1", "psalm-clear": "tools/psalm --clear-cache && tools/psalm --clear-global-cache", "psalm-fix": "tools/psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType", + "phpstan": "tools/phpstan analyse", + "rector": "tools/rector process --dry-run src/ tests/", + "rector-fix": "tools/rector process src/ tests/", "post-install-cmd": "tools/composer-git-hooks add --ignore-lock", "post-update-cmd": "tools/composer-git-hooks update" }, @@ -115,7 +127,9 @@ ], "pre-push": [ "tools/phpunit --testsuite=\"BigBlueButton unit test suite,BigBlueButton integration test suite\"", - "tools/psalm --threads=1" + "tools/psalm --threads=1", + "tools/phpstan analyse", + "tools/rector process --dry-run src/ tests/" ], "post-merge": "composer install", "post-checkout": "composer install" @@ -128,8 +142,10 @@ } }, "friendsofphp/php-cs-fixer": "^3.3", + "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9", - "vimeo/psalm": "^4.22" + "rector/rector": "^1.0", + "vimeo/psalm": "^5.23" } } } diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..9110ad71 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,17 @@ +parameters: + paths: + - src + - tests + parallel: + maximumNumberOfProcesses: 4 + level: 6 + inferPrivatePropertyTypeFromConstructor: true + bootstrapFiles: + - tools/bootstrap.php + ignoreErrors: + - + message: '#^Offset ''input'' does not exist on array\{\}\.$#' + path: tests/integration/Http/Transport/CurlTransportTest.php + - + message: '#^Offset ''vars'' does not exist on array\{\}\.$#' + path: tests/integration/Http/Transport/CurlTransportTest.php diff --git a/phpunit.xml.dist b/phpunit.xml similarity index 100% rename from phpunit.xml.dist rename to phpunit.xml diff --git a/rector.php b/rector.php new file mode 100644 index 00000000..8698ee66 --- /dev/null +++ b/rector.php @@ -0,0 +1,35 @@ +withPaths([ + __DIR__.'/src', + __DIR__.'/tests', + ]) + ->withPhpSets() + ->withRules([ + AddVoidReturnTypeWhereNoReturnRector::class, + DeclareStrictTypesRector::class, + FinalizeTestCaseClassRector::class, + RemoveUnusedVariableAssignRector::class, + RemoveUselessParamTagRector::class, + RemoveUselessReturnTagRector::class, + TypedPropertyFromAssignsRector::class, + TypedPropertyFromStrictConstructorRector::class, + TypedPropertyFromStrictSetUpRector::class, + ]) + ->withImportNames(importShortClasses: false, removeUnusedImports: true) +; diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index 5bd73a71..c3c18f31 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -1,4 +1,7 @@ securitySecret = $secret ?: getenv('BBB_SECURITY_SALT') ?: getenv('BBB_SECRET'); - $this->bbbServerBaseUrl = $baseUrl ?: getenv('BBB_SERVER_BASE_URL'); + $securitySecret = $secret ?: getenv('BBB_SECURITY_SALT') ?: getenv('BBB_SECRET'); + + if (false === $securitySecret) { + // @codeCoverageIgnoreStart + @trigger_error(\sprintf('Constructing "%s" without passing a secret is deprecated since 6.0 and will throw an exception in 7.0.', self::class), \E_USER_DEPRECATED); + $this->securitySecret = ''; // previous behaviour + // @codeCoverageIgnoreEnd + } else { + $this->securitySecret = $securitySecret; + } - $this->hashingAlgorithm = $hashingAlgorithm; + $bbbServerBaseUrl = $baseUrl ?: getenv('BBB_SERVER_BASE_URL'); + + if (false === $bbbServerBaseUrl) { + // @codeCoverageIgnoreStart + @trigger_error(\sprintf('Constructing "%s" without passing a server base URL is deprecated since 6.0 and will throw an exception in 7.0.', self::class), \E_USER_DEPRECATED); + $this->bbbServerBaseUrl = ''; // previous behaviour + // @codeCoverageIgnoreEnd + } else { + $this->bbbServerBaseUrl = $bbbServerBaseUrl; + } if (empty($this->bbbServerBaseUrl)) { throw new ConfigException('Base url required'); @@ -186,7 +183,7 @@ public function isConnectionWorking(): bool } // HTTP exception or XML parse - } catch (\Exception $e) { + } catch (\Exception) { } $this->connectionError = self::CONNECTION_ERROR_BASEURL; diff --git a/src/Core/ApiMethod.php b/src/Core/ApiMethod.php deleted file mode 100644 index 7d960eab..00000000 --- a/src/Core/ApiMethod.php +++ /dev/null @@ -1,41 +0,0 @@ -. - */ - -namespace BigBlueButton\Core; - -/* @deprecated and will be removed in 6.0. Use \BigBlueButton\Enum\ApiMethod instead */ -final class ApiMethod -{ - public const CREATE = \BigBlueButton\Enum\ApiMethod::CREATE; - public const JOIN = \BigBlueButton\Enum\ApiMethod::JOIN; - public const END = \BigBlueButton\Enum\ApiMethod::END; - public const IS_MEETING_RUNNING = \BigBlueButton\Enum\ApiMethod::IS_MEETING_RUNNING; - public const GET_MEETING_INFO = \BigBlueButton\Enum\ApiMethod::GET_MEETING_INFO; - public const GET_MEETINGS = \BigBlueButton\Enum\ApiMethod::GET_MEETINGS; - public const GET_RECORDINGS = \BigBlueButton\Enum\ApiMethod::GET_RECORDINGS; - public const PUBLISH_RECORDINGS = \BigBlueButton\Enum\ApiMethod::PUBLISH_RECORDINGS; - public const DELETE_RECORDINGS = \BigBlueButton\Enum\ApiMethod::DELETE_RECORDINGS; - public const UPDATE_RECORDINGS = \BigBlueButton\Enum\ApiMethod::UPDATE_RECORDINGS; - public const GET_RECORDING_TEXT_TRACKS = \BigBlueButton\Enum\ApiMethod::GET_RECORDING_TEXT_TRACKS; - public const PUT_RECORDING_TEXT_TRACK = \BigBlueButton\Enum\ApiMethod::PUT_RECORDING_TEXT_TRACK; - public const HOOKS_CREATE = \BigBlueButton\Enum\ApiMethod::HOOKS_CREATE; - public const HOOKS_LIST = \BigBlueButton\Enum\ApiMethod::HOOKS_LIST; - public const HOOKS_DESTROY = \BigBlueButton\Enum\ApiMethod::HOOKS_DESTROY; - public const INSERT_DOCUMENT = \BigBlueButton\Enum\ApiMethod::INSERT_DOCUMENT; -} diff --git a/src/Core/Attendee.php b/src/Core/Attendee.php index b71b4d9d..1ef79b21 100644 --- a/src/Core/Attendee.php +++ b/src/Core/Attendee.php @@ -1,4 +1,7 @@ */ + private array $customData = []; + + private readonly string $clientType; public function __construct(\SimpleXMLElement $xml) { @@ -124,6 +101,7 @@ public function getClientType(): string return $this->clientType; } + /** @return array */ public function getCustomData(): array { return $this->customData; diff --git a/src/Core/GuestPolicy.php b/src/Core/GuestPolicy.php deleted file mode 100644 index 94d95060..00000000 --- a/src/Core/GuestPolicy.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -namespace BigBlueButton\Core; - -/* @deprecated and will be removed in 6.0. Use \BigBlueButton\Enum\GuestPolicy instead */ -final class GuestPolicy -{ - public const ALWAYS_ACCEPT = \BigBlueButton\Enum\GuestPolicy::ALWAYS_ACCEPT; - public const ALWAYS_DENY = \BigBlueButton\Enum\GuestPolicy::ALWAYS_DENY; - public const ASK_MODERATOR = \BigBlueButton\Enum\GuestPolicy::ASK_MODERATOR; - public const ALWAYS_ACCEPT_AUTH = \BigBlueButton\Enum\GuestPolicy::ALWAYS_ACCEPT_AUTH; -} diff --git a/src/Core/Hook.php b/src/Core/Hook.php index 3c173dfe..5cda828c 100644 --- a/src/Core/Hook.php +++ b/src/Core/Hook.php @@ -1,5 +1,7 @@ rawXml = $xml; - $this->hookId = (int) $xml->hookID->__toString(); - $this->callbackUrl = $xml->callbackURL->__toString(); - $this->meetingId = $xml->meetingID->__toString(); - $this->permanentHook = $xml->permanentHook->__toString() === 'true'; - $this->rawData = $xml->rawData->__toString() === 'true'; + $this->hookId = (int) $this->rawXml->hookID->__toString(); + $this->callbackUrl = $this->rawXml->callbackURL->__toString(); + $this->meetingId = $this->rawXml->meetingID->__toString(); + $this->permanentHook = $this->rawXml->permanentHook->__toString() === 'true'; + $this->rawData = $this->rawXml->rawData->__toString() === 'true'; } public function getHookId(): int diff --git a/src/Core/ImagePreview.php b/src/Core/ImagePreview.php index 737db8c7..f58d4421 100644 --- a/src/Core/ImagePreview.php +++ b/src/Core/ImagePreview.php @@ -23,24 +23,12 @@ class ImagePreview { - /** @var int */ - private $width; - - /** @var int */ - private $height; - - /** @var string */ - private $alt; - - /** @var string */ - private $url; - - public function __construct(int $width, int $height, string $alt, string $url) - { - $this->width = $width; - $this->height = $height; - $this->alt = $alt; - $this->url = $url; + public function __construct( + private readonly int $width, + private readonly int $height, + private readonly string $alt, + private readonly string $url, + ) { } public function getWidth(): int diff --git a/src/Core/Meeting.php b/src/Core/Meeting.php index 5ca34386..84d24ded 100644 --- a/src/Core/Meeting.php +++ b/src/Core/Meeting.php @@ -1,5 +1,7 @@ |null */ + private ?array $metas = null; - /** - * @var bool - */ - private $isBreakout; + private readonly bool $isBreakout; - public function __construct(\SimpleXMLElement $xml) + public function __construct(protected \SimpleXMLElement $rawXml) { - $this->rawXml = $xml; - $this->meetingId = $xml->meetingID->__toString(); - $this->meetingName = $xml->meetingName->__toString(); - $this->creationTime = (float) $xml->createTime; - $this->creationDate = $xml->createDate->__toString(); - $this->voiceBridge = (int) $xml->voiceBridge; - $this->dialNumber = $xml->dialNumber->__toString(); - $this->hasBeenForciblyEnded = $xml->hasBeenForciblyEnded->__toString() === 'true'; - $this->isRunning = $xml->running->__toString() === 'true'; - $this->participantCount = (int) $xml->participantCount; - $this->listenerCount = (int) $xml->listenerCount; - $this->voiceParticipantCount = (int) $xml->voiceParticipantCount; - $this->videoCount = (int) $xml->videoCount; - $this->duration = (int) $xml->duration; - $this->hasUserJoined = $xml->hasUserJoined->__toString() === 'true'; - $this->internalMeetingId = $xml->internalMeetingID->__toString(); - $this->parentMeetingID = $xml->parentMeetingID->__toString(); - $this->isRecording = $xml->recording->__toString() === 'true'; - $this->startTime = (float) $xml->startTime; - $this->endTime = (float) $xml->endTime; - $this->maxUsers = (int) $xml->maxUsers->__toString(); - $this->moderatorCount = (int) $xml->moderatorCount->__toString(); - $this->isBreakout = $xml->isBreakout->__toString() === 'true'; + $this->meetingId = $this->rawXml->meetingID->__toString(); + $this->meetingName = $this->rawXml->meetingName->__toString(); + $this->creationTime = (float) $this->rawXml->createTime; + $this->creationDate = $this->rawXml->createDate->__toString(); + $this->voiceBridge = (int) $this->rawXml->voiceBridge; + $this->dialNumber = $this->rawXml->dialNumber->__toString(); + $this->hasBeenForciblyEnded = $this->rawXml->hasBeenForciblyEnded->__toString() === 'true'; + $this->isRunning = $this->rawXml->running->__toString() === 'true'; + $this->participantCount = (int) $this->rawXml->participantCount; + $this->listenerCount = (int) $this->rawXml->listenerCount; + $this->voiceParticipantCount = (int) $this->rawXml->voiceParticipantCount; + $this->videoCount = (int) $this->rawXml->videoCount; + $this->duration = (int) $this->rawXml->duration; + $this->hasUserJoined = $this->rawXml->hasUserJoined->__toString() === 'true'; + $this->internalMeetingId = $this->rawXml->internalMeetingID->__toString(); + $this->parentMeetingID = $this->rawXml->parentMeetingID->__toString(); + $this->isRecording = $this->rawXml->recording->__toString() === 'true'; + $this->startTime = (float) $this->rawXml->startTime; + $this->endTime = (float) $this->rawXml->endTime; + $this->maxUsers = (int) $this->rawXml->maxUsers->__toString(); + $this->moderatorCount = (int) $this->rawXml->moderatorCount->__toString(); + $this->isBreakout = $this->rawXml->isBreakout->__toString() === 'true'; } public function getMeetingId(): string @@ -308,9 +235,7 @@ public function getModerators(): array { $attendees = $this->getAttendees(); - $moderators = array_filter($attendees, function ($attendee) { - return $attendee->getRole() === Role::MODERATOR->value; - }); + $moderators = array_filter($attendees, static fn ($attendee) => $attendee->getRole() === Role::MODERATOR->value); return array_values($moderators); } @@ -324,13 +249,12 @@ public function getViewers(): array { $attendees = $this->getAttendees(); - $viewers = array_filter($attendees, function ($attendee) { - return $attendee->getRole() === Role::VIEWER->value; - }); + $viewers = array_filter($attendees, static fn ($attendee) => $attendee->getRole() === Role::VIEWER->value); return array_values($viewers); } + /** @return array */ public function getMetas(): array { if ($this->metas === null) { diff --git a/src/Core/MeetingLayout.php b/src/Core/MeetingLayout.php deleted file mode 100644 index 4691720c..00000000 --- a/src/Core/MeetingLayout.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -namespace BigBlueButton\Core; - -/* @deprecated Use \BigBlueButton\Enum\MeetingLayout instead */ -final class MeetingLayout -{ - public const CUSTOM_LAYOUT = \BigBlueButton\Enum\MeetingLayout::CUSTOM_LAYOUT; - public const SMART_LAYOUT = \BigBlueButton\Enum\MeetingLayout::SMART_LAYOUT; - public const PRESENTATION_FOCUS = \BigBlueButton\Enum\MeetingLayout::PRESENTATION_FOCUS; - public const VIDEO_FOCUS = \BigBlueButton\Enum\MeetingLayout::VIDEO_FOCUS; -} diff --git a/src/Core/PlaybackFormat.php b/src/Core/PlaybackFormat.php index bf9cb728..ef1209e1 100644 --- a/src/Core/PlaybackFormat.php +++ b/src/Core/PlaybackFormat.php @@ -23,23 +23,18 @@ class PlaybackFormat { - /** @var string */ - private $type; + private readonly string $type; - /** @var string */ - private $url; + private readonly string $url; - /** @var int */ - private $processingTime; + private readonly int $processingTime; - /** @var int */ - private $length; + private readonly int $length; /** @var ImagePreview[] */ - private $imagePreviews; + private ?array $imagePreviews = null; - /** @var \SimpleXMLElement */ - private $imagePreviewsRaw; + private readonly ?\SimpleXMLElement $imagePreviewsRaw; public function __construct(\SimpleXMLElement $xml) { diff --git a/src/Core/Record.php b/src/Core/Record.php index 0cf21290..4bc11415 100644 --- a/src/Core/Record.php +++ b/src/Core/Record.php @@ -1,4 +1,7 @@ */ + private array $metas = []; /** @var PlaybackFormat[] */ - private $playbackFormats = []; - private $playbackType; - private $playbackUrl; - private $playbackLength; + private array $playbackFormats = []; public function __construct(\SimpleXMLElement $xml) { @@ -50,9 +51,6 @@ public function __construct(\SimpleXMLElement $xml) $this->startTime = (float) $xml->startTime->__toString(); $this->endTime = (float) $xml->endTime->__toString(); $this->participantCount = (int) $xml->participants->__toString(); - $this->playbackType = $xml->playback->format->type->__toString(); - $this->playbackUrl = $xml->playback->format->url->__toString(); - $this->playbackLength = (int) $xml->playback->format->length->__toString(); foreach ($xml->playback->children() as $format) { $this->playbackFormats[] = new PlaybackFormat($format); @@ -103,6 +101,7 @@ public function getParticipantCount(): int return $this->participantCount; } + /** @return array */ public function getMetas(): array { return $this->metas; diff --git a/src/Core/Track.php b/src/Core/Track.php index e1807f56..7ef014ac 100644 --- a/src/Core/Track.php +++ b/src/Core/Track.php @@ -1,4 +1,7 @@ */ + private static array $defaults = [ 'Name' => null, 'Value' => null, 'Domain' => null, @@ -50,9 +48,9 @@ final class SetCookie ]; /** - * @var array Cookie data + * @var array Cookie data */ - private $data; + private ?array $data; /** * Create a new SetCookie object from a string. @@ -66,7 +64,7 @@ public static function fromString(string $cookie): self // Explode the cookie string using a series of semicolons $pieces = array_filter(array_map('trim', explode(';', $cookie))); // The name of the cookie (first kvp) must exist and include an equal sign. - if (!isset($pieces[0]) || strpos($pieces[0], '=') === false) { + if (!isset($pieces[0]) || !str_contains($pieces[0], '=')) { return new self($data); } @@ -98,19 +96,11 @@ public static function fromString(string $cookie): self } /** - * @param array $data Array of cookie data provided by a Cookie parser + * @param array $data Array of cookie data provided by a Cookie parser */ public function __construct(array $data = []) { - /** @var array|null $replaced will be null in case of replace error */ - $replaced = array_replace(self::$defaults, $data); - // @codeCoverageIgnoreStart - if ($replaced === null) { - throw new \InvalidArgumentException('Unable to replace the default values for the Cookie.'); - } - // @codeCoverageIgnoreEnd - - $this->data = $replaced; + $this->data = array_replace(self::$defaults, $data); // Extract the Expires value and turn it into a UNIX timestamp if needed if (!$this->getExpires() && $this->getMaxAge()) { // Calculate the Expires date @@ -120,13 +110,13 @@ public function __construct(array $data = []) } } - public function __toString() + public function __toString(): string { $str = $this->data['Name'].'='.$this->data['Value'].'; '; foreach ($this->data as $k => $v) { if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) { if ($k === 'Expires') { - $str .= 'Expires='.gmdate('D, d M Y H:i:s \G\M\T', $v).'; '; + $str .= 'Expires='.gmdate('D, d M Y H:i:s \G\M\T', (int) $v).'; '; } else { $str .= ($v === true ? $k : "{$k}={$v}").'; '; } @@ -136,6 +126,7 @@ public function __toString() return rtrim($str, '; '); } + /** @return array */ public function toArray(): array { return $this->data; @@ -216,7 +207,7 @@ public function setPath(string $path): void */ public function getMaxAge(): ?int { - return $this->data['Max-Age'] == null ? null : (int) $this->data['Max-Age']; + return $this->data['Max-Age'] === null ? null : (int) $this->data['Max-Age']; } /** @@ -231,10 +222,8 @@ public function setMaxAge(int $maxAge): void /** * The UNIX timestamp when the cookie Expires. - * - * @return string|int|null */ - public function getExpires() + public function getExpires(): int|string|null { return $this->data['Expires']; } @@ -244,7 +233,7 @@ public function getExpires() * * @param int|string $timestamp unix timestamp or any English textual datetime description */ - public function setExpires($timestamp): void + public function setExpires(int|string $timestamp): void { $this->data['Expires'] = is_numeric($timestamp) ? (int) $timestamp @@ -325,22 +314,22 @@ public function matchesPath(string $requestPath): bool $cookiePath = $this->getPath(); // Match on exact matches or when path is the default empty "/" - if ($cookiePath === '/' || $cookiePath == $requestPath) { + if ($cookiePath === '/' || $cookiePath === $requestPath) { return true; } // Ensure that the cookie-path is a prefix of the request path. - if (0 !== strpos($requestPath, $cookiePath)) { + if (!str_starts_with($requestPath, $cookiePath)) { return false; } // Match if the last character of the cookie-path is "/" - if (substr($cookiePath, -1, 1) === '/') { + if (str_ends_with($cookiePath, '/')) { return true; } // Match if the first character not included in cookie path is "/" - return substr($requestPath, \strlen($cookiePath), 1) === '/'; + return $requestPath[\strlen($cookiePath)] === '/'; } /** @@ -386,7 +375,7 @@ public function isExpired(): bool * * @return bool|string Returns true if valid or an error message if invalid */ - public function validate() + public function validate(): bool|string { $name = $this->getName(); if ($name === '') { diff --git a/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php b/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php index 8dd1426a..befa70d9 100644 --- a/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php +++ b/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php @@ -69,39 +69,11 @@ */ final class PsrHttpClientTransport implements TransportInterface { - /** - * @var ClientInterface - */ - private $httpClient; - - /** - * @var RequestFactoryInterface - */ - private $requestFactory; - - /** - * @var StreamFactoryInterface - */ - private $streamFactory; - - /** - * @var string[] - */ - private $defaultHeaders; - /** * @param string[] $defaultHeaders additional headers to pass on each request */ - public function __construct( - ClientInterface $httpClient, - RequestFactoryInterface $requestFactory, - StreamFactoryInterface $streamFactory, - array $defaultHeaders = [] - ) { - $this->httpClient = $httpClient; - $this->requestFactory = $requestFactory; - $this->streamFactory = $streamFactory; - $this->defaultHeaders = $defaultHeaders; + public function __construct(private readonly ClientInterface $httpClient, private readonly RequestFactoryInterface $requestFactory, private readonly StreamFactoryInterface $streamFactory, private readonly array $defaultHeaders = []) + { } public function request(TransportRequest $request): TransportResponse diff --git a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php index b07f8ebe..dcdbbc8f 100644 --- a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php +++ b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php @@ -53,30 +53,12 @@ */ final class SymfonyHttpClientTransport implements TransportInterface { - /** - * @var HttpClientInterface - */ - private $httpClient; - - /** - * @var string[] - */ - private $defaultHeaders; - - /** - * @var mixed[] - */ - private $defaultOptions; - /** * @param string[] $defaultHeaders additional HTTP headers to pass on each request * @param mixed[] $defaultOptions Options for Symfony HTTP client passed on every request. See {@link https://symfony.com/doc/current/http_client.html} for details. */ - public function __construct(HttpClientInterface $httpClient, array $defaultHeaders = [], array $defaultOptions = []) + public function __construct(private readonly HttpClientInterface $httpClient, private array $defaultHeaders = [], private readonly array $defaultOptions = []) { - $this->httpClient = $httpClient; - $this->defaultHeaders = $defaultHeaders; - $this->defaultOptions = $defaultOptions; } /** diff --git a/src/Http/Transport/CurlTransport.php b/src/Http/Transport/CurlTransport.php index f0c4708d..7bfb82c5 100644 --- a/src/Http/Transport/CurlTransport.php +++ b/src/Http/Transport/CurlTransport.php @@ -55,11 +55,6 @@ final class CurlTransport implements TransportInterface */ private const DEFAULT_TIMEOUT = 30; - /** - * @var mixed[] - */ - private $curlOptions; - /** * Allows to inject custom cURL options used on dispatching request to BBB. * Please note that you must ensure on your own that the usage of custom options does not break the transport. @@ -69,9 +64,8 @@ final class CurlTransport implements TransportInterface * * @param mixed[] $curlOptions A list of cURL options to pass to the cURL handle. Option name as key, option value as value. */ - public function __construct(array $curlOptions = []) + public function __construct(private readonly array $curlOptions = []) { - $this->curlOptions = $curlOptions; } /** @@ -94,6 +88,7 @@ public function request(TransportRequest $request): TransportResponse $ch = curl_init(); // @codeCoverageIgnoreStart + /* @phpstan-ignore-next-line */ if (!$ch) { throw new RuntimeException('Could not create curl instance. Error: '.curl_error($ch)); } @@ -127,6 +122,7 @@ public function request(TransportRequest $request): TransportResponse return new TransportResponse($data, $sessionId); } + /** @return array */ private static function buildPostOptions(TransportRequest $request): array { $options = []; @@ -137,13 +133,14 @@ private static function buildPostOptions(TransportRequest $request): array $options[\CURLOPT_POSTFIELDS] = $payload; $options[\CURLOPT_HTTPHEADER] = [ 'Content-type: '.$request->getContentType(), - 'Content-length: '.mb_strlen($payload), + 'Content-length: '.mb_strlen((string) $payload), ]; } return $options; } + /** @return array */ private static function buildUrlOptions(TransportRequest $request): array { return [ @@ -157,6 +154,8 @@ private static function buildUrlOptions(TransportRequest $request): array * The CURLOPT_HTTPHEADER will be treated in a special * way and merged instead, but on values with same header name * only the header from the first option set will be preserved. + * + * @return array */ private static function mergeCurlOptions(array ...$options): array { @@ -183,26 +182,16 @@ private static function mergeCurlOptions(array ...$options): array /** * A raw response as returned from cURL will contain the headers followed by "\r\n\r\n" and the content. * - * @param \CurlHandle|resource $curlHandle - * - * @return array{0: string, 1: string[]} First key headers, second key is content + * @return (string|string[][])[] First key headers, second key is content * * @throws NetworkException * * @see https://stackoverflow.com/questions/10589889/returning-header-as-array-using-curl + * + * @psalm-return array{0: array>, 1: string} */ - private static function getHeadersAndContentFromCurlHandle($curlHandle): array + private static function getHeadersAndContentFromCurlHandle(\CurlHandle $curlHandle): array { - /* @noinspection PhpElementIsNotAvailableInCurrentPhpVersionInspection */ - // @codeCoverageIgnoreStart - if (\PHP_VERSION_ID >= 80000 && !$curlHandle instanceof \CurlHandle) { - /* @noinspection PhpElementIsNotAvailableInCurrentPhpVersionInspection */ - throw new \InvalidArgumentException(\sprintf('$curlHandle must be "%s". "%s" given.', \CurlHandle::class, get_debug_type($curlHandle))); - } elseif (\PHP_VERSION_ID < 80000 && !\is_resource($curlHandle)) { - throw new \InvalidArgumentException(\sprintf('$curlHandle must be resource. "%s" given.', \is_object($curlHandle) ? \get_class($curlHandle) : \gettype($curlHandle))); - } - // @codeCoverageIgnoreEnd - $headers = []; curl_setopt($curlHandle, \CURLOPT_HEADER, 1); diff --git a/src/Http/Transport/Header.php b/src/Http/Transport/Header.php index 1a3f71d1..ea339ee2 100644 --- a/src/Http/Transport/Header.php +++ b/src/Http/Transport/Header.php @@ -45,7 +45,7 @@ public static function mergeCurlHeaders(array ...$headers): array if (!\is_string($header)) { throw new \InvalidArgumentException(\sprintf( 'Non-string header with type "%s" passed.', - \is_object($header) ? \get_class($header) : \gettype($header) + get_debug_type($header) )); } diff --git a/src/Http/Transport/TransportRequest.php b/src/Http/Transport/TransportRequest.php index 0217f1ef..b1ae3ced 100644 --- a/src/Http/Transport/TransportRequest.php +++ b/src/Http/Transport/TransportRequest.php @@ -26,26 +26,8 @@ */ class TransportRequest { - /** - * @var string - */ - private $url; - - /** - * @var string - */ - private $payload; - - /** - * @var string - */ - private $contentType; - - public function __construct(string $url, string $payload, string $contentType) + public function __construct(private readonly string $url, private readonly string $payload, private readonly string $contentType) { - $this->url = $url; - $this->payload = $payload; - $this->contentType = $contentType; } public function getUrl(): string diff --git a/src/Http/Transport/TransportResponse.php b/src/Http/Transport/TransportResponse.php index 650961c0..42a97dd3 100644 --- a/src/Http/Transport/TransportResponse.php +++ b/src/Http/Transport/TransportResponse.php @@ -26,20 +26,8 @@ */ class TransportResponse { - /** - * @var string - */ - private $body; - - /** - * @var string|null - */ - private $sessionId; - - public function __construct(string $body, ?string $sessionId) + public function __construct(private readonly string $body, private readonly ?string $sessionId) { - $this->body = $body; - $this->sessionId = $sessionId; } public function getBody(): string diff --git a/src/Parameters/BaseParameters.php b/src/Parameters/BaseParameters.php index 69588dad..09cb1ff0 100644 --- a/src/Parameters/BaseParameters.php +++ b/src/Parameters/BaseParameters.php @@ -1,4 +1,7 @@ */ + protected array $ignoreProperties = []; /** + * @param array $arguments + * * @return $this|bool|mixed|null */ public function __call(string $name, array $arguments) @@ -34,24 +40,28 @@ public function __call(string $name, array $arguments) if (!preg_match('/^(get|is|set)[A-Z]/', $name)) { throw new \BadFunctionCallException($name.' does not exist'); } - if (strpos($name, 'get') === 0) { + if (str_starts_with($name, 'get')) { return $this->getter(lcfirst(substr($name, 3))); - } elseif (strpos($name, 'is') === 0) { + } + + if (str_starts_with($name, 'is')) { return $this->booleanGetter(lcfirst(substr($name, 2))); - } elseif (strpos($name, 'set') === 0) { + } + + if (str_starts_with($name, 'set')) { return $this->setter(lcfirst(substr($name, 3)), $arguments); } return null; } - protected function getter(string $name) + protected function getter(string $name): mixed { if (property_exists($this, $name)) { return $this->$name; - } else { - throw new \BadFunctionCallException($name.' is not a valid property'); } + + throw new \BadFunctionCallException($name.' is not a valid property'); } protected function booleanGetter(string $name): ?bool @@ -65,32 +75,43 @@ protected function booleanGetter(string $name): ?bool return $value; } - protected function setter(string $name, array $arguments): self + /** @param array $arguments */ + protected function setter(string $name, array $arguments): static { if (!property_exists($this, $name)) { throw new \BadFunctionCallException($name.' is not a valid property'); } + $property = new \ReflectionProperty($this, $name); + $type = $property->getType(); + + // Construct enum on demand + if ($type instanceof \ReflectionNamedType && enum_exists($type->getName()) && !\is_object($arguments[0])) { + /* @phpstan-ignore-next-line */ + $arguments[0] = ($type->getName())::from($arguments[0]); + } $this->$name = $arguments[0]; return $this; } + /** @return array */ protected function getProperties(): array { - return array_filter(get_object_vars($this), function ($name) { - return $name !== 'ignoreProperties' && !\in_array($name, $this->ignoreProperties); - }, \ARRAY_FILTER_USE_KEY); + return array_filter(get_object_vars($this), fn ($name) => $name !== 'ignoreProperties' && !\in_array( + $name, + $this->ignoreProperties, + true + ), \ARRAY_FILTER_USE_KEY); } + /** @return array */ protected function getHTTPQueryArray(): array { $properties = $this->getProperties(); - $properties = array_filter($properties, function ($value) { - return $value !== null; - }); + $properties = array_filter($properties, fn ($value) => $value !== null); - return array_map(function ($value) { + return array_map(static function ($value) { if (\is_bool($value)) { return $value ? 'true' : 'false'; } diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index c0a7c05d..85ace07d 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -1,5 +1,7 @@ - */ - private $breakoutRoomsGroups = []; - - /** - * @var array - */ - protected $disabledFeatures = []; - - /** - * @var array - */ - protected $disabledFeaturesExclude = []; - - /** - * @var int - */ - protected $meetingCameraCap; - - /** - * @var int - */ - protected $meetingExpireIfNoUserJoinedInMinutes; - - /** - * @var int - */ - protected $meetingExpireWhenLastUserLeftInMinutes; - - /** - * @var bool - */ - protected $preUploadedPresentationOverrideDefault; - - /** - * @var string - */ - protected $preUploadedPresentation; - - /** - * @var string - */ - protected $preUploadedPresentationName; - - /** - * @var bool - */ - protected $notifyRecordingIsOn; - - /** - * @var bool - */ - protected $remindRecordingIsOn; - - /** - * @var bool - */ - protected $recordFullDurationMedia; - - /** - * @var string - */ - protected $presentationUploadExternalUrl; - - /** - * @var string - */ - protected $presentationUploadExternalDescription; - - /** - * @var array - */ - private $presentations = []; - - public function __construct(string $meetingID, string $name) + protected ?string $welcome = null; + protected ?string $dialNumber = null; + protected ?int $voiceBridge = null; + protected ?string $webVoice = null; + protected ?int $maxParticipants = null; + protected ?string $logoutURL = null; + protected ?bool $record = null; + protected ?int $duration = null; + protected ?bool $isBreakout = null; + protected ?string $parentMeetingID = null; + protected ?int $sequence = null; + protected ?bool $freeJoin = null; + protected ?bool $breakoutRoomsPrivateChatEnabled = null; + protected ?bool $breakoutRoomsRecord = null; + protected ?string $moderatorOnlyMessage = null; + protected ?bool $autoStartRecording = null; + protected ?bool $allowStartStopRecording = null; + protected ?bool $webcamsOnlyForModerator = null; + protected ?string $logo = null; + protected ?string $bannerText = null; + protected ?string $bannerColor = null; + protected ?string $copyright = null; + protected ?bool $muteOnStart = null; + protected ?bool $allowModsToUnmuteUsers = null; + protected ?bool $lockSettingsDisableCam = null; + protected ?bool $lockSettingsDisableMic = null; + protected ?bool $lockSettingsDisablePrivateChat = null; + protected ?bool $lockSettingsDisablePublicChat = null; + protected ?bool $lockSettingsDisableNotes = null; + protected ?bool $lockSettingsLockedLayout = null; + protected ?bool $lockSettingsHideUserList = null; + protected ?bool $lockSettingsLockOnJoin = null; + protected ?bool $lockSettingsLockOnJoinConfigurable = null; + protected ?bool $lockSettingsHideViewersCursor = null; + protected GuestPolicy $guestPolicy; + protected ?bool $meetingKeepEvents = null; + protected ?bool $endWhenNoModerator = null; + protected int $endWhenNoModeratorDelayInMinutes; + + protected ?MeetingLayout $meetingLayout = null; + protected ?string $meetingEndedURL = null; + protected ?int $learningDashboardCleanupDelayInMinutes = null; + protected ?bool $allowModsToEjectCameras = null; + protected ?bool $allowRequestsWithoutSession = null; + protected ?bool $allowPromoteGuestToModerator = null; + protected ?int $userCameraCap = null; + + /** + * @var array}> + */ + private array $breakoutRoomsGroups = []; + + /** + * @var array + */ + protected array $disabledFeatures = []; + + /** + * @var array + */ + protected array $disabledFeaturesExclude = []; + + protected ?int $meetingCameraCap = null; + protected ?int $meetingExpireIfNoUserJoinedInMinutes = null; + protected ?int $meetingExpireWhenLastUserLeftInMinutes = null; + protected ?bool $preUploadedPresentationOverrideDefault = null; + protected ?string $preUploadedPresentation = null; + protected ?string $preUploadedPresentationName = null; + protected ?bool $notifyRecordingIsOn = null; + protected ?bool $remindRecordingIsOn = null; + protected ?bool $recordFullDurationMedia = null; + protected ?string $presentationUploadExternalUrl = null; + protected ?string $presentationUploadExternalDescription = null; + + /** + * @var array + */ + private array $presentations = []; + + public function __construct(protected string $meetingID, protected string $name) { - $this->ignoreProperties = ['disabledFeatures', 'disabledFeaturesExclude']; + $this->guestPolicy = GuestPolicy::ALWAYS_ACCEPT; - $this->meetingID = $meetingID; - $this->name = $name; + $this->ignoreProperties = ['disabledFeatures', 'disabledFeaturesExclude']; } public function setEndCallbackUrl(string $endCallbackUrl): self @@ -577,7 +338,7 @@ public function addPresentation(string $nameOrUrl, ?string $content = null, ?str } /** - * @return array + * @return array}> */ public function getBreakoutRoomsGroups(): array { @@ -585,6 +346,8 @@ public function getBreakoutRoomsGroups(): array } /** + * @param array $roster + * * @return $this */ public function addBreakoutRoomsGroup(string $id, ?string $name, array $roster): self @@ -594,12 +357,13 @@ public function addBreakoutRoomsGroup(string $id, ?string $name, array $roster): return $this; } + /** @return array */ public function getPresentations(): array { return $this->presentations; } - public function getPresentationsAsXML() + public function getPresentationsAsXML(): string|false { $result = ''; @@ -609,7 +373,7 @@ public function getPresentationsAsXML() $module->addAttribute('name', 'presentation'); foreach ($this->presentations as $nameOrUrl => $content) { - if (strpos($nameOrUrl, 'http') === 0) { + if (str_starts_with($nameOrUrl, 'http')) { $presentation = $module->addChild('document'); $presentation->addAttribute('url', $nameOrUrl); if (\is_string($content)) { @@ -618,6 +382,7 @@ public function getPresentationsAsXML() } else { $document = $module->addChild('document'); $document->addAttribute('name', $nameOrUrl); + /* @phpstan-ignore-next-line */ $document[0] = $content; } } @@ -663,10 +428,13 @@ public function getHTTPQuery(): string return http_build_query($queries, '', '&', \PHP_QUERY_RFC3986); } + /** + * @param array $queries + * + * @return array + */ private function filterBreakoutRelatedQueries(array $queries): array { - return array_filter($queries, function ($query) { - return !\in_array($query, ['isBreakout', 'parentMeetingID', 'sequence', 'freeJoin']); - }); + return array_filter($queries, static fn ($query) => !\in_array($query, ['isBreakout', 'parentMeetingID', 'sequence', 'freeJoin'])); } } diff --git a/src/Parameters/DeleteRecordingsParameters.php b/src/Parameters/DeleteRecordingsParameters.php index f5d46b8a..3754105d 100644 --- a/src/Parameters/DeleteRecordingsParameters.php +++ b/src/Parameters/DeleteRecordingsParameters.php @@ -1,4 +1,7 @@ recordID = $recordID; } } diff --git a/src/Parameters/EndMeetingParameters.php b/src/Parameters/EndMeetingParameters.php index c1644075..918f5c81 100644 --- a/src/Parameters/EndMeetingParameters.php +++ b/src/Parameters/EndMeetingParameters.php @@ -1,5 +1,7 @@ meetingID = $meetingID; } } diff --git a/src/Parameters/GetMeetingInfoParameters.php b/src/Parameters/GetMeetingInfoParameters.php index c6fe1a18..c11e1b2e 100644 --- a/src/Parameters/GetMeetingInfoParameters.php +++ b/src/Parameters/GetMeetingInfoParameters.php @@ -1,4 +1,7 @@ meetingID = $meetingID; } } diff --git a/src/Parameters/GetRecordingTextTracksParameters.php b/src/Parameters/GetRecordingTextTracksParameters.php index c7c0443b..59cbf83b 100644 --- a/src/Parameters/GetRecordingTextTracksParameters.php +++ b/src/Parameters/GetRecordingTextTracksParameters.php @@ -1,4 +1,7 @@ recordID = $recordID; } } diff --git a/src/Parameters/GetRecordingsParameters.php b/src/Parameters/GetRecordingsParameters.php index 745ee36b..38cb842c 100644 --- a/src/Parameters/GetRecordingsParameters.php +++ b/src/Parameters/GetRecordingsParameters.php @@ -1,4 +1,7 @@ callbackURL = $callbackURL; } } diff --git a/src/Parameters/HooksDestroyParameters.php b/src/Parameters/HooksDestroyParameters.php index c22e953c..f1134de9 100644 --- a/src/Parameters/HooksDestroyParameters.php +++ b/src/Parameters/HooksDestroyParameters.php @@ -1,4 +1,7 @@ hookID = $hookID; } } diff --git a/src/Parameters/HooksListParameters.php b/src/Parameters/HooksListParameters.php index 7f5027e9..0df6305c 100644 --- a/src/Parameters/HooksListParameters.php +++ b/src/Parameters/HooksListParameters.php @@ -1,4 +1,7 @@ */ + private array $presentations = []; - /** - * @var array - */ - private $presentations = []; - - public function __construct(string $meetingID) + public function __construct(protected string $meetingID) { - $this->meetingID = $meetingID; } public function addPresentation(string $url, string $filename, ?bool $downloadable = null, ?bool $removable = null): self @@ -60,7 +52,7 @@ public function removePresentation(string $url): self return $this; } - public function getPresentationsAsXML() + public function getPresentationsAsXML(): string|false { $result = ''; diff --git a/src/Parameters/IsMeetingRunningParameters.php b/src/Parameters/IsMeetingRunningParameters.php index 9c87923c..9244f666 100644 --- a/src/Parameters/IsMeetingRunningParameters.php +++ b/src/Parameters/IsMeetingRunningParameters.php @@ -1,4 +1,7 @@ meetingID = $meetingID; } } diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index 28d467b8..83680930 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -1,5 +1,7 @@ meetingID = $meetingID; - $this->fullName = $fullName; - $this->role = $role; } /** diff --git a/src/Parameters/MetaParameters.php b/src/Parameters/MetaParameters.php index 50ae4910..2adab816 100644 --- a/src/Parameters/MetaParameters.php +++ b/src/Parameters/MetaParameters.php @@ -1,4 +1,7 @@ */ + private array $meta = []; - /** - * @return string|bool - */ - public function getMeta(string $key) + public function getMeta(string $key): string|bool { return $this->meta[$key]; } - /** - * @param string|bool $value - */ - public function addMeta(string $key, $value): self + public function addMeta(string $key, bool|string $value): static { $this->meta[$key] = $value; diff --git a/src/Parameters/PublishRecordingsParameters.php b/src/Parameters/PublishRecordingsParameters.php index d003b2ba..fd73ef0d 100644 --- a/src/Parameters/PublishRecordingsParameters.php +++ b/src/Parameters/PublishRecordingsParameters.php @@ -1,4 +1,7 @@ recordID = $recordID; - $this->publish = $publish; } } diff --git a/src/Parameters/PutRecordingTextTrackParameters.php b/src/Parameters/PutRecordingTextTrackParameters.php index b8fb2fc9..7969bcbc 100644 --- a/src/Parameters/PutRecordingTextTrackParameters.php +++ b/src/Parameters/PutRecordingTextTrackParameters.php @@ -1,4 +1,7 @@ ignoreProperties = ['contentType', 'file']; - - $this->recordID = $recordID; - $this->kind = $kind; - $this->lang = $lang; - $this->label = $label; } } diff --git a/src/Parameters/UpdateRecordingsParameters.php b/src/Parameters/UpdateRecordingsParameters.php index 65c8ec47..1dc2f2a6 100644 --- a/src/Parameters/UpdateRecordingsParameters.php +++ b/src/Parameters/UpdateRecordingsParameters.php @@ -1,4 +1,7 @@ recordID = $recordID; } } diff --git a/src/Parameters/UserDataParameters.php b/src/Parameters/UserDataParameters.php index a412a335..a1f788f0 100644 --- a/src/Parameters/UserDataParameters.php +++ b/src/Parameters/UserDataParameters.php @@ -1,4 +1,7 @@ */ + private array $userData = []; - /** - * @return string|bool - */ - public function getUserData(string $key) + public function getUserData(string $key): bool|string { return $this->userData[$key]; } - /** - * @param string|bool $value - */ - public function addUserData(string $key, $value): self + public function addUserData(string $key, bool|string $value): self { $this->userData[$key] = $value; diff --git a/src/Responses/ApiVersionResponse.php b/src/Responses/ApiVersionResponse.php index f747eefd..bbe86ed9 100644 --- a/src/Responses/ApiVersionResponse.php +++ b/src/Responses/ApiVersionResponse.php @@ -1,4 +1,7 @@ rawXml = $xml; } public function getRawXml(): \SimpleXMLElement @@ -61,12 +58,12 @@ public function getMessage(): string return $this->rawXml->message->__toString(); } - public function success() + public function success(): bool { return $this->getReturnCode() === self::SUCCESS; } - public function failed() + public function failed(): bool { return $this->getReturnCode() === self::FAILED; } @@ -76,6 +73,6 @@ public function failed() */ public function hasChecksumError(): bool { - return $this->failed() && $this->getMessageKey() == self::CHECKSUM_ERROR; + return $this->failed() && $this->getMessageKey() === self::CHECKSUM_ERROR; } } diff --git a/src/Responses/BaseResponseAsJson.php b/src/Responses/BaseResponseAsJson.php index 420fef3c..77b8fa56 100644 --- a/src/Responses/BaseResponseAsJson.php +++ b/src/Responses/BaseResponseAsJson.php @@ -1,4 +1,7 @@ data); } + /** + * @return array + */ public function getRawArray(): array { return json_decode(json_encode($this->data), true); diff --git a/src/Responses/CreateMeetingResponse.php b/src/Responses/CreateMeetingResponse.php index c109e7e6..2c5f350a 100644 --- a/src/Responses/CreateMeetingResponse.php +++ b/src/Responses/CreateMeetingResponse.php @@ -1,5 +1,7 @@ $arrays + * @param bool $reorderNested reorder nested array starting from the second level instead of merging them + * + * @return array */ public static function mergeRecursive(bool $reorderNested, array ...$arrays): array { @@ -51,6 +54,12 @@ public static function mergeRecursive(bool $reorderNested, array ...$arrays): ar return $merged; } + /** + * @param array $array1 + * @param array $array2 + * + * @return array + */ private static function mergeArrays(array $array1, array $array2): array { $newArray = []; diff --git a/src/Util/UrlBuilder.php b/src/Util/UrlBuilder.php index 81638b9c..0c90873c 100644 --- a/src/Util/UrlBuilder.php +++ b/src/Util/UrlBuilder.php @@ -1,4 +1,7 @@ securitySalt = $secret; - $this->bbbServerBaseUrl = $serverBaseUrl; - $this->hashingAlgorithm = $hashingAlgorithm; + public function __construct( + private readonly string $securitySalt, + private readonly string $bbbServerBaseUrl, + private readonly HashingAlgorithm $hashingAlgorithm + ) { } /** * Builds an API method URL that includes the url + params + its generated checksum. */ - public function buildUrl(string $method = '', string $params = '', bool $append = true): string + public function buildUrl(string|ApiMethod $method = '', string $params = '', bool $append = true): string { + if ($method instanceof ApiMethod) { + $method = $method->value; + } + return $this->bbbServerBaseUrl.'api/'.$method.($append ? '?'.$this->buildQs($method, $params) : ''); } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 64a63992..d22a1a3c 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,4 +1,7 @@ load(...$files); } - -// Include custom test class -require_once __DIR__.'/TestCase.php'; diff --git a/tests/TestCase.php b/tests/common/TestCase.php similarity index 82% rename from tests/TestCase.php rename to tests/common/TestCase.php index fdf49f54..41573db1 100644 --- a/tests/TestCase.php +++ b/tests/common/TestCase.php @@ -1,5 +1,7 @@ . */ -namespace BigBlueButton; +namespace BigBlueButton\Tests\Common; +use BigBlueButton\BigBlueButton; use BigBlueButton\Enum\Feature; use BigBlueButton\Enum\GuestPolicy; use BigBlueButton\Enum\MeetingLayout; @@ -36,26 +39,16 @@ /** * Class TestCase. */ -class TestCase extends \PHPUnit\Framework\TestCase +abstract class TestCase extends \PHPUnit\Framework\TestCase { - /** - * @var Generator - */ - protected $faker; + protected Generator $faker; protected function setUp(): void { - parent::setUp(); - $this->faker = Faker::create(); } - /** - * @param $bbb BigBlueButton - * - * @return CreateMeetingResponse - */ - protected function createRealMeeting($bbb) + protected function createRealMeeting(BigBlueButton $bbb): CreateMeetingResponse { $createMeetingParams = $this->generateCreateParams(); $createMeetingMock = $this->getCreateMock($createMeetingParams); @@ -63,10 +56,8 @@ protected function createRealMeeting($bbb) return $bbb->createMeeting($createMeetingMock); } - /** - * @return array - */ - protected function generateCreateParams() + /** @return array */ + protected function generateCreateParams(): array { return [ 'name' => $this->faker->name, @@ -101,13 +92,11 @@ protected function generateCreateParams() 'disabledFeatures' => $this->faker->randomElements(Feature::cases(), 3), 'disabledFeaturesExclude' => $this->faker->randomElements(Feature::cases(), 2), 'allowPromoteGuestToModerator' => $this->faker->boolean(50), - 'disabledFeatures' => $this->faker->randomElements(Feature::getValues(), 3), - 'disabledFeaturesExclude' => $this->faker->randomElements(Feature::getValues(), 2), 'meta_presenter' => $this->faker->name, 'meta_endCallbackUrl' => $this->faker->url, 'meta_bbb-recording-ready-url' => $this->faker->url, 'bannerText' => $this->faker->sentence, - 'bannerColor' => $this->faker->hexcolor, + 'bannerColor' => $this->faker->hexColor, 'meetingKeepEvents' => $this->faker->boolean(50), 'endWhenNoModerator' => $this->faker->boolean(50), 'endWhenNoModeratorDelayInMinutes' => $this->faker->numberBetween(1, 100), @@ -130,7 +119,7 @@ protected function generateCreateParams() } /** - * @return array + * @return array}> */ protected function generateBreakoutRoomsGroups(): array { @@ -144,9 +133,11 @@ protected function generateBreakoutRoomsGroups(): array } /** - * @return array + * @param array $createParams + * + * @return array */ - protected function generateBreakoutCreateParams($createParams) + protected function generateBreakoutCreateParams(array $createParams): array { return array_merge($createParams, [ 'isBreakout' => true, @@ -156,12 +147,8 @@ protected function generateBreakoutCreateParams($createParams) ]); } - /** - * @param $params array - * - * @return CreateMeetingParameters - */ - protected function getCreateMock($params) + /** @param array $params */ + protected function getCreateMock(array $params): CreateMeetingParameters { $createMeetingParams = new CreateMeetingParameters($params['meetingID'], $params['name']); @@ -203,15 +190,12 @@ protected function getCreateMock($params) ->setMeetingEndedURL($params['meetingEndedURL']) ->setMeetingLayout($params['meetingLayout']) ->setMeetingKeepEvents($params['meetingKeepEvents']) - ->setLearningDashboardEnabled($params['learningDashboardEnabled']) ->setLearningDashboardCleanupDelayInMinutes($params['learningDashboardCleanupDelayInMinutes']) ->setAllowModsToEjectCameras($params['allowModsToEjectCameras']) - ->setBreakoutRoomsEnabled($params['breakoutRoomsEnabled']) ->setBreakoutRoomsPrivateChatEnabled($params['breakoutRoomsPrivateChatEnabled']) ->setBreakoutRoomsRecord($params['breakoutRoomsRecord']) ->setAllowRequestsWithoutSession($params['allowRequestsWithoutSession']) ->setAllowPromoteGuestToModerator($params['allowPromoteGuestToModerator']) - ->setVirtualBackgroundsDisabled($params['virtualBackgroundsDisabled']) ->setUserCameraCap($params['userCameraCap']) ->setDisabledFeatures($params['disabledFeatures']) ->setDisabledFeaturesExclude($params['disabledFeaturesExclude']); @@ -223,25 +207,21 @@ protected function getCreateMock($params) return $createMeetingParams; } - /** - * @return CreateMeetingParameters - */ - protected function getBreakoutCreateMock($params) + /** @param array $params */ + protected function getBreakoutCreateMock(array $params): CreateMeetingParameters { $createMeetingParams = $this->getCreateMock($params); return $createMeetingParams->setBreakout($params['isBreakout'])->setParentMeetingID($params['parentMeetingId'])->setSequence($params['sequence'])->setFreeJoin($params['freeJoin']); } - /** - * @return array - */ - protected function generateJoinMeetingParams() + /** @return array */ + protected function generateJoinMeetingParams(): array { return ['meetingID' => $this->faker->uuid, 'fullName' => $this->faker->name, 'role' => $this->faker->randomElement(Role::cases()), - 'userID' => $this->faker->numberBetween(1, 1000), + 'userID' => (string) $this->faker->numberBetween(1, 1000), 'webVoiceConf' => $this->faker->word, 'createTime' => $this->faker->unixTime, 'errorRedirectUrl' => $this->faker->url, @@ -251,16 +231,12 @@ protected function generateJoinMeetingParams() ]; } - /** - * @param $params array - * - * @return JoinMeetingParameters - */ - protected function getJoinMeetingMock($params) + /** @param array $params */ + protected function getJoinMeetingMock(array $params): JoinMeetingParameters { $joinMeetingParams = new JoinMeetingParameters($params['meetingID'], $params['fullName'], $params['role']); - return $joinMeetingParams + $joinMeetingParams ->setUserID($params['userID']) ->setWebVoiceConf($params['webVoiceConf']) ->setCreateTime($params['createTime']) @@ -268,34 +244,25 @@ protected function getJoinMeetingMock($params) ->addUserData('countrycode', $params['userdata-countrycode']) ->addUserData('email', $params['userdata-email']) ->addUserData('commercial', $params['userdata-commercial']); + + return $joinMeetingParams; } - /** - * @return array - */ - protected function generateEndMeetingParams() + /** @return array */ + protected function generateEndMeetingParams(): array { return [ 'meetingID' => $this->faker->uuid, ]; } - /** - * @param $params array - * - * @return EndMeetingParameters - */ - protected function getEndMeetingMock($params) + /** @param array $params */ + protected function getEndMeetingMock(array $params): EndMeetingParameters { return new EndMeetingParameters($params['meetingID']); } - /** - * @param $bbb BigBlueButton - * - * @return UpdateRecordingsResponse - */ - protected function updateRecordings($bbb) + protected function updateRecordings(BigBlueButton $bbb): UpdateRecordingsResponse { $updateRecordingsParams = $this->generateUpdateRecordingsParams(); $updateRecordingsMock = $this->getUpdateRecordingsParamsMock($updateRecordingsParams); @@ -303,10 +270,8 @@ protected function updateRecordings($bbb) return $bbb->updateRecordings($updateRecordingsMock); } - /** - * @return array - */ - protected function generateUpdateRecordingsParams() + /** @return array */ + protected function generateUpdateRecordingsParams(): array { return [ 'recordID' => $this->faker->uuid, @@ -314,65 +279,75 @@ protected function generateUpdateRecordingsParams() ]; } - /** - * @param $params array - * - * @return UpdateRecordingsParameters - */ - protected function getUpdateRecordingsParamsMock($params) + /** @param array $params */ + protected function getUpdateRecordingsParamsMock(array $params): UpdateRecordingsParameters { - $updateRecordingsParams = new UpdateRecordingsParameters($params['recordID']); + $updateRecordingParameters = new UpdateRecordingsParameters($params['recordID']); + $updateRecordingParameters->addMeta('presenter', $params['meta_presenter']); - return $updateRecordingsParams->addMeta('presenter', $params['meta_presenter']); + return $updateRecordingParameters; } // Load fixtures - protected function loadXmlFile($path) + protected function loadXmlFile(string $path): \SimpleXMLElement { return simplexml_load_string(file_get_contents($path)); } - protected function loadJsonFile($path) + protected function loadJsonFile(string $path): string { return file_get_contents($path); } - protected function minifyString($string) + protected function minifyString(string $string): string { - return str_replace(["\r\n", "\r", "\n", "\t", ' '], '', $string); + return str_replace(["\r\n", "\r", "\n", "\t", ' '], '', (string) $string); } // Additional assertions - public function assertEachGetterValueIsString($obj, $getters) + /** + * @param array $getters + */ + public function assertEachGetterValueIsString(object $obj, array $getters): void { foreach ($getters as $getterName) { $this->assertIsString($obj->$getterName(), 'Got a '.\gettype($obj->$getterName()).' instead of a string for property -> '.$getterName); } } - public function assertEachGetterValueIsInteger($obj, $getters) + /** + * @param array $getters + */ + public function assertEachGetterValueIsInteger(object $obj, array $getters): void { foreach ($getters as $getterName) { $this->assertIsInt($obj->$getterName(), 'Got a '.\gettype($obj->$getterName()).' instead of an integer for property -> '.$getterName); } } - public function assertEachGetterValueIsDouble($obj, $getters) + /** + * @param array $getters + */ + public function assertEachGetterValueIsDouble(object $obj, array $getters): void { foreach ($getters as $getterName) { $this->assertIsFloat($obj->$getterName(), 'Got a '.\gettype($obj->$getterName()).' instead of a double for property -> '.$getterName); } } - public function assertEachGetterValueIsBoolean($obj, $getters) + /** + * @param array $getters + */ + public function assertEachGetterValueIsBoolean(object $obj, array $getters): void { foreach ($getters as $getterName) { $this->assertIsBool($obj->$getterName(), 'Got a '.\gettype($obj->$getterName()).' instead of a boolean for property -> '.$getterName); } } + /** @param array $parameters */ public function assertUrlContainsAllRequestParameters(string $url, array $parameters): void { foreach ($parameters as $parameter) { @@ -385,7 +360,7 @@ public function assertUrlContainsAllRequestParameters(string $url, array $parame } if (!\is_array($parameter)) { - $this->assertStringContainsString($parameter, urldecode($url)); + $this->assertStringContainsString((string) $parameter, urldecode($url)); } else { $this->assertUrlContainsAllRequestParameters($url, $parameter); } diff --git a/tests/functional/AbstractBigBlueButtonFunctionalTest.php b/tests/functional/AbstractBigBlueButtonFunctionalTest.php index eb75b2f0..074963ff 100644 --- a/tests/functional/AbstractBigBlueButtonFunctionalTest.php +++ b/tests/functional/AbstractBigBlueButtonFunctionalTest.php @@ -1,5 +1,7 @@ bbb->isConnectionWorking(); @@ -89,7 +88,7 @@ public function testIsConnectionWorking() /** * Test API version call. */ - public function testApiVersion() + public function testApiVersion(): void { $apiVersion = $this->bbb->getApiVersion(); $this->assertEquals('SUCCESS', $apiVersion->getReturnCode()); @@ -102,7 +101,7 @@ public function testApiVersion() /** * Test create meeting. */ - public function testCreateMeeting() + public function testCreateMeeting(): void { $result = $this->createRealMeeting($this->bbb); $this->assertEquals('SUCCESS', $result->getReturnCode()); @@ -115,7 +114,7 @@ public function testCreateMeeting() /** * Test create meeting with a document URL. */ - public function testCreateMeetingWithDocumentUrl() + public function testCreateMeetingWithDocumentUrl(): void { $params = $this->getCreateMock($this->generateCreateParams()); $params->addPresentation('https://picsum.photos/3840/2160/?random'); @@ -133,7 +132,7 @@ public function testCreateMeetingWithDocumentUrl() /** * Test create meeting with a document URL and filename. */ - public function testCreateMeetingWithDocumentUrlAndFileName() + public function testCreateMeetingWithDocumentUrlAndFileName(): void { $params = $this->getCreateMock($this->generateCreateParams()); $params->addPresentation('https://picsum.photos/3840/2160/?random', null, 'placeholder.png'); @@ -151,7 +150,7 @@ public function testCreateMeetingWithDocumentUrlAndFileName() /** * Test create meeting with a document URL. */ - public function testCreateMeetingWithDocumentEmbedded() + public function testCreateMeetingWithDocumentEmbedded(): void { $params = $this->getCreateMock($this->generateCreateParams()); $params->addPresentation('bbb_logo.png', file_get_contents(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'bbb_logo.png')); @@ -169,7 +168,7 @@ public function testCreateMeetingWithDocumentEmbedded() /** * Test create meeting with a multiple documents. */ - public function testCreateMeetingWithMultiDocument() + public function testCreateMeetingWithMultiDocument(): void { $params = $this->getCreateMock($this->generateCreateParams()); $params->addPresentation('https://picsum.photos/3840/2160/?random', null, 'presentation.png'); @@ -187,7 +186,7 @@ public function testCreateMeetingWithMultiDocument() /* Join Meeting */ - public function testJoinMeeting() + public function testJoinMeeting(): void { $params = $this->getCreateMock($this->generateCreateParams()); $params->setGuestPolicy('ALWAYS_ACCEPT'); @@ -198,7 +197,7 @@ public function testJoinMeeting() $params = $this->generateJoinMeetingParams(); $joinMeetingParams = new JoinMeetingParameters($result->getMeetingId(), $params['fullName'], $params['role']); $joinMeetingParams->setRedirect(false); - $joinMeetingParams->setCreateTime(\sprintf('%.0f', $creationTime)); + $joinMeetingParams->setCreateTime((int) \sprintf('%.0f', $creationTime)); $joinMeeting = $this->bbb->joinMeeting($joinMeetingParams); $this->assertEquals('SUCCESS', $joinMeeting->getReturnCode(), 'Join meeting'); @@ -215,7 +214,7 @@ public function testJoinMeeting() /* End Meeting */ - public function testEndMeeting() + public function testEndMeeting(): void { $meeting = $this->createRealMeeting($this->bbb); @@ -225,7 +224,7 @@ public function testEndMeeting() $this->assertTrue($result->success()); } - public function testEndNonExistingMeeting() + public function testEndNonExistingMeeting(): void { $params = $this->generateEndMeetingParams(); $result = $this->bbb->endMeeting($this->getEndMeetingMock($params)); @@ -235,7 +234,7 @@ public function testEndNonExistingMeeting() /* Is Meeting Running */ - public function testIsMeetingRunning() + public function testIsMeetingRunning(): void { $result = $this->bbb->isMeetingRunning(new IsMeetingRunningParameters($this->faker->uuid)); $this->assertEquals('SUCCESS', $result->getReturnCode()); @@ -245,7 +244,7 @@ public function testIsMeetingRunning() /* Get Meetings */ - public function testGetMeetings() + public function testGetMeetings(): void { $meeting = $this->createRealMeeting($this->bbb); @@ -269,7 +268,7 @@ public function testGetMeetingInfoUrl(): void $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId())); } - public function testGetMeetingInfo() + public function testGetMeetingInfo(): void { $meeting = $this->createRealMeeting($this->bbb); @@ -281,28 +280,28 @@ public function testGetMeetingInfo() $this->bbb->endMeeting(new EndMeetingParameters($meeting->getMeetingId())); } - public function testGetRecordings() + public function testGetRecordings(): void { $result = $this->bbb->getRecordings(new GetRecordingsParameters()); $this->assertEquals('SUCCESS', $result->getReturnCode()); $this->assertTrue($result->success()); } - public function testPublishRecordings() + public function testPublishRecordings(): void { $result = $this->bbb->publishRecordings(new PublishRecordingsParameters('non-existing-id-'.$this->faker->sha1, true)); $this->assertEquals('FAILED', $result->getReturnCode()); $this->assertTrue($result->failed()); } - public function testDeleteRecordings() + public function testDeleteRecordings(): void { $result = $this->bbb->deleteRecordings(new DeleteRecordingsParameters('non-existing-id-'.$this->faker->sha1)); $this->assertEquals('FAILED', $result->getReturnCode()); $this->assertTrue($result->failed()); } - public function testUpdateRecordings() + public function testUpdateRecordings(): void { $params = $this->generateUpdateRecordingsParams(); $result = $this->bbb->updateRecordings($this->getUpdateRecordingsParamsMock($params)); diff --git a/tests/integration/Http/Transport/CurlTransportTest.php b/tests/integration/Http/Transport/CurlTransportTest.php index 6f79185a..0980173b 100644 --- a/tests/integration/Http/Transport/CurlTransportTest.php +++ b/tests/integration/Http/Transport/CurlTransportTest.php @@ -19,9 +19,11 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Http\Transport; +namespace BigBlueButton\Tests\Integration\Http\Transport; use BigBlueButton\Exceptions\NetworkException; +use BigBlueButton\Http\Transport\CurlTransport; +use BigBlueButton\Http\Transport\TransportRequest; use PHPUnit\Framework\TestCase; /** @@ -39,6 +41,7 @@ public static function setUpBeforeClass(): void TestHttpServer::start(); } + /** @return array> */ public function provideBadResponseCodes(): iterable { // cURL does not understand codes below 200 properly. @@ -77,6 +80,13 @@ public function testRequestWithPayloadAndAdditionalHeader(): void // BEWARE: Never do this in any production code. You have been warned. eval('$dump = '.$response->getBody().';'); + $this->assertArrayHasKey('input', $dump); + $this->assertArrayHasKey('vars', $dump); + $this->assertArrayHasKey('HTTP_CONTENT_LENGTH', $dump['vars']); + $this->assertArrayHasKey('HTTP_X_FOO', $dump['vars']); + $this->assertArrayHasKey('HTTP_X_BAR', $dump['vars']); + $this->assertArrayHasKey('REQUEST_METHOD', $dump['vars']); + $this->assertSame('FOO', $dump['input'], 'input echo is correct'); $this->assertSame('3', $dump['vars']['HTTP_CONTENT_LENGTH'], 'Content-Length echo is correct'); $this->assertSame('application/xml', $dump['vars']['HTTP_CONTENT_TYPE'], 'Content-Type echo is correct'); @@ -96,6 +106,11 @@ public function testRequestWithPayload(): void // BEWARE: Never do this in any production code. You have been warned. eval('$dump = '.$response->getBody().';'); + $this->assertArrayHasKey('input', $dump); + $this->assertArrayHasKey('vars', $dump); + $this->assertArrayHasKey('HTTP_CONTENT_LENGTH', $dump['vars']); + $this->assertArrayHasKey('REQUEST_METHOD', $dump['vars']); + $this->assertSame('FOO', $dump['input'], 'input echo is correct'); $this->assertSame('3', $dump['vars']['HTTP_CONTENT_LENGTH'], 'Content-Length echo is correct'); $this->assertSame('application/xml', $dump['vars']['HTTP_CONTENT_TYPE'], 'Content-Type echo is correct'); @@ -113,6 +128,10 @@ public function testRequestWithoutPayload(): void // BEWARE: Never do this in any production code. You have been warned. eval('$dump = '.$response->getBody().';'); + $this->assertArrayHasKey('input', $dump); + $this->assertArrayHasKey('vars', $dump); + $this->assertArrayHasKey('REQUEST_METHOD', $dump['vars']); + $this->assertSame('', $dump['input'], 'input echo is correct'); $this->assertSame('GET', $dump['vars']['REQUEST_METHOD'], 'request method echo is correct'); } @@ -150,6 +169,10 @@ public function testRequestWithDuplicatedHeader(): void // BEWARE: Never do this in any production code. You have been warned. eval('$dump = '.$response->getBody().';'); + $this->assertArrayHasKey('input', $dump); + $this->assertArrayHasKey('vars', $dump); + $this->assertArrayHasKey('HTTP_CONTENT_LENGTH', $dump['vars']); + $this->assertSame('FOO', $dump['input'], 'input echo is correct'); $this->assertSame('3', $dump['vars']['HTTP_CONTENT_LENGTH'], 'Content-Length echo is correct'); } diff --git a/tests/integration/Http/Transport/Fixtures/web/dump.php b/tests/integration/Http/Transport/Fixtures/web/dump.php index 19be4420..31445fdc 100644 --- a/tests/integration/Http/Transport/Fixtures/web/dump.php +++ b/tests/integration/Http/Transport/Fixtures/web/dump.php @@ -38,7 +38,7 @@ foreach ($_SERVER as $k => $v) { switch ($k) { default: - if (0 !== strpos($k, 'HTTP_')) { + if (!str_starts_with($k, 'HTTP_')) { continue 2; } // no break diff --git a/tests/integration/Http/Transport/TestHttpServer.php b/tests/integration/Http/Transport/TestHttpServer.php index 35192f2d..f5895d21 100644 --- a/tests/integration/Http/Transport/TestHttpServer.php +++ b/tests/integration/Http/Transport/TestHttpServer.php @@ -26,7 +26,7 @@ * THE SOFTWARE. */ -namespace BigBlueButton\Http\Transport; +namespace BigBlueButton\Tests\Integration\Http\Transport; use Symfony\Component\Process\PhpExecutableFinder; use Symfony\Component\Process\Process; @@ -38,9 +38,10 @@ */ final class TestHttpServer { - private static $process = []; + /** @var array */ + private static array $process = []; - public static function start(int $port = 8057) + public static function start(int $port = 8057): Process { if (isset(self::$process[$port])) { self::$process[$port]->stop(); diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index 64f68a06..2293c269 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -1,5 +1,7 @@ . */ -namespace BigBlueButton; +namespace BigBlueButton\Tests\Unit; +use BigBlueButton\BigBlueButton; use BigBlueButton\Enum\ApiMethod; use BigBlueButton\Enum\HashingAlgorithm; use BigBlueButton\Exceptions\ConfigException; @@ -37,6 +40,7 @@ use BigBlueButton\Parameters\InsertDocumentParameters; use BigBlueButton\Parameters\PublishRecordingsParameters; use BigBlueButton\Parameters\PutRecordingTextTrackParameters; +use BigBlueButton\Tests\Common\TestCase; use PHPUnit\Framework\MockObject\MockObject; /** @@ -44,13 +48,8 @@ */ final class BigBlueButtonTest extends TestCase { - /** @var MockObject */ - private $transport; - - /** - * @var BigBlueButton - */ - private $bbb; + private MockObject $transport; + private BigBlueButton $bbb; /** * Setup test class. @@ -167,7 +166,7 @@ public function testGetMeetingInfoUrl(): void $meetingId = $this->faker->uuid; $url = $this->bbb->getMeetingInfoUrl(new GetMeetingInfoParameters($meetingId)); - $this->assertStringContainsString('='.rawurlencode($meetingId), $url); + $this->assertStringContainsString('='.rawurlencode((string) $meetingId), $url); } public function testGetMeetingInfo(): void @@ -310,7 +309,7 @@ public function testEndMeeting(): void public function testGetMeetingsUrl(): void { $url = $this->bbb->getMeetingsUrl(); - $this->assertStringContainsString(ApiMethod::GET_MEETINGS, $url); + $this->assertStringContainsString(ApiMethod::GET_MEETINGS->value, $url); } public function testGetMeetings(): void @@ -370,7 +369,7 @@ public function testGetMeetings(): void public function testGetRecordingsUrl(): void { $url = $this->bbb->getRecordingsUrl(new GetRecordingsParameters()); - $this->assertStringContainsString(ApiMethod::GET_RECORDINGS, $url); + $this->assertStringContainsString(ApiMethod::GET_RECORDINGS->value, $url); } public function testGetRecordings(): void @@ -424,7 +423,7 @@ public function testGetRecordings(): void public function testPublishRecordingsUrl(): void { $url = $this->bbb->getPublishRecordingsUrl(new PublishRecordingsParameters($this->faker->sha1, true)); - $this->assertStringContainsString(ApiMethod::PUBLISH_RECORDINGS, $url); + $this->assertStringContainsString(ApiMethod::PUBLISH_RECORDINGS->value, $url); } public function testPublishRecordings(): void @@ -446,7 +445,7 @@ public function testPublishRecordings(): void public function testDeleteRecordingsUrl(): void { $url = $this->bbb->getDeleteRecordingsUrl(new DeleteRecordingsParameters($this->faker->sha1)); - $this->assertStringContainsString(ApiMethod::DELETE_RECORDINGS, $url); + $this->assertStringContainsString(ApiMethod::DELETE_RECORDINGS->value, $url); } public function testDeleteRecordings(): void @@ -669,7 +668,7 @@ public function testHooksListUrl(): void $params = new HooksListParameters(); $url = $this->bbb->getHooksListUrl($params); - $this->assertStringContainsString(ApiMethod::HOOKS_LIST, $url); + $this->assertStringContainsString(ApiMethod::HOOKS_LIST->value, $url); $this->assertStringNotContainsString('meetingID=', $url); // Test with meeting ID @@ -682,7 +681,7 @@ public function testHooksListUrl(): void public function testHookDestroy(): void { - $params = new HooksDestroyParameters(1); + $params = new HooksDestroyParameters('1'); $xml = ' SUCCESS diff --git a/tests/unit/Http/SetCookieTest.php b/tests/unit/Http/SetCookieTest.php index 588ae033..8ad3a0c8 100644 --- a/tests/unit/Http/SetCookieTest.php +++ b/tests/unit/Http/SetCookieTest.php @@ -24,8 +24,9 @@ * THE SOFTWARE. */ -namespace BigBlueButton\Http; +namespace BigBlueButton\Tests\Unit\Http; +use BigBlueButton\Http\SetCookie; use PHPUnit\Framework\TestCase; /** @@ -148,6 +149,7 @@ public function testMatchesDomain(): void self::assertFalse($cookie->matchesDomain('example.com')); } + /** @return array> */ public function pathMatchProvider(): array { return [ @@ -179,6 +181,7 @@ public function testMatchesPath(string $cookiePath, string $requestPath, bool $i self::assertSame($isMatch, $cookie->matchesPath($requestPath)); } + /** @return array> */ public function cookieValidateProvider(): array { return [ @@ -234,6 +237,8 @@ public function testConvertsToString(): void /** * Provides the parsed information from a cookie. + * + * @return array */ public function cookieParserDataProvider(): array { @@ -392,9 +397,10 @@ public function cookieParserDataProvider(): array /** * @dataProvider cookieParserDataProvider * - * @param string|array $cookie + * @param array|string $cookie + * @param array $parsed */ - public function testParseCookie($cookie, array $parsed): void + public function testParseCookie(array|string $cookie, array $parsed): void { foreach ((array) $cookie as $v) { $c = SetCookie::fromString($v); @@ -402,7 +408,7 @@ public function testParseCookie($cookie, array $parsed): void if (isset($p['Expires'])) { $delta = 40; - $parsedExpires = is_numeric($parsed['Expires']) ? $parsed['Expires'] : strtotime($parsed['Expires']); + $parsedExpires = is_numeric($parsed['Expires']) ? $parsed['Expires'] : strtotime((string) $parsed['Expires']); self::assertLessThan($delta, abs($p['Expires'] - $parsedExpires), 'Comparing Expires '.var_export($p['Expires'], true).' : '.var_export($parsed, true).' | '.var_export($p, true)); unset($p['Expires']); unset($parsed['Expires']); @@ -433,6 +439,8 @@ public function testParseCookie($cookie, array $parsed): void /** * Provides the data for testing isExpired. + * + * @return array> */ public function isExpiredProvider(): array { diff --git a/tests/unit/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransportTest.php b/tests/unit/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransportTest.php index dc7fa204..093d23cb 100644 --- a/tests/unit/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransportTest.php +++ b/tests/unit/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransportTest.php @@ -19,10 +19,11 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Http\Transport\Bridge\PsrHttpClient; +namespace BigBlueButton\Tests\Unit\Http\Transport\Bridge\PsrHttpClient; use BigBlueButton\Exceptions\NetworkException; use BigBlueButton\Exceptions\RuntimeException; +use BigBlueButton\Http\Transport\Bridge\PsrHttpClient\PsrHttpClientTransport; use BigBlueButton\Http\Transport\TransportRequest; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -43,24 +44,21 @@ */ final class PsrHttpClientTransportTest extends TestCase { - /** - * @var PsrHttpClientTransport - */ - private $transport; + private PsrHttpClientTransport $transport; /** * @var MockObject&ClientInterface */ - private $httpClientMock; + private ?MockObject $httpClientMock = null; /** * @var MockObject&RequestFactoryInterface */ - private $requestFactoryMock; + private ?MockObject $requestFactoryMock = null; /** * @var MockObject&StreamFactoryInterface */ - private $streamFactoryMock; + private ?MockObject $streamFactoryMock = null; protected function setUp(): void { @@ -200,6 +198,7 @@ public function testRequestWithClientException(): void $this->transport->request($request); } + /** @return iterable> */ public function provideBadResponseCodes(): iterable { foreach (range(100, 199) as $badCode) { diff --git a/tests/unit/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransportTest.php b/tests/unit/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransportTest.php index 34c1f9a0..740596ce 100644 --- a/tests/unit/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransportTest.php +++ b/tests/unit/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransportTest.php @@ -19,10 +19,11 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Http\Transport\Bridge\SymfonyHttpClient; +namespace BigBlueButton\Tests\Unit\Http\Transport\Bridge\SymfonyHttpClient; use BigBlueButton\Exceptions\NetworkException; use BigBlueButton\Exceptions\RuntimeException; +use BigBlueButton\Http\Transport\Bridge\SymfonyHttpClient\SymfonyHttpClientTransport; use BigBlueButton\Http\Transport\TransportRequest; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpClient\Exception\TransportException; @@ -200,6 +201,7 @@ public function testRequestWithDefaultOptions(): void } } + /** @return iterable> */ public function provideBadResponseCodes(): iterable { foreach (range(100, 199) as $badCode) { @@ -241,6 +243,7 @@ public function testRequestWithBadResponseCode(int $badCode): void } } + /** @return iterable> */ public function provideBadResponseExceptions(): iterable { yield 'Client exception' => [new FakeClientException(), 400]; diff --git a/tests/unit/Http/Transport/CookieTest.php b/tests/unit/Http/Transport/CookieTest.php index aab7cd0e..5b131aa6 100644 --- a/tests/unit/Http/Transport/CookieTest.php +++ b/tests/unit/Http/Transport/CookieTest.php @@ -19,8 +19,9 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Http\Transport; +namespace BigBlueButton\Tests\Unit\Http\Transport; +use BigBlueButton\Http\Transport\Cookie; use PHPUnit\Framework\TestCase; /** diff --git a/tests/unit/Http/Transport/HeaderTest.php b/tests/unit/Http/Transport/HeaderTest.php index fc34d692..d823c559 100644 --- a/tests/unit/Http/Transport/HeaderTest.php +++ b/tests/unit/Http/Transport/HeaderTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace BigBlueButton\Http; +namespace BigBlueButton\Tests\Unit\Http; /** * This file is part of littleredbutton/bigbluebutton-api-php. @@ -21,7 +21,7 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Http; +namespace BigBlueButton\Tests\Unit\Http\Transport; use BigBlueButton\Http\Transport\Header; use PHPUnit\Framework\TestCase; @@ -79,12 +79,12 @@ public function provideNonStringHeaders(): iterable /** * @dataProvider provideNonStringHeaders */ - public function testMergeCurlHeadersWithNonStringHeaders($badHeader): void + public function testMergeCurlHeadersWithNonStringHeaders(mixed $badHeader): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage(\sprintf( 'Non-string header with type "%s" passed.', - \is_object($badHeader) ? \get_class($badHeader) : \gettype($badHeader) + get_debug_type($badHeader) )); Header::mergeCurlHeaders([$badHeader]); diff --git a/tests/unit/Http/Transport/TransportRequestTest.php b/tests/unit/Http/Transport/TransportRequestTest.php index ec9a728f..4ec702a1 100644 --- a/tests/unit/Http/Transport/TransportRequestTest.php +++ b/tests/unit/Http/Transport/TransportRequestTest.php @@ -19,7 +19,7 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Http; +namespace BigBlueButton\Tests\Unit\Http; use BigBlueButton\Http\Transport\TransportRequest; use PHPUnit\Framework\TestCase; diff --git a/tests/unit/Http/Transport/TransportResponseTest.php b/tests/unit/Http/Transport/TransportResponseTest.php index 5ab01bdc..adf293bd 100644 --- a/tests/unit/Http/Transport/TransportResponseTest.php +++ b/tests/unit/Http/Transport/TransportResponseTest.php @@ -19,8 +19,9 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Http\Transport; +namespace BigBlueButton\Tests\Unit\Http\Transport; +use BigBlueButton\Http\Transport\TransportResponse; use PHPUnit\Framework\TestCase; /** diff --git a/tests/unit/Parameters/BaseParametersTest.php b/tests/unit/Parameters/BaseParametersTest.php index 9a430c7f..9645f10b 100644 --- a/tests/unit/Parameters/BaseParametersTest.php +++ b/tests/unit/Parameters/BaseParametersTest.php @@ -19,8 +19,9 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; +use BigBlueButton\Parameters\BaseParameters; use PHPUnit\Framework\TestCase; final class BaseParametersTest extends TestCase @@ -54,6 +55,17 @@ public function testSetterWithInvalid(): void $params->setInvalid('foobar'); } + + public function testEnum(): void + { + $params = new TestEnumParameters(); + + $params->setEnum('one'); + $this->assertSame(TestEnum::ONE, $params->getEnum()); + + $params->setEnum('two'); + $this->assertSame(TestEnum::TWO, $params->getEnum()); + } } /** @@ -65,5 +77,22 @@ public function testSetterWithInvalid(): void */ final class TestParameters extends BaseParameters { - protected $notABool = 'string'; + protected string $notABool = 'string'; +} + +/** + * @internal + * + * @method self setEnum(TestEnum|string $enum) + * @method TestEnum getEnum() + */ +final class TestEnumParameters extends BaseParameters +{ + protected ?TestEnum $enum = null; +} + +enum TestEnum: string +{ + case ONE = 'one'; + case TWO = 'two'; } diff --git a/tests/unit/Parameters/CreateMeetingParametersTest.php b/tests/unit/Parameters/CreateMeetingParametersTest.php index 4e66d781..a9389a61 100644 --- a/tests/unit/Parameters/CreateMeetingParametersTest.php +++ b/tests/unit/Parameters/CreateMeetingParametersTest.php @@ -1,5 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; use BigBlueButton\Enum\Feature; use BigBlueButton\Enum\GuestPolicy; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\CreateMeetingParameters; +use BigBlueButton\Tests\Common\TestCase; /** * Class CreateMeetingParametersTest. */ final class CreateMeetingParametersTest extends TestCase { - public function testCreateMeetingParameters() + public function testCreateMeetingParameters(): void { $params = $this->generateCreateParams(); $createMeetingParams = $this->getCreateMock($params); @@ -82,7 +85,6 @@ public function testCreateMeetingParameters() $this->assertEquals($params['meetingLayout'], $createMeetingParams->getMeetingLayout()); $this->assertEquals($params['learningDashboardCleanupDelayInMinutes'], $createMeetingParams->getLearningDashboardCleanupDelayInMinutes()); $this->assertEquals($params['allowModsToEjectCameras'], $createMeetingParams->isAllowModsToEjectCameras()); - $this->assertEquals($params['breakoutRoomsEnabled'], $createMeetingParams->isBreakoutRoomsEnabled()); $this->assertEquals($params['breakoutRoomsPrivateChatEnabled'], $createMeetingParams->isBreakoutRoomsPrivateChatEnabled()); $this->assertEquals($params['breakoutRoomsRecord'], $createMeetingParams->isBreakoutRoomsRecord()); $this->assertEquals($params['allowRequestsWithoutSession'], $createMeetingParams->isAllowRequestsWithoutSession()); @@ -150,7 +152,7 @@ public function testDisabledFeatures(): void $this->assertStringContainsString('disabledFeaturesExclude=chat,polls', $params); } - public function testCreateBreakoutMeeting() + public function testCreateBreakoutMeeting(): void { $params = $this->generateBreakoutCreateParams($this->generateCreateParams()); $createBreakoutMeetingParams = $this->getBreakoutCreateMock($params); @@ -163,7 +165,7 @@ public function testCreateBreakoutMeeting() $this->assertStringContainsString('isBreakout='.rawurlencode($createBreakoutMeetingParams->isBreakout() ? 'true' : 'false'), $params); $this->assertStringContainsString('parentMeetingID='.rawurlencode($createBreakoutMeetingParams->getParentMeetingID()), $params); - $this->assertStringContainsString('sequence='.rawurlencode($createBreakoutMeetingParams->getSequence()), $params); + $this->assertStringContainsString('sequence='.rawurlencode((string) $createBreakoutMeetingParams->getSequence()), $params); $this->assertStringContainsString('freeJoin='.rawurlencode($createBreakoutMeetingParams->isFreeJoin() ? 'true' : 'false'), $params); } @@ -181,6 +183,7 @@ public function testNonExistingProperty(): void $this->expectException(\BadFunctionCallException::class); $params = new CreateMeetingParameters($this->faker->uuid, $this->faker->name); + /* @phpstan-ignore-next-line */ $params->getFoobar(); } @@ -189,6 +192,7 @@ public function testWrongMethodName(): void $this->expectException(\BadFunctionCallException::class); $params = new CreateMeetingParameters($this->faker->uuid, $this->faker->name); + /* @phpstan-ignore-next-line */ $params->getname(); } diff --git a/tests/unit/Parameters/DeleteRecordingsParametersTest.php b/tests/unit/Parameters/DeleteRecordingsParametersTest.php index 449ddea9..1b7e0346 100644 --- a/tests/unit/Parameters/DeleteRecordingsParametersTest.php +++ b/tests/unit/Parameters/DeleteRecordingsParametersTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\DeleteRecordingsParameters; +use BigBlueButton\Tests\Common\TestCase; final class DeleteRecordingsParametersTest extends TestCase { - public function testDeleteRecordingParameter() + public function testDeleteRecordingParameter(): void { $recordingId = $this->faker->uuid; $deleteRecording = new DeleteRecordingsParameters($recordingId); diff --git a/tests/unit/Parameters/EndMeetingParametersTest.php b/tests/unit/Parameters/EndMeetingParametersTest.php index 45a6e2cf..45a3693c 100644 --- a/tests/unit/Parameters/EndMeetingParametersTest.php +++ b/tests/unit/Parameters/EndMeetingParametersTest.php @@ -1,5 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\EndMeetingParameters; +use BigBlueButton\Tests\Common\TestCase; final class EndMeetingParametersTest extends TestCase { diff --git a/tests/unit/Parameters/GetMeetingInfoParametersTest.php b/tests/unit/Parameters/GetMeetingInfoParametersTest.php index 16ada01a..df6bba99 100644 --- a/tests/unit/Parameters/GetMeetingInfoParametersTest.php +++ b/tests/unit/Parameters/GetMeetingInfoParametersTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\GetMeetingInfoParameters; +use BigBlueButton\Tests\Common\TestCase; final class GetMeetingInfoParametersTest extends TestCase { - public function testGetMeetingInfoParameters() + public function testGetMeetingInfoParameters(): void { $getMeetingInfoParams = new GetMeetingInfoParameters($meetingId = $this->faker->uuid); diff --git a/tests/unit/Parameters/GetRecordingTextTracksParametersTest.php b/tests/unit/Parameters/GetRecordingTextTracksParametersTest.php index c230b8ac..22164b6b 100644 --- a/tests/unit/Parameters/GetRecordingTextTracksParametersTest.php +++ b/tests/unit/Parameters/GetRecordingTextTracksParametersTest.php @@ -1,5 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\GetRecordingTextTracksParameters; +use BigBlueButton\Tests\Common\TestCase; final class GetRecordingTextTracksParametersTest extends TestCase { - public function testGetRecordingTextTracksParameters() + public function testGetRecordingTextTracksParameters(): void { $getRecordingTextTracksParams = new GetRecordingTextTracksParameters($recordId = $this->faker->uuid); diff --git a/tests/unit/Parameters/GetRecordingsParametersTest.php b/tests/unit/Parameters/GetRecordingsParametersTest.php index 21cfa985..d3967a2d 100644 --- a/tests/unit/Parameters/GetRecordingsParametersTest.php +++ b/tests/unit/Parameters/GetRecordingsParametersTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\GetRecordingsParameters; +use BigBlueButton\Tests\Common\TestCase; final class GetRecordingsParametersTest extends TestCase { - public function testGetRecordingsParameters() + public function testGetRecordingsParameters(): void { $getRecordings = new GetRecordingsParameters(); $getRecordings->setMeetingID($meetingId = $this->faker->uuid); diff --git a/tests/unit/Parameters/HooksCreateParametersTest.php b/tests/unit/Parameters/HooksCreateParametersTest.php index fb194cca..f8e344c0 100644 --- a/tests/unit/Parameters/HooksCreateParametersTest.php +++ b/tests/unit/Parameters/HooksCreateParametersTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\HooksCreateParameters; +use BigBlueButton\Tests\Common\TestCase; final class HooksCreateParametersTest extends TestCase { - public function testHooksCreateParameters() + public function testHooksCreateParameters(): void { $hooksCreateParameters = new HooksCreateParameters($callBackUrl = $this->faker->url); diff --git a/tests/unit/Parameters/HooksDestroyParametersTest.php b/tests/unit/Parameters/HooksDestroyParametersTest.php index b1907721..aa3ea0ff 100644 --- a/tests/unit/Parameters/HooksDestroyParametersTest.php +++ b/tests/unit/Parameters/HooksDestroyParametersTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\HooksDestroyParameters; +use BigBlueButton\Tests\Common\TestCase; final class HooksDestroyParametersTest extends TestCase { public function testHooksDestroyParameters(): void { - $hooksCreateParameters = new HooksDestroyParameters($hookId = $this->faker->numberBetween(1, 50)); + $hooksCreateParameters = new HooksDestroyParameters((string) $hookId = $this->faker->numberBetween(1, 50)); $this->assertEquals($hookId, $hooksCreateParameters->getHookID()); } diff --git a/tests/unit/Parameters/HooksListParametersTest.php b/tests/unit/Parameters/HooksListParametersTest.php index f4c25822..5aa44d53 100644 --- a/tests/unit/Parameters/HooksListParametersTest.php +++ b/tests/unit/Parameters/HooksListParametersTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\HooksListParameters; +use BigBlueButton\Tests\Common\TestCase; final class HooksListParametersTest extends TestCase { diff --git a/tests/unit/Parameters/InsertDocumentParametersTest.php b/tests/unit/Parameters/InsertDocumentParametersTest.php index 05caa17c..d9bdd361 100644 --- a/tests/unit/Parameters/InsertDocumentParametersTest.php +++ b/tests/unit/Parameters/InsertDocumentParametersTest.php @@ -19,9 +19,10 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\InsertDocumentParameters; +use BigBlueButton\Tests\Common\TestCase; final class InsertDocumentParametersTest extends TestCase { diff --git a/tests/unit/Parameters/IsMeetingRunningParametersTest.php b/tests/unit/Parameters/IsMeetingRunningParametersTest.php index 90f28352..3c941408 100644 --- a/tests/unit/Parameters/IsMeetingRunningParametersTest.php +++ b/tests/unit/Parameters/IsMeetingRunningParametersTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\IsMeetingRunningParameters; +use BigBlueButton\Tests\Common\TestCase; /** * Class IsMeetingRunningParametersTest. */ final class IsMeetingRunningParametersTest extends TestCase { - public function testIsMeetingRunningParameters() + public function testIsMeetingRunningParameters(): void { $meetingId = $this->faker->uuid; $isRunningParams = new IsMeetingRunningParameters($meetingId); diff --git a/tests/unit/Parameters/JoinMeetingParametersTest.php b/tests/unit/Parameters/JoinMeetingParametersTest.php index 45f5dbef..615bd479 100644 --- a/tests/unit/Parameters/JoinMeetingParametersTest.php +++ b/tests/unit/Parameters/JoinMeetingParametersTest.php @@ -1,5 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; use BigBlueButton\Enum\Role; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class JoinMeetingParametersTest extends TestCase { diff --git a/tests/unit/Parameters/PublishRecordingsParametersTest.php b/tests/unit/Parameters/PublishRecordingsParametersTest.php index c9fde0f4..95cc3228 100644 --- a/tests/unit/Parameters/PublishRecordingsParametersTest.php +++ b/tests/unit/Parameters/PublishRecordingsParametersTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\PublishRecordingsParameters; +use BigBlueButton\Tests\Common\TestCase; final class PublishRecordingsParametersTest extends TestCase { - public function testPublishRecordingsParameters() + public function testPublishRecordingsParameters(): void { $recordingId = $this->faker->uuid; $publish = $this->faker->boolean(50); @@ -33,7 +37,7 @@ public function testPublishRecordingsParameters() $this->assertEquals($publish, $publishRecording->isPublish()); // Test setters that are ignored by the constructor - $publishRecording->setRecordID($newRecordingId = !$this->faker->uuid); + $publishRecording->setRecordID($newRecordingId = $this->faker->uuid); $publishRecording->setPublish($publish = !$publish); $this->assertEquals($newRecordingId, $publishRecording->getRecordID()); $this->assertEquals($publish, $publishRecording->isPublish()); diff --git a/tests/unit/Parameters/PutRecordingTextTracksParametersTest.php b/tests/unit/Parameters/PutRecordingTextTracksParametersTest.php index a43edf17..0e02f5b8 100644 --- a/tests/unit/Parameters/PutRecordingTextTracksParametersTest.php +++ b/tests/unit/Parameters/PutRecordingTextTracksParametersTest.php @@ -1,5 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Parameters\PutRecordingTextTrackParameters; +use BigBlueButton\Tests\Common\TestCase; final class PutRecordingTextTracksParametersTest extends TestCase { - public function testPutRecordingTextTracksParameters() + public function testPutRecordingTextTracksParameters(): void { $getRecordingTextTracksParams = new PutRecordingTextTrackParameters( $recordId = $this->faker->uuid, diff --git a/tests/unit/Parameters/UpdateRecordingsParametersTest.php b/tests/unit/Parameters/UpdateRecordingsParametersTest.php index e9baf7a0..8f4eafa5 100644 --- a/tests/unit/Parameters/UpdateRecordingsParametersTest.php +++ b/tests/unit/Parameters/UpdateRecordingsParametersTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Parameters; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class UpdateRecordingsParametersTest extends TestCase { - public function testUpdateRecordingsParameters() + public function testUpdateRecordingsParameters(): void { $params = $this->generateUpdateRecordingsParams(); $updateRecordingsParams = $this->getUpdateRecordingsParamsMock($params); diff --git a/tests/unit/Responses/ApiVersionResponseTest.php b/tests/unit/Responses/ApiVersionResponseTest.php index ec0ac72f..a43c8401 100644 --- a/tests/unit/Responses/ApiVersionResponseTest.php +++ b/tests/unit/Responses/ApiVersionResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\ApiVersionResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class ApiVersionResponseTest extends TestCase { - /** - * @var ApiVersionResponse - */ - private $version; + private ApiVersionResponse $version; protected function setUp(): void { @@ -38,7 +38,7 @@ protected function setUp(): void $this->version = new ApiVersionResponse($xml); } - public function testApiVersionResponseContent() + public function testApiVersionResponseContent(): void { $this->assertEquals('SUCCESS', $this->version->getReturnCode()); $this->assertEquals('2.0', $this->version->getVersion()); @@ -46,7 +46,7 @@ public function testApiVersionResponseContent() $this->assertEquals('2.4-rc-7', $this->version->getBbbVersion()); } - public function testApiVersionResponseTypes() + public function testApiVersionResponseTypes(): void { $this->assertEachGetterValueIsString($this->version, ['getReturnCode', 'getVersion', 'getApiVersion', 'getBbbVersion']); } diff --git a/tests/unit/Responses/CreateMeetingResponseTest.php b/tests/unit/Responses/CreateMeetingResponseTest.php index 146fa02a..6d5d40f2 100644 --- a/tests/unit/Responses/CreateMeetingResponseTest.php +++ b/tests/unit/Responses/CreateMeetingResponseTest.php @@ -1,5 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\CreateMeetingResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class CreateMeetingResponseTest extends TestCase { - /** - * @var CreateMeetingResponse - */ - private $meeting; + private CreateMeetingResponse $meeting; protected function setUp(): void { @@ -39,7 +38,7 @@ protected function setUp(): void $this->meeting = new CreateMeetingResponse($xml); } - public function testCreateMeetingResponseContent() + public function testCreateMeetingResponseContent(): void { $this->assertTrue($this->meeting->success()); $this->assertFalse($this->meeting->failed()); @@ -62,7 +61,7 @@ public function testCreateMeetingResponseContent() $this->assertFalse($this->meeting->isIdNotUnique()); } - public function testCreateMeetingResponseTypes() + public function testCreateMeetingResponseTypes(): void { $this->assertEachGetterValueIsString($this->meeting, [ 'getReturnCode', 'getInternalMeetingId', 'getParentMeetingId', @@ -73,7 +72,7 @@ public function testCreateMeetingResponseTypes() $this->assertEachGetterValueIsBoolean($this->meeting, ['hasUserJoined', 'hasBeenForciblyEnded']); } - public function testIdNotUnique() + public function testIdNotUnique(): void { $xml = $this->loadXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'create_meeting_not_unique_error.xml'); diff --git a/tests/unit/Responses/DeleteRecordingsResponseTest.php b/tests/unit/Responses/DeleteRecordingsResponseTest.php index 38cf4cfc..39c9be87 100644 --- a/tests/unit/Responses/DeleteRecordingsResponseTest.php +++ b/tests/unit/Responses/DeleteRecordingsResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\DeleteRecordingsResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class DeleteRecordingsResponseTest extends TestCase { - /** - * @var DeleteRecordingsResponse - */ - private $delete; + private DeleteRecordingsResponse $delete; protected function setUp(): void { @@ -38,13 +38,13 @@ protected function setUp(): void $this->delete = new DeleteRecordingsResponse($xml); } - public function testDeleteRecordingsResponseContent() + public function testDeleteRecordingsResponseContent(): void { $this->assertEquals('SUCCESS', $this->delete->getReturnCode()); $this->assertTrue($this->delete->isDeleted()); } - public function testDeleteRecordingsResponseTypes() + public function testDeleteRecordingsResponseTypes(): void { $this->assertEachGetterValueIsString($this->delete, ['getReturnCode']); $this->assertEachGetterValueIsBoolean($this->delete, ['isDeleted']); diff --git a/tests/unit/Responses/EndMeetingResponseTest.php b/tests/unit/Responses/EndMeetingResponseTest.php index 16a72a27..1e1300e1 100644 --- a/tests/unit/Responses/EndMeetingResponseTest.php +++ b/tests/unit/Responses/EndMeetingResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\EndMeetingResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class EndMeetingResponseTest extends TestCase { - /** - * @var EndMeetingResponse - */ - private $end; + private EndMeetingResponse $end; protected function setUp(): void { @@ -38,14 +38,14 @@ protected function setUp(): void $this->end = new EndMeetingResponse($xml); } - public function testEndMeetingResponseContent() + public function testEndMeetingResponseContent(): void { $this->assertEquals('SUCCESS', $this->end->getReturnCode()); $this->assertEquals('sentEndMeetingRequest', $this->end->getMessageKey()); $this->assertEquals('A request to end the meeting was sent. Please wait a few seconds, and then use the getMeetingInfo or isMeetingRunning API calls to verify that it was ended.', $this->end->getMessage()); } - public function testEndMeetingResponseTypes() + public function testEndMeetingResponseTypes(): void { $this->assertEachGetterValueIsString($this->end, ['getReturnCode', 'getMessageKey', 'getMessage']); } diff --git a/tests/unit/Responses/GetMeetingInfoResponseTest.php b/tests/unit/Responses/GetMeetingInfoResponseTest.php index 96526538..6ab4e8fd 100644 --- a/tests/unit/Responses/GetMeetingInfoResponseTest.php +++ b/tests/unit/Responses/GetMeetingInfoResponseTest.php @@ -1,5 +1,11 @@ . */ -final class GetMeetingInfoResponseTest extends BigBlueButton\TestCase +final class GetMeetingInfoResponseTest extends TestCase { - /** - * @var BigBlueButton\Responses\GetMeetingInfoResponse - */ - private $meetingInfo; + private GetMeetingInfoResponse $meetingInfo; protected function setUp(): void { @@ -30,12 +33,12 @@ protected function setUp(): void $xml = $this->loadXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'get_meeting_info.xml'); - $this->meetingInfo = new BigBlueButton\Responses\GetMeetingInfoResponse($xml); + $this->meetingInfo = new GetMeetingInfoResponse($xml); } - public function testGetMeetingInfoResponseContent() + public function testGetMeetingInfoResponseContent(): void { - $this->assertInstanceOf('BigBlueButton\Core\Meeting', $this->meetingInfo->getMeeting()); + $this->assertInstanceOf(Meeting::class, $this->meetingInfo->getMeeting()); $this->assertCount(4, $this->meetingInfo->getMeeting()->getAttendees()); $this->assertEquals('SUCCESS', $this->meetingInfo->getReturnCode()); @@ -64,7 +67,7 @@ public function testGetMeetingInfoResponseContent() $this->assertTrue($info->isBreakout()); } - public function testMeetingAttendeeContent() + public function testMeetingAttendeeContent(): void { $this->assertCount(4, $this->meetingInfo->getMeeting()->getAttendees()); @@ -116,7 +119,7 @@ public function testMeetingViewers(): void $this->assertEquals('VIEWER', $secondViewer->getRole()); } - public function testGetMeetingInfoResponseTypes() + public function testGetMeetingInfoResponseTypes(): void { $info = $this->meetingInfo->getMeeting(); @@ -140,7 +143,7 @@ public function testGetMeetingInfoResponseTypes() $this->assertEachGetterValueIsBoolean($anAttendee, ['isPresenter', 'isListeningOnly', 'hasJoinedVoice', 'hasVideo']); } - public function testGetMeetingInfoMetadataContent() + public function testGetMeetingInfoMetadataContent(): void { $metas = $this->meetingInfo->getMeeting()->getMetas(); diff --git a/tests/unit/Responses/GetMeetingsResponseTest.php b/tests/unit/Responses/GetMeetingsResponseTest.php index a89e8d31..f39df44a 100644 --- a/tests/unit/Responses/GetMeetingsResponseTest.php +++ b/tests/unit/Responses/GetMeetingsResponseTest.php @@ -1,5 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\GetMeetingsResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class GetMeetingsResponseTest extends TestCase { - /** - * @var GetMeetingsResponse - */ - private $meetings; + private GetMeetingsResponse $meetings; protected function setUp(): void { @@ -39,7 +38,7 @@ protected function setUp(): void $this->meetings = new GetMeetingsResponse($xml); } - public function testGetMeetingsResponseContent() + public function testGetMeetingsResponseContent(): void { $this->assertEquals('SUCCESS', $this->meetings->getReturnCode()); @@ -67,7 +66,7 @@ public function testGetMeetingsResponseContent() $this->assertEquals('http://www.muller.biz/autem-dolor-aut-nam-doloribus-molestiae', $aMeeting->getMetas()['endcallbackurl']); } - public function testGetMeetingsResponseTypes() + public function testGetMeetingsResponseTypes(): void { $this->assertEachGetterValueIsString($this->meetings, ['getReturnCode']); @@ -82,7 +81,7 @@ public function testGetMeetingsResponseTypes() $this->assertEachGetterValueIsBoolean($aMeeting, ['hasBeenForciblyEnded', 'isRunning', 'hasUserJoined']); } - public function testGetMeetingsNoMeetings() + public function testGetMeetingsNoMeetings(): void { // scalelite response no meetings $xml = simplexml_load_string('SUCCESSnoMeetingsNo meetings were found on this server.'); diff --git a/tests/unit/Responses/GetRecordingsResponseTest.php b/tests/unit/Responses/GetRecordingsResponseTest.php index 7f79c393..d95d8e6b 100644 --- a/tests/unit/Responses/GetRecordingsResponseTest.php +++ b/tests/unit/Responses/GetRecordingsResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\GetRecordingsResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class GetRecordingsResponseTest extends TestCase { - /** - * @var GetRecordingsResponse - */ - private $records; + private GetRecordingsResponse $records; protected function setUp(): void { @@ -38,7 +38,7 @@ protected function setUp(): void $this->records = new GetRecordingsResponse($xml); } - public function testGetRecordingResponseContent() + public function testGetRecordingResponseContent(): void { $this->assertEquals('SUCCESS', $this->records->getReturnCode()); @@ -60,14 +60,14 @@ public function testGetRecordingResponseContent() $this->assertEquals(9, \count($aRecord->getMetas())); } - public function testRecordMetadataContent() + public function testRecordMetadataContent(): void { $metas = $this->records->getRecords()[4]->getMetas(); $this->assertEquals('moodle-mod_bigbluebuttonbn (2015080611)', $metas['bbb-origin-tag']); } - public function testGetRecordingResponseTypes() + public function testGetRecordingResponseTypes(): void { $this->assertEachGetterValueIsString($this->records, ['getReturnCode']); diff --git a/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php b/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php index 5eecf46c..ef3c7cc6 100644 --- a/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php +++ b/tests/unit/Responses/GetRecordingsTextTracksResponseTest.php @@ -1,16 +1,15 @@ tracks = new GetRecordingTextTracksResponse($json); } - public function testGetRecordingTextTracksResponseContent() + public function testGetRecordingTextTracksResponseContent(): void { $this->assertEquals(GetRecordingTextTracksResponse::SUCCESS, $this->tracks->getReturnCode()); $this->assertTrue($this->tracks->success()); @@ -30,7 +29,7 @@ public function testGetRecordingTextTracksResponseContent() $this->assertCount(2, $this->tracks->getTracks()); } - public function testGetRecordingTextTracksResponseTypes() + public function testGetRecordingTextTracksResponseTypes(): void { $this->assertEachGetterValueIsString($this->tracks, ['getReturnCode']); @@ -50,7 +49,7 @@ public function testGetRecordingTextTracksResponseTypes() ); } - public function testGetRecordingTextTracksResponseValues() + public function testGetRecordingTextTracksResponseValues(): void { $secondTracks = $this->tracks->getTracks()[1]; diff --git a/tests/unit/Responses/HooksCreateResponseTest.php b/tests/unit/Responses/HooksCreateResponseTest.php index 97de3944..77a35d1a 100644 --- a/tests/unit/Responses/HooksCreateResponseTest.php +++ b/tests/unit/Responses/HooksCreateResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\HooksCreateResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class HooksCreateResponseTest extends TestCase { - /** - * @var HooksCreateResponse - */ - private $createResponse; + private HooksCreateResponse $createResponse; protected function setUp(): void { @@ -38,7 +38,7 @@ protected function setUp(): void $this->createResponse = new HooksCreateResponse($xml); } - public function testHooksCreateResponseContent() + public function testHooksCreateResponseContent(): void { $this->assertEquals('SUCCESS', $this->createResponse->getReturnCode()); $this->assertEquals(1, $this->createResponse->getHookId()); @@ -46,7 +46,7 @@ public function testHooksCreateResponseContent() $this->assertFalse($this->createResponse->hasRawData()); } - public function testHooksCreateResponseTypes() + public function testHooksCreateResponseTypes(): void { $this->assertEachGetterValueIsString($this->createResponse, ['getReturnCode']); $this->assertEachGetterValueIsInteger($this->createResponse, ['getHookId']); diff --git a/tests/unit/Responses/HooksDestroyResponseTest.php b/tests/unit/Responses/HooksDestroyResponseTest.php index 0454288c..7704ee1a 100644 --- a/tests/unit/Responses/HooksDestroyResponseTest.php +++ b/tests/unit/Responses/HooksDestroyResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\HooksDestroyResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class HooksDestroyResponseTest extends TestCase { - /** - * @var HooksDestroyResponse - */ - private $destroyResponse; + private HooksDestroyResponse $destroyResponse; protected function setUp(): void { @@ -38,13 +38,13 @@ protected function setUp(): void $this->destroyResponse = new HooksDestroyResponse($xml); } - public function testHooksDestroyResponseContent() + public function testHooksDestroyResponseContent(): void { $this->assertEquals('SUCCESS', $this->destroyResponse->getReturnCode()); $this->assertTrue($this->destroyResponse->removed()); } - public function testHooksDestroyResponseTypes() + public function testHooksDestroyResponseTypes(): void { $this->assertEachGetterValueIsString($this->destroyResponse, ['getReturnCode']); $this->assertEachGetterValueIsBoolean($this->destroyResponse, ['removed']); diff --git a/tests/unit/Responses/HooksListResponseTest.php b/tests/unit/Responses/HooksListResponseTest.php index 0ea9a572..8395fd19 100644 --- a/tests/unit/Responses/HooksListResponseTest.php +++ b/tests/unit/Responses/HooksListResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\HooksListResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class HooksListResponseTest extends TestCase { - /** - * @var HooksListResponse - */ - private $listResponse; + private HooksListResponse $listResponse; protected function setUp(): void { @@ -38,7 +38,7 @@ protected function setUp(): void $this->listResponse = new HooksListResponse($xml); } - public function testHooksListResponseContent() + public function testHooksListResponseContent(): void { $this->assertEquals('SUCCESS', $this->listResponse->getReturnCode()); $this->assertCount(2, $this->listResponse->getHooks()); @@ -52,7 +52,7 @@ public function testHooksListResponseContent() $this->assertFalse($aHook->hasRawData()); } - public function testHooksListResponseTypes() + public function testHooksListResponseTypes(): void { $this->assertEachGetterValueIsString($this->listResponse, ['getReturnCode']); diff --git a/tests/unit/Responses/InsertDocumentResponseTest.php b/tests/unit/Responses/InsertDocumentResponseTest.php index da69dbd4..01d1012e 100644 --- a/tests/unit/Responses/InsertDocumentResponseTest.php +++ b/tests/unit/Responses/InsertDocumentResponseTest.php @@ -19,17 +19,14 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\InsertDocumentResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class InsertDocumentResponseTest extends TestCase { - /** - * @var \BigBlueButton\Responses\IsMeetingRunningResponse - */ - private $running; + private InsertDocumentResponse $running; protected function setUp(): void { diff --git a/tests/unit/Responses/IsMeetingRunningResponseTest.php b/tests/unit/Responses/IsMeetingRunningResponseTest.php index 874964f4..70dce13f 100644 --- a/tests/unit/Responses/IsMeetingRunningResponseTest.php +++ b/tests/unit/Responses/IsMeetingRunningResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\IsMeetingRunningResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class IsMeetingRunningResponseTest extends TestCase { - /** - * @var IsMeetingRunningResponse - */ - private $running; + private IsMeetingRunningResponse $running; protected function setUp(): void { @@ -38,7 +38,7 @@ protected function setUp(): void $this->running = new IsMeetingRunningResponse($xml); } - public function testIsMeetingRunningResponseContent() + public function testIsMeetingRunningResponseContent(): void { $this->assertEquals('SUCCESS', $this->running->getReturnCode()); $this->assertTrue($this->running->isRunning()); @@ -46,7 +46,7 @@ public function testIsMeetingRunningResponseContent() $this->assertEquals('SUCCESStrue', $this->minifyString($this->running->getRawXml()->asXML())); } - public function testIsMeetingRunningResponseTypes() + public function testIsMeetingRunningResponseTypes(): void { $this->assertEachGetterValueIsString($this->running, ['getReturnCode']); $this->assertEachGetterValueIsBoolean($this->running, ['isRunning']); diff --git a/tests/unit/Responses/JoinMeetingResponseTest.php b/tests/unit/Responses/JoinMeetingResponseTest.php index 3ad928ff..836e3060 100644 --- a/tests/unit/Responses/JoinMeetingResponseTest.php +++ b/tests/unit/Responses/JoinMeetingResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\JoinMeetingResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class JoinMeetingResponseTest extends TestCase { - /** - * @var JoinMeetingResponse - */ - private $joinMeeting; + private JoinMeetingResponse $joinMeeting; protected function setUp(): void { @@ -38,7 +38,7 @@ protected function setUp(): void $this->joinMeeting = new JoinMeetingResponse($xml); } - public function testJoinMeetingResponseContent() + public function testJoinMeetingResponseContent(): void { $this->assertEquals('SUCCESS', $this->joinMeeting->getReturnCode()); $this->assertEquals('successfullyJoined', $this->joinMeeting->getMessageKey()); @@ -51,7 +51,7 @@ public function testJoinMeetingResponseContent() $this->assertEquals('https://bigblubutton-server.sample/client/BigBlueButton.html?sessionToken=0wzsph6uaelwc68z', $this->joinMeeting->getUrl()); } - public function testJoinMeetingResponseTypes() + public function testJoinMeetingResponseTypes(): void { $this->assertEachGetterValueIsString($this->joinMeeting, ['getReturnCode', 'getMessageKey', 'getMessage', 'getMeetingId', 'getUserId', 'getAuthToken', 'getSessionToken', 'getGuestStatus', 'getUrl']); } diff --git a/tests/unit/Responses/PublishRecordingsResponseTest.php b/tests/unit/Responses/PublishRecordingsResponseTest.php index 62d9979f..b8fe8727 100644 --- a/tests/unit/Responses/PublishRecordingsResponseTest.php +++ b/tests/unit/Responses/PublishRecordingsResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\PublishRecordingsResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class PublishRecordingsResponseTest extends TestCase { - /** - * @var PublishRecordingsResponse - */ - private $publish; + private PublishRecordingsResponse $publish; protected function setUp(): void { @@ -38,13 +38,13 @@ protected function setUp(): void $this->publish = new PublishRecordingsResponse($xml); } - public function testPublishRecordingsResponseContent() + public function testPublishRecordingsResponseContent(): void { $this->assertEquals('SUCCESS', $this->publish->getReturnCode()); $this->assertTrue($this->publish->isPublished()); } - public function testPublishRecordingsResponseTypes() + public function testPublishRecordingsResponseTypes(): void { $this->assertEachGetterValueIsString($this->publish, ['getReturnCode']); $this->assertEachGetterValueIsBoolean($this->publish, ['isPublished']); diff --git a/tests/unit/Responses/PutRecordingTextTrackResponseTest.php b/tests/unit/Responses/PutRecordingTextTrackResponseTest.php index 32b9bf04..8b6b9a34 100644 --- a/tests/unit/Responses/PutRecordingTextTrackResponseTest.php +++ b/tests/unit/Responses/PutRecordingTextTrackResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\PutRecordingTextTrackResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class PutRecordingTextTrackResponseTest extends TestCase { diff --git a/tests/unit/Responses/UpdateRecordingsResponseTest.php b/tests/unit/Responses/UpdateRecordingsResponseTest.php index 69b2759d..7f78c536 100644 --- a/tests/unit/Responses/UpdateRecordingsResponseTest.php +++ b/tests/unit/Responses/UpdateRecordingsResponseTest.php @@ -1,4 +1,7 @@ . */ -namespace BigBlueButton\Parameters; +namespace BigBlueButton\Tests\Unit\Responses; use BigBlueButton\Responses\UpdateRecordingsResponse; -use BigBlueButton\TestCase; +use BigBlueButton\Tests\Common\TestCase; final class UpdateRecordingsResponseTest extends TestCase { - /** - * @var UpdateRecordingsResponse - */ - private $update; + private UpdateRecordingsResponse $update; protected function setUp(): void { @@ -38,13 +38,13 @@ protected function setUp(): void $this->update = new UpdateRecordingsResponse($xml); } - public function testUpdateRecordingsResponseContent() + public function testUpdateRecordingsResponseContent(): void { $this->assertEquals('SUCCESS', $this->update->getReturnCode()); $this->assertTrue($this->update->isUpdated()); } - public function testUpdateRecordingsResponseTypes() + public function testUpdateRecordingsResponseTypes(): void { $this->assertEachGetterValueIsString($this->update, ['getReturnCode']); $this->assertEachGetterValueIsBoolean($this->update, ['isUpdated']); diff --git a/tests/unit/Util/ArrayHelperTest.php b/tests/unit/Util/ArrayHelperTest.php index 16e43593..9ea33908 100644 --- a/tests/unit/Util/ArrayHelperTest.php +++ b/tests/unit/Util/ArrayHelperTest.php @@ -19,8 +19,9 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Util; +namespace BigBlueButton\Tests\Unit\Util; +use BigBlueButton\Util\ArrayHelper; use PHPUnit\Framework\TestCase; /** @@ -28,6 +29,7 @@ */ final class ArrayHelperTest extends TestCase { + /** @return iterable> */ public function provideArrays(): iterable { yield 'simple flat arrays' => [ @@ -58,6 +60,10 @@ public function provideArrays(): iterable /** * @dataProvider provideArrays + * + * @param array $input1 + * @param array $input2 + * @param array $output */ public function testMergeRecursive(array $input1, array $input2, bool $reorderNested, array $output): void { diff --git a/tests/unit/Util/UrlBuilderTest.php b/tests/unit/Util/UrlBuilderTest.php index 105dfebb..0c6acc94 100644 --- a/tests/unit/Util/UrlBuilderTest.php +++ b/tests/unit/Util/UrlBuilderTest.php @@ -19,9 +19,10 @@ * along with littleredbutton/bigbluebutton-api-php. If not, see . */ -namespace BigBlueButton\Util; +namespace BigBlueButton\Tests\Unit\Util; use BigBlueButton\Enum\HashingAlgorithm; +use BigBlueButton\Util\UrlBuilder; use PHPUnit\Framework\TestCase; /** diff --git a/tools/.phpstan/.gitignore b/tools/.phpstan/.gitignore new file mode 100644 index 00000000..57872d0f --- /dev/null +++ b/tools/.phpstan/.gitignore @@ -0,0 +1 @@ +/vendor/ diff --git a/tools/.phpstan/composer.json b/tools/.phpstan/composer.json new file mode 100644 index 00000000..90c99dfd --- /dev/null +++ b/tools/.phpstan/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "phpstan/phpstan": "^1.10" + } +} diff --git a/tools/.phpstan/composer.lock b/tools/.phpstan/composer.lock new file mode 100644 index 00000000..2cffe70d --- /dev/null +++ b/tools/.phpstan/composer.lock @@ -0,0 +1,81 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "14812c2a05a5972f00f9d67abbd710a9", + "packages": [ + { + "name": "phpstan/phpstan", + "version": "1.10.62", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd5c8a1660ed3540b211407c77abf4af193a6af9", + "reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2024-03-13T12:27:20+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/tools/.psalm/composer.json b/tools/.psalm/composer.json index e2261577..70de5195 100644 --- a/tools/.psalm/composer.json +++ b/tools/.psalm/composer.json @@ -1,5 +1,5 @@ { "require": { - "vimeo/psalm": "^4.22" + "vimeo/psalm": "^5.23" } } diff --git a/tools/.rector/.gitignore b/tools/.rector/.gitignore new file mode 100644 index 00000000..4fbb073c --- /dev/null +++ b/tools/.rector/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +/composer.lock diff --git a/tools/.rector/composer.json b/tools/.rector/composer.json new file mode 100644 index 00000000..056d015c --- /dev/null +++ b/tools/.rector/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "rector/rector": "^1.0" + } +} diff --git a/tools/README.md b/tools/README.md index d8dc27e2..3ceb0402 100644 --- a/tools/README.md +++ b/tools/README.md @@ -5,7 +5,7 @@ The dependencies are not pulled via the main composer.json to keep the dependenc ## Structure of the `tools` folder -Each tool has a hidden (dot) folder with it's tool name. For exmaple, PHP-CS-Fixer uses `tools/.php-cs-fixer`: +Each tool has a hidden (dot) folder with its tool name. For example, PHP-CS-Fixer uses `tools/.php-cs-fixer`: ~~~ tools/ diff --git a/tools/bootstrap.php b/tools/bootstrap.php new file mode 100644 index 00000000..5a34c481 --- /dev/null +++ b/tools/bootstrap.php @@ -0,0 +1,13 @@ +mustRun(); + +require __DIR__.'/.phpunit/vendor/autoload.php'; diff --git a/tools/phpstan b/tools/phpstan new file mode 100755 index 00000000..9d0b643e --- /dev/null +++ b/tools/phpstan @@ -0,0 +1,7 @@ +#!/bin/bash +# This file was created automatically by cotor as a tool wrapper. + +DIR=$(realpath "$(dirname "${BASH_SOURCE[0]}")") + +composer install --working-dir=$DIR/.phpstan --quiet +exec $DIR/.phpstan/vendor/bin/phpstan "$@" diff --git a/tools/rector b/tools/rector new file mode 100755 index 00000000..c5f602ae --- /dev/null +++ b/tools/rector @@ -0,0 +1,7 @@ +#!/bin/bash +# This file was created automatically by cotor as a tool wrapper. + +DIR=$(realpath "$(dirname "${BASH_SOURCE[0]}")") + +composer install --working-dir=$DIR/.rector --quiet +exec $DIR/.rector/vendor/bin/rector "$@" From b2a7a0d7cdc6396b27fb2fa2b1b66bc092e27def Mon Sep 17 00:00:00 2001 From: Felix Jacobi Date: Fri, 23 Aug 2024 02:20:14 +0200 Subject: [PATCH 42/68] Removed deprecated setClientUrl / getClientUrl --- src/Parameters/JoinMeetingParameters.php | 27 ------------------------ 1 file changed, 27 deletions(-) diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index 83680930..e17c6167 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -54,12 +54,6 @@ */ class JoinMeetingParameters extends UserDataParameters { - /* @deprecated and will be removed in 6.0. Use BigBlueButton\Enum\Role::MODERATOR instead */ - public const MODERATOR = Role::MODERATOR; - - /* @deprecated and will be removed in 6.0. Use BigBlueButton\Enum\Role::VIEWER instead */ - public const VIEWER = Role::VIEWER; - protected ?int $createTime = null; protected ?string $userID = null; protected ?string $webVoiceConf = null; @@ -67,31 +61,10 @@ class JoinMeetingParameters extends UserDataParameters protected ?string $avatarURL = null; protected ?bool $redirect = null; protected ?string $errorRedirectUrl = null; - protected ?string $clientURL = null; protected ?bool $guest = null; protected ?bool $excludeFromDashboard = null; public function __construct(protected string $meetingID, protected string $fullName, protected Role $role) { } - - /** - * @deprecated and will be removed in 6.0. Old BigBlueButton flash client parameter. - */ - public function getClientURL(): ?string - { - return $this->clientURL; - } - - /** - * @deprecated and will be removed in 6.0. Old BigBlueButton flash client parameter. - * - * @return $this - */ - public function setClientURL(string $clientURL): self - { - $this->clientURL = $clientURL; - - return $this; - } } From e0f653e18dc8780703ffeb8a31ba3d6a7bc264ab Mon Sep 17 00:00:00 2001 From: Felix Jacobi Date: Fri, 23 Aug 2024 02:23:16 +0200 Subject: [PATCH 43/68] Fixed CS, removed obsolete test parts --- src/BigBlueButton.php | 8 ++++---- .../Bridge/PsrHttpClient/PsrHttpClientTransport.php | 8 ++++---- .../SymfonyHttpClient/SymfonyHttpClientTransport.php | 6 +++--- src/Http/Transport/CurlTransport.php | 2 +- src/Http/Transport/Header.php | 6 +++--- tests/functional/AbstractBigBlueButtonFunctionalTest.php | 2 +- tests/unit/Http/Transport/HeaderTest.php | 4 ++-- tests/unit/Parameters/JoinMeetingParametersTest.php | 2 -- 8 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index c3c18f31..24f9dfaf 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -97,11 +97,11 @@ class BigBlueButton public function __construct(?string $baseUrl = null, ?string $secret = null, ?TransportInterface $transport = null, protected HashingAlgorithm $hashingAlgorithm = HashingAlgorithm::SHA_1) { if (null === $baseUrl) { - @trigger_error(\sprintf('Constructing "%s" without passing a server base URL is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); + @trigger_error(sprintf('Constructing "%s" without passing a server base URL is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); } if (null === $secret) { - @trigger_error(\sprintf('Constructing "%s" without passing a secret is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); + @trigger_error(sprintf('Constructing "%s" without passing a secret is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); } if (getenv('BBB_SECURITY_SALT') !== false || getenv('BBB_SECRET') !== false) { @@ -117,7 +117,7 @@ public function __construct(?string $baseUrl = null, ?string $secret = null, ?Tr if (false === $securitySecret) { // @codeCoverageIgnoreStart - @trigger_error(\sprintf('Constructing "%s" without passing a secret is deprecated since 6.0 and will throw an exception in 7.0.', self::class), \E_USER_DEPRECATED); + @trigger_error(sprintf('Constructing "%s" without passing a secret is deprecated since 6.0 and will throw an exception in 7.0.', self::class), \E_USER_DEPRECATED); $this->securitySecret = ''; // previous behaviour // @codeCoverageIgnoreEnd } else { @@ -128,7 +128,7 @@ public function __construct(?string $baseUrl = null, ?string $secret = null, ?Tr if (false === $bbbServerBaseUrl) { // @codeCoverageIgnoreStart - @trigger_error(\sprintf('Constructing "%s" without passing a server base URL is deprecated since 6.0 and will throw an exception in 7.0.', self::class), \E_USER_DEPRECATED); + @trigger_error(sprintf('Constructing "%s" without passing a server base URL is deprecated since 6.0 and will throw an exception in 7.0.', self::class), \E_USER_DEPRECATED); $this->bbbServerBaseUrl = ''; // previous behaviour // @codeCoverageIgnoreEnd } else { diff --git a/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php b/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php index befa70d9..9343889b 100644 --- a/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php +++ b/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php @@ -34,7 +34,7 @@ // @codeCoverageIgnoreStart if (!interface_exists(ClientInterface::class)) { - throw new \LogicException(\sprintf( + throw new \LogicException(sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides psr/http-client-implementation.', @@ -44,7 +44,7 @@ } if (!interface_exists(RequestFactoryInterface::class)) { - throw new \LogicException(\sprintf( + throw new \LogicException(sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides psr/http-factory-implementation.', @@ -54,7 +54,7 @@ } if (!interface_exists(StreamFactoryInterface::class)) { - throw new \LogicException(\sprintf( + throw new \LogicException(sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides psr/http-factory-implementation.', @@ -93,7 +93,7 @@ public function request(TransportRequest $request): TransportResponse try { $psrResponse = $this->httpClient->sendRequest($psrRequest); } catch (ClientExceptionInterface $e) { - throw new RuntimeException(\sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); + throw new RuntimeException(sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); } if ($psrResponse->getStatusCode() < 200 || $psrResponse->getStatusCode() >= 300) { diff --git a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php index dcdbbc8f..a3394e52 100644 --- a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php +++ b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php @@ -38,7 +38,7 @@ // @codeCoverageIgnoreStart if (!interface_exists(HttpClientInterface::class)) { - throw new \LogicException(\sprintf( + throw new \LogicException(sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides symfony/http-client-implementation.', @@ -71,7 +71,7 @@ public static function create(array $defaultHeaders = [], array $defaultOptions { // @codeCoverageIgnoreStart if (!class_exists(HttpClient::class)) { - throw new \LogicException(\sprintf( + throw new \LogicException(sprintf( 'Cannot create an instance of "%s" when Symfony HttpClient is not installed. '. 'Either instantiate the class by yourself and pass a proper implementation or '. 'try to run "composer require symfony/http-client".', @@ -113,7 +113,7 @@ public function request(TransportRequest $request): TransportResponse return new TransportResponse($symfonyResponse->getContent(), self::extractJsessionCookie($symfonyResponse)); } catch (TransportExceptionInterface $e) { - throw new RuntimeException(\sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); + throw new RuntimeException(sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); } catch (ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface $e) { throw new NetworkException('Bad response.', $e->getCode(), $e); } diff --git a/src/Http/Transport/CurlTransport.php b/src/Http/Transport/CurlTransport.php index 7bfb82c5..4be0fc57 100644 --- a/src/Http/Transport/CurlTransport.php +++ b/src/Http/Transport/CurlTransport.php @@ -220,7 +220,7 @@ private static function getHeadersAndContentFromCurlHandle(\CurlHandle $curlHand $splitHeader = explode(': ', $line, 2); // @codeCoverageIgnoreStart if (!isset($splitHeader[0], $splitHeader[1])) { - throw new \InvalidArgumentException(\sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $line)); + throw new \InvalidArgumentException(sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $line)); } // @codeCoverageIgnoreEnd diff --git a/src/Http/Transport/Header.php b/src/Http/Transport/Header.php index ea339ee2..4a86236b 100644 --- a/src/Http/Transport/Header.php +++ b/src/Http/Transport/Header.php @@ -43,7 +43,7 @@ public static function mergeCurlHeaders(array ...$headers): array foreach ($headers as $headerSet) { foreach ($headerSet as $header) { if (!\is_string($header)) { - throw new \InvalidArgumentException(\sprintf( + throw new \InvalidArgumentException(sprintf( 'Non-string header with type "%s" passed.', get_debug_type($header) )); @@ -51,7 +51,7 @@ public static function mergeCurlHeaders(array ...$headers): array $splitHeader = explode(': ', $header, 2); if (!isset($splitHeader[0], $splitHeader[1])) { - throw new \InvalidArgumentException(\sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $header)); + throw new \InvalidArgumentException(sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $header)); } // Enforce lower case for header names to avoid duplicates in mixed case. The case of header names should @@ -62,7 +62,7 @@ public static function mergeCurlHeaders(array ...$headers): array $result = []; foreach ($mergedHeaders as $header => $value) { - $result[] = \sprintf('%s: %s', $header, $value); + $result[] = sprintf('%s: %s', $header, $value); } return $result; diff --git a/tests/functional/AbstractBigBlueButtonFunctionalTest.php b/tests/functional/AbstractBigBlueButtonFunctionalTest.php index 074963ff..9fc63704 100644 --- a/tests/functional/AbstractBigBlueButtonFunctionalTest.php +++ b/tests/functional/AbstractBigBlueButtonFunctionalTest.php @@ -197,7 +197,7 @@ public function testJoinMeeting(): void $params = $this->generateJoinMeetingParams(); $joinMeetingParams = new JoinMeetingParameters($result->getMeetingId(), $params['fullName'], $params['role']); $joinMeetingParams->setRedirect(false); - $joinMeetingParams->setCreateTime((int) \sprintf('%.0f', $creationTime)); + $joinMeetingParams->setCreateTime((int) sprintf('%.0f', $creationTime)); $joinMeeting = $this->bbb->joinMeeting($joinMeetingParams); $this->assertEquals('SUCCESS', $joinMeeting->getReturnCode(), 'Join meeting'); diff --git a/tests/unit/Http/Transport/HeaderTest.php b/tests/unit/Http/Transport/HeaderTest.php index d823c559..aacccb44 100644 --- a/tests/unit/Http/Transport/HeaderTest.php +++ b/tests/unit/Http/Transport/HeaderTest.php @@ -61,7 +61,7 @@ public function provideBadlyFormattedHeaders(): iterable public function testMergeCurlHeadersWithBadHeaders(string $badHeader): void { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage(\sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $badHeader)); + $this->expectExceptionMessage(sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $badHeader)); Header::mergeCurlHeaders([$badHeader]); } @@ -82,7 +82,7 @@ public function provideNonStringHeaders(): iterable public function testMergeCurlHeadersWithNonStringHeaders(mixed $badHeader): void { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage(\sprintf( + $this->expectExceptionMessage(sprintf( 'Non-string header with type "%s" passed.', get_debug_type($badHeader) )); diff --git a/tests/unit/Parameters/JoinMeetingParametersTest.php b/tests/unit/Parameters/JoinMeetingParametersTest.php index 615bd479..c7bd6ab7 100644 --- a/tests/unit/Parameters/JoinMeetingParametersTest.php +++ b/tests/unit/Parameters/JoinMeetingParametersTest.php @@ -50,7 +50,6 @@ public function testJoinMeetingParameters(): void $joinMeetingParams->setRole($newRole = Role::VIEWER); $joinMeetingParams->setAvatarURL($avatarUrl = $this->faker->url); $joinMeetingParams->setRedirect($redirect = $this->faker->boolean(50)); - $joinMeetingParams->setClientURL($clientUrl = $this->faker->url); $joinMeetingParams->setErrorRedirectUrl($newErrorRedirectUrl = $this->faker->url); $joinMeetingParams->setGuest($guest = $this->faker->boolean(50)); $this->assertEquals($newId, $joinMeetingParams->getMeetingID()); @@ -58,7 +57,6 @@ public function testJoinMeetingParameters(): void $this->assertEquals($newRole, $joinMeetingParams->getRole()); $this->assertEquals($avatarUrl, $joinMeetingParams->getAvatarURL()); $this->assertEquals($redirect, $joinMeetingParams->isRedirect()); - $this->assertEquals($clientUrl, $joinMeetingParams->getClientURL()); $this->assertEquals($newErrorRedirectUrl, $joinMeetingParams->getErrorRedirectUrl()); $this->assertEquals($guest, $joinMeetingParams->isGuest()); } From 0a312c155e210f17bd6baca4dcf6ee4c39c3f4c1 Mon Sep 17 00:00:00 2001 From: Felix Jacobi Date: Fri, 23 Aug 2024 02:25:44 +0200 Subject: [PATCH 44/68] Removed wrong CS fix --- src/BigBlueButton.php | 8 ++++---- .../PsrHttpClient/PsrHttpClientTransport.php | 8 ++++---- .../SymfonyHttpClientTransport.php | 6 +++--- src/Http/Transport/CurlTransport.php | 2 +- src/Http/Transport/Header.php | 6 +++--- .../AbstractBigBlueButtonFunctionalTest.php | 2 +- tests/unit/Http/Transport/HeaderTest.php | 4 ++-- tools/.phpstan/composer.lock | 14 +++++--------- 8 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index 24f9dfaf..c3c18f31 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -97,11 +97,11 @@ class BigBlueButton public function __construct(?string $baseUrl = null, ?string $secret = null, ?TransportInterface $transport = null, protected HashingAlgorithm $hashingAlgorithm = HashingAlgorithm::SHA_1) { if (null === $baseUrl) { - @trigger_error(sprintf('Constructing "%s" without passing a server base URL is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); + @trigger_error(\sprintf('Constructing "%s" without passing a server base URL is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); } if (null === $secret) { - @trigger_error(sprintf('Constructing "%s" without passing a secret is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); + @trigger_error(\sprintf('Constructing "%s" without passing a secret is deprecated and will throw an exception 6.0.', self::class), \E_USER_DEPRECATED); } if (getenv('BBB_SECURITY_SALT') !== false || getenv('BBB_SECRET') !== false) { @@ -117,7 +117,7 @@ public function __construct(?string $baseUrl = null, ?string $secret = null, ?Tr if (false === $securitySecret) { // @codeCoverageIgnoreStart - @trigger_error(sprintf('Constructing "%s" without passing a secret is deprecated since 6.0 and will throw an exception in 7.0.', self::class), \E_USER_DEPRECATED); + @trigger_error(\sprintf('Constructing "%s" without passing a secret is deprecated since 6.0 and will throw an exception in 7.0.', self::class), \E_USER_DEPRECATED); $this->securitySecret = ''; // previous behaviour // @codeCoverageIgnoreEnd } else { @@ -128,7 +128,7 @@ public function __construct(?string $baseUrl = null, ?string $secret = null, ?Tr if (false === $bbbServerBaseUrl) { // @codeCoverageIgnoreStart - @trigger_error(sprintf('Constructing "%s" without passing a server base URL is deprecated since 6.0 and will throw an exception in 7.0.', self::class), \E_USER_DEPRECATED); + @trigger_error(\sprintf('Constructing "%s" without passing a server base URL is deprecated since 6.0 and will throw an exception in 7.0.', self::class), \E_USER_DEPRECATED); $this->bbbServerBaseUrl = ''; // previous behaviour // @codeCoverageIgnoreEnd } else { diff --git a/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php b/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php index 9343889b..befa70d9 100644 --- a/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php +++ b/src/Http/Transport/Bridge/PsrHttpClient/PsrHttpClientTransport.php @@ -34,7 +34,7 @@ // @codeCoverageIgnoreStart if (!interface_exists(ClientInterface::class)) { - throw new \LogicException(sprintf( + throw new \LogicException(\sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides psr/http-client-implementation.', @@ -44,7 +44,7 @@ } if (!interface_exists(RequestFactoryInterface::class)) { - throw new \LogicException(sprintf( + throw new \LogicException(\sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides psr/http-factory-implementation.', @@ -54,7 +54,7 @@ } if (!interface_exists(StreamFactoryInterface::class)) { - throw new \LogicException(sprintf( + throw new \LogicException(\sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides psr/http-factory-implementation.', @@ -93,7 +93,7 @@ public function request(TransportRequest $request): TransportResponse try { $psrResponse = $this->httpClient->sendRequest($psrRequest); } catch (ClientExceptionInterface $e) { - throw new RuntimeException(sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); + throw new RuntimeException(\sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); } if ($psrResponse->getStatusCode() < 200 || $psrResponse->getStatusCode() >= 300) { diff --git a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php index a3394e52..dcdbbc8f 100644 --- a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php +++ b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php @@ -38,7 +38,7 @@ // @codeCoverageIgnoreStart if (!interface_exists(HttpClientInterface::class)) { - throw new \LogicException(sprintf( + throw new \LogicException(\sprintf( 'The "%s" interface was not found. '. 'You cannot use "%s" without it.'. 'Try running "composer require" for a package which provides symfony/http-client-implementation.', @@ -71,7 +71,7 @@ public static function create(array $defaultHeaders = [], array $defaultOptions { // @codeCoverageIgnoreStart if (!class_exists(HttpClient::class)) { - throw new \LogicException(sprintf( + throw new \LogicException(\sprintf( 'Cannot create an instance of "%s" when Symfony HttpClient is not installed. '. 'Either instantiate the class by yourself and pass a proper implementation or '. 'try to run "composer require symfony/http-client".', @@ -113,7 +113,7 @@ public function request(TransportRequest $request): TransportResponse return new TransportResponse($symfonyResponse->getContent(), self::extractJsessionCookie($symfonyResponse)); } catch (TransportExceptionInterface $e) { - throw new RuntimeException(sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); + throw new RuntimeException(\sprintf('HTTP request failed: %s', $e->getMessage()), 0, $e); } catch (ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface $e) { throw new NetworkException('Bad response.', $e->getCode(), $e); } diff --git a/src/Http/Transport/CurlTransport.php b/src/Http/Transport/CurlTransport.php index 4be0fc57..7bfb82c5 100644 --- a/src/Http/Transport/CurlTransport.php +++ b/src/Http/Transport/CurlTransport.php @@ -220,7 +220,7 @@ private static function getHeadersAndContentFromCurlHandle(\CurlHandle $curlHand $splitHeader = explode(': ', $line, 2); // @codeCoverageIgnoreStart if (!isset($splitHeader[0], $splitHeader[1])) { - throw new \InvalidArgumentException(sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $line)); + throw new \InvalidArgumentException(\sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $line)); } // @codeCoverageIgnoreEnd diff --git a/src/Http/Transport/Header.php b/src/Http/Transport/Header.php index 4a86236b..ea339ee2 100644 --- a/src/Http/Transport/Header.php +++ b/src/Http/Transport/Header.php @@ -43,7 +43,7 @@ public static function mergeCurlHeaders(array ...$headers): array foreach ($headers as $headerSet) { foreach ($headerSet as $header) { if (!\is_string($header)) { - throw new \InvalidArgumentException(sprintf( + throw new \InvalidArgumentException(\sprintf( 'Non-string header with type "%s" passed.', get_debug_type($header) )); @@ -51,7 +51,7 @@ public static function mergeCurlHeaders(array ...$headers): array $splitHeader = explode(': ', $header, 2); if (!isset($splitHeader[0], $splitHeader[1])) { - throw new \InvalidArgumentException(sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $header)); + throw new \InvalidArgumentException(\sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $header)); } // Enforce lower case for header names to avoid duplicates in mixed case. The case of header names should @@ -62,7 +62,7 @@ public static function mergeCurlHeaders(array ...$headers): array $result = []; foreach ($mergedHeaders as $header => $value) { - $result[] = sprintf('%s: %s', $header, $value); + $result[] = \sprintf('%s: %s', $header, $value); } return $result; diff --git a/tests/functional/AbstractBigBlueButtonFunctionalTest.php b/tests/functional/AbstractBigBlueButtonFunctionalTest.php index 9fc63704..074963ff 100644 --- a/tests/functional/AbstractBigBlueButtonFunctionalTest.php +++ b/tests/functional/AbstractBigBlueButtonFunctionalTest.php @@ -197,7 +197,7 @@ public function testJoinMeeting(): void $params = $this->generateJoinMeetingParams(); $joinMeetingParams = new JoinMeetingParameters($result->getMeetingId(), $params['fullName'], $params['role']); $joinMeetingParams->setRedirect(false); - $joinMeetingParams->setCreateTime((int) sprintf('%.0f', $creationTime)); + $joinMeetingParams->setCreateTime((int) \sprintf('%.0f', $creationTime)); $joinMeeting = $this->bbb->joinMeeting($joinMeetingParams); $this->assertEquals('SUCCESS', $joinMeeting->getReturnCode(), 'Join meeting'); diff --git a/tests/unit/Http/Transport/HeaderTest.php b/tests/unit/Http/Transport/HeaderTest.php index aacccb44..d823c559 100644 --- a/tests/unit/Http/Transport/HeaderTest.php +++ b/tests/unit/Http/Transport/HeaderTest.php @@ -61,7 +61,7 @@ public function provideBadlyFormattedHeaders(): iterable public function testMergeCurlHeadersWithBadHeaders(string $badHeader): void { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $badHeader)); + $this->expectExceptionMessage(\sprintf('Header value "%s" is invalid. Expected format is "Header-Name: value".', $badHeader)); Header::mergeCurlHeaders([$badHeader]); } @@ -82,7 +82,7 @@ public function provideNonStringHeaders(): iterable public function testMergeCurlHeadersWithNonStringHeaders(mixed $badHeader): void { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf( + $this->expectExceptionMessage(\sprintf( 'Non-string header with type "%s" passed.', get_debug_type($badHeader) )); diff --git a/tools/.phpstan/composer.lock b/tools/.phpstan/composer.lock index 2cffe70d..21f3a9d3 100644 --- a/tools/.phpstan/composer.lock +++ b/tools/.phpstan/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "phpstan/phpstan", - "version": "1.10.62", + "version": "1.11.11", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9" + "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd5c8a1660ed3540b211407c77abf4af193a6af9", - "reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/707c2aed5d8d0075666e673a5e71440c1d01a5a3", + "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3", "shasum": "" }, "require": { @@ -60,13 +60,9 @@ { "url": "https://github.com/phpstan", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2024-03-13T12:27:20+00:00" + "time": "2024-08-19T14:37:29+00:00" } ], "packages-dev": [], From 1db2fac9884197c18986eb99101123ac1ae036f7 Mon Sep 17 00:00:00 2001 From: Felix Jacobi Date: Fri, 23 Aug 2024 02:27:27 +0200 Subject: [PATCH 45/68] CI: Fully enabled PHP 8.3 --- .github/workflows/ci.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8693cf9f..557a7733 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['8.1', '8.2'] + php-versions: ['8.1', '8.2', '8.3'] experimental: [false] steps: @@ -37,11 +37,8 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['8.1', '8.2'] + php-versions: ['8.1', '8.2', '8.3'] experimental: [false] - include: - - php-versions: '8.3' - experimental: true steps: - name: Checkout uses: actions/checkout@v2 From 21f4e46661313c65b52449e9f3b3ede2b3f7e069 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 19:17:14 +0200 Subject: [PATCH 46/68] Update symfony/http-client-contracts requirement (#209) --- updated-dependencies: - dependency-name: symfony/http-client-contracts dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c79ab95a..ceb080c1 100644 --- a/composer.json +++ b/composer.json @@ -76,7 +76,7 @@ "psr/http-factory": "^1.0", "psr/http-message": "^1.0 || ^2.0", "symfony/dotenv": "^5.4|^6.4|^7.0", - "symfony/http-client-contracts": "^1.1|^2.0", + "symfony/http-client-contracts": "^1.1|^2.0|^3.0", "symfony/http-client": "^5.4|^6.4|^7.0", "symfony/process": "^5.4|^6.4|^7.0", "nyholm/psr7": "^1.4" From 672f881b4f92fe9d0ec0b47a6081085c69b90e49 Mon Sep 17 00:00:00 2001 From: Henning <105713989+marineusde@users.noreply.github.com> Date: Fri, 13 Sep 2024 21:00:17 +0200 Subject: [PATCH 47/68] getting the internal meeting-id from the meeting of the recording (#208) --- src/Core/Record.php | 7 +++++++ tests/unit/BigBlueButtonTest.php | 2 ++ 2 files changed, 9 insertions(+) diff --git a/src/Core/Record.php b/src/Core/Record.php index 4bc11415..c011bf57 100644 --- a/src/Core/Record.php +++ b/src/Core/Record.php @@ -29,6 +29,7 @@ class Record { private readonly string $recordId; private readonly string $meetingId; + private readonly string $internalMeetingId; private readonly string $name; private readonly bool $isPublished; private readonly string $state; @@ -45,6 +46,7 @@ public function __construct(\SimpleXMLElement $xml) { $this->recordId = $xml->recordID->__toString(); $this->meetingId = $xml->meetingID->__toString(); + $this->internalMeetingId = $xml->internalMeetingID->__toString(); $this->name = $xml->name->__toString(); $this->isPublished = $xml->published->__toString() === 'true'; $this->state = $xml->state->__toString(); @@ -71,6 +73,11 @@ public function getMeetingId(): string return $this->meetingId; } + public function getInternalMeetingId(): string + { + return $this->internalMeetingId; + } + public function getName(): string { return $this->name; diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index 2293c269..cf8a60c8 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -380,6 +380,7 @@ public function testGetRecordings(): void f71d810b6e90a4a34ae02b8c7143e8733178578e-1462807897120 9d287cf50490ca856ca5273bd303a7e321df6051-4-119 + c654308ef4b71eeb74eb8436dc52a31415d9a911-1724671588959 true published @@ -415,6 +416,7 @@ public function testGetRecordings(): void $recording = $response->getRecords()[0]; $this->assertEquals('f71d810b6e90a4a34ae02b8c7143e8733178578e-1462807897120', $recording->getRecordID()); $this->assertEquals('9d287cf50490ca856ca5273bd303a7e321df6051-4-119', $recording->getMeetingID()); + $this->assertEquals('c654308ef4b71eeb74eb8436dc52a31415d9a911-1724671588959', $recording->getInternalMeetingID()); $this->assertEquals('SAT- Writing-Humanities (All participants)', $recording->getName()); } From 13fabd0870512030979e4a46e8b9a7096bf70a6a Mon Sep 17 00:00:00 2001 From: Henning <105713989+marineusde@users.noreply.github.com> Date: Fri, 13 Sep 2024 21:01:34 +0200 Subject: [PATCH 48/68] =?UTF-8?q?-=20changed=20the=20type=20from=20string?= =?UTF-8?q?=20to=20integer=20for=20the=20setter=20und=20getter=20o?= =?UTF-8?q?=E2=80=A6=20(#211)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * - changed the type from string to integer for the setter und getter of the voiceBridge * - codestyle fix in the URLBuilder class --------- Co-authored-by: Felix Jacobi --- src/Parameters/CreateMeetingParameters.php | 4 ++-- src/Util/UrlBuilder.php | 2 +- tests/unit/BigBlueButtonTest.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index 85ace07d..a197ff63 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -35,8 +35,8 @@ * @method $this setWelcome(string $welcome) * @method string getDialNumber() * @method $this setDialNumber(string $dialNumber) - * @method string getVoiceBridge() - * @method $this setVoiceBridge(string $voiceBridge) + * @method int getVoiceBridge() + * @method $this setVoiceBridge(int $voiceBridge) * @method string getWebVoice() * @method $this setWebVoice(string $webVoice) * @method int getMaxParticipants() diff --git a/src/Util/UrlBuilder.php b/src/Util/UrlBuilder.php index 0c90873c..822e04a9 100644 --- a/src/Util/UrlBuilder.php +++ b/src/Util/UrlBuilder.php @@ -35,7 +35,7 @@ final class UrlBuilder public function __construct( private readonly string $securitySalt, private readonly string $bbbServerBaseUrl, - private readonly HashingAlgorithm $hashingAlgorithm + private readonly HashingAlgorithm $hashingAlgorithm, ) { } diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index cf8a60c8..9f804c42 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -357,7 +357,7 @@ public function testGetMeetings(): void $this->assertEquals('12345', $response->getMeetings()[0]->getInternalMeetingId()); $this->assertEquals(1531241258036, $response->getMeetings()[0]->getCreationTime()); $this->assertEquals('Tue Jul 10 16:47:38 UTC 2018', $response->getMeetings()[0]->getCreationDate()); - $this->assertEquals('70066', $response->getMeetings()[0]->getVoiceBridge()); + $this->assertEquals(70066, $response->getMeetings()[0]->getVoiceBridge()); $this->assertEquals('613-555-1234', $response->getMeetings()[0]->getDialNumber()); $this->assertFalse($response->getMeetings()[0]->isRunning()); $this->assertEquals(0, $response->getMeetings()[0]->getDuration()); From 35635036ad31412d40de22f7138b3a71c34c1815 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Tue, 17 Sep 2024 06:48:56 +0200 Subject: [PATCH 49/68] Add sendchatmessage api endpoint (#204) * Implement SendChatMessage api * Update src/Parameters/SendChatMessageParameters.php Co-authored-by: Felix Jacobi * Rectored code * Fixed PHPStan --------- Co-authored-by: Felix Jacobi --- src/BigBlueButton.php | 19 ++++++++++ src/Enum/ApiMethod.php | 1 + src/Http/Transport/CurlTransport.php | 3 +- src/Parameters/SendChatMessageParameters.php | 39 ++++++++++++++++++++ src/Responses/SendChatMessageResponse.php | 26 +++++++++++++ tools/.phpstan/composer.lock | 10 ++--- 6 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 src/Parameters/SendChatMessageParameters.php create mode 100644 src/Responses/SendChatMessageResponse.php diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index c3c18f31..5564e460 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -45,6 +45,7 @@ use BigBlueButton\Parameters\JoinMeetingParameters; use BigBlueButton\Parameters\PublishRecordingsParameters; use BigBlueButton\Parameters\PutRecordingTextTrackParameters; +use BigBlueButton\Parameters\SendChatMessageParameters; use BigBlueButton\Parameters\UpdateRecordingsParameters; use BigBlueButton\Responses\ApiVersionResponse; use BigBlueButton\Responses\CreateMeetingResponse; @@ -62,6 +63,7 @@ use BigBlueButton\Responses\JoinMeetingResponse; use BigBlueButton\Responses\PublishRecordingsResponse; use BigBlueButton\Responses\PutRecordingTextTrackResponse; +use BigBlueButton\Responses\SendChatMessageResponse; use BigBlueButton\Responses\UpdateRecordingsResponse; use BigBlueButton\Util\UrlBuilder; @@ -478,6 +480,23 @@ public function insertDocument(InsertDocumentParameters $insertDocumentParams): return new InsertDocumentResponse($xml); } + public function getSendChatMessageUrl(SendChatMessageParameters $sendChatMessageParams): string + { + return $this->urlBuilder->buildUrl(ApiMethod::SEND_CHAT_MESSAGE, $sendChatMessageParams->getHTTPQuery()); + } + + /** + * @throws NetworkException + * @throws ParsingException + * @throws RuntimeException + */ + public function getSendChatMessage(SendChatMessageParameters $sendChatMessageParams): SendChatMessageResponse + { + $xml = $this->processXmlResponse($this->getSendChatMessageUrl($sendChatMessageParams)); + + return new SendChatMessageResponse($xml); + } + /* ____________________ SPECIAL METHODS ___________________ */ public function getJSessionId(): ?string diff --git a/src/Enum/ApiMethod.php b/src/Enum/ApiMethod.php index 519b0c6c..e8b9e79a 100644 --- a/src/Enum/ApiMethod.php +++ b/src/Enum/ApiMethod.php @@ -45,4 +45,5 @@ enum ApiMethod: string case HOOKS_LIST = 'hooks/list'; case HOOKS_DESTROY = 'hooks/destroy'; case INSERT_DOCUMENT = 'insertDocument'; + case SEND_CHAT_MESSAGE = 'sendChatMessage'; } diff --git a/src/Http/Transport/CurlTransport.php b/src/Http/Transport/CurlTransport.php index 7bfb82c5..16f20fc5 100644 --- a/src/Http/Transport/CurlTransport.php +++ b/src/Http/Transport/CurlTransport.php @@ -88,9 +88,8 @@ public function request(TransportRequest $request): TransportResponse $ch = curl_init(); // @codeCoverageIgnoreStart - /* @phpstan-ignore-next-line */ if (!$ch) { - throw new RuntimeException('Could not create curl instance. Error: '.curl_error($ch)); + throw new RuntimeException('Could not create curl instance.'); } // @codeCoverageIgnoreEnd diff --git a/src/Parameters/SendChatMessageParameters.php b/src/Parameters/SendChatMessageParameters.php new file mode 100644 index 00000000..3fb30f97 --- /dev/null +++ b/src/Parameters/SendChatMessageParameters.php @@ -0,0 +1,39 @@ +. + */ + +namespace BigBlueButton\Parameters; + +/** + * Class SendChatMessageParameters. + * + * @method string getMeetingID() + * @method $this setMeetingID(string $id) + * @method string getMessage() + * @method $this setMessage(string $message) + * @method string|null getUserName() + * @method $this setUserName(string $userName) + */ +final class SendChatMessageParameters extends BaseParameters +{ + public function __construct(protected string $meetingID, protected string $message, protected ?string $userName = null) + { + } +} diff --git a/src/Responses/SendChatMessageResponse.php b/src/Responses/SendChatMessageResponse.php new file mode 100644 index 00000000..95ee4ebd --- /dev/null +++ b/src/Responses/SendChatMessageResponse.php @@ -0,0 +1,26 @@ +. + */ + +namespace BigBlueButton\Responses; + +final class SendChatMessageResponse extends BaseResponse +{ +} diff --git a/tools/.phpstan/composer.lock b/tools/.phpstan/composer.lock index 21f3a9d3..2c3ffe96 100644 --- a/tools/.phpstan/composer.lock +++ b/tools/.phpstan/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "phpstan/phpstan", - "version": "1.11.11", + "version": "1.12.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3" + "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/707c2aed5d8d0075666e673a5e71440c1d01a5a3", - "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0fcbf194ab63d8159bb70d9aa3e1350051632009", + "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009", "shasum": "" }, "require": { @@ -62,7 +62,7 @@ "type": "github" } ], - "time": "2024-08-19T14:37:29+00:00" + "time": "2024-09-09T08:10:35+00:00" } ], "packages-dev": [], From 0df16da657a8555d7f880edf3e797e5ae0ade5dc Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sat, 28 Sep 2024 00:04:05 +0200 Subject: [PATCH 50/68] Add learningDashboardDownloadSessionData to Feature enum (#213) --- src/Enum/Feature.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php index 490e288b..b995f41b 100644 --- a/src/Enum/Feature.php +++ b/src/Enum/Feature.php @@ -36,6 +36,7 @@ enum Feature: string case IMPORT_SHARED_NOTES_FROM_BREAKOUT_ROOMS = 'importSharedNotesFromBreakoutRooms'; case LAYOUTS = 'layouts'; case LEARNING_DASHBOARD = 'learningDashboard'; + case LEARNING_DASHBOARD_DOWNLOAD_SESSION_DATA = 'learningDashboardDownloadSessionData'; case POLLS = 'polls'; case SCREENSHARE = 'screenshare'; case SHARED_NOTES = 'sharedNotes'; From edfdd95bb76476e95ecc9c8fecbd80594b10afb8 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sat, 28 Sep 2024 00:06:09 +0200 Subject: [PATCH 51/68] Add webcamBackgroundURL (#214) Co-authored-by: Felix Jacobi --- src/Parameters/JoinMeetingParameters.php | 3 +++ tests/unit/Parameters/JoinMeetingParametersTest.php | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index e17c6167..f55ee924 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -51,6 +51,8 @@ * @method $this setRole(Role $role) * @method bool|null isExcludeFromDashboard() * @method $this setExcludeFromDashboard(bool $excludeFromDashboard) + * @method string getWebcamBackgroundURL() + * @method $this setWebcamBackgroundURL(string $webcamBackgroundURL) */ class JoinMeetingParameters extends UserDataParameters { @@ -63,6 +65,7 @@ class JoinMeetingParameters extends UserDataParameters protected ?string $errorRedirectUrl = null; protected ?bool $guest = null; protected ?bool $excludeFromDashboard = null; + protected ?string $webcamBackgroundURL = null; public function __construct(protected string $meetingID, protected string $fullName, protected Role $role) { diff --git a/tests/unit/Parameters/JoinMeetingParametersTest.php b/tests/unit/Parameters/JoinMeetingParametersTest.php index c7bd6ab7..9c7b900a 100644 --- a/tests/unit/Parameters/JoinMeetingParametersTest.php +++ b/tests/unit/Parameters/JoinMeetingParametersTest.php @@ -52,6 +52,7 @@ public function testJoinMeetingParameters(): void $joinMeetingParams->setRedirect($redirect = $this->faker->boolean(50)); $joinMeetingParams->setErrorRedirectUrl($newErrorRedirectUrl = $this->faker->url); $joinMeetingParams->setGuest($guest = $this->faker->boolean(50)); + $joinMeetingParams->setWebcamBackgroundURL($webcamBackgroundURL = $this->faker->url); $this->assertEquals($newId, $joinMeetingParams->getMeetingID()); $this->assertEquals($newName, $joinMeetingParams->getFullName()); $this->assertEquals($newRole, $joinMeetingParams->getRole()); @@ -59,5 +60,6 @@ public function testJoinMeetingParameters(): void $this->assertEquals($redirect, $joinMeetingParams->isRedirect()); $this->assertEquals($newErrorRedirectUrl, $joinMeetingParams->getErrorRedirectUrl()); $this->assertEquals($guest, $joinMeetingParams->isGuest()); + $this->assertEquals($webcamBackgroundURL, $joinMeetingParams->getWebcamBackgroundURL()); } } From 7d82f34559d136bbd97411c317a62814200a2137 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sat, 28 Sep 2024 00:07:39 +0200 Subject: [PATCH 52/68] Add dark logo (#215) Co-authored-by: Felix Jacobi --- src/Parameters/CreateMeetingParameters.php | 3 +++ tests/common/TestCase.php | 2 ++ tests/unit/Parameters/CreateMeetingParametersTest.php | 1 + 3 files changed, 6 insertions(+) diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index a197ff63..02db9d60 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -73,6 +73,8 @@ * @method $this setWebcamsOnlyForModerator(bool $isWebcamsOnlyForModerator) * @method string getLogo() * @method $this setLogo(string $logo) + * @method string getDarklogo() + * @method $this setDarklogo(string $darklogo) * @method string getBannerText() * @method $this setBannerText(string $bannerText) * @method string getBannerColor() @@ -167,6 +169,7 @@ class CreateMeetingParameters extends MetaParameters protected ?bool $allowStartStopRecording = null; protected ?bool $webcamsOnlyForModerator = null; protected ?string $logo = null; + protected ?string $darklogo = null; protected ?string $bannerText = null; protected ?string $bannerColor = null; protected ?string $copyright = null; diff --git a/tests/common/TestCase.php b/tests/common/TestCase.php index 41573db1..19c792fc 100644 --- a/tests/common/TestCase.php +++ b/tests/common/TestCase.php @@ -75,6 +75,7 @@ protected function generateCreateParams(): array 'moderatorOnlyMessage' => $this->faker->sentence, 'webcamsOnlyForModerator' => $this->faker->boolean(50), 'logo' => $this->faker->imageUrl(330, 70), + 'darklogo' => $this->faker->imageUrl(330, 70), 'copyright' => $this->faker->text, 'guestPolicy' => $this->faker->randomElement([GuestPolicy::ALWAYS_ACCEPT, GuestPolicy::ALWAYS_DENY, GuestPolicy::ASK_MODERATOR]), 'muteOnStart' => $this->faker->boolean(50), @@ -165,6 +166,7 @@ protected function getCreateMock(array $params): CreateMeetingParameters ->setModeratorOnlyMessage($params['moderatorOnlyMessage']) ->setWebcamsOnlyForModerator($params['webcamsOnlyForModerator']) ->setLogo($params['logo']) + ->setDarklogo($params['darklogo']) ->setCopyright($params['copyright']) ->setEndCallbackUrl($params['meta_endCallbackUrl']) ->setRecordingReadyCallbackUrl($params['meta_bbb-recording-ready-url']) diff --git a/tests/unit/Parameters/CreateMeetingParametersTest.php b/tests/unit/Parameters/CreateMeetingParametersTest.php index a9389a61..29028494 100644 --- a/tests/unit/Parameters/CreateMeetingParametersTest.php +++ b/tests/unit/Parameters/CreateMeetingParametersTest.php @@ -51,6 +51,7 @@ public function testCreateMeetingParameters(): void $this->assertEquals($params['moderatorOnlyMessage'], $createMeetingParams->getModeratorOnlyMessage()); $this->assertEquals($params['webcamsOnlyForModerator'], $createMeetingParams->isWebcamsOnlyForModerator()); $this->assertEquals($params['logo'], $createMeetingParams->getLogo()); + $this->assertEquals($params['darklogo'], $createMeetingParams->getDarklogo()); $this->assertEquals($params['copyright'], $createMeetingParams->getCopyright()); $this->assertEquals($params['muteOnStart'], $createMeetingParams->isMuteOnStart()); $this->assertEquals($params['guestPolicy'], $createMeetingParams->getGuestPolicy()); From 9a3bc9486deae47fceb73b6ecdb5c49d3d32fcb7 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sat, 28 Sep 2024 11:18:30 +0200 Subject: [PATCH 53/68] Add infiniteWhiteboard to features enum (#220) --- src/Enum/Feature.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php index b995f41b..a88b1691 100644 --- a/src/Enum/Feature.php +++ b/src/Enum/Feature.php @@ -49,4 +49,5 @@ enum Feature: string case DOWNLOAD_PRESENTATION_ORIGINAL_FILE = 'downloadPresentationOriginalFile'; case DOWNLOAD_PRESENTATION_CONVERTED_TO_PDF = 'downloadPresentationConvertedToPdf'; case TIMER = 'timer'; + case INFINITE_WHITEBOARD = 'infiniteWhiteboard'; } From 7a7f832b521f101b66607789d2a7efbddf138a31 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Fri, 4 Oct 2024 20:06:51 +0200 Subject: [PATCH 54/68] Add enforce layout and new layout options (#219) * Add enforce layout and new layout options * Update JoinMeetingParameters.php --- src/Enum/MeetingLayout.php | 3 +++ src/Parameters/JoinMeetingParameters.php | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/Enum/MeetingLayout.php b/src/Enum/MeetingLayout.php index 07f6107f..e3b1b217 100644 --- a/src/Enum/MeetingLayout.php +++ b/src/Enum/MeetingLayout.php @@ -31,4 +31,7 @@ enum MeetingLayout: string case SMART_LAYOUT = 'SMART_LAYOUT'; case PRESENTATION_FOCUS = 'PRESENTATION_FOCUS'; case VIDEO_FOCUS = 'VIDEO_FOCUS'; + case CAMERAS_ONLY = 'CAMERAS_ONLY'; + case PARTICIPANTS_CHAT_ONLY = 'PARTICIPANTS_CHAT_ONLY'; + case PRESENTATION_ONLY = 'PRESENTATION_ONLY'; } diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index f55ee924..04928cd4 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -22,6 +22,7 @@ namespace BigBlueButton\Parameters; +use BigBlueButton\Enum\MeetingLayout; use BigBlueButton\Enum\Role; /** @@ -51,6 +52,8 @@ * @method $this setRole(Role $role) * @method bool|null isExcludeFromDashboard() * @method $this setExcludeFromDashboard(bool $excludeFromDashboard) + * @method string getEnforceLayout() + * @method $this setEnforceLayout(MeetingLayout $enforceLayout) * @method string getWebcamBackgroundURL() * @method $this setWebcamBackgroundURL(string $webcamBackgroundURL) */ @@ -65,6 +68,7 @@ class JoinMeetingParameters extends UserDataParameters protected ?string $errorRedirectUrl = null; protected ?bool $guest = null; protected ?bool $excludeFromDashboard = null; + protected ?MeetingLayout $enforceLayout = null; protected ?string $webcamBackgroundURL = null; public function __construct(protected string $meetingID, protected string $fullName, protected Role $role) From 49315e5029a7284d624739d90722a2ec14e07d4c Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Wed, 9 Apr 2025 15:25:59 +0200 Subject: [PATCH 55/68] Add missing enforceLayout value 'MEDIA_ONLY' BBB 3.0 --- src/Enum/MeetingLayout.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Enum/MeetingLayout.php b/src/Enum/MeetingLayout.php index e3b1b217..a06293c3 100644 --- a/src/Enum/MeetingLayout.php +++ b/src/Enum/MeetingLayout.php @@ -34,4 +34,5 @@ enum MeetingLayout: string case CAMERAS_ONLY = 'CAMERAS_ONLY'; case PARTICIPANTS_CHAT_ONLY = 'PARTICIPANTS_CHAT_ONLY'; case PRESENTATION_ONLY = 'PRESENTATION_ONLY'; + case MEDIA_ONLY = 'MEDIA_ONLY'; } From b56c4dcd04f57461d5f38715c42e2442616cffc0 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Wed, 9 Apr 2025 15:36:12 +0000 Subject: [PATCH 56/68] Update type declarations of SymfonyHttpClientTransport constructor --- .../Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php index dcdbbc8f..0545c74d 100644 --- a/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php +++ b/src/Http/Transport/Bridge/SymfonyHttpClient/SymfonyHttpClientTransport.php @@ -57,7 +57,7 @@ final class SymfonyHttpClientTransport implements TransportInterface * @param string[] $defaultHeaders additional HTTP headers to pass on each request * @param mixed[] $defaultOptions Options for Symfony HTTP client passed on every request. See {@link https://symfony.com/doc/current/http_client.html} for details. */ - public function __construct(private readonly HttpClientInterface $httpClient, private array $defaultHeaders = [], private readonly array $defaultOptions = []) + public function __construct(private readonly HttpClientInterface $httpClient, private readonly array $defaultHeaders = [], private readonly array $defaultOptions = []) { } From 58f3d5e950fc4f2ff773d5651f8278cdef763ac7 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Wed, 30 Apr 2025 13:16:28 +0200 Subject: [PATCH 57/68] Add new join parameter bot (#224) --- src/Parameters/JoinMeetingParameters.php | 3 +++ tests/unit/Parameters/JoinMeetingParametersTest.php | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index 04928cd4..f59de439 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -56,6 +56,8 @@ * @method $this setEnforceLayout(MeetingLayout $enforceLayout) * @method string getWebcamBackgroundURL() * @method $this setWebcamBackgroundURL(string $webcamBackgroundURL) + * @method bool|null isBot() + * @method $this setBot(bool $bot) */ class JoinMeetingParameters extends UserDataParameters { @@ -70,6 +72,7 @@ class JoinMeetingParameters extends UserDataParameters protected ?bool $excludeFromDashboard = null; protected ?MeetingLayout $enforceLayout = null; protected ?string $webcamBackgroundURL = null; + protected ?bool $bot = null; public function __construct(protected string $meetingID, protected string $fullName, protected Role $role) { diff --git a/tests/unit/Parameters/JoinMeetingParametersTest.php b/tests/unit/Parameters/JoinMeetingParametersTest.php index 9c7b900a..4aa1f16b 100644 --- a/tests/unit/Parameters/JoinMeetingParametersTest.php +++ b/tests/unit/Parameters/JoinMeetingParametersTest.php @@ -53,6 +53,7 @@ public function testJoinMeetingParameters(): void $joinMeetingParams->setErrorRedirectUrl($newErrorRedirectUrl = $this->faker->url); $joinMeetingParams->setGuest($guest = $this->faker->boolean(50)); $joinMeetingParams->setWebcamBackgroundURL($webcamBackgroundURL = $this->faker->url); + $joinMeetingParams->setBot($bot = $this->faker->boolean(50)); $this->assertEquals($newId, $joinMeetingParams->getMeetingID()); $this->assertEquals($newName, $joinMeetingParams->getFullName()); $this->assertEquals($newRole, $joinMeetingParams->getRole()); @@ -61,5 +62,6 @@ public function testJoinMeetingParameters(): void $this->assertEquals($newErrorRedirectUrl, $joinMeetingParams->getErrorRedirectUrl()); $this->assertEquals($guest, $joinMeetingParams->isGuest()); $this->assertEquals($webcamBackgroundURL, $joinMeetingParams->getWebcamBackgroundURL()); + $this->assertEquals($bot, $joinMeetingParams->isBot()); } } From ec9c644ed89dd15c622fdc162e44f2ee4c1ce361 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Sat, 5 Jul 2025 19:16:59 +0200 Subject: [PATCH 58/68] Update feature enum for BBB 3.0 (#225) * Update features to BBB 3.0 * Fix const casing, add privateChat --- src/Enum/Feature.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php index a88b1691..31b54408 100644 --- a/src/Enum/Feature.php +++ b/src/Enum/Feature.php @@ -30,6 +30,7 @@ enum Feature: string case BREAKOUT_ROOMS = 'breakoutRooms'; case CAPTIONS = 'captions'; case CHAT = 'chat'; + case PRIVATE_CHAT = 'privateChat'; case DOWNLOAD_PRESENTATION_WITH_ANNOTATIONS = 'downloadPresentationWithAnnotations'; case EXTERNAL_VIDEOS = 'externalVideos'; case IMPORT_PRESENTATION_WITH_ANNOTATIONS_FROM_BREAKOUT_ROOMS = 'importPresentationWithAnnotationsFromBreakoutRooms'; @@ -50,4 +51,11 @@ enum Feature: string case DOWNLOAD_PRESENTATION_CONVERTED_TO_PDF = 'downloadPresentationConvertedToPdf'; case TIMER = 'timer'; case INFINITE_WHITEBOARD = 'infiniteWhiteboard'; + case DELETE_CHAT_MESSAGE = 'deleteChatMessage'; + case EDIT_CHAT_MESSAGE = 'editChatMessage'; + case REPLY_CHAT_MESSAGE = 'replyChatMessage'; + case CHAT_MESSAGE_REACTIONS = 'chatMessageReactions'; + case RAISE_HAND = 'raiseHand'; + case USER_ACTIONS = 'userActions'; + case CHAT_EMOJI_PICKER = 'chatEmojiPicker'; } From 17232705cd3488b1818319e7273255535f66722e Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:02:25 +0200 Subject: [PATCH 59/68] Fix cs --- src/Http/Transport/CurlTransport.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Http/Transport/CurlTransport.php b/src/Http/Transport/CurlTransport.php index 16f20fc5..8f537677 100644 --- a/src/Http/Transport/CurlTransport.php +++ b/src/Http/Transport/CurlTransport.php @@ -183,11 +183,11 @@ private static function mergeCurlOptions(array ...$options): array * * @return (string|string[][])[] First key headers, second key is content * - * @throws NetworkException - * * @see https://stackoverflow.com/questions/10589889/returning-header-as-array-using-curl * * @psalm-return array{0: array>, 1: string} + * + * @throws NetworkException */ private static function getHeadersAndContentFromCurlHandle(\CurlHandle $curlHandle): array { From 232213d9897e8f1e89035094c916bf0efaf00f54 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:17:34 +0200 Subject: [PATCH 60/68] Add new create and join parameters (#226) --- src/Parameters/CreateMeetingParameters.php | 15 +++++++++++++++ src/Parameters/JoinMeetingParameters.php | 9 +++++++++ 2 files changed, 24 insertions(+) diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index 02db9d60..e3480d44 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -41,6 +41,8 @@ * @method $this setWebVoice(string $webVoice) * @method int getMaxParticipants() * @method $this setMaxParticipants(int $maxParticipants) + * @method string getLoginURL() + * @method $this setLoginURL(string $loginURL) * @method string getLogoutURL() * @method $this setLogoutURL(string $logoutURL) * @method bool|null isRecord() @@ -147,6 +149,14 @@ * @method $this setPreUploadedPresentation(string $preUploadedPresentation) * @method string getPreUploadedPresentationName() * @method $this setPreUploadedPresentationName(string $preUploadedPresentationName) + * @method int|null getMaxNumPages() + * @method $this setMaxNumPages(int $maxNumPages) + * @method string getPluginManifests() + * @method $this setPluginManifests(string $pluginManifests) + * @method string getPluginManifestsFetchUrl() + * @method $this setPluginManifestsFetchUrl(string $pluginManifestsFetchUrl) + * @method bool|null isPresentationConversionCacheEnabled() + * @method $this setPresentationConversionCacheEnabled(bool $presentationConversionCacheEnabled) */ class CreateMeetingParameters extends MetaParameters { @@ -155,6 +165,7 @@ class CreateMeetingParameters extends MetaParameters protected ?int $voiceBridge = null; protected ?string $webVoice = null; protected ?int $maxParticipants = null; + protected ?string $loginURL = null; protected ?string $logoutURL = null; protected ?bool $record = null; protected ?int $duration = null; @@ -224,6 +235,10 @@ class CreateMeetingParameters extends MetaParameters protected ?bool $recordFullDurationMedia = null; protected ?string $presentationUploadExternalUrl = null; protected ?string $presentationUploadExternalDescription = null; + protected ?int $maxNumPages = null; + protected ?string $pluginManifests = null; + protected ?string $pluginManifestsFetchUrl = null; + protected ?bool $presentationConversionCacheEnabled = null; /** * @var array diff --git a/src/Parameters/JoinMeetingParameters.php b/src/Parameters/JoinMeetingParameters.php index f59de439..a95eb384 100644 --- a/src/Parameters/JoinMeetingParameters.php +++ b/src/Parameters/JoinMeetingParameters.php @@ -58,6 +58,12 @@ * @method $this setWebcamBackgroundURL(string $webcamBackgroundURL) * @method bool|null isBot() * @method $this setBot(bool $bot) + * @method string getLogoutURL() + * @method $this setLogoutURL(string $logoutURL) + * @method string getFirstName() + * @method $this setFirstName(string $firstName) + * @method string getLastName() + * @method $this setLastName(string $lastName) */ class JoinMeetingParameters extends UserDataParameters { @@ -72,6 +78,9 @@ class JoinMeetingParameters extends UserDataParameters protected ?bool $excludeFromDashboard = null; protected ?MeetingLayout $enforceLayout = null; protected ?string $webcamBackgroundURL = null; + protected ?string $logoutURL = null; + protected ?string $firstName = null; + protected ?string $lastName = null; protected ?bool $bot = null; public function __construct(protected string $meetingID, protected string $fullName, protected Role $role) From f892715ec73e8c05f8c8e07146f961c24b1284a1 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Thu, 2 Oct 2025 01:46:27 +0200 Subject: [PATCH 61/68] Add BBB 3.0 client settings override (#227) * Add support for clientSettingsOverride * Update src/Util/SimpleXMLElementExtended.php Co-authored-by: Felix Jacobi * Add unit test --------- Co-authored-by: Felix Jacobi --- composer.json | 3 +- src/BigBlueButton.php | 2 +- src/Parameters/CreateMeetingParameters.php | 32 ++++++++++--- src/Util/SimpleXMLElementExtended.php | 24 ++++++++++ tests/fixtures/client_settings.xml | 6 +++ .../CreateMeetingParametersTest.php | 16 +++++-- .../Util/SimpleXMLElementExtendedTest.php | 46 +++++++++++++++++++ 7 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 src/Util/SimpleXMLElementExtended.php create mode 100644 tests/fixtures/client_settings.xml create mode 100644 tests/unit/Util/SimpleXMLElementExtendedTest.php diff --git a/composer.json b/composer.json index ceb080c1..a81e1f04 100644 --- a/composer.json +++ b/composer.json @@ -62,7 +62,8 @@ "ext-curl": "*", "ext-simplexml": "*", "ext-mbstring": "*", - "ext-json": "*" + "ext-json": "*", + "ext-dom": "*" }, "suggest": { "psr/http-client-implementation": "To use the PsrHttpClientTransport.", diff --git a/src/BigBlueButton.php b/src/BigBlueButton.php index 5564e460..8e4431d0 100644 --- a/src/BigBlueButton.php +++ b/src/BigBlueButton.php @@ -222,7 +222,7 @@ public function getCreateMeetingUrl(CreateMeetingParameters $createMeetingParams */ public function createMeeting(CreateMeetingParameters $createMeetingParams): CreateMeetingResponse { - $xml = $this->processXmlResponse($this->getCreateMeetingUrl($createMeetingParams), $createMeetingParams->getPresentationsAsXML()); + $xml = $this->processXmlResponse($this->getCreateMeetingUrl($createMeetingParams), $createMeetingParams->getModules()); return new CreateMeetingResponse($xml); } diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index e3480d44..131ad623 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -25,6 +25,7 @@ use BigBlueButton\Enum\Feature; use BigBlueButton\Enum\GuestPolicy; use BigBlueButton\Enum\MeetingLayout; +use BigBlueButton\Util\SimpleXMLElementExtended; /** * @method string getName() @@ -157,6 +158,10 @@ * @method $this setPluginManifestsFetchUrl(string $pluginManifestsFetchUrl) * @method bool|null isPresentationConversionCacheEnabled() * @method $this setPresentationConversionCacheEnabled(bool $presentationConversionCacheEnabled) + * @method bool|null isAllowOverrideClientSettingsOnCreateCall() + * @method $this setAllowOverrideClientSettingsOnCreateCall(bool $allowOverrideClientSettingsOnCreateCall) + * @method string getClientSettingsOverride() + * @method $this setClientSettingsOverride(string $clientSettingsOverride) */ class CreateMeetingParameters extends MetaParameters { @@ -239,6 +244,8 @@ class CreateMeetingParameters extends MetaParameters protected ?string $pluginManifests = null; protected ?string $pluginManifestsFetchUrl = null; protected ?bool $presentationConversionCacheEnabled = null; + protected ?bool $allowOverrideClientSettingsOnCreateCall = null; + protected ?string $clientSettingsOverride = null; /** * @var array @@ -249,7 +256,7 @@ public function __construct(protected string $meetingID, protected string $name) { $this->guestPolicy = GuestPolicy::ALWAYS_ACCEPT; - $this->ignoreProperties = ['disabledFeatures', 'disabledFeaturesExclude']; + $this->ignoreProperties = ['disabledFeatures', 'disabledFeaturesExclude', 'clientSettingsOverride']; } public function setEndCallbackUrl(string $endCallbackUrl): self @@ -381,12 +388,26 @@ public function getPresentations(): array return $this->presentations; } - public function getPresentationsAsXML(): string|false + public function getModules(): string { - $result = ''; + $xml = new SimpleXMLElementExtended(''); + $this->addPresentationsModule($xml); + $this->addClientSettingsOverrideModule($xml); + return $xml->asXML(); + } + + public function addClientSettingsOverrideModule(SimpleXMLElementExtended $xml): void + { + if (!empty($this->clientSettingsOverride)) { + $module = $xml->addChildWithCData('module', $this->clientSettingsOverride); + $module->addAttribute('name', 'clientSettingsOverride'); + } + } + + public function addPresentationsModule(SimpleXMLElementExtended $xml): void + { if (!empty($this->presentations)) { - $xml = new \SimpleXMLElement(''); $module = $xml->addChild('module'); $module->addAttribute('name', 'presentation'); @@ -404,10 +425,7 @@ public function getPresentationsAsXML(): string|false $document[0] = $content; } } - $result = $xml->asXML(); } - - return $result; } public function getHTTPQuery(): string diff --git a/src/Util/SimpleXMLElementExtended.php b/src/Util/SimpleXMLElementExtended.php new file mode 100644 index 00000000..d78c9e20 --- /dev/null +++ b/src/Util/SimpleXMLElementExtended.php @@ -0,0 +1,24 @@ +ownerDocument; + $element->appendChild($docOwner->createCDATASection($value)); + + return $child; + } +} diff --git a/tests/fixtures/client_settings.xml b/tests/fixtures/client_settings.xml new file mode 100644 index 00000000..6ef5db4b --- /dev/null +++ b/tests/fixtures/client_settings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/unit/Parameters/CreateMeetingParametersTest.php b/tests/unit/Parameters/CreateMeetingParametersTest.php index 29028494..be94bead 100644 --- a/tests/unit/Parameters/CreateMeetingParametersTest.php +++ b/tests/unit/Parameters/CreateMeetingParametersTest.php @@ -202,7 +202,7 @@ public function testGetPresentationsAsXMLWithUrl(): void $params = $this->generateCreateParams(); $createMeetingParams = $this->getCreateMock($params); $createMeetingParams->addPresentation('http://test-install.blindsidenetworks.com/default.pdf'); - $this->assertXmlStringEqualsXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'presentation_with_url.xml', $createMeetingParams->getPresentationsAsXML()); + $this->assertXmlStringEqualsXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'presentation_with_url.xml', $createMeetingParams->getModules()); } public function testGetPresentationsAsXMLWithUrlAndFilename(): void @@ -210,7 +210,7 @@ public function testGetPresentationsAsXMLWithUrlAndFilename(): void $params = $this->generateCreateParams(); $createMeetingParams = $this->getCreateMock($params); $createMeetingParams->addPresentation('http://test-install.blindsidenetworks.com/default.pdf', null, 'presentation.pdf'); - $this->assertXmlStringEqualsXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'presentation_with_filename.xml', $createMeetingParams->getPresentationsAsXML()); + $this->assertXmlStringEqualsXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'presentation_with_filename.xml', $createMeetingParams->getModules()); } public function testGetPresentationsAsXMLWithFile(): void @@ -218,7 +218,7 @@ public function testGetPresentationsAsXMLWithFile(): void $params = $this->generateCreateParams(); $createMeetingParams = $this->getCreateMock($params); $createMeetingParams->addPresentation('bbb_logo.png', file_get_contents(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'bbb_logo.png')); - $this->assertXmlStringEqualsXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'presentation_with_embedded_file.xml', $createMeetingParams->getPresentationsAsXML()); + $this->assertXmlStringEqualsXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'presentation_with_embedded_file.xml', $createMeetingParams->getModules()); } public function testUserCameraCap(): void @@ -272,4 +272,14 @@ public function testGuestPolicyAskModerator(): void $this->assertSame(GuestPolicy::ASK_MODERATOR, $createMeetingParams->getGuestPolicy()); $this->assertTrue($createMeetingParams->isGuestPolicyAskModerator()); } + + public function testClientSettingsOverride(): void + { + $params = $this->generateCreateParams(); + $createMeetingParams = $this->getCreateMock($params); + + $createMeetingParams->setClientSettingsOverride('{ "public": { "app": { "appName": "Test" } } }'); + + $this->assertXmlStringEqualsXmlFile(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'client_settings.xml', $createMeetingParams->getModules()); + } } diff --git a/tests/unit/Util/SimpleXMLElementExtendedTest.php b/tests/unit/Util/SimpleXMLElementExtendedTest.php new file mode 100644 index 00000000..c29a09c7 --- /dev/null +++ b/tests/unit/Util/SimpleXMLElementExtendedTest.php @@ -0,0 +1,46 @@ +. + */ + +namespace BigBlueButton\Tests\Unit\Util; + +use BigBlueButton\Tests\Common\TestCase; +use BigBlueButton\Util\SimpleXMLElementExtended; + +/** + * @covers \BigBlueButton\Util\SimpleXMLElementExtended + */ +final class SimpleXMLElementExtendedTest extends TestCase +{ + /** + * Test adding a child element with CDATA content. + */ + public function testAddChildWithCData(): void + { + $xml = new SimpleXMLElementExtended(''); + $module = $xml->addChildWithCData('module', '{"foo": {"foo": "baa"}}'); + $module->addAttribute('name', 'clientSettingsOverride'); + + $expected = ' +'; + + $this->assertXmlStringEqualsXmlString($expected, $xml->asXML()); + } +} From 9194583adb1610690e2f972ad485b5e1a1be487d Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Tue, 28 Oct 2025 13:01:57 +0100 Subject: [PATCH 62/68] Add QUIZZES to Feature enum See https://docs.bigbluebutton.org/development/api/#updates-to-api-in-bigbluebutton --- src/Enum/Feature.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php index 31b54408..640f1db9 100644 --- a/src/Enum/Feature.php +++ b/src/Enum/Feature.php @@ -58,4 +58,5 @@ enum Feature: string case RAISE_HAND = 'raiseHand'; case USER_ACTIONS = 'userActions'; case CHAT_EMOJI_PICKER = 'chatEmojiPicker'; + case QUIZZES = 'quizzes'; } From a8c6b3cd84ae586d5676aa979197f608d6be22a9 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Tue, 28 Oct 2025 16:05:36 +0100 Subject: [PATCH 63/68] Fix: Create meeting call is always a POST request (#230) * Add tests * Fix: getModules() should return empty string if no modules are attached * Fix cs and docs --- src/Parameters/CreateMeetingParameters.php | 14 +++- tests/unit/BigBlueButtonTest.php | 84 ++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index 131ad623..ac8fb194 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -391,10 +391,22 @@ public function getPresentations(): array public function getModules(): string { $xml = new SimpleXMLElementExtended(''); + // Get empty xml as string + $emptyXML = $xml->asXML(); + + // Add modules $this->addPresentationsModule($xml); $this->addClientSettingsOverrideModule($xml); - return $xml->asXML(); + // Get xml as string after modules have been added + $resultXML = $xml->asXML(); + + // If xml was not modified (no modules added), return an empty string + if ($emptyXML === $resultXML) { + return ''; + } + + return $resultXML; } public function addClientSettingsOverrideModule(SimpleXMLElementExtended $xml): void diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index 9f804c42..e211d8c0 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -227,6 +227,90 @@ public function testCreateMeetingUrl(): void $this->assertUrlContainsAllRequestParameters($url, $params); } + /** + * Test create meeting without modules. + */ + public function testCreate(): void + { + $createMeetingParams = $this->generateCreateParams(); + $params = $this->getCreateMock($createMeetingParams); + + $xml = ' + SUCCESS + '.$params->getMeetingID().' + 1a6938c707cdf5d052958672d66c219c30690c47-1524212045514 + 1453283819419 + '.$params->getVoiceBridge().' + 613-555-1234 + Wed Jan 20 04:56:59 EST 2016 + false + 20 + false + '; + + $this->transport->method('request') + ->with(self::callback(function ($request) { + $payload = $request->getPayload(); + + return $payload === ''; + })) + ->willReturn(new TransportResponse($xml, null)); + + $response = $this->bbb->createMeeting($params); + + $this->assertTrue($response->success()); + $this->assertFalse($response->isDuplicate()); + $this->assertFalse($response->isIdNotUnique()); + } + + /** + * Test create meeting with modules (presentations and clientSettingsOverride). + */ + public function testCreateWithPresentation(): void + { + $createMeetingParams = $this->generateCreateParams(); + $params = $this->getCreateMock($createMeetingParams); + $params->addPresentation('http://test-install.blindsidenetworks.com/default.pdf', null, 'presentation.pdf'); + $params->addPresentation('http://test-install.blindsidenetworks.com/file.pdf'); + $params->setClientSettingsOverride('{ "public": { "app": { "appName": "Test" } } }'); + + $xml = ' + SUCCESS + '.$params->getMeetingID().' + 1a6938c707cdf5d052958672d66c219c30690c47-1524212045514 + 1453283819419 + '.$params->getVoiceBridge().' + 613-555-1234 + Wed Jan 20 04:56:59 EST 2016 + false + 20 + false + '; + + $this->transport->method('request') + ->with(self::callback(function ($request) { + $payload = $request->getPayload(); + $xml = simplexml_load_string($payload); + + $presentations = $xml->module[0]; + $clientSettingsOverride = $xml->module[1]; + + return \count($xml->module) == 2 + && $presentations->attributes()['name']->__toString() == 'presentation' + && $clientSettingsOverride->attributes()['name']->__toString() == 'clientSettingsOverride' + && $presentations->children()[0]->attributes()['url']->__toString() == 'http://test-install.blindsidenetworks.com/default.pdf' + && $presentations->children()[0]->attributes()['filename']->__toString() == 'presentation.pdf' + && $presentations->children()[1]->attributes()['url']->__toString() == 'http://test-install.blindsidenetworks.com/file.pdf'; + })) + ->willReturn(new TransportResponse($xml, null)); + + $response = $this->bbb->createMeeting($params); + + $this->assertTrue($response->success()); + $this->assertFalse($response->isDuplicate()); + $this->assertFalse($response->isIdNotUnique()); + } + /* Join Meeting */ /** From 0178d70c05c2bcf35efbfe57a423e068c6edb15e Mon Sep 17 00:00:00 2001 From: Gregor Kralik Date: Mon, 17 Nov 2025 13:30:55 +0100 Subject: [PATCH 64/68] Fix: mis-spelled userReactions feature (#231) "Update feature enum for BBB 3.0" (littleredbutton/bigbluebutton-api-php#225) introduced new cases for the Feature enum. The BBB feature 'userReactions' was mis-spelled and included as 'userActions' (case USER_ACTIONS). Add the correct USER_REACTIONS case with value 'userReactions'. Keep the wrong USER_ACTIONS case to not break existing (changing its value to userReactions is not possible as PHP enums do not allow duplicate values). See https://docs.bigbluebutton.org/development/api/#updates-to-api-in-bigbluebutton --- src/Enum/Feature.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php index 640f1db9..16c18d72 100644 --- a/src/Enum/Feature.php +++ b/src/Enum/Feature.php @@ -56,7 +56,9 @@ enum Feature: string case REPLY_CHAT_MESSAGE = 'replyChatMessage'; case CHAT_MESSAGE_REACTIONS = 'chatMessageReactions'; case RAISE_HAND = 'raiseHand'; + /** @deprecated BC only. Use Feature::USER_REACTIONS instead. */ case USER_ACTIONS = 'userActions'; + case USER_REACTIONS = 'userReactions'; case CHAT_EMOJI_PICKER = 'chatEmojiPicker'; case QUIZZES = 'quizzes'; } From ccdeb34e369440b3e492a0951028bab0a351e818 Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+SamuelWei@users.noreply.github.com> Date: Wed, 18 Feb 2026 16:53:28 +0100 Subject: [PATCH 65/68] Fix code style --- src/Parameters/BaseParameters.php | 2 +- src/Parameters/CreateMeetingParameters.php | 4 ++-- tests/unit/BigBlueButtonTest.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Parameters/BaseParameters.php b/src/Parameters/BaseParameters.php index 09cb1ff0..6bf144f2 100644 --- a/src/Parameters/BaseParameters.php +++ b/src/Parameters/BaseParameters.php @@ -109,7 +109,7 @@ protected function getProperties(): array protected function getHTTPQueryArray(): array { $properties = $this->getProperties(); - $properties = array_filter($properties, fn ($value) => $value !== null); + $properties = array_filter($properties, static fn ($value) => $value !== null); return array_map(static function ($value) { if (\is_bool($value)) { diff --git a/src/Parameters/CreateMeetingParameters.php b/src/Parameters/CreateMeetingParameters.php index ac8fb194..8e00d7ae 100644 --- a/src/Parameters/CreateMeetingParameters.php +++ b/src/Parameters/CreateMeetingParameters.php @@ -447,14 +447,14 @@ public function getHTTPQuery(): string // Add disabled features if any are set if (!empty($this->disabledFeatures)) { $queries = array_merge($queries, [ - 'disabledFeatures' => implode(',', array_map(fn (Feature $disabledFeature): string => $disabledFeature->value, $this->disabledFeatures)), + 'disabledFeatures' => implode(',', array_map(static fn (Feature $disabledFeature): string => $disabledFeature->value, $this->disabledFeatures)), ]); } // Add disabled features exclude if any are set if (!empty($this->disabledFeaturesExclude)) { $queries = array_merge($queries, [ - 'disabledFeaturesExclude' => implode(',', array_map(fn (Feature $disabledFeatureExclude): string => $disabledFeatureExclude->value, $this->disabledFeaturesExclude)), + 'disabledFeaturesExclude' => implode(',', array_map(static fn (Feature $disabledFeatureExclude): string => $disabledFeatureExclude->value, $this->disabledFeaturesExclude)), ]); } diff --git a/tests/unit/BigBlueButtonTest.php b/tests/unit/BigBlueButtonTest.php index e211d8c0..944639c9 100644 --- a/tests/unit/BigBlueButtonTest.php +++ b/tests/unit/BigBlueButtonTest.php @@ -249,7 +249,7 @@ public function testCreate(): void '; $this->transport->method('request') - ->with(self::callback(function ($request) { + ->with(self::callback(static function ($request) { $payload = $request->getPayload(); return $payload === ''; @@ -288,7 +288,7 @@ public function testCreateWithPresentation(): void '; $this->transport->method('request') - ->with(self::callback(function ($request) { + ->with(self::callback(static function ($request) { $payload = $request->getPayload(); $xml = simplexml_load_string($payload); From 846afb0fff4981bb358485a0373eea9db3bae99f Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+samuelwei@users.noreply.github.com> Date: Fri, 17 Apr 2026 14:04:15 +0000 Subject: [PATCH 66/68] Adjust php-cs-fixer rules to perserve strict_types --- .php-cs-fixer.php | 3 +++ rector.php | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index ccd311ce..93f29942 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -20,6 +20,9 @@ 'increment_style' => false, 'modernize_strpos' => false, 'get_class_to_class_keyword' => false, + 'declare_strict_types' => [ + 'strategy' => 'enforce' + ] ]) ->setRiskyAllowed(true) ->setFinder($finder); diff --git a/rector.php b/rector.php index 8698ee66..814ee5cf 100644 --- a/rector.php +++ b/rector.php @@ -6,7 +6,6 @@ use Rector\DeadCode\Rector\Assign\RemoveUnusedVariableAssignRector; use Rector\DeadCode\Rector\ClassMethod\RemoveUselessParamTagRector; use Rector\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector; -use Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector; use Rector\Privatization\Rector\Class_\FinalizeTestCaseClassRector; use Rector\TypeDeclaration\Rector\ClassMethod\AddVoidReturnTypeWhereNoReturnRector; use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector; From f611762e06d8021770aba412676aa5b595bda5fe Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+samuelwei@users.noreply.github.com> Date: Fri, 17 Apr 2026 16:07:17 +0200 Subject: [PATCH 67/68] Add UNIFIED_LAYOUT case to MeetingLayout enum (#235) --- src/Enum/MeetingLayout.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Enum/MeetingLayout.php b/src/Enum/MeetingLayout.php index a06293c3..b359459d 100644 --- a/src/Enum/MeetingLayout.php +++ b/src/Enum/MeetingLayout.php @@ -27,6 +27,7 @@ */ enum MeetingLayout: string { + case UNIFIED_LAYOUT = 'UNIFIED_LAYOUT'; case CUSTOM_LAYOUT = 'CUSTOM_LAYOUT'; case SMART_LAYOUT = 'SMART_LAYOUT'; case PRESENTATION_FOCUS = 'PRESENTATION_FOCUS'; From dfdd7d1059837ca3dea0e2d866dc0cca07f0387d Mon Sep 17 00:00:00 2001 From: Samuel Weirich <4281791+samuelwei@users.noreply.github.com> Date: Tue, 28 Apr 2026 15:15:29 +0200 Subject: [PATCH 68/68] Add PLUGINS case to Feature enum --- src/Enum/Feature.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Enum/Feature.php b/src/Enum/Feature.php index 16c18d72..05be5571 100644 --- a/src/Enum/Feature.php +++ b/src/Enum/Feature.php @@ -61,4 +61,5 @@ enum Feature: string case USER_REACTIONS = 'userReactions'; case CHAT_EMOJI_PICKER = 'chatEmojiPicker'; case QUIZZES = 'quizzes'; + case PLUGINS = 'plugins'; }