ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.ilLegalDocumentsAdministrationGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
39 
41 {
42  private readonly Container $container;
43  private readonly UI $ui;
44  private readonly Administration $admin;
45 
46  public function __construct(
47  private readonly string $parent_class,
48  private readonly Config $config,
49  private readonly Closure $after_document_deletion,
50  ?Container $container = null
51  ) {
52  $this->container = $container ?? $GLOBALS['DIC'];
53  $this->container->language()->loadLanguageModule('ldoc');
54  $this->ui = new UI(
55  $this->config->legalDocuments()->id(),
56  $this->container->ui(),
57  $this->container->language()
58  );
59  $this->admin = new Administration($this->config, $this->container, $this->ui);
60  }
61 
62  public function executeCommand(): void
63  {
64  $cmd = $this->container->ctrl()->getCmd('documents');
65  if (!$this->isCommand($cmd)) {
66  throw new Exception('Unknown command: ' . $cmd);
67  }
68  $this->$cmd();
69  }
70 
71  public function history(): void
72  {
73  if (!$this->admin->canReadUserAdministration()) {
74  $this->container['ilErr']->raiseError($this->container->language()->txt('permission_denied'), $this->container['ilErr']->WARNING);
75  }
76  $this->container->tabs()->activateTab('history');
77  $this->admin->setContent($this->config->legalDocuments()->history()->table(
78  $this,
79  'history',
80  'historyResetFilter',
81  'searchUser'
82  ));
83  }
84 
85  public function searchUser(): void
86  {
87  $auto = new ilUserAutoComplete();
88  $auto->setSearchFields(['login', 'firstname', 'lastname', 'email']);
89  $auto->enableFieldSearchableCheck(false);
90  $auto->setMoreLinkAvailable(true);
91 
92  if ($this->container->http()->wrapper()->query()->has('fetchall')) {
93  $auto->setLimit(ilUserAutoComplete::MAX_ENTRIES);
94  }
95 
96  if ($this->container->http()->wrapper()->query()->has('term')) {
97  $query = ilUtil::stripSlashes(
98  $this->container->http()->wrapper()->query()->retrieve('term', $this->container->refinery()->kindlyTo()->string())
99  );
100  $response = $this->container->http()
101  ->response()
102  ->withHeader(ResponseHeader::CONTENT_TYPE, 'application/json')
103  ->withBody(Streams::ofString($auto->getList($query)));
104  $this->container->http()->saveResponse($response);
105  }
106 
107  $this->container->http()->sendResponse();
108  $this->container->http()->close();
109  }
110 
111  public function historyResetFilter(): void
112  {
113  $this->history();
114  }
115 
116  public function addDocument(): void
117  {
118  $this->admin->requireEditable();
119  $this->ctrlTo('setParameterByClass', 'hash', $this->config->legalDocuments()->document()->hash());
120  $this->ctrlTo('redirectByClass', 'editDocument');
121  }
122 
123  public function addCriterion(): void
124  {
125  $this->admin->requireEditable();
126  $this->container->tabs()->clearTargets();
127  $this->container->tabs()->setBackTarget($this->container->language()->txt('back'), $this->ctrlTo('getLinkTargetByClass', 'documents'));
128 
129  $document = $this->admin->currentDocument()->value();
130 
131  $this->container->language()->loadLanguageModule('meta');
132 
133  $url = $this->admin->targetWithDoc($this, $document, 'addCriterion', 'getFormAction');
134  $form = $this->admin->criterionForm($url, $document);
135 
136  $form = $this->admin->withFormData($form, function (array $x) use ($document) {
137  $content = new CriterionContent(...$x[0]['content']);
138  $this->returnWithResult($this->config->legalDocuments()->document()->validateCriteriaContent($document->criteria(), $content)->map(
139  fn() => $this->config->legalDocuments()->document()->repository()->createCriterion($document, $content)
140  ), 'doc_crit_attached', 'documents');
141  });
142 
143  $this->admin->setContent($form);
144  }
145 
146  public function editCriterion(): void
147  {
148  $this->admin->requireEditable();
149  $this->admin->withDocumentAndCriterion(function (Document $document, Criterion $criterion) {
150  $this->container->language()->loadLanguageModule('meta');
151  $url = $this->admin->targetWithDocAndCriterion($this, $document, $criterion, 'editCriterion', 'getFormAction');
152  $form = $this->admin->criterionForm($url, $document, $criterion->content());
153  $form = $this->admin->withFormData($form, function (array $data) use ($document, $criterion) {
154  $content = new CriterionContent(...$data[0]['content']);
155  $criteria = array_filter($document->criteria(), fn(Criterion $other) => $other->id() !== $criterion->id());
156  $this->returnWithResult($this->config->legalDocuments()->document()->validateCriteriaContent($criteria, $content)->map(
157  fn() => $this->config->legalDocuments()->document()->repository()->updateCriterionContent($criterion->id(), $content)
158  ), 'doc_crit_changed', 'documents');
159  });
160 
161  $this->container->tabs()->clearTargets();
162  $this->container->tabs()->setBackTarget($this->container->language()->txt('back'), $this->ctrlTo('getLinkTargetByClass', 'documents'));
163  $condition = $this->config->legalDocuments()->document()->toCondition($criterion->content());
164  $this->container->ui()->mainTemplate()->setTitle(join(' - ', [$document->content()->title(), $condition->definition()->translatedType()]));
165  $this->admin->setContent($form);
166  });
167  }
168 
169  public function deleteCriterion(): void
170  {
171  $this->admin->requireEditable();
172  $this->admin->withDocumentAndCriterion(function (Document $document, Criterion $criterion) {
173  $this->config->legalDocuments()->document()->repository()->deleteCriterion($criterion->id());
174  $this->returnWithMessage('doc_crit_detached', 'documents');
175  });
176  }
177 
178  public function upload(): void
179  {
180  $this->admin->requireEditable();
181  $this->admin->idOrHash($this, function (Closure $link, string $title, DocumentId $id) {
182  $raw_content = $this->admin->uploadContent();
183  $sanitised_value = trim((new HTMLPurifier())->purify($raw_content));
184  if ($this->admin->isInvalidHTML($sanitised_value)) {
185  $sanitised_value = nl2br($sanitised_value);
186  }
187 
188  $this->config->legalDocuments()->document()->repository()->updateDocumentContent($id, new DocumentContent('html', $title, $sanitised_value));
189  $this->admin->exitWithJsonResponse(['status' => 1]);
190  });
191  }
192 
193  public function documents(): void
194  {
195  $this->container->language()->loadLanguageModule('meta');
196  $this->container->tabs()->activateTab('documents');
197 
198  if ($this->config->editable()) {
199  $this->container->toolbar()->addStickyItem($this->admin->addDocumentButton($this->ctrlTo('getLinkTargetByClass', 'addDocument')));
200  }
201 
202  $edit_links = $this->config->editable() ? new AdministrationEditLinks($this, $this->admin) : null;
203  $this->admin->setContent($this->config->legalDocuments()->document()->table($this, __FUNCTION__, $edit_links));
204  }
205 
206  public function deleteDocuments(): void
207  {
208  $documents = $this->admin->retrieveDocuments();
209  if ($documents === []) {
210  $this->ui->mainTemplate()->setOnScreenMessage('failure', $this->ui->txt('select_at_least_one_object'), true);
211  $this->ctrlTo('redirectByClass', 'documents');
212  }
213  $this->deleteDocumentsConfirmation($documents);
214  }
215 
216  public function deleteDocument(): void
217  {
218  $this->deleteDocumentsConfirmation([$this->admin->currentDocument()->value()]);
219  }
220 
221  public function deleteConfirmed(): void
222  {
223  $this->admin->requireEditable();
224  $docs = $this->admin->retrieveDocuments();
225  $this->admin->deleteDocuments($docs);
226  ($this->after_document_deletion)();
227  $this->returnWithMessage(count($docs) === 1 ? 'deleted_documents_s' : 'deleted_documents_p', 'documents');
228  }
229 
230  public function editDocument(): void
231  {
232  $this->admin->requireEditable();
233  $this->container->tabs()->clearTargets();
234  $this->admin->idOrHash($this, function (Closure $link, string $title, DocumentId $id, bool $may_be_new) {
235  $content = fn() => $this->config->legalDocuments()->document()->repository()->findId($id)->map(fn($d) => $d->content());
236  $form = $this->admin->documentForm($link, $title, $content, $may_be_new);
237  $form = $this->admin->withFormData($form, function ($data) use (/* $edit_link, */$id) {
238  $this->config->legalDocuments()->document()->repository()->updateDocumentTitle($id, $data[0]['title']);
239  $this->returnWithMessage('saved_successfully', 'documents');
240  });
241 
242  $this->container->tabs()->setBackTarget($this->container->language()->txt('back'), $this->ctrlTo('getLinkTargetByClass', 'documents'));
243  $this->container->tabs()->activateTab('documents');
244  $this->admin->setContent($form);
245  });
246  }
247 
248  public function saveOrder(): void
249  {
250  $this->admin->requireEditable();
251  try {
252  $this->admin->withDocumentsAndOrder($this->admin->saveDocumentOrder(...));
253  $this->returnWithMessage('saved_successfully', 'documents');
254  } catch (ConstraintViolationException) {
255  $this->ui->mainTemplate()->setOnScreenMessage('failure', $this->ui->txt('ldoc_order_invalid'), true);
256  $this->ctrlTo('redirectByClass', 'documents');
257  }
258 
259  }
260 
264  public function tabs(array $run_after = []): void
265  {
266  $this->admin->tabs([
267  $this->tab('documents', $this->ui->txt('agreement_documents_tab_label')),
268  $this->tab('history', $this->ui->txt('acceptance_history'), $this->admin->canReadUserAdministration()),
269  ], $run_after);
270  }
271 
275  private function tab(string $cmd, string $label, bool $can_access = true): array
276  {
277  return [$cmd, $label, $this->ctrlTo('getLinkTargetByClass', $cmd), $can_access];
278  }
279 
280  public function admin(): Administration
281  {
282  return $this->admin;
283  }
284 
285  private function ctrlTo(string $method, ...$args)
286  {
287  $path = [$this->parent_class, self::class];
288  if ($method === 'setParameterByClass') {
289  $path = self::class;
290  }
291  return $this->container->ctrl()->$method($path, ...$args);
292  }
293 
294  private function isCommand(string $cmd): bool
295  {
296  $reflection = new ReflectionClass($this);
297  return $reflection->hasMethod($cmd)
298  && $reflection->getMethod($cmd)->isPublic()
299  && (string) $reflection->getMethod($cmd)->getReturnType() === 'void'
300  && $reflection->getMethod($cmd)->getNumberOfParameters() === 0;
301  }
302 
306  private function deleteDocumentsConfirmation(array $documents): void
307  {
308  $this->admin->requireEditable();
309  $this->container->tabs()->activateTab('documents');
310  $this->admin->setContent($this->admin->deleteDocumentsConfirmation(
311  $this->ctrlTo('getFormActionByClass', 'ignored'),
312  'deleteConfirmed',
313  'documents',
314  $documents
315  ));
316  }
317 
321  private function criterionErrorMessage($error): string
322  {
323  if (!is_string($error)) {
324  throw $error;
325  }
326 
327  return match ($error) {
328  ProvideDocument::CRITERION_ALREADY_EXISTS => $this->ui->txt('criterion_assignment_must_be_unique'),
329  ProvideDocument::CRITERION_WOULD_NEVER_MATCH => $this->ui->txt('criterion_assignment_cannot_match'),
330  default => $error,
331  };
332  }
333 
334  private function returnWithMessage(string $message, string $command): void
335  {
336  $this->ui->mainTemplate()->setOnScreenMessage('success', $this->ui->txt($message), true);
337  $this->ctrlTo('redirectByClass', $command);
338  }
339 
340  private function returnWithResult(Result $result, string $success_message, string $target): void
341  {
342  if ($result->isOk()) {
343  $this->ui->mainTemplate()->setOnScreenMessage('success', $this->ui->txt($success_message), true);
344  } else {
345  $this->ui->mainTemplate()->setOnScreenMessage('failure', $this->criterionErrorMessage($result->error()), true);
346  }
347 
348  $this->ctrlTo('redirectByClass', $target);
349  }
350 }
tab(string $cmd, string $label, bool $can_access=true)
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
$response
Definition: xapitoken.php:90
$url
Definition: shib_logout.php:63
Customizing of pimple-DIC for ILIAS.
Definition: Container.php:35
$path
Definition: ltiservices.php:30
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
returnWithResult(Result $result, string $success_message, string $target)
$GLOBALS["DIC"]
Definition: wac.php:30
error()
Get the encapsulated error.
__construct(private readonly string $parent_class, private readonly Config $config, private readonly Closure $after_document_deletion, ?Container $container=null)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:24