Browse Source

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

Yannick Warnier 8 years ago
parent
commit
77e13fb5c3

+ 10 - 11
main/announcements/announcements.php

@@ -86,7 +86,6 @@ $searchFormToString = '';
 switch ($action) {
     case 'move':
         /* Move announcement up/down */
-
         if (!empty($_GET['down'])) {
             $thisAnnouncementId = intval($_GET['down']);
             $sortDirection = "DESC";
@@ -105,15 +104,15 @@ switch ($action) {
             $announcementInfo = AnnouncementManager::get_by_id($course_id, $thisAnnouncementId);
 
             $sql = "SELECT DISTINCT announcement.id, announcement.display_order
-                FROM $tbl_announcement announcement,
-				$tbl_item_property itemproperty
-				WHERE
-				    announcement.c_id =  $course_id AND
-				    itemproperty.c_id =  $course_id AND
-					itemproperty.ref = announcement.id AND
-                    itemproperty.tool = '".TOOL_ANNOUNCEMENT."'  AND
-                    itemproperty.visibility <> 2
-                ORDER BY display_order $sortDirection";
+                    FROM $tbl_announcement announcement,
+                    $tbl_item_property itemproperty
+                    WHERE
+                        announcement.c_id =  $course_id AND
+                        itemproperty.c_id =  $course_id AND
+                        itemproperty.ref = announcement.id AND
+                        itemproperty.tool = '".TOOL_ANNOUNCEMENT."'  AND
+                        itemproperty.visibility <> 2
+                    ORDER BY display_order $sortDirection";
             $result = Database::query($sql);
             $thisAnnouncementOrderFound = false;
             $thisAnnouncementOrder = null;
@@ -549,6 +548,7 @@ switch ($action) {
                             $sendToUsersInSession
                         );
                     }
+
                     Display::addFlash(
                         Display::return_message(
                             get_lang('AnnouncementAdded'),
@@ -565,7 +565,6 @@ switch ($action) {
                     }
                     header('Location: '.$homeUrl);
                     exit;
-
                 } // end condition token
             }
         }

+ 2 - 1
main/calendar/agenda.php

@@ -219,6 +219,7 @@ if (api_is_allowed_to_edit(false, true) ||
                     exit;
                 }
 
+                $usersToSend = isset($values['users_to_send']) ? $values['users_to_send'] : '';
                 // Editing normal event.
                 $agenda->editEvent(
                     $eventId,
@@ -227,7 +228,7 @@ if (api_is_allowed_to_edit(false, true) ||
                     $allDay,
                     $values['title'],
                     $values['content'],
-                    $values['users_to_send'],
+                    $usersToSend,
                     $attachmentList,
                     $attachmentCommentList,
                     $comment,

+ 1 - 0
main/course_info/download.php

@@ -1,5 +1,6 @@
 <?php
 /* For licensing terms, see /license.txt */
+
 use Chamilo\CourseBundle\Component\CourseCopy\CourseArchiver;
 
 /**

+ 1 - 1
main/cron/user_import/client.php

@@ -27,7 +27,7 @@ $response = $client->call(
     'import_users',
     array(
         'filepath' => api_get_path(SYS_UPLOAD_PATH)."users_import.csv",
-        'security_key' => $_configuration['security_key'],
+        'security_key' => api_get_configuration_value('security_key'),
     )
 );
 echo $response;

+ 0 - 15
main/document/create_document.php

@@ -502,21 +502,6 @@ if ($form->validate()) {
 		fclose($fp);
 		chmod($filepath.$filename.'.'.$extension, api_get_permissions_for_new_files());
 
-        /*
-		if (!is_dir($filepath.'css')) {
-			mkdir($filepath.'css', api_get_permissions_for_new_directories());
-			$doc_id = add_document($_course, $dir.'css', 'folder', 0, 'css');
-			api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'FolderCreated', $userId, null, null, null, null, $current_session_id);
-			api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'invisible', $userId, null, null, null, null, $current_session_id);
-		}
-
-		if (!is_file($filepath.'css/frames.css')) {
-			// Make a copy of the current css for the new document
-			copy(api_get_path(SYS_CODE_PATH).'css/'.api_get_setting('stylesheets').'/frames.css', $filepath.'css/frames.css');
-			$doc_id = add_document($_course, $dir.'css/frames.css', 'file', filesize($filepath.'css/frames.css'), 'frames.css');
-			api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $userId, null, null, null, null, $current_session_id);
-			api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'invisible', $userId, null, null, null, null, $current_session_id);
-		}*/
 
 		$file_size = filesize($filepath.$filename.'.'.$extension);
 		$save_file_path = $dir.$filename.'.'.$extension;

+ 3 - 2
main/document/downloadfolder.inc.php

@@ -1,13 +1,14 @@
 <?php
 /* For licensing terms, see /license.txt */
+
+use ChamiloSession as Session;
+
 /**
  *	Functions and main code for the download folder feature
  *
  *	@package chamilo.document
  */
 
-use ChamiloSession as Session;
-
 set_time_limit(0);
 
 require_once '../inc/global.inc.php';

+ 2 - 4
main/inc/email_editor.php

@@ -1,6 +1,8 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use ChamiloSession as Session;
+
 /**
  * This script contains the code to edit and send an e-mail to one of
  * the platform's users.
@@ -10,8 +12,6 @@
  * @author Julio Montoya <gugli100@gmail.com> Updating form with formvalidator
  */
 
-use ChamiloSession as Session;
-
 require_once '../inc/global.inc.php';
 
 if (empty($_user['user_id'])) {
@@ -31,12 +31,10 @@ $form->addElement('text', 'email_address', get_lang('EmailDestination'));
 $form->addElement('text', 'email_title', get_lang('EmailTitle'));
 $form->freeze('email_address');
 $form->addElement('textarea', 'email_text', get_lang('EmailText'), array('rows' => '6'));
-
 $form->addRule('email_address', get_lang('ThisFieldIsRequired'), 'required');
 $form->addRule('email_title', get_lang('ThisFieldIsRequired'), 'required');
 $form->addRule('email_text', get_lang('ThisFieldIsRequired'), 'required');
 $form->addRule('email_address', get_lang('EmailWrong'), 'email');
-
 $form->addButtonSend(get_lang('SendMail'));
 
 switch ($action) {

+ 2 - 3
main/inc/global_error_message.inc.php

@@ -49,7 +49,6 @@ $TechnicalIssuesTitle = 'Technical issues';
 $TechnicalIssuesDescription = 'This portal is currently experiencing technical issues. Please report this to the portal administrator. Thank you for your help.';
 
 if (is_int($global_error_code) && $global_error_code > 0) {
-
     if (class_exists('Template') && function_exists('api_get_configuration_value')) {
         $theme = Template::getThemeFallback().'/';
     } else {
@@ -58,7 +57,7 @@ if (is_int($global_error_code) && $global_error_code > 0) {
 
     $root_rel = '';
     $installation_guide_url = $root_rel.'documentation/installation_guide.html';
-    
+
     $css_path = 'app/Resources/public/css/';
     $css_web_assets = 'web/assets/';
     $css_web_path = 'web/css/';
@@ -251,7 +250,7 @@ if (is_int($global_error_code) && $global_error_code > 0) {
 </html>
 EOM;
     } else {
-        $global_error_message_page = 
+        $global_error_message_page =
 <<<EOM
     <!DOCTYPE html>
         <html>

+ 5 - 10
main/inc/introductionSection.inc.php

@@ -96,7 +96,6 @@ if ($intro_editAllowed) {
                 }
                 Database::getManager()->persist($toolIntro);
                 Database::getManager()->flush();
-
                 Display::addFlash(
                     Display::return_message(
                         get_lang('IntroductionTextUpdated'),
@@ -164,10 +163,9 @@ if (!empty($session_id)) {
     }
 }
 
-$intro_content = Security::remove_XSS($intro_content);
+$intro_content = Security::remove_XSS($intro_content, COURSEMANAGER);
 
 /* Determines the correct display */
-
 if ($intro_cmdEdit || $intro_cmdAdd) {
     $intro_dispDefault = false;
     $intro_dispForm = true;
@@ -190,7 +188,7 @@ if ($intro_dispForm) {
     $default['intro_content'] = $intro_content;
     $form->setDefaults($default);
     $introduction_section .= '<div id="courseintro" style="width: 98%">';
-    $introduction_section .= $form->return_form();
+    $introduction_section .= $form->returnForm();
     $introduction_section .= '</div>';
 }
 
@@ -209,7 +207,7 @@ if ($tool == TOOL_COURSE_HOMEPAGE && !isset($_GET['intro_cmdEdit'])) {
         $thematic_advance_info = $thematic->get_thematic_advance_list($last_done_advance);
         $subTitle1 = get_lang('CurrentTopic');
         $class1 = ' current';
-    } else if($displayMode == '2') {
+    } else if ($displayMode == '2') {
         // Show only the two next course progress steps
         // $information_title = get_lang('InfoAboutNextAdvanceNotDone');
         $last_done_advance = $thematic->get_next_thematic_advance_not_done();
@@ -217,7 +215,7 @@ if ($tool == TOOL_COURSE_HOMEPAGE && !isset($_GET['intro_cmdEdit'])) {
         $thematic_advance_info = $thematic->get_thematic_advance_list($last_done_advance);
         $thematic_advance_info2 = $thematic->get_thematic_advance_list($next_advance_not_done);
         $subTitle1 = $subTitle2 = get_lang('NextTopic');
-    } else if($displayMode == '3') {
+    } else if ($displayMode == '3') {
         // Show the current and next course progress steps
         // $information_title = get_lang('InfoAboutLastDoneAdvanceAndNextAdvanceNotDone');
         $last_done_advance =  $thematic->get_last_done_thematic_advance();
@@ -232,8 +230,7 @@ if ($tool == TOOL_COURSE_HOMEPAGE && !isset($_GET['intro_cmdEdit'])) {
     if (!empty($thematic_advance_info)) {
         $thematic_advance = get_lang('CourseThematicAdvance');
         $thematicScore = $thematic->get_total_average_of_thematic_advances() . '%';
-        $thematicUrl = api_get_path(WEB_CODE_PATH) .
-            'course_progress/index.php?action=thematic_details&'.api_get_cidreq();
+        $thematicUrl = api_get_path(WEB_CODE_PATH).'course_progress/index.php?action=thematic_details&'.api_get_cidreq();
         $thematic_info = $thematic->get_thematic_list(
             $thematic_advance_info['thematic_id']
         );
@@ -283,8 +280,6 @@ if ($tool == TOOL_COURSE_HOMEPAGE && !isset($_GET['intro_cmdEdit'])) {
                     </div>
                 </div>';
         }
-
-
         $thematicPanel = '<div class="row">';
         $thematicPanel .= '<div class="col-md-2">' . $infoUser . '</div>';
         $thematicPanel .= '<div class="col-md-10"><div class="row">' . $thematicItemOne . $thematicItemTwo . '</div></div>';

+ 10 - 0
main/inc/lib/AnnouncementEmail.php

@@ -307,6 +307,10 @@ class AnnouncementEmail
         // Send email one by one to avoid antispam
         $users = $this->sent_to();
 
+        $batchSize = 20;
+        $counter = 1;
+        $em = Database::getManager();
+
         foreach ($users as $user) {
             $message = $this->message($user['user_id']);
             MessageManager::send_message_simple(
@@ -317,6 +321,12 @@ class AnnouncementEmail
                 $sendToDrhUsers,
                 true
             );
+
+            if (($counter % $batchSize) === 0) {
+                $em->flush();
+                $em->clear();
+            }
+            $counter++;
         }
 
         if ($sendToUsersInSession) {

+ 38 - 16
main/inc/lib/AnnouncementManager.php

@@ -153,11 +153,17 @@ class AnnouncementManager
     /**
      * Deletes an announcement
      * @param array $_course the course array
-     * @param int 	$id the announcement id
+     * @param int $id the announcement id
      */
     public static function delete_announcement($_course, $id)
     {
-        api_item_property_update($_course, TOOL_ANNOUNCEMENT, $id, 'delete', api_get_user_id());
+        api_item_property_update(
+            $_course,
+            TOOL_ANNOUNCEMENT,
+            $id,
+            'delete',
+            api_get_user_id()
+        );
     }
 
     /**
@@ -387,13 +393,13 @@ class AnnouncementManager
 
     /**
      * Store an announcement in the database (including its attached file if any)
-     * @param string    Announcement title (pure text)
-     * @param string    Content of the announcement (can be HTML)
-     * @param int       Display order in the list of announcements
-     * @param array     Array of users and groups to send the announcement to
-     * @param array	    uploaded file $_FILES
-     * @param string    Comment describing the attachment
-     * @param bool  $sendToUsersInSession
+     * @param string $emailTitle   Announcement title (pure text)
+     * @param string $newContent   Content of the announcement (can be HTML)
+     * @param array  $sentTo      Array of users and groups to send the announcement to
+     * @param array   $file     uploaded file $_FILES
+     * @param string  $file_comment  Comment describing the attachment
+     * @param string $end_date
+     * @param bool $sendToUsersInSession
      * @return int      false on failure, ID of the announcement on success
      */
     public static function add_announcement(
@@ -458,8 +464,11 @@ class AnnouncementManager
             } else {
                 $send_to = CourseManager::separateUsersGroups($sentTo);
 
+                $batchSize = 20;
+                $em = Database::getManager();
                 // Storing the selected groups
                 if (is_array($send_to['groups']) && !empty($send_to['groups'])) {
+                    $counter = 1;
                     foreach ($send_to['groups'] as $group) {
                         api_item_property_update(
                             $_course,
@@ -469,11 +478,18 @@ class AnnouncementManager
                             api_get_user_id(),
                             $group
                         );
+
+                        if (($counter % $batchSize) === 0) {
+                             $em->flush();
+                             $em->clear();
+                        }
+                        $counter++;
                     }
                 }
 
                 // Storing the selected users
                 if (is_array($send_to['users'])) {
+                    $counter = 1;
                     foreach ($send_to['users'] as $user) {
                         api_item_property_update(
                             $_course,
@@ -484,6 +500,12 @@ class AnnouncementManager
                             '',
                             $user
                         );
+
+                        if (($counter % $batchSize) === 0) {
+                             $em->flush();
+                             $em->clear();
+                        }
+                        $counter++;
                     }
                 }
             }
@@ -1206,8 +1228,11 @@ class AnnouncementManager
      * @param bool $sendToUsersInSession
      * @param bool $sendToDrhUsers
      */
-    public static function send_email($id, $sendToUsersInSession = false, $sendToDrhUsers = false)
-    {
+    public static function send_email(
+        $id,
+        $sendToUsersInSession = false,
+        $sendToDrhUsers = false
+    ) {
         $email = AnnouncementEmail::create(null, $id);
         $email->send($sendToUsersInSession, $sendToDrhUsers);
     }
@@ -1278,7 +1303,7 @@ class AnnouncementManager
 
             //if (!empty($user_id)) {
             if (0) {
-                if (is_array($group_memberships) && count($group_memberships) > 0 ) {
+                if (is_array($group_memberships) && count($group_memberships) > 0) {
                     $sql = "SELECT $select
                             FROM $tbl_announcement announcement, $tbl_item_property ip
                             WHERE
@@ -1325,7 +1350,6 @@ class AnnouncementManager
                         ORDER BY display_order DESC";
                 //GROUP BY ip.ref
             } else {
-
                 // A.3 you are a course admin without any group or user filter
                 // A.3.a you are a course admin without user or group filter but WITH studentview
                 // => see all the messages of all the users and groups without editing possibilities
@@ -1402,7 +1426,6 @@ class AnnouncementManager
                             AND ip.visibility='1'
                         ORDER BY display_order DESC";
             } else {
-
                 if ($user_id) {
                     if ($allowUserEditSetting && !api_is_anonymous()) {
                         $cond_user_id = " AND (
@@ -1426,7 +1449,6 @@ class AnnouncementManager
     						AND ip.visibility='1'
     						AND announcement.session_id IN(0, ".$session_id.")
 						ORDER BY display_order DESC";
-
                 } else {
                     if (($allowUserEditSetting && !api_is_anonymous())) {
                         $cond_user_id = " AND (
@@ -1691,7 +1713,7 @@ class AnnouncementManager
                         }
 
                         // the user is not identiefied => show only the general announcements
-                        $sql="SELECT announcement.*, ip.visibility, ip.to_group_id, ip.insert_user_id
+                        $sql = "SELECT announcement.*, ip.visibility, ip.to_group_id, ip.insert_user_id
                                 FROM $tbl_announcement announcement, $tbl_item_property ip
                                 WHERE
                                     announcement.c_id = $course_id AND

+ 14 - 21
main/inc/lib/MoodleImport.php

@@ -32,7 +32,12 @@ class MoodleImport
             }
 
             if (!$mainFileKey) {
-                Display::addFlash(Display::return_message(get_lang('FailedToImportThisIsNotAMoodleFile'), 'error'));
+                Display::addFlash(
+                    Display::return_message(
+                        get_lang('FailedToImportThisIsNotAMoodleFile'),
+                        'error'
+                    )
+                );
             }
 
             $folder = api_get_unique_id();
@@ -45,7 +50,7 @@ class MoodleImport
 
             mkdir($destinationDir, api_get_permissions_for_new_directories(), true);
 
-            $newFolderData = create_unexisting_directory(
+            create_unexisting_directory(
                 $courseInfo,
                 api_get_user_id(),
                 $sessionId,
@@ -90,7 +95,7 @@ class MoodleImport
                                 // Create a Forum category based on Moodle forum type.
                                 $catForumValues['forum_category_title'] = $moduleValues['type'];
                                 $catForumValues['forum_category_comment'] = '';
-                                $catId = store_forumcategory($catForumValues, [], false);
+                                $catId = store_forumcategory($catForumValues, $courseInfo, false);
                                 $forumValues = [];
                                 $forumValues['forum_title'] = $moduleValues['name'];
                                 $forumValues['forum_image'] = '';
@@ -98,10 +103,9 @@ class MoodleImport
                                 $forumValues['forum_category'] = $catId;
                                 $forumValues['moderated'] = 0;
 
-                                store_forum($forumValues);
+                                store_forum($forumValues, $courseInfo);
                                 break;
                             case 'quiz':
-
                                 // Read the current quiz module xml.
                                 // The quiz case is the very complicate process of all the import.
                                 // Please if you want to review the script, try to see the readingXML functions.
@@ -117,7 +121,7 @@ class MoodleImport
                                 // var_dump($moduleValues); // <-- uncomment this to see the final array
 
                                 // Lets do this ...
-                                $exercise = new Exercise();
+                                $exercise = new Exercise($courseInfo['real_id']);
                                 $exercise->updateTitle(Exercise::format_title_variable($moduleValues['name']));
                                 $exercise->updateDescription($moduleValues['intro']);
                                 $exercise->updateAttempts($moduleValues['attempts_number']);
@@ -177,7 +181,7 @@ class MoodleImport
                                         $questionList = $moduleValues['question_instances'][$index]['plugin_qtype_'.$qType.'_question'];
                                         $currentQuestion = $moduleValues['question_instances'][$index];
 
-                                        $result = $this->processAnswers($questionList, $qType, $questionInstance, $currentQuestion);
+                                        $this->processAnswers($questionList, $qType, $questionInstance, $currentQuestion);
                                     }
                                 }
 
@@ -337,6 +341,7 @@ class MoodleImport
             }
 
             $currentItem['contextid'] = $contextId;
+
             return $currentItem;
         }
 
@@ -464,7 +469,7 @@ class MoodleImport
     }
 
     /**
-     * Search the current quiestion resource in main Questions XML
+     * Search the current question resource in main Questions XML
      *
      * @param resource $questionsXml XML file
      * @param int $questionId
@@ -617,13 +622,9 @@ class MoodleImport
                 break;
             case 'multianswer':
                 $objAnswer = new Answer($questionInstance->id);
-
                 $coursePath = api_get_course_path();
-
                 $placeholder = str_replace('@@PLUGINFILE@@', '/courses/' . $coursePath . '/document/moodle', $currentQuestion['questiontext']);
-
                 $optionsValues = [];
-
                 foreach ($questionList as $slot => $subQuestion) {
                     $qtype = $subQuestion['qtype'];
                     $optionsValues[] = $this->processFillBlanks($objAnswer, $qtype, $subQuestion['plugin_qtype_'.$qtype.'_question'], $placeholder, $slot + 1);
@@ -794,13 +795,11 @@ class MoodleImport
      */
     public function processFillBlanks($objAnswer, $questionType, $answerValues, &$placeholder, $position)
     {
-
         $coursePath = api_get_course_path();
 
         switch ($questionType) {
             case 'multichoice':
                 $optionsValues = [];
-
                 $correctAnswer = '';
                 $othersAnswer = '';
                 foreach ($answerValues as $answer) {
@@ -818,13 +817,10 @@ class MoodleImport
                 $placeholder = str_replace("{#$position}", $currentAnswers, $placeholder);
 
                 return $optionsValues;
-
                 break;
             case 'shortanswer':
                 $optionsValues = [];
-
                 $correctAnswer = '';
-
                 foreach ($answerValues as $answer) {
                     $correct = intval($answer['fraction']);
                     if ($correct) {
@@ -838,7 +834,6 @@ class MoodleImport
                 $placeholder = str_replace("{#$position}", $currentAnswers, $placeholder);
 
                 return $optionsValues;
-
                 break;
             case 'match':
                 $answers = [];
@@ -893,7 +888,6 @@ class MoodleImport
         if ($moduleRes) {
             $activities = $moduleDoc->getElementsByTagName('file');
             foreach ($activities as $activity) {
-
                 $currentItem = [];
                 $thisIsAnInvalidItem = false;
 
@@ -953,5 +947,4 @@ class MoodleImport
             }
         }
     }
-
-}
+}

+ 2 - 1
main/inc/lib/api.lib.php

@@ -2,6 +2,7 @@
 /* For licensing terms, see /license.txt */
 
 use ChamiloSession as Session;
+use Chamilo\CourseBundle\Entity\CItemProperty;
 
 /**
  * This is a code library for Chamilo.
@@ -3717,7 +3718,7 @@ function api_item_property_update(
         $startVisibleDate = !empty($start_visible) ? new DateTime($start_visible, new DateTimeZone('UTC')) : null;
         $endVisibleDate = !empty($endVisibleDate) ? new DateTime($endVisibleDate, new DateTimeZone('UTC')) : null;
 
-        $cItemProperty = new \Chamilo\CourseBundle\Entity\CItemProperty($objCourse);
+        $cItemProperty = new CItemProperty($objCourse);
         $cItemProperty
             ->setTool($tool)
             ->setRef($item_id)

+ 17 - 15
main/inc/lib/tracking.lib.php

@@ -3381,13 +3381,15 @@ class Tracking
             }
 
             $sql = "SELECT count(ip.tool) AS count
-                    FROM $tbl_item_property ip INNER JOIN $tbl_document pub
-                            ON ip.ref = pub.id
-                    WHERE 	ip.c_id  = $course_id AND
-                            pub.c_id  = $course_id AND
-                            pub.filetype ='file' AND
-                            ip.tool = 'document'
-                            $condition_user $condition_session ";
+                    FROM $tbl_item_property ip 
+                    INNER JOIN $tbl_document pub
+                    ON (ip.ref = pub.id AND ip.c_id = pub.c_id)
+                    WHERE 	
+                        ip.c_id  = $course_id AND
+                        pub.c_id  = $course_id AND
+                        pub.filetype ='file' AND
+                        ip.tool = 'document'
+                        $condition_user $condition_session ";
             $rs = Database::query($sql);
             $row = Database::fetch_array($rs, 'ASSOC');
             return $row['count'];
@@ -3438,7 +3440,8 @@ class Tracking
 
         $sql = "SELECT count(ip.tool) as count
                 FROM $tbl_item_property ip
-                INNER JOIN $tbl_student_publication pub ON ip.ref = pub.id
+                INNER JOIN $tbl_student_publication pub 
+                ON (ip.ref = pub.id AND ip.c_id = pub.c_id)
                 WHERE
                     ip.tool='work' AND
                     $conditionToString";
@@ -3465,7 +3468,7 @@ class Tracking
         $courseCondition = null;
         $conditions = array();
         if (!empty($courseInfo)) {
-            $course_id	    = $courseInfo['real_id'];
+            $course_id = $courseInfo['real_id'];
             $conditions[]= " post.c_id  = $course_id AND forum.c_id = $course_id ";
         }
 
@@ -3489,7 +3492,7 @@ class Tracking
         $conditionsToString = implode('AND ', $conditions);
         $sql = "SELECT count(poster_id) as count
                 FROM $tbl_forum_post post INNER JOIN $tbl_forum forum
-                ON forum.forum_id = post.forum_id
+                ON (forum.forum_id = post.forum_id AND forum.c_id = post.c_id)
                 WHERE $conditionsToString";
 
         $rs = Database::query($sql);
@@ -3651,7 +3654,7 @@ class Tracking
         $sql = "SELECT count(*)
                 FROM $tbl_forums f
                 INNER JOIN $item i
-                    ON f.c_id = i.c_id AND f.iid = i.ref AND tool = '".TOOL_FORUM."'
+                ON f.c_id = i.c_id AND f.iid = i.ref AND tool = '".TOOL_FORUM."'
                 WHERE
                     f.c_id = $course_id AND
                     $groupCondition
@@ -3741,9 +3744,9 @@ class Tracking
 
     /**
      * Get count student's visited links
-     * @param    int        Student id
-     * @param    int    $courseId
-     * @param    int        Session id (optional)
+     * @param    int $student_id Student id
+     * @param    int $courseId
+     * @param    int $session_id Session id (optional)
      * @return    int        count of visited links
      */
     public static function count_student_visited_links($student_id, $courseId, $session_id = 0)
@@ -3887,7 +3890,6 @@ class Tracking
                             session_course_user.c_id = ' . $courseId . ' AND
                             stats_login.login_course_date IS NULL
                         GROUP BY session_course_user.user_id';
-
             }
         }
 

+ 1 - 2
main/inc/local.inc.php

@@ -487,8 +487,7 @@ if (!empty($_SESSION['_user']['user_id']) && !($login || $logout)) {
                     }
 
                     header(
-                        'Location: '.api_get_path(WEB_PATH)
-                        .'index.php?loginFailed=1&error=user_password_incorrect'
+                        'Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=user_password_incorrect'
                     );
                     exit;
                 }

+ 2 - 1
main/install/index.php

@@ -881,8 +881,9 @@ if (@$_POST['step2']) {
         $connection->executeQuery("ALTER TABLE faq_category_translation ADD CONSTRAINT FK_5493B0FC2C2AC5D3 FOREIGN KEY (translatable_id) REFERENCES faq_category (id) ON DELETE CASCADE;");
         $connection->executeQuery("ALTER TABLE faq_question ADD CONSTRAINT FK_4A55B05912469DE2 FOREIGN KEY (category_id) REFERENCES faq_category (id);");
         */
+
         // Add version table
-        $connection->executeQuery('CREATE TABLE version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(20), PRIMARY KEY(id), UNIQUE(version))');
+        $connection->executeQuery('CREATE TABLE IF NOT EXISTS version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(20), PRIMARY KEY(id), UNIQUE(version))');
 
         // Tickets
         $ticketProject = new TicketProject();

+ 6 - 1
main/install/install.lib.php

@@ -2776,9 +2776,14 @@ function finishInstallation(
     updateDirAndFilesPermissions();
 
     // Set the latest version
-    $path = api_get_path(SYS_PATH).'app/Migrations/Schema/V111/';
+    $path = $sysPath.'app/Migrations/Schema/V111/';
     $finder = new \Symfony\Component\Finder\Finder();
     $files = $finder->files()->in($path);
+
+    // Needed for chash
+    $sql = 'CREATE TABLE IF NOT EXISTS version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(255), PRIMARY KEY(id), UNIQUE(version));';
+    Database::query($sql);
+
     foreach ($files as $version) {
         $version = str_replace(['Version',  '.php' ], '', $version->getFilename());
         $sql = "INSERT INTO version (version) VALUES ('$version')";

+ 14 - 0
plugin/vchamilo/README.md

@@ -6,6 +6,20 @@ Authors : Valery Fremaux (valery.fremaux@gmail.com), Julio Montoya
 Virtual chamilo is a feature that allows running several chamilo instances sharing the same
 code base.
 
+Changelog
+=========
+
+Version 1.4
+
+Database upgrade needed: 
+
+ALTER TABLE vchamilo ADD COLUMN password_encryption VARCHAR(255);
+
+Version 1.3
+
+Add vchamilo import
+
+
 Version features
 ===================
 This is a yet prototypal version that is not full featured in back-office tools.

+ 2 - 1
plugin/vchamilo/install.php

@@ -36,8 +36,9 @@ $sql = "CREATE TABLE IF NOT EXISTS $tablename (
   `lastcron` int(11),
   `croncount` int(11),
   `template` varchar(255),
+  `password_encryption` varchar(255),  
   PRIMARY KEY (`id`)
-) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
+) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
 ";
 Database::query($sql);
 

+ 1 - 1
plugin/vchamilo/lib/VChamiloPlugin.php

@@ -16,7 +16,7 @@ class VChamiloPlugin extends Plugin
      */
     public function __construct()
     {
-        parent::__construct('1.3', 'Valery Fremaux, Julio Montoya');
+        parent::__construct('1.4', 'Valery Fremaux, Julio Montoya');
     }
 
     /**

+ 35 - 9
plugin/vchamilo/lib/Virtual.php

@@ -16,7 +16,7 @@ class Virtual
     /**
      * @param array $_configuration
      */
-    public static function hookConfiguration(&$_configuration)
+    public static function hookConfiguration(& $_configuration)
     {
         global $virtualChamilo;
 
@@ -55,6 +55,7 @@ class Virtual
             $coursePath = '';
             $archivePath = '';
             $uploadPath = '';
+            $passwordEncryption = '';
 
             foreach ($virtualSettings as $setting) {
                 switch ($setting['variable']) {
@@ -70,6 +71,9 @@ class Virtual
                     case 'vchamilo_archive_real_root':
                         $archivePath = $setting['selected_value'];
                         break;
+                    case 'vchamilo_password_encryption':
+                        $passwordEncryption = $setting['selected_value'];
+                        break;
                 }
             }
 
@@ -92,6 +96,10 @@ class Virtual
                 $data['SYS_COURSE_PATH'] = $coursePath.'/'.$data['slug'];
                 $data['SYS_UPLOAD_PATH'] = $uploadPath.'/'.$data['slug'];
 
+                if (!empty($passwordEncryption)) {
+                    $_configuration['password_encryption'] = $passwordEncryption;
+                }
+
                 $virtualChamilo = $data;
             } else {
                 exit("This portal is disabled. Please contact your administrator");
@@ -967,8 +975,9 @@ class Virtual
 
     /**
      * @param stdClass $data
+     * @param string $fromVersion
      */
-    public static function importInstance($data)
+    public static function importInstance($data, $fromVersion)
     {
         if (isset($data->what)) {
             unset($data->what);
@@ -1061,6 +1070,7 @@ class Virtual
         }
 
         if (!$id) {
+            var_dump($data);
             throw new Exception('Was not registered');
         }
 
@@ -1069,7 +1079,6 @@ class Virtual
         }
 
         self::createDirsFromSlug($slug);
-        self::ctrace("Create database");
         $databaseCreated = Virtual::createDatabase($newDatabase);
         if (!$databaseCreated) {
             Display::addFlash(
@@ -1078,6 +1087,10 @@ class Virtual
             return false;
         }
 
+        $coursePath = self::getConfig('vchamilo', 'course_real_root').'/'.$slug;
+        $homePath = self::getConfig('vchamilo', 'home_real_root').'/'.$slug;
+        $uploadPath = self::getConfig('vchamilo', 'upload_real_root').'/'.$slug;
+
         $dumpFile = api_get_path(SYS_ARCHIVE_PATH).uniqid($data->main_database.'_dump_', true).'.sql';
         self::ctrace('Create backup from "'.$data->main_database.'" here: '.$dumpFile.' ');
         Virtual::backupDatabase($data, $dumpFile);
@@ -1117,7 +1130,7 @@ class Virtual
         $outputStream = new \Symfony\Component\Console\Output\BufferedOutput($tmpFile);
 
         $arguments = array(
-            'from-version' => '1.10.0', // @todo change value
+            'from-version' => $fromVersion, // @todo change value
             'to-version' => '1.11.x',
             'host' => $newDatabase->db_host,
             'username' => $newDatabase->db_user,
@@ -1129,16 +1142,12 @@ class Virtual
         $input = new ArrayInput($arguments);
         $command->run($input, $outputStream);
 
-        Display::addFlash(Display::return_message($outputStream->fetch()));
+        error_log($outputStream->fetch());
 
         if (file_exists($dumpFile)) {
             unlink($dumpFile);
         }
 
-        $coursePath = self::getConfig('vchamilo', 'course_real_root').'/'.$slug;
-        $homePath = self::getConfig('vchamilo', 'home_real_root').'/'.$slug;
-        $uploadPath = self::getConfig('vchamilo', 'upload_real_root').'/'.$slug;
-
         // Course
         self::ctrace("Copy from '$fromCoursePath' to backup '$coursePath' ");
         copyDirTo(
@@ -1276,5 +1285,22 @@ class Virtual
 
         return false;
     }
+
+    /**
+     * @return array
+     */
+    public static function getEncryptList()
+    {
+        $encryptList = [
+            'bcrypt',
+            'sha1',
+            'md5',
+            'none'
+        ];
+
+        return array_combine($encryptList, $encryptList);
+    }
+
+
 }
 

+ 1 - 0
plugin/vchamilo/vcron.php

@@ -1,4 +1,5 @@
 <?php
+exit;
 /**
  * This file is a cron microclock script.
  * It will be used as replacement of setting individual

+ 8 - 2
plugin/vchamilo/views/editinstance_form.php

@@ -352,9 +352,7 @@ class InstanceForm extends ChamiloForm
         $form->addHeader($plugin->get_lang('hostdefinition'));
         $form->addText('sitename', [$plugin->get_lang('sitename'), $plugin->get_lang('SiteNameExample')]);
         $form->applyFilter('sitename', 'trim');
-
         $form->addText('institution', [$plugin->get_lang('institution'), $plugin->get_lang('InstitutionExample')]);
-
         $form->applyFilter('institution', 'trim');
 
         // Host's name.
@@ -366,6 +364,14 @@ class InstanceForm extends ChamiloForm
         $form->applyFilter('root_web', 'trim');
 
         if ($this->_mode == 'update') {
+            $encryptList = Virtual::getEncryptList();
+            $encryptMethod = $form->addElement(
+                'select',
+                'password_encryption',
+                get_lang('EncryptMethodUserPass'),
+                $encryptList
+            );
+            $encryptMethod->freeze();
             $elementWeb->freeze();
         }
 

+ 27 - 1
plugin/vchamilo/views/import.php

@@ -45,6 +45,29 @@ $form->addText(
     true
 );
 
+$encryptList = Virtual::getEncryptList();
+
+$form->addSelect(
+    'password_encryption',
+    get_lang('EncryptMethodUserPass'),
+    $encryptList
+);
+
+$encryptList = Virtual::getEncryptList();
+
+$versionList = [
+    '1.11.x',
+    '1.10.x',
+    '1.9.x'
+];
+
+$form->addSelect(
+    'version',
+    get_lang('FromVersion'),
+    array_combine($versionList, $versionList)
+);
+
+
 $form->addText(
     'course_path',
     [
@@ -143,8 +166,11 @@ if ($form->validate()) {
         $vchamilo->course_path = $values['course_path'];
         $vchamilo->home_path = $values['home_path'];
         $vchamilo->upload_path = $values['upload_path'];
+        $vchamilo->password_encryption = $values['password_encryption'];
+
+        Virtual::importInstance($vchamilo, $values['version']);
 
-        Virtual::importInstance($vchamilo);
+        Virtual::redirect(api_get_path(WEB_PLUGIN_PATH).'vchamilo/views/manage.php');
     }
 }
 

+ 10 - 9
src/Chamilo/CourseBundle/Component/CourseCopy/CourseArchiver.php

@@ -42,17 +42,18 @@ class CourseArchiver
     public static function cleanBackupDir()
     {
         $dir = self::getBackupDir();
-
-        if ($handle = @ opendir($dir)) {
-            while (($file = readdir($handle)) !== false) {
-                if ($file != "." && $file != ".." &&
-                    strpos($file, 'CourseArchiver_') === 0 &&
-                    is_dir($dir . '/' . $file)
-                ) {
-                    rmdirr($dir . '/' . $file);
+        if (is_dir($dir)) {
+            if ($handle = @ opendir($dir)) {
+                while (($file = readdir($handle)) !== false) {
+                    if ($file != "." && $file != ".." &&
+                        strpos($file, 'CourseArchiver_') === 0 &&
+                        is_dir($dir.'/'.$file)
+                    ) {
+                        rmdirr($dir.'/'.$file);
+                    }
                 }
+                closedir($handle);
             }
-            closedir($handle);
         }
     }