The Item API
Every provider — LinkedIn, RSS, YouTube, Bluesky, future ones — normalizes into the same TheWPFeeds\Item\Item value object. One model, one template contract: that's what makes a mixed LinkedIn + YouTube page render through the same pipeline.
Items are immutable. Getters return raw values — escape in your templates.
Getters
| Method | Returns | Notes |
|---|---|---|
title( $fallback = null ) |
?string |
Post/article/video title. LinkedIn posts and Bluesky posts usually have none — hence the fallback. |
content() |
string |
Full plain-text body. HTML is already stripped, entities decoded. |
excerpt( $words = 30 ) |
string |
Body trimmed via wp_trim_words(). |
date( $format = '' ) |
string |
Localized via wp_date(). Empty format = the site's date format setting. |
datetime() |
DateTimeImmutable |
For datetime="" attributes and custom formatting. |
url() |
string |
Permalink on the source platform (LinkedIn post, YouTube watch page, Bluesky post…). |
hasImage() |
bool |
|
image() |
?string |
Image URL — the locally cached copy when available (see Caching), remote fallback otherwise. |
imageTag( $attrs = [] ) |
string |
Ready-made escaped <img> with loading="lazy", dimensions when known, alt text. Pass extra attributes: $item->imageTag(['class' => 'card__img']). |
author() |
?ItemAuthor |
Struct with ->name, ->url, ->imageUrl (avatar). The company page, channel, or profile. |
raw() |
array |
The untouched provider payload — the escape hatch. |
Public readonly properties are also available: $item->id, $item->provider, $item->title, $item->content, $item->image (an ItemImage with ->remoteUrl, ->localUrl, ->alt, ->width, ->height).
provider and branching
$item->provider is the provider id (linkedin, rss, youtube, bluesky, mock). Prefer the item template hierarchy over if-chains — but for small differences inline branching is fine:
<span class="badge badge--<?php echo esc_attr( $item->provider ); ?>">
<?php echo esc_html( $item->provider ); ?>
</span>
raw() — the escape hatch
Anything provider-specific that didn't fit the normalized model is preserved verbatim. Examples:
// LinkedIn: the full /rest/posts element
$urn = $item->raw()['id'] ?? '';
// Bluesky: engagement counts
$likes = $item->raw()['likeCount'] ?? 0;
// YouTube: derive the video id from the watch URL
parse_str( (string) parse_url( $item->url(), PHP_URL_QUERY ), $q );
$video_id = $q['v'] ?? '';
Rule of thumb: if you find yourself using raw() for the same thing in every template, that's feedback — tell us and it may become a first-class getter.