Skip to content

Commit

Permalink
Merge branch 'labels' into post-builder
Browse files Browse the repository at this point in the history
Merged the 'labels' feature branch into 'post-builder', which implements the `SelfLabels` lexicon.
  • Loading branch information
shahmal1yev committed Oct 13, 2024
2 parents 74d77a9 + b21eb13 commit 28a0544
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/Contracts/Lexicons/App/Bsky/Feed/PostBuilderContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Atproto\Contracts\LexiconBuilder;
use Atproto\Contracts\Lexicons\App\Bsky\Embed\EmbedInterface;
use Atproto\Contracts\Stringable;
use Atproto\Lexicons\Com\Atproto\Label\SelfLabels;
use Atproto\Lexicons\Com\Atproto\Repo\StrongRef;
use DateTimeImmutable;

Expand All @@ -25,4 +26,6 @@ public function embed(EmbedInterface $embed): PostBuilderContract;
public function reply(StrongRef $root, StrongRef $parent): PostBuilderContract;

public function langs(array $languages): PostBuilderContract;

public function labels(SelfLabels $labels): PostBuilderContract;
}
11 changes: 11 additions & 0 deletions src/Lexicons/App/Bsky/Feed/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Atproto\Lexicons\App\Bsky\RichText\Facet;
use Atproto\Lexicons\App\Bsky\RichText\FeatureAbstract;
use Atproto\Lexicons\App\Bsky\RichText\FeatureFactory;
use Atproto\Lexicons\Com\Atproto\Label\SelfLabels;
use Atproto\Lexicons\Com\Atproto\Repo\StrongRef;
use Carbon\Carbon;
use DateTimeImmutable;
Expand All @@ -26,6 +27,8 @@ class Post implements PostBuilderContract
private ?EmbedInterface $embed = null;
private ?array $reply = null;
private ?array $languages = null;
private ?SelfLabels $labels = null;


public function __construct()
{
Expand Down Expand Up @@ -120,6 +123,13 @@ public function langs(array $languages): PostBuilderContract
return $this;
}

public function labels(SelfLabels $labels): PostBuilderContract
{
$this->labels = $labels;

return $this;
}

/**
* Validates the format of a language code.
*
Expand Down Expand Up @@ -165,6 +175,7 @@ public function jsonSerialize(): array
'embed' => $this->embed,
'replyRef' => $this->reply,
'langs' => $this->languages,
'labels' => $this->labels
]);
}

Expand Down
74 changes: 74 additions & 0 deletions src/Lexicons/Com/Atproto/Label/SelfLabels.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace Atproto\Lexicons\Com\Atproto\Label;

use Atproto\Contracts\Stringable;
use Atproto\Exceptions\InvalidArgumentException;
use GenericCollection\GenericCollection;
use JsonSerializable;

class SelfLabels extends GenericCollection implements JsonSerializable, Stringable
{
private const MAXLENGTH = 10;
private const MAXLENGTH_BY_ITEM = 128;

/**
* @throws InvalidArgumentException
*/
public function __construct(iterable $collection = [])
{
$this->collection = $collection;

try {
parent::__construct($this->validator(), $collection);
} catch (\TypeError|\GenericCollection\Exceptions\InvalidArgumentException $e) {
$this->throw($e);
}
}

private function validator(): \Closure
{
return function (string $val): bool {
if ($this->count() + 1 > self::MAXLENGTH) {
throw new InvalidArgumentException("Maximum allowed length is " . self::MAXLENGTH);
}

if (strlen($val) > self::MAXLENGTH_BY_ITEM) {
throw new InvalidArgumentException("Length exceeded for $val. Max ".self::MAXLENGTH_BY_ITEM." characters allowed.");
}

return true;
};
}

/**
* @throws InvalidArgumentException
*/
private function throw($exception): void
{
throw new InvalidArgumentException(
str_replace(
"::".__NAMESPACE__."\{closure}()",
"",
$exception->getMessage()
),
0,
$exception
);
}

public function __toString(): string
{
return json_encode($this);
}

public function jsonSerialize()
{
return $this->toArray();
}

public function toArray(): array
{
return array_map(fn (string $val) => ['val' => $val], $this->collection);
}
}
23 changes: 23 additions & 0 deletions tests/Unit/Lexicons/App/Bsky/Feed/PostTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Atproto\Lexicons\App\Bsky\Feed\Post;
use Atproto\Lexicons\App\Bsky\RichText\FeatureAbstract;
use Atproto\Lexicons\App\Bsky\RichText\Mention;
use Atproto\Lexicons\Com\Atproto\Label\SelfLabels;
use Atproto\Lexicons\Com\Atproto\Repo\StrongRef;
use Carbon\Carbon;
use DateTimeImmutable;
Expand Down Expand Up @@ -213,6 +214,23 @@ public function testLangsMethodThrowsExceptionOnInvalidLanguageCode()
$this->post->langs(['en', 'd']);
}

/**
* @throws InvalidArgumentException
*/
public function testLabelsMethod(): void
{
$labels = new SelfLabels(['v 1', 'v 2', 'v 3']);

$this->post->labels($labels);

$result = json_decode($this->post, true);
$this->assertArrayHasKey('labels', $result);
$this->assertEquals([
['val' => 'v 1'],
['val' => 'v 2'],
['val' => 'v 3'],
], $result['labels']);
}

/**
* @throws InvalidArgumentException
Expand All @@ -226,6 +244,10 @@ public function testJsonSerialize()
$sRef = new StrongRef('foo', 'bar');
$this->post->reply($sRef, clone $sRef);
$this->post->langs(['en', 'fr', 'es']);
$this->post->labels(new SelfLabels([
'val 1',
'val 2'
]));

$result = $this->post->jsonSerialize();
$this->assertArrayHasKey('$type', $result);
Expand All @@ -236,6 +258,7 @@ public function testJsonSerialize()
$this->assertArrayHasKey('embed', $result);
$this->assertArrayHasKey('replyRef', $result);
$this->assertArrayHasKey('langs', $result);
$this->assertArrayHasKey('labels', $result);
}

public function testConstructorWorksCorrectlyOnDirectBuild()
Expand Down
73 changes: 73 additions & 0 deletions tests/Unit/Lexicons/Com/Atproto/Label/SelfLabelsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace Tests\Unit\Lexicons\Com\Atproto\Label;

use Atproto\Exceptions\InvalidArgumentException;
use Atproto\Lexicons\Com\Atproto\Label\SelfLabels;
use PHPUnit\Framework\TestCase;
use stdClass;

class SelfLabelsTest extends TestCase
{
private SelfLabels $selfLabels;
private int $maxlength = 10;
private int $maxlengthByItem = 128;

public function setUp(): void
{
$this->selfLabels = new SelfLabels();
}

/**
* @throws InvalidArgumentException
*/
public function test__constructFillsDataCorrectly(): void
{
$expected = array_map(fn (string $val) => ['val' => $val], ['val 1', 'val 2', 'val 3']);

$this->selfLabels = new SelfLabels(array_column(
$expected,
'val'
));

$this->assertEquals($expected, $this->selfLabels->toArray());
}

public function test__constructorThrowsInvalidArgumentExceptionWhenPassedInvalidArgument(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("must be of the type string");

$this->selfLabels = new SelfLabels(['val 1', new stdClass()]);
}

public function test__constructThrowsInvalidArgumentExceptionWhenLimitExceeded(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("Maximum allowed length is ".$this->maxlength);

$trigger = str_split(str_pad('', ++$this->maxlength, 'a'));
$this->selfLabels = new SelfLabels($trigger);
}

public function test__constructorThrowsExceptionWhenPassedArgumentThatExceedsLimit(): void
{
$trigger = [str_pad('', ++$this->maxlengthByItem, 'a')];
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("Length exceeded for " . current($trigger));

$this->selfLabels = new SelfLabels($trigger);
}

public function testAddThrowsExceptionWhenPassedArgumentExceedsMaxLengthLimit(): void
{
$trigger = str_split(str_pad('', ++$this->maxlength, 'a'));

$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("Maximum allowed length is ".--$this->maxlength);

foreach($trigger as $item) {
$this->selfLabels[] = $item;
}
}
}

0 comments on commit 28a0544

Please sign in to comment.