ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilExPeerReview.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
11{
15 protected $db;
16
20 protected $user;
21
22 protected $assignment; // [$a_assignment]
23 protected $assignment_id; // [int]
24
25 public function __construct(ilExAssignment $a_assignment)
26 {
27 global $DIC;
28
29 $this->db = $DIC->database();
30 $this->user = $DIC->user();
31 $this->assignment = $a_assignment;
32 $this->assignment_id = $a_assignment->getId();
33 }
34
35 public function hasPeerReviewGroups()
36 {
38
39 $set = $ilDB->query("SELECT count(*) cnt" .
40 " FROM exc_assignment_peer" .
41 " WHERE ass_id = " . $ilDB->quote($this->assignment_id, "integer"));
42 $cnt = $ilDB->fetchAssoc($set);
43 return (bool) $cnt["cnt"];
44 }
45
46 protected function getValidPeerReviewUsers()
47 {
49
50 $user_ids = array();
51
52 // returned / assigned ?!
53 $set = $ilDB->query("SELECT DISTINCT(user_id)" .
54 " FROM exc_returned" .
55 " WHERE ass_id = " . $ilDB->quote($this->assignment_id, "integer") .
56 " AND (filename IS NOT NULL OR atext IS NOT NULL)");
57 while ($row = $ilDB->fetchAssoc($set)) {
58 $user_ids[] = $row["user_id"];
59 }
60
61 return $user_ids;
62 }
63
64 protected function initPeerReviews()
65 {
67
68 // see #22246
69 if (!$this->assignment->afterDeadlineStrict()) {
70 return false;
71 }
72
73 if (!$this->hasPeerReviewGroups()) {
74 $user_ids = $this->getValidPeerReviewUsers();
75
76 include_once("./Modules/Exercise/PeerReview/class.ExcPeerReviewDistribution.php");
77 $distribution = new \ILIAS\Exercise\PeerReview\ExcPeerReviewDistribution($user_ids, $this->assignment->getPeerReviewMin());
78
79 foreach ($user_ids as $rater_id) {
80 foreach ($distribution->getPeersOfRater($rater_id) as $peer_id) {
81 $ilDB->manipulate("INSERT INTO exc_assignment_peer" .
82 " (ass_id, giver_id, peer_id)" .
83 " VALUES (" . $ilDB->quote($this->assignment_id, "integer") .
84 ", " . $ilDB->quote($rater_id, "integer") .
85 ", " . $ilDB->quote($peer_id, "integer") . ")");
86 }
87 }
88 }
89 return true;
90 }
91
92 public function resetPeerReviews()
93 {
95
96 $all = array();
97
98 if ($this->hasPeerReviewGroups()) {
99 foreach ($this->getAllPeerReviews(false) as $peer_id => $reviews) {
100 foreach (array_keys($reviews) as $giver_id) {
101 $all[] = $giver_id;
102
103 foreach ($this->assignment->getPeerReviewCriteriaCatalogueItems() as $crit) {
104 $crit->setPeerReviewContext($this->assignment, $giver_id, $peer_id);
105 $crit->resetReview();
106 }
107 }
108 }
109
110 // peer groups
111 $ilDB->manipulate("DELETE FROM exc_assignment_peer" .
112 " WHERE ass_id = " . $ilDB->quote($this->assignment_id, "integer"));
113 }
114
115 return $all;
116 }
117
118 public function validatePeerReviewGroups()
119 {
120 if ($this->hasPeerReviewGroups()) {
121 include_once "./Modules/Exercise/classes/class.ilExerciseMembers.php";
122 $all_exc = ilExerciseMembers::_getMembers($this->assignment->getExerciseId());
123 $all_valid = $this->getValidPeerReviewUsers(); // only returned
124
125 $peer_ids = $invalid_peer_ids = $invalid_giver_ids = $all_reviews = array();
126 foreach ($this->getAllPeerReviews(false) as $peer_id => $reviews) {
127 $peer_ids[] = $peer_id;
128
129 if (!in_array($peer_id, $all_valid) ||
130 !in_array($peer_id, $all_exc)) {
131 $invalid_peer_ids[] = $peer_id;
132 }
133 foreach ($reviews as $giver_id => $valid) {
134 if (!in_array($giver_id, $all_valid) ||
135 !in_array($peer_id, $all_exc)) {
136 $invalid_giver_ids[] = $giver_id;
137 } else {
138 $all_reviews[$peer_id][$giver_id] = $valid;
139 }
140 }
141 }
142 $invalid_giver_ids = array_unique($invalid_giver_ids);
143
144 $missing_user_ids = array();
145 foreach ($all_valid as $user_id) {
146 // a missing peer is also a missing giver
147 if (!in_array($user_id, $peer_ids)) {
148 $missing_user_ids[] = $user_id;
149 }
150 }
151
152 $not_returned_ids = array();
153 foreach ($all_exc as $user_id) {
154 if (!in_array($user_id, $all_valid)) {
155 $not_returned_ids[] = $user_id;
156 }
157 }
158
159 return array(
160 "invalid" => (sizeof($missing_user_ids) ||
161 sizeof($invalid_peer_ids) ||
162 sizeof($invalid_giver_ids)),
163 "missing_user_ids" => $missing_user_ids,
164 "not_returned_ids" => $not_returned_ids,
165 "invalid_peer_ids" => $invalid_peer_ids,
166 "invalid_giver_ids" => $invalid_giver_ids,
167 "reviews" => $all_reviews);
168 }
169 }
170
171 public function getPeerReviewValues($a_giver_id, $a_peer_id)
172 {
173 $peer = null;
174 foreach ($this->getPeerReviewsByGiver($a_giver_id) as $item) {
175 if ($item["peer_id"] == $a_peer_id) {
176 $peer = $item;
177 }
178 }
179 if (!$peer) {
180 return;
181 }
182 $data = $peer["pcomment"];
183 if ($data) {
184 $items = @unserialize($data);
185 if (!is_array($items)) {
186 // v1 - pcomment == text
187 $items = array("text" => $data);
188 }
189 return $items;
190 }
191 }
192
193 public function getPeerReviewsByGiver($a_user_id)
194 {
196
197 $res = array();
198
199 if ($this->initPeerReviews()) {
200 $idx = 0;
201 $set = $ilDB->query("SELECT *" .
202 " FROM exc_assignment_peer" .
203 " WHERE giver_id = " . $ilDB->quote($a_user_id, "integer") .
204 " AND ass_id = " . $ilDB->quote($this->assignment_id, "integer") .
205 " ORDER BY peer_id");
206 while ($row = $ilDB->fetchAssoc($set)) {
207 $row["seq"] = ++$idx;
208 $res[] = $row;
209 }
210 }
211
212 return $res;
213 }
214
215 public function getPeerMaskedId($a_giver_id, $a_peer_id)
216 {
217 foreach ($this->getPeerReviewsByGiver($a_giver_id) as $idx => $peer) {
218 if ($peer["peer_id"] == $a_peer_id) {
219 return $peer["seq"];
220 }
221 }
222 }
223
224 protected function validatePeerReview(array $a_data)
225 {
226 $all_empty = true;
227
228 // see getPeerReviewValues()
229 $values = null;
230 $data = $a_data["pcomment"];
231 if ($data) {
232 $values = @unserialize($data);
233 if (!is_array($values)) {
234 // v1 - pcomment == text
235 $values = array("text" => $data);
236 }
237 }
238
239 /* #18491 - values can be empty, text is optional (rating/file values are handled internally in criteria)
240 if(!$values)
241 {
242 return false;
243 }
244 */
245
246 foreach ($this->assignment->getPeerReviewCriteriaCatalogueItems() as $crit) {
247 $crit_id = $crit->getId()
248 ? $crit->getId()
249 : $crit->getType();
250 $crit->setPeerReviewContext(
251 $this->assignment,
252 $a_data["giver_id"],
253 $a_data["peer_id"]
254 );
255 if (!$crit->validate($values[$crit_id])) {
256 return false;
257 }
258 if ($crit->hasValue($values[$crit_id])) {
259 $all_empty = false;
260 }
261 }
262
263 return !$all_empty;
264 }
265
266 public function getPeerReviewsByPeerId($a_user_id, $a_only_valid = false)
267 {
269
270 $res = array();
271
272 $idx = 0;
273 $set = $ilDB->query("SELECT *" .
274 " FROM exc_assignment_peer" .
275 " WHERE peer_id = " . $ilDB->quote($a_user_id, "integer") .
276 " AND ass_id = " . $ilDB->quote($this->assignment_id, "integer") .
277 " ORDER BY peer_id");
278 while ($row = $ilDB->fetchAssoc($set)) {
279 if (!$a_only_valid ||
280 $this->validatePeerReview($row)) {
281 // this would be correct but rather senseless
282 // $row["seq"] = $this->getPeerMaskedId($row["giver_id"], $a_user_id);
283 $row["seq"] = ++$idx;
284 $res[] = $row;
285 }
286 }
287
288 return $res;
289 }
290
291 public function getAllPeerReviews($a_only_valid = true)
292 {
294
295 $res = array();
296
297 $set = $ilDB->query("SELECT *" .
298 " FROM exc_assignment_peer" .
299 " WHERE ass_id = " . $ilDB->quote($this->assignment_id, "integer") .
300 " ORDER BY peer_id");
301 while ($row = $ilDB->fetchAssoc($set)) {
303 if (!$a_only_valid ||
304 $valid) {
305 $res[$row["peer_id"]][$row["giver_id"]] = $valid;
306 }
307 }
308
309 return $res;
310 }
311
312 public function hasPeerReviewAccess($a_peer_id)
313 {
316
317 $set = $ilDB->query("SELECT ass_id" .
318 " FROM exc_assignment_peer" .
319 " WHERE giver_id = " . $ilDB->quote($ilUser->getId(), "integer") .
320 " AND peer_id = " . $ilDB->quote($a_peer_id, "integer") .
321 " AND ass_id = " . $ilDB->quote($this->assignment_id, "integer"));
322 $row = $ilDB->fetchAssoc($set);
323 return (bool) $row["ass_id"];
324 }
325
326 public function updatePeerReviewTimestamp($a_peer_id)
327 {
330
331 $ilDB->manipulate("UPDATE exc_assignment_peer" .
332 " SET tstamp = " . $ilDB->quote(ilUtil::now(), "timestamp") .
333 " WHERE giver_id = " . $ilDB->quote($ilUser->getId(), "integer") .
334 " AND peer_id = " . $ilDB->quote($a_peer_id, "integer") .
335 " AND ass_id = " . $ilDB->quote($this->assignment_id, "integer"));
336 }
337
338 public function updatePeerReview($a_peer_id, array $a_values)
339 {
342
343 $sql = "UPDATE exc_assignment_peer" .
344 " SET tstamp = " . $ilDB->quote(ilUtil::now(), "timestamp") .
345 ",pcomment = " . $ilDB->quote(serialize($a_values), "text") .
346 " WHERE giver_id = " . $ilDB->quote($ilUser->getId(), "integer") .
347 " AND peer_id = " . $ilDB->quote($a_peer_id, "integer") .
348 " AND ass_id = " . $ilDB->quote($this->assignment_id, "integer");
349
350 $ilDB->manipulate($sql);
351 }
352
353 public function countGivenFeedback($a_validate = true, $a_user_id = null)
354 {
357
358 if (!$a_user_id) {
359 $a_user_id = $ilUser->getId();
360 }
361
362 $cnt = 0;
363
364 include_once './Services/Rating/classes/class.ilRating.php';
365
366 $set = $ilDB->query("SELECT *" .
367 " FROM exc_assignment_peer" .
368 " WHERE ass_id = " . $ilDB->quote($this->assignment_id, "integer") .
369 " AND giver_id = " . $ilDB->quote($a_user_id, "integer"));
370 while ($row = $ilDB->fetchAssoc($set)) {
371 if (!(bool) $a_validate ||
372 $this->validatePeerReview($row)) {
373 $cnt++;
374 }
375 }
376
377 return $cnt;
378 }
379
380 protected function getMaxPossibleFeedbacks()
381 {
383
384 // check if number of returned assignments is lower than assignment peer min
385 $set = $ilDB->query("SELECT COUNT(DISTINCT(user_id)) cnt" .
386 " FROM exc_returned" .
387 " WHERE ass_id = " . $ilDB->quote($this->assignment_id, "integer"));
388 $cnt = $ilDB->fetchAssoc($set);
389 $cnt = (int) $cnt["cnt"];
390 return $cnt - 1;
391 }
392
394 {
395 $max = $this->getMaxPossibleFeedbacks();
396
397 // #16160 - forever alone
398 if (!$max) {
399 return;
400 }
401
402 // are all required or just 1?
403 if (!$this->assignment->getPeerReviewSimpleUnlock()) {
404 $needed = $this->assignment->getPeerReviewMin();
405 } else {
406 $needed = 1;
407 }
408
409 // there could be less participants than stated in the min required setting
410 $min = min($max, $needed);
411
412 return max(0, $min - $this->countGivenFeedback());
413 }
414
415 public function isFeedbackValidForPassed($a_user_id)
416 {
417 // peer feedback is not required for passing
418 if ($this->assignment->getPeerReviewValid() == ilExAssignment::PEER_REVIEW_VALID_NONE) {
419 return true;
420 }
421
422 // #16227 - no processing before reaching the peer review period
423 if (!$this->assignment->afterDeadlineStrict()) {
424 return false;
425 }
426
427 // forever alone - should be valid
428 $max = $this->getMaxPossibleFeedbacks();
429 if (!$max) {
430 return true;
431 }
432
433 $no_of_feedbacks = $this->countGivenFeedback(true, $a_user_id);
434
435 switch ($this->assignment->getPeerReviewValid()) {
437 return (bool) $no_of_feedbacks;
438
440 // there could be less participants than stated in the min required setting
441 $min = min($max, $this->assignment->getPeerReviewMin());
442
443 return (($min - $no_of_feedbacks) < 1);
444 }
445 }
446
447 public static function lookupGiversWithPendingFeedback($a_ass_id)
448 {
449 global $DIC;
450
451 $ilDB = $DIC->database();
452 $user_ids = array();
453
454 $set = $ilDB->query(
455 "SELECT DISTINCT(giver_id) FROM exc_assignment_peer " .
456 " WHERE ass_id = " . $ilDB->quote($a_ass_id, "integer") .
457 " AND tstamp is NULL"
458 );
459
460 while ($row = $ilDB->fetchAssoc($set)) {
461 array_push($user_ids, $row["giver_id"]);
462 }
463
464 return $user_ids;
465 }
466}
user()
Definition: user.php:4
An exception for terminatinating execution or to throw for unit testing.
Exercise assignment.
getId()
Get assignment id.
Exercise peer review.
countGivenFeedback($a_validate=true, $a_user_id=null)
hasPeerReviewAccess($a_peer_id)
getAllPeerReviews($a_only_valid=true)
isFeedbackValidForPassed($a_user_id)
updatePeerReview($a_peer_id, array $a_values)
getPeerReviewsByGiver($a_user_id)
__construct(ilExAssignment $a_assignment)
getPeerReviewsByPeerId($a_user_id, $a_only_valid=false)
static lookupGiversWithPendingFeedback($a_ass_id)
validatePeerReview(array $a_data)
updatePeerReviewTimestamp($a_peer_id)
getPeerMaskedId($a_giver_id, $a_peer_id)
getPeerReviewValues($a_giver_id, $a_peer_id)
static _getMembers($a_obj_id)
static now()
Return current timestamp in Y-m-d H:i:s format.
$valid
$row
global $DIC
Definition: saml.php:7
foreach($_POST as $key=> $value) $res
global $ilDB
$values
$ilUser
Definition: imgupload.php:18
$data
Definition: bench.php:6