From 9d6da09ef3cc7d78e12266bddcbecae2a53573d2 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 26 Mar 2022 15:01:46 +0100 Subject: [PATCH] undo serialize deprecation and switch to installExternal api calls --- Admin/Installer.php | 189 +++++++++++--------- Controller/ApiController.php | 177 ++++++++++++++++-- Models/MediaType.php | 3 +- Models/MediaTypeL11n.php | 3 +- Models/PathSettings.php | 2 - Theme/Backend/Components/Media/list.tpl.php | 2 + Theme/Backend/media-list.tpl.php | 4 - Theme/Backend/template-functions.php | 2 + 8 files changed, 274 insertions(+), 108 deletions(-) diff --git a/Admin/Installer.php b/Admin/Installer.php index b7ea350..adc7c66 100755 --- a/Admin/Installer.php +++ b/Admin/Installer.php @@ -25,15 +25,19 @@ use Modules\Media\Models\MediaType; use Modules\Media\Models\MediaTypeL11n; use Modules\Media\Models\MediaTypeL11nMapper; use Modules\Media\Models\MediaTypeMapper; +use Modules\Media\Models\PathSettings; use Modules\Media\Models\UploadFile; use phpOMS\Application\ApplicationAbstract; use phpOMS\Config\SettingsInterface; use phpOMS\DataStorage\Database\DatabasePool; +use phpOMS\Message\Http\HttpRequest; +use phpOMS\Message\Http\HttpResponse; use phpOMS\Module\InstallerAbstract; use phpOMS\Module\ModuleInfo; use phpOMS\System\File\Local\Directory; use phpOMS\System\File\Local\File; use phpOMS\System\File\PathException; +use phpOMS\Uri\HttpUri; /** * Installer class. @@ -114,9 +118,17 @@ final class Installer extends InstallerAbstract throw new \Exception(); // @codeCoverageIgnore } - if (\is_dir(__DIR__ . '/tmp')) { - Directory::delete(__DIR__ . '/tmp'); - } + $apiApp = new class() extends ApplicationAbstract + { + protected string $appName = 'Api'; + }; + + $apiApp->dbPool = $app->dbPool; + $apiApp->orgId = $app->orgId; + $apiApp->accountManager = $app->accountManager; + $apiApp->appSettings = $app->appSettings; + $apiApp->moduleManager = $app->moduleManager; + $apiApp->eventManager = $app->eventManager; $result = [ 'collection' => [], @@ -124,22 +136,24 @@ final class Installer extends InstallerAbstract 'type' => [], ]; - \mkdir(__DIR__ . '/tmp'); + if (!\is_dir(__DIR__ . '/../../../temp')) { + \mkdir(__DIR__ . '/../../../temp'); + } + foreach ($mediaData as $media) { switch ($media['type']) { case 'collection': - $result['collection'][] = self::createCollection($app->dbPool, $media); + $result['collection'][] = self::createCollection($apiApp, $media); break; case 'upload': - $result['upload'][] = self::uploadMedia($app->dbPool, $media); + $result['upload'][] = self::uploadMedia($apiApp, $media); break; case 'type': - $result['type'][] = self::createType($app->dbPool, $media); + $result['type'][] = self::createType($apiApp, $media); break; default: } } - Directory::delete(__DIR__ . '/tmp'); return $result; } @@ -147,61 +161,74 @@ final class Installer extends InstallerAbstract /** * Create collection. * - * @param DatabasePool $dbPool Database instance + * @param ApplicationAbstract $app Application * @param array $data Media info * * @return Collection * * @since 1.0.0 */ - private static function createCollection(DatabasePool $dbPool, array $data) : Collection + private static function createCollection(ApplicationAbstract $app, array $data) : Collection { + /** @var \Modules\Media\Controller\ApiController $module */ + $module = $app->moduleManager->getModuleInstance('Media'); + if (!isset($data['path'])) { - $dirPath = __DIR__ . '/../../../Modules/Media/Files' . ($data['virtualPath'] ?? '/') . '/' . ($data['name'] ?? ''); - $path = '/Modules/Media/Files' . ($data['virtualPath'] ?? '') . '/' . ($data['name'] ?? ''); + $path = '/Modules/Media/Files' . ($data['virtualPath'] ?? '') . '/' . ($data['name'] ?? ''); } else { - $dirPath = $data['path'] . '/' . ($data['name'] ?? ''); - $path = $data['path'] ?? '/Modules/Media/Files/' . ($data['name'] ?? ''); + $path = $data['path'] ?? '/Modules/Media/Files/' . ($data['name'] ?? ''); } - $collection = new Collection(); - $collection->name = $data['name'] ?? ''; - $collection->setVirtualPath($data['virtualPath'] ?? '/'); - $collection->setPath($path); - $collection->createdBy = new NullAccount((int) $data['user'] ?? 1); + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); - CollectionMapper::create()->execute($collection); + $request->header->account = 1; + $request->setData('name', $data['name'] ?? ''); + $request->setData('virtualpath', $data['virtualPath'] ?? '/'); + $request->setData('path', $path); + $request->setData('create_directory', $data['create_directory'] ?? false); - if ($data['create_directory'] && !\is_dir($dirPath)) { - // @todo fix permission mode - \mkdir($dirPath, 0755, true); - } + $module->apiCollectionCreate($request, $response); - return $collection; + return $response->get('')['response']; } /** * Create type. * - * @param DatabasePool $dbPool Database instance + * @param ApplicationAbstract $app Application * @param array $data Media info * * @return MediaType * * @since 1.0.0 */ - private static function createType(DatabasePool $dbPool, array $data) : MediaType + private static function createType(ApplicationAbstract $app, array $data) : MediaType { - $type = new MediaType(); - $type->name = $data['name'] ?? ''; + /** @var \Modules\Media\Controller\ApiController $module */ + $module = $app->moduleManager->get('Media'); - $id = MediaTypeMapper::create()->execute($type); + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('name', $data['name'] ?? ''); + + $module->apiMediaTypeCreate($request, $response); + + $type = $response->get('')['response']; + $id = $type->getId(); foreach ($data['l11n'] as $l11n) { - $l11n = new MediaTypeL11n($l11n['title'], $l11n['lang']); - $l11n->type = $id; + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); - MediaTypeL11nMapper::create()->execute($l11n); + $request->header->account = 1; + $request->setData('title', $l11n['title'] ?? ''); + $request->setData('lang', $l11n['lang'] ?? null); + $request->setData('type', $id); + + $module->apiMediaTypeL11nCreate($request, $response); } return $type; @@ -210,31 +237,50 @@ final class Installer extends InstallerAbstract /** * Upload media. * - * @param DatabasePool $dbPool Database instance + * @param ApplicationAbstract $app Application * @param array $data Media info * * @return array * * @since 1.0.0 */ - private static function uploadMedia(DatabasePool $dbPool, array $data) : array + private static function uploadMedia(ApplicationAbstract $app, array $data) : array { - $files = []; + /** @var \Modules\Media\Controller\ApiController $module */ + $module = $app->moduleManager->get('Media'); + + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('path', empty($data['path'] ?? '') ? '' : $data['path']); + $request->setData('virtualPath', + (string) ( + $data['create_collection'] + ? \rtrim($data['virtualPath'] ?? '/', '/') . '/' . ((string) $data['name'] ?? '') + : ($data['virtualPath'] ?? '/') + ) + ); + $request->setData('type', $data['media_type'] ?? null); // = identifier for modules + $request->setData('pathsettings', $data['path_setting'] ?? PathSettings::FILE_PATH); + + $tempPath = __DIR__ . '/../../../temp/'; + foreach ($data['files'] as $file) { if (\is_file(__DIR__ . '/../../..' . $file)) { - File::copy(__DIR__ . '/../../..' . $file, __DIR__ . '/tmp' . $file); + File::copy(__DIR__ . '/../../..' . $file, $tempPath . $file); - $files[] = [ - 'size' => \filesize(__DIR__ . '/tmp' . $file), + $request->addFile([ + 'size' => \filesize($tempPath . $file), 'name' => \basename($file), - 'tmp_name' => __DIR__ . '/tmp' . $file, + 'tmp_name' => $tempPath . $file, 'error' => \UPLOAD_ERR_OK, - ]; + ]); } if (\is_dir(__DIR__ . '/../../..' . $file)) { - Directory::copy(__DIR__ . '/../../..' . $file, __DIR__ . '/tmp' . $file); + Directory::copy(__DIR__ . '/../../..' . $file, $tempPath . $file); $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator(__DIR__ . '/tmp' . $file . '/', \RecursiveDirectoryIterator::SKIP_DOTS), + new \RecursiveDirectoryIterator($tempPath . $file . '/', \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST ); @@ -243,63 +289,32 @@ final class Installer extends InstallerAbstract continue; } - $files[] = [ + $request->addFile([ 'size' => \filesize($item->getPathname()), 'name' => \basename($item->getPathname()), 'tmp_name' => $item->getPathname(), 'error' => \UPLOAD_ERR_OK, - ]; + ]); } } } - $upload = new UploadFile(); - $upload->preserveFileName = $data['fixed_names'] ?? true; - $upload->outputDir = empty($data['path'] ?? '') - ? ApiController::createMediaPath() - : __DIR__ . '/../../..' . $data['path']; - - $status = $upload->upload($files, ($data['fixed_names'] ?? true) ? [] : [$data['name']], true); - - $mediaFiles = []; - foreach ($status as $uFile) { - $media = new Media(); - - $media->setPath(ApiController::normalizeDbPath($data['path']) . '/' . $uFile['filename']); - $media->name = !empty($uFile['name']) ? $uFile['name'] : $uFile['filename']; - $media->size = $uFile['size']; - $media->createdBy = new NullAccount((int) $data['user'] ?? 1); - $media->extension = $uFile['extension']; - - // Use defined virtual path if no collection is used. - // If a collection is created modify the virtual path so that it is the virtual path + the collection name for the uploaded files - $media->setVirtualPath((string) ( - $data['create_collection'] - ? \rtrim($data['virtualPath'] ?? '/', '/') . '/' . ((string) $data['name'] ?? '') - : ($data['virtualPath'] ?? '/') - ) - ); - - $media->type = $data['media_type'] ?? null; // = identifier for modules - - MediaMapper::create()->execute($media); - - $mediaFiles[] = $media; - } + $module->apiMediaUpload($request, $response); if ($data['create_collection']) { - $collection = new Collection(); - $collection->name = (string) $data['name'] ?? ''; - $collection->setVirtualPath((string) $data['virtualPath'] ?? '/'); - $collection->setPath((string) ($data['path'] ?? '/Modules/Media/Files/' . ((string) $data['name'] ?? ''))); - $collection->createdBy = new NullAccount((int) $data['user'] ?? 1); + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); - $collection->setSources($mediaFiles); + $request->header->account = 1; + $request->setData('name', (string) $data['name'] ?? ''); + $request->setData('virtualpath', (string) $data['virtualPath'] ?? '/'); + $request->setData('path', (string) ($data['path'] ?? '/Modules/Media/Files/' . ((string) $data['name'] ?? ''))); - CollectionMapper::create()->execute($collection); - return [$collection]; + $module->apiCollectionCreate($request, $response); + + return $response->get('')['resposne']; } - return $mediaFiles; + return $response->get('')['response']; } } diff --git a/Controller/ApiController.php b/Controller/ApiController.php index e89cb5f..fe664b1 100755 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -21,6 +21,10 @@ use Modules\Media\Models\CollectionMapper; use Modules\Media\Models\Media; use Modules\Media\Models\MediaContent; use Modules\Media\Models\MediaMapper; +use Modules\Media\Models\MediaType; +use Modules\Media\Models\MediaTypeL11n; +use Modules\Media\Models\MediaTypeL11nMapper; +use Modules\Media\Models\MediaTypeMapper; use Modules\Media\Models\NullCollection; use Modules\Media\Models\NullMedia; use Modules\Media\Models\NullMediaType; @@ -76,16 +80,16 @@ final class ApiController extends Controller public function apiMediaUpload(RequestAbstract $request, ResponseAbstract $response, $data = null) : void { $uploads = $this->uploadFiles( - $request->getDataList('names') ?? [], - $request->getDataList('filenames') ?? [], - $request->getFiles(), - $request->header->account, - __DIR__ . '/../../../Modules/Media/Files' . \urldecode((string) ($request->getData('path') ?? '')), - \urldecode((string) ($request->getData('virtualpath') ?? '')), - $request->getData('type', 'int'), - (string) ($request->getData('password') ?? ''), - (string) ($request->getData('encrypt') ?? ''), - (int) ($request->getData('pathsettings') ?? PathSettings::RANDOM_PATH) + names: $request->getDataList('names') ?? [], + fileNames: $request->getDataList('filenames') ?? [], + files: $request->getFiles(), + account: $request->header->account, + basePath: __DIR__ . '/../../../Modules/Media/Files' . \urldecode((string) ($request->getData('path') ?? '')), + virtualPath: \urldecode((string) ($request->getData('virtualpath') ?? '')), + type: $request->getData('type', 'int'), + password: (string) ($request->getData('password') ?? ''), + encryptionKey: (string) ($request->getData('encrypt') ?? ''), + pathSettings: (int) ($request->getData('pathsettings') ?? PathSettings::RANDOM_PATH) // IMPORTANT!!! ); $ids = []; @@ -166,6 +170,8 @@ final class ApiController extends Controller $outputDir = ''; $absolute = false; + // @todo sandatize $basePath, we don't know if it might be relative! + if ($pathSettings === PathSettings::RANDOM_PATH) { $outputDir = self::createMediaPath($basePath); } elseif ($pathSettings === PathSettings::FILE_PATH) { @@ -177,6 +183,7 @@ final class ApiController extends Controller $upload = new UploadFile(); $upload->outputDir = $outputDir; + $upload->preserveFileName = empty($fileNames) || \count($fileNames) === \count($files); $status = $upload->upload($files, $fileNames, $absolute, $encryptionKey); @@ -186,6 +193,8 @@ final class ApiController extends Controller $created = []; foreach ($status as &$stat) { ++$nCounter; + + // Possible: name != filename (name = database media name, filename = name on the file system) $stat['name'] = $sameLength ? $names[$nCounter] : $stat['filename']; $created[] = self::createDbEntry( @@ -450,6 +459,7 @@ final class ApiController extends Controller $collection = $this->createCollectionFromRequest($request); $this->createModel($request->header->account, $collection, CollectionMapper::class, 'collection', $request->getOrigin()); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Collection', 'Collection successfully created.', $collection); } @@ -504,6 +514,7 @@ final class ApiController extends Controller Directory::create($outputDir . '/' . $request->getData('name'), 0775, true); } + $dirPath = $outputDir . '/' . $request->getData('name'); $outputDir = \substr($outputDir, \strlen(__DIR__ . '/../../..')); $mediaCollection->setVirtualPath($virtualPath); @@ -511,6 +522,11 @@ final class ApiController extends Controller CollectionMapper::create()->execute($mediaCollection); + if (((bool) ($request->getData('create_directory') ?? false)) + && !\is_dir($dirPath)) { + \mkdir($dirPath, 0755, true); + } + return $mediaCollection; } @@ -613,7 +629,7 @@ final class ApiController extends Controller public function apiMediaCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void { $path = \urldecode((string) ($request->getData('path') ?? '')); - $virtualPath = \urldecode((string) ($request->getData('virtualpath') ?? '')); + $virtualPath = \urldecode((string) ($request->getData('virtualpath') ?? '/')); $fileName = (string) ($request->getData('filename') ?? ($request->getData('name') ?? '')); $fileName .= \strripos($fileName, '.') === false ? '.txt' : ''; @@ -843,4 +859,143 @@ final class ApiController extends Controller $response->header->set('Content-Type', MimeType::M_BIN, true); } } + + /** + * Validate document create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateMediaTypeCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['name'] = empty($request->getData('name'))) + ) { + return $val; + } + + return []; + } + + /** + * Api method to create document + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiMediaTypeCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void + { + if (!empty($val = $this->validateMediaTypeCreate($request))) { + $response->set('media_type_create', new FormValidation($val)); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + $type = $this->createDocTypeFromRequest($request); + $this->createModel($request->header->account, $type, MediaTypeMapper::class, 'doc_type', $request->getOrigin()); + + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Media', 'Media type successfully created', $type); + } + + /** + * Method to create task from request. + * + * @param RequestAbstract $request Request + * + * @return EditorDoc + * + * @since 1.0.0 + */ + private function createDocTypeFromRequest(RequestAbstract $request) : MediaType + { + $type = new MediaType(); + $type->name = $request->getData('name'); + + if (!empty($request->getData('title'))) { + $type->setL11n($request->getData('title'), $request->getData('lang') ?? $request->getLanguage()); + } + + return $type; + } + + /** + * Validate l11n create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateMediaTypeL11nCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['title'] = empty($request->getData('title'))) + || ($val['type'] = empty($request->getData('type'))) + ) { + return $val; + } + + return []; + } + + /** + * Api method to create tag localization + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiMediaTypeL11nCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void + { + if (!empty($val = $this->validateMediaTypeL11nCreate($request))) { + $response->set('media_type_l11n_create', new FormValidation($val)); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + $l11nMediaType = $this->createMediaTypeL11nFromRequest($request); + $this->createModel($request->header->account, $l11nMediaType, MediaTypeL11nMapper::class, 'media_type_l11n', $request->getOrigin()); + + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Localization', 'Category localization successfully created', $l11nMediaType); + } + + /** + * Method to create tag localization from request. + * + * @param RequestAbstract $request Request + * + * @return MediaTypeL11n + * + * @since 1.0.0 + */ + private function createMediaTypeL11nFromRequest(RequestAbstract $request) : MediaTypeL11n + { + $l11nMediaType = new MediaTypeL11n(); + $l11nMediaType->type = (int) ($request->getData('type') ?? 0); + $l11nMediaType->setLanguage((string) ( + $request->getData('language') ?? $request->getLanguage() + )); + $l11nMediaType->title = (string) ($request->getData('title') ?? ''); + + return $l11nMediaType; + } } diff --git a/Models/MediaType.php b/Models/MediaType.php index 1db6fc7..2ea72ac 100644 --- a/Models/MediaType.php +++ b/Models/MediaType.php @@ -14,7 +14,6 @@ declare(strict_types=1); namespace Modules\Media\Models; -use phpOMS\Contract\ArrayableInterface; use phpOMS\Localization\ISO639x1Enum; /** @@ -25,7 +24,7 @@ use phpOMS\Localization\ISO639x1Enum; * @link https://karaka.app * @since 1.0.0 */ -class MediaType implements \JsonSerializable, ArrayableInterface +class MediaType implements \JsonSerializable { /** * Article ID. diff --git a/Models/MediaTypeL11n.php b/Models/MediaTypeL11n.php index 3e9fa94..dfdac66 100644 --- a/Models/MediaTypeL11n.php +++ b/Models/MediaTypeL11n.php @@ -14,7 +14,6 @@ declare(strict_types=1); namespace Modules\Media\Models; -use phpOMS\Contract\ArrayableInterface; use phpOMS\Localization\ISO639x1Enum; /** @@ -25,7 +24,7 @@ use phpOMS\Localization\ISO639x1Enum; * @link https://karaka.app * @since 1.0.0 */ -class MediaTypeL11n implements \JsonSerializable, ArrayableInterface +class MediaTypeL11n implements \JsonSerializable { /** * ID. diff --git a/Models/PathSettings.php b/Models/PathSettings.php index 8ea801e..6edd6b6 100755 --- a/Models/PathSettings.php +++ b/Models/PathSettings.php @@ -29,6 +29,4 @@ abstract class PathSettings extends Enum public const FILE_PATH = 1; public const RANDOM_PATH = 2; - - public const COLLECTION_PATH = 3; } diff --git a/Theme/Backend/Components/Media/list.tpl.php b/Theme/Backend/Components/Media/list.tpl.php index 5c1e290..7dba210 100755 --- a/Theme/Backend/Components/Media/list.tpl.php +++ b/Theme/Backend/Components/Media/list.tpl.php @@ -29,6 +29,7 @@ $next = empty($this->media)
+ getHtml('Path', 'Media'); ?> getHtml('Name', 'Media'); ?> getHtml('Type', 'Media'); ?> getHtml('Size', 'Media'); ?> @@ -44,6 +45,7 @@ $next = empty($this->media) ?>
+ printHtml($value->getVirtualPath()); ?> printHtml($value->name); ?> printHtml($value->extension); ?> size; ?> diff --git a/Theme/Backend/media-list.tpl.php b/Theme/Backend/media-list.tpl.php index aa65970..752dafc 100755 --- a/Theme/Backend/media-list.tpl.php +++ b/Theme/Backend/media-list.tpl.php @@ -172,10 +172,6 @@ $next = empty($media) ? '{/prefix}media/list' : '{/prefix}media/list?{?}&id= foreach ($media as $key => $value) : ++$count; - if ($value->class === MediaClass::REFERENCE) { - $value = $value->source; - } - $url = $value->extension === 'collection' ? UriFactory::build('{/prefix}media/list?path=' . \rtrim($value->getVirtualPath(), '/') . '/' . $value->name) : UriFactory::build('{/prefix}media/single?id=' . $value->getId() diff --git a/Theme/Backend/template-functions.php b/Theme/Backend/template-functions.php index 3f2f4e5..2fe5df6 100755 --- a/Theme/Backend/template-functions.php +++ b/Theme/Backend/template-functions.php @@ -36,6 +36,8 @@ $fileIconFunction = function (int $extensionType) : string return 'file-excel-o'; } elseif ($extensionType === ExtensionType::DIRECTORY) { return 'folder-open-o'; + } elseif ($extensionType === ExtensionType::REFERENCE) { + return 'share'; } return 'file';