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