From 97d016055f4701e9b1cdd7f3e40bb5aae6df2048 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 5 Aug 2025 18:11:34 +0300 Subject: [PATCH] =?UTF-8?q?fix=20#2=20Error:=20Cannot=20instantiate=20abst?= =?UTF-8?q?ract=20class=20AbstractAttachment=20=D0=BF=D0=BE=D1=81=D0=BB?= =?UTF-8?q?=D0=B5=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BD=D0=BE=D0=BC=D0=B5=D1=80=D0=B0=20=D1=82=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D1=84=D0=BE=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 9 +-- src/Enums/AttachmentType.php | 2 +- src/ModelFactory.php | 70 ++++++++++------- .../Attachments/InlineKeyboardAttachment.php | 3 +- .../Attachments/Payloads/PhotoToken.php | 6 +- .../ReplyKeyboardAttachmentRequestPayload.php | 2 - .../UploadedInfoAttachmentRequestPayload.php | 37 +++++---- .../Attachments/ReplyKeyboardAttachment.php | 3 +- src/Models/MessageBody.php | 3 - tests/Models/MessageBodyTest.php | 76 +++++++++++++++++++ 10 files changed, 149 insertions(+), 62 deletions(-) diff --git a/.gitattributes b/.gitattributes index 83ebb44..ead320a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,4 @@ -/.gitattributes export-ignore -/.gitignore export-ignore -/.github export-ignore -/phpunit.xml export-ignore -/tests export-ignore +/.* export-ignore +/phpunit.xml export-ignore +/phpstan.neon export-ignore +/tests export-ignore diff --git a/src/Enums/AttachmentType.php b/src/Enums/AttachmentType.php index 4d7d301..4e3d35d 100644 --- a/src/Enums/AttachmentType.php +++ b/src/Enums/AttachmentType.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace BushlanovDev\MaxMessengerBot\Enums; -enum AttachmentType: string +enum AttachmentType: string { case Image = 'image'; case Video = 'video'; diff --git a/src/ModelFactory.php b/src/ModelFactory.php index 9a9c1cc..5af3988 100644 --- a/src/ModelFactory.php +++ b/src/ModelFactory.php @@ -47,6 +47,7 @@ use BushlanovDev\MaxMessengerBot\Models\Markup\StrongMarkup; use BushlanovDev\MaxMessengerBot\Models\Markup\UnderlineMarkup; use BushlanovDev\MaxMessengerBot\Models\Markup\UserMentionMarkup; use BushlanovDev\MaxMessengerBot\Models\Message; +use BushlanovDev\MaxMessengerBot\Models\MessageBody; use BushlanovDev\MaxMessengerBot\Models\Result; use BushlanovDev\MaxMessengerBot\Models\Subscription; use BushlanovDev\MaxMessengerBot\Models\UpdateList; @@ -136,23 +137,54 @@ class ModelFactory */ public function createMessage(array $data): Message { - if (isset($data['body']['attachments']) && is_array($data['body']['attachments'])) { - $data['body']['attachments'] = array_map( - [$this, 'createAttachment'], - $data['body']['attachments'], - ); - } - - if (isset($data['body']['markup']) && is_array($data['body']['markup'])) { - $data['body']['markup'] = array_map( - [$this, 'createMarkupElement'], - $data['body']['markup'], - ); + if (isset($data['body']) && is_array($data['body'])) { + $data['body'] = $this->createMessageBody($data['body']); } return Message::fromArray($data); } + /** + * List of messages. + * + * @param array $data + * + * @return Message[] + */ + public function createMessages(array $data): array + { + return isset($data['messages']) && is_array($data['messages']) + ? array_map([$this, 'createMessage'], $data['messages']) + : []; + } + + /** + * Creates a MessageBody object from raw API data, handling polymorphic attachments and markup. + * + * @param array $data + * + * @return MessageBody + * @throws ReflectionException + */ + private function createMessageBody(array $data): MessageBody + { + if (isset($data['attachments']) && is_array($data['attachments'])) { + $data['attachments'] = array_map( + [$this, 'createAttachment'], + $data['attachments'], + ); + } + + if (isset($data['markup']) && is_array($data['markup'])) { + $data['markup'] = array_map( + [$this, 'createMarkupElement'], + $data['markup'], + ); + } + + return MessageBody::fromArray($data); + } + /** * Creates a specific Attachment model based on the 'type' field. * @@ -237,20 +269,6 @@ class ModelFactory }; } - /** - * List of messages. - * - * @param array $data - * - * @return Message[] - */ - public function createMessages(array $data): array - { - return isset($data['messages']) && is_array($data['messages']) - ? array_map([$this, 'createMessage'], $data['messages']) - : []; - } - /** * Endpoint you should upload to your binaries. * diff --git a/src/Models/Attachments/InlineKeyboardAttachment.php b/src/Models/Attachments/InlineKeyboardAttachment.php index c50fcd8..a9d11be 100644 --- a/src/Models/Attachments/InlineKeyboardAttachment.php +++ b/src/Models/Attachments/InlineKeyboardAttachment.php @@ -12,7 +12,8 @@ final readonly class InlineKeyboardAttachment extends AbstractAttachment /** * @param KeyboardPayload $payload Keyboard payload. */ - public function __construct(public KeyboardPayload $payload) { + public function __construct(public KeyboardPayload $payload) + { parent::__construct(AttachmentType::InlineKeyboard); } } diff --git a/src/Models/Attachments/Payloads/PhotoToken.php b/src/Models/Attachments/Payloads/PhotoToken.php index dded503..e7667d6 100644 --- a/src/Models/Attachments/Payloads/PhotoToken.php +++ b/src/Models/Attachments/Payloads/PhotoToken.php @@ -14,9 +14,7 @@ final readonly class PhotoToken extends AbstractModel /** * @param string $token Encoded information of uploaded image. */ - public function __construct( - public string $token, - ) { + public function __construct(public string $token) + { } } - diff --git a/src/Models/Attachments/Payloads/ReplyKeyboardAttachmentRequestPayload.php b/src/Models/Attachments/Payloads/ReplyKeyboardAttachmentRequestPayload.php index b878130..ed594dd 100644 --- a/src/Models/Attachments/Payloads/ReplyKeyboardAttachmentRequestPayload.php +++ b/src/Models/Attachments/Payloads/ReplyKeyboardAttachmentRequestPayload.php @@ -4,7 +4,6 @@ declare(strict_types=1); namespace BushlanovDev\MaxMessengerBot\Models\Attachments\Payloads; -use BushlanovDev\MaxMessengerBot\Attributes\ArrayOf; use BushlanovDev\MaxMessengerBot\Models\Attachments\Buttons\Reply\AbstractReplyButton; final readonly class ReplyKeyboardAttachmentRequestPayload extends AbstractAttachmentRequestPayload @@ -15,7 +14,6 @@ final readonly class ReplyKeyboardAttachmentRequestPayload extends AbstractAttac * @param int|null $directUserId If set, reply keyboard will only be shown to this participant. */ public function __construct( - #[ArrayOf(AbstractReplyButton::class)] public array $buttons, public bool $direct = false, public ?int $directUserId = null, diff --git a/src/Models/Attachments/Payloads/UploadedInfoAttachmentRequestPayload.php b/src/Models/Attachments/Payloads/UploadedInfoAttachmentRequestPayload.php index dfc74e9..7482a03 100644 --- a/src/Models/Attachments/Payloads/UploadedInfoAttachmentRequestPayload.php +++ b/src/Models/Attachments/Payloads/UploadedInfoAttachmentRequestPayload.php @@ -1,19 +1,18 @@ -assertIsArray($array); $this->assertSame($data, $array); } + + #[Test] + public function createMessageCorrectlyHydratesComplexMessageBody(): void + { + $messageData = [ + 'timestamp' => time(), + 'body' => [ + 'mid' => 'mid.poly.test', + 'seq' => 200, + 'text' => 'Message with mixed content', + 'attachments' => [ + [ + 'type' => 'contact', + 'payload' => [ + 'vcf_info' => 'vcf...', + 'max_info' => [ + 'user_id' => 1111, + 'first_name' => 'aaaaa', + 'is_bot' => false, + 'last_activity_time' => 1754385571000, + ], + ], + ], + [ + 'type' => 'image', + 'payload' => ['photo_id' => 1, 'token' => 't', 'url' => 'u'], + ] + ], + 'markup' => [ + ['type' => 'strong', 'from' => 0, 'length' => 7], + ] + ], + 'recipient' => ['chat_type' => 'dialog', 'user_id' => 123], + ]; + + $factory = new ModelFactory(); + $message = $factory->createMessage($messageData); + + $this->assertInstanceOf(Message::class, $message); + $this->assertInstanceOf(MessageBody::class, $message->body); + + $attachments = $message->body->attachments; + $this->assertIsArray($attachments); + $this->assertCount(2, $attachments); + $this->assertInstanceOf(ContactAttachment::class, $attachments[0]); + $this->assertInstanceOf(PhotoAttachment::class, $attachments[1]); + + $markup = $message->body->markup; + $this->assertIsArray($markup); + $this->assertCount(1, $markup); + $this->assertInstanceOf(StrongMarkup::class, $markup[0]); + $this->assertSame(0, $markup[0]->from); + } }