19declare(strict_types=1);
39 protected UIFactory $ui_factory,
40 protected UIRenderer $ui_renderer,
41 protected DataFactory $data_factory,
51 protected TaxonomyService $taxonomy,
52 protected NotesService $notes_service,
53 protected int $parent_obj_id,
54 protected int $request_ref_id
56 $lng->loadLanguageModule(
'qpl');
63 return $this->ui_factory->table()->data(
65 $this->
lng->txt(
'questions'),
69 ->withId(
'qpt' . $this->parent_obj_id .
'_' . $this->request_ref_id);
78 $lifecycle_options = array_merge(
79 [
'' => $this->
lng->txt(
'qst_lifecycle_filter_all')],
82 $question_type_options = [
83 '' => $this->
lng->txt(
'filter_all_question_types')
86 foreach ($question_types as $translation => $row) {
87 $question_type_options[$row[
'type_tag']] = $translation;
90 $field_factory = $this->ui_factory->input()->field();
92 'title' => $field_factory->text($this->
lng->txt(
"title")),
93 'description' => $field_factory->text($this->
lng->txt(
"description")),
94 'author' => $field_factory->text($this->
lng->txt(
"author")),
95 'lifecycle' => $field_factory->select($this->
lng->txt(
"qst_lifecycle"), $lifecycle_options),
96 'type' => $field_factory->select($this->
lng->txt(
"type"), $question_type_options),
97 'commented' => $field_factory->select(
98 $this->
lng->txt(
"ass_comments"),
106 $taxs = $this->taxonomy->getUsageOfObject($this->parent_obj_id,
true);
107 $tax_filter_options = [
108 'null' =>
'<b>' . $this->
lng->txt(
'tax_filter_notax') .
'</b>'
111 foreach ($taxs as $tax_entry) {
112 $tax = new \ilObjTaxonomy($tax_entry[
'tax_id']);
113 $tax_tree = $tax->getTree();
115 $children = $this->
taxNodeReader($tax_tree, $sortfield, $tax_tree->readRootId());
116 $nodes = implode(
'-', array_map(fn($node) => $node[
'obj_id'], $children));
118 $tax_id = $tax_entry[
'tax_id'] .
'-0-' . $nodes;
119 $tax_title =
'<b>' . $tax_entry[
'title'] .
'</b>';
120 if ($children === []) {
123 $tax_filter_options[$tax_id] = $tax_title;
125 foreach ($children as $subtax) {
126 $stax_id = $subtax[
'tax_id'] .
'-' . $subtax[
'obj_id'];
127 $stax_title = str_repeat(
' ', ($subtax[
'depth'] - 2) * 2)
128 .
' └─ '
131 $tax_filter_options[$stax_id] = $stax_title;
134 $filter_inputs[
'taxonomies'] = $field_factory->multiSelect($this->
lng->txt(
"tax_filter"), $tax_filter_options);
136 $active = array_fill(0, count($filter_inputs),
true);
138 $filter = $ui_service->
filter()->standard(
139 'question_table_filter_id',
152 $f = $this->ui_factory->table()->column();
153 $df = $this->data_factory->dateFormat();
154 $icon_yes = $this->ui_factory->symbol()->icon()->custom(\
ilUtil::getImagePath(
'standard/icon_checked.svg'),
'yes');
155 $icon_no = $this->ui_factory->symbol()->icon()->custom(\
ilUtil::getImagePath(
'standard/icon_unchecked.svg'),
'no');
158 'title' =>
$f->link($this->
lng->txt(
'title')),
159 'description' =>
$f->text($this->
lng->txt(
'description'))->withIsOptional(
true,
true),
160 'ttype' =>
$f->text($this->
lng->txt(
'question_type'))->withIsOptional(
true,
true),
161 'points' =>
$f->number($this->
lng->txt(
'points'))->withDecimals(2)->withIsOptional(
true,
true),
162 'author' =>
$f->text($this->
lng->txt(
'author'))->withIsOptional(
true,
true),
163 'lifecycle' =>
$f->text($this->
lng->txt(
'qst_lifecycle'))->withIsOptional(
true,
true),
164 'taxonomies' =>
$f->text($this->
lng->txt(
'qpl_settings_subtab_taxonomies'))->withIsOptional(
true,
true),
165 'feedback' =>
$f->boolean($this->
lng->txt(
'feedback'), $icon_yes, $icon_no)->withIsOptional(
true,
true),
166 'created' =>
$f->date(
167 $this->
lng->txt(
'create_date'),
168 $this->current_user->getDateTimeFormat()
169 )->withIsOptional(
true,
true),
170 'tstamp' =>
$f->date(
171 $this->
lng->txt(
'last_update'),
172 $this->current_user->getDateTimeFormat()
173 )->withIsOptional(
true,
true),
174 'comments' =>
$f->number($this->
lng->txt(
'comments'))->withIsOptional(
true,
false),
180 $hop = array_shift($stack);
184 if (! array_key_exists($hop, $pointer)) {
187 $this->
treeify($pointer[$hop], $stack);
193 foreach ($nodes as $k => $n) {
200 return $this->ui_renderer->render(
201 $this->ui_factory->listing()->unordered($entries)
208 $nodes = $tree->getChildsByTypeFilter($node_id, [
'taxn']);
211 fn(
$a,
$b) => strcmp(
212 (
string)
$a[$sortfield],
213 (
string)
$b[$sortfield]
217 foreach ($nodes as $node) {
219 foreach ($this->
taxNodeReader($tree, $sortfield, $node[
'obj_id']) as
$c) {
228 array $stored_tax_data,
234 $taxnodes = $this->
taxNodeReader($tax_tree, $sortfield, $tax_tree->readRootId());
237 foreach ($taxnodes as $taxnode) {
238 $taxdata = array_filter(
240 fn($data_child) => $data_child[
'node_id'] === $taxnode[
'obj_id']
243 foreach (array_keys($taxdata) as $node_obj_id) {
245 fn($n) => in_array($n[
'obj_id'], array_keys($stored_tax_data)) ? $check_marker . $n[
'title'] : $n[
'title'],
246 $tax_tree->getPathFull($node_obj_id),
257 $check = $this->ui_renderer->render(
258 $this->ui_factory->symbol()->icon()->custom(\
ilUtil::getImagePath(
'standard/icon_checked.svg'),
'checked')
262 $taxs = $this->taxonomy->getUsageOfObject($this->parent_obj_id,
true);
263 foreach ($taxs as $tax_entry) {
264 $tax_id = $tax_entry[
'tax_id'];
265 if (!array_key_exists($tax_id, $taxonomy_data)) {
268 $taxonomies[] = $this->singleTaxonomyRepresentation(
270 $taxonomy_data[$tax_id],
274 return implode(
'', $taxonomies);
279 array $visible_column_ids,
283 ?array $additional_parameters
285 $timezone = new \DateTimeZone($this->current_user->getTimeZone());
286 foreach ($this->getData($order,
$range) as $record) {
287 $row_id = (string) $record[
'question_id'];
288 $record[
'created'] = (new \DateTimeImmutable(
"@{$record['created']}"))->setTimezone($timezone);
289 $record[
'tstamp'] = (new \DateTimeImmutable(
"@{$record['tstamp']}"))->setTimezone($timezone);
291 $record[
'lifecycle'] =
$lifecycle->getTranslation($this->
lng);
293 $title = $record[
'title'];
294 $to_question = $this->url_builder
295 ->withParameter($this->action_parameter_token,
'preview')
296 ->withParameter($this->row_id_token, $row_id)
297 ->buildURI()->__toString();
298 if (!(
bool) $record[
'complete']) {
299 $title .=
' (' . $this->
lng->txt(
'warning_question_not_complete') .
')';
301 $record[
'title'] = $this->ui_factory->link()->standard($title, $to_question);
302 $record[
'taxonomies'] = $this->taxonomyRepresentation($record[
'taxonomies']);
304 yield $row_builder->buildDataRow($row_id, $record);
310 ?array $additional_parameters
312 $this->setParentObjId($this->parent_obj_id);
314 return count($this->getQuestionDataArray());
319 $this->setParentObjId($this->parent_obj_id);
321 $data = $this->postOrder($this->getQuestionDataArray(), $order);
323 $length = $length > 0 ? $length :
null;
324 return array_slice(
$data, $offset, $length);
329 $write_access = $this->
rbac->checkAccess(
'write', $this->request_ref_id);
331 $this->buildAction(
'copy',
'standard'),
332 $write_access ? $this->buildAction(
'move',
'standard') : [],
333 $write_access ? $this->buildAction(
'delete',
'standard') : [],
334 $this->buildAction(
'export',
'multi'),
335 $this->buildAction(
'preview',
'single'),
336 $this->buildAction(
'statistics',
'single'),
337 $write_access ? $this->buildAction(
'edit_question',
'single') : [],
338 $write_access ? $this->buildAction(
'edit_page',
'single') : [],
339 $write_access ? $this->buildAction(
'feedback',
'single') : [],
343 $this->showCommentAction() ? $this->buildAction(
'comments',
'single',
true) : []
347 protected function buildAction(
string $act,
string $type,
bool $async =
false): array
349 $action = $this->ui_factory->table()->action()
351 $this->
lng->txt($act),
352 $this->url_builder->withParameter($this->action_parameter_token, $act),
356 $action = $action->withAsync(
true);
359 return [$act => $action];
364 [$aspect, $direction] = $order->join(
'',
function ($i, $k, $v) {
367 usort($list,
static function (array
$a, array
$b) use ($aspect):
int {
368 if (is_numeric(
$a[$aspect]) || is_bool(
$a[$aspect])) {
369 return $a[$aspect] <=>
$b[$aspect];
371 if (is_array(
$a[$aspect])) {
372 return $a[$aspect] <=>
$b[$aspect];
377 if (
$a[$aspect] !==
null) {
378 $aspect_a =
$a[$aspect];
380 if (
$b[$aspect] !==
null) {
381 $aspect_b =
$b[$aspect];
384 return strcoll($aspect_a, $aspect_b);
387 if ($direction === $order::DESC) {
388 $list = array_reverse($list);
395 return $this->notes_service->domain()->commentsActive($this->parent_obj_id)
396 || $this->
rbac->checkAccess(
'write', $this->request_ref_id);
Builds a Color from either hex- or rgb values.
Both the subject and the direction need to be specified when expressing an order.
A simple class to express a naive range of whole positive numbers.
treeify(&$pointer, $stack)
toNestedList(array $nodes)
buildAction(string $act, string $type, bool $async=false)
getRows(Table\DataRowBuilder $row_builder, array $visible_column_ids, Range $range, Order $order, ?array $filter_data, ?array $additional_parameters)
__construct(protected UIFactory $ui_factory, protected UIRenderer $ui_renderer, protected DataFactory $data_factory, protected Refinery $refinery, protected URLBuilder $url_builder, protected URLBuilderToken $action_parameter_token, protected URLBuilderToken $row_id_token, protected \ilDBInterface $db, protected \ilLanguage $lng, protected \ilComponentRepository $component_repository, protected \ilRbacSystem $rbac, protected \ilObjUser $current_user, protected TaxonomyService $taxonomy, protected NotesService $notes_service, protected int $parent_obj_id, protected int $request_ref_id)
taxonomyRepresentation(array $taxonomy_data)
singleTaxonomyRepresentation(int $tax_id, array $stored_tax_data, string $check_marker)
getFilter(\ilUIService $ui_service, string $action)
Filters should be part of the Table; for now, since they are not fully integrated,...
getData(Order $order, Range $range)
postOrder(array $list, \ILIAS\Data\Order $order)
taxNodeReader($tree, $sortfield, $node_id)
getTotalRowCount(?array $filter_data, ?array $additional_parameters)
static getDraftInstance()
static getInstance($identifier)
setAvailableTaxonomyIds(array $availableTaxonomyIds)
const QUESTION_COMMENTED_EXCLUDED
const QUESTION_COMMENTED_ONLY
static _getQuestionTypes($all_tags=false, $fixOrder=false, $withDeprecatedTypes=true)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _lookupTitle(int $obj_id)
class ilRbacSystem system function like checkAccess, addActiveRole ... Supporting system functions ar...
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
This describes a Data Table.
withActions(array $actions)
An entity that renders components to a string output.
Readable part of repository interface to ilComponentDataDB.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples