mirror of
https://github.com/adlawson/php-vfs.git
synced 2024-11-21 20:15:13 +00:00
Add source
This commit is contained in:
parent
4f985e21f9
commit
404b908bbd
14
src/Exception/ExceptionInterface.php
Normal file
14
src/Exception/ExceptionInterface.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Exception;
|
||||
|
||||
interface ExceptionInterface
|
||||
{
|
||||
}
|
52
src/Exception/ExistingNodeException.php
Normal file
52
src/Exception/ExistingNodeException.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Exception;
|
||||
|
||||
use Exception;
|
||||
use OutOfBoundsException;
|
||||
use Vfs\Node\NodeContainerInterface;
|
||||
|
||||
class ExistingNodeException extends OutOfBoundsException implements ExceptionInterface
|
||||
{
|
||||
protected $container;
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param NodeContainerInterface $container
|
||||
* @param integer $code
|
||||
* @param Exception $previous
|
||||
*/
|
||||
public function __construct($name, NodeContainerInterface $container, $code = 0, Exception $previous = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->name = $name;
|
||||
|
||||
$message = sprintf('Node with name "%s" already exists in container.', $name);
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NodeContainerInterface
|
||||
*/
|
||||
public function getContainer()
|
||||
{
|
||||
return $this->container;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
52
src/Exception/MissingNodeException.php
Normal file
52
src/Exception/MissingNodeException.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Exception;
|
||||
|
||||
use Exception;
|
||||
use OutOfRangeException;
|
||||
use Vfs\Node\NodeContainerInterface;
|
||||
|
||||
class MissingNodeException extends OutOfRangeException implements ExceptionInterface
|
||||
{
|
||||
protected $container;
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param NodeContainerInterface $container
|
||||
* @param integer $code
|
||||
* @param Exception $previous
|
||||
*/
|
||||
public function __construct($name, NodeContainerInterface $container, $code = 0, Exception $previous = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->name = $name;
|
||||
|
||||
$message = sprintf('Node with name "%s" doesn\'t exist in container.', $name);
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NodeContainerInterface
|
||||
*/
|
||||
public function getContainer()
|
||||
{
|
||||
return $this->container;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
40
src/Exception/RegisteredSchemeException.php
Normal file
40
src/Exception/RegisteredSchemeException.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Exception;
|
||||
|
||||
use Exception;
|
||||
use OutOfBoundsException;
|
||||
|
||||
class RegisteredSchemeException extends OutOfBoundsException implements ExceptionInterface
|
||||
{
|
||||
protected $scheme;
|
||||
|
||||
/**
|
||||
* @param string $scheme
|
||||
* @param integer $code
|
||||
* @param Exception $previous
|
||||
*/
|
||||
public function __construct($scheme, $code = 0, Exception $previous = null)
|
||||
{
|
||||
$this->scheme = $scheme;
|
||||
|
||||
$message = sprintf('File system with scheme "%s" has already been registered.', $scheme);
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getScheme()
|
||||
{
|
||||
return $this->scheme;
|
||||
}
|
||||
}
|
52
src/Exception/UnopenedHandleException.php
Normal file
52
src/Exception/UnopenedHandleException.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Exception;
|
||||
|
||||
use Exception;
|
||||
use RuntimeException;
|
||||
use Vfs\Stream\HandleInterface;
|
||||
|
||||
class UnopenedHandleException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
protected $handle;
|
||||
protected $url;
|
||||
|
||||
/**
|
||||
* @param HandleInterface $handle
|
||||
* @param string $url
|
||||
* @param integer $code
|
||||
* @param Exception $previous
|
||||
*/
|
||||
public function __construct(HandleInterface $handle, $url, $code = 0, Exception $previous = null)
|
||||
{
|
||||
$this->handle = $handle;
|
||||
$this->url = $url;
|
||||
|
||||
$message = sprintf('Handle at url "%s" hasn\'t been opened.', $url);
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HandleInterface
|
||||
*/
|
||||
public function getHandle()
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl()
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
}
|
40
src/Exception/UnregisteredSchemeException.php
Normal file
40
src/Exception/UnregisteredSchemeException.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Exception;
|
||||
|
||||
use Exception;
|
||||
use OutOfRangeException;
|
||||
|
||||
class UnregisteredSchemeException extends OutOfRangeException implements ExceptionInterface
|
||||
{
|
||||
protected $scheme;
|
||||
|
||||
/**
|
||||
* @param string $scheme
|
||||
* @param integer $code
|
||||
* @param Exception $previous
|
||||
*/
|
||||
public function __construct($scheme, $code = 0, Exception $previous = null)
|
||||
{
|
||||
$this->scheme = $scheme;
|
||||
|
||||
$message = sprintf('File system with scheme "%s" has not been registered.', $scheme);
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getScheme()
|
||||
{
|
||||
return $this->scheme;
|
||||
}
|
||||
}
|
149
src/FileSystem.php
Normal file
149
src/FileSystem.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Vfs\Exception\RegisteredSchemeException;
|
||||
use Vfs\Exception\UnregisteredSchemeException;
|
||||
use Vfs\Node\Factory\NodeFactoryInterface;
|
||||
use Vfs\Node\Walker\NodeWalkerInterface;
|
||||
|
||||
class FileSystem implements FileSystemInterface
|
||||
{
|
||||
protected $factory;
|
||||
protected $registry;
|
||||
protected $logger;
|
||||
protected $scheme;
|
||||
protected $walker;
|
||||
protected $wrapperClass;
|
||||
|
||||
/**
|
||||
* @param string $scheme
|
||||
* @param string $wrapperClass
|
||||
* @param NodeFactoryInterface $factory
|
||||
* @param NodeWalkerInterface $walker
|
||||
* @param RegistryInterface $registry
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct(
|
||||
$scheme,
|
||||
$wrapperClass,
|
||||
NodeFactoryInterface $factory,
|
||||
NodeWalkerInterface $walker,
|
||||
RegistryInterface $registry,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->wrapperClass = $wrapperClass;
|
||||
$this->scheme = $this->formatScheme($scheme);
|
||||
$this->walker = $walker;
|
||||
$this->logger = $logger;
|
||||
$this->factory = $factory;
|
||||
$this->registry = $registry;
|
||||
|
||||
$this->root = $factory->buildDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $scheme
|
||||
* @return FileSystem
|
||||
*/
|
||||
public static function factory($scheme = self::SCHEME)
|
||||
{
|
||||
$builder = new FileSystemBuilder($scheme);
|
||||
|
||||
$fs = $builder->build();
|
||||
$fs->mount();
|
||||
|
||||
return $fs;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($path)
|
||||
{
|
||||
return $this->walker->findNode($this->root, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLogger()
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNodeFactory()
|
||||
{
|
||||
return $this->factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNodeWalker()
|
||||
{
|
||||
return $this->walker;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getScheme()
|
||||
{
|
||||
return $this->scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mount()
|
||||
{
|
||||
if ($this->registry->has($this->scheme) || in_array($this->scheme, stream_get_wrappers())) {
|
||||
throw new RegisteredSchemeException($this->scheme);
|
||||
}
|
||||
|
||||
if (stream_wrapper_register($this->scheme, $this->wrapperClass)) {
|
||||
$this->registry->add($this->scheme, $this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function unmount()
|
||||
{
|
||||
if (!$this->registry->has($this->scheme) && !in_array($this->scheme, stream_get_wrappers())) {
|
||||
throw new UnregisteredSchemeException($this->scheme);
|
||||
}
|
||||
|
||||
if (stream_wrapper_unregister($this->scheme)) {
|
||||
$this->registry->remove($this->scheme, $this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $scheme
|
||||
* @return string
|
||||
*/
|
||||
protected function formatScheme($scheme)
|
||||
{
|
||||
return rtrim($scheme, ':/\\');
|
||||
}
|
||||
}
|
232
src/FileSystemBuilder.php
Normal file
232
src/FileSystemBuilder.php
Normal file
@ -0,0 +1,232 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Vfs\Logger\PhpErrorLogger;
|
||||
use Vfs\Node\Factory\NodeFactory;
|
||||
use Vfs\Node\Factory\NodeFactoryInterface;
|
||||
use Vfs\Node\Walker\NodeWalker;
|
||||
use Vfs\Node\Walker\NodeWalkerInterface;
|
||||
|
||||
class FileSystemBuilder
|
||||
{
|
||||
protected $factory;
|
||||
protected $registry;
|
||||
protected $logger;
|
||||
protected $scheme;
|
||||
protected $walker;
|
||||
protected $wrapperClass;
|
||||
protected $tree = [];
|
||||
|
||||
/**
|
||||
* @param string $scheme
|
||||
*/
|
||||
public function __construct($scheme = FileSystemInterface::SCHEME)
|
||||
{
|
||||
$this->setScheme($scheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FileSystemInterface
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$fs = new FileSystem(
|
||||
$this->getScheme(),
|
||||
$this->getStreamWrapper() ?: $this->buildDefaultStreamWrapper(),
|
||||
$this->getNodeFactory() ?: $this->buildDefaultNodeFactory(),
|
||||
$this->getNodeWalker() ?: $this->buildDefaultNodeWalker(),
|
||||
$this->getRegistry() ?: $this->buildDefaultRegistry(),
|
||||
$this->getLogger() ?: $this->buildDefaultLogger()
|
||||
);
|
||||
|
||||
$root = $fs->get('/');
|
||||
$factory = $fs->getNodeFactory();
|
||||
foreach ($factory->buildTree($this->getTree()) as $name => $node) {
|
||||
$root->set($name, $node);
|
||||
}
|
||||
|
||||
return $fs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
public function getLogger()
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param LoggerInterface $logger
|
||||
* @return FileSystemBuilder
|
||||
*/
|
||||
public function setLogger(LoggerInterface $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NodeFactoryInterface
|
||||
*/
|
||||
public function getNodeFactory()
|
||||
{
|
||||
return $this->factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NodeFactoryInterface $factory
|
||||
* @return FileSystemBuilder
|
||||
*/
|
||||
public function setNodeFactory(NodeFactoryInterface $factory)
|
||||
{
|
||||
$this->factory = $factory;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NodeWalkerInterface
|
||||
*/
|
||||
public function getNodeWalker()
|
||||
{
|
||||
return $this->walker;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NodeWalkerInterface $walker
|
||||
* @return FileSystemBuilder
|
||||
*/
|
||||
public function setNodeWalker(NodeWalkerInterface $walker)
|
||||
{
|
||||
$this->walker = $walker;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RegistryInterface
|
||||
*/
|
||||
public function getRegistry()
|
||||
{
|
||||
return $this->registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RegistryInterface $registry
|
||||
* @return FileSystemBuilder
|
||||
*/
|
||||
public function setRegistry(RegistryInterface $registry)
|
||||
{
|
||||
$this->registry = $registry;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getScheme()
|
||||
{
|
||||
return $this->scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $scheme
|
||||
* @return FileSystemBuilder
|
||||
*/
|
||||
public function setScheme($scheme)
|
||||
{
|
||||
$this->scheme = $scheme;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getStreamWrapper()
|
||||
{
|
||||
return $this->wrapperClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @return FileSystemBuilder
|
||||
*/
|
||||
public function setStreamWrapper($class)
|
||||
{
|
||||
$this->wrapperClass = $class;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTree()
|
||||
{
|
||||
return $this->tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $tree
|
||||
* @return FileSystemBuilder
|
||||
*/
|
||||
public function setTree($tree)
|
||||
{
|
||||
$this->tree = $tree;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
protected function buildDefaultLogger()
|
||||
{
|
||||
return new PhpErrorLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NodeFactoryInterface
|
||||
*/
|
||||
protected function buildDefaultNodeFactory()
|
||||
{
|
||||
return new NodeFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NodeWalkerInterface
|
||||
*/
|
||||
protected function buildDefaultNodeWalker()
|
||||
{
|
||||
return new NodeWalker();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RegistryInterface
|
||||
*/
|
||||
protected function buildDefaultRegistry()
|
||||
{
|
||||
return FileSystemRegistry::getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function buildDefaultStreamWrapper()
|
||||
{
|
||||
return 'Vfs\\Stream\\StreamWrapper';
|
||||
}
|
||||
}
|
60
src/FileSystemInterface.php
Normal file
60
src/FileSystemInterface.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Vfs\Exception\RegisteredSchemeException;
|
||||
use Vfs\Exception\UnregisteredSchemeException;
|
||||
use Vfs\Node\Factory\NodeFactoryInterface;
|
||||
use Vfs\Node\Walker\NodeWalkerInterface;
|
||||
use Vfs\Node\NodeInterface;
|
||||
|
||||
interface FileSystemInterface
|
||||
{
|
||||
const SCHEME = 'vfs';
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function get($path);
|
||||
|
||||
/**
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
public function getLogger();
|
||||
|
||||
/**
|
||||
* @return NodeFactoryInterface
|
||||
*/
|
||||
public function getNodeFactory();
|
||||
|
||||
/**
|
||||
* @return NodeWalkerInterface
|
||||
*/
|
||||
public function getNodeWalker();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getScheme();
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
* @throws RegisteredSchemeException If a mounted file system exists at scheme
|
||||
*/
|
||||
public function mount();
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
* @throws UnregisteredSchemeException If a mounted file system doesn't exist at scheme
|
||||
*/
|
||||
public function unmount();
|
||||
}
|
85
src/FileSystemRegistry.php
Normal file
85
src/FileSystemRegistry.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs;
|
||||
|
||||
use Vfs\Exception\RegisteredSchemeException;
|
||||
use Vfs\Exception\UnregisteredSchemeException;
|
||||
|
||||
class FileSystemRegistry implements RegistryInterface
|
||||
{
|
||||
protected static $instance;
|
||||
protected $registered = [];
|
||||
|
||||
/**
|
||||
* @param FileSystemRegistry[] $fss
|
||||
*/
|
||||
public function __construct(array $fss = [])
|
||||
{
|
||||
foreach ($fss as $name => $fs) {
|
||||
$this->add($name, $fs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FileSystemRegistry
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add($scheme, FileSystemInterface $fs)
|
||||
{
|
||||
if ($this->has($scheme)) {
|
||||
throw new RegisteredSchemeException($scheme);
|
||||
}
|
||||
|
||||
$this->registered[$scheme] = $fs;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($scheme)
|
||||
{
|
||||
if (!$this->has($scheme)) {
|
||||
throw new UnregisteredSchemeException($scheme);
|
||||
}
|
||||
|
||||
return $this->registered[$scheme];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has($scheme)
|
||||
{
|
||||
return isset($this->registered[$scheme]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function remove($scheme)
|
||||
{
|
||||
if (!$this->has($scheme)) {
|
||||
throw new UnregisteredSchemeException($scheme);
|
||||
}
|
||||
|
||||
unset($this->registered[$scheme]);
|
||||
}
|
||||
}
|
70
src/Logger/PhpErrorLogger.php
Normal file
70
src/Logger/PhpErrorLogger.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Logger;
|
||||
|
||||
use Psr\Log\AbstractLogger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class PhpErrorLogger extends AbstractLogger
|
||||
{
|
||||
/**
|
||||
* @param mixed $level
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*/
|
||||
public function log($level, $message, array $context = [])
|
||||
{
|
||||
switch ($level) {
|
||||
case LogLevel::EMERGENCY:
|
||||
case LogLevel::ALERT:
|
||||
case LogLevel::CRITICAL:
|
||||
case LogLevel::ERROR:
|
||||
trigger_error($this->format($message, $context), E_USER_ERROR);
|
||||
break;
|
||||
case LogLevel::WARNING:
|
||||
trigger_error($this->format($message, $context), E_USER_WARNING);
|
||||
break;
|
||||
case LogLevel::NOTICE:
|
||||
case LogLevel::INFO:
|
||||
case LogLevel::DEBUG:
|
||||
trigger_error($this->format($message, $context), E_USER_NOTICE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return string
|
||||
*/
|
||||
protected function format($message, array $context)
|
||||
{
|
||||
foreach ($context as $key => $value) {
|
||||
$message = str_replace(sprintf('{%s}', $key), $value, $message);
|
||||
}
|
||||
|
||||
return $message . $this->formatTrace(debug_backtrace(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $backtrace
|
||||
* @return string
|
||||
*/
|
||||
protected function formatTrace(array $backtrace)
|
||||
{
|
||||
$index = min((count($backtrace) + 1), 6);
|
||||
$origin = $backtrace[$index];
|
||||
|
||||
$file = isset($origin['file']) ? $origin['file'] : 'unknown';
|
||||
$line = isset($origin['line']) ? $origin['line'] : 0;
|
||||
|
||||
return sprintf(' in %s on line %d; triggered', $file, $line);
|
||||
}
|
||||
}
|
158
src/Node/Directory.php
Normal file
158
src/Node/Directory.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Node;
|
||||
|
||||
use ArrayIterator;
|
||||
use DateTime;
|
||||
use Vfs\Exception\ExistingNodeException;
|
||||
use Vfs\Exception\MissingNodeException;
|
||||
|
||||
class Directory implements NodeContainerInterface
|
||||
{
|
||||
const DOT_SELF = '.';
|
||||
const DOT_UP = '..';
|
||||
|
||||
protected $dateAccessed;
|
||||
protected $dateCreated;
|
||||
protected $dateModified;
|
||||
protected $mode;
|
||||
protected $nodes = [];
|
||||
|
||||
/**
|
||||
* @param NodeInterface[] $nodes
|
||||
*/
|
||||
public function __construct(array $nodes = [])
|
||||
{
|
||||
$this->mode = self::TYPE_BLOCK | self::TYPE_DIR;
|
||||
|
||||
$this->dateAccessed = new DateTime();
|
||||
$this->dateCreated = new DateTime();
|
||||
$this->dateModified = new DateTime();
|
||||
|
||||
foreach ($nodes as $name => $node) {
|
||||
$this->add($name, $node);
|
||||
}
|
||||
|
||||
$this->set(self::DOT_SELF, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add($name, NodeInterface $node)
|
||||
{
|
||||
if ($this->has($name)) {
|
||||
throw new ExistingNodeException($name, $this);
|
||||
}
|
||||
|
||||
$this->set($name, $node);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
if (!$this->has($name)) {
|
||||
throw new MissingNodeException($name, $this);
|
||||
}
|
||||
|
||||
return $this->nodes[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has($name)
|
||||
{
|
||||
return isset($this->nodes[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function remove($name)
|
||||
{
|
||||
if (!$this->has($name)) {
|
||||
throw new MissingNodeException($name, $this);
|
||||
}
|
||||
|
||||
unset($this->nodes[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param NodeInterface $node
|
||||
*/
|
||||
public function set($name, NodeInterface $node)
|
||||
{
|
||||
$this->nodes[$name] = $node;
|
||||
|
||||
if (self::DOT_UP !== $name && $node instanceof NodeContainerInterface) {
|
||||
$node->set(self::DOT_UP, $this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDateAccessed()
|
||||
{
|
||||
return $this->dateAccessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDateCreated()
|
||||
{
|
||||
return $this->dateCreated;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDateModified()
|
||||
{
|
||||
return $this->dateModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMode()
|
||||
{
|
||||
return $this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
$size = 0;
|
||||
|
||||
foreach ($this->nodes as $name => $node) {
|
||||
if (!in_array($name, [self::DOT_SELF, self::DOT_UP])) {
|
||||
$size += $node->getSize();
|
||||
}
|
||||
}
|
||||
|
||||
return $size;
|
||||
}
|
||||
}
|
65
src/Node/Factory/NodeFactory.php
Normal file
65
src/Node/Factory/NodeFactory.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Node\Factory;
|
||||
|
||||
use LogicException;
|
||||
use Vfs\Node\Directory;
|
||||
use Vfs\Node\File;
|
||||
use Vfs\Node\NodeContainerInterface;
|
||||
use Vfs\Node\NodeInterface;
|
||||
|
||||
class NodeFactory implements NodeFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @param NodeInterface[] $children
|
||||
* @return NodeContainerInterface
|
||||
*/
|
||||
public function buildDirectory(array $children = [])
|
||||
{
|
||||
return new Directory($children);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function buildFile($content = '')
|
||||
{
|
||||
return new File($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function buildLink($content = '')
|
||||
{
|
||||
throw new LogicException('Symlinks aren\'t supported yet.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $tree
|
||||
* @return NodeContainerInterface
|
||||
*/
|
||||
public function buildTree(array $tree)
|
||||
{
|
||||
$nodes = [];
|
||||
|
||||
foreach ($tree as $name => $content) {
|
||||
if (is_array($content)) {
|
||||
$nodes[$name] = $this->buildTree($content);
|
||||
} else {
|
||||
$nodes[$name] = $this->buildFile($content);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->buildDirectory($nodes);
|
||||
}
|
||||
}
|
34
src/Node/Factory/NodeFactoryInterface.php
Normal file
34
src/Node/Factory/NodeFactoryInterface.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Node\Factory;
|
||||
|
||||
use Vfs\Node\NodeContainerInterface;
|
||||
use Vfs\Node\NodeInterface;
|
||||
|
||||
interface NodeFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @param NodeInterface[] $children
|
||||
* @return NodeContainerInterface
|
||||
*/
|
||||
public function buildDirectory(array $children = []);
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function buildFile($content = '');
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function buildLink($content = '');
|
||||
}
|
98
src/Node/File.php
Normal file
98
src/Node/File.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Node;
|
||||
|
||||
use DateTime;
|
||||
|
||||
class File implements FileInterface
|
||||
{
|
||||
protected $dateAccessed;
|
||||
protected $dateCreated;
|
||||
protected $dateModified;
|
||||
protected $content;
|
||||
protected $mode;
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
*/
|
||||
public function __construct($content = '')
|
||||
{
|
||||
$this->content = (string) $content;
|
||||
$this->mode = self::TYPE_BLOCK | self::TYPE_FILE;
|
||||
|
||||
$this->dateAccessed = new DateTime();
|
||||
$this->dateCreated = new DateTime();
|
||||
$this->dateModified = new DateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = (string) $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDateAccessed()
|
||||
{
|
||||
return $this->dateAccessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDateCreated()
|
||||
{
|
||||
return $this->dateCreated;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDateModified()
|
||||
{
|
||||
return $this->dateModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMode()
|
||||
{
|
||||
return $this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
return strlen($this->content);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
}
|
28
src/Node/FileInterface.php
Normal file
28
src/Node/FileInterface.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Node;
|
||||
|
||||
interface FileInterface extends NodeInterface
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getContent();
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
*/
|
||||
public function setContent($content);
|
||||
|
||||
/**
|
||||
* @return string The file content
|
||||
*/
|
||||
public function __toString();
|
||||
}
|
18
src/Node/LinkInterface.php
Normal file
18
src/Node/LinkInterface.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Node;
|
||||
|
||||
interface LinkInterface extends NodeInterface
|
||||
{
|
||||
/**
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function getTarget();
|
||||
}
|
49
src/Node/NodeContainerInterface.php
Normal file
49
src/Node/NodeContainerInterface.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Node;
|
||||
|
||||
use DateTime;
|
||||
use IteratorAggregate;
|
||||
use Vfs\Exception\ExistingNodeException;
|
||||
use Vfs\Exception\MissingNodeException;
|
||||
|
||||
interface NodeContainerInterface extends NodeInterface, IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @param string $name
|
||||
* @param NodeInterface $node
|
||||
* @throws ExistingNodeException If a node exists in container with name
|
||||
*/
|
||||
public function add($name, NodeInterface $node);
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @throws MissingNodeException If a node doesn't exist in container with name
|
||||
*/
|
||||
public function get($name);
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return boolean
|
||||
*/
|
||||
public function has($name);
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @throws MissingNodeException If a node doesn't exist in container with name
|
||||
*/
|
||||
public function remove($name);
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param NodeInterface $node
|
||||
*/
|
||||
public function set($name, NodeInterface $node);
|
||||
}
|
35
src/Node/NodeInterface.php
Normal file
35
src/Node/NodeInterface.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Node;
|
||||
|
||||
use DateTime;
|
||||
|
||||
interface NodeInterface extends StatInterface
|
||||
{
|
||||
/**
|
||||
* @return DateTime
|
||||
*/
|
||||
public function getDateAccessed();
|
||||
|
||||
/**
|
||||
* @return DateTime
|
||||
*/
|
||||
public function getDateCreated();
|
||||
|
||||
/**
|
||||
* @return DateTime
|
||||
*/
|
||||
public function getDateModified();
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getSize();
|
||||
}
|
49
src/Node/StatInterface.php
Normal file
49
src/Node/StatInterface.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Node;
|
||||
|
||||
/**
|
||||
* @link http://www.gnu.org/software/libc/manual/html_node/Permission-Bits.html
|
||||
*/
|
||||
interface StatInterface
|
||||
{
|
||||
const S_IFMT = 0170000;
|
||||
const S_IFLNK = 0120000;
|
||||
const S_IFREG = 0100000;
|
||||
const S_IFDIR = 0040000;
|
||||
const S_IRUSR = 0000400;
|
||||
const S_IWUSR = 0000200;
|
||||
const S_IXUSR = 0000100;
|
||||
const S_IRGRP = 0000040;
|
||||
const S_IWGRP = 0000020;
|
||||
const S_IXGRP = 0000010;
|
||||
const S_IROTH = 0000004;
|
||||
const S_IWOTH = 0000002;
|
||||
const S_IXOTH = 0000001;
|
||||
|
||||
const GROUP_EXEC = self::S_IXGRP;
|
||||
const GROUP_WRITE = self::S_IWGRP;
|
||||
const GROUP_READ = self::S_IRGRP;
|
||||
const OTHER_EXEC = self::S_IXOTH;
|
||||
const OTHER_WRITE = self::S_IWOTH;
|
||||
const OTHER_READ = self::S_IROTH;
|
||||
const USER_EXEC = self::S_IXUSR;
|
||||
const USER_READ = self::S_IRUSR;
|
||||
const USER_WRITE = self::S_IWUSR;
|
||||
const TYPE_BLOCK = self::S_IFMT;
|
||||
const TYPE_FILE = self::S_IFREG;
|
||||
const TYPE_DIR = self::S_IFDIR;
|
||||
const TYPE_LINK = self::S_IFLNK;
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getMode();
|
||||
}
|
75
src/Node/Walker/NodeWalker.php
Normal file
75
src/Node/Walker/NodeWalker.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Node\Walker;
|
||||
|
||||
use Vfs\Exception\InvalidNodeTypeException;
|
||||
use Vfs\Node\NodeContainerInterface;
|
||||
use Vfs\Node\NodeInterface;
|
||||
|
||||
class NodeWalker implements NodeWalkerInterface
|
||||
{
|
||||
protected $separator;
|
||||
|
||||
/**
|
||||
* @param string $separator
|
||||
*/
|
||||
public function __construct($separator = DIRECTORY_SEPARATOR)
|
||||
{
|
||||
$this->separator = $separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NodeInterface $root
|
||||
* @param string $path
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function findNode(NodeInterface $root, $path)
|
||||
{
|
||||
$parts = $this->splitPath($path);
|
||||
$node = $root;
|
||||
|
||||
return $this->walkPath($root, $path, function (NodeInterface $node, $name) {
|
||||
if (!$node instanceof NodeContainerInterface || !$node->has($name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $node->get($name);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NodeInterface $root
|
||||
* @param string $path
|
||||
* @param callable $fn
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function walkPath(NodeInterface $root, $path, callable $fn)
|
||||
{
|
||||
$parts = $this->splitPath($path);
|
||||
$name = current($parts);
|
||||
$node = $root;
|
||||
|
||||
while ($node && $name) {
|
||||
$node = $fn($node, $name);
|
||||
$name = next($parts);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return string[]
|
||||
*/
|
||||
protected function splitPath($path)
|
||||
{
|
||||
return array_filter(explode($this->separator, $path));
|
||||
}
|
||||
}
|
22
src/Node/Walker/NodeWalkerInterface.php
Normal file
22
src/Node/Walker/NodeWalkerInterface.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Node\Walker;
|
||||
|
||||
use Vfs\Node\NodeInterface;
|
||||
|
||||
interface NodeWalkerInterface
|
||||
{
|
||||
/**
|
||||
* @param NodeInterface $root
|
||||
* @param string $path
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function findNode(NodeInterface $root, $path);
|
||||
}
|
43
src/RegistryInterface.php
Normal file
43
src/RegistryInterface.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs;
|
||||
|
||||
use Vfs\Exception\RegisteredSchemeException;
|
||||
use Vfs\Exception\UnregisteredSchemeException;
|
||||
|
||||
interface RegistryInterface
|
||||
{
|
||||
/**
|
||||
* @param string $scheme
|
||||
* @param FileSystemInterface $fs
|
||||
* @throws RegisteredSchemeException If a mounted file system exists at scheme
|
||||
*/
|
||||
public function add($scheme, FileSystemInterface $fs);
|
||||
|
||||
/**
|
||||
* @param string $scheme
|
||||
* @return FileSystemInterface
|
||||
* @throws UnregisteredSchemeException If a mounted file system doesn't exist at scheme
|
||||
*/
|
||||
public function get($scheme);
|
||||
|
||||
/**
|
||||
* @param string $scheme
|
||||
* @return boolean
|
||||
*/
|
||||
public function has($scheme);
|
||||
|
||||
/**
|
||||
* @param string $scheme
|
||||
* @return FileSystemInterface
|
||||
* @throws UnregisteredSchemeException If a mounted file system doesn't exist at scheme
|
||||
*/
|
||||
public function remove($scheme);
|
||||
}
|
117
src/Stream/AbstractHandle.php
Normal file
117
src/Stream/AbstractHandle.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Stream;
|
||||
|
||||
use Vfs\FileSystemInterface;
|
||||
use Vfs\Node\NodeInterface;
|
||||
|
||||
abstract class AbstractHandle implements HandleInterface
|
||||
{
|
||||
protected $fs;
|
||||
protected $node;
|
||||
protected $mode;
|
||||
protected $modifier;
|
||||
protected $path;
|
||||
protected $scheme;
|
||||
protected $url;
|
||||
|
||||
/**
|
||||
* @param FileSystemInterface $fs
|
||||
* @param string $url
|
||||
* @param string $mode
|
||||
*/
|
||||
public function __construct(FileSystemInterface $fs, $url, $mode = null)
|
||||
{
|
||||
$this->fs = $fs;
|
||||
$this->url = $url;
|
||||
|
||||
list($this->mode, $this->modifier) = $this->parseMode($mode);
|
||||
list($this->scheme, $this->path) = $this->parseUrl($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function getNode()
|
||||
{
|
||||
return $this->node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $origin
|
||||
* @param string $target
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function rename($target)
|
||||
{
|
||||
$this->node = $this->findNode($this->path);
|
||||
$parent = $this->fs->get(dirname($this->path));
|
||||
|
||||
list($_, $targetPath) = $this->parseUrl($target);
|
||||
$targetParent = $this->fs->get(dirname($targetPath));
|
||||
|
||||
if (!$this->node || !$targetPath) {
|
||||
$this->node = null;
|
||||
$this->warn('rename({origin},{target}): No such file or directory', [
|
||||
'origin' => $this->url,
|
||||
'target' => $target
|
||||
]);
|
||||
} else {
|
||||
$parent->remove(basename($this->path));
|
||||
$targetParent->add(basename($targetPath), $this->node);
|
||||
}
|
||||
|
||||
return $this->node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NodeInterface
|
||||
*/
|
||||
protected function findNode()
|
||||
{
|
||||
return $this->fs->get($this->path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mode
|
||||
* @return string[]
|
||||
*/
|
||||
protected function parseMode($mode)
|
||||
{
|
||||
return [substr($mode, 0, 1), substr($mode, 1, 2)];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @return string[]
|
||||
*/
|
||||
protected function parseUrl($url)
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
$path = null;
|
||||
$scheme = null;
|
||||
|
||||
if (isset($parts['scheme'])) {
|
||||
$path = substr($url, strlen($parts['scheme'] . ':/'));
|
||||
$scheme = $parts['scheme'];
|
||||
}
|
||||
|
||||
return [$scheme, $path];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*/
|
||||
protected function warn($message, array $context = [])
|
||||
{
|
||||
$this->fs->getLogger()->warning($message, $context);
|
||||
}
|
||||
}
|
133
src/Stream/DirectoryHandle.php
Normal file
133
src/Stream/DirectoryHandle.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Stream;
|
||||
|
||||
use Vfs\Exception\UnopenedHandleException;
|
||||
|
||||
class DirectoryHandle extends AbstractHandle
|
||||
{
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function canRead()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $perms
|
||||
* @param boolean $recursive
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function create($perms, $recursive = false)
|
||||
{
|
||||
$this->node = $this->findNode();
|
||||
|
||||
if (!$this->node) {
|
||||
$parentPath = dirname($this->path);
|
||||
$parent = $this->fs->get($parentPath);
|
||||
|
||||
if (!$parent && $this->checkBit($options, STREAM_MKDIR_RECURSIVE)) {
|
||||
$parent = $this->buildNodesRecursive($this->fs->get('/'), $this->path);
|
||||
}
|
||||
|
||||
if ($parent) {
|
||||
$this->node = $this->fs->getNodeFactory()->buildDirectory();
|
||||
$parent->add(basename($this->path), $this->node);
|
||||
} else {
|
||||
$this->warn('mkdir({url}): No such file or directory', [
|
||||
'url' => $this->url
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$this->warn('mkdir({url}): File exists', ['url' => $this->url]);
|
||||
$this->node = null;
|
||||
}
|
||||
|
||||
return $this->node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function destroy()
|
||||
{
|
||||
$this->node = $this->findNode();
|
||||
|
||||
if (!$this->node) {
|
||||
return (boolean) $this->warn('rmdir({url}): No such file or directory', [
|
||||
'url' => $this->url
|
||||
]);
|
||||
} elseif (!$this->node instanceof NodeContainerInterface) {
|
||||
return (boolean) $this->warn('rmdir({url}): Not a directory', [
|
||||
'url' => $this->url
|
||||
]);
|
||||
}
|
||||
|
||||
$parent = $fs->get(dirname($this->path));
|
||||
$parent->remove(basename($this->path));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function open()
|
||||
{
|
||||
return $this->node = $this->findNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $offset
|
||||
* @return string
|
||||
*/
|
||||
public function read($offset = 0)
|
||||
{
|
||||
if (!$this->node) {
|
||||
throw new UnopenedHandleException($this, $this->url);
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
foreach ($this->node as $name => $node) {
|
||||
if ($i++ === $offset) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return boolean
|
||||
*/
|
||||
public function write($content)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NodeContainerInterface $root
|
||||
* @param string $path
|
||||
* @return NodeContainerInterface
|
||||
*/
|
||||
protected function buildNodesRecursive(NodeContainerInterface $root, $path)
|
||||
{
|
||||
$factory = $this->fs->getNodeFactory();
|
||||
$walker = $this->fs->getNodeWalker();
|
||||
|
||||
return $walker->walkPath($root, $this->path, function ($node, $name) use ($factory) {
|
||||
if (!$node->has($name)) {
|
||||
$node->add($name, $factory->buildDirectory());
|
||||
}
|
||||
|
||||
return $node->get($name);
|
||||
});
|
||||
}
|
||||
}
|
130
src/Stream/FileHandle.php
Normal file
130
src/Stream/FileHandle.php
Normal file
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Stream;
|
||||
|
||||
use Vfs\Exception\UnopenedHandleException;
|
||||
use Vfs\Node\FileInterface;
|
||||
use Vfs\Node\NodeContainerInterface;
|
||||
|
||||
class FileHandle extends AbstractHandle
|
||||
{
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function canRead()
|
||||
{
|
||||
return self::MODE_READ === $this->mode || self::MOD_EXTENDED === $this->modifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $perms
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function create($perms)
|
||||
{
|
||||
return $this->node = $this->findOrBuildNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function destroy()
|
||||
{
|
||||
$this->node = $this->findNode();
|
||||
|
||||
if (!$this->node) {
|
||||
return (boolean) $this->warn('unlink({url}): No such file or directory', [
|
||||
'url' => $this->url
|
||||
]);
|
||||
} elseif ($this->node instanceof NodeContainerInterface) {
|
||||
return (boolean) $this->warn('unlink({url}): Is a directory', [
|
||||
'url' => $this->url
|
||||
]);
|
||||
}
|
||||
|
||||
$parent = $this->fs->get(dirname($this->path));
|
||||
$parent->remove(basename($this->path));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function open()
|
||||
{
|
||||
$this->node = $this->findOrBuildNode();
|
||||
|
||||
if ($this->node instanceof FileInterface && self::MODE_TRUNCATE === $this->mode) {
|
||||
$this->node->setContent('');
|
||||
}
|
||||
|
||||
return $this->node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $offset
|
||||
* @param integer $length
|
||||
* @return string
|
||||
*/
|
||||
public function read($offset = 0, $length = null)
|
||||
{
|
||||
if (!$this->node) {
|
||||
throw new UnopenedHandleException($this, $this->url);
|
||||
}
|
||||
|
||||
if (null !== $length) {
|
||||
return substr($this->node->getContent(), $offset, $length);
|
||||
}
|
||||
|
||||
return substr($this->node->getContent(), $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return boolean
|
||||
*/
|
||||
public function write($content)
|
||||
{
|
||||
if (!$this->node) {
|
||||
throw new UnopenedHandleException($this, $this->url);
|
||||
}
|
||||
|
||||
$this->node->setContent($content);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NodeInterface
|
||||
*/
|
||||
protected function findOrBuildNode()
|
||||
{
|
||||
$this->node = $this->fs->get($this->path);
|
||||
|
||||
if ($this->node && self::MODE_WRITE === $this->mode) {
|
||||
$this->node = null;
|
||||
} elseif (!$this->node && in_array($this->mode, [
|
||||
self::MODE_APPEND,
|
||||
self::MODE_TRUNCATE,
|
||||
self::MODE_WRITE,
|
||||
self::MODE_WRITE_NEW
|
||||
])) {
|
||||
$dir = $this->fs->get(dirname($this->path));
|
||||
|
||||
if ($dir && $dir instanceof NodeContainerInterface) {
|
||||
$this->node = $this->fs->getNodeFactory()->buildFile();
|
||||
$dir->set(basename($this->path), $this->node);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->node;
|
||||
}
|
||||
}
|
69
src/Stream/HandleInterface.php
Normal file
69
src/Stream/HandleInterface.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Stream;
|
||||
|
||||
use Vfs\Node\NodeInterface;
|
||||
|
||||
interface HandleInterface
|
||||
{
|
||||
const MODE_APPEND = 'a';
|
||||
const MODE_READ = 'r';
|
||||
const MODE_TRUNCATE = 'w';
|
||||
const MODE_WRITE = 'x';
|
||||
const MODE_WRITE_NEW = 'c';
|
||||
const MOD_BINARY = 'b';
|
||||
const MOD_EXTENDED = '+';
|
||||
const MOD_TEXT = 't';
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function canRead();
|
||||
|
||||
/**
|
||||
* @param integer $perms
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function create($perms);
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function destroy();
|
||||
|
||||
/**
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function getNode();
|
||||
|
||||
/**
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function open();
|
||||
|
||||
/**
|
||||
* @param string $origin
|
||||
* @param string $target
|
||||
* @return NodeInterface
|
||||
*/
|
||||
public function rename($target);
|
||||
|
||||
/**
|
||||
* @param integer $offset
|
||||
* @return string
|
||||
*/
|
||||
public function read($offset = 0);
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return boolean
|
||||
*/
|
||||
public function write($content);
|
||||
}
|
345
src/Stream/StreamWrapper.php
Normal file
345
src/Stream/StreamWrapper.php
Normal file
@ -0,0 +1,345 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of VFS
|
||||
*
|
||||
* Copyright (c) 2014 Andrew Lawson <http://adlawson.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Vfs\Stream;
|
||||
|
||||
use Vfs\Node\LinkInterface;
|
||||
use Vfs\FileSystemRegistry;
|
||||
|
||||
class StreamWrapper
|
||||
{
|
||||
protected $cursor = 0;
|
||||
protected $handle;
|
||||
protected $mode;
|
||||
protected $url;
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function dir_closedir()
|
||||
{
|
||||
$this->stream_close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param integer $options
|
||||
* @return boolean
|
||||
*/
|
||||
public function dir_opendir($url, $options)
|
||||
{
|
||||
$this->handle = $this->buildDirectoryHandle($url);
|
||||
|
||||
return (boolean) $this->handle->open();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function dir_readdir()
|
||||
{
|
||||
return $this->handle->read($this->cursor++);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function dir_rewinddir()
|
||||
{
|
||||
$this->cursor = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param integer $perms
|
||||
* @param integer $flags
|
||||
* @return boolean
|
||||
*/
|
||||
public function mkdir($url, $perms, $flags)
|
||||
{
|
||||
$this->handle = $this->buildDirectoryHandle($url);
|
||||
$recursive = $this->checkBit($flags, STREAM_MKDIR_RECURSIVE);
|
||||
|
||||
return (boolean) $this->handle->create($perms, $recursive);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $origin
|
||||
* @param string $target
|
||||
* @return boolean
|
||||
*/
|
||||
public function rename($origin, $target)
|
||||
{
|
||||
$this->handle = $this->buildFileHandle($origin);
|
||||
|
||||
return (boolean) $this->handle->rename($target);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param integer $options
|
||||
* @return boolean
|
||||
*/
|
||||
public function rmdir($url, $options)
|
||||
{
|
||||
$this->handle = $this->buildDirectoryHandle($url);
|
||||
|
||||
return (boolean) $this->handle->destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $cast
|
||||
* @return resource|boolean
|
||||
*/
|
||||
public function stream_cast($cast)
|
||||
{
|
||||
return false; // No underlying resource
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function stream_close()
|
||||
{
|
||||
$this->cursor = 0;
|
||||
$this->handle = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function stream_eof()
|
||||
{
|
||||
$node = $this->handle->getNode();
|
||||
|
||||
return !$node || $node->getSize() <= $this->cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function stream_flush()
|
||||
{
|
||||
return true; // Non-buffered writing
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $mode
|
||||
* @param integer $options
|
||||
* @param string $openedPath
|
||||
* @return boolean
|
||||
*/
|
||||
public function stream_open($url, $mode, $options, &$openedPath)
|
||||
{
|
||||
$this->cursor = 0;
|
||||
$this->handle = $this->buildFileHandle($url, $mode);
|
||||
$node = $this->handle->open();
|
||||
|
||||
if ($node && $this->checkBit($options, STREAM_USE_PATH)) {
|
||||
$openedPath = $url;
|
||||
}
|
||||
|
||||
if (isset($mode[0]) && $node && HandleInterface::MODE_APPEND === $mode[0]) {
|
||||
$this->cursor = $node->getSize();
|
||||
}
|
||||
|
||||
return (boolean) $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $length
|
||||
* @return string|boolean
|
||||
*/
|
||||
public function stream_read($length)
|
||||
{
|
||||
if ($this->handle->canRead()) {
|
||||
$out = $this->handle->read($this->cursor, $length);
|
||||
$this->cursor += strlen($out);
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $offset
|
||||
* @param integer $whence
|
||||
* @return boolean
|
||||
*/
|
||||
public function stream_seek($offset, $whence = SEEK_SET)
|
||||
{
|
||||
switch ($whence) {
|
||||
case SEEK_SET:
|
||||
$this->cursor = (integer) $offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
$this->cursor += (integer) $offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
$length = strlen($this->wrapper->read());
|
||||
$this->cursor = $length + (integer) $offset;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $option
|
||||
* @param integer $arg1
|
||||
* @param integer $arg2
|
||||
* @return boolean
|
||||
*/
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $followLink
|
||||
* @return array|boolean
|
||||
*/
|
||||
public function stream_stat($followLink = false)
|
||||
{
|
||||
$node = $this->handle->getNode();
|
||||
|
||||
if (!$node) {
|
||||
return false;
|
||||
} elseif ($followLink && $node instanceof LinkInterface) {
|
||||
$node = $node->getTarget();
|
||||
}
|
||||
|
||||
$stat = [
|
||||
'dev' => 0,
|
||||
'ino' => 0,
|
||||
'mode' => $node->getMode(),
|
||||
'nlink' => 0,
|
||||
'uid' => 0,
|
||||
'gid' => 0,
|
||||
'rdev' => 0,
|
||||
'size' => $node->getSize(),
|
||||
'atime' => $node->getDateAccessed()->getTimestamp(),
|
||||
'mtime' => $node->getDateModified()->getTimestamp(),
|
||||
'ctime' => $node->getDateCreated()->getTimestamp(),
|
||||
'blksize' => -1,
|
||||
'blocks' => -1
|
||||
];
|
||||
|
||||
return array_values($stat) + $stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $size
|
||||
* @return boolean
|
||||
*/
|
||||
public function stream_truncate($size)
|
||||
{
|
||||
if ($size > $current) {
|
||||
$this->handle->write($this->handle->read() . str_repeat("\0", $size - $current));
|
||||
} else {
|
||||
$this->handle->write($this->handle->read(0, $size));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @return integer
|
||||
*/
|
||||
public function stream_write($data)
|
||||
{
|
||||
$content = substr($this->handle->read(0, $this->cursor), 0, $this->cursor) . $data;
|
||||
$written = $this->handle->write($content);
|
||||
|
||||
$this->cursor = strlen($content);
|
||||
|
||||
return $written ? strlen($data) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @return boolean
|
||||
*/
|
||||
public function unlink($url)
|
||||
{
|
||||
$this->handle = $this->buildFileHandle($url);
|
||||
|
||||
return (boolean) $this->handle->destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param integer $flags
|
||||
* @return array
|
||||
*/
|
||||
public function url_stat($url, $flags)
|
||||
{
|
||||
$this->handle = $this->buildFileHandle($url);
|
||||
$this->handle->open();
|
||||
|
||||
return $this->stream_stat(!$this->checkBit($flags, STREAM_URL_STAT_LINK));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @return DirectoryHandle
|
||||
*/
|
||||
protected function buildDirectoryHandle($url)
|
||||
{
|
||||
return new DirectoryHandle($this->getFileSystemForUrl($url), $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $mode
|
||||
* @return FileHandle
|
||||
*/
|
||||
protected function buildFileHandle($url, $mode = null)
|
||||
{
|
||||
return new FileHandle($this->getFileSystemForUrl($url), $url, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $mask
|
||||
* @param integer $bit
|
||||
* @return boolean
|
||||
*/
|
||||
protected function checkBit($mask, $bit)
|
||||
{
|
||||
return ($mask & $bit) === $bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @return FileSystemInterface
|
||||
*/
|
||||
protected function getFileSystemForUrl($url)
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
$scheme = isset($parts['scheme']) ? $parts['scheme'] : null;
|
||||
|
||||
return FileSystemRegistry::getInstance()->get($scheme);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user