Attachment Model
Data-access models live in includes/models/ and are the only supported way
to read or write Jetonomy's custom tables - no raw $wpdb outside
includes/db/. This page documents Jetonomy\Models\Attachment.
Attachment
Jetonomy\Models\Attachment - includes/models/class-attachment.php
Links WordPress media items to posts/replies, with ordering and a batch
primer so rendering N reply cards issues zero per-row queries. Table:
jt_attachments (free-owned since 1.8.0; it's the renamed jt_pro_attachments
- same schema, no rows copied). Free carries the link so a site that drops Pro still shows its attachments; Pro adds the upload composer, size/type limits, and richer previews on top of the same table.
hydrate()
Attachment::hydrate( object $row ): ?array
Turns a jt_attachments link row into the canonical attachment shape. There is
exactly ONE shape, used by both the frontend renderer and the REST payload, so
the web and the app cannot drift apart.
Returns null when the underlying media item has been deleted, so a dangling
link renders nothing rather than a broken card.
[
'id' => 0, // the MEDIA id
'link_id' => 0, // the jt_attachments row id
'url' => '',
'thumb' => '', // 'medium' for images, 'thumbnail' otherwise
'mime' => '',
'name' => '', // real filename WITH extension, e.g. "sample.pdf"
'size' => 0, // bytes; 0 when the file is not on disk
'type' => '', // 'image' | 'pdf' | 'file'
'ext' => '', // uppercased, e.g. "PDF"
'is_image' => false,
]
id being the media id while link_id is the row id reads backwards, but it is
the established contract the app already consumes and is not worth breaking
clients over. Pro enriches each item through
jetonomy_rest_attachment_data
(it swaps in its own download URL for non-images), so a Pro site's payload shape
is unchanged.
link()
Attachment::link( string $object_type, int $object_id, int $attachment_id, int $sort = 0 ): int
Attaches a WP media item to a post or reply. Returns the jt_attachments row
id. Idempotent - linking the same file to the same object twice is a no-op
(backed by a UNIQUE KEY on object_type, object_id, attachment_id), so a
resumed or re-run import can't double-attach a file.
get_for()
Attachment::get_for( string $object_type, int $object_id ): array
All link rows for one object, ordered by sort then id. Request-cached per
[type][object_id].
get_for_many()
Attachment::get_for_many( string $object_type, int[] $object_ids ): array
Batch-loads attachments for many objects of one type in one query and seeds the per-object cache, keyed by object id (empty array for objects with none). Use when rendering a page of N posts/replies.
prime_for_post()
Attachment::prime_for_post( int $post_id ): void
The N+1 guard for a single-post view: loads attachments for every reply on
a post in one query (JOIN jt_replies), so rendering N reply cards costs
zero further attachment queries. Called by Attachments::render_post()
before the reply loop. Seeds every reply on the post, including ones with no
attachments, so a later get_for() call never re-queries.
count_for()
Attachment::count_for( string $object_type, int $object_id ): int
SELECT COUNT(*) for one object. Use for a badge/count display - never
count( Attachment::get_for(...) ).
unlink()
Attachment::unlink( int $link_id ): bool
Removes one link row by its own id (not the media id).
unlink_all()
Attachment::unlink_all( string $object_type, int $object_id ): int
Removes every link row for an object (post/reply cascade delete). Returns the number of rows deleted.
hydrate()
Attachment::hydrate( object $row ): ?array
Turns a jt_attachments row into the canonical attachment shape consumed by
both the frontend card renderer and the REST payload - one shape, so the web
and the app can never drift. Returns null when the underlying media item
was deleted (render nothing rather than a broken card). See the shape table
in Hooks Reference - REST payload.
payload_for()
Attachment::payload_for( string $object_type, int $object_id ): array
Hydrates every attachment on an object and runs each through the
jetonomy_rest_attachment_data
filter. Backs both Attachments::render() and the REST attachments field.
Usage example
use Jetonomy\Models\Attachment;
// Attach an already-uploaded media item to a reply.
$link_id = Attachment::link( 'reply', $reply_id, $media_id, $sort = 0 );
// Render a page of replies without N+1 attachment queries.
Attachment::prime_for_post( $post_id );
foreach ( $replies as $reply ) {
$attachments = Attachment::get_for( 'reply', $reply->id ); // no extra query
}