Developer corner¶
Table of Contents
Introduction¶
This extension provides classes and interfaces to implement feeds in different formats. You don't have to worry about the details of the feeds and how they are build, you only have to collect the according data from your model.
Example¶
Let's start with an example on how this is done:
<?php
declare(strict_types=1);
namespace MyVender\MyExtension\Feed;
use Brotkrueml\FeedGenerator\Attributes\Feed;
use Brotkrueml\FeedGenerator\Feed\FeedFormat;
use Brotkrueml\FeedGenerator\Feed\FeedInterface;
use MyVender\MyExtension\Domain\Repository\MyRepository;
#[Feed('/feed.atom', FeedFormat::ATOM)]
#[Feed('/feed.json', FeedFormat::JSON)]
#[Feed('/feed.rss', FeedFormat::RSS)]
final class MyFeed implements FeedInterface
{
public function __construct(
private readonly MyRepository $repository,
) {
}
public function getTitle(): string
{
return 'My Website';
}
public function getDescription(): string
{
return '';
}
public function getLanguage(): string
{
return 'en';
}
public function getLogo(): string
{
return '';
}
public function getLastModified(): ?\DateTimeInterface
{
return new \DateTimeImmutable();
}
public function getPublicId(): string
{
return '';
}
public function getLink(): string
{
return 'https://example.com/';
}
public function getItems(): array
{
$items = [];
$records = $this->repository->findAll();
foreach ($records as $record) {
$lastModified = (new \DateTimeImmutable())->setTimestamp($record['lastModified']);
$items[] = new Item(
title: $record['title'],
publicId: $record['uid'],
lastModified: $lastModified,
link: $this->buildLink($record['uid']),
summary: $record['summary'] ?? '',
content: $record['content'] ?? '',
);
}
return $items;
}
private function buildLink(int $uid): string
{
// This has to be implemented, we'll come back to this in a moment
return '';
}
}
First, a class which provides the data for one or more feeds must implement
the Brotkrueml\FeedGenerator\Feed\FeedInterface
interface. This marks
the class as a feed data provider.
To define under which URL a feed is available and which format should be used
you add one or more Brotkrueml\FeedGenerator\Attributes\Feed
attributes
to the class. The attribute can be assigned multiple times, like in the example
above. As format a name of the Brotkrueml\FeedGenerator\Attributes\Feed
enum is used which defines the according format. Optionally it is also possible
to define one or more site identifiers when you have a multiple site
installation.
You can use constructor injection to add inject service classes. Implement the
methods necessary for the Brotkrueml\FeedGenerator\Feed\FeedInterface
interface. When returning an empty value the feed property is not available
in the resulting feed.
As you see in the above example, the link is hardcoded by now and the item's
link is also not implemented. Also no logo is given. To provide dynamic values
for these properties we need an instance of the current request object. This can
easily be achieved by implementing the
Brotkrueml\FeedGenerator\Feed\RequestAwareInterface
interface:
// use Brotkrueml\FeedGenerator\Feed\RequestAwareInterface;
// use Psr\Http\Message\ServerRequestInterface;
// ... the attributes like above
final class MyFeed implements FeedInterface, RequestAwareInterface
{
private const PATH_LOGO = 'EXT:my_extension/Resources/Public/Images/logo.png';
private ServerRequestInterface $request;
public function setRequest(ServerRequestInterface $request): void
{
$this->request = $request;
}
public function getLogo(): string
{
return $this->request->getAttribute('normalizedParams')->getRequestHost()
. PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName(self::PATH_LOGO));
}
public function getLink(): string
{
return $this->request->getAttribute('normalizedParams')->getSiteUrl();
}
private function buildLink(int $uid): string
{
$router = $this->request->getAttribute('site')->getRouter();
return (string)$router->generateUri($uid);
}
// ... the other methods from above are untouched
}
Now the method setRequest()
has to be implemented, which provides you
with the request. Now it is easy to provide a logo from an extension, to
dynamically set the website links and the item's links.
When you now call one of the paths defined in the attributes you will see the feed in the according format.
Important
Not all properties are used in every format. For example, the content of an item is only available in an Atom feed and not in an RSS feed.
Tip
Have a look into the API chapter to see this different interfaces and classes.