Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
6a4673b
Test: Show Deleted Users as Deleted
kergomard Jun 24, 2026
81ee5a8
Test: Retrieve Importname in Participant Repo
kergomard Jun 24, 2026
0923cd5
Test: Retrieve Importname in Participant Repo
kergomard Jun 24, 2026
f62fa2c
Test: Set Original Id on Test Copy
kergomard Jun 25, 2026
4ca7cef
BookingPool: Remove reservations on pool deletion
matheuszych Jan 20, 2026
3e76fa3
T&A Streamline usage of getAdditionalTableName to never expect a arra…
thojou Dec 3, 2025
097b2a3
BookingPool: Render Pool Without Booking Info
matheuszych Jan 20, 2026
829fe9c
BookingPool: Allow Pool Filter in Course Resources
matheuszych Jan 16, 2026
b49dc72
BookingPool: Disambiguate Info Stakeholders
matheuszych Apr 17, 2026
a290618
fix: missing logger dependency
lukas-heinrich Jan 27, 2026
6bddf94
News: Fix duplicated property declaration in ContextBlockGUI
thojou Jun 26, 2026
9bec14a
BackgroundTasks: Add grp to folder-type whitelist
matheuszych Feb 20, 2026
241d08f
ItemGroup: Add migration for display fields
matheuszych Jun 24, 2026
1f31266
Test: Full Width for Cloze Inputs in Scoring
matheuszych Mar 12, 2026
a981ee4
Test: Resize Mark Icon and Unify Summary Icons
matheuszych Mar 16, 2026
f127cd0
[Fix] glossary: make copying glossary against broken terms
alex40724 Jun 26, 2026
3c55bf1
copage: drag/drop array fix
alex40724 Jun 26, 2026
1fd9907
blog: removed static calls
alex40724 Jun 27, 2026
a1ee21d
blog: removed static calls
alex40724 Jun 27, 2026
c6c4f54
blog: removed static calls
alex40724 Jun 27, 2026
d5815fc
blog: improve DIC handling
alex40724 Jun 27, 2026
4c20b8d
blog: improve DIC handling
alex40724 Jun 27, 2026
391b068
blog: improve DIC handling
alex40724 Jun 27, 2026
42f193e
fixed copyright
alex40724 Jun 27, 2026
05623dd
blog: moved contributor code to subservice
alex40724 Jun 27, 2026
dd7e52f
blog: moved side block rendering to navigation subservice
alex40724 Jun 28, 2026
9856b10
blog: moved side block rendering to navigation subservice
alex40724 Jun 28, 2026
bbb17a7
add Http StatusCode::HTTP_UNPROCESSABLE_ENTITY
GitHamo Jun 26, 2026
9721802
Questions: Build General Structure
kergomard Jun 4, 2026
0ca7f96
Questions: Start Implementing Cloze Question
kergomard Dec 15, 2025
7f33ed4
Questions: Implementing Persistence
kergomard Dec 23, 2025
238d91b
Questions: Implement Answer Form Editing
kergomard Jan 8, 2026
abacb62
Questions: Implement Basic Migration
kergomard Jan 20, 2026
14eddda
Questions: Implement Combinations
kergomard Jan 28, 2026
323016d
Questions: Add LangVar For AnswerForm
kergomard Jan 28, 2026
b2aa506
Questions: Implement Migration For TextSubset
kergomard Jan 28, 2026
b43d6c5
Questions: Speedup Loading Lists
kergomard Jan 28, 2026
0e48eea
Questions: Improvements in Migration and Display
kergomard Jan 29, 2026
bd34ec5
Questions: Small Improvements
kergomard Jan 30, 2026
9804a4b
Questions: TextLegacy Cannot Be Null
kergomard Jan 30, 2026
a2d9128
Questions: Fix Deleting Questions
kergomard Jan 30, 2026
e7c92c3
Questions: No Duplicating Questions on Page Update
kergomard Jan 30, 2026
e1efa8f
Questions: Fix Cloze Migrations
kergomard Feb 2, 2026
ec6d065
Questions: Add Page Component for Legacy Text
kergomard Feb 2, 2026
462cacb
COPage/Export: Add LegacyTextElement
kergomard Feb 2, 2026
76c8efd
Questions: Little Improvement in SubText Migration
kergomard Feb 2, 2026
8cd32b0
Questions: Rename Function for More Clarity
kergomard Feb 2, 2026
bccac81
UI: Add Icon For Questions
kergomard Feb 3, 2026
c68562e
UI: Add Icon For Questions
kergomard Feb 3, 2026
e42f7a4
Questions: Add Simple Create Mode
kergomard Feb 5, 2026
c84c735
Questions: Add Add Legacy Button
kergomard Feb 5, 2026
dbfb718
Questions: Proberly Escape Legacy Texts
kergomard Feb 5, 2026
358ec70
Questions: Add forgotten Parameter
kergomard Feb 6, 2026
5ad9964
Questions: Fix Migration of LongMenu-Forms
kergomard Feb 6, 2026
9f22d3e
Questions: Show Legacy Text in Panel
kergomard Feb 6, 2026
c603201
Questions: Move Adding Text to Page
kergomard Feb 6, 2026
fdab342
Questions: Function Needs to be Public
kergomard Feb 6, 2026
6199b1f
Questions: Update Method Call
kergomard Feb 6, 2026
469ce1a
Questions: Introduce Persistence Factory
kergomard Feb 6, 2026
a7a6260
Questions: Move to New Mechanism For Carry
kergomard Feb 10, 2026
3d56190
Questions: Fix Typo
kergomard Feb 11, 2026
152770c
Questions: Implement New Carry Mechanism
kergomard Feb 11, 2026
e2588a9
Questions: Fix Input on LegacyClozeText
kergomard Feb 11, 2026
0d1f58a
Questions: Fixes in Combinations
kergomard Feb 11, 2026
7e58d28
Questions: Fix Typo in Variable Name
kergomard Feb 12, 2026
84daed4
Questions: Move To InputsBuilderSession
kergomard Feb 18, 2026
202f143
Questions: Make Create Button Primary
kergomard Feb 18, 2026
cbc0de9
Questions: Change LangVar for Gap-Placeholder
kergomard Feb 18, 2026
4196135
Questions: Fix Requirement of ClozeText
kergomard Feb 18, 2026
c1043a7
Questions: Change Title LangVars
kergomard Feb 18, 2026
116d93e
Questions: Remove Tabs from Question Editing
kergomard Feb 18, 2026
b362587
Questions: Add Create and New and Fix Redirects
kergomard Feb 19, 2026
e2ccb55
Questions: Fix Crash on Missing Question Title
kergomard Feb 19, 2026
6f0534d
Questions: Add Central Facilities to Environment
kergomard Feb 19, 2026
78cde27
Questions: Rename type to type_definition
kergomard Feb 19, 2026
51f01f5
Questions: Start Implementing Feedback
kergomard Feb 25, 2026
6e65e99
Questions: Move to Generic Persistence
kergomard Feb 25, 2026
94e594f
Questions: Implement Feedback
kergomard Mar 10, 2026
49d738e
Questions: Remove Unneeded Parameter
kergomard Mar 13, 2026
4985da9
Questions: Always use FormActions for CSRF-Checks
kergomard Mar 13, 2026
bdddd07
Questions: Remove Unneeded Include
kergomard Mar 13, 2026
efdade6
Questions: Implement Suggested Learning Content
kergomard Mar 31, 2026
d7de02a
Questions: Remove PersistenceFactory in Migration
kergomard Apr 3, 2026
e7b5a43
Questions: Rename EnvironmentImplementation
kergomard Apr 3, 2026
c3662c8
Questions: Rename QuestionClass and Interface
kergomard Apr 3, 2026
c9d53a8
Questions: Rename Step to SubAction
kergomard Apr 3, 2026
6f1e90c
Questions: Move AnswerOptionsUpload to Actor
kergomard Apr 4, 2026
c73cd15
Questions: Move ilDBConstants to FieldDefinition
kergomard Apr 4, 2026
ea9f3c6
Questions: Move Marking to Capability
kergomard Apr 3, 2026
2cd46a2
Questions: Add Missing Parameters to Function Call
kergomard Apr 8, 2026
38b5c9e
Questions: Fix Tabs Handling
kergomard Apr 8, 2026
e33c3b9
Questions: Add Filter, Range, and Order to Table
kergomard May 6, 2026
8cbab06
Questions: Move From Renderable to Viewable
kergomard May 8, 2026
45d932e
Questions: Clarify TabeDefinitions
kergomard May 8, 2026
8f4fae3
Questions: Introduce ForImmediateStorage
kergomard May 8, 2026
9f1bd75
Question: Implementing Attempt
kergomard Apr 27, 2026
32eace1
Questions: Clarify Parameters in Join
kergomard May 14, 2026
5c193f3
Question: Extract Database-Functions From Question
kergomard May 14, 2026
172a686
Questions: Implement Response
kergomard May 18, 2026
8dcaa80
Questions: Add Language Variables
kergomard Jun 4, 2026
bd3ea12
Questions: Fix Testing Issues in Combinations
kergomard Jun 5, 2026
8988aeb
Questions: Fix Migrations
kergomard Jun 8, 2026
9ae70e3
Questions: Change Name of Getter in Query
kergomard Jun 12, 2026
a06b4d8
Questions: Allow More Flexibility in EditOverview
kergomard Jun 22, 2026
89e6d26
Questions: Add Deletion to Capabilities
kergomard Jun 22, 2026
3e6d612
Questions: Implement Async View
kergomard Jun 23, 2026
13659d9
Questions: Implement Copying
kergomard Jun 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -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" =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,37 @@ public function run(array $input, Observer $observer): Value

foreach ($object_ref_ids as $object_ref_id) {
$object = ilObjectFactory::getInstanceByRefId($object_ref_id);
if (!$object instanceof ilObject) {
continue;
}

$object_type = $object->getType();
$object_name = $object->getTitle();
$object_temp_dir = ""; // empty as content will be added in recurseFolder and getFileDirs
$object_temp_dir = ''; // empty as content will be added in recurseFolder and getFileDirs

if ($object_type === "fold" || $object_type === "crs") {
if (in_array($object_type, ['fold', 'crs', 'grp'], true)) {
$num_recursions = 0;
$files_from_folder = $this->recurseFolder($object_ref_id, $object_name, $object_temp_dir, $num_recursions, $initiated_by_folder_action);
$files_from_folder = $this->recurseFolder(
$object_ref_id,
$object_name,
$object_temp_dir,
$num_recursions,
$initiated_by_folder_action
);
$files = array_merge($files, $files_from_folder);
} elseif (($object_type === "file") && (($file_dirs = $this->getFileDirs(
$object_ref_id,
$object_name,
$object_temp_dir
)) !== false)) {
$files[] = $file_dirs;
continue;
}

if ($object_type !== 'file') {
continue;
}

$file_dirs = $this->getFileDirs($object_ref_id, $object_name, $object_temp_dir);
if (!is_array($file_dirs)) {
continue;
}

$files[] = $file_dirs;
}
$this->logger->debug('Collected files:');
$this->logger->dump($files);
Expand Down
262 changes: 262 additions & 0 deletions components/ILIAS/Blog/Contributor/ContributorGUI.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
<?php

/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/

declare(strict_types=1);

namespace ILIAS\Blog\Contributor;

use ILIAS\Blog\InternalDataService;
use ILIAS\Blog\InternalDomainService;
use ILIAS\Blog\InternalGUIService;
use ilRepositorySearchGUI;
use ilObjUser;
use ilConfirmationGUI;

/**
* @ilCtrl_Calls ILIAS\Blog\Contributor\ContributorGUI: ilRepositorySearchGUI
*/
class ContributorGUI
{
public function __construct(
protected InternalDataService $data,
protected InternalDomainService $domain,
protected InternalGUIService $gui,
protected int $node_id,
protected \ilObjBlog $blog
) {
}

public function executeCommand(): void
{
$ctrl = $this->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");
}
}
11 changes: 11 additions & 0 deletions components/ILIAS/Blog/Contributor/Service/class.GUIService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
}
}
17 changes: 10 additions & 7 deletions components/ILIAS/Blog/Export/BlogHtmlExport.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
{
Expand Down Expand Up @@ -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();
Expand All @@ -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);

Expand Down
Loading
Loading