Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for issue #209 #210

Merged
merged 8 commits into from
Jun 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 1.0.9
## Bugfixes
- #209 Fix Url helper parsing of Uri with parameters

# 1.0.8
## Bugfixes
- #186 Removed dead code in File class
Expand Down
110 changes: 95 additions & 15 deletions src/Entities/Url.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,7 @@ public function parse($uri = '')
$this->loadSiteUrl();
$uri = $this->cleanUri($uri);

$parts = explode('/', $uri);
foreach ($parts as &$part) {
if (strpos($part, 'index') !== false) {
$part = null;
continue;
}
$part = rawurlencode($part);
}
unset($part);

$parts = array_filter($parts, function ($value) {
return ! is_null($value);
});

return $this->siteUrl.'/'.implode('/', $parts);
return $this->siteUrl.'/'.$this->encode($uri);
}

private function loadSiteUrl()
Expand All @@ -70,4 +56,98 @@ private function cleanUri($text)

return ($text === false) ? '' : $text;
}

/**
* @param string $uri
* @return array
*/
private function encode($uri = '')
{
$parts = explode('/', $uri);
foreach ($parts as &$part) {
if (strpos($part, 'index') !== false) {
$part = null;
continue;
}
$part = $this->encodePart($part);
}
unset($part);

$parts = array_filter($parts, function ($value) {
return ! is_null($value);
});

// If the last uri part doesn't contain a file name e.g. index.html or readme.txt

$e = end($parts);
if (
strlen($e) > 0 &&
strpos($e, '?') === false &&
strpos($e, '=') === false &&
strpos($e, '&') === false &&
strpos($e, '#') === false &&
strpos($e, '.') === false
) {
array_push($parts, '');
}

return trim(implode('/', $parts));
}

/**
* Ensures that uri parts containing ? or # get encoded correctly.
*
* @param string $part
* @return string
*/
private function encodePart($part)
{
if (strpos($part, '?') !== false) {
if (strpos($part, '?') === 0) {
$output = '?';
$part = substr($part, 1);
} else {
$pe = explode('?', $part);
$output = $pe[0].'/?';
$part = $pe[1];
unset($pe);
}

if (strpos($part, '&')) {
$parts = explode('&', $part);
} else {
$parts = [$part];
}
foreach ($parts as &$p) {
if (strpos($p, '=') !== false) {
$pe = explode('=', $p);
$p = $pe[0].'='.urlencode($pe[1]);
}
}
unset($p, $pe);

$output .= implode('&', $parts);

return $output;
}

if (strpos($part, '#') !== false) {
if (strpos($part, '#') === 0) {
if (substr($part, 1, 1) === '!') {
return '#!'.rawurlencode(substr($part, 2));
}

return '#'.rawurlencode(substr($part, 1));
}

$pe = explode('#', $part);
if (substr($pe[1], 0, 1) === '!') {
return $pe[0].'/#!'.rawurlencode(substr($pe[1], 1));
}

return $pe[0].'/#'.rawurlencode($pe[1]);
}

return rawurlencode($part);
}
}
53 changes: 39 additions & 14 deletions tests/EntitiesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,58 @@ public function testUrlEntity()
$this->assertSame('http://www.example.com/', $url->parse(''));
$this->assertSame('http://www.example.com/', $url->parse('/'));

$this->assertSame('http://www.example.com/?abc=123&def=456', $url->parse('?abc=123&def=456'));
$this->assertSame('http://www.example.com/?abc=123&def=456', $url->parse('/?abc=123&def=456'));

$this->assertSame('http://www.example.com/abc', $url->parse('abc'));
$this->assertSame('http://www.example.com/abc', $url->parse('/abc'));
$this->assertSame('http://www.example.com/#abc-123', $url->parse('#abc-123'));
$this->assertSame('http://www.example.com/#abc-123', $url->parse('/#abc-123'));

$this->assertSame('http://www.example.com/abc/', $url->parse('abc'));
$this->assertSame('http://www.example.com/abc/', $url->parse('/abc'));
$this->assertSame('http://www.example.com/abc/', $url->parse('/abc/'));

$this->assertSame('http://www.example.com/abc/123', $url->parse('abc/123'));
$this->assertSame('http://www.example.com/abc/123', $url->parse('/abc/123'));
$this->assertSame('http://www.example.com/abc/#!abc', $url->parse('abc#!abc'));
$this->assertSame('http://www.example.com/abc/#!abc', $url->parse('/abc#!abc'));
$this->assertSame('http://www.example.com/abc/#!abc', $url->parse('/abc/#!abc'));

$this->assertSame('http://www.example.com/abc/123/', $url->parse('abc/123'));
$this->assertSame('http://www.example.com/abc/123/', $url->parse('/abc/123'));
$this->assertSame('http://www.example.com/abc/123/', $url->parse('/abc/123/'));

$this->assertEquals('http://www.example.com/abc', $url->parse('abc/index.html'));
$this->assertEquals('http://www.example.com/abc/123', $url->parse('abc/123/index.html'));
$this->assertSame('http://www.example.com/abc/123/?abc=123&def=456', $url->parse('abc/123?abc=123&def=456'));
$this->assertSame('http://www.example.com/abc/123/?abc=123&def=456', $url->parse('/abc/123?abc=123&def=456'));
$this->assertSame('http://www.example.com/abc/123/?abc=123&def=456', $url->parse('/abc/123/?abc=123&def=456'));

$this->assertSame('http://www.example.com/abc/123/?abc=123+xyz&def=456+abc', $url->parse('abc/123?abc=123 xyz&def=456 abc'));
$this->assertSame('http://www.example.com/abc/123/?abc=123+xyz&def=456+abc', $url->parse('/abc/123?abc=123 xyz&def=456 abc'));
$this->assertSame('http://www.example.com/abc/123/?abc=123+xyz&def=456+abc', $url->parse('/abc/123/?abc=123 xyz&def=456 abc'));

$this->assertSame('http://www.example.com/abc/123/#abc-123', $url->parse('abc/123#abc-123'));
$this->assertSame('http://www.example.com/abc/123/#abc-123', $url->parse('/abc/123#abc-123'));
$this->assertSame('http://www.example.com/abc/123/#abc-123', $url->parse('/abc/123/#abc-123'));

$this->assertSame('http://www.example.com/abc/123/#abc%20123', $url->parse('abc/123#abc 123'));
$this->assertSame('http://www.example.com/abc/123/#abc%20123', $url->parse('/abc/123#abc 123'));
$this->assertSame('http://www.example.com/abc/123/#abc%20123', $url->parse('/abc/123/#abc 123'));

$this->assertEquals('http://www.example.com/abc/', $url->parse('abc/index.html'));
$this->assertEquals('http://www.example.com/abc/123/', $url->parse('abc/123/index.html'));
$this->assertEquals('http://www.example.com/abc/123.html', $url->parse('abc/123.html'));

$this->assertEquals('http://www.example.com/0', $url->parse(0));
$this->assertEquals('http://www.example.com/0/', $url->parse(0));
$this->assertEquals('http://www.example.com/', $url->parse(null));
$this->assertEquals('http://www.example.com/-1', $url->parse(-1));
$this->assertEquals('http://www.example.com/3.33', $url->parse(3.33));
$this->assertEquals('http://www.example.com/-1/', $url->parse(-1));
$this->assertEquals('http://www.example.com/3.33', $url->parse(3.33)); // 3.33 is a file named 3 with the ext 33

$this->assertSame('http://www.example.com/hello%20world', $url->parse('hello world'));
$this->assertSame('http://www.example.com/hello%20world', $url->parse('/hello world'));
$this->assertSame('http://www.example.com/hello%20world/', $url->parse('hello world'));
$this->assertSame('http://www.example.com/hello%20world/', $url->parse('/hello world'));
$this->assertSame('http://www.example.com/hello%20world/', $url->parse('/hello world/'));

$this->assertSame('http://www.example.com/hello%20world/this%20is%20a%20test', $url->parse('hello world/this is a test'));
$this->assertSame('http://www.example.com/hello%20world/this%20is%20a%20test', $url->parse('/hello world/this is a test'));
$this->assertSame('http://www.example.com/hello%20world/this%20is%20a%20test/', $url->parse('hello world/this is a test'));
$this->assertSame('http://www.example.com/hello%20world/this%20is%20a%20test/', $url->parse('/hello world/this is a test'));
$this->assertSame('http://www.example.com/hello%20world/this%20is%20a%20test/', $url->parse('/hello world/this is a test/'));

$this->assertSame('http://www.example.com/hello/world', $url->parse('hello/world/index.html'));
$this->assertSame('http://www.example.com/hello/world/', $url->parse('hello/world/index.html'));
}

public function testUrlEntityThrowsException()
Expand Down
2 changes: 1 addition & 1 deletion tests/ViewFileTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public function testGetUrlHelper()
__DIR__ . '/mocks/TestExcerptFile.md', ['site' => ['url' => 'http://www.example.com']]
);

$this->assertEquals('http://www.example.com/testexcerptfile', $viewFile->getUrl());
$this->assertEquals('http://www.example.com/testexcerptfile/', $viewFile->getUrl());

$viewFile->getFile()->setData(['permalink' => '/folder1/folder2/folder3/test.html']);
$this->assertEquals('http://www.example.com/folder1/folder2/folder3/test.html', $viewFile->getUrl());
Expand Down