19 declare(strict_types=1);
57 $object_id_of_test_id = [ilObjTest::class,
'_getObjectIDFromTestID'],
58 $references_of = [ilObject::class,
'_getAllReferences'],
59 $session = [ilSession::class,
'get'],
60 ?callable $checkResultsAccess =
null,
63 $this->incident = $incident ??
new Incident();
64 $this->object_id_of_test_id = Closure::fromCallable($object_id_of_test_id);
65 $this->references_of = Closure::fromCallable($references_of);
66 $this->session = Closure::fromCallable($session);
67 $checkResultsAccess = $checkResultsAccess ??
static function (
int $reference,
int $test_id,
int $active_id):
bool {
69 return $access->checkResultsAccessForActiveId($active_id, $test_id);
71 $this->checkResultsAccess = Closure::fromCallable($checkResultsAccess);
78 if (!$path_and_test) {
79 return new Error(
'Not a file upload path of test answers.');
81 if (!$path_and_test[
'test']) {
85 $object_id = (
int) ($this->object_id_of_test_id)($path_and_test[
'test']);
92 return new Ok($this->readable->references($references) && $this->
roleBasedCheck($path_and_test[
'test'], $references, $path_and_test[
'path']));
97 return $this->
user->isAnonymous() || !$this->
user->getId();
104 return $code && $this->
userDidUpload($test_id, $file, $code);
110 'active_id = active_fi',
113 'anonymous_id ' . (
null === $code ?
'IS' :
'=') .
' %s',
118 'SELECT 1 FROM tst_solutions WHERE EXISTS (SELECT 1 FROM tst_active WHERE ' . implode(
' AND ', $where) .
')',
119 [
'integer',
'text',
'text',
'integer'],
120 [$this->
user->getId(), $file, $code, $test_id]
123 return (
bool) $this->
database->numRows($result);
128 $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)';
129 $is_in_test =
'EXISTS (SELECT 1 FROM tst_active WHERE test_fi = %s AND active_id = active_fi)';
132 "SELECT active_fi, value1 FROM tst_solutions WHERE $is_upload_question AND $is_in_test",
134 [
'assFileUpload', $test]
137 while (($row = $this->
database->fetchAssoc($result))) {
138 if ($row[
'value1'] === $file) {
139 return (
int) $row[
'active_fi'];
153 private function roleBasedCheck(
int $test_id, array $references,
string $file): bool
172 return $this->incident->any(fn(
int $reference):
bool => (
173 ($this->checkResultsAccess)($reference, $test_id, $active_id)
185 if (!preg_match(
':/assessment/tst_(\d+)/.*/([^/]+)$:', $path,
$results)) {
readonly Closure $object_id_of_test_id
readonly Incident $incident
readonly Closure $session
const ACCESS_CODE_SESSION_INDEX
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
readonly Closure $references_of
__construct(private readonly ilObjUser $user, private readonly ilDBInterface $database, private readonly 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)
isPermitted(string $path)
roleBasedCheck(int $test_id, array $references, string $file)
A result encapsulates a value or an error and simplifies the handling of those.
readonly Closure $checkResultsAccess
pathAndTestId(string $path)
activeIdOfFile(string $file, int $test)
accessCodeOk(string $file, int $test_id)
userDidUpload(int $test_id, string $file, ?string $code=null)
canAccessResults(int $test_id, array $references, string $file)