");
$snippet = str_replace("&", "&", $snippet);
$snippet = "";
diff --git a/components/ILIAS/Blog/Service/class.InternalGUIService.php b/components/ILIAS/Blog/Service/class.InternalGUIService.php
index 3d616e8ef350..fad63aa0f514 100755
--- a/components/ILIAS/Blog/Service/class.InternalGUIService.php
+++ b/components/ILIAS/Blog/Service/class.InternalGUIService.php
@@ -25,6 +25,7 @@
use ILIAS\PermanentLink\PermanentLinkManager;
use ILIAS\Blog\ReadingTime\GUIService;
use ILIAS\Blog\RSS\RSSGUI;
+use ILIAS\Blog\Posting\Service\GUIService as PostingGUIService;
class InternalGUIService
{
@@ -114,6 +115,15 @@ public function readingTime(): GUIService
);
}
+ public function posting(): PostingGUIService
+ {
+ return self::$instance["posting"] ??= new PostingGUIService(
+ $this->data_service,
+ $this->domain_service,
+ $this
+ );
+ }
+
public function rss(): RSSGUI
{
return self::$instance["rss"] ??= new RSSGUI(
diff --git a/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php b/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
index 9ea6bf02de9c..099336228a0b 100755
--- a/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
+++ b/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
@@ -1254,7 +1254,7 @@ public function renderList(
$wtpl->parseCurrentBlock();
}
- $snippet = ilBlogPostingGUI::getSnippet(
+ $snippet = $this->gui->posting()->getSnippet(
$item_id,
$this->blog_settings->getAbstractShorten(),
$this->blog_settings->getAbstractShortenLength(),
From c6c4f54392a576f899710d43a9250e7184752ef9 Mon Sep 17 00:00:00 2001
From: Alexander Killing
Date: Sat, 27 Jun 2026 14:25:03 +0200
Subject: [PATCH 020/108] blog: removed static calls
---
components/ILIAS/Blog/Posting/class.ilBlogPostingGUI.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/components/ILIAS/Blog/Posting/class.ilBlogPostingGUI.php b/components/ILIAS/Blog/Posting/class.ilBlogPostingGUI.php
index 997bf8b97e62..a5a648b4a515 100755
--- a/components/ILIAS/Blog/Posting/class.ilBlogPostingGUI.php
+++ b/components/ILIAS/Blog/Posting/class.ilBlogPostingGUI.php
@@ -805,7 +805,7 @@ protected function getFirstMediaObjectAsTag(
// see ilCOPageHTMLExport::exportHTMLMOB()
$mob_dir = "./mobs/mm_" . $mob_obj->getId();
}
- $mob_res = self::parseImage(
+ $mob_res = $this->parseImage(
$mob_size["width"],
$mob_size["height"],
$a_width,
@@ -828,7 +828,7 @@ protected function getFirstMediaObjectAsTag(
return "";
}
- protected static function parseImage(
+ protected function parseImage(
int $src_width,
int $src_height,
int $tgt_width,
From d5815fcf71fd2711cd0191359d46723a589e9901 Mon Sep 17 00:00:00 2001
From: Alexander Killing
Date: Sat, 27 Jun 2026 17:10:53 +0200
Subject: [PATCH 021/108] blog: improve DIC handling
---
.../Blog/Posting/class.ilBlogPostingGUI.php | 21 +++++++------------
.../class.ilBlogDraftsDerivedTaskProvider.php | 5 +++--
.../classes/class.ilBlogNewsRendererGUI.php | 16 ++++++++------
.../ILIAS/Blog/classes/class.ilObjBlog.php | 5 +++--
.../ILIAS/Blog/classes/class.ilObjBlogGUI.php | 6 ++----
5 files changed, 26 insertions(+), 27 deletions(-)
diff --git a/components/ILIAS/Blog/Posting/class.ilBlogPostingGUI.php b/components/ILIAS/Blog/Posting/class.ilBlogPostingGUI.php
index a5a648b4a515..af3fc1ae46a3 100755
--- a/components/ILIAS/Blog/Posting/class.ilBlogPostingGUI.php
+++ b/components/ILIAS/Blog/Posting/class.ilBlogPostingGUI.php
@@ -44,6 +44,7 @@ class ilBlogPostingGUI extends ilPageObjectGUI
protected ilLocatorGUI $locator;
protected ilSetting $settings;
protected LOMServices $lom_services;
+ protected ilToolbarGUI $toolbar;
protected int $node_id;
protected PostingManager $posting_manager;
protected ?object $access_handler = null;
@@ -114,6 +115,7 @@ public function __construct(
$this->notes = $DIC->notes();
$this->profile_gui = $DIC->blog()->internal()->gui()->profile();
$this->posting_manager = $DIC->blog()->internal()->domain()->posting();
+ $this->toolbar = $DIC->toolbar();
}
public function executeCommand(): string
@@ -179,12 +181,11 @@ protected function checkAccess(string $a_cmd): bool
public function preview(
?string $a_mode = null
): string {
- global $DIC;
$ilCtrl = $this->ctrl;
$tpl = $this->tpl;
$ilSetting = $this->settings;
- $toolbar = $DIC->toolbar();
+ $toolbar = $this->toolbar;
$append = "";
$this->getBlogPosting()->increaseViewCnt();
@@ -628,9 +629,7 @@ public function activatePage(bool $a_to_list = false): void
*/
public function editKeywords(): void
{
- global $DIC;
-
- $renderer = $DIC->ui()->renderer();
+ $renderer = $this->blog_gui->ui()->renderer();
$ilTabs = $this->tabs;
$tpl = $this->tpl;
@@ -652,9 +651,7 @@ public function editKeywords(): void
*/
protected function initKeywordsForm(): \ILIAS\UI\Component\Input\Container\Form\Standard
{
- global $DIC;
-
- $ui_factory = $DIC->ui()->factory();
+ $ui_factory = $this->blog_gui->ui()->factory();
$keywords = $this->posting_manager->getKeywords(
$this->getBlogPosting()->getBlogId(),
@@ -681,7 +678,7 @@ protected function initKeywordsForm(): \ILIAS\UI\Component\Input\Container\Form\
$input_tag = $input_tag->withValue($keywords);
}
- $DIC->ctrl()->setParameter(
+ $this->ctrl->setParameter(
$this,
'tags',
'tags_processing'
@@ -689,7 +686,7 @@ protected function initKeywordsForm(): \ILIAS\UI\Component\Input\Container\Form\
$section = $ui_factory->input()->field()->section([$input_tag], $this->lng->txt("blog_edit_keywords"), "");
- $form_action = $DIC->ctrl()->getFormAction($this, "saveKeywordsForm");
+ $form_action = $this->ctrl->getFormAction($this, "saveKeywordsForm");
return $ui_factory->input()->container()->form()->standard($form_action, ["tags" => $section]);
}
@@ -707,9 +704,7 @@ protected function getParentObjId(): int
public function saveKeywordsForm(): void
{
- global $DIC;
-
- $request = $DIC->http()->request();
+ $request = $this->blog_gui->http()->request();
$form = $this->initKeywordsForm();
if ($request->getMethod() === "POST"
diff --git a/components/ILIAS/Blog/Tasks/classes/class.ilBlogDraftsDerivedTaskProvider.php b/components/ILIAS/Blog/Tasks/classes/class.ilBlogDraftsDerivedTaskProvider.php
index 800be9b2ff13..49f0c0a3c3aa 100755
--- a/components/ILIAS/Blog/Tasks/classes/class.ilBlogDraftsDerivedTaskProvider.php
+++ b/components/ILIAS/Blog/Tasks/classes/class.ilBlogDraftsDerivedTaskProvider.php
@@ -37,8 +37,9 @@ public function __construct(
) {
global $DIC;
- $this->gui = $DIC->blog()->internal()->gui();
- $this->domain = $DIC->blog()->internal()->domain();
+ $service = $DIC->blog()->internal();
+ $this->gui = $service->gui();
+ $this->domain = $service->domain();
$this->taskService = $taskService;
$this->accessHandler = $accessHandler;
$this->lng = $lng;
diff --git a/components/ILIAS/Blog/classes/class.ilBlogNewsRendererGUI.php b/components/ILIAS/Blog/classes/class.ilBlogNewsRendererGUI.php
index 3275e896e556..32dfa9f6ddc2 100755
--- a/components/ILIAS/Blog/classes/class.ilBlogNewsRendererGUI.php
+++ b/components/ILIAS/Blog/classes/class.ilBlogNewsRendererGUI.php
@@ -18,17 +18,21 @@
declare(strict_types=1);
-/**
- * Blog news renderer
- * @author Alexander Killing
- */
class ilBlogNewsRendererGUI extends ilNewsDefaultRendererGUI
{
- public function getObjectLink(): string
+ protected \ILIAS\Blog\InternalGUIService $blog_gui;
+
+ public function __construct()
{
global $DIC;
+ parent::__construct();
+ $service = $DIC->blog()->internal();
+ $this->blog_gui = $service->gui();
+ }
- $pl = $DIC->blog()->internal()->gui()->permanentLink($this->getNewsRefId());
+ public function getObjectLink(): string
+ {
+ $pl = $this->blog_gui->permanentLink($this->getNewsRefId());
$n = $this->getNewsItem();
$posting_id = 0;
diff --git a/components/ILIAS/Blog/classes/class.ilObjBlog.php b/components/ILIAS/Blog/classes/class.ilObjBlog.php
index 27da54a1f0b0..90092326f992 100755
--- a/components/ILIAS/Blog/classes/class.ilObjBlog.php
+++ b/components/ILIAS/Blog/classes/class.ilObjBlog.php
@@ -44,8 +44,9 @@ public function __construct(
) {
global $DIC;
+ $service = $DIC->blog()->internal();
$this->notes_service = $DIC->notes();
- $this->settings_manager = $DIC->blog()->internal()->domain()->blogSettings();
+ $this->settings_manager = $service->domain()->blogSettings();
parent::__construct($a_id, $a_reference);
$this->rbac_review = $DIC->rbac()->review();
@@ -57,7 +58,7 @@ public function __construct(
if ($this->getId() > 0) {
$this->blog_settings = $this->settings_manager->getByObjId($this->getId());
}
- $this->posting_manager = $DIC->blog()->internal()->domain()->posting();
+ $this->posting_manager = $service->domain()->posting();
}
protected function initType(): void
diff --git a/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php b/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
index 099336228a0b..49b0f4b51f14 100755
--- a/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
+++ b/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
@@ -1810,10 +1810,8 @@ public function renderNavigation(
}
if (count($blocks)) {
- global $DIC;
-
- $ui_factory = $DIC->ui()->factory();
- $ui_renderer = $DIC->ui()->renderer();
+ $ui_factory = $this->ui->factory();
+ $ui_renderer = $this->ui->renderer();
ksort($blocks);
foreach ($blocks as $block) {
From 4c20b8d80ccf22184ad28043210253155bdefc17 Mon Sep 17 00:00:00 2001
From: Alexander Killing
Date: Sat, 27 Jun 2026 17:23:45 +0200
Subject: [PATCH 022/108] blog: improve DIC handling
---
components/ILIAS/Blog/Export/BlogHtmlExport.php | 17 ++++++++++-------
.../ILIAS/Blog/Export/class.ilBlogDataSet.php | 8 +++++---
.../ILIAS/Blog/Export/class.ilBlogExporter.php | 5 ++++-
.../ILIAS/Blog/Export/class.ilBlogImporter.php | 3 ++-
.../ILIAS/Blog/News/class.NewsManager.php | 6 +++---
.../Blog/PermanentLink/StaticUrlHandler.php | 3 ++-
.../Service/class.InternalDomainService.php | 3 ++-
.../Blog/classes/class.ilObjBlogListGUI.php | 5 ++---
8 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/components/ILIAS/Blog/Export/BlogHtmlExport.php b/components/ILIAS/Blog/Export/BlogHtmlExport.php
index b94f698f5158..e23f6447c2da 100755
--- a/components/ILIAS/Blog/Export/BlogHtmlExport.php
+++ b/components/ILIAS/Blog/Export/BlogHtmlExport.php
@@ -56,11 +56,13 @@ public function __construct(
$this->blog_gui = $blog_gui;
/** @var \ilObjBlog $blog */
$blog = $blog_gui->getObject();
+ $this->blog = $blog;
+
+ $blog_service = $DIC->blog()->internal();
+
$this->collector = $DIC->export()->domain()->html()->collector($blog->getId());
$this->collector->init();
- $this->blog = $blog;
- //$this->export_dir = $exp_dir;
$this->sub_dir = $sub_dir;
$this->target_dir = $exp_dir . "/" . $sub_dir;
@@ -86,7 +88,7 @@ public function __construct(
} else {
$this->content_style_domain = $cs->domain()->styleForObjId($this->blog->getId());
}
- $this->posting_manager = $DIC->blog()->internal()->domain()->posting();
+ $this->posting_manager = $blog_service->domain()->posting();
}
protected function init(): void
{
@@ -339,8 +341,6 @@ public function buildExportLink(
protected function getInitialisedTemplate(
string $a_back_url = ""
): \ilGlobalPageTemplate {
- global $DIC;
-
$this->export_util->resetGlobalScreen();
$location_stylesheet = \ilUtil::getStyleSheetLocation();
@@ -350,13 +350,16 @@ protected function getInitialisedTemplate(
);
\ilPCQuestion::resetInitialState();
- $tabs = $DIC->tabs();
+ $tabs = $this->tabs;
$tabs->clearTargets();
$tabs->clearSubTabs();
if ($a_back_url) {
$tabs->setBackTarget($this->lng->txt("back"), $a_back_url);
}
- $tpl = new \ilGlobalPageTemplate($DIC->globalScreen(), $DIC->ui(), $DIC->http());
+
+ /** @var \ILIAS\DI\Container $DIC */
+ global $DIC;
+ $tpl = new \ilGlobalPageTemplate($this->global_screen, $DIC->ui(), $DIC->http());
$this->co_page_html_export->getPreparedMainTemplate($tpl);
diff --git a/components/ILIAS/Blog/Export/class.ilBlogDataSet.php b/components/ILIAS/Blog/Export/class.ilBlogDataSet.php
index 7e688a01008b..b8f8e9195cbe 100755
--- a/components/ILIAS/Blog/Export/class.ilBlogDataSet.php
+++ b/components/ILIAS/Blog/Export/class.ilBlogDataSet.php
@@ -44,13 +44,15 @@ public function __construct()
{
global $DIC;
parent::__construct();
+
+ $blog_service = $DIC->blog()->internal();
+
$this->content_style_domain = $DIC
->contentStyle()
->domain();
$this->notes = $DIC->notes();
- $this->reading_time = $DIC->blog()->internal()->domain()->readingTime();
- $this->blog_settings = $DIC->blog()->internal()->domain()->blogSettings();
- $this->service = $DIC->blog()->internal();
+ $this->reading_time = $blog_service->domain()->readingTime();
+ $this->blog_settings = $blog_service->domain()->blogSettings();
}
public function getSupportedVersions(): array
diff --git a/components/ILIAS/Blog/Export/class.ilBlogExporter.php b/components/ILIAS/Blog/Export/class.ilBlogExporter.php
index ca20e3be90f0..71b49d3c5e4a 100755
--- a/components/ILIAS/Blog/Export/class.ilBlogExporter.php
+++ b/components/ILIAS/Blog/Export/class.ilBlogExporter.php
@@ -34,10 +34,13 @@ public function init(): void
$this->ds = new ilBlogDataSet();
$this->ds->setDSPrefix("ds");
+
+ $blog_service = $DIC->blog()->internal();
+
$this->content_style_domain = $DIC
->contentStyle()
->domain();
- $this->posting_manager = $DIC->blog()->internal()->domain()->posting();
+ $this->posting_manager = $blog_service->domain()->posting();
}
public function getXmlExportTailDependencies(
diff --git a/components/ILIAS/Blog/Export/class.ilBlogImporter.php b/components/ILIAS/Blog/Export/class.ilBlogImporter.php
index 60f8f93b4a01..d5b1e2b0ed29 100755
--- a/components/ILIAS/Blog/Export/class.ilBlogImporter.php
+++ b/components/ILIAS/Blog/Export/class.ilBlogImporter.php
@@ -62,11 +62,12 @@ public function finalProcessing(
ilImportMapping $a_mapping
): void {
global $DIC;
+ $blog_service = $DIC->blog()->internal();
$blp_map = $a_mapping->getMappingsOfEntity("components/ILIAS/COPage", "pg");
foreach ($blp_map as $blp_id) {
$blp_id = (int) substr($blp_id, 4);
- $blog_id = $DIC->blog()->internal()->domain()->posting()->lookupBlogId($blp_id);
+ $blog_id = $blog_service->domain()->posting()->lookupBlogId($blp_id);
ilBlogPosting::_writeParentId("blp", $blp_id, (int) $blog_id);
}
diff --git a/components/ILIAS/Blog/News/class.NewsManager.php b/components/ILIAS/Blog/News/class.NewsManager.php
index cc3c2d6b68ae..59227a090de8 100644
--- a/components/ILIAS/Blog/News/class.NewsManager.php
+++ b/components/ILIAS/Blog/News/class.NewsManager.php
@@ -34,10 +34,10 @@ class NewsManager
public function __construct(
protected InternalDataService $data,
protected InternalRepoService $repo,
- protected InternalDomainService $domain
+ protected InternalDomainService $domain,
+ \ILIAS\Blog\InternalGUIService $gui
) {
- global $DIC;
- $this->posting_gui = $DIC->blog()->internal()->gui()->posting();
+ $this->posting_gui = $gui->posting();
}
/**
diff --git a/components/ILIAS/Blog/PermanentLink/StaticUrlHandler.php b/components/ILIAS/Blog/PermanentLink/StaticUrlHandler.php
index f2e3ea3b9f5c..5589c26e47e2 100644
--- a/components/ILIAS/Blog/PermanentLink/StaticUrlHandler.php
+++ b/components/ILIAS/Blog/PermanentLink/StaticUrlHandler.php
@@ -37,11 +37,12 @@ public function getNamespace(): string
public function handle(Request $request, Context $context, Factory $response_factory): Response
{
global $DIC;
+ $blog_service = $DIC->blog()->internal();
$ctrl = $DIC->ctrl();
$access = $DIC->access();
$uri = null;
- $blog_domain = $DIC->blog()->internal()->domain();
+ $blog_domain = $blog_service->domain();
$id = $request->getReferenceId()?->toInt() ?? 0;
$additional_params = $request->getAdditionalParameters() ?? [];
diff --git a/components/ILIAS/Blog/Service/class.InternalDomainService.php b/components/ILIAS/Blog/Service/class.InternalDomainService.php
index 55b2141439c3..8aa784d42057 100755
--- a/components/ILIAS/Blog/Service/class.InternalDomainService.php
+++ b/components/ILIAS/Blog/Service/class.InternalDomainService.php
@@ -119,7 +119,8 @@ public function news(): NewsManager
return self::$instance["news"] ??= new NewsManager(
$this->data,
$this->repo,
- $this
+ $this,
+ $this->dic->blog()->internal()->gui()
);
}
diff --git a/components/ILIAS/Blog/classes/class.ilObjBlogListGUI.php b/components/ILIAS/Blog/classes/class.ilObjBlogListGUI.php
index 6212950298f3..ffd04737cbe0 100755
--- a/components/ILIAS/Blog/classes/class.ilObjBlogListGUI.php
+++ b/components/ILIAS/Blog/classes/class.ilObjBlogListGUI.php
@@ -70,11 +70,10 @@ public function insertCommand(
string $onclick = ""
): void {
global $DIC;
+ $blog_service = $DIC->blog()->internal();
$tpl = $this->ui->mainTemplate();
- $export_possible = $DIC->blog()
- ->internal()
- ->domain()
+ $export_possible = $blog_service->domain()
->export()
->isCommentsExportPossible($this->obj_id);
if ($cmd === "export"
From 391b0683627f0b4b2ce27d827aaeae2bbc0ad82f Mon Sep 17 00:00:00 2001
From: Alexander Killing
Date: Sat, 27 Jun 2026 19:17:27 +0200
Subject: [PATCH 023/108] blog: improve DIC handling
---
.../ILIAS/Blog/Export/class.ilBlogExporter.php | 14 +++++++++-----
.../ILIAS/Blog/Export/class.ilBlogImporter.php | 17 +++++++++--------
.../Blog/PermanentLink/StaticUrlHandler.php | 17 ++++++++++++-----
.../Blog/classes/class.ilObjBlogListGUI.php | 11 +++++++++--
4 files changed, 39 insertions(+), 20 deletions(-)
diff --git a/components/ILIAS/Blog/Export/class.ilBlogExporter.php b/components/ILIAS/Blog/Export/class.ilBlogExporter.php
index 71b49d3c5e4a..4132a223fb5f 100755
--- a/components/ILIAS/Blog/Export/class.ilBlogExporter.php
+++ b/components/ILIAS/Blog/Export/class.ilBlogExporter.php
@@ -28,13 +28,10 @@ class ilBlogExporter extends ilXmlExporter
protected ilBlogDataSet $ds;
protected \ILIAS\Style\Content\DomainService $content_style_domain;
- public function init(): void
+ public function __construct()
{
global $DIC;
-
- $this->ds = new ilBlogDataSet();
- $this->ds->setDSPrefix("ds");
-
+ parent::__construct();
$blog_service = $DIC->blog()->internal();
$this->content_style_domain = $DIC
@@ -43,6 +40,13 @@ public function init(): void
$this->posting_manager = $blog_service->domain()->posting();
}
+
+ public function init(): void
+ {
+ $this->ds = new ilBlogDataSet();
+ $this->ds->setDSPrefix("ds");
+ }
+
public function getXmlExportTailDependencies(
string $a_entity,
string $a_target_release,
diff --git a/components/ILIAS/Blog/Export/class.ilBlogImporter.php b/components/ILIAS/Blog/Export/class.ilBlogImporter.php
index d5b1e2b0ed29..d0c21290b127 100755
--- a/components/ILIAS/Blog/Export/class.ilBlogImporter.php
+++ b/components/ILIAS/Blog/Export/class.ilBlogImporter.php
@@ -25,19 +25,23 @@
*/
class ilBlogImporter extends ilXmlImporter
{
+ protected \ILIAS\Blog\InternalService $blog_service;
protected ilBlogDataSet $ds;
protected \ILIAS\Style\Content\DomainService $content_style_domain;
- public function init(): void
+ public function __construct()
{
global $DIC;
-
- $this->ds = new ilBlogDataSet();
- $this->ds->setDSPrefix("ds");
$this->content_style_domain = $DIC
->contentStyle()
->domain();
+ $this->blog_service = $DIC->blog()->internal();
+ }
+ public function init(): void
+ {
+ $this->ds = new ilBlogDataSet();
+ $this->ds->setDSPrefix("ds");
$cop_config = $this->getImport()->getConfig("components/ILIAS/COPage");
$cop_config->setUpdateIfExists(true);
}
@@ -61,13 +65,10 @@ public function importXmlRepresentation(
public function finalProcessing(
ilImportMapping $a_mapping
): void {
- global $DIC;
- $blog_service = $DIC->blog()->internal();
-
$blp_map = $a_mapping->getMappingsOfEntity("components/ILIAS/COPage", "pg");
foreach ($blp_map as $blp_id) {
$blp_id = (int) substr($blp_id, 4);
- $blog_id = $blog_service->domain()->posting()->lookupBlogId($blp_id);
+ $blog_id = $this->blog_service->domain()->posting()->lookupBlogId($blp_id);
ilBlogPosting::_writeParentId("blp", $blp_id, (int) $blog_id);
}
diff --git a/components/ILIAS/Blog/PermanentLink/StaticUrlHandler.php b/components/ILIAS/Blog/PermanentLink/StaticUrlHandler.php
index 5589c26e47e2..2a0261e113f7 100644
--- a/components/ILIAS/Blog/PermanentLink/StaticUrlHandler.php
+++ b/components/ILIAS/Blog/PermanentLink/StaticUrlHandler.php
@@ -29,6 +29,15 @@
class StaticURLHandler extends BaseHandler implements Handler
{
+ protected \ILIAS\Blog\InternalService $blog_service;
+
+ public function __construct()
+ {
+ global $DIC;
+ $this->blog_service = $DIC->blog()->internal();
+ parent::__construct();
+ }
+
public function getNamespace(): string
{
return 'blog';
@@ -36,11 +45,9 @@ public function getNamespace(): string
public function handle(Request $request, Context $context, Factory $response_factory): Response
{
- global $DIC;
- $blog_service = $DIC->blog()->internal();
-
- $ctrl = $DIC->ctrl();
- $access = $DIC->access();
+ $blog_service = $this->blog_service;
+ $ctrl = $blog_service->gui()->ctrl();
+ $access = $blog_service->domain()->access();
$uri = null;
$blog_domain = $blog_service->domain();
diff --git a/components/ILIAS/Blog/classes/class.ilObjBlogListGUI.php b/components/ILIAS/Blog/classes/class.ilObjBlogListGUI.php
index ffd04737cbe0..d0437edddf09 100755
--- a/components/ILIAS/Blog/classes/class.ilObjBlogListGUI.php
+++ b/components/ILIAS/Blog/classes/class.ilObjBlogListGUI.php
@@ -27,6 +27,14 @@
class ilObjBlogListGUI extends ilObjectListGUI
{
private ?Modal $comment_modal = null;
+ protected \ILIAS\Blog\InternalService $blog_service;
+
+ public function __construct(int $context = self::CONTEXT_REPOSITORY)
+ {
+ global $DIC;
+ parent::__construct($context);
+ $this->blog_service = $DIC->blog()->internal();
+ }
public function init(): void
{
@@ -69,8 +77,7 @@ public function insertCommand(
string $cmd = "",
string $onclick = ""
): void {
- global $DIC;
- $blog_service = $DIC->blog()->internal();
+ $blog_service = $this->blog_service;
$tpl = $this->ui->mainTemplate();
$export_possible = $blog_service->domain()
From 42f193e1470a7ebf9ba4aaaaac46e7be576a556e Mon Sep 17 00:00:00 2001
From: Alexander Killing
Date: Sat, 27 Jun 2026 19:51:52 +0200
Subject: [PATCH 024/108] fixed copyright
---
.../Blog/Posting/Service/class.GUIService.php | 16 +++++++++++++++-
components/ILIAS/Blog/RSS/RSSGUI.php | 16 +++++++++++++++-
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/components/ILIAS/Blog/Posting/Service/class.GUIService.php b/components/ILIAS/Blog/Posting/Service/class.GUIService.php
index 7fcd9217f95e..8e90ca73064a 100644
--- a/components/ILIAS/Blog/Posting/Service/class.GUIService.php
+++ b/components/ILIAS/Blog/Posting/Service/class.GUIService.php
@@ -1,6 +1,20 @@
Date: Sat, 27 Jun 2026 21:54:29 +0200
Subject: [PATCH 025/108] blog: moved contributor code to subservice
---
.../ILIAS/Blog/Contributor/ContributorGUI.php | 262 ++++++++++++++++++
.../Contributor/Service/class.GUIService.php | 11 +
.../Blog/Service/class.InternalGUIService.php | 11 +-
.../ILIAS/Blog/classes/class.ilObjBlogGUI.php | 229 ++-------------
4 files changed, 297 insertions(+), 216 deletions(-)
create mode 100644 components/ILIAS/Blog/Contributor/ContributorGUI.php
diff --git a/components/ILIAS/Blog/Contributor/ContributorGUI.php b/components/ILIAS/Blog/Contributor/ContributorGUI.php
new file mode 100644
index 000000000000..c2a277e0581e
--- /dev/null
+++ b/components/ILIAS/Blog/Contributor/ContributorGUI.php
@@ -0,0 +1,262 @@
+gui->ctrl();
+ $next_class = $ctrl->getNextClass($this);
+ $cmd = $ctrl->getCmd("contributors");
+
+ switch ($next_class) {
+ case strtolower(\ilRepositorySearchGUI::class):
+ $rep_search = new \ilRepositorySearchGUI();
+ $rep_search->setTitle($this->domain->lng()->txt("blog_add_contributor"));
+ $rep_search->setCallback($this, 'addContributor', $this->blog->getAllLocalRoles($this->node_id));
+ $ctrl->setReturn($this, 'contributors');
+ $ctrl->forwardCommand($rep_search);
+ break;
+
+ default:
+ if (method_exists($this, $cmd)) {
+ $this->$cmd();
+ }
+ break;
+ }
+ }
+
+ public function contributors(): void
+ {
+ $ilTabs = $this->gui->tabs();
+ $ilToolbar = $this->gui->toolbar();
+ $ilCtrl = $this->gui->ctrl();
+ $lng = $this->domain->lng();
+ $tpl = $this->gui->ui()->mainTemplate();
+
+ $ilTabs->activateTab("contributors");
+
+ $local_roles = $this->blog->getAllLocalRoles($this->node_id);
+
+ // add member
+ ilRepositorySearchGUI::fillAutoCompleteToolbar(
+ $this,
+ $ilToolbar,
+ array(
+ 'auto_complete_name' => $lng->txt('user'),
+ 'submit_name' => $lng->txt('add'),
+ 'add_search' => true,
+ 'add_from_container' => $this->node_id,
+ 'user_type' => $local_roles
+ ),
+ true
+ );
+
+ $other_roles = $this->blog->getRolesWithContributeOrRedact($this->node_id);
+ if ($other_roles) {
+ $tpl->setOnScreenMessage('info', sprintf($lng->txt("blog_contribute_other_roles"), implode(", ", $other_roles)));
+ }
+
+ $table = $this->gui->contributor()->contributorTableBuilder(
+ $this->blog->getAllLocalRoles($this->node_id),
+ $this,
+ "contributors"
+ )->getTable();
+
+ if ($table->handleCommand()) {
+ return;
+ }
+
+ $tpl->setContent($table->render());
+ }
+
+ /**
+ * Autocomplete submit
+ */
+ public function addUserFromAutoComplete(): void
+ {
+ $lng = $this->domain->lng();
+ $req = $this->gui->standardRequest();
+
+ $user_login = $req->getUserLogin();
+ $user_type = $req->getUserType();
+
+ if (trim($user_login) === '') {
+ $this->gui->ui()->mainTemplate()->setOnScreenMessage('failure', $lng->txt('msg_no_search_string'));
+ $this->contributors();
+ return;
+ }
+ $users = explode(',', $user_login);
+
+ $user_ids = array();
+ foreach ($users as $user) {
+ $user_id = ilObjUser::_lookupId($user);
+
+ if (!$user_id) {
+ $this->gui->ui()->mainTemplate()->setOnScreenMessage('failure', $lng->txt('user_not_known'));
+ $this->contributors();
+ return;
+ }
+
+ $user_ids[] = (int) $user_id;
+ }
+
+ $this->addContributor($user_ids, $user_type);
+ }
+
+ /**
+ * Centralized method to add contributors
+ */
+ public function addContributor(
+ array $a_user_ids = array(),
+ ?string $a_user_type = null
+ ): void {
+ $ilCtrl = $this->gui->ctrl();
+ $lng = $this->domain->lng();
+ $rbacreview = $this->domain->rbac()->review();
+ $rbacadmin = $this->domain->rbac()->admin();
+ $a_user_type = (int) $a_user_type;
+
+ if (empty($a_user_ids)) {
+ $a_user_ids = $this->gui->standardRequest()->getIds();
+ }
+
+ if (!count($a_user_ids) || !$a_user_type) {
+ $this->gui->ui()->mainTemplate()->setOnScreenMessage('failure', $lng->txt("no_checkbox"));
+ $this->contributors();
+ return;
+ }
+
+ // get contributor role
+ $local_roles = array_keys($this->blog->getAllLocalRoles($this->node_id));
+ if (!in_array($a_user_type, $local_roles)) {
+ $this->gui->ui()->mainTemplate()->setOnScreenMessage('failure', $lng->txt("missing_perm"));
+ $this->contributors();
+ return;
+ }
+
+ foreach ($a_user_ids as $user_id) {
+ $user_id = (int) $user_id;
+ $a_user_type = (int) $a_user_type;
+ if (!$rbacreview->isAssigned($user_id, $a_user_type)) {
+ $rbacadmin->assignUser($a_user_type, $user_id);
+ }
+ }
+
+ $this->gui->ui()->mainTemplate()->setOnScreenMessage('success', $lng->txt("settings_saved"), true);
+ $ilCtrl->redirect($this, "contributors");
+ }
+
+ /**
+ * Used in ContributorTableBuilder
+ */
+ public function confirmRemoveContributor(array $ids = []): void
+ {
+ if (empty($ids)) {
+ $ids = $this->gui->standardRequest()->getIds();
+ }
+ if (count($ids) === 0) {
+ $this->gui->ui()->mainTemplate()->setOnScreenMessage('failure', $this->domain->lng()->txt("select_one"), true);
+ $this->gui->ctrl()->redirect($this, "contributors");
+ }
+
+ $confirm = new ilConfirmationGUI();
+ $confirm->setHeaderText($this->domain->lng()->txt('blog_confirm_delete_contributors'));
+ $confirm->setFormAction($this->gui->ctrl()->getFormAction($this, 'removeContributor'));
+ $confirm->setConfirm($this->domain->lng()->txt('delete'), 'removeContributor');
+ $confirm->setCancel($this->domain->lng()->txt('cancel'), 'contributors');
+
+ foreach ($ids as $user_id) {
+ $confirm->addItem(
+ 'id[]',
+ (string) $user_id,
+ \ilUserUtil::getNamePresentation($user_id, false, false, "", true)
+ );
+ }
+
+ $this->gui->ui()->mainTemplate()->setContent($confirm->getHTML());
+ }
+
+ public function removeContributor(): void
+ {
+ $ilCtrl = $this->gui->ctrl();
+ $lng = $this->domain->lng();
+ $rbacadmin = $this->domain->rbac()->admin();
+
+ $ids = $this->gui->standardRequest()->getIds();
+
+ if (count($ids) === 0) {
+ $this->gui->ui()->mainTemplate()->setOnScreenMessage('failure', $lng->txt("select_one"), true);
+ $ilCtrl->redirect($this, "contributors");
+ }
+
+ // get contributor role
+ $local_roles = array_keys($this->blog->getAllLocalRoles($this->node_id));
+ if (!$local_roles) {
+ $this->gui->ui()->mainTemplate()->setOnScreenMessage('failure', $lng->txt("missing_perm"));
+ $this->contributors();
+ return;
+ }
+
+ foreach ($ids as $user_id) {
+ foreach ($local_roles as $role_id) {
+ $rbacadmin->deassignUser($role_id, $user_id);
+ }
+ }
+
+ $this->gui->ui()->mainTemplate()->setOnScreenMessage('success', $lng->txt("settings_saved"), true);
+ $this->gui->ctrl()->redirect($this, "contributors");
+ }
+
+ /**
+ * Used in ContributorTableBuilder
+ */
+ public function addContributorContainerAction(array $ids = []): void
+ {
+ if (empty($ids)) {
+ $ids = $this->gui->standardRequest()->getIds();
+ }
+
+ // This would typically add contributors from a container
+ // For now, redirecting back to contributors as this seems to be a placeholder action
+ $this->gui->ctrl()->redirect($this, "contributors");
+ }
+}
diff --git a/components/ILIAS/Blog/Contributor/Service/class.GUIService.php b/components/ILIAS/Blog/Contributor/Service/class.GUIService.php
index ef8de2f00f64..8007e5d6d2d8 100755
--- a/components/ILIAS/Blog/Contributor/Service/class.GUIService.php
+++ b/components/ILIAS/Blog/Contributor/Service/class.GUIService.php
@@ -57,4 +57,15 @@ public function contributorTableBuilder(
$parent_cmd
);
}
+
+ public function contributorGUI(int $node_id, \ilObjBlog $blog): ContributorGUI
+ {
+ return new ContributorGUI(
+ $this->data_service,
+ $this->domain_service,
+ $this->gui,
+ $node_id,
+ $blog
+ );
+ }
}
diff --git a/components/ILIAS/Blog/Service/class.InternalGUIService.php b/components/ILIAS/Blog/Service/class.InternalGUIService.php
index fad63aa0f514..7fad2a4afa9c 100755
--- a/components/ILIAS/Blog/Service/class.InternalGUIService.php
+++ b/components/ILIAS/Blog/Service/class.InternalGUIService.php
@@ -67,11 +67,12 @@ public function standardRequest(): StandardGUIRequest
public function contributor(): Contributor\GUIService
{
- return new Contributor\GUIService(
- $this->data_service,
- $this->domain_service,
- $this
- );
+ return self::$instance["contributor"] ??
+ self::$instance["contributor"] = new Contributor\GUIService(
+ $this->data_service,
+ $this->domain_service,
+ $this
+ );
}
public function exercise(): Exercise\GUIService
diff --git a/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php b/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
index 49b0f4b51f14..6938914a27d5 100755
--- a/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
+++ b/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
@@ -30,15 +30,17 @@
use ILIAS\Blog\Settings\Settings;
use ILIAS\Blog\ReadingTime\ReadingTimeManager;
use ILIAS\Blog\Posting\PostingManager;
+use ILIAS\Blog\Contributor\ContributorGUI;
/**
* @ilCtrl_Calls ilObjBlogGUI: ilBlogPostingGUI, ilWorkspaceAccessGUI
* @ilCtrl_Calls ilObjBlogGUI: ilInfoScreenGUI, ilNoteGUI, ilCommonActionDispatcherGUI
- * @ilCtrl_Calls ilObjBlogGUI: ilPermissionGUI, ilObjectCopyGUI, ilRepositorySearchGUI
+ * @ilCtrl_Calls ilObjBlogGUI: ilPermissionGUI, ilObjectCopyGUI
* @ilCtrl_Calls ilObjBlogGUI: ilExportGUI, ilObjectContentStyleSettingsGUI, ilBlogExerciseGUI, ilObjNotificationSettingsGUI
* @ilCtrl_Calls ilObjBlogGUI: ilObjectMetaDataGUI
* @ilCtrl_Calls ilObjBlogGUI: ILIAS\Blog\Settings\SettingsGUI
* @ilCtrl_Calls ilObjBlogGUI: ILIAS\Blog\Settings\BlockSettingsGUI
+ * @ilCtrl_Calls ilObjBlogGUI: ILIAS\Blog\Contributor\ContributorGUI
*/
class ilObjBlogGUI extends ilObject2GUI implements ilDesktopItemHandling
{
@@ -295,7 +297,7 @@ protected function setTabs(): void
$this->tabs_gui->addTab(
"contributors",
$lng->txt("blog_contributors"),
- $this->ctrl->getLinkTarget($this, "contributors")
+ $this->ctrl->getLinkTargetByClass(ContributorGUI::class, "contributors")
);
}
@@ -508,14 +510,11 @@ public function executeCommand(): void
$this->ctrl->forwardCommand($cp);
break;
- case 'ilrepositorysearchgui':
+ case strtolower(\ilRepositorySearchGUI::class):
+ $this->checkPermission("write");
$this->prepareOutput();
$ilTabs->activateTab("contributors");
- $rep_search = new ilRepositorySearchGUI();
- $rep_search->setTitle($this->lng->txt("blog_add_contributor"));
- $rep_search->setCallback($this, 'addContributor', $this->object->getAllLocalRoles($this->node_id));
- $this->ctrl->setReturn($this, 'contributors');
- $this->ctrl->forwardCommand($rep_search);
+ $this->ctrl->forwardCommand($this->gui->contributor()->contributorGUI($this->node_id, $this->object));
break;
case 'ilexportgui':
@@ -581,6 +580,17 @@ public function executeCommand(): void
$this->ctrl->forwardCommand($gui);
break;
+ case strtolower(ContributorGUI::class):
+ $this->checkPermission("write");
+ $this->prepareOutput();
+ $ilTabs->activateTab("contributors");
+ $gui = $this->gui->contributor()->contributorGUI(
+ $this->node_id,
+ $this->object
+ );
+ $this->ctrl->forwardCommand($gui);
+ break;
+
case strtolower(\ILIAS\Blog\Settings\BlockSettingsGUI::class):
$this->checkPermission("write");
$this->prepareOutput();
@@ -2127,209 +2137,6 @@ public function approve(): void
}
- //
- // contributors
- //
-
- public function contributors(): void
- {
- $ilTabs = $this->tabs;
- $ilToolbar = $this->toolbar;
- $ilCtrl = $this->ctrl;
- $lng = $this->lng;
- $tpl = $this->tpl;
-
- if (!$this->checkPermissionBool("write")) {
- return;
- }
-
- $ilTabs->activateTab("contributors");
-
- $local_roles = $this->object->getAllLocalRoles($this->node_id);
-
- // add member
- ilRepositorySearchGUI::fillAutoCompleteToolbar(
- $this,
- $ilToolbar,
- array(
- 'auto_complete_name' => $lng->txt('user'),
- 'submit_name' => $lng->txt('add'),
- 'add_search' => true,
- 'add_from_container' => $this->node_id,
- 'user_type' => $local_roles
- ),
- true
- );
-
- $other_roles = $this->object->getRolesWithContributeOrRedact($this->node_id);
- if ($other_roles) {
- $this->tpl->setOnScreenMessage('info', sprintf($lng->txt("blog_contribute_other_roles"), implode(", ", $other_roles)));
- }
-
- $table = $this->gui->contributor()->contributorTableBuilder(
- $this->object->getAllLocalRoles($this->node_id),
- $this,
- "contributors"
- )->getTable();
-
- if ($table->handleCommand()) {
- return;
- }
-
- $tpl->setContent($table->render());
- }
-
- /**
- * Autocomplete submit
- */
- public function addUserFromAutoComplete(): void
- {
- $lng = $this->lng;
-
- $user_login = $this->blog_request->getUserLogin();
- $user_type = $this->blog_request->getUserType();
-
- if (trim($user_login) === '') {
- $this->tpl->setOnScreenMessage('failure', $lng->txt('msg_no_search_string'));
- $this->contributors();
- return;
- }
- $users = explode(',', $user_login);
-
- $user_ids = array();
- foreach ($users as $user) {
- $user_id = ilObjUser::_lookupId($user);
-
- if (!$user_id) {
- $this->tpl->setOnScreenMessage('failure', $lng->txt('user_not_known'));
- $this->contributors();
- return;
- }
-
- $user_ids[] = (int) $user_id;
- }
-
- $this->addContributor($user_ids, $user_type);
- }
-
- /**
- * Centralized method to add contributors
- */
- public function addContributor(
- array $a_user_ids = array(),
- ?string $a_user_type = null
- ): void {
- $ilCtrl = $this->ctrl;
- $lng = $this->lng;
- $rbacreview = $this->rbac_review;
- $rbacadmin = $this->rbacadmin;
- $a_user_type = (int) $a_user_type;
-
- if (!$this->checkPermissionBool("write")) {
- return;
- }
-
- if (!count($a_user_ids) || !$a_user_type) {
- $this->tpl->setOnScreenMessage('failure', $lng->txt("no_checkbox"));
- $this->contributors();
- return;
- }
-
- // get contributor role
- $local_roles = array_keys($this->object->getAllLocalRoles($this->node_id));
- if (!in_array($a_user_type, $local_roles)) {
- $this->tpl->setOnScreenMessage('failure', $lng->txt("missing_perm"));
- $this->contributors();
- return;
- }
-
- foreach ($a_user_ids as $user_id) {
- $user_id = (int) $user_id;
- $a_user_type = (int) $a_user_type;
- if (!$rbacreview->isAssigned($user_id, $a_user_type)) {
- $rbacadmin->assignUser($a_user_type, $user_id);
- }
- }
-
- $this->tpl->setOnScreenMessage('success', $lng->txt("settings_saved"), true);
- $ilCtrl->redirect($this, "contributors");
- }
-
- /**
- * Used in ContributorTableBuilder
- */
- public function confirmRemoveContributor(array $ids = []): void
- {
- if (empty($ids)) {
- $ids = $this->blog_request->getIds();
- }
- if (count($ids) === 0) {
- $this->tpl->setOnScreenMessage('failure', $this->lng->txt("select_one"), true);
- $this->ctrl->redirect($this, "contributors");
- }
-
- $confirm = new ilConfirmationGUI();
- $confirm->setHeaderText($this->lng->txt('blog_confirm_delete_contributors'));
- $confirm->setFormAction($this->ctrl->getFormAction($this, 'removeContributor'));
- $confirm->setConfirm($this->lng->txt('delete'), 'removeContributor');
- $confirm->setCancel($this->lng->txt('cancel'), 'contributors');
-
- foreach ($ids as $user_id) {
- $confirm->addItem(
- 'id[]',
- (string) $user_id,
- $this->profile_gui->getNamePresentation($user_id, false, "", true)
- );
- }
-
- $this->tpl->setContent($confirm->getHTML());
- }
-
- public function removeContributor(): void
- {
- $ilCtrl = $this->ctrl;
- $lng = $this->lng;
- $rbacadmin = $this->rbacadmin;
-
- $ids = $this->blog_request->getIds();
-
- if (count($ids) === 0) {
- $this->tpl->setOnScreenMessage('failure', $lng->txt("select_one"), true);
- $ilCtrl->redirect($this, "contributors");
- }
-
- // get contributor role
- $local_roles = array_keys($this->object->getAllLocalRoles($this->node_id));
- if (!$local_roles) {
- $this->tpl->setOnScreenMessage('failure', $lng->txt("missing_perm"));
- $this->contributors();
- return;
- }
-
- foreach ($ids as $user_id) {
- foreach ($local_roles as $role_id) {
- $rbacadmin->deassignUser($role_id, $user_id);
- }
- }
-
- $this->tpl->setOnScreenMessage('success', $lng->txt("settings_saved"), true);
- $this->ctrl->redirect($this, "contributors");
- }
-
- /**
- * Used in ContributorTableBuilder
- */
- public function addContributorContainerAction(array $ids = []): void
- {
- if (empty($ids)) {
- $ids = $this->blog_request->getIds();
- }
-
- // This would typically add contributors from a container
- // For now, redirecting back to contributors as this seems to be a placeholder action
- $this->ctrl->redirect($this, "contributors");
- }
-
public function deactivateAdmin(): void
{
if ($this->checkPermissionBool("write") && $this->apid > 0) {
From dd7e52ff3981157dbd2747393a81bde2911a4bd3 Mon Sep 17 00:00:00 2001
From: Alexander Killing
Date: Sun, 28 Jun 2026 09:58:31 +0200
Subject: [PATCH 026/108] blog: moved side block rendering to navigation
subservice
---
.../Navigation/Service/class.GUIService.php | 24 ++
.../Blog/Service/class.InternalGUIService.php | 9 +-
.../ILIAS/Blog/classes/class.ilObjBlogGUI.php | 369 ++----------------
3 files changed, 53 insertions(+), 349 deletions(-)
diff --git a/components/ILIAS/Blog/Navigation/Service/class.GUIService.php b/components/ILIAS/Blog/Navigation/Service/class.GUIService.php
index e89279158f08..d420f56023c6 100755
--- a/components/ILIAS/Blog/Navigation/Service/class.GUIService.php
+++ b/components/ILIAS/Blog/Navigation/Service/class.GUIService.php
@@ -43,4 +43,28 @@ public function toolbarNavigationRenderer(
$this->gui
);
}
+
+ public function monthBlock(): MonthBlockGUI
+ {
+ return new MonthBlockGUI(
+ $this->domain,
+ $this->gui
+ );
+ }
+
+ public function authorBlock(): AuthorBlockGUI
+ {
+ return new AuthorBlockGUI(
+ $this->domain,
+ $this->gui
+ );
+ }
+
+ public function keywordBlock(): KeywordBlockGUI
+ {
+ return new KeywordBlockGUI(
+ $this->domain,
+ $this->gui
+ );
+ }
}
diff --git a/components/ILIAS/Blog/Service/class.InternalGUIService.php b/components/ILIAS/Blog/Service/class.InternalGUIService.php
index 7fad2a4afa9c..ddc5461168db 100755
--- a/components/ILIAS/Blog/Service/class.InternalGUIService.php
+++ b/components/ILIAS/Blog/Service/class.InternalGUIService.php
@@ -43,10 +43,11 @@ public function __construct(
public function navigation(): Navigation\GUIService
{
- return new Navigation\GUIService(
- $this->domain_service,
- $this
- );
+ return self::$instance["navigation"] ??
+ self::$instance["navigation"] = new Navigation\GUIService(
+ $this->domain_service,
+ $this
+ );
}
public function presentation(): Presentation\GUIService
diff --git a/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php b/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
index 6938914a27d5..11e4381f6043 100755
--- a/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
+++ b/components/ILIAS/Blog/classes/class.ilObjBlogGUI.php
@@ -518,7 +518,10 @@ public function executeCommand(): void
break;
case 'ilexportgui':
- $this->showExportGUI();
+ $this->prepareOutput();
+ $this->tabs->activateTab("export");
+ $exp_gui = new ilExportGUI($this);
+ $this->ctrl->forwardCommand($exp_gui);
break;
case "ilobjectcontentstylesettingsgui":
@@ -621,14 +624,6 @@ public function executeCommand(): void
}
}
- protected function showExportGUI(): void
- {
- $this->prepareOutput();
- $this->tabs->activateTab("export");
- $exp_gui = new ilExportGUI($this);
- $this->ctrl->forwardCommand($exp_gui);
- }
-
protected function createExportFileWithComments(): void
{
$this->buildExportFile(true);
@@ -1380,339 +1375,6 @@ protected function buildExportLink(
}
- /**
- * Build navigation by date block
- */
- protected function renderNavigationByDate(
- array $a_items,
- string $a_list_cmd = "render",
- string $a_posting_cmd = "preview",
- ?string $a_link_template = null,
- bool $a_show_inactive = false,
- int $a_blpg = 0
- ): string {
- $ilCtrl = $this->ctrl;
-
- $blpg = ($a_blpg > 0)
- ? $a_blpg
- : $this->blpg;
-
-
- // gather page active status
- foreach ($a_items as $month => $postings) {
- foreach (array_keys($postings) as $id) {
- $active = ilBlogPosting::_lookupActive($id, "blp");
- if (!$a_show_inactive && !$active) {
- unset($a_items[$month][$id]);
- }
- }
- if (!count($a_items[$month])) {
- unset($a_items[$month]);
- }
- }
-
- // list month (incl. postings)
- if ($this->blog_settings->getNavMode() === ilObjBlog::NAV_MODE_LIST || $a_link_template) {
- $max_months = $this->blog_settings->getNavModeListMonths();
-
- $wtpl = new ilTemplate("tpl.blog_list_navigation_by_date.html", true, true, "components/ILIAS/Blog");
-
- $ilCtrl->setParameter($this, "blpg", "");
-
- $counter = $mon_counter = $last_year = 0;
- foreach ($a_items as $month => $postings) {
- if (!$a_link_template && $max_months && $mon_counter >= $max_months) {
- break;
- }
-
- $add_year = false;
- $year = substr($month, 0, 4);
- if (!$last_year || $year != $last_year) {
- // #13562
- $add_year = true;
- $last_year = $year;
- }
-
- $mon_counter++;
-
- $month_name = ilCalendarUtil::_numericMonthToString((int) substr($month, 5));
- if (!$a_link_template) {
- $ilCtrl->setParameter($this, "bmn", $month);
- $month_url = $ilCtrl->getLinkTarget($this, $a_list_cmd);
- } else {
- $month_url = $this->buildExportLink($a_link_template, "list", (string) $month);
- }
-
- // list postings for month
- //if($counter < $max_detail_postings)
- if ($mon_counter <= $this->blog_settings->getNavModeListMonthsWithPostings()) {
- if ($add_year) {
- $wtpl->setCurrentBlock("navigation_year_details");
- $wtpl->setVariable("YEAR", $year);
- $wtpl->parseCurrentBlock();
- }
-
- foreach ($postings as $id => $posting) {
- //if($max_detail_postings && $counter >= $max_detail_postings)
- //{
- // break;
- //}
-
- $counter++;
-
- $caption = /* ilDatePresentation::formatDate($posting["created"], IL_CAL_DATETIME).
- ", ".*/ $posting->getTitle();
-
- if (!$a_link_template) {
- $ilCtrl->setParameterByClass("ilblogpostinggui", "bmn", $month);
- $ilCtrl->setParameterByClass("ilblogpostinggui", "blpg", $id);
- $url = $ilCtrl->getLinkTargetByClass("ilblogpostinggui", $a_posting_cmd);
- } else {
- $url = $this->buildExportLink($a_link_template, "posting", (string) $id);
- }
-
- if (!$posting->isActive()) {
- $wtpl->setVariable("NAV_ITEM_DRAFT", $this->lng->txt("blog_draft"));
- } elseif ($this->blog_settings->getApproval() && !$posting->isApproved()) {
- $wtpl->setVariable("NAV_ITEM_APPROVAL", $this->lng->txt("blog_needs_approval"));
- }
-
- $wtpl->setCurrentBlock("navigation_item");
- $wtpl->setVariable("NAV_ITEM_URL", $url);
- $wtpl->setVariable("NAV_ITEM_CAPTION", $caption);
- $wtpl->parseCurrentBlock();
- }
-
- $wtpl->setCurrentBlock("navigation_month_details");
- $wtpl->setVariable("NAV_MONTH", $month_name);
- $wtpl->setVariable("URL_MONTH", $month_url);
- }
- // summarized month
- else {
- if ($add_year) {
- $wtpl->setCurrentBlock("navigation_year");
- $wtpl->setVariable("YEAR", $year);
- $wtpl->parseCurrentBlock();
- }
-
- $wtpl->setCurrentBlock("navigation_month");
- $wtpl->setVariable("MONTH_NAME", $month_name);
- $wtpl->setVariable("URL_MONTH", $month_url);
- $wtpl->setVariable("MONTH_COUNT", count($postings));
- }
- $wtpl->parseCurrentBlock();
- }
- if (!$a_link_template) {
- $this->ctrl->setParameterByClass(self::class, "bmn", null);
- $url = $this->ctrl->getLinkTargetByClass(self::class, $a_list_cmd);
- } else {
- $url = "index.html";
- }
-
- $wtpl->setVariable(
- "STARTING_PAGE",
- $this->ui->renderer()->render(
- $this->ui->factory()->link()->standard(
- $this->lng->txt("blog_starting_page"),
- $url
- )
- )
- );
- }
- // single month
- else {
- $wtpl = new ilTemplate("tpl.blog_list_navigation_month.html", true, true, "components/ILIAS/Blog");
-
- $ilCtrl->setParameter($this, "blpg", "");
-
- $month_options = array();
- foreach ($a_items as $month => $postings) {
- $month_name = $this->gui->presentation()->util()->getMonthPresentation($month);
-
- $month_options[$month] = $month_name;
-
- if ($month == $this->month) {
- if (!$a_link_template) {
- $ilCtrl->setParameter($this, "bmn", $month);
- $month_url = $ilCtrl->getLinkTarget($this, $a_list_cmd);
- } else {
- $month_url = $this->buildExportLink($a_link_template, "list", (string) $month);
- }
-
- foreach ($postings as $id => $posting) {
- $caption = /* ilDatePresentation::formatDate($posting["created"], IL_CAL_DATETIME).
- ", ".*/ $posting["title"];
-
- if (!$a_link_template) {
- $ilCtrl->setParameterByClass("ilblogpostinggui", "bmn", $month);
- $ilCtrl->setParameterByClass("ilblogpostinggui", "blpg", $id);
- $url = $ilCtrl->getLinkTargetByClass("ilblogpostinggui", $a_posting_cmd);
- } else {
- $url = $this->buildExportLink($a_link_template, "posting", (string) $id);
- }
-
- if (!$posting->isActive()) {
- $wtpl->setVariable("NAV_ITEM_DRAFT", $this->lng->txt("blog_draft"));
- } elseif ($this->blog_settings->getApproval() && !$posting["approved"]) {
- $wtpl->setVariable("NAV_ITEM_APPROVAL", $this->lng->txt("blog_needs_approval"));
- }
-
- $wtpl->setCurrentBlock("navigation_item");
- $wtpl->setVariable("NAV_ITEM_URL", $url);
- $wtpl->setVariable("NAV_ITEM_CAPTION", $caption);
- $wtpl->parseCurrentBlock();
- }
-
- $wtpl->setCurrentBlock("navigation_month_details");
- if ($blpg > 0) {
- $wtpl->setVariable("NAV_MONTH", $month_name);
- $wtpl->setVariable("URL_MONTH", $month_url);
- }
- $wtpl->parseCurrentBlock();
- }
- }
-
- if ($blpg === 0) {
- $wtpl->setCurrentBlock("option_bl");
- foreach ($month_options as $value => $caption) {
- $wtpl->setVariable("OPTION_VALUE", $value);
- $wtpl->setVariable("OPTION_CAPTION", $caption);
- if ($value == $this->month) {
- $wtpl->setVariable("OPTION_SEL", ' selected="selected"');
- }
- $wtpl->parseCurrentBlock();
- }
-
- $wtpl->setVariable("FORM_ACTION", $ilCtrl->getFormAction($this, $a_list_cmd));
- }
- }
- $ilCtrl->setParameter($this, "bmn", $this->month);
- $ilCtrl->setParameterByClass("ilblogpostinggui", "bmn", "");
- return $wtpl->get();
- }
-
- /**
- * Build navigation by keywords block
- */
- protected function renderNavigationByKeywords(
- string $a_list_cmd = "render",
- bool $a_show_inactive = false,
- string $a_link_template = "",
- int $a_blpg = 0
- ): string {
- $ilCtrl = $this->ctrl;
-
- $blpg = ($a_blpg > 0)
- ? $a_blpg
- : $this->blpg;
-
- $keywords = $this->getKeywords($a_show_inactive, $blpg);
- if ($keywords) {
- $wtpl = new ilTemplate("tpl.blog_list_navigation_keywords.html", true, true, "components/ILIAS/Blog");
-
- $max = max($keywords);
-
- $wtpl->setCurrentBlock("keyword");
- foreach ($keywords as $keyword => $counter) {
- if (!$a_link_template) {
- $ilCtrl->setParameter($this, "kwd", urlencode((string) $keyword)); // #15885
- $url = $ilCtrl->getLinkTarget($this, $a_list_cmd);
- $ilCtrl->setParameter($this, "kwd", "");
- } else {
- $url = $this->buildExportLink($a_link_template, "keyword", (string) $keyword);
- }
-
- $wtpl->setVariable("TXT_KEYWORD", $keyword);
- $wtpl->setVariable("CLASS_KEYWORD", ilTagging::getRelevanceClass($counter, $max));
- $wtpl->setVariable("URL_KEYWORD", $url);
- $wtpl->parseCurrentBlock();
- }
-
- return $wtpl->get();
- }
- return "";
- }
-
- protected function renderNavigationByAuthors(
- array $a_items,
- string $a_list_cmd = "render",
- bool $a_show_inactive = false
- ): string {
- $ilCtrl = $this->ctrl;
-
- $authors = array();
- foreach ($a_items as $month => $items) {
- foreach ($items as $item) {
- /** @var \ILIAS\Blog\Posting\Posting $item */
- $item_id = $item->getId();
- if (($a_show_inactive || ilBlogPosting::_lookupActive($item_id, "blp"))) {
- $author_id = $item->getAuthor();
- if ($author_id) {
- $authors[] = $author_id;
- }
- foreach (\ilPageObject::getPageContributors("blp", $item_id) as $editor) {
- $editor_id = (int) $editor["user_id"];
- if ($editor_id !== $author_id) {
- $authors[] = $editor_id;
- }
- }
- }
- }
- }
-
- $authors = array_unique($authors);
-
- // filter out deleted users
- $authors = array_filter($authors, function ($id) {
- return ilObject::_lookupType($id) == "usr";
- });
-
- if (count($authors) > 1) {
- $list = array();
- foreach ($authors as $user_id) {
- if ($user_id) {
- $ilCtrl->setParameter($this, "ath", $user_id);
- $url = $ilCtrl->getLinkTarget($this, $a_list_cmd);
- $ilCtrl->setParameter($this, "ath", "");
-
- $base_name = ilUserUtil::getNamePresentation($user_id);
- if (str_starts_with($base_name, "[")) {
- $name = ilUserUtil::getNamePresentation($user_id, true);
- $sort = $name;
- } else {
- $name = ilUserUtil::getNamePresentation(
- $user_id,
- true,
- false,
- "",
- false,
- true,
- false
- );
- $name_arr = ilObjUser::_lookupName($user_id);
- $sort = $name_arr["lastname"] . " " . $name_arr["firstname"];
- }
-
- $idx = trim(strip_tags($sort)) . "///" . $user_id; // #10934
- $list[$idx] = array($name, $url);
- }
- }
- ksort($list);
-
- $wtpl = new ilTemplate("tpl.blog_list_navigation_authors.html", true, true, "components/ILIAS/Blog");
-
- $wtpl->setCurrentBlock("author");
- foreach ($list as $author) {
- $wtpl->setVariable("TXT_AUTHOR", $author[0]);
- $wtpl->setVariable("URL_AUTHOR", $author[1]);
- $wtpl->parseCurrentBlock();
- }
-
- return $wtpl->get();
- }
- return "";
- }
-
/**
* Toolbar navigation
*/
@@ -1765,7 +1427,14 @@ public function renderNavigation(
if (count($a_items)) {
$blocks[$order["navigation"] ?? 0] = array(
$this->lng->txt("blog_navigation"),
- $this->renderNavigationByDate($a_items, $a_list_cmd, $a_posting_cmd, $a_link_template, $a_show_inactive, $a_blpg)
+ $this->gui->navigation()->monthBlock()->render(
+ $a_items,
+ $a_list_cmd,
+ $a_posting_cmd,
+ $a_link_template,
+ $a_show_inactive,
+ $a_blpg
+ )
);
}
@@ -1776,7 +1445,13 @@ public function renderNavigation(
$a_list_cmd !== "preview" &&
$a_list_cmd !== "gethtml" &&
!$a_link_template);
- $keywords = $this->renderNavigationByKeywords($a_list_cmd, $a_show_inactive, (string) $a_link_template, $a_blpg);
+ $keywords = $this->gui->navigation()->keywordBlock()->render(
+ $a_items,
+ $a_list_cmd,
+ $a_show_inactive,
+ (string) $a_link_template,
+ $a_blpg
+ );
if ($keywords || $may_edit_keywords) {
if (!$keywords) {
$keywords = $this->lng->txt("blog_no_keywords");
@@ -1797,7 +1472,11 @@ public function renderNavigation(
// authors
if ($this->id_type === self::REPOSITORY_NODE_ID &&
$this->blog_settings->getAuthors()) {
- $authors = $this->renderNavigationByAuthors($a_items, $a_list_cmd, $a_show_inactive);
+ $authors = $this->gui->navigation()->authorBlock()->render(
+ $a_items,
+ $a_list_cmd,
+ $a_show_inactive
+ );
if ($authors) {
$blocks[$order["authors"] ?? 1] = array($this->lng->txt("blog_authors"), $authors);
}
From 9856b104c4254f624ee41c08182c2262cea7f50d Mon Sep 17 00:00:00 2001
From: Alexander Killing
Date: Sun, 28 Jun 2026 09:59:09 +0200
Subject: [PATCH 027/108] blog: moved side block rendering to navigation
subservice
---
.../ILIAS/Blog/Navigation/AuthorBlockGUI.php | 122 +++++++++
.../ILIAS/Blog/Navigation/KeywordBlockGUI.php | 138 ++++++++++
.../ILIAS/Blog/Navigation/MonthBlockGUI.php | 253 ++++++++++++++++++
3 files changed, 513 insertions(+)
create mode 100644 components/ILIAS/Blog/Navigation/AuthorBlockGUI.php
create mode 100644 components/ILIAS/Blog/Navigation/KeywordBlockGUI.php
create mode 100644 components/ILIAS/Blog/Navigation/MonthBlockGUI.php
diff --git a/components/ILIAS/Blog/Navigation/AuthorBlockGUI.php b/components/ILIAS/Blog/Navigation/AuthorBlockGUI.php
new file mode 100644
index 000000000000..6a88ce305357
--- /dev/null
+++ b/components/ILIAS/Blog/Navigation/AuthorBlockGUI.php
@@ -0,0 +1,122 @@
+domain = $domain;
+ $this->gui = $gui;
+ }
+
+ /**
+ * @param Posting[][] $items
+ */
+ public function render(
+ array $items,
+ string $list_cmd = "render",
+ bool $show_inactive = false
+ ): string {
+ $ctrl = $this->gui->ctrl();
+ $lng = $this->domain->lng();
+
+ $authors = array();
+ foreach ($items as $month => $month_items) {
+ foreach ($month_items as $item) {
+ $item_id = $item->getId();
+ if (($show_inactive || \ilBlogPosting::_lookupActive($item_id, "blp"))) {
+ $author_id = $item->getAuthor();
+ if ($author_id) {
+ $authors[] = $author_id;
+ }
+ foreach (\ilPageObject::getPageContributors("blp", $item_id) as $editor) {
+ $editor_id = (int) $editor["user_id"];
+ if ($editor_id !== $author_id) {
+ $authors[] = $editor_id;
+ }
+ }
+ }
+ }
+ }
+
+ $authors = array_unique($authors);
+
+ // filter out deleted users
+ $authors = array_filter($authors, function ($id) {
+ return \ilObject::_lookupType($id) == "usr";
+ });
+
+ if (count($authors) > 1) {
+ $list = array();
+ foreach ($authors as $user_id) {
+ if ($user_id) {
+ $ctrl->setParameterByClass(\ilObjBlogGUI::class, "ath", (string) $user_id);
+ $url = $ctrl->getLinkTargetByClass(\ilObjBlogGUI::class, $list_cmd);
+ $ctrl->setParameterByClass(\ilObjBlogGUI::class, "ath", "");
+
+ $base_name = \ilUserUtil::getNamePresentation($user_id);
+ if (str_starts_with($base_name, "[")) {
+ $name = \ilUserUtil::getNamePresentation($user_id, true);
+ $sort = $name;
+ } else {
+ $name = \ilUserUtil::getNamePresentation(
+ $user_id,
+ true,
+ false,
+ "",
+ false,
+ true,
+ false
+ );
+ $name_arr = \ilObjUser::_lookupName($user_id);
+ $sort = $name_arr["lastname"] . " " . $name_arr["firstname"];
+ }
+
+ $idx = trim(strip_tags((string) $sort)) . "///" . $user_id;
+ $list[$idx] = array($name, $url);
+ }
+ }
+ ksort($list);
+
+ $wtpl = new \ilTemplate("tpl.blog_list_navigation_authors.html", true, true, "components/ILIAS/Blog");
+
+ $wtpl->setCurrentBlock("author");
+ foreach ($list as $author) {
+ $wtpl->setVariable("TXT_AUTHOR", $author[0]);
+ $wtpl->setVariable("URL_AUTHOR", $author[1]);
+ $wtpl->parseCurrentBlock();
+ }
+
+ return $wtpl->get();
+ }
+ return "";
+ }
+}
diff --git a/components/ILIAS/Blog/Navigation/KeywordBlockGUI.php b/components/ILIAS/Blog/Navigation/KeywordBlockGUI.php
new file mode 100644
index 000000000000..7a177ae023da
--- /dev/null
+++ b/components/ILIAS/Blog/Navigation/KeywordBlockGUI.php
@@ -0,0 +1,138 @@
+domain = $domain;
+ $this->gui = $gui;
+ }
+
+ /**
+ * @param Posting[][] $items
+ */
+ public function render(
+ array $items,
+ string $list_cmd = "render",
+ bool $show_inactive = false,
+ string $link_template = "",
+ int $blpg = 0
+ ): string {
+ $ctrl = $this->gui->ctrl();
+ $lng = $this->domain->lng();
+
+ $keywords = $this->getKeywords($items, $show_inactive, $blpg);
+ if ($keywords) {
+ $wtpl = new \ilTemplate("tpl.blog_list_navigation_keywords.html", true, true, "components/ILIAS/Blog");
+
+ $max = max($keywords);
+
+ $wtpl->setCurrentBlock("keyword");
+ foreach ($keywords as $keyword => $counter) {
+ if (!$link_template) {
+ $ctrl->setParameterByClass(\ilObjBlogGUI::class, "kwd", urlencode((string) $keyword));
+ $url = $ctrl->getLinkTargetByClass(\ilObjBlogGUI::class, $list_cmd);
+ $ctrl->setParameterByClass(\ilObjBlogGUI::class, "kwd", "");
+ } else {
+ $url = $this->buildExportLink($link_template, "keyword", (string) $keyword);
+ }
+
+ $wtpl->setVariable("TXT_KEYWORD", (string) $keyword);
+ $wtpl->setVariable("CLASS_KEYWORD", \ilTagging::getRelevanceClass((int) $counter, (int) $max));
+ $wtpl->setVariable("URL_KEYWORD", $url);
+ $wtpl->parseCurrentBlock();
+ }
+
+ return $wtpl->get();
+ }
+ return "";
+ }
+
+ /**
+ * @param Posting[][] $items
+ */
+ protected function getKeywords(
+ array $items,
+ bool $show_inactive,
+ ?int $posting_id = null
+ ): array {
+ $keywords = array();
+ $posting_manager = $this->domain->posting();
+ $obj_id = \ilObject::_lookupObjId($this->gui->standardRequest()->getRefId());
+
+ if ($posting_id) {
+ foreach ($posting_manager->getKeywords($obj_id, $posting_id) as $keyword) {
+ if (isset($keywords[$keyword])) {
+ $keywords[$keyword]++;
+ } else {
+ $keywords[$keyword] = 1;
+ }
+ }
+ } else {
+ foreach ($items as $month => $month_items) {
+ foreach ($month_items as $item) {
+ $item_id = $item->getId();
+ if ($show_inactive || \ilBlogPosting::_lookupActive($item_id, "blp")) {
+ foreach ($posting_manager->getKeywords($obj_id, $item_id) as $keyword) {
+ if (isset($keywords[$keyword])) {
+ $keywords[$keyword]++;
+ } else {
+ $keywords[$keyword] = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ $tmp = array();
+ foreach ($keywords as $keyword => $counter) {
+ $tmp[] = array("keyword" => $keyword, "counter" => $counter);
+ }
+ $tmp = \ilArrayUtil::sortArray($tmp, "keyword", "ASC");
+
+ $keywords = array();
+ foreach ($tmp as $item) {
+ $keywords[(string) $item["keyword"]] = $item["counter"];
+ }
+ return $keywords;
+ }
+
+ protected function buildExportLink(
+ string $template,
+ string $type,
+ string $id
+ ): string {
+ $blog_export = new \ILIAS\Blog\Export\BlogHtmlExport($this->gui->standardRequest()->getRefId());
+ return $blog_export->buildExportLink($template, $type, $id, []);
+ }
+}
diff --git a/components/ILIAS/Blog/Navigation/MonthBlockGUI.php b/components/ILIAS/Blog/Navigation/MonthBlockGUI.php
new file mode 100644
index 000000000000..1c948d4031b7
--- /dev/null
+++ b/components/ILIAS/Blog/Navigation/MonthBlockGUI.php
@@ -0,0 +1,253 @@
+domain = $domain;
+ $this->gui = $gui;
+ }
+
+ /**
+ * @param Posting[][] $items
+ */
+ public function render(
+ array $items,
+ string $list_cmd = "render",
+ string $posting_cmd = "preview",
+ ?string $link_template = null,
+ bool $show_inactive = false,
+ int $blpg = 0
+ ): string {
+ $ctrl = $this->gui->ctrl();
+ $lng = $this->domain->lng();
+ $settings = $this->domain->blogSettings()->getByObjId(
+ \ilObject::_lookupObjId($this->gui->standardRequest()->getRefId())
+ );
+
+ // gather page active status
+ foreach ($items as $month => $postings) {
+ foreach (array_keys($postings) as $id) {
+ $active = \ilBlogPosting::_lookupActive($id, "blp");
+ if (!$show_inactive && !$active) {
+ unset($items[$month][$id]);
+ }
+ }
+ if (!count($items[$month])) {
+ unset($items[$month]);
+ }
+ }
+
+ // list month (incl. postings)
+ if ($settings->getNavMode() === \ilObjBlog::NAV_MODE_LIST || $link_template) {
+ $max_months = $settings->getNavModeListMonths();
+
+ $wtpl = new \ilTemplate("tpl.blog_list_navigation_by_date.html", true, true, "components/ILIAS/Blog");
+
+ $ctrl->setParameterByClass(\ilObjBlogGUI::class, "blpg", "");
+
+ $counter = $mon_counter = $last_year = 0;
+ foreach ($items as $month => $postings) {
+ if (!$link_template && $max_months && $mon_counter >= $max_months) {
+ break;
+ }
+
+ $add_year = false;
+ $year = substr((string) $month, 0, 4);
+ if (!$last_year || $year != $last_year) {
+ $add_year = true;
+ $last_year = $year;
+ }
+
+ $mon_counter++;
+
+ $month_name = \ilCalendarUtil::_numericMonthToString((int) substr((string) $month, 5));
+ if (!$link_template) {
+ $ctrl->setParameterByClass(\ilObjBlogGUI::class, "bmn", $month);
+ $month_url = $ctrl->getLinkTargetByClass(\ilObjBlogGUI::class, $list_cmd);
+ } else {
+ $month_url = $this->buildExportLink($link_template, "list", (string) $month);
+ }
+
+ if ($mon_counter <= $settings->getNavModeListMonthsWithPostings()) {
+ if ($add_year) {
+ $wtpl->setCurrentBlock("navigation_year_details");
+ $wtpl->setVariable("YEAR", $year);
+ $wtpl->parseCurrentBlock();
+ }
+
+ foreach ($postings as $id => $posting) {
+ $counter++;
+ $caption = $posting->getTitle();
+
+ if (!$link_template) {
+ $ctrl->setParameterByClass(\ilBlogPostingGUI::class, "bmn", $month);
+ $ctrl->setParameterByClass(\ilBlogPostingGUI::class, "blpg", (string) $id);
+ $url = $ctrl->getLinkTargetByClass(\ilBlogPostingGUI::class, $posting_cmd);
+ } else {
+ $url = $this->buildExportLink($link_template, "posting", (string) $id);
+ }
+
+ if (!$posting->isActive()) {
+ $wtpl->setVariable("NAV_ITEM_DRAFT", $lng->txt("blog_draft"));
+ } elseif ($settings->getApproval() && !$posting->isApproved()) {
+ $wtpl->setVariable("NAV_ITEM_APPROVAL", $lng->txt("blog_needs_approval"));
+ }
+
+ $wtpl->setCurrentBlock("navigation_item");
+ $wtpl->setVariable("NAV_ITEM_URL", $url);
+ $wtpl->setVariable("NAV_ITEM_CAPTION", $caption);
+ $wtpl->parseCurrentBlock();
+ }
+
+ $wtpl->setCurrentBlock("navigation_month_details");
+ $wtpl->setVariable("NAV_MONTH", $month_name);
+ $wtpl->setVariable("URL_MONTH", $month_url);
+ $wtpl->parseCurrentBlock();
+ }
+ // summarized month
+ else {
+ if ($add_year) {
+ $wtpl->setCurrentBlock("navigation_year");
+ $wtpl->setVariable("YEAR", $year);
+ $wtpl->parseCurrentBlock();
+ }
+
+ $wtpl->setCurrentBlock("navigation_month");
+ $wtpl->setVariable("MONTH_NAME", $month_name);
+ $wtpl->setVariable("URL_MONTH", $month_url);
+ $wtpl->setVariable("MONTH_COUNT", (string) count($postings));
+ $wtpl->parseCurrentBlock();
+ }
+ }
+ if (!$link_template) {
+ $ctrl->setParameterByClass(\ilObjBlogGUI::class, "bmn", null);
+ $url = $ctrl->getLinkTargetByClass(\ilObjBlogGUI::class, $list_cmd);
+ } else {
+ $url = "index.html";
+ }
+
+ $wtpl->setVariable(
+ "STARTING_PAGE",
+ $this->gui->ui()->renderer()->render(
+ $this->gui->ui()->factory()->link()->standard(
+ $lng->txt("blog_starting_page"),
+ $url
+ )
+ )
+ );
+ $ctrl->setParameterByClass(\ilObjBlogGUI::class, "bmn", $this->gui->standardRequest()->getMonth());
+ $ctrl->setParameterByClass(\ilBlogPostingGUI::class, "bmn", "");
+ return $wtpl->get();
+ }
+ // single month
+ else {
+ $wtpl = new \ilTemplate("tpl.blog_list_navigation_month.html", true, true, "components/ILIAS/Blog");
+
+ $ctrl->setParameterByClass(\ilObjBlogGUI::class, "blpg", "");
+
+ $month_options = array();
+ foreach ($items as $month => $postings) {
+ $month_name = $this->gui->presentation()->util()->getMonthPresentation((string) $month);
+
+ $month_options[(string) $month] = $month_name;
+
+ if ($month == $this->gui->standardRequest()->getMonth()) {
+ if (!$link_template) {
+ $ctrl->setParameterByClass(\ilObjBlogGUI::class, "bmn", (string) $month);
+ $month_url = $ctrl->getLinkTargetByClass(\ilObjBlogGUI::class, $list_cmd);
+ } else {
+ $month_url = $this->buildExportLink($link_template, "list", (string) $month);
+ }
+
+ foreach ($postings as $id => $posting) {
+ $caption = $posting->getTitle();
+
+ if (!$link_template) {
+ $ctrl->setParameterByClass(\ilBlogPostingGUI::class, "bmn", (string) $month);
+ $ctrl->setParameterByClass(\ilBlogPostingGUI::class, "blpg", (string) $id);
+ $url = $ctrl->getLinkTargetByClass(\ilBlogPostingGUI::class, $posting_cmd);
+ } else {
+ $url = $this->buildExportLink($link_template, "posting", (string) $id);
+ }
+
+ if (!$posting->isActive()) {
+ $wtpl->setVariable("NAV_ITEM_DRAFT", $lng->txt("blog_draft"));
+ } elseif ($settings->getApproval() && !$posting->isApproved()) {
+ $wtpl->setVariable("NAV_ITEM_APPROVAL", $lng->txt("blog_needs_approval"));
+ }
+
+ $wtpl->setCurrentBlock("navigation_item");
+ $wtpl->setVariable("NAV_ITEM_URL", $url);
+ $wtpl->setVariable("NAV_ITEM_CAPTION", $caption);
+ $wtpl->parseCurrentBlock();
+ }
+
+ $wtpl->setCurrentBlock("navigation_month_details");
+ if ($blpg > 0) {
+ $wtpl->setVariable("NAV_MONTH", $month_name);
+ $wtpl->setVariable("URL_MONTH", $month_url);
+ }
+ $wtpl->parseCurrentBlock();
+ }
+ }
+
+ if ($blpg === 0) {
+ $wtpl->setCurrentBlock("option_bl");
+ foreach ($month_options as $value => $caption) {
+ $wtpl->setVariable("OPTION_VALUE", $value);
+ $wtpl->setVariable("OPTION_CAPTION", $caption);
+ if ($value == $this->gui->standardRequest()->getMonth()) {
+ $wtpl->setVariable("OPTION_SEL", ' selected="selected"');
+ }
+ $wtpl->parseCurrentBlock();
+ }
+
+ $wtpl->setVariable("FORM_ACTION", $ctrl->getFormActionByClass(\ilObjBlogGUI::class, $list_cmd));
+ }
+ }
+ $ctrl->setParameterByClass(\ilObjBlogGUI::class, "bmn", $this->gui->standardRequest()->getMonth());
+ $ctrl->setParameterByClass(\ilBlogPostingGUI::class, "bmn", "");
+ return $wtpl->get();
+ }
+
+ protected function buildExportLink(
+ string $template,
+ string $type,
+ string $id
+ ): string {
+ $blog_export = new \ILIAS\Blog\Export\BlogHtmlExport($this->gui->standardRequest()->getRefId());
+ // Note: this might need adjustment since the original used $this->getKeywords(false)
+ // For now we assume keywords are not needed for these links or handled elsewhere
+ return $blog_export->buildExportLink($template, $type, $id, []);
+ }
+}
From bbb17a76f1657e1e5a02a8fe632c331b4f6b2df4 Mon Sep 17 00:00:00 2001
From: Ahmed Hamouda
Date: Fri, 26 Jun 2026 10:47:02 +0200
Subject: [PATCH 028/108] add Http StatusCode::HTTP_UNPROCESSABLE_ENTITY
---
components/ILIAS/HTTP/src/StatusCode.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/components/ILIAS/HTTP/src/StatusCode.php b/components/ILIAS/HTTP/src/StatusCode.php
index cdac27a2a57f..0d46f3a347a5 100755
--- a/components/ILIAS/HTTP/src/StatusCode.php
+++ b/components/ILIAS/HTTP/src/StatusCode.php
@@ -71,6 +71,7 @@ interface StatusCode
public const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
public const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
public const HTTP_EXPECTATION_FAILED = 417;
+ public const HTTP_UNPROCESSABLE_ENTITY = 422;
public const HTTP_TOO_MANY_REQUESTS = 429;
// [Server Error 5xx]
From 9721802d190100be95ed26e5dbd7caff3dce7499 Mon Sep 17 00:00:00 2001
From: Stephan Kergomard
Date: Thu, 4 Jun 2026 11:26:12 +0200
Subject: [PATCH 029/108] Questions: Build General Structure
---
.../classes/AdministrationMainBarProvider.php | 2 +-
.../COPage/classes/class.ilPageObject.php | 2 +-
components/ILIAS/COPage/xsl/page.xsl | 4 +
components/ILIAS/Export/xml/ilias_pg_12.dtd | 566 ++++++++++++++++++
.../Administration/class.ilObjQuestions.php | 28 +
.../class.ilObjQuestionsAccess.php | 27 +
.../class.ilObjQuestionsGUI.php | 138 +++++
.../ILIAS/Questions/Legacy/LocalDIC.php | 152 +++++
.../Legacy/PageEditor/QstsQuestionPage.php | 27 +
.../PageEditor/QstsQuestionPageConfig.php | 30 +
.../PageEditor/class.QstsQuestionPageGUI.php | 42 ++
.../PageEditor/class.ilPCAnswerForm.php | 460 ++++++++++++++
.../PageEditor/class.ilPCAnswerFormGUI.php | 96 +++
components/ILIAS/Questions/Questions.php | 46 ++
components/ILIAS/Questions/README.md | 1 +
components/ILIAS/Questions/maintenance.json | 14 +
components/ILIAS/Questions/service.xml | 20 +
.../AnswerForm/Capabilities/Capability.php | 26 +
.../src/AnswerForm/Capabilities/Feedback.php | 29 +
.../src/AnswerForm/Capabilities/Marking.php | 29 +
.../src/AnswerForm/Capabilities/Skills.php | 28 +
.../Questions/src/AnswerForm/Definition.php | 40 ++
.../Questions/src/AnswerForm/Factory.php | 86 +++
.../Questions/src/AnswerForm/Persistence.php | 36 ++
.../Questions/src/AnswerForm/Properties.php | 26 +
.../src/AnswerForm/TypeGenericProperties.php | 72 +++
.../Questions/src/AnswerForm/Views/Edit.php | 46 ++
.../src/AnswerForm/Views/Participant.php | 31 +
.../Cloze/Capabilities/Feedback.php | 42 ++
.../Cloze/Capabilities/Marking.php | 43 ++
.../Cloze/Capabilities/Skills.php | 37 ++
.../src/AnswerFormTypes/Cloze/Definition.php | 87 +++
.../src/AnswerFormTypes/Cloze/Persistence.php | 141 +++++
.../Cloze/Properties/AnswerForm/Factory.php | 76 +++
.../Properties/AnswerForm/Properties.php | 224 +++++++
.../Cloze/Properties/ClozeText/Factory.php | 57 ++
.../Cloze/Properties/ClozeText/Text.php | 157 +++++
.../Definitions/ScoringIdentical.php | 61 ++
.../Cloze/Properties/Gaps/Factory.php | 90 +++
.../Cloze/Properties/Gaps/Gap.php | 196 ++++++
.../Cloze/Properties/Gaps/Gaps.php | 238 ++++++++
.../Cloze/Properties/Gaps/LongMenu.php | 158 +++++
.../Cloze/Properties/Gaps/Numeric.php | 129 ++++
.../Gaps/Properties/AnswerOption.php | 137 +++++
.../Gaps/Properties/AnswerOptions.php | 223 +++++++
.../Properties/Gaps/Properties/Factory.php | 86 +++
.../Properties/Gaps/Properties/Properties.php | 267 +++++++++
.../Cloze/Properties/Gaps/Select.php | 108 ++++
.../Cloze/Properties/Gaps/Text.php | 122 ++++
.../Cloze/Properties/Gaps/Type.php | 56 ++
.../Gaps/class.UploadAnswerOptionsGUI.php | 97 +++
.../src/AnswerFormTypes/Cloze/Views/Edit.php | 280 +++++++++
.../Cloze/Views/Participant.php | 39 ++
components/ILIAS/Questions/src/Collector.php | 57 ++
.../Presentation/Definitions/CarryWrapper.php | 65 ++
.../src/Presentation/Definitions/EditForm.php | 555 +++++++++++++++++
.../Definitions/EditFormFactory.php | 555 +++++++++++++++++
.../Presentation/Definitions/EditOverview.php | 555 +++++++++++++++++
.../Presentation/Definitions/Editability.php | 28 +
.../src/Presentation/Definitions/Leaf.php | 65 ++
.../Definitions/QuestionsTable.php | 123 ++++
.../Presentation/Layout/LayoutProvider.php | 154 +++++
.../Questions/src/Presentation/Views/Edit.php | 555 +++++++++++++++++
.../ILIAS/Questions/src/PublicInterface.php | 43 ++
.../src/Question/Definitions/Lifecycle.php | 31 +
.../Definitions/TextMatchingOptions.php | 54 ++
.../src/Question/Persistence/Column.php | 40 ++
.../src/Question/Persistence/Join.php | 51 ++
.../src/Question/Persistence/JoinType.php | 27 +
.../src/Question/Persistence/Junctor.php | 27 +
.../Question/Persistence/ManipulateQuery.php | 66 ++
.../src/Question/Persistence/Operator.php | 50 ++
.../src/Question/Persistence/Order.php | 35 ++
.../Question/Persistence/OrderDirection.php | 27 +
.../src/Question/Persistence/Repository.php | 219 +++++++
.../src/Question/Persistence/Select.php | 38 ++
.../src/Question/Persistence/SelectQuery.php | 165 +++++
.../Question/Persistence/TableNameBuilder.php | 57 ++
.../Question/Persistence/TableNameSpace.php | 44 ++
.../Persistence/TableNameSpaceCore.php | 34 ++
.../src/Question/Persistence/Value.php | 49 ++
.../src/Question/Persistence/Where.php | 52 ++
.../ILIAS/Questions/src/Question/Question.php | 26 +
.../src/Question/QuestionImplementation.php | 255 ++++++++
.../ILIAS/Questions/src/Question/Response.php | 25 +
.../Questions/src/Question/Views/Edit.php | 180 ++++++
.../src/Question/Views/Participant.php | 81 +++
.../Questions/src/Response/Repository.php | 28 +
.../ILIAS/Questions/src/Response/Response.php | 30 +
.../ILIAS/Questions/src/Setup/Agent.php | 74 +++
.../src/Setup/ClozeQuestionTables.php | 249 ++++++++
.../src/Setup/OverarchingQuestionTables.php | 206 +++++++
lang/ilias_de.lang | 27 +-
lang/ilias_en.lang | 27 +-
94 files changed, 10266 insertions(+), 18 deletions(-)
create mode 100755 components/ILIAS/Export/xml/ilias_pg_12.dtd
create mode 100755 components/ILIAS/Questions/Legacy/Administration/class.ilObjQuestions.php
create mode 100755 components/ILIAS/Questions/Legacy/Administration/class.ilObjQuestionsAccess.php
create mode 100755 components/ILIAS/Questions/Legacy/Administration/class.ilObjQuestionsGUI.php
create mode 100755 components/ILIAS/Questions/Legacy/LocalDIC.php
create mode 100644 components/ILIAS/Questions/Legacy/PageEditor/QstsQuestionPage.php
create mode 100644 components/ILIAS/Questions/Legacy/PageEditor/QstsQuestionPageConfig.php
create mode 100644 components/ILIAS/Questions/Legacy/PageEditor/class.QstsQuestionPageGUI.php
create mode 100644 components/ILIAS/Questions/Legacy/PageEditor/class.ilPCAnswerForm.php
create mode 100644 components/ILIAS/Questions/Legacy/PageEditor/class.ilPCAnswerFormGUI.php
create mode 100644 components/ILIAS/Questions/Questions.php
create mode 100644 components/ILIAS/Questions/README.md
create mode 100644 components/ILIAS/Questions/maintenance.json
create mode 100644 components/ILIAS/Questions/service.xml
create mode 100644 components/ILIAS/Questions/src/AnswerForm/Capabilities/Capability.php
create mode 100644 components/ILIAS/Questions/src/AnswerForm/Capabilities/Feedback.php
create mode 100644 components/ILIAS/Questions/src/AnswerForm/Capabilities/Marking.php
create mode 100644 components/ILIAS/Questions/src/AnswerForm/Capabilities/Skills.php
create mode 100644 components/ILIAS/Questions/src/AnswerForm/Definition.php
create mode 100644 components/ILIAS/Questions/src/AnswerForm/Factory.php
create mode 100644 components/ILIAS/Questions/src/AnswerForm/Persistence.php
create mode 100644 components/ILIAS/Questions/src/AnswerForm/Properties.php
create mode 100644 components/ILIAS/Questions/src/AnswerForm/TypeGenericProperties.php
create mode 100644 components/ILIAS/Questions/src/AnswerForm/Views/Edit.php
create mode 100644 components/ILIAS/Questions/src/AnswerForm/Views/Participant.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Capabilities/Feedback.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Capabilities/Marking.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Capabilities/Skills.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Definition.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Persistence.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/AnswerForm/Factory.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/AnswerForm/Properties.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/ClozeText/Factory.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/ClozeText/Text.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Definitions/ScoringIdentical.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/Factory.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/Gap.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/Gaps.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/LongMenu.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/Numeric.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/Properties/AnswerOption.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/Properties/AnswerOptions.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/Properties/Factory.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/Properties/Properties.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/Select.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/Text.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/Type.php
create mode 100755 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Properties/Gaps/class.UploadAnswerOptionsGUI.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Views/Edit.php
create mode 100644 components/ILIAS/Questions/src/AnswerFormTypes/Cloze/Views/Participant.php
create mode 100644 components/ILIAS/Questions/src/Collector.php
create mode 100755 components/ILIAS/Questions/src/Presentation/Definitions/CarryWrapper.php
create mode 100644 components/ILIAS/Questions/src/Presentation/Definitions/EditForm.php
create mode 100644 components/ILIAS/Questions/src/Presentation/Definitions/EditFormFactory.php
create mode 100644 components/ILIAS/Questions/src/Presentation/Definitions/EditOverview.php
create mode 100644 components/ILIAS/Questions/src/Presentation/Definitions/Editability.php
create mode 100755 components/ILIAS/Questions/src/Presentation/Definitions/Leaf.php
create mode 100644 components/ILIAS/Questions/src/Presentation/Definitions/QuestionsTable.php
create mode 100755 components/ILIAS/Questions/src/Presentation/Layout/LayoutProvider.php
create mode 100644 components/ILIAS/Questions/src/Presentation/Views/Edit.php
create mode 100644 components/ILIAS/Questions/src/PublicInterface.php
create mode 100644 components/ILIAS/Questions/src/Question/Definitions/Lifecycle.php
create mode 100644 components/ILIAS/Questions/src/Question/Definitions/TextMatchingOptions.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/Column.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/Join.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/JoinType.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/Junctor.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/ManipulateQuery.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/Operator.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/Order.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/OrderDirection.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/Repository.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/Select.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/SelectQuery.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/TableNameBuilder.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/TableNameSpace.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/TableNameSpaceCore.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/Value.php
create mode 100644 components/ILIAS/Questions/src/Question/Persistence/Where.php
create mode 100644 components/ILIAS/Questions/src/Question/Question.php
create mode 100644 components/ILIAS/Questions/src/Question/QuestionImplementation.php
create mode 100644 components/ILIAS/Questions/src/Question/Response.php
create mode 100644 components/ILIAS/Questions/src/Question/Views/Edit.php
create mode 100644 components/ILIAS/Questions/src/Question/Views/Participant.php
create mode 100644 components/ILIAS/Questions/src/Response/Repository.php
create mode 100644 components/ILIAS/Questions/src/Response/Response.php
create mode 100644 components/ILIAS/Questions/src/Setup/Agent.php
create mode 100644 components/ILIAS/Questions/src/Setup/ClozeQuestionTables.php
create mode 100644 components/ILIAS/Questions/src/Setup/OverarchingQuestionTables.php
diff --git a/components/ILIAS/Administration/GlobalScreen/classes/AdministrationMainBarProvider.php b/components/ILIAS/Administration/GlobalScreen/classes/AdministrationMainBarProvider.php
index 3f9baaa54ae2..660af1b3f27f 100755
--- a/components/ILIAS/Administration/GlobalScreen/classes/AdministrationMainBarProvider.php
+++ b/components/ILIAS/Administration/GlobalScreen/classes/AdministrationMainBarProvider.php
@@ -225,7 +225,7 @@ private function getGroups(): array
// admin menu layout
$layout = array(
"maintenance" =>
- array("adma", "serv", "cron", "bnmk", "lngf", "hlps", "wfe", 'fils', 'logs', 'sysc', "recf", "root"),
+ array("adma", "serv", "cron", "bnmk", "lngf", "hlps", "wfe", 'fils', 'qsts', 'logs', 'sysc', "recf", "root"),
"layout_and_navigation" =>
array("mme", "gsfo", "dshs", "stys", "adve", "stus"),
"repository_and_objects" =>
diff --git a/components/ILIAS/COPage/classes/class.ilPageObject.php b/components/ILIAS/COPage/classes/class.ilPageObject.php
index 9bdd0fb89a41..92a0d77988ce 100755
--- a/components/ILIAS/COPage/classes/class.ilPageObject.php
+++ b/components/ILIAS/COPage/classes/class.ilPageObject.php
@@ -75,7 +75,7 @@ abstract class ilPageObject
public string $xml = "";
public string $encoding = "";
public DomNode $node;
- public string $cur_dtd = "ilias_pg_9.dtd";
+ public string $cur_dtd = "ilias_pg_12.dtd";
public bool $contains_int_link = false;
public bool $needs_parsing = false;
public string $parent_type = "";
diff --git a/components/ILIAS/COPage/xsl/page.xsl b/components/ILIAS/COPage/xsl/page.xsl
index 5d368b5851b4..bcdd7a8af4a1 100755
--- a/components/ILIAS/COPage/xsl/page.xsl
+++ b/components/ILIAS/COPage/xsl/page.xsl
@@ -3721,6 +3721,10 @@