Compare commits
14 Commits
Author | SHA1 | Date |
---|---|---|
|
9b7d03c546 | 7 months ago |
|
c512bc3114 | 7 months ago |
|
0283f79c7b | 7 months ago |
|
844d094d49 | 7 months ago |
|
ca67c164fe | 7 months ago |
|
a49fd421d0 | 7 months ago |
|
b70f1fb0de | 7 months ago |
|
3279992be7 | 7 months ago |
|
f2e6216765 | 7 months ago |
|
bbddefc0de | 7 months ago |
|
deb4524b8f | 7 months ago |
|
9e438c2a2c | 7 months ago |
|
dce3a58477 | 7 months ago |
|
58fe768a21 | 7 months ago |
18 changed files with 735 additions and 2 deletions
@ -0,0 +1,69 @@
|
||||
stages: |
||||
- test |
||||
- report |
||||
|
||||
cache: |
||||
key: composer-cache |
||||
paths: |
||||
- .composer-cache/ |
||||
|
||||
.test: |
||||
before_script: |
||||
# install system packages |
||||
- apt-get update && apt-get install -y git unzip |
||||
# install extensions |
||||
- if [ "$INSTALL_XDEBUG" -eq 1 ]; then curl --location https://github.com/FriendsOfPHP/pickle/releases/latest/download/pickle.phar --output pickle.phar; php pickle.phar install --defaults xdebug; docker-php-ext-enable xdebug; fi |
||||
# install composer |
||||
- php -r "copy('https://composer.github.io/installer.sig', '/tmp/composer.sig');" |
||||
- php -r "copy('https://getcomposer.org/installer', '/tmp/composer-setup.php');" |
||||
- php -r '$expected = file_get_contents("/tmp/composer.sig"); $actual = hash_file("sha384", "/tmp/composer-setup.php"); exit(intval(!hash_equals($expected, $actual)));' |
||||
- php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer |
||||
- chmod +x /usr/local/bin/composer |
||||
- rm /tmp/composer-setup.php /tmp/composer.sig |
||||
# cache dependencies |
||||
- composer config -g cache-dir "$(pwd)/.composer-cache" |
||||
script: |
||||
- composer update |
||||
- vendor/bin/phpunit |
||||
|
||||
# lowest version with lowest dependencies |
||||
test-7.4-lowest: |
||||
extends: .test |
||||
stage: test |
||||
image: php:7.4 |
||||
script: |
||||
- composer update --prefer-lowest |
||||
- vendor/bin/phpunit |
||||
|
||||
# lowest version |
||||
test-7.4: |
||||
extends: .test |
||||
stage: test |
||||
image: php:7.4 |
||||
|
||||
## current release |
||||
test-8.0: |
||||
extends: .test |
||||
stage: test |
||||
image: php:8.0 |
||||
|
||||
# latest unstable |
||||
test-rc: |
||||
extends: .test |
||||
stage: test |
||||
image: php:rc |
||||
allow_failure: true |
||||
|
||||
# coverage |
||||
coverage: |
||||
variables: |
||||
INSTALL_XDEBUG: 1 |
||||
extends: .test |
||||
stage: report |
||||
only: |
||||
- master |
||||
image: php:8.0 |
||||
script: |
||||
- composer update |
||||
- XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-clover coverage.xml |
||||
- bash <(curl -s https://codecov.io/bash) |
@ -0,0 +1,25 @@
|
||||
The MIT License (MIT) |
||||
===================== |
||||
|
||||
Copyright © 2021 Anton Smirnov |
||||
|
||||
Permission is hereby granted, free of charge, to any person |
||||
obtaining a copy of this software and associated documentation |
||||
files (the “Software”), to deal in the Software without |
||||
restriction, including without limitation the rights to use, |
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following |
||||
conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be |
||||
included in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, |
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||||
OTHER DEALINGS IN THE SOFTWARE. |
@ -0,0 +1,55 @@
|
||||
# PHP Path Library |
||||
|
||||
[](https://packagist.org/packages/arokettu/path) |
||||
[](https://packagist.org/packages/arokettu/path) |
||||
[](https://opensource.org/licenses/MIT) |
||||
[](https://gitlab.com/sandfox/php-path/-/pipelines) |
||||
[](https://codecov.io/gl/sandfox/php-path/) |
||||
|
||||
A PHP library to work with absolute and relative paths. |
||||
|
||||
## Usage |
||||
|
||||
```php |
||||
<?php |
||||
|
||||
use Arokettu\Path\PathUtils; |
||||
use Arokettu\Path\RelativePath; |
||||
use Arokettu\Path\UrlPath; |
||||
|
||||
// simple interface |
||||
|
||||
PathUtils::resolveRelativePath('/some/path', '../other/path'); |
||||
// => /some/other/path |
||||
PathUtils::makeRelativePath('/some/path', '/some/other/path'); |
||||
// => ../other/path |
||||
|
||||
// OOP interface, more control |
||||
|
||||
$url = UrlPath::parse('https://example.com/some/path'); |
||||
$rel = RelativePath::unix('../other/path'); |
||||
$url->resolveRelative($rel)->toString(); |
||||
// => https://example.com/some/other/path |
||||
``` |
||||
|
||||
## Installation |
||||
|
||||
```bash |
||||
composer require arokettu/path |
||||
``` |
||||
|
||||
## Documentation |
||||
|
||||
Read full documentation here: <https://sandfox.dev/php/path.html> |
||||
|
||||
Also on Read the Docs: <https://php-path.readthedocs.io/> |
||||
|
||||
## Support |
||||
|
||||
Please file issues on our main repo at GitLab: <https://gitlab.com/sandfox/path/-/issues> |
||||
|
||||
## License |
||||
|
||||
The library is available as open source under the terms of the [MIT License]. |
||||
|
||||
[MIT License]: https://opensource.org/licenses/MIT |
@ -0,0 +1,22 @@
|
||||
<a class="sidebar-brand{% if logo %} centered{% endif %}" href="{{ pathto(master_doc) }}"> |
||||
{% block brand_content %} |
||||
{%- if logo %} |
||||
<div class="sidebar-logo-container"> |
||||
<img class="sidebar-logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/> |
||||
</div> |
||||
{%- endif %} |
||||
{%- if theme_light_logo and theme_dark_logo %} |
||||
<div class="sidebar-logo-container"> |
||||
<img class="sidebar-logo only-light" src="{{ pathto('_static/' + theme_light_logo, 1) }}" alt="Light Logo"/> |
||||
<img class="sidebar-logo only-dark" src="{{ pathto('_static/' + theme_dark_logo, 1) }}" alt="Dark Logo"/> |
||||
</div> |
||||
{%- endif %} |
||||
{% if not theme_sidebar_hide_name %} |
||||
<span class="sidebar-brand-text">{{ docstitle }}</span> |
||||
{%- endif %} |
||||
{% endblock brand_content %} |
||||
</a> |
||||
|
||||
{%- if current_version -%} |
||||
<div class="sidebar-brand">{{ current_version }}</div> |
||||
{%- endif -%} |
@ -0,0 +1,10 @@
|
||||
from datetime import datetime |
||||
|
||||
project = 'Path Library' |
||||
author = 'Anton Smirnov' |
||||
copyright = '{} {}'.format(datetime.now().year, author) |
||||
language = 'en' |
||||
|
||||
html_title = project |
||||
html_theme = 'furo' |
||||
templates_path = ["_templates"] |
@ -0,0 +1,73 @@
|
||||
Helper Classes |
||||
############## |
||||
|
||||
PathFactory |
||||
=========== |
||||
|
||||
``parse()`` |
||||
----------- |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
PathFactory::parse( |
||||
string $path, |
||||
array $urlSchemes = [], |
||||
array $streamSchemes = [] |
||||
): PathInterface; |
||||
|
||||
The ``parse`` function tries to detect the type of the given string path in the following order: |
||||
|
||||
* Unix path |
||||
* Windows path |
||||
* Url/Scheme paths: |
||||
|
||||
* If both ``$urlSchemes`` and ``$streamSchemes`` are empty, all scheme prefixed paths are parsed as URLs. |
||||
* If at least one of the lists is non-empty, all unknown schemes throw an exception. |
||||
* Known schemes are parsed according to which list they belong. |
||||
* Relative path of the current OS type. |
||||
|
||||
* Since there is no way to separate root relative path from Unix path, root relative paths are never returned. |
||||
|
||||
All paths are returned by the ``parse()`` constructor in a non strict mode. |
||||
|
||||
PathUtils |
||||
========= |
||||
|
||||
``resolveRelativePath()`` |
||||
------------------------- |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
PathUtils::resolveRelativePath( |
||||
string|PathInterface $basePath, |
||||
string|PathInterface $relativePath |
||||
): string; |
||||
|
||||
Resolves relative path from the base path. |
||||
|
||||
If a string is passed: it goes through ``PathFactory::parse()``. |
||||
|
||||
If ``relativePath`` is an absolute path, it is converted to string and returned. |
||||
|
||||
Otherwise ``$basePath->resolveRelative($relativePath)->toString()`` is returned. |
||||
|
||||
``makeRelativePath()`` |
||||
---------------------- |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
PathUtils::makeRelativePath( |
||||
string|AbsolutePathInterface $basePath, |
||||
string|AbsolutePathInterface $targetPath |
||||
): string; |
||||
|
||||
Makes relative path from two absolute paths. |
||||
|
||||
If a string is passed: it goes through ``PathFactory::parse()``. |
||||
|
||||
If any of the paths is a relative path, an exception is thrown. |
||||
|
||||
Otherwise ``$basePath->makeRelative($targetPath)->toString()`` is returned. |
@ -0,0 +1,41 @@
|
||||
Path Library |
||||
############ |
||||
|
||||
|Packagist| |GitLab| |GitHub| |Bitbucket| |Gitea| |
||||
|
||||
A PHP library to work with absolute and relative paths. |
||||
|
||||
Installation |
||||
============ |
||||
|
||||
.. code-block:: bash |
||||
|
||||
composer require arokettu/path |
||||
|
||||
Documentation |
||||
============= |
||||
|
||||
.. toctree:: |
||||
:maxdepth: 2 |
||||
|
||||
path_interfaces |
||||
path_classes |
||||
helper_classes |
||||
|
||||
License |
||||
======= |
||||
|
||||
The library is available as open source under the terms of the `MIT License`_. |
||||
|
||||
.. _MIT License: https://opensource.org/licenses/MIT |
||||
|
||||
.. |Packagist| image:: https://img.shields.io/packagist/v/arokettu/path.svg?style=flat-square |
||||
:target: https://packagist.org/packages/arokettu/path |
||||
.. |GitHub| image:: https://img.shields.io/badge/get%20on-GitHub-informational.svg?style=flat-square&logo=github |
||||
:target: https://github.com/arokettu/php-path |
||||
.. |GitLab| image:: https://img.shields.io/badge/get%20on-GitLab-informational.svg?style=flat-square&logo=gitlab |
||||
:target: https://gitlab.com/sandfox/php-path |
||||
.. |Bitbucket| image:: https://img.shields.io/badge/get%20on-Bitbucket-informational.svg?style=flat-square&logo=bitbucket |
||||
:target: https://bitbucket.org/sandfox/php-path |
||||
.. |Gitea| image:: https://img.shields.io/badge/get%20on-Gitea-informational.svg?style=flat-square&logo=gitea |
||||
:target: https://sandfox.org/sandfox/php-path |
@ -0,0 +1,159 @@
|
||||
Path Classes |
||||
############ |
||||
|
||||
RelativePath |
||||
============ |
||||
|
||||
The only concrete implementation of ``RelativePathInterface``. |
||||
In non-root relative paths first component returned by ``getComponents()`` is either ``'.'`` or ``'..'``. |
||||
|
||||
When resolving relative, windows-ness of the resulting relative will be inherited from the base path. |
||||
|
||||
Available constructors: |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
new RelativePath(string $path, bool $windows = false); |
||||
|
||||
``$windows = false``: Unix-like path. Path separators are slashes. |
||||
|
||||
``$windows = true``: Windows-like path. Path separators are both slashes and backslashes. |
||||
When exporting a string, backslashes are used. |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
RelativePath::unix(string $path): self; |
||||
|
||||
Same as ``new RelativePath($path, windows: false)`` |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
RelativePath::windows(string $path): self; |
||||
|
||||
Same as ``new RelativePath($path, windows: true)`` |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
RelativePath::currentOS(string $path): self; |
||||
|
||||
If Windows is detected, create a Windows-like path, otherwise create Unix-like path. |
||||
|
||||
.. note:: Windows is detected by the ``DIRECTORY_SEPARATOR`` constant. |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
RelativePath::parse(string $path): self; |
||||
|
||||
Alias of ``currentOS()``. |
||||
|
||||
FilesystemPath |
||||
============== |
||||
|
||||
A base class for ``UnixPath`` and ``WindowsPath``. |
||||
|
||||
No default constructor, only a named constructor is available: |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
FilesystemPath::parse(string $path, bool $strict = false): self; |
||||
|
||||
If Windows is detected, create a Windows path, otherwise create a Unix path. |
||||
Strict mode does not allow to have relative components that traverse beyond root. |
||||
|
||||
.. note:: Windows is detected by the ``DIRECTORY_SEPARATOR`` constant. |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
use Arokettu\Path\FilesystemPath; |
||||
|
||||
// on windows |
||||
FilesystemPath::parse('C:\Windows\..\..\..\Users'); // C:\Users |
||||
FilesystemPath::parse('C:\Windows\..\..\..\Users' strict: true); // exception |
||||
|
||||
UnixPath |
||||
-------- |
||||
|
||||
A class for Unix paths. |
||||
The prefix is ``'/'`` |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
// these are equal |
||||
new UnixPath(string $path, bool $strict = false); |
||||
UnixPath::parse(string $path, bool $strict = false): self; |
||||
|
||||
WindowsPath |
||||
----------- |
||||
|
||||
.. warning:: |
||||
Windows usually have much more restrictions on file path than unix-like operating systems |
||||
like forbidding characters like ``|`` and ``:``. |
||||
The library doesn't check for that even in strict mode. |
||||
|
||||
A class for Windows paths. |
||||
``makeRelative()`` returns relatives of the Windows-like type. |
||||
|
||||
Supported paths: |
||||
|
||||
* DOS-like paths. |
||||
The classic paths with a drive letter: ``C:\Path``. |
||||
Both slashes and backslashes are supported as component separators. |
||||
Relative components are resolved on creation like in most other classes here. |
||||
The prefix here is a drive letter. |
||||
* UNC paths. |
||||
Examples: |
||||
|
||||
* Local paths like ``\\*\C:\Path``. The prefix here is ``\\*\C:\``. |
||||
* Network paths like ``\\AROKETTUPC\c$``. The prefix here is ``\\AROKETTUPC\``. |
||||
|
||||
UNC paths do not allow forward slashes and relative components. |
||||
|
||||
.. note:: |
||||
Relative paths with drive letter like ``C:Path\Path`` are valid in Windows |
||||
but are not supported by the library in any way. |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
// these are equal |
||||
new WindowsPath(string $path, bool $strict = false); |
||||
WindowsPath::parse(string $path, bool $strict = false): self; |
||||
|
||||
UrlPath |
||||
======= |
||||
|
||||
A class for URL paths. |
||||
The prefix is scheme + hostname. |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
// these are equal |
||||
new UrlPath(string $path, bool $strict = false); |
||||
UrlPath::parse(string $path, bool $strict = false): self; |
||||
|
||||
StreamPath |
||||
========== |
||||
|
||||
A class for PHP stream like paths. |
||||
Examples include php streams like ``php://temp``. |
||||
It can be useful with libraries that create virtual file systems like `adlawson/vfs`_ and `mikey179/vfsstream`_. |
||||
The prefix is scheme. |
||||
|
||||
.. _adlawson/vfs: https://packagist.org/packages/adlawson/vfs |
||||
.. _mikey179/vfsstream: https://packagist.org/packages/mikey179/vfsstream |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
// these are equal |
||||
new StreamPath(string $path, bool $strict = false); |
||||
StreamPath::parse(string $path, bool $strict = false): self; |
@ -0,0 +1,131 @@
|
||||
Path Interfaces |
||||
############### |
||||
|
||||
PathInterface |
||||
============= |
||||
|
||||
``resolveRelative()`` |
||||
--------------------- |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
public function resolveRelative(RelativePathInterface $path, bool $strict = false): self; |
||||
|
||||
Convert relative path to absolute or combine two relative paths using the caller object as base. |
||||
|
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
use Arokettu\Path\RelativePath; |
||||
use Arokettu\Path\UnixPath; |
||||
|
||||
$path = UnixPath::parse('/some/path'); |
||||
$rel1 = RelativePath::parse('../other/path'); |
||||
// trailing slashes are preserved |
||||
$rel2 = RelativePath::parse('../diff/path/'); |
||||
|
||||
$path->resolveRelative($rel1); // /some/other/path |
||||
// trailing slash will be present if target path has it |
||||
$rel1->resolveRelative($rel2); // ../other/diff/path/ |
||||
|
||||
Strict mode throws exception if traversal happens beyond root (no effect if the base path is relative): |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
use Arokettu\Path\RelativePath; |
||||
use Arokettu\Path\UnixPath; |
||||
|
||||
$path = UnixPath::parse('/some/path'); |
||||
$rel = RelativePath::parse('../../../../etc/passwd'); |
||||
|
||||
$path->resolveRelative($rel); // /etc/passwd |
||||
$path->resolveRelative($rel, strict: true); // exception |
||||
|
||||
``getPrefix()`` |
||||
--------------- |
||||
|
||||
Path prefix that you can't traverse beyond like root unix path, windows drive path (C:\\), and url hostname. |
||||
|
||||
``getComponents()`` |
||||
------------------- |
||||
|
||||
An array of path components excluding prefix. |
||||
The last component of the path is empty string if path has trailing (back)slash |
||||
|
||||
``isAbsolute()`` |
||||
---------------- |
||||
|
||||
``true`` for instances of ``AbsolutePathInterface``. |
||||
``false`` for instances of ``RelativePathInterface``. |
||||
|
||||
``isRelative()`` |
||||
---------------- |
||||
|
||||
``false`` for instances of ``AbsolutePathInterface``. |
||||
``true`` for instances of ``RelativePathInterface``. |
||||
|
||||
``toString()`` & ``__toString()`` |
||||
--------------------------------- |
||||
|
||||
Get string value of the path. |
||||
|
||||
AbsolutePathInterface |
||||
===================== |
||||
|
||||
``makeRelative()`` |
||||
------------------ |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
public function makeRelative(self $targetPath, ?\Closure $equals = null): RelativePathInterface; |
||||
|
||||
Make relative path from base path and target path of the same type having equal prefixes. |
||||
The paths are treated as case sensitive unless ``$equals`` callback is provided. |
||||
|
||||
.. code-block:: php |
||||
|
||||
<?php |
||||
|
||||
use Arokettu\Path\UnixPath; |
||||
use Arokettu\Path\UrlPath; |
||||
use Arokettu\Path\WindowsPath; |
||||
|
||||
$path1 = UnixPath::parse('/home/arokettu'); |
||||
$path2 = UnixPath::parse('/home/sandfox/'); |
||||
// there will be a trailing slash if target path has it |
||||
$path1->makeRelative($path2); // ../sandfox/ |
||||
|
||||
// ignore case on Windows |
||||
$path1 = WindowsPath::parse('c:\users\arokettu'); |
||||
$path2 = WindowsPath::parse('C:\Users\SandFox'); |
||||
$path1->makeRelative( |
||||
$path2, |
||||
fn ($a, $b) => strtoupper($a) === strtoupper($b) |
||||
); // ..\SandFox |
||||
|
||||
// resolve urlencoded url path |
||||
$path1 = UrlPath::parse('https://example.com/some%20path/child%20dir'); |
||||
$path2 = UrlPath::parse('https://example.com/some path/child dir'); |
||||
$path1->makeRelative( |
||||
$path2, |
||||
fn ($a, $b) => urldecode($a) === urldecode($b) |
||||
); // . |
||||
|
||||
RelativePathInterface |
||||
===================== |
||||
|
||||
``isRoot()`` |
||||
------------ |
||||
|
||||
``true`` if the relative path is 'root path', i.e. full path excluding prefix. |
||||
Examples: |
||||
|
||||
* ``\Users\SandFox`` for Windows path ``C:\Users\SandFox`` |
||||
* ``/some path/child dir`` for UrlPath ``https://example.com/some path/child dir`` |
||||
* Functionally equal to Unix path |
||||
|
||||
When applying root path in ``resolveRelative()``, it replaces the whole path excluding prefix. |
@ -0,0 +1,66 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Arokettu\Path; |
||||
|
||||
final class PathUtils |
||||
{ |
||||
/** |
||||
* @param string|PathInterface $basePath |
||||
* @param string|PathInterface $relativePath |
||||
* @return string |
||||
*/ |
||||
public static function resolveRelativePath($basePath, $relativePath): string |
||||
{ |
||||
if (\is_string($basePath)) { |
||||
$basePath = PathFactory::parse($basePath); |
||||
} |
||||
|
||||
if (\is_string($relativePath)) { |
||||
$relativePath = PathFactory::parse($relativePath); |
||||
} |
||||
|
||||
if (!($basePath instanceof PathInterface)) { |
||||
throw new \InvalidArgumentException('basePath must be a string or an instance of PathInterface'); |
||||
} |
||||
|
||||
if ($relativePath instanceof RelativePathInterface) { |
||||
return $basePath->resolveRelative($relativePath)->toString(); |
||||
} elseif ($relativePath instanceof AbsolutePathInterface) { |
||||
return $relativePath->toString(); |
||||
} |
||||
|
||||
throw new \InvalidArgumentException('relativePath must be a string or an instance of PathInterface'); |
||||
} |
||||
|
||||
/** |
||||
* @param string|AbsolutePathInterface $basePath |
||||
* @param string|AbsolutePathInterface $targetPath |
||||
* @return string |
||||
*/ |
||||
public static function makeRelativePath($basePath, $targetPath): string |
||||
{ |
||||
if (\is_string($basePath)) { |
||||
$basePath = PathFactory::parse($basePath); |
||||
} |
||||
|
||||
if (\is_string($targetPath)) { |
||||
$targetPath = PathFactory::parse($targetPath); |
||||
} |
||||
|
||||
if (!($basePath instanceof AbsolutePathInterface) || !$basePath->isAbsolute()) { |
||||
throw new \InvalidArgumentException( |
||||
'basePath must be a string containing absolute path or an instance of AbsolutePathInterface' |
||||
); |
||||
} |
||||
|
||||
if (!($targetPath instanceof AbsolutePathInterface) || !$targetPath->isAbsolute()) { |
||||
throw new \InvalidArgumentException( |
||||
'targetPath must be a string containing absolute path or an instance of AbsolutePathInterface' |
||||
); |
||||
} |
||||
|
||||
return $basePath->makeRelative($targetPath)->toString(); |
||||
} |
||||
} |
@ -0,0 +1,60 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Arokettu\Path\Tests; |
||||
|
||||
use Arokettu\Path\PathUtils; |
||||
use PHPUnit\Framework\TestCase; |
||||
|
||||
class PathUtilsTest extends TestCase |
||||
{ |
||||
public function testMakeRelative(): void |
||||
{ |
||||
self::assertEquals( |
||||
'../../.config/composer', |
||||
PathUtils::makeRelativePath( |
||||
'/home/arokettu/tmp/test', |
||||
'/home/arokettu/.config/composer', |
||||
), |
||||
); |
||||
|
||||
self::assertEquals( |
||||
'..\..\AppData\Roaming', |
||||
PathUtils::makeRelativePath( |
||||
'C:\Users\Arokettu\tmp\test', |
||||
'C:\Users\Arokettu\AppData\Roaming', |
||||
), |
||||
); |
||||
} |
||||
|
||||
public function testResolveRelative(): void |
||||
{ |
||||
// any, absolute |
||||
self::assertEquals( |
||||
'/home/arokettu/.config/composer', |
||||
PathUtils::resolveRelativePath( |
||||
'/home/arokettu/tmp/test', |
||||
'/home/arokettu/.config/composer', |
||||
), |
||||
); |
||||
|
||||
// absolute, relative |
||||
self::assertEquals( |
||||
'/home/arokettu/.config/composer', |
||||
PathUtils::resolveRelativePath( |
||||
'/home/arokettu/tmp/test', |
||||
'../../.config/composer', |
||||
), |
||||
); |
||||
|
||||
// relative, relative |
||||
self::assertEquals( |
||||
'.config/composer', |
||||
PathUtils::resolveRelativePath( |
||||
'./tmp/test', |
||||
'../../.config/composer', |
||||
), |
||||
); |
||||
} |
||||
} |
Loading…
Reference in new issue