Skip to content

Commit bc0d8ac

Browse files
imp: Allow to set feeds alternate to original links
1 parent 0a474ba commit bc0d8ac

File tree

6 files changed

+129
-8
lines changed

6 files changed

+129
-8
lines changed

src/controllers/collections/Feeds.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ class Feeds
1717
* Show the feed of a collection.
1818
*
1919
* @request_param string id
20+
* @request_param boolean direct
21+
* Indicate if <link rel=alternate> should point directly to the
22+
* external websites (true) or not (false, default).
2023
*
2124
* @response 404
2225
* if the collection doesn’t exist or is inaccessible
@@ -28,8 +31,9 @@ public function show($request)
2831
{
2932
$user = auth\CurrentUser::get();
3033
$collection_id = $request->param('id');
31-
$collection = models\Collection::find($collection_id);
34+
$direct = $request->paramBoolean('direct', false);
3235

36+
$collection = models\Collection::find($collection_id);
3337
if (!auth\CollectionsAccess::canView($user, $collection)) {
3438
return Response::notFound('not_found.phtml');
3539
}
@@ -54,6 +58,7 @@ public function show($request)
5458
'topics' => $topics,
5559
'links' => $links,
5660
'user_agent' => \Minz\Configuration::$application['user_agent'],
61+
'direct' => $direct,
5762
]);
5863
$response->setHeader('X-Content-Type-Options', 'nosniff');
5964
return $response;
@@ -70,6 +75,9 @@ public function alias($request)
7075
{
7176
$collection_id = $request->param('id');
7277
$url = \Minz\Url::for('collection feed', ['id' => $collection_id]);
78+
if (!empty($_SERVER['QUERY_STRING'])) {
79+
$url .= '?' . $_SERVER['QUERY_STRING'];
80+
}
7381
return Response::movedPermanently($url);
7482
}
7583
}

src/controllers/profiles/Feeds.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ class Feeds
1717
* Show the feed of a user.
1818
*
1919
* @request_param string id
20+
* @request_param boolean direct
21+
* Indicate if <link rel=alternate> should point directly to the
22+
* external websites (true) or not (false, default).
2023
*
2124
* @response 404
2225
* If the requested profile doesn’t exist or is associated to the
@@ -27,8 +30,9 @@ class Feeds
2730
public function show($request)
2831
{
2932
$user_id = $request->param('id');
30-
$user = models\User::find($user_id);
33+
$direct = $request->paramBoolean('direct', false);
3134

35+
$user = models\User::find($user_id);
3236
if (!$user || $user->isSupportUser()) {
3337
return Response::notFound('not_found.phtml');
3438
}
@@ -43,6 +47,7 @@ public function show($request)
4347
'user' => $user,
4448
'links' => $links,
4549
'user_agent' => \Minz\Configuration::$application['user_agent'],
50+
'direct' => $direct,
4651
]);
4752
$response->setHeader('X-Content-Type-Options', 'nosniff');
4853
return $response;
@@ -59,6 +64,9 @@ public function alias($request)
5964
{
6065
$user_id = $request->param('id');
6166
$url = \Minz\Url::for('profile feed', ['id' => $user_id]);
67+
if (!empty($_SERVER['QUERY_STRING'])) {
68+
$url .= '?' . $_SERVER['QUERY_STRING'];
69+
}
6270
return Response::movedPermanently($url);
6371
}
6472
}

src/views/collections/feeds/show.atom.xml.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,13 @@
3030
<title><?= protect($link->title) ?></title>
3131
<id><?= $link->tagUri() ?></id>
3232

33-
<link href="<?= url_full('link', ['id' => $link->id]) ?>" rel="alternate" type="text/html" />
34-
<link href="<?= protect($link->url) ?>" rel="via" type="text/html" />
33+
<?php if ($direct): ?>
34+
<link href="<?= protect($link->url) ?>" rel="alternate" type="text/html" />
35+
<link href="<?= url_full('link', ['id' => $link->id]) ?>" rel="replies" type="text/html" />
36+
<?php else: ?>
37+
<link href="<?= url_full('link', ['id' => $link->id]) ?>" rel="alternate" type="text/html" />
38+
<link href="<?= protect($link->url) ?>" rel="via" type="text/html" />
39+
<?php endif; ?>
3540

3641
<?php
3742
$messages = $link->messages();

src/views/profiles/feeds/show.atom.xml.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@
2323
<title><?= protect($link->title) ?></title>
2424
<id><?= $link->tagUri() ?></id>
2525

26-
<link href="<?= url_full('link', ['id' => $link->id]) ?>" rel="alternate" type="text/html" />
27-
<link href="<?= protect($link->url) ?>" rel="via" type="text/html" />
26+
<?php if ($direct): ?>
27+
<link href="<?= protect($link->url) ?>" rel="alternate" type="text/html" />
28+
<link href="<?= url_full('link', ['id' => $link->id]) ?>" rel="replies" type="text/html" />
29+
<?php else: ?>
30+
<link href="<?= url_full('link', ['id' => $link->id]) ?>" rel="alternate" type="text/html" />
31+
<link href="<?= protect($link->url) ?>" rel="via" type="text/html" />
32+
<?php endif; ?>
2833

2934
<?php
3035
$messages = $link->messages();

tests/controllers/collections/FeedsTest.php

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ class FeedsTest extends \PHPUnit\Framework\TestCase
1313
public function testShowRendersCorrectly()
1414
{
1515
$link_title = $this->fake('words', 3, true);
16+
$link_url = $this->fake('url');
1617
$collection_id = $this->create('collection', [
1718
'type' => 'collection',
1819
'is_public' => 1,
1920
]);
2021
$link_id = $this->create('link', [
2122
'title' => $link_title,
23+
'url' => $link_url,
2224
'is_hidden' => 0,
2325
]);
2426
$this->create('link_to_collection', [
@@ -29,12 +31,45 @@ public function testShowRendersCorrectly()
2931
$response = $this->appRun('get', "/collections/{$collection_id}/feed.atom.xml");
3032

3133
$this->assertResponseCode($response, 200);
32-
$this->assertResponseContains($response, $link_title);
3334
$this->assertResponsePointer($response, 'collections/feeds/show.atom.xml.php');
3435
$this->assertResponseHeaders($response, [
3536
'Content-Type' => 'application/xml',
3637
'X-Content-Type-Options' => 'nosniff',
3738
]);
39+
$feed = \SpiderBits\feeds\Feed::fromText($response->render());
40+
$link_alternate = \Minz\Url::absoluteFor('link', ['id' => $link_id]);
41+
$this->assertSame(1, count($feed->entries));
42+
$this->assertSame($link_title, $feed->entries[0]->title);
43+
$this->assertSame($link_alternate, $feed->entries[0]->links['alternate']);
44+
$this->assertSame($link_url, $feed->entries[0]->links['via']);
45+
}
46+
47+
public function testShowRendersAlternateLinksAsOriginalUrlWithDirectTrue()
48+
{
49+
$link_url = $this->fake('url');
50+
$collection_id = $this->create('collection', [
51+
'type' => 'collection',
52+
'is_public' => 1,
53+
]);
54+
$link_id = $this->create('link', [
55+
'url' => $link_url,
56+
'is_hidden' => 0,
57+
]);
58+
$this->create('link_to_collection', [
59+
'link_id' => $link_id,
60+
'collection_id' => $collection_id,
61+
]);
62+
63+
$response = $this->appRun('get', "/collections/{$collection_id}/feed.atom.xml", [
64+
'direct' => true,
65+
]);
66+
67+
$this->assertResponseCode($response, 200);
68+
$feed = \SpiderBits\feeds\Feed::fromText($response->render());
69+
$link_replies = \Minz\Url::absoluteFor('link', ['id' => $link_id]);
70+
$this->assertSame(1, count($feed->entries));
71+
$this->assertSame($link_url, $feed->entries[0]->links['alternate']);
72+
$this->assertSame($link_replies, $feed->entries[0]->links['replies']);
3873
}
3974

4075
public function testShowDoesNotRenderHiddenLinks()
@@ -102,4 +137,15 @@ public function testAliasRedirectsToShow()
102137

103138
$this->assertResponseCode($response, 301, "/collections/{$collection_id}/feed.atom.xml");
104139
}
140+
141+
public function testAliasRedirectsWithQuery()
142+
{
143+
$collection_id = $this->create('collection');
144+
$_SERVER['QUERY_STRING'] = 'direct=true';
145+
146+
$response = $this->appRun('get', "/collections/{$collection_id}/feed");
147+
148+
$_SERVER['QUERY_STRING'] = '';
149+
$this->assertResponseCode($response, 301, "/collections/{$collection_id}/feed.atom.xml?direct=true");
150+
}
105151
}

tests/controllers/profiles/FeedsTest.php

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public function testShowRendersCorrectly()
1414
{
1515
$user_id = $this->create('user');
1616
$link_title = $this->fake('words', 3, true);
17+
$link_url = $this->fake('url');
1718
$collection_id = $this->create('collection', [
1819
'user_id' => $user_id,
1920
'type' => 'collection',
@@ -23,6 +24,7 @@ public function testShowRendersCorrectly()
2324
'user_id' => $user_id,
2425
'is_hidden' => 0,
2526
'title' => $link_title,
27+
'url' => $link_url,
2628
]);
2729
$this->create('link_to_collection', [
2830
'collection_id' => $collection_id,
@@ -33,11 +35,47 @@ public function testShowRendersCorrectly()
3335

3436
$this->assertResponseCode($response, 200);
3537
$this->assertResponsePointer($response, 'profiles/feeds/show.atom.xml.php');
36-
$this->assertResponseContains($response, $link_title);
3738
$this->assertResponseHeaders($response, [
3839
'Content-Type' => 'application/xml',
3940
'X-Content-Type-Options' => 'nosniff',
4041
]);
42+
$feed = \SpiderBits\feeds\Feed::fromText($response->render());
43+
$link_alternate = \Minz\Url::absoluteFor('link', ['id' => $link_id]);
44+
$this->assertSame(1, count($feed->entries));
45+
$this->assertSame($link_title, $feed->entries[0]->title);
46+
$this->assertSame($link_alternate, $feed->entries[0]->links['alternate']);
47+
$this->assertSame($link_url, $feed->entries[0]->links['via']);
48+
}
49+
50+
public function testShowRendersAlternateLinksAsOriginalUrlWithDirectTrue()
51+
{
52+
$user_id = $this->create('user');
53+
$link_url = $this->fake('url');
54+
$collection_id = $this->create('collection', [
55+
'user_id' => $user_id,
56+
'type' => 'collection',
57+
'is_public' => 1,
58+
]);
59+
$link_id = $this->create('link', [
60+
'user_id' => $user_id,
61+
'is_hidden' => 0,
62+
'url' => $link_url,
63+
]);
64+
$this->create('link_to_collection', [
65+
'collection_id' => $collection_id,
66+
'link_id' => $link_id,
67+
]);
68+
69+
$response = $this->appRun('get', "/p/{$user_id}/feed.atom.xml", [
70+
'direct' => 'true',
71+
]);
72+
73+
$this->assertResponseCode($response, 200);
74+
$feed = \SpiderBits\feeds\Feed::fromText($response->render());
75+
$link_replies = \Minz\Url::absoluteFor('link', ['id' => $link_id]);
76+
$this->assertSame(1, count($feed->entries));
77+
$this->assertSame($link_url, $feed->entries[0]->links['alternate']);
78+
$this->assertSame($link_replies, $feed->entries[0]->links['replies']);
4179
}
4280

4381
public function testShowDoesNotRenderHiddenLinks()
@@ -121,4 +159,15 @@ public function testAliasRedirectsToShow()
121159

122160
$this->assertResponseCode($response, 301, "/p/{$user_id}/feed.atom.xml");
123161
}
162+
163+
public function testAliasRedirectsWithQuery()
164+
{
165+
$user_id = $this->create('user');
166+
$_SERVER['QUERY_STRING'] = 'direct=true';
167+
168+
$response = $this->appRun('get', "/p/{$user_id}/feed");
169+
170+
$_SERVER['QUERY_STRING'] = '';
171+
$this->assertResponseCode($response, 301, "/p/{$user_id}/feed.atom.xml?direct=true");
172+
}
124173
}

0 commit comments

Comments
 (0)