Skip to content

Commit 33ba99f

Browse files
GrotaxSMillerDev
andcommitted
make sure href starts with /
Co-authored-by: Sean Molenaar <[email protected]>
1 parent 29601f3 commit 33ba99f

File tree

4 files changed

+163
-3
lines changed

4 files changed

+163
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
- Add logic to set the node's link from the <guid> element when isPermaLink="true" and no link is present. (#12)
1212

1313
### Fixed
14-
- Fix: Analysis of relative links for the Atom feed (#10)
14+
- Fix: Analysis of relative links for the Atom feed (#13)

src/FeedIo/Feed/Node.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ protected function setHostInContent(string $host = null): void
176176
$this->pregReplaceInProperty('description', $pattern, '\1\2\3'.$host.'\4');
177177

178178
$itemFullLink = $this->getLinkForAnalysis();
179-
$itemLink = implode("/", array_slice(explode("/", $itemFullLink), 0, -1))."/";
179+
$itemLink = implode("/", array_slice(explode("/", $itemFullLink ?? ''), 0, -1))."/";
180180

181181
// Replaced links like href="#aaa/bbb.xxx"
182182
$pattern = '(<\s*[^>]*)(href=|src=)(.?)(#)(?!(.(?!<code))*<\/code>)';

src/FeedIo/Rule/Atom/Link.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,14 @@ protected function selectAlternateLink(NodeInterface $node, \DOMElement $element
3030
) {
3131
$href = $element->getAttribute('href');
3232
if (parse_url($href, PHP_URL_HOST) == null) {
33-
$href = $node->getHostFromLink(). $href;
33+
$baseUrl = $node->getHostFromLink();
34+
if ($baseUrl !== null) {
35+
// Add slash if href doesn't start with one
36+
if (!str_starts_with($href, '/')) {
37+
$href = '/' . $href;
38+
}
39+
$href = $baseUrl . $href;
40+
}
3441
}
3542
$node->setLink($href);
3643
}

tests/FeedIo/Rule/Atom/LinkTest.php

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,157 @@ public function testCreateElement()
6060
$document->saveXML()
6161
);
6262
}
63+
64+
public function testRelativeHrefWithoutLeadingSlash()
65+
{
66+
$item = new Item();
67+
$item->setLink('https://example.com/some/path.html');
68+
$document = new \DOMDocument();
69+
70+
$link = $document->createElement('link');
71+
$link->setAttribute('href', 'page.html');
72+
$link->setAttribute('rel', 'alternate');
73+
$this->object->setProperty($item, $link);
74+
75+
$this->assertEquals('https://example.com/page.html', $item->getLink());
76+
}
77+
78+
public function testRelativeHrefWithLeadingSlash()
79+
{
80+
$item = new Item();
81+
$item->setLink('https://example.com/some/path.html');
82+
$document = new \DOMDocument();
83+
84+
$link = $document->createElement('link');
85+
$link->setAttribute('href', '/absolute/path.html');
86+
$link->setAttribute('rel', 'alternate');
87+
$this->object->setProperty($item, $link);
88+
89+
$this->assertEquals('https://example.com/absolute/path.html', $item->getLink());
90+
}
91+
92+
public function testAbsoluteHrefIsNotModified()
93+
{
94+
$item = new Item();
95+
$item->setLink('https://example.com/some/path.html');
96+
$document = new \DOMDocument();
97+
98+
$link = $document->createElement('link');
99+
$link->setAttribute('href', 'https://other.com/page.html');
100+
$link->setAttribute('rel', 'alternate');
101+
$this->object->setProperty($item, $link);
102+
103+
$this->assertEquals('https://other.com/page.html', $item->getLink());
104+
}
105+
106+
public function testNonAlternateLinkIsIgnored()
107+
{
108+
$item = new Item();
109+
$item->setLink('https://example.com/original.html');
110+
$document = new \DOMDocument();
111+
112+
$link = $document->createElement('link');
113+
$link->setAttribute('href', '/new/path.html');
114+
$link->setAttribute('rel', 'stylesheet');
115+
$this->object->setProperty($item, $link);
116+
117+
$this->assertEquals('https://example.com/original.html', $item->getLink());
118+
}
119+
120+
public function testLinkWithoutRelAttributeWhenNodeLinkIsNull()
121+
{
122+
$item = new Item();
123+
$item->setLink(null);
124+
$document = new \DOMDocument();
125+
126+
$link = $document->createElement('link');
127+
$link->setAttribute('href', '/path.html');
128+
$this->object->setProperty($item, $link);
129+
130+
$this->assertEquals('/path.html', $item->getLink());
131+
}
132+
133+
public function testLinkWithNullBaseUrl()
134+
{
135+
$item = new Item();
136+
$item->setLink(null);
137+
$document = new \DOMDocument();
138+
139+
$link = $document->createElement('link');
140+
$link->setAttribute('href', 'relative.html');
141+
$link->setAttribute('rel', 'alternate');
142+
$this->object->setProperty($item, $link);
143+
144+
$this->assertEquals('relative.html', $item->getLink());
145+
}
146+
147+
public function testProtocolRelativeUrl()
148+
{
149+
$item = new Item();
150+
$item->setLink('https://example.com/path.html');
151+
$document = new \DOMDocument();
152+
153+
$link = $document->createElement('link');
154+
$link->setAttribute('href', '//cdn.example.com/resource.css');
155+
$link->setAttribute('rel', 'alternate');
156+
$this->object->setProperty($item, $link);
157+
158+
$this->assertEquals('//cdn.example.com/resource.css', $item->getLink());
159+
}
160+
161+
public function testFragmentUrl()
162+
{
163+
$item = new Item();
164+
$item->setLink('https://example.com/page.html');
165+
$document = new \DOMDocument();
166+
167+
$link = $document->createElement('link');
168+
$link->setAttribute('href', '#section1');
169+
$link->setAttribute('rel', 'alternate');
170+
$this->object->setProperty($item, $link);
171+
172+
$this->assertEquals('https://example.com/#section1', $item->getLink());
173+
}
174+
175+
public function testQueryParameterUrl()
176+
{
177+
$item = new Item();
178+
$item->setLink('https://example.com/page.html');
179+
$document = new \DOMDocument();
180+
181+
$link = $document->createElement('link');
182+
$link->setAttribute('href', '?param=value');
183+
$link->setAttribute('rel', 'alternate');
184+
$this->object->setProperty($item, $link);
185+
186+
$this->assertEquals('https://example.com/?param=value', $item->getLink());
187+
}
188+
189+
public function testHttpScheme()
190+
{
191+
$item = new Item();
192+
$item->setLink('http://example.com/path.html');
193+
$document = new \DOMDocument();
194+
195+
$link = $document->createElement('link');
196+
$link->setAttribute('href', '/secure/path.html');
197+
$link->setAttribute('rel', 'alternate');
198+
$this->object->setProperty($item, $link);
199+
200+
$this->assertEquals('http://example.com/secure/path.html', $item->getLink());
201+
}
202+
203+
public function testEmptyHref()
204+
{
205+
$item = new Item();
206+
$item->setLink('https://example.com/original.html');
207+
$document = new \DOMDocument();
208+
209+
$link = $document->createElement('link');
210+
$link->setAttribute('href', '');
211+
$link->setAttribute('rel', 'alternate');
212+
$this->object->setProperty($item, $link);
213+
214+
$this->assertEquals('https://example.com/', $item->getLink());
215+
}
63216
}

0 commit comments

Comments
 (0)