19 declare(strict_types=1);
    53         protected int $parent_obj_id,
    54         protected int $request_ref_id
    63         return $this->ui_factory->table()->data(
    64             $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             $tax_filter_options[$tax_id] = $tax_title;
   122             foreach ($children as $subtax) {
   123                 $stax_id = $subtax[
'tax_id'] . 
'-' . $subtax[
'obj_id'];
   124                 $stax_title = str_repeat(
'  ', ($subtax[
'depth'] - 2) * 2)
   125                     . 
' └─ '   128                 $tax_filter_options[$stax_id] = $stax_title;
   131         $filter_inputs[
'taxonomies'] = $field_factory->multiSelect($this->
lng->txt(
"tax_filter"), $tax_filter_options);
   133         $active = array_fill(0, count($filter_inputs), 
true);
   135         $filter = $ui_service->
filter()->standard(
   136             'question_table_filter_id',
   149         $f = $this->ui_factory->table()->column();
   150         $df = $this->data_factory->dateFormat();
   151         $icon_yes = $this->ui_factory->symbol()->icon()->custom(\
ilUtil::getImagePath(
'standard/icon_checked.svg'), 
'yes');
   152         $icon_no = $this->ui_factory->symbol()->icon()->custom(\
ilUtil::getImagePath(
'standard/icon_unchecked.svg'), 
'no');
   155             'title' => 
$f->link($this->
lng->txt(
'title')),
   156             'description' => 
$f->text($this->lng->txt(
'description'))->withIsOptional(
true, 
true),
   157             'ttype' => 
$f->text($this->
lng->txt(
'question_type'))->withIsOptional(
true, 
true),
   158             'points' => 
$f->number($this->
lng->txt(
'points'))->withDecimals(2)->withIsOptional(
true, 
true),
   159             'author' => 
$f->text($this->
lng->txt(
'author'))->withIsOptional(
true, 
true),
   160             'lifecycle' => 
$f->text($this->
lng->txt(
'qst_lifecycle'))->withIsOptional(
true, 
true),
   161             'taxonomies' => 
$f->text($this->
lng->txt(
'qpl_settings_subtab_taxonomies'))->withIsOptional(
true, 
true),
   162             'feedback' => 
$f->boolean($this->
lng->txt(
'feedback'), $icon_yes, $icon_no)->withIsOptional(
true, 
true),
   163             'hints' => 
$f->boolean($this->
lng->txt(
'hints'), $icon_yes, $icon_no)->withIsOptional(
true, 
true),
   164             'created' => 
$f->date(
   165                 $this->
lng->txt(
'create_date'),
   166                 $this->current_user->getDateTimeFormat()
   167             )->withIsOptional(
true, 
true),
   168             'tstamp' => 
$f->date(
   169                 $this->
lng->txt(
'last_update'),
   170                 $this->current_user->getDateTimeFormat()
   171             )->withIsOptional(
true, 
true),
   172             'comments' => 
$f->number($this->
lng->txt(
'comments'))->withIsOptional(
true, 
false),
   178         $hop = array_shift($stack);
   182         if (! array_key_exists($hop, $pointer)) {
   185         $this->
treeify($pointer[$hop], $stack);
   191         foreach ($nodes as $k => $n) {
   198         return $this->ui_renderer->render(
   199             $this->ui_factory->listing()->unordered($entries)
   206         $nodes = $tree->getChildsByTypeFilter($node_id, [
'taxn']);
   209             fn(
$a, 
$b) => strcmp(
   210                 (
string) 
$a[$sortfield],
   211                 (
string) 
$b[$sortfield]
   215         foreach ($nodes as $node) {
   217             foreach ($this->
taxNodeReader($tree, $sortfield, $node[
'obj_id']) as 
$c) {
   226         array $stored_tax_data,
   229         $tax = new \ilObjTaxonomy($tax_id);
   230         $tax_tree = $tax->getTree();
   232         $taxnodes = $this->
taxNodeReader($tax_tree, $sortfield, $tax_tree->readRootId());
   235         foreach ($taxnodes as $taxnode) {
   236             $taxdata = array_filter(
   238                 fn($data_child) => $data_child[
'node_id'] === $taxnode[
'obj_id']
   241             foreach (array_keys($taxdata) as $node_obj_id) {
   243                     fn($n) => in_array($n[
'obj_id'], array_keys($stored_tax_data)) ? $check_marker . $n[
'title'] : $n[
'title'],
   244                     $tax_tree->getPathFull($node_obj_id),
   255         $check = $this->ui_renderer->render(
   256             $this->ui_factory->symbol()->icon()->custom(\
ilUtil::getImagePath(
'standard/icon_checked.svg'), 
'checked')
   260         $taxs = $this->taxonomy->getUsageOfObject($this->parent_obj_id, 
true);
   261         foreach ($taxs as $tax_entry) {
   262             $tax_id = $tax_entry[
'tax_id'];
   263             if (!array_key_exists($tax_id, $taxonomy_data)) {
   268                 $taxonomy_data[$tax_id],
   272         return implode(
'', $taxonomies);
   277         array $visible_column_ids,
   281         ?array $additional_parameters
   283         $no_write_access = !($this->
rbac->checkAccess(
'write', $this->request_ref_id));
   284         $timezone = new \DateTimeZone($this->current_user->getTimeZone());
   285         foreach ($this->
getData($order, $range) as $record) {
   286             $row_id = (string) $record[
'question_id'];
   287             $record[
'created'] = (new \DateTimeImmutable(
"@{$record['created']}"))->setTimezone($timezone);
   288             $record[
'tstamp'] = (new \DateTimeImmutable(
"@{$record['tstamp']}"))->setTimezone($timezone);
   290             $record[
'lifecycle'] = 
$lifecycle->getTranslation($this->
lng);
   292             $title = $record[
'title'];
   293             $to_question = $this->url_builder
   294                 ->withParameter($this->action_parameter_token, 
'preview')
   295                 ->withParameter($this->row_id_token, $row_id)
   296                 ->buildURI()->__toString();
   297             if (!(
bool) $record[
'complete']) {
   298                 $title .= 
' (' . $this->
lng->txt(
'warning_question_not_complete') . 
')';
   300             $record[
'title'] = $this->ui_factory->link()->standard($title, $to_question);
   303             yield $row_builder->buildDataRow($row_id, $record)
   304                 ->withDisabledAction(
'move', $no_write_access)
   305                 ->withDisabledAction(
'copy', $no_write_access)
   306                 ->withDisabledAction(
'delete', $no_write_access)
   307                 ->withDisabledAction(
'feedback', $no_write_access)
   308                 ->withDisabledAction(
'hints', $no_write_access)
   315         ?array $additional_parameters
   327         [$offset, $length] = $range->
unpack();
   328         $length = $length > 0 ? $length : null;
   329         return array_slice(
$data, $offset, $length);
   352     protected function buildAction(
string $act, 
string $type, 
bool $async = 
false): array
   354         $action = $this->ui_factory->table()->action()
   356                 $this->
lng->txt($act),
   357                 $this->url_builder->withParameter($this->action_parameter_token, $act),
   361             $action = $action->withAsync(
true);
   364         return [$act => $action];
   369         [$aspect, $direction] = $order->join(
'', 
function ($i, $k, $v) {
   372         usort($list, 
static function (array 
$a, array 
$b) use ($aspect): 
int {
   373             if (is_numeric($a[$aspect]) || is_bool($a[$aspect])) {
   374                 return $a[$aspect] <=> $b[$aspect];
   376             if (is_array($a[$aspect])) {
   377                 return $a[$aspect] <=> $b[$aspect];
   382             if ($a[$aspect] !== null) {
   383                 $aspect_a = $a[$aspect];
   385             if ($b[$aspect] !== null) {
   386                 $aspect_b = $b[$aspect];
   389             return strcoll($aspect_a, $aspect_b);
   392         if ($direction === $order::DESC) {
   393             $list = array_reverse($list);
   400         return $this->notes_service->domain()->commentsActive($this->parent_obj_id)
   401             || $this->
rbac->checkAccess(
'write', $this->request_ref_id);
 
static getInstance($identifier)
 
Readable part of repository interface to ilComponentDataDB. 
 
setAvailableTaxonomyIds(array $availableTaxonomyIds)
 
Interface Observer  Contains several chained tasks and infos about them. 
 
taxNodeReader($tree, $sortfield, $node_id)
 
const QUESTION_COMMENTED_ONLY
 
loadLanguageModule(string $a_module)
Load language module. 
 
const QUESTION_COMMENTED_EXCLUDED
 
Both the subject and the direction need to be specified when expressing an order. ...
 
__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)
 
toNestedList(array $nodes)
 
static _lookupTitle(int $obj_id)
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
treeify(&$pointer, $stack)
 
postOrder(array $list, \ILIAS\Data\Order $order)
 
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory) 
 
getRows(Table\DataRowBuilder $row_builder, array $visible_column_ids, Range $range, Order $order, ?array $filter_data, ?array $additional_parameters)
 
getData(Order $order, Range $range)
 
setParentObjId(?int $parentObjId)
 
__construct(Container $dic, ilPlugin $plugin)
 
getTotalRowCount(?array $filter_data, ?array $additional_parameters)
 
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples 
 
taxonomyRepresentation(array $taxonomy_data)
 
singleTaxonomyRepresentation(int $tax_id, array $stored_tax_data, string $check_marker)
 
A simple class to express a naive range of whole positive numbers. 
 
static getDraftInstance()
 
getFilter(\ilUIService $ui_service, string $action)
Filters should be part of the Table; for now, since they are not fully integrated, they are rendered and applied seperately. 
 
buildAction(string $act, string $type, bool $async=false)
 
static _getQuestionTypes($all_tags=false, $fixOrder=false, $withDeprecatedTypes=true)