diff --git a/CHANGELOG.md b/CHANGELOG.md index a46e2d86..a47bd767 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Get GroupTypeRoles ([PR197](https://github.com/5pm-HDH/churchtools-api/pull/197)) - PHP coding standard ([PR193](https://github.com/5pm-HDH/churchtools-api/pull/193)) - Added new property 'postsEnabled' to the group type model ([PR204](https://github.com/5pm-HDH/churchtools-api/pull/204)) +- Add Note for Group and SongArrangement ([PR216](https://github.com/5pm-HDH/churchtools-api/pull/216)) - Login with Session Cookie ([PR207](https://github.com/5pm-HDH/churchtools-api/pull/207)) ### Changed diff --git a/docs/out/GroupAPI.md b/docs/out/GroupAPI.md index 2394568b..a31076e9 100644 --- a/docs/out/GroupAPI.md +++ b/docs/out/GroupAPI.md @@ -612,4 +612,22 @@ // Output: 0 -``` \ No newline at end of file +``` + +## Group Notes / Comments + +Retrieve all notes: + +(EXAMPLE CODE IS MISSING) + +Create new note: + +(EXAMPLE CODE IS MISSING) + +Update note: + +(EXAMPLE CODE IS MISSING) + +Delete note: + +(EXAMPLE CODE IS MISSING) \ No newline at end of file diff --git a/docs/out/SongAPI.md b/docs/out/SongAPI.md index 572f324d..2425f63f 100644 --- a/docs/out/SongAPI.md +++ b/docs/out/SongAPI.md @@ -201,64 +201,9 @@ ``` -## Retrieve, create and delete comments: - -**Retrieve comments:** - -```php - use CTApi\Models\Events\Song\SongCommentRequest; - - $comments = SongCommentRequest::getForSongArrangement(2); - $comment = $comments[0]; - - var_dump( $comment->getId()); - // Output: 2 - - var_dump( $comment->getDomainId()); - // Output: 3 - - var_dump( $comment->getDomainType()); - // Output: "arrangement" - - var_dump( $comment->getText()); - // Output: "Ich finde den Song super!" - - var_dump( $comment->getMeta()?->getModifiedDate()); - // Output: "2023-12-11 13:06:35" - - var_dump( $comment->getMeta()?->getModifiedPerson()?->getId()); - // Output: 12 - - - $person = $comment->getMeta()?->requestModifiedPerson(); - - var_dump( $person->getFirstName()); - // Output: "David" - - -``` - -**Create comment:** - -```php - use CTApi\Models\Events\Song\SongCommentRequest; - - SongCommentRequest::create(2, "Die Tonart ist super für Sopran."); - -``` - -**Delete comments:** - -```php - use CTApi\Models\Events\Song\SongCommentRequest; - - $comments = SongCommentRequest::getForSongArrangement(2); - $comment = $comments[0]; - - SongCommentRequest::delete($comment->getIdAsInteger()); - -``` +## Create Song-Arrangement Notes +(EXAMPLE CODE IS MISSING) ## Retrieve Data from CCLI diff --git a/docs/src/ressources/GroupAPI.md b/docs/src/ressources/GroupAPI.md index 5b77bd06..ac7019cd 100644 --- a/docs/src/ressources/GroupAPI.md +++ b/docs/src/ressources/GroupAPI.md @@ -26,4 +26,22 @@ ## Group Roles -{{ \CTApi\Test\Unit\Docs\GroupTypeRoleRequestTest.testGetGroupTypeRoleRequest }} \ No newline at end of file +{{ \CTApi\Test\Unit\Docs\GroupTypeRoleRequestTest.testGetGroupTypeRoleRequest }} + +## Group Notes / Comments + +Retrieve all notes: + +{{ \CTApi\Test\Unit\Docs\NoteRequest.testRequestNotes }} + +Create new note: + +{{ \CTApi\Test\Unit\Docs\NoteRequest.testCreateNote }} + +Update note: + +{{ \CTApi\Test\Unit\Docs\NoteRequest.testUpdateNote }} + +Delete note: + +{{ \CTApi\Test\Unit\Docs\NoteRequest.testDeleteNote }} \ No newline at end of file diff --git a/docs/src/ressources/SongAPI.md b/docs/src/ressources/SongAPI.md index b1042cde..b3f7b42f 100644 --- a/docs/src/ressources/SongAPI.md +++ b/docs/src/ressources/SongAPI.md @@ -16,20 +16,9 @@ {{ \CTApi\Test\Unit\Docs\SongRequestTest.testUpdateArrangement }} -## Retrieve, create and delete comments: - -**Retrieve comments:** - -{{ \CTApi\Test\Unit\Docs\SongCommentRequestTest.testGetAllComments }} - -**Create comment:** - -{{ \CTApi\Test\Unit\Docs\SongCommentRequestTest.testCreateComments }} - -**Delete comments:** - -{{ \CTApi\Test\Unit\Docs\SongCommentRequestTest.testDeleteComments }} +## Create Song-Arrangement Notes +{{ \CTApi\Test\Unit\Docs\NoteRequest.testUpdateSongArrangementNotes }} ## Retrieve Data from CCLI diff --git a/src/Models/Common/Note/Note.php b/src/Models/Common/Note/Note.php new file mode 100644 index 00000000..bc15fe67 --- /dev/null +++ b/src/Models/Common/Note/Note.php @@ -0,0 +1,66 @@ +setMeta(Meta::createModelFromData($data)); + break; + } + } + + public function setId(?string $id): Note + { + $this->id = $id; + return $this; + } + + public function getDomainId(): ?string + { + return $this->domainId; + } + + public function setDomainId(?string $domainId): Note + { + $this->domainId = $domainId; + return $this; + } + + public function getDomainType(): ?string + { + return $this->domainType; + } + + public function setDomainType(?string $domainType): Note + { + $this->domainType = $domainType; + return $this; + } + + public function getText(): ?string + { + return $this->text; + } + + public function setText(?string $text): Note + { + $this->text = $text; + return $this; + } +} diff --git a/src/Models/Common/Note/NoteRequest.php b/src/Models/Common/Note/NoteRequest.php new file mode 100644 index 00000000..a833e596 --- /dev/null +++ b/src/Models/Common/Note/NoteRequest.php @@ -0,0 +1,16 @@ +domainType . "/" . $this->domainIdentifier; + } + + + /** + * @return Note[] + */ + public function get(): array + { + $ctClient = CTClient::getClient(); + $response = $ctClient->get($this->getApiEndpoint()); + $data = CTResponseUtil::dataAsArray($response); + if (empty($data)) { + return []; + } else { + return Note::createModelsFromArray($data); + } + } + + public function delete(int $noteId): void + { + $ctClient = CTClient::getClient(); + $ctClient->delete($this->getApiEndpoint() . "/" . $noteId); + } + + public function create(string $text, ?int $securityLevelId = null): ?Note + { + $ctClient = CTClient::getClient(); + $response = $ctClient->post($this->getApiEndpoint(), [ + "json" => [ + "domainId" => "" . $this->domainIdentifier, + "domainType" => $this->domainType, + "securityLevelId" => $securityLevelId, + "text" => $text, + ] + ]); + + $data = CTResponseUtil::dataAsArray($response); + if (empty($data)) { + return null; + } else { + return Note::createModelFromData($data); + } + } + + public function update(int $noteId, string $text, ?int $securityLevelId = null): ?Note + { + $ctClient = CTClient::getClient(); + $response = $ctClient->put($this->getApiEndpoint() . '/' . $noteId, [ + "json" => [ + "text" => $text, + "securityLevelId" => $securityLevelId, + ] + ]); + + $data = CTResponseUtil::dataAsArray($response); + if (empty($data)) { + return null; + } else { + return Note::createModelFromData($data); + } + } +} diff --git a/src/Models/Events/Song/SongComment.php b/src/Models/Events/Song/SongComment.php index 184c44bd..63487579 100644 --- a/src/Models/Events/Song/SongComment.php +++ b/src/Models/Events/Song/SongComment.php @@ -6,15 +6,19 @@ use CTApi\Models\Common\Domain\Meta; use CTApi\Models\Groups\Person\Person; use CTApi\Traits\Model\FillWithData; +use CTApi\Traits\Model\MetaAttribute; +/** + * @deprecated Use Note instead. This class will be removed in the next major-release v3. + */ class SongComment extends AbstractModel { use FillWithData; + use MetaAttribute; private ?string $domainId = null; private ?string $domainType = null; private ?string $text = null; - private ?Meta $meta = null; protected function fillNonArrayType(string $key, $value): void { @@ -42,6 +46,17 @@ protected function fillNonArrayType(string $key, $value): void } } + protected function fillArrayType(string $key, array $data): void + { + switch ($key) { + case "meta": + $this->meta = Meta::createModelFromData($data); + break; + default: + $this->fillDefault($key, $data); + } + } + public function getDomainId(): ?string { return $this->domainId; diff --git a/src/Models/Events/Song/SongCommentRequest.php b/src/Models/Events/Song/SongCommentRequest.php index 7592f659..4faf7334 100644 --- a/src/Models/Events/Song/SongCommentRequest.php +++ b/src/Models/Events/Song/SongCommentRequest.php @@ -2,6 +2,9 @@ namespace CTApi\Models\Events\Song; +/** + * @deprecated Use NoteRequest::forSongArrangement() instead. This class will be removed in the next major-release v3. + */ class SongCommentRequest { public static function getForSongArrangement(int $arrangementId): array diff --git a/src/Models/Events/Song/SongCommentRequestBuilder.php b/src/Models/Events/Song/SongCommentRequestBuilder.php index ff4002be..08081585 100644 --- a/src/Models/Events/Song/SongCommentRequestBuilder.php +++ b/src/Models/Events/Song/SongCommentRequestBuilder.php @@ -2,9 +2,14 @@ namespace CTApi\Models\Events\Song; +use CTApi\CTClient; +use CTApi\Models\Common\Note\NoteRequest; use CTApi\Traits\Request\AjaxApi; use CTApi\Utils\CTResponseUtil; +/** + * @deprecated Use NoteRequest::forSongArrangement() instead. This class will be removed in the next major-release v3. + */ class SongCommentRequestBuilder { use AjaxApi; @@ -16,29 +21,23 @@ public function __construct( public function getComments() { - $response = $this->requestAjax("churchservice/ajax", "getComments", [ - "domain_type" => "arrangement", - "domain_id" => $this->arrangementId - ]); - + $ctClient = CTClient::getClient(); + $response = $ctClient->get("/api/notes/song_arrangement/" . $this->arrangementId); $data = CTResponseUtil::dataAsArray($response); - return SongComment::createModelsFromArray(array_values($data)); + if (empty($data)) { + return []; + } else { + return SongComment::createModelsFromArray($data); + } } public function createComment(string $text): void { - $this->requestAjax("churchservice/ajax", "addComment", [ - "domain_type" => "arrangement", - "domain_id" => $this->arrangementId, - "text" => $text - ]); + NoteRequest::forSongArrangement($this->arrangementId)->create($text); } public function deleteComment(int $commentId): void { - $this->requestAjax("churchservice/ajax", "delComment", [ - "id" => $commentId, - ]); + NoteRequest::forSongArrangement($this->arrangementId)->delete($commentId); } - } diff --git a/tests/Integration/Requests/NoteRequestTest.php b/tests/Integration/Requests/NoteRequestTest.php new file mode 100644 index 00000000..ef5b1d44 --- /dev/null +++ b/tests/Integration/Requests/NoteRequestTest.php @@ -0,0 +1,66 @@ +get(); + foreach($notes as $note) { + NoteRequest::forGroup($groupId)->delete($note->getIdAsInteger()); + } + + $notes = NoteRequest::forGroup($groupId)->get(); + $this->assertEmpty($notes); + + // Add one note + $note = NoteRequest::forGroup($groupId)->create("Hello new comment!"); + $this->assertEquals("Hello new comment!", $note->getText()); + + $noteUpdate = NoteRequest::forGroup($groupId)->update($note->getIdAsInteger(), "Hello comment!"); + $this->assertEquals("Hello comment!", $noteUpdate->getText()); + + // Check if note is present + $notes = NoteRequest::forGroup($groupId)->get(); + $this->assertEquals(1, sizeof($notes)); + $firstNote = end($notes); + + $this->assertEquals("Hello comment!", $firstNote->getText()); + } + + public function testForSongArrangement() + { + // Remove all notes from group + $songArrangementId = IntegrationTestData::getFilterAsInt("create_and_delete_song_comments", "song_arrangement_id"); + + $notes = NoteRequest::forSongArrangement($songArrangementId)->get(); + foreach($notes as $note) { + NoteRequest::forSongArrangement($songArrangementId)->delete($note->getIdAsInteger()); + } + + $notes = NoteRequest::forSongArrangement($songArrangementId)->get(); + $this->assertEmpty($notes); + + // Add one note + $note = NoteRequest::forSongArrangement($songArrangementId)->create("Hello new comment!"); + $this->assertEquals("Hello new comment!", $note->getText()); + + // Check if note is present + $notes = NoteRequest::forSongArrangement($songArrangementId)->get(); + $this->assertEquals(1, sizeof($notes)); + $firstNote = end($notes); + + $this->assertEquals("Hello new comment!", $firstNote->getText()); + } + +} diff --git a/tests/Integration/integration-test-data.json b/tests/Integration/integration-test-data.json index f1e85653..9923a323 100644 --- a/tests/Integration/integration-test-data.json +++ b/tests/Integration/integration-test-data.json @@ -202,6 +202,12 @@ } } }, + "group_note": { + "description": "Add and remove note from group. All notes from group are removed.", + "filter": { + "group_id": 17 + } + }, "load_public_group": { "description": "PublicGroup to register on homepage", "filter": { @@ -307,10 +313,10 @@ }, "result": { "any_comment": { - "id": 2, + "id": 179, "text": "Ich finde den Song super!", - "modified_date": "2023-12-11 13:06:35", - "modified_person_id": 1 + "modified_date": "2024-07-31T10:09:27Z", + "modified_person_id": 12 } } }, diff --git a/tests/Unit/Docs/NoteRequestTest.php b/tests/Unit/Docs/NoteRequestTest.php new file mode 100644 index 00000000..28e59bf1 --- /dev/null +++ b/tests/Unit/Docs/NoteRequestTest.php @@ -0,0 +1,54 @@ +get(); + $this->assertEquals("Hello new comment!", $notes[0]->getText()); + $this->assertEquals("17", $notes[0]->getDomainId()); + $this->assertEquals("group", $notes[0]->getDomainType()); + $this->assertEquals("212", $notes[0]->getId()); + } + + public function testCreateNote() + { + $note = NoteRequest::forGroup(52)->create("Add new comment."); + $this->assertEquals("Add new comment.", $note->getText()); + } + + public function testUpdateNote() + { + $note = NoteRequest::forGroup(52)->update(25, "Updated comment."); + $this->assertEquals("Updated comment.", $note->getText()); + } + + /** + * @doesNotPerformAssertions + */ + public function testDeleteNote() + { + NoteRequest::forGroup(52)->delete(25); + } + + public function testUpdateSongArrangementNotes() + { + $notes = NoteRequest::forSongArrangement(21)->get(); + + $this->assertEquals("Hello new comment!", $notes[0]->getText()); + $this->assertEquals("17", $notes[0]->getDomainId()); + $this->assertEquals("group", $notes[0]->getDomainType()); + $this->assertEquals("212", $notes[0]->getId()); + + $securityLevelId = 2; + $note = NoteRequest::forSongArrangement(21)->create("New comment", $securityLevelId); + $note = NoteRequest::forSongArrangement(21)->update(2, "New comment"); + + NoteRequest::forSongArrangement(21)->delete(2); + } +} diff --git a/tests/Unit/Docs/SongCommentRequestTest.php b/tests/Unit/Docs/SongCommentRequestTest.php deleted file mode 100644 index ba0f1cf4..00000000 --- a/tests/Unit/Docs/SongCommentRequestTest.php +++ /dev/null @@ -1,48 +0,0 @@ -assertEquals(2, $comment->getId()); - $this->assertEquals(3, $comment->getDomainId()); - $this->assertEquals("arrangement", $comment->getDomainType()); - $this->assertEquals("Ich finde den Song super!", $comment->getText()); - $this->assertEquals("2023-12-11 13:06:35", $comment->getMeta()?->getModifiedDate()); - $this->assertEquals(12, $comment->getMeta()?->getModifiedPerson()?->getId()); - - $person = $comment->getMeta()?->requestModifiedPerson(); - - $this->assertEquals("David", $person->getFirstName()); - } - - /** - * @return void - * @doesNotPerformAssertions - */ - public function testCreateComments() - { - SongCommentRequest::create(2, "Die Tonart ist super für Sopran."); - } - - /** - * @return void - * @doesNotPerformAssertions - */ - public function testDeleteComments() - { - $comments = SongCommentRequest::getForSongArrangement(2); - $comment = $comments[0]; - - SongCommentRequest::delete($comment->getIdAsInteger()); - } - -} diff --git a/tests/Unit/HttpMock/data/POST_api_notes_group_52.json b/tests/Unit/HttpMock/data/POST_api_notes_group_52.json new file mode 100644 index 00000000..223f9e09 --- /dev/null +++ b/tests/Unit/HttpMock/data/POST_api_notes_group_52.json @@ -0,0 +1,24 @@ +{ + "data": + { + "id": 212, + "domainType": "group", + "domainId": 17, + "securityLevelId": null, + "text": "Add new comment.", + "meta": { + "createdDate": "2024-07-31T13:44:52Z", + "createdPerson": { + "id": 12 + }, + "modifiedDate": "2024-07-31T13:44:52Z", + "modifiedPerson": { + "id": 12 + } + } + } + , + "meta": { + "count": 1 + } +} \ No newline at end of file diff --git a/tests/Unit/HttpMock/data/POST_index.php_q=churchservice_ajax_func=getcomments.json b/tests/Unit/HttpMock/data/POST_index.php_q=churchservice_ajax_func=getcomments.json index 1bb93553..bc0b143d 100644 --- a/tests/Unit/HttpMock/data/POST_index.php_q=churchservice_ajax_func=getcomments.json +++ b/tests/Unit/HttpMock/data/POST_index.php_q=churchservice_ajax_func=getcomments.json @@ -3,7 +3,7 @@ "data": { "2": { "id": "2", - "domain_type": "arrangement", + "domain_type": "song_arrangement", "domain_id": "3", "securitylevel_id": null, "text": "Ich finde den Song super!", diff --git a/tests/Unit/HttpMock/data/PUT_api_notes_group_52_25.json b/tests/Unit/HttpMock/data/PUT_api_notes_group_52_25.json new file mode 100644 index 00000000..35965e0e --- /dev/null +++ b/tests/Unit/HttpMock/data/PUT_api_notes_group_52_25.json @@ -0,0 +1,24 @@ +{ + "data": + { + "id": 212, + "domainType": "group", + "domainId": 17, + "securityLevelId": null, + "text": "Updated comment.", + "meta": { + "createdDate": "2024-07-31T13:44:52Z", + "createdPerson": { + "id": 12 + }, + "modifiedDate": "2024-07-31T13:44:52Z", + "modifiedPerson": { + "id": 12 + } + } + } + , + "meta": { + "count": 1 + } +} \ No newline at end of file diff --git a/tests/Unit/HttpMock/data/api_notes_group_212.json b/tests/Unit/HttpMock/data/api_notes_group_212.json new file mode 100644 index 00000000..63ff1129 --- /dev/null +++ b/tests/Unit/HttpMock/data/api_notes_group_212.json @@ -0,0 +1,24 @@ +{ + "data": [ + { + "id": 212, + "domainType": "group", + "domainId": 17, + "securityLevelId": null, + "text": "Hello new comment!", + "meta": { + "createdDate": "2024-07-31T13:44:52Z", + "createdPerson": { + "id": 12 + }, + "modifiedDate": "2024-07-31T13:44:52Z", + "modifiedPerson": { + "id": 12 + } + } + } + ], + "meta": { + "count": 1 + } +} \ No newline at end of file diff --git a/tests/Unit/HttpMock/data/api_notes_song_arrangement_21.json b/tests/Unit/HttpMock/data/api_notes_song_arrangement_21.json new file mode 100644 index 00000000..63ff1129 --- /dev/null +++ b/tests/Unit/HttpMock/data/api_notes_song_arrangement_21.json @@ -0,0 +1,24 @@ +{ + "data": [ + { + "id": 212, + "domainType": "group", + "domainId": 17, + "securityLevelId": null, + "text": "Hello new comment!", + "meta": { + "createdDate": "2024-07-31T13:44:52Z", + "createdPerson": { + "id": 12 + }, + "modifiedDate": "2024-07-31T13:44:52Z", + "modifiedPerson": { + "id": 12 + } + } + } + ], + "meta": { + "count": 1 + } +} \ No newline at end of file