Browse Source

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

aragonc 9 years ago
parent
commit
7a9b4629e9

+ 0 - 1
app/Migrations/Schema/V110/Version20150805161000.php

@@ -1,5 +1,4 @@
 <?php
-
 /* For licensing terms, see /license.txt */
 
 namespace Application\Migrations\Schema\V110;

+ 29 - 0
app/Migrations/Schema/V110/Version20150810132615.php

@@ -0,0 +1,29 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Application\Migrations\Schema\V110;
+
+use Application\Migrations\AbstractMigrationChamilo;
+use Doctrine\DBAL\Schema\Schema;
+
+/**
+ * Calendar color
+ */
+class Version20150810132615 extends AbstractMigrationChamilo
+{
+    /**
+     * @param Schema $schema
+     */
+    public function up(Schema $schema)
+    {
+        $this->addSql('ALTER TABLE personal_agenda ADD color VARCHAR(255) DEFAULT NULL');
+    }
+
+    /**
+     * @param Schema $schema
+     */
+    public function down(Schema $schema)
+    {
+        $this->addSql('ALTER TABLE personal_agenda DROP color');
+    }
+}

+ 9 - 10
main/exercice/exercise.class.php

@@ -2495,12 +2495,11 @@ class Exercise
                         }
                     }
                     break;
-                // for fill in the blanks
                 case FILL_IN_BLANKS:
 
                     // insert the student result in the track_e_attempt table, field answer
                     // $answer is the answer like in the c_quiz_answer table for the question
-                    // student datas are choice[]
+                    // student data are choice[]
 
                     $listCorrectAnswers = FillBlanks::getAnswerInfo($answer);
                     $switchableAnswerSet = $listCorrectAnswers["switchable"];
@@ -2509,12 +2508,13 @@ class Exercise
 
                     // get existing user data in n the BDD
                     if ($from_database) {
-                        $queryfill = "SELECT answer
-                                      FROM $TBL_TRACK_ATTEMPT
-                                      WHERE exe_id = $exeId
-                                      AND question_id= ".intval($questionId);
-                        $resfill = Database::query($queryfill);
-                        $str = Database::result($resfill, 0, 'answer');
+                        $sql = "SELECT answer
+                                FROM $TBL_TRACK_ATTEMPT
+                                WHERE
+                                    exe_id = $exeId AND
+                                    question_id= ".intval($questionId);
+                        $result = Database::query($sql);
+                        $str = Database::result($result, 0, 'answer');
 
                         $listStudentResults = FillBlanks::getAnswerInfo($str, true);
                         $choice = $listStudentResults['studentanswer'];
@@ -2549,9 +2549,7 @@ class Exercise
                     } else {
                         // switchable answer
                         $listStudentAnswerTemp = $choice;
-
                         $listTeacherAnswerTemp = $listCorrectAnswers['tabwords'];
-                        $listBadAnswerIndice = array();
                         // for every teacher answer, check if there is a student answer
                         for ($i=0; $i < count($listStudentAnswerTemp); $i++) {
                             $studentAnswer = trim($listStudentAnswerTemp[$i]);
@@ -2575,6 +2573,7 @@ class Exercise
                             }
                         }
                     }
+
                     $answer = FillBlanks::getAnswerInStudentAttempt($listCorrectAnswers);
 
                     // the question is encoded like this

+ 101 - 41
main/exercice/fill_blanks.class.php

@@ -33,8 +33,6 @@ class FillBlanks extends Question
      */
     public function createAnswersForm($form)
     {
-        $fillBlanksAllowedSeparator = self::getAllowedSeparator();
-
         $defaults = array();
 
         if (!empty($this->id)) {
@@ -57,10 +55,8 @@ class FillBlanks extends Question
             $blanksepartornumber = 0;
         }
 
-        $blankSeparatortStart = self::getStartSeparator($blanksepartornumber);
-        $blankSeparatortEnd = self::getEndSeparator($blanksepartornumber);
-        $blankSeparatortStartRegexp = self::escapeForRegexp($blankSeparatortStart);
-        $blankSeparatortEndRegexp = self::escapeForRegexp($blankSeparatortEnd);
+        $blankSeparatorStart = self::getStartSeparator($blanksepartornumber);
+        $blankSeparatorEnd = self::getEndSeparator($blanksepartornumber);
 
         $setValues = null;
 
@@ -72,8 +68,8 @@ class FillBlanks extends Question
         // javascript
         echo '<script>
 
-            var blankSeparatortStart = "'.$blankSeparatortStart.'";
-            var blankSeparatortEnd = "'.$blankSeparatortEnd.'";
+            var blankSeparatortStart = "'.$blankSeparatorStart.'";
+            var blankSeparatortEnd = "'.$blankSeparatorEnd.'";
             var blankSeparatortStartRegexp = getBlankSeparatorRegexp(blankSeparatortStart);
             var blankSeparatortEndRegexp = getBlankSeparatorRegexp(blankSeparatortEnd);
 
@@ -287,7 +283,7 @@ class FillBlanks extends Question
     }
 
     /**
-     * abstract function which creates the form to create / edit the answers of the question
+     * Function which creates the form to create/edit the answers of the question
      * @param FormValidator $form
      */
     public function processAnswersCreation($form)
@@ -295,15 +291,15 @@ class FillBlanks extends Question
         global $charset;
 
         $answer = $form->getSubmitValue('answer');
-        //var_dump($answer);
-        // Due the fckeditor transform the elements to their HTML value
-        $answer = api_html_entity_decode($answer, ENT_QUOTES, $charset);
+        // Due the ckeditor transform the elements to their HTML value
+
+        //$answer = api_html_entity_decode($answer, ENT_QUOTES, $charset);
+        //$answer = htmlentities(api_utf8_encode($answer));
 
         // remove the :: eventually written by the user
         $answer = str_replace('::', '', $answer);
 
         // remove starting and ending space and &nbsp;
-
         $answer = api_preg_replace("/\xc2\xa0/", " ", $answer);
 
         // start and end separator
@@ -420,6 +416,7 @@ class FillBlanks extends Question
             <tr>
                 <th>'.get_lang("Answer").'</th>
             </tr>';
+
         return $header;
     }
 
@@ -485,14 +482,16 @@ class FillBlanks extends Question
                 $result = Display::input('text', "choice[$questionId][]", $correctItem, $attributes);
                 break;
         }
+
         return $result;
     }
 
-
     /**
-     * Return an array with the different choices available when the answers between bracket show as a menu
-     * @param $correctAnswer
-     * @param $displayForStudent  true if we want to shuffle the choices of the menu for students
+     * Return an array with the different choices available
+     * when the answers between bracket show as a menu
+     * @param string $correctAnswer
+     * @param bool $displayForStudent true if we want to shuffle the choices of the menu for students
+     *
      * @return array
      */
     public static function getFillTheBlankMenuAnswers($correctAnswer, $displayForStudent)
@@ -502,15 +501,16 @@ class FillBlanks extends Question
         if ($displayForStudent) {
             shuffle($listChoises);
         }
+
         return $listChoises;
     }
 
-
     /**
      * Return the array index of the student answer
-     * @param $correctAnswer  the menu Choice1|Choice2|Choice3
-     * @param $studentAnswer  the student answer must be Choice1 or Choice2 or Choice3
-     * @return int  in the exemple 0 1 or 2 depending of the choice of the student
+     * @param string $correctAnswer the menu Choice1|Choice2|Choice3
+     * @param string $studentAnswer the student answer must be Choice1 or Choice2 or Choice3
+     *
+     * @return int  in the example 0 1 or 2 depending of the choice of the student
      */
     public static function getFillTheBlankMenuAnswerNum($correctAnswer, $studentAnswer)
     {
@@ -520,19 +520,23 @@ class FillBlanks extends Question
                 return $num;
             }
         }
-        return -1; // should not happened, because student choose the answer in a menu of possible answers
+
+        // should not happened, because student choose the answer in a menu of possible answers
+        return -1;
     }
 
 
     /**
      * Return the possible answer if the answer between brackets is a multiple choice menu
-     * @param $correctAnswer
+     * @param string $correctAnswer
+     *
      * @return array
      */
     public static function getFillTheBlankSeveralAnswers($correctAnswer)
     {
         // is answer||Answer||response||Response , mean answer or Answer ...
         $listSeveral = api_preg_split("/\|\|/", $correctAnswer);
+
         return $listSeveral;
     }
 
@@ -540,8 +544,9 @@ class FillBlanks extends Question
      * Return true if student answer is right according to the correctAnswer
      * it is not as simple as equality, because of the type of Fill The Blank question
      * eg : studentAnswer = 'Un' and correctAnswer = 'Un||1||un'
-     * @param $studentAnswer the [studentanswer] of the info array of the answer field
-     * @param $correctAnswer the [tabwords] of the info array of the answer field
+     * @param string $studentAnswer [studentanswer] of the info array of the answer field
+     * @param string $correctAnswer [tabwords] of the info array of the answer field
+     *
      * @return bool
      */
     public static function isGoodStudentAnswer($studentAnswer, $correctAnswer)
@@ -549,20 +554,27 @@ class FillBlanks extends Question
         switch (self::getFillTheBlankAnswerType($correctAnswer)) {
             case self::FILL_THE_BLANK_MENU:
                 $listMenu = self::getFillTheBlankMenuAnswers($correctAnswer, false);
-                return ($listMenu[0] == $studentAnswer);
+                $result = $listMenu[0] == $studentAnswer;
                 break;
             case self::FILL_THE_BLANK_SEVERAL_ANSWER:
                 // the answer must be one of the choice made
                 $listSeveral = self::getFillTheBlankSeveralAnswers($correctAnswer);
-                return (in_array($studentAnswer, $listSeveral));
+                $result = in_array($studentAnswer, $listSeveral);
                 break;
             case self::FILL_THE_BLANK_STANDARD:
             default:
-                return ($studentAnswer == $correctAnswer);
+                $result = $studentAnswer == $correctAnswer;
+                break;
         }
-    }
 
+        return $result;
+    }
 
+    /**
+     * @param string $correctAnswer
+     *
+     * @return int
+     */
     public static function getFillTheBlankAnswerType($correctAnswer)
     {
         if (api_strpos($correctAnswer, "|") && !api_strpos($correctAnswer, "||")) {
@@ -576,8 +588,8 @@ class FillBlanks extends Question
 
     /**
      * Return information about the answer
-     * @param string $userAnswer : the text of the answer of the question
-     * @param bool $isStudentAnswer : true if it is a student answer and not the empty question model
+     * @param string $userAnswer the text of the answer of the question
+     * @param bool   $isStudentAnswer true if it's a student answer false the empty question model
      *
      * @return array of information about the answer
      */
@@ -608,7 +620,7 @@ class FillBlanks extends Question
 
         $listAnswerResults['systemstring'] = $listDoubleColon[1];
 
-        //make sure we only take the last bit to find special marks
+        // make sure we only take the last bit to find special marks
         $listArobaseSplit = explode('@', $listDoubleColon[1]);
 
         if (count($listArobaseSplit) < 2) {
@@ -676,9 +688,11 @@ class FillBlanks extends Question
             $listDoubleColon[0]
         );
 
-        // if student answer, the second [] is the student answer, the third is if student scored or not
+        // if student answer, the second [] is the student answer,
+        // the third is if student scored or not
         $listBrackets = array();
         $listWords =  array();
+
         if ($isStudentAnswer) {
             for ($i=0; $i < count($listAnswerResults['tabwords']); $i++) {
                 $listBrackets[] = $listAnswerResults['tabwordsbracket'][$i];
@@ -700,15 +714,16 @@ class FillBlanks extends Question
             // if we are in student view, we've got 3 times :::::: for common words
             $commonWords = api_preg_replace("/::::::/", "::", $commonWords);
         }
+
         $listAnswerResults['commonwords'] = explode("::", $commonWords);
 
         return $listAnswerResults;
     }
 
-
     /**
-     * Replace the occurence of blank word with [correct answer][student answer][answer is correct]
+     * Replace the occurrence of blank word with [correct answer][student answer][answer is correct]
      * @param array $listWithStudentAnswer
+     *
      * @return string
      */
     public static function getAnswerInStudentAttempt($listWithStudentAnswer)
@@ -733,13 +748,35 @@ class FillBlanks extends Question
 
     /**
      * This function is the same than the js one above getBlankSeparatorRegexp
-     * @param $inChar
+     * @param string $inChar
      *
      * @return string
      */
     public static function escapeForRegexp($inChar)
     {
-        if (in_array($inChar, array(".", "+", "*", "?", "[", "^", "]", "$", "(", ")", "{", "}", "=", "!", ">", "|", ":", "-", ")"))) {
+        $listChars = [
+            ".",
+            "+",
+            "*",
+            "?",
+            "[",
+            "^",
+            "]",
+            "$",
+            "(",
+            ")",
+            "{",
+            "}",
+            "=",
+            "!",
+            ">",
+            "|",
+            ":",
+            "-",
+            ")",
+        ];
+
+        if (in_array($inChar, $listChars)) {
             return "\\".$inChar;
         } else {
             return $inChar;
@@ -748,13 +785,34 @@ class FillBlanks extends Question
 
     /**
      * return $text protected for use in regexp
-     * @param $text
+     * @param string $text
      *
      * @return mixed
      */
     public static function getRegexpProtected($text)
     {
-        $listRegexpCharacters = array("/", ".", "+", "*", "?", "[", "^", "]", "$", "(", ")", "{", "}", "=", "!", ">", "|", ":", "-", ")");
+        $listRegexpCharacters = [
+            "/",
+            ".",
+            "+",
+            "*",
+            "?",
+            "[",
+            "^",
+            "]",
+            "$",
+            "(",
+            ")",
+            "{",
+            "}",
+            "=",
+            "!",
+            ">",
+            "|",
+            ":",
+            "-",
+            ")",
+        ];
         $result = $text;
         for ($i=0; $i < count($listRegexpCharacters); $i++) {
             $result = str_replace($listRegexpCharacters[$i], "\\".$listRegexpCharacters[$i], $result);
@@ -785,7 +843,8 @@ class FillBlanks extends Question
 
     /**
      * return the start separator for answer
-     * @param $number
+     * @param string $number
+     *
      * @return mixed
      */
     public static function getStartSeparator($number)
@@ -797,7 +856,8 @@ class FillBlanks extends Question
 
     /**
      * return the end separator for answer
-     * @param $number
+     * @param string $number
+     *
      * @return mixed
      */
     public static function getEndSeparator($number)

+ 21 - 15
main/inc/global.inc.php

@@ -67,6 +67,15 @@ if ($passwordEncryption == 'bcrypt') {
 // Check the PHP version
 api_check_php_version($includePath.'/');
 
+// Error reporting settings.
+if (api_get_setting('server_type') == 'test') {
+    ini_set('display_errors', '1');
+    ini_set('log_errors', '1');
+    error_reporting(-1);
+} else {
+    error_reporting(E_COMPILE_ERROR | E_ERROR | E_CORE_ERROR);
+}
+
 // Specification for usernames:
 // 1. ASCII-letters, digits, "." (dot), "_" (underscore) are acceptable, 40 characters maximum length.
 // 2. Empty username is formally valid, but it is reserved for the anonymous user.
@@ -276,12 +285,9 @@ require_once $libraryPath.'formvalidator/Rule/allowed_tags.inc.php';
 // which will then be usable from the banner and header scripts
 $this_section = SECTION_GLOBAL;
 
-// include the local (contextual) parameters of this course or section
-require $includePath.'/local.inc.php';
-
-//Include Chamilo Mail conf this is added here because the api_get_setting works
+// Include Chamilo Mail conf this is added here because the api_get_setting works
 
-//Fixes bug in Chamilo 1.8.7.1 array was not set
+// Fixes bug in Chamilo 1.8.7.1 array was not set
 $administrator['email'] = isset($administrator['email']) ? $administrator['email'] : 'admin@example.com';
 $administrator['name'] = isset($administrator['name']) ? $administrator['name'] : 'Admin';
 
@@ -303,14 +309,6 @@ foreach ($configurationFiles as $file) {
     }
 }
 
-// Error reporting settings.
-if (api_get_setting('server_type') == 'test') {
-    ini_set('display_errors', '1');
-    ini_set('log_errors', '1');
-    error_reporting(-1);
-} else {
-    error_reporting(E_COMPILE_ERROR | E_ERROR | E_CORE_ERROR);
-}
 
 /*  LOAD LANGUAGE FILES SECTION */
 
@@ -456,6 +454,8 @@ if (!empty($valid_languages)) {
 // to use it within the function get_lang(...).
 $language_interface_initial_value = $language_interface;
 
+
+
 /**
  * Include the trad4all language file
  */
@@ -487,8 +487,12 @@ if (!empty($parent_path)) {
     }
 }
 
+// include the local (contextual) parameters of this course or section
+require $includePath.'/local.inc.php';
+
 // The global variable $text_dir has been defined in the language file trad4all.inc.php.
-// For determing text direction correspondent to the current language we use now information from the internationalization library.
+// For determining text direction correspondent to the current language
+// we use now information from the internationalization library.
 $text_dir = api_get_text_direction();
 
 // ===== "who is logged in?" module section =====
@@ -553,7 +557,9 @@ if (!isset($_SESSION['login_as']) && isset($_user)) {
 // The langstat object will then be used in the get_lang() function.
 // This block can be removed to speed things up a bit as it should only ever
 // be used in development versions.
-if (isset($_configuration['language_measure_frequency']) && $_configuration['language_measure_frequency'] == 1) {
+if (isset($_configuration['language_measure_frequency']) &&
+    $_configuration['language_measure_frequency'] == 1
+) {
     require_once api_get_path(SYS_CODE_PATH).'/cron/lang/langstats.class.php';
     $langstats = new langstats();
 }

+ 7 - 1
main/inc/lib/agenda.lib.php

@@ -1741,7 +1741,13 @@ class Agenda
      */
     private function formatEventDate($utcTime)
     {
-        return date(DateTime::ISO8601, api_strtotime(api_get_local_time($utcTime)));
+        $utcTimeZone = new DateTimeZone('UTC');
+        $platformTimeZone = new DateTimeZone(_api_get_timezone());
+        
+        $eventDate = new DateTime($utcTime, $utcTimeZone);
+        $eventDate->setTimezone($platformTimeZone);
+
+        return $eventDate->format(DateTime::ISO8601);
     }
 
     /**

+ 23 - 13
main/inc/lib/course.lib.php

@@ -3133,6 +3133,9 @@ class CourseManager
     /**
      * Builds the course block in user_portal.php
      * @todo use Twig
+     *
+     * @param array $params
+     * @return string
      */
     public static function course_item_html_no_icon($params)
     {
@@ -3167,6 +3170,11 @@ class CourseManager
         return $html;
     }
 
+    /**
+     * @param $params
+     * @param bool|false $is_sub_content
+     * @return string
+     */
     public static function session_items_html($params, $is_sub_content = false)
     {
         $html = '';
@@ -3192,6 +3200,9 @@ class CourseManager
     /**
      * Builds the course block in user_portal.php
      * @todo use Twig
+     * @param array $params
+     * @param bool|false $is_sub_content
+     * @return string
      */
     public static function course_item_html($params, $is_sub_content = false)
     {
@@ -3216,9 +3227,9 @@ class CourseManager
         }
 
         $html .= '</div>';
-        $notifications = isset($params['notifications']) ? $params['notifications'] : null;
-        $param_class = isset($params['class']) ? $params['class'] : null;
-        $params['right_actions'] = isset($params['right_actions']) ? $params['right_actions'] : null;
+        $notifications = isset($params['notifications']) ? $params['notifications'] : '';
+        $param_class = isset($params['class']) ? $params['class'] : '';
+        $params['right_actions'] = isset($params['right_actions']) ? $params['right_actions'] : '';
 
         $html .= '<div class="col-md-10 ' . $param_class . '">';
         $html .= '<div class="pull-right">' . $params['right_actions'] . '</div>';
@@ -3231,12 +3242,14 @@ class CourseManager
             $html .= '<div class="subtitle-session">' . $params['subtitle'] . '</div>';
         }
         if (!empty($params['teachers'])) {
-            $html .= '<h5>' . Display::return_icon('teacher.png', get_lang('Teacher'), array(),
-                    ICON_SIZE_TINY) . $params['teachers'] . '</h5>';
+            $html .= '<h5>' .
+                    Display::return_icon('teacher.png', get_lang('Teacher'), array(), ICON_SIZE_TINY) .
+                $params['teachers'] . '</h5>';
         }
         if (!empty($params['coaches'])) {
-            $html .= '<h5>' . Display::return_icon('teacher.png', get_lang('Coach'), array(),
-                    ICON_SIZE_TINY) . $params['coaches'] . '</h5>';
+            $html .= '<h5>' .
+                Display::return_icon('teacher.png', get_lang('Coach'), array(), ICON_SIZE_TINY) .
+                $params['coaches'] . '</h5>';
         }
 
         $html .= '</div>';
@@ -3520,7 +3533,6 @@ class CourseManager
         $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
 
         $result = Database::query($sql);
-        $status_icon = '';
         $html = '';
 
         $course_list = array();
@@ -3605,8 +3617,6 @@ class CourseManager
                 }
             }
 
-            $course_title = $course_info['title'];
-
             $course_title_url = '';
             if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course['status'] == COURSEMANAGER) {
                 $course_title_url = api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php?id_session=0';
@@ -3638,11 +3648,11 @@ class CourseManager
                 $params['notifications'] = $show_notification;
             }
 
-            $isSubcontent = true;
+            $isSubContent = true;
             if (empty($user_category_id)) {
-                $isSubcontent = false;
+                $isSubContent = false;
             }
-            $html .= self::course_item_html($params, $isSubcontent);
+            $html .= self::course_item_html($params, $isSubContent);
         }
 
         return [

+ 28 - 13
main/inc/lib/display.lib.php

@@ -1290,6 +1290,10 @@ class Display
      */
     public static function show_notification($course_info)
     {
+        if (empty($course_info)) {
+            return '';
+        }
+
         $t_track_e_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
         $course_tool_table = Database::get_course_table(TABLE_TOOL_LIST);
         $tool_edit_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
@@ -1297,7 +1301,7 @@ class Display
 
         $user_id = api_get_user_id();
         $course_id = intval($course_info['real_id']);
-        $course_info['id_session'] = intval($course_info['id_session']);
+        $sessionId = intval($course_info['id_session']);
 
         // Get the user's last access dates to all tools of this course
         $sql = "SELECT *
@@ -1305,7 +1309,7 @@ class Display
                 WHERE
                     c_id = $course_id AND
                     access_user_id = '$user_id' AND
-                    access_session_id ='".$course_info['id_session']."'";
+                    access_session_id ='".$sessionId."'";
         $resLastTrackInCourse = Database::query($sql);
 
         $oldestTrackDate = $oldestTrackDateOrig = '3000-01-01 00:00:00';
@@ -1322,6 +1326,13 @@ class Display
             $oldestTrackDate = $course_info['creation_date'];
         }
 
+        $sessionCondition = api_get_session_condition(
+            $sessionId,
+            true,
+            false,
+            'tet.session_id'
+        );
+
         // Get the last edits of all tools of this course.
         $sql = "SELECT
                     tet.*,
@@ -1332,15 +1343,15 @@ class Display
                     tet.to_group_id group_id,
                     ctt.image image,
                     ctt.link link
-                FROM $tool_edit_table tet, $course_tool_table ctt
+                FROM $tool_edit_table tet INNER JOIN $course_tool_table ctt
+                ON  tet.c_id = ctt.c_id
                 WHERE
                     tet.c_id = $course_id AND
-                    ctt.c_id = $course_id AND
                     tet.lastedit_date > '$oldestTrackDate' ".
                     // Special hack for work tool, which is called student_publication in c_tool and work in c_item_property :-/ BT#7104
-                    " AND (ctt.name = tet.tool OR (ctt.name = 'student_publication' AND tet.tool = 'work')) ".
-                    " AND ctt.visibility = '1' ".
-                    " AND tet.lastedit_user_id != $user_id AND tet.session_id = '".$course_info['id_session']."'
+                    " AND (ctt.name = tet.tool OR (ctt.name = 'student_publication' AND tet.tool = 'work'))
+                    AND ctt.visibility = '1'
+                    AND tet.lastedit_user_id != $user_id $sessionCondition
                  ORDER BY tet.lastedit_date";
 
         $res = Database::query($sql);
@@ -1412,13 +1423,8 @@ class Display
         while (list($key, $notification) = each($notifications)) {
             $lastDate = date('d/m/Y H:i', convert_sql_date($notification['lastedit_date']));
             $type = $notification['lastedit_type'];
-            if (empty($course_info['id_session'])) {
-                $my_course['id_session'] = 0;
-            } else {
-                $my_course['id_session'] = $course_info['id_session'];
-            }
             $label = get_lang('TitleNotification').": ".get_lang($type)." ($lastDate)";
-            $retvalue .= '<a href="'.api_get_path(WEB_CODE_PATH).$notification['link'].'?cidReq='.$course_code.'&ref='.$notification['ref'].'&gidReq='.$notification['to_group_id'].'&id_session='.$my_course['id_session'].'">'.
+            $retvalue .= '<a href="'.api_get_path(WEB_CODE_PATH).$notification['link'].'?cidReq='.$course_code.'&ref='.$notification['ref'].'&gidReq='.$notification['to_group_id'].'&id_session='.$sessionId.'">'.
                             Display::return_icon($notification['image'], $label).'</a>&nbsp;';
         }
 
@@ -1854,6 +1860,9 @@ class Display
 
     /**
      * Prints a tooltip
+     * @param string $text
+     * @param string $tip
+     * @return string
      */
     public static function tip($text, $tip)
     {
@@ -1863,6 +1872,12 @@ class Display
         return self::span($text, array('class' => 'boot-tooltip', 'title' => strip_tags($tip)));
     }
 
+    /**
+     * @param array $items
+     * @param string $type
+     * @param null $id
+     * @return null|string
+     */
     public static function generate_accordion($items, $type = 'jquery', $id = null)
     {
         $html = null;

+ 15 - 5
main/inc/lib/export.lib.inc.php

@@ -115,8 +115,13 @@ class Export
     * @param string Name of the root element. A root element should always be given.
     * @param string Encoding in which the data is provided
     */
-	public static function arrayToXml($data, $filename = 'export', $item_tagname = 'item', $wrapper_tagname = null, $encoding = null)
-    {
+    public static function arrayToXml(
+        $data,
+        $filename = 'export',
+        $item_tagname = 'item',
+        $wrapper_tagname = null,
+        $encoding = null
+    ) {
 		if (empty($encoding)) {
 			$encoding = api_get_system_encoding();
 		}
@@ -150,8 +155,12 @@ class Export
      * @param string Encoding in which the data is provided
      * @return void  Prompts the user for a file download
      */
-    public static function export_complex_table_xml ($data, $filename = 'export', $wrapper_tagname, $encoding = 'ISO-8859-1')
-    {
+    public static function export_complex_table_xml(
+        $data,
+        $filename = 'export',
+        $wrapper_tagname,
+        $encoding = 'ISO-8859-1'
+    ) {
         $file = api_get_path(SYS_ARCHIVE_PATH).'/'.uniqid('').'.xml';
         $handle = fopen($file, 'a+');
         fwrite($handle, '<?xml version="1.0" encoding="'.$encoding.'"?>'."\n");
@@ -175,7 +184,7 @@ class Export
      * @param   int     Level of recursivity. Allows the XML to be finely presented
      * @return string   The XML string to be inserted into the root element
      */
-    public static function _export_complex_table_xml_helper ($data, $level = 1)
+    public static function _export_complex_table_xml_helper($data, $level = 1)
     {
         if (count($data) < 1) {
             return '';
@@ -259,6 +268,7 @@ class Export
             $row++;
         }
         $table_tp_html = $table->toHtml();
+
         return $table_tp_html;
     }
 

+ 1 - 1
main/inc/lib/internationalization.lib.php

@@ -1078,7 +1078,7 @@ function api_htmlentities($string, $quote_style = ENT_COMPAT, $encoding = 'UTF-8
  * This function is aimed at replacing the function html_entity_decode() for human-language strings.
  * @link http://php.net/html_entity_decode
  */
-function api_html_entity_decode($string, $quote_style = ENT_COMPAT, $encoding = null) {
+function api_html_entity_decode($string, $quote_style = ENT_COMPAT, $encoding = 'UTF-8') {
     if (empty($encoding)) {
         $encoding = _api_mb_internal_encoding();
     }

+ 6 - 4
main/inc/lib/userportal.lib.php

@@ -941,7 +941,11 @@ class IndexManager
         $my_account_content .= '</ul>';
 
         if (!empty($my_account_content)) {
-            $html =  self::show_right_block(get_lang('Courses'), $my_account_content, 'course_block');
+            $html = self::show_right_block(
+                get_lang('Courses'),
+                $my_account_content,
+                'course_block'
+            );
         }
         return $html;
     }
@@ -967,9 +971,7 @@ class IndexManager
         }
 
         $html = '';
-
         // Showing history title
-
         if ($load_history) {
             $html .= Display::page_subheader(get_lang('HistoryTrainingSession'));
             if (empty($session_categories)) {
@@ -1294,7 +1296,7 @@ class IndexManager
         }
 
         return [
-            'html' => $sessions_with_category . $sessions_with_no_category . $courses_html . $special_courses,
+            'html' => $sessions_with_category.$sessions_with_no_category.$courses_html.$special_courses,
             'session_count' => $sessionCount,
             'course_count' => $courseCount
         ];

+ 0 - 13
main/newscorm/back_compat.inc.php

@@ -1,13 +0,0 @@
-<?php
-/* For licensing terms, see /license.txt */
-/**
- * This script used to allow compatibility between the New SCORM tool and both
- * version 1.6.3 and 1.8 of Dokeos by loading libraries in a different way.
- * The switch is now deprecated and this file will be renamed later on to
- * something like lp_includes.inc.php
- * @package chamilo.learnpath
- */
-/**
- * Code
- */
-

+ 0 - 23
main/newscorm/lp_comm.common.php

@@ -1,23 +0,0 @@
-<?php
-/* For licensing terms, see /license.txt */
-/**
- * This script contains the server part of the xajax interaction process. The client part is located
- * in lp_api.php or other api's.
- * This is a first attempt at using xajax and AJAX in general, so the code might be a bit unsettling.
- * @package chamilo.learnpath
- * @author Yannick Warnier <ywarnier@beeznest.org>
- */
-/**
- * Code
- */
-// Flag to allow for anonymous user - needs to be set before global.inc.php.
-$use_anonymous = true;
-
-require_once '../inc/global.inc.php';
-
-$xajax = new xajax(api_get_path(WEB_CODE_PATH).'newscorm/lp_comm.server.php');
-$xajax->registerFunction('save_item');
-$xajax->registerFunction('save_objectives');
-$xajax->registerFunction('switch_item_details');
-$xajax->registerFunction('backup_item_details');
-$xajax->registerFunction('start_timer');

+ 0 - 378
main/newscorm/lp_comm.server.php

@@ -1,378 +0,0 @@
-<?php
-/* For licensing terms, see /license.txt */
-/**
- * This script contains the server part of the xajax interaction process. The client part is located
- * in lp_api.php or other api's.
- * This is a first attempt at using xajax and AJAX in general, so the code might be a bit unsettling.
- * @package chamilo.learnpath
- * @author Yannick Warnier <ywarnier@beeznest.org>
- */
-
-// Flag to allow for anonymous user - needs to be set before global.inc.php.
-$use_anonymous = true;
-require_once '../inc/global.inc.php';
-
-/**
- * Backup an item's values into the javascript API as "old" values (so we still have them at hand)
- * @param	integer	Learnpath ID
- * @param	integer	User ID
- * @param	integer View ID
- * @param	integer	Item ID
- * @param	double	Current score
- * @param	double	Maximum score
- * @param	double	Minimum score
- * @param	string	Lesson status
- * @param	string	Session time
- * @param	string	Suspend data
- * @param	string	Lesson location
- */
-function backup_item_details($lp_id, $user_id, $view_id, $item_id, $score = -1, $max = -1, $min = -1, $status = '', $time = '', $suspend = '', $location = '') {
-    $objResponse = new xajaxResponse();
-    $objResponse->addScript(
-            "old_score=".$score.";" .
-            "old_max=".$max.";" .
-            "old_min=".$min.";" .
-            "old_lesson_status='".$status."';" .
-            "old_session_time='".$time."';" .
-            "lms_old_item_id='".$item_id."';" .
-            "old_suspend_data='".$suspend."';" .
-            "old_lesson_location='".$location."';");
-    //$objResponse->addAlert('data for item '.$item_id.', user '.$user_id.' backed up');
-    return $objResponse;
-}
-
-/**
- * Writes an item's new values into the database and returns the operation result
- * @param	integer	Learnpath ID
- * @param	integer	User ID
- * @param	integer View ID
- * @param	integer	Item ID
- * @param	double	Current score
- * @param	double	Maximum score
- * @param	double	Minimum score
- * @param	string	Lesson status
- * @param	string	Session time
- * @param	string	Suspend data
- * @param	string	Lesson location
- * @param	string	Core exit SCORM string
- */
-function save_item($lp_id, $user_id, $view_id, $item_id, $score = -1, $max = -1, $min = -1, $status = '', $time = 0, $suspend = '', $location = '', $interactions = array(), $core_exit = 'none') {
-    global $_configuration;
-    $debug = 0;
-    if ($debug > 0) { error_log('In xajax_save_item('.$lp_id.','.$user_id.','.$view_id.','.$item_id.','.$score.','.$max.','.$min.',"'.$status.'",'.$time.',"'.$suspend.'","'.$location.'","'.(count($interactions)>0?$interactions[0]:'').'","'.$core_exit.'")', 0); }
-    $objResponse = new xajaxResponse();
-    $mylp = learnpath::getLpFromSession(api_get_course_id(), $lp_id, $user_id);
-    $prereq_check = $mylp->prerequisites_match($item_id);
-    if ($prereq_check === true) { // Launch the prerequisites check and set error if needed.
-
-        $mylpi =& $mylp->items[$item_id];
-        //$mylpi->set_lp_view($view_id);
-        if ($max != -1) {
-            $mylpi->max_score = $max;
-        }
-        if ($min != -1) {
-            $mylpi->min_score = $min;
-        }
-        if ($score != -1) {
-            $mylpi->set_score($score);
-        }
-        if ($status != '') {
-            if ($debug > 1) { error_log('Calling set_status('.$status.') from xajax', 0); }
-            $mylpi->set_status($status);
-            if ($debug > 1) { error_log('Done calling set_status from xajax', 0); }
-        }
-        if ($time != '') {
-            // If big integer, then it's a timestamp, otherwise it's normal scorm time.
-            if ($time == intval(strval($time)) && $time > 1000000) {
-                $real_time = time() - $time;
-                //$real_time += $mylpi->get_total_time();
-                $mylpi->set_time($real_time, 'int');
-            } else {
-                $mylpi->set_time($time);
-            }
-        }
-        if ($suspend != '') {
-            $mylpi->current_data = $suspend; //escapetxt($suspend);
-        }
-        if ($location != '') {
-            $mylpi->set_lesson_location($location);
-        }
-        // Deal with interactions provided in arrays in the following format
-        // id(0), type(1), time(2), weighting(3), correct_responses(4), student_response(5), result(6), latency(7)
-        if (is_array($interactions) && count($interactions) > 0) {
-            foreach ($interactions as $index => $interaction) {
-                $mylpi->add_interaction($index, $interactions[$index]);
-            }
-        }
-        $mylpi->set_core_exit($core_exit);
-        $mylp->save_item($item_id, false);
-    } else {
-        return $objResponse;
-    }
-
-    $mystatus           = $mylpi->get_status(false);
-    $mytotal            = $mylp->get_total_items_count_without_chapters();
-    $mycomplete         = $mylp->get_complete_items_count();
-    $myprogress_mode    = $mylp->get_progress_bar_mode();
-    $myprogress_mode    = ($myprogress_mode == '' ? '%' : $myprogress_mode);
-
-    //$mylpi->write_to_db();
-    $_SESSION['lpobject'] = serialize($mylp);
-    if ($mylpi->get_type()!='sco'){
-        // If this object's JS status has not been updated by the SCORM API, update now.
-        $objResponse->addScript("lesson_status='".$mystatus."';");
-    }
-    $objResponse->addScript("update_toc('".$mystatus."','".$item_id."');");
-    $update_list = $mylp->get_update_queue();
-    foreach ($update_list as $my_upd_id => $my_upd_status) {
-        if ($my_upd_id != $item_id) { // Only update the status from other items (i.e. parents and brothers), do not update current as we just did it already.
-            $objResponse->addScript("update_toc('".$my_upd_status."','".$my_upd_id."');");
-        }
-    }
-    $objResponse->addScript("update_progress_bar('$mycomplete','$mytotal','$myprogress_mode');");
-
-    if ($debug > 0) {
-        $objResponse->addScript("logit_lms('Saved data for item ".$item_id.", user ".$user_id." (status=".$mystatus.")',2)");
-        if ($debug > 1) { error_log('End of xajax_save_item()', 0); }
-    }
-
-    if (!isset($_SESSION['login_as'])) {
-        // If $_SESSION['login_as'] is set, then the user is an admin logged as the user.
-
-        $tbl_track_login = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
-
-        $sql_last_connection = "SELECT login_id, login_date FROM $tbl_track_login
-                                WHERE login_user_id='".api_get_user_id()."' ORDER BY login_date DESC LIMIT 0,1";
-
-        $q_last_connection = Database::query($sql_last_connection);
-        if (Database::num_rows($q_last_connection) > 0) {
-            $row = Database::fetch_array($q_last_connection);
-            $i_id_last_connection = $row['login_id'];
-            $now = api_get_utc_datetime();
-            $s_sql_update_logout_date = "UPDATE $tbl_track_login SET logout_date = '$now' WHERE login_id='$i_id_last_connection'";
-            Database::query($s_sql_update_logout_date);
-        }
-
-    }
-
-    return $objResponse;
-}
-
-/**
- * Writes an item's new values into the database and returns the operation result
- * @param	integer	Learnpath ID
- * @param	integer	User ID
- * @param	integer View ID
- * @param	integer	Item ID
- * @param	array	Objectives array
- */
-function save_objectives($lp_id, $user_id, $view_id, $item_id, $objectives = array()) {
-    global $_configuration;
-    $debug = 0;
-    if ($debug > 0) { error_log('In xajax_save_objectives('.$lp_id.','.$user_id.','.$view_id.','.$item_id.',"'.(count($objectives) > 0 ? count($objectives) : '').'")', 0); }
-    $objResponse = new xajaxResponse();
-
-    $mylp = learnpath::getLpFromSession(api_get_course_id(), $lp_id, $user_id);
-    $mylpi =& $mylp->items[$item_id];
-    if (is_array($objectives) && count($objectives)>0){
-        foreach($objectives as $index=>$objective){
-            //error_log(__FILE__.' '.__LINE__.' '.$objectives[$index][0], 0);
-            $mylpi->add_objective($index,$objectives[$index]);
-        }
-        $mylpi->write_objectives_to_db();
-    }
-    return $objResponse;
-}
-
-/**
- * Get one item's details
- * @param	integer	LP ID
- * @param	integer	user ID
- * @param	integer	View ID
- * @param	integer	Current item ID
- * @param	integer New item ID
- */
-function switch_item_details($lp_id, $user_id, $view_id, $current_item, $next_item) {
-    global $charset;
-
-    $debug = 0;
-    if ($debug > 0) { error_log('In xajax_switch_item_details('.$lp_id.','.$user_id.','.$view_id.','.$current_item.','.$next_item.')', 0); }
-    $objResponse = new xajaxResponse();
-    /*$item_id may be one of:
-     * -'next'
-     * -'previous'
-     * -'first'
-     * -'last'
-     * - a real item ID
-     */
-    $mylp = learnpath::getLpFromSession(api_get_course_id(), $lp_id, $user_id);
-    $new_item_id = 0;
-    switch ($next_item) {
-        case 'next':
-            $mylp->set_current_item($current_item);
-            $mylp->next();
-            $new_item_id = $mylp->get_current_item_id();
-            if ($debug > 1) { error_log('In {next} - next item is '.$new_item_id.'(current: '.$current_item.')', 0); }
-            break;
-        case 'previous':
-            $mylp->set_current_item($current_item);
-            $mylp->previous();
-            $new_item_id = $mylp->get_current_item_id();
-            if ($debug > 1) { error_log('In {previous} - next item is '.$new_item_id.'(current: '.$current_item.')', 0); }
-            break;
-        case 'first':
-            $mylp->set_current_item($current_item);
-            $mylp->first();
-            $new_item_id = $mylp->get_current_item_id();
-            if ($debug > 1) { error_log('In {first} - next item is '.$new_item_id.'(current: '.$current_item.')', 0); }
-            break;
-        case 'last':
-            break;
-        default:
-            // Should be filtered to check it's not hacked.
-            if($next_item == $current_item){
-                // If we're opening the same item again.
-                $mylp->items[$current_item]->restart();
-            }
-            $new_item_id = $next_item;
-            $mylp->set_current_item($new_item_id);
-            if ($debug > 1) { error_log('In {default} - next item is '.$new_item_id.'(current: '.$current_item.')', 0); }
-            break;
-    }
-    $mylp->start_current_item(true);
-    if ($mylp->force_commit){
-        $mylp->save_current();
-    }
-    //$objResponse->addAlert(api_get_path(REL_CODE_PATH).'newscorm/learnpathItem.class.php');
-    if (is_object($mylp->items[$new_item_id])) {
-        $mylpi = $mylp->items[$new_item_id];
-    } else {
-        if ($debug > 1) { error_log('In switch_item_details - generating new item object', 0); }
-        $mylpi = new learnpathItem($new_item_id, $user_id);
-        $mylpi->set_lp_view($view_id);
-    }
-    /*
-     * now get what's needed by the SCORM API:
-     * -score
-     * -max
-     * -min
-     * -lesson_status
-     * -session_time
-     * -suspend_data
-     */
-    $myscore = $mylpi->get_score();
-    $mymax = $mylpi->get_max();
-    $mymin = $mylpi->get_min();
-    $mylesson_status = $mylpi->get_status();
-    $mylesson_location = $mylpi->get_lesson_location();
-    $mytotal_time = $mylpi->get_scorm_time('js');
-    $mymastery_score = $mylpi->get_mastery_score();
-    $mymax_time_allowed = $mylpi->get_max_time_allowed();
-    $mylaunch_data = $mylpi->get_launch_data();
-    /*
-    if ($mylpi->get_type() == 'asset') {
-        // Temporary measure to save completion of an asset. Later on, Chamilo should trigger something on unload, maybe... (even though that would mean the last item cannot be completed)
-        $mylesson_status = 'completed';
-        $mylpi->set_status('completed');
-        $mylpi->save();
-    }
-    */
-    $mysession_time = $mylpi->get_total_time();
-    $mysuspend_data = $mylpi->get_suspend_data();
-    $mylesson_location = $mylpi->get_lesson_location();
-    $objResponse->addScript(
-            "score=".$myscore.";" .
-            "max=".$mymax.";" .
-            "min=".$mymin.";" .
-            "lesson_status='".$mylesson_status."';" .
-            "lesson_location='".$mylesson_location."';" .
-            "session_time='".$mysession_time."';" .
-            "suspend_data='".$mysuspend_data."';" .
-            "lesson_location='".$mylesson_location."';" .
-            "total_time = '".$mytotal_time."';" .
-            "mastery_score = '".$mymastery_score."';" .
-            "max_time_allowed = '".$mymax_time_allowed."';" .
-            "launch_data = '".$mylaunch_data."';" .
-            "interactions = new Array();" .
-            "item_objectives = new Array();" .
-            "G_lastError = 0;" .
-            "G_LastErrorMessage = 'No error';");
-    /*
-     * and re-initialise the rest
-     * -saved_lesson_status = 'not attempted'
-     * -lms_lp_id
-     * -lms_item_id
-     * -lms_old_item_id
-     * -lms_new_item_id
-     * -lms_been_synchronized
-     * -lms_initialized
-     * -lms_total_lessons
-     * -lms_complete_lessons
-     * -lms_progress_bar_mode
-     * -lms_view_id
-     * -lms_user_id
-     */
-    $mytotal = $mylp->get_total_items_count_without_chapters();
-    $mycomplete = $mylp->get_complete_items_count();
-    $myprogress_mode = $mylp->get_progress_bar_mode();
-    $myprogress_mode = ($myprogress_mode == '' ? '%' : $myprogress_mode);
-    $mynext = $mylp->get_next_item_id();
-    $myprevious = $mylp->get_previous_item_id();
-    $myitemtype = $mylpi->get_type();
-    $mylesson_mode = $mylpi->get_lesson_mode();
-    $mycredit = $mylpi->get_credit();
-    $mylaunch_data = $mylpi->get_launch_data();
-    $myinteractions_count = $mylpi->get_interactions_count();
-    $myobjectives_count = $mylpi->get_objectives_count();
-    $mycore_exit = $mylpi->get_core_exit();
-    $objResponse->addScript(
-            "saved_lesson_status='not attempted';" .
-            "lms_lp_id=".$lp_id.";" .
-            "lms_item_id=".$new_item_id.";" .
-            "lms_old_item_id=0;" .
-            "lms_been_synchronized=0;" .
-            "lms_initialized=0;" .
-            "lms_total_lessons=".$mytotal.";" .
-            "lms_complete_lessons=".$mycomplete.";" .
-            "lms_progress_bar_mod='".$myprogress_mode."';" .
-            "lms_view_id=".$view_id.";" .
-            "lms_user_id=".$user_id.";" .
-            "next_item=".$new_item_id.";" . // This one is very important to replace possible literal strings.
-            "lms_next_item=".$mynext.";" .
-            "lms_previous_item=".$myprevious.";" .
-            "lms_item_type = '".$myitemtype."';" .
-            "lms_item_credit = '".$mycredit."';" .
-            "lms_item_lesson_mode = '".$mylesson_mode."';" .
-            "lms_item_launch_data = '".$mylaunch_data."';" .
-            "lms_item_interactions_count = '".$myinteractions_count."';" .
-            "lms_item_objectives_count = '".$myinteractions_count."';" .
-            "lms_item_core_exit = '".$mycore_exit."';" .
-            "asset_timer = 0;"
-            );
-    $objResponse->addScript("update_toc('unhighlight','".$current_item."');");
-    $objResponse->addScript("update_toc('highlight','".$new_item_id."');");
-    $objResponse->addScript("update_toc('$mylesson_status','".$new_item_id."');");
-    $objResponse->addScript("update_progress_bar('$mycomplete','$mytotal','$myprogress_mode');");
-
-    $mylp->set_error_msg('');
-    $mylp->prerequisites_match(); // Check the prerequisites are all complete.
-    if ($debug > 1) { error_log('Prereq_match() returned '.api_htmlentities($mylp->error, ENT_QUOTES, $charset), 0); }
-    $objResponse->addScript("update_message_frame('".str_replace("'", "\'", api_htmlentities($mylp->error, ENT_QUOTES, $charset))."');");
-    $_SESSION['scorm_item_id'] = $new_item_id; // Save the new item ID for the exercise tool to use.
-    $_SESSION['lpobject'] = serialize($mylp);
-    return $objResponse;
-}
-
-/**
- * Start a timer and hand it back to the JS by assigning the current time (of start) to
- * var asset_timer
- */
-function start_timer() {
-    $objResponse = new xajaxResponse();
-    $time = time();
-    $objResponse->addScript("asset_timer='$time';asset_timer_total=0;");
-    return $objResponse;
-}
-
-require 'lp_comm.common.php';
-$xajax->processRequests();

+ 1 - 1
main/template/default/agenda/month.tpl

@@ -121,7 +121,7 @@ $(document).ready(function() {
 			//$("#users_to_send_id").trigger("chosen:updated");
 
 			if ({{ can_add_events }} == 1) {
-				var url = '{{ web_agenda_ajax_url }}&a=add_event&start='+start.unix()+'&end='+end.unix()+'&all_day='+allDay+'&view='+view.name;
+				var url = '{{ web_agenda_ajax_url }}&a=add_event&start='+start.format('YYYY-MM-DD 00:00:00')+'&end='+end.format('YYYY-MM-DD 00:00:00')+'&all_day='+allDay+'&view='+view.name;
                 var start_date_value = start.format('{{ js_format_date }}');
                 var end_date_value = end.format('{{ js_format_date }}');
 

+ 56 - 38
main/tracking/exams.php

@@ -4,11 +4,8 @@
  * Exams script
  * @package chamilo.tracking
  */
-/**
- * Code
- */
 require_once '../inc/global.inc.php';
-require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer.php';
+//require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer.php';
 
 $toolTable = Database::get_course_table(TABLE_TOOL_LIST);
 $quizTable = Database::get_course_table(TABLE_QUIZ_TEST);
@@ -92,7 +89,12 @@ if (!$exportToXLS) {
 
         echo '<span style="float:right">';
 
-        echo '<a href="'.api_get_self().'?export=1&score='.$filter_score.'&exercise_id='.$exerciseId.'&'.api_get_cidreq().'">'.
+        $courseLink = '';
+        if (!empty(api_get_course_info())) {
+            $courseLink = api_get_cidreq();
+        }
+
+        echo '<a href="'.api_get_self().'?export=1&score='.$filter_score.'&exercise_id='.$exerciseId.'&'.$courseLink.'">'.
             Display::return_icon('export_excel.png',get_lang('ExportAsXLS'),'',ICON_SIZE_MEDIUM).'</a>';
         echo '<a href="javascript: void(0);" onclick="javascript: window.print()">'.
             Display::return_icon('printer.png',get_lang('Print'),'',ICON_SIZE_MEDIUM).'</a>';
@@ -124,19 +126,19 @@ if (!$exportToXLS) {
     } else {
         echo Display::url(
             Display::return_icon('user.png', get_lang('StudentsTracking'), array(), 32),
-            'courseLog.php?'.api_get_cidreq().'&amp;studentlist=true'
+            'courseLog.php?'.api_get_cidreq().'&studentlist=true'
         );
         echo Display::url(
             Display::return_icon('course.png', get_lang('CourseTracking'), array(), 32),
-            'courseLog.php?'.api_get_cidreq().'&amp;studentlist=false'
+            'courseLog.php?'.api_get_cidreq().'&studentlist=false'
         );
         echo Display::url(
             Display::return_icon('tools.png', get_lang('ResourcesTracking'), array(), 32),
-            'courseLog.php?'.api_get_cidreq().'&amp;studentlist=resouces'
+            'courseLog.php?'.api_get_cidreq().'&studentlist=resouces'
         );
         echo Display::url(
             Display::return_icon('export_excel.png', get_lang('ExportAsXLS'), array(), 32),
-            api_get_self().'?'.api_get_cidreq().'&amp;export=1&amp;score='.$filter_score.'&amp;exercise_id='.$exerciseId
+            api_get_self().'?'.api_get_cidreq().'&export=1&score='.$filter_score.'&exercise_id='.$exerciseId
         );
 
     }
@@ -216,7 +218,7 @@ if (!empty($courseList) && is_array($courseList)) {
         $result = Database::query($sql);
 
         // If main tool is visible.
-        if (Database::result($result, 0 ,'visibility') == 1) {
+        if (Database::result($result, 0, 'visibility') == 1) {
             // Getting the exam list.
             if ($global) {
                 $sql = "SELECT quiz.title, id, session_id
@@ -321,7 +323,6 @@ if (!empty($courseList) && is_array($courseList)) {
                                 );
                             }
                         }
-
                     } else {
                         // If the exercise only exists in this session.
 
@@ -335,7 +336,10 @@ if (!empty($courseList) && is_array($courseList)) {
                         );
 
                         $html .= $result['html'];
-                        $export_array_global = array_merge($export_array_global, $result['export_array_global']);
+                        $export_array_global = array_merge(
+                            $export_array_global,
+                            $result['export_array_global']
+                        );
                     }
                 }
             } else {
@@ -363,7 +367,8 @@ if (!$exportToXLS) {
     echo $html;
 }
 
-$filename = 'exam-reporting-'.date('Y-m-d-h:i:s').'.xls';
+$filename = 'exam-reporting-'.api_get_local_time().'.xlsx';
+
 if ($exportToXLS) {
     if ($global) {
         export_complete_report_xls($filename, $export_array_global);
@@ -393,66 +398,75 @@ function sort_user($a, $b) {
  */
 function export_complete_report_xls($filename, $array)
 {
-    global $charset, $global, $filter_score;
-    $workbook = new Spreadsheet_Excel_Writer();
-    $workbook ->setTempDir(api_get_path(SYS_ARCHIVE_PATH));
-    $workbook->send($filename);
-    $workbook->setVersion(8); // BIFF8
-    $worksheet =& $workbook->addWorksheet('Report');
-    //$worksheet->setInputEncoding(api_get_system_encoding());
-    $worksheet->setInputEncoding($charset);
+    global $global, $filter_score;
+
+    $spreadsheet = new PHPExcel();
+    $spreadsheet->setActiveSheetIndex(0);
 
+    $worksheet = $spreadsheet->getActiveSheet();
     $line = 0;
     $column = 0; //skip the first column (row titles)
 
     if ($global) {
-        $worksheet->write($line, $column, get_lang('Courses'));
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('Courses'));
         $column++;
-        $worksheet->write($line, $column, get_lang('Exercises'));
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('Exercises'));
         $column++;
-        $worksheet->write($line, $column, get_lang('ExamTaken'));
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('ExamTaken'));
         $column++;
-        $worksheet->write($line, $column, get_lang('ExamNotTaken'));
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('ExamNotTaken'));
         $column++;
-        $worksheet->write($line, $column, sprintf(get_lang('ExamPassX'), $filter_score) . '%');
+        $worksheet->SetCellValueByColumnAndRow($line, $column, sprintf(get_lang('ExamPassX'), $filter_score) . '%');
         $column++;
-        $worksheet->write($line, $column, get_lang('ExamFail'));
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('ExamFail'));
         $column++;
-        $worksheet->write($line, $column, get_lang('TotalStudents'));
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('TotalStudents'));
         $column++;
 
         $line++;
         foreach ($array as $row) {
             $column = 0;
             foreach ($row as $item) {
-                $worksheet->write($line,$column,html_entity_decode(strip_tags($item)));
+                $worksheet->SetCellValueByColumnAndRow($line, $column, html_entity_decode(strip_tags($item)));
                 $column++;
             }
             $line++;
         }
         $line++;
     } else {
-        $worksheet->write($line,$column,get_lang('Exercises'));
+        $worksheet->SetCellValueByColumnAndRow($line,$column,get_lang('Exercises'));
         $column++;
-        $worksheet->write($line,$column,get_lang('User'));
+        $worksheet->SetCellValueByColumnAndRow($line,$column,get_lang('User'));
         $column++;
-        $worksheet->write($line,$column,get_lang('Percentage'));
+        $worksheet->SetCellValueByColumnAndRow($line,$column,get_lang('Percentage'));
         $column++;
-        $worksheet->write($line,$column,get_lang('Status'));
+        $worksheet->SetCellValueByColumnAndRow($line,$column,get_lang('Status'));
         $column++;
-        $worksheet->write($line,$column,get_lang('Attempts'));
+        $worksheet->SetCellValueByColumnAndRow($line,$column,get_lang('Attempts'));
         $column++;
         $line++;
         foreach ($array as $row) {
             $column = 0;
-            $worksheet->write($line,$column,html_entity_decode(strip_tags($row['exercise'])));
+            $worksheet->SetCellValueByColumnAndRow(
+                $line,
+                $column,
+                html_entity_decode(strip_tags($row['exercise']))
+            );
             $column++;
             foreach ($row['users'] as $key=>$user) {
                 $column = 1;
-                $worksheet->write($line,$column,html_entity_decode(strip_tags($user)));
+                $worksheet->SetCellValueByColumnAndRow(
+                    $line,
+                    $column,
+                    html_entity_decode(strip_tags($user))
+                );
                 $column++;
                 foreach ($row['results'][$key] as $result_item) {
-                    $worksheet->write($line,$column,html_entity_decode(strip_tags($result_item)));
+                    $worksheet->SetCellValueByColumnAndRow(
+                        $line,
+                        $column,
+                        html_entity_decode(strip_tags($result_item))
+                    );
                     $column++;
                 }
                 $line++;
@@ -460,7 +474,11 @@ function export_complete_report_xls($filename, $array)
         }
         $line++;
     }
-    $workbook->close();
+
+    $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
+    $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
+    $writer->save($file);
+    DocumentManager::file_send_for_download($file, false, $filename);
     exit;
 }
 

+ 35 - 7
src/Chamilo/CoreBundle/Entity/PersonalAgenda.php

@@ -1,4 +1,5 @@
 <?php
+/* For licensing terms, see /license.txt */
 
 namespace Chamilo\CoreBundle\Entity;
 
@@ -12,6 +13,15 @@ use Doctrine\ORM\Mapping as ORM;
  */
 class PersonalAgenda
 {
+    /**
+     * @var integer
+     *
+     * @ORM\Column(name="id", type="integer")
+     * @ORM\Id
+     * @ORM\GeneratedValue
+     */
+    private $id;
+
     /**
      * @var integer
      *
@@ -69,20 +79,17 @@ class PersonalAgenda
     private $allDay;
 
     /**
-     * @var integer
+     * @var string
      *
-     * @ORM\Column(name="id", type="integer")
-     * @ORM\Id
-     * @ORM\GeneratedValue(strategy="IDENTITY")
+     * @ORM\Column(name="color", type="string", length=255, nullable=true)
      */
-    private $id;
-
-
+    private $color;
 
     /**
      * Set user
      *
      * @param integer $user
+     *
      * @return PersonalAgenda
      */
     public function setUser($user)
@@ -272,4 +279,25 @@ class PersonalAgenda
     {
         return $this->id;
     }
+
+    /**
+     * @return string
+     */
+    public function getColor()
+    {
+        return $this->color;
+    }
+
+    /**
+     * @param string $color
+     *
+     * @return PersonalAgenda
+     */
+    public function setColor($color)
+    {
+        $this->color = $color;
+
+        return $this;
+    }
+
 }

+ 3 - 6
user_portal.php

@@ -94,9 +94,9 @@ $nameTools = get_lang('MyCourses');
     Include the HTTP, HTML headers plus the top banner.
 */
 if ($load_dirs) {
-	$url 			= api_get_path(WEB_AJAX_PATH).'document.ajax.php?a=document_preview';
-	$folder_icon 	= api_get_path(WEB_IMG_PATH).'icons/22/folder.png';
-	$close_icon 	= api_get_path(WEB_IMG_PATH).'loading1.gif';
+	$url = api_get_path(WEB_AJAX_PATH).'document.ajax.php?a=document_preview';
+	$folder_icon = api_get_path(WEB_IMG_PATH).'icons/22/folder.png';
+	$close_icon = api_get_path(WEB_IMG_PATH).'loading1.gif';
 
 	$htmlHeadXtra[] =  '<script>
 	$(document).ready(function() {
@@ -121,7 +121,6 @@ if ($load_dirs) {
 	            success: function(return_value) {
 	            	image.attr("src", "'.$folder_icon.'");
 	            	$("#document_result_" +course_id+"_" + session_id).html(return_value);
-
 	            }
 	        });
 
@@ -130,8 +129,6 @@ if ($load_dirs) {
 	</script>';
 }
 
-
-
 //Show the chamilo mascot
 if (empty($courseAndSessions['html']) && !isset($_GET['history'])) {
 	$controller->tpl->assign('welcome_to_course_block', $controller->return_welcome_to_course_block());