Make FeedBuilder instance creation independant of the request stack

This commit is contained in:
ArthurHoaro 2020-05-18 13:03:13 +02:00
parent c56a540c6e
commit f4929b1188
3 changed files with 87 additions and 129 deletions

View file

@ -43,21 +43,9 @@ class FeedBuilder
*/
protected $formatter;
/**
* @var string RSS or ATOM feed.
*/
protected $feedType;
/**
* @var array $_SERVER
*/
/** @var mixed[] $_SERVER */
protected $serverInfo;
/**
* @var array $_GET
*/
protected $userInput;
/**
* @var boolean True if the user is currently logged in, false otherwise.
*/
@ -77,7 +65,6 @@ class FeedBuilder
* @var string server locale.
*/
protected $locale;
/**
* @var DateTime Latest item date.
*/
@ -88,37 +75,36 @@ class FeedBuilder
*
* @param BookmarkServiceInterface $linkDB LinkDB instance.
* @param BookmarkFormatter $formatter instance.
* @param string $feedType Type of feed.
* @param array $serverInfo $_SERVER.
* @param array $userInput $_GET.
* @param boolean $isLoggedIn True if the user is currently logged in, false otherwise.
*/
public function __construct($linkDB, $formatter, $feedType, $serverInfo, $userInput, $isLoggedIn)
public function __construct($linkDB, $formatter, array $serverInfo, $isLoggedIn)
{
$this->linkDB = $linkDB;
$this->formatter = $formatter;
$this->feedType = $feedType;
$this->serverInfo = $serverInfo;
$this->userInput = $userInput;
$this->isLoggedIn = $isLoggedIn;
}
/**
* Build data for feed templates.
*
* @param string $feedType Type of feed (RSS/ATOM).
* @param array $userInput $_GET.
*
* @return array Formatted data for feeds templates.
*/
public function buildData()
public function buildData(string $feedType, ?array $userInput)
{
// Search for untagged bookmarks
if (isset($this->userInput['searchtags']) && empty($this->userInput['searchtags'])) {
$this->userInput['searchtags'] = false;
if (isset($this->userInput['searchtags']) && empty($userInput['searchtags'])) {
$userInput['searchtags'] = false;
}
// Optionally filter the results:
$linksToDisplay = $this->linkDB->search($this->userInput);
$linksToDisplay = $this->linkDB->search($userInput);
$nblinksToDisplay = $this->getNbLinks(count($linksToDisplay));
$nblinksToDisplay = $this->getNbLinks(count($linksToDisplay), $userInput);
// Can't use array_keys() because $link is a LinkDB instance and not a real array.
$keys = array();
@ -130,11 +116,11 @@ public function buildData()
$this->formatter->addContextData('index_url', $pageaddr);
$linkDisplayed = array();
for ($i = 0; $i < $nblinksToDisplay && $i < count($keys); $i++) {
$linkDisplayed[$keys[$i]] = $this->buildItem($linksToDisplay[$keys[$i]], $pageaddr);
$linkDisplayed[$keys[$i]] = $this->buildItem($feedType, $linksToDisplay[$keys[$i]], $pageaddr);
}
$data['language'] = $this->getTypeLanguage();
$data['last_update'] = $this->getLatestDateFormatted();
$data['language'] = $this->getTypeLanguage($feedType);
$data['last_update'] = $this->getLatestDateFormatted($feedType);
$data['show_dates'] = !$this->hideDates || $this->isLoggedIn;
// Remove leading slash from REQUEST_URI.
$data['self_link'] = escape(server_url($this->serverInfo))
@ -146,45 +132,6 @@ public function buildData()
return $data;
}
/**
* Build a feed item (one per shaare).
*
* @param Bookmark $link Single link array extracted from LinkDB.
* @param string $pageaddr Index URL.
*
* @return array Link array with feed attributes.
*/
protected function buildItem($link, $pageaddr)
{
$data = $this->formatter->format($link);
$data['guid'] = $pageaddr . '?' . $data['shorturl'];
if ($this->usePermalinks === true) {
$permalink = '<a href="'. $data['url'] .'" title="'. t('Direct link') .'">'. t('Direct link') .'</a>';
} else {
$permalink = '<a href="'. $data['guid'] .'" title="'. t('Permalink') .'">'. t('Permalink') .'</a>';
}
$data['description'] .= PHP_EOL . PHP_EOL . '<br>&#8212; ' . $permalink;
$data['pub_iso_date'] = $this->getIsoDate($data['created']);
// atom:entry elements MUST contain exactly one atom:updated element.
if (!empty($link->getUpdated())) {
$data['up_iso_date'] = $this->getIsoDate($data['updated'], DateTime::ATOM);
} else {
$data['up_iso_date'] = $this->getIsoDate($data['created'], DateTime::ATOM);
}
// Save the more recent item.
if (empty($this->latestDate) || $this->latestDate < $data['created']) {
$this->latestDate = $data['created'];
}
if (!empty($data['updated']) && $this->latestDate < $data['updated']) {
$this->latestDate = $data['updated'];
}
return $data;
}
/**
* Set this to true to use permalinks instead of direct bookmarks.
*
@ -215,22 +162,64 @@ public function setLocale($locale)
$this->locale = strtolower($locale);
}
/**
* Build a feed item (one per shaare).
*
* @param string $feedType Type of feed (RSS/ATOM).
* @param Bookmark $link Single link array extracted from LinkDB.
* @param string $pageaddr Index URL.
*
* @return array Link array with feed attributes.
*/
protected function buildItem(string $feedType, $link, $pageaddr)
{
$data = $this->formatter->format($link);
$data['guid'] = $pageaddr . '?' . $data['shorturl'];
if ($this->usePermalinks === true) {
$permalink = '<a href="'. $data['url'] .'" title="'. t('Direct link') .'">'. t('Direct link') .'</a>';
} else {
$permalink = '<a href="'. $data['guid'] .'" title="'. t('Permalink') .'">'. t('Permalink') .'</a>';
}
$data['description'] .= PHP_EOL . PHP_EOL . '<br>&#8212; ' . $permalink;
$data['pub_iso_date'] = $this->getIsoDate($feedType, $data['created']);
// atom:entry elements MUST contain exactly one atom:updated element.
if (!empty($link->getUpdated())) {
$data['up_iso_date'] = $this->getIsoDate($feedType, $data['updated'], DateTime::ATOM);
} else {
$data['up_iso_date'] = $this->getIsoDate($feedType, $data['created'], DateTime::ATOM);
}
// Save the more recent item.
if (empty($this->latestDate) || $this->latestDate < $data['created']) {
$this->latestDate = $data['created'];
}
if (!empty($data['updated']) && $this->latestDate < $data['updated']) {
$this->latestDate = $data['updated'];
}
return $data;
}
/**
* Get the language according to the feed type, based on the locale:
*
* - RSS format: en-us (default: 'en-en').
* - ATOM format: fr (default: 'en').
*
* @param string $feedType Type of feed (RSS/ATOM).
*
* @return string The language.
*/
public function getTypeLanguage()
protected function getTypeLanguage(string $feedType)
{
// Use the locale do define the language, if available.
if (!empty($this->locale) && preg_match('/^\w{2}[_\-]\w{2}/', $this->locale)) {
$length = ($this->feedType === self::$FEED_RSS) ? 5 : 2;
$length = ($feedType === self::$FEED_RSS) ? 5 : 2;
return str_replace('_', '-', substr($this->locale, 0, $length));
}
return ($this->feedType === self::$FEED_RSS) ? 'en-en' : 'en';
return ($feedType === self::$FEED_RSS) ? 'en-en' : 'en';
}
/**
@ -238,32 +227,35 @@ public function getTypeLanguage()
*
* Return an empty string if invalid DateTime is passed.
*
* @param string $feedType Type of feed (RSS/ATOM).
*
* @return string Formatted date.
*/
protected function getLatestDateFormatted()
protected function getLatestDateFormatted(string $feedType)
{
if (empty($this->latestDate) || !$this->latestDate instanceof DateTime) {
return '';
}
$type = ($this->feedType == self::$FEED_RSS) ? DateTime::RSS : DateTime::ATOM;
$type = ($feedType == self::$FEED_RSS) ? DateTime::RSS : DateTime::ATOM;
return $this->latestDate->format($type);
}
/**
* Get ISO date from DateTime according to feed type.
*
* @param string $feedType Type of feed (RSS/ATOM).
* @param DateTime $date Date to format.
* @param string|bool $format Force format.
*
* @return string Formatted date.
*/
protected function getIsoDate(DateTime $date, $format = false)
protected function getIsoDate(string $feedType, DateTime $date, $format = false)
{
if ($format !== false) {
return $date->format($format);
}
if ($this->feedType == self::$FEED_RSS) {
if ($feedType == self::$FEED_RSS) {
return $date->format(DateTime::RSS);
}
return $date->format(DateTime::ATOM);
@ -276,20 +268,21 @@ protected function getIsoDate(DateTime $date, $format = false)
* If 'nb' is set to 'all', display all filtered bookmarks (max parameter).
*
* @param int $max maximum number of bookmarks to display.
* @param array $userInput $_GET.
*
* @return int number of bookmarks to display.
*/
public function getNbLinks($max)
protected function getNbLinks($max, ?array $userInput)
{
if (empty($this->userInput['nb'])) {
if (empty($userInput['nb'])) {
return self::$DEFAULT_NB_LINKS;
}
if ($this->userInput['nb'] == 'all') {
if ($userInput['nb'] == 'all') {
return $max;
}
$intNb = intval($this->userInput['nb']);
$intNb = intval($userInput['nb']);
if (!is_int($intNb) || $intNb == 0) {
return self::$DEFAULT_NB_LINKS;
}

View file

@ -452,15 +452,13 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM
$feedGenerator = new FeedBuilder(
$bookmarkService,
$factory->getFormatter(),
$feedType,
$_SERVER,
$_GET,
$loginManager->isLoggedIn()
);
$feedGenerator->setLocale(strtolower(setlocale(LC_COLLATE, 0)));
$feedGenerator->setHideDates($conf->get('privacy.hide_timestamps') && !$loginManager->isLoggedIn());
$feedGenerator->setUsePermalinks(isset($_GET['permalinks']) || !$conf->get('feed.rss_permalinks'));
$data = $feedGenerator->buildData();
$data = $feedGenerator->buildData($feedType, $_GET);
// Process plugin hook.
$pluginManager->executeHooks('render_feed', $data, array(

View file

@ -64,23 +64,6 @@ public static function setUpBeforeClass()
);
}
/**
* Test GetTypeLanguage().
*/
public function testGetTypeLanguage()
{
$feedBuilder = new FeedBuilder(null, self::$formatter, FeedBuilder::$FEED_ATOM, null, null, false);
$feedBuilder->setLocale(self::$LOCALE);
$this->assertEquals(self::$ATOM_LANGUAGUE, $feedBuilder->getTypeLanguage());
$feedBuilder = new FeedBuilder(null, self::$formatter, FeedBuilder::$FEED_RSS, null, null, false);
$feedBuilder->setLocale(self::$LOCALE);
$this->assertEquals(self::$RSS_LANGUAGE, $feedBuilder->getTypeLanguage());
$feedBuilder = new FeedBuilder(null, self::$formatter, FeedBuilder::$FEED_ATOM, null, null, false);
$this->assertEquals('en', $feedBuilder->getTypeLanguage());
$feedBuilder = new FeedBuilder(null, self::$formatter, FeedBuilder::$FEED_RSS, null, null, false);
$this->assertEquals('en-en', $feedBuilder->getTypeLanguage());
}
/**
* Test buildData with RSS feed.
*/
@ -89,13 +72,11 @@ public function testRSSBuildData()
$feedBuilder = new FeedBuilder(
self::$bookmarkService,
self::$formatter,
FeedBuilder::$FEED_RSS,
self::$serverInfo,
null,
static::$serverInfo,
false
);
$feedBuilder->setLocale(self::$LOCALE);
$data = $feedBuilder->buildData();
$data = $feedBuilder->buildData(FeedBuilder::$FEED_RSS, null);
// Test headers (RSS)
$this->assertEquals(self::$RSS_LANGUAGE, $data['language']);
$this->assertRegExp('/Wed, 03 Aug 2016 09:30:33 \+\d{4}/', $data['last_update']);
@ -140,13 +121,11 @@ public function testAtomBuildData()
$feedBuilder = new FeedBuilder(
self::$bookmarkService,
self::$formatter,
FeedBuilder::$FEED_ATOM,
self::$serverInfo,
null,
static::$serverInfo,
false
);
$feedBuilder->setLocale(self::$LOCALE);
$data = $feedBuilder->buildData();
$data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null);
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
$this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['last_update']);
$link = $data['links'][array_keys($data['links'])[2]];
@ -166,13 +145,11 @@ public function testBuildDataFiltered()
$feedBuilder = new FeedBuilder(
self::$bookmarkService,
self::$formatter,
FeedBuilder::$FEED_ATOM,
self::$serverInfo,
$criteria,
static::$serverInfo,
false
);
$feedBuilder->setLocale(self::$LOCALE);
$data = $feedBuilder->buildData();
$data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, $criteria);
$this->assertEquals(1, count($data['links']));
$link = array_shift($data['links']);
$this->assertEquals(41, $link['id']);
@ -190,13 +167,11 @@ public function testBuildDataCount()
$feedBuilder = new FeedBuilder(
self::$bookmarkService,
self::$formatter,
FeedBuilder::$FEED_ATOM,
self::$serverInfo,
$criteria,
static::$serverInfo,
false
);
$feedBuilder->setLocale(self::$LOCALE);
$data = $feedBuilder->buildData();
$data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, $criteria);
$this->assertEquals(3, count($data['links']));
$link = $data['links'][array_keys($data['links'])[2]];
$this->assertEquals(41, $link['id']);
@ -211,14 +186,12 @@ public function testBuildDataPermalinks()
$feedBuilder = new FeedBuilder(
self::$bookmarkService,
self::$formatter,
FeedBuilder::$FEED_ATOM,
self::$serverInfo,
null,
static::$serverInfo,
false
);
$feedBuilder->setLocale(self::$LOCALE);
$feedBuilder->setUsePermalinks(true);
$data = $feedBuilder->buildData();
$data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null);
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
$this->assertTrue($data['usepermalinks']);
// First link is a permalink
@ -247,14 +220,12 @@ public function testBuildDataHideDates()
$feedBuilder = new FeedBuilder(
self::$bookmarkService,
self::$formatter,
FeedBuilder::$FEED_ATOM,
self::$serverInfo,
null,
static::$serverInfo,
false
);
$feedBuilder->setLocale(self::$LOCALE);
$feedBuilder->setHideDates(true);
$data = $feedBuilder->buildData();
$data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null);
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
$this->assertFalse($data['show_dates']);
@ -262,14 +233,12 @@ public function testBuildDataHideDates()
$feedBuilder = new FeedBuilder(
self::$bookmarkService,
self::$formatter,
FeedBuilder::$FEED_ATOM,
self::$serverInfo,
null,
static::$serverInfo,
true
);
$feedBuilder->setLocale(self::$LOCALE);
$feedBuilder->setHideDates(true);
$data = $feedBuilder->buildData();
$data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null);
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
$this->assertTrue($data['show_dates']);
}
@ -289,13 +258,11 @@ public function testBuildDataServerSubdir()
$feedBuilder = new FeedBuilder(
self::$bookmarkService,
self::$formatter,
FeedBuilder::$FEED_ATOM,
$serverInfo,
null,
false
);
$feedBuilder->setLocale(self::$LOCALE);
$data = $feedBuilder->buildData();
$data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null);
$this->assertEquals(
'http://host.tld:8080/~user/shaarli/index.php?do=feed',