]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - application/feed/FeedBuilder.php
Remove legacy handling of /add-tag route
[github/shaarli/Shaarli.git] / application / feed / FeedBuilder.php
CommitLineData
82e36802 1<?php
dfc650aa
V
2namespace Shaarli\Feed;
3
4use DateTime;
cf92b4dd
A
5use Shaarli\Bookmark\Bookmark;
6use Shaarli\Bookmark\BookmarkServiceInterface;
7use Shaarli\Formatter\BookmarkFormatter;
82e36802
A
8
9/**
10 * FeedBuilder class.
11 *
12 * Used to build ATOM and RSS feeds data.
13 */
14class FeedBuilder
15{
16 /**
17 * @var string Constant: RSS feed type.
18 */
19 public static $FEED_RSS = 'rss';
20
21 /**
22 * @var string Constant: ATOM feed type.
23 */
24 public static $FEED_ATOM = 'atom';
25
26 /**
27 * @var string Default language if the locale isn't set.
28 */
29 public static $DEFAULT_LANGUAGE = 'en-en';
30
31 /**
cf92b4dd 32 * @var int Number of bookmarks to display in a feed by default.
82e36802
A
33 */
34 public static $DEFAULT_NB_LINKS = 50;
35
36 /**
cf92b4dd 37 * @var BookmarkServiceInterface instance.
82e36802
A
38 */
39 protected $linkDB;
40
cf92b4dd
A
41 /**
42 * @var BookmarkFormatter instance.
43 */
44 protected $formatter;
45
82e36802
A
46 /**
47 * @var string RSS or ATOM feed.
48 */
49 protected $feedType;
50
51 /**
dfc650aa 52 * @var array $_SERVER
82e36802
A
53 */
54 protected $serverInfo;
55
56 /**
dfc650aa 57 * @var array $_GET
82e36802
A
58 */
59 protected $userInput;
60
61 /**
62 * @var boolean True if the user is currently logged in, false otherwise.
63 */
64 protected $isLoggedIn;
65
66 /**
cf92b4dd 67 * @var boolean Use permalinks instead of direct bookmarks if true.
82e36802
A
68 */
69 protected $usePermalinks;
70
71 /**
72 * @var boolean true to hide dates in feeds.
73 */
74 protected $hideDates;
75
82e36802
A
76 /**
77 * @var string server locale.
78 */
79 protected $locale;
80
81 /**
82 * @var DateTime Latest item date.
83 */
84 protected $latestDate;
85
86 /**
87 * Feed constructor.
88 *
cf92b4dd
A
89 * @param BookmarkServiceInterface $linkDB LinkDB instance.
90 * @param BookmarkFormatter $formatter instance.
f24896b2
V
91 * @param string $feedType Type of feed.
92 * @param array $serverInfo $_SERVER.
93 * @param array $userInput $_GET.
cf92b4dd 94 * @param boolean $isLoggedIn True if the user is currently logged in, false otherwise.
82e36802 95 */
cf92b4dd 96 public function __construct($linkDB, $formatter, $feedType, $serverInfo, $userInput, $isLoggedIn)
82e36802
A
97 {
98 $this->linkDB = $linkDB;
cf92b4dd 99 $this->formatter = $formatter;
82e36802
A
100 $this->feedType = $feedType;
101 $this->serverInfo = $serverInfo;
102 $this->userInput = $userInput;
103 $this->isLoggedIn = $isLoggedIn;
104 }
105
106 /**
107 * Build data for feed templates.
108 *
109 * @return array Formatted data for feeds templates.
110 */
111 public function buildData()
112 {
cf92b4dd 113 // Search for untagged bookmarks
7d86f40b
A
114 if (isset($this->userInput['searchtags']) && empty($this->userInput['searchtags'])) {
115 $this->userInput['searchtags'] = false;
116 }
117
82e36802 118 // Optionally filter the results:
cf92b4dd 119 $linksToDisplay = $this->linkDB->search($this->userInput);
82e36802
A
120
121 $nblinksToDisplay = $this->getNbLinks(count($linksToDisplay));
122
123 // Can't use array_keys() because $link is a LinkDB instance and not a real array.
124 $keys = array();
125 foreach ($linksToDisplay as $key => $value) {
126 $keys[] = $key;
127 }
128
129 $pageaddr = escape(index_url($this->serverInfo));
cf92b4dd 130 $this->formatter->addContextData('index_url', $pageaddr);
82e36802
A
131 $linkDisplayed = array();
132 for ($i = 0; $i < $nblinksToDisplay && $i < count($keys); $i++) {
133 $linkDisplayed[$keys[$i]] = $this->buildItem($linksToDisplay[$keys[$i]], $pageaddr);
134 }
135
136 $data['language'] = $this->getTypeLanguage();
82e36802
A
137 $data['last_update'] = $this->getLatestDateFormatted();
138 $data['show_dates'] = !$this->hideDates || $this->isLoggedIn;
139 // Remove leading slash from REQUEST_URI.
44a71809 140 $data['self_link'] = escape(server_url($this->serverInfo))
dfc650aa 141 . escape($this->serverInfo['REQUEST_URI']);
82e36802
A
142 $data['index_url'] = $pageaddr;
143 $data['usepermalinks'] = $this->usePermalinks === true;
144 $data['links'] = $linkDisplayed;
145
146 return $data;
147 }
148
149 /**
150 * Build a feed item (one per shaare).
151 *
cf92b4dd
A
152 * @param Bookmark $link Single link array extracted from LinkDB.
153 * @param string $pageaddr Index URL.
82e36802
A
154 *
155 * @return array Link array with feed attributes.
156 */
157 protected function buildItem($link, $pageaddr)
158 {
cf92b4dd
A
159 $data = $this->formatter->format($link);
160 $data['guid'] = $pageaddr . '?' . $data['shorturl'];
82e36802 161 if ($this->usePermalinks === true) {
cf92b4dd 162 $permalink = '<a href="'. $data['url'] .'" title="'. t('Direct link') .'">'. t('Direct link') .'</a>';
82e36802 163 } else {
cf92b4dd 164 $permalink = '<a href="'. $data['guid'] .'" title="'. t('Permalink') .'">'. t('Permalink') .'</a>';
82e36802 165 }
cf92b4dd 166 $data['description'] .= PHP_EOL . PHP_EOL . '<br>&#8212; ' . $permalink;
82e36802 167
cf92b4dd 168 $data['pub_iso_date'] = $this->getIsoDate($data['created']);
82e36802 169
c6d876bb 170 // atom:entry elements MUST contain exactly one atom:updated element.
cf92b4dd
A
171 if (!empty($link->getUpdated())) {
172 $data['up_iso_date'] = $this->getIsoDate($data['updated'], DateTime::ATOM);
82e36802 173 } else {
cf92b4dd 174 $data['up_iso_date'] = $this->getIsoDate($data['created'], DateTime::ATOM);
82e36802
A
175 }
176
177 // Save the more recent item.
cf92b4dd
A
178 if (empty($this->latestDate) || $this->latestDate < $data['created']) {
179 $this->latestDate = $data['created'];
c6d876bb 180 }
cf92b4dd
A
181 if (!empty($data['updated']) && $this->latestDate < $data['updated']) {
182 $this->latestDate = $data['updated'];
82e36802
A
183 }
184
cf92b4dd 185 return $data;
82e36802
A
186 }
187
82e36802 188 /**
cf92b4dd 189 * Set this to true to use permalinks instead of direct bookmarks.
82e36802
A
190 *
191 * @param boolean $usePermalinks true to force permalinks.
192 */
193 public function setUsePermalinks($usePermalinks)
194 {
195 $this->usePermalinks = $usePermalinks;
196 }
197
198 /**
199 * Set this to true to hide timestamps in feeds.
200 *
201 * @param boolean $hideDates true to enable.
202 */
203 public function setHideDates($hideDates)
204 {
205 $this->hideDates = $hideDates;
206 }
207
208 /**
209 * Set the locale. Used to show feed language.
210 *
211 * @param string $locale The locale (eg. 'fr_FR.UTF8').
212 */
213 public function setLocale($locale)
214 {
215 $this->locale = strtolower($locale);
216 }
217
218 /**
219 * Get the language according to the feed type, based on the locale:
220 *
221 * - RSS format: en-us (default: 'en-en').
222 * - ATOM format: fr (default: 'en').
223 *
224 * @return string The language.
225 */
226 public function getTypeLanguage()
227 {
228 // Use the locale do define the language, if available.
dfc650aa
V
229 if (!empty($this->locale) && preg_match('/^\w{2}[_\-]\w{2}/', $this->locale)) {
230 $length = ($this->feedType === self::$FEED_RSS) ? 5 : 2;
82e36802
A
231 return str_replace('_', '-', substr($this->locale, 0, $length));
232 }
dfc650aa 233 return ($this->feedType === self::$FEED_RSS) ? 'en-en' : 'en';
82e36802
A
234 }
235
236 /**
237 * Format the latest item date found according to the feed type.
238 *
239 * Return an empty string if invalid DateTime is passed.
240 *
241 * @return string Formatted date.
242 */
243 protected function getLatestDateFormatted()
244 {
245 if (empty($this->latestDate) || !$this->latestDate instanceof DateTime) {
246 return '';
247 }
248
249 $type = ($this->feedType == self::$FEED_RSS) ? DateTime::RSS : DateTime::ATOM;
250 return $this->latestDate->format($type);
251 }
252
c6d876bb
A
253 /**
254 * Get ISO date from DateTime according to feed type.
255 *
256 * @param DateTime $date Date to format.
257 * @param string|bool $format Force format.
258 *
259 * @return string Formatted date.
260 */
261 protected function getIsoDate(DateTime $date, $format = false)
262 {
263 if ($format !== false) {
264 return $date->format($format);
265 }
266 if ($this->feedType == self::$FEED_RSS) {
267 return $date->format(DateTime::RSS);
c6d876bb
A
268 }
269 return $date->format(DateTime::ATOM);
270 }
271
82e36802
A
272 /**
273 * Returns the number of link to display according to 'nb' user input parameter.
274 *
275 * If 'nb' not set or invalid, default value: $DEFAULT_NB_LINKS.
cf92b4dd 276 * If 'nb' is set to 'all', display all filtered bookmarks (max parameter).
82e36802 277 *
cf92b4dd 278 * @param int $max maximum number of bookmarks to display.
82e36802 279 *
cf92b4dd 280 * @return int number of bookmarks to display.
82e36802
A
281 */
282 public function getNbLinks($max)
283 {
284 if (empty($this->userInput['nb'])) {
285 return self::$DEFAULT_NB_LINKS;
286 }
287
288 if ($this->userInput['nb'] == 'all') {
289 return $max;
290 }
291
292 $intNb = intval($this->userInput['nb']);
dfc650aa 293 if (!is_int($intNb) || $intNb == 0) {
82e36802
A
294 return self::$DEFAULT_NB_LINKS;
295 }
296
297 return $intNb;
298 }
299}