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  {
37  $ilDB = $this->db;
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  {
48  $ilDB = $this->db;
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  {
66  $ilDB = $this->db;
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  {
94  $ilDB = $this->db;
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  {
195  $ilDB = $this->db;
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  {
268  $ilDB = $this->db;
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  {
293  $ilDB = $this->db;
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)) {
302  $valid = $this->validatePeerReview($row);
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  {
314  $ilDB = $this->db;
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  {
328  $ilDB = $this->db;
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  {
340  $ilDB = $this->db;
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  {
355  $ilDB = $this->db;
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  {
382  $ilDB = $this->db;
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 }
Exercise assignment.
global $DIC
Definition: saml.php:7
updatePeerReview($a_peer_id, array $a_values)
getId()
Get assignment id.
countGivenFeedback($a_validate=true, $a_user_id=null)
$valid
isFeedbackValidForPassed($a_user_id)
static now()
Return current timestamp in Y-m-d H:i:s format.
user()
Definition: user.php:4
hasPeerReviewAccess($a_peer_id)
getPeerMaskedId($a_giver_id, $a_peer_id)
getAllPeerReviews($a_only_valid=true)
Exercise peer review.
updatePeerReviewTimestamp($a_peer_id)
foreach($_POST as $key=> $value) $res
static lookupGiversWithPendingFeedback($a_ass_id)
$values
validatePeerReview(array $a_data)
$ilUser
Definition: imgupload.php:18
getPeerReviewsByGiver($a_user_id)
$row
global $ilDB
getPeerReviewsByPeerId($a_user_id, $a_only_valid=false)
getPeerReviewValues($a_giver_id, $a_peer_id)
static _getMembers($a_obj_id)
$data
Definition: bench.php:6
__construct(ilExAssignment $a_assignment)