refactor: Cleanup git state - commit all staged changes

Major refactoring cleanup:
- Add new controller architecture (class-controller-*.php)
- Add new settings-v2 UI (views/settings-v2/)
- Add new CSS architecture (agentic-sidebar.css, tokens)
- Add esbuild build pipeline (scripts/build.js, package.json)
- Add composer dependencies (vendor/)
- Add frontend src directory (assets/js/src/index.jsx)
- Add documentation files
- Remove old/obsolete files (class-settings.php, old CSS)

This commits all pending changes from previous refactoring efforts.
This commit is contained in:
Dwindi Ramadhana
2026-06-17 05:27:58 +07:00
parent d3f142222c
commit 690991c526
7963 changed files with 941566 additions and 67372 deletions

View File

@@ -0,0 +1,23 @@
======================================
Contribute to the phpDocumentor Guides
======================================
Go to the mono-repository
=========================
This project is developed in the mono-repository `phpDocumentor Guides <https://github.com/phpDocumentor/guides>`__.
The repository you are currently in gets auto-created by splitting the mono-repository. You **must not** contribute
to this repository directly but always to the mono-repository linked above.
Create Issues
=============
* If you find something missing or something is wrong in this library, you are welcome to write an issue
describing the problem: `Issues on GitHub <https://github.com/phpDocumentor/guides/issues>`__.
* If you can, please try to fix the problem yourself.
Make changes (create pull requests)
===================================
See the `Contribution chapter <https://docs.phpdoc.org/components/guides/guides/contributions/index.html>`__ in the
`Documentation` <https://docs.phpdoc.org/components/guides/guides/index.html>`__.

View File

@@ -0,0 +1,297 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace League\Flysystem;
use function interface_exists;
if (interface_exists('League\Flysystem\FilesystemInterface') === false) {
interface FilesystemInterface
{
/**
* Check whether a file exists.
*
* @param string $path
*
* @return bool
*/
public function has($path);
/**
* Read a file.
*
* @param string $path The path to the file.
*
* @throws FileNotFoundException
*
* @return string|false The file contents or false on failure.
*/
public function read($path);
/**
* Retrieves a read-stream for a path.
*
* @param string $path The path to the file.
*
* @throws FileNotFoundException
*
* @return resource|false The path resource or false on failure.
*/
public function readStream($path);
/**
* List contents of a directory.
*
* @param string $directory The directory to list.
* @param bool $recursive Whether to list recursively.
*
* @return array A list of file metadata.
*/
public function listContents($directory = '', $recursive = false);
/**
* Get a file's metadata.
*
* @param string $path The path to the file.
*
* @throws FileNotFoundException
*
* @return array|false The file metadata or false on failure.
*/
public function getMetadata($path);
/**
* Get a file's size.
*
* @param string $path The path to the file.
*
* @throws FileNotFoundException
*
* @return int|false The file size or false on failure.
*/
public function getSize($path);
/**
* Get a file's mime-type.
*
* @param string $path The path to the file.
*
* @throws FileNotFoundException
*
* @return string|false The file mime-type or false on failure.
*/
public function getMimetype($path);
/**
* Get a file's timestamp.
*
* @param string $path The path to the file.
*
* @throws FileNotFoundException
*
* @return int|false The timestamp or false on failure.
*/
public function getTimestamp($path);
/**
* Get a file's visibility.
*
* @param string $path The path to the file.
*
* @throws FileNotFoundException
*
* @return string|false The visibility (public|private) or false on failure.
*/
public function getVisibility($path);
/**
* Write a new file.
*
* @param string $path The path of the new file.
* @param string $contents The file contents.
* @param array $config An optional configuration array.
*
* @throws FileExistsException
*
* @return bool True on success, false on failure.
*/
public function write($path, $contents, array $config = []);
/**
* Write a new file using a stream.
*
* @param string $path The path of the new file.
* @param resource $resource The file handle.
* @param array $config An optional configuration array.
*
* @throws InvalidArgumentException If $resource is not a file handle.
* @throws FileExistsException
*
* @return bool True on success, false on failure.
*/
public function writeStream($path, $resource, array $config = []);
/**
* Update an existing file.
*
* @param string $path The path of the existing file.
* @param string $contents The file contents.
* @param array $config An optional configuration array.
*
* @throws FileNotFoundException
*
* @return bool True on success, false on failure.
*/
public function update($path, $contents, array $config = []);
/**
* Update an existing file using a stream.
*
* @param string $path The path of the existing file.
* @param resource $resource The file handle.
* @param array $config An optional configuration array.
*
* @throws InvalidArgumentException If $resource is not a file handle.
* @throws FileNotFoundException
*
* @return bool True on success, false on failure.
*/
public function updateStream($path, $resource, array $config = []);
/**
* Rename a file.
*
* @param string $path Path to the existing file.
* @param string $newpath The new path of the file.
*
* @throws FileExistsException Thrown if $newpath exists.
* @throws FileNotFoundException Thrown if $path does not exist.
*
* @return bool True on success, false on failure.
*/
public function rename($path, $newpath);
/**
* Copy a file.
*
* @param string $path Path to the existing file.
* @param string $newpath The new path of the file.
*
* @throws FileExistsException Thrown if $newpath exists.
* @throws FileNotFoundException Thrown if $path does not exist.
*
* @return bool True on success, false on failure.
*/
public function copy($path, $newpath);
/**
* Delete a file.
*
* @param string $path
*
* @throws FileNotFoundException
*
* @return bool True on success, false on failure.
*/
public function delete($path);
/**
* Delete a directory.
*
* @param string $dirname
*
* @throws RootViolationException Thrown if $dirname is empty.
*
* @return bool True on success, false on failure.
*/
public function deleteDir($dirname);
/**
* Create a directory.
*
* @param string $dirname The name of the new directory.
* @param array $config An optional configuration array.
*
* @return bool True on success, false on failure.
*/
public function createDir($dirname, array $config = []);
/**
* Set the visibility for a file.
*
* @param string $path The path to the file.
* @param string $visibility One of 'public' or 'private'.
*
* @throws FileNotFoundException
*
* @return bool True on success, false on failure.
*/
public function setVisibility($path, $visibility);
/**
* Create a file or update if exists.
*
* @param string $path The path to the file.
* @param string $contents The file contents.
* @param array $config An optional configuration array.
*
* @return bool True on success, false on failure.
*/
public function put($path, $contents, array $config = []);
/**
* Create a file or update if exists.
*
* @param string $path The path to the file.
* @param resource $resource The file handle.
* @param array $config An optional configuration array.
*
* @throws InvalidArgumentException Thrown if $resource is not a resource.
*
* @return bool True on success, false on failure.
*/
public function putStream($path, $resource, array $config = []);
/**
* Read and delete a file.
*
* @param string $path The path to the file.
*
* @throws FileNotFoundException
*
* @return string|false The file contents, or false on failure.
*/
public function readAndDelete($path);
/**
* Get a file/directory handler.
*
* @deprecated
*
* @param string $path The path to the file.
* @param Handler $handler An optional existing handler to populate.
*
* @return Handler Either a file or directory handler.
*/
public function get($path, Handler $handler = null);
/**
* Register a plugin.
*
* @param PluginInterface $plugin The plugin to register.
*
* @return $this
*/
public function addPlugin(PluginInterface $plugin);
}
}

21
vendor/phpdocumentor/filesystem/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2010 Mike van Riel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,34 @@
.. image:: https://poser.pugx.org/phpdocumentor/filesystem/require/php
:alt: PHP Version Require
:target: https://packagist.org/packages/phpdocumentor/filesystem
.. image:: https://poser.pugx.org/phpdocumentor/filesystem/v/stable
:alt: Latest Stable Version
:target: https://packagist.org/packages/phpdocumentor/filesystem
.. image:: https://poser.pugx.org/phpdocumentor/filesystem/v/unstable
:alt: Latest Unstable Version
:target: https://packagist.org/packages/phpdocumentor/filesystem
.. image:: https://poser.pugx.org/phpdocumentor/filesystem/d/total
:alt: Total Downloads
:target: https://packagist.org/packages/phpdocumentor/filesystem
.. image:: https://poser.pugx.org/phpdocumentor/filesystem/d/monthly
:alt: Monthly Downloads
:target: https://packagist.org/packages/phpdocumentor/filesystem
========================
phpDocumentor FileSystem
========================
This repository is part of `phpDocumentor's Guides library <https://github.com/phpDocumentor/guides>`__.
The package `phpdocumentor/filesystem <https://packagist.org/packages/phpdocumentor/filesystem>`__ provides
filesystem abstractions for phpDocumentor libraries.
:Mono-Repository: https://github.com/phpDocumentor/guides
:Documentation: https://docs.phpdoc.org/components/guides/guides/index.html
:Packagist: https://packagist.org/packages/phpdocumentor/filesystem
:Contribution: https://github.com/phpDocumentor/guides/tree/main/CONTRIBUTING.rst

View File

@@ -0,0 +1,35 @@
{
"name": "phpdocumentor/filesystem",
"description": "Filesystem abstraction for phpdocumentor projects.",
"type": "library",
"license": "MIT",
"homepage": "https://www.phpdoc.org",
"config": {
"sort-packages": true
},
"autoload": {
"psr-4": {
"phpDocumentor\\FileSystem\\": "src/"
},
"classmap": [
"Flysystem/"
]
},
"autoload-dev": {
"psr-4": {
"phpDocumentor\\FileSystem\\": [
"tests/unit/"
]
}
},
"minimum-stability": "stable",
"require": {
"php": "^8.1",
"webmozart/assert": "^1.3"
},
"extra": {
"branch-alias": {
"dev-main": "1.x-dev"
}
}
}

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem;
use Exception;
class FileNotFoundException extends Exception
{
}

View File

@@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem;
use Flyfinder\Specification\SpecificationInterface;
interface FileSystem
{
/**
* Check whether a file exists.
*/
public function has(string $path): bool;
/**
* Retrieves a read-stream for a path.
*
* @param string $path The path to the file.
*
* @return resource|false The path resource or false on failure.
*
* @throws FileNotFoundException
*/
public function readStream(string $path): mixed;
/**
* Read a file.
*
* @param string $path The path to the file.
*
* @return string|false The file contents or false on failure.
*
* @throws FileNotFoundException
*/
public function read(string $path): string|false;
public function put(string $path, string $contents): bool;
/** @param resource $resource */
public function putStream(string $path, $resource): void;
/** @return StorageAttributes[] */
public function listContents(string $directory = '', bool $recursive = false): array;
/** @return StorageAttributes[] */
public function find(SpecificationInterface $specification): iterable;
public function isDirectory(string $path): bool;
/** return the unix timestamp file was modified. */
public function lastModified(string $path): int;
}

View File

@@ -0,0 +1,72 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem\Finder;
use phpDocumentor\FileSystem\Path;
use function array_map;
use function array_values;
use function str_starts_with;
final class Exclude
{
/** @var list<string> */
private readonly array $paths;
/** @param list<string|Path> $paths */
public function __construct(
array $paths = [],
private readonly bool $hidden = false,
private readonly bool $symlinks = false,
) {
$this->paths = array_values(
array_map(
static function (string|Path $path): string {
if (str_starts_with((string) $path, '/')) {
return (string) $path;
}
return '/' . $path;
},
$paths,
),
);
}
/** @return list<string> */
public function getPaths(): array
{
return $this->paths;
}
public function excludeHidden(): bool
{
return $this->hidden;
}
public function followSymlinks(): bool
{
return $this->symlinks;
}
/** @param list<string|path> $excludePaths */
public function withPaths(array $excludePaths): self
{
return new self(
$excludePaths,
$this->hidden,
$this->symlinks,
);
}
}

View File

@@ -0,0 +1,83 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem\Finder;
use Flyfinder\Path as FlyFinderPath;
use Flyfinder\Specification\Glob;
use Flyfinder\Specification\HasExtension;
use Flyfinder\Specification\InPath;
use Flyfinder\Specification\IsHidden;
use Flyfinder\Specification\NotSpecification;
use Flyfinder\Specification\SpecificationInterface;
use phpDocumentor\FileSystem\Path;
/**
* Factory class to build Specification used by FlyFinder when reading files to process.
*/
final class SpecificationFactory implements SpecificationFactoryInterface
{
/**
* Creates a SpecificationInterface object based on the ignore and extension parameters.
*
* @param list<string|Path> $paths
* @param list<string> $extensions
*/
public function create(array $paths, Exclude $ignore, array $extensions): SpecificationInterface
{
/** @var ?Glob $pathSpec */
$pathSpec = null;
foreach ($paths as $path) {
if ($path instanceof Path) {
$condition = new InPath(new FlyFinderPath((string) $path));
} else {
$condition = new Glob($path);
}
if ($pathSpec === null) {
$pathSpec = $condition;
continue;
}
$pathSpec = $pathSpec->orSpecification($condition);
}
/** @var ?Glob $ignoreSpec */
$ignoreSpec = null;
foreach ($ignore->getPaths() as $path) {
if ($ignoreSpec === null) {
$ignoreSpec = new Glob($path);
continue;
}
$ignoreSpec = $ignoreSpec->orSpecification(new Glob($path));
}
if ($ignore->excludeHidden()) {
$ignoreSpec = $ignoreSpec === null
? new IsHidden()
: $ignoreSpec->orSpecification(new IsHidden());
}
$result = new HasExtension($extensions);
if ($ignoreSpec !== null) {
$result = $result->andSpecification(new NotSpecification($ignoreSpec));
}
if ($pathSpec !== null) {
$result = $result->andSpecification($pathSpec);
}
return $result;
}
}

View File

@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem\Finder;
use Flyfinder\Specification\SpecificationInterface;
use phpDocumentor\FileSystem\Path;
/**
* Interface for Specifications used to filter the FileSystem.
*/
interface SpecificationFactoryInterface
{
/**
* Creates a SpecificationInterface object based on the ignore and extension parameters.
*
* @param list<string|Path> $paths
* @param list<string> $extensions
*/
public function create(array $paths, Exclude $ignore, array $extensions): SpecificationInterface;
}

View File

@@ -0,0 +1,105 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem;
use Flyfinder\Specification\SpecificationInterface;
use League\Flysystem\Adapter\Local;
use League\Flysystem\Filesystem as LeagueFilesystem;
use League\Flysystem\FilesystemInterface;
use League\Flysystem\Local\LocalFilesystemAdapter;
use phpDocumentor\FileSystem\FlysystemV1\FlysystemV1;
use phpDocumentor\FileSystem\FlysystemV3\FlysystemV3;
use function class_exists;
class FlySystemAdapter implements FileSystem
{
public function __construct(
private FileSystem $filesystem,
) {
}
public static function createForPath(string $path): self
{
if (class_exists(Local::class)) {
/** @phpstan-ignore-next-line */
$filesystem = new FlysystemV1(new LeagueFilesystem(new Local($path)));
} else {
$filesystem = new FlysystemV3(
new LeagueFilesystem(
new LocalFilesystemAdapter($path),
),
);
}
return new self($filesystem);
}
public static function createFromFileSystem(LeagueFilesystem|FilesystemInterface $filesystem): self
{
if ($filesystem instanceof FilesystemInterface) {
return new self(new FlysystemV1($filesystem));
}
return new self(new FlysystemV3($filesystem));
}
public function has(string $path): bool
{
return $this->filesystem->has($path);
}
public function readStream(string $path): mixed
{
return $this->filesystem->readStream($path);
}
public function read(string $path): string|false
{
return $this->filesystem->read($path);
}
public function put(string $path, string $contents): bool
{
return $this->filesystem->put($path, $contents);
}
/** @param resource $resource */
public function putStream(string $path, $resource): void
{
$this->filesystem->putStream($path, $resource);
}
/** @return StorageAttributes[] */
public function listContents(string $directory = '', bool $recursive = false): array
{
return $this->filesystem->listContents($directory, $recursive);
}
/** @return StorageAttributes[] */
public function find(SpecificationInterface $specification): iterable
{
return $this->filesystem->find($specification);
}
public function isDirectory(string $path): bool
{
return $this->filesystem->isDirectory($path);
}
public function lastModified(string $path): int
{
return $this->filesystem->lastModified($path);
}
}

View File

@@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem\FlysystemV1;
use Flyfinder\Finder;
use Flyfinder\Specification\SpecificationInterface;
use League\Flysystem\FilesystemInterface;
use phpDocumentor\FileSystem\FileNotFoundException;
use phpDocumentor\FileSystem\FileSystem;
use phpDocumentor\FileSystem\StorageAttributes;
use function array_map;
class FlysystemV1 implements Filesystem
{
private FilesystemInterface $filesystem;
public function __construct(FilesystemInterface $wrappedFilesystem)
{
$this->filesystem = $wrappedFilesystem;
/** @phpstan-ignore-next-line */
$this->filesystem->addPlugin(new Finder());
}
public function has(string $path): bool
{
return $this->filesystem->has($path);
}
public function readStream(string $path): mixed
{
return $this->filesystem->readStream($path);
}
public function read(string $path): string|false
{
return $this->filesystem->read($path);
}
public function put(string $path, string $contents): bool
{
return $this->filesystem->put($path, $contents);
}
/** @param resource $resource */
public function putStream(string $path, $resource): void
{
$this->filesystem->putStream($path, $resource);
}
/** @return StorageAttributes[] */
public function listContents(string $directory = '', bool $recursive = false): array
{
return array_map(
static fn (array $attr) => new \phpDocumentor\FileSystem\FlysystemV1\StorageAttributes($attr),
$this->filesystem->listContents($directory, $recursive),
);
}
/** @return StorageAttributes[] */
public function find(SpecificationInterface $specification): iterable
{
/** @phpstan-ignore-next-line */
foreach ($this->filesystem->find($specification) as $file) {
yield new \phpDocumentor\FileSystem\FlysystemV1\StorageAttributes($file);
}
}
public function isDirectory(string $path): bool
{
$metadata = $this->filesystem->getMetadata($path);
if ($metadata === false) {
return false;
}
return $metadata['type'] === 'dir';
}
public function lastModified(string $path): int
{
$timestamp = $this->filesystem->getTimestamp($path);
if ($timestamp === false) {
throw new FileNotFoundException('File not found: ' . $path);
}
return $timestamp;
}
}

View File

@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem\FlysystemV1;
use phpDocumentor\FileSystem\MethodNotAllowedException;
use phpDocumentor\FileSystem\StorageAttributes as StorageAttributesInterface;
class StorageAttributes implements StorageAttributesInterface
{
/** @param string[] $attributes */
public function __construct(private array $attributes = [])
{
}
public function offsetExists(mixed $offset): bool
{
return isset($this->attributes[$offset]);
}
public function offsetGet(mixed $offset): mixed
{
return $this->attributes[$offset];
}
public function offsetSet(mixed $offset, mixed $value): void
{
throw new MethodNotAllowedException();
}
public function offsetUnset(mixed $offset): void
{
throw new MethodNotAllowedException();
}
}

View File

@@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem\FlysystemV3;
use phpDocumentor\FileSystem\MethodNotAllowedException;
use phpDocumentor\FileSystem\StorageAttributes;
use function basename;
use function dirname;
use function in_array;
use function pathinfo;
final class FileAttributes implements StorageAttributes
{
public function __construct(
private readonly \League\Flysystem\StorageAttributes $attributes,
) {
}
public function offsetExists(mixed $offset): bool
{
return $this->attributes->offsetExists($offset);
}
public function offsetGet(mixed $offset): mixed
{
if ($offset === 'basename') {
return basename($this->attributes->path());
}
if ($offset === 'dirname') {
$dirname = dirname($this->attributes->path());
if ($dirname === '.') {
return '';
}
return $dirname;
}
if (in_array($offset, ['filename'], true)) {
return pathinfo($this->attributes->path())[$offset];
}
return $this->attributes->offsetGet($offset);
}
public function offsetSet(mixed $offset, mixed $value): void
{
throw new MethodNotAllowedException('Cannot set attributes on storage attributes');
}
public function offsetUnset(mixed $offset): void
{
throw new MethodNotAllowedException('Cannot unset attributes on storage attributes');
}
}

View File

@@ -0,0 +1,87 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem\FlysystemV3;
use Flyfinder\Finder;
use Flyfinder\Specification\SpecificationInterface;
use League\Flysystem\Filesystem as LeagueFilesystem;
use League\Flysystem\StorageAttributes;
use phpDocumentor\FileSystem\FileSystem;
final class FlysystemV3 implements FileSystem
{
private LeagueFilesystem $filesystem;
private Finder $finder;
public function __construct(LeagueFilesystem $wrappedFilesystem)
{
$this->filesystem = $wrappedFilesystem;
$this->finder = new Finder($this->filesystem);
}
public function has(string $path): bool
{
return $this->filesystem->has($path);
}
public function isDirectory(string $path): bool
{
return $this->filesystem->directoryExists($path);
}
public function readStream(string $path): mixed
{
return $this->filesystem->readStream($path);
}
public function read(string $path): string|false
{
return $this->filesystem->read($path);
}
public function put(string $path, string $contents): bool
{
$this->filesystem->write($path, $contents);
return true;
}
/** @param resource $resource */
public function putStream(string $path, $resource): void
{
$this->filesystem->writeStream($path, $resource);
}
/** @return FileAttributes[] */
public function listContents(string $directory = '', bool $recursive = false): array
{
return $this->filesystem->listContents($directory, $recursive)->map(
static fn (StorageAttributes $attributes) => new FileAttributes($attributes),
)->toArray();
}
/** @return FileAttributes[] */
public function find(SpecificationInterface $specification): iterable
{
foreach ($this->finder->find($specification) as $file) {
/** @phpstan-ignore-next-line */
yield new FileAttributes($file);
}
}
public function lastModified(string $path): int
{
return $this->filesystem->lastModified($path);
}
}

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem;
use Exception;
class MethodNotAllowedException extends Exception
{
}

View File

@@ -0,0 +1,90 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem;
use Stringable;
use Webmozart\Assert\Assert;
use function array_pop;
use function ctype_alpha;
use function explode;
use function implode;
use function parse_url;
use function sprintf;
use function strlen;
use function strspn;
use const PHP_URL_SCHEME;
/**
* Value Object for paths.
* This can be absolute or relative.
*/
final class Path implements Stringable
{
/**
* Initializes the path.
*/
public function __construct(private readonly string $path)
{
Assert::notEmpty(
$path,
sprintf('"%s" is not a valid path', $path),
);
}
/**
* Verifies if another Path object has the same identity as this one.
*/
public function equals(self $otherPath): bool
{
return $this->path === (string) $otherPath;
}
/**
* returns a string representation of the path.
*/
public function __toString(): string
{
return $this->path;
}
/**
* Returns whether the file path is an absolute path.
*
* @param string $file A file path
*/
public static function isAbsolutePath(string $file): bool
{
return strspn($file, '/\\', 0, 1)
|| (strlen($file) > 3 && ctype_alpha($file[0])
&& $file[1] === ':'
&& strspn($file, '/\\', 2, 1)
)
|| parse_url($file, PHP_URL_SCHEME) !== null;
}
public static function dirname(Path $input): self
{
$parts = explode('/', (string) $input);
array_pop($parts);
$path = implode('/', $parts);
if ($path === '') {
return new self('/');
}
return new self($path);
}
}

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link https://phpdoc.org
*/
namespace phpDocumentor\FileSystem;
use ArrayAccess;
/** @extends ArrayAccess<string, mixed> */
interface StorageAttributes extends ArrayAccess
{
/** @return ($offset is 'filename' ? string : mixed) */
public function offsetGet(mixed $offset): mixed;
}