-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Working on new component for filesystems (#51)
- Loading branch information
0 parents
commit 9e1d0cf
Showing
35 changed files
with
1,922 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/Tests export-ignore | ||
/phpunit.xml.dist export-ignore | ||
/.gitattributes export-ignore | ||
/.gitignore export-ignore |
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,3 @@ | ||
composer.lock | ||
phpunit.xml | ||
vendor/ |
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,60 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SonsOfPHP\Component\Filesystem\Adapter; | ||
|
||
use SonsOfPHP\Component\Filesystem\ContextInterface; | ||
use SonsOfPHP\Component\Filesystem\Exception\FilesystemException; | ||
use SonsOfPHP\Component\Filesystem\Exception\FileNotFoundException; | ||
|
||
/** | ||
* Base Adapter Interface that all adapters implement. | ||
* | ||
* @author Joshua Estes <[email protected]> | ||
*/ | ||
interface AdapterInterface | ||
{ | ||
/** | ||
* Adds a file to the filesystem. | ||
* | ||
* @param string|resource $contents | ||
* Can either be a string or a resource. If not one of these types, the | ||
* adapter should throw an exception | ||
* | ||
* @throws FilesystemException When $contents is invalid argument | ||
* @throws FilesystemException Generic Failure Exception | ||
*/ | ||
public function add(string $path, mixed $contents, ?ContextInterface $context = null): void; | ||
|
||
/** | ||
* Returns the content of a given file found at $path | ||
* | ||
* @throws FileNotFoundException When $path does not exist | ||
* @throws FilesystemException Generic Failure Exception | ||
* | ||
* @return string|resouce | ||
* This should return either a string or resouce | ||
*/ | ||
public function get(string $path, ?ContextInterface $context = null): mixed; | ||
|
||
/** | ||
* Deletes files and directories | ||
* | ||
* @throws FileNotFouneException When $path does not exist | ||
* @throws FilesystemException Generic Failure Exception | ||
*/ | ||
public function remove(string $path, ?ContextInterface $context = null): void; | ||
|
||
/** | ||
* Checks to see if a file or directory exists | ||
* | ||
* @throws FilesystemException Generic Failure Exception | ||
*/ | ||
public function has(string $path, ?ContextInterface $context = null): bool; | ||
|
||
/** | ||
* @throws FilesystemException Generic Failure Exception | ||
*/ | ||
public function isFile(string $path, ?ContextInterface $context = null): bool; | ||
} |
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,107 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SonsOfPHP\Component\Filesystem\Adapter; | ||
|
||
use SonsOfPHP\Component\Filesystem\ContextInterface; | ||
use SonsOfPHP\Component\Filesystem\Exception\FileNotFoundException; | ||
use SonsOfPHP\Component\Filesystem\Exception\FilesystemException; | ||
|
||
/** | ||
* Chain adapter allows you to use multiple adapters together. | ||
* | ||
* Usage: | ||
* $adapter = new ChainAdapter([new InMemoryAdapter(), new NativeAdapter('/tmp')]); | ||
* | ||
* @author Joshua Estes <[email protected]> | ||
*/ | ||
final class ChainAdapter implements AdapterInterface, CopyAwareInterface, DirectoryAwareInterface, MoveAwareInterface | ||
{ | ||
public function __construct( | ||
private iterable $adapters, | ||
) {} | ||
|
||
public function add(string $path, mixed $contents, ?ContextInterface $context = null): void | ||
{ | ||
foreach ($this->adapters as $adapter) { | ||
$adapter->add($path, $contents, $context); | ||
} | ||
} | ||
|
||
public function get(string $path, ?ContextInterface $context = null): mixed | ||
{ | ||
foreach ($this->adapters as $adapter) { | ||
if ($adapter->has($path, $context)) { | ||
return $adapter->get($path, $context); | ||
} | ||
} | ||
|
||
throw new FileNotFoundException(); | ||
} | ||
|
||
public function remove(string $path, ?ContextInterface $context = null): void | ||
{ | ||
foreach ($this->adapters as $adapter) { | ||
$adapter->remove($path, $context); | ||
} | ||
} | ||
|
||
public function has(string $path, ?ContextInterface $context = null): bool | ||
{ | ||
foreach ($this->adapters as $adapter) { | ||
if ($adapter->has($path, $context)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public function isFile(string $path, ?ContextInterface $context = null): bool | ||
{ | ||
foreach ($this->adapters as $adapter) { | ||
if ($adapter->isFile($path, $context)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public function copy(string $source, string $destination, ?ContextInterface $context = null): void | ||
{ | ||
foreach ($this->adapters as $adapter) { | ||
if ($adapter instanceof CopyAwareInterface) { | ||
$adapter->copy($source, $destination, $context); | ||
continue; | ||
} | ||
|
||
$adapter->add($destination, $adapter->get($source, $context), $context); | ||
} | ||
} | ||
|
||
public function isDirectory(string $path, ?ContextInterface $context = null): bool | ||
{ | ||
foreach ($this->adapters as $adapter) { | ||
if ($adapter instanceof DirectoryAwareInterface && $adapter->isDirectory($path, $context)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public function move(string $source, string $destination, ?ContextInterface $context = null): void | ||
{ | ||
foreach ($this->adapters as $adapter) { | ||
if ($adapter instanceof MoveAwareInterface) { | ||
$adapter->move($source, $destination, $context); | ||
continue; | ||
} | ||
|
||
$adapter->add($destination, $adapter->get($source, $context), $context); | ||
$adapter->remove($source, $context); | ||
} | ||
} | ||
} |
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,27 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SonsOfPHP\Component\Filesystem\Adapter; | ||
|
||
use SonsOfPHP\Component\Filesystem\ContextInterface; | ||
use SonsOfPHP\Component\Filesystem\Exception\FilesystemException; | ||
use SonsOfPHP\Component\Filesystem\Exception\FileNotFoundException; | ||
|
||
/** | ||
* If an adapter supports the ability to copy a file from one place to another | ||
* they should implement this interface. | ||
* | ||
* @author Joshua Estes <[email protected]> | ||
*/ | ||
interface CopyAwareInterface | ||
{ | ||
/** | ||
* Copies file from $source to $destination | ||
* | ||
* @throws FileNotFoundException When $source does not exist | ||
* @throws FilesystemException Generic Failure Exception, might be throw | ||
* if destintation exists | ||
*/ | ||
public function copy(string $source, string $destination, ?ContextInterface $context = null): void; | ||
} |
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,23 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SonsOfPHP\Component\Filesystem\Adapter; | ||
|
||
use SonsOfPHP\Component\Filesystem\ContextInterface; | ||
use SonsOfPHP\Component\Filesystem\Exception\FilesystemException; | ||
use SonsOfPHP\Component\Filesystem\Exception\FileNotFoundException; | ||
|
||
/** | ||
* If an adapter is able to manage directories, it should implement this | ||
* interface. | ||
* | ||
* @author Joshua Estes <[email protected]> | ||
*/ | ||
interface DirectoryAwareInterface | ||
{ | ||
/** | ||
* @throws FilesystemException Generic Failure Exception | ||
*/ | ||
public function isDirectory(string $path, ?ContextInterface $context = null): bool; | ||
} |
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,98 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SonsOfPHP\Component\Filesystem\Adapter; | ||
|
||
use SonsOfPHP\Component\Filesystem\ContextInterface; | ||
use SonsOfPHP\Component\Filesystem\Exception\FileNotFoundException; | ||
use SonsOfPHP\Component\Filesystem\Exception\UnableToReadFileException; | ||
|
||
/** | ||
* Just keeps files in memory, does not write anything to disk | ||
* | ||
* Usage: | ||
* $adapter = new InMemoryAdapter(); | ||
* | ||
* @author Joshua Estes <[email protected]> | ||
*/ | ||
final class InMemoryAdapter implements AdapterInterface, CopyAwareInterface, MoveAwareInterface, DirectoryAwareInterface | ||
{ | ||
private array $files = []; | ||
|
||
public function add(string $path, mixed $contents, ?ContextInterface $context = null): void | ||
{ | ||
$path = $this->normalizePath($path); | ||
|
||
if (is_resource($contents)) { | ||
$contents = stream_get_contents($contents, null, 0); | ||
} | ||
|
||
$this->files[$path] = $contents; | ||
} | ||
|
||
public function get(string $path, ?ContextInterface $context = null): string | ||
{ | ||
$path = $this->normalizePath($path); | ||
|
||
if (!array_key_exists($path, $this->files)) { | ||
throw new UnableToReadFileException(sprintf('No file was found at "%s"', $path)); | ||
} | ||
|
||
return $this->files[$path]; | ||
} | ||
|
||
public function remove(string $path, ?ContextInterface $context = null): void | ||
{ | ||
$path = $this->normalizePath($path); | ||
|
||
unset($this->files[$path]); | ||
} | ||
|
||
public function copy(string $source, string $destination, ?ContextInterface $context = null): void | ||
{ | ||
$source = $this->normalizePath($source); | ||
$destination = $this->normalizePath($destination); | ||
|
||
$this->files[$destination] = $this->files[$source]; | ||
} | ||
|
||
public function move(string $source, string $destination, ?ContextInterface $context = null): void | ||
{ | ||
$this->copy($source, $destination); | ||
$this->remove($source); | ||
} | ||
|
||
public function has(string $path, ?ContextInterface $context = null): bool | ||
{ | ||
return $this->isFile($path) || $this->isDirectory($path); | ||
} | ||
|
||
public function isFile(string $path, ?ContextInterface $context = null): bool | ||
{ | ||
$path = $this->normalizePath($path); | ||
|
||
return array_key_exists($path, $this->files); | ||
} | ||
|
||
public function isDirectory(string $path, ?ContextInterface $context = null): bool | ||
{ | ||
$path = $this->normalizePath($path); | ||
|
||
foreach ($this->files as $key => $contents) { | ||
$parts = explode('/', $key); | ||
array_pop($parts); | ||
|
||
if (implode('/', $parts) === $path) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
private function normalizePath(string $path): string | ||
{ | ||
return ltrim($path, '/'); | ||
} | ||
} |
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,27 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SonsOfPHP\Component\Filesystem\Adapter; | ||
|
||
use SonsOfPHP\Component\Filesystem\ContextInterface; | ||
use SonsOfPHP\Component\Filesystem\Exception\FilesystemException; | ||
use SonsOfPHP\Component\Filesystem\Exception\FileNotFoundException; | ||
|
||
/** | ||
* If an adapter supports the ability to move a file from one place to another | ||
* they should implement this interface. | ||
* | ||
* @author Joshua Estes <[email protected]> | ||
*/ | ||
interface MoveAwareInterface | ||
{ | ||
/** | ||
* Moves file from $source to $destination | ||
* | ||
* @throws FileNotFoundException When $source does not exist | ||
* @throws FilesystemException Generic Failure Exception, might be throw | ||
* if destintation exists | ||
*/ | ||
public function move(string $source, string $destination, ?ContextInterface $context = null): void; | ||
} |
Oops, something went wrong.