$action * @property Consultation $consultation * @property \app\models\settings\Layout $layoutParams * * @method string render(string $template, array $params) * @method string renderPartial(string $template, array $params) */ trait MotionExportTraits { public function actionViewimage(string $motionSlug, int $sectionId, ?string $showAlways = null): ResponseInterface { $motion = $this->getMotionWithCheck($motionSlug); foreach ($motion->getActiveSections() as $section) { if ($section->sectionId === $sectionId) { if (!$motion->isReadable() && $section->getShowAlwaysToken() !== $showAlways && !$this->consultation->havePrivilege(Privileges::PRIVILEGE_SCREENING, PrivilegeQueryContext::motion($motion)) ) { return new HtmlResponse($this->render('view_not_visible', ['motion' => $motion, 'adminEdit' => false])); } if ($section->getSectionType()->isEmpty()) { return new HtmlErrorResponse(404, 'Image not found'); } $metadata = json_decode($section->metadata, true); return new BinaryFileResponse( BinaryFileResponse::mimeTypeToType($metadata['mime']), $section->getData(), false, null, $this->layoutParams->isRobotsIndex($this->action) ); } } return new HtmlErrorResponse(404, 'Image not found'); } /** * @throws NotFoundHttpException * @throws NotFound */ public function actionViewpdf(string $motionSlug, int $sectionId, ?string $showAlways = null): ResponseInterface { $motion = $this->getMotionWithCheck($motionSlug); $maySeeAdminSections = $this->consultation->havePrivilege(Privileges::PRIVILEGE_CONTENT_EDIT, PrivilegeQueryContext::motion($motion)); foreach ($motion->getActiveSections(showAdminSections: $maySeeAdminSections) as $section) { if ($section->sectionId === $sectionId) { if (!$motion->isReadable() && $section->getShowAlwaysToken() !== $showAlways && !$this->consultation->havePrivilege(Privileges::PRIVILEGE_SCREENING, PrivilegeQueryContext::motion($motion)) ) { return new HtmlResponse($this->render('view_not_visible', ['motion' => $motion, 'adminEdit' => false])); } return new BinaryFileResponse( BinaryFileResponse::TYPE_PDF, $section->getData(), false, null, $this->layoutParams->isRobotsIndex($this->action) ); } } throw new NotFoundHttpException('Not found'); } public function actionEmbeddedpdf(string $file): HtmlResponse { return new HtmlResponse($this->renderPartial('pdf_embed', ['file' => $file])); } public function actionPdf(string $motionSlug, ?string $showAlways = null): ResponseInterface { $motion = $this->getMotionWithCheck($motionSlug); if (!($motion->isReadable() || $showAlways === $motion->getShowAlwaysToken())) { return new HtmlResponse($this->render('view_not_visible', ['motion' => $motion, 'adminEdit' => false])); } $selectedPdfLayout = IPDFLayout::getPdfLayoutForMotionType($motion->getMyMotionType()); $hasLaTeX = (AntragsgruenApp::getInstance()->xelatexPath || AntragsgruenApp::getInstance()->lualatexPath); if (!($hasLaTeX && $selectedPdfLayout->latexId !== null) && $selectedPdfLayout->id === null) { return new HtmlErrorResponse(404, \Yii::t('motion', 'err_no_pdf')); } if ($motion->getAlternativePdfSection()) { $pdfData = $motion->getAlternativePdfSection()->getData(); } elseif ($selectedPdfLayout->isHtmlToPdfLayout()) { $pdfData = LayoutHelper::createPdfFromHtml($motion); } elseif ($selectedPdfLayout->latexId !== null) { $pdfData = LayoutHelper::createPdfLatex($motion); } else { $pdfData = LayoutHelper::createPdfTcpdf($motion); } return new BinaryFileResponse(BinaryFileResponse::TYPE_PDF, $pdfData, false, $motion->getFilenameBase(false), $this->layoutParams->isRobotsIndex($this->action), null ); } public function actionPdfamendcollection(string $motionSlug): ResponseInterface { $motion = $this->getMotionWithCheck($motionSlug); if (!$motion->isReadable()) { return new HtmlResponse($this->render('view_not_visible', ['motion' => $motion, 'adminEdit' => false])); } $amendments = $motion->getVisibleAmendmentsSorted(); $selectedPdfLayout = IPDFLayout::getPdfLayoutForMotionType($motion->getMyMotionType()); $hasLaTeX = (AntragsgruenApp::getInstance()->xelatexPath || AntragsgruenApp::getInstance()->lualatexPath); if (!($hasLaTeX && $selectedPdfLayout->latexId !== null) && $selectedPdfLayout->id === null) { return new HtmlErrorResponse(404, \Yii::t('motion', 'err_no_pdf')); } if ($selectedPdfLayout->isHtmlToPdfLayout()) { $pdfData = $this->renderPartial('pdf_amend_collection_html2pdf', [ 'motion' => $motion, 'amendments' => $amendments ]); } elseif ($selectedPdfLayout->latexId !== null) { $pdfData = $this->renderPartial('pdf_amend_collection_tex', [ 'motion' => $motion, 'amendments' => $amendments, 'texTemplate' => $motion->motionType->texTemplate ]); } else { $pdfData = $this->renderPartial('pdf_amend_collection_tcpdf', [ 'motion' => $motion, 'amendments' => $amendments ]); } return new BinaryFileResponse( BinaryFileResponse::TYPE_PDF, $pdfData, false, $motion->getFilenameBase(false) . '.collection', $this->layoutParams->isRobotsIndex($this->action) ); } private function getMotionsAndTemplate(string $motionTypeId, bool $inactive, bool $resolutions, bool $admin): array { /** @var TexTemplate $texTemplate */ $texTemplate = null; $showAdminMotions = $admin && User::havePrivilege($this->consultation, Privileges::PRIVILEGE_MOTION_SEE_UNPUBLISHED, null); $search = AdminMotionFilterForm::getForConsultationFromRequest( $this->consultation, $this->consultation->motions, $this->getRequestValue('Search'), false, ); $imotions = $search->getMotionsForExport($this->consultation, $motionTypeId, $inactive); $imotionsFiltered = []; foreach ($imotions as $imotion) { if ($resolutions && !$imotion->isResolution()) { continue; } if (!$imotion->isVisible() && !$showAdminMotions) { continue; } if ($texTemplate === null) { $texTemplate = $imotion->getMyMotionType()->texTemplate; $imotionsFiltered[] = $imotion; } elseif ($imotion->getMyMotionType()->texTemplate && $imotion->getMyMotionType()->texTemplate->id === $texTemplate->id) { $imotionsFiltered[] = $imotion; } } return [$imotionsFiltered, $texTemplate]; } public function actionFullpdf(string $motionTypeId = '', bool $inactive = false, bool $resolutions = false, bool $admin = false): ResponseInterface { try { list($imotions, $texTemplate) = $this->getMotionsAndTemplate($motionTypeId, $inactive, $resolutions, $admin); /** @var IMotion[] $imotions */ if (count($imotions) === 0) { return new HtmlErrorResponse(404, \Yii::t('motion', 'none_yet')); } // Hint: If it is an amendmentOnly type, we will include the base motion here, too. Hence, no differentiation. } catch (ResponseException $e) { throw $e; } catch (ExceptionBase $e) { return new HtmlErrorResponse(404, $e->getMessage()); } $selectedPdfLayout = IPDFLayout::getPdfLayoutForMotionType($imotions[0]->getMyMotionType()); $hasLaTeX = (AntragsgruenApp::getInstance()->xelatexPath || AntragsgruenApp::getInstance()->lualatexPath); if (!($hasLaTeX && $selectedPdfLayout->latexId !== null) && $selectedPdfLayout->id === null) { return new HtmlErrorResponse(404, \Yii::t('motion', 'err_no_pdf')); } if ($selectedPdfLayout->isHtmlToPdfLayout()) { $pdfData = $this->renderPartial('pdf_full_html2pdf', ['imotions' => $imotions]); } elseif ($selectedPdfLayout->latexId !== null) { $pdfData = $this->renderPartial('pdf_full_tex', ['imotions' => $imotions, 'texTemplate' => $texTemplate]); } else { $pdfData = $this->renderPartial('pdf_full_tcpdf', ['imotions' => $imotions]); } return new BinaryFileResponse( BinaryFileResponse::TYPE_PDF, $pdfData, false, null, $this->layoutParams->isRobotsIndex($this->action) ); } public function actionPdfcollection(string $motionTypeId = '', bool $inactive = false, bool $resolutions = false, bool $admin = false): ResponseInterface { try { list($imotions, $texTemplate) = $this->getMotionsAndTemplate($motionTypeId, $inactive, $resolutions, $admin); if (count($imotions) === 0) { return new HtmlErrorResponse(404, \Yii::t('motion', 'filter_none_found')); } /** @var IMotion[] $imotions */ $motionType = $imotions[0]->getMyMotionType(); if ($motionType->amendmentsOnly) { $imotions = []; foreach ($motionType->motions as $motion) { $filter = IMotionStatusFilter::adminExport($this->consultation, $inactive); $imotions = array_merge($imotions, $motion->getFilteredAndSortedAmendments($filter)); } if (count($imotions) === 0) { return new HtmlErrorResponse(404, \Yii::t('motion', 'filter_none_found')); } } } catch (ResponseException $e) { throw $e; } catch (ExceptionBase $e) { return new HtmlErrorResponse(404, $e->getMessage()); } $selectedPdfLayout = IPDFLayout::getPdfLayoutForMotionType($motionType); $hasLaTeX = (AntragsgruenApp::getInstance()->xelatexPath || AntragsgruenApp::getInstance()->lualatexPath); if (!($hasLaTeX && $selectedPdfLayout->latexId !== null) && $selectedPdfLayout->id === null) { return new HtmlErrorResponse(404, \Yii::t('motion', 'err_no_pdf')); } if ($selectedPdfLayout->isHtmlToPdfLayout()) { $pdfData = $this->renderPartial('pdf_collection_html2pdf', ['imotions' => $imotions]); } elseif ($selectedPdfLayout->latexId !== null) { $pdfData = $this->renderPartial('pdf_collection_tex', ['imotions' => $imotions, 'texTemplate' => $texTemplate]); } else { $pdfData = $this->renderPartial('pdf_collection_tcpdf', ['imotions' => $imotions]); } return new BinaryFileResponse( BinaryFileResponse::TYPE_PDF, $pdfData, false, Tools::sanitizeFilename($motionType->getTitlePluralForDisplay(), false), $this->layoutParams->isRobotsIndex($this->action) ); } public function actionEmbeddedAmendmentsPdf(string $motionSlug): ResponseInterface { $motion = $this->getMotionWithCheck($motionSlug); if (!$motion->isReadable()) { return new HtmlResponse($this->render('view_not_visible', ['motion' => $motion, 'adminEdit' => false])); } $form = Init::forEmbeddedAmendmentsExport($motion); return new BinaryFileResponse( BinaryFileResponse::TYPE_PDF, $this->renderPartial('pdf_embedded_amendments_tcpdf', ['form' => $form]), false, null, false ); } /** * Landscape PDF with the motion text on the left and the changes of all amendments on the right side. * Users who may see unpublished motions also get unpublished amendments. */ public function actionAmendmentSynopsisPdf(string $motionSlug): ResponseInterface { $motion = $this->getMotionWithCheck($motionSlug); $context = PrivilegeQueryContext::motion($motion); $maySeeUnpublished = $this->consultation->havePrivilege(Privileges::PRIVILEGE_MOTION_SEE_UNPUBLISHED, $context); if (!$motion->isReadable() && !$maySeeUnpublished) { return new HtmlResponse($this->render('view_not_visible', ['motion' => $motion, 'adminEdit' => false])); } $filter = IMotionStatusFilter::adminExport($this->consultation, inactive: true, context: $context) ->noAmendmentsIfMotionIsMoved(); $amendments = $motion->getFilteredAndSortedAmendments($filter); return new BinaryFileResponse( BinaryFileResponse::TYPE_PDF, LayoutHelper::createAmendmentSynopsisPdf($motion, $amendments), false, $motion->getFilenameBase(false) . '_synopsis', false ); } public function actionOdt(string $motionSlug): ResponseInterface { $motion = $this->getMotionWithCheck($motionSlug); if (!$motion->isReadable()) { return new HtmlResponse($this->render('view_not_visible', ['motion' => $motion, 'adminEdit' => false])); } $doc = $motion->getMyMotionType()->createOdtTextHandler(); LayoutHelper::printMotionToOdt($motion, $doc); $odtData = $doc->finishAndGetDocument(); return new BinaryFileResponse( BinaryFileResponse::TYPE_ODT, $odtData, true, $motion->getFilenameBase(false), false ); } public function actionPlainhtml(string $motionSlug): ResponseInterface { $motion = $this->getMotionWithCheck($motionSlug); if (!$motion->isReadable()) { return new HtmlResponse($this->render('view_not_visible', ['motion' => $motion, 'adminEdit' => false])); } return new BinaryFileResponse( BinaryFileResponse::TYPE_HTML, $this->renderPartial('plain_html', ['motion' => $motion]), false, null, $this->layoutParams->isRobotsIndex($this->action) ); } public function actionViewChangesOdt(string $motionSlug): ResponseInterface { $motion = $this->getMotionWithCheck($motionSlug); $parentMotion = $motion->replacedMotion; if (!$motion->isReadable() && !$motion->canMergeAmendments()) { return new HtmlResponse($this->render('view_not_visible', ['motion' => $motion, 'adminEdit' => false])); } if (!$parentMotion || !$parentMotion->isReadable()) { RequestContext::getSession()->setFlash('error', 'The diff-view is not available'); return new RedirectResponse(UrlHelper::createMotionUrl($motion)); } try { $changes = MotionSectionChanges::motionToSectionChanges($parentMotion, $motion); } catch (\Exception $e) { return new HtmlErrorResponse(500, $e->getMessage()); } $odtData = $this->renderPartial('view_changes_odt', [ 'oldMotion' => $parentMotion, 'changes' => $changes, ]); return new BinaryFileResponse( BinaryFileResponse::TYPE_ODT, $odtData, true, $motion->getFilenameBase(false) . '-changes', false ); } }