forked from sebsauvage/Shaarli
-
Notifications
You must be signed in to change notification settings - Fork 297
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #515 from ArthurHoaro/template-feeds
Refactor RSS feeds generation, and do it through templates
- Loading branch information
Showing
16 changed files
with
859 additions
and
339 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,279 @@ | ||
<?php | ||
|
||
/** | ||
* FeedBuilder class. | ||
* | ||
* Used to build ATOM and RSS feeds data. | ||
*/ | ||
class FeedBuilder | ||
{ | ||
/** | ||
* @var string Constant: RSS feed type. | ||
*/ | ||
public static $FEED_RSS = 'rss'; | ||
|
||
/** | ||
* @var string Constant: ATOM feed type. | ||
*/ | ||
public static $FEED_ATOM = 'atom'; | ||
|
||
/** | ||
* @var string Default language if the locale isn't set. | ||
*/ | ||
public static $DEFAULT_LANGUAGE = 'en-en'; | ||
|
||
/** | ||
* @var int Number of links to display in a feed by default. | ||
*/ | ||
public static $DEFAULT_NB_LINKS = 50; | ||
|
||
/** | ||
* @var LinkDB instance. | ||
*/ | ||
protected $linkDB; | ||
|
||
/** | ||
* @var string RSS or ATOM feed. | ||
*/ | ||
protected $feedType; | ||
|
||
/** | ||
* @var array $_SERVER. | ||
*/ | ||
protected $serverInfo; | ||
|
||
/** | ||
* @var array $_GET. | ||
*/ | ||
protected $userInput; | ||
|
||
/** | ||
* @var boolean True if the user is currently logged in, false otherwise. | ||
*/ | ||
protected $isLoggedIn; | ||
|
||
/** | ||
* @var boolean Use permalinks instead of direct links if true. | ||
*/ | ||
protected $usePermalinks; | ||
|
||
/** | ||
* @var boolean true to hide dates in feeds. | ||
*/ | ||
protected $hideDates; | ||
|
||
/** | ||
* @var string PubSub hub URL. | ||
*/ | ||
protected $pubsubhubUrl; | ||
|
||
/** | ||
* @var string server locale. | ||
*/ | ||
protected $locale; | ||
|
||
/** | ||
* @var DateTime Latest item date. | ||
*/ | ||
protected $latestDate; | ||
|
||
/** | ||
* Feed constructor. | ||
* | ||
* @param LinkDB $linkDB LinkDB 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, $feedType, $serverInfo, $userInput, $isLoggedIn) | ||
{ | ||
$this->linkDB = $linkDB; | ||
$this->feedType = $feedType; | ||
$this->serverInfo = $serverInfo; | ||
$this->userInput = $userInput; | ||
$this->isLoggedIn = $isLoggedIn; | ||
} | ||
|
||
/** | ||
* Build data for feed templates. | ||
* | ||
* @return array Formatted data for feeds templates. | ||
*/ | ||
public function buildData() | ||
{ | ||
// Optionally filter the results: | ||
$linksToDisplay = $this->linkDB->filterSearch($this->userInput); | ||
|
||
$nblinksToDisplay = $this->getNbLinks(count($linksToDisplay)); | ||
|
||
// Can't use array_keys() because $link is a LinkDB instance and not a real array. | ||
$keys = array(); | ||
foreach ($linksToDisplay as $key => $value) { | ||
$keys[] = $key; | ||
} | ||
|
||
$pageaddr = escape(index_url($this->serverInfo)); | ||
$linkDisplayed = array(); | ||
for ($i = 0; $i < $nblinksToDisplay && $i < count($keys); $i++) { | ||
$linkDisplayed[$keys[$i]] = $this->buildItem($linksToDisplay[$keys[$i]], $pageaddr); | ||
} | ||
|
||
$data['language'] = $this->getTypeLanguage(); | ||
$data['pubsubhub_url'] = $this->pubsubhubUrl; | ||
$data['last_update'] = $this->getLatestDateFormatted(); | ||
$data['show_dates'] = !$this->hideDates || $this->isLoggedIn; | ||
// Remove leading slash from REQUEST_URI. | ||
$data['self_link'] = $pageaddr . escape(ltrim($this->serverInfo['REQUEST_URI'], '/')); | ||
$data['index_url'] = $pageaddr; | ||
$data['usepermalinks'] = $this->usePermalinks === true; | ||
$data['links'] = $linkDisplayed; | ||
|
||
return $data; | ||
} | ||
|
||
/** | ||
* Build a feed item (one per shaare). | ||
* | ||
* @param array $link Single link array extracted from LinkDB. | ||
* @param string $pageaddr Index URL. | ||
* | ||
* @return array Link array with feed attributes. | ||
*/ | ||
protected function buildItem($link, $pageaddr) | ||
{ | ||
$link['guid'] = $pageaddr .'?'. smallHash($link['linkdate']); | ||
// Check for both signs of a note: starting with ? and 7 chars long. | ||
if ($link['url'][0] === '?' && strlen($link['url']) === 7) { | ||
$link['url'] = $pageaddr . $link['url']; | ||
} | ||
if ($this->usePermalinks === true) { | ||
$permalink = '<a href="'. $link['url'] .'" title="Direct link">Direct link</a>'; | ||
} else { | ||
$permalink = '<a href="'. $link['guid'] .'" title="Permalink">Permalink</a>'; | ||
} | ||
$link['description'] = format_description($link['description']) . PHP_EOL .'<br>— '. $permalink; | ||
|
||
$date = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $link['linkdate']); | ||
|
||
if ($this->feedType == self::$FEED_RSS) { | ||
$link['iso_date'] = $date->format(DateTime::RSS); | ||
} else { | ||
$link['iso_date'] = $date->format(DateTime::ATOM); | ||
} | ||
|
||
// Save the more recent item. | ||
if (empty($this->latestDate) || $this->latestDate < $date) { | ||
$this->latestDate = $date; | ||
} | ||
|
||
$taglist = array_filter(explode(' ', $link['tags']), 'strlen'); | ||
uasort($taglist, 'strcasecmp'); | ||
$link['taglist'] = $taglist; | ||
|
||
return $link; | ||
} | ||
|
||
/** | ||
* Assign PubSub hub URL. | ||
* | ||
* @param string $pubsubhubUrl PubSub hub url. | ||
*/ | ||
public function setPubsubhubUrl($pubsubhubUrl) | ||
{ | ||
$this->pubsubhubUrl = $pubsubhubUrl; | ||
} | ||
|
||
/** | ||
* Set this to true to use permalinks instead of direct links. | ||
* | ||
* @param boolean $usePermalinks true to force permalinks. | ||
*/ | ||
public function setUsePermalinks($usePermalinks) | ||
{ | ||
$this->usePermalinks = $usePermalinks; | ||
} | ||
|
||
/** | ||
* Set this to true to hide timestamps in feeds. | ||
* | ||
* @param boolean $hideDates true to enable. | ||
*/ | ||
public function setHideDates($hideDates) | ||
{ | ||
$this->hideDates = $hideDates; | ||
} | ||
|
||
/** | ||
* Set the locale. Used to show feed language. | ||
* | ||
* @param string $locale The locale (eg. 'fr_FR.UTF8'). | ||
*/ | ||
public function setLocale($locale) | ||
{ | ||
$this->locale = strtolower($locale); | ||
} | ||
|
||
/** | ||
* Get the language according to the feed type, based on the locale: | ||
* | ||
* - RSS format: en-us (default: 'en-en'). | ||
* - ATOM format: fr (default: 'en'). | ||
* | ||
* @return string The language. | ||
*/ | ||
public function getTypeLanguage() | ||
{ | ||
// 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; | ||
return str_replace('_', '-', substr($this->locale, 0, $length)); | ||
} | ||
return ($this->feedType == self::$FEED_RSS) ? 'en-en' : 'en'; | ||
} | ||
|
||
/** | ||
* Format the latest item date found according to the feed type. | ||
* | ||
* Return an empty string if invalid DateTime is passed. | ||
* | ||
* @return string Formatted date. | ||
*/ | ||
protected function getLatestDateFormatted() | ||
{ | ||
if (empty($this->latestDate) || !$this->latestDate instanceof DateTime) { | ||
return ''; | ||
} | ||
|
||
$type = ($this->feedType == self::$FEED_RSS) ? DateTime::RSS : DateTime::ATOM; | ||
return $this->latestDate->format($type); | ||
} | ||
|
||
/** | ||
* Returns the number of link to display according to 'nb' user input parameter. | ||
* | ||
* If 'nb' not set or invalid, default value: $DEFAULT_NB_LINKS. | ||
* If 'nb' is set to 'all', display all filtered links (max parameter). | ||
* | ||
* @param int $max maximum number of links to display. | ||
* | ||
* @return int number of links to display. | ||
*/ | ||
public function getNbLinks($max) | ||
{ | ||
if (empty($this->userInput['nb'])) { | ||
return self::$DEFAULT_NB_LINKS; | ||
} | ||
|
||
if ($this->userInput['nb'] == 'all') { | ||
return $max; | ||
} | ||
|
||
$intNb = intval($this->userInput['nb']); | ||
if (! is_int($intNb) || $intNb == 0) { | ||
return self::$DEFAULT_NB_LINKS; | ||
} | ||
|
||
return $intNb; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.