Browse Source

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

Yannick Warnier 10 years ago
parent
commit
febda57393

+ 2 - 1
composer.json

@@ -65,7 +65,8 @@
         "bower-asset/mediaelement": "2.16.*",
         "bower-asset/modernizr": "2.8.*",
         "bower-asset/jqueryui-timepicker-addon": "1.5.*",
-        "ramsey/array_column": "~1.1"
+        "ramsey/array_column": "~1.1",
+        "bower-asset/imageMap-resizer": "0.5.3"
     },
     "require-dev": {
         "behat/behat": "2.5.*@stable",

+ 1 - 1
main/auth/courses_controller.php

@@ -532,7 +532,7 @@ class CoursesController
      */
     public function getSessionIcon($sessionName)
     {
-        return Display::return_icon('window_list.png', $sessionName, null, ICON_SIZE_BIG);
+        return Display::return_icon('window_list.png', $sessionName, null,ICON_SIZE_MEDIUM);
     }
 
     /**

+ 2 - 0
main/course_info/infocours.php

@@ -229,6 +229,8 @@ $group[]=$form->createElement('radio', 'email_alert_students_on_new_homework', n
 $form->addGroup($group, '', array(get_lang("NewHomeworkEmailAlert")), '');
 
 $group = array();
+$group[]=$form->createElement('radio', 'email_alert_manager_on_new_doc', null, get_lang('WorkEmailAlertActivateOnlyForTeachers'), 3);
+$group[]=$form->createElement('radio', 'email_alert_manager_on_new_doc', null, get_lang('WorkEmailAlertActivateOnlyForStudents'), 2);
 $group[]=$form->createElement('radio', 'email_alert_manager_on_new_doc', get_lang('WorkEmailAlert'), get_lang('WorkEmailAlertActivate'), 1);
 $group[]=$form->createElement('radio', 'email_alert_manager_on_new_doc', null, get_lang('WorkEmailAlertDeactivate'), 0);
 $form->addGroup($group, '', array(get_lang("WorkEmailAlert")), '');

+ 4 - 0
main/css/base.css

@@ -84,6 +84,10 @@ select {
 #announcements-slider .carousel-indicators .active{
   background: #C52D2F;
 }
+#announcements-slider .carousel-inner img {
+    height: auto;
+    width: 100%;
+}
 .carousel-indicators{
   bottom: 0px !important;
 }

+ 150 - 20
main/gradebook/certificate_report.php

@@ -23,10 +23,23 @@ $interbreadcrumb[] = array(
 $selectedSession = isset($_POST['session']) && !empty($_POST['session']) ? intval($_POST['session']) : 0;
 $selectedCourse = isset($_POST['course']) && !empty($_POST['course']) ? intval($_POST['course']) : 0;
 $selectedMonth = isset($_POST['month']) && !empty($_POST['month']) ? intval($_POST['month']) : 0;
-$selectedYear = isset($_POST['year']) && !empty($_POST['year']) ? $_POST['year'] : null;
+$selectedYear = isset($_POST['year']) && !empty($_POST['year']) ? trim($_POST['year']) : null;
+$selectedStudent = isset($_POST['student']) && !empty($_POST['student']) ? intval($_POST['student']) : 0;
 
 $userId = api_get_user_id();
-$sessions = SessionManager::getSessionsCoachedByUser($userId);
+
+$sessions = $courses = $months = $students = [0 => get_lang('Select')];
+
+if (api_is_student_boss()) {
+    $userList = GroupPortalManager::getGroupUsersByUser($userId);
+    $sessionsList = SessionManager::getSessionsFollowedForGroupAdmin($userId);
+} else {
+    $sessionsList = SessionManager::getSessionsCoachedByUser($userId);
+}
+
+foreach ($sessionsList as $session) {
+    $sessions[$session['id']] = $session['name'];
+}
 
 if ($selectedSession > 0) {
     if (!SessionManager::isValidId($selectedSession)) {
@@ -36,32 +49,39 @@ if ($selectedSession > 0) {
         exit;
     }
 
-    $courses = SessionManager::get_course_list_by_session_id($selectedSession);
+    $coursesList = SessionManager::get_course_list_by_session_id($selectedSession);
 
-    if (is_array($courses)) {
-        foreach ($courses as &$course) {
+    if (is_array($coursesList)) {
+        foreach ($coursesList as &$course) {
             $course['real_id'] = $course['id'];
         }
     }
 } else {
-    $courses = CourseManager::get_courses_list_by_user_id($userId);
+    if (api_is_student_boss()) {
+        $coursesList = CourseManager::getCoursesFollowedByGroupAdmin($userId);
+    } else {
+        $coursesList = CourseManager::get_courses_list_by_user_id($userId);
 
-    if (is_array($courses)) {
-        foreach ($courses as &$course) {
-            $courseInfo = api_get_course_info_by_id($course['real_id']);
+        if (is_array($coursesList)) {
+            foreach ($coursesList as &$course) {
+                $courseInfo = api_get_course_info_by_id($course['real_id']);
 
-            $course = array_merge($course, $courseInfo);
+                $course = array_merge($course, $courseInfo);
+            }
         }
     }
 }
 
-$months = array();
+foreach ($coursesList as $course) {
+    if (isset($course['real_id'])) {
+        $courses[$course['real_id']] = $course['title'];
+    } else {
+        $courses[$course['id']] = $course['title'];
+    }
+}
 
 for ($key = 1; $key <= 12; $key++) {
-    $months[] = array(
-        'key' => $key,
-        'name' => sprintf("%02d", $key)
-    );
+    $months[$key] = sprintf("%02d", $key);
 }
 
 $exportAllLink = null;
@@ -69,6 +89,7 @@ $certificateStudents = array();
 
 $searchSessionAndCourse = $selectedSession > 0 && $selectedCourse > 0;
 $searchCourseOnly = $selectedSession <= 0 && $selectedCourse > 0;
+$searchStudentOnly = $selectedStudent > 0;
 
 if ($searchSessionAndCourse || $searchCourseOnly) {
     $selectedCourseInfo = api_get_course_info_by_id($selectedCourse);
@@ -98,14 +119,23 @@ if ($searchSessionAndCourse || $searchCourseOnly) {
             "cat_id" => $gradebook->get_id()
         ));
 
+        $sessionName = api_get_session_name($selectedSession);
+        $courseName = api_get_course_info($selectedCourseInfo['code'])['title'];
+
         $studentList = GradebookUtils::get_list_users_certificates($gradebook->get_id());
 
         $certificateStudents = array();
 
         if (is_array($studentList) && !empty($studentList)) {
             foreach ($studentList as $student) {
+                if (api_is_student_boss() && !in_array($student['user_id'], $userList)) {
+                    continue;
+                }
+
                 $certificateStudent = array(
                     'fullName' => api_get_person_name($student['firstname'], $student['lastname']),
+                    'sessionName' => $sessionName,
+                    'courseName' => $courseName,
                     'certificates' => array()
                 );
 
@@ -133,7 +163,7 @@ if ($searchSessionAndCourse || $searchCourseOnly) {
                             continue;
                         }
                     } elseif ($selectedMonth > 0 && !empty($selectedYear)) {
-                        if ($creationMonthYear != sprintf("%d %s", $selectedMonth, $selectedYear)) {
+                        if ($creationMonthYear != sprintf("%02d %s", $selectedMonth, $selectedYear)) {
                             continue;
                         }
                     }
@@ -144,6 +174,62 @@ if ($searchSessionAndCourse || $searchCourseOnly) {
                     );
                 }
 
+                if (count($certificateStudent['certificates']) > 0) {
+                    $certificateStudents[] = $certificateStudent;
+                }
+            }
+        }
+    }
+} elseif ($searchStudentOnly) {
+    $selectedStudentInfo = api_get_user_info($selectedStudent);
+
+    if (empty($selectedStudentInfo)) {
+        Session::write('reportErrorMessage', get_lang('NoUser'));
+
+        Header::location($selfUrl);
+    }
+
+    $sessionList = SessionManager::getSessionsFollowedByUser($selectedStudent);
+
+    foreach ($sessionList as $session) {
+        $sessionCourseList = SessionManager::get_course_list_by_session_id($session['id']);
+
+        foreach ($sessionCourseList as $sessionCourse) {
+            $gradebookCategories = Category::load(null, null, $sessionCourse['code'], null, false, $session['id']);
+
+            $gradebook = null;
+
+            if (!empty($gradebookCategories)) {
+                $gradebook = current($gradebookCategories);
+            }
+
+            if (!is_null($gradebook)) {
+                $sessionName = $session['name'];
+                $courseName = $sessionCourse['title'];
+
+                $certificateStudent = [
+                    'fullName' => $selectedStudentInfo['complete_name'],
+                    'sessionName' => $sessionName,
+                    'courseName' => $courseName,
+                    'certificates' => []
+                ];
+
+                $studentCertificates = GradebookUtils::get_list_gradebook_certificates_by_user_id(
+                    $selectedStudent,
+                    $gradebook->get_id()
+                );
+
+                if (!is_array($studentCertificates) || empty($studentCertificates)) {
+                    continue;
+                }
+
+                foreach ($studentCertificates as $certificate) {
+                    $certificateStudent['certificates'][] = array(
+                        'createdAt' => api_convert_and_format_date($certificate['created_at']),
+                        'id' => $certificate['id']
+                    );
+                }
+
                 if (count($certificateStudent['certificates']) > 0) {
                     $certificateStudents[] = $certificateStudent;
                 }
@@ -159,10 +245,54 @@ if (Session::has('reportErrorMessage')) {
     $template->assign('errorMessage', Session::read('reportErrorMessage'));
 }
 
-$template->assign('selectedSession', $selectedSession);
-$template->assign('selectedCourse', $selectedCourse);
-$template->assign('selectedMonth', $selectedMonth);
-$template->assign('selectedYear', $selectedYear);
+$searchBySessionCourseDateForm = new FormValidator(
+    'certificate_report_form',
+    'post',
+    api_get_path(WEB_CODE_PATH) . 'gradebook/certificate_report.php'
+);
+$searchBySessionCourseDateForm->addSelect('session', get_lang('Sessions'), $sessions, ['id' => 'session']);
+$searchBySessionCourseDateForm->addSelect('course', get_lang('Courses'), $courses, ['id' => 'course']);
+$searchBySessionCourseDateForm->addGroup(
+    [
+        $searchBySessionCourseDateForm->createElement('select', 'month', null, $months, ['id' => 'month']),
+        $searchBySessionCourseDateForm->createElement(
+            'text',
+            'year',
+            null,
+            ['id' => 'year', 'placeholder' => get_lang('Year')]
+        )
+    ],
+    null,
+    get_lang('Date')
+);
+$searchBySessionCourseDateForm->addButtonSearch();
+$searchBySessionCourseDateForm->setDefaults([
+    'session' => $selectedSession,
+    'course' => $selectedCourse,
+    'month' => $selectedMonth,
+    'year' => $selectedYear
+]);
+
+if (api_is_student_boss()) {
+    foreach ($userList as $studentId) {
+        $students[$studentId] = api_get_user_info($studentId)['complete_name_with_username'];
+    }
+
+    $searchByStudentForm = new FormValidator(
+        'certificate_report_form',
+        'post',
+        api_get_path(WEB_CODE_PATH) . 'gradebook/certificate_report.php'
+    );
+    $searchByStudentForm->addSelect('student', get_lang('Students'), $students, ['id' => 'student']);
+    $searchByStudentForm->addButtonSearch();
+    $searchByStudentForm->setDefaults([
+        'student' => $selectedStudent
+    ]);
+
+    $template->assign('searchByStudentForm', $searchByStudentForm->returnForm());
+}
+
+$template->assign('searchBySessionCourseDateForm', $searchBySessionCourseDateForm->returnForm());
 $template->assign('sessions', $sessions);
 $template->assign('courses', $courses);
 $template->assign('months', $months);

+ 12 - 5
main/gradebook/gradebook_display_certificate.php

@@ -8,7 +8,9 @@
 require_once '../inc/global.inc.php';
 $current_course_tool  = TOOL_GRADEBOOK;
 
-api_protect_course_script();
+if (!api_is_student_boss()) {
+    api_protect_course_script();
+}
 
 set_time_limit(0);
 ini_set('max_execution_time', 0);
@@ -25,7 +27,7 @@ function confirmation() {
 </script>";
 api_block_anonymous_users();
 
-if (!api_is_allowed_to_edit()) {
+if (!api_is_allowed_to_edit() && !api_is_student_boss()) {
     api_not_allowed(true);
 }
 
@@ -36,10 +38,15 @@ $filterOfficialCodeGet = isset($_GET['filter']) ? Security::remove_XSS($_GET['fi
 
 switch ($action) {
     case 'export_all_certificates':
-        $userList = array();
-        if (!empty($filterOfficialCodeGet)) {
-            $userList = UserManager::getUsersByOfficialCode($filterOfficialCodeGet);
+        if (api_is_student_boss()) {
+            $userList = GroupPortalManager::getGroupUsersByUser(api_get_user_id());
+        } else {
+            $userList = array();
+            if (!empty($filterOfficialCodeGet)) {
+                $userList = UserManager::getUsersByOfficialCode($filterOfficialCodeGet);
+            }
         }
+
         Category::exportAllCertificates($cat_id, $userList);
         break;
     case 'generate_all_certificates':

+ 4 - 33
main/inc/ajax/model.ajax.php

@@ -211,39 +211,10 @@ switch ($action) {
         }
 
         if ($searchByGroups) {
-            $groups = GroupPortalManager::get_groups_by_user(api_get_user_id(), GROUP_USER_PERMISSION_ADMIN);
-            $groupsId = array_keys($groups);
-            $subgroupsId = [];
-
-            if (is_array($groupsId)) {
-                foreach ($groupsId as $groupId) {
-                    $subgroupsId = array_merge(
-                        $subgroupsId,
-                        GroupPortalManager::getGroupsByDepthLevel($groupId)
-                    );
-                }
-
-                $groupsId = array_merge(
-                    $groupsId,
-                    $subgroupsId
-                );
-
-                foreach ($groupsId as $groupId) {
-                    $groupUsers = GroupPortalManager::get_users_by_group($groupId);
-
-                    if (!is_array($groupUsers)) {
-                        continue;
-                    }
-
-                    foreach ($groupUsers as $memberId => $member) {
-                        if ($member['user_id'] == $userId ) {
-                            continue;
-                        }
-
-                        $userIdList[] = intval($member['user_id']);
-                    }
-                }
-            }
+            $userIdList = array_merge(
+                $userIdList,
+                GroupPortalManager::getGroupUsersByUser(api_get_user_id())
+            );
         }
 
         if (is_array($userIdList)) {

+ 6 - 0
main/inc/lib/api.lib.php

@@ -71,6 +71,12 @@ define('COURSE_REQUEST_ACCEPTED', 1);
 define('COURSE_REQUEST_REJECTED', 2);
 define('DELETE_ACTION_ENABLED', false);
 
+
+// EMAIL SENDING RECIPIENT CONSTANTS
+define('SEND_EMAIL_EVERYONE',  1);
+define('SEND_EMAIL_STUDENTS', 2);
+define('SEND_EMAIL_TEACHERS', 3);
+
 // SESSION VISIBILITY CONSTANTS
 define('SESSION_VISIBLE_READ_ONLY', 1);
 define('SESSION_VISIBLE', 2);

+ 52 - 0
main/inc/lib/course.lib.php

@@ -5682,4 +5682,56 @@ class CourseManager
         }
         return $courses;
     }
+
+    /**
+     * Get list of courses based on users of a group for a group admin
+     * @param int $userId The user id
+     * @return array
+     */
+    public static function getCoursesFollowedByGroupAdmin($userId)
+    {
+        $coursesList = [];
+
+        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
+        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_USER);
+
+        $userIdList = GroupPortalManager::getGroupUsersByUser($userId);
+
+        if (empty($userIdList)) {
+            return [];
+        }
+
+        $sql = "SELECT DISTINCT(c.id), c.title "
+            . "FROM $courseTable c "
+            . "INNER JOIN $courseUserTable cru ON c.code = cru.course_code "
+            . "WHERE ( "
+            . "cru.user_id IN(" . implode(', ', $userIdList) . ") "
+            . "AND cru.relation_type = 0 "
+            . ")";
+
+        if (api_is_multiple_url_enabled()) {
+            $courseAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
+            $accessUrlId = api_get_current_access_url_id();
+
+            if ($accessUrlId != -1) {
+                $sql = "SELECT DISTINCT(c.id), c.title "
+                    . "FROM $courseTable c "
+                    . "INNER JOIN $courseUserTable cru ON c.code = cru.course_code "
+                    . "INNER JOIN $courseAccessUrlTable crau ON c.code = crau.course_code "
+                    . "WHERE crau.access_url_id = $accessUrlId "
+                    . "AND ( "
+                    . "cru.id_user IN (" . implode(', ', $userIdList) . ") "
+                    . "AND cru.relation_type = 0 "
+                    . ")";
+            }
+        }
+
+        $result = Database::query($sql);
+
+        while ($row = Database::fetch_assoc($result)) {
+            $coursesList[] = $row;
+        }
+
+        return $coursesList;
+    }
 }

+ 5 - 10
main/inc/lib/course_category.lib.php

@@ -932,6 +932,7 @@ function getCataloguePagination($pageCurrent, $pageLength, $pageTotal)
 {
     // Start empty html
     $pageDiv = '';
+    $html='';
     $pageBottom = max(1, $pageCurrent - 3);
     $pageTop = min($pageTotal, $pageCurrent + 3);
 
@@ -970,17 +971,11 @@ function getCataloguePagination($pageCurrent, $pageLength, $pageTotal)
     }
 
     // Complete pagination html
-    $pageDiv = Display::div(
-        Display::tag(
-            'ul',
-            $pageDiv
-        ),
-        array(
-            'class' => 'pagination pagination-centered',
-        )
-    );
+    $pageDiv = Display::tag('ul',$pageDiv,array('class' => 'pagination'));
+
 
-    return $pageDiv;
+    $html.='<nav>'.$pageDiv.'</nav>';
+    return $html;
 }
 
 /**

+ 55 - 0
main/inc/lib/group_portal_manager.lib.php

@@ -1359,4 +1359,59 @@ class GroupPortalManager
         }
         return true;
     }
+
+    /**
+     * Get the group member list by a user and his group role
+     * @param int $userId The user ID
+     * @param int $relationType Optional. The relation type. GROUP_USER_PERMISSION_ADMIN by default
+     * @param boolean $includeSubgroupsUsers Optional. Whether include the users from subgroups
+     * @return array
+     */
+    public static function getGroupUsersByUser(
+        $userId,
+        $relationType = GROUP_USER_PERMISSION_ADMIN,
+        $includeSubgroupsUsers = true
+    )
+    {
+        $userId = intval($userId);
+
+        $groups = GroupPortalManager::get_groups_by_user($userId, $relationType);
+
+        $groupsId = array_keys($groups);
+        $subgroupsId = [];
+        $userIdList = [];
+
+        if ($includeSubgroupsUsers) {
+            foreach ($groupsId as $groupId) {
+                $subgroupsId = array_merge($subgroupsId, GroupPortalManager::getGroupsByDepthLevel($groupId));
+            }
+
+            $groupsId = array_merge($groupsId, $subgroupsId);
+        }
+
+        $groupsId = array_unique($groupsId);
+
+        if (empty($groupsId)) {
+            return [];
+        }
+
+        foreach ($groupsId as $groupId) {
+            $groupUsers = GroupPortalManager::get_users_by_group($groupId);
+
+            if (empty($groupUsers)) {
+                continue;
+            }
+
+            foreach ($groupUsers as $member) {
+                if ($member['user_id'] == $userId) {
+                    continue;
+                }
+
+                $userIdList[] = intval($member['user_id']);
+            }
+        }
+
+        return array_unique($userIdList);
+    }
+
 }

+ 52 - 0
main/inc/lib/sessionmanager.lib.php

@@ -5952,4 +5952,56 @@ class SessionManager
 
         return false;
     }
+
+    /**
+     * Get list of sessions based on users of a group for a group admin
+     * @param int $userId The user id
+     * @return array
+     */
+    public static function getSessionsFollowedForGroupAdmin($userId)
+    {
+        $sessionList = array();
+
+        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
+        $sessionUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER);
+
+        $userIdList = GroupPortalManager::getGroupUsersByUser($userId);
+
+        if (empty($userIdList)) {
+            return [];
+        }
+
+        $sql = "SELECT DISTINCT s.* "
+            . "FROM $sessionTable s "
+            . "INNER JOIN $sessionUserTable sru ON s.id = sru.id_session "
+            . "WHERE ( "
+            . "sru.id_user IN (" . implode(', ', $userIdList) . ") "
+            . "AND sru.relation_type = 0"
+            . ")";
+
+        if (api_is_multiple_url_enabled()) {
+            $sessionAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
+            $accessUrlId = api_get_current_access_url_id();
+
+            if ($accessUrlId != -1) {
+                $sql = "SELECT DISTINCT s.* "
+                    . "FROM $sessionTable s "
+                    . "INNER JOIN $sessionUserTable sru ON s.id = sru.id_session "
+                    . "INNER JOIN $sessionAccessUrlTable srau ON s.id = srau.session_id "
+                    . "WHERE srau.access_url_id = $accessUrlId "
+                    . "AND ( "
+                    . "sru.id_user IN (" . implode(', ', $userIdList) . ") "
+                    . "AND sru.relation_type = 0"
+                    . ")";
+            }
+        }
+
+        $result = Database::query($sql);
+
+        while ($row = Database::fetch_assoc($result)) {
+            $sessionList[] = $row;
+        }
+
+        return $sessionList;
+    }
 }

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

@@ -615,7 +615,8 @@ class Template
             'bootstrap-daterangepicker/daterangepicker.js',
             'jquery-timeago/jquery.timeago.js',
             'mediaelement/build/mediaelement-and-player.min.js',
-            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.js'
+            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.js',
+            'imagemap-resizer/js/imageMapResizer.min.js'
         ];
 
         if ($isoCode != 'en') {

+ 9 - 0
main/mySpace/company_reports.php

@@ -110,6 +110,15 @@ if (api_is_student_boss()) {
         Display::return_icon("statistics.png", get_lang("CompanyReport"), array(), ICON_SIZE_MEDIUM),
         "#"
     );
+    $actions .= Display::url(
+        Display::return_icon(
+            "certificate_list.png",
+            get_lang("GradebookSeeListOfStudentsCertificates"),
+            [],
+            ICON_SIZE_MEDIUM
+        ),
+        api_get_path(WEB_CODE_PATH) . "gradebook/certificate_report.php"
+    );
 }
 
 $content = '<div class="actions">';

+ 9 - 0
main/mySpace/company_reports_resumed.php

@@ -99,6 +99,15 @@ if (api_is_student_boss()) {
         Display::return_icon("statistics.png", get_lang("CompanyReport"), array(), ICON_SIZE_MEDIUM),
         api_get_path(WEB_CODE_PATH) . "mySpace/company_reports.php"
     );
+    $actions .= Display::url(
+        Display::return_icon(
+            "certificate_list.png",
+            get_lang("GradebookSeeListOfStudentsCertificates"),
+            [],
+            ICON_SIZE_MEDIUM
+        ),
+        api_get_path(WEB_CODE_PATH) . "gradebook/certificate_report.php"
+    );
 }
 
 $content = '<div class="actions">';

+ 9 - 0
main/mySpace/student.php

@@ -211,6 +211,15 @@ if (api_is_drh()) {
         Display::return_icon("statistics.png", get_lang("CompanyReport"), array(), ICON_SIZE_MEDIUM),
         api_get_path(WEB_CODE_PATH) . "mySpace/company_reports.php"
     );
+    $actions .= Display::url(
+        Display::return_icon(
+            "certificate_list.png",
+            get_lang("GradebookSeeListOfStudentsCertificates"),
+            [],
+            ICON_SIZE_MEDIUM
+        ),
+        api_get_path(WEB_CODE_PATH) . "gradebook/certificate_report.php"
+    );
 }
 
 $actions .= '<span style="float:right">';

+ 67 - 70
main/template/default/auth/sessions_catalog.tpl

@@ -7,13 +7,13 @@
                 dateFormat: 'yy-mm-dd'
             });
 
-            $('.accordion').click(function(e) {
+            $('#list-course').click(function(e) {
                 e.preventDefault();
                 var tempTarget = e.target.toString().split('#');
                 tempTarget = '#' + tempTarget[1];
                 // use the target of the link as the ID of the element to find
                 var target = $(tempTarget);
-                var targetContent = target.find('.accordion-inner');
+                var targetContent = target.find('.list');
 
                 if (targetContent.is(':empty')) {
                     var idParts = tempTarget.split('-');
@@ -42,11 +42,11 @@
                             targetContent.html('<ul class="items-session">' + coursesUL + '</ul>');
                             target.css({
                                 height: targetContent.outerHeight()
-                            }).addClass('in');
+                            }).addClass(' in');
                         }
                     });
                 } else {
-                    target.addClass('in');
+                    target.addClass(' in');
                 }
             });
         });
@@ -54,105 +54,102 @@
 
     <div class="col-md-3">
         {% if showCourses %}
-            <div class="well">
-                {% if not hiddenLinks %}
+            <div class="panel panel-default">
+                <div class="panel-body">
+                    {% if not hiddenLinks %}
                     <form class="form-search" method="post" action="{{ courseUrl }}">
-                        <fieldset>
+
                             <input type="hidden" name="sec_token" value="{{ searchToken }}">
                             <input type="hidden" name="search_course" value="1" />
-                            <div class="control-group">
-                                <div class="controls">
-                                    <div class="input-append">
-                                        <input class="span2" type="text" name="search_term" />
-                                        <button class="btn btn-default" type="submit"><i class="fa fa-search"></i> {{ 'Search' | get_lang }}</button>
-                                    </div>
-                                </div>
+                            <div class="form-group">
+                                <input  type="text" name="search_term" class="form-control"/>
+                                <button class="btn btn-block btn-default" type="submit"><i class="fa fa-search"></i> {{ 'Search' | get_lang }}</button>
                             </div>
-                        </fieldset>
+
                     </form>
-                {% endif %}
+                    {% endif %}
 
-                {% if coursesCategoriesList is not empty %}
-                    <a class="btn btn-default" href="{{ api_get_self }}?action=display_random_courses">{{ 'RandomPick' | get_lang }}</a>
-                {% endif %}
+                    {% if coursesCategoriesList is not empty %}
+                    <a class="btn btn-block btn-default" href="{{ api_get_self }}?action=display_random_courses">{{ 'RandomPick' | get_lang }}</a>
+                    {% endif %}
+                </div>
             </div>
 
             {% if coursesCategoriesList is not empty %}
-                <div class="well sidebar-nav">
-                    <h4>{{ 'CourseCategories' | get_lang }}</h4>
-                    <ul class="nav nav-list">
-                        {{ coursesCategoriesList }}
-                    </ul>
+                <div class="sidebar-nav">
+                    <div class="panel panel-default">
+                        <div class="panel-heading">
+                            {{ 'CourseCategories' | get_lang }}
+                        </div>
+                        <div class="panel-body">
+                            <ul class="list-categories">
+                                {{ coursesCategoriesList }}
+                            </ul>
+                        </div>
+                    </div>
                 </div>
             {% endif %}
         {% endif %}
 
         {% if showSessions %}
-            <div class="well sidebar-nav">
-                <h4>{{ 'Sessions' | get_lang }}</h4>
-                <ul class="nav nav-list">
-                    <li>{{ 'SearchSessions' | get_lang }}</li>
-                    <li>
+            <div class="sidebar-nav">
+
+                <div class="panel panel-default">
+                    <div class="panel-heading">
+                        {{ 'Sessions' | get_lang }}
+                    </div>
+                    <div class="panel-body">
                         <form class="form-search" method="post" action="{{ api_get_self }}?action=display_sessions">
-                            <div class="input-append">
-                                <input type="date" name="date" id="date" class="span2 search-session" value="{{ searchDate }}" readonly>
-                                <button class="btn btn-default" type="submit"><i class="fa fa-search"></i> {{ 'Search' | get_lang }}</button>
+                            <div class="form-group">
+                                <input type="date" name="date" id="date" class="form-control" value="{{ searchDate }}" readonly>
+                                <button class="btn btn-block btn-default" type="submit"><i class="fa fa-search"></i> {{ 'Search' | get_lang }}</button>
                             </div>
                         </form>
-                    </li>
-                </ul>
+                    </div>
+                </div>
+
             </div>
         {% endif %}
     </div>
     <div class="col-md-9">
         {% for session in sessions_blocks %}
-            <div class="well well-small session-group" id="session-{{ session.id }}">
-                <div class="row">
-                    <div class="col-md-9">
-                        <div class="row padding-clear">
-                            <div class="col-md-2">
-                                <span class="thumbnail">
-                                    {{ session.icon }}
-                                </span>
-                            </div>
-                            <div class="col-md-10 border-info">
-                                <h3>{{ session.name }}</h3>
-                                <div class="tutor">
-                                    <img src="{{ 'teacher.png' | icon(22) }}" width="16"> {{ 'GeneralCoach' | get_lang }} {{ session.coach_name }}
-                                </div>
+
+            <div class="panel panel-default" id="panel-{{ session.id }}">
+                <div class="panel-heading">
+                    {{ session.icon }} {{ session.name }}
+                </div>
+                <div class="panel-body">
+                    <div class="row">
+                        <div class="col-md-9">
+                            <div class="tutor">
+                                <img src="{{ 'teacher.png' | icon(22) }}" width="16"> {{ 'GeneralCoach' | get_lang }} {{ session.coach_name }}
                             </div>
-                        </div>
-                        <div class="row">
-                            <div class="accordion" id="session-{{ session.id }}-accordion">
-                                <div class="accordion-group">
-                                    <div class="accordion-heading">
-                                        <a class="accordion-toggle" data-toggle="collapse" data-parent="#session-{{ session.id }}-accordion" href="#session-{{ session.id }}-courses">
-                                            {{ 'CourseList' | get_lang }}
-                                        </a>
-                                    </div>
-                                    <div id="session-{{ session.id }}-courses" class="accordion-body collapse in">
-                                        <div class="accordion-inner"></div>
-                                    </div>
-                                </div>
+                            <a id="list-course" class="btn btn-default" data-toggle="collapse" href="#session-{{ session.id }}-courses">
+                                {{ 'CourseList' | get_lang }}
+                            </a>
+                            <div class="collapse" id="session-{{ session.id }}-courses">
+                                <div class="list"></div>
                             </div>
+
                         </div>
-                    </div>
-                    <div class="col-md-3">
-                        {% if session.showDescription %}
+                        <div class="col-md-3">
+                            {% if session.showDescription %}
                             <div class="buttom-subscribed">
                                 <a class="ajax btn btn-large btn-info" href="{{ _p.web_ajax }}session.ajax.php?a=get_description&session={{ session.id }}">{{ 'Description' | get_lang }}</a>
                             </div>
-                        {% endif %}
+                            {% endif %}
 
-                        <div class="buttom-subscribed">
-                            {% if session.is_subscribed %}
+                            <div class="buttom-subscribed">
+                                {% if session.is_subscribed %}
                                 {{ already_subscribed_label }}
-                            {% else %}
+                                {% else %}
                                 {{ session.subscribe_button }}
-                            {% endif %}
+                                {% endif %}
+                            </div>
+                            <div class="time"><img src="{{ 'agenda.png' | icon(22) }}"> {{ session.date }}</div>
                         </div>
-                        <div class="time"><img src="{{ 'agenda.png' | icon(22) }}"> {{ session.date }}</div>
                     </div>
+
                 </div>
             </div>
         {% endfor %}

+ 18 - 47
main/template/default/gradebook/certificate_report.tpl

@@ -10,8 +10,6 @@
                 a: 'display_sessions_courses',
                 session: sessionId
             }, function (courseList) {
-                var $option = null;
-
                 $('<option>', {
                     value: 0,
                     text: "{{ 'Select' | get_lang }}"
@@ -30,63 +28,32 @@
     });
 </script>
 
-<form action="{{ _p.web_main }}gradebook/certificate_report.php" method="post" class="form-horizontal">
-    <div class="control-group">
-        <label class="control-label" for="session">{{ 'Sessions' | get_lang }}</label>
-        <div class="controls">
-            <select name="session" id="session">
-                <option value="0">{{ 'Select' | get_lang }}</option>
-                {% for session in sessions %}
-                    <option value="{{ session.id }}" {{ selectedSession == session.id ? 'selected' : '' }}>{{ session.name }}</option>
-                {% endfor %}
-            </select>
-        </div>
-    </div>
-    <div class="control-group">
-        <label class="control-label" for="course">{{ 'Courses' | get_lang }}</label>
-        <div class="controls">
-            <select name="course" id="course">
-                <option value="0">{{ 'Select' | get_lang }}</option>
-                {% for course in courses %}
-                    <option value="{{ course.real_id }}" {{ selectedCourse == course.real_id ? 'selected' : ''}}>{{ course.title }}</option>
-                {% endfor %}
-            </select>
-        </div>
-    </div>
-    <div class="control-group">
-        <label class="control-label" for="month">{{ 'Date' | get_lang }}</label>
-        <div class="controls">
-            <select name="month" id="month">
-                <option value="0">{{ 'Select' | get_lang }}</option>
-                {% for month in months %}
-                    <option value="{{ month.key }}" {{ selectedMonth == month.key ? 'selected' : ''}}>{{ month.name }}</option>
-                {% endfor %}
-            </select>
-            <input type="text" name="year" id="year" class="input-mini" value="{{ selectedYear }}">
-        </div>
-    </div>
-    <div class="control-group">
-        <div class="controls">
-            <button type="submit" class="btn btn-primary">{{ 'Search' | get_lang }}</button>
-        </div>
-    </div>
-</form>
+{{ searchBySessionCourseDateForm }}
+
+<hr>
 
-<h1 class="page-header">{{ 'GradebookListOfStudentsCertificates' | get_lang }}</h1>
+{{ searchByStudentForm }}
 
 {% if errorMessage is defined %}
     <div class="alert alert-error">{{ errorMessage }}</div>
 {% endif %}
 
 {% if not certificateStudents is empty %}
-    <p>
-        <a href="{{ exportAllLink }}" class="btn btn-info">{{ 'ExportAllCertificatesToPDF' | get_lang }}</a>
-    </p>
+    <h2 class="page-header">{{ "GradebookListOfStudentsCertificates" | get_lang }}</h2>
+    {% if not exportAllLink is null %}
+        <div class="actions">
+            <a href="{{ exportAllLink }}" class="btn btn-info">
+                <i class="fa fa-check"></i> {{ 'ExportAllCertificatesToPDF' | get_lang }}
+            </a>
+        </div>
+    {% endif %}
 
     <table class="table table-striped">
         <thead>
             <tr>
                 <th>{{ 'Student' | get_lang }}</th>
+                <th>{{ 'Sesion' | get_lang }}</th>
+                <th>{{ 'Course' | get_lang }}</th>
                 <th>{{ 'Date' | get_lang }}</th>
                 <th>{{ 'Certificate' | get_lang }}</th>
             </tr>
@@ -94,6 +61,8 @@
         <tfoot>
             <tr>
                 <th>{{ 'Student' | get_lang }}</th>
+                <th>{{ 'Sesion' | get_lang }}</th>
+                <th>{{ 'Course' | get_lang }}</th>
                 <th>{{ 'Date' | get_lang }}</th>
                 <th>{{ 'Certificate' | get_lang }}</th>
             </tr>
@@ -102,6 +71,8 @@
             {% for student in certificateStudents %}
                 <tr>
                     <td>{{ student.fullName }}</td>
+                    <td>{{ student.sessionName }}</td>
+                    <td>{{ student.courseName }}</td>
                     <td>
                         {% for certificate in student.certificates %}
                             <p>{{ certificate.createdAt }}</p>

+ 3 - 0
main/template/default/layout/head.tpl

@@ -465,6 +465,9 @@ $(function() {
     $(".td_actions").parent('tr').mouseout(function() {
         $(".td_actions").hide();
     });*/
+
+    /* Make responsive image maps */
+    $('map').imageMapResize();
 });
 </script>
 {{ css_custom_file_to_string }}

+ 45 - 5
main/work/work.lib.php

@@ -3825,14 +3825,15 @@ function uploadWork($my_folder_data, $_course)
  * @param array $courseInfo
  * @param int $session_id
  */
-function sendAlertToTeacher($workId, $courseInfo, $session_id)
+function sendAlertToUsers($workId, $courseInfo, $session_id)
 {
+    $user_list = array();
     $workData = get_work_assignment_by_id($workId, $courseInfo['real_id']);
     //last value is to check this is not "just" an edit
     //YW Tis part serve to send a e-mail to the tutors when a new file is sent
     $send = api_get_course_setting('email_alert_manager_on_new_doc');
 
-    if ($send > 0) {
+    if ($send == SEND_EMAIL_EVERYONE || $send == SEND_EMAIL_TEACHERS) {
         // Lets predefine some variables. Be sure to change the from address!
         if (empty($session_id)) {
             //Teachers
@@ -3853,9 +3854,37 @@ function sendAlertToTeacher($workId, $courseInfo, $session_id)
                 2
             );
         }
+    }
 
-        $subject = "[" . api_get_setting('siteName') . "] ".get_lang('SendMailBody')."\n".get_lang('CourseName')." : ".$courseInfo['name']."  ";
+    if ($send == SEND_EMAIL_EVERYONE || $send == SEND_EMAIL_STUDENTS) {
+        if (!$session_id) {
+            $session_id = null;
+        }
+        $student = CourseManager::get_user_list_from_course_code(
+            api_get_course_id(),
+            $session_id,
+            null,
+            null,
+            STUDENT,
+            null,
+            null,
+            null,
+            null,
+            null,
+            array(api_get_user_id())
+        );
+        $user_list = array_merge($user_list, $student);
+    }
 
+    if ($send) {
+        $senderEmail = api_get_setting('emailAdministrator');
+        $senderName = api_get_person_name(
+            api_get_setting('administratorName'),
+            api_get_setting('administratorSurname'),
+            null,
+            PERSON_NAME_EMAIL_ADDRESS
+        );
+        $subject = "[" . api_get_setting('siteName') . "] ".get_lang('SendMailBody')."\n".get_lang('CourseName')." : ".$courseInfo['name']."  ";
         foreach ($user_list as $user_data) {
             $to_user_id = $user_data['user_id'];
             $user_info = api_get_user_info($to_user_id);
@@ -3865,8 +3894,19 @@ function sendAlertToTeacher($workId, $courseInfo, $session_id)
             $message .= get_lang('WorkName')." : ".$workData['title']."\n\n".get_lang('DownloadLink')."\n";
             $url = api_get_path(WEB_CODE_PATH)."work/work.php?cidReq=".$courseInfo['code']."&id_session=".$session_id."&id=".$workData['id'];
             $message .= $url;
-
             MessageManager::send_message_simple($to_user_id, $subject, $message);
+            api_mail_html(
+                api_get_person_name(
+                    $user_info['firstname'].' '.$user_info['lastname'],
+                    null,
+                    PERSON_NAME_EMAIL_ADDRESS
+                ),
+                $user_info['email'],
+                $subject,
+                $message,
+                $senderName,
+                $senderEmail
+            );
         }
     }
 }
@@ -3958,7 +3998,7 @@ function processWorkForm($workInfo, $values, $courseInfo, $sessionId, $groupId,
                 $userId,
                 $groupId
             );
-            sendAlertToTeacher($workId, $courseInfo, $sessionId);
+            sendAlertToUsers($workId, $courseInfo, $sessionId);
             Event::event_upload($workId);
             $message = Display::return_message(get_lang('DocAdd'));
         }

+ 5 - 6
plugin/advanced_subscription/src/admin_view.php

@@ -27,21 +27,20 @@ if (!empty($sessionId)) {
     $sessionList[$sessionId]['selected'] = 'selected="selected"';
     $studentList['session']['id'] = $sessionId;
     // Assign variables
-    $fieldsArray = array('description', 'target', 'mode', 'publication_end_date', 'recommended_number_of_participants');
+    $fieldsArray = array('description', 'target', 'mode', 'publication_end_date', 'recommended_number_of_participants', 'vacancies');
     $sessionArray = api_get_session_info($sessionId);
     $extraSession = new ExtraFieldValue('session');
     $extraField = new ExtraField('session');
     // Get session fields
     $fieldList = $extraField->get_all(array(
-        'field_variable IN ( ?, ?, ?, ?, ?)' => $fieldsArray
+        'field_variable IN ( ?, ?, ?, ?, ?, ?)' => $fieldsArray
     ));
     // Index session fields
     foreach ($fieldList as $field) {
         $fields[$field['id']] = $field['field_variable'];
     }
-
-    $mergedArray = array_merge(array($sessionId), array_keys($fields));
-    $sessionFieldValueList = $extraSession->get_all(array('session_id = ? field_id IN ( ?, ?, ?, ?, ?, ?, ? )' => $mergedArray));
+    $params = array(' session_id = ? '  => $sessionId);
+    $sessionFieldValueList = $extraSession->get_all(array('where' => $params));
     foreach ($sessionFieldValueList as $sessionFieldValue) {
             // Check if session field value is set in session field list
         if (isset($fields[$sessionFieldValue['field_id']])) {
@@ -73,7 +72,7 @@ if (!empty($sessionId)) {
             $student['firstname'] . ', ' . $student['lastname'] :
             $student['lastname'] . ', ' . $student['firstname'];
     }
-    $tpl->assign('session', $studentList['session']);
+    $tpl->assign('session', $sessionArray);
     $tpl->assign('students', $studentList['students']);
 }
 

+ 11 - 7
plugin/resubscription/src/HookResubscription.php

@@ -31,13 +31,17 @@ class HookResubscription extends HookObserver implements HookResubscribeObserver
 
             $resubscriptionLimit = Resubscription::create()->get('resubscription_limit');
 
-            $limitDate = gmdate('Y-m-d');
+            // Initialize variables as a calendar year by default
+            $limitDateFormat = 'Y-01-01';
+            $limitDate = gmdate($limitDateFormat);
+            $resubscriptionOffset = "1 year";
 
-            switch ($resubscriptionLimit) {
-                case 'calendar_year':
-                    $resubscriptionLimit = "1 year";
-                    $limitDate = gmdate('Y-m-d', strtotime(gmdate('Y-m-d')." -$resubscriptionLimit"));
-                    break;
+            // No need to use a 'switch' with only two options so an 'if' is enough.
+            // However this could change if the number of options increases
+            if ($resubscriptionLimit === 'natural_year') {
+                $limitDateFormat = 'Y-m-d';
+                $limitDate = gmdate($limitDateFormat);
+                $limitDate = gmdate($limitDateFormat, strtotime("$limitDate -$resubscriptionOffset"));
             }
 
             $join = " INNER JOIN ".Database::get_main_table(TABLE_MAIN_SESSION)."ON id = id_session";
@@ -94,7 +98,7 @@ class HookResubscription extends HookObserver implements HookResubscribeObserver
             foreach ($currentSessionCourseResult as $currentSessionCourse) {
                 if (isset($userSessionCourses[$currentSessionCourse['course_code']])) {
                     $endDate = $userSessionCourses[$currentSessionCourse['course_code']];
-                    $resubscriptionDate = gmdate('Y-m-d', strtotime($endDate." +$resubscriptionLimit"));
+                    $resubscriptionDate = gmdate($limitDateFormat, strtotime($endDate." +$resubscriptionOffset"));
                     $icon = Display::return_icon('students.gif', get_lang('Student'));
                     $canResubscribeFrom = sprintf(get_plugin_lang('CanResubscribeFromX', 'resubscription'), $resubscriptionDate);
                     throw new Exception(Display::label($icon . ' ' . $canResubscribeFrom, "info"));

+ 2 - 2
plugin/resubscription/src/Resubscription.php

@@ -16,7 +16,8 @@ class Resubscription extends Plugin implements HookPluginInterface
     protected function __construct()
     {
         $options = array(
-            'calendar_year' => get_lang('CalendarYear')
+            'calendar_year' => get_lang('CalendarYear'),
+            'natural_year' => get_lang('NaturalYear')
         );
         $parameters = array(
             'resubscription_limit' => array(
@@ -24,7 +25,6 @@ class Resubscription extends Plugin implements HookPluginInterface
                 'options' => $options
             )
         );
-
         parent::__construct('0.1', 'Imanol Losada Oriol', $parameters);
     }