Initial commit IQParts\Content
This commit is contained in:
86
src/AssetResolver.php
Normal file
86
src/AssetResolver.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace IQParts\Content;
|
||||
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
use IQParts\Content\Object\CacheControl;
|
||||
use IQParts\Content\Object\File;
|
||||
use League\Flysystem\FileNotFoundException;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Class AssetResolver
|
||||
* @package IQParts\Framework\Content
|
||||
*/
|
||||
final class AssetResolver
|
||||
{
|
||||
/**
|
||||
* @var MimeDetector
|
||||
*/
|
||||
private $detector;
|
||||
/**
|
||||
* @var Filesystem
|
||||
*/
|
||||
private $filesystem;
|
||||
|
||||
/**
|
||||
* AssetResolver constructor.
|
||||
* @param Filesystem $filesystem
|
||||
* @internal param string $assetDir
|
||||
*/
|
||||
public function __construct(Filesystem $filesystem )
|
||||
{
|
||||
$this->detector = new MimeDetector();
|
||||
$this->filesystem = $filesystem ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $file
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(string $file): bool
|
||||
{
|
||||
// Will never throw as we check if the file exists.
|
||||
return $this->filesystem->exists($file) && $this->filesystem->get($file) instanceof File;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RequestInterface $request
|
||||
* @param ResponseInterface $response
|
||||
* @param CacheControl $cacheControl
|
||||
* @param bool $inline
|
||||
* @return ResponseInterface|bool
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public function resolve(
|
||||
RequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
CacheControl $cacheControl,
|
||||
bool $inline = true
|
||||
)
|
||||
{
|
||||
$target = $request->getRequestTarget();
|
||||
|
||||
$file = $this->filesystem->get($target);
|
||||
|
||||
/** @var ResponseInterface $response */
|
||||
$response = $response->withHeader('Cache-Control', (string) $cacheControl);
|
||||
$response = $response->withHeader('Content-Type', $this->detector->detectFromExtension(
|
||||
$file->getBasename())
|
||||
);
|
||||
|
||||
if ($inline) {
|
||||
$response = $response->withHeader('Content-Disposition', 'inline; filename="' . $file->getBasename() . '";');
|
||||
} else {
|
||||
$response = $response->withHeader('Content-Disposition', 'attachment; filename="' . $file->getBasename() . '";');
|
||||
}
|
||||
$response = $response->withHeader('Content-Length', (string)$file->getSize());
|
||||
|
||||
/**
|
||||
* Will always return a stream
|
||||
*/
|
||||
$stream = $file->getStream();
|
||||
return $response->withBody(new Stream($stream))->withStatus(200);
|
||||
}
|
||||
}
|
||||
56
src/ContentProviderInterface.php
Normal file
56
src/ContentProviderInterface.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace IQParts\Framework\Content;
|
||||
|
||||
|
||||
interface ContentProviderInterface
|
||||
{
|
||||
/**
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(string $location): bool;
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @param $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function put(string $location, $data);
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return resource
|
||||
*/
|
||||
public function get(string $location);
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return array
|
||||
*/
|
||||
public function getCollection(string $location): array;
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return int
|
||||
*/
|
||||
public function getSize(string $location): int;
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*/
|
||||
public function remove(string $location): bool;
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return string
|
||||
*/
|
||||
public function getPermissions(string $location): string;
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*/
|
||||
public function createCollection(string $location): bool;
|
||||
}
|
||||
197
src/Filesystem.php
Normal file
197
src/Filesystem.php
Normal file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
namespace IQParts\Content;
|
||||
|
||||
use IQParts\Content\Object\File;
|
||||
use IQParts\Content\Object\Folder;
|
||||
use League\Flysystem\AdapterInterface;
|
||||
use League\Flysystem\Config;
|
||||
use League\Flysystem\Directory;
|
||||
use League\Flysystem\FileNotFoundException;
|
||||
use League\Flysystem\Filesystem as FlySystem;
|
||||
use League\Flysystem\Plugin\ListPaths;
|
||||
|
||||
/**
|
||||
* Class Filesystem
|
||||
* @package IQParts\Content
|
||||
*/
|
||||
final class Filesystem
|
||||
{
|
||||
/**
|
||||
* @var FlySystem
|
||||
*/
|
||||
private $flySystem;
|
||||
|
||||
/**
|
||||
* Filesystem constructor.
|
||||
* @param AdapterInterface $adapter
|
||||
* @param Config $config
|
||||
*/
|
||||
public function __construct(AdapterInterface $adapter, Config $config = null)
|
||||
{
|
||||
if (!$config) $config = [];
|
||||
$flySystem = new FlySystem($adapter, $config);
|
||||
$flySystem->addPlugin(new ListPaths());
|
||||
$this->flySystem = $flySystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(string $path): bool
|
||||
{
|
||||
if ($path === '/') $path = '';
|
||||
return $this->flySystem->has($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return File|Folder|false
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public function get(string $path)
|
||||
{
|
||||
/**
|
||||
* If path = '/' -> create a folder object with all dirs and folders as children
|
||||
*/
|
||||
if ($path === '/' || $path === '') {
|
||||
$dirs = [];
|
||||
$files = [];
|
||||
$paths = $this->flySystem->listPaths('', false);
|
||||
foreach ($paths as $item) {
|
||||
/** @var File|Directory $i */
|
||||
$i = $this->flySystem->get($item);
|
||||
if ($i->getType() === 'dir') {
|
||||
$dirs[] = base64_encode($i->getPath());
|
||||
} else {
|
||||
$files[] = base64_encode($i->getPath());
|
||||
}
|
||||
}
|
||||
|
||||
return Folder::fromVariables(base64_encode('/'), '/', '', null, $dirs, $files);
|
||||
} else {
|
||||
$item = $this->flySystem->get($path);
|
||||
if ($item instanceof Directory) {
|
||||
return new Folder($item);
|
||||
} else {
|
||||
return new File($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return bool|false|resource
|
||||
*/
|
||||
public function getStream(string $path)
|
||||
{
|
||||
return $this->flySystem->readStream($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param bool $recursive
|
||||
* @return \Iterator|Folder[]|File[]
|
||||
*/
|
||||
public function listDirContents(string $path, bool $recursive = false): \Iterator
|
||||
{
|
||||
if ($path === '/') $path = '';
|
||||
foreach ($this->flySystem->listPaths($path, $recursive) as $path) {
|
||||
$item = $this->flySystem->get($path);
|
||||
if ($item instanceof Directory) {
|
||||
yield new Folder($item);
|
||||
} else {
|
||||
yield new File($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param bool $recursive
|
||||
* @return \Iterator|Folder[]
|
||||
*/
|
||||
public function listDirs(string $path, bool $recursive = false): \Iterator
|
||||
{
|
||||
if ($path === '/') $path = '';
|
||||
foreach ($this->flySystem->listPaths($path, $recursive) as $path) {
|
||||
$item = $this->flySystem->get($path);
|
||||
if ($item instanceof Directory) {
|
||||
yield new Folder($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param bool $recursive
|
||||
* @return \Iterator|File[]
|
||||
*/
|
||||
public function listFiles(string $path, bool $recursive = false): \Iterator
|
||||
{
|
||||
if ($path === '/') $path = '';
|
||||
foreach ($this->flySystem->listContents($path, $recursive) as $i) {
|
||||
$item = $this->flySystem->get($i['path']);
|
||||
if ($item instanceof \League\Flysystem\File) yield new File($item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public function delete(string $path)
|
||||
{
|
||||
return $this->flySystem->delete($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteDir(string $path)
|
||||
{
|
||||
return $this->flySystem->deleteDir($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $config
|
||||
* @return bool
|
||||
*/
|
||||
public function createDir(string $path, array $config = [])
|
||||
{
|
||||
return $this->flySystem->createDir($path, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param $contents
|
||||
* @param array $config
|
||||
* @return bool
|
||||
*/
|
||||
public function put(string $path, $contents, array $config = []): bool
|
||||
{
|
||||
return $this->flySystem->put($path, $contents, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param resource $contents
|
||||
* @param array $config
|
||||
* @return bool
|
||||
*/
|
||||
public function putStream(string $path, $contents, array $config = []): bool
|
||||
{
|
||||
return $this->flySystem->putStream($path, $contents, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FlySystem
|
||||
*/
|
||||
public function getFlySystem(): FlySystem
|
||||
{
|
||||
return $this->flySystem;
|
||||
}
|
||||
}
|
||||
162
src/MimeDetector.php
Normal file
162
src/MimeDetector.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace IQParts\Content;
|
||||
|
||||
/**
|
||||
* Class MimeDetector
|
||||
* @package IQParts\Framework\Content
|
||||
*/
|
||||
final class MimeDetector
|
||||
{
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
private $mimeTypes;
|
||||
|
||||
/**
|
||||
* Factory constructor.
|
||||
* @param array $extraMimes
|
||||
*/
|
||||
public function __construct(array $extraMimes = [])
|
||||
{
|
||||
$this->mimeTypes = array_merge(
|
||||
[
|
||||
'doc' => 'application/msword',
|
||||
'dot' => 'application/msword',
|
||||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
|
||||
'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
|
||||
'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
|
||||
'xls' => 'application/vnd.ms-excel',
|
||||
'xlt' => 'application/vnd.ms-excel',
|
||||
'xla' => 'application/vnd.ms-excel',
|
||||
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
|
||||
'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
|
||||
'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
|
||||
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
|
||||
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
|
||||
'ppt' => 'application/vnd.ms-powerpoint',
|
||||
'pot' => 'application/vnd.ms-powerpoint',
|
||||
'pps' => 'application/vnd.ms-powerpoint',
|
||||
'ppa' => 'application/vnd.ms-powerpoint',
|
||||
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
|
||||
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
|
||||
'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
|
||||
'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
|
||||
'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
|
||||
'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
|
||||
'mdb' => 'application/vnd.ms-access',
|
||||
'aac' => 'audio/aac',
|
||||
'abw' => 'application/x-abiword',
|
||||
'arc' => 'application/octet-stream',
|
||||
'avi' => 'video/x-msvideo',
|
||||
'azw' => 'application/vnd.amazon.ebook',
|
||||
'bin' => 'application/octet-stream',
|
||||
'bz' => 'application/x-bzip',
|
||||
'bz2' => 'application/x-bzip2',
|
||||
'csh' => 'application/x-csh',
|
||||
'css' => 'text/css',
|
||||
'csv' => 'text/csv',
|
||||
'eot' => 'application/vnd.ms-fontobject',
|
||||
'epub' => 'application/epub+zip',
|
||||
'gif' => 'image/gif',
|
||||
'htm' => 'text/html',
|
||||
'html' => 'text/html',
|
||||
'twig' => 'text/html',
|
||||
'ico' => 'image/x-icon',
|
||||
'ics' => 'text/calendar',
|
||||
'jar' => 'application/java-archive',
|
||||
'jpeg' => 'image/jpeg',
|
||||
'jpg' => 'image/jpg',
|
||||
'js' => 'application/javascript',
|
||||
'json' => 'application/json',
|
||||
'mid' => 'audio/midi',
|
||||
'midi' => 'audio/midi',
|
||||
'mpeg' => 'video/mpeg',
|
||||
'mpkg' => 'application/vnd.apple.installer+xml',
|
||||
'odp' => 'application/vnd.oasis.opendocument.presentation',
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||||
'oga' => 'audio/ogg',
|
||||
'ogv' => 'video/ogg',
|
||||
'ogx' => 'application/ogg',
|
||||
'otf' => 'font/otf',
|
||||
'png' => 'image/png',
|
||||
'pdf' => 'application/pdf',
|
||||
'rar' => 'application/x-rar-compressed',
|
||||
'rtf' => 'application/rtf',
|
||||
'sh' => 'application/x-sh',
|
||||
'svg' => 'image/svg+xml',
|
||||
'swf' => 'application/x-shockwave-flash',
|
||||
'tar' => 'application/x-tar',
|
||||
'tif' => 'image/tiff',
|
||||
'tiff' => 'image/tiff',
|
||||
'ts' => 'application/typescript',
|
||||
'txt' => 'text/plain',
|
||||
'ttf' => 'font/ttf',
|
||||
'vsd' => 'application/vnd.visio',
|
||||
'wav' => 'audio/x-wav',
|
||||
'weba' => 'audio/webm',
|
||||
'webm' => 'video/webm',
|
||||
'webp' => 'image/webp',
|
||||
'woff' => 'font/woff',
|
||||
'woff2' => 'font/woff2',
|
||||
'xhtml' => 'application/xhtml+xml',
|
||||
'xml' => 'application/xml',
|
||||
'xul' => 'application/vnd.mozilla.xul+xml',
|
||||
'zip' => 'application/zip',
|
||||
'3gp' => 'video/3gpp',
|
||||
'3g2' => 'video/3gpp2',
|
||||
'7z' => 'application/x-7z-compressed'
|
||||
],
|
||||
$extraMimes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
public function detectFromExtension(string $filename): string
|
||||
{
|
||||
return $this->mimeTypes[$this->getExtension($filename)] ?? 'text/plain';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
* @return bool
|
||||
*/
|
||||
public function isText(string $filename): bool
|
||||
{
|
||||
$mime = $this->detectFromExtension($filename);
|
||||
if (fnmatch('text/*', $mime)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$text = [
|
||||
"application/javascript" => true,
|
||||
"application/rtf" => true,
|
||||
"application/json" => true,
|
||||
"application/x-sh" => true,
|
||||
"application/xml" => true
|
||||
];
|
||||
return isset($text[$mime]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filename
|
||||
* @return string
|
||||
*/
|
||||
private function getExtension($filename): string
|
||||
{
|
||||
$file = basename($filename);
|
||||
$dotPlace = strrpos($file, '.');
|
||||
if ($dotPlace === false) {
|
||||
return $file;
|
||||
}
|
||||
return substr($file, $dotPlace + 1);
|
||||
}
|
||||
|
||||
}
|
||||
74
src/Object/CacheControl.php
Normal file
74
src/Object/CacheControl.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace IQParts\Content\Object;
|
||||
|
||||
final class CacheControl
|
||||
{
|
||||
public const MUST_REVALIDATE = 0;
|
||||
public const NO_TRANSFORM = 1;
|
||||
public const NO_CACHE = 2;
|
||||
public const NO_STORE = 3;
|
||||
public const PUBLIC = 4;
|
||||
public const PRIVATE = 5;
|
||||
public const PROXY = 6;
|
||||
public const MAX_AGE = 7;
|
||||
public const S_MAX_AGE = 8;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $modes = [
|
||||
'must-revalidate',
|
||||
'no-transform',
|
||||
'no-cache',
|
||||
'no-store',
|
||||
'public',
|
||||
'private',
|
||||
'proxy-revalidate',
|
||||
'max-age',
|
||||
's-max-age'
|
||||
];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $mode;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $seconds;
|
||||
|
||||
/**
|
||||
* CacheControl constructor.
|
||||
* @param int $mode
|
||||
* @param int $seconds
|
||||
*/
|
||||
public function __construct(int $mode, int $seconds = -1)
|
||||
{
|
||||
if ($mode < 0 || $mode > 7) {
|
||||
throw new \InvalidArgumentException('Invalid mode.');
|
||||
}
|
||||
|
||||
if ($mode >= 7 && $seconds < 0) {
|
||||
throw new \InvalidArgumentException('Invalid number of seconds.');
|
||||
}
|
||||
|
||||
$this->mode = $mode;
|
||||
$this->seconds = $seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$mode = $this->modes[$this->mode];
|
||||
|
||||
if ($this->mode >= 7) {
|
||||
return $mode . '=' . (string)$this->seconds;
|
||||
}
|
||||
|
||||
return $mode;
|
||||
}
|
||||
}
|
||||
252
src/Object/File.php
Normal file
252
src/Object/File.php
Normal file
@@ -0,0 +1,252 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace IQParts\Content\Object;
|
||||
|
||||
use IQParts\Content\MimeDetector;
|
||||
use League\Flysystem\File as FlyFile;
|
||||
|
||||
/**
|
||||
* Class File
|
||||
* @package IQParts\Content\Object
|
||||
*/
|
||||
final class File extends Item
|
||||
{
|
||||
/**
|
||||
* @var FlyFile
|
||||
*/
|
||||
private $file;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $path;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $basename;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $size;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $extension;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $parent;
|
||||
/**
|
||||
* @var \DateTime
|
||||
*/
|
||||
private $date;
|
||||
/**
|
||||
* @var false|int
|
||||
*/
|
||||
private $timestamp;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $isEditable;
|
||||
|
||||
/**
|
||||
* PublicFile constructor.
|
||||
* @param FlyFile $file
|
||||
*/
|
||||
public function __construct(FlyFile $file = null)
|
||||
{
|
||||
if ($file !== null) {
|
||||
$editable = [
|
||||
"js" => true,
|
||||
"css" => true,
|
||||
"html" => true,
|
||||
"svg" => true
|
||||
];
|
||||
|
||||
$this->file = $file;
|
||||
$this->path = $file->getPath();
|
||||
$this->size = $file->getSize();
|
||||
$this->basename = basename($file->getPath());
|
||||
$this->date = new \DateTime();
|
||||
$timestamp = $file->getTimestamp();
|
||||
$this->date->setTimestamp($timestamp);
|
||||
$this->timestamp = $timestamp;
|
||||
|
||||
$dotPlace = strrpos($this->basename, '.');
|
||||
if ($dotPlace !== false) $extension = substr($this->basename, $dotPlace + 1);
|
||||
else $extension = '';
|
||||
$this->extension = $extension;
|
||||
|
||||
$parentSep = strrpos($this->path, '/');
|
||||
if ($parentSep !== false) {
|
||||
$parent = substr($this->path, 0, $parentSep);
|
||||
} else $parent = '/';
|
||||
$this->parent = base64_encode($parent);
|
||||
$this->isEditable = $editable[$extension] ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getId(): string
|
||||
{
|
||||
return base64_encode($this->path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FlyFile
|
||||
*/
|
||||
public function getFile(): FlyFile
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPath(): string
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getSize(): int
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBasename(): string
|
||||
{
|
||||
return $this->basename;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getExtension()
|
||||
{
|
||||
return $this->extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getDate(): \DateTime
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTimestamp()
|
||||
{
|
||||
return $this->timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMD5(): string
|
||||
{
|
||||
return md5($this->file->read());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false|string
|
||||
*/
|
||||
public function getContents()
|
||||
{
|
||||
return $this->file->read();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false|resource
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
return $this->file->readStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false|string
|
||||
*/
|
||||
public function getMimetype()
|
||||
{
|
||||
return $this->file->getMimetype();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isEditable(): bool
|
||||
{
|
||||
return (new MimeDetector())->isText($this->basename);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'basename' => $this->getBasename(),
|
||||
'contents' => $this->isEditable() ? $this->getContents() : null,
|
||||
'date' => $this->getDate()->format(DATE_ISO8601),
|
||||
'extension' => $this->getExtension(),
|
||||
'id' => $this->getId(),
|
||||
'isEditable' => $this->isEditable(),
|
||||
'mimetype' => $this->getMimetype(),
|
||||
'md5' => $this->getMD5(),
|
||||
'parent' => $this->getParent(),
|
||||
'path' => $this->getPath(),
|
||||
'size' => $this->getSize(),
|
||||
'timestamp' => $this->getTimestamp()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function isDir(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function isFile(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string $parent
|
||||
* @param int $timestamp
|
||||
* @return File
|
||||
*/
|
||||
public static function fromVariables(string $path, string $parent, int $timestamp): self
|
||||
{
|
||||
$file = new self;
|
||||
$file->path = $path;
|
||||
$file->parent = $parent;
|
||||
$file->timestamp = $timestamp;
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
187
src/Object/Folder.php
Normal file
187
src/Object/Folder.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
namespace IQParts\Content\Object;
|
||||
|
||||
use League\Flysystem\Directory;
|
||||
|
||||
/**
|
||||
* Class Folder
|
||||
* @package IQParts\Content\Object
|
||||
*/
|
||||
final class Folder extends Item
|
||||
{
|
||||
/**
|
||||
* @var Directory
|
||||
*/
|
||||
private $directory;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $path;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $parent;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $basename;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $dirs;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $files;
|
||||
|
||||
/**
|
||||
* Folder constructor.
|
||||
* @param Directory $directory
|
||||
*/
|
||||
public function __construct(Directory $directory = null)
|
||||
{
|
||||
if ($directory) {
|
||||
$this->directory = $directory;
|
||||
$this->path = $directory->getPath();
|
||||
$filesystem = $directory->getFilesystem();
|
||||
|
||||
$parentSep = strrpos($this->path, '/');
|
||||
if ($parentSep !== false) {
|
||||
$parent = substr($this->path, 0, $parentSep);
|
||||
} else $parent = '/';
|
||||
$this->parent = base64_encode($parent);
|
||||
$this->basename = basename($this->path);
|
||||
|
||||
$paths = $filesystem->listContents($this->path);
|
||||
$dirs = [];
|
||||
$files = [];
|
||||
|
||||
foreach ($paths as $path) {
|
||||
$item = $filesystem->get($path['path']);
|
||||
if ($item instanceof Directory) {
|
||||
$dirs[] = base64_encode($item->getPath());
|
||||
} else {
|
||||
$files[] = base64_encode($item->getPath());
|
||||
}
|
||||
}
|
||||
$this->dirs = $dirs;
|
||||
$this->files = $files;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Directory
|
||||
*/
|
||||
public function getDirectory(): Directory
|
||||
{
|
||||
return $this->directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getId(): string
|
||||
{
|
||||
return base64_encode($this->getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPath(): string
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBasename(): string
|
||||
{
|
||||
return $this->basename;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDirs(): array
|
||||
{
|
||||
return $this->dirs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getFiles(): array
|
||||
{
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->getId(),
|
||||
'path' => $this->getPath(),
|
||||
'basename' => $this->getBasename(),
|
||||
'parent' => $this->getParent(),
|
||||
'dirs' => $this->getDirs(),
|
||||
'files' => $this->getFiles()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function isDir(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function isFile(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @param string $path
|
||||
* @param string $basename
|
||||
* @param string|null $parent
|
||||
* @param array $dirs
|
||||
* @param array $files
|
||||
* @return Folder
|
||||
*/
|
||||
public static function fromVariables(
|
||||
string $id,
|
||||
string $path,
|
||||
string $basename,
|
||||
$parent = null,
|
||||
array $dirs = [],
|
||||
array $files = []
|
||||
): Folder
|
||||
{
|
||||
$dir = new self();
|
||||
$dir->id = $id;
|
||||
$dir->path = $path;
|
||||
$dir->basename = $basename;
|
||||
$dir->parent = $parent;
|
||||
$dir->dirs = $dirs;
|
||||
$dir->files = $files;
|
||||
return $dir;
|
||||
}
|
||||
}
|
||||
20
src/Object/Item.php
Normal file
20
src/Object/Item.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace IQParts\Content\Object;
|
||||
|
||||
/**
|
||||
* Class Item
|
||||
* @package IQParts\Content\Object
|
||||
*/
|
||||
abstract class Item
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
abstract function isDir(): bool;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
abstract function isFile(): bool;
|
||||
}
|
||||
Reference in New Issue
Block a user