Commit f3f28275 authored by Anton Smirnov's avatar Anton Smirnov
Browse files

Path factory

parent e5810281
Loading
Loading
Loading
Loading

src/PathFactory.php

0 → 100644
+46 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Arokettu\Path;

final class PathFactory
{
    public static function parse(string $path, array $urlSchemes = [], array $streamSchemes = []): PathInterface
    {
        if ($path[0] === '/') {
            return UnixPath::parse($path);
        }

        if (preg_match('@^[a-zA-Z]:[\\\\/]@', $path) || str_starts_with($path, '\\\\')) {
            return new WindowsPath($path);
        }

        if (preg_match('@^([-.+a-zA-Z0-9]+)://@', $path, $matches)) {
            return self::parseUrlLike($path, $matches[1], $urlSchemes, $streamSchemes);
        }

        return DIRECTORY_SEPARATOR === '\\' ? RelativePath::windows($path) : RelativePath::unix($path);
    }

    private static function parseUrlLike(
        string $path,
        string $scheme,
        array $urlSchemes = [],
        array $streamSchemes = []
    ): PathInterface {
        if ($urlSchemes === [] && $streamSchemes === []) {
            return UrlPath::parse($path);
        }

        if (\in_array($scheme, $urlSchemes)) {
            return UrlPath::parse($path);
        }

        if (\in_array($scheme, $streamSchemes)) {
            return StreamPath::parse($path);
        }

        throw new \InvalidArgumentException('Unknown scheme: ' . $scheme);
    }
}
+55 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Arokettu\Path\Tests;

use Arokettu\Path\PathFactory;
use Arokettu\Path\RelativePath;
use Arokettu\Path\StreamPath;
use Arokettu\Path\UnixPath;
use Arokettu\Path\UrlPath;
use Arokettu\Path\WindowsPath;
use PHPUnit\Framework\TestCase;

class PathFactoryTest extends TestCase
{
    public function testValid(): void
    {
        self::assertInstanceOf(UnixPath::class, PathFactory::parse('/unix/path'));
        self::assertInstanceOf(WindowsPath::class, PathFactory::parse('C:/unixlike/path'));
        self::assertInstanceOf(WindowsPath::class, PathFactory::parse('c:\win\path'));
        self::assertInstanceOf(WindowsPath::class, PathFactory::parse('\\\\unc\path'));
        self::assertInstanceOf(RelativePath::class, PathFactory::parse('../test/path'));
        self::assertInstanceOf(RelativePath::class, PathFactory::parse('./test/path'));
        self::assertInstanceOf(RelativePath::class, PathFactory::parse('test/path'));
    }

    public function testValidUrls(): void
    {
        self::assertInstanceOf(UrlPath::class, PathFactory::parse('https://example.com/test/test'));
        self::assertInstanceOf(UrlPath::class, PathFactory::parse('vfs://test/test'));

        $urlSchemes = ['http', 'https', 'ftp'];
        $streamSchemes = ['vfs', 'php'];
        self::assertInstanceOf(
            UrlPath::class,
            PathFactory::parse('https://example.com/test/test', $urlSchemes, $streamSchemes)
        );
        self::assertInstanceOf(
            StreamPath::class,
            PathFactory::parse('vfs://test/test', $urlSchemes, $streamSchemes)
        );
    }

    public function testUnknownScheme(): void
    {
        $this->expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage('Unknown scheme: unk');

        $urlSchemes = ['http', 'https', 'ftp'];
        $streamSchemes = ['vfs', 'php'];

        PathFactory::parse('unk://test/test', $urlSchemes, $streamSchemes);
    }
}