assertEquals(1, EntityTools::mbStrlen('t'));
$this->assertEquals(1, EntityTools::mbStrlen('ั'));
$this->assertEquals(2, EntityTools::mbStrlen('๐'));
$this->assertEquals(4, EntityTools::mbStrlen('๐บ๐ฆ'));
$this->assertEquals('st', EntityTools::mbSubstr('test', 2));
$this->assertEquals('aั', EntityTools::mbSubstr('aัaั', 2));
$this->assertEquals('a๐', EntityTools::mbSubstr('a๐a๐', 3));
$this->assertEquals('๐บ๐ฆ', EntityTools::mbSubstr('๐บ๐ฆ๐บ๐ฆ', 4));
$this->assertEquals(['te', 'st'], EntityTools::mbStrSplit('test', 2));
$this->assertEquals(['aั', 'aั'], EntityTools::mbStrSplit('aัaั', 2));
$this->assertEquals(['a๐', 'a๐'], EntityTools::mbStrSplit('a๐a๐', 3));
$this->assertEquals(['๐บ๐ฆ', '๐บ๐ฆ'], EntityTools::mbStrSplit('๐บ๐ฆ๐บ๐ฆ', 4));
}
private static function render(string $message, string $parse_mode): Entities
{
return match ($parse_mode) {
'html' => Entities::fromHtml($message),
'markdown' => Entities::fromMarkdown($message),
};
}
public function testEntities(): void
{
foreach ($this->provideEntities() as $params) {
$this->testEntitiesInner(...$params);
}
}
public function testUnclosed(): void
{
$this->expectExceptionMessage("Found unclosed markdown elements ](");
Entities::fromMarkdown('[');
}
public function testUnclosedLink(): void
{
$this->expectExceptionMessage("Unclosed ) opened @ pos 7!");
Entities::fromMarkdown('[test](https://google.com');
}
public function testUnclosedCode(): void
{
$this->expectExceptionMessage('Unclosed ``` opened @ pos 3!');
Entities::fromMarkdown('```');
}
public function testStandalone(): void
{
$test = Entities::fromMarkdown(']');
$this->assertEmpty($test->entities);
$this->assertSame(']', $test->message);
$test = Entities::fromMarkdown('!!');
$this->assertEmpty($test->entities);
$this->assertSame('!!', $test->message);
$test = Entities::fromMarkdown('|');
$this->assertEmpty($test->entities);
$this->assertSame('|', $test->message);
}
private function testEntitiesInner(string $mode, string $html, string $bare, array $entities, ?string $htmlReverse = null): void
{
$result = self::render(message: $html, parse_mode: $mode);
$this->assertEquals($bare, $result->message);
$this->assertEquals($entities, $result->entities);
if (
!\str_contains($html, 'tg://emoji')
&& !\str_contains($html, '
request(new Request(
"https://api.telegram.org/bot{$token}/sendMessage?".\http_build_query([
'chat_id'=> $dest,
'parse_mode'=> match ($mode) {
'markdown' => 'MarkdownV2',
'html' => 'html'
},
'text' => $html
])
))->getBody()->buffer(), true);
if (!isset($resultApi['result'])) {
throw new AssertionError(\json_encode($resultApi));
}
$entities = $resultApi['result']['entities'] ?? [];
$entities = \array_map(function (array $e): array {
if (isset($e['user'])) {
$e['user'] = ['id' => $e['user']['id']];
}
return $e;
}, $entities);
$this->assertEquals($bare, $resultApi['result']['text']);
$this->assertEquals($entities, $entities);
}
if (\strtolower($mode) === 'html') {
$this->assertEquals(
\trim(\str_replace(['
', ' ', 'mention:'], ['
', ' ', 'tg://user?id='], $htmlReverse ?? $html)),
$result->toHTML(true)
);
$result = self::render(message: EntityTools::htmlEscape($html), parse_mode: $mode);
$this->assertEquals($html, $result->message);
$this->assertNoRelevantEntities($result->entities);
} else {
$result = self::render(message: EntityTools::markdownEscape($html), parse_mode: $mode);
$this->assertEquals($html, $result->message);
$this->assertNoRelevantEntities($result->entities);
$result = self::render(message: "```\n".EntityTools::markdownCodeblockEscape($html)."\n```", parse_mode: $mode);
$this->assertEquals($html, \rtrim($result->message));
$this->assertEquals([['offset' => 0, 'length' => EntityTools::mbStrlen($html), 'language' => '', 'type' => 'pre']], $result->entities);
}
}
private function assertNoRelevantEntities(array $entities): void
{
$entities = \array_filter($entities, static fn (array $e) => !\in_array(
$e['type'],
['url', 'email', 'phone_number', 'mention', 'bot_command'],
true
));
$this->assertEmpty($entities);
}
private function provideEntities(): array
{
return [
[
'html',
'test',
'test',
[
[
'offset' => 0,
'length' => 4,
'type' => 'bold',
],
],
],
[
'html',
'test
test',
"test\ntest",
[
[
'offset' => 0,
'length' => 4,
'type' => 'bold',
],
],
],
[
'html',
'test
test',
"test\ntest",
[
[
'offset' => 0,
'length' => 4,
'type' => 'bold',
],
],
],
[
'html',
'๐บ๐ฆ๐บ๐ฆ',
'๐บ๐ฆ๐บ๐ฆ',
[
[
'offset' => 4,
'length' => 4,
'type' => 'bold',
],
],
],
[
'html',
'testtest ',
'testtest',
[
[
'offset' => 4,
'length' => 4,
'type' => 'bold',
],
],
],
[
'html',
'รจยปtesttest test',
'รจยปtesttest test',
[
[
'offset' => 6,
'length' => 4,
'type' => 'bold',
],
],
],
[
'html',
'test test',
'test test',
[
[
'offset' => 4,
'length' => 5,
'type' => 'bold',
],
],
],
[
'markdown',
'test* test*',
'test test',
[
[
'offset' => 4,
'length' => 5,
'type' => 'bold',
],
],
],
[
'html',
'test
test test
testtest
blockquotehttps://google.com daniil@daniil.it +39398172758722 @daniilgentili
test
testtest
blockquotehttps://google.com daniil@daniil.it +39398172758722 @daniilgentili