org -> unit change, some new functionality

This commit is contained in:
Dennis Eichhorn 2023-01-26 21:54:13 +01:00
parent 81519fe144
commit 26af2f83de
11 changed files with 308 additions and 27 deletions

View File

@ -179,8 +179,8 @@
"type": "INT",
"default": null,
"null": true,
"foreignTable": "organization_unit",
"foreignKey": "organization_unit_id"
"foreignTable": "unit",
"foreignKey": "unit_id"
},
"media_language": {
"name": "media_language",
@ -263,5 +263,31 @@
"foreignKey": "tag_id"
}
}
},
"media_type_rel": {
"name": "media_type_rel",
"fields": {
"media_type_rel_id": {
"name": "media_type_rel_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"media_type_rel_src": {
"name": "media_type_rel_src",
"type": "INT",
"null": false,
"foreignTable": "media",
"foreignKey": "media_id"
},
"media_type_rel_dst": {
"name": "media_type_rel_dst",
"type": "INT",
"null": false,
"foreignTable": "type",
"foreignKey": "type_id"
}
}
}
}

View File

@ -116,7 +116,7 @@ final class Installer extends InstallerAbstract
};
$apiApp->dbPool = $app->dbPool;
$apiApp->orgId = $app->orgId;
$apiApp->unitId = $app->unitId;
$apiApp->accountManager = $app->accountManager;
$apiApp->appSettings = $app->appSettings;
$apiApp->moduleManager = $app->moduleManager;
@ -144,6 +144,9 @@ final class Installer extends InstallerAbstract
case 'type':
$result['type'][] = self::createType($apiApp, $media);
break;
case 'reference':
$result['reference'][] = self::createReference($apiApp, $media);
break;
default:
}
}
@ -151,6 +154,21 @@ final class Installer extends InstallerAbstract
return $result;
}
/**
* Create collection.
*
* @param ApplicationAbstract $app Application
* @param array{path?:string, name?:string, virtualPath?:string, create_directory?:bool} $data Media info
*
* @return array
*
* @since 1.0.0
*/
private static function createReference(ApplicationAbstract $app, array $data) : array
{
return [];
}
/**
* Create collection.
*

View File

@ -30,11 +30,11 @@ use Modules\Media\Models\NullMedia;
use Modules\Media\Models\NullMediaType;
use Modules\Media\Models\PathSettings;
use Modules\Media\Models\PermissionCategory;
use Modules\Media\Models\Reference;
use Modules\Media\Models\ReferenceMapper;
use Modules\Media\Models\UploadFile;
use Modules\Media\Models\UploadStatus;
use Modules\Tag\Models\NullTag;
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\Writer\HTML;
use phpOMS\Account\PermissionType;
use phpOMS\Application\ApplicationAbstract;
use phpOMS\Asset\AssetType;
@ -86,7 +86,6 @@ final class ApiController extends Controller
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!!!
@ -98,6 +97,39 @@ final class ApiController extends Controller
$ids = [];
foreach ($uploads as $file) {
$ids[] = $file->getId();
// add media types
if (!empty($types = $request->getDataJson('types'))) {
foreach ($types as $type) {
if (!isset($type['id'])) {
$request->setData('name', $type['name'], true);
$request->setData('title', $type['title'], true);
$request->setData('lang', $type['lang'] ?? null, true);
$internalResponse = new HttpResponse();
$this->apiMediaTypeCreate($request, $internalResponse, null);
if (!\is_array($data = $internalResponse->get($request->uri->__toString()))) {
continue;
}
$file->addMediaType($tId = $data['response']);
} else {
$file->addMediaType(new NullMediaType($tId = (int) $type['id']));
}
$this->createModelRelation(
$request->header->account,
$file->getId(),
$tId,
MediaMapper::class,
'types',
'',
$request->getOrigin()
);
}
}
// add tags
if (!empty($tags = $request->getDataJson('tags'))) {
foreach ($tags as $tag) {
@ -144,7 +176,6 @@ final class ApiController extends Controller
* @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
* @param int $type Media type (internal/custom media categorization)
* 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.
@ -164,7 +195,6 @@ final class ApiController extends Controller
int $account,
string $basePath = '/Modules/Media/Files',
string $virtualPath = '',
int $type = null,
string $password = '',
string $encryptionKey = '',
int $pathSettings = PathSettings::RANDOM_PATH,
@ -211,7 +241,6 @@ final class ApiController extends Controller
$stat,
$account,
$virtualPath,
$type,
app: $hasAccountRelation ? $this->app : null,
readContent: $readContent,
unit: $unit
@ -268,7 +297,6 @@ final class ApiController extends Controller
* @param array $status Files
* @param int $account Uploader
* @param string $virtualPath Virtual path (not on the hard-drive)
* @param null|int $type Media type (internal categorization)
* @param string $ip Ip of the origin
* @param null|ApplicationAbstract $app Should create relation to uploader
* @param bool $readContent Should the content of the file be stored in the db
@ -281,7 +309,6 @@ final class ApiController extends Controller
array $status,
int $account,
string $virtualPath = '',
int $type = null,
string $ip = '127.0.0.1',
ApplicationAbstract $app = null,
bool $readContent = false,
@ -299,7 +326,6 @@ final class ApiController extends Controller
$media->size = $status['size'];
$media->createdBy = new NullAccount($account);
$media->extension = $status['extension'];
$media->type = $type === null ? null : new NullMediaType($type);
$media->unit = $unit;
$media->setVirtualPath($virtualPath);
@ -318,7 +344,7 @@ final class ApiController extends Controller
$app->moduleManager->get('Admin')->createAccountModelPermission(
new AccountPermission(
$account,
$app->orgId,
$app->unitId,
$app->appName,
self::NAME,
self::NAME,
@ -476,6 +502,85 @@ final class ApiController extends Controller
return $media;
}
public function apiReferenceCreate(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
{
if (!empty($val = $this->validateReferenceCreate($request))) {
$response->set('collection_create', new FormValidation($val));
$response->header->status = RequestStatusCode::R_400;
return;
}
$reference = $this->createReferenceFromRequest($request);
$this->createModel($request->header->account, $reference, ReferenceMapper::class, 'reference', $request->getOrigin());
// get parent collection
// create relation
$parentCollectionId = (int) $request->getData('parent');
if ($parentCollectionId === 0) {
$parentCollection = CollectionMapper::get()
->where('virtualPath', (string) ($request->getData('virtualpath') ?? ''))
->where('name', (string) ($request->getData('name') ?? ''))
->execute();
$parentCollectionId = $parentCollection->getId();
}
CollectionMapper::writer()->createRelationTable('sources', [$parentCollectionId], $reference->getId());
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Reference', 'Reference successfully created.', $reference);
}
/**
* Method to create collection from request.
*
* @param RequestAbstract $request Request
*
* @return Reference Returns the collection from the request
*
* @since 1.0.0
*/
private function createReferenceFromRequest(RequestAbstract $request) : Reference
{
$mediaReference = new Reference();
$mediaReference->name = (string) $request->getData('name');
$mediaReference->source = new NullMedia((int) $request->getData('source'));
$mediaReference->createdBy = new NullAccount($request->header->account);
$mediaReference->setVirtualPath($request->getData('virtualpath'));
return $mediaReference;
}
/**
* Validate collection create request
*
* @param RequestAbstract $request Request
*
* @return array<string, bool> Returns the validation array of the request
*
* @since 1.0.0
*/
private function validateReferenceCreate(RequestAbstract $request) : array
{
$val = [];
if (($val['name'] = empty($request->getData('name')))
|| ($val['virtualpath'] = empty($request->getData('virtualpath')))
|| ($val['source'] = empty($request->getData('source')))
) {
return $val;
}
return [];
}
// Very similar to create Reference
// Reference = it's own media element which points to another element (disadvantage = additional step)
// Collection add = directly pointing to other media element (disadvantage = we don't know if we are allowed to modify/delete)
public function apiCollectionAdd(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
{
}
/**
* Api method to create a collection.
*
@ -590,7 +695,7 @@ final class ApiController extends Controller
{
if (empty($media)
|| !$this->app->accountManager->get($account)->hasPermission(
PermissionType::CREATE, $this->app->orgId, null, self::NAME, PermissionCategory::COLLECTION, null)
PermissionType::CREATE, $this->app->unitId, null, self::NAME, PermissionCategory::COLLECTION, null)
) {
return new NullCollection();
}
@ -731,7 +836,6 @@ final class ApiController extends Controller
$stat,
$request->header->account,
$virtualPath,
$request->getData('type', 'int'),
$request->getOrigin(),
$this->app,
unit: $request->getData('unit', 'int')
@ -775,6 +879,15 @@ final class ApiController extends Controller
}
}
if ($media->hasPassword()
&& !$media->comparePassword((string) $request->getData('password'))
) {
$view = new View($this->app->l11nManager, $request, $response);
$view->setTemplate('/Modules/Media/Theme/Api/invalidPassword');
return;
}
$this->setMediaResponseHeader($media, $request, $response);
$view = $this->createView($media, $request, $response);
$view->setData('path', __DIR__ . '/../../../');

View File

@ -81,7 +81,7 @@ final class BackendController extends Controller
$hasPermission = $this->app->accountManager->get($request->header->account)
->hasPermission(
PermissionType::READ,
$this->app->orgId,
$this->app->unitId,
$this->app->appName,
self::NAME,
PermissionCategory::MEDIA,
@ -93,7 +93,7 @@ final class BackendController extends Controller
$permWhere = PermissionAbstractMapper::helper($this->app->dbPool->get('select'))
->groups($this->app->accountManager->get($request->header->account)->getGroupIds())
->account($request->header->account)
->units([null, $this->app->orgId])
->units([null, $this->app->unitId])
->apps([null, 'Api', $this->app->appName])
->modules([null, self::NAME])
->categories([null, PermissionCategory::MEDIA])
@ -112,7 +112,7 @@ final class BackendController extends Controller
$permWhere = PermissionAbstractMapper::helper($this->app->dbPool->get('select'))
->groups($this->app->accountManager->get($request->header->account)->getGroupIds())
->account($request->header->account)
->units([null, $this->app->orgId])
->units([null, $this->app->unitId])
->apps([null, 'Api', $this->app->appName])
->modules([null, self::NAME])
->categories([null, PermissionCategory::MEDIA])
@ -236,6 +236,14 @@ final class BackendController extends Controller
->where('tags/title/language', $request->getLanguage())
->execute();
if ($media->hasPassword()
&& !$media->comparePassword((string) $request->getData('password'))
) {
$view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/invalidPassword');
return $view;
}
if ($media->class === MediaClass::COLLECTION) {
/** @var \Modules\Media\Models\Media[] $files */
$files = MediaMapper::getByVirtualPath(
@ -293,6 +301,15 @@ final class BackendController extends Controller
private function createMediaView(Media $media, RequestAbstract $request, ResponseAbstract $response) : View
{
$view = new ElementView($this->app->l11nManager, $request, $response);
if ($media->hasPassword()
&& !$media->comparePassword((string) $request->getData('password'))
) {
$view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/invalidPassword');
return $view;
}
switch (\strtolower($media->extension)) {
case 'pdf':
$view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/pdf');

View File

@ -74,7 +74,8 @@ final class CollectionMapper extends MediaMapper
*/
public static function getByVirtualPath(string $virtualPath = '/', int $status = MediaStatus::NORMAL) : ReadMapper
{
return self::getAll()->where('virtualPath', $virtualPath)
return self::getAll()
->where('virtualPath', $virtualPath)
->with('createdBy')
->with('tags')
->where('status', $status)

View File

@ -56,10 +56,10 @@ class Media implements \JsonSerializable
/**
* Type.
*
* @var null|int|MediaType
* @var MediaType[]
* @since 1.0.0
*/
public null | int | MediaType $type = null;
public array $types = [];
/**
* Extension.
@ -290,6 +290,11 @@ class Media implements \JsonSerializable
return $this->nonce !== null;
}
public function hasPassword() : bool
{
return !empty($password);
}
/**
* Set encryption password
*
@ -392,6 +397,72 @@ class Media implements \JsonSerializable
$this->virtualPath = \str_replace('\\', '/', $path);
}
/**
* Adding new type.
*
* @param MediaType $type MediaType
*
* @return int
*
* @since 1.0.0
*/
public function addMediaType(MediaType $type) : int
{
$this->types[] = $type;
\end($this->types);
$key = (int) \key($this->types);
\reset($this->types);
return $key;
}
/**
* Remove MediaType from list.
*
* @param int $id MediaType
*
* @return bool
*
* @since 1.0.0
*/
public function removeMediaType($id) : bool
{
if (isset($this->types[$id])) {
unset($this->types[$id]);
return true;
}
return false;
}
/**
* Get media types.
*
* @return MediaType[]
*
* @since 1.0.0
*/
public function getMediaTypes() : array
{
return $this->types;
}
/**
* Get media type.
*
* @param int $id Element id
*
* @return MediaType
*
* @since 1.0.0
*/
public function getMediaType(int $id) : MediaType
{
return $this->types[$id] ?? new NullMediaType();
}
/**
* Adding new tag.
*
@ -433,7 +504,7 @@ class Media implements \JsonSerializable
}
/**
* Get task elements.
* Get tags.
*
* @return Tag[]
*
@ -445,7 +516,7 @@ class Media implements \JsonSerializable
}
/**
* Get task elements.
* Get tag.
*
* @param int $id Element id
*

View File

@ -38,7 +38,6 @@ class MediaMapper extends DataMapperFactory
public const COLUMNS = [
'media_id' => ['name' => 'media_id', 'type' => 'int', 'internal' => 'id'],
'media_name' => ['name' => 'media_name', 'type' => 'string', 'internal' => 'name', 'autocomplete' => true],
'media_type' => ['name' => 'media_type', 'type' => 'int', 'internal' => 'type'],
'media_description' => ['name' => 'media_description', 'type' => 'string', 'internal' => 'description', 'autocomplete' => true],
'media_description_raw' => ['name' => 'media_description_raw', 'type' => 'string', 'internal' => 'descriptionRaw'],
'media_content' => ['name' => 'media_content', 'type' => 'int', 'internal' => 'content'],
@ -107,6 +106,12 @@ class MediaMapper extends DataMapperFactory
'external' => 'media_tag_dst',
'self' => 'media_tag_src',
],
'types' => [
'mapper' => MediaTypeMapper::class,
'table' => 'media_type_rel',
'external' => 'media_type_rel_dst',
'self' => 'media_type_rel_src',
],
];
/**
@ -169,7 +174,7 @@ class MediaMapper extends DataMapperFactory
->with('createdBy')
->with('source')
->with('tags')
->with('tags/title')
->with('tags/content')
->where('virtualPath', $virtualPath)
->where('status', $status);
}

View File

@ -49,7 +49,7 @@ final class MediaTypeMapper extends DataMapperFactory
'mapper' => MediaTypeL11nMapper::class,
'table' => 'media_type_l11n',
'self' => 'media_type_l11n_type',
'column' => 'title',
'column' => 'content',
'external'=> null,
],
];

View File

@ -0,0 +1 @@
Invalid Password

View File

@ -0,0 +1,29 @@
<?php
/**
* Karaka
*
* PHP Version 8.1
*
* @package Modules\News
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
use phpOMS\Uri\UriFactory;
?>
<section id="mediaFile" class="portlet">
<div class="portlet-body">
<form id="mediaPassword" method="GET" action="<?= UriFactory::build('{%}'); ?>">
<div class="form-group">
<label for="iPassword"><?= $this->getHtml('Password'); ?></label>
<input id="iPassword" type="password" name="password">
</div>
<input type="submit" value="<?= $this->getHtml('Submit', '0', '0'); ?>">
</form>
</div>
</section>

View File

@ -48,7 +48,7 @@ final class ApiControllerTest extends \PHPUnit\Framework\TestCase
};
$this->app->dbPool = $GLOBALS['dbpool'];
$this->app->orgId = 1;
$this->app->unitId = 1;
$this->app->appName = 'Api';
$this->app->accountManager = new AccountManager($GLOBALS['session']);
$this->app->appSettings = new CoreSettings();