Skip to content

Commit

Permalink
Adding BaseUri::unixPath and BaseUri::windowsPath (#125)
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod authored Sep 29, 2023
1 parent bae16ca commit e457b42
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 1 deletion.
16 changes: 16 additions & 0 deletions docs/uri/7.0/base-uri.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,19 @@ use League\Uri\BaseUri;

BaseUri::from((Http::new('/path/to/endpoint'))->origin(); //returns null
~~~

### BaseUri::unixPath and BaseUri::windowsPath

<p class="message-notice">since version <code>7.3.0</code></p>

Returns the OS specific path from a URI.

~~~php
BaseUri::from('file://server/share/My%20Documents%20100%2520/foo.txt')->windowsPath();
//returns '\\server\share\My Documents 100%20\foo.txt'

BaseUri::from('file:///path%20empty/bar')->unixPath();
//returns '/path empty/bar'
~~~

If the URI scheme is present and is not the `file` scheme, `null` will be returned,
51 changes: 51 additions & 0 deletions uri/BaseUri.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@
use function end;
use function explode;
use function implode;
use function in_array;
use function preg_match;
use function rawurldecode;
use function str_repeat;
use function str_replace;
use function strpos;
use function substr;

Expand Down Expand Up @@ -98,6 +102,53 @@ public function origin(): ?self
};
}

/**
* Returns the Unix filesystem path.
*
* The method will return null if a scheme is present and is not the `file` scheme
*/
public function unixPath(): ?string
{
return match ($this->uri->getScheme()) {
'file', $this->nullValue => rawurldecode($this->uri->getPath()),
default => null,
};
}

/**
* Returns the Windows filesystem path.
*
* The method will return null if a scheme is present and is not the `file` scheme
*/
public function windowsPath(): ?string
{
static $regexpWindowsPath = ',^(?<root>[a-zA-Z]:),';

if (!in_array($this->uri->getScheme(), ['file', $this->nullValue], true)) {
return null;
}

$originalPath = $this->uri->getPath();
$path = $originalPath;
if ('/' === ($path[0] ?? '')) {
$path = substr($path, 1);
}

if (1 === preg_match($regexpWindowsPath, $path, $matches)) {
$root = $matches['root'];
$path = substr($path, strlen($root));

return $root.str_replace('/', '\\', rawurldecode($path));
}

$host = $this->uri->getHost();

return match ($this->nullValue) {
$host => str_replace('/', '\\', rawurldecode($originalPath)),
default => '\\\\'.$host.'\\'.str_replace('/', '\\', rawurldecode($path)),
};
}

/**
* Tells whether two URI do not share the same origin.
*/
Expand Down
87 changes: 87 additions & 0 deletions uri/BaseUriTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -488,4 +488,91 @@ public static function provideIDNUri(): iterable
'expected' => false,
];
}

/** @dataProvider unixpathProvider */
public function testReturnsUnixPath(?string $expected, string $input): void
{
self::assertSame($expected, BaseUri::from($input)->unixPath());
self::assertSame($expected, BaseUri::from(Utils::uriFor($input))->unixPath());
}

public static function unixpathProvider(): array
{
return [
'relative path' => [
'expected' => 'path',
'input' => 'path',
],
'absolute path' => [
'expected' => '/path',
'inout' => 'file:///path',
],
'path with empty char' => [
'expected' => '/path empty/bar',
'inout' => 'file:///path%20empty/bar',
],
'relative path with dot segments' => [
'expected' => 'path/./relative',
'input' => 'path/./relative',
],
'absolute path with dot segments' => [
'expected' => '/path/./../relative',
'input' => 'file:///path/./../relative',
],
'unsupported scheme' => [
'expected' => null,
'input' => 'http://example.com/foo/bar',
],
];
}

/** @dataProvider windowLocalPathProvider */
public function testReturnsWindowsPath(?string $expected, string $input): void
{
self::assertSame($expected, BaseUri::from($input)->windowsPath());
self::assertSame($expected, BaseUri::from(Utils::uriFor($input))->windowsPath());

}

public static function windowLocalPathProvider(): array
{
return [
'relative path' => [
'expected' => 'path',
'input' => 'path',
],
'relative path with dot segments' => [
'expected' => 'path\.\relative',
'input' => 'path/./relative',
],
'absolute path' => [
'expected' => 'c:\windows\My Documents 100%20\foo.txt',
'input' => 'file:///c:/windows/My%20Documents%20100%2520/foo.txt',
],
'windows relative path' => [
'expected' => 'c:My Documents 100%20\foo.txt',
'input' => 'file:///c:My%20Documents%20100%2520/foo.txt',
],
'absolute path with `|`' => [
'expected' => 'c:\windows\My Documents 100%20\foo.txt',
'input' => 'file:///c:/windows/My%20Documents%20100%2520/foo.txt',
],
'windows relative path with `|`' => [
'expected' => 'c:My Documents 100%20\foo.txt',
'input' => 'file:///c:My%20Documents%20100%2520/foo.txt',
],
'absolute path with dot segments' => [
'expected' => '\path\.\..\relative',
'input' => '/path/./../relative',
],
'absolute UNC path' => [
'expected' => '\\\\server\share\My Documents 100%20\foo.txt',
'input' => 'file://server/share/My%20Documents%20100%2520/foo.txt',
],
'unsupported scheme' => [
'expected' => null,
'input' => 'http://example.com/foo/bar',
],
];
}
}
3 changes: 2 additions & 1 deletion uri/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ All Notable changes to `League\Uri` will be documented in this file

### Added

- None
- `BaseUri::unixPath`
- `BaseUri::windowsPath`

### Fixed

Expand Down

0 comments on commit e457b42

Please sign in to comment.