make media handle upload, create file and collection more uniform

This commit is contained in:
Dennis Eichhorn 2020-07-30 21:24:32 +02:00
parent 07f19d5f56
commit 4b9610f341
17 changed files with 272 additions and 56 deletions

View File

@ -85,7 +85,7 @@ final class Installer extends InstallerAbstract
$collection = new Collection();
$collection->setName((string) $data['name'] ?? '');
$collection->setVirtualPath((string) $data['virtualPath'] ?? '/');
$collection->setPath((string) $data['virtualPath'] ?? '/');
$collection->setPath((string) ($data['path'] ?? '/Modules/Media/Files/' . ((string) $data['name'] ?? '')));
$collection->setCreatedBy(new NullAccount((int) $data['user'] ?? 1));
CollectionMapper::create($collection);

View File

@ -37,6 +37,17 @@ return [
],
],
],
'^.*/media/collection(\?+.*|$)' => [
[
'dest' => '\Modules\Media\Controller\ApiController:apiCollectionCreate',
'verb' => RouteVerb::PUT,
'permission' => [
'module' => ApiController::MODULE_NAME,
'type' => PermissionType::CREATE,
'state' => PermissionState::MEDIA,
],
],
],
'^.*/media/find.*$' => [
[
'dest' => '\Modules\Media\Controller\ApiController:apiMediaFind',

View File

@ -114,7 +114,7 @@ final class ApiController extends Controller
$request->getData('name') === null || $request->getFiles() !== null ? '' : $request->getData('name'),
$request->getFiles(),
$request->getHeader()->getAccount(),
(string) ($request->getData('path') ?? __DIR__ . '/../../../Modules/Media/Files'),
__DIR__ . '/../../../Modules/Media/Files' . ((string) ($request->getData('path') ?? '')),
(string) ($request->getData('virtualPath') ?? ''),
(string) ($request->getData('password') ?? ''),
(string) ($request->getData('encrypt') ?? ''),
@ -152,7 +152,7 @@ final class ApiController extends Controller
string $name,
array $files,
int $account,
string $basePath = 'Modules/Media/Files',
string $basePath = '/Modules/Media/Files',
string $virtualPath = '',
string $password = '',
string $encryptionKey = '',
@ -286,7 +286,7 @@ final class ApiController extends Controller
return \str_replace('\\', '/',
\str_replace($realpath, '',
\rtrim($path, '/')
\rtrim($path, '\\/')
)
);
}
@ -327,14 +327,32 @@ final class ApiController extends Controller
*/
private function updateMediaFromRequest(RequestAbstract $request) : Media
{
$id = (int) $request->getData('id');
/** @var Media $media */
$media = MediaMapper::get((int) $request->getData('id'));
$media = MediaMapper::get($id);
$media->setName((string) ($request->getData('name') ?? $media->getName()));
$media->setVirtualPath(\urldecode((string) ($request->getData('virtualpath') ?? $media->getVirtualPath())));
if ($id == 0) {
$path = \urldecode($request->getData('path'));
if ($media instanceof NullMedia
&& \is_file(__DIR__ . '/../Files' . $path)
) {
$name = \explode('.', \basename($path));
$media->setName($name[0]);
$media->setExtension($name[1] ?? '');
$media->setVirtualPath(\dirname($path));
$media->setPath('/Modules/Media/Files/' . \ltrim($path, '\\/'));
$media->setAbsolute(false);
}
}
if ($request->getData('content') !== null) {
\file_put_contents(
$media->isAbsolute() ? $media->getPath() : __DIR__ . '/../../../' . \ltrim($media->getPath(), '/'),
$media->isAbsolute() ? $media->getPath() : __DIR__ . '/../../../' . \ltrim($media->getPath(), '\\/'),
$request->getData('content')
);
@ -382,9 +400,7 @@ final class ApiController extends Controller
private function validateCollectionCreate(RequestAbstract $request) : array
{
$val = [];
if (($val['name'] = empty($request->getData('name')))
|| ($val['media'] = empty($request->getDataJson('media-list')))
) {
if (($val['name'] = empty($request->getData('name')))) {
return $val;
}
@ -413,8 +429,20 @@ final class ApiController extends Controller
$mediaCollection->addSource(new NullMedia((int) $file));
}
$mediaCollection->setVirtualPath($request->getData('virtualpath') ?? '/');
$mediaCollection->setPath($request->getData('virtualpath') ?? '/');
$virtualPath = \urldecode((string) ($request->getData('virtualpath') ?? '/'));
$outputDir = '';
if (empty($request->getData('path'))) {
$outputDir = self::createMediaPath(__DIR__ . '/../../../Modules/Media/Files');
} else {
$outputDir = __DIR__ . '/../../../Modules/Media/Files/' . \ltrim($request->getData('path'), '\\/');
Directory::create($outputDir . '/' . $request->getData('name'), 0775, true);
}
$outputDir = \substr($outputDir, \strlen(__DIR__ . '/../../..'));
$mediaCollection->setVirtualPath($virtualPath);
$mediaCollection->setPath($outputDir);
CollectionMapper::create($mediaCollection);
@ -453,10 +481,8 @@ final class ApiController extends Controller
$mediaCollection->setDescriptionRaw($description);
$mediaCollection->setCreatedBy(new NullAccount($account));
$mediaCollection->setSources($media);
$mediaCollection->setVirtualPath('/Modules/Helper');
$mediaCollection->setPath('/Modules/Helper');
CollectionMapper::create($mediaCollection);
$mediaCollection->setVirtualPath('/');
$mediaCollection->setPath('/Modules/Media/Files');
return $mediaCollection;
}
@ -476,23 +502,28 @@ final class ApiController extends Controller
*/
public function apiMediaCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void
{
$virtualPath = \urldecode((string) ($request->getData('path') ?? ''));
$path = \urldecode((string) ($request->getData('path') ?? ''));
$virtualPath = \urldecode((string) ($request->getData('virtualpath') ?? ''));
$fileName = (string) ($request->getData('fileName') ?? ($request->getData('name') ?? ''));
$fileName .= \strripos($fileName, '.') === false ? '.txt' : '';
$pathSettings = (int) ($request->getData('pathsettings') ?? PathSettings::RANDOM_PATH);
$outputDir = '';
if ($pathSettings === PathSettings::RANDOM_PATH) {
if (empty($request->getData('path'))) {
$outputDir = self::createMediaPath(__DIR__ . '/../../../Modules/Media/Files');
} elseif ($pathSettings === PathSettings::FILE_PATH) {
$outputDir = __DIR__ . '/../../../Modules/Media/Files/' . \ltrim($virtualPath, '\\/');
} else {
$outputDir = __DIR__ . '/../../../Modules/Media/Files/' . \ltrim($path, '\\/');
}
if (!\is_dir($outputDir)) {
Directory::create($outputDir, 0755, true);
$created = Directory::create($outputDir, 0775, true);
if (!$created) {
throw new \Exception('Couldn\'t create outputdir: "' . $outputDir . '"');
}
}
\file_put_contents($outputDir . '/' . $fileName, (string) ($request->getData('content') ?? ''));
$outputDir = \substr($outputDir, \strlen(__DIR__ . '/../../..'));
$status = [
[

View File

@ -19,6 +19,7 @@ use Modules\Media\Models\Collection;
use Modules\Media\Models\CollectionMapper;
use Modules\Media\Models\Media;
use Modules\Media\Models\MediaMapper;
use Modules\Media\Models\NullMedia;
use Modules\Media\Views\MediaView;
use phpOMS\Asset\AssetType;
use phpOMS\Contract\RenderableInterface;
@ -130,16 +131,32 @@ final class BackendController extends Controller
$media = MediaMapper::getByVirtualPath($path);
$collection = CollectionMapper::getParentCollection(\str_replace('+', ' ', $path));
if (\is_array($collection) && \is_dir(__DIR__ . '/../Files' . $path)) {
$collection = new Collection();
$collection->setName(\basename($path));
$collection->setVirtualPath(\dirname($path));
$collection->setPath(\dirname($path));
$collection->setAbsolute(false);
}
if ($collection instanceof Collection) {
$media += $collection->getSources();
/** @var string[] $glob */
$glob = \glob(__DIR__ . '/../Files' . \trim($collection->getPath(), '/') . '/' . $collection->getName() . '/*');
$glob = $collection->isAbsolute()
? $collection->getPath() . '/' . $collection->getName() . '/*'
: \glob(__DIR__ . '/../Files' . '/' . \rtrim($collection->getPath(), '/') . '/' . $collection->getName() . '/*');
$glob = $glob === false ? [] : $glob;
foreach ($glob as $file) {
foreach ($media as $obj) {
if ($obj->getName() . '.' . $obj->getExtension() === \basename($file)) {
if (($obj->getExtension() !== 'collection'
&& !empty($obj->getExtension())
&& $obj->getName() . '.' . $obj->getExtension() === \basename($file))
|| ($obj->getExtension() === 'collection'
&& $obj->getName() === \basename($file))
) {
continue 2;
}
}
@ -148,7 +165,8 @@ final class BackendController extends Controller
$localMedia = new Media();
$localMedia->setName($pathinfo['filename']);
$localMedia->setExtension($pathinfo['extension'] ?? '');
$localMedia->setExtension(\is_dir($file) ? 'collection' : $pathinfo['extension'] ?? '');
$localMedia->setVirtualPath($path);
$localMedia->setCreatedBy(new Account());
$media[] = $localMedia;
@ -179,10 +197,10 @@ final class BackendController extends Controller
$view->setTemplate('/Modules/Media/Theme/Backend/media-single');
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1000401001, $request, $response));
$media = MediaMapper::get((int) $request->getData('id'));
$id = (int) $request->getData('id');
$media = MediaMapper::get($id);
if ($media->getExtension() === 'collection') {
//$media = CollectionMapper::get($media->getId());
$media = MediaMapper::getByVirtualPath(
$media->getVirtualPath() . ($media->getVirtualPath() !== '/' ? '/' : '') . $media->getName()
);
@ -194,6 +212,22 @@ final class BackendController extends Controller
$view->setTemplate('/Modules/Media/Theme/Backend/media-list');
}
if ($id == 0) {
$path = \urldecode($request->getData('path'));
if ($media instanceof NullMedia
&& \is_file(__DIR__ . '/../Files' . $path)
) {
$name = \explode('.', \basename($path));
$media->setName($name[0]);
$media->setExtension($name[1] ?? '');
$media->setVirtualPath(\dirname($path));
$media->setPath('/Modules/Media/Files/' . \ltrim($path, '\\/'));
$media->setAbsolute(false);
}
}
$view->addData('media', $media);
return $view;

4
Docs/Dev/en/SUMMARY.md Normal file
View File

@ -0,0 +1,4 @@
# Developer Content
* [Media]({%}&page=Dev/media)
* [Collection]({%}&page=Dev/collection)

View File

@ -0,0 +1,7 @@
# Collection
A collection is a special `Media` element similar to directories. A collection can contain other collections, media elements and hard drive files & directories.
If a directory on the hard drive has the same path as the virtual path of the colllection, all files in that directory are also shown as part of that collection. If the content of the hard drive directory changes the colllection also shows the changed content.
A collection doesn't need to have a hard drive directory, this is optional.

24
Docs/Dev/en/media.md Normal file
View File

@ -0,0 +1,24 @@
# Media
A media element is used in order to handle files, directories, virtual directories and other resources (e.g. links, external resource such as dropbox etc.).
## Path
### File system
The path is either the absolute path on the file system or relative path in relation to applications path. If the path is an absolute path the media element also needs to be set to `isAbsolute() === true`. The path includes the file itself.
## Virtual Path
The virtual path is the virtual location where it should show up in the media module. This makes it possible to change the visual location without changing the physical storage location. Additionally, this makes it also possible to reference the same physical file from different locations. Think about it similar to `symlink`
## Absolute
Is the file path an absolute file path or a relative file path (relative to the application path).
## Extensions
The extension can be one of the following two:
1. Extension of the file
2. `collection` if it is a virtual directory/collection

3
Docs/Help/en/SUMMARY.md Normal file
View File

@ -0,0 +1,3 @@
# Developer Content
* [Templates]({%}&page=Dev/api_template)

View File

@ -156,6 +156,8 @@ class Media implements \JsonSerializable
{
$this->createdBy = new NullAccount();
$this->createdAt = new \DateTime();
$this->setExtension('colection');
}
/**
@ -337,7 +339,7 @@ class Media implements \JsonSerializable
*/
public function getPath() : string
{
return $this->isAbsolute ? $this->path : \ltrim($this->path, '/');
return $this->isAbsolute ? $this->path : \ltrim($this->path, '\\/');
}
/**

View File

@ -42,5 +42,6 @@ return ['Media' => [
'Size' => 'Größe',
'Type' => 'Typ',
'Upload' => 'Hochladen',
'VirtualPath' => 'Virtueller Pfad',
'Visibility' => 'Sichtbarkeit',
]];

View File

@ -42,5 +42,6 @@ return ['Media' => [
'Size' => 'Size',
'Type' => 'Type',
'Upload' => 'Upload',
'VirtualPath' => 'Virtual Path',
'Visibility' => 'Visibility',
]];

View File

@ -0,0 +1,63 @@
<?php
/**
* Orange Management
*
* PHP Version 7.4
*
* @package Modules\Media
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
use phpOMS\Uri\UriFactory;
/**
* @todo Orange-Management/Modules#58
* Implement drag/drop upload
*/
/**
* @var \phpOMS\Views\View $this
*/
?>
<div class="row">
<div class="col-xs-12">
<div class="box">
<a tabindex="0" class="button" href="<?= UriFactory::build('{/prefix}media/list?path={?path}'); ?>"><?= $this->getHtml('Back', '0', '0'); ?></a>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<form method="PUT" id="media-uploader" action="<?= UriFactory::build('{/api}media/collection'); ?>">
<div class="portlet">
<div class="portlet-head"><?= $this->getHtml('CreateCollection') ?></div>
<div class="portlet-body">
<table class="layout wf-100">
<tr><td><label for="iVirtualPath"><?= $this->getHtml('VirtualPath') ?></label>
<tr><td><input type="text" id="iVirtualPath" name="virtualPath" value="<?= empty($this->request->getUri()->getQuery('path')) ? '/' : $this->request->getUri()->getQuery('path'); ?>" disabled>
<tr><td><label for="iPath"><?= $this->getHtml('Path') ?></label>
<tr><td><input type="text" id="iPath" name="path" value="<?= empty($this->request->getUri()->getQuery('path')) ? '/' : $this->request->getUri()->getQuery('path'); ?>">
<tr><td><label><?= $this->getHtml('Settings') ?></label>
<tr><td>
<label class="checkbox" for="iAddCollection">
<input type="checkbox" id="iAddCollection" name="addcollection" checked>
<span class="checkmark"></span>
<?= $this->getHtml('AddToCollection') ?>
</label>
<tr><td><label for="iName"><?= $this->getHtml('Name') ?></label>
<tr><td><input type="text" id="iName" name="name" multiple>
</table>
</div>
<div class="portlet-foot">
<input type="submit" id="iMediaCreate" name="mediaCreateButton" value="<?= $this->getHtml('Create', '0', '0'); ?>">
</div>
</form>
</div>
</div>
</div>

View File

@ -19,23 +19,10 @@ use phpOMS\Uri\UriFactory;
*/
?>
<div class="row">
<div class="col-xs-12">
<div class="box">
<a tabindex="0" class="button" href="<?= UriFactory::build('{/prefix}media/list?path={?path}'); ?>"><?= $this->getHtml('Back'); ?></a>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="col-xs-12 col-md-8">
<div class="portlet">
<div class="portlet-body">
<form id="fEditor" method="PUT" action="<?= UriFactory::build('{/api}media/file?{?}&csrf={$CSRF}'); ?>">
<div class="ipt-wrap">
<div class="ipt-first"><input autocomplete="off" name="name" type="text" class="wf-100"></div>
<div class="ipt-second"><input type="submit" value="<?= $this->getHtml('Save', '0', '0') ?>"></div>
</div>
</form>
<input autocomplete="off" form="fEditor" name="name" type="text" class="wf-100">
</div>
</div>
@ -49,4 +36,50 @@ use phpOMS\Uri\UriFactory;
<?= $this->getData('editor')->getData('text')->render('editor', 'content', 'fEditor'); ?>
</div>
</div>
<div class="col-xs-12 col-md-4">
<div class="box">
<a tabindex="0" class="button" href="<?= UriFactory::build('{/prefix}media/list?path={?path}'); ?>"><?= $this->getHtml('Back'); ?></a>
</div>
<div class="portlet">
<form id="fEditor" method="PUT" action="<?= UriFactory::build('{/api}media/file?{?}&csrf={$CSRF}'); ?>">
<div class="portlet-head"><?= $this->getHtml('Settings'); ?></div>
<div class="portlet-body">
<table class="layout wf-100">
<tr><td><label for="iVirtualPath"><?= $this->getHtml('VirtualPath') ?></label>
<tr><td><input type="text" id="iVirtualPath" name="virtualPath" value="<?= empty($this->request->getUri()->getQuery('path')) ? '/' : $this->request->getUri()->getQuery('path'); ?>" disabled>
<tr><td><label for="iPath"><?= $this->getHtml('Path') ?></label>
<tr><td><input type="text" id="iPath" name="path" value="<?= empty($this->request->getUri()->getQuery('path')) ? '/' : $this->request->getUri()->getQuery('path'); ?>">
<tr><td><label><?= $this->getHtml('Settings') ?></label>
<tr><td>
<label class="checkbox" for="iAddCollection">
<input type="checkbox" id="iAddCollection" name="addcollection" checked>
<span class="checkmark"></span>
<?= $this->getHtml('AddToCollection') ?>
</label>
</table>
</div>
<div class="portlet-foot">
<input type="submit" value="<?= $this->getHtml('Save', '0', '0') ?>">
</div>
</form>
</div>
<div class="portlet">
<div class="portlet-body">
<form>
<table class="layout">
<tr><td colspan="2"><label><?= $this->getHtml('Permission'); ?></label>
<tr><td><select>
<option>
</select>
<tr><td colspan="2"><label><?= $this->getHtml('GroupUser'); ?></label>
<tr><td><input id="iPermission" name="group" type="text" placeholder="&#xf084;"><td><button><?= $this->getHtml('Add'); ?></button>
</table>
</form>
</div>
</div>
</div>
</div>

View File

@ -13,6 +13,7 @@
declare(strict_types=1);
use phpOMS\Uri\UriFactory;
use phpOMS\System\File\FileUtils;
include __DIR__ . '/template-functions.php';
@ -27,8 +28,8 @@ $mediaPath = \urldecode($this->getData('path') ?? '/');
*/
$media = $this->getData('media');
$previous = empty($media) ? '{/prefix}media/list' : '{/prefix}media/list?{?}&id=' . \reset($media)->getId() . '&ptype=-';
$next = empty($media) ? '{/prefix}media/list' : '{/prefix}media/list?{?}&id=' . \end($media)->getId() . '&ptype=+';
$previous = empty($media) ? '{/prefix}media/list' : '{/prefix}media/list?{?}&id=' . \reset($media)->getId() . '&ptype=p';
$next = empty($media) ? '{/prefix}media/list' : '{/prefix}media/list?{?}&id=' . \end($media)->getId() . '&ptype=n';
?>
<div class="row">
@ -87,9 +88,15 @@ $next = empty($media) ? '{/prefix}media/list' : '{/prefix}media/list?{?}&id=
$url = $value->getExtension() === 'collection'
? UriFactory::build('{/prefix}media/list?path=' . \rtrim($value->getVirtualPath(), '/') . '/' . $value->getName())
: UriFactory::build('{/prefix}media/single?id=' . $value->getId() . '&path={?path}');
: UriFactory::build('{/prefix}media/single?id=' . $value->getId()
. '&path={?path}' . (
$value->getId() === 0
? '/' . $value->getName() . (!empty($value->getExtension()) ? '.' . $value->getExtension() : '')
: ''
)
);
$icon = $fileIconFunction(\phpOMS\System\File\FileUtils::getExtensionType($value->getExtension()));
$icon = $fileIconFunction(FileUtils::getExtensionType($value->getExtension()));
?>
<tr tabindex="0" data-href="<?= $url; ?>">
<td data-label="<?= $this->getHtml('Type') ?>"><a href="<?= $url; ?>"><i class="fa fa-<?= $this->printHtml($icon); ?>"></i></a>

View File

@ -28,7 +28,7 @@ echo $this->getData('nav')->render();
<div class="col-xs-12">
<div class="box">
<?php if ($this->request->getData('path') !== null) : ?>
<a tabindex="0" class="button" href="<?= UriFactory::build('{/prefix}media/list?path={?path}'); ?>"><?= $this->getHtml('Back'); ?></a>
<a tabindex="0" class="button" href="<?= UriFactory::build('{/prefix}media/list?path=' . ($media->getId() === 0 ? $media->getVirtualPath() : '{?path}')); ?>"><?= $this->getHtml('Back'); ?></a>
<?php else: ?>
<a tabindex="0" class="button" href="<?= UriFactory::build('{/prefix}media/list'); ?>"><?= $this->getHtml('Back'); ?></a>
<?php endif; ?>

View File

@ -12,7 +12,6 @@
*/
declare(strict_types=1);
use Modules\Media\Models\PathSettings;
use phpOMS\Uri\UriFactory;
/**
@ -28,7 +27,7 @@ use phpOMS\Uri\UriFactory;
<div class="row">
<div class="col-xs-12">
<div class="box">
<a tabindex="0" class="button" href="<?= UriFactory::build('{/prefix}media/list?path={?path}'); ?>">Back</a>
<a tabindex="0" class="button" href="<?= UriFactory::build('{/prefix}media/list?path={?path}'); ?>"><?= $this->getHtml('Back', '0', '0'); ?></a>
</div>
</div>
</div>
@ -40,8 +39,10 @@ use phpOMS\Uri\UriFactory;
<div class="portlet-head"><?= $this->getHtml('Upload') ?></div>
<div class="portlet-body">
<table class="layout wf-100">
<tr><td><label for="iVirtualPath"><?= $this->getHtml('VirtualPath') ?></label>
<tr><td><input type="text" id="iVirtualPath" name="virtualPath" value="<?= empty($this->request->getUri()->getQuery('path')) ? '/' : $this->request->getUri()->getQuery('path'); ?>" disabled>
<tr><td><label for="iPath"><?= $this->getHtml('Path') ?></label>
<tr><td><input type="text" id="iPath" name="virtualPath" value="<?= empty($this->request->getUri()->getQuery('path')) ? '/' : $this->request->getUri()->getQuery('path'); ?>" disabled>
<tr><td><input type="text" id="iPath" name="path" value="<?= empty($this->request->getUri()->getQuery('path')) ? '/' : $this->request->getUri()->getQuery('path'); ?>">
<tr><td><label><?= $this->getHtml('Settings') ?></label>
<tr><td>
<label class="checkbox" for="iAddCollection">
@ -49,12 +50,6 @@ use phpOMS\Uri\UriFactory;
<span class="checkmark"></span>
<?= $this->getHtml('AddToCollection') ?>
</label>
<tr><td><label for="iPathSettings"><?= $this->getHtml('PathSettings') ?></label>
<tr><td>
<select id="iPathSettings" name="pathsettings">
<option value="<?= PathSettings::FILE_PATH ?>" selected><?= $this->getHtml('FilePath') ?>
<option value="<?= PathSettings::RANDOM_PATH ?>"><?= $this->getHtml('RandomPath') ?>
</select>
<tr><td><label for="iFiles"><?= $this->getHtml('Files') ?></label>
<tr><td><input type="file" id="iFiles" name="files" multiple>
</table>