config = new attachments_c(); } /** * @inheritDoc */ public function list(string $type, int $object_id, array $options = []): array { $rows = $this->fetchAttachmentRows($type, [$object_id], $options); return array_map(fn(array $row): attachment => $this->toAttachment($row), $rows); } /** * List attachments for multiple objects in one query. * * @param string $type * @param int[] $object_ids * @param array $options * @return array */ public function listMany(string $type, array $object_ids, array $options = []): array { $object_ids = array_values(array_unique(array_filter(array_map('intval', $object_ids), static fn(int $id): bool => $id > 0))); if (empty($object_ids)) { return []; } $rows = $this->fetchAttachmentRows($type, $object_ids, $options); $grouped = []; foreach ($object_ids as $object_id) { $grouped[$object_id] = []; } foreach ($rows as $row) { $object_id = (int)($row['object_id'] ?? 0); if (!isset($grouped[$object_id])) { $grouped[$object_id] = []; } $grouped[$object_id][] = $this->toAttachment($row); } return $grouped; } /** * @inheritDoc * @throws Exception If the attachment is not found */ public function get(int $attachment_id): ?object_attachments_o { return (new object_attachments_o())->select($attachment_id) ?: null; } /** * Format an object_attachments_o to an attachment object * @param object_attachments_o $object_attachments_o The object to format * @return attachment The formatted attachment * @throws Exception If the attachment cannot be formatted */ public function format(object_attachments_o $object_attachments_o): attachment { $data = (object)$object_attachments_o->toArray(); // If content is JSON, decode it if (is_string($data->content) && $data->content !== '' && $data->content[0] === '{') { $data->content = json_decode($data->content, true); } return (new attachment())->populate($data); } /** * @inheritDoc * @throws Exception If the attachment cannot be created */ public function create(string $type, int $object_id, attachment_content $attachment_content): int|bool { $object_attachments_o = new object_attachments_o(); $object_attachments_o->add([ 'object_type' => $type, 'object_id' => $object_id, 'content' => json_encode($attachment_content->toArray()), // Store as JSON ]); return $object_attachments_o->id ?: false; } /** * @inheritDoc * @throws Exception If the attachment cannot be deleted */ public function delete(int $attachment_id): bool { $object_attachments_o = new object_attachments_o(); if ($object_attachments_o->select($attachment_id)) { $object_attachments_o->delete(); return true; } return false; } /** * @inheritDoc * @throws Exception If the attachment cannot be updated */ public function update(int $attachment_id, attachment_content $attachment_content): bool { $object_attachments_o = new object_attachments_o(); if ($object_attachments_o->select($attachment_id)) { $object_attachments_o->content->set(json_encode($attachment_content->toArray())); return true; } return false; } protected function fetchAttachmentRows(string $type, array $object_ids, array $options = []): array { $options = $this->normalizeAttachmentOptions($options); $rawType = trim($type, '`'); $objectTypes = array_values(array_unique([ $rawType, '`' . $rawType . '`', ])); return (new object_attachments_o())->getFieldsWhereIn([ 'object_type' => $objectTypes, 'object_id' => $object_ids, 'deleted_at' => null ], $options); } protected function toAttachment(array $item): attachment { $payload = (object)$item; $payload->content = json_decode((string)$payload->content, true); return (new attachment())->populate($payload); } protected function normalizeAttachmentOptions(array $options): array { if (count($options) === 0) { return ['id', 'content', 'created_at', 'object_id', 'object_type', 'created_at', 'updated_at']; } return $options; } }