From 29ee7babb1a5ba921a8f7fc6ce4bdfae2b726805 Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Thu, 2 Jan 2025 13:52:38 +0100 Subject: [PATCH] can add tags, remove tags and persist this in subscriber entity --- src/Entities/Subscriber.php | 67 +++++++++++++--- src/Resources/Subscriber.php | 10 ++- tests/unit/Entities/SubscriberTest.php | 107 ++++++++++++++++++++++++- 3 files changed, 170 insertions(+), 14 deletions(-) diff --git a/src/Entities/Subscriber.php b/src/Entities/Subscriber.php index ac206fb..ac17145 100644 --- a/src/Entities/Subscriber.php +++ b/src/Entities/Subscriber.php @@ -123,9 +123,6 @@ class Subscriber extends ArrayCollection return $this->get('sms_phone'); } - /** - * @throws BaseException - */ public function setSmsPhone(string $smsPhone): void { $this->set('sms_phone', $smsPhone); @@ -172,9 +169,6 @@ class Subscriber extends ArrayCollection return $this->getFields()->get($this->getFieldLongName($fieldId)); } - /** - * @throws BaseException - */ public function setField(string $fieldId, string $value): void { $this->set($this->getFieldLongName($fieldId), $value); @@ -197,6 +191,33 @@ class Subscriber extends ArrayCollection return $this->getTags()->contains($tagId); } + public function clearTags(): void + { + $tags = $this->getTags(); + $tags->clear(); + $this->set('tags', $tags->toArray()); + + // use persist method to send to Klicktipp + } + + public function addTag(string $tagId): void + { + $tags = $this->getTags(); + $tags->add($tagId); + $this->set('tags', $tags->toArray()); + + // use persist method to send to Klicktipp + } + + public function removeTag(string $tagId): void + { + $tags = $this->getTags(); + $tags->removeElement($tagId); + $this->set('tags', $tags->toArray()); + + // use persist method to send to Klicktipp + } + /** * manuelle Tags */ @@ -292,17 +313,45 @@ class Subscriber extends ArrayCollection } /** - * @return bool + * @return ?bool * @throws BaseException */ - public function persist(): bool + public function persist(): ?bool { - return $this->endpoint?->update( + $return = $this->endpoint?->update( $this->getId(), $this->getFields()->toArray(), $this->getEmailAddress(), $this->getSmsPhone() ); + + $this->persistTags(); + + return $return; + } + + /** + * @throws BaseException + */ + protected function persistTags(): void + { + if (!$this->endpoint instanceof SubscriberEndpoint) { + return; + } + + $currentTags = $this->endpoint->get( $this->getId() )->getTags(); + + $removeTags = array_diff( $currentTags->toArray(), $this->getTags()->toArray() ); + if ( count( $removeTags ) ) { + foreach ( $removeTags as $removeTag ) { + $this->endpoint->untag( $this->getEmailAddress(), $removeTag ); + } + } + + $addTags = array_diff( $this->getTags()->toArray(), $currentTags->toArray() ); + if ( count( $addTags ) ) { + $this->endpoint->tag( $this->getEmailAddress(), array_diff( $this->getTags()->toArray(), $currentTags->toArray() ) ); + } } protected function getDateTimeFromValue($value): ?DateTime diff --git a/src/Resources/Subscriber.php b/src/Resources/Subscriber.php index 741ce95..0c7e068 100644 --- a/src/Resources/Subscriber.php +++ b/src/Resources/Subscriber.php @@ -117,11 +117,12 @@ class Subscriber extends Model } /** + * add tag * @throws BaseException */ - public function tag(string $mailAddress, array $tagIds): string + public function tag(string $mailAddress, array $tagIds): bool { - return current( + return (bool) current( $this->connection->requestAndParse( 'POST', 'subscriber/tag.json', @@ -138,11 +139,12 @@ class Subscriber extends Model } /** + * remove tag * @throws BaseException */ - public function untag(string $mailAddress, string $tagId): string + public function untag(string $mailAddress, string $tagId): bool { - return current( + return (bool) current( $this->connection->requestAndParse( 'POST', 'subscriber/untag.json', diff --git a/tests/unit/Entities/SubscriberTest.php b/tests/unit/Entities/SubscriberTest.php index ee4a37d..a9578b6 100644 --- a/tests/unit/Entities/SubscriberTest.php +++ b/tests/unit/Entities/SubscriberTest.php @@ -523,6 +523,59 @@ class SubscriberTest extends TestCase yield 'missing tag' => ['12495463', false]; } + /** + * @test + * @return void + * @covers \D3\KlicktippPhpClient\Entities\Subscriber::clearTags + * @throws ReflectionException + */ + public function testClearTags(): void + { + $this->callMethod( + $this->entity, + 'clearTags' + ); + + $this->assertCount(0, $this->callMethod($this->entity, 'getTags')); + } + + /** + * @test + * @return void + * @covers \D3\KlicktippPhpClient\Entities\Subscriber::addTag + * @throws ReflectionException + */ + public function testAddTag(): void + { + $this->callMethod( + $this->entity, + 'addTag', + ['78546214'] + ); + + $this->assertCount(3, $this->callMethod($this->entity, 'getTags')); + $this->assertContains('78546214', $this->callMethod($this->entity, 'getTags')); + } + + /** + * @test + * @return void + * @covers \D3\KlicktippPhpClient\Entities\Subscriber::removeTag + * @throws ReflectionException + */ + public function testRemoveTag(): void + { + $this->callMethod( + $this->entity, + 'removeTag', + ['12494453'] + ); + + $this->assertCount(1, $this->callMethod($this->entity, 'getTags')); + $this->assertContains('12494463', $this->callMethod($this->entity, 'getTags')); + $this->assertNotContains('12494453', $this->callMethod($this->entity, 'getTags')); + } + /** * @test * @throws ReflectionException @@ -540,7 +593,11 @@ class SubscriberTest extends TestCase ->getMock(); $endpointMock->expects($endpointInvocation)->method('update')->willReturn(true); - $sut = new Subscriber(['id' => 'foo'], $endpointSet ? $endpointMock : null); + $sut = $this->getMockBuilder(Subscriber::class) + ->setConstructorArgs([['id' => 'foo'], $endpointSet ? $endpointMock : null]) + ->onlyMethods(['persistTags']) + ->getMock(); + $sut->expects($this->once())->method('persistTags'); $this->assertSame( $expectedReturn, @@ -557,6 +614,54 @@ class SubscriberTest extends TestCase yield 'has no endpoint' => [false, self::never(), null]; } + /** + * @test + * @throws ReflectionException + * @covers \D3\KlicktippPhpClient\Entities\Subscriber::persistTags + * @dataProvider persistTagsDataProvider + */ + public function testPersistTags( + bool $endpointSet, + InvokedCount $endpointInvocation, + ?array $newTagList, + InvokedCount $removeTagInvocation, + InvokedCount $setTagInvocation + ) + { + $entityMock = $this->getMockBuilder(Subscriber::class) + ->disableOriginalConstructor() + ->onlyMethods(['getTags']) + ->getMock(); + $entityMock->method('getTags')->willReturn(new ArrayCollection([ + "12494453", + "12494463", + ])); + + $endpointMock = $this->getMockBuilder(\D3\KlicktippPhpClient\Resources\Subscriber::class) + ->disableOriginalConstructor() + ->onlyMethods(['get', 'tag', 'untag']) + ->getMock(); + $endpointMock->expects($endpointInvocation)->method('get')->willReturn($entityMock); + $endpointMock->expects($setTagInvocation)->method('tag')->willReturn(true); + $endpointMock->expects($removeTagInvocation)->method('untag')->willReturn(true); + + $sut = new Subscriber(['id' => 'foo', 'email' => 'mymail@mydomain.tld'], $endpointSet ? $endpointMock : null); + if ($newTagList) $sut->set('tags', $newTagList); + + $this->callMethod( + $sut, + 'persistTags' + ); + } + + public static function persistTagsDataProvider(): Generator + { + yield 'has endpoint, tag removed' => [true, self::once(), ["12494453"], self::once(), self::never()]; + yield 'has endpoint, tag added' => [true, self::once(), ["12494453","12494463","12494464"], self::never(), self::once()]; + yield 'has endpoint, taglist equals' => [true, self::once(), ["12494453","12494463"], self::never(), self::never()]; + yield 'has no endpoint' => [false, self::never(), null, self::never(), self::never()]; + } + /** * @test * @throws ReflectionException