Lean library extension providing the data-transfer and response objects
exchanged between the fixpunkt social server and TYPO3. It encapsulates the
protocol (currently version 2) as typed PHP objects and is used, among others,
by fp_social.
The extension deliberately contains no business logic of its own, no TCA and
no plugins – only the shared classes, so that the server and client side use the
same format.
fp_social_bridge is a lean library extension. It provides the
data-transfer and response objects exchanged between the fixpunkt social
server and TYPO3. The protocol (currently version 2) is encapsulated as typed
PHP objects and is used, among others, by
fp_social.
The extension deliberately contains no business logic of its own, no TCA and
no plugins – only the shared classes, so that the server and client side use the
same format.
Included classes
Class
Purpose
SerializableInterface
Contract: fromJson(), fromArray(), toArray()
v2\Data\Post
A single post (id, headline, message, url, date, hashtags,
mentions, pictures)
v2\Data\Posts
Iterable, countable collection of Post objects
v2\Data\Channel
A selectable page or channel of a connected account (id, name)
v2\Data\Account
A connected account incl. its channels (uid, network, display name,
e-mail, expiry)
v2\Data\Accounts
Iterable, countable collection of Account objects, grouped by
network
v2\Response\SocialServerResponse
Abstract base incl. version check and the fromJson() factory
Response containing all connected accounts, grouped by network
v2\Response\SocialServerErrorResponse
Error response (code with prefix 5550, message)
Installation
The extension is installed via Composer:
composer require fixpunkt/fp-social-bridge
Copied!
Requirements
Component
Version
TYPO3
12.4 – 14.3
PHP
8.4 – 8.5
Usage
This extension describes the protocol between the fixpunkt social server
(server side) and a TYPO3 instance such as fp_social (client side). Both sides use the
same classes, so that creation and evaluation are guaranteed to use the same
format.
Every response carries the fully qualified class name in the type field and
the protocol version (currently 2) in the version field. Based on these
two fields the factory decides which object to reconstruct and checks version
compatibility.
Note
All of the following examples use anonymized sample data (example.com,
fictional IDs). The format matches that of real responses.
Structure of a post object
Before we get to the responses, it is worth looking at the JSON of a single
Post, since some fields have a particular format here:
Field
Format
headline
Headline. Empty ("") for many sources (e.g. Facebook).
message
HTML text. May contain <br /> and <a> tags as well as emoji
placeholders of the form {emoji:9728} (Unicode code point).
update_time
Serialized \DateTime object with the keys date,
timezone_type and timezone.
hashtags
List of strings without a leading # (e.g. "summer").
mentions
List of objects with displayName and systemName; empty when
there are no mentions.
pictures
List of picture URLs.
Example 1: A single post (SocialServerPostResponse)
Server side – create and output as JSON:
useFixpunkt\FpSocialBridge\v2\Data\Post;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerPostResponse;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerResponse;
$post = new Post(
id: '100000000000001_200000000000001',
headline: '',
message: 'Summertime! Here is our favourite recipe for hot days.<br />'
. "\n" . 'Have fun trying it out {emoji:9728} '
. '<a href=\'https://social.example.com/hashtag/recipe\'>#recipe</a>',
post_url: 'https://social.example.com/100000000000001/posts/200000000000001',
update_time: new \DateTime('2026-06-27 08:00:38+00:00'),
link: 'https://social.example.com/100000000000001/posts/200000000000001',
hashtags: ['recipe', 'summer', 'drinks', 'tip'],
mentions: [],
pictures: ['https://cdn.example.com/media/image-1.jpg'],
);
$response = new SocialServerPostResponse(SocialServerResponse::version, $post);
echo json_encode($response->toArray());
useFixpunkt\FpSocialBridge\v2\Response\SocialServerPostResponse;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerResponse;
$response = SocialServerResponse::fromJson($json);
if ($response instanceof SocialServerPostResponse) {
$post = $response->getPost();
echo $post->getMessage();
foreach ($post->getHashtags() as $hashtag) {
echo'#' . $hashtag; // the leading # is not part of the value
}
}
Copied!
Note
If a post contains mentions, the mentions field looks like this:
Example 2: Multiple posts with pagination (SocialServerPostsResponse)
This is the most common response: a list of posts plus the cursors for paging.
previousPage is empty on the first page; nextPage contains the full URL
for the next fetch (or is empty when no further page exists).
Server side – create and output as JSON:
useFixpunkt\FpSocialBridge\v2\Data\Post;
useFixpunkt\FpSocialBridge\v2\Data\Posts;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerPostsResponse;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerResponse;
$posts = new Posts([
new Post(
id: '100000000000001_200000000000001',
headline: '',
message: 'Summertime! Here is our favourite recipe for hot days.',
post_url: 'https://social.example.com/100000000000001/posts/200000000000001',
update_time: new \DateTime('2026-06-27 08:00:38+00:00'),
link: 'https://social.example.com/100000000000001/posts/200000000000001',
hashtags: ['recipe', 'summer', 'drinks', 'tip'],
mentions: [],
pictures: ['https://cdn.example.com/media/image-1.jpg'],
),
new Post(
id: '100000000000001_200000000000002',
headline: '',
message: 'We will soon present our new project – stay tuned!',
post_url: 'https://social.example.com/100000000000001/posts/200000000000002',
update_time: new \DateTime('2026-06-24 17:00:14+00:00'),
link: 'https://social.example.com/100000000000001/posts/200000000000002',
hashtags: ['project', 'news', 'outlook'],
mentions: [],
pictures: ['https://cdn.example.com/media/image-2.jpg'],
),
]);
$response = new SocialServerPostsResponse(
SocialServerResponse::version,
$posts,
previous: '',
next: 'https://social-server.example.com/networks/example/posts?tx_fpsocialserver_show%5Bafter%5D=QVFI...&tx_fpsocialserver_show%5Bversion%5D=2&cHash=0123456789abcdef0123456789abcdef',
);
echo json_encode($response->toArray());
Copied!
The resulting JSON (posts and nextPage shortened):
Client side – evaluate and iterate over the collection:
useFixpunkt\FpSocialBridge\v2\Response\SocialServerPostsResponse;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerResponse;
$response = SocialServerResponse::fromJson($json);
if ($response instanceof SocialServerPostsResponse) {
foreach ($response->getPosts() as $post) {
echo $post->getMessage();
}
// Cursors (URLs) for the next and previous page
$next = $response->getNext();
$previous = $response->getPrevious();
}
Copied!
Note
Posts implements Iterator and Countable and
can therefore be iterated directly with foreach and counted with
count().
Example 3: Error response (SocialServerErrorResponse)
If an error occurs on the social server, it creates a
SocialServerErrorResponse instead of a data
response.
Server side – create and output as JSON:
useFixpunkt\FpSocialBridge\v2\Response\SocialServerErrorResponse;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerResponse;
$response = new SocialServerErrorResponse(
SocialServerResponse::version,
code: 42,
message: 'The requested account does not exist.',
);
echo json_encode($response->toArray());
Copied!
The resulting JSON:
{
"type": "Fixpunkt\\FpSocialBridge\\v2\\Response\\SocialServerErrorResponse",
"version": 2,
"code": 555042,
"message": "The requested account does not exist."
}
Copied!
Note
The supplied error code is combined with the prefix 5550 in the
constructor and stored as an int. So code: 42 becomes 555042.
Example 4: The available accounts (SocialServerAccountsResponse)
The endpoint POST /api/accounts returns every account the authenticated user
has connected on the social server, grouped by network. The client side uses it
to prefill the account, channel and label fields of an account record instead of
having editors type page ids by hand.
Only networks whose access is established on the server appear here – Facebook,
Instagram, Instagram (direct login) and LinkedIn. Wordpress, Youtube and Bluesky
are configured entirely on the client side and are therefore absent.
useFixpunkt\FpSocialBridge\v2\Response\SocialServerAccountsResponse;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerResponse;
$response = SocialServerResponse::fromJson($json);
if ($response instanceof SocialServerAccountsResponse) {
foreach ($response->getAccounts() as $network => $accounts) {
foreach ($accounts as $account) {
foreach ($account->getChannels() as $channel) {
// channel field ← getId(), label field ← getName()echo $account->getDisplayName() . ': ' . $channel->getName();
}
}
}
}
Copied!
Note
expires is null for networks whose access keys do not expire
(Facebook, Instagram). For LinkedIn and Instagram (direct login) it is a
serialized \DateTime in the same format as update_time on a post.
Note
Instagram reuses the Facebook access key. The same account therefore shows up
under both networks with the same uid but different channels –
Facebook pages in one case, Instagram business accounts in the other.
Handling all types together
In practice the client side does not know in advance which type will come back.
The factory always returns the matching object; instanceof is used to tell
them apart:
useFixpunkt\FpSocialBridge\v2\Response\SocialServerResponse;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerPostsResponse;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerPostResponse;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerAccountsResponse;
useFixpunkt\FpSocialBridge\v2\Response\SocialServerErrorResponse;
$response = SocialServerResponse::fromJson($json);
if ($response instanceof SocialServerErrorResponse) {
thrownew \RuntimeException(
$response->getMessage(),
$response->getCode()
);
}
if ($response instanceof SocialServerPostsResponse) {
foreach ($response->getPosts() as $post) {
echo $post->getMessage();
}
$next = $response->getNext(); // URL for the next page
}
if ($response instanceof SocialServerPostResponse) {
$post = $response->getPost();
}
if ($response instanceof SocialServerAccountsResponse) {
foreach ($response->getAccounts() as $network => $accounts) {
// ...
}
}
Copied!
Note
fromJson() checks the protocol version and throws an \Exception if
the data is corrupted or the version does not match. See
SocialServerResponse.
Class reference
All classes live in the Fixpunkt\FpSocialBridge namespace. They fall into
three types:
Interface – the shared serialization contract.
DTOs (data transfer objects) – the plain data carriers.
Responses – the typed response objects of the social server.
Shared contract of all data-transfer and response objects.
Method
Description
fromJson(string $json): static
Creates an object from a JSON string.
fromArray(array $data): static
Creates an object from an associative array.
toArray(): array
Serializes the object back into an array.
DTOs
The data transfer objects in the v2\Data namespace contain only data and
accessor methods, no business logic.
v2\Data\Post
Represents a single post.
Method
Return value
getId()
string – unique ID of the post
getHeadline()
string – headline (empty for many sources)
getMessage()
string – message text as HTML (may contain <br />/<a> as
well as emoji placeholders {emoji:…})
getPostUrl()
string – URL of the post on the network
getLink()
string – linked URL
getUpdateTime()
\DateTime – time of last update (in JSON as date /
timezone_type / timezone)
getHashtags()
array – hashtags as strings without a leading #
getMentions()
array – mentions as objects with displayName and
systemName
getPictures()
array – picture URLs
v2\Data\Posts
Iterable, countable collection of Post objects. Implements Iterator and
Countable, so it can be used directly with foreach and count().
v2\Data\Channel
A selectable page or channel of a connected account. This is exactly what the
client side writes into the channel and label fields of an account
record.
Method
Return value
getId()
string – id of the page/channel in the network
getName()
string – display name of the page/channel
v2\Data\Account
A single connected account of the social server.
Method
Return value
getUid()
int – uid of the access key record on the social server
getNetwork()
string – connector class name, e.g.
Fixpunkt\FpSocialServer\Networks\Facebook\Connector
getNetworkKey()
string – short form of the network (facebook,
instagram, instagramlogin, linkedin)
getNetworkName()
string – human readable network name, e.g.
Instagram (Direktanmeldung)
getDisplayName()
string – name of the account as shown to the user
getUsername()
string – identifier of the account within the network
getEmail()
string – e-mail address, may be empty
getExpires()
\DateTime|null – expiry of the access key, null for
networks whose keys do not expire
getExpired()
bool – whether the access key has already expired
getChannels()
Channel[] – the pages/channels reachable with this account
v2\Data\Accounts
Iterable, countable collection of Account objects, grouped by network.
Unlike Posts it is not a flat list: iterating yields
the network class name as key and an Account[] as value.
Method
Description
getIterator()
Iterates network => Account[] (IteratorAggregate)
count()
Total number of accounts across all networks
getNetworks()
string[] – the networks that have accounts
getByNetwork(string $network)
Account[] – the accounts of one network, empty if unknown
getAll()
Account[] – all accounts as a flat list
Responses
The response objects in the v2\Response namespace represent the various
response types of the social server. The base class factory turns a received
JSON response into the matching object.
v2\Response\SocialServerResponse
Abstract base class of all server responses.
Method
Description
fromJson(string $json): static
Factory: checks the protocol version and returns the matching
response object. Throws an \Exception on corrupted data or a
mismatching version.
getVersion(): int
Protocol version of the response.
v2\Response\SocialServerPostResponse
Response containing a single post.
getPost(): Post – returns the contained post.
v2\Response\SocialServerPostsResponse
Response containing multiple posts including pagination.
Method
Description
getPosts(): Posts
Collection of the contained posts.
getNext(): string
Cursor for the next page (nextPage).
getPrevious(): string
Cursor for the previous page (previousPage).
v2\Response\SocialServerAccountsResponse
Response containing all accounts the authenticated user has connected on the
social server, grouped by network.
getAccounts(): Accounts – the contained collection.
v2\Response\SocialServerErrorResponse
Error response of the social server.
Method
Description
getCode(): int
Composite error code (prefix 5550).
getMessage(): string
Error message.
Changelog
1.4.0
Added v2\Response\SocialServerAccountsResponse together with the data
transfer objects v2\Data\Account, v2\Data\Accounts and
v2\Data\Channel. They carry the accounts a user has connected on the
social server, grouped by network, so that the client side can prefill the
account, channel and label fields of an account record.
SocialServerResponse::fromJson() now also recognizes the new accounts
response.
1.3.0
Added compatibility with TYPO3 14. The extension now supports TYPO3 12.4,
13.4 and 14.3.
Reference to the headline
Copy and freely share the link
This link target has no permanent anchor assigned.The link below can be used, but is prone to change if the page gets moved.