improve media view

This commit is contained in:
Dennis Eichhorn 2020-02-09 15:45:58 +01:00
parent 9563866507
commit b1c868ade0
18 changed files with 315 additions and 105 deletions

View File

@ -13,36 +13,6 @@
"permission": { "permission": 2, "type": null, "element": null },
"parent": 1006901001,
"children": [
{
"id": 1000402001,
"pid": "/media",
"type": 3,
"subtype": 1,
"name": "List",
"uri": "{/prefix}media/list?{?}",
"target": "self",
"icon": null,
"order": 1,
"from": "Media",
"permission": { "permission": 2, "type": null, "element": null },
"parent": 1000401001,
"children": []
},
{
"id": 1000403001,
"pid": "/media",
"type": 3,
"subtype": 5,
"name": "Create",
"uri": "{/prefix}media/create?{?}",
"target": "self",
"icon": null,
"order": 5,
"from": "Media",
"permission": { "permission": 4, "type": null, "element": null },
"parent": 1000401001,
"children": []
}
]
},
{

View File

@ -37,6 +37,11 @@
"type": "TINYINT",
"null": false
},
"media_hidden": {
"name": "media_hidden",
"type": "TINYINT",
"null": false
},
"media_file": {
"name": "media_file",
"type": "VARCHAR(255)",

View File

@ -84,6 +84,7 @@ class Installer extends InstallerAbstract
$collection = new Collection();
$collection->setName((string) $data['name'] ?? '');
$collection->setVirtualPath((string) $data['virtualPath'] ?? '/');
$collection->setPath((string) $data['virtualPath'] ?? '/');
$collection->setCreatedBy((int) $data['user'] ?? 1);
CollectionMapper::create($collection);

View File

@ -15,11 +15,6 @@ return [
'type' => PermissionType::CREATE,
'state' => PermissionState::MEDIA,
],
'data' => [
'field_name' => [
'type' => 'string', 'default' => 'Hello', 'validation' => '[\\w]*', 'required' => false,'annotation' => [],
],
],
],
[
'dest' => '\Modules\Media\Controller\ApiController:apiMediaUpdate',

View File

@ -17,9 +17,9 @@ return [
],
],
],
'^.*/media/create.*$' => [
'^.*/media/upload.*$' => [
[
'dest' => '\Modules\Media\Controller\BackendController:setUpFileUploader',
'dest' => '\Modules\Media\Controller\BackendController:viewMediaUpload',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::MODULE_NAME,
@ -27,8 +27,21 @@ return [
'state' => PermissionState::MEDIA,
],
],
],
'^.*/media/file/create.*$' => [
[
'dest' => '\Modules\Media\Controller\BackendController:viewMediaCreate',
'dest' => '\Modules\Media\Controller\BackendController:viewMediaFileCreate',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::MODULE_NAME,
'type' => PermissionType::CREATE,
'state' => PermissionState::MEDIA,
],
],
],
'^.*/media/collection/create.*$' => [
[
'dest' => '\Modules\Media\Controller\BackendController:viewMediaCollectionCreate',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::MODULE_NAME,

View File

@ -20,6 +20,7 @@ use Modules\Media\Models\CollectionMapper;
use Modules\Media\Models\Media;
use Modules\Media\Models\MediaMapper;
use Modules\Media\Models\NullCollection;
use Modules\Media\Models\PathSettings;
use Modules\Media\Models\PermissionState;
use Modules\Media\Models\UploadFile;
use Modules\Media\Models\UploadStatus;
@ -102,7 +103,8 @@ final class ApiController extends Controller
(string) ($request->getData('path') ?? __DIR__ . '/../../../Modules/Media/Files'),
(string) ($request->getData('virtualPath') ?? ''),
(string) ($request->getData('password') ?? ''),
(string) ($request->getData('encrypt') ?? '')
(string) ($request->getData('encrypt') ?? ''),
(int) ($request->getData('pathsettings') ?? PathSettings::RANDOM_PATH)
);
$ids = [];
@ -114,10 +116,19 @@ final class ApiController extends Controller
}
/**
* @param string $name Name
* @param array $files Files
* @param int $account Uploader
* @param string $basePath Base path
* Upload a media file
*
* @param string $name Name
* @param array $files Files
* @param int $account Uploader
* @param string $basePath Base path. The path which is used for the upload.
* @param string $virtualPath Virtual path The path which is used to visually structure the files, like directories.
* The file storage on the system can be different
* @param string $password File password. The password to protect the file (only database)
* @param string $encryptionKey Encryption key. Used to encrypt the file on the local file storage.
* @param int $pathSettings Settings which describe where the file should be uploaded to (physically)
* RANDOM_PATH = random location in the base path
* FILE_PATH = combination of base path and virtual path
*
* @return array
*
@ -130,16 +141,28 @@ final class ApiController extends Controller
string $basePath = 'Modules/Media/Files',
string $virtualPath = '',
string $password = '',
string $encryptionKey = ''
) : array
{
string $encryptionKey = '',
int $pathSettings = PathSettings::RANDOM_PATH
) : array {
$mediaCreated = [];
if (!empty($files)) {
$upload = new UploadFile();
$upload->setOutputDir(self::createMediaPath($basePath));
$outputDir = '';
$absolute = false;
$status = $upload->upload($files, $name, $encryptionKey);
if ($pathSettings === PathSettings::RANDOM_PATH) {
$outputDir = self::createMediaPath($basePath);
} elseif ($pathSettings === PathSettings::FILE_PATH) {
$outputDir = $basePath . $virtualPath;
$absolute = true;
} else {
return $mediaCreated;
}
$upload = new UploadFile();
$upload->setOutputDir($outputDir);
$status = $upload->upload($files, $name, $absolute, $encryptionKey);
$mediaCreated = $this->createDbEntries($status, $account, $virtualPath);
}
@ -332,6 +355,7 @@ final class ApiController extends Controller
$mediaCollection->setCreatedBy($account);
$mediaCollection->setSources($media);
$mediaCollection->setVirtualPath('/Modules/Helper');
$mediaCollection->setPath('/Modules/Helper');
CollectionMapper::create($mediaCollection);

View File

@ -14,11 +14,11 @@ declare(strict_types=1);
namespace Modules\Media\Controller;
use Modules\Admin\Models\Account;
use Modules\Media\Models\CollectionMapper;
use Modules\Media\Models\Media;
use Modules\Media\Models\MediaMapper;
use Modules\Media\Views\MediaView;
use phpOMS\Asset\AssetType;
use phpOMS\Contract\RenderableInterface;
use phpOMS\Message\RequestAbstract;
@ -127,11 +127,34 @@ final class BackendController extends Controller
{
$view = new View($this->app->l11nManager, $request, $response);
$view->setTemplate('/Modules/Media/Theme/Backend/media-list');
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1000401001, $request, $response));
$path = (string) ($request->getData('path') ?? '/');
$media = MediaMapper::getByVirtualPath($path);
$collection = CollectionMapper::getParentCollection($path);
if (!empty($collection)) {
$media += $collection->getSources();
$glob = \glob(__DIR__ . '/../Files' . \trim($collection->getPath(), '/') . '/' . $collection->getName() . '/*');
foreach ($glob as $file) {
foreach ($media as $obj) {
if ($obj->getName() . '.' . $obj->getExtension() === \basename($file)){
continue 2;
}
}
$pathinfo = \pathinfo($file);
$localMedia = new Media();
$localMedia->setName($pathinfo['filename']);
$localMedia->setExtension($pathinfo['extension']);
$localMedia->setCreatedBy(new Account());
$media[] = $localMedia;
}
}
$view->addData('media', $media);
$view->addData('path', $path);
@ -193,11 +216,50 @@ final class BackendController extends Controller
* @since 1.0.0
* @codeCoverageIgnore
*/
public function viewMediaCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
public function viewMediaUpload(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
{
$view = new View($this->app->l11nManager, $request, $response);
$view->setTemplate('/Modules/Media/Theme/Backend/media-create');
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1000401001, $request, $response));
$view->setTemplate('/Modules/Media/Theme/Backend/media-upload');
return $view;
}
/**
* Routing end-point for application behaviour.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
* @param mixed $data Generic data
*
* @return RenderableInterface
*
* @since 1.0.0
* @codeCoverageIgnore
*/
public function viewMediaFileCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
{
$view = new View($this->app->l11nManager, $request, $response);
$view->setTemplate('/Modules/Media/Theme/Backend/media-file-create');
return $view;
}
/**
* Routing end-point for application behaviour.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
* @param mixed $data Generic data
*
* @return RenderableInterface
*
* @since 1.0.0
* @codeCoverageIgnore
*/
public function viewMediaCollectionCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
{
$view = new View($this->app->l11nManager, $request, $response);
$view->setTemplate('/Modules/Media/Theme/Backend/media-collection-create');
return $view;
}

View File

@ -27,7 +27,7 @@ class Collection extends Media implements \Iterator
/**
* Resource id.
*
* @var array<int|Media>
* @var array<int, int|Media>
* @since 1.0.0
*/
private $sources = [];

View File

@ -136,6 +136,14 @@ class Media implements \JsonSerializable
*/
protected ?string $password = null;
/**
* Media is hidden.
*
* @var bool
* @since 1.0.0
*/
protected bool $hidden = false;
/**
* Constructor.
*
@ -494,6 +502,28 @@ class Media implements \JsonSerializable
$this->versioned = $versioned;
}
/**
* @return bool
*
* @since 1.0.0
*/
public function isHidden() : bool
{
return $this->hidden;
}
/**
* @param bool $hidden File is hidden
*
* @return void
*
* @since 1.0.0
*/
public function setHidden(bool $hidden) : void
{
$this->hidden = $hidden;
}
/**
* {@inheritdoc}
*/
@ -504,7 +534,9 @@ class Media implements \JsonSerializable
'name' => $this->name,
'description' => $this->description,
'extension' => $this->extension,
'virtualpath' => $this->virtualPath,
'size' => $this->size,
'hidden' => $this->hidden,
];
}

View File

@ -39,6 +39,7 @@ class MediaMapper extends DataMapperAbstract
'media_description' => ['name' => 'media_description', 'type' => 'string', 'internal' => 'description', 'autocomplete' => true],
'media_description_raw' => ['name' => 'media_description_raw', 'type' => 'string', 'internal' => 'descriptionRaw'],
'media_versioned' => ['name' => 'media_versioned', 'type' => 'bool', 'internal' => 'versioned'],
'media_hidden' => ['name' => 'media_hidden', 'type' => 'bool', 'internal' => 'hidden'],
'media_file' => ['name' => 'media_file', 'type' => 'string', 'internal' => 'path', 'autocomplete' => true],
'media_virtual' => ['name' => 'media_virtual', 'type' => 'string', 'internal' => 'virtualPath', 'autocomplete' => true],
'media_absolute' => ['name' => 'media_absolute', 'type' => 'bool', 'internal' => 'isAbsolute'],
@ -103,16 +104,44 @@ class MediaMapper extends DataMapperAbstract
* path if so desired without deleting or moving the orginal media files.
*
* @param string $virtualPath Virtual path
* @param string $hidden Get hidden files
*
* @return array
*
* @since 1.0.0
*/
public static function getByVirtualPath(string $virtualPath = '/') : array
public static function getByVirtualPath(string $virtualPath = '/', bool $hidden = false) : array
{
$query = self::getQuery();
$query->where(self::$table . '.media_virtual', '=', $virtualPath);
if ($hidden === false) {
$query->where(self::$table . '.media_hidden', '=', (int) $hidden);
}
return self::getAllByQuery($query);
}
/**
* Get parent collection
*
* @param string $path Virtual path
*
* @return mixed
*
* @since 1.0.0
*/
public static function getParentCollection(string $path = '/')
{
$virtualPath = \substr($path, 0, \strripos($path, '/') + 1);
$name = \substr($path, \strripos($path, '/') + 1);
$query = self::getQuery();
$query->where(self::$table . '.media_virtual', '=', $virtualPath)
->andWhere(self::$table . '.media_name', '=', $name);
$objs = self::getAllByQuery($query);
return \count($objs) === 1 ? \reset($objs) : $objs;
}
}

32
Models/PathSettings.php Normal file
View File

@ -0,0 +1,32 @@
<?php
/**
* Orange Management
*
* PHP Version 7.4
*
* @package Modules\Media\Models
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
namespace Modules\Media\Models;
use phpOMS\Stdlib\Base\Enum;
/**
* Path settings enum.
*
* @package Modules\Media\Models
* @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*/
abstract class PathSettings extends Enum
{
public const FILE_PATH = 1;
public const RANDOM_PATH = 2;
public const COLLECTION_PATH = 3;
}

View File

@ -89,6 +89,7 @@ class UploadFile
*
* @param array $files File data ($_FILE)
* @param string $name File name
* @param bool $absolute Use absolute path
* @param string $encryptionKey Encryption key
* @param string $encoding Encoding used for uploaded file. Empty string will not convert file content.
*
@ -98,16 +99,21 @@ class UploadFile
*
* @since 1.0.0
*/
public function upload(array $files, string $name = '', string $encryptionKey = '', string $encoding = 'UTF-8') : array
{
public function upload(
array $files,
string $name = '',
bool $absolute = false,
string $encryptionKey = '',
string $encoding = 'UTF-8'
) : array {
$result = [];
if (\count($files) === \count($files, \COUNT_RECURSIVE)) {
$files = [$files];
}
if (\count($files) > 1) {
$this->outputDir = $this->findOutputDir($files);
if (!$absolute && \count($files) > 1) {
$this->outputDir = $this->findOutputDir();
}
$path = $this->outputDir;
@ -308,13 +314,11 @@ class UploadFile
/**
* Find unique output path for batch of files
*
* @param array $files Array of files
*
* @return string
*
* @since 1.0.0
*/
private function findOutputDir(array $files) : string
private function findOutputDir() : string
{
do {
$rndPath = \str_pad(\dechex(\mt_rand(0, 65535)), 4, '0', \STR_PAD_LEFT);

View File

@ -14,6 +14,7 @@ declare(strict_types=1);
return ['Media' => [
'Account' => 'Account',
'AddToCollection' => 'Add to collection',
'Author' => 'Author',
'Changed' => 'Changed',
'Changedby' => 'Changed by',
@ -24,11 +25,15 @@ return ['Media' => [
'Edit' => 'Edit',
'Editability' => 'Editability',
'Extension' => 'Extension',
'FilePath' => 'File Path',
'Files' => 'Files',
'Media' => 'Media',
'Name' => 'Name',
'Path' => 'Path',
'PathSettings' => 'Path Settings',
'Permission' => 'Permission',
'Preview' => 'Preview',
'RandomPath' => 'Random Path',
'Select' => 'Select',
'Settings' => 'Settings',
'Size' => 'Size',

View File

@ -1,39 +0,0 @@
<?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);
/**
* @todo Orange-Management/Modules#58
* Implement drag/drop upload
*/
/**
* @var \phpOMS\Views\View $this
*/
echo $this->getData('nav')->render(); ?>
<div class="row">
<div class="col-xs-12 col-md-6">
<section class="box wf-100">
<header><h1><?= $this->getHtml('Upload') ?></h1></header>
<div class="inner">
<form method="POST" id="media-uploader" action="">
<table class="layout wf-100">
<tr><td><label for="iFiles"><?= $this->getHtml('Files') ?></label>
<tr><td><input type="file" id="iFiles" name="files" multiple><input name="media" type="hidden">
<tr><td><input type="submit" id="iMediaCreate" name="mediaCreateButton" value="<?= $this->getHtml('Create', '0', '0'); ?>">
</table>
</form>
</div>
</section>
</div>
</div>

View File

View File

@ -12,6 +12,7 @@
*/
declare(strict_types=1);
use Modules\Media\Models\Collection;
use phpOMS\Uri\UriFactory;
include __DIR__ . '/template-functions.php';
@ -26,8 +27,17 @@ $mediaPath = $this->getData('path') ?? '/';
* @var \Modules\Media\Models\Media[] $media
*/
$media = $this->getData('media');
?>
echo $this->getData('nav')->render(); ?>
<div class="row">
<div class="col-xs-12">
<div class="box">
<a class="button" href="<?= UriFactory::build('{/prefix}media/upload?path={?path}'); ?>">Upload</a>
<a class="button" href="<?= UriFactory::build('{/prefix}media/file/create?path={?path}'); ?>">Create File</a>
<a class="button" href="<?= UriFactory::build('{/prefix}media/collection/create?path={?path}'); ?>">Create Collection</a>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
@ -72,12 +82,18 @@ echo $this->getData('nav')->render(); ?>
<?php $count = 0;
foreach ($media as $key => $value) :
++$count;
$url = UriFactory::build('{/prefix}media/single?id=' . $value->getId());
if ($value->getExtension() === 'collection') {
$url = UriFactory::build('{/prefix}media/list?path=' . \rtrim($value->getVirtualPath(), '/') . '/' . $value->getName());
} else {
$url = UriFactory::build('{/prefix}media/single?id=' . $value->getId());
}
$icon = $fileIconFunction(\phpOMS\System\File\FileUtils::getExtensionType($value->getExtension()));
?>
<tr data-href="<?= $url; ?>">
<td data-label="<?= $this->getHtml('Type') ?>"><a href="<?= $url; ?>"><i class="fa fa-<?= $this->printHtml($icon); ?>"></i></a>
<td data-label="<?= $this->getHtml('Name') ?>"><a href="<?= $url; ?>"><?= $this->printHtml($value->getName()); ?></a>
<td data-label="<?= $this->getHtml('Name') ?>"><a href="<?= $url; ?>"><?= $this->printHtml(
$value->getExtension() !== 'collection' ? $value->getName() . '.' . $value->getExtension() : $value->getName()); ?></a>
<td data-label="<?= $this->getHtml('Extension') ?>"><a href="<?= $url; ?>"><?= $this->printHtml($value->getExtension()); ?></a>
<td data-label="<?= $this->getHtml('Size') ?>"><a href="<?= $url; ?>"><?= $this->printHtml($value->getSize()); ?></a>
<td data-label="<?= $this->getHtml('Creator') ?>"><a href="<?= $url; ?>"><?= $this->printHtml($value->getCreatedBy()->getName1()); ?></a>

View File

@ -0,0 +1,61 @@
<?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 Modules\Media\Models\PathSettings;
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 class="button" href="<?= UriFactory::build('{/prefix}media/list?path={?path}'); ?>">Back</a>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<section class="box wf-100">
<header><h1><?= $this->getHtml('Upload') ?></h1></header>
<div class="inner">
<form method="PUT" id="media-uploader" action="<?= UriFactory::build('{/api}media'); ?>">
<table class="layout wf-100">
<tr><td><label for="iPath"><?= $this->getHtml('Path') ?></label>
<tr><td><input type="text" id="iPath" name="virtualPath" value="<?= $this->request->getUri()->getQuery('path') ?? ''; ?>" disabled>
<tr><td><label><?= $this->getHtml('Settings') ?></label>
<tr><td><input type="checkbox" id="iAddCollection" name="addcollection" checked><label for="iAddCollection"><?= $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>
<tr><td><input type="submit" id="iMediaCreate" name="mediaCreateButton" value="<?= $this->getHtml('Create', '0', '0'); ?>">
</table>
</form>
</div>
</section>
</div>
</div>