ILIAS  Release_4_1_x_branch Revision 61804
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilObjExercise.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once "classes/class.ilObject.php";
5 require_once "./Modules/Exercise/classes/class.ilFileDataExercise.php";
6 require_once "./Modules/Exercise/classes/class.ilExerciseMembers.php";
7 
19 class ilObjExercise extends ilObject
20 {
21  var $file_obj;
23  var $files;
24 
26  var $hour;
27  var $minutes;
28  var $day;
29  var $month;
30  var $year;
32 
39  function ilObjExercise($a_id = 0,$a_call_by_reference = true)
40  {
41  $this->setPassMode("all");
42  $this->type = "exc";
43  $this->ilObject($a_id,$a_call_by_reference);
44  }
45 
46  // SET, GET METHODS
47  function setDate($a_hour,$a_minutes,$a_day,$a_month,$a_year)
48  {
49  $this->hour = (int) $a_hour;
50  $this->minutes = (int) $a_minutes;
51  $this->day = (int) $a_day;
52  $this->month = (int) $a_month;
53  $this->year = (int) $a_year;
54  $this->timestamp = mktime($this->hour,$this->minutes,0,$this->month,$this->day,$this->year);
55  return true;
56  }
57  function getTimestamp()
58  {
59  return $this->timestamp;
60  }
61  function setTimestamp($a_timestamp)
62  {
63  $this->timestamp = $a_timestamp;
64  }
65  function setInstruction($a_instruction)
66  {
67  $this->instruction = $a_instruction;
68  }
69  function getInstruction()
70  {
71  return $this->instruction;
72  }
73 
79  function setPassMode($a_val)
80  {
81  $this->pass_mode = $a_val;
82  }
83 
89  function getPassMode()
90  {
91  return $this->pass_mode;
92  }
93 
99  function setPassNr($a_val)
100  {
101  $this->pass_nr = $a_val;
102  }
103 
109  function getPassNr()
110  {
111  return $this->pass_nr;
112  }
113 
119  function setShowSubmissions($a_val)
120  {
121  $this->show_submissions = $a_val;
122  }
123 
130  {
131  return $this->show_submissions;
132  }
133 
134 
135 /* function getFiles()
136  {
137  return $this->files;
138  }*/
139 
140  function checkDate()
141  {
142  return $this->hour == (int) date("H",$this->timestamp) and
143  $this->minutes == (int) date("i",$this->timestamp) and
144  $this->day == (int) date("d",$this->timestamp) and
145  $this->month == (int) date("m",$this->timestamp) and
146  $this->year == (int) date("Y",$this->timestamp);
147 
148  }
149 
153  function deliverFile($a_http_post_files, $a_ass_id, $user_id, $unzip = false)
154  {
155  global $ilDB;
156 
157  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
158  $storage = new ilFSStorageExercise($this->getId(), $a_ass_id);
159  $deliver_result = $storage->deliverFile($a_http_post_files, $user_id, $unzip);
160 //var_dump($deliver_result);
161  if ($deliver_result)
162  {
163  $next_id = $ilDB->nextId("exc_returned");
164  $query = sprintf("INSERT INTO exc_returned ".
165  "(returned_id, obj_id, user_id, filename, filetitle, mimetype, ts, ass_id) ".
166  "VALUES (%s, %s, %s, %s, %s, %s, %s, %s)",
167  $ilDB->quote($next_id, "integer"),
168  $ilDB->quote($this->getId(), "integer"),
169  $ilDB->quote($user_id, "integer"),
170  $ilDB->quote($deliver_result["fullname"], "text"),
171  $ilDB->quote($a_http_post_files["name"], "text"),
172  $ilDB->quote($deliver_result["mimetype"], "text"),
173  $ilDB->quote(ilUtil::now(), "timestamp"),
174  $ilDB->quote($a_ass_id, "integer")
175  );
176  $ilDB->manipulate($query);
177  if (!$this->members_obj->isAssigned($user_id))
178  {
179  $this->members_obj->assignMember($user_id);
180  }
181  ilExAssignment::updateStatusReturnedForUser($a_ass_id, $user_id, 1);
182  ilExerciseMembers::_writeReturned($this->getId(), $user_id, 1);
183  }
184  return true;
185  }
186 
190  function addUploadedFile($a_http_post_files, $unzipUploadedFile = false)
191  {
192  global $lng;
193  if ($unzipUploadedFile && preg_match("/zip/", $a_http_post_files["type"]) == 1)
194  {
195 
196  $this->processUploadedFile($a_http_post_files["tmp_name"], "storeUploadedFile", true);
197  return true;
198 
199 
200  }
201  else
202  {
203  $this->file_obj->storeUploadedFile($a_http_post_files, true);
204  return true;
205  }
206  }
207  function deleteFiles($a_files)
208  {
209  $this->file_obj->unlinkFiles($a_files);
210  }
211 
212  function saveData()
213  {
214  global $ilDB;
215 
216  // SAVE ONLY EXERCISE SPECIFIC DATA
217  /*$query = "INSERT INTO exc_data SET ".
218  "obj_id = ".$ilDB->quote($this->getId()).", ".
219  "instruction = ".$ilDB->quote($this->getInstruction()).", ".
220  "time_stamp = ".$ilDB->quote($this->getTimestamp());
221  $this->ilias->db->query($query);*/
222 
223  $ilDB->insert("exc_data", array(
224  "obj_id" => array("integer", $this->getId()),
225  "instruction" => array("clob", $this->getInstruction()),
226  "time_stamp" => array("integer", $this->getTimestamp()),
227  "pass_mode" => array("text", $this->getPassMode()),
228  "pass_nr" => array("text", $this->getPassNr()),
229  "show_submissions" => array("integer", (int) $this->getShowSubmissions())
230  ));
231  return true;
232  }
233 
241  public function cloneObject($a_target_id,$a_copy_id = 0)
242  {
243  global $ilDB;
244 
245  // Copy settings
246  $new_obj = parent::cloneObject($a_target_id,$a_copy_id);
247  $new_obj->setInstruction($this->getInstruction());
248  $new_obj->setTimestamp($this->getTimestamp());
249  $new_obj->setPassMode($this->getPassMode());
250  $new_obj->saveData();
251  $new_obj->setPassNr($this->getPassNr());
252  $new_obj->setShowSubmissions($this->getShowSubmissions());
253  $new_obj->update();
254 
255  // Copy assignments
256  include_once("./Modules/Exercise/classes/class.ilExAssignment.php");
257  ilExAssignment::cloneAssignmentsOfExercise($this->getId(), $new_obj->getId());
258  //$tmp_file_obj =& new ilFileDataExercise($this->getId());
259  //$tmp_file_obj->ilClone($new_obj->getId());
260  //unset($tmp_file_obj);
261 
262  // Copy learning progress settings
263  include_once('Services/Tracking/classes/class.ilLPObjSettings.php');
264  $obj_settings = new ilLPObjSettings($this->getId());
265  $obj_settings->cloneSettings($new_obj->getId());
266  unset($obj_settings);
267 
268  return $new_obj;
269  }
270 
277  function deleteDeliveredFiles($a_exc_id, $a_ass_id, $file_id_array, $user_id)
278  {
279  ilExAssignment::deleteDeliveredFiles($a_exc_id, $a_ass_id, $file_id_array, $user_id);
280 
281  // Finally update status 'returned' of member if no file exists
282  if(!count(ilExAssignment::getDeliveredFiles($a_exc_id, $a_ass_id, $user_id)))
283  {
284  ilExAssignment::updateStatusReturnedForUser($a_ass_id, $user_id, 0);
285  }
286  }
287 
293  function deliverReturnedFiles($user_id)
294  {
295  require_once "./Services/Utilities/classes/class.ilUtil.php";
296  }
297 
304  function delete()
305  {
306  global $ilDB;
307 
308  // always call parent delete function first!!
309  if (!parent::delete())
310  {
311  return false;
312  }
313  // put here course specific stuff
314  $ilDB->manipulate("DELETE FROM exc_data ".
315  "WHERE obj_id = ".$ilDB->quote($this->getId(), "integer"));
316 
317  //$this->ilias->db->query($query);
318 
319  //$this->file_obj->delete();
320  //$this->members_obj->delete();
321 
322  // remove all notifications
323  include_once "./Services/Notification/classes/class.ilNotification.php";
325 
326  return true;
327  }
328 
339  function notify($a_event,$a_ref_id,$a_node_id,$a_params = 0)
340  {
341  // object specific event handling
342 
343  parent::notify($a_event,$a_ref_id,$a_node_id,$a_params);
344  }
345 
346  function read()
347  {
348  global $ilDB;
349 
350  parent::read();
351 
352  $query = "SELECT * FROM exc_data ".
353  "WHERE obj_id = ".$ilDB->quote($this->getId(), "integer");
354 
355  $res = $ilDB->query($query);
356  while($row = $ilDB->fetchObject($res))
357  {
358  $this->setInstruction($row->instruction);
359  $this->setTimestamp($row->time_stamp);
360  $pm = ($row->pass_mode == "")
361  ? "all"
362  : $row->pass_mode;
363  $this->setPassMode($pm);
364  $this->setShowSubmissions($row->show_submissions);
365  if ($row->pass_mode == "nr")
366  {
367  $this->setPassNr($row->pass_nr);
368  }
369  }
370 
371  $this->members_obj = new ilExerciseMembers($this);
372 
373  // GET FILE ASSIGNED TO EXERCISE
374 // $this->file_obj = new ilFileDataExercise($this->getId());
375 // $this->files = $this->file_obj->getFiles();
376 
377  return true;
378  }
379 
380  function update()
381  {
382  global $ilDB;
383 
384  parent::update();
385 
386  /*$query = "UPDATE exc_data SET ".
387  "instruction = ".$ilDB->quote($this->getInstruction()).", ".
388  "time_stamp = ".$ilDB->quote($this->getTimestamp())." ".
389  "WHERE obj_id = ".$ilDB->quote($this->getId());
390  */
391 
392  if ($this->getPassMode() == "all")
393  {
394  $pass_nr = null;
395  }
396  else
397  {
398  $pass_nr = $this->getPassNr();
399  }
400 
401  $ilDB->update("exc_data", array(
402  "instruction" => array("clob", $this->getInstruction()),
403  "time_stamp" => array("integer", $this->getTimestamp()),
404  "pass_mode" => array("text", $this->getPassMode()),
405  "pass_nr" => array("integer", $this->getPassNr()),
406  "show_submissions" => array("integer", (int) $this->getShowSubmissions())
407  ), array(
408  "obj_id" => array("integer", $this->getId())
409  ));
410 
411  $this->updateAllUsersStatus();
412 
413  //$res = $this->ilias->db->query($query);
414 
415  #$this->members_obj->update();
416  return true;
417  }
418 
422  function sendAssignment($a_exc_id, $a_ass_id, $a_members)
423  {
424  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
425  $storage = new ilFSStorageExercise($a_exc_id, $a_ass_id);
426  $files = $storage->getFiles();
427 
428  if(count($files))
429  {
430  include_once "./classes/class.ilFileDataMail.php";
431 
432  $mfile_obj = new ilFileDataMail($_SESSION["AccountId"]);
433  foreach($files as $file)
434  {
435  $mfile_obj->copyAttachmentFile($file["fullpath"], $file["name"]);
436  $file_names[] = $file["name"];
437  }
438  }
439 
440  include_once "Services/Mail/classes/class.ilMail.php";
441 
442  $tmp_mail_obj = new ilMail($_SESSION["AccountId"]);
443  $message = $tmp_mail_obj->sendMail(
444  $this->__formatRecipients($a_members),"","",
445  $this->__formatSubject(), $this->__formatBody($a_ass_id),
446  count($file_names) ? $file_names : array(),array("normal"));
447 
448  unset($tmp_mail_obj);
449 
450  if(count($file_names))
451  {
452  $mfile_obj->unlinkFiles($file_names);
453  unset($mfile_obj);
454  }
455 
456 
457  // SET STATUS SENT FOR ALL RECIPIENTS
458  foreach($a_members as $member_id => $value)
459  {
460  ilExAssignment::updateStatusSentForUser($a_ass_id, $member_id, 1);
461  }
462 
463  return true;
464  }
465 
469  function _lookupStatusTime($exc_id, $member_id)
470  {
471 
472  global $ilDB, $lng;
473 
474  $q = "SELECT * ".
475  "FROM exc_members ".
476  "WHERE obj_id= ".$ilDB->quote($exc_id, "integer").
477  " AND usr_id= ".$ilDB->quote($member_id, "integer");
478 
479  $set = $ilDB->query($q);
480  if ($rec = $ilDB->fetchAssoc($set))
481  {
482  return ilUtil::getMySQLTimestamp($rec["status_time"]);
483  }
484  }
485 
486  // PRIVATE METHODS
487  function __formatBody($a_ass_id)
488  {
489  global $lng;
490 
491  include_once("./Modules/Exercise/classes/class.ilExAssignment.php");
492  $ass = new ilExAssignment($a_ass_id);
493 
494  $body = $ass->getInstruction();
495  $body .= "\n\n";
496  $body .= $lng->txt("exc_edit_until") . ": ".
497  ilFormat::formatDate(date("Y-m-d H:i:s",$ass->getDeadline()), "datetime", true);
498  $body .= "\n\n";
499  $body .= ILIAS_HTTP_PATH.
500  "/goto.php?target=".
501  $this->getType().
502  "_".$this->getRefId()."&client_id=".CLIENT_ID;
503 
504  return $body;
505  }
506 
507  function __formatSubject()
508  {
509  return $subject = $this->getTitle()." (".$this->getDescription().")";
510  }
511 
512  function __formatRecipients($a_members)
513  {
514  foreach($a_members as $member_id => $value)
515  {
516  $tmp_obj = ilObjectFactory::getInstanceByObjId($member_id);
517  $tmp_members[] = $tmp_obj->getLogin();
518 
519  unset($tmp_obj);
520  }
521 
522  return implode(',',$tmp_members ? $tmp_members : array());
523  }
524 
525  function _checkCondition($a_exc_id,$a_operator,$a_value,$a_usr_id = 0)
526  {
527  global $ilUser;
528 
529  $a_usr_id = $a_usr_id ? $a_usr_id : $ilUser->getId();
530 
531  switch($a_operator)
532  {
533  case 'passed':
534  if (ilExerciseMembers::_lookupStatus($a_exc_id, $a_usr_id) == "passed")
535  {
536  return true;
537  }
538  else
539  {
540  return false;
541  }
542  break;
543 
544  default:
545  return true;
546  }
547  return true;
548  }
549 
556  function processUploadedFile ($fileTmp, $storageMethod, $persistentErrorMessage,
557  $a_ass_id)
558  {
559  global $lng, $ilUser;
560 
561  // Create unzip-directory
562  $newDir = ilUtil::ilTempnam();
563  ilUtil::makeDir($newDir);
564 
565  include_once ("Services/Utilities/classes/class.ilFileUtils.php");
566 
567  try
568  {
569  $processDone = ilFileUtils::processZipFile($newDir,$fileTmp, false);
570  ilFileUtils::recursive_dirscan($newDir, $filearray);
571 
572  foreach ($filearray["file"] as $key => $filename)
573  {
574  $a_http_post_files["name"] = ilFileUtils::utf8_encode($filename);
575  $a_http_post_files["type"] = "other";
576  $a_http_post_files["tmp_name"] = $filearray["path"][$key]."/".$filename;
577  $a_http_post_files["error"] = 0;
578  $a_http_post_files["size"] = filesize($filearray["path"][$key]."/".$filename);
579 
580  if ($storageMethod == "deliverFile")
581  {
582  $this->$storageMethod($a_http_post_files, $a_ass_id, $ilUser->id, true);
583  }
584  else if ($storageMethod == "storeUploadedFile")
585  {
586  $this->file_obj->$storageMethod($a_http_post_files, true, true);
587  }
588  }
589  ilExerciseMembers::_writeReturned($this->getId(), $ilUser->id, 1);
590  ilUtil::sendSuccess($this->lng->txt("file_added"),$persistentErrorMessage);
591 
592  }
593  catch (ilFileUtilsException $e)
594  {
595  ilUtil::sendFailure($e->getMessage(), $persistentErrorMessage);
596  }
597 
598 
599  ilUtil::delDir($newDir);
600  return $processDone;
601 
602  }
603 
614  static function _fixFilename($a_filename)
615  {
616  $ex_pos = strrpos($a_filename, "/exercise/");
617  if ($ex_pos > 0)
618  {
619  $a_filename = CLIENT_DATA_DIR.substr($a_filename, $ex_pos);
620  }
621  return $a_filename;
622  }
623 
628  static function _fixFilenameArray($a_array)
629  {
630  if (is_array($a_array))
631  {
632  foreach ($a_array as $k => $v)
633  {
634  if ($v["filename"] != "")
635  {
636  $a_array[$k]["filename"] = ilObjExercise::_fixFilename($a_array[$k]["filename"]);
637  }
638  }
639  }
640 
641  return $a_array;
642  }
643 
647  function determinStatusOfUser($a_user_id = 0)
648  {
649  global $ilUser;
650 
651  if ($a_user_id == 0)
652  {
653  $a_user_id = $ilUser->getId();
654  }
655 
656  include_once("./Modules/Exercise/classes/class.ilExAssignment.php");
658 
659  $passed_all_mandatory = true;
660  $failed_a_mandatory = false;
661  $cnt_passed = 0;
662  $cnt_notgraded = 0;
663  $passed_at_least_one = false;
664 
665  foreach ($ass as $a)
666  {
667  $stat = ilExAssignment::lookupStatusOfUser($a["id"], $a_user_id);
668  if ($a["mandatory"] && ($stat == "failed" || $stat == "notgraded"))
669  {
670  $passed_all_mandatory = false;
671  }
672  if ($a["mandatory"] && ($stat == "failed"))
673  {
674  $failed_a_mandatory = true;
675  }
676  if ($stat == "passed")
677  {
678  $cnt_passed++;
679  }
680  if ($stat == "notgraded")
681  {
682  $cnt_notgraded++;
683  }
684  }
685 
686  if (count($ass) == 0)
687  {
688  $passed_all_mandatory = false;
689  }
690 
691  if ($this->getPassMode() != "nr")
692  {
693 //echo "5";
694  $overall_stat = "notgraded";
695  if ($failed_a_mandatory)
696  {
697 //echo "6";
698  $overall_stat = "failed";
699  }
700  else if ($passed_all_mandatory && $cnt_passed > 0)
701  {
702 //echo "7";
703  $overall_stat = "passed";
704  }
705  }
706  else
707  {
708 //echo "8";
709  $min_nr = $this->getPassNr();
710  $overall_stat = "notgraded";
711 //echo "*".$cnt_passed."*".$cnt_notgraded."*".$min_nr."*";
712  if ($failed_a_mandatory || ($cnt_passed + $cnt_notgraded < $min_nr))
713  {
714 //echo "9";
715  $overall_stat = "failed";
716  }
717  else if ($passed_all_mandatory && $cnt_passed >= $min_nr)
718  {
719 //echo "A";
720  $overall_stat = "passed";
721  }
722  }
723 
724  $ret = array(
725  "overall_status" => $overall_stat,
726  "failed_a_mandatory" => $failed_a_mandatory);
727 //echo "<br>p:".$cnt_passed.":ng:".$cnt_notgraded;
728 //var_dump($ret);
729  return $ret;
730  }
731 
735  function updateUserStatus($a_user_id = 0)
736  {
737  global $ilUser;
738 
739  if ($a_user_id == 0)
740  {
741  $a_user_id = $ilUser->getId();
742  }
743 
744  $st = $this->determinStatusOfUser($a_user_id);
745 
746  include_once("./Modules/Exercise/classes/class.ilExerciseMembers.php");
747  ilExerciseMembers::_writeStatus($this->getId(), $a_user_id,
748  $st["overall_status"]);
749  }
750 
755  {
756  if (!is_object($this->members_obj));
757  {
758  $this->members_obj = new ilExerciseMembers($this);
759  }
760 
761  $mems = $this->members_obj->getMembers();
762  foreach ($mems as $mem)
763  {
764  $this->updateUserStatus($mem);
765  }
766  }
767 
771  function exportGradesExcel()
772  {
773  include_once("./Modules/Exercise/classes/class.ilExAssignment.php");
775 
776  include_once "./Services/Excel/classes/class.ilExcelWriterAdapter.php";
777  $excelfile = ilUtil::ilTempnam();
778  $adapter = new ilExcelWriterAdapter($excelfile, FALSE);
779  $workbook = $adapter->getWorkbook();
780  $workbook->setVersion(8); // Use Excel97/2000 Format
781  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
782 
783  //
784  // status
785  //
786  $mainworksheet = $workbook->addWorksheet();
787 
788  // header row
789  $mainworksheet->writeString(0, 0, ilExcelUtils::_convert_text($this->lng->txt("name")));
790  $cnt = 1;
791  foreach ($ass_data as $ass)
792  {
793  $mainworksheet->writeString(0, $cnt, $cnt);
794  $cnt++;
795  }
796  $mainworksheet->writeString(0, $cnt, ilExcelUtils::_convert_text($this->lng->txt("exc_total_exc")));
797 
798  // data rows
799  $this->mem_obj = new ilExerciseMembers($this);
800  $getmems = $this->mem_obj->getMembers();
801  $mems = array();
802  foreach ($getmems as $user_id)
803  {
804  $mems[$user_id] = ilObjUser::_lookupName($user_id);
805  }
806  $mems = ilUtil::sortArray($mems, "lastname", "asc", false, true);
807 
808  $data = array();
809  $row_cnt = 1;
810  foreach ($mems as $user_id => $d)
811  {
812  $col_cnt = 1;
813 
814  // name
815  $mainworksheet->writeString($row_cnt, 0,
816  ilExcelUtils::_convert_text($d["lastname"].", ".$d["firstname"]." [".$d["login"]."]"));
817 
818  reset($ass_data);
819 
820  foreach ($ass_data as $ass)
821  {
822  $status = ilExAssignment::lookupStatusOfUser($ass["id"], $user_id);
823  $mainworksheet->writeString($row_cnt, $col_cnt, ilExcelUtils::_convert_text($this->lng->txt("exc_".$status)));
824  $col_cnt++;
825  }
826 
827  // total status
828  $status = ilExerciseMembers::_lookupStatus($this->getId(), $user_id);
829  $mainworksheet->writeString($row_cnt, $col_cnt, ilExcelUtils::_convert_text($this->lng->txt("exc_".$status)));
830 
831  $row_cnt++;
832  }
833 
834  //
835  // mark
836  //
837  $worksheet2 = $workbook->addWorksheet();
838 
839  // header row
840  $worksheet2->writeString(0, 0, ilExcelUtils::_convert_text($this->lng->txt("name")));
841  $cnt = 1;
842  foreach ($ass_data as $ass)
843  {
844  $worksheet2->writeString(0, $cnt, $cnt);
845  $cnt++;
846  }
847  $worksheet2->writeString(0, $cnt, ilExcelUtils::_convert_text($this->lng->txt("exc_total_exc")));
848 
849  // data rows
850  $data = array();
851  $row_cnt = 1;
852  reset($mems);
853  foreach ($mems as $user_id => $d)
854  {
855  $col_cnt = 1;
856  $d = ilObjUser::_lookupName($user_id);
857 
858  // name
859  $worksheet2->writeString($row_cnt, 0,
860  ilExcelUtils::_convert_text($d["lastname"].", ".$d["firstname"]." [".$d["login"]."]"));
861 
862  reset($ass_data);
863 
864  foreach ($ass_data as $ass)
865  {
866  $worksheet2->writeString($row_cnt, $col_cnt,
868  $col_cnt++;
869  }
870 
871  // total mark
872  include_once 'Services/Tracking/classes/class.ilLPMarks.php';
873  $worksheet2->writeString($row_cnt, $col_cnt,
875 
876  $row_cnt++;
877  }
878 
879 
880  $workbook->close();
881  $exc_name = ilUtil::getASCIIFilename(preg_replace("/\s/", "_", $this->getTitle()));
882  ilUtil::deliverFile($excelfile, $exc_name.".xls", "application/vnd.ms-excel");
883  }
884 
888  function sendFeedbackFileNotification($a_feedback_file, $a_user_id, $a_ass_id)
889  {
890  include_once("./Modules/Exercise/classes/class.ilExerciseMailNotification.php");
891  $not = new ilExerciseMailNotification();
893  $not->setAssignmentId($a_ass_id);
894  $not->setRefId($this->getRefId());
895  $not->setRecipients(array($a_user_id));
896  $not->send();
897  }
898 
899 }
900 ?>