├── .phpunit-watcher.yml ├── .styleci.yml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── config └── common.php ├── infection.json.dist ├── psalm.xml ├── rector.php └── src ├── FileStorageConfigs.php ├── Filesystem.php └── FilesystemInterface.php /.phpunit-watcher.yml: -------------------------------------------------------------------------------- 1 | watch: 2 | directories: 3 | - src 4 | - tests 5 | fileMask: '*.php' 6 | notifications: 7 | passingTests: false 8 | failingTests: false 9 | phpunit: 10 | binaryPath: vendor/bin/phpunit 11 | timeout: 180 12 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: psr12 2 | risky: true 3 | 4 | version: 8 5 | 6 | finder: 7 | exclude: 8 | - docs 9 | - vendor 10 | - resources 11 | - views 12 | - public 13 | - templates 14 | not-name: 15 | - UnionCar.php 16 | - TimerUnionTypes.php 17 | - schema1.php 18 | 19 | enabled: 20 | - alpha_ordered_traits 21 | - array_indentation 22 | - array_push 23 | - combine_consecutive_issets 24 | - combine_consecutive_unsets 25 | - combine_nested_dirname 26 | - declare_strict_types 27 | - dir_constant 28 | - fully_qualified_strict_types 29 | - function_to_constant 30 | - hash_to_slash_comment 31 | - is_null 32 | - logical_operators 33 | - magic_constant_casing 34 | - magic_method_casing 35 | - method_separation 36 | - modernize_types_casting 37 | - native_function_casing 38 | - native_function_type_declaration_casing 39 | - no_alias_functions 40 | - no_empty_comment 41 | - no_empty_phpdoc 42 | - no_empty_statement 43 | - no_extra_block_blank_lines 44 | - no_short_bool_cast 45 | - no_superfluous_elseif 46 | - no_unneeded_control_parentheses 47 | - no_unneeded_curly_braces 48 | - no_unneeded_final_method 49 | - no_unset_cast 50 | - no_unused_imports 51 | - no_unused_lambda_imports 52 | - no_useless_else 53 | - no_useless_return 54 | - normalize_index_brace 55 | - php_unit_dedicate_assert 56 | - php_unit_dedicate_assert_internal_type 57 | - php_unit_expectation 58 | - php_unit_mock 59 | - php_unit_mock_short_will_return 60 | - php_unit_namespaced 61 | - php_unit_no_expectation_annotation 62 | - phpdoc_no_empty_return 63 | - phpdoc_no_useless_inheritdoc 64 | - phpdoc_order 65 | - phpdoc_property 66 | - phpdoc_scalar 67 | - phpdoc_separation 68 | - phpdoc_singular_inheritdoc 69 | - phpdoc_trim 70 | - phpdoc_trim_consecutive_blank_line_separation 71 | - phpdoc_type_to_var 72 | - phpdoc_types 73 | - phpdoc_types_order 74 | - print_to_echo 75 | - regular_callable_call 76 | - return_assignment 77 | - self_accessor 78 | - self_static_accessor 79 | - set_type_to_cast 80 | - short_array_syntax 81 | - short_list_syntax 82 | - simplified_if_return 83 | - single_quote 84 | - standardize_not_equals 85 | - ternary_to_null_coalescing 86 | - trailing_comma_in_multiline_array 87 | - unalign_double_arrow 88 | - unalign_equals 89 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Yii filesystem Change Log 2 | 3 | ## 1.0.0 under development 4 | 5 | - Initial release. 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2008 by Yii Software (https://www.yiiframework.com/) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Yii Software nor the names of its 15 | contributors may be used to endorse or promote products derived 16 | from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | This package is deprecated. Use https://flysystem.thephpleague.com/ directly. 4 | 5 |

6 |

7 | ❌ 8 |

9 | 10 | --- 11 | 12 |

13 | 14 | 15 | 16 |

Yii filesystem

17 |
18 |

19 | 20 | An abstract filesystem that allows to swap underlying file system without rewriting application code. 21 | Based on [Flysystem](https://flysystem.thephpleague.com/v2/docs/). 22 | 23 | [![Latest Stable Version](https://poser.pugx.org/yiisoft/yii-filesystem/v/stable.png)](https://packagist.org/packages/yiisoft/yii-filesystem) 24 | [![Total Downloads](https://poser.pugx.org/yiisoft/yii-filesystem/downloads.png)](https://packagist.org/packages/yiisoft/yii-filesystem) 25 | [![Build status](https://github.com/yiisoft/yii-filesystem/workflows/build/badge.svg)](https://github.com/yiisoft/yii-filesystem/actions?query=workflow%3Abuild) 26 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/yiisoft/yii-filesystem/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/yii-filesystem/?branch=master) 27 | [![Code Coverage](https://scrutinizer-ci.com/g/yiisoft/yii-filesystem/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/yii-filesystem/?branch=master) 28 | [![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fyiisoft%2Fyii-filesystem%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/yiisoft/yii-filesystem/master) 29 | [![static analysis](https://github.com/yiisoft/yii-filesystem/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/yii-filesystem/actions?query=workflow%3A%22static+analysis%22) 30 | [![type-coverage](https://shepherd.dev/github/yiisoft/yii-filesystem/coverage.svg)](https://shepherd.dev/github/yiisoft/yii-filesystem) 31 | 32 | ## Requirements 33 | 34 | The package requires PHP 8.0 and is meant to be used with Yii3. 35 | 36 | ## Installation 37 | 38 | ``` 39 | composer require yiisoft/yii-filesystem 40 | ``` 41 | 42 | After installation, the `Yiisoft\Yii\Filesystem\FilesystemInterface` will be automatically registered 43 | in the main application container. This interface provides a local filesystem with root, as defined in the `@root` alias 44 | of the `aliases` parameter. 45 | 46 | ## Getting started 47 | 48 | The service could be obtained via DI container autowiring: 49 | 50 | ```php 51 | public function view(\Yiisoft\Yii\Filesystem\FilesystemInterface $filesystem) 52 | { 53 | $someFileContent = $filesystem->read('/runtime/somefile.txt'); 54 | //... 55 | } 56 | ``` 57 | 58 | Also you can use aliases 59 | 60 | ```php 61 | $someFileContent = $filesystem->write('@views/site/testfile.txt', 'Test content'); 62 | ``` 63 | 64 | ## Configuration 65 | 66 | Additional filesystems could be configured in `config/params.php` as described below: 67 | 68 | ```php 69 | 'file.storage' => [ 70 | 'runtimeStorage' => [ 71 | 'adapter' => [ 72 | 'class' => \League\Flysystem\Local\LocalFilesystemAdapter::class, 73 | '__construct()' => [ 74 | dirname(__DIR__) . '/runtime', 75 | \League\Flysystem\UnixVisibility\PortableVisibilityConverter::fromArray([ 76 | 'file' => [ 77 | 'public' => 0644, 78 | 'private' => 0600, 79 | ], 80 | 'dir' => [ 81 | 'public' => 0755, 82 | 'private' => 0700, 83 | ], 84 | ]), 85 | LOCK_EX, 86 | \League\Flysystem\Local\LocalFilesystemAdapter::DISALLOW_LINKS 87 | ] 88 | ], 89 | 'aliases' => [ 90 | '@cache' => '@root/cache', 91 | ] 92 | ], 93 | 'documentStorage' => [ 94 | 'adapter' => [ 95 | 'class' => \League\Flysystem\Local\LocalFilesystemAdapter::class, 96 | '__construct()' => [ 97 | dirname(__DIR__) . '/docs', 98 | \League\Flysystem\UnixVisibility\PortableVisibilityConverter::fromArray([ 99 | 'file' => [ 100 | 'public' => 0644, 101 | 'private' => 0600, 102 | ], 103 | 'dir' => [ 104 | 'public' => 0755, 105 | 'private' => 0700, 106 | ], 107 | ]), 108 | LOCK_EX, 109 | \League\Flysystem\Local\LocalFilesystemAdapter::DISALLOW_LINKS 110 | ] 111 | ], 112 | 'aliases' => [ 113 | '@invoices' => '@root/export/invoices', 114 | '@orders' => '@root/export/orders', 115 | ], 116 | ], 117 | ], 118 | ``` 119 | 120 | Aliases `runtimeStorage` and `documentStorage` will be automatically registered in the main application container. 121 | So, you can get it from the container: 122 | 123 | ```php 124 | public function index(ContainerInterface $container) 125 | { 126 | $documentStorage = $container->get('documentStorage'); 127 | } 128 | ``` 129 | 130 | If you prefer to use autowiring, you can create own interface for your filesystem. 131 | 132 | ```php 133 | interface ImageStorageInterface extends \Yiisoft\Yii\Filesystem\FilesystemInterface 134 | { 135 | } 136 | ``` 137 | 138 | And then register it in the `params`: 139 | 140 | ```php 141 | 'file.storage' => [ 142 | ImageStorageInterface::class => [ 143 | 'adapter' => [ 144 | 'class' => \League\Flysystem\Local\LocalFilesystemAdapter::class, 145 | '__construct()' => [ 146 | dirname(__DIR__) . '/storage/images', 147 | \League\Flysystem\UnixVisibility\PortableVisibilityConverter::fromArray([ 148 | 'file' => [ 149 | 'public' => 0644, 150 | 'private' => 0600, 151 | ], 152 | 'dir' => [ 153 | 'public' => 0755, 154 | 'private' => 0700, 155 | ], 156 | ]), 157 | LOCK_EX, 158 | \League\Flysystem\Local\LocalFilesystemAdapter::DISALLOW_LINKS 159 | ] 160 | ], 161 | ], 162 | ] 163 | ``` 164 | 165 | Now you can use it like this: 166 | 167 | ```php 168 | //controller action 169 | public function addImage(ImageStorageInterface $imageStorage) 170 | { 171 | //get image stream... 172 | 173 | $imageStorage->writeStream('/path/to/image/myimage.jpeg', $myImageStream); 174 | } 175 | ``` 176 | 177 | You can find documentation on `FilesystemInterface` methods in the [Flysystem Docs](https://flysystem.thephpleague.com/v2/docs/). 178 | 179 | ### Unit testing 180 | 181 | The package is tested with [PHPUnit](https://phpunit.de/). To run tests: 182 | 183 | ```shell 184 | ./vendor/bin/phpunit 185 | ``` 186 | 187 | ### Mutation testing 188 | 189 | The package tests are checked with [Infection](https://infection.github.io/) mutation framework. To run it: 190 | 191 | ```shell 192 | ./vendor/bin/infection 193 | ``` 194 | 195 | ### Static analysis 196 | 197 | The code is statically analyzed with [Psalm](https://psalm.dev/). To run static analysis: 198 | 199 | ```shell 200 | ./vendor/bin/psalm 201 | ``` 202 | 203 | ### Support the project 204 | 205 | [![Open Collective](https://img.shields.io/badge/Open%20Collective-sponsor-7eadf1?logo=open%20collective&logoColor=7eadf1&labelColor=555555)](https://opencollective.com/yiisoft) 206 | 207 | ### Follow updates 208 | 209 | [![Official website](https://img.shields.io/badge/Powered_by-Yii_Framework-green.svg?style=flat)](https://www.yiiframework.com/) 210 | [![Twitter](https://img.shields.io/badge/twitter-follow-1DA1F2?logo=twitter&logoColor=1DA1F2&labelColor=555555?style=flat)](https://twitter.com/yiiframework) 211 | [![Telegram](https://img.shields.io/badge/telegram-join-1DA1F2?style=flat&logo=telegram)](https://t.me/yii3en) 212 | [![Facebook](https://img.shields.io/badge/facebook-join-1DA1F2?style=flat&logo=facebook&logoColor=ffffff)](https://www.facebook.com/groups/yiitalk) 213 | [![Slack](https://img.shields.io/badge/slack-join-1DA1F2?style=flat&logo=slack)](https://yiiframework.com/go/slack) 214 | 215 | ## License 216 | 217 | The Yii filesystem is free software. It is released under the terms of the BSD License. 218 | Please see [`LICENSE`](./LICENSE.md) for more information. 219 | 220 | Maintained by [Yii Software](https://www.yiiframework.com/). 221 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yiisoft/yii-filesystem", 3 | "type": "library", 4 | "description": "yii-filesystem", 5 | "keywords": [ 6 | "filesystem", 7 | "file", 8 | "system" 9 | ], 10 | "homepage": "https://www.yiiframework.com/", 11 | "license": "BSD-3-Clause", 12 | "support": { 13 | "issues": "https://github.com/yiisoft/yii-filesystem/issues?state=open", 14 | "forum": "https://www.yiiframework.com/forum/", 15 | "wiki": "https://www.yiiframework.com/wiki/", 16 | "irc": "irc://irc.freenode.net/yii", 17 | "chat": "https://t.me/yii3en", 18 | "source": "https://github.com/yiisoft/yii-filesystem" 19 | }, 20 | "minimum-stability": "dev", 21 | "prefer-stable": true, 22 | "require": { 23 | "php": "^8.0", 24 | "league/flysystem": "^2.0", 25 | "yiisoft/aliases": "^1.1|^2.0", 26 | "yiisoft/di": "^1.0" 27 | }, 28 | "require-dev": { 29 | "phpunit/phpunit": "^9.5", 30 | "rector/rector": "^0.15.1", 31 | "roave/infection-static-analysis-plugin": "^1.16", 32 | "spatie/phpunit-watcher": "^1.23", 33 | "vimeo/psalm": "^4.18" 34 | }, 35 | "autoload": { 36 | "psr-4": { 37 | "Yiisoft\\Yii\\Filesystem\\": "src" 38 | } 39 | }, 40 | "autoload-dev": { 41 | "psr-4": { 42 | "Yiisoft\\Yii\\Filesystem\\Tests\\": "tests" 43 | } 44 | }, 45 | "extra": { 46 | "branch-alias": { 47 | "dev-master": "3.0.x-dev" 48 | }, 49 | "config-plugin-options": { 50 | "source-directory": "config" 51 | }, 52 | "config-plugin": { 53 | "common": "common.php" 54 | } 55 | }, 56 | "scripts": { 57 | "phan": "phan --progress-bar -o analysis.txt", 58 | "test": "phpunit --testdox --no-interaction", 59 | "test-watch": "phpunit-watcher watch" 60 | }, 61 | "config": { 62 | "sort-packages": true, 63 | "allow-plugins": { 64 | "infection/extension-installer": true, 65 | "composer/package-versions-deprecated": true 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /config/common.php: -------------------------------------------------------------------------------- 1 | static function () use ($params) { 17 | $aliases = $params['yiisoft/aliases']['aliases'] ?? []; 18 | if (!isset($aliases['@root'])) { 19 | throw new \RuntimeException('Alias of the root directory is not defined.'); 20 | } 21 | 22 | $adapter = new LocalFilesystemAdapter( 23 | $aliases['@root'], 24 | PortableVisibilityConverter::fromArray([ 25 | 'file' => [ 26 | 'public' => 0644, 27 | 'private' => 0600, 28 | ], 29 | 'dir' => [ 30 | 'public' => 0755, 31 | 'private' => 0700, 32 | ], 33 | ]), 34 | LOCK_EX, 35 | LocalFilesystemAdapter::DISALLOW_LINKS 36 | ); 37 | 38 | return new Filesystem($adapter, $aliases); 39 | }, 40 | FileStorageConfigs::class => static fn () => new FileStorageConfigs($params['file.storage'] ?? []), 41 | ]; 42 | -------------------------------------------------------------------------------- /infection.json.dist: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "directories": [ 4 | "src" 5 | ] 6 | }, 7 | "logs": { 8 | "text": "php:\/\/stderr", 9 | "stryker": { 10 | "report": "master" 11 | } 12 | }, 13 | "mutators": { 14 | "@default": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /psalm.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /rector.php: -------------------------------------------------------------------------------- 1 | paths([ 11 | __DIR__ . '/src', 12 | __DIR__ . '/tests', 13 | ]); 14 | 15 | // register a single rule 16 | $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); 17 | 18 | // define sets of rules 19 | $rectorConfig->sets([ 20 | LevelSetList::UP_TO_PHP_80, 21 | ]); 22 | }; 23 | -------------------------------------------------------------------------------- /src/FileStorageConfigs.php: -------------------------------------------------------------------------------- 1 | storageConfigs; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Filesystem.php: -------------------------------------------------------------------------------- 1 | prepareAliases($aliases); 24 | 25 | parent::__construct($adapter, $config, $pathNormalizer); 26 | } 27 | 28 | public function fileExists(string $location): bool 29 | { 30 | $location = $this->aliases->get($location); 31 | return parent::fileExists($location); 32 | } 33 | 34 | public function write(string $location, string $contents, array $config = []): void 35 | { 36 | $location = $this->aliases->get($location); 37 | parent::write($location, $contents, $config); 38 | } 39 | 40 | public function writeStream(string $location, $contents, array $config = []): void 41 | { 42 | $location = $this->aliases->get($location); 43 | parent::writeStream($location, $contents, $config); 44 | } 45 | 46 | public function read(string $location): string 47 | { 48 | $location = $this->aliases->get($location); 49 | return parent::read($location); 50 | } 51 | 52 | public function readStream(string $location) 53 | { 54 | $location = $this->aliases->get($location); 55 | return parent::readStream($location); 56 | } 57 | 58 | public function delete(string $location): void 59 | { 60 | $location = $this->aliases->get($location); 61 | parent::delete($location); 62 | } 63 | 64 | public function createDirectory(string $location, array $config = []): void 65 | { 66 | $location = $this->aliases->get($location); 67 | parent::createDirectory($location, $config); 68 | } 69 | 70 | public function deleteDirectory(string $location): void 71 | { 72 | $location = $this->aliases->get($location); 73 | parent::deleteDirectory($location); 74 | } 75 | 76 | public function copy(string $source, string $destination, array $config = []): void 77 | { 78 | $source = $this->aliases->get($source); 79 | $destination = $this->aliases->get($destination); 80 | parent::copy($source, $destination, $config); 81 | } 82 | 83 | public function move(string $source, string $destination, array $config = []): void 84 | { 85 | $source = $this->aliases->get($source); 86 | $destination = $this->aliases->get($destination); 87 | parent::move($source, $destination, $config); 88 | } 89 | 90 | public function setVisibility(string $path, string $visibility): void 91 | { 92 | $path = $this->aliases->get($path); 93 | parent::setVisibility($path, $visibility); 94 | } 95 | 96 | public function visibility(string $path): string 97 | { 98 | $path = $this->aliases->get($path); 99 | return parent::visibility($path); 100 | } 101 | 102 | public function mimeType(string $path): string 103 | { 104 | $path = $this->aliases->get($path); 105 | return parent::mimeType($path); 106 | } 107 | 108 | public function lastModified(string $path): int 109 | { 110 | $path = $this->aliases->get($path); 111 | return parent::lastModified($path); 112 | } 113 | 114 | public function listContents(string $location, bool $deep = LeagueFilesystem::LIST_SHALLOW): DirectoryListing 115 | { 116 | $location = $this->aliases->get($location); 117 | return parent::listContents($location, $deep); 118 | } 119 | 120 | public function fileSize(string $path): int 121 | { 122 | $path = $this->aliases->get($path); 123 | return parent::fileSize($path); 124 | } 125 | 126 | private function prepareAliases(array $aliases): void 127 | { 128 | if ($aliases !== []) { 129 | $aliases = array_merge(['@root' => ''], $aliases); 130 | $aliases['@root'] = ''; 131 | } 132 | $this->aliases = new Aliases($aliases); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/FilesystemInterface.php: -------------------------------------------------------------------------------- 1 |