ILIAS  release_8 Revision v8.24
AccessFileUploadAnswer.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
27use ilObjTest;
28use ilObject;
29use ilSession;
31use ilTestAccess;
32use Closure;
33
35{
39 private Closure $object_id_of_test_id;
41 private Closure $references_of;
43 private Closure $session;
45 private Closure $checkResultsAccess;
47
54 public function __construct(
57 $object_id_of_test_id = [ilObjTest::class, '_getObjectIDFromTestID'],
58 $references_of = [ilObject::class, '_getAllReferences'],
59 $session = [ilSession::class, 'get'],
60 callable $checkResultsAccess = null,
61 Incident $incident = null
62 ) {
63 $this->container = $container;
64 $this->readable = $readable;
65 $this->incident = $incident ?? new Incident();
66 $this->object_id_of_test_id = Closure::fromCallable($object_id_of_test_id);
67 $this->references_of = Closure::fromCallable($references_of);
68 $this->session = Closure::fromCallable($session);
69 $checkResultsAccess = $checkResultsAccess ?? static function (int $reference, int $test_id, int $active_id): bool {
70 $access = new ilTestAccess($reference, $test_id);
71 return $access->checkResultsAccessForActiveId($active_id);
72 };
73 $this->checkResultsAccess = Closure::fromCallable($checkResultsAccess);
74 }
75
76 public function isPermitted(string $path): Result
77 {
78 $path_and_test = $this->pathAndTestId($path);
79
80 if (!$path_and_test) {
81 return new Error('Not a file upload path of test answers.');
82 }
83 if (!$path_and_test['test']) {
84 return new Ok(false);
85 }
86
87 $object_id = (int) ($this->object_id_of_test_id)($path_and_test['test']);
88 if (!$object_id) {
89 return new Ok(false);
90 }
91
92 $references = ($this->references_of)($object_id);
93
94 return new Ok($this->readable->references($references) && $this->roleBasedCheck($path_and_test['test'], $references, $path_and_test['path']));
95 }
96
97 private function isAnonymous(): bool
98 {
99 return $this->container->user()->isAnonymous() || !$this->container->user()->getId();
100 }
101
102 private function accessCodeOk(string $file, int $test_id): bool
103 {
104 $code = ($this->session)(ilTestSession::ACCESS_CODE_SESSION_INDEX)[$test_id] ?? false;
105
106 return $code && $this->userDidUpload($test_id, $file, $code);
107 }
108
109 private function userDidUpload(int $test_id, string $file, string $code = null): bool
110 {
111 $where = [
112 'active_id = active_fi',
113 'user_fi = %s',
114 'value1 = %s',
115 'anonymous_id ' . (null === $code ? 'IS' : '=') . ' %s',
116 'test_fi = %s',
117 ];
118
119 $result = $this->container->database()->queryF(
120 'SELECT 1 FROM tst_solutions WHERE EXISTS (SELECT 1 FROM tst_active WHERE ' . implode(' AND ', $where) . ')',
121 ['integer', 'text', 'text', 'integer'],
122 [$this->container->user()->getId(), $file, $code, $test_id]
123 );
124
125 return (bool) $this->container->database()->numRows($result);
126 }
127
128 private function activeIdOfFile(string $file, int $test): ?int
129 {
130 $is_upload_question = 'EXISTS (SELECT 1 FROM qpl_qst_type INNER JOIN qpl_questions ON question_type_id = question_type_fi WHERE type_tag = %s AND tst_solutions.question_fi = qpl_questions.question_id)';
131 $is_in_test = 'EXISTS (SELECT 1 FROM tst_active WHERE test_fi = %s AND active_id = active_fi)';
132
133 $result = $this->container->database()->queryF(
134 "SELECT active_fi, value1 FROM tst_solutions WHERE $is_upload_question AND $is_in_test",
135 ['text', 'integer'],
136 ['assFileUpload', $test]
137 );
138
139 while (($row = $this->container->database()->fetchAssoc($result))) {
140 if ($row['value1'] === $file) {
141 return (int) $row['active_fi'];
142 }
143 }
144
145 return null;
146 }
147
155 private function roleBasedCheck(int $test_id, array $references, string $file): bool
156 {
157 return $this->isAnonymous() ? $this->accessCodeOk($file, $test_id) : $this->canAccessResults($test_id, $references, $file) || $this->userDidUpload($test_id, $file);
158 }
159
167 private function canAccessResults(int $test_id, array $references, string $file): bool
168 {
169 $active_id = $this->activeIdOfFile($file, $test_id);
170 if (!$active_id) {
171 return false;
172 }
173
174 return $this->incident->any(fn (int $reference): bool => (
175 ($this->checkResultsAccess)($reference, $test_id, $active_id)
176 ), $references);
177 }
178
184 private function pathAndTestId(string $path): ?array
185 {
186 $results = [];
187 if (!preg_match(':/assessment/tst_(\d+)/.*/([^/]+)$:', $path, $results)) {
188 return null;
189 }
190
191 return [
192 'test' => (int) $results[1],
193 'path' => $results[2],
194 ];
195 }
196}
Customizing of pimple-DIC for ILIAS.
Definition: Container.php:32
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Error.php:18
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Ok.php:17
canAccessResults(int $test_id, array $references, string $file)
__construct(Container $container, Readable $readable, $object_id_of_test_id=[ilObjTest::class, '_getObjectIDFromTestID'], $references_of=[ilObject::class, '_getAllReferences'], $session=[ilSession::class, 'get'], callable $checkResultsAccess=null, Incident $incident=null)
userDidUpload(int $test_id, string $file, string $code=null)
roleBasedCheck(int $test_id, array $references, string $file)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Result.php:15
$path
Definition: ltiservices.php:32
$results