diff --git a/src/File.php b/src/File.php index 4b4f4e5..957c536 100644 --- a/src/File.php +++ b/src/File.php @@ -4,6 +4,9 @@ namespace DigitalCz\Streams; +use InvalidArgumentException; +use Psr\Http\Message\StreamInterface as PsrStreamInterface; + final class File implements FileInterface { use StreamDecoratorTrait; @@ -39,6 +42,42 @@ public static function temp(): self return new self($path); } + /** + * @param PsrStreamInterface|resource|string $from + */ + public static function from(mixed $from): self + { + if ($from instanceof PsrStreamInterface) { + $file = self::temp(); + $file->copy($from); + $file->rewind(); + + return $file; + } + + if (is_string($from)) { + if (file_exists($from)) { + return new self($from); + } + + $file = self::temp(); + $file->write($from); + $file->rewind(); + + return $file; + } + + if (is_resource($from)) { + $file = self::temp(); + $file->copy(new Stream($from)); + $file->rewind(); + + return $file; + } + + throw new InvalidArgumentException(sprintf('Cannot create %s from %s.', self::class, get_debug_type($from))); + } + public function getPath(): string { return $this->path; diff --git a/tests/FileTest.php b/tests/FileTest.php index 895d235..0f07e87 100644 --- a/tests/FileTest.php +++ b/tests/FileTest.php @@ -4,7 +4,9 @@ namespace DigitalCz\Streams; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; +use stdClass; /** * @covers \DigitalCz\Streams\File @@ -36,4 +38,47 @@ public function testTemp(): void self::assertSame('plainfile', $file->getMetadata('wrapper_type')); self::assertSame('STDIO', $file->getMetadata('stream_type')); } + + public function testFromStream(): void + { + $stream = Stream::from('test'); + $file = File::from($stream); + self::assertSame('test', $file->getContents()); + } + + public function testFromString(): void + { + $file = File::from('test'); + self::assertSame('test', $file->getContents()); + } + + public function testFromFilename(): void + { + $path = tempnam(sys_get_temp_dir(), 'temp'); + self::assertNotFalse($path); + file_put_contents($path, 'test'); + + $file = File::from($path); + self::assertSame('test', $file->getContents()); + } + + public function testFromResource(): void + { + $resource = fopen('php://temp', 'wb+'); + self::assertNotFalse($resource); + fwrite($resource, 'test'); + fseek($resource, 0); + + $file = File::from($resource); + self::assertSame('test', $file->getContents()); + } + + public function testFromInvalid(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Cannot create DigitalCz\Streams\File from stdClass'); + + $object = new stdClass(); + File::from($object); // @phpstan-ignore-line + } }