feat: adds filesystem component
To do:
- [x] Add basic file manipulation.
- [ ] Add file stream interaction.
- [x] Add basic directory manipulation.
- [ ] Add directory iteration helpers?
- [ ] Spot check error checking + security.
- [x] 100% coverage.
Closes #272
Hey, it might be good to check how https://github.com/thephpleague/Flysystem/blob/3.x/src%2FLocal%2FLocalFilesystemAdapter.php uses clearstatcache to avoid edge cases.
Yes, for sure we will want to utilize clearstatcache. 🙂
Do we want to avoid the dependency on Flysystem? I think it would be less work to wrap them than to rewrite and maintain an equivalent. This would also allow people to use third-party Flysystem adapters, as this is the de-facto storage implementation in PHP land
Hey, @innocenzi! See #272 where we discuss this a little bit. I'd like to keep this portion lightweight and independent of Flysystem, but potentially make use of it for the "storage" component.
Ah sorry, didn't check the linked issue. Makes total sense 👌
One thing I want to be possible is to create a file WITH the directory if it doesn't exist, so basically a oneliner for this
if (! is_dir(dirname($path))) {
mkdir(dirname($path), recursive: true);
}
file_put_contents(…
// or
copy(__DIR__ . '/index.php', $path);
Definitely a good thought. I'll think about the API a bit. I'd like to also allow the disabling of that functionality if the developer determines they don't want that to happen.
@brendt - What do you think about the API with the Permission class here? I have a couple of thoughts...
We could simplify the combinations by allowing an integer to the with method. So then you could do:
Permission::allow(
Permission::ownerReadWrite(),
Permission::groupRead(),
Permission::othersRead(),
);
There's not an easy way to validate that though.
@aidan-casey instead of providing methods that combine permissions, I'd simply provide values:
case OWNER_ALL = 0o700;
case OWNER_READ_WRITE = 0o600;
case OWNER_READ_EXECUTE = 0o500;
case OWNER_WRITE_EXECUTE = 0o300;
case OWNER_NONE = 0o000;
…
It's only 8 permutations per role, which I think it fine, and it would make your example possible without having to typehint on int.
I'd also add a without method on the enum which starts from 777 and subtracts
Sidenote: this is a genius idea and I already don't want anything else anymore
@brendt - Good thought. Instead of counting back from 777, I am counting back from the current value. It feels safer to me than something like:
// With counting from 777: 577
Permission::OWNER_FULL->without(Permission::OWNER_WRITE);
// With counting from current value (700): 500
Permission::OWNER_FULL->without(Permission::OWNER_WRITE);
With that, I did add Permission::FULL though which could be used like so:
// 744
Permission::FULL->without(
Permission::GROUP_WRITE_EXECUTE,
Permission::OTHERS_WRITE_EXECUTE
);
Let me know if you want to change that though.
Totally agree, this is awesome
Mental note:
- Exception messages are a little inconsistent right now. Clean that up.
- Method behavior is a little inconsistent right now. Clean that up.
- Determine a good API for directory traversal maybe use in methods like
deleteDirectory. - Add some helpers for file metadata.
- Add some helpers for file streams.
Pull Request Test Coverage Report for Build 11676909429
Details
- 120 of 120 (100.0%) changed or added relevant lines in 10 files are covered.
- No unchanged relevant lines lost coverage.
- Overall coverage increased (+0.2%) to 82.844%
| Totals | |
|---|---|
| Change from base Build 11675478150: | 0.2% |
| Covered Lines: | 7224 |
| Relevant Lines: | 8720 |
💛 - Coveralls
I think the best way forward with this PR is to rebase and merge it. We can always improve on it later, but right now it's in limbo and no one else is able to help with it because it's not on main but a separate branch.
@aidan-casey wdyt?