ILIAS  trunk Revision v11.0_alpha-1689-g66c127b4ae8
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
QuestionsBrowserTable.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
38 
40 {
41  public const ACTION_INSERT = 'insert';
42 
43  public function __construct(
44  private readonly string $table_id,
45  private readonly \ilObjUser $current_user,
46  private readonly UIFactory $ui_factory,
47  private readonly UIRenderer $ui_renderer,
48  private readonly \ilLanguage $lng,
49  private readonly \ilCtrl $ctrl,
50  private readonly DataFactory $data_factory,
51  private readonly \ilAssQuestionList $question_list,
52  private readonly TaxonomyService $taxonomy,
53  private readonly string $parent_title
54  ) {
55  }
56 
57  public function getComponent(ServerRequestInterface $request, ?array $filter): Data
58  {
59  return $this->ui_factory->table()->data(
60  $this,
61  $this->lng->txt('list_of_questions'),
62  $this->getColumns(),
63  )->withId($this->table_id)
64  ->withActions($this->getActions())
65  ->withRequest($request)
66  ->withFilter($filter);
67  }
68 
69  public function getColumns(): array
70  {
71  $column_factory = $this->ui_factory->table()->column();
72  $icon_factory = $this->ui_factory->symbol()->icon();
73  $iconYes = $icon_factory->custom('assets/images/standard/icon_checked.svg', 'yes');
74  $iconNo = $icon_factory->custom('assets/images/standard/icon_unchecked.svg', 'no');
75 
76  $columns = [
77  'title' => $column_factory->text(
78  $this->lng->txt('tst_question_title')
79  )->withIsOptional(false, true),
80  'description' => $column_factory->text(
81  $this->lng->txt('description')
82  )->withIsOptional(true, true),
83  'type_tag' => $column_factory->text(
84  $this->lng->txt('tst_question_type')
85  )->withIsOptional(false, true),
86  'points' => $column_factory->number(
87  $this->lng->txt('points')
88  )->withIsOptional(false, true),
89  'author' => $column_factory->text(
90  $this->lng->txt('author')
91  )->withIsOptional(true, false),
92  'lifecycle' => $column_factory->text(
93  $this->lng->txt('qst_lifecycle')
94  )->withIsOptional(true, false),
95  'parent_title' => $column_factory->text(
96  $this->lng->txt($this->parent_title)
97  )->withIsOptional(false, true),
98  'taxonomies' => $column_factory->text(
99  $this->lng->txt('qpl_settings_subtab_taxonomies')
100  )->withIsOptional(false, true),
101  'feedback' => $column_factory->boolean(
102  $this->lng->txt('feedback'),
103  $iconYes,
104  $iconNo
105  )->withIsOptional(true, false),
106  'hints' => $column_factory->boolean(
107  $this->lng->txt('hints'),
108  $iconYes,
109  $iconNo
110  )->withIsOptional(true, false),
111  'created' => $column_factory->date(
112  $this->lng->txt('created'),
113  $this->current_user->getDateTimeFormat()
114  )->withIsOptional(true, false),
115  'tstamp' => $column_factory->date(
116  $this->lng->txt('updated'),
117  $this->current_user->getDateTimeFormat()
118  )->withIsOptional(true, false)
119  ];
120 
121  return array_map(static fn(Column $column): Column => $column->withIsSortable(true), $columns);
122  }
123 
124  public function getActions(): array
125  {
126  return [self::ACTION_INSERT => $this->getInsertAction()];
127  }
128 
129  private function getInsertAction(): TableAction
130  {
131  $url_builder = new URLBuilder($this->data_factory->uri(
132  ServerRequest::getUriFromGlobals() . $this->ctrl->getLinkTargetByClass(
133  ilTestQuestionBrowserTableGUI::class,
135  )
136  ));
137 
138  [$url_builder, $row_id_token] = $url_builder->acquireParameters(['qlist'], 'q_id');
139 
140  return $this->ui_factory->table()->action()->standard(
141  $this->lng->txt('tst_insert_in_test'),
142  $url_builder,
143  $row_id_token
144  );
145  }
146 
147  public function getRows(
148  DataRowBuilder $row_builder,
149  array $visible_column_ids,
150  Range $range,
151  Order $order,
152  ?array $filter_data,
153  ?array $additional_parameters
154  ): \Generator {
155  $timezone = new \DateTimeZone($this->current_user->getTimeZone());
156  foreach ($this->loadRecords($filter_data ?? [], $order, $range) as $record) {
157  $question_id = $record['question_id'];
158 
159  $record['type_tag'] = $this->lng->txt($record['type_tag']);
160  $record['complete'] = (bool) $record['complete'];
161  $record['lifecycle'] = \ilAssQuestionLifecycle::getInstance($record['lifecycle'])->getTranslation($this->lng) ?? '';
162 
163  $record['created'] = (new \DateTimeImmutable("@{$record['created']}"))->setTimezone($timezone);
164  $record['tstamp'] = (new \DateTimeImmutable("@{$record['tstamp']}"))->setTimezone($timezone);
165  $record['taxonomies'] = $this->resolveTaxonomiesRowData($record['obj_fi'], $question_id);
166 
167  yield $row_builder->buildDataRow((string) $question_id, $record);
168  }
169  }
170 
171  public function getTotalRowCount(?array $filter_data, ?array $additional_parameters): int
172  {
173  $filter_data ??= [];
174  $this->addFiltersToQuestionList($filter_data);
175  return $this->question_list->getTotalRowCount($filter_data, $additional_parameters);
176  }
177 
178  public function loadRecords(array $filters = [], ?Order $order = null, ?Range $range = null): array
179  {
180  $this->addFiltersToQuestionList($filters);
181 
182  $this->question_list->setOrder($order);
183  $this->question_list->setRange($range);
184  $this->question_list->load();
185 
186  return $this->question_list->getQuestionDataArray();
187  }
188 
189  private function addFiltersToQuestionList(array $filters): void
190  {
191  foreach (array_filter($filters) as $key => $filter) {
192  if ($key === 'commented') {
193  $this->question_list->setCommentFilter((int) $filter);
194  continue;
195  }
196 
197  $this->question_list->addFieldFilter($key, $filter);
198  }
199  }
200 
201  private function resolveTaxonomiesRowData(int $obj_fi, int $questionId): string
202  {
203  $available_taxonomy_ids = $this->taxonomy->getUsageOfObject($obj_fi);
204  $data = $this->loadTaxonomyAssignmentData($obj_fi, $questionId, $available_taxonomy_ids);
205 
206  $taxonomies = [];
207 
208  foreach ($data as $taxonomyId => $taxData) {
209  $taxonomies[] = \ilObject::_lookupTitle($taxonomyId);
210  $taxonomies[] = $this->ui_renderer->render(
211  $this->ui_factory->listing()->unordered(
212  array_map(static function ($node) {
213  return \ilTaxonomyNode::_lookupTitle($node['node_id']);
214  }, $taxData)
215  )
216  );
217  }
218 
219  return implode('', $taxonomies);
220  }
221 
222  private function loadTaxonomyAssignmentData(int $parentObjId, int $questionId, array $available_taxonomy_ids): array
223  {
224  $taxonomyAssignmentData = [];
225 
226  foreach ($available_taxonomy_ids as $taxId) {
227  $taxTree = new \ilTaxonomyTree($taxId);
228  $assignments = (new \ilTaxNodeAssignment(
229  'qpl',
230  $parentObjId,
231  'quest',
232  $taxId
233  ))->getAssignmentsOfItem($questionId);
234 
235  foreach ($assignments as $assData) {
236  $taxId = $assData['tax_id'];
237  if (!isset($taxonomyAssignmentData[$taxId])) {
238  $taxonomyAssignmentData[$taxId] = [];
239  }
240 
241  $nodeId = $assData['node_id'];
242  $assData['node_lft'] = $taxTree->getNodeData($nodeId)['lft'];
243  $taxonomyAssignmentData[$taxId][$nodeId] = $assData;
244  }
245  }
246 
247  return $taxonomyAssignmentData;
248  }
249 }
getComponent(ServerRequestInterface $request, ?array $filter)
getTotalRowCount(?array $filter_data, ?array $additional_parameters)
Mainly for the purpose of pagination-support, it is important to know about the total number of recor...
loadRecords(array $filters=[], ?Order $order=null, ?Range $range=null)
loadTaxonomyAssignmentData(int $parentObjId, int $questionId, array $available_taxonomy_ids)
Both the subject and the direction need to be specified when expressing an order. ...
Definition: Order.php:28
buildDataRow(string $id, array $record)
getRows(DataRowBuilder $row_builder, array $visible_column_ids, Range $range, Order $order, ?array $filter_data, ?array $additional_parameters)
This is called by the table to retrieve rows; map data-records to rows using the $row_builder e...
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static _lookupTitle(int $obj_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
__construct(private readonly string $table_id, private readonly \ilObjUser $current_user, private readonly UIFactory $ui_factory, private readonly UIRenderer $ui_renderer, private readonly \ilLanguage $lng, private readonly \ilCtrl $ctrl, private readonly DataFactory $data_factory, private readonly \ilAssQuestionList $question_list, private readonly TaxonomyService $taxonomy, private readonly string $parent_title)
global $lng
Definition: privfeed.php:31
URLBuilder.
Definition: URLBuilder.php:40
A simple class to express a naive range of whole positive numbers.
Definition: Range.php:28
A Column describes the form of presentation for a certain aspect of data, i.e.
Definition: Column.php:27