From 4b9610f341f5c405645ad62a3db2cf3f56447f0a Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 30 Jul 2020 21:24:32 +0200 Subject: [PATCH] make media handle upload, create file and collection more uniform --- Admin/Installer.php | 2 +- Admin/Routes/Web/Api.php | 11 +++ Controller/ApiController.php | 71 +++++++++++++------ Controller/BackendController.php | 44 ++++++++++-- Docs/Dev/en/SUMMARY.md | 4 ++ Docs/Dev/en/collection.md | 7 ++ Docs/Dev/en/media.md | 24 +++++++ Docs/Help/en/SUMMARY.md | 3 + Docs/{ => Help/en}/introduction.md | 0 Models/Media.php | 4 +- Theme/Backend/Lang/de.lang.php | 1 + Theme/Backend/Lang/en.lang.php | 1 + Theme/Backend/media-collection-create.tpl.php | 63 ++++++++++++++++ Theme/Backend/media-file-create.tpl.php | 63 ++++++++++++---- Theme/Backend/media-list.tpl.php | 15 ++-- Theme/Backend/media-single.tpl.php | 2 +- Theme/Backend/media-upload.tpl.php | 13 ++-- 17 files changed, 272 insertions(+), 56 deletions(-) create mode 100644 Docs/Dev/en/SUMMARY.md create mode 100644 Docs/Dev/en/collection.md create mode 100644 Docs/Dev/en/media.md create mode 100644 Docs/Help/en/SUMMARY.md rename Docs/{ => Help/en}/introduction.md (100%) diff --git a/Admin/Installer.php b/Admin/Installer.php index 787c545..94cba81 100755 --- a/Admin/Installer.php +++ b/Admin/Installer.php @@ -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); diff --git a/Admin/Routes/Web/Api.php b/Admin/Routes/Web/Api.php index e5e3344..74c60aa 100755 --- a/Admin/Routes/Web/Api.php +++ b/Admin/Routes/Web/Api.php @@ -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', diff --git a/Controller/ApiController.php b/Controller/ApiController.php index 5faac8f..ece1222 100755 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -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 = [ [ diff --git a/Controller/BackendController.php b/Controller/BackendController.php index 04d77bc..de85207 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -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; diff --git a/Docs/Dev/en/SUMMARY.md b/Docs/Dev/en/SUMMARY.md new file mode 100644 index 0000000..6329860 --- /dev/null +++ b/Docs/Dev/en/SUMMARY.md @@ -0,0 +1,4 @@ +# Developer Content + +* [Media]({%}&page=Dev/media) +* [Collection]({%}&page=Dev/collection) diff --git a/Docs/Dev/en/collection.md b/Docs/Dev/en/collection.md new file mode 100644 index 0000000..7fec1f9 --- /dev/null +++ b/Docs/Dev/en/collection.md @@ -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. diff --git a/Docs/Dev/en/media.md b/Docs/Dev/en/media.md new file mode 100644 index 0000000..5d09f8a --- /dev/null +++ b/Docs/Dev/en/media.md @@ -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 \ No newline at end of file diff --git a/Docs/Help/en/SUMMARY.md b/Docs/Help/en/SUMMARY.md new file mode 100644 index 0000000..4b927b3 --- /dev/null +++ b/Docs/Help/en/SUMMARY.md @@ -0,0 +1,3 @@ +# Developer Content + +* [Templates]({%}&page=Dev/api_template) diff --git a/Docs/introduction.md b/Docs/Help/en/introduction.md similarity index 100% rename from Docs/introduction.md rename to Docs/Help/en/introduction.md diff --git a/Models/Media.php b/Models/Media.php index 9c1f90a..706027b 100755 --- a/Models/Media.php +++ b/Models/Media.php @@ -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, '\\/'); } /** diff --git a/Theme/Backend/Lang/de.lang.php b/Theme/Backend/Lang/de.lang.php index 547f82e..db10801 100755 --- a/Theme/Backend/Lang/de.lang.php +++ b/Theme/Backend/Lang/de.lang.php @@ -42,5 +42,6 @@ return ['Media' => [ 'Size' => 'Größe', 'Type' => 'Typ', 'Upload' => 'Hochladen', + 'VirtualPath' => 'Virtueller Pfad', 'Visibility' => 'Sichtbarkeit', ]]; diff --git a/Theme/Backend/Lang/en.lang.php b/Theme/Backend/Lang/en.lang.php index 1783a97..ac14a23 100755 --- a/Theme/Backend/Lang/en.lang.php +++ b/Theme/Backend/Lang/en.lang.php @@ -42,5 +42,6 @@ return ['Media' => [ 'Size' => 'Size', 'Type' => 'Type', 'Upload' => 'Upload', + 'VirtualPath' => 'Virtual Path', 'Visibility' => 'Visibility', ]]; diff --git a/Theme/Backend/media-collection-create.tpl.php b/Theme/Backend/media-collection-create.tpl.php index e69de29..2482f4c 100755 --- a/Theme/Backend/media-collection-create.tpl.php +++ b/Theme/Backend/media-collection-create.tpl.php @@ -0,0 +1,63 @@ + + +
+ +
+ +
+
+
+
+
getHtml('CreateCollection') ?>
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+ +
+ +
+
+
\ No newline at end of file diff --git a/Theme/Backend/media-file-create.tpl.php b/Theme/Backend/media-file-create.tpl.php index 4028bba..c440613 100755 --- a/Theme/Backend/media-file-create.tpl.php +++ b/Theme/Backend/media-file-create.tpl.php @@ -19,23 +19,10 @@ use phpOMS\Uri\UriFactory; */ ?>
- -
- -
-
+
-
-
-
-
-
-
+
@@ -49,4 +36,50 @@ use phpOMS\Uri\UriFactory; getData('editor')->getData('text')->render('editor', 'content', 'fEditor'); ?>
+ +
+ + +
+
+
getHtml('Settings'); ?>
+
+ +
+
+
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+
+ diff --git a/Theme/Backend/media-list.tpl.php b/Theme/Backend/media-list.tpl.php index 929cda1..d96f3a5 100755 --- a/Theme/Backend/media-list.tpl.php +++ b/Theme/Backend/media-list.tpl.php @@ -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'; ?>
@@ -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())); ?> diff --git a/Theme/Backend/media-single.tpl.php b/Theme/Backend/media-single.tpl.php index 6a79963..c0d452a 100755 --- a/Theme/Backend/media-single.tpl.php +++ b/Theme/Backend/media-single.tpl.php @@ -28,7 +28,7 @@ echo $this->getData('nav')->render();
request->getData('path') !== null) : ?> - getHtml('Back'); ?> + getHtml('Back'); ?> getHtml('Back'); ?> diff --git a/Theme/Backend/media-upload.tpl.php b/Theme/Backend/media-upload.tpl.php index 79a6dd2..9ce7651 100755 --- a/Theme/Backend/media-upload.tpl.php +++ b/Theme/Backend/media-upload.tpl.php @@ -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; @@ -40,8 +39,10 @@ use phpOMS\Uri\UriFactory;
getHtml('Upload') ?>
+
+
-
+
-
-
-