From 439c37760f736b7806b801b1e609e83baff0ffa3 Mon Sep 17 00:00:00 2001
From: Farbod Zamani <zamani@elan-ev.de>
Date: Fri, 25 Feb 2022 11:21:08 +0000
Subject: [PATCH] Resolves "using templates for courseware pdfExport"

---
 .../Courseware/BlockTypes/BlockType.php       | 32 +++++++++++++-----
 lib/models/Courseware/BlockTypes/Code.php     |  8 -----
 lib/models/Courseware/BlockTypes/Confirm.php  |  8 -----
 lib/models/Courseware/BlockTypes/Date.php     |  8 -----
 lib/models/Courseware/BlockTypes/Embed.php    | 12 -------
 lib/models/Courseware/BlockTypes/Headline.php |  9 -----
 lib/models/Courseware/BlockTypes/KeyPoint.php |  8 -----
 lib/models/Courseware/BlockTypes/Link.php     |  9 -----
 lib/models/Courseware/BlockTypes/Text.php     |  8 -----
 .../Courseware/BlockTypes/Typewriter.php      |  8 -----
 .../ContainerTypes/AccordionContainer.php     | 24 --------------
 .../ContainerTypes/ContainerType.php          | 33 +++++++++++++++----
 .../ContainerTypes/ListContainer.php          | 20 -----------
 .../ContainerTypes/TabsContainer.php          | 24 --------------
 lib/models/Courseware/StructuralElement.php   |  4 ++-
 templates/courseware/block_types/code.php     |  2 ++
 templates/courseware/block_types/confirm.php  |  2 ++
 templates/courseware/block_types/date.php     |  2 ++
 templates/courseware/block_types/default.php  |  8 +++++
 templates/courseware/block_types/embed.php    |  6 ++++
 templates/courseware/block_types/headline.php |  4 +++
 .../courseware/block_types/key_point.php      |  2 ++
 templates/courseware/block_types/link.php     |  3 ++
 templates/courseware/block_types/text.php     |  2 ++
 .../courseware/block_types/typewriter.php     |  2 ++
 .../container_types/accordion_container.php   | 15 +++++++++
 .../courseware/container_types/default.php    |  1 +
 .../container_types/list_container.php        | 12 +++++++
 .../container_types/tabs_container.php        | 15 +++++++++
 29 files changed, 129 insertions(+), 162 deletions(-)
 create mode 100755 templates/courseware/block_types/code.php
 create mode 100755 templates/courseware/block_types/confirm.php
 create mode 100755 templates/courseware/block_types/date.php
 create mode 100644 templates/courseware/block_types/default.php
 create mode 100755 templates/courseware/block_types/embed.php
 create mode 100755 templates/courseware/block_types/headline.php
 create mode 100755 templates/courseware/block_types/key_point.php
 create mode 100755 templates/courseware/block_types/link.php
 create mode 100755 templates/courseware/block_types/text.php
 create mode 100755 templates/courseware/block_types/typewriter.php
 create mode 100644 templates/courseware/container_types/accordion_container.php
 create mode 100644 templates/courseware/container_types/default.php
 create mode 100644 templates/courseware/container_types/list_container.php
 create mode 100644 templates/courseware/container_types/tabs_container.php

diff --git a/lib/models/Courseware/BlockTypes/BlockType.php b/lib/models/Courseware/BlockTypes/BlockType.php
index 203f6450be7..bee1df7d450 100755
--- a/lib/models/Courseware/BlockTypes/BlockType.php
+++ b/lib/models/Courseware/BlockTypes/BlockType.php
@@ -398,16 +398,32 @@ abstract class BlockType
         return $destinationFolder;
     }
 
-    public function pdfExport()
+    /**
+     * Gets the related block's html template if exists otherwise a default one, to be exported as pdf if exists.
+     *
+     * It turns the classname into snakecase in order to find the
+     * template file in templates/courseware/block_types.
+     *
+     * @return mixed the \Flexi_Template instance if exists, otherwise null.
+     */
+    public function getPdfHtmlTemplate(): ?\Flexi_Template
     {
-        $html = '<h5>' . sprintf(_('Block-Typ: %s'), $this->getTitle()) . '</h5>';
-        $html .= '<h6>' . _('Block-Daten') . ': ' . '</h6>';
-        foreach($this->getPayload() as $key => $value) {
-            if ($value !== '') {
-                $html .= '<h6>' . $key . ' => ' . $value . '</h6>';
+        $template = null;
+        try {
+            $template_name = strtosnakecase((new \ReflectionClass($this))->getShortName());
+            $template_path = $GLOBALS['template_factory']->get_path() . "courseware/block_types/{$template_name}.php";
+            if (file_exists($template_path)) {
+                $template = $GLOBALS['template_factory']->open("courseware/block_types/{$template_name}");
+            } else {
+                $template = $GLOBALS['template_factory']->open("courseware/block_types/default");
             }
+            $template->set_attributes([
+                'title' => $this->getTitle(),
+                'payload' => $this->getPayload()
+            ]);
+        } catch (\Exception $e) {
+            // it catches the exception mostly because the template file could not be found.
         }
-
-        return $html;
+        return $template;
     }
 }
diff --git a/lib/models/Courseware/BlockTypes/Code.php b/lib/models/Courseware/BlockTypes/Code.php
index 99888d4f380..2ee634255a3 100755
--- a/lib/models/Courseware/BlockTypes/Code.php
+++ b/lib/models/Courseware/BlockTypes/Code.php
@@ -58,12 +58,4 @@ class Code extends BlockType
     {
         return [];
     }
-
-    public function pdfExport()
-    {
-        $html = '<h5>' . sprintf(_('Block-Typ: %s'), $this->getTitle()) . '</h5>';
-        $html .= '<pre>' . htmlspecialchars($this->getPayload()['content']) . '</pre>';
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/BlockTypes/Confirm.php b/lib/models/Courseware/BlockTypes/Confirm.php
index 92c61d4d467..7204e6bf8c8 100755
--- a/lib/models/Courseware/BlockTypes/Confirm.php
+++ b/lib/models/Courseware/BlockTypes/Confirm.php
@@ -57,12 +57,4 @@ class Confirm extends BlockType
     {
         return [];
     }
-
-    public function pdfExport()
-    {
-        $html = '<h5>' . sprintf(_('Block-Typ: %s'), $this->getTitle()) . '</h5>';
-        $html .= '<p>' . htmlspecialchars($this->getPayload()['text']) . '</p>';
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/BlockTypes/Date.php b/lib/models/Courseware/BlockTypes/Date.php
index 66075f32fcd..df37590b315 100755
--- a/lib/models/Courseware/BlockTypes/Date.php
+++ b/lib/models/Courseware/BlockTypes/Date.php
@@ -58,12 +58,4 @@ class Date extends BlockType
     {
         return [];
     }
-
-    public function pdfExport()
-    {
-        $html = '<h5>' . sprintf(_('Block-Typ: %s'), $this->getTitle()) . '</h5>';
-        $html .= '<p>' . date('d.m.Y h:i', (int) $this->getPayload()['timestamp'] / 1000) . '</p>';
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/BlockTypes/Embed.php b/lib/models/Courseware/BlockTypes/Embed.php
index 5d067ec8732..a6496c66543 100755
--- a/lib/models/Courseware/BlockTypes/Embed.php
+++ b/lib/models/Courseware/BlockTypes/Embed.php
@@ -121,16 +121,4 @@ class Embed extends BlockType
     {
         return [];
     }
-
-    public function pdfExport()
-    {
-        $payload = $this->getPayload();
-        $html = '<h5>' . sprintf(_('Block-Typ: %s'), $this->getTitle()) . '</h5>';
-        $html .= '<h6>' . _('Block-Daten') . ': ' . '</h6>';
-        $html .= '<h6>' . _('Titel') . ' => ' . $payload['title'] . '</h6>';
-        $html .= '<h6>' . _('Quelle') . ' => ' . $payload['source'] . '</h6>';
-        $html .= '<h6>' . _('URL') . ' => ' . $payload['url'] . '</h6>';
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/BlockTypes/Headline.php b/lib/models/Courseware/BlockTypes/Headline.php
index a3add744f57..855e2a94a54 100755
--- a/lib/models/Courseware/BlockTypes/Headline.php
+++ b/lib/models/Courseware/BlockTypes/Headline.php
@@ -106,13 +106,4 @@ class Headline extends BlockType
     {
         return [];
     }
-
-    public function pdfExport()
-    {
-        $html = '<h5>' . sprintf(_('Block-Typ: %s'), $this->getTitle()) . '</h5>';
-        $html .= '<h5>' . htmlspecialchars($this->getPayload()['title']) . '</h5>';
-        $html .= '<h6>' . htmlspecialchars($this->getPayload()['subtitle']) . '</h6>';
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/BlockTypes/KeyPoint.php b/lib/models/Courseware/BlockTypes/KeyPoint.php
index 90f4852770a..fae16d3b9a6 100755
--- a/lib/models/Courseware/BlockTypes/KeyPoint.php
+++ b/lib/models/Courseware/BlockTypes/KeyPoint.php
@@ -59,12 +59,4 @@ class KeyPoint extends BlockType
     {
         return [];
     }
-
-    public function pdfExport()
-    {
-        $html = '<h5>' . sprintf(_('Block-Typ: %s'), $this->getTitle()) . '</h5>';
-        $html .= '<p>' . htmlspecialchars($this->getPayload()['text']) . '</p>';
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/BlockTypes/Link.php b/lib/models/Courseware/BlockTypes/Link.php
index 1e804b74580..7b93aeb7166 100755
--- a/lib/models/Courseware/BlockTypes/Link.php
+++ b/lib/models/Courseware/BlockTypes/Link.php
@@ -60,13 +60,4 @@ class Link extends BlockType
     {
         return [];
     }
-
-    public function pdfExport()
-    {
-        $html = '<h5>' . sprintf(_('Block-Typ: %s'), $this->getTitle()) . '</h5>';
-        $html .= '<p>' . htmlspecialchars($this->getPayload()['title']) . '</p>';
-        $html .= '<p>' . htmlspecialchars($this->getPayload()['url']) . '</p>';
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/BlockTypes/Text.php b/lib/models/Courseware/BlockTypes/Text.php
index 3857c02911e..c4fe67c68db 100755
--- a/lib/models/Courseware/BlockTypes/Text.php
+++ b/lib/models/Courseware/BlockTypes/Text.php
@@ -165,12 +165,4 @@ class Text extends BlockType
             return array();
         });
     }
-
-    public function pdfExport()
-    {
-        $html = '<h5>' . sprintf(_('Block-Typ: %s'), $this->getTitle()) . '</h5>';
-        $html .= $this->getPayload()['text'];
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/BlockTypes/Typewriter.php b/lib/models/Courseware/BlockTypes/Typewriter.php
index 064065bd613..583e64e7a1e 100755
--- a/lib/models/Courseware/BlockTypes/Typewriter.php
+++ b/lib/models/Courseware/BlockTypes/Typewriter.php
@@ -60,12 +60,4 @@ class Typewriter extends BlockType
     {
         return [];
     }
-
-    public function pdfExport()
-    {
-        $html = '<h5>' . sprintf(_('Block-Typ: %s'), $this->getTitle()) . '</h5>';
-        $html .= '<p>' . htmlspecialchars($this->getPayload()['text']) . '</p>';
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/ContainerTypes/AccordionContainer.php b/lib/models/Courseware/ContainerTypes/AccordionContainer.php
index 510a388cdbb..832520401aa 100755
--- a/lib/models/Courseware/ContainerTypes/AccordionContainer.php
+++ b/lib/models/Courseware/ContainerTypes/AccordionContainer.php
@@ -56,28 +56,4 @@ class AccordionContainer extends ContainerType
 
         return Schema::fromJsonString(file_get_contents($schemaFile));
     }
-
-    public function pdfExport()
-    {
-        $html = '<h3>' . sprintf(_('Container-Typ: %s'), $this->getTitle()) . '</h3>';
-
-        $payload = $this->getPayload();
-
-        $sections = $payload['sections'];
-        foreach ($sections as $section) {
-            $block_ids = $section['blocks'];
-            $html .= '<h4>' . $section['name'] . '</h4>';
-            foreach ($block_ids as $block_id) {
-                $block = $this->container->blocks->find($block_id);
-                if ($block) {
-                    $html .= $block->type->PdfExport();
-                }
-                else {
-                    $html .= '<p>' . _('Block konnte nicht gefunden werden') . '</p>';
-                }
-            }
-        }
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/ContainerTypes/ContainerType.php b/lib/models/Courseware/ContainerTypes/ContainerType.php
index a2552d415af..4b28b345875 100755
--- a/lib/models/Courseware/ContainerTypes/ContainerType.php
+++ b/lib/models/Courseware/ContainerTypes/ContainerType.php
@@ -245,14 +245,33 @@ abstract class ContainerType
         }
     }
 
-    public function pdfExport()
+    /**
+     * Gets the related container's html template if exists otherwise a default one, to be exported as pdf if exists.
+     *
+     * It turns the classname into snakecase in order to find the
+     * template file in templates/courseware/container_types.
+     *
+     * @return mixed the \Flexi_Template instance if exists, otherwise null.
+     */
+    public function getPdfHtmlTemplate(): ?\Flexi_Template
     {
-        $html = '<h3>' . sprintf(_('Container-Typ: %s'), $this->getTitle()) . '</h3>';
-
-        foreach ($this->container->blocks as $block) {
-            $html .= $block->type->PdfExport();
+        $template = null;
+        try {
+            $template_name = strtosnakecase((new \ReflectionClass($this))->getShortName());
+            $template_path = $GLOBALS['template_factory']->get_path() . "courseware/container_types/{$template_name}.php";
+            if (file_exists($template_path)) {
+                $template = $GLOBALS['template_factory']->open("courseware/container_types/{$template_name}");
+            } else {
+                $template = $GLOBALS['template_factory']->open("courseware/container_types/default");
+            }
+            $template->set_attributes([
+                'title' => $this->getTitle(),
+                'payload' => $this->getPayload(),
+                'container' => $this->container
+            ]);
+        } catch (\Exception $e) {
+            // it catches the exception mostly because the template file could not be found.
         }
-
-        return $html;
+        return $template;
     }
 }
diff --git a/lib/models/Courseware/ContainerTypes/ListContainer.php b/lib/models/Courseware/ContainerTypes/ListContainer.php
index d8e283c24f5..4918271a40e 100755
--- a/lib/models/Courseware/ContainerTypes/ListContainer.php
+++ b/lib/models/Courseware/ContainerTypes/ListContainer.php
@@ -56,24 +56,4 @@ class ListContainer extends ContainerType
 
         return Schema::fromJsonString(file_get_contents($schemaFile));
     }
-
-    public function pdfExport()
-    {
-        $html = '<h3>' . sprintf(_('Container-Typ: %s'), $this->getTitle()) . '</h3>';
-
-        $payload = $this->getPayload();
-        $block_ids = $payload['sections'][0]['blocks'];
-
-        foreach ($block_ids as $block_id) {
-            $block = $this->container->blocks->find($block_id);
-            if ($block) {
-                $html .= $block->type->PdfExport();
-            }
-            else {
-                $html .= '<p>' . _('Block konnte nicht gefunden werden') . '</p>';
-            }
-        }
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/ContainerTypes/TabsContainer.php b/lib/models/Courseware/ContainerTypes/TabsContainer.php
index 72a15f464a8..b884bbb67ee 100755
--- a/lib/models/Courseware/ContainerTypes/TabsContainer.php
+++ b/lib/models/Courseware/ContainerTypes/TabsContainer.php
@@ -57,28 +57,4 @@ class TabsContainer extends ContainerType
 
         return Schema::fromJsonString(file_get_contents($schemaFile));
     }
-
-    public function pdfExport()
-    {
-        $html = '<h3>' . sprintf(_('Container-Typ: %s'), $this->getTitle()) . '</h3>';
-
-        $payload = $this->getPayload();
-
-        $sections = $payload['sections'];
-        foreach ($sections as $section) {
-            $block_ids = $section['blocks'];
-            $html .= '<h4>' . $section['name'] . '</h4>';
-            foreach ($block_ids as $block_id) {
-                $block = $this->container->blocks->find($block_id);
-                if ($block) {
-                    $html .= $block->type->PdfExport();
-                }
-                else {
-                    $html .= '<p>' . _('Block konnte nicht gefunden werden') . '</p>';
-                }
-            }
-        }
-
-        return $html;
-    }
 }
diff --git a/lib/models/Courseware/StructuralElement.php b/lib/models/Courseware/StructuralElement.php
index 54e28805414..ba1563e1434 100755
--- a/lib/models/Courseware/StructuralElement.php
+++ b/lib/models/Courseware/StructuralElement.php
@@ -768,8 +768,10 @@ SQL;
     {
         $containers = \Courseware\Container::findBySQL('structural_element_id = ?', [$this->id]);
 
+        $html = '';
         foreach ($containers as $container) {
-            $html .= $container->type->pdfExport();
+            $container_html_template = $container->type->getPdfHtmlTemplate();
+            $html .= $container_html_template ? $container_html_template->render() : '';
         }
 
         return $html;
diff --git a/templates/courseware/block_types/code.php b/templates/courseware/block_types/code.php
new file mode 100755
index 00000000000..0c369e2f318
--- /dev/null
+++ b/templates/courseware/block_types/code.php
@@ -0,0 +1,2 @@
+<h5><?= sprintf(_('Block-Typ: %s'), htmlReady($title)) ?></h5>
+<pre><?= htmlReady($payload['content']) ?></pre>
diff --git a/templates/courseware/block_types/confirm.php b/templates/courseware/block_types/confirm.php
new file mode 100755
index 00000000000..714e8e8e6f2
--- /dev/null
+++ b/templates/courseware/block_types/confirm.php
@@ -0,0 +1,2 @@
+<h5><?= sprintf(_('Block-Typ: %s'), htmlReady($title)) ?></h5>
+<p><?= htmlReady($payload['text']) ?></p>
diff --git a/templates/courseware/block_types/date.php b/templates/courseware/block_types/date.php
new file mode 100755
index 00000000000..2f748049af5
--- /dev/null
+++ b/templates/courseware/block_types/date.php
@@ -0,0 +1,2 @@
+<h5><?= sprintf(_('Block-Typ: %s'), htmlReady($title)) ?></h5>
+<p><?=  date('d.m.Y h:i', (int) $payload['timestamp'] / 1000) ?></p>
diff --git a/templates/courseware/block_types/default.php b/templates/courseware/block_types/default.php
new file mode 100644
index 00000000000..6e09444e998
--- /dev/null
+++ b/templates/courseware/block_types/default.php
@@ -0,0 +1,8 @@
+<h5><?= sprintf(_('Block-Typ: %s'), htmlReady($title)) ?></h5>
+<h6><?= _('Block-Daten') ?>:</h6>
+<? foreach ($payload as $key => $value): ?>
+    <? $value = is_bool($value) ? ($value ? 'true' : 'false') : $value; ?>
+    <? if (!empty($value)): ?>
+        <h6><?= htmlReady(str_replace('_', ' ', strtocamelcase($key, true)) . ' => ' . $value) ?></h6>
+    <? endif; ?>
+<? endforeach; ?>
diff --git a/templates/courseware/block_types/embed.php b/templates/courseware/block_types/embed.php
new file mode 100755
index 00000000000..f22f133614e
--- /dev/null
+++ b/templates/courseware/block_types/embed.php
@@ -0,0 +1,6 @@
+<h5><?= sprintf(_('Block-Typ: %s'), htmlReady($title)) ?></h5>
+<h6><?= _('Block-Daten') . ': ' ?></h6>
+<h6><?= htmlReady(_('Titel') . ' => ' . $payload['title']) ?></h6>
+<h6><?= htmlReady(_('Quelle') . ' => ' . $payload['source']) ?></h6>
+<h6><?= htmlReady(_('URL') . ' => ' . $payload['url']) ?></h6>
+
diff --git a/templates/courseware/block_types/headline.php b/templates/courseware/block_types/headline.php
new file mode 100755
index 00000000000..fc573268d41
--- /dev/null
+++ b/templates/courseware/block_types/headline.php
@@ -0,0 +1,4 @@
+<h5><?= sprintf(_('Block-Typ: %s'), htmlReady($title)) ?></h5>
+<h5><?= htmlReady($payload['title']) ?></h5>
+<h6><?= htmlReady($payload['subtitle']) ?></h6>
+
diff --git a/templates/courseware/block_types/key_point.php b/templates/courseware/block_types/key_point.php
new file mode 100755
index 00000000000..714e8e8e6f2
--- /dev/null
+++ b/templates/courseware/block_types/key_point.php
@@ -0,0 +1,2 @@
+<h5><?= sprintf(_('Block-Typ: %s'), htmlReady($title)) ?></h5>
+<p><?= htmlReady($payload['text']) ?></p>
diff --git a/templates/courseware/block_types/link.php b/templates/courseware/block_types/link.php
new file mode 100755
index 00000000000..c1da7643d14
--- /dev/null
+++ b/templates/courseware/block_types/link.php
@@ -0,0 +1,3 @@
+<h5><?= sprintf(_('Block-Typ: %s'), htmlReady($title)) ?></h5>
+<p><?= htmlReady($payload['title']) ?></p>
+<p><?= htmlReady($payload['url']) ?></p>
diff --git a/templates/courseware/block_types/text.php b/templates/courseware/block_types/text.php
new file mode 100755
index 00000000000..f92fe0748f8
--- /dev/null
+++ b/templates/courseware/block_types/text.php
@@ -0,0 +1,2 @@
+<h5><?= sprintf(_('Block-Typ: %s'), htmlReady($title)) ?></h5>
+<?= formatReady($payload['text']) ?>
diff --git a/templates/courseware/block_types/typewriter.php b/templates/courseware/block_types/typewriter.php
new file mode 100755
index 00000000000..714e8e8e6f2
--- /dev/null
+++ b/templates/courseware/block_types/typewriter.php
@@ -0,0 +1,2 @@
+<h5><?= sprintf(_('Block-Typ: %s'), htmlReady($title)) ?></h5>
+<p><?= htmlReady($payload['text']) ?></p>
diff --git a/templates/courseware/container_types/accordion_container.php b/templates/courseware/container_types/accordion_container.php
new file mode 100644
index 00000000000..afc25e04bd7
--- /dev/null
+++ b/templates/courseware/container_types/accordion_container.php
@@ -0,0 +1,15 @@
+<h3><?= sprintf(_('Container-Typ: %s'), htmlReady($title)) ?></h3>
+<? foreach ($payload['sections'] as $section): ?>
+    <h4><?= htmlReady($section['name']) ?></h4>
+    <? foreach ($section['blocks'] as $block_id): ?>
+        <? $block = $container->blocks->find($block_id); ?>
+        <? if ($block): ?>
+            <? $block_html_template = $block->type->getPdfHtmlTemplate(); ?>
+            <? if ($block_html_template): ?>
+                <?= $block_html_template->render(); ?>
+            <? endif; ?>
+        <? else: ?>
+            <p><?= _('Block konnte nicht gefunden werden') ?></p>
+        <? endif; ?>
+    <? endforeach ?>
+<? endforeach ?>
diff --git a/templates/courseware/container_types/default.php b/templates/courseware/container_types/default.php
new file mode 100644
index 00000000000..fc4fb0a693b
--- /dev/null
+++ b/templates/courseware/container_types/default.php
@@ -0,0 +1 @@
+<h3><?= sprintf(_('Container-Typ: %s'), htmlReady($title)) ?></h3>
diff --git a/templates/courseware/container_types/list_container.php b/templates/courseware/container_types/list_container.php
new file mode 100644
index 00000000000..1dc4376864d
--- /dev/null
+++ b/templates/courseware/container_types/list_container.php
@@ -0,0 +1,12 @@
+<h3><?= sprintf(_('Container-Typ: %s'), htmlReady($title)) ?></h3>
+<? foreach ($payload['sections'][0]['blocks'] as $block_id): ?>
+    <? $block = $container->blocks->find($block_id); ?>
+    <? if ($block): ?>
+        <? $block_html_template = $block->type->getPdfHtmlTemplate(); ?>
+        <? if ($block_html_template): ?>
+            <?= $block_html_template->render(); ?>
+        <? endif; ?>
+    <? else: ?>
+        <p><?= _('Block konnte nicht gefunden werden') ?></p>
+    <? endif; ?>
+<? endforeach ?>
diff --git a/templates/courseware/container_types/tabs_container.php b/templates/courseware/container_types/tabs_container.php
new file mode 100644
index 00000000000..afc25e04bd7
--- /dev/null
+++ b/templates/courseware/container_types/tabs_container.php
@@ -0,0 +1,15 @@
+<h3><?= sprintf(_('Container-Typ: %s'), htmlReady($title)) ?></h3>
+<? foreach ($payload['sections'] as $section): ?>
+    <h4><?= htmlReady($section['name']) ?></h4>
+    <? foreach ($section['blocks'] as $block_id): ?>
+        <? $block = $container->blocks->find($block_id); ?>
+        <? if ($block): ?>
+            <? $block_html_template = $block->type->getPdfHtmlTemplate(); ?>
+            <? if ($block_html_template): ?>
+                <?= $block_html_template->render(); ?>
+            <? endif; ?>
+        <? else: ?>
+            <p><?= _('Block konnte nicht gefunden werden') ?></p>
+        <? endif; ?>
+    <? endforeach ?>
+<? endforeach ?>
-- 
GitLab