ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
AccessFileUploadAnswer.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
27 use ilObjTest;
28 use ilObject;
29 use ilSession;
30 use ilTestSession;
31 use ilTestAccess;
32 use Closure;
33 
35 {
37  private $container;
39  private $readable;
43  private $references_of;
45  private $session;
49  private $incident;
50 
60  public function __construct(
63  $object_id_of_test_id = [ilObjTest::class, '_getObjectIDFromTestID'],
64  $references_of = [ilObject::class, '_getAllReferences'],
65  $session = [ilSession::class, 'get'],
66  callable $checkResultsAccess = null,
67  Incident $incident = null
68  ) {
69  $this->container = $container;
70  $this->readable = $readable;
71  $this->incident = $incident ?? new Incident();
72  $this->object_id_of_test_id = Closure::fromCallable($object_id_of_test_id);
73  $this->references_of = Closure::fromCallable($references_of);
74  $this->session = Closure::fromCallable($session);
75  $this->checkResultsAccess = $checkResultsAccess ?? static function (int $reference, int $test_id, int $active_id): bool {
76  $access = new ilTestAccess($reference, $test_id);
77  return $access->checkResultsAccessForActiveId($active_id);
78  };
79  }
80 
81  public function isPermitted(string $path): Result
82  {
83  $path_and_test = $this->pathAndTestId($path);
84 
85  if (!$path_and_test) {
86  return new Error('Not a file upload path of test answers.');
87  }
88  if (!$path_and_test['test']) {
89  return new Ok(false);
90  }
91 
92  $object_id = (int) ($this->object_id_of_test_id)($path_and_test['test']);
93  if (!$object_id) {
94  return new Ok(false);
95  }
96 
97  $references = array_map('intval', ($this->references_of)($object_id));
98 
99  return new Ok($this->readable->references($references) && $this->roleBasedCheck($path_and_test['test'], $references, $path_and_test['path']));
100  }
101 
102  private function isAnonymous() : bool
103  {
104  return $this->container->user()->isAnonymous() || !$this->container->user()->getId();
105  }
106 
107  private function accessCodeOk(string $file, int $test_id) : bool
108  {
109  $code = ($this->session)(ilTestSession::ACCESS_CODE_SESSION_INDEX)[$test_id] ?? false;
110 
111  return $code && $this->userDidUpload($test_id, $file, $code);
112  }
113 
114  private function userDidUpload(int $test_id, string $file, string $code = null) : bool
115  {
116  $where = [
117  'active_id = active_fi',
118  'user_fi = %s',
119  'value1 = %s',
120  'anonymous_id ' . (null === $code ? 'IS' : '=') . ' %s',
121  'test_fi = %s',
122  ];
123 
124  $result = $this->container->database()->queryF(
125  'SELECT 1 FROM tst_solutions WHERE EXISTS (SELECT 1 FROM tst_active WHERE ' . implode(' AND ', $where) . ')',
126  ['integer', 'text', 'text', 'integer'],
127  [$this->container->user()->getId(), $file, $code, $test_id]
128  );
129 
130  return (bool) $this->container->database()->numRows($result);
131  }
132 
133  private function activeIdOfFile(string $file, int $test) : ?int
134  {
135  $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)';
136  $is_in_test = 'EXISTS (SELECT 1 FROM tst_active WHERE test_fi = %s AND active_id = active_fi)';
137 
138  $result = $this->container->database()->queryF(
139  "SELECT active_fi, value1 FROM tst_solutions WHERE $is_upload_question AND $is_in_test",
140  ['text', 'integer'],
141  ['assFileUpload', $test]
142  );
143 
144  while (($row = $this->container->database()->fetchAssoc($result))) {
145  if ($row['value1'] === $file) {
146  return (int) $row['active_fi'];
147  }
148  }
149 
150  return null;
151  }
152 
160  private function roleBasedCheck(int $test_id, array $references, string $file) : bool
161  {
162  return $this->isAnonymous() ? $this->accessCodeOk($file, $test_id) : $this->canAccessResults($test_id, $references, $file) || $this->userDidUpload($test_id, $file);
163  }
164 
172  private function canAccessResults(int $test_id, array $references, string $file) : bool
173  {
174  $active_id = $this->activeIdOfFile($file, $test_id);
175  if (!$active_id) {
176  return false;
177  }
178 
179  return $this->incident->any(function (int $reference) use ($test_id, $active_id): bool {
180  return ($this->checkResultsAccess)($reference, $test_id, $active_id);
181  }, $references);
182  }
183 
189  private function pathAndTestId(string $path) : ?array
190  {
191  $results = [];
192  if (!preg_match(':/assessment/tst_(\d+)/.*/([^/]+)$:', $path, $results)) {
193  return null;
194  }
195 
196  return [
197  'test' => (int) $results[1],
198  'path' => $results[2],
199  ];
200  }
201 }
$result
__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)
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Result.php:11
Customizing of pimple-DIC for ILIAS.
Definition: Container.php:18
canAccessResults(int $test_id, array $references, string $file)
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Ok.php:13
$results
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Error.php:13
roleBasedCheck(int $test_id, array $references, string $file)
userDidUpload(int $test_id, string $file, string $code=null)
$test
Definition: Utf8Test.php:84