diff --git a/main/dropbox/dropbox_class.inc.php b/main/dropbox/dropbox_class.inc.php index f957a8be05..453a5f974c 100755 --- a/main/dropbox/dropbox_class.inc.php +++ b/main/dropbox/dropbox_class.inc.php @@ -57,7 +57,7 @@ class Dropbox_Work public $feedback; /** - * Constructor calls private functions to create a new work or retreive an existing work from DB + * Constructor calls private functions to create a new work or retrieve an existing work from DB * depending on the number of parameters. * * @param int $arg1 @@ -171,7 +171,7 @@ class Dropbox_Work } /** - * private function creating existing object by retreiving info from db. + * private function creating existing object by retrieving info from db. * * @param int $id */ @@ -263,7 +263,7 @@ class Dropbox_SentWork extends Dropbox_Work public $recipients; //array of ['id']['name'] arrays /** - * Constructor calls private functions to create a new work or retreive an existing work from DB + * Constructor calls private functions to create a new work or retrieve an existing work from DB * depending on the number of parameters. * * @param int $arg1 @@ -310,8 +310,8 @@ class Dropbox_SentWork extends Dropbox_Work $course_id = api_get_course_int_id(); - // Do sanity checks on recipient_ids array & property fillin - // The sanity check for ex-coursemembers is already done in base constructor + // Do sanity checks on recipient_ids array & property filling + // The sanity check for ex-course members is already done in base constructor $uploader_id = (int) $uploader_id; $justSubmit = false; @@ -386,7 +386,7 @@ class Dropbox_SentWork extends Dropbox_Work } /** - * private function creating existing object by retreiving info from db. + * private function creating existing object by retrieving info from db. * * @param int $id */ @@ -440,10 +440,22 @@ class Dropbox_Person * @param int $userId * @param bool $isCourseAdmin * @param bool $isCourseTutor + * @param int $courseId + * @param int $sessionId */ - public function __construct($userId, $isCourseAdmin, $isCourseTutor) - { - $course_id = api_get_course_int_id(); + public function __construct( + int $userId, + bool $isCourseAdmin, + bool $isCourseTutor, + int $courseId = 0, + int $sessionId = 0 + ) { + if (empty($courseId)) { + $courseId = api_get_course_int_id(); + } + if (empty($sessionId)) { + $sessionId = api_get_session_id(); + } // Fill in properties $this->userId = $userId; @@ -452,10 +464,9 @@ class Dropbox_Person $this->receivedWork = []; $this->sentWork = []; - // Note: perhaps include an ex coursemember check to delete old files + // Note: perhaps include an ex course member check to delete old files - $session_id = api_get_session_id(); - $condition_session = api_get_session_condition($session_id); + $condition_session = api_get_session_condition($sessionId); $post_tbl = Database::get_course_table(TABLE_DROPBOX_POST); $person_tbl = Database::get_course_table(TABLE_DROPBOX_PERSON); @@ -467,7 +478,7 @@ class Dropbox_Person INNER JOIN $person_tbl p ON (r.file_id = p.file_id AND r.c_id = p.c_id) WHERE - r.c_id = $course_id AND + r.c_id = $courseId AND p.user_id = ".intval($this->userId).' AND r.dest_user_id = '.intval($this->userId)." $condition_session "; @@ -483,7 +494,7 @@ class Dropbox_Person INNER JOIN $person_tbl p ON (f.id = p.file_id AND f.c_id = p.c_id) WHERE - f.c_id = $course_id AND + f.c_id = $courseId AND f.uploader_id = ".intval($this->userId).' AND p.user_id = '.intval($this->userId)." $condition_session @@ -498,24 +509,32 @@ class Dropbox_Person * Deletes all the received categories and work of this person. * * @param int $id + * @param int $courseId + * @param int $sessionId * * @return bool */ - public function deleteReceivedWorkFolder($id) + public function deleteReceivedWorkFolder(int $id, int $courseId = 0, int $sessionId = 0): bool { - $course_id = api_get_course_int_id(); + if (empty($courseId)) { + $courseId = api_get_course_int_id(); + } + if (empty($sessionId)) { + $sessionId = api_get_session_id(); + } + + $condition_session = api_get_session_condition($sessionId); - $id = intval($id); $sql = 'DELETE FROM '.Database::get_course_table(TABLE_DROPBOX_FILE)." - WHERE c_id = $course_id AND cat_id = '".$id."' "; + WHERE c_id = $courseId $condition_session AND cat_id = $id"; Database::query($sql); $sql = 'DELETE FROM '.Database::get_course_table(TABLE_DROPBOX_CATEGORY)." - WHERE c_id = $course_id AND cat_id = '".$id."' "; + WHERE c_id = $courseId $condition_session AND cat_id = $id"; Database::query($sql); $sql = 'DELETE FROM '.Database::get_course_table(TABLE_DROPBOX_POST)." - WHERE c_id = $course_id AND cat_id = '".$id."' "; + WHERE c_id = $courseId $condition_session AND cat_id = $id"; Database::query($sql); return true; @@ -525,11 +544,17 @@ class Dropbox_Person * Deletes a received dropbox file of this person with id=$id. * * @param int $id + * @param int $courseId + * @param int $sessionId */ - public function deleteReceivedWork($id) + public function deleteReceivedWork(int $id, int $courseId = 0, int $sessionId = 0): void { - $course_id = api_get_course_int_id(); - $id = (int) $id; + if (empty($courseId)) { + $courseId = api_get_course_int_id(); + } + if (empty($sessionId)) { + $sessionId = api_get_session_id(); + } // index check $found = false; @@ -541,13 +566,13 @@ class Dropbox_Person } if (!$found) { - if (!$this->deleteReceivedWorkFolder($id)) { + if (!$this->deleteReceivedWorkFolder($id, $courseId, $sessionId)) { exit(get_lang('GeneralError').' (code 216)'); } } // Delete entries in person table concerning received works $sql = 'DELETE FROM '.Database::get_course_table(TABLE_DROPBOX_PERSON)." - WHERE c_id = $course_id AND user_id = '".$this->userId."' AND file_id ='".$id."'"; + WHERE c_id = $courseId AND user_id = ".$this->userId." AND file_id = $id"; Database::query($sql); removeUnusedFiles(); // Check for unused files } @@ -556,12 +581,17 @@ class Dropbox_Person * Deletes a sent dropbox file of this person with id=$id. * * @param int $id + * @param int $courseId + * @param int $sessionId */ - public function deleteSentWork($id) + public function deleteSentWork(int $id, int $courseId = 0, int $sessionId = 0): void { - $course_id = api_get_course_int_id(); - - $id = (int) $id; + if (empty($courseId)) { + $courseId = api_get_course_int_id(); + } + if (empty($sessionId)) { + $sessionId = api_get_session_id(); + } // index check $found = false; @@ -572,14 +602,14 @@ class Dropbox_Person } } if (!$found) { - if (!$this->deleteReceivedWorkFolder($id)) { + if (!$this->deleteReceivedWorkFolder($id, $courseId, $sessionId)) { exit(get_lang('GeneralError').' (code 219)'); } } //$file_id = $this->sentWork[$index]->id; // Delete entries in person table concerning sent works $sql = 'DELETE FROM '.Database::get_course_table(TABLE_DROPBOX_PERSON)." - WHERE c_id = $course_id AND user_id='".$this->userId."' AND file_id='".$id."'"; + WHERE c_id = $courseId AND user_id = ".$this->userId." AND file_id = $id"; Database::query($sql); removeMoreIfMailing($id); removeUnusedFiles(); // Check for unused files diff --git a/main/dropbox/dropbox_functions.inc.php b/main/dropbox/dropbox_functions.inc.php index 7cebd0eb17..8eb269f6d5 100755 --- a/main/dropbox/dropbox_functions.inc.php +++ b/main/dropbox/dropbox_functions.inc.php @@ -761,28 +761,39 @@ function display_add_form($viewReceivedCategory, $viewSentCategory, $view, $id = /** * Checks if there are files in the dropbox_file table that aren't used anymore in dropbox_person table. * If there are, all entries concerning the file are deleted from the db + the file is deleted from the server. + * + * @param int $courseId + * @param int $sessionId */ -function removeUnusedFiles() +function removeUnusedFiles(int $courseId = 0, int $sessionId = 0) { - $_course = api_get_course_info(); - $course_id = $_course['real_id']; + if (empty($courseId)) { + $courseId = api_get_course_int_id(); + } + $_course = api_get_course_info_by_id($courseId); + if (empty($sessionId)) { + $sessionId = api_get_session_id(); + } + $condition_session = api_get_session_condition($sessionId, true, false, 'f.session_id'); // select all files that aren't referenced anymore - $sql = "SELECT DISTINCT f.id, f.filename + $sql = "SELECT DISTINCT f.iid, f.filename FROM ".Database::get_course_table(TABLE_DROPBOX_FILE)." f LEFT JOIN ".Database::get_course_table(TABLE_DROPBOX_PERSON)." p - ON (f.id = p.file_id) + ON (f.iid = p.file_id) WHERE p.user_id IS NULL AND - f.c_id = $course_id + f.c_id = $courseId + $condition_session "; $result = Database::query($sql); + $condition_session = api_get_session_condition($sessionId); while ($res = Database::fetch_array($result)) { //delete the selected files from the post and file tables $sql = "DELETE FROM ".Database::get_course_table(TABLE_DROPBOX_POST)." - WHERE c_id = $course_id AND file_id = '".$res['id']."'"; + WHERE c_id = $courseId $condition_session AND file_id = ".$res['iid']; Database::query($sql); $sql = "DELETE FROM ".Database::get_course_table(TABLE_DROPBOX_FILE)." - WHERE c_id = $course_id AND id ='".$res['id']."'"; + WHERE iid = ".$res['iid']; Database::query($sql); //delete file from server @unlink(api_get_path(SYS_COURSE_PATH).$_course['path'].'/dropbox/'.$res['filename']); @@ -832,18 +843,26 @@ function getUserOwningThisMailing($mailingPseudoId, $owner = 0, $or_die = '') * * @todo check if this function is still necessary. */ -function removeMoreIfMailing($file_id) +function removeMoreIfMailing(int $file_id, int $courseId = 0, int $sessionId = 0, int $uploaderId = 0) { - $course_id = api_get_course_int_id(); + if (empty($courseId)) { + $courseId = api_get_course_int_id(); + } + if (empty($sessionId)) { + $sessionId = api_get_session_id(); + } + $condition_session = api_get_session_condition($sessionId); + if (empty($uploaderId)) { + $uploaderId = api_get_user_id(); + } // when deleting a mailing zip-file (posted to mailingPseudoId): // 1. the detail window is no longer reachable, so // for all content files, delete mailingPseudoId from person-table // 2. finding the owner (getUserOwningThisMailing) is no longer possible, so // for all content files, replace mailingPseudoId by owner as uploader - $file_id = (int) $file_id; $sql = "SELECT p.dest_user_id FROM ".Database::get_course_table(TABLE_DROPBOX_POST)." p - WHERE c_id = $course_id AND p.file_id = '".$file_id."'"; + WHERE c_id = $courseId $condition_session AND p.file_id = $file_id"; $result = Database::query($sql); if ($res = Database::fetch_array($result)) { @@ -851,12 +870,12 @@ function removeMoreIfMailing($file_id) $mailId = get_mail_id_base(); if ($mailingPseudoId > $mailId) { $sql = "DELETE FROM ".Database::get_course_table(TABLE_DROPBOX_PERSON)." - WHERE c_id = $course_id AND user_id='".$mailingPseudoId."'"; + WHERE c_id = $courseId AND user_id = $mailingPseudoId"; Database::query($sql); $sql = "UPDATE ".Database::get_course_table(TABLE_DROPBOX_FILE)." - SET uploader_id='".api_get_user_id()."' - WHERE c_id = $course_id AND uploader_id='".$mailingPseudoId."'"; + SET uploader_id = $uploaderId + WHERE c_id = $courseId $condition_session AND uploader_id = $mailingPseudoId"; Database::query($sql); } } diff --git a/main/exercise/oral_expression.class.php b/main/exercise/oral_expression.class.php index 1be7d388bd..7e22134f4f 100755 --- a/main/exercise/oral_expression.class.php +++ b/main/exercise/oral_expression.class.php @@ -79,22 +79,33 @@ class OralExpression extends Question } /** - * initialize the attributes to generate the file path. + * Initialize the attributes to generate the file path. * * @param int $sessionId * @param int $userId * @param int $exerciseId * @param int $exeId + * @param int $courseId + * + * @return void */ - public function initFile($sessionId, $userId, $exerciseId, $exeId) - { - $this->sessionId = (int) $sessionId; - $this->userId = (int) $userId; + public function initFile( + int $sessionId, + int $userId, + int $exerciseId, + int $exeId, + int $courseId = 0 + ): void { + if (!empty($courseId)) { + $this->course = api_get_course_info_by_id($courseId); + } + $this->sessionId = $sessionId; + $this->userId = $userId; $this->exerciseId = 0; - $this->exeId = (int) $exeId; if (!empty($exerciseId)) { - $this->exerciseId = (int) $exerciseId; + $this->exerciseId = $exerciseId; } + $this->exeId = $exeId; $this->storePath = $this->generateDirectory(); $this->fileName = $this->generateFileName(); $this->filePath = $this->storePath.$this->fileName; diff --git a/main/inc/lib/sessionmanager.lib.php b/main/inc/lib/sessionmanager.lib.php index 0d8d335dfd..93c900b050 100755 --- a/main/inc/lib/sessionmanager.lib.php +++ b/main/inc/lib/sessionmanager.lib.php @@ -1763,11 +1763,18 @@ class SessionManager $userGroupSessionTable = Database::get_main_table(TABLE_USERGROUP_REL_SESSION); $trackCourseAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS); $trackAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS); + $tbl_learnpath = Database::get_course_table(TABLE_LP_MAIN); + $tbl_dropbox = Database::get_course_table(TABLE_DROPBOX_FILE); + $trackEExercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); + $trackEAttempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT); + $ticket = Database::get_main_table(TABLE_TICKET_TICKET); $em = Database::getManager(); $userId = api_get_user_id(); + // If this session is involved in any sequence, cancel deletion and ask + // for the sequence update before deleting. /** @var SequenceResourceRepository $repo */ $repo = Database::getManager()->getRepository('ChamiloCoreBundle:SequenceResource'); $sequenceResource = $repo->findRequirementForResource( @@ -1786,6 +1793,8 @@ class SessionManager return false; } + // If the $id_checked param is an array, split it into individual + // sessions deletion. if (is_array($id_checked)) { foreach ($id_checked as $sessionId) { self::delete($sessionId); @@ -1794,6 +1803,9 @@ class SessionManager $id_checked = intval($id_checked); } + // Check permissions from the person launching the deletion. + // If the call is issued from a web service or automated process, + // we assume the caller checks for permissions ($from_ws). if (self::allowed($id_checked) && !$from_ws) { $qb = $em ->createQuery(' @@ -1811,11 +1823,14 @@ class SessionManager $sessionInfo = api_get_session_info($id_checked); - // Delete documents inside a session + // Delete documents and assignments inside a session $courses = self::getCoursesInSession($id_checked); foreach ($courses as $courseId) { $courseInfo = api_get_course_info_by_id($courseId); + // Delete documents DocumentManager::deleteDocumentsFromSession($courseInfo, $id_checked); + + // Delete assignments $works = Database::select( '*', $tbl_student_publication, @@ -1823,7 +1838,6 @@ class SessionManager 'where' => ['session_id = ? AND c_id = ?' => [$id_checked, $courseId]], ] ); - $currentCourseRepositorySys = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/'; foreach ($works as $index => $work) { if ($work['filetype'] = 'folder') { @@ -1831,6 +1845,62 @@ class SessionManager } my_delete($currentCourseRepositorySys.'/'.$work['url']); } + + // Delete learning paths + $learnpaths = Database::select( + 'iid', + $tbl_learnpath, + [ + 'where' => ['session_id = ? AND c_id = ?' => [$id_checked, $courseId]], + ] + ); + $courseInfo = api_get_course_info_by_id($courseId); + foreach ($learnpaths as $lpData) { + $lp = new learnpath($courseInfo['code'], $lpData['iid'], $userId); + $lp->delete($courseInfo, $lpData['iid'], true); + unset($lp); + } + + // Delete dropbox documents + $dropboxes = Database::select( + 'iid', + $tbl_dropbox, + [ + 'where' => ['session_id = ? AND c_id = ?' => [$id_checked, $courseId]], + ] + ); + require_once __DIR__.'/../../dropbox/dropbox_functions.inc.php'; + foreach ($dropboxes as $dropbox) { + $dropboxPerson = new Dropbox_Person( + $userId, + true, + false, + $courseId, + $id_checked + ); + $dropboxPerson->deleteReceivedWork($dropbox['iid'], $courseId, $id_checked); + $dropboxPerson->deleteSentWork($dropbox['iid'], $courseId, $id_checked); + } + + // TODO: Delete audio files from test answers + $attempts = Database::select( + ['id', 'user_id', 'exe_id'], + $trackEAttempt, + [ + 'where' => [ + 'session_id = ? AND c_id = ? AND (filename IS NOT NULL AND filename != \'\')' => [ + $id_checked, + $courseId + ] + ], + ] + ); + foreach ($attempts as $attempt) { + $attempt = new OralExpression(); + $attempt->initFile($id_checked, $attempt['user_id'], 0, $attempt['exe_id'], $courseId); + $filename = $attempt->getAbsoluteFilePath(true); + my_delete($filename); + } } // Class