Skip to content

Commit ede66dc

Browse files
Badge: Fix handling of deleted objects
See: https://mantis.ilias.de/view.php?id=43259 (cherry picked from commit a2e5c16)
1 parent 2e7b90f commit ede66dc

File tree

4 files changed

+138
-106
lines changed

4 files changed

+138
-106
lines changed

components/ILIAS/Badge/classes/class.ilBadge.php

+39-28
Original file line numberDiff line numberDiff line change
@@ -170,57 +170,68 @@ public function copy(
170170
}
171171

172172
/**
173-
* @param array<string, mixed>|null $a_filter
174-
* @return array[]
173+
* @param array{type: string, title: string, object: string}|null $filter
174+
* @return list<array{
175+
* id: int,
176+
* parent_id: int,
177+
* type_id: string,
178+
* active: int,
179+
* title: ?string,
180+
* descr: ?string,
181+
* conf: ?string,
182+
* image: ?string,
183+
* valid: ?string,
184+
* crit: ?string,
185+
* image_rid: ?string,
186+
* parent_title: ?string,
187+
* parent_type: ?string,
188+
* deleted: bool
189+
* }>
175190
*/
176191
public static function getObjectInstances(
177-
array $a_filter = null
192+
?array $filter = null
178193
): array {
179194
global $DIC;
180195

181196
$ilDB = $DIC->database();
182197

183-
$res = $raw = [];
198+
$rows = [];
184199

185-
$where = "";
200+
$where = '';
186201

187-
if ($a_filter["type"]) {
188-
$where .= " AND bb.type_id = " . $ilDB->quote($a_filter["type"], "text");
202+
if ($filter['type']) {
203+
$where .= ' AND bb.type_id = ' . $ilDB->quote($filter['type'], ilDBConstants::T_TEXT);
189204
}
190-
if ($a_filter["title"]) {
191-
$where .= " AND " . $ilDB->like("bb.title", "text", "%" . $a_filter["title"] . "%");
205+
if ($filter['title']) {
206+
$where .= ' AND ' . $ilDB->like('bb.title', ilDBConstants::T_TEXT, '%' . $filter['title'] . '%');
192207
}
193-
if ($a_filter["object"]) {
194-
$where .= " AND " . $ilDB->like("od.title", "text", "%" . $a_filter["object"] . "%");
208+
if ($filter['object']) {
209+
$where .= ' AND ' . $ilDB->like('od.title', ilDBConstants::T_TEXT, '%' . $filter['object'] . '%');
195210
}
196211

197-
$set = $ilDB->query("SELECT bb.*, od.title parent_title, od.type parent_type" .
198-
" FROM badge_badge bb" .
199-
" JOIN object_data od ON (bb.parent_id = od.obj_id)" .
200-
" WHERE od.type <> " . $ilDB->quote("bdga", "text") .
212+
$set = $ilDB->query('SELECT bb.*, od.title parent_title, od.type parent_type' .
213+
' FROM badge_badge bb' .
214+
' INNER JOIN object_data od ON bb.parent_id = od.obj_id' .
215+
' WHERE od.type != ' . $ilDB->quote('bdga', ilDBConstants::T_TEXT) .
201216
$where);
202217
while ($row = $ilDB->fetchAssoc($set)) {
203-
$raw[] = $row;
218+
$row['deleted'] = false;
219+
$rows[] = $row;
204220
}
205221

206-
$set = $ilDB->query("SELECT bb.*, od.title parent_title, od.type parent_type" .
207-
" FROM badge_badge bb" .
208-
" JOIN object_data_del od ON (bb.parent_id = od.obj_id)" .
209-
" WHERE od.type <> " . $ilDB->quote("bdga", "text") .
222+
$set = $ilDB->query('SELECT bb.*, od.title parent_title, od.type parent_type' .
223+
' FROM badge_badge bb' .
224+
' INNER JOIN object_data_del od ON bb.parent_id = od.obj_id' .
225+
' WHERE od.type != ' . $ilDB->quote('bdga', ilDBConstants::T_TEXT) .
210226
$where);
211227
while ($row = $ilDB->fetchAssoc($set)) {
212-
$row["deleted"] = true;
213-
$raw[] = $row;
214-
}
215-
216-
foreach ($raw as $row) {
217-
$res[] = $row;
228+
$row['deleted'] = true;
229+
$rows[] = $row;
218230
}
219231

220-
return $res;
232+
return $rows;
221233
}
222234

223-
224235
//
225236
// setter/getter
226237
//

components/ILIAS/Badge/classes/class.ilBadgeImage.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ public function getImageFromResourceId(
6868
if ($identification !== null) {
6969
$flavour = $this->resource_storage->flavours()->get($identification, new \ilBadgePictureDefinition());
7070
$urls = $this->resource_storage->consume()->flavourUrls($flavour)->getURLsAsArray(false);
71-
if (count($urls) === self::IMAGE_URL_COUNT && isset($urls[$size])) {
71+
if (\count($urls) === self::IMAGE_URL_COUNT && isset($urls[$size])) {
7272
$image_src = $urls[$size];
7373
}
7474
}
75-
} elseif (is_array($badge) && isset($badge['image'])) {
75+
} elseif (\is_array($badge) && isset($badge['image'])) {
7676
$image_src = $badge['image'];
7777
} elseif ($badge instanceof ilBadge) {
7878
$image_src = $badge->getImage();

components/ILIAS/Badge/classes/class.ilObjBadgeAdministrationGUI.php

+1-3
Original file line numberDiff line numberDiff line change
@@ -710,9 +710,7 @@ protected function toggleObjectBadges(bool $a_status): void
710710
$filter = ['type' => '' , 'title' => '', 'object' => ''];
711711
$badge_ids = [];
712712
foreach (ilBadge::getObjectInstances($filter) as $badge_item) {
713-
if (isset($badge_item['id'])) {
714-
$badge_ids[] = $badge_item['id'];
715-
}
713+
$badge_ids[] = $badge_item['id'];
716714
}
717715
foreach ($badge_ids as $badge_id) {
718716
$badge = new ilBadge($badge_id);

components/ILIAS/Badge/classes/class.ilObjectBadgeTableGUI.php

+96-73
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ class ilObjectBadgeTableGUI
5555
private readonly ilLanguage $lng;
5656
private readonly ilGlobalTemplateInterface $tpl;
5757
private ilObjBadgeAdministrationGUI $parent_obj;
58-
private ?bool $user_has_write_permission = null;
5958
private ilAccess $access;
6059

6160
public function __construct(ilObjBadgeAdministrationGUI $parentObj)
@@ -74,20 +73,6 @@ public function __construct(ilObjBadgeAdministrationGUI $parentObj)
7473

7574
}
7675

77-
private function userHasWritePermission(int $parent_id): bool
78-
{
79-
if ($this->user_has_write_permission === null) {
80-
$parent_ref_id = ilObject::_getAllReferences($parent_id);
81-
if (\count($parent_ref_id) > 0) {
82-
$parent_ref_id = array_pop($parent_ref_id);
83-
}
84-
$this->user_has_write_permission = $this->access->checkAccess('write', '', $parent_ref_id);
85-
}
86-
87-
return $this->user_has_write_permission;
88-
}
89-
90-
9176
private function buildDataRetrievalObject(
9277
Factory $f,
9378
Renderer $r,
@@ -100,7 +85,6 @@ private function buildDataRetrievalObject(
10085
private \ilCtrlInterface $ctrl;
10186
private ilLanguage $lng;
10287
private \ilAccessHandler $access;
103-
private ?bool $user_has_write_permission = null;
10488

10589
public function __construct(
10690
private Factory $ui_factory,
@@ -148,93 +132,119 @@ public function getTotalRowCount(
148132
* id: int,
149133
* active: bool,
150134
* type: string,
151-
* image_rid: string,
135+
* image: string,
136+
* image_sortable: string,
152137
* title: string,
138+
* title_sortable: string,
153139
* container: string,
154-
* container_icon: string,
155-
* container_url: string,
156-
* container_deleted: bool,
157-
* container_id: int,
158-
* container_type: string}>
140+
* container_sortable: string
141+
* }>
159142
*/
160143
private function getRecords(Range $range = null, Order $order = null): array
161144
{
162-
$data = [];
163-
$image_html = '';
164-
$badge_img_large = '';
165-
$container_icon = '';
145+
$container_deleted_title_part = '<span class="il_ItemAlertProperty">' . $this->lng->txt('deleted') . '</span>';
166146
$modal_container = new ModalBuilder();
167147

148+
// A filter is not implemented, yet
149+
$filter = [
150+
'type' => '',
151+
'title' => '',
152+
'object' => ''
153+
];
154+
168155
$types = ilBadgeHandler::getInstance()->getAvailableTypes(false);
169-
$filter = ['type' => '', 'title' => '', 'object' => ''];
156+
$rows = [];
170157
foreach (ilBadge::getObjectInstances($filter) as $badge_item) {
171158
$type_caption = ilBadge::getExtendedTypeCaption($types[$badge_item['type_id']]);
172-
$badge_rid = $badge_item['image_rid'];
173-
$image_src = $this->badge_image_service->getImageFromResourceId($badge_item, $badge_rid);
174-
if ($badge_rid) {
175-
$badge_template_image = $image_src;
176-
if ($badge_template_image !== '') {
177-
$badge_img = $this->factory->image()->responsive(
178-
$badge_template_image,
159+
160+
$images = [
161+
'rendered' => '',
162+
'rendered_large' => '',
163+
];
164+
$image_src = $this->badge_image_service->getImageFromResourceId(
165+
$badge_item,
166+
$badge_item['image_rid']
167+
);
168+
if ($image_src !== '') {
169+
$images['rendered'] = $this->renderer->render(
170+
$this->factory->image()->responsive(
171+
$image_src,
179172
$badge_item['title']
180-
);
181-
$image_html = $this->renderer->render($badge_img);
182-
}
173+
)
174+
);
175+
183176
$image_html_large = $this->badge_image_service->getImageFromResourceId(
184177
$badge_item,
185-
$badge_rid,
178+
$badge_item['image_rid'],
186179
ilBadgeImage::IMAGE_SIZE_XL
187180
);
188181
if ($image_html_large !== '') {
189-
$badge_img_large = $this->ui_factory->image()->responsive(
182+
$images['rendered_large'] = $this->ui_factory->image()->responsive(
190183
$image_html_large,
191184
$badge_item['title']
192185
);
193186
}
194187
}
195188

196-
$ref_ids = ilObject::_getAllReferences($badge_item['parent_id']);
197-
$ref_id = array_shift($ref_ids);
189+
$sortable_container_title_parts = [
190+
'title' => $badge_item['parent_title'] ?? ''
191+
];
192+
$container_title_parts = [
193+
'icon' => $this->ui_renderer->render($this->ui_factory->symbol()->icon()->custom(
194+
ilObject::_getIcon($badge_item['parent_id'], 'big', $badge_item['parent_type'] ?? ''),
195+
$this->lng->txt('obj_' . ($badge_item['parent_type'] ?? ''))
196+
)),
197+
'title' => $sortable_container_title_parts['title'],
198+
];
198199

199-
$container_url_link = '';
200-
if ($this->access->checkAccess('read', '', $ref_id)) {
201-
$container_url = ilLink::_getLink($ref_id);
202-
$container_url_link = $this->renderer->render(
203-
new Standard($badge_item['parent_title'], (string) new URI($container_url))
204-
);
205-
$container_icon = '<img class="ilIcon" src="' .
206-
ilObject::_getIcon((int) $badge_item['parent_id'], 'big', $badge_item['parent_type']) .
207-
'" alt="' . $this->lng->txt('obj_' . $badge_item['parent_type']) .
208-
'" title="' . $this->lng->txt('obj_' . $badge_item['parent_type']) . '" /> ';
200+
if ($badge_item['deleted']) {
201+
$container_title_parts['suffix'] = $container_deleted_title_part;
202+
$sortable_container_title_parts['suffix'] = $container_deleted_title_part;
203+
} else {
204+
$ref_ids = ilObject::_getAllReferences($badge_item['parent_id']);
205+
$ref_id = array_shift($ref_ids);
206+
if ($ref_id && $this->access->checkAccess('read', '', $ref_id)) {
207+
$container_title_parts['title'] = $this->renderer->render(
208+
new Standard(
209+
$container_title_parts['title'],
210+
(string) new URI(ilLink::_getLink($ref_id))
211+
)
212+
);
213+
} else {
214+
$container_title_parts['suffix'] = $container_deleted_title_part;
215+
$sortable_container_title_parts['suffix'] = $container_deleted_title_part;
216+
}
209217
}
210218

211219
$badge_information = [
212-
'active' => ($badge_item['active'] ? $this->lng->txt('yes') : $this->lng->txt('no')),
220+
'active' => $badge_item['active'] ? $this->lng->txt('yes') : $this->lng->txt('no'),
213221
'type' => $type_caption,
214-
'container' => $container_url_link ?: $badge_item['parent_title'],
222+
'container' => implode(' ', \array_slice($container_title_parts, 1, null, true)),
215223
];
216224

217225
$modal = $modal_container->constructModal(
218-
$badge_img_large ?: null,
226+
$images['rendered_large'] ?: null,
219227
$badge_item['title'],
220228
$badge_information
221229
);
222230

223-
$data[] = [
224-
'id' => (int) $badge_item['id'],
231+
$rows[] = [
232+
'id' => $badge_item['id'],
225233
'active' => (bool) $badge_item['active'],
226234
'type' => $type_caption,
227-
'image_rid' => $modal_container->renderShyButton(
228-
$image_html,
235+
'image' => $images['rendered'] ? ($modal_container->renderShyButton(
236+
$images['rendered'],
229237
$modal
230-
) . ' ' . $modal_container->renderModal($modal),
231-
'title' => $modal_container->renderShyButton($badge_item['title'], $modal),
232-
'container' => $badge_item['parent_title'],
233-
'container_icon' => $container_icon,
234-
'container_url' => $container_icon . $container_url_link ?: '',
235-
'container_deleted' => ($badge_item['deleted'] ?? false),
236-
'container_id' => (int) $badge_item['parent_id'],
237-
'container_type' => $badge_item['parent_type'],
238+
) . ' ') : '',
239+
// Just an boolean-like indicator for sorting
240+
'image_sortable' => $images['rendered'] ? 'A' : 'Z',
241+
'title' => implode('', [
242+
$modal_container->renderShyButton($badge_item['title'], $modal),
243+
$modal_container->renderModal($modal)
244+
]),
245+
'title_sortable' => $badge_item['title'],
246+
'container' => implode(' ', $container_title_parts),
247+
'container_sortable' => implode(' ', $sortable_container_title_parts),
238248
];
239249
}
240250

@@ -243,21 +253,33 @@ private function getRecords(Range $range = null, Order $order = null): array
243253
[],
244254
fn($ret, $key, $value) => [$key, $value]
245255
);
246-
usort($data, static fn($a, $b) => $a[$order_field] <=> $b[$order_field]);
256+
usort(
257+
$rows,
258+
static function (array $left, array $right) use ($order_field): int {
259+
if (\in_array($order_field, ['image', 'container', 'title'], true)) {
260+
return \ilStr::strCmp(
261+
$left[$order_field . '_sortable'],
262+
$right[$order_field . '_sortable']
263+
);
264+
}
265+
266+
return $left[$order_field] <=> $right[$order_field];
267+
}
268+
);
247269
if ($order_field === 'active') {
248270
if ($order_direction === 'ASC') {
249-
$data = array_reverse($data);
271+
$rows = array_reverse($rows);
250272
}
251273
} elseif ($order_direction === 'DESC') {
252-
$data = array_reverse($data);
274+
$rows = array_reverse($rows);
253275
}
254276
}
255277

256278
if ($range) {
257-
$data = \array_slice($data, $range->getStart(), $range->getLength());
279+
$rows = \array_slice($rows, $range->getStart(), $range->getLength());
258280
}
259281

260-
return $data;
282+
return $rows;
261283
}
262284
};
263285
}
@@ -309,10 +331,10 @@ public function renderTable(): void
309331
$df = new \ILIAS\Data\Factory();
310332

311333
$columns = [
312-
'image_rid' => $f->table()->column()->text($this->lng->txt('image')),
334+
'image' => $f->table()->column()->text($this->lng->txt('image')),
313335
'title' => $f->table()->column()->text($this->lng->txt('title')),
314336
'type' => $f->table()->column()->text($this->lng->txt('type')),
315-
'container_url' => $f->table()->column()->text($this->lng->txt('container')),
337+
'container' => $f->table()->column()->text($this->lng->txt('container')),
316338
'active' => $f->table()->column()->boolean(
317339
$this->lng->txt('active'),
318340
$this->lng->txt('yes'),
@@ -337,6 +359,7 @@ public function renderTable(): void
337359

338360
$table = $f->table()
339361
->data($this->lng->txt('badge_object_badges'), $columns, $data_retrieval)
362+
->withOrder(new Order('title', Order::ASC))
340363
->withActions($actions)
341364
->withRequest($request);
342365

0 commit comments

Comments
 (0)