validateExport($request))) { $response->data['export'] = new FormValidation($val); $response->header->status = RequestStatusCode::R_400; return; } /** @var Template $template */ $template = TemplateMapper::get() ->with('source') ->with('source/sources') ->with('reports') ->with('reports/source') ->with('reports/source/sources') ->with('createdBy') ->where('id', (int) $request->getData('id')) ->execute(); $accountId = $request->header->account; $isExport = \in_array($request->getData('type'), ['xlsx', 'pdf', 'docx', 'pptx', 'csv', 'json']); // is allowed to read if (!$this->app->accountManager->get($accountId)->hasPermission(PermissionType::READ, $this->app->unitId, null, self::NAME, PermissionCategory::REPORT, $template->id) || ($isExport && !$this->app->accountManager->get($accountId)->hasPermission(PermissionType::READ, $this->app->unitId, $this->app->appId, self::NAME, PermissionCategory::EXPORT)) ) { $response->header->status = RequestStatusCode::R_403; return; } if ($isExport) { Autoloader::addPath(__DIR__ . '/../../../Resources/'); $response->header->setDownloadable($template->name, (string) $request->getData('type')); } $view = $this->createView($template, $request, $response); $this->setHelperResponseHeader($view, $template->name, $request, $response); $view->data['path'] = __DIR__ . '/../../../'; $response->set('export', $view); } /** * Validate export request * * @param RequestAbstract $request Request * * @return array * * @since 1.0.0 */ private function validateExport(RequestAbstract $request) : array { $val = []; if (($val['id'] = !$request->hasData('id'))) { return $val; } return []; } /** * Set header for report/template * * @param View $view Template view * @param string $name Template name * @param RequestAbstract $request Request * @param ResponseAbstract $response Response * * @return void * * @api * * @since 1.0.0 */ private function setHelperResponseHeader(View $view, string $name, RequestAbstract $request, ResponseAbstract $response) : void { /** @var array $tcoll */ $tcoll = $view->getData('tcoll') ?? []; switch ($request->getData('type')) { case 'pdf': if (!isset($tcoll['pdf'])) { break; } $response->header->set( 'Content-disposition', 'attachment; filename="' . $name . '.' . ((string) $request->getData('type')) . '"' , true); $response->header->set('Content-Type', MimeType::M_PDF, true); $view->setTemplate('/' . \substr($tcoll['pdf']->getPath(), 0, -8), 'pdf.php'); break; case 'csv': if (!isset($tcoll['csv'])) { break; } $response->header->set( 'Content-disposition', 'attachment; filename="' . $name . '.' . ((string) $request->getData('type')) . '"' , true); $response->header->set('Content-Type', MimeType::M_CONF, true); $view->setTemplate('/' . \substr($tcoll['csv']->getPath(), 0, -8), 'csv.php'); break; case 'xls': case 'xlsx': if (!isset($tcoll['excel'])) { break; } $response->header->set( 'Content-disposition', 'attachment; filename="' . $name . '.' . ((string) $request->getData('type')) . '"' , true); $response->header->set('Content-Type', MimeType::M_XLSX, true); $view->setTemplate('/' . \substr($tcoll['excel']->getPath(), 0, -8), 'xls.php'); break; case 'doc': case 'docx': if (!isset($tcoll['word'])) { break; } $response->header->set( 'Content-disposition', 'attachment; filename="' . $name . '.' . ((string) $request->getData('type')) . '"' , true); $response->header->set('Content-Type', MimeType::M_XLSX, true); $view->setTemplate('/' . \substr($tcoll['word']->getPath(), 0, -8), 'doc.php'); break; case 'ppt': case 'pptx': if (!isset($tcoll['powerpoint'])) { break; } $response->header->set( 'Content-disposition', 'attachment; filename="' . $name . '.' . ((string) $request->getData('type')) . '"' , true); $response->header->set('Content-Type', MimeType::M_XLSX, true); $view->setTemplate('/' . \substr($tcoll['powerpoint']->getPath(), 0, -8), 'ppt.php'); break; case 'json': if (!isset($tcoll['json'])) { break; } $response->header->set('Content-Type', MimeType::M_JSON, true); $view->setTemplate('/' . \substr($tcoll['json']->getPath(), 0, -9), 'json.php'); break; default: if (!isset($tcoll['template'])) { break; } $response->header->set('Content-Type', 'text/html; charset=utf-8'); $view->setTemplate('/' . \substr($tcoll['template']->getPath(), 0, -8)); } } /** * Create media directory path * * @param string $name Name * * @return string * * @since 1.0.0 */ private function createHelperDir(string $name) : string { $dt = new \DateTime('now'); return '/Modules/Helper/' . $dt->format('Y-m-d') . '_' . $name; } /** * Create view from template * * @param Template $template Template to create view from * @param RequestAbstract $request Request * @param ResponseAbstract $response Response * * @return View * * @api * * @since 1.0.0 */ private function createView(Template $template, RequestAbstract $request, ResponseAbstract $response) : View { /** @var array{lang?:\Modules\Media\Models\Media, cfg?:\Modules\Media\Models\Media, excel?:\Modules\Media\Models\Media, word?:\Modules\Media\Models\Media, powerpoint?:\Modules\Media\Models\Media, pdf?:\Modules\Media\Models\Media, csv?:\Modules\Media\Models\Media, json?:\Modules\Media\Models\Media, template?:\Modules\Media\Models\Media, css?:array, js?:array, db?:array, other?:array} $tcoll */ $tcoll = []; /** @var \Modules\Media\Models\Media[] $files */ $files = $template->source->getSources(); /** @var \Modules\Media\Models\Media $tMedia */ foreach ($files as $tMedia) { $lowerPath = \strtolower($tMedia->getPath()); switch (true) { case StringUtils::endsWith($lowerPath, '.lang.php'): $tcoll['lang'] = $tMedia; break; case StringUtils::endsWith($lowerPath, '.cfg.json'): $tcoll['cfg'] = $tMedia; break; case StringUtils::endsWith($lowerPath, '.xlsx.php'): case StringUtils::endsWith($lowerPath, '.xls.php'): $tcoll['excel'] = $tMedia; break; case StringUtils::endsWith($lowerPath, '.docx.php'): case StringUtils::endsWith($lowerPath, '.doc.php'): $tcoll['word'] = $tMedia; break; case StringUtils::endsWith($lowerPath, '.pptx.php'): case StringUtils::endsWith($lowerPath, '.ppt.php'): $tcoll['powerpoint'] = $tMedia; break; case StringUtils::endsWith($lowerPath, '.pdf.php'): $tcoll['pdf'] = $tMedia; break; case StringUtils::endsWith($lowerPath, '.csv.php'): $tcoll['csv'] = $tMedia; break; case StringUtils::endsWith($lowerPath, '.json.php'): $tcoll['json'] = $tMedia; break; case StringUtils::endsWith($lowerPath, '.tpl.php'): $tcoll['template'] = $tMedia; break; case StringUtils::endsWith($lowerPath, '.css'): if (!isset($tcoll['css'])) { $tcoll['css'] = []; } $tcoll['css'][$tMedia->name] = $tMedia; break; case StringUtils::endsWith($lowerPath, '.js'): if (!isset($tcoll['js'])) { $tcoll['js'] = []; } $tcoll['js'][$tMedia->name] = $tMedia; break; case StringUtils::endsWith($lowerPath, '.sqlite'): case StringUtils::endsWith($lowerPath, '.db'): if (!isset($tcoll['db'])) { $tcoll['db'] = []; } $tcoll['db'][$tMedia->name] = $tMedia; break; default: if (!isset($tcoll['other'])) { $tcoll['other'] = []; } $tcoll['other'][$tMedia->name] = $tMedia; } } $view = new View($this->app->l11nManager, $request, $response); $rcoll = []; $report = null; if (!$template->isStandalone) { /** @var Report $report */ $report = ReportMapper::get() ->with('template') ->with('source') ->with('source/sources') ->where('template', $template->id) ->sort('id', OrderType::DESC) ->limit(1) ->execute(); if ($report->id > 0) { $files = $report->source->getSources(); foreach ($files as $media) { $rcoll[$media->name . '.' . $media->extension] = $media; } } } $view->data['report'] = $report; $view->data['rcoll'] = $rcoll; $view->data['tcoll'] = $tcoll; $view->data['lang'] = ISO639x1Enum::tryFromValue($request->getDataString('lang')) ?? $request->header->l11n->language; $view->data['template'] = $template; $view->data['basepath'] = __DIR__ . '/../../../'; return $view; } /** * Routing end-point for application behavior. * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response * @param array $data Generic data * * @return void * * @api * * @since 1.0.0 */ public function apiTemplateCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void { $dbFiles = $request->getDataJson('media-list'); $uploadedFiles = $request->files; $files = []; if (!empty($val = $this->validateTemplateCreate($request))) { $response->header->status = RequestStatusCode::R_400; $this->createInvalidCreateResponse($request, $response, $val); return; } // is allowed to create if (!$this->app->accountManager->get($request->header->account) ->hasPermission(PermissionType::CREATE, $this->app->unitId, null, self::NAME, PermissionCategory::TEMPLATE) ) { $response->header->status = RequestStatusCode::R_403; $this->createInvalidCreateResponse($request, $response, []); return; } $path = $this->createHelperDir($request->getDataString('name') ?? ''); /** @var \Modules\Media\Models\Media[] $uploaded */ $uploaded = $this->app->moduleManager->get('Media', 'Api')->uploadFiles( $request->getDataList('names'), $request->getDataList('filenames'), $uploadedFiles, $request->header->account, __DIR__ . '/../../../Modules/Media/Files' . $path, $path, pathSettings: PathSettings::FILE_PATH ); foreach ($uploaded as $upload) { if ($upload->id === 0) { continue; } $files[] = $upload; } foreach ($dbFiles as $db) { $files[] = new NullMedia($db); } /** @var Collection $collection */ $collection = $this->app->moduleManager->get('Media', 'Api')->createMediaCollectionFromMedia( $request->getDataString('name') ?? '', $request->getDataString('description') ?? '', $files, $request->header->account ); $collection->setPath('/Modules/Media/Files/Modules/Helper/' . ($request->getDataString('name') ?? '')); $collection->setVirtualPath('/Modules/Helper'); $this->createModel($request->header->account, $collection, CollectionMapper::class, 'collection', $request->getOrigin()); if ($collection->id < 1) { $response->header->status = RequestStatusCode::R_403; $this->createInvalidCreateResponse($request, $response, $collection); return; } $template = $this->createTemplateFromRequest($request, $collection->id); $this->app->moduleManager->get('Admin')->createAccountModelPermission( new AccountPermission( $request->header->account, $this->app->unitId, $this->app->appId, self::NAME, self::NAME, PermissionCategory::TEMPLATE, $template->id, null, PermissionType::READ | PermissionType::MODIFY | PermissionType::DELETE | PermissionType::PERMISSION, ), $request->header->account, $request->getOrigin() ); $this->createModel($request->header->account, $template, TemplateMapper::class, 'template', $request->getOrigin()); $this->createStandardCreateResponse($request, $response, $template); } /** * Validate template create request * * @param RequestAbstract $request Request * * @return array * * @since 1.0.0 */ private function validateTemplateCreate(RequestAbstract $request) : array { $val = []; if (($val['name'] = !$request->hasData('name')) || ($val['files'] = empty($request->files)) ) { return $val; } return []; } /** * Method to create template from request. * * @param RequestAbstract $request Request * * @return Template * * @since 1.0.0 */ private function createTemplateFromRequest(RequestAbstract $request, int $collectionId) : Template { $helperTemplate = new Template(); $helperTemplate->name = $request->getDataString('name') ?? ''; $helperTemplate->description = Markdown::parse($request->getDataString('description') ?? ''); $helperTemplate->descriptionRaw = $request->getDataString('description') ?? ''; if ($collectionId > 0) { $helperTemplate->source = new NullCollection($collectionId); } $helperTemplate->isStandalone = $request->getDataBool('standalone') ?? false; $helperTemplate->createdBy = new NullAccount($request->header->account); $helperTemplate->virtualPath = $request->getDataString('virtualpath') ?? '/'; $helperTemplate->setExpected($request->getDataJson('expected')); $helperTemplate->setDatatype($request->getDataInt('datatype') ?? TemplateDataType::OTHER); if ($request->hasData('tags')) { $helperTemplate->tags = $this->app->moduleManager->get('Tag', 'Api')->createTagsFromRequest($request); } return $helperTemplate; } /** * Routing end-point for application behavior. * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response * @param array $data Generic data * * @return void * * @api * * @since 1.0.0 */ public function apiReportCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void { if (!empty($val = $this->validateReportCreate($request))) { $response->header->status = RequestStatusCode::R_400; $this->createInvalidCreateResponse($request, $response, $val); return; } // is allowed to create if (!$this->app->accountManager->get($request->header->account)->hasPermission(PermissionType::CREATE, $this->app->unitId, null, self::NAME, PermissionCategory::REPORT)) { $response->header->status = RequestStatusCode::R_403; return; } $files = $this->app->moduleManager->get('Media', 'Api')->uploadFiles( $request->getDataList('names'), $request->getDataList('filenames'), $request->files, $request->header->account, __DIR__ . '/../../../Modules/Media/Files' ); $collection = $this->app->moduleManager->get('Media')->createMediaCollectionFromMedia( $request->getDataString('name') ?? '', $request->getDataString('description') ?? '', $files, $request->header->account ); $collection->setPath('/Modules/Media/Files/Modules/Helper/' . ($request->getDataString('name') ?? '')); $collection->setVirtualPath('/Modules/Helper'); $this->createModel($request->header->account, $collection, CollectionMapper::class, 'collection', $request->getOrigin()); if ($collection->id < 1) { $response->header->status = RequestStatusCode::R_403; $this->createInvalidCreateResponse($request, $response, $collection); return; } $report = $this->createReportFromRequest($request, $response, $collection->id); $this->app->moduleManager->get('Admin')->createAccountModelPermission( new AccountPermission( $request->header->account, $this->app->unitId, $this->app->appId, self::NAME, self::NAME, PermissionCategory::REPORT, $report->id, null, PermissionType::READ | PermissionType::MODIFY | PermissionType::DELETE | PermissionType::PERMISSION, ), $request->header->account, $request->getOrigin() ); $this->createModel($request->header->account, $report, ReportMapper::class, 'report', $request->getOrigin()); $this->createStandardCreateResponse($request, $response, $report); } /** * Validate template create request * * @param RequestAbstract $request Request * * @return array * * @since 1.0.0 */ private function validateReportCreate(RequestAbstract $request) : array { $val = []; if (($val['template'] = !$request->hasData('template')) ) { return $val; } return []; } /** * Method to create report from request. * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response * @param int $collectionId Id of media collection * * @return Report * * @since 1.0.0 */ private function createReportFromRequest(RequestAbstract $request, ResponseAbstract $response, int $collectionId) : Report { $helperReport = new Report(); $helperReport->title = $request->getDataString('name') ?? ''; $helperReport->source = new NullCollection($collectionId); $helperReport->template = new NullTemplate((int) $request->getData('template')); $helperReport->createdBy = new NullAccount($request->header->account); return $helperReport; } }