Initial xentral_oss_20.3.c9ffacf
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Adapter;
|
||||
|
||||
interface AdapterInterface extends ReaderAdapterInterface
|
||||
{
|
||||
/**
|
||||
* Creates a new file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $contents
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function write($path, $contents, array $config = []);
|
||||
|
||||
/**
|
||||
* Creates a new file using a stream
|
||||
*
|
||||
* @param string $path
|
||||
* @param resource $resource
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function writeStream($path, $resource, array $config = []);
|
||||
|
||||
/**
|
||||
* Updates an existing file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $contents
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function update($path, $contents, array $config = []);
|
||||
|
||||
/**
|
||||
* Updates an existing file using a stream
|
||||
*
|
||||
* @param string $path
|
||||
* @param resource $resource
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function updateStream($path, $resource, array $config = []);
|
||||
|
||||
/**
|
||||
* Renames a file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $newpath
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function rename($path, $newpath);
|
||||
|
||||
/**
|
||||
* Copies a file to new location
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $newpath
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function copy($path, $newpath);
|
||||
|
||||
/**
|
||||
* Deletes a single file
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($path);
|
||||
|
||||
/**
|
||||
* Deletes a directory and its contents
|
||||
*
|
||||
* @param string $directory
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteDir($directory);
|
||||
|
||||
/**
|
||||
* @param string $directory
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createDir($directory, array $config = []);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Adapter;
|
||||
|
||||
use Xentral\Components\Filesystem\Exception\InvalidArgumentException;
|
||||
|
||||
final class FtpConfig
|
||||
{
|
||||
/** @var string $hostname */
|
||||
private $hostname;
|
||||
|
||||
/** @var string $username */
|
||||
private $username;
|
||||
|
||||
/** @var string $password */
|
||||
private $password;
|
||||
|
||||
/** @var string $rootDir */
|
||||
private $rootDir;
|
||||
|
||||
/** @var int $port */
|
||||
private $port;
|
||||
|
||||
/** @var int $timeout */
|
||||
private $timeout;
|
||||
|
||||
/** @var bool $passive */
|
||||
private $passive;
|
||||
|
||||
/** @var bool $ssl */
|
||||
private $ssl;
|
||||
|
||||
/**
|
||||
* @param string $hostname
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $rootDir
|
||||
* @param int $port
|
||||
* @param int $timeout
|
||||
* @param bool $passive
|
||||
* @param bool $ssl
|
||||
*/
|
||||
public function __construct(
|
||||
$hostname,
|
||||
$username,
|
||||
$password,
|
||||
$rootDir = '/',
|
||||
$port = 21,
|
||||
$timeout = 30,
|
||||
$passive = true,
|
||||
$ssl = false
|
||||
) {
|
||||
if (empty($hostname)) {
|
||||
throw new InvalidArgumentException('Hostname is empty.');
|
||||
}
|
||||
if (empty($username)) {
|
||||
throw new InvalidArgumentException('Username is empty.');
|
||||
}
|
||||
if (empty($password)) {
|
||||
throw new InvalidArgumentException('Password is empty.');
|
||||
}
|
||||
if (empty($rootDir)) {
|
||||
throw new InvalidArgumentException('Root dir is empty.');
|
||||
}
|
||||
|
||||
$this->hostname = (string)$hostname;
|
||||
$this->username = (string)$username;
|
||||
$this->password = (string)$password;
|
||||
$this->rootDir = (string)$rootDir;
|
||||
$this->port = (int)$port;
|
||||
$this->timeout = (int)$timeout;
|
||||
$this->passive = (bool)$passive;
|
||||
$this->ssl = (bool)$ssl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'host' => $this->hostname,
|
||||
'username' => $this->username,
|
||||
'password' => $this->password,
|
||||
'root' => $this->rootDir,
|
||||
'port' => $this->port,
|
||||
'timeout' => $this->timeout,
|
||||
'passive' => $this->passive,
|
||||
'ssl' => $this->ssl,
|
||||
'recurseManually' => true,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getHostname()
|
||||
{
|
||||
return $this->hostname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUsername()
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null
|
||||
*/
|
||||
public function getRootDir()
|
||||
{
|
||||
return $this->rootDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPort()
|
||||
{
|
||||
return $this->port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTimeout()
|
||||
{
|
||||
return $this->timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isPassive()
|
||||
{
|
||||
return $this->passive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSsl()
|
||||
{
|
||||
return $this->ssl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Adapter;
|
||||
|
||||
use League\Flysystem\AdapterInterface as LeagueAdapterInterface;
|
||||
use League\Flysystem\Config as LeagueConfig;
|
||||
use League\Flysystem\Util;
|
||||
use League\Flysystem\Util\ContentListingFormatter;
|
||||
use Xentral\Components\Filesystem\PathInfo;
|
||||
|
||||
final class LeagueAdapterWrapper implements AdapterInterface
|
||||
{
|
||||
/** @var LeagueAdapterInterface $league */
|
||||
private $league;
|
||||
|
||||
/** @var bool $caseSensitive */
|
||||
private $caseSensitive = true;
|
||||
|
||||
/**
|
||||
* @param LeagueAdapterInterface $league
|
||||
*/
|
||||
public function __construct(LeagueAdapterInterface $league)
|
||||
{
|
||||
$this->league = $league;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($path)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
return (bool)$this->league->has($path) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return PathInfo|false
|
||||
*/
|
||||
public function getInfo($path)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
$metainfo = $this->league->getMetadata($path);
|
||||
if (!$metainfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$directory = Util::dirname($path);
|
||||
$metainfo['path'] = $path;
|
||||
|
||||
$formatter = new ContentListingFormatter($directory, false, $this->caseSensitive);
|
||||
$contents = $formatter->formatListing([$metainfo]);
|
||||
if (count($contents) !== 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return new PathInfo($contents[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function read($path)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
$meta = $this->league->getMetadata($path);
|
||||
if ($meta['type'] === self::TYPE_DIR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$result = $this->league->read($path);
|
||||
if (!$result || !isset($result['contents'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $result['contents'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return resource|false
|
||||
*/
|
||||
public function readStream($path)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
$meta = $this->league->getMetadata($path);
|
||||
if ($meta['type'] === self::TYPE_DIR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $this->league->readStream($path);
|
||||
if (!$result || !isset($result['stream'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $result['stream'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listContents($directory = '', $recursive = false)
|
||||
{
|
||||
$directory = $this->normalizePath($directory);
|
||||
$contents = $this->getLeagueAdapter()->listContents($directory, $recursive);
|
||||
$formatter = new ContentListingFormatter($directory, $recursive, $this->caseSensitive);
|
||||
|
||||
return $formatter->formatListing($contents);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public function getMetadata($path)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
return $this->league->getMetadata($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function getType($path)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
$meta = $this->league->getMetadata($path);
|
||||
if ($meta === false || !isset($meta['type'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $meta['type'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function getSize($path)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
$meta = $this->league->getSize($path);
|
||||
if ($meta === false || !isset($meta['size'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (int)$meta['size'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function getTimestamp($path)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
$meta = $this->league->getTimestamp($path);
|
||||
if ($meta === false || !isset($meta['timestamp'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (int)$meta['timestamp'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function getMimetype($path)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
$meta = $this->league->getMimetype($path);
|
||||
if ($meta === false || !isset($meta['mimetype'])) {
|
||||
return false;
|
||||
}
|
||||
if ($meta['type'] === 'dir') {
|
||||
return 'directory';
|
||||
}
|
||||
|
||||
return $meta['mimetype'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $contents
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function write($path, $contents, array $config = [])
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
return $this->league->write($path, $contents, new LeagueConfig($config)) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new file using a stream
|
||||
*
|
||||
* @param string $path
|
||||
* @param resource $resource
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function writeStream($path, $resource, array $config = [])
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
return $this->league->writeStream($path, $resource, new LeagueConfig($config)) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $contents
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function update($path, $contents, array $config = [])
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
return $this->league->update($path, $contents, new LeagueConfig($config)) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing file using a stream
|
||||
*
|
||||
* @param string $path
|
||||
* @param resource $resource
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function updateStream($path, $resource, array $config = [])
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
return $this->league->updateStream($path, $resource, new LeagueConfig($config)) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames a file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $newpath
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function rename($path, $newpath)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
$newpath = $this->normalizePath($newpath);
|
||||
|
||||
return $this->league->rename($path, $newpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a file to new location
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $newpath
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function copy($path, $newpath)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
$newpath = $this->normalizePath($newpath);
|
||||
|
||||
return $this->league->copy($path, $newpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a single file
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($path)
|
||||
{
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
return $this->league->delete($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a directory and its contents
|
||||
*
|
||||
* @param string $directory
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteDir($directory)
|
||||
{
|
||||
$directory = $this->normalizePath($directory);
|
||||
|
||||
return $this->league->deleteDir($directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $directory
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createDir($directory, array $config = [])
|
||||
{
|
||||
$directory = $this->normalizePath($directory);
|
||||
|
||||
return $this->league->createDir($directory, new LeagueConfig($config)) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LeagueAdapterInterface
|
||||
*/
|
||||
public function getLeagueAdapter()
|
||||
{
|
||||
return $this->league;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function normalizePath($path)
|
||||
{
|
||||
return Util::normalizePath($path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Adapter;
|
||||
|
||||
use Xentral\Components\Filesystem\PathInfo;
|
||||
|
||||
interface ReaderAdapterInterface
|
||||
{
|
||||
const TYPE_DIR = 'dir';
|
||||
const TYPE_FILE = 'file';
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($path);
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return PathInfo|false
|
||||
*/
|
||||
public function getInfo($path);
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function read($path);
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return resource|false
|
||||
*/
|
||||
public function readStream($path);
|
||||
|
||||
/**
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listContents($directory = '', $recursive = false);
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return string|false [dir|file]
|
||||
*/
|
||||
public function getType($path);
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public function getMetadata($path);
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function getSize($path);
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function getTimestamp($path);
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function getMimetype($path);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem;
|
||||
|
||||
use Xentral\Core\DependencyInjection\ContainerInterface;
|
||||
|
||||
final class Bootstrap
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function registerServices()
|
||||
{
|
||||
return [
|
||||
'FilesystemFactory' => 'onInitFilesystemFactory',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return FilesystemFactory
|
||||
*/
|
||||
public static function onInitFilesystemFactory(ContainerInterface $container)
|
||||
{
|
||||
return new FilesystemFactory($container->get('Database'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class DirNotFoundException extends RuntimeException implements FilesystemExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class FileExistsException extends RuntimeException implements FilesystemExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class FileNotFoundException extends RuntimeException implements FilesystemExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class FilesystemException extends RuntimeException implements FilesystemExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Exception;
|
||||
|
||||
use Xentral\Core\Exception\ComponentExceptionInterface;
|
||||
|
||||
interface FilesystemExceptionInterface extends ComponentExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Exception;
|
||||
|
||||
use InvalidArgumentException as SplInvalidArgumentException;
|
||||
|
||||
class InvalidArgumentException extends SplInvalidArgumentException implements FilesystemExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Exception;
|
||||
|
||||
use LogicException;
|
||||
|
||||
class RootViolationException extends LogicException implements FilesystemExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem;
|
||||
|
||||
use Xentral\Components\Filesystem\Adapter\AdapterInterface;
|
||||
use Xentral\Components\Filesystem\Exception\DirNotFoundException;
|
||||
use Xentral\Components\Filesystem\Exception\FileExistsException;
|
||||
use Xentral\Components\Filesystem\Exception\FileNotFoundException;
|
||||
use Xentral\Components\Filesystem\Exception\InvalidArgumentException;
|
||||
use Xentral\Components\Filesystem\Exception\RootViolationException;
|
||||
|
||||
final class Filesystem implements FilesystemInterface
|
||||
{
|
||||
/** @var AdapterInterface $adapter */
|
||||
private $adapter;
|
||||
|
||||
/**
|
||||
* @param AdapterInterface $adapter
|
||||
*/
|
||||
public function __construct(AdapterInterface $adapter)
|
||||
{
|
||||
$this->adapter = $adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if file or directory exists
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($path)
|
||||
{
|
||||
return $this->adapter->has($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return PathInfo|false
|
||||
*/
|
||||
public function getInfo($path)
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
throw new FileNotFoundException(sprintf('File "%s" not found.', $path));
|
||||
}
|
||||
|
||||
return $this->adapter->getInfo($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* List directory contents
|
||||
*
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array|PathInfo[]
|
||||
*/
|
||||
public function listContents($directory = '', $recursive = false)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
$contents = $this->adapter->listContents($directory, $recursive);
|
||||
foreach ($contents as $metainfo) {
|
||||
$result[] = PathInfo::fromMeta($metainfo);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists only directories
|
||||
*
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array|PathInfo[]
|
||||
*/
|
||||
public function listDirs($directory = '', $recursive = false)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
$contents = $this->adapter->listContents($directory, $recursive);
|
||||
foreach ($contents as $metainfo) {
|
||||
if ($metainfo['type'] === 'dir') {
|
||||
$result[] = PathInfo::fromMeta($metainfo);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists only files
|
||||
*
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array|PathInfo[]
|
||||
*/
|
||||
public function listFiles($directory = '', $recursive = false)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
$contents = $this->adapter->listContents($directory, $recursive);
|
||||
foreach ($contents as $metainfo) {
|
||||
if ($metainfo['type'] === 'file') {
|
||||
$result[] = PathInfo::fromMeta($metainfo);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* List only paths as strings
|
||||
*
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array|string[]
|
||||
*/
|
||||
public function listPaths($directory = '', $recursive = false)
|
||||
{
|
||||
$contents = $this->adapter->listContents($directory, $recursive);
|
||||
|
||||
return array_column($contents, 'path');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return string [dir|file]
|
||||
*/
|
||||
public function getType($path)
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
throw new FileNotFoundException(sprintf('File "%s" not found.', $path));
|
||||
}
|
||||
|
||||
return $this->adapter->getType($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filesize
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function getSize($path)
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
throw new FileNotFoundException(sprintf('File "%s" not found.', $path));
|
||||
}
|
||||
|
||||
return $this->adapter->getSize($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the timestamp from last update
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function getTimestamp($path)
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
throw new FileNotFoundException(sprintf('File "%s" not found.', $path));
|
||||
}
|
||||
|
||||
return $this->adapter->getTimestamp($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function getMimetype($path)
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
throw new FileNotFoundException(sprintf('File "%s" not found.', $path));
|
||||
}
|
||||
|
||||
return $this->adapter->getMimetype($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read file content
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function read($path)
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
throw new FileNotFoundException(sprintf('File "%s" not found.', $path));
|
||||
}
|
||||
|
||||
return $this->adapter->read($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read file content
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return resource|false
|
||||
*/
|
||||
public function readStream($path)
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
throw new FileNotFoundException(sprintf('File "%s" not found.', $path));
|
||||
}
|
||||
|
||||
return $this->adapter->readStream($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes to a new file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $contents
|
||||
* @param array $config
|
||||
*
|
||||
* @throws FileExistsException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function write($path, $contents, array $config = [])
|
||||
{
|
||||
if ($this->has($path)) {
|
||||
throw new FileExistsException(sprintf('File "%s" exists already.', $path));
|
||||
}
|
||||
|
||||
return $this->adapter->write($path, $contents, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes to a new file
|
||||
*
|
||||
* @param string $path
|
||||
* @param resource $resource
|
||||
* @param array $config
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @throws FileExistsException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function writeStream($path, $resource, array $config = [])
|
||||
{
|
||||
if ($this->has($path)) {
|
||||
throw new FileExistsException(sprintf('File "%s" exists already.', $path));
|
||||
}
|
||||
if (!is_resource($resource)) {
|
||||
throw new InvalidArgumentException('Second parameter must be a resource.');
|
||||
}
|
||||
|
||||
return $this->adapter->writeStream($path, $resource, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file or updates the file contents
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $contents
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function put($path, $contents, array $config = [])
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
return $this->adapter->write($path, $contents, $config);
|
||||
}
|
||||
|
||||
return $this->adapter->update($path, $contents, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file or updates the file contents
|
||||
*
|
||||
* @param string $path
|
||||
* @param resource $resource
|
||||
* @param array $config
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function putStream($path, $resource, array $config = [])
|
||||
{
|
||||
if (!is_resource($resource)) {
|
||||
throw new InvalidArgumentException('Second parameter must be a resource.');
|
||||
}
|
||||
|
||||
if (!$this->has($path)) {
|
||||
return $this->adapter->writeStream($path, $resource, $config);
|
||||
}
|
||||
|
||||
return $this->adapter->updateStream($path, $resource, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames a file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $newpath
|
||||
*
|
||||
* @throws FileExistsException
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function rename($path, $newpath)
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
throw new FileNotFoundException(sprintf('File "%s" not found.', $path));
|
||||
}
|
||||
if ($this->has($newpath)) {
|
||||
throw new FileExistsException(sprintf('File "%s" exists already.', $newpath));
|
||||
}
|
||||
|
||||
return $this->adapter->rename($path, $newpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a file to new location
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $newpath
|
||||
*
|
||||
* @throws FileExistsException
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function copy($path, $newpath)
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
throw new FileNotFoundException(sprintf('File "%s" not found.', $path));
|
||||
}
|
||||
if ($this->has($newpath)) {
|
||||
throw new FileExistsException(sprintf('File "%s" exists already.', $newpath));
|
||||
}
|
||||
|
||||
return $this->adapter->copy($path, $newpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a single file
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($path)
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
throw new FileNotFoundException(sprintf('File "%s" not found.', $path));
|
||||
}
|
||||
|
||||
return $this->adapter->delete($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a directory and all its contents
|
||||
*
|
||||
* @param string $dirname
|
||||
*
|
||||
* @throws DirNotFoundException
|
||||
* @throws RootViolationException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteDir($dirname)
|
||||
{
|
||||
$info = $this->adapter->getInfo($dirname);
|
||||
if (!$info) {
|
||||
throw new DirNotFoundException(sprintf('Directory "%s" not found.', $dirname));
|
||||
}
|
||||
if ($info->getPath() === '') {
|
||||
throw new RootViolationException('Root directory can not be deleted.');
|
||||
}
|
||||
|
||||
return $this->adapter->deleteDir($dirname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a directory
|
||||
*
|
||||
* @param string $dirname
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createDir($dirname, array $config = [])
|
||||
{
|
||||
return $this->adapter->createDir($dirname, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AdapterInterface
|
||||
*/
|
||||
public function getAdapter()
|
||||
{
|
||||
return $this->adapter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem;
|
||||
|
||||
use Exception;
|
||||
use Xentral\Components\Database\Database;
|
||||
use Xentral\Components\Filesystem\Adapter\FtpConfig;
|
||||
use Xentral\Components\Filesystem\Adapter\LeagueAdapterWrapper;
|
||||
use Xentral\Components\Filesystem\Exception\FilesystemException;
|
||||
use Xentral\Components\Filesystem\Exception\InvalidArgumentException;
|
||||
use Xentral\Components\Filesystem\Flysystem\FtpAdapterDecorator;
|
||||
use Xentral\Components\Filesystem\Flysystem\LocalAdapterDecorator;
|
||||
|
||||
final class FilesystemFactory
|
||||
{
|
||||
/** @var Database $db */
|
||||
private $db;
|
||||
|
||||
/**
|
||||
* @param Database $database
|
||||
*/
|
||||
public function __construct(Database $database)
|
||||
{
|
||||
$this->db = $database;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $root Absolute path
|
||||
* @param array $config
|
||||
*
|
||||
* @return FilesystemInterface
|
||||
*/
|
||||
public function createLocal($root, array $config = [])
|
||||
{
|
||||
try {
|
||||
$writeFlags = isset($config['write_flags']) ? $config['write_flags'] : LOCK_EX;
|
||||
$linkHandling = isset($config['link_handling']) ? $config['link_handling'] : LocalAdapterDecorator::SKIP_LINKS;
|
||||
$permissions = isset($config['permissions']) ? $config['permissions'] : [];
|
||||
|
||||
$leagueLocalAdapter = new LocalAdapterDecorator($root, $writeFlags, $linkHandling, $permissions);
|
||||
$leagueAdapterWrapper = new LeagueAdapterWrapper($leagueLocalAdapter);
|
||||
|
||||
return new Filesystem($leagueAdapterWrapper);
|
||||
//
|
||||
} catch (Exception $e) {
|
||||
throw new FilesystemException($e->getMessage(), (int)$e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FtpConfig $config
|
||||
*
|
||||
* @return FilesystemInterface
|
||||
*/
|
||||
public function createFtp(FtpConfig $config)
|
||||
{
|
||||
try {
|
||||
$leagueFtpAdapter = new FtpAdapterDecorator($config->toArray());
|
||||
$leagueAdapterWrapper = new LeagueAdapterWrapper($leagueFtpAdapter);
|
||||
|
||||
return new Filesystem($leagueAdapterWrapper);
|
||||
//
|
||||
} catch (Exception $e) {
|
||||
throw new FilesystemException($e->getMessage(), (int)$e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FilesystemInterface $filesystem
|
||||
* @param int $syncId
|
||||
*
|
||||
* @return FilesystemSyncCache
|
||||
*/
|
||||
public function createSync(FilesystemInterface $filesystem, $syncId)
|
||||
{
|
||||
try {
|
||||
if (get_class($filesystem) === FilesystemSyncCache::class) {
|
||||
throw new InvalidArgumentException('FilesystemSyncWrapper can not wrap it self.');
|
||||
}
|
||||
|
||||
return new FilesystemSyncCache($this->db, $filesystem, $syncId);
|
||||
//
|
||||
} catch (Exception $e) {
|
||||
throw new FilesystemException($e->getMessage(), (int)$e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem;
|
||||
|
||||
use Xentral\Components\Filesystem\Adapter\AdapterInterface;
|
||||
use Xentral\Components\Filesystem\Exception\DirNotFoundException;
|
||||
use Xentral\Components\Filesystem\Exception\FileExistsException;
|
||||
use Xentral\Components\Filesystem\Exception\FileNotFoundException;
|
||||
use Xentral\Components\Filesystem\Exception\InvalidArgumentException;
|
||||
use Xentral\Components\Filesystem\Exception\RootViolationException;
|
||||
|
||||
interface FilesystemInterface
|
||||
{
|
||||
/**
|
||||
* Checks if file or directory exists
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($path);
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return PathInfo|false
|
||||
*/
|
||||
public function getInfo($path);
|
||||
|
||||
/**
|
||||
* List directory contents
|
||||
*
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array|PathInfo[]
|
||||
*/
|
||||
public function listContents($directory = '', $recursive = false);
|
||||
|
||||
// public function filterContents(array $filter = [], $directory = '', $recursive = false); // @todo
|
||||
//
|
||||
// // @todo ExtendedLocal
|
||||
// public function isReadable();
|
||||
// public function isWriteable();
|
||||
// public function getOwner();
|
||||
// public function getGroup();
|
||||
|
||||
/**
|
||||
* Lists only directories
|
||||
*
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array|PathInfo[]
|
||||
*/
|
||||
public function listDirs($directory = '', $recursive = false);
|
||||
|
||||
/**
|
||||
* Lists only files
|
||||
*
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array|PathInfo[]
|
||||
*/
|
||||
public function listFiles($directory = '', $recursive = false);
|
||||
|
||||
/**
|
||||
* List only paths as strings
|
||||
*
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array|string[]
|
||||
*/
|
||||
public function listPaths($directory = '', $recursive = false);
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return string [dir|file]
|
||||
*/
|
||||
public function getType($path);
|
||||
|
||||
/**
|
||||
* Gets the filesize
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function getSize($path);
|
||||
|
||||
/**
|
||||
* Gets the timestamp from last update
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function getTimestamp($path);
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function getMimetype($path);
|
||||
|
||||
/**
|
||||
* Read file content
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function read($path);
|
||||
|
||||
/**
|
||||
* Read file content
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return resource|false
|
||||
*/
|
||||
public function readStream($path);
|
||||
|
||||
/**
|
||||
* Writes to a new file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $contents
|
||||
* @param array $config
|
||||
*
|
||||
* @throws FileExistsException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function write($path, $contents, array $config = []);
|
||||
|
||||
/**
|
||||
* Writes to a new file
|
||||
*
|
||||
* @param string $path
|
||||
* @param resource $resource
|
||||
* @param array $config
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @throws FileExistsException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function writeStream($path, $resource, array $config = []);
|
||||
|
||||
/**
|
||||
* Creates a file or updates the file contents
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $contents
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function put($path, $contents, array $config = []);
|
||||
|
||||
/**
|
||||
* Creates a file or updates the file contents
|
||||
*
|
||||
* @param string $path
|
||||
* @param resource $resource
|
||||
* @param array $config
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function putStream($path, $resource, array $config = []);
|
||||
|
||||
/**
|
||||
* Renames a file
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $newpath
|
||||
*
|
||||
* @throws FileExistsException
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function rename($path, $newpath);
|
||||
|
||||
/**
|
||||
* Copies a file to new location
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $newpath
|
||||
*
|
||||
* @throws FileExistsException
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function copy($path, $newpath);
|
||||
|
||||
/**
|
||||
* Deletes a single file
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($path);
|
||||
|
||||
/**
|
||||
* Deletes a directory and all its contents
|
||||
*
|
||||
* @param string $dirname
|
||||
*
|
||||
* @throws DirNotFoundException
|
||||
* @throws RootViolationException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteDir($dirname);
|
||||
|
||||
/**
|
||||
* Creates a directory
|
||||
*
|
||||
* @param string $dirname
|
||||
* @param array $config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createDir($dirname, array $config = []);
|
||||
|
||||
/**
|
||||
* @return AdapterInterface
|
||||
*/
|
||||
public function getAdapter();
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem;
|
||||
|
||||
use Xentral\Components\Database\Database;
|
||||
use Xentral\Components\Filesystem\Exception\FileNotFoundException;
|
||||
use Xentral\Components\Filesystem\Exception\FilesystemException;
|
||||
use Xentral\Components\Filesystem\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @todo Datenbank anlegen
|
||||
*/
|
||||
final class FilesystemSyncCache implements FilesystemInterface
|
||||
{
|
||||
/** @var Database $db */
|
||||
private $db;
|
||||
|
||||
/** @var FilesystemInterface $fs */
|
||||
private $fs;
|
||||
|
||||
/** @var int $syncId */
|
||||
private $syncId;
|
||||
|
||||
/**
|
||||
* @param Database $database
|
||||
* @param FilesystemInterface $filesystem
|
||||
* @param int $syncId
|
||||
*/
|
||||
public function __construct(Database $database, FilesystemInterface $filesystem, $syncId)
|
||||
{
|
||||
if ((int)$syncId <= 0) {
|
||||
throw new InvalidArgumentException(sprintf('Sync-ID "%s" is invalid.', $syncId));
|
||||
}
|
||||
|
||||
$this->db = $database;
|
||||
$this->fs = $filesystem;
|
||||
$this->syncId = (int)$syncId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array|PathInfo[]
|
||||
*/
|
||||
public function listChanges($directory = '', $recursive = false)
|
||||
{
|
||||
$result = $this->fs->listContents($directory, $recursive);
|
||||
|
||||
$location = PathUtil::normalizePath($directory);
|
||||
$cache = $this->readCache($location, $recursive);
|
||||
|
||||
foreach ($result as $item) {
|
||||
$path = $item->getPath();
|
||||
|
||||
// Ignore directories; only files are nessesary for syncing
|
||||
if ($item->isDir()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Defaults
|
||||
$item->set('missing', false);
|
||||
$item->set('modified', null);
|
||||
|
||||
if (!array_key_exists($path, $cache)) {
|
||||
$item->set('missing', true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((int)$cache[$path]['size'] !== (int)$item->getSize()) {
|
||||
$item->set('modified', true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((int)$cache[$path]['timestamp'] !== (int)$item->getTimestamp()) {
|
||||
$item->set('modified', true);
|
||||
continue;
|
||||
}
|
||||
|
||||
$item->set('modified', false);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists deleted files
|
||||
*
|
||||
* Lists files that are present in cache but does not exist on the filesystem any more.
|
||||
*
|
||||
* @param string $directory
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array|PathInfo[]
|
||||
*/
|
||||
public function listDeleted($directory = '', $recursive = false)
|
||||
{
|
||||
$paths = $this->fs->listPaths($directory, $recursive);
|
||||
|
||||
$location = PathUtil::normalizePath($directory);
|
||||
$cache = $this->readCache($location, $recursive);
|
||||
|
||||
foreach ($cache as $path => $cacheItem) {
|
||||
if (in_array($path, $paths, true)) {
|
||||
unset($cache[$path]);
|
||||
}
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach ($cache as $cacheItem) {
|
||||
$pathinfo = PathUtil::pathinfo($cacheItem['path']);
|
||||
$result[] = new PathInfo(array_merge($cacheItem, $pathinfo));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function has($path)
|
||||
{
|
||||
return $this->fs->has($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getInfo($path)
|
||||
{
|
||||
return $this->fs->getInfo($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getType($path)
|
||||
{
|
||||
return $this->fs->getType($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getSize($path)
|
||||
{
|
||||
return $this->fs->getSize($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getTimestamp($path)
|
||||
{
|
||||
return $this->fs->getTimestamp($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getMimetype($path)
|
||||
{
|
||||
return $this->fs->getMimetype($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function listContents($directory = '', $recursive = false)
|
||||
{
|
||||
return $this->fs->listContents($directory, $recursive);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function listDirs($directory = '', $recursive = false)
|
||||
{
|
||||
return $this->fs->listDirs($directory, $recursive);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function listFiles($directory = '', $recursive = false)
|
||||
{
|
||||
return $this->fs->listFiles($directory, $recursive);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function listPaths($directory = '', $recursive = false)
|
||||
{
|
||||
return $this->fs->listPaths($directory, $recursive);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function read($path)
|
||||
{
|
||||
$result = $this->fs->read($path);
|
||||
$this->updateCachePath($path);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function readStream($path)
|
||||
{
|
||||
$result = $this->fs->readStream($path);
|
||||
$this->updateCachePath($path);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function write($path, $contents, array $config = [])
|
||||
{
|
||||
$result = $this->fs->write($path, $contents, $config);
|
||||
$this->updateCachePath($path);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function writeStream($path, $resource, array $config = [])
|
||||
{
|
||||
$result = $this->fs->writeStream($path, $resource, $config);
|
||||
$this->updateCachePath($path);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function put($path, $contents, array $config = [])
|
||||
{
|
||||
$result = $this->fs->put($path, $contents, $config);
|
||||
$this->updateCachePath($path);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function putStream($path, $resource, array $config = [])
|
||||
{
|
||||
$result = $this->fs->putStream($path, $resource, $config);
|
||||
$this->updateCachePath($path);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function delete($path)
|
||||
{
|
||||
$result = $this->fs->delete($path);
|
||||
$this->deleteCachePath($path);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a single file, but without Exception if path does not exist.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function softDelete($path)
|
||||
{
|
||||
$result = false;
|
||||
try {
|
||||
$this->deleteCachePath($path);
|
||||
$result = $this->fs->delete($path);
|
||||
} catch (FileNotFoundException $e) {
|
||||
// nope - its soft
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function deleteDir($dirname)
|
||||
{
|
||||
$result = $this->fs->deleteDir($dirname);
|
||||
$this->deleteCacheDir($dirname);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function createDir($dirname, array $config = [])
|
||||
{
|
||||
return $this->fs->createDir($dirname, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rename($path, $newpath)
|
||||
{
|
||||
$result = $this->fs->rename($path, $newpath);
|
||||
$this->deleteCachePath($path);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function copy($path, $newpath)
|
||||
{
|
||||
$result = $this->fs->copy($path, $newpath);
|
||||
$this->updateCachePath($newpath);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getAdapter()
|
||||
{
|
||||
return $this->fs->getAdapter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function readCache($path, $recursive = false)
|
||||
{
|
||||
$this->ensureDependencies();
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
return $this->db->fetchAssoc(
|
||||
'SELECT f.path, f.dirname, f.type, f.size, f.updated_at AS timestamp ' .
|
||||
'FROM sync_files AS f ' .
|
||||
'WHERE f.sync_id = :sync_id AND f.dirname LIKE :path_prefix',
|
||||
[
|
||||
'sync_id' => $this->syncId,
|
||||
'path_prefix' => $recursive === true ? $path . '%' : $path,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function updateCachePath($path)
|
||||
{
|
||||
$this->ensureDependencies();
|
||||
$info = $this->fs->getInfo($path);
|
||||
|
||||
$this->db->perform(
|
||||
'REPLACE INTO sync_files (sync_id, `path`, dirname, type, size, updated_at) ' .
|
||||
'VALUES (:sync_id, :path, :dirname, :type, :size, :updated_at)',
|
||||
[
|
||||
'sync_id' => $this->syncId,
|
||||
'path' => $info->getPath(),
|
||||
'dirname' => $info->getDir(),
|
||||
'type' => $info->getType(),
|
||||
'size' => (int)$info->getSize(),
|
||||
'updated_at' => (int)$info->getTimestamp(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return int Deleted row count
|
||||
*/
|
||||
private function deleteCachePath($path)
|
||||
{
|
||||
$this->ensureDependencies();
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
return $this->db->fetchAffected(
|
||||
'DELETE FROM sync_files WHERE sync_id = :sync_id AND `path` = :path',
|
||||
['sync_id' => $this->syncId, 'path' => $path]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dirname
|
||||
*
|
||||
* @return int Deleted row count
|
||||
*/
|
||||
private function deleteCacheDir($dirname)
|
||||
{
|
||||
$this->ensureDependencies();
|
||||
$dirname = $this->normalizePath($dirname);
|
||||
|
||||
return $this->db->fetchAffected(
|
||||
'DELETE FROM sync_files WHERE sync_id = :sync_id AND `dirname` LIKE :dirname',
|
||||
['sync_id' => $this->syncId, 'dirname' => $dirname . '%']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function normalizePath($path)
|
||||
{
|
||||
return PathUtil::normalizePath($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FilesystemException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function ensureDependencies()
|
||||
{
|
||||
if ($this->db === null || $this->syncId === null) {
|
||||
throw new FilesystemException('Can not continue. Required dependencies are missing.');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Flysystem;
|
||||
|
||||
use League\Flysystem\Adapter\Ftp;
|
||||
|
||||
final class FtpAdapterDecorator extends Ftp
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getMetadata($path)
|
||||
{
|
||||
$metadata = parent::getMetadata($path);
|
||||
if ($metadata === false) {
|
||||
return false; // File does not exist
|
||||
}
|
||||
|
||||
if ($metadata['type'] === 'dir') {
|
||||
$metadata['timestamp'] = null; // ftp_mdtm() does not work with directories.
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
if ($metadata['timestamp'] === null) {
|
||||
$data = $this->getTimestamp($path);
|
||||
$metadata['timestamp'] = $data !== false && isset($data['timestamp']) ? $data['timestamp'] : null;
|
||||
}
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function normalizeListing(array $listing, $prefix = '')
|
||||
{
|
||||
$result = parent::normalizeListing($listing, $prefix);
|
||||
|
||||
foreach ($result as &$item) {
|
||||
if ($item['type'] === 'dir') {
|
||||
$item['timestamp'] = null; // ftp_mdtm() does not work with directories.
|
||||
continue;
|
||||
}
|
||||
if (!isset($item['timestamp'])) {
|
||||
$data = $this->getTimestamp($item['path']);
|
||||
$item['timestamp'] = $data !== false && isset($data['timestamp']) ? $data['timestamp'] : null;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Flysystem;
|
||||
|
||||
use League\Flysystem\Adapter\Local;
|
||||
|
||||
final class LocalAdapterDecorator extends Local
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem;
|
||||
|
||||
use League\Flysystem\Util;
|
||||
use Xentral\Components\Filesystem\Exception\InvalidArgumentException;
|
||||
|
||||
final class PathInfo
|
||||
{
|
||||
const TYPE_FILE = 'file';
|
||||
const TYPE_DIR = 'dir';
|
||||
|
||||
/** @var array $readonlyProperties */
|
||||
private static $readonlyProperties = [
|
||||
'type',
|
||||
'path',
|
||||
'dirname',
|
||||
'filename',
|
||||
'basename',
|
||||
'extension',
|
||||
'timestamp',
|
||||
'size',
|
||||
];
|
||||
|
||||
/** @var array $data */
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function __construct(array $data)
|
||||
{
|
||||
// required
|
||||
$data['type'] = (string)$data['type'];
|
||||
$data['path'] = (string)$data['path'];
|
||||
$data['dirname'] = (string)$data['dirname'];
|
||||
$data['filename'] = (string)$data['filename'];
|
||||
$data['basename'] = (string)$data['basename'];
|
||||
|
||||
// optional
|
||||
$data['extension'] = !empty($data['extension']) ? (string)$data['extension'] : null;
|
||||
$data['timestamp'] = is_numeric($data['timestamp']) ? (int)$data['timestamp'] : null;
|
||||
$data['size'] = is_numeric($data['size']) ? (int)$data['size'] : null;
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $metainfo
|
||||
*
|
||||
* @return PathInfo
|
||||
*/
|
||||
public static function fromMeta(array $metainfo = [])
|
||||
{
|
||||
$pathinfo = Util::pathinfo($metainfo['path']);
|
||||
|
||||
return new PathInfo(array_merge($pathinfo, $metainfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isFile()
|
||||
{
|
||||
return $this->getType() === self::TYPE_FILE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isDir()
|
||||
{
|
||||
return $this->getType() === self::TYPE_DIR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string [dir|file]
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->data['type'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Filename with extension and without path
|
||||
*/
|
||||
public function getBasename()
|
||||
{
|
||||
return $this->data['basename'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Filename without extension and without path
|
||||
*/
|
||||
public function getFilename()
|
||||
{
|
||||
return $this->data['filename'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null File extension or null if directory
|
||||
*/
|
||||
public function getExtension()
|
||||
{
|
||||
return $this->data['extension'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Path without filename
|
||||
*/
|
||||
public function getDir()
|
||||
{
|
||||
return $this->data['dirname'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Relativer Pfad zum Mountpoint
|
||||
*
|
||||
* @return string Path with filename
|
||||
*/
|
||||
public function getPath()
|
||||
{
|
||||
return $this->data['path'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null File size or null if not available
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
return $this->data['size'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null Last updated timestamp or null if not available
|
||||
*/
|
||||
public function getTimestamp()
|
||||
{
|
||||
return $this->data['timestamp'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($name)
|
||||
{
|
||||
return isset($this->data[(string)$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
if ($this->has($name)) {
|
||||
return $this->data[(string)$name];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($name, $value)
|
||||
{
|
||||
if (in_array((string)$name, self::$readonlyProperties, true)) {
|
||||
throw new InvalidArgumentException(sprintf('Property "%s" is readonly.', $name));
|
||||
}
|
||||
|
||||
$this->data[(string)$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return $this->has($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$this->set($name, $value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem;
|
||||
|
||||
use League\Flysystem\Util;
|
||||
|
||||
final class PathUtil extends Util
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Plugin;
|
||||
|
||||
use Xentral\Components\Filesystem\FilesystemInterface;
|
||||
|
||||
final class FilterPathsPlugin implements PluginInterface
|
||||
{
|
||||
/** @var FilesystemInterface $filesystem */
|
||||
private $filesystem;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod()
|
||||
{
|
||||
return 'filterPaths';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FilesystemInterface $filesystem
|
||||
*/
|
||||
public function setFilesystem(FilesystemInterface $filesystem)
|
||||
{
|
||||
$this->filesystem = $filesystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @example filterPaths(['extension' => 'php', 'filename' => 'Bootstrap'])
|
||||
*
|
||||
* @param array $filter
|
||||
* @param string $path
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function handle(array $filter = [], $path = '', $recursive = false)
|
||||
{
|
||||
$result = [];
|
||||
$contents = $this->filesystem->listContents($path, $recursive);
|
||||
|
||||
foreach ($contents as $object) {
|
||||
$matchesFilter = true;
|
||||
|
||||
foreach ($filter as $property => $value) {
|
||||
if (!isset($object[$property])) {
|
||||
$matchesFilter = false;
|
||||
continue;
|
||||
}
|
||||
if ($object[$property] !== $value) {
|
||||
$matchesFilter = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($matchesFilter === true) {
|
||||
$result[] = $object['path'];
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Plugin;
|
||||
|
||||
use League\Flysystem\Plugin\AbstractPlugin;
|
||||
|
||||
final class ListDirectoriesPlugin extends AbstractPlugin
|
||||
{
|
||||
/**
|
||||
* Get the method name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod()
|
||||
{
|
||||
return 'listDirectories';
|
||||
}
|
||||
|
||||
/**
|
||||
* List all directories 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'] === 'dir';
|
||||
};
|
||||
|
||||
return array_values(array_filter($contents, $filter));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Filesystem\Plugin;
|
||||
|
||||
use Xentral\Components\Filesystem\FilesystemInterface;
|
||||
|
||||
interface PluginInterface
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod();
|
||||
|
||||
/**
|
||||
* @param FilesystemInterface $filesystem
|
||||
*/
|
||||
public function setFilesystem(FilesystemInterface $filesystem);
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
# Filesystem-Komponente
|
||||
|
||||
## Beispiele
|
||||
|
||||
### FTP
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
/** @var \Xentral\Components\Filesystem\FilesystemFactory $factory */
|
||||
$factory = $this->app->Container->get('FilesystemFactory');
|
||||
|
||||
$config = new \Xentral\Components\Filesystem\Adapter\FtpConfig('192.168.0.123', 'username', 'passwort', '/root-dir');
|
||||
$ftp = $factory->createFtp($config);
|
||||
|
||||
if ($ftp->has('/some/file.txt')) {
|
||||
$contents = $ftp->read('/some/file.txt');
|
||||
} else {
|
||||
$ftp->write('/some/file.txt', 'hello world!');
|
||||
}
|
||||
```
|
||||
|
||||
### Lokales Dateisystem
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
/** @var \Xentral\Components\Filesystem\FilesystemFactory $factory */
|
||||
$factory = $this->app->Container->get('FilesystemFactory');
|
||||
|
||||
$local = $factory->createLocal(dirname(__DIR__));
|
||||
|
||||
if ($local->has('/some/file.txt')) {
|
||||
$contents = $local->read('/some/file.txt');
|
||||
} else {
|
||||
$local->write('/some/file.txt', 'hello world!');
|
||||
}
|
||||
```
|
||||
|
||||
### Große Dateien kopieren
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$ftp = $factory->createFtp($config);
|
||||
$local = $factory->createLocal(dirname(__DIR__));
|
||||
|
||||
$ftp->writeStream('/ziel-pfad', $local->readStream('/quell-pfad'));
|
||||
```
|
||||
|
||||
### Datei-Uploads
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$factory = $this->app->Container->get('FilesystemFactory');
|
||||
$local = $factory->createLocal(dirname(__DIR__));
|
||||
|
||||
$stream = fopen($_FILES['upload']['tmp_name'], 'rb+');
|
||||
$local->writeStream(
|
||||
'uploads/' . $_FILES['upload']['name'],
|
||||
$stream
|
||||
);
|
||||
|
||||
if (is_resource($stream)) {
|
||||
fclose($stream);
|
||||
}
|
||||
```
|
||||
|
||||
### FilesystemSyncCache
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$ftp = $factory->createFtp($config);
|
||||
$sync = $factory->createSync($ftp, 1);
|
||||
|
||||
$changes = $sync->listChanges('/sub', true); // Hinzugekommene und geänderte Dateien abrufen
|
||||
$deletes = $sync->listDeleted('/sub', true); // Gelöschte Dateien abrufen
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### FilesystemInterface
|
||||
|
||||
---
|
||||
|
||||
#### `has($path)`
|
||||
|
||||
Prüfen ob eine Datei oder ein Verzeichnis existiert.
|
||||
|
||||
Rückgabe: `true` oder `false`
|
||||
|
||||
---
|
||||
|
||||
#### `listContents($directory = '', $recursive = false)`
|
||||
|
||||
Verzeichnisinhalte abrufen.
|
||||
|
||||
Rückgabe: `array` mit `PathInfo`-Objekten
|
||||
|
||||
---
|
||||
|
||||
#### `listDirs($directory = '', $recursive = false)`
|
||||
|
||||
Verzeichnisinhalte abrufen; nur Verzeichnisse.
|
||||
|
||||
Rückgabe: `array` mit `PathInfo`-Objekten
|
||||
|
||||
---
|
||||
|
||||
#### `listFiles($directory = '', $recursive = false)`
|
||||
|
||||
Verzeichnisinhalte abrufen; nur Dateien.
|
||||
|
||||
Rückgabe: `array` mit `PathInfo`-Objekten
|
||||
|
||||
---
|
||||
|
||||
#### `listPaths($directory = '', $recursive = false)`
|
||||
|
||||
Verzeichnisinhalte abrufen; nur Pfadauflistung; keine Details.
|
||||
|
||||
Rückgabe: `array` mit Pfaden als `string`
|
||||
|
||||
---
|
||||
|
||||
#### `getInfo($path)`
|
||||
|
||||
Informationen über eine Datei oder ein Verzeichnis abrufen.
|
||||
|
||||
Rückgabe: `PathInfo`-Objekt
|
||||
|
||||
---
|
||||
|
||||
#### `getType($path)`
|
||||
|
||||
Prüfen ob Pfad eine Datei oder ein Verzeichnis ist.
|
||||
|
||||
Rückgabe: `'dir'` oder `'file''`
|
||||
|
||||
---
|
||||
|
||||
#### `getSize($path)`
|
||||
|
||||
Dateigröße abrufen.
|
||||
|
||||
Rückgabe: Dateigröße als `int` oder `false` bei einem Verzeichnis.
|
||||
|
||||
---
|
||||
|
||||
#### `getTimestamp($path)`
|
||||
|
||||
Datum der letzten Änderung abrufen.
|
||||
|
||||
Rückgabe: Timestamp als `int` oder `false` falls Information nicht verfügbar
|
||||
(z.B. bei Verzeichnissen über FTP).
|
||||
|
||||
---
|
||||
|
||||
#### `getMimetype($path)`
|
||||
|
||||
Mimetype abrufen.
|
||||
|
||||
Rückgabe: Mimetype als `string` oder `'directory'` bei einem Verzeichnis.
|
||||
|
||||
---
|
||||
|
||||
#### `read($path)`
|
||||
|
||||
Datei-Inhalt abrufen.
|
||||
|
||||
Rückgabe: `string`
|
||||
|
||||
---
|
||||
|
||||
#### `readStream($path)`
|
||||
|
||||
Datei-Inhalt als Stream abrufen.
|
||||
|
||||
Rückgabe: `resource`
|
||||
|
||||
---
|
||||
|
||||
#### `write($path, $contents, array $config = [])`
|
||||
#### `writeStream($path, $resource, array $config = [])`
|
||||
|
||||
Datei anlegen.
|
||||
|
||||
Besonderheit: Wenn Zieldatei bereits existiert, wird eine `FileExistsException` geworfen.
|
||||
|
||||
Rückgabe: `true` oder `false`
|
||||
|
||||
---
|
||||
|
||||
#### `put($path, $contents, array $config = [])`
|
||||
#### `putStream($path, $resource, array $config = [])`
|
||||
|
||||
Datei anlegen oder überschreiben.
|
||||
|
||||
Besonderheit: Im Unterschied zu `write()` und `writeStream()` wird keine Exception geworfen wenn das Ziel bereits existiert.
|
||||
|
||||
Rückgabe: `true` oder `false`
|
||||
|
||||
---
|
||||
|
||||
#### `createDir($dirname)`
|
||||
|
||||
Verzeichnis anlegen; funktioniert auch rekursiv.
|
||||
|
||||
Rückgabe: `true` oder `false`
|
||||
|
||||
---
|
||||
|
||||
#### `deleteDir($dirname)`
|
||||
|
||||
Verzeichnis löschen; funktioniert auch wenn Verzeichnis nicht leer.
|
||||
|
||||
Rückgabe: `true` oder `false`
|
||||
|
||||
---
|
||||
|
||||
#### `delete($path)`
|
||||
|
||||
Einzelne Datei löschen.
|
||||
|
||||
Rückgabe: `true` oder `false`
|
||||
|
||||
---
|
||||
|
||||
#### `rename($path, $newpath)`
|
||||
|
||||
Datei umbenennen.
|
||||
|
||||
Rückgabe: `true` oder `false`
|
||||
|
||||
---
|
||||
|
||||
#### `copy($path, $newpath)`
|
||||
|
||||
Datei kopieren.
|
||||
|
||||
Rückgabe: `true` oder `false`
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user