Skip to content

Commit

Permalink
Fix issue with location outside of the main path not returning the co…
Browse files Browse the repository at this point in the history
…rrect relative path.
  • Loading branch information
lcharette committed Nov 13, 2021
1 parent a0522c6 commit 71817c5
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 28 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## 4.6.1
## [4.6.1](https://github.com/userfrosting/framework/compare/4.6.0...4.6.1)
- Fix issue with location outside of the main path not returning the correct relative path.
- Update php-cs-fixer to V3

## 4.6.0
Expand Down
4 changes: 2 additions & 2 deletions src/UniformResourceLocator/Normalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ public static function normalize($uri, $throwException = false, $splitStream = f
}

/**
* Normalise a path:
* Normalize a path:
* - Make sure all `\` (from a Windows path) are changed to `/`
* - Make sure a trailling slash is present
* - Make sure a trailing slash is present
* - Doesn't change the beginning of the path (don't change absolute / relative path), but will change `C:\` to `C:/`.
*
* @param string $path
Expand Down
8 changes: 4 additions & 4 deletions src/UniformResourceLocator/Resource.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
* paths of the file. Using this information, we can later rebuilt the URI used
* to find this file. Since the full path will contains the relative location of
* the stream and location inside the filesystem, this information will be
* removed to recrete the relative 'basepath' of the file, allowing the
* recreatation of the uri (scheme://basePath).
* removed to recreate the relative 'basepath' of the file, allowing the
* recreation of the uri (scheme://basePath).
*
* @author Louis Charette
*/
Expand Down Expand Up @@ -64,7 +64,7 @@ public function __construct(ResourceStreamInterface $stream, ResourceLocationInt

/**
* Get Resource URI
* Also adds the prefix stream prefix if it existprefix.
* Also adds the prefix stream prefix if it exist.
*
* @return string
*/
Expand All @@ -83,7 +83,7 @@ public function getUri(): string
$parts[] = $this->getBasePath();
}

// Glue parts togeter.
// Glue parts together.
$path = implode('/', $parts);

return $this->stream->getScheme().'://'.$path;
Expand Down
43 changes: 29 additions & 14 deletions src/UniformResourceLocator/ResourceLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ protected function setupStreamWrapper(string $scheme): void
return;
}

// First unset the sheme. Prevent issue if someone else already registered it
// First unset the scheme. Prevent issue if someone else already registered it
$this->unsetStreamWrapper($scheme);

// register the scheme as a stream wrapper
Expand Down Expand Up @@ -189,7 +189,9 @@ public function registerStream(string $scheme, string $prefix = '', $paths = nul
*/
public function registerSharedStream(string $scheme, string $prefix = '', $paths = null): self
{
return $this->registerStream($scheme, $prefix, $paths, true);
$this->registerStream($scheme, $prefix, $paths, true);

return $this;
}

/**
Expand Down Expand Up @@ -347,15 +349,15 @@ public function listResources(string $uri, bool $all = false, bool $sort = true)
{
$list = [];

// Get all directory where we can find this ressource. Will be returned with the priority order
// Get all directory where we can find this resource. Will be returned with the priority order
$directories = $this->getResources($uri);

foreach ($directories as $directory) {

// Use Filesystem to list all file in the directory
$files = $this->filesystem->allFiles($directory->getAbsolutePath());

// Sort files. Filesystem can return inconsistant order sometime
// Sort files. Filesystem can return inconsistent order sometime
// Files will be sorted alphabetically inside a location even if don't resort later across all sprinkles
$files = Arr::sort($files, function ($resource) {
return $resource->getRealPath();
Expand All @@ -367,10 +369,15 @@ public function listResources(string $uri, bool $all = false, bool $sort = true)
$basePath = rtrim($this->getBasePath(), $this->separator).$this->separator;
$fullPath = $file->getPathname();
$relPath = str_replace($basePath, '', $fullPath);
$relPath = ltrim($relPath, $this->separator);

// Create the ressource and add it to the list
$resource = new Resource($directory->getStream(), $directory->getLocation(), $relPath, $basePath);
// Create the resource and add it to the list
// Handle relPath that is an absolute outside the basePath
// This can happen when the location has an absolute path outside the locator base path.
if ($fullPath == $relPath) {
$resource = new Resource($directory->getStream(), $directory->getLocation(), $fullPath);
} else {
$resource = new Resource($directory->getStream(), $directory->getLocation(), $relPath, $basePath);
}

if ($all) {
// Add all files to the list
Expand Down Expand Up @@ -428,7 +435,7 @@ public function isStream($uri): bool

/**
* Find highest priority instance from a resource. Return the path for said resource
* For example, if looking for a `test.json` ressource, only the top priority
* For example, if looking for a `test.json` resource, only the top priority
* instance of `test.json` found will be returned.
*
* @param string $uri Input URI to be searched (can be a file or directory)
Expand All @@ -437,7 +444,7 @@ public function isStream($uri): bool
*
* @throws \BadMethodCallException
*
* @return string|bool The ressource path, or false if not found resource
* @return string|bool The resource path, or false if not found resource
*/
public function findResource($uri, $absolute = true, $first = false)
{
Expand All @@ -456,14 +463,14 @@ public function findResource($uri, $absolute = true, $first = false)

/**
* Find all instances from a resource. Return an array of paths for said resource
* For example, if looking for a `test.json` ressource, all instance
* For example, if looking for a `test.json` resource, all instance
* of `test.json` found will be listed.
*
* @param string $uri Input URI to be searched (can be a file or directory)
* @param bool $absolute Whether to return absolute path.
* @param bool $all Whether to return all paths even if they don't exist.
*
* @return string[] An array of all the ressources path
* @return string[] An array of all the resources path
*/
public function findResources($uri, $absolute = true, $all = false)
{
Expand All @@ -488,7 +495,7 @@ public function findResources($uri, $absolute = true, $all = false)
* @param bool $array Return an array or a single path
* @param bool $all Whether to return all paths even if they don't exist.
*
* @return ResourceInterface[]|ResourceInterface|false The ressource path or an array of all the ressources path or false if not resource can be found
* @return ResourceInterface[]|ResourceInterface|false The resource path or an array of all the resources path or false if not resource can be found
*/
protected function findCached(string $uri, bool $array, bool $all)
{
Expand All @@ -510,7 +517,7 @@ protected function findCached(string $uri, bool $array, bool $all)
}

/**
* Build the search path out of the defined strean and locations.
* Build the search path out of the defined stream and locations.
* If the scheme is shared, we don't need to involve locations and can return it's path directly.
*
* @param ResourceStreamInterface $stream The stream to search for
Expand Down Expand Up @@ -597,7 +604,15 @@ protected function find(string $scheme, string $file, bool $array, bool $all)

// Add the result to the list if the path exist, unless we want all results
if ($all || $this->filesystem->exists($fullPath)) {
$currentResource = new Resource($stream, $location, $relPath, $basePath);

// Handle relpath that is an absolute outside the basePath
// This can happen when the location has an absolute path outside the locator base path.
if ($fullPath == $relPath) {
$currentResource = new Resource($stream, $location, $fullPath);
} else {
$currentResource = new Resource($stream, $location, $relPath, $basePath);
}

if (!$array) {
return $currentResource;
}
Expand Down
12 changes: 6 additions & 6 deletions src/UniformResourceLocator/ResourceLocatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function addStream(ResourceStreamInterface $stream);
* @param string $scheme
* @param string $prefix (default '')
* @param string|string[]|null $paths (default null). When using null path, the scheme will be used as a path
* @param bool $shared (default false) Shared resoureces are not affected by locations
* @param bool $shared (default false) Shared resources are not affected by locations
*
* @return static
*/
Expand All @@ -61,7 +61,7 @@ public function registerStream(string $scheme, string $prefix = '', $paths = nul
public function removeStream(string $scheme);

/**
* Return information about a specfic stream.
* Return information about a specific stream.
* Return value is an array of ResourceStreamInterface, for each prefix
* For example :
* $array = array(
Expand Down Expand Up @@ -111,7 +111,7 @@ public function listStreams();
public function schemeExists(string $scheme): bool;

/**
* Add an existing RessourceLocation instance to the location list.
* Add an existing ResourceLocation instance to the location list.
*
* @param ResourceLocationInterface $location
*
Expand Down Expand Up @@ -193,15 +193,15 @@ public function getResource(string $uri, bool $first = false);
public function getResources(string $uri, bool $all = false): array;

/**
* List all ressources found at a given uri.
* List all resources found at a given uri.
* Same as listing all file in a directory, except here all topmost
* ressources will be returned when considering all locations.
* resources will be returned when considering all locations.
*
* @param string $uri Input URI to be searched (can be a uri/path ONLY)
* @param bool $all If true, all resources will be returned, not only topmost ones
* @param bool $sort Set to true to sort results alphabetically by absolute path. Set to false to sort by absolute priority, higest location first. Default to true.
*
* @return ResourceInterface[] The ressources list
* @return ResourceInterface[] The resources list
*/
public function listResources(string $uri, bool $all = false, bool $sort = true);

Expand Down
30 changes: 29 additions & 1 deletion tests/UniformResourceLocator/ResourceLocatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ public function testStreamWithEmptyPath(): void
}

/**
* With stream poiting to `app/uploads/profile`, we make sure we can't access `app/uploads/MyFile.txt`.
* With stream pointing to `app/uploads/profile`, we make sure we can't access `app/uploads/MyFile.txt`.
*/
public function testFindResourceWithBackPath(): void
{
Expand All @@ -451,4 +451,32 @@ public function testFindResourceWithBackPath(): void

$this->assertFalse($result);
}

/**
* Test a location outside of the main path produce the correct relative path.
*/
public function testFindResourceOutsideMainPath(): void
{
$locator = new ResourceLocator(__DIR__.'/Building/Floors');
$locator->registerStream('files');
$locator->registerLocation('Garage', __DIR__.'/Building/Garage');

$resource = $locator->findResource('files://blah.json');

$this->assertSame(__DIR__.'/Building/Garage/files/blah.json', $resource);
}

/**
* Test a location outside of the main path produce the correct relative path.
*/
public function testListResourceOutsideMainPath(): void
{
$locator = new ResourceLocator(__DIR__.'/Building/Floors');
$locator->registerStream('files');
$locator->registerLocation('Garage', __DIR__.'/Building/Garage');

$resources = $locator->listResources('files://', true);

$this->assertSame(__DIR__.'/Building/Garage/files/blah.json', $resources[0]->getAbsolutePath());
}
}

0 comments on commit 71817c5

Please sign in to comment.