Эх сурвалжийг харах

Merge branch '1.11.x' of https://github.com/chamilo/chamilo-lms into 1.11.x

Alex Aragón 6 жил өмнө
parent
commit
94fdb10fbf

+ 13 - 17
main/coursecopy/create_backup.php

@@ -40,23 +40,22 @@ Display::display_header($nameTools);
 
 // Display the tool title
 echo Display::page_header($nameTools);
+$action = isset($_POST['action']) ? $_POST['action'] : '';
+$backupOption = isset($_POST['backup_option']) ? $_POST['backup_option'] : '';
 
-if (Security::check_token('post') && (
-        (
-            isset($_POST['action']) &&
-            $_POST['action'] == 'course_select_form'
-        ) || (
-            isset($_POST['backup_option']) &&
-            $_POST['backup_option'] == 'full_backup'
-        )
-    )
+if (Security::check_token('post') &&
+    ($action === 'course_select_form' || $backupOption === 'full_backup')
 ) {
     // Clear token
     Security::clear_token();
-    $cb = new CourseBuilder();
-    $course = $cb->build();
-    if (isset($_POST['action']) && $_POST['action'] == 'course_select_form') {
+
+    if ($action === 'course_select_form') {
+        $cb = new CourseBuilder('partial');
+        $course = $cb->build(0, null, false, array_keys($_POST['resource']), $_POST['resource']);
         $course = CourseSelectForm::get_posted_course(null, 0, '', $course);
+    } else {
+        $cb = new CourseBuilder('complete');
+        $course = $cb->build();
     }
     $zipFile = CourseArchiver::createBackup($course);
     echo Display::return_message(get_lang('BackupCreated'), 'confirm');
@@ -66,11 +65,7 @@ if (Security::check_token('post') && (
         api_get_path(WEB_CODE_PATH).'course_info/download.php?archive='.$zipFile.'&'.api_get_cidreq(),
         ['class' => 'btn btn-primary btn-large']
     );
-} elseif (Security::check_token('post') && (
-        isset($_POST['backup_option']) &&
-        $_POST['backup_option'] == 'select_items'
-    )
-) {
+} elseif (Security::check_token('post') && $backupOption === 'select_items') {
     // Clear token
     Security::clear_token();
     $cb = new CourseBuilder('partial');
@@ -120,3 +115,4 @@ if (Security::check_token('post') && (
 }
 
 Display::display_footer();
+

+ 4 - 4
main/inc/ajax/course.ajax.php

@@ -13,8 +13,8 @@ $user_id = api_get_user_id();
 
 switch ($action) {
     case 'add_course_vote':
-        $course_id = intval($_REQUEST['course_id']);
-        $star = intval($_REQUEST['star']);
+        $course_id = (int) $_REQUEST['course_id'];
+        $star = (int) $_REQUEST['star'];
 
         if (!api_is_anonymous()) {
             CourseManager::add_course_vote($user_id, $star, $course_id, 0);
@@ -40,7 +40,7 @@ switch ($action) {
     case 'get_user_courses':
         // Only search my courses
         if (api_is_platform_admin() || api_is_session_admin()) {
-            $userId = intval($_REQUEST['user_id']);
+            $userId = (int) $_REQUEST['user_id'];
             $list = CourseManager::get_courses_list_by_user_id(
                 $userId,
                 false
@@ -126,7 +126,7 @@ switch ($action) {
         break;
     case 'search_course':
         if (api_is_teacher()) {
-            if (!empty($_GET['session_id']) && intval($_GET['session_id'])) {
+            if (isset($_GET['session_id']) && !empty($_GET['session_id'])) {
                 //if session is defined, lets find only courses of this session
                 $courseList = SessionManager::get_course_list_by_session_id(
                     $_GET['session_id'],

+ 2 - 2
main/inc/lib/exercise.lib.php

@@ -2923,7 +2923,7 @@ EOT;
             } else {
                 $conditions = [
                     'where' => [
-                        $active_sql.' (session_id = 0 OR session_id = ? ) AND c_id = ? '.$needle_where.$time_conditions => [
+                        $active_sql.' (session_id = 0 OR session_id IS NULL OR session_id = ? ) AND c_id = ? '.$needle_where.$time_conditions => [
                             $session_id,
                             $course_id,
                             $needle,
@@ -3012,7 +3012,7 @@ EOT;
         } else {
             // All exercises
             $conditions = [
-                'where' => ["$sql_active_exercises (session_id = 0 OR session_id = ? ) AND c_id=?" => $params],
+                'where' => ["$sql_active_exercises (session_id = 0 OR session_id IS NULL OR session_id = ? ) AND c_id=?" => $params],
                 'order' => 'title',
             ];
         }

+ 4 - 0
main/install/configuration.dist.php

@@ -494,6 +494,10 @@ ALTER TABLE c_survey_question ADD is_required TINYINT(1) DEFAULT 0 NOT NULL;
 // Hide survey edition tools for all or some surveys.
 //Set an asterisk to hide for all, otherwise set an array with the survey codes in which the options will be blocked
 //$_configuration['hide_survey_edition'] = ['codes' => []];
+// Allows to set the date and time of availability for surveys. Requires DB changes:
+// ALTER TABLE c_survey CHANGE avail_from avail_from DATETIME DEFAULT NULL, CHANGE avail_till avail_till DATETIME DEFAULT NULL;
+// Requires change the Doctrine type from date to datime in CSurvey::$availFrom and CSurvey::$availTill
+//$_configuration['allow_survey_availability_datetime'] = false;
 // ------
 
 // Allow career diagram, requires a DB change:

+ 5 - 5
main/lp/learnpathItem.class.php

@@ -112,7 +112,7 @@ class learnpathItem
             if (empty($course_id)) {
                 $course_id = api_get_course_int_id();
             } else {
-                $course_id = intval($course_id);
+                $course_id = (int) $course_id;
             }
             $sql = "SELECT * FROM $items_table
                     WHERE iid = $id";
@@ -365,7 +365,7 @@ class learnpathItem
         }
         $res = 1;
         if (!empty($this->attempt_id)) {
-            $res = intval($this->attempt_id);
+            $res = (int) $this->attempt_id;
         }
         if (self::DEBUG > 0) {
             error_log(
@@ -3587,7 +3587,7 @@ class learnpathItem
         }
 
         $lp_table = Database::get_course_table(TABLE_LP_MAIN);
-        $lp_id = intval($this->lp_id);
+        $lp_id = (int) $this->lp_id;
         $sql = "SELECT * FROM $lp_table WHERE iid = $lp_id";
         $res = Database::query($sql);
         $accumulateScormTime = 'false';
@@ -4501,7 +4501,7 @@ class learnpathItem
      */
     public function getForumThread($lpCourseId, $lpSessionId = 0)
     {
-        $lpSessionId = intval($lpSessionId);
+        $lpSessionId = (int) $lpSessionId;
         $forumThreadTable = Database::get_course_table(TABLE_FORUM_THREAD);
         $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
 
@@ -4565,7 +4565,7 @@ class learnpathItem
         $threadRepo = $em->getRepository('ChamiloCourseBundle:CForumThread');
         $forumThread = $threadRepo->findOneBy([
             'threadTitle' => "{$this->title} - {$this->db_id}",
-            'forumId' => intval($currentForumId),
+            'forumId' => (int) $currentForumId,
         ]);
 
         if (!$forumThread) {

+ 27 - 6
main/survey/create_new_survey.php

@@ -18,6 +18,8 @@ require_once __DIR__.'/../inc/global.inc.php';
 
 $this_section = SECTION_COURSES;
 
+$allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
+
 // Database table definitions
 $table_survey = Database::get_course_table(TABLE_SURVEY);
 $table_user = Database::get_main_table(TABLE_MAIN_USER);
@@ -72,6 +74,13 @@ if ($_GET['action'] == 'edit' && isset($survey_id) && is_numeric($survey_id)) {
     $defaults['survey_id'] = $survey_id;
     $defaults['anonymous'] = $survey_data['anonymous'];
 
+    if ($allowSurveyAvailabilityDatetime) {
+        $defaults['avail_from'] = api_get_local_time($defaults['avail_from'], null, 'UTC');
+        $defaults['avail_till'] = api_get_local_time($defaults['avail_till'], null, 'UTC');
+        $defaults['start_date'] = $defaults['avail_from'];
+        $defaults['end_date'] = $defaults['avail_till'];
+    }
+
     $link_info = GradebookUtils::isResourceInCourseGradebook(
         $course_id,
         $gradebook_link_type,
@@ -93,9 +102,15 @@ if ($_GET['action'] == 'edit' && isset($survey_id) && is_numeric($survey_id)) {
     }
 } else {
     $defaults['survey_language'] = $_course['language'];
-    $defaults['start_date'] = date('Y-m-d', api_strtotime(api_get_local_time()));
+    $defaults['start_date'] = date(
+        $allowSurveyAvailabilityDatetime ? 'Y-m-d 00:00:00' : 'Y-m-d',
+        api_strtotime(api_get_local_time())
+    );
     $startdateandxdays = time() + 864000; // today + 10 days
-    $defaults['end_date'] = date('Y-m-d', $startdateandxdays);
+    $defaults['end_date'] = date(
+        $allowSurveyAvailabilityDatetime ? 'Y-m-d 23:59:59' : 'Y-m-d',
+        $startdateandxdays
+    );
     //$defaults['survey_share']['survey_share'] = 0;
     //$form_share_value = 1;
     $defaults['anonymous'] = 0;
@@ -149,8 +164,14 @@ $form->addElement(
 
 // Pass the language of the survey in the form
 $form->addElement('hidden', 'survey_language');
-$form->addElement('date_picker', 'start_date', get_lang('StartDate'));
-$form->addElement('date_picker', 'end_date', get_lang('EndDate'));
+
+if ($allowSurveyAvailabilityDatetime) {
+    $form->addDateTimePicker('start_date', get_lang('StartDate'));
+    $form->addDateTimePicker('end_date', get_lang('EndDate'));
+} else {
+    $form->addElement('date_picker', 'start_date', get_lang('StartDate'));
+    $form->addElement('date_picker', 'end_date', get_lang('EndDate'));
+}
 
 $form->addElement('checkbox', 'anonymous', null, get_lang('Anonymous'));
 $visibleResults = [
@@ -298,8 +319,8 @@ if ($_GET['action'] == 'add') {
     $form->addRule('survey_code', '', 'maxlength', 20);
 }
 $form->addRule('survey_title', get_lang('ThisFieldIsRequired'), 'required');
-$form->addRule('start_date', get_lang('InvalidDate'), 'date');
-$form->addRule('end_date', get_lang('InvalidDate'), 'date');
+$form->addRule('start_date', get_lang('InvalidDate'), $allowSurveyAvailabilityDatetime ? 'datetime': 'date');
+$form->addRule('end_date', get_lang('InvalidDate'), $allowSurveyAvailabilityDatetime ? 'datetime': 'date');
 $form->addRule(
     ['start_date', 'end_date'],
     get_lang('StartDateShouldBeBeforeEndDate'),

+ 4 - 1
main/survey/fillsurvey.php

@@ -1364,11 +1364,14 @@ Display::display_footer();
  */
 function check_time_availability($surveyData)
 {
+    $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
     $utcZone = new DateTimeZone('UTC');
     $startDate = new DateTime($surveyData['start_date'], $utcZone);
     $endDate = new DateTime($surveyData['end_date'], $utcZone);
     $currentDate = new DateTime('now', $utcZone);
-    $currentDate->modify('today');
+    if (!$allowSurveyAvailabilityDatetime) {
+        $currentDate->modify('today');
+    }
     if ($currentDate < $startDate) {
         api_not_allowed(
             true,

+ 13 - 4
main/survey/survey.lib.php

@@ -218,6 +218,7 @@ class SurveyManager
      */
     public static function store_survey($values)
     {
+        $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
         $_user = api_get_user_info();
         $course_id = api_get_course_int_id();
         $session_id = api_get_session_id();
@@ -338,8 +339,12 @@ class SurveyManager
                 'subtitle' => $values['survey_subtitle'],
                 'author' => $_user['user_id'],
                 'lang' => $values['survey_language'],
-                'avail_from' => $values['start_date'],
-                'avail_till' => $values['end_date'],
+                'avail_from' => $allowSurveyAvailabilityDatetime
+                    ? api_get_utc_datetime($values['start_date'])
+                    : $values['start_date'],
+                'avail_till' => $allowSurveyAvailabilityDatetime
+                    ? api_get_utc_datetime($values['end_date'])
+                    : $values['end_date'],
                 'is_shared' => $shared_survey_id,
                 'template' => 'template',
                 'intro' => $values['survey_introduction'],
@@ -444,8 +449,12 @@ class SurveyManager
                 'subtitle' => $values['survey_subtitle'],
                 'author' => $_user['user_id'],
                 'lang' => $values['survey_language'],
-                'avail_from' => $values['start_date'],
-                'avail_till' => $values['end_date'],
+                'avail_from' => $allowSurveyAvailabilityDatetime
+                    ? api_get_utc_datetime($values['start_date'])
+                    : $values['start_date'],
+                'avail_till' => $allowSurveyAvailabilityDatetime
+                    ? api_get_utc_datetime($values['end_date'])
+                    : $values['end_date'],
                 'is_shared' => $shared_survey_id,
                 'template' => 'template',
                 'intro' => $values['survey_introduction'],

+ 24 - 4
main/survey/surveyUtil.class.php

@@ -3075,6 +3075,8 @@ class SurveyUtil
         $mandatoryAllowed = api_get_configuration_value('allow_mandatory_survey');
         $_user = api_get_user_info();
 
+        $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
+
         // Searching
         $search_restriction = self::survey_search_restriction();
         if ($search_restriction) {
@@ -3145,8 +3147,14 @@ class SurveyUtil
             $array[2] = $survey[2].$session_img;
             $array[3] = $survey[3];
             $array[4] = $survey[4];
-            $array[5] = $survey[5];
-            $array[6] = $survey[6];
+            $array[5] = api_convert_and_format_date(
+                $survey[5],
+                $allowSurveyAvailabilityDatetime ? DATE_TIME_FORMAT_LONG : DATE_FORMAT_LONG
+            );
+            $array[6] = api_convert_and_format_date(
+                $survey[6],
+                $allowSurveyAvailabilityDatetime ? DATE_TIME_FORMAT_LONG : DATE_FORMAT_LONG
+            );
             $array[7] =
                 Display::url(
                     $survey['answered'],
@@ -3196,6 +3204,7 @@ class SurveyUtil
     public static function get_survey_data_for_coach($from, $number_of_items, $column, $direction)
     {
         $mandatoryAllowed = api_get_configuration_value('allow_mandatory_survey');
+        $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
         $survey_tree = new SurveyTree();
         //$last_version_surveys = $survey_tree->get_last_children_from_branch($survey_tree->surveylist);
         $last_version_surveys = $survey_tree->surveylist;
@@ -3251,6 +3260,15 @@ class SurveyUtil
         $res = Database::query($sql);
         $surveys = [];
         while ($survey = Database::fetch_array($res)) {
+            $survey['col5'] = api_convert_and_format_date(
+                $survey['col5'],
+                $allowSurveyAvailabilityDatetime ? DATE_TIME_FORMAT_LONG : DATE_FORMAT_LONG
+            );
+            $survey['col6'] = api_convert_and_format_date(
+                $survey['col6'],
+                $allowSurveyAvailabilityDatetime ? DATE_TIME_FORMAT_LONG : DATE_FORMAT_LONG
+            );
+
             if ($mandatoryAllowed) {
                 $survey['col10'] = $survey['col9'];
                 $efvMandatory = $efv->get_values_by_handler_and_field_variable(
@@ -3281,6 +3299,7 @@ class SurveyUtil
         $user_id = intval($user_id);
         $sessionId = api_get_session_id();
         $mandatoryAllowed = api_get_configuration_value('allow_mandatory_survey');
+        $allowSurveyAvailabilityDatetime = api_get_configuration_value('allow_survey_availability_datetime');
 
         // Database table definitions
         $table_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
@@ -3311,6 +3330,7 @@ class SurveyUtil
 
         /** @var \DateTime $now */
         $now = api_get_utc_datetime(null, false, true);
+        $filterDate = $allowSurveyAvailabilityDatetime ? $now->format('Y-m-d H:i') : $now->format('Y-m-d');
 
         $sql = "SELECT *
                 FROM $table_survey survey 
@@ -3323,8 +3343,8 @@ class SurveyUtil
                 )
 				WHERE
                     survey_invitation.user = $user_id AND                    
-                    survey.avail_from <= '".$now->format('Y-m-d')."' AND
-                    survey.avail_till >= '".$now->format('Y-m-d')."' AND
+                    survey.avail_from <= '$filterDate' AND
+                    survey.avail_till >= '$filterDate' AND
                     survey.c_id = $course_id AND
                     survey.session_id = $sessionId AND
                     survey_invitation.c_id = $course_id

+ 200 - 141
src/Chamilo/CourseBundle/Component/CourseCopy/CourseBuilder.php

@@ -76,6 +76,29 @@ class CourseBuilder
         'gradebook',
     ];
 
+    public $toolToName = [
+        'announcements' => RESOURCE_ANNOUNCEMENT,
+        'attendance' => RESOURCE_ATTENDANCE,
+        'course_descriptions' => RESOURCE_COURSEDESCRIPTION,
+        'documents' => RESOURCE_DOCUMENT,
+        'events' => RESOURCE_EVENT,
+        'forum_category' => RESOURCE_FORUMCATEGORY,
+        'forums' => RESOURCE_FORUM,
+        'forum_topics' => RESOURCE_FORUMTOPIC,
+        'glossary' => RESOURCE_GLOSSARY,
+        'quizzes' => RESOURCE_QUIZ,
+        'test_category' => RESOURCE_TEST_CATEGORY,
+        'learnpath_category' => RESOURCE_LEARNPATH_CATEGORY,
+        'learnpaths' => RESOURCE_LEARNPATH,
+        'links' => RESOURCE_LINK,
+        'surveys' => RESOURCE_SURVEY,
+        'tool_intro' => RESOURCE_TOOL_INTRO,
+        'thematic' => RESOURCE_THEMATIC,
+        'wiki' => RESOURCE_WIKI,
+        'works' => RESOURCE_WORK,
+        'gradebook' => RESOURCE_GRADEBOOK,
+    ];
+
     /* With this array you can filter wich elements of the tools are going
     to be added in the course obj (only works with LPs) */
     public $specific_id_list = [];
@@ -136,32 +159,56 @@ class CourseBuilder
      * @param string $courseCode
      * @param bool   $withBaseContent true if you want to get the elements that exists in the course and
      *                                in the session, (session_id = 0 or session_id = X)
+     * @param array $parseOnlyToolList
+     * @param array $toolsFromPost
      *
      * @return Course The course object structure
      */
     public function build(
         $session_id = 0,
         $courseCode = '',
-        $withBaseContent = false
+        $withBaseContent = false,
+        $parseOnlyToolList = [],
+        $toolsFromPost = []
     ) {
-        $table_properties = Database::get_course_table(TABLE_ITEM_PROPERTY);
         $course = api_get_course_info($courseCode);
         $courseId = $course['real_id'];
-
         foreach ($this->tools_to_build as $tool) {
+            if (!empty($parseOnlyToolList) && !in_array($this->toolToName[$tool], $parseOnlyToolList)) {
+                continue;
+            }
             $function_build = 'build_'.$tool;
             $specificIdList = isset($this->specific_id_list[$tool]) ? $this->specific_id_list[$tool] : null;
+            $buildOrphanQuestions = true;
+            if ($tool === 'quizzes') {
+                if (!isset($toolsFromPost[RESOURCE_QUIZ][-1])) {
+                    $buildOrphanQuestions = false;
+                }
 
-            $this->$function_build(
-                $session_id,
-                $courseId,
-                $withBaseContent,
-                $specificIdList
-            );
+                // Force orphan load
+                if ($this->course->type === 'complete') {
+                    $buildOrphanQuestions = true;
+                }
+
+                $this->build_quizzes(
+                    $session_id,
+                    $courseId,
+                    $withBaseContent,
+                    $specificIdList,
+                    $buildOrphanQuestions
+                );
+            } else {
+                $this->$function_build(
+                    $session_id,
+                    $courseId,
+                    $withBaseContent,
+                    $specificIdList
+                );
+            }
         }
 
         // Add asset
-        if ($course['course_image_source'] && basename($course['course_image_source']) != 'course.png') {
+        if ($course['course_image_source'] && basename($course['course_image_source']) !== 'course.png') {
             // Add course image courses/XXX/course-pic85x85.png
             $asset = new Asset(
                 $course['course_image_source'],
@@ -179,22 +226,28 @@ class CourseBuilder
         }
 
         // Once we've built the resources array a bit more, try to get items
-        //  from the item_property table and order them in the "resources" array
+        // from the item_property table and order them in the "resources" array
+        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
         foreach ($this->course->resources as $type => $resources) {
+            if (!empty($parseOnlyToolList) && !in_array($this->toolToName[$tool], $parseOnlyToolList)) {
+                continue;
+            }
             foreach ($resources as $id => $resource) {
-                $tool = $resource->get_tool();
-                if ($tool != null) {
-                    $sql = "SELECT * FROM $table_properties
-                            WHERE
-                                c_id = $courseId AND
-                                tool = '".$tool."' AND
-                                ref = '".$resource->get_id()."'";
-                    $res = Database::query($sql);
-                    $all_properties = [];
-                    while ($item_property = Database::fetch_array($res)) {
-                        $all_properties[] = $item_property;
+                if ($resource) {
+                    $tool = $resource->get_tool();
+                    if ($tool != null) {
+                        $sql = "SELECT * FROM $table
+                                WHERE
+                                    c_id = $courseId AND
+                                    tool = '".$tool."' AND
+                                    ref = '".$resource->get_id()."'";
+                        $res = Database::query($sql);
+                        $properties = [];
+                        while ($property = Database::fetch_array($res)) {
+                            $properties[] = $property;
+                        }
+                        $this->course->resources[$type][$id]->item_properties = $properties;
                     }
-                    $this->course->resources[$type][$id]->item_properties = $all_properties;
                 }
             }
         }
@@ -231,7 +284,7 @@ class CourseBuilder
         }
 
         if (!empty($courseId) && !empty($session_id)) {
-            $session_id = intval($session_id);
+            $session_id = (int) $session_id;
             if ($withBaseContent) {
                 $session_condition = api_get_session_condition(
                     $session_id,
@@ -616,12 +669,14 @@ class CourseBuilder
      * @param int   $courseId        Internal course ID
      * @param bool  $withBaseContent Whether to include content from the course without session or not
      * @param array $idList          If you want to restrict the structure to only the given IDs
+     * @param bool  $buildOrphanQuestions
      */
     public function build_quizzes(
         $session_id = 0,
         $courseId = 0,
         $withBaseContent = false,
-        $idList = []
+        $idList = [],
+        $buildOrphanQuestions = true
     ) {
         $table_qui = Database::get_course_table(TABLE_QUIZ_TEST);
         $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
@@ -635,15 +690,15 @@ class CourseBuilder
         }
 
         if (!empty($courseId) && !empty($session_id)) {
-            $session_id = intval($session_id);
+            $session_id = (int) $session_id;
             if ($withBaseContent) {
-                $session_condition = api_get_session_condition(
+                $sessionCondition = api_get_session_condition(
                     $session_id,
                     true,
                     true
                 );
             } else {
-                $session_condition = api_get_session_condition(
+                $sessionCondition = api_get_session_condition(
                     $session_id,
                     true
                 );
@@ -655,7 +710,7 @@ class CourseBuilder
                       c_id = $courseId AND 
                       $idCondition
                       active >=0 
-                      $session_condition ";
+                      $sessionCondition ";
         } else {
             // Select only quizzes with active = 0 or 1 (not -1 which is for deleted quizzes)
             $sql = "SELECT * FROM $table_qui
@@ -666,9 +721,9 @@ class CourseBuilder
                       (session_id = 0 OR session_id IS NULL)";
         }
 
-        $sql .= 'ORDER BY title';
-
+        $sql .= ' ORDER BY title';
         $db_result = Database::query($sql);
+        $questionList = [];
         while ($obj = Database::fetch_object($db_result)) {
             if (strlen($obj->sound) > 0) {
                 $sql = "SELECT id FROM $table_doc
@@ -677,40 +732,45 @@ class CourseBuilder
                 $doc = Database::fetch_object($res);
                 $obj->sound = $doc->id;
             }
+
             $quiz = new Quiz($obj);
             $sql = 'SELECT * FROM '.$table_rel.'
                     WHERE c_id = '.$courseId.' AND exercice_id = '.$obj->id;
             $db_result2 = Database::query($sql);
             while ($obj2 = Database::fetch_object($db_result2)) {
                 $quiz->add_question($obj2->question_id, $obj2->question_order);
+                $questionList[] = $obj2->question_id;
             }
             $this->course->add_resource($quiz);
         }
 
         if (!empty($courseId)) {
-            $this->build_quiz_questions($courseId);
+            $this->build_quiz_questions($courseId, $questionList, $buildOrphanQuestions);
         } else {
-            $this->build_quiz_questions();
+            $this->build_quiz_questions(0, $questionList, $buildOrphanQuestions);
         }
     }
 
     /**
      * Build the Quiz-Questions.
      *
-     * @param int $courseId Internal course ID
+     * @param int   $courseId Internal course ID
+     * @param array $questionList
+     * @param bool  $buildOrphanQuestions
+     *
      */
-    public function build_quiz_questions($courseId = 0)
+    public function build_quiz_questions($courseId = 0, $questionList = [], $buildOrphanQuestions = true)
     {
         $table_qui = Database::get_course_table(TABLE_QUIZ_TEST);
         $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
         $table_que = Database::get_course_table(TABLE_QUIZ_QUESTION);
         $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER);
-
         $courseId = (int) $courseId;
+        $questionListToString = implode("','", $questionList);
 
-        // Building normal tests.
+        // Building normal tests (many queries)
         $sql = "SELECT * FROM $table_que
-                WHERE c_id = $courseId ";
+                WHERE c_id = $courseId AND id IN ('$questionListToString')";
         $result = Database::query($sql);
 
         while ($obj = Database::fetch_object($result)) {
@@ -739,7 +799,6 @@ class CourseBuilder
             $sql = 'SELECT * FROM '.$table_ans.'
                     WHERE c_id = '.$courseId.' AND question_id = '.$obj->id;
             $db_result2 = Database::query($sql);
-
             while ($obj2 = Database::fetch_object($db_result2)) {
                 $question->add_answer(
                     $obj2->id,
@@ -765,105 +824,105 @@ class CourseBuilder
             $this->course->add_resource($question);
         }
 
-        // Building a fictional test for collecting orphan questions.
-        // When a course is emptied this option should be activated (true).
-        $build_orphan_questions = !empty($_POST['recycle_option']);
-
-        // 1st union gets the orphan questions from deleted exercises
-        // 2nd union gets the orphan questions from question that were deleted in a exercise.
-        $sql = " (
-                    SELECT question_id, q.* FROM $table_que q 
-                    INNER JOIN $table_rel r
-                    ON (q.c_id = r.c_id AND q.id = r.question_id)
-                    INNER JOIN $table_qui ex
-                    ON (ex.id = r.exercice_id AND ex.c_id = r.c_id )
-                    WHERE ex.c_id = $courseId AND ex.active = '-1'
-                 )
-                 UNION
-                 (
-                    SELECT question_id, q.* FROM $table_que q 
-                    left OUTER JOIN $table_rel r
-                    ON (q.c_id = r.c_id AND q.id = r.question_id)
-                    WHERE q.c_id = $courseId AND r.question_id is null
-                 )
-                 UNION
-                 (
-                    SELECT question_id, q.* FROM $table_que q
-                    INNER JOIN $table_rel r
-                    ON (q.c_id = r.c_id AND q.id = r.question_id)
-                    WHERE r.c_id = $courseId AND (r.exercice_id = '-1' OR r.exercice_id = '0')
-                 )
-        ";
+        if ($buildOrphanQuestions) {
+            // Building a fictional test for collecting orphan questions.
+            // When a course is emptied this option should be activated (true).
+            //$build_orphan_questions = !empty($_POST['recycle_option']);
+
+            // 1st union gets the orphan questions from deleted exercises
+            // 2nd union gets the orphan questions from question that were deleted in a exercise.
+            $sql = " (
+                        SELECT question_id, q.* FROM $table_que q
+                        INNER JOIN $table_rel r
+                        ON (q.c_id = r.c_id AND q.id = r.question_id)
+                        INNER JOIN $table_qui ex
+                        ON (ex.id = r.exercice_id AND ex.c_id = r.c_id)
+                        WHERE ex.c_id = $courseId AND ex.active = '-1'
+                    )
+                    UNION
+                     (
+                        SELECT question_id, q.* FROM $table_que q
+                        left OUTER JOIN $table_rel r
+                        ON (q.c_id = r.c_id AND q.id = r.question_id)
+                        WHERE q.c_id = $courseId AND r.question_id is null
+                     )
+                     UNION
+                     (
+                        SELECT question_id, q.* FROM $table_que q
+                        INNER JOIN $table_rel r
+                        ON (q.c_id = r.c_id AND q.id = r.question_id)
+                        WHERE r.c_id = $courseId AND (r.exercice_id = '-1' OR r.exercice_id = '0')
+                     )
+                 ";
 
-        $result = Database::query($sql);
-        if (Database::num_rows($result) > 0) {
-            $build_orphan_questions = true;
-            $orphanQuestionIds = [];
-            while ($obj = Database::fetch_object($result)) {
-                // Orphan questions
-                if (!empty($obj->question_id)) {
-                    $obj->id = $obj->question_id;
-                }
+            $result = Database::query($sql);
+            if (Database::num_rows($result) > 0) {
+                $orphanQuestionIds = [];
+                while ($obj = Database::fetch_object($result)) {
+                    // Orphan questions
+                    if (!empty($obj->question_id)) {
+                        $obj->id = $obj->question_id;
+                    }
 
-                // Avoid adding the same question twice
-                if (!isset($this->course->resources[$obj->id])) {
-                    // find the question category
-                    // @todo : need to be adapted for multi category questions in 1.10
-                    $question_category_id = TestCategory::getCategoryForQuestion($obj->id, $courseId);
-                    $question = new QuizQuestion(
-                        $obj->id,
-                        $obj->question,
-                        $obj->description,
-                        $obj->ponderation,
-                        $obj->type,
-                        $obj->position,
-                        $obj->picture,
-                        $obj->level,
-                        $obj->extra,
-                        $question_category_id
-                    );
-                    $question->addPicture($this);
-                    $sql = "SELECT * FROM $table_ans
-                            WHERE c_id = $courseId AND question_id = ".$obj->id;
-                    $db_result2 = Database::query($sql);
-                    if (Database::num_rows($db_result2)) {
-                        while ($obj2 = Database::fetch_object($db_result2)) {
-                            $question->add_answer(
-                                $obj2->id,
-                                $obj2->answer,
-                                $obj2->correct,
-                                $obj2->comment,
-                                $obj2->ponderation,
-                                $obj2->position,
-                                $obj2->hotspot_coordinates,
-                                $obj2->hotspot_type
-                            );
+                    // Avoid adding the same question twice
+                    if (!isset($this->course->resources[$obj->id])) {
+                        // find the question category
+                        // @todo : need to be adapted for multi category questions in 1.10
+                        $question_category_id = TestCategory::getCategoryForQuestion($obj->id, $courseId);
+                        $question = new QuizQuestion(
+                            $obj->id,
+                            $obj->question,
+                            $obj->description,
+                            $obj->ponderation,
+                            $obj->type,
+                            $obj->position,
+                            $obj->picture,
+                            $obj->level,
+                            $obj->extra,
+                            $question_category_id
+                        );
+                        $question->addPicture($this);
+                        $sql = "SELECT * FROM $table_ans
+                                WHERE c_id = $courseId AND question_id = ".$obj->id;
+                        $db_result2 = Database::query($sql);
+                        if (Database::num_rows($db_result2)) {
+                            while ($obj2 = Database::fetch_object($db_result2)) {
+                                $question->add_answer(
+                                    $obj2->id,
+                                    $obj2->answer,
+                                    $obj2->correct,
+                                    $obj2->comment,
+                                    $obj2->ponderation,
+                                    $obj2->position,
+                                    $obj2->hotspot_coordinates,
+                                    $obj2->hotspot_type
+                                );
+                            }
+                            $orphanQuestionIds[] = $obj->id;
                         }
-                        $orphanQuestionIds[] = $obj->id;
+                        $this->course->add_resource($question);
                     }
-                    $this->course->add_resource($question);
                 }
             }
         }
 
-        if ($build_orphan_questions) {
-            $obj = [
-                'id' => -1,
-                'title' => get_lang('OrphanQuestions', ''),
-                'type' => 2,
-            ];
-            $newQuiz = new Quiz((object) $obj);
-            if (!empty($orphanQuestionIds)) {
-                foreach ($orphanQuestionIds as $index => $orphanId) {
-                    $order = $index + 1;
-                    $newQuiz->add_question($orphanId, $order);
-                }
+        $obj = [
+            'id' => -1,
+            'title' => get_lang('OrphanQuestions'),
+            'type' => 2,
+        ];
+        $newQuiz = new Quiz((object) $obj);
+        if (!empty($orphanQuestionIds)) {
+            foreach ($orphanQuestionIds as $index => $orphanId) {
+                $order = $index + 1;
+                $newQuiz->add_question($orphanId, $order);
             }
-            $this->course->add_resource($newQuiz);
         }
+        $this->course->add_resource($newQuiz);
     }
 
     /**
+     * @deprecated
      * Build the orphan questions.
      */
     public function build_quiz_orphan_questions()
@@ -1214,19 +1273,19 @@ class CourseBuilder
         if (!empty($session_id) && !empty($courseId)) {
             $session_id = intval($session_id);
             if ($withBaseContent) {
-                $session_condition = api_get_session_condition(
+                $sessionCondition = api_get_session_condition(
                     $session_id,
                     true,
                     true
                 );
             } else {
-                $session_condition = api_get_session_condition(
+                $sessionCondition = api_get_session_condition(
                     $session_id,
                     true
                 );
             }
             $sql = 'SELECT * FROM '.$table.'
-                    WHERE c_id = '.$courseId.' '.$session_condition;
+                    WHERE c_id = '.$courseId.' '.$sessionCondition;
         } else {
             $table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
             $sql = 'SELECT * FROM '.$table.'
@@ -1293,19 +1352,19 @@ class CourseBuilder
         if (!empty($session_id) && !empty($courseId)) {
             $session_id = intval($session_id);
             if ($withBaseContent) {
-                $session_condition = api_get_session_condition(
+                $sessionCondition = api_get_session_condition(
                     $session_id,
                     true,
                     true
                 );
             } else {
-                $session_condition = api_get_session_condition(
+                $sessionCondition = api_get_session_condition(
                     $session_id,
                     true
                 );
             }
             $sql = 'SELECT * FROM '.$table_main.'
-                    WHERE c_id = '.$courseId.'  '.$session_condition;
+                    WHERE c_id = '.$courseId.'  '.$sessionCondition;
         } else {
             $sql = 'SELECT * FROM '.$table_main.'
                     WHERE c_id = '.$courseId.' AND (session_id = 0 OR session_id IS NULL)';
@@ -1438,13 +1497,13 @@ class CourseBuilder
         if (!empty($session_id) && !empty($courseId)) {
             $session_id = intval($session_id);
             if ($withBaseContent) {
-                $session_condition = api_get_session_condition(
+                $sessionCondition = api_get_session_condition(
                     $session_id,
                     true,
                     true
                 );
             } else {
-                $session_condition = api_get_session_condition(
+                $sessionCondition = api_get_session_condition(
                     $session_id,
                     true
                 );
@@ -1453,10 +1512,10 @@ class CourseBuilder
             //@todo check this queries are the same ...
             if (!empty($this->course->type) && $this->course->type == 'partial') {
                 $sql = 'SELECT * FROM '.$table_glossary.' g
-                        WHERE g.c_id = '.$courseId.' '.$session_condition;
+                        WHERE g.c_id = '.$courseId.' '.$sessionCondition;
             } else {
                 $sql = 'SELECT * FROM '.$table_glossary.' g
-                        WHERE g.c_id = '.$courseId.' '.$session_condition;
+                        WHERE g.c_id = '.$courseId.' '.$sessionCondition;
             }
         } else {
             $table_glossary = Database::get_course_table(TABLE_GLOSSARY);
@@ -1535,19 +1594,19 @@ class CourseBuilder
         if (!empty($session_id) && !empty($courseId)) {
             $session_id = intval($session_id);
             if ($withBaseContent) {
-                $session_condition = api_get_session_condition(
+                $sessionCondition = api_get_session_condition(
                     $session_id,
                     true,
                     true
                 );
             } else {
-                $session_condition = api_get_session_condition(
+                $sessionCondition = api_get_session_condition(
                     $session_id,
                     true
                 );
             }
             $sql = 'SELECT * FROM '.$tbl_wiki.'
-                    WHERE c_id = '.$courseId.' '.$session_condition;
+                    WHERE c_id = '.$courseId.' '.$sessionCondition;
         } else {
             $tbl_wiki = Database::get_course_table(TABLE_WIKI);
             $sql = 'SELECT * FROM '.$tbl_wiki.'
@@ -1593,17 +1652,17 @@ class CourseBuilder
         $courseInfo = api_get_course_info_by_id($courseId);
         $session_id = intval($session_id);
         if ($withBaseContent) {
-            $session_condition = api_get_session_condition(
+            $sessionCondition = api_get_session_condition(
                 $session_id,
                 true,
                 true
             );
         } else {
-            $session_condition = api_get_session_condition($session_id, true);
+            $sessionCondition = api_get_session_condition($session_id, true);
         }
 
         $sql = "SELECT * FROM $table_thematic
-                WHERE c_id = $courseId $session_condition ";
+                WHERE c_id = $courseId $sessionCondition ";
         $db_result = Database::query($sql);
         while ($row = Database::fetch_array($db_result, 'ASSOC')) {
             $thematic = new Thematic($row);

+ 12 - 15
src/Chamilo/CourseBundle/Component/CourseCopy/CourseRestorer.php

@@ -152,7 +152,7 @@ class CourseRestorer
         }
         $this->destination_course_id = $course_info['real_id'];
 
-        //Getting first teacher (for the forums)
+        // Getting first teacher (for the forums)
         $teacher_list = CourseManager::get_teacher_list_from_course_code(
             $course_info['code']
         );
@@ -207,7 +207,6 @@ class CourseRestorer
 
         // Restore the item properties
         $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
-
         foreach ($this->course->resources as $type => $resources) {
             if (is_array($resources)) {
                 foreach ($resources as $id => $resource) {
@@ -222,7 +221,7 @@ class CourseRestorer
 
                             $params = [];
                             if (!empty($session_id)) {
-                                $params['session_id'] = intval($session_id);
+                                $params['session_id'] = (int) $session_id;
                             }
 
                             $res = Database::query($sql);
@@ -1080,7 +1079,7 @@ class CourseRestorer
     public function restore_forums($sessionId = 0)
     {
         if ($this->course->has_resources(RESOURCE_FORUM)) {
-            $sessionId = intval($sessionId);
+            $sessionId = (int) $sessionId;
             $table_forum = Database::get_course_table(TABLE_FORUM);
             $resources = $this->course->resources;
             foreach ($resources[RESOURCE_FORUM] as $id => $forum) {
@@ -1458,7 +1457,7 @@ class CourseRestorer
     public function restore_tool_intro($sessionId = 0)
     {
         if ($this->course->has_resources(RESOURCE_TOOL_INTRO)) {
-            $sessionId = intval($sessionId);
+            $sessionId = (int) $sessionId;
             $tool_intro_table = Database::get_course_table(TABLE_TOOL_INTRO);
             $resources = $this->course->resources;
             foreach ($resources[RESOURCE_TOOL_INTRO] as $id => $tool_intro) {
@@ -1503,7 +1502,7 @@ class CourseRestorer
     public function restore_events($sessionId = 0)
     {
         if ($this->course->has_resources(RESOURCE_EVENT)) {
-            $sessionId = intval($sessionId);
+            $sessionId = (int) $sessionId;
             $table = Database::get_course_table(TABLE_AGENDA);
             $resources = $this->course->resources;
             foreach ($resources[RESOURCE_EVENT] as $id => $event) {
@@ -1638,7 +1637,7 @@ class CourseRestorer
                 );
 
                 $params = [];
-                $session_id = intval($session_id);
+                $session_id = (int) $session_id;
                 $params['session_id'] = $session_id;
                 $params['c_id'] = $this->destination_course_id;
                 $params['description_type'] = self::DBUTF8($descriptionType);
@@ -1668,7 +1667,7 @@ class CourseRestorer
     public function restore_announcements($sessionId = 0)
     {
         if ($this->course->has_resources(RESOURCE_ANNOUNCEMENT)) {
-            $sessionId = intval($sessionId);
+            $sessionId = (int) $sessionId;
             $table = Database::get_course_table(TABLE_ANNOUNCEMENT);
             $resources = $this->course->resources;
             foreach ($resources[RESOURCE_ANNOUNCEMENT] as $id => $announcement) {
@@ -1880,7 +1879,7 @@ class CourseRestorer
                         $params['session_id'] = $my_session_id;
                     } else {
                         if (!empty($session_id)) {
-                            $session_id = intval($session_id);
+                            $session_id = (int) $session_id;
                             $params['session_id'] = $session_id;
                         }
                     }
@@ -1897,7 +1896,6 @@ class CourseRestorer
                 }
 
                 $this->course->resources[RESOURCE_QUIZ][$id]->destination_id = $new_id;
-
                 $order = 0;
                 if (!empty($quiz->question_ids)) {
                     foreach ($quiz->question_ids as $index => $question_id) {
@@ -1911,6 +1909,7 @@ class CourseRestorer
                         Database::query($sql);
                     }
                 }
+
             }
         }
     }
@@ -2030,7 +2029,6 @@ class CourseRestorer
                         $quizAnswer
                             ->setId($answerId)
                             ->setIdAuto($answerId);
-
                         $em->merge($quizAnswer);
                         $em->flush();
 
@@ -2299,7 +2297,7 @@ class CourseRestorer
      */
     public function restore_surveys($sessionId = 0)
     {
-        $sessionId = intval($sessionId);
+        $sessionId = (int) $sessionId;
         if ($this->course->has_resources(RESOURCE_SURVEY)) {
             $table_sur = Database::get_course_table(TABLE_SURVEY);
             $table_que = Database::get_course_table(TABLE_SURVEY_QUESTION);
@@ -2405,7 +2403,6 @@ class CourseRestorer
                             // Delete the existing survey with the same code and language and
                             // import the one of the source course
                             // getting the information of the survey (used for when the survey is shared)
-
                             $sql = "SELECT * FROM $table_sur
                                     WHERE
                                         c_id = ".$this->destination_course_id." AND
@@ -2641,7 +2638,7 @@ class CourseRestorer
                         }
                         $condition_session = $my_session_id;
                     } else {
-                        $session_id = intval($session_id);
+                        $session_id = (int) $session_id;
                         $condition_session = $session_id;
                     }
                 }
@@ -3011,7 +3008,7 @@ class CourseRestorer
             foreach ($resources[RESOURCE_GLOSSARY] as $id => $glossary) {
                 $params = [];
                 if (!empty($session_id)) {
-                    $session_id = intval($session_id);
+                    $session_id = (int) $session_id;
                     $params['session_id'] = $session_id;
                 }
 

+ 194 - 134
src/Chamilo/CourseBundle/Component/CourseCopy/CourseSelectForm.php

@@ -18,6 +18,36 @@ use Display;
  */
 class CourseSelectForm
 {
+    /**
+     * @return array
+     */
+    public static function getResourceTitleList()
+    {
+        $list = [];
+        $list[RESOURCE_LEARNPATH_CATEGORY] = get_lang('Learnpath').' '.get_lang('Category');
+        $list[RESOURCE_ASSET] = get_lang('Assets');
+        $list[RESOURCE_GRADEBOOK] = get_lang('Gradebook');
+        $list[RESOURCE_EVENT] = get_lang('Events');
+        $list[RESOURCE_ANNOUNCEMENT] = get_lang('Announcements');
+        $list[RESOURCE_DOCUMENT] = get_lang('Documents');
+        $list[RESOURCE_LINK] = get_lang('Links');
+        $list[RESOURCE_COURSEDESCRIPTION] = get_lang('CourseDescription');
+        $list[RESOURCE_FORUM] = get_lang('Forums');
+        $list[RESOURCE_FORUMCATEGORY] = get_lang('ForumCategory');
+        $list[RESOURCE_QUIZ] = get_lang('Tests');
+        $list[RESOURCE_TEST_CATEGORY] = get_lang('QuestionCategory');
+        $list[RESOURCE_LEARNPATH] = get_lang('ToolLearnpath');
+        $list[RESOURCE_SCORM] = 'SCORM';
+        $list[RESOURCE_TOOL_INTRO] = get_lang('ToolIntro');
+        $list[RESOURCE_SURVEY] = get_lang('Survey');
+        $list[RESOURCE_GLOSSARY] = get_lang('Glossary');
+        $list[RESOURCE_WIKI] = get_lang('Wiki');
+        $list[RESOURCE_THEMATIC] = get_lang('Thematic');
+        $list[RESOURCE_ATTENDANCE] = get_lang('Attendance');
+        $list[RESOURCE_WORK] = get_lang('ToolStudentPublication');
+
+        return $list;
+    }
     /**
      * Display the form.
      *
@@ -34,38 +64,19 @@ class CourseSelectForm
         $avoidCourseInForm = false
     ) {
         global $charset;
-        $resource_titles[RESOURCE_LEARNPATH_CATEGORY] = get_lang('Learnpath').' '.get_lang('Category');
-        $resource_titles[RESOURCE_ASSET] = get_lang('Assets');
-        $resource_titles[RESOURCE_GRADEBOOK] = get_lang('Gradebook');
-        $resource_titles[RESOURCE_EVENT] = get_lang('Events');
-        $resource_titles[RESOURCE_ANNOUNCEMENT] = get_lang('Announcements');
-        $resource_titles[RESOURCE_DOCUMENT] = get_lang('Documents');
-        $resource_titles[RESOURCE_LINK] = get_lang('Links');
-        $resource_titles[RESOURCE_COURSEDESCRIPTION] = get_lang('CourseDescription');
-        $resource_titles[RESOURCE_FORUM] = get_lang('Forums');
-        $resource_titles[RESOURCE_FORUMCATEGORY] = get_lang('ForumCategory');
-        $resource_titles[RESOURCE_QUIZ] = get_lang('Tests');
-        $resource_titles[RESOURCE_TEST_CATEGORY] = get_lang('QuestionCategory');
-        $resource_titles[RESOURCE_LEARNPATH] = get_lang('ToolLearnpath');
-        $resource_titles[RESOURCE_SCORM] = 'SCORM';
-        $resource_titles[RESOURCE_TOOL_INTRO] = get_lang('ToolIntro');
-        $resource_titles[RESOURCE_SURVEY] = get_lang('Survey');
-        $resource_titles[RESOURCE_GLOSSARY] = get_lang('Glossary');
-        $resource_titles[RESOURCE_WIKI] = get_lang('Wiki');
-        $resource_titles[RESOURCE_THEMATIC] = get_lang('Thematic');
-        $resource_titles[RESOURCE_ATTENDANCE] = get_lang('Attendance');
-        $resource_titles[RESOURCE_WORK] = get_lang('ToolStudentPublication'); ?>
+        ?>
         <script>
             function exp(item) {
                 el = document.getElementById('div_'+item);
                 if (el.style.display == 'none') {
                     el.style.display = '';
-                    if (document.getElementById('img_'+item).length)
-                    document.getElementById('img_'+item).className = 'fa fa-minus-square-o fa-lg';
+                    $('#img_'+item).removeClass();
+                    $('#img_'+item).addClass('fa fa-minus-square-o fa-lg');
+
                 } else {
-                    el.style.display='none';
-                    if (document.getElementById('img_'+item).length)
-                    document.getElementById('img_'+item).className ='fa fa-plus-square-o fa-lg';
+                    el.style.display = 'none';
+                    $('#img_'+item).removeClass();
+                    $('#img_'+item).addClass('fa fa-plus-square-o fa-lg');
                 }
             }
 
@@ -157,6 +168,7 @@ class CourseSelectForm
             echo get_lang('DestinationCourse').' : '.$courseInfo['title'].' ('.$courseInfo['code'].') '.$sessionTitle;
             echo '</h3>';
         }
+
         echo '<script src="'.api_get_path(WEB_CODE_PATH).'inc/lib/javascript/upload.js" type="text/javascript"></script>';
         echo '<div class="tool-backups-options">';
         echo '<form method="post" id="upload_form" name="course_select_form">';
@@ -173,7 +185,6 @@ class CourseSelectForm
             echo '<input type="hidden" name="origin_session" value="'.$hidden_fields['origin_session'].'"/>';
         }
 
-        $element_count = 0;
         $forum_categories = [];
         $forums = [];
         $forum_topics = [];
@@ -183,97 +194,8 @@ class CourseSelectForm
         echo '</p>';
         echo Display::return_message(get_lang('DontForgetToSelectTheMediaFilesIfYourResourceNeedIt'));
 
-        foreach ($course->resources as $type => $resources) {
-            if (count($resources) > 0) {
-                switch ($type) {
-                    // Resources to avoid
-                    case RESOURCE_FORUMCATEGORY:
-                        foreach ($resources as $id => $resource) {
-                            $forum_categories[$id] = $resource;
-                        }
-                        $element_count++;
-                        break;
-                    case RESOURCE_FORUM:
-                        foreach ($resources as $id => $resource) {
-                            $forums[$resource->obj->forum_category][$id] = $resource;
-                        }
-                        $element_count++;
-                        break;
-                    case RESOURCE_FORUMTOPIC:
-                        foreach ($resources as $id => $resource) {
-                            $forum_topics[$resource->obj->forum_id][$id] = $resource;
-                        }
-                        $element_count++;
-                        break;
-                    case RESOURCE_LINKCATEGORY:
-                    case RESOURCE_FORUMPOST:
-                    case RESOURCE_QUIZQUESTION:
-                    case RESOURCE_SURVEYQUESTION:
-                    case RESOURCE_SURVEYINVITATION:
-                    case RESOURCE_SCORM:
-                        break;
-                    default:
-                        echo '<div class="item-backup" onclick="javascript:exp('."'$type'".');">';
-                        echo '<em id="img_'.$type.'" class="fa fa-minus-square-o fa-lg" ></em>';
-                        echo '<span class="title">'.$resource_titles[$type].'</span></div>';
-                        echo '<div class="item-content" id="div_'.$type.'">';
-                        if ($type == RESOURCE_LEARNPATH) {
-                            echo Display::return_message(
-                                get_lang(
-                                    'ToExportLearnpathWithQuizYouHaveToSelectQuiz'
-                                ),
-                                'warning'
-                            );
-                            echo Display::return_message(
-                                get_lang(
-                                    'IfYourLPsHaveAudioFilesIncludedYouShouldSelectThemFromTheDocuments'
-                                ),
-                                'warning'
-                            );
-                        }
-                        if ($type == RESOURCE_DOCUMENT) {
-                            if (api_get_setting('show_glossary_in_documents') != 'none') {
-                                echo Display::return_message(
-                                    get_lang(
-                                        'ToExportDocumentsWithGlossaryYouHaveToSelectGlossary'
-                                    ),
-                                    'warning'
-                                );
-                            }
-                        }
-
-                        echo '<div class="well">';
-                        echo '<div class="btn-group">';
-                        echo "<a class=\"btn btn-default\" 
-                                    href=\"javascript: void(0);\" 
-                                    onclick=\"javascript: setCheckbox('$type',true);\" >".get_lang('All')."</a>";
-                        echo "<a class=\"btn btn-default\" 
-                                    href=\"javascript: void(0);\" 
-                                    onclick=\"javascript:setCheckbox('$type',false);\" >".get_lang('None')."</a>";
-                        echo '</div>';
-                        echo '<ul class="list-backups-options">';
-                        foreach ($resources as $id => $resource) {
-                            if ($resource) {
-                                echo '<li>';
-                                // Event obj in 1.9.x in 1.10.x the class is CalendarEvent
-                                Resource::setClassType($resource);
-                                echo '<label class="checkbox">';
-                                echo '<input 
-                                    type="checkbox" 
-                                    name="resource['.$type.']['.$id.']"  id="resource['.$type.']['.$id.']" />';
-                                $resource->show();
-                                echo '</label>';
-                                echo '</li>';
-                            }
-                        }
-                        echo '</ul>';
-                        echo '</div>';
-                        echo '</div>';
-                        echo '<script language="javascript">exp('."'$type'".')</script>';
-                        $element_count++;
-                }
-            }
-        }
+        $resource_titles = self::getResourceTitleList();
+        $element_count = self::parseResources($resource_titles, $course->resources, true, true);
 
         // Fixes forum order
         if (!empty($forum_categories)) {
@@ -282,12 +204,15 @@ class CourseSelectForm
             echo '<em id="img_'.$type.'" class="fa fa-minus-square-o fa-lg"></em>';
             echo '<span class="title">'.$resource_titles[RESOURCE_FORUM].'</span></div>';
             echo '<div class="item-content" id="div_'.$type.'">';
-
             echo '<ul class="list-backups-options">';
             foreach ($forum_categories as $forum_category_id => $forum_category) {
                 echo '<li>';
                 echo '<label class="checkbox">';
-                echo '<input type="checkbox" id="resource_'.RESOURCE_FORUMCATEGORY.'_'.$forum_category_id.'" my_rel="'.$forum_category_id.'" onclick="javascript:check_category(this);"  name="resource['.RESOURCE_FORUMCATEGORY.']['.$forum_category_id.']"  /> ';
+                echo '<input type="checkbox" 
+                    id="resource_'.RESOURCE_FORUMCATEGORY.'_'.$forum_category_id.'" 
+                    my_rel="'.$forum_category_id.'" 
+                    onclick="javascript:check_category(this);" 
+                    name="resource['.RESOURCE_FORUMCATEGORY.']['.$forum_category_id.']" /> ';
                 $forum_category->show();
                 echo '</label>';
                 echo '</li>';
@@ -298,7 +223,13 @@ class CourseSelectForm
                     foreach ($my_forums as $forum_id => $forum) {
                         echo '<li>';
                         echo '<label class="checkbox">';
-                        echo '<input type="checkbox" class="resource_forum" id="resource_'.RESOURCE_FORUM.'_'.$forum_id.'" onclick="javascript:check_forum(this);" my_rel="'.$forum_id.'" rel="'.$forum_category_id.'" name="resource['.RESOURCE_FORUM.']['.$forum_id.']"  />';
+                        echo '<input type="checkbox" 
+                            class="resource_forum" 
+                            id="resource_'.RESOURCE_FORUM.'_'.$forum_id.'" 
+                            onclick="javascript:check_forum(this);" 
+                            my_rel="'.$forum_id.'" 
+                            rel="'.$forum_category_id.'" 
+                            name="resource['.RESOURCE_FORUM.']['.$forum_id.']" />';
                         $forum->show();
                         echo '</label>';
                         echo '</li>';
@@ -309,7 +240,14 @@ class CourseSelectForm
                                 foreach ($my_forum_topics as $topic_id => $topic) {
                                     echo '<li>';
                                     echo '<label class="checkbox">';
-                                    echo '<input type="checkbox"  id="resource_'.RESOURCE_FORUMTOPIC.'_'.$topic_id.'" onclick="javascript:check_topic(this);" class="resource_topic" forum_id="'.$forum_id.'"  rel="'.$forum_id.'" cat_id="'.$forum_category_id.'" name="resource['.RESOURCE_FORUMTOPIC.']['.$topic_id.']"  />';
+                                    echo '<input 
+                                        type="checkbox" 
+                                        id="resource_'.RESOURCE_FORUMTOPIC.'_'.$topic_id.'" 
+                                        onclick="javascript:check_topic(this);" class="resource_topic" 
+                                        forum_id="'.$forum_id.'"  
+                                        rel="'.$forum_id.'" 
+                                        cat_id="'.$forum_category_id.'" 
+                                        name="resource['.RESOURCE_FORUMTOPIC.']['.$topic_id.']" />';
                                     $topic->show();
                                     echo '</label>';
                                     echo '</li>';
@@ -347,25 +285,23 @@ class CourseSelectForm
         }
 
         $recycleOption = isset($_POST['recycle_option']) ? true : false;
-
         if (empty($element_count)) {
             echo Display::return_message(get_lang('NoDataAvailable'), 'warning');
         } else {
             if (!empty($hidden_fields['destination_session'])) {
                 echo '<br />
-                        <button 
-                            class="save" 
-                            type="submit" 
-                            onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"), ENT_QUOTES, $charset))."'".')) return false;" >'.
+                      <button 
+                        class="save" 
+                        type="submit" 
+                        onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"), ENT_QUOTES, $charset))."'".')) return false;" >'.
                     get_lang('Ok').'</button>';
             } else {
                 if ($recycleOption) {
-                    echo '<br /><button class="save" type="submit">'.
-                        get_lang('Ok').'</button>';
+                    echo '<br /><button class="save" type="submit">'.get_lang('Ok').'</button>';
                 } else {
                     echo '<br />
                           <button 
-                                class="save" 
+                                class="save btn btn-primary" 
                                 type="submit" 
                                 onclick="checkLearnPath(\''.addslashes(get_lang('DocumentsWillBeAddedToo')).'\')">'.
                     get_lang('Ok').'</button>';
@@ -380,6 +316,127 @@ class CourseSelectForm
         echo '<div id="dynamic_div" style="display:block;margin-left:40%;margin-top:10px;height:50px;"></div>';
     }
 
+    /**
+     * @param array $resource_titles
+     * @param array $resourceList
+     * @param bool  $showHeader
+     * @param bool  $showItems
+     *
+     * @return int
+     */
+    public static function parseResources(
+        $resource_titles,
+        $resourceList,
+        $showHeader = true,
+        $showItems = true
+    ) {
+        $element_count = 0;
+        foreach ($resourceList as $type => $resources) {
+            if (count($resources) > 0) {
+                switch ($type) {
+                    // Resources to avoid
+                    case RESOURCE_FORUMCATEGORY:
+                        foreach ($resources as $id => $resource) {
+                            $forum_categories[$id] = $resource;
+                        }
+                        $element_count++;
+                        break;
+                    case RESOURCE_FORUM:
+                        foreach ($resources as $id => $resource) {
+                            $forums[$resource->obj->forum_category][$id] = $resource;
+                        }
+                        $element_count++;
+                        break;
+                    case RESOURCE_FORUMTOPIC:
+                        foreach ($resources as $id => $resource) {
+                            $forum_topics[$resource->obj->forum_id][$id] = $resource;
+                        }
+                        $element_count++;
+                        break;
+                    case RESOURCE_LINKCATEGORY:
+                    case RESOURCE_FORUMPOST:
+                    case RESOURCE_QUIZQUESTION:
+                    case RESOURCE_SURVEYQUESTION:
+                    case RESOURCE_SURVEYINVITATION:
+                    case RESOURCE_SCORM:
+                        break;
+                    default:
+                        if ($showHeader) {
+                            echo '<div class="item-backup" onclick="javascript:exp('."'$type'".');">';
+                            echo '<em id="img_'.$type.'" class="fa fa-plus-square-o fa-lg"></em>';
+                            echo '<span class="title">'.$resource_titles[$type].'</span>';
+                            echo '</div>';
+                            echo '<div class="item-content" id="div_'.$type.'">';
+                        }
+
+                        if ($type == RESOURCE_LEARNPATH) {
+                            echo Display::return_message(
+                                get_lang(
+                                    'ToExportLearnpathWithQuizYouHaveToSelectQuiz'
+                                ),
+                                'warning'
+                            );
+                            echo Display::return_message(
+                                get_lang(
+                                    'IfYourLPsHaveAudioFilesIncludedYouShouldSelectThemFromTheDocuments'
+                                ),
+                                'warning'
+                            );
+                        }
+
+                        if ($type == RESOURCE_DOCUMENT) {
+                            if (api_get_setting('show_glossary_in_documents') != 'none') {
+                                echo Display::return_message(
+                                    get_lang(
+                                        'ToExportDocumentsWithGlossaryYouHaveToSelectGlossary'
+                                    ),
+                                    'warning'
+                                );
+                            }
+                        }
+
+                        if ($showItems) {
+                            echo '<div class="well">';
+                            echo '<div class="btn-group">';
+                            echo "<a class=\"btn btn-default\" 
+                                        href=\"javascript: void(0);\" 
+                                        onclick=\"javascript: setCheckbox('$type',true);\" >".get_lang('All')."</a>";
+                            echo "<a class=\"btn btn-default\" 
+                                        href=\"javascript: void(0);\" 
+                                        onclick=\"javascript:setCheckbox('$type',false);\" >".get_lang('None')."</a>";
+                            echo '</div>';
+                            echo '<ul class="list-backups-options">';
+                            foreach ($resources as $id => $resource) {
+                                if ($resource) {
+                                    echo '<li>';
+                                    // Event obj in 1.9.x in 1.10.x the class is CalendarEvent
+                                    Resource::setClassType($resource);
+                                    echo '<label class="checkbox">';
+                                    echo '<input 
+                                        type="checkbox" 
+                                        name="resource['.$type.']['.$id.']"  
+                                        id="resource['.$type.']['.$id.']" />';
+                                    $resource->show();
+                                    echo '</label>';
+                                    echo '</li>';
+                                }
+                            }
+                            echo '</ul>';
+                            echo '</div>';
+                        }
+
+                        if ($showHeader) {
+                            echo '</div>';
+                            echo '<script language="javascript">exp('."'$type'".')</script>';
+                        }
+                        $element_count++;
+                }
+            }
+        }
+
+        return $element_count;
+    }
+
     /**
      * @param $course
      */
@@ -623,8 +680,11 @@ class CourseSelectForm
                                         }
                                     }
                                 }
-                                if (!isset($_POST['resource'][$type][$id]) && !$resource_is_used_elsewhere) {
-                                    unset($course->resources[$type][$id]);
+                                // quiz question can be, not attached to an exercise
+                                if ($type != RESOURCE_QUIZQUESTION) {
+                                    if (!isset($_POST['resource'][$type][$id]) && !$resource_is_used_elsewhere) {
+                                        unset($course->resources[$type][$id]);
+                                    }
                                 }
                             }
                         }
@@ -655,13 +715,13 @@ class CourseSelectForm
                     el.style.display = '';
                     if (document.getElementById('img_'+item).length)
                     document.getElementById('img_'+item).className('fa fa-minus-square-o fa-lg');
-                }
-                else{
+                } else {
                     el.style.display = 'none';
                     if (document.getElementById('img_'+item).length)
                     document.getElementById('img_'+item).className('fa fa-plus-square-o fa-lg');
                 }
             }
+
             function setCheckbox(type,value) {
                 d = document.course_select_form;
                 for (i = 0; i < d.elements.length; i++) {