update v1.0.3.3

This commit is contained in:
sujitprasad
2015-12-22 14:09:23 +05:30
parent 2bc3db252e
commit 696e0390fe
8590 changed files with 3456 additions and 818 deletions

View File

@@ -0,0 +1,86 @@
<?php
namespace League\Flysystem\Adapter;
use League\Flysystem\AdapterInterface;
abstract class AbstractAdapter implements AdapterInterface
{
/**
* @var string path prefix
*/
protected $pathPrefix;
/**
* @var string
*/
protected $pathSeparator = '/';
/**
* Set the path prefix.
*
* @param string $prefix
*
* @return self
*/
public function setPathPrefix($prefix)
{
$is_empty = empty($prefix);
if (! $is_empty) {
$prefix = rtrim($prefix, $this->pathSeparator).$this->pathSeparator;
}
$this->pathPrefix = $is_empty ? null : $prefix;
}
/**
* Get the path prefix.
*
* @return string path prefix
*/
public function getPathPrefix()
{
return $this->pathPrefix;
}
/**
* Prefix a path.
*
* @param string $path
*
* @return string prefixed path
*/
public function applyPathPrefix($path)
{
$path = ltrim($path, '\\/');
if (strlen($path) === 0) {
return $this->getPathPrefix() ?: '';
}
if ($prefix = $this->getPathPrefix()) {
$path = $prefix.$path;
}
return $path;
}
/**
* Remove a path prefix.
*
* @param string $path
*
* @return string path without the prefix
*/
public function removePathPrefix($path)
{
$pathPrefix = $this->getPathPrefix();
if ($pathPrefix === null) {
return $path;
}
return substr($path, strlen($pathPrefix));
}
}

View File

@@ -0,0 +1,613 @@
<?php
namespace League\Flysystem\Adapter;
use DateTime;
use League\Flysystem\AdapterInterface;
use League\Flysystem\Config;
use League\Flysystem\NotSupportedException;
abstract class AbstractFtpAdapter extends AbstractAdapter
{
/**
* @var mixed
*/
protected $connection;
/**
* @var string
*/
protected $host;
/**
* @var int
*/
protected $port = 21;
/**
* @var string|null
*/
protected $username;
/**
* @var string|null
*/
protected $password;
/**
* @var bool
*/
protected $ssl = false;
/**
* @var int
*/
protected $timeout = 90;
/**
* @var bool
*/
protected $passive = true;
/**
* @var string
*/
protected $separator = '/';
/**
* @var string|null
*/
protected $root;
/**
* @var int
*/
protected $permPublic = 0744;
/**
* @var int
*/
protected $permPrivate = 0700;
/**
* @var array
*/
protected $configurable = [];
/**
* @var string
*/
protected $systemType;
/**
* Constructor.
*
* @param array $config
*/
public function __construct(array $config)
{
$this->setConfig($config);
}
/**
* Set the config.
*
* @param array $config
*
* @return $this
*/
public function setConfig(array $config)
{
foreach ($this->configurable as $setting) {
if (! isset($config[$setting])) {
continue;
}
$method = 'set'.ucfirst($setting);
if (method_exists($this, $method)) {
$this->$method($config[$setting]);
}
}
return $this;
}
/**
* Returns the host.
*
* @return string
*/
public function getHost()
{
return $this->host;
}
/**
* Set the host.
*
* @param string $host
*
* @return $this
*/
public function setHost($host)
{
$this->host = $host;
return $this;
}
/**
* Set the public permission value.
*
* @param int $permPublic
*
* @return $this
*/
public function setPermPublic($permPublic)
{
$this->permPublic = $permPublic;
return $this;
}
/**
* Set the private permission value.
*
* @param int $permPrivate
*
* @return $this
*/
public function setPermPrivate($permPrivate)
{
$this->permPrivate = $permPrivate;
return $this;
}
/**
* Returns the ftp port.
*
* @return int
*/
public function getPort()
{
return $this->port;
}
/**
* Returns the root folder to work from.
*
* @return string
*/
public function getRoot()
{
return $this->root;
}
/**
* Set the ftp port.
*
* @param int|string $port
*
* @return $this
*/
public function setPort($port)
{
$this->port = (int) $port;
return $this;
}
/**
* Set the root folder to work from.
*
* @param string $root
*
* @return $this
*/
public function setRoot($root)
{
$this->root = rtrim($root, '\\/').$this->separator;
return $this;
}
/**
* Returns the ftp username.
*
* @return string username
*/
public function getUsername()
{
return empty($this->username) ? 'anonymous' : $this->username;
}
/**
* Set ftp username.
*
* @param string $username
*
* @return $this
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Returns the password.
*
* @return string password
*/
public function getPassword()
{
return $this->password;
}
/**
* Set the ftp password.
*
* @param string $password
*
* @return $this
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Returns the amount of seconds before the connection will timeout.
*
* @return int
*/
public function getTimeout()
{
return $this->timeout;
}
/**
* Set the amount of seconds before the connection should timeout.
*
* @param int $timeout
*
* @return $this
*/
public function setTimeout($timeout)
{
$this->timeout = (int) $timeout;
return $this;
}
/**
* Return the FTP system type.
*
* @return string
*/
public function getSystemType()
{
return $this->systemType;
}
/**
* Set the FTP system type (windows or unix).
*
* @param string $systemType
*
* @return $this
*/
public function setSystemType($systemType)
{
$this->systemType = strtolower($systemType);
return $this;
}
/**
* @inheritdoc
*/
public function listContents($directory = '', $recursive = false)
{
return $this->listDirectoryContents($directory, $recursive);
}
/**
* Normalize a directory listing.
*
* @param array $listing
* @param string $prefix
*
* @return array directory listing
*/
protected function normalizeListing(array $listing, $prefix = '')
{
$base = $prefix;
$result = [];
$listing = $this->removeDotDirectories($listing);
while ($item = array_shift($listing)) {
if (preg_match('#^.*:$#', $item)) {
$base = trim($item, ':');
continue;
}
$result[] = $this->normalizeObject($item, $base);
}
return $this->sortListing($result);
}
/**
* Sort a directory listing.
*
* @param array $result
*
* @return array sorted listing
*/
protected function sortListing(array $result)
{
$compare = function ($one, $two) {
return strnatcmp($one['path'], $two['path']);
};
usort($result, $compare);
return $result;
}
/**
* Normalize a file entry.
*
* @param string $item
* @param string $base
*
* @return array normalized file array
*
* @throws NotSupportedException
*/
protected function normalizeObject($item, $base)
{
$systemType = $this->systemType ?: $this->detectSystemType($item);
if ($systemType === 'unix') {
return $this->normalizeUnixObject($item, $base);
} elseif ($systemType === 'windows') {
return $this->normalizeWindowsObject($item, $base);
}
throw NotSupportedException::forFtpSystemType($systemType);
}
/**
* Normalize a Unix file entry.
*
* @param string $item
* @param string $base
*
* @return array normalized file array
*/
protected function normalizeUnixObject($item, $base)
{
$item = preg_replace('#\s+#', ' ', trim($item), 7);
list($permissions, /* $number */, /* $owner */, /* $group */, $size, /* $month */, /* $day */, /* $time*/, $name) = explode(' ', $item, 9);
$type = $this->detectType($permissions);
$path = empty($base) ? $name : $base.$this->separator.$name;
if ($type === 'dir') {
return compact('type', 'path');
}
$permissions = $this->normalizePermissions($permissions);
$visibility = $permissions & 0044 ? AdapterInterface::VISIBILITY_PUBLIC : AdapterInterface::VISIBILITY_PRIVATE;
$size = (int) $size;
return compact('type', 'path', 'visibility', 'size');
}
/**
* Normalize a Windows/DOS file entry.
*
* @param string $item
* @param string $base
*
* @return array normalized file array
*/
protected function normalizeWindowsObject($item, $base)
{
$item = preg_replace('#\s+#', ' ', trim($item), 3);
list($date, $time, $size, $name) = explode(' ', $item, 4);
$path = empty($base) ? $name : $base.$this->separator.$name;
// Check for the correct date/time format
$format = strlen($date) === 8 ? 'm-d-yH:iA' : 'Y-m-dH:i';
$timestamp = DateTime::createFromFormat($format, $date.$time)->getTimestamp();
if ($size === '<DIR>') {
$type = 'dir';
return compact('type', 'path', 'timestamp');
}
$type = 'file';
$visibility = AdapterInterface::VISIBILITY_PUBLIC;
$size = (int) $size;
return compact('type', 'path', 'visibility', 'size', 'timestamp');
}
/**
* Get the system type from a listing item.
*
* @param string $item
*
* @return string the system type
*/
protected function detectSystemType($item)
{
if (preg_match('/^[0-9]{2,4}-[0-9]{2}-[0-9]{2}/', $item)) {
return $this->systemType = 'windows';
}
return $this->systemType = 'unix';
}
/**
* Get the file type from the permissions.
*
* @param string $permissions
*
* @return string file type
*/
protected function detectType($permissions)
{
return substr($permissions, 0, 1) === 'd' ? 'dir' : 'file';
}
/**
* Normalize a permissions string.
*
* @param string $permissions
*
* @return int
*/
protected function normalizePermissions($permissions)
{
// remove the type identifier
$permissions = substr($permissions, 1);
// map the string rights to the numeric counterparts
$map = ['-' => '0', 'r' => '4', 'w' => '2', 'x' => '1'];
$permissions = strtr($permissions, $map);
// split up the permission groups
$parts = str_split($permissions, 3);
// convert the groups
$mapper = function ($part) {
return array_sum(str_split($part));
};
// get the sum of the groups
return array_sum(array_map($mapper, $parts));
}
/**
* Filter out dot-directories.
*
* @param array $list
*
* @return array
*/
public function removeDotDirectories(array $list)
{
$filter = function ($line) {
if (! empty($line) && !preg_match('#.* \.(\.)?$|^total#', $line)) {
return true;
}
return false;
};
return array_filter($list, $filter);
}
/**
* @inheritdoc
*/
public function has($path)
{
return $this->getMetadata($path);
}
/**
* @inheritdoc
*/
public function getSize($path)
{
return $this->getMetadata($path);
}
/**
* @inheritdoc
*/
public function getVisibility($path)
{
return $this->getMetadata($path);
}
/**
* Ensure a directory exists.
*
* @param string $dirname
*/
public function ensureDirectory($dirname)
{
if (! empty($dirname) && !$this->has($dirname)) {
$this->createDir($dirname, new Config());
}
}
/**
* @return mixed
*/
public function getConnection()
{
if (! $this->isConnected()) {
$this->disconnect();
$this->connect();
}
return $this->connection;
}
/**
* Get the public permission value.
*
* @return int
*/
public function getPermPublic()
{
return $this->permPublic;
}
/**
* Get the private permission value.
*
* @return int
*/
public function getPermPrivate()
{
return $this->permPrivate;
}
/**
* Disconnect on destruction.
*/
public function __destruct()
{
$this->disconnect();
}
/**
* Establish a connection.
*/
abstract public function connect();
/**
* Close the connection.
*/
abstract public function disconnect();
/**
* Check if a connection is active.
*
* @return bool
*/
abstract public function isConnected();
}

View File

@@ -0,0 +1,424 @@
<?php
namespace League\Flysystem\Adapter;
use League\Flysystem\Adapter\Polyfill\StreamedCopyTrait;
use League\Flysystem\AdapterInterface;
use League\Flysystem\Config;
use League\Flysystem\Util;
use RuntimeException;
class Ftp extends AbstractFtpAdapter
{
use StreamedCopyTrait;
/**
* @var int
*/
protected $transferMode = FTP_BINARY;
/**
* @var array
*/
protected $configurable = [
'host',
'port',
'username',
'password',
'ssl',
'timeout',
'root',
'permPrivate',
'permPublic',
'passive',
'transferMode',
'systemType',
];
/**
* Set the transfer mode.
*
* @param int $mode
*
* @return $this
*/
public function setTransferMode($mode)
{
$this->transferMode = $mode;
return $this;
}
/**
* Set if Ssl is enabled.
*
* @param bool $ssl
*
* @return $this
*/
public function setSsl($ssl)
{
$this->ssl = (bool) $ssl;
return $this;
}
/**
* Set if passive mode should be used.
*
* @param bool $passive
*/
public function setPassive($passive = true)
{
$this->passive = $passive;
}
/**
* Connect to the FTP server.
*/
public function connect()
{
if ($this->ssl) {
$this->connection = ftp_ssl_connect($this->getHost(), $this->getPort(), $this->getTimeout());
} else {
$this->connection = ftp_connect($this->getHost(), $this->getPort(), $this->getTimeout());
}
if (! $this->connection) {
throw new RuntimeException('Could not connect to host: ' . $this->getHost() . ', port:' . $this->getPort());
}
$this->login();
$this->setConnectionPassiveMode();
$this->setConnectionRoot();
}
/**
* Set the connections to passive mode.
*
* @throws RuntimeException
*/
protected function setConnectionPassiveMode()
{
if (! ftp_pasv($this->connection, $this->passive)) {
throw new RuntimeException(
'Could not set passive mode for connection: ' . $this->getHost() . '::' . $this->getPort()
);
}
}
/**
* Set the connection root.
*/
protected function setConnectionRoot()
{
$root = $this->getRoot();
$connection = $this->connection;
if (empty($root) === false && ! ftp_chdir($connection, $root)) {
throw new RuntimeException('Root is invalid or does not exist: ' . $this->getRoot());
}
// Store absolute path for further reference.
// This is needed when creating directories and
// initial root was a relative path, else the root
// would be relative to the chdir'd path.
$this->root = ftp_pwd($connection);
}
/**
* Login.
*
* @throws RuntimeException
*/
protected function login()
{
set_error_handler(
function () {
}
);
$isLoggedIn = ftp_login($this->connection, $this->getUsername(), $this->getPassword());
restore_error_handler();
if (! $isLoggedIn) {
$this->disconnect();
throw new RuntimeException(
'Could not login with connection: ' . $this->getHost() . '::' . $this->getPort(
) . ', username: ' . $this->getUsername()
);
}
}
/**
* Disconnect from the FTP server.
*/
public function disconnect()
{
if ($this->isConnected()) {
ftp_close($this->connection);
}
$this->connection = null;
}
/**
* @inheritdoc
*/
public function write($path, $contents, Config $config)
{
$stream = fopen('php://temp', 'w+b');
fwrite($stream, $contents);
rewind($stream);
$result = $this->writeStream($path, $stream, $config);
fclose($stream);
if ($result === false) {
return false;
}
$result['contents'] = $contents;
$result['mimetype'] = Util::guessMimeType($path, $contents);
return $result;
}
/**
* @inheritdoc
*/
public function writeStream($path, $resource, Config $config)
{
$this->ensureDirectory(Util::dirname($path));
if (! ftp_fput($this->getConnection(), $path, $resource, $this->transferMode)) {
return false;
}
if ($visibility = $config->get('visibility')) {
$this->setVisibility($path, $visibility);
}
return compact('path', 'visibility');
}
/**
* @inheritdoc
*/
public function update($path, $contents, Config $config)
{
return $this->write($path, $contents, $config);
}
/**
* @inheritdoc
*/
public function updateStream($path, $resource, Config $config)
{
return $this->writeStream($path, $resource, $config);
}
/**
* @inheritdoc
*/
public function rename($path, $newpath)
{
return ftp_rename($this->getConnection(), $path, $newpath);
}
/**
* @inheritdoc
*/
public function delete($path)
{
return ftp_delete($this->getConnection(), $path);
}
/**
* @inheritdoc
*/
public function deleteDir($dirname)
{
$connection = $this->getConnection();
$contents = array_reverse($this->listDirectoryContents($dirname));
foreach ($contents as $object) {
if ($object['type'] === 'file') {
if (! ftp_delete($connection, $object['path'])) {
return false;
}
} elseif (! ftp_rmdir($connection, $object['path'])) {
return false;
}
}
return ftp_rmdir($connection, $dirname);
}
/**
* @inheritdoc
*/
public function createDir($dirname, Config $config)
{
$connection = $this->getConnection();
$directories = explode('/', $dirname);
foreach ($directories as $directory) {
if (false === $this->createActualDirectory($directory, $connection)) {
$this->setConnectionRoot();
return false;
}
ftp_chdir($connection, $directory);
}
$this->setConnectionRoot();
return ['path' => $dirname];
}
/**
* Create a directory.
*
* @param string $directory
* @param resource $connection
*
* @return bool
*/
protected function createActualDirectory($directory, $connection)
{
// List the current directory
$listing = ftp_nlist($connection, '.');
foreach ($listing as $key => $item) {
if (preg_match('~^\./.*~', $item)) {
$listing[$key] = substr($item, 2);
}
}
if (in_array($directory, $listing)) {
return true;
}
return (boolean) ftp_mkdir($connection, $directory);
}
/**
* @inheritdoc
*/
public function getMetadata($path)
{
$connection = $this->getConnection();
if ($path === '') {
return ['type' => 'dir', 'path' => ''];
}
if (@ftp_chdir($connection, $path) === true) {
$this->setConnectionRoot();
return ['type' => 'dir', 'path' => $path];
}
$listing = ftp_rawlist($connection, $path);
if (empty($listing)) {
return false;
}
return $this->normalizeObject($listing[0], '');
}
/**
* @inheritdoc
*/
public function getMimetype($path)
{
if (! $metadata = $this->read($path)) {
return false;
}
$metadata['mimetype'] = Util::guessMimeType($path, $metadata['contents']);
return $metadata;
}
/**
* @inheritdoc
*/
public function getTimestamp($path)
{
$timestamp = ftp_mdtm($this->getConnection(), $path);
return ($timestamp !== -1) ? ['timestamp' => $timestamp] : false;
}
/**
* @inheritdoc
*/
public function read($path)
{
if (! $object = $this->readStream($path)) {
return false;
}
$object['contents'] = stream_get_contents($object['stream']);
fclose($object['stream']);
unset($object['stream']);
return $object;
}
/**
* @inheritdoc
*/
public function readStream($path)
{
$stream = fopen('php://temp', 'w+');
$result = ftp_fget($this->getConnection(), $stream, $path, $this->transferMode);
rewind($stream);
if (! $result) {
fclose($stream);
return false;
}
return compact('stream');
}
/**
* @inheritdoc
*/
public function setVisibility($path, $visibility)
{
$mode = $visibility === AdapterInterface::VISIBILITY_PUBLIC ? $this->getPermPublic() : $this->getPermPrivate();
if (! ftp_chmod($this->getConnection(), $mode, $path)) {
return false;
}
return compact('visibility');
}
/**
* @inheritdoc
*
* @param string $directory
*/
protected function listDirectoryContents($directory, $recursive = true)
{
$listing = ftp_rawlist($this->getConnection(), '-lna ' . $directory, $recursive);
return $listing ? $this->normalizeListing($listing, $directory) : [];
}
/**
* Check if the connection is open.
*
* @return bool
*/
public function isConnected()
{
return ! is_null($this->connection) && ftp_systype($this->connection) !== false;
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace League\Flysystem\Adapter;
class Ftpd extends Ftp
{
/**
* @inheritdoc
*/
public function getMetadata($path)
{
if (empty($path) || !($object = ftp_raw($this->getConnection(), 'STAT '.$path)) || count($object) < 3) {
return false;
}
if (substr($object[1], 0, 5) === "ftpd:") {
return false;
}
return $this->normalizeObject($object[1], '');
}
/**
* @inheritdoc
*/
protected function listDirectoryContents($directory, $recursive = true)
{
$listing = ftp_rawlist($this->getConnection(), $directory, $recursive);
if ($listing === false || (!empty($listing) && substr($listing[0], 0, 5) === "ftpd:")) {
return [];
}
return $this->normalizeListing($listing, $directory);
}
}

View File

@@ -0,0 +1,477 @@
<?php
namespace League\Flysystem\Adapter;
use DirectoryIterator;
use FilesystemIterator;
use Finfo;
use League\Flysystem\AdapterInterface;
use League\Flysystem\Config;
use League\Flysystem\NotSupportedException;
use League\Flysystem\Util;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use SplFileInfo;
class Local extends AbstractAdapter
{
/**
* @var int
*/
const SKIP_LINKS = 0001;
/**
* @var int
*/
const DISALLOW_LINKS = 0002;
/**
* @var array
*/
protected static $permissions = [
'file' => [
'public' => 0744,
'private' => 0700,
],
'dir' => [
'public' => 0755,
'private' => 0700,
]
];
/**
* @var string
*/
protected $pathSeparator = DIRECTORY_SEPARATOR;
/**
* @var array
*/
protected $permissionMap;
/**
* @var int
*/
protected $writeFlags;
/**
* @var int
*/
private $linkHandling;
/**
* Constructor.
*
* @param string $root
* @param int $writeFlags
* @param int $linkHandling
* @param array $permissions
*/
public function __construct($root, $writeFlags = LOCK_EX, $linkHandling = self::DISALLOW_LINKS, array $permissions = [])
{
// permissionMap needs to be set before ensureDirectory() is called.
$this->permissionMap = array_replace_recursive(static::$permissions, $permissions);
$realRoot = $this->ensureDirectory($root);
if (! is_dir($realRoot) || !is_readable($realRoot)) {
throw new \LogicException('The root path '.$root.' is not readable.');
}
$this->setPathPrefix($realRoot);
$this->writeFlags = $writeFlags;
$this->linkHandling = $linkHandling;
}
/**
* Ensure the root directory exists.
*
* @param string $root root directory path
*
* @return string real path to root
*/
protected function ensureDirectory($root)
{
if (! is_dir($root)) {
$umask = umask(0);
mkdir($root, $this->permissionMap['dir']['public'], true);
umask($umask);
}
return realpath($root);
}
/**
* @inheritdoc
*/
public function has($path)
{
$location = $this->applyPathPrefix($path);
return file_exists($location);
}
/**
* @inheritdoc
*/
public function write($path, $contents, Config $config)
{
$location = $this->applyPathPrefix($path);
$this->ensureDirectory(dirname($location));
if (($size = file_put_contents($location, $contents, $this->writeFlags)) === false) {
return false;
}
$type = 'file';
$result = compact('contents', 'type', 'size', 'path');
if ($visibility = $config->get('visibility')) {
$result['visibility'] = $visibility;
$this->setVisibility($path, $visibility);
}
return $result;
}
/**
* @inheritdoc
*/
public function writeStream($path, $resource, Config $config)
{
$location = $this->applyPathPrefix($path);
$this->ensureDirectory(dirname($location));
$stream = fopen($location, 'w+');
if (! $stream) {
return false;
}
stream_copy_to_stream($resource, $stream);
if (! fclose($stream)) {
return false;
}
if ($visibility = $config->get('visibility')) {
$this->setVisibility($path, $visibility);
}
return compact('path', 'visibility');
}
/**
* @inheritdoc
*/
public function readStream($path)
{
$location = $this->applyPathPrefix($path);
$stream = fopen($location, 'r');
return compact('stream', 'path');
}
/**
* @inheritdoc
*/
public function updateStream($path, $resource, Config $config)
{
return $this->writeStream($path, $resource, $config);
}
/**
* @inheritdoc
*/
public function update($path, $contents, Config $config)
{
$location = $this->applyPathPrefix($path);
$mimetype = Util::guessMimeType($path, $contents);
$size = file_put_contents($location, $contents, $this->writeFlags);
if ($size === false) {
return false;
}
return compact('path', 'size', 'contents', 'mimetype');
}
/**
* @inheritdoc
*/
public function read($path)
{
$location = $this->applyPathPrefix($path);
$contents = file_get_contents($location);
if ($contents === false) {
return false;
}
return compact('contents', 'path');
}
/**
* @inheritdoc
*/
public function rename($path, $newpath)
{
$location = $this->applyPathPrefix($path);
$destination = $this->applyPathPrefix($newpath);
$parentDirectory = $this->applyPathPrefix(Util::dirname($newpath));
$this->ensureDirectory($parentDirectory);
return rename($location, $destination);
}
/**
* @inheritdoc
*/
public function copy($path, $newpath)
{
$location = $this->applyPathPrefix($path);
$destination = $this->applyPathPrefix($newpath);
$this->ensureDirectory(dirname($destination));
return copy($location, $destination);
}
/**
* @inheritdoc
*/
public function delete($path)
{
$location = $this->applyPathPrefix($path);
return unlink($location);
}
/**
* @inheritdoc
*/
public function listContents($directory = '', $recursive = false)
{
$result = [];
$location = $this->applyPathPrefix($directory).$this->pathSeparator;
if (! is_dir($location)) {
return [];
}
$iterator = $recursive ? $this->getRecursiveDirectoryIterator($location) : $this->getDirectoryIterator($location);
foreach ($iterator as $file) {
$path = $this->getFilePath($file);
if (preg_match('#(^|/|\\\\)\.{1,2}$#', $path)) {
continue;
}
$result[] = $this->normalizeFileInfo($file);
}
return array_filter($result);
}
/**
* @inheritdoc
*/
public function getMetadata($path)
{
$location = $this->applyPathPrefix($path);
$info = new SplFileInfo($location);
return $this->normalizeFileInfo($info);
}
/**
* @inheritdoc
*/
public function getSize($path)
{
return $this->getMetadata($path);
}
/**
* @inheritdoc
*/
public function getMimetype($path)
{
$location = $this->applyPathPrefix($path);
$finfo = new Finfo(FILEINFO_MIME_TYPE);
return ['mimetype' => $finfo->file($location)];
}
/**
* @inheritdoc
*/
public function getTimestamp($path)
{
return $this->getMetadata($path);
}
/**
* @inheritdoc
*/
public function getVisibility($path)
{
$location = $this->applyPathPrefix($path);
clearstatcache(false, $location);
$permissions = octdec(substr(sprintf('%o', fileperms($location)), -4));
$visibility = $permissions & 0044 ? AdapterInterface::VISIBILITY_PUBLIC : AdapterInterface::VISIBILITY_PRIVATE;
return compact('visibility');
}
/**
* @inheritdoc
*/
public function setVisibility($path, $visibility)
{
$location = $this->applyPathPrefix($path);
$type = is_dir($location) ? 'dir' : 'file';
chmod($location, $this->permissionMap[$type][$visibility]);
return compact('visibility');
}
/**
* @inheritdoc
*/
public function createDir($dirname, Config $config)
{
$location = $this->applyPathPrefix($dirname);
$umask = umask(0);
$visibility = $config->get('visibility', 'public');
if (! is_dir($location) && !mkdir($location, $this->permissionMap['dir'][$visibility], true)) {
$return = false;
} else {
$return = ['path' => $dirname, 'type' => 'dir'];
}
umask($umask);
return $return;
}
/**
* @inheritdoc
*/
public function deleteDir($dirname)
{
$location = $this->applyPathPrefix($dirname);
if (! is_dir($location)) {
return false;
}
$contents = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($location, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
/** @var SplFileInfo $file */
foreach ($contents as $file) {
switch ($file->getType()) {
case 'dir':
rmdir($file->getRealPath());
break;
case 'link':
unlink($file->getPathname());
break;
default:
unlink($file->getRealPath());
}
}
return rmdir($location);
}
/**
* Normalize the file info.
*
* @param SplFileInfo $file
*
* @return array
*/
protected function normalizeFileInfo(SplFileInfo $file)
{
if (! $file->isLink()) {
return $this->mapFileInfo($file);
}
if ($this->linkHandling & self::DISALLOW_LINKS) {
throw NotSupportedException::forLink($file);
}
}
/**
* Get the normalized path from a SplFileInfo object.
*
* @param SplFileInfo $file
*
* @return string
*/
protected function getFilePath(SplFileInfo $file)
{
$location = $file->getPathname();
$path = $this->removePathPrefix($location);
return trim(str_replace('\\', '/', $path), '/');
}
/**
* @param string $path
*
* @return RecursiveIteratorIterator
*/
protected function getRecursiveDirectoryIterator($path)
{
$directory = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
$iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST);
return $iterator;
}
/**
* @param string $path
*
* @return DirectoryIterator
*/
protected function getDirectoryIterator($path)
{
$iterator = new DirectoryIterator($path);
return $iterator;
}
/**
* @param SplFileInfo $file
*
* @return array
*/
protected function mapFileInfo(SplFileInfo $file)
{
$normalized = [
'type' => $file->getType(),
'path' => $this->getFilePath($file),
];
$normalized['timestamp'] = $file->getMTime();
if ($normalized['type'] === 'file') {
$normalized['size'] = $file->getSize();
}
return $normalized;
}
/**
* @inheritdoc
*/
public function applyPathPrefix($path)
{
$prefixedPath = parent::applyPathPrefix($path);
return str_replace('/', DIRECTORY_SEPARATOR, $prefixedPath);
}
}

View File

@@ -0,0 +1,144 @@
<?php
namespace League\Flysystem\Adapter;
use League\Flysystem\Adapter\Polyfill\StreamedCopyTrait;
use League\Flysystem\Adapter\Polyfill\StreamedTrait;
use League\Flysystem\Config;
class NullAdapter extends AbstractAdapter
{
use StreamedTrait;
use StreamedCopyTrait;
/**
* Check whether a file is present.
*
* @param string $path
*
* @return bool
*/
public function has($path)
{
return false;
}
/**
* @inheritdoc
*/
public function write($path, $contents, Config $config)
{
$type = 'file';
$result = compact('contents', 'type', 'size', 'path');
if ($visibility = $config->get('visibility')) {
$result['visibility'] = $visibility;
}
return $result;
}
/**
* @inheritdoc
*/
public function update($path, $contents, Config $config)
{
return false;
}
/**
* @inheritdoc
*/
public function read($path)
{
return false;
}
/**
* @inheritdoc
*/
public function rename($path, $newpath)
{
return false;
}
/**
* @inheritdoc
*/
public function delete($path)
{
return false;
}
/**
* @inheritdoc
*/
public function listContents($directory = '', $recursive = false)
{
return [];
}
/**
* @inheritdoc
*/
public function getMetadata($path)
{
return false;
}
/**
* @inheritdoc
*/
public function getSize($path)
{
return false;
}
/**
* @inheritdoc
*/
public function getMimetype($path)
{
return false;
}
/**
* @inheritdoc
*/
public function getTimestamp($path)
{
return false;
}
/**
* @inheritdoc
*/
public function getVisibility($path)
{
return false;
}
/**
* @inheritdoc
*/
public function setVisibility($path, $visibility)
{
return compact('visibility');
}
/**
* @inheritdoc
*/
public function createDir($dirname, Config $config)
{
return ['path' => $dirname, 'type' => 'dir'];
}
/**
* @inheritdoc
*/
public function deleteDir($dirname)
{
return false;
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace League\Flysystem\Adapter\Polyfill;
use LogicException;
trait NotSupportingVisibilityTrait
{
/**
* Get the visibility of a file.
*
* @param string $path
*
* @throws LogicException
*/
public function getVisibility($path)
{
throw new LogicException(get_class($this).' does not support visibility. Path: '.$path);
}
/**
* Set the visibility for a file.
*
* @param string $path
* @param string $visibility
*
* @throws LogicException
*/
public function setVisibility($path, $visibility)
{
throw new LogicException(get_class($this).' does not support visibility. Path: '.$path.', visibility: '.$visibility);
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace League\Flysystem\Adapter\Polyfill;
use League\Flysystem\Config;
trait StreamedCopyTrait
{
/**
* Copy a file.
*
* @param string $path
* @param string $newpath
*
* @return bool
*/
public function copy($path, $newpath)
{
$response = $this->readStream($path);
if ($response === false || !is_resource($response['stream'])) {
return false;
}
$result = $this->writeStream($newpath, $response['stream'], new Config());
if ($result !== false && is_resource($response['stream'])) {
fclose($response['stream']);
}
return $result !== false;
}
// Required abstract method
/**
* @param string $path
*/
abstract public function readStream($path);
/**
* @param string $path
*/
abstract public function writeStream($path, $resource, Config $config);
}

View File

@@ -0,0 +1,37 @@
<?php
namespace League\Flysystem\Adapter\Polyfill;
trait StreamedReadingTrait
{
/**
* Get the contents of a file in a stream.
*
* @param string $path
*
* @return resource|false false when not found, or a resource
*/
public function readStream($path)
{
if (! $data = $this->read($path)) {
return false;
}
$stream = tmpfile();
fwrite($stream, $data['contents']);
rewind($stream);
$data['stream'] = $stream;
unset($data['contents']);
return $data;
}
// Required abstract method
/**
* @param string $path
*
* @return resource
*/
abstract public function read($path);
}

View File

@@ -0,0 +1,9 @@
<?php
namespace League\Flysystem\Adapter\Polyfill;
trait StreamedTrait
{
use StreamedReadingTrait;
use StreamedWritingTrait;
}

View File

@@ -0,0 +1,60 @@
<?php
namespace League\Flysystem\Adapter\Polyfill;
use League\Flysystem\Config;
use League\Flysystem\Util;
trait StreamedWritingTrait
{
/**
* Stream fallback delegator.
*
* @param string $path
* @param resource $resource
* @param Config $config
* @param string $fallback
*
* @return mixed fallback result
*/
protected function stream($path, $resource, Config $config, $fallback)
{
Util::rewindStream($resource);
$contents = stream_get_contents($resource);
$fallbackCall = [$this, $fallback];
return call_user_func($fallbackCall, $path, $contents, $config);
}
/**
* Write using a stream.
*
* @param string $path
* @param resource $resource
* @param Config $config
*
* @return mixed false or file metadata
*/
public function writeStream($path, $resource, Config $config)
{
return $this->stream($path, $resource, $config, 'write');
}
/**
* Update a file using a stream.
*
* @param string $path
* @param resource $resource
* @param Config $config Config object or visibility setting
*
* @return mixed false of file metadata
*/
public function updateStream($path, $resource, Config $config)
{
return $this->stream($path, $resource, $config, 'update');
}
// Required abstract methods
abstract public function write($pash, $contents, Config $config);
abstract public function update($pash, $contents, Config $config);
}

View File

@@ -0,0 +1,8 @@
<?php
namespace League\Flysystem\Adapter;
class SynologyFtp extends Ftpd
{
// This class merely exists because of BC.
}

View File

@@ -0,0 +1,118 @@
<?php
namespace League\Flysystem;
interface AdapterInterface extends ReadInterface
{
/**
* @const VISIBILITY_PUBLIC public visibility
*/
const VISIBILITY_PUBLIC = 'public';
/**
* @const VISIBILITY_PRIVATE private visibility
*/
const VISIBILITY_PRIVATE = 'private';
/**
* Write a new file.
*
* @param string $path
* @param string $contents
* @param Config $config Config object
*
* @return array|false false on failure file meta data on success
*/
public function write($path, $contents, Config $config);
/**
* Write a new file using a stream.
*
* @param string $path
* @param resource $resource
* @param Config $config Config object
*
* @return array|false false on failure file meta data on success
*/
public function writeStream($path, $resource, Config $config);
/**
* Update a file.
*
* @param string $path
* @param string $contents
* @param Config $config Config object
*
* @return array|false false on failure file meta data on success
*/
public function update($path, $contents, Config $config);
/**
* Update a file using a stream.
*
* @param string $path
* @param resource $resource
* @param Config $config Config object
*
* @return array|false false on failure file meta data on success
*/
public function updateStream($path, $resource, Config $config);
/**
* Rename a file.
*
* @param string $path
* @param string $newpath
*
* @return bool
*/
public function rename($path, $newpath);
/**
* Copy a file.
*
* @param string $path
* @param string $newpath
*
* @return bool
*/
public function copy($path, $newpath);
/**
* Delete a file.
*
* @param string $path
*
* @return bool
*/
public function delete($path);
/**
* Delete a directory.
*
* @param string $dirname
*
* @return bool
*/
public function deleteDir($dirname);
/**
* Create a directory.
*
* @param string $dirname directory name
* @param Config $config
*
* @return array|false
*/
public function createDir($dirname, Config $config);
/**
* Set the visibility for a file.
*
* @param string $path
* @param string $visibility
*
* @return array|false file meta data
*/
public function setVisibility($path, $visibility);
}

101
vendor/league/flysystem/src/Config.php vendored Normal file
View File

@@ -0,0 +1,101 @@
<?php
namespace League\Flysystem;
class Config
{
/**
* @var array
*/
protected $settings = [];
/**
* @var Config
*/
protected $fallback;
/**
* Constructor.
*
* @param array $settings
*/
public function __construct(array $settings = [])
{
$this->settings = $settings;
}
/**
* Get a setting.
*
* @param string $key
* @param mixed $default
*
* @return mixed config setting or default when not found
*/
public function get($key, $default = null)
{
if (! array_key_exists($key, $this->settings)) {
return $this->getDefault($key, $default);
}
return $this->settings[$key];
}
/**
* Check if an item exists by key.
*
* @param string $key
*
* @return bool
*/
public function has($key)
{
return array_key_exists($key, $this->settings);
}
/**
* Try to retrieve a default setting from a config fallback.
*
* @param string $key
* @param mixed $default
*
* @return mixed config setting or default when not found
*/
protected function getDefault($key, $default)
{
if (! $this->fallback) {
return $default;
}
return $this->fallback->get($key, $default);
}
/**
* Set a setting.
*
* @param string $key
* @param mixed $value
*
* @return $this
*/
public function set($key, $value)
{
$this->settings[$key] = $value;
return $this;
}
/**
* Set the fallback.
*
* @param Config $fallback
*
* @return $this
*/
public function setFallback(Config $fallback)
{
$this->fallback = $fallback;
return $this;
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace League\Flysystem;
/**
* @internal
*/
trait ConfigAwareTrait
{
/**
* @var Config
*/
protected $config;
/**
* Set the config.
*
* @param Config|array|null $config
*/
protected function setConfig($config)
{
$this->config = $config ? Util::ensureConfig($config) : null;
}
/**
* Get the Config.
*
* @return Config config object
*/
public function getConfig()
{
if ($this->config === null) {
return $this->config = new Config;
}
return $this->config;
}
/**
* Convert a config array to a Config object with the correct fallback.
*
* @param array $config
*
* @return Config
*/
protected function prepareConfig(array $config)
{
$config = new Config($config);
$config->setFallback($this->getConfig());
return $config;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace League\Flysystem;
class Directory extends Handler
{
/**
* Delete the directory.
*
* @return bool
*/
public function delete()
{
return $this->filesystem->deleteDir($this->path);
}
/**
* List the directory contents.
*
* @param bool $recursive
*
* @return array|bool directory contents or false
*/
public function getContents($recursive = false)
{
return $this->filesystem->listContents($this->path, $recursive);
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace League\Flysystem;
class Exception extends \Exception
{
//
}

202
vendor/league/flysystem/src/File.php vendored Normal file
View File

@@ -0,0 +1,202 @@
<?php
namespace League\Flysystem;
class File extends Handler
{
/**
* Check whether the file exists.
*
* @return bool
*/
public function exists()
{
return $this->filesystem->has($this->path);
}
/**
* Read the file.
*
* @return string file contents
*/
public function read()
{
return $this->filesystem->read($this->path);
}
/**
* Read the file as a stream.
*
* @return resource file stream
*/
public function readStream()
{
return $this->filesystem->readStream($this->path);
}
/**
* Write the new file.
*
* @param string $content
*
* @return bool success boolean
*/
public function write($content)
{
return $this->filesystem->write($this->path, $content);
}
/**
* Write the new file using a stream.
*
* @param resource $resource
*
* @return bool success boolean
*/
public function writeStream($resource)
{
return $this->filesystem->writeStream($this->path, $resource);
}
/**
* Update the file contents.
*
* @param string $content
*
* @return bool success boolean
*/
public function update($content)
{
return $this->filesystem->update($this->path, $content);
}
/**
* Update the file contents with a stream.
*
* @param resource $resource
*
* @return bool success boolean
*/
public function updateStream($resource)
{
return $this->filesystem->updateStream($this->path, $resource);
}
/**
* Create the file or update if exists.
*
* @param string $content
*
* @return bool success boolean
*/
public function put($content)
{
return $this->filesystem->put($this->path, $content);
}
/**
* Create the file or update if exists using a stream.
*
* @param resource $resource
*
* @return bool success boolean
*/
public function putStream($resource)
{
return $this->filesystem->putStream($this->path, $resource);
}
/**
* Rename the file.
*
* @param string $newpath
*
* @return bool success boolean
*/
public function rename($newpath)
{
if ($this->filesystem->rename($this->path, $newpath)) {
$this->path = $newpath;
return true;
}
return false;
}
/**
* Copy the file.
*
* @param string $newpath
*
* @return File|false new file or false
*/
public function copy($newpath)
{
if ($this->filesystem->copy($this->path, $newpath)) {
return new File($this->filesystem, $newpath);
}
return false;
}
/**
* Get the file's timestamp.
*
* @return int unix timestamp
*/
public function getTimestamp()
{
return $this->filesystem->getTimestamp($this->path);
}
/**
* Get the file's mimetype.
*
* @return string mimetime
*/
public function getMimetype()
{
return $this->filesystem->getMimetype($this->path);
}
/**
* Get the file's visibility.
*
* @return string visibility
*/
public function getVisibility()
{
return $this->filesystem->getVisibility($this->path);
}
/**
* Get the file's metadata.
*
* @return array
*/
public function getMetadata()
{
return $this->filesystem->getMetadata($this->path);
}
/**
* Get the file size.
*
* @return int file size
*/
public function getSize()
{
return $this->filesystem->getSize($this->path);
}
/**
* Delete the file.
*
* @return bool success boolean
*/
public function delete()
{
return $this->filesystem->delete($this->path);
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace League\Flysystem;
use Exception as BaseException;
class FileExistsException extends Exception
{
/**
* @var string
*/
protected $path;
/**
* Constructor.
*
* @param string $path
* @param int $code
* @param BaseException $previous
*/
public function __construct($path, $code = 0, BaseException $previous = null)
{
$this->path = $path;
parent::__construct('File already exists at path: '.$this->getPath(), $code, $previous);
}
/**
* Get the path which was not found.
*
* @return string
*/
public function getPath()
{
return $this->path;
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace League\Flysystem;
use Exception as BaseException;
class FileNotFoundException extends Exception
{
/**
* @var string
*/
protected $path;
/**
* Constructor.
*
* @param string $path
* @param int $code
* @param \Exception $previous
*/
public function __construct($path, $code = 0, BaseException $previous = null)
{
$this->path = $path;
parent::__construct('File not found at path: '.$this->getPath(), $code, $previous);
}
/**
* Get the path which was not found.
*
* @return string
*/
public function getPath()
{
return $this->path;
}
}

View File

@@ -0,0 +1,398 @@
<?php
namespace League\Flysystem;
use InvalidArgumentException;
use League\Flysystem\Plugin\PluggableTrait;
use League\Flysystem\Util\ContentListingFormatter;
/**
* @method array getWithMetadata(string $path, array $metadata)
* @method array listFiles(string $path = '', boolean $recursive = false)
* @method array listPaths(string $path = '', boolean $recursive = false)
* @method array listWith(array $keys = [], $directory = '', $recursive = false)
*/
class Filesystem implements FilesystemInterface
{
use PluggableTrait;
use ConfigAwareTrait;
/**
* @var AdapterInterface
*/
protected $adapter;
/**
* Constructor.
*
* @param AdapterInterface $adapter
* @param Config|array $config
*/
public function __construct(AdapterInterface $adapter, $config = null)
{
$this->adapter = $adapter;
$this->setConfig($config);
}
/**
* Get the Adapter.
*
* @return AdapterInterface adapter
*/
public function getAdapter()
{
return $this->adapter;
}
/**
* @inheritdoc
*/
public function has($path)
{
$path = Util::normalizePath($path);
return (bool) $this->getAdapter()->has($path);
}
/**
* @inheritdoc
*/
public function write($path, $contents, array $config = [])
{
$path = Util::normalizePath($path);
$this->assertAbsent($path);
$config = $this->prepareConfig($config);
return (bool) $this->getAdapter()->write($path, $contents, $config);
}
/**
* @inheritdoc
*/
public function writeStream($path, $resource, array $config = [])
{
if (! is_resource($resource)) {
throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');
}
$path = Util::normalizePath($path);
$this->assertAbsent($path);
$config = $this->prepareConfig($config);
Util::rewindStream($resource);
return (bool) $this->getAdapter()->writeStream($path, $resource, $config);
}
/**
* @inheritdoc
*/
public function put($path, $contents, array $config = [])
{
$path = Util::normalizePath($path);
$config = $this->prepareConfig($config);
if ($this->has($path)) {
return (bool) $this->getAdapter()->update($path, $contents, $config);
}
return (bool) $this->getAdapter()->write($path, $contents, $config);
}
/**
* @inheritdoc
*/
public function putStream($path, $resource, array $config = [])
{
if (! is_resource($resource)) {
throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');
}
$path = Util::normalizePath($path);
$config = $this->prepareConfig($config);
Util::rewindStream($resource);
if ($this->has($path)) {
return (bool) $this->getAdapter()->updateStream($path, $resource, $config);
}
return (bool) $this->getAdapter()->writeStream($path, $resource, $config);
}
/**
* @inheritdoc
*/
public function readAndDelete($path)
{
$path = Util::normalizePath($path);
$this->assertPresent($path);
$contents = $this->read($path);
if ($contents === false) {
return false;
}
$this->delete($path);
return $contents;
}
/**
* @inheritdoc
*/
public function update($path, $contents, array $config = [])
{
$path = Util::normalizePath($path);
$config = $this->prepareConfig($config);
$this->assertPresent($path);
return (bool) $this->getAdapter()->update($path, $contents, $config);
}
/**
* @inheritdoc
*/
public function updateStream($path, $resource, array $config = [])
{
if (! is_resource($resource)) {
throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');
}
$path = Util::normalizePath($path);
$config = $this->prepareConfig($config);
$this->assertPresent($path);
Util::rewindStream($resource);
return (bool) $this->getAdapter()->updateStream($path, $resource, $config);
}
/**
* @inheritdoc
*/
public function read($path)
{
$path = Util::normalizePath($path);
$this->assertPresent($path);
if (! ($object = $this->getAdapter()->read($path))) {
return false;
}
return $object['contents'];
}
/**
* @inheritdoc
*/
public function readStream($path)
{
$path = Util::normalizePath($path);
$this->assertPresent($path);
if (! $object = $this->getAdapter()->readStream($path)) {
return false;
}
return $object['stream'];
}
/**
* @inheritdoc
*/
public function rename($path, $newpath)
{
$path = Util::normalizePath($path);
$newpath = Util::normalizePath($newpath);
$this->assertPresent($path);
$this->assertAbsent($newpath);
return (bool) $this->getAdapter()->rename($path, $newpath);
}
/**
* @inheritdoc
*/
public function copy($path, $newpath)
{
$path = Util::normalizePath($path);
$newpath = Util::normalizePath($newpath);
$this->assertPresent($path);
$this->assertAbsent($newpath);
return $this->getAdapter()->copy($path, $newpath);
}
/**
* @inheritdoc
*/
public function delete($path)
{
$path = Util::normalizePath($path);
$this->assertPresent($path);
return $this->getAdapter()->delete($path);
}
/**
* @inheritdoc
*/
public function deleteDir($dirname)
{
$dirname = Util::normalizePath($dirname);
if ($dirname === '') {
throw new RootViolationException('Root directories can not be deleted.');
}
return (bool) $this->getAdapter()->deleteDir($dirname);
}
/**
* @inheritdoc
*/
public function createDir($dirname, array $config = [])
{
$dirname = Util::normalizePath($dirname);
$config = $this->prepareConfig($config);
return (bool) $this->getAdapter()->createDir($dirname, $config);
}
/**
* @inheritdoc
*/
public function listContents($directory = '', $recursive = false)
{
$directory = Util::normalizePath($directory);
$contents = $this->getAdapter()->listContents($directory, $recursive);
return (new ContentListingFormatter($directory, $recursive))->formatListing($contents);
}
/**
* @inheritdoc
*/
public function getMimetype($path)
{
$path = Util::normalizePath($path);
$this->assertPresent($path);
if (! $object = $this->getAdapter()->getMimetype($path)) {
return false;
}
return $object['mimetype'];
}
/**
* @inheritdoc
*/
public function getTimestamp($path)
{
$path = Util::normalizePath($path);
$this->assertPresent($path);
if (! $object = $this->getAdapter()->getTimestamp($path)) {
return false;
}
return $object['timestamp'];
}
/**
* @inheritdoc
*/
public function getVisibility($path)
{
$path = Util::normalizePath($path);
$this->assertPresent($path);
if (($object = $this->getAdapter()->getVisibility($path)) === false) {
return false;
}
return $object['visibility'];
}
/**
* @inheritdoc
*/
public function getSize($path)
{
$path = Util::normalizePath($path);
if (($object = $this->getAdapter()->getSize($path)) === false || !isset($object['size'])) {
return false;
}
return (int) $object['size'];
}
/**
* @inheritdoc
*/
public function setVisibility($path, $visibility)
{
$path = Util::normalizePath($path);
return (bool) $this->getAdapter()->setVisibility($path, $visibility);
}
/**
* @inheritdoc
*/
public function getMetadata($path)
{
$path = Util::normalizePath($path);
$this->assertPresent($path);
return $this->getAdapter()->getMetadata($path);
}
/**
* @inheritdoc
*/
public function get($path, Handler $handler = null)
{
$path = Util::normalizePath($path);
if (! $handler) {
$metadata = $this->getMetadata($path);
$handler = $metadata['type'] === 'file' ? new File($this, $path) : new Directory($this, $path);
}
$handler->setPath($path);
$handler->setFilesystem($this);
return $handler;
}
/**
* Assert a file is present.
*
* @param string $path path to file
*
* @throws FileNotFoundException
*/
public function assertPresent($path)
{
if (! $this->has($path)) {
throw new FileNotFoundException($path);
}
}
/**
* Assert a file is absent.
*
* @param string $path path to file
*
* @throws FileExistsException
*/
public function assertAbsent($path)
{
if ($this->has($path)) {
throw new FileExistsException($path);
}
}
}

View File

@@ -0,0 +1,276 @@
<?php
namespace League\Flysystem;
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.
*
* @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 string|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'.
*
* @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.
*
* @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);
}

134
vendor/league/flysystem/src/Handler.php vendored Normal file
View File

@@ -0,0 +1,134 @@
<?php
namespace League\Flysystem;
use BadMethodCallException;
abstract class Handler
{
/**
* @var string
*/
protected $path;
/**
* @var FilesystemInterface
*/
protected $filesystem;
/**
* Constructor.
*
* @param FilesystemInterface $filesystem
* @param string $path
*/
public function __construct(FilesystemInterface $filesystem = null, $path = null)
{
$this->path = $path;
$this->filesystem = $filesystem;
}
/**
* Check whether the entree is a directory.
*
* @return bool
*/
public function isDir()
{
return $this->getType() === 'dir';
}
/**
* Check whether the entree is a file.
*
* @return bool
*/
public function isFile()
{
return $this->getType() === 'file';
}
/**
* Retrieve the entree type (file|dir).
*
* @return string file or dir
*/
public function getType()
{
$metadata = $this->filesystem->getMetadata($this->path);
return $metadata['type'];
}
/**
* Set the Filesystem object.
*
* @param FilesystemInterface $filesystem
*
* @return $this
*/
public function setFilesystem(FilesystemInterface $filesystem)
{
$this->filesystem = $filesystem;
return $this;
}
/**
* Retrieve the Filesystem object.
*
* @return FilesystemInterface
*/
public function getFilesystem()
{
return $this->filesystem;
}
/**
* Set the entree path.
*
* @param string $path
*
* @return $this
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Retrieve the entree path.
*
* @return string path
*/
public function getPath()
{
return $this->path;
}
/**
* Plugins pass-through.
*
* @param string $method
* @param array $arguments
*
* @return mixed
*/
public function __call($method, array $arguments)
{
array_unshift($arguments, $this->path);
$callback = [$this->filesystem, $method];
try {
return call_user_func_array($callback, $arguments);
} catch (BadMethodCallException $e) {
throw new BadMethodCallException(
'Call to undefined method '
.get_called_class()
.'::'.$method
);
}
}
}

View File

@@ -0,0 +1,269 @@
<?php
namespace League\Flysystem;
use InvalidArgumentException;
use League\Flysystem\Plugin\PluggableTrait;
use League\Flysystem\Plugin\PluginNotFoundException;
use LogicException;
/**
* Class MountManager.
*
* Proxies methods to Filesystem (@see __call):
*
* @method AdapterInterface getAdapter($prefix)
* @method Config getConfig($prefix)
* @method bool has($path)
* @method bool write($path, $contents, array $config = [])
* @method bool writeStream($path, $resource, array $config = [])
* @method bool put($path, $contents, $config = [])
* @method bool putStream($path, $contents, $config = [])
* @method string readAndDelete($path)
* @method bool update($path, $contents, $config = [])
* @method bool updateStream($path, $resource, $config = [])
* @method string|false read($path)
* @method resource|false readStream($path)
* @method bool rename($path, $newpath)
* @method bool delete($path)
* @method bool deleteDir($dirname)
* @method bool createDir($dirname, $config = [])
* @method array listFiles($directory = '', $recursive = false)
* @method array listPaths($directory = '', $recursive = false)
* @method array getWithMetadata($path, array $metadata)
* @method string|false getMimetype($path)
* @method string|false getTimestamp($path)
* @method string|false getVisibility($path)
* @method int|false getSize($path);
* @method bool setVisibility($path, $visibility)
* @method array|false getMetadata($path)
* @method Handler get($path, Handler $handler = null)
* @method Filesystem flushCache()
* @method assertPresent($path)
* @method assertAbsent($path)
* @method Filesystem addPlugin(PluginInterface $plugin)
*/
class MountManager
{
use PluggableTrait;
/**
* @var array
*/
protected $filesystems = [];
/**
* Constructor.
*
* @param array $filesystems
*/
public function __construct(array $filesystems = [])
{
$this->mountFilesystems($filesystems);
}
/**
* Mount filesystems.
*
* @param array $filesystems [:prefix => Filesystem,]
*
* @return $this
*/
public function mountFilesystems(array $filesystems)
{
foreach ($filesystems as $prefix => $filesystem) {
$this->mountFilesystem($prefix, $filesystem);
}
return $this;
}
/**
* Mount filesystems.
*
* @param string $prefix
* @param FilesystemInterface $filesystem
*
* @return $this
*/
public function mountFilesystem($prefix, FilesystemInterface $filesystem)
{
if (! is_string($prefix)) {
throw new InvalidArgumentException(__METHOD__.' expects argument #1 to be a string.');
}
$this->filesystems[$prefix] = $filesystem;
return $this;
}
/**
* Get the filesystem with the corresponding prefix.
*
* @param string $prefix
*
* @throws LogicException
*
* @return FilesystemInterface
*/
public function getFilesystem($prefix)
{
if (! isset($this->filesystems[$prefix])) {
throw new LogicException('No filesystem mounted with prefix '.$prefix);
}
return $this->filesystems[$prefix];
}
/**
* Retrieve the prefix from an arguments array.
*
* @param array $arguments
*
* @return array [:prefix, :arguments]
*/
public function filterPrefix(array $arguments)
{
if (empty($arguments)) {
throw new LogicException('At least one argument needed');
}
$path = array_shift($arguments);
if (! is_string($path)) {
throw new InvalidArgumentException('First argument should be a string');
}
if (! preg_match('#^.+\:\/\/.*#', $path)) {
throw new InvalidArgumentException('No prefix detected in path: '.$path);
}
list($prefix, $path) = explode('://', $path, 2);
array_unshift($arguments, $path);
return [$prefix, $arguments];
}
/**
* @param string $directory
* @param bool $recursive
*
* @return array
*/
public function listContents($directory = '', $recursive = false)
{
list($prefix, $arguments) = $this->filterPrefix([$directory]);
$filesystem = $this->getFilesystem($prefix);
$directory = array_shift($arguments);
$result = $filesystem->listContents($directory, $recursive);
foreach ($result as &$file) {
$file['filesystem'] = $prefix;
}
return $result;
}
/**
* Call forwarder.
*
* @param string $method
* @param array $arguments
*
* @return mixed
*/
public function __call($method, $arguments)
{
list($prefix, $arguments) = $this->filterPrefix($arguments);
return $this->invokePluginOnFilesystem($method, $arguments, $prefix);
}
/**
* @param $from
* @param $to
*
* @return bool
*/
public function copy($from, $to)
{
list($prefixFrom, $arguments) = $this->filterPrefix([$from]);
$fsFrom = $this->getFilesystem($prefixFrom);
$buffer = call_user_func_array([$fsFrom, 'readStream'], $arguments);
if ($buffer === false) {
return false;
}
list($prefixTo, $arguments) = $this->filterPrefix([$to]);
$fsTo = $this->getFilesystem($prefixTo);
$result = call_user_func_array([$fsTo, 'writeStream'], array_merge($arguments, [$buffer]));
if (is_resource($buffer)) {
fclose($buffer);
}
return $result;
}
/**
* List with plugin adapter.
*
* @param array $keys
* @param string $directory
* @param bool $recursive
*/
public function listWith(array $keys = [], $directory = '', $recursive = false)
{
list($prefix, $arguments) = $this->filterPrefix([$directory]);
$directory = $arguments[0];
$arguments = [$keys, $directory, $recursive];
return $this->invokePluginOnFilesystem('listWith', $arguments, $prefix);
}
/**
* Move a file.
*
* @param $from
* @param $to
*
* @return bool
*/
public function move($from, $to)
{
$copied = $this->copy($from, $to);
if ($copied) {
return $this->delete($from);
}
return false;
}
/**
* Invoke a plugin on a filesystem mounted on a given prefix.
*
* @param $method
* @param $arguments
* @param $prefix
*
* @return mixed
*/
public function invokePluginOnFilesystem($method, $arguments, $prefix)
{
$filesystem = $this->getFilesystem($prefix);
try {
return $this->invokePlugin($method, $arguments, $filesystem);
} catch (PluginNotFoundException $e) {
// Let it pass, it's ok, don't panic.
}
$callback = [$filesystem, $method];
return call_user_func_array($callback, $arguments);
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace League\Flysystem;
use RuntimeException;
use SplFileInfo;
class NotSupportedException extends RuntimeException
{
/**
* Create a new exception for a link.
*
* @param SplFileInfo $file
*
* @return static
*/
public static function forLink(SplFileInfo $file)
{
$message = 'Links are not supported, encountered link at ';
return new static($message.$file->getPathname());
}
/**
* Create a new exception for a link.
*
* @param string $systemType
*
* @return static
*/
public static function forFtpSystemType($systemType)
{
$message = "The FTP system type '$systemType' is currently not supported.";
return new static($message);
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace League\Flysystem\Plugin;
use League\Flysystem\FilesystemInterface;
use League\Flysystem\PluginInterface;
abstract class AbstractPlugin implements PluginInterface
{
/**
* @var FilesystemInterface
*/
protected $filesystem;
/**
* Set the Filesystem object.
*
* @param FilesystemInterface $filesystem
*/
public function setFilesystem(FilesystemInterface $filesystem)
{
$this->filesystem = $filesystem;
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace League\Flysystem\Plugin;
class EmptyDir extends AbstractPlugin
{
/**
* Get the method name.
*
* @return string
*/
public function getMethod()
{
return 'emptyDir';
}
/**
* Empty a directory's contents.
*
* @param $dirname
*/
public function handle($dirname)
{
$listing = $this->filesystem->listContents($dirname, false);
foreach ($listing as $item) {
if ($item['type'] === 'dir') {
$this->filesystem->deleteDir($item['path']);
} else {
$this->filesystem->delete($item['path']);
}
}
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace League\Flysystem\Plugin;
use InvalidArgumentException;
class GetWithMetadata extends AbstractPlugin
{
/**
* Get the method name.
*
* @return string
*/
public function getMethod()
{
return 'getWithMetadata';
}
/**
* Get metadata for an object with required metadata.
*
* @param string $path path to file
* @param array $metadata metadata keys
*
* @throws InvalidArgumentException
*
* @return array metadata
*/
public function handle($path, array $metadata)
{
$object = $this->filesystem->getMetadata($path);
if (! $object) {
return false;
}
$keys = array_diff($metadata, array_keys($object));
foreach ($keys as $key) {
if (! method_exists($this->filesystem, $method = 'get'.ucfirst($key))) {
throw new InvalidArgumentException('Could not fetch metadata: '.$key);
}
$object[$key] = $this->filesystem->{$method}($path);
}
return $object;
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace League\Flysystem\Plugin;
class ListFiles extends AbstractPlugin
{
/**
* Get the method name.
*
* @return string
*/
public function getMethod()
{
return 'listFiles';
}
/**
* List all files in the directory.
*
* @param string $directory
* @param bool $recursive
*
* @return array
*/
public function handle($directory = '', $recursive = false)
{
$contents = $this->filesystem->listContents($directory, $recursive);
$filter = function ($object) {
return $object['type'] === 'file';
};
return array_values(array_filter($contents, $filter));
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace League\Flysystem\Plugin;
class ListPaths extends AbstractPlugin
{
/**
* Get the method name.
*
* @return string
*/
public function getMethod()
{
return 'listPaths';
}
/**
* List all paths.
*
* @param string $directory
* @param bool $recursive
*
* @return array paths
*/
public function handle($directory = '', $recursive = false)
{
$result = [];
$contents = $this->filesystem->listContents($directory, $recursive);
foreach ($contents as $object) {
$result[] = $object['path'];
}
return $result;
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace League\Flysystem\Plugin;
class ListWith extends AbstractPlugin
{
/**
* Get the method name.
*
* @return string
*/
public function getMethod()
{
return 'listWith';
}
/**
* List contents with metadata.
*
* @param array $keys
* @param string $directory
* @param bool $recursive
*
* @return array listing with metadata
*/
public function handle(array $keys = [], $directory = '', $recursive = false)
{
$contents = $this->filesystem->listContents($directory, $recursive);
foreach ($contents as $index => $object) {
if ($object['type'] === 'file') {
$missingKeys = array_diff($keys, array_keys($object));
$contents[$index] = array_reduce($missingKeys, [$this, 'getMetadataByName'], $object);
}
}
return $contents;
}
/**
* Get a meta-data value by key name.
*
* @param array $object
* @param $key
*
* @return array
*/
protected function getMetadataByName(array $object, $key)
{
$method = 'get'.ucfirst($key);
if (! method_exists($this->filesystem, $method)) {
throw new \InvalidArgumentException('Could not get meta-data for key: '.$key);
}
$object[$key] = $this->filesystem->{$method}($object['path']);
return $object;
}
}

View File

@@ -0,0 +1,92 @@
<?php
namespace League\Flysystem\Plugin;
use BadMethodCallException;
use League\Flysystem\FilesystemInterface;
use League\Flysystem\PluginInterface;
use LogicException;
trait PluggableTrait
{
/**
* @var array
*/
protected $plugins = [];
/**
* Register a plugin.
*
* @param PluginInterface $plugin
*
* @return $this
*/
public function addPlugin(PluginInterface $plugin)
{
$this->plugins[$plugin->getMethod()] = $plugin;
return $this;
}
/**
* Find a specific plugin.
*
* @param string $method
*
* @throws LogicException
*
* @return PluginInterface $plugin
*/
protected function findPlugin($method)
{
if (! isset($this->plugins[$method])) {
throw new PluginNotFoundException('Plugin not found for method: '.$method);
}
if (! method_exists($this->plugins[$method], 'handle')) {
throw new LogicException(get_class($this->plugins[$method]).' does not have a handle method.');
}
return $this->plugins[$method];
}
/**
* Invoke a plugin by method name.
*
* @param string $method
* @param array $arguments
*
* @return mixed
*/
protected function invokePlugin($method, array $arguments, FilesystemInterface $filesystem)
{
$plugin = $this->findPlugin($method);
$plugin->setFilesystem($filesystem);
$callback = [$plugin, 'handle'];
return call_user_func_array($callback, $arguments);
}
/**
* Plugins pass-through.
*
* @param string $method
* @param array $arguments
*
* @throws BadMethodCallException
*
* @return mixed
*/
public function __call($method, array $arguments)
{
try {
return $this->invokePlugin($method, $arguments, $this);
} catch (PluginNotFoundException $e) {
throw new BadMethodCallException(
'Call to undefined method '
.get_class($this)
.'::'.$method
);
}
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace League\Flysystem\Plugin;
use LogicException;
class PluginNotFoundException extends LogicException
{
// This exception doesn't require additional information.
}

View File

@@ -0,0 +1,20 @@
<?php
namespace League\Flysystem;
interface PluginInterface
{
/**
* Get the method name.
*
* @return string
*/
public function getMethod();
/**
* Set the Filesystem object.
*
* @param FilesystemInterface $filesystem
*/
public function setFilesystem(FilesystemInterface $filesystem);
}

View File

@@ -0,0 +1,88 @@
<?php
namespace League\Flysystem;
interface ReadInterface
{
/**
* Check whether a file exists.
*
* @param string $path
*
* @return array|bool|null
*/
public function has($path);
/**
* Read a file.
*
* @param string $path
*
* @return array|false
*/
public function read($path);
/**
* Read a file as a stream.
*
* @param string $path
*
* @return array|false
*/
public function readStream($path);
/**
* List contents of a directory.
*
* @param string $directory
* @param bool $recursive
*
* @return array
*/
public function listContents($directory = '', $recursive = false);
/**
* Get all the meta data of a file or directory.
*
* @param string $path
*
* @return array|false
*/
public function getMetadata($path);
/**
* Get all the meta data of a file or directory.
*
* @param string $path
*
* @return array|false
*/
public function getSize($path);
/**
* Get the mimetype of a file.
*
* @param string $path
*
* @return array|false
*/
public function getMimetype($path);
/**
* Get the timestamp of a file.
*
* @param string $path
*
* @return array|false
*/
public function getTimestamp($path);
/**
* Get the visibility of a file.
*
* @param string $path
*
* @return array|false
*/
public function getVisibility($path);
}

View File

@@ -0,0 +1,10 @@
<?php
namespace League\Flysystem;
use LogicException;
class RootViolationException extends LogicException
{
//
}

297
vendor/league/flysystem/src/Util.php vendored Normal file
View File

@@ -0,0 +1,297 @@
<?php
namespace League\Flysystem;
use League\Flysystem\Util\MimeType;
use LogicException;
class Util
{
/**
* Get normalized pathinfo.
*
* @param string $path
*
* @return array pathinfo
*/
public static function pathinfo($path)
{
$pathinfo = pathinfo($path) + compact('path');
$pathinfo['dirname'] = array_key_exists('dirname', $pathinfo)
? static::normalizeDirname($pathinfo['dirname'])
: '';
return $pathinfo;
}
/**
* Normalize a dirname return value.
*
* @param string $dirname
*
* @return string normalized dirname
*/
public static function normalizeDirname($dirname)
{
if ($dirname === '.') {
return '';
}
return $dirname;
}
/**
* Get a normalized dirname from a path.
*
* @param string $path
*
* @return string dirname
*/
public static function dirname($path)
{
return static::normalizeDirname(dirname($path));
}
/**
* Map result arrays.
*
* @param array $object
* @param array $map
*
* @return array mapped result
*/
public static function map(array $object, array $map)
{
$result = [];
foreach ($map as $from => $to) {
if (! isset($object[$from])) {
continue;
}
$result[$to] = $object[$from];
}
return $result;
}
/**
* Normalize path.
*
* @param string $path
*
* @throws LogicException
*
* @return string
*/
public static function normalizePath($path)
{
// Remove any kind of funky unicode whitespace
$normalized = preg_replace('#\p{C}+|^\./#u', '', $path);
$normalized = static::normalizeRelativePath($normalized);
if (preg_match('#/\.{2}|^\.{2}/|^\.{2}$#', $normalized)) {
throw new LogicException(
'Path is outside of the defined root, path: [' . $path . '], resolved: [' . $normalized . ']'
);
}
$normalized = preg_replace('#\\\{2,}#', '\\', trim($normalized, '\\'));
$normalized = preg_replace('#/{2,}#', '/', trim($normalized, '/'));
return $normalized;
}
/**
* Normalize relative directories in a path.
*
* @param string $path
*
* @return string
*/
public static function normalizeRelativePath($path)
{
// Path remove self referring paths ("/./").
$path = preg_replace('#/\.(?=/)|^\./|/\./?$#', '', $path);
// Regex for resolving relative paths
$regex = '#/*[^/\.]+/\.\.#Uu';
while (preg_match($regex, $path)) {
$path = preg_replace($regex, '', $path);
}
return $path;
}
/**
* Normalize prefix.
*
* @param string $prefix
* @param string $separator
*
* @return string normalized path
*/
public static function normalizePrefix($prefix, $separator)
{
return rtrim($prefix, $separator) . $separator;
}
/**
* Get content size.
*
* @param string $contents
*
* @return int content size
*/
public static function contentSize($contents)
{
return defined('MB_OVERLOAD_STRING') ? mb_strlen($contents, '8bit') : strlen($contents);
}
/**
* Guess MIME Type based on the path of the file and it's content.
*
* @param string $path
* @param string $content
*
* @return string|null MIME Type or NULL if no extension detected
*/
public static function guessMimeType($path, $content)
{
$mimeType = MimeType::detectByContent($content);
if (empty($mimeType) || $mimeType === 'text/plain') {
$extension = pathinfo($path, PATHINFO_EXTENSION);
if ($extension) {
$mimeType = MimeType::detectByFileExtension($extension) ?: 'text/plain';
}
}
return $mimeType;
}
/**
* Emulate directories.
*
* @param array $listing
*
* @return array listing with emulated directories
*/
public static function emulateDirectories(array $listing)
{
$directories = [];
$listedDirectories = [];
foreach ($listing as $object) {
list($directories, $listedDirectories) = static::emulateObjectDirectories(
$object,
$directories,
$listedDirectories
);
}
$directories = array_diff(array_unique($directories), array_unique($listedDirectories));
foreach ($directories as $directory) {
$listing[] = static::pathinfo($directory) + ['type' => 'dir'];
}
return $listing;
}
/**
* Ensure a Config instance.
*
* @param null|array|Config $config
*
* @return Config config instance
*
* @throw LogicException
*/
public static function ensureConfig($config)
{
if ($config === null) {
return new Config();
}
if ($config instanceof Config) {
return $config;
}
if (is_array($config)) {
return new Config($config);
}
throw new LogicException('A config should either be an array or a Flysystem\Config object.');
}
/**
* Rewind a stream.
*
* @param resource $resource
*/
public static function rewindStream($resource)
{
if (ftell($resource) !== 0 && static::isSeekableStream($resource)) {
rewind($resource);
}
}
public static function isSeekableStream($resource)
{
$metadata = stream_get_meta_data($resource);
return $metadata['seekable'];
}
/**
* Get the size of a stream.
*
* @param resource $resource
*
* @return int stream size
*/
public static function getStreamSize($resource)
{
$stat = fstat($resource);
return $stat['size'];
}
/**
* Emulate the directories of a single object.
*
* @param array $object
* @param array $directories
* @param array $listedDirectories
*
* @return array
*/
protected static function emulateObjectDirectories(array $object, array $directories, array $listedDirectories)
{
if ($object['type'] === 'dir') {
$listedDirectories[] = $object['path'];
}
if (empty($object['dirname'])) {
return [$directories, $listedDirectories];
}
$parent = $object['dirname'];
while (! empty($parent) && ! in_array($parent, $directories)) {
$directories[] = $parent;
$parent = static::dirname($parent);
}
if (isset($object['type']) && $object['type'] === 'dir') {
$listedDirectories[] = $object['path'];
return [$directories, $listedDirectories];
}
return [$directories, $listedDirectories];
}
}

View File

@@ -0,0 +1,119 @@
<?php
namespace League\Flysystem\Util;
use League\Flysystem\Util;
/**
* @internal
*/
class ContentListingFormatter
{
/**
* @var string
*/
private $directory;
/**
* @var bool
*/
private $recursive;
/**
* @param string $directory
* @param bool $recursive
*/
public function __construct($directory, $recursive)
{
$this->directory = $directory;
$this->recursive = $recursive;
}
/**
* Format contents listing.
*
* @param array $listing
*
* @return array
*/
public function formatListing(array $listing)
{
$listing = array_values(
array_map(
[$this, 'addPathInfo'],
array_filter($listing, [$this, 'isEntryOutOfScope'])
)
);
return $this->sortListing($listing);
}
private function addPathInfo(array $entry)
{
return $entry + Util::pathinfo($entry['path']);
}
/**
* Determine if the entry is out of scope.
*
* @param array $entry
*
* @return bool
*/
private function isEntryOutOfScope(array $entry)
{
if (empty($entry['path']) && $entry['path'] !== '0') {
return false;
}
if ($this->recursive) {
return $this->residesInDirectory($entry);
}
return $this->isDirectChild($entry);
}
/**
* Check if the entry resides within the parent directory.
*
* @param $entry
*
* @return bool
*/
private function residesInDirectory(array $entry)
{
if ($this->directory === '') {
return true;
}
return strpos($entry['path'], $this->directory . '/') === 0;
}
/**
* Check if the entry is a direct child of the directory.
*
* @param $entry
*
* @return bool
*/
private function isDirectChild(array $entry)
{
return Util::dirname($entry['path']) === $this->directory;
}
/**
* @param array $listing
*
* @return array
*/
private function sortListing(array $listing)
{
usort(
$listing,
function ($a, $b) {
return strcasecmp($a['path'], $b['path']);
}
);
return $listing;
}
}

View File

@@ -0,0 +1,198 @@
<?php
namespace League\Flysystem\Util;
use Finfo;
/**
* @internal
*/
class MimeType
{
/**
* Detects MIME Type based on given content.
*
* @param string $content
*
* @return string|null MIME Type or NULL if no mime type detected
*/
public static function detectByContent($content)
{
if (! class_exists('Finfo')) {
return;
}
$finfo = new Finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->buffer($content);
return $mimeType ?: null;
}
/**
* Detects MIME Type based on file extension.
*
* @param string $extension
*
* @return string|null MIME Type or NULL if no extension detected
*/
public static function detectByFileExtension($extension)
{
static $extensionToMimeTypeMap;
if (! $extensionToMimeTypeMap) {
$extensionToMimeTypeMap = static::getExtensionToMimeTypeMap();
}
if (isset($extensionToMimeTypeMap[$extension])) {
return $extensionToMimeTypeMap[$extension];
}
}
/**
* @return array Map of file extension to MIME Type
*/
public static function getExtensionToMimeTypeMap()
{
return [
'hqx' => 'application/mac-binhex40',
'cpt' => 'application/mac-compactpro',
'csv' => 'text/x-comma-separated-values',
'bin' => 'application/octet-stream',
'dms' => 'application/octet-stream',
'lha' => 'application/octet-stream',
'lzh' => 'application/octet-stream',
'exe' => 'application/octet-stream',
'class' => 'application/octet-stream',
'psd' => 'application/x-photoshop',
'so' => 'application/octet-stream',
'sea' => 'application/octet-stream',
'dll' => 'application/octet-stream',
'oda' => 'application/oda',
'pdf' => 'application/pdf',
'ai' => 'application/pdf',
'eps' => 'application/postscript',
'ps' => 'application/postscript',
'smi' => 'application/smil',
'smil' => 'application/smil',
'mif' => 'application/vnd.mif',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/powerpoint',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'wbxml' => 'application/wbxml',
'wmlc' => 'application/wmlc',
'dcr' => 'application/x-director',
'dir' => 'application/x-director',
'dxr' => 'application/x-director',
'dvi' => 'application/x-dvi',
'gtar' => 'application/x-gtar',
'gz' => 'application/x-gzip',
'gzip' => 'application/x-gzip',
'php' => 'application/x-httpd-php',
'php4' => 'application/x-httpd-php',
'php3' => 'application/x-httpd-php',
'phtml' => 'application/x-httpd-php',
'phps' => 'application/x-httpd-php-source',
'js' => 'application/javascript',
'swf' => 'application/x-shockwave-flash',
'sit' => 'application/x-stuffit',
'tar' => 'application/x-tar',
'tgz' => 'application/x-tar',
'z' => 'application/x-compress',
'xhtml' => 'application/xhtml+xml',
'xht' => 'application/xhtml+xml',
'zip' => 'application/x-zip',
'rar' => 'application/x-rar',
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mpga' => 'audio/mpeg',
'mp2' => 'audio/mpeg',
'mp3' => 'audio/mpeg',
'aif' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff',
'aifc' => 'audio/x-aiff',
'ram' => 'audio/x-pn-realaudio',
'rm' => 'audio/x-pn-realaudio',
'rpm' => 'audio/x-pn-realaudio-plugin',
'ra' => 'audio/x-realaudio',
'rv' => 'video/vnd.rn-realvideo',
'wav' => 'audio/x-wav',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'bmp' => 'image/bmp',
'tiff' => 'image/tiff',
'tif' => 'image/tiff',
'css' => 'text/css',
'html' => 'text/html',
'htm' => 'text/html',
'shtml' => 'text/html',
'txt' => 'text/plain',
'text' => 'text/plain',
'log' => 'text/plain',
'rtx' => 'text/richtext',
'rtf' => 'text/rtf',
'xml' => 'application/xml',
'xsl' => 'application/xml',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpe' => 'video/mpeg',
'qt' => 'video/quicktime',
'mov' => 'video/quicktime',
'avi' => 'video/x-msvideo',
'movie' => 'video/x-sgi-movie',
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'dot' => 'application/msword',
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'word' => 'application/msword',
'xl' => 'application/excel',
'eml' => 'message/rfc822',
'json' => 'application/json',
'pem' => 'application/x-x509-user-cert',
'p10' => 'application/x-pkcs10',
'p12' => 'application/x-pkcs12',
'p7a' => 'application/x-pkcs7-signature',
'p7c' => 'application/pkcs7-mime',
'p7m' => 'application/pkcs7-mime',
'p7r' => 'application/x-pkcs7-certreqresp',
'p7s' => 'application/pkcs7-signature',
'crt' => 'application/x-x509-ca-cert',
'crl' => 'application/pkix-crl',
'der' => 'application/x-x509-ca-cert',
'kdb' => 'application/octet-stream',
'pgp' => 'application/pgp',
'gpg' => 'application/gpg-keys',
'sst' => 'application/octet-stream',
'csr' => 'application/octet-stream',
'rsa' => 'application/x-pkcs7',
'cer' => 'application/pkix-cert',
'3g2' => 'video/3gpp2',
'3gp' => 'video/3gp',
'mp4' => 'video/mp4',
'm4a' => 'audio/x-m4a',
'f4v' => 'video/mp4',
'webm' => 'video/webm',
'aac' => 'audio/x-acc',
'm4u' => 'application/vnd.mpegurl',
'm3u' => 'text/plain',
'xspf' => 'application/xspf+xml',
'vlc' => 'application/videolan',
'wmv' => 'video/x-ms-wmv',
'au' => 'audio/x-au',
'ac3' => 'audio/ac3',
'flac' => 'audio/x-flac',
'ogg' => 'audio/ogg',
'kmz' => 'application/vnd.google-earth.kmz',
'kml' => 'application/vnd.google-earth.kml+xml',
'ics' => 'text/calendar',
'zsh' => 'text/x-scriptzsh',
'7zip' => 'application/x-7z-compressed',
'cdr' => 'application/cdr',
'wma' => 'audio/x-ms-wma',
'jar' => 'application/java-archive',
];
}
}