Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/elazar/flystream

PHP stream wrapper for Flysystem v2/3
https://github.com/elazar/flystream

Last synced: 6 days ago
JSON representation

PHP stream wrapper for Flysystem v2/3

Awesome Lists containing this project

README

        

# Flystream

[![PHP Version Support](https://img.shields.io/static/v1?label=php&message=%3E=%208.1.0&color=blue)](https://packagist.org/packages/elazar/flystream)
[![Packagist Version](https://img.shields.io/static/v1?label=packagist&message=1.2.0&color=blue)](https://packagist.org/packages/elazar/flystream)
[![Software License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE.md)
[![Buy Me a Cofee](https://img.shields.io/badge/buy%20me%20a%20coffee-donate-blue.svg)](https://ko-fi.com/elazar)

[Flysystem v2/3](https://flysystem.thephpleague.com/v2/docs/) + [PHP stream wrappers](https://www.php.net/manual/en/class.streamwrapper.php) = 🔥

Flystream enables you to use core PHP filesystem functions to interact with Flysystem filesystems by registering them as custom protocols.

Released under the [MIT License](https://en.wikipedia.org/wiki/MIT_License).

## Supported Use Cases

* Using Flysystem with another library that interacts with the filesystem using PHP filesystem functions instead of Flysystem.
* Intercepting filesystem operations for verification in tests.
* Improving the speed of tests where the code under test would otherwise require access to the local filesystem.

## Unsupported Use Cases

* Flystream doesn't and won't support Flysystem v1. If you want a similar library for v1, see [twistor/flysystem-stream-wrapper](https://github.com/twistor/flysystem-stream-wrapper).

## Known Issues

* If a file or directory handle is not explicitly closed after use (i.e. using [`fclose()`](https://www.php.net/fclose) or [`closedir()`](https://www.php.net/closedir) as appropriate), PHP will implicitly attempt to close it during [shutdown](https://www.php.net/manual/en/function.register-shutdown-function.php). This situation may trigger a segmentation fault in some environments. This issue has [been resolved](https://github.com/elazar/xdebug-date-stream-php-segfault) and is available in PHP 7.4.23, 8.0.10, and 8.1.0. In older versions, the easiest work-around is to ensure that file and directory handles are explicitly closed.

## Requirements

* PHP 8.1+
* Flysystem 2 or 3

## Installation

Use [Composer](https://getcomposer.org/).

```sh
composer require elazar/flystream
```

**Note**: This will automatically install the latest version of the Flysystem core library that is available for your environment. However, you must handle installing adapters yourself. See [the Flysystem documentation](https://flysystem.thephpleague.com/docs/) for a list of official adapters.

## Usage

If you want to run the examples below, you will need to install [`league/flysystem-memory`](https://packagist.org/packages/league/flysystem-memory).

```sh
composer require league/flysystem-memory
```

These examples below aren't comprehensive, but should provide a basic understanding of the capabilities of Flystream.

```php
register('mem', $filesystem);

/**
* 3. Interact with the filesystem using the custom protocol.
*/

mkdir('mem://foo');

$file = fopen('mem://foo/bar', 'w');
fwrite($file, 'baz');
fclose($file);

file_put_contents('mem://foo/bar', 'bay');

$contents = file_get_contents('mem://foo/bar');
// or
$contents = stream_get_contents(fopen('mem://foo/bar', 'r'));

if (file_exists('mem://foo/bar')) {
rename('mem://foo/bar', 'mem://foo/baz');
touch('mem://foo/bar');
}

$file = fopen('mem://foo/baz', 'r');
fseek($file, 2);
$position = ftell($file);
ftruncate($file, 0);
fclose($file);

$dir = opendir('mem://foo');
while (($entry = readdir($dir)) !== false) {
echo $entry, PHP_EOL;
}
closedir($dir);

unlink('mem://foo/bar');
unlink('mem://foo/baz');

rmdir('mem://foo');

// These won't have any effect because Flysystem doesn't support them.
chmod('mem://foo', 0755);
chown('mem://foo', 'root');
chgrp('mem://foo', 'root');

/**
* 4. Optionally, unregister the filesystem with Flystream.
*/
$registry->unregister('mem');
```

## Configuration

For its most basic use, Flystream requires two parameters:

1. a string containing a name for a custom protocol used by PHP filesystem functions; and
2. an object that implements the Flysystem `FilesystemOperator` interface (e.g. an instance of the `Filesystem` class).

### Path Normalization

The Flysystem `Filesystem` class supports normalization of supplied paths before they're passed to the underlying adapter. The Flysystem `PathNormalizer` interface represents this normalization process.

The implementation of this interface that Flysystem uses by default is `WhitespacePathNormalizer`, which handles normalizing the directory separator (i.e. converting `\` to `/`), removing abnormal whitespace characters, and resolving relative paths.

If you're using a third-party adapter, you'll probably need path normalization to include removing the custom protocol used to register the Flysystem filesystem with Flystream. As such, by default, Flystream registers a custom path normalizer that it defines, `StripProtocolPathNormalizer`. You can configure your `Filesystem` instance to use this normalizer like so.

```php
setMaxMemory($maxMemory);
ServiceLocator::set(BufferInterface::class, $buffer);
```

You may want to check the value of your [`memory_limit`](https://www.php.net/manual/en/ini.core.php#ini.memory-limit) PHP INI setting and use either a [profiler](http://xdebug.org/docs/profiler) or functions like [`memory_get_usage()`](https://www.php.net/memory_get_usage) and [`memory_get_peak_usage()`](https://www.php.net/memory_get_peak_usage) to get an idea of which strategy is best for your use case.

Another option is using your own buffer strategy implementation, by creating a class that implements `BufferInterface` and then configuring Flystream to use it in the same fashion as the above examples.

### Visibility

Flysystem implements an abstraction layer for [visibility](https://flysystem.thephpleague.com/v2/docs/usage/unix-visibility/) and an implementation for handling [Unix-style visibility](https://flysystem.thephpleague.com/v2/docs/usage/unix-visibility/).

By default, Flystream uses this Unix-style visibility implementation with its default configuration. If you want to override its settings, you can override it with a configured instance.

```php