Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for URI mapped document roots
- Loading branch information
Jason Terando
committed
Jul 2, 2020
1 parent
c321b39
commit 5fefe8d
Showing
10 changed files
with
447 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
<?php | ||
|
||
/** | ||
* @see https://github.com/mezzio/mezzio-swoole for the canonical source repository | ||
* @copyright https://github.com/mezzio/mezzio-swoole/blob/master/COPYRIGHT.md | ||
* @license https://github.com/mezzio/mezzio-swoole/blob/master/LICENSE.md New BSD License | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Mezzio\Swoole\StaticResourceHandler; | ||
|
||
use InvalidArgumentException; | ||
|
||
class FileLocationRepository implements FileLocationRepositoryInterface { | ||
/** | ||
* @var array | ||
* Associative array of URI prefixes and directories | ||
*/ | ||
private $mappedDocRoots = []; | ||
|
||
/** | ||
* Initialize repository with default mapped document roots | ||
*/ | ||
public function __construct(array $defaultMappedDocRoots) | ||
{ | ||
foreach($defaultMappedDocRoots as $prefix => $directories) { | ||
foreach($directories as $directory) { | ||
$this->addMappedDocumentRoot($prefix, $directory); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Add the specified directory to list of mapped directories | ||
*/ | ||
public function addMappedDocumentRoot(string $prefix, string $directory): void | ||
{ | ||
$valPrefix =$this->validatePrefix($prefix); | ||
$valDirectory = $this->validateDirectory($directory, $valPrefix); | ||
|
||
if(array_key_exists($valPrefix, $this->mappedDocRoots)) { | ||
$dirs = &$this->mappedDocRoots[$valPrefix]; | ||
if(! in_array($valDirectory, $dirs)) { | ||
$dirs[] = $valDirectory; | ||
} | ||
} else { | ||
$this->mappedDocRoots[$valPrefix] = [$valDirectory]; | ||
} | ||
} | ||
|
||
/** | ||
* Validate prefix, ensuring it is non-empty and starts and ends with a slash | ||
*/ | ||
private function validatePrefix(string $prefix): string | ||
{ | ||
if(empty($prefix)) { | ||
// For the default prefix, set it to a slash to get matching to work | ||
$prefix = '/'; | ||
} else { | ||
if($prefix[0] != '/') $prefix = "/$prefix"; | ||
if($prefix[-1] != '/') $prefix .= '/'; | ||
} | ||
return $prefix; | ||
} | ||
|
||
/** | ||
* Validate directory, ensuring it exists and | ||
*/ | ||
private function validateDirectory(string $directory, string $prefix): string | ||
{ | ||
if(! is_dir($directory)) { | ||
throw new InvalidArgumentException(sprintf( | ||
'The document root for "%s", "%s", does not exist; please check your configuration.', | ||
empty($prefix) ? "(Default)" : $prefix, $directory | ||
)); | ||
} | ||
if($directory[-1] != '/') $directory .= '/'; | ||
return $directory; | ||
} | ||
|
||
/** | ||
* Return the mapped document roots | ||
*/ | ||
public function listMappedDocumentRoots(): array | ||
{ | ||
return $this->mappedDocRoots; | ||
} | ||
|
||
/** | ||
* Searches for the specified file in mapped document root | ||
* directories; returns the location if found, or null if not | ||
*/ | ||
public function findFile(string $filename): ?string | ||
{ | ||
foreach($this->mappedDocRoots as $prefix => $directories) { | ||
foreach($directories as $directory) { | ||
if(stripos($filename, $prefix) == 0) { | ||
$mappedFileName = $directory . substr($filename, strlen($prefix)); | ||
if(file_exists($mappedFileName)) { | ||
return $mappedFileName; | ||
} | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
src/StaticResourceHandler/FileLocationRepositoryFactory.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
/** | ||
* @see https://github.com/mezzio/mezzio-swoole for the canonical source repository | ||
* @copyright https://github.com/mezzio/mezzio-swoole/blob/master/COPYRIGHT.md | ||
* @license https://github.com/mezzio/mezzio-swoole/blob/master/LICENSE.md New BSD License | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Mezzio\Swoole\StaticResourceHandler; | ||
|
||
use Psr\Container\ContainerInterface; | ||
use InvalidArgumentException; | ||
use function getcwd; | ||
|
||
class FileLocationRepositoryFactory | ||
{ | ||
/** | ||
* Create a file location repository, initializing with the static files setting configured by mezzio-swoole | ||
*/ | ||
public function __invoke(ContainerInterface $container) : FileLocationRepository | ||
{ | ||
$docRoots = $container->get('config')['mezzio-swoole']['swoole-http-server']['static-files']['document-root'] | ||
?? [getcwd() . '/public']; | ||
if(! is_array($docRoots)) { | ||
// Accomodate if the user defines document-root as a string or array | ||
$docRoots = [$docRoots]; | ||
} | ||
return new FileLocationRepository(count($docRoots) > 0 ? ['' => $docRoots] : []); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/StaticResourceHandler/FileLocationRepositoryInterface.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
/** | ||
* @see https://github.com/mezzio/mezzio-swoole for the canonical source repository | ||
* @copyright https://github.com/mezzio/mezzio-swoole/blob/master/COPYRIGHT.md | ||
* @license https://github.com/mezzio/mezzio-swoole/blob/master/LICENSE.md New BSD License | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Mezzio\Swoole\StaticResourceHandler; | ||
|
||
/** | ||
* Interface to implement a repository for storing the association | ||
* between the start of a URI (prefix) and directory | ||
*/ | ||
interface FileLocationRepositoryInterface | ||
{ | ||
function addMappedDocumentRoot(string $prefix, string $directory): void; | ||
function listMappedDocumentRoots(): array; | ||
function findFile(string $filename): ?string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
test/StaticResourceHandler/FileLocationRepositoryFactoryTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
<?php | ||
/** | ||
* @see https://github.com/mezzio/mezzio-swoole for the canonical source repository | ||
* @copyright https://github.com/mezzio/mezzio-swoole/blob/master/COPYRIGHT.md | ||
* @license https://github.com/mezzio/mezzio-swoole/blob/master/LICENSE.md New BSD License | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace MezzioTest\Swoole; | ||
|
||
require_once('_MockIsDir.php'); | ||
|
||
use Mezzio\Swoole\StaticResourceHandler\FileLocationRepository; | ||
use Mezzio\Swoole\StaticResourceHandler\FileLocationRepositoryFactory; | ||
use PHPUnit\Framework\TestCase; | ||
use Psr\Container\ContainerInterface; | ||
|
||
class FileLocationRepositoryFactoryTest extends TestCase | ||
{ | ||
protected function setUp() : void | ||
{ | ||
$this->container = $this->prophesize(ContainerInterface::class); | ||
$this->fileLocRepoFactory = new FileLocationRepositoryFactory(); | ||
} | ||
|
||
public function testFactoryReturnsFileLocationRepository() | ||
{ | ||
$factory = $this->fileLocRepoFactory; | ||
$fileLocRepo = $factory($this->container->reveal()); | ||
$this->assertInstanceOf(FileLocationRepository::class, $fileLocRepo); | ||
} | ||
|
||
public function testFactoryUsesConfiguredDocumentRoot() | ||
{ | ||
$dir = getcwd() . '/public/'; | ||
$this->container->get('config')->willReturn([ | ||
'mezzio-swoole' => [ | ||
'swoole-http-server' => [ | ||
'static-files' => [ | ||
'document-root' => [$dir] | ||
] | ||
] | ||
] | ||
]); | ||
$factory = $this->fileLocRepoFactory; | ||
$fileLocRepo = $factory($this->container->reveal()); | ||
$this->assertEquals(['/' => [$dir]], $fileLocRepo->listMappedDocumentRoots()); | ||
} | ||
|
||
public function testFactoryHasNoDefaultsIfEmptyDocumentRoot() | ||
{ | ||
$dir = getcwd() . '/public/'; | ||
$this->container->get('config')->willReturn([ | ||
'mezzio-swoole' => [ | ||
'swoole-http-server' => [ | ||
'static-files' => [ | ||
'document-root' => [] | ||
] | ||
] | ||
] | ||
]); | ||
$factory = $this->fileLocRepoFactory; | ||
$fileLocRepo = $factory($this->container->reveal()); | ||
$this->assertEquals([], $fileLocRepo->listMappedDocumentRoots()); | ||
} | ||
|
||
public function testFactoryUsesDefaultDocumentRoot() | ||
{ | ||
$dir = getcwd() . '/public/'; | ||
$factory = $this->fileLocRepoFactory; | ||
$fileLocRepo = $factory($this->container->reveal()); | ||
$this->assertEquals(['/' => [$dir]], $fileLocRepo->listMappedDocumentRoots()); | ||
} | ||
} |
Oops, something went wrong.