Skip to content

Commit

Permalink
add splitDrive method and complete normPath method
Browse files Browse the repository at this point in the history
  • Loading branch information
olinox14 committed Apr 15, 2024
1 parent e61dc37 commit c4bf333
Showing 1 changed file with 55 additions and 17 deletions.
72 changes: 55 additions & 17 deletions src/Path.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,49 @@ public static function join(string|self $path, string|self ...$parts): self
return new self($path);
}

/**
* Split the pathname path into a pair (drive, tail) where drive is either a mount point or the empty string.
* On systems which do not use drive specifications, drive will always be the empty string. In all cases,
* drive + tail will be the same as path.
*
* On Windows, splits a pathname into drive/UNC sharepoint and relative path.
*
* If the path contains a drive letter, drive will contain everything up to and including the colon:
*
* Path::splitDrive("c:/dir")
* >>> ["c:", "/dir"]
*
* If the path contains a UNC path, drive will contain the host name and share:
*
* Path::splitDrive("//host/computer/dir")
* >>> ["//host/computer", "/dir"]
*
* @param string|self $path The path with the drive.
* @return array An array containing the drive and the path.
*/
public static function splitDrive(string|self $path): array {

Check failure on line 77 in src/Path.php

View workflow job for this annotation

GitHub Actions / Code quality (8.1)

Method Path\Path::splitDrive() return type has no value type specified in iterable type array.

Check failure on line 77 in src/Path.php

View workflow job for this annotation

GitHub Actions / Code quality (8.3)

Method Path\Path::splitDrive() return type has no value type specified in iterable type array.
$path = (string)$path;

$matches = [];

preg_match('/(^[a-zA-Z]:)(.*)/', $path, $matches);
if ($matches) {
return array_slice($matches, -2);
}

$rx =
DIRECTORY_SEPARATOR === '/' ?
'/(^\/\/[\w\-\s]{2,15}\/[\w\-\s]+)(.*)/' :
'/(^\\\\\\\\[\w\-\s]{2,15}\\\[\w\-\s]+)(.*)/';

preg_match($rx, $path, $matches);
if ($matches) {
return array_slice($matches, -2);
}

return ['', $path];
}

public function __construct(string|self $path)
{
$this->builtin = new BuiltinProxy();
Expand Down Expand Up @@ -322,33 +365,26 @@ public function normCase(): self
* and A/foo/../B all become A/B. This string manipulation may change the meaning of a path that contains
* symbolic links. On Windows, it converts forward slashes to backward slashes. To normalize case, use normcase().
*
* // TODO: becare of the normcase when we're getting to the windows compat
*
* @return self A new instance of the class with the normalized path.
*/
public function normPath(): self
{
$path = $this->normCase()->path();
$path = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $this->path());

// TODO: handle case where path start with //
if (empty($path)) {
return $this->cast('.');
}

// Also tests some special cases we can't really do anything with
if (!str_contains($path, '/') || $path === '/' || '.' === $path || '..' === $path) {
if (!str_contains($path, DIRECTORY_SEPARATOR) || $path === '/' || '.' === $path || '..' === $path) {
return $this->cast($path);
}

$path = rtrim($path, '/');
$path = rtrim($path, DIRECTORY_SEPARATOR);

// Extract the scheme if any
$scheme = null;
if (strpos($path, '://')) {
list($scheme, $path) = explode('://', $path, 2);
}
[$prefix, $path] = $this->splitDrive($path);

$parts = explode('/', $path);
$parts = explode(DIRECTORY_SEPARATOR, $path);
$newParts = [];

foreach ($parts as $part) {
Expand Down Expand Up @@ -376,13 +412,15 @@ public function normPath(): self
}

// Rebuild path
$newPath = implode('/', $newParts);

// Add scheme if any
if ($scheme !== null) {
$newPath = $scheme . '://' . $newPath;
if ($prefix) {
array_shift($newParts); // Get rid of the leading empty string resulting from slitDrive result
array_unshift($newParts, rtrim($prefix, DIRECTORY_SEPARATOR));
}

$newPath = implode(DIRECTORY_SEPARATOR, $newParts);



return $this->cast($newPath);
}

Expand Down

0 comments on commit c4bf333

Please sign in to comment.