diff --git a/main/attendance/attendance_calendar.php b/main/attendance/attendance_calendar.php
index 776b0b4ab1..a9f2ad81e6 100755
--- a/main/attendance/attendance_calendar.php
+++ b/main/attendance/attendance_calendar.php
@@ -91,9 +91,24 @@ if (isset($action) && $action == 'calendar_add') {
$a_repeat_type = [
'daily' => get_lang('RepeatDaily'),
'weekly' => get_lang('RepeatWeekly'),
+ 'biweekly' => get_lang('RepeatBiweekly'),
+ 'xdays' => get_lang('RepeatXDays'),
'monthlyByDate' => get_lang('RepeatMonthlyByDate'),
];
- $form->addElement('select', 'repeat_type', get_lang('RepeatType'), $a_repeat_type);
+
+ $form->addElement(
+ 'select',
+ 'repeat_type',
+ get_lang('RepeatType'),
+ $a_repeat_type,
+ [
+ 'onchange' => "javascript: if(this.value == 'xdays'){document.getElementById('repeat-date-xdaysnumber').style.display='block';}else{document.getElementById('repeat-date-xdaysnumber').style.display='none';}",
+ ]
+ );
+
+ $form->addElement('html', '
');
+ $form->addText('xdays_number', get_lang('NumberOfDays'));
+ $form->addElement('html', '
');
$form->addElement(
'date_picker',
@@ -104,8 +119,20 @@ if (isset($action) && $action == 'calendar_add') {
$defaults['end_date_time'] = date('Y-m-d');
$form->addElement('html', '');
- $defaults['repeat_type'] = 'weekly';
+ $extraField = new ExtraField('attendance_calendar');
+ $extraField->addElements(
+ $form,
+ 0,
+ [], //exclude
+ false, // filter
+ false, // tag as select
+ [], //show only fields
+ [], // order fields
+ [] // extra data
+ );
+ $defaults['repeat_type'] = 'weekly';
+ $defaults['xdays_number'] = '0';
$form->addSelect('groups', get_lang('Group'), $groupIdList);
$form->addButtonCreate(get_lang('Save'));
@@ -142,6 +169,19 @@ if (isset($action) && $action == 'calendar_add') {
['form_name' => 'attendance_calendar_edit'],
5
);
+
+ $extraField = new ExtraField('attendance_calendar');
+ $extraField->addElements(
+ $form,
+ $calendar_id,
+ [], //exclude
+ false, // filter
+ false, // tag as select
+ [], //show only fields
+ [], // order fields
+ [] // extra data
+ );
+
$defaults['date_time'] = $calendar['date_time'];
$form->addButtonSave(get_lang('Save'));
$form->addButtonCancel(get_lang('Cancel'), 'cancel');
@@ -149,6 +189,9 @@ if (isset($action) && $action == 'calendar_add') {
$form->display();
echo '';
} else {
+ $extraValueDuration = Attendance::getAttendanceCalendarExtraFieldValue('duration', $calendar['id']);
+ $labelDuration = !empty($extraValueDuration) ? ' - '.get_lang('Duration').': '.$extraValueDuration : '';
+
echo Display::return_icon(
'lp_calendar_event.png',
get_lang('DateTime'),
@@ -160,7 +203,7 @@ if (isset($action) && $action == 'calendar_add') {
0,
strlen($calendar['date_time']) - 3
).
- ' ';
+ ' '.$labelDuration;
if (isset($calendar['groups']) && !empty($calendar['groups'])) {
foreach ($calendar['groups'] as $group) {
diff --git a/main/attendance/attendance_comment.inc.php b/main/attendance/attendance_comment.inc.php
new file mode 100644
index 0000000000..6941104926
--- /dev/null
+++ b/main/attendance/attendance_comment.inc.php
@@ -0,0 +1,88 @@
+
+
diff --git a/main/attendance/attendance_controller.php b/main/attendance/attendance_controller.php
index bb54903833..95a7568b96 100755
--- a/main/attendance/attendance_controller.php
+++ b/main/attendance/attendance_controller.php
@@ -406,6 +406,7 @@ class AttendanceController
$attendanceInfo = $attendance->get_attendance_by_id($attendance_id);
$allowSignature = api_get_configuration_value('enable_sign_attendance_sheet');
+ $allowComment = api_get_configuration_value('attendance_allow_comments');
$func = isset($_REQUEST['func']) ? $_REQUEST['func'] : null;
$calendarId = isset($_REQUEST['calendar_id']) ? (int) $_REQUEST['calendar_id'] : null;
$fullScreen = ($func == 'fullscreen' && $calendarId > 0 && $allowSignature);
@@ -413,6 +414,7 @@ class AttendanceController
$data['edit_table'] = intval($edit);
$data['is_locked_attendance'] = $attendance->is_locked_attendance($attendance_id);
$data['allowSignature'] = $allowSignature;
+ $data['allowComment'] = $allowComment;
$data['fullScreen'] = $fullScreen;
$data['attendanceName'] = $attendanceInfo['name'];
@@ -478,7 +480,8 @@ class AttendanceController
$start_datetime,
$end_datetime,
$repeat_type,
- $groupList
+ $groupList,
+ $_POST
);
$action = 'calendar_list';
} else {
@@ -513,7 +516,7 @@ class AttendanceController
$datetime = $_POST['date_time'];
$datetimezone = api_get_utc_datetime($datetime);
$attendance->set_date_time($datetimezone);
- $attendance->attendance_calendar_edit($calendar_id, $attendance_id);
+ $attendance->attendance_calendar_edit($calendar_id, $attendance_id, $_POST);
$data['calendar_id'] = 0;
$action = 'calendar_list';
} else {
@@ -544,6 +547,47 @@ class AttendanceController
$this->view->render();
}
+ /**
+ * It checks the attendance sheet to export XLS.
+ *
+ * @param $attendanceId
+ * @param int $studentId
+ * @param string $courseId
+ * @param null $groupId
+ * @param null $filter
+ */
+ public function attendanceSheetExportToXls(
+ $attendanceId,
+ $studentId = 0,
+ $courseId = '',
+ $groupId = null,
+ $filter = null
+ ) {
+ $attendance = new Attendance();
+ $courseInfo = api_get_course_info($courseId);
+ $attendance->set_course_id($courseInfo['code']);
+
+ $filterType = 'today';
+ if (!empty($filter)) {
+ $filterType = $filter;
+ }
+
+ $myCalendarId = null;
+ if (is_numeric($filterType)) {
+ $myCalendarId = $filterType;
+ $filterType = 'calendar_id';
+ }
+
+ $attendance->exportAttendanceSheetToXls(
+ $attendanceId,
+ $studentId,
+ $courseId,
+ $groupId,
+ $filterType,
+ $myCalendarId
+ );
+ }
+
/**
* It's used to print attendance sheet.
*
@@ -613,9 +657,11 @@ class AttendanceController
$data_table = [];
$head_table = ['#', get_lang('Name')];
foreach ($data_array['attendant_calendar'] as $class_day) {
+ $labelDuration = !empty($class_day['duration']) ? get_lang('Duration').' : '.$class_day['duration'] : '';
$head_table[] =
api_format_date($class_day['date_time'], DATE_FORMAT_NUMBER_NO_YEAR).' '.
- api_format_date($class_day['date_time'], TIME_NO_SEC_FORMAT);
+ api_format_date($class_day['date_time'], TIME_NO_SEC_FORMAT).' '.
+ $labelDuration;
}
$data_table[] = $head_table;
$data_attendant_calendar = $data_array['attendant_calendar'];
diff --git a/main/attendance/attendance_sheet.php b/main/attendance/attendance_sheet.php
index 130739a54a..f52338c7f9 100755
--- a/main/attendance/attendance_sheet.php
+++ b/main/attendance/attendance_sheet.php
@@ -114,6 +114,8 @@ if (api_is_allowed_to_edit(null, true) ||
Display::return_icon('attendance_calendar.png', get_lang('AttendanceCalendar'), '', ICON_SIZE_MEDIUM).'';
$actionsLeft .= ''.
Display::return_icon('pdf.png', get_lang('ExportToPDF'), '', ICON_SIZE_MEDIUM).'';
+ $actionsLeft .= ''.
+ Display::return_icon('export_excel.png', get_lang('ExportToXls'), '', ICON_SIZE_MEDIUM).'';
$actionsLeft .= ''.
Display::return_icon('paint.png', get_lang('DownloadQr'), '', ICON_SIZE_MEDIUM).'';
$actionsRight = $form->returnForm();
@@ -270,7 +272,8 @@ if (api_is_allowed_to_edit(null, true) ||
foreach ($attendant_calendar as $calendar) {
$date = $calendar['date'];
$time = $calendar['time'];
- $datetime = ''.$date.' - '.$time.'
';
+ $duration = !empty($calendar['duration']) ? get_lang('Duration').' : '.$calendar['duration'] : '';
+ $datetime = ''.$date.' - '.$time.' '.$duration.'
';
$img_lock = Display::return_icon(
'lock-closed.png',
@@ -394,31 +397,35 @@ if (api_is_allowed_to_edit(null, true) ||
echo '';
echo '';
+ $commentBtnIcon = '';
+ if ($allowComment) {
+ $commentBtnIcon = ' ';
+ }
+
if (api_is_allowed_to_edit(null, true)) {
if (!$is_locked_attendance || api_is_platform_admin()) {
if ($allowSignature) {
if ($signed) {
echo Display::return_icon('checkbox_on.png', get_lang('Presence'), null, ICON_SIZE_TINY);
echo ' ';
- echo ' ';
+ echo $commentBtnIcon;
+ echo '
+
+ ';
} else {
echo ' ';
echo ' ';
- echo ' ';
+ echo $commentBtnIcon;
+ echo '
+
+ ';
}
} else {
echo ' ';
echo ' ';
+ echo $commentBtnIcon;
}
} else {
echo $presence ? Display::return_icon('checkbox_on.png', get_lang('Presence'), null, ICON_SIZE_TINY) : Display::return_icon('checkbox_off.png', get_lang('Presence'), null, ICON_SIZE_TINY);
@@ -564,4 +571,6 @@ if (api_is_allowed_to_edit(null, true) ||
if ($allowSignature) {
include_once 'attendance_signature.inc.php';
}
-?>
+if ($allowComment) {
+ include_once 'attendance_comment.inc.php';
+}
diff --git a/main/attendance/index.php b/main/attendance/index.php
index 9018d978fb..a0be765a34 100755
--- a/main/attendance/index.php
+++ b/main/attendance/index.php
@@ -37,6 +37,7 @@ $actions = [
'attendance_set_visible_select',
'attendance_restore',
'attendance_sheet_export_to_pdf',
+ 'attendance_sheet_export_to_xls',
'attendance_sheet_list_no_edit',
'calendar_logins',
'lock_attendance',
@@ -349,6 +350,18 @@ switch ($action) {
$student_id,
$course_id
);
+ break;
+ case 'attendance_sheet_export_to_xls':
+ $groupId = isset($_REQUEST['group_id']) ? $_REQUEST['group_id'] : null;
+ $filter = isset($_REQUEST['filter']) ? $_REQUEST['filter'] : null;
+ $attendanceController->attendanceSheetExportToXls(
+ $attendance_id,
+ $student_id,
+ $course_id,
+ $groupId,
+ $filter
+ );
+
break;
case 'attendance_sheet_add':
if ($allowToEdit) {
diff --git a/main/inc/ajax/user_manager.ajax.php b/main/inc/ajax/user_manager.ajax.php
index b14d362f60..2bee845685 100755
--- a/main/inc/ajax/user_manager.ajax.php
+++ b/main/inc/ajax/user_manager.ajax.php
@@ -17,6 +17,36 @@ $isRequestByAjax = $request->isXmlHttpRequest();
$action = $_REQUEST['a'];
switch ($action) {
+ case 'comment_attendance':
+ $selected = $_REQUEST['selected'];
+ $comment = $_REQUEST['comment'];
+ $attendanceId = (int) $_REQUEST['attendance_id'];
+ if (!empty($selected)) {
+ list($prefix, $userId, $attendanceCalendarId) = explode('-', $selected);
+ $attendance = new Attendance();
+ $attendance->saveComment(
+ (int) $userId,
+ (int) $attendanceCalendarId,
+ $comment,
+ $attendanceId
+ );
+ echo 1;
+ exit;
+ }
+ echo 0;
+ break;
+ case 'get_attendance_comment':
+ $selected = $_REQUEST['selected'];
+ if (!empty($selected)) {
+ list($prefix, $userId, $attendanceCalendarId) = explode('-', $selected);
+ $attendance = new Attendance();
+ $comment = $attendance->getComment(
+ (int) $userId,
+ (int) $attendanceCalendarId
+ );
+ echo $comment;
+ }
+ break;
case 'block_attendance_calendar':
$calendarId = (int) $_REQUEST['calendar_id'];
$attendance = new Attendance();
diff --git a/main/inc/lib/attendance.lib.php b/main/inc/lib/attendance.lib.php
index f3248030cf..efc7eaaaaf 100755
--- a/main/inc/lib/attendance.lib.php
+++ b/main/inc/lib/attendance.lib.php
@@ -12,6 +12,7 @@
*/
use Chamilo\CourseBundle\Entity\CAttendanceCalendar;
+use Chamilo\CourseBundle\Entity\CAttendanceResultComment;
use Chamilo\CourseBundle\Entity\CAttendanceSheet;
class Attendance
@@ -1567,6 +1568,7 @@ class Attendance
$row['date'] = api_format_date($row['date_time'], DATE_FORMAT_SHORT);
$row['time'] = api_format_date($row['date_time'], TIME_NO_SEC_FORMAT);
$row['groups'] = $this->getGroupListByAttendanceCalendar($row['id'], $course_id);
+ $row['duration'] = Attendance::getAttendanceCalendarExtraFieldValue('duration', $row['id']);
if ($type == 'today') {
if (date('d-m-Y', api_strtotime($row['date_time'], 'UTC')) == date('d-m-Y', time())) {
$data[] = $row;
@@ -1746,10 +1748,11 @@ class Attendance
*
* @param int $attendanceId
* @param array $groupList
+ * @param array $extraValues
*
* @return int affected rows
*/
- public function attendance_calendar_add($attendanceId, $groupList = [])
+ public function attendance_calendar_add($attendanceId, $groupList = [], $extraValues = [])
{
$tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
$affected_rows = 0;
@@ -1775,6 +1778,13 @@ class Attendance
$sql = "UPDATE $tbl_attendance_calendar SET id = iid WHERE iid = $id";
Database::query($sql);
$affected_rows++;
+
+ if (!empty($extraValues)) {
+ // It saves extra fields values
+ $extraFieldValue = new ExtraFieldValue('attendance_calendar');
+ $extraValues['item_id'] = $id;
+ $extraFieldValue->saveFieldValues($extraValues);
+ }
}
$this->addAttendanceCalendarToGroup($id, $course_id, $groupList);
//}
@@ -1892,7 +1902,7 @@ class Attendance
* @param int $attendanceId
* @param int $start_date start date in tms
* @param int $end_date end date in tms
- * @param string $repeat_type daily, weekly, monthlyByDate
+ * @param string $repeat_type daily, weekly, biweekly, xdays, monthlyByDate
* @param array $groupList
*/
public function attendance_repeat_calendar_add(
@@ -1900,58 +1910,84 @@ class Attendance
$start_date,
$end_date,
$repeat_type,
- $groupList = []
+ $groupList = [],
+ $extraValues = []
) {
$attendanceId = intval($attendanceId);
// save start date
$datetimezone = api_get_utc_datetime($start_date);
$this->set_date_time($datetimezone);
- $this->attendance_calendar_add($attendanceId, $groupList);
+ $this->attendance_calendar_add($attendanceId, $groupList, $extraValues);
// 86400 = 24 hours in seconds
// 604800 = 1 week in seconds
+ // 1296000 = 2 weeks in seconds
+ // 2419200 = 1 month in seconds
+ // 86400 x xdays = interval by x days (in seconds)
// Saves repeated dates
+ $seconds = 0;
switch ($repeat_type) {
case 'daily':
- $j = 1;
- for ($i = $start_date + 86400; ($i <= $end_date); $i += 86400) {
- $datetimezone = api_get_utc_datetime($i);
- $this->set_date_time($datetimezone);
- $this->attendance_calendar_add($attendanceId, $groupList);
- $j++;
- }
+ $seconds = 86400;
break;
case 'weekly':
- $j = 1;
- for ($i = $start_date + 604800; ($i <= $end_date); $i += 604800) {
- $datetimezone = api_get_utc_datetime($i);
- $this->set_date_time($datetimezone);
- $this->attendance_calendar_add($attendanceId, $groupList);
- $j++;
- }
+ $seconds = 604800;
+ break;
+ case 'biweekly':
+ $seconds = 1296000;
break;
case 'monthlyByDate':
- $j = 1;
- //@todo fix bug with february
- for ($i = $start_date + 2419200; ($i <= $end_date); $i += 2419200) {
- $datetimezone = api_get_utc_datetime($i);
- $this->set_date_time($datetimezone);
- $this->attendance_calendar_add($attendanceId, $groupList);
- $j++;
- }
+ $seconds = 2419200;
break;
+ case 'xdays':
+ $seconds = isset($extraValues['xdays_number']) ? (int) $extraValues['xdays_number'] * 86400 : 0;
+ break;
+ }
+
+ if ($seconds > 0) {
+ $j = 1;
+ for ($i = $start_date + $seconds; ($i <= $end_date); $i += $seconds) {
+ $datetimezone = api_get_utc_datetime($i);
+ $this->set_date_time($datetimezone);
+ $this->attendance_calendar_add($attendanceId, $groupList, $extraValues);
+ $j++;
+ }
}
}
+ /**
+ * Gets the value of a attendance calendar extra field. Returns null if it was not found.
+ *
+ * @param string $variable Name of the extra field
+ * @param string $calendarId Calendar id
+ *
+ * @return string Value
+ */
+ public static function getAttendanceCalendarExtraFieldValue($variable, $calendarId)
+ {
+ if (true !== api_get_configuration_value('attendance_calendar_set_duration')) {
+ return false;
+ }
+
+ $extraFieldValues = new ExtraFieldValue('attendance_calendar');
+ $result = $extraFieldValues->get_values_by_handler_and_field_variable($calendarId, $variable);
+ if (!empty($result['value'])) {
+ return $result['value'];
+ }
+
+ return null;
+ }
+
/**
* edit a datetime inside attendance calendar table.
*
- * @param int attendance calendar id
- * @param int attendance id
+ * @param int attendance calendar id
+ * @param int attendance id
+ * @param array extra values
*
* @return int affected rows
*/
- public function attendance_calendar_edit($calendar_id, $attendanceId)
+ public function attendance_calendar_edit($calendar_id, $attendanceId, $extraValues = [])
{
$tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
$affected_rows = 0;
@@ -1972,6 +2008,11 @@ class Attendance
Database::query($sql);
}
+ // It saves extra fields values
+ $extraFieldValue = new ExtraFieldValue('attendance_calendar');
+ $extraValues['item_id'] = $calendar_id;
+ $extraFieldValue->saveFieldValues($extraValues);
+
// update locked attendance
$is_all_calendar_done = self::is_all_attendance_calendar_done($attendanceId);
if (!$is_all_calendar_done) {
@@ -2635,6 +2676,211 @@ class Attendance
return $signature;
}
+ /**
+ * Exports the attendance sheet to Xls format.
+ */
+ public function exportAttendanceSheetToXls(
+ int $attendanceId,
+ int $studentId,
+ string $courseCode,
+ int $groupId,
+ string $filterType,
+ int $myCalendarId
+ ) {
+ $users = $this->get_users_rel_course($attendanceId, $groupId);
+ $calendar = $this->get_attendance_calendar(
+ $attendanceId,
+ $filterType,
+ $myCalendarId,
+ $groupId
+ );
+
+ if (!empty($studentId)) {
+ $userId = $studentId;
+ } else {
+ $userId = api_get_user_id();
+ }
+ $courseInfo = api_get_course_info($courseCode);
+
+ $userPresence = [];
+ if (api_is_allowed_to_edit(null, true) || api_is_drh()) {
+ $userPresence = $this->get_users_attendance_sheet($attendanceId, 0, $groupId);
+ } else {
+ $userPresence = $this->get_users_attendance_sheet($attendanceId, $userId, $groupId);
+ }
+
+ // Set headers pdf.
+ $teacherInfo = CourseManager::get_teacher_list_from_course_code($courseInfo['code']);
+ $teacherName = null;
+ foreach ($teacherInfo as $teacherData) {
+ if ($teacherName != null) {
+ $teacherName = $teacherName." / ";
+ }
+ $teacherName .= api_get_person_name($teacherData['firstname'], $teacherData['lastname']);
+ }
+
+ // Get data table
+ $dataTable = [];
+ $headTable = ['#', get_lang('Name')];
+ foreach ($calendar as $classDay) {
+ $labelDuration = !empty($classDay['duration']) ? get_lang('Duration').' : '.$classDay['duration'] : '';
+ $headTable[] =
+ api_format_date($classDay['date_time'], DATE_FORMAT_NUMBER_NO_YEAR).' '.
+ api_format_date($classDay['date_time'], TIME_NO_SEC_FORMAT).' '.
+ $labelDuration;
+ }
+ $dataTable[] = $headTable;
+ $dataUsersPresence = $userPresence;
+ $count = 1;
+
+ if (!empty($users)) {
+ foreach ($users as $user) {
+ $cols = 1;
+ $result = [];
+ $result['count'] = $count;
+ $result['full_name'] = api_get_person_name($user['firstname'], $user['lastname']);
+ foreach ($calendar as $classDay) {
+ $comment = $this->getComment($user['user_id'], $classDay['id']);
+ $txtComment = !empty($comment) ? '[comment]'.$comment : '';
+ if (1 == (int) $classDay['done_attendance']) {
+ if (1 == (int) $dataUsersPresence[$user['user_id']][$classDay['id']]['presence']) {
+ $result[$classDay['id']] = get_lang('UserAttendedSymbol').$txtComment;
+ } else {
+ $result[$classDay['id']] = get_lang('UserNotAttendedSymbol').$txtComment;
+ }
+ } else {
+ $result[$classDay['id']] = ' ';
+ }
+ $cols++;
+ }
+ $count++;
+ $dataTable[] = $result;
+ }
+ }
+
+ $filename = get_lang('Attendance').'-'.api_get_local_time();
+ Export::arrayToXlsAndComments($dataTable, $filename);
+
+ exit;
+ }
+
+ /**
+ * Get the user comment in attendance sheet.
+ *
+ * @return false|string
+ */
+ public function getComment(
+ int $userId,
+ int $attendanceCalendarId
+ ) {
+ $allowComment = api_get_configuration_value('attendance_allow_comments');
+ if (!$allowComment) {
+ return false;
+ }
+
+ $courseId = api_get_course_int_id();
+ $em = Database::getManager();
+ $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
+
+ $criteria = [
+ 'userId' => $userId,
+ 'attendanceCalendarId' => $attendanceCalendarId,
+ 'cId' => $courseId,
+ ];
+ $attendanceSheet = $repo->findOneBy($criteria);
+
+ $comment = "";
+ if ($attendanceSheet) {
+ /** @var CAttendanceSheet $attendanceSheet */
+ $attendanceSheetId = $attendanceSheet->getIid();
+
+ $criteria = [
+ 'userId' => $userId,
+ 'attendanceSheetId' => $attendanceSheetId,
+ ];
+
+ $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceResultComment');
+ $attendanceResultComment = $repo->findOneBy($criteria);
+
+ /** @var CAttendanceResultComment $attendanceResultComment */
+ if ($attendanceResultComment) {
+ $comment = $attendanceResultComment->getComment();
+ }
+ }
+
+ return $comment;
+ }
+
+ /**
+ * Saves the user comment from attendance sheet.
+ *
+ * @return false
+ */
+ public function saveComment(
+ int $userId,
+ int $attendanceCalendarId,
+ string $comment,
+ int $attendanceId
+ ) {
+ $allowComment = api_get_configuration_value('attendance_allow_comments');
+ if (!$allowComment) {
+ return false;
+ }
+
+ $courseId = api_get_course_int_id();
+ $em = Database::getManager();
+ $criteria = [
+ 'userId' => $userId,
+ 'attendanceCalendarId' => $attendanceCalendarId,
+ 'cId' => $courseId,
+ ];
+
+ $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
+ $attendanceSheet = $repo->findOneBy($criteria);
+
+ /** @var CAttendanceSheet $attendanceSheet */
+ if (!$attendanceSheet) {
+ $attendanceSheet = new CAttendanceSheet();
+ $attendanceSheet
+ ->setCId($courseId)
+ ->setPresence(0)
+ ->setUserId($userId)
+ ->setAttendanceCalendarId($attendanceCalendarId);
+
+ $em->persist($attendanceSheet);
+ $em->flush();
+ }
+ $this->updateUsersResults([$userId], $attendanceId);
+
+ $attendanceSheetId = $attendanceSheet->getIid();
+
+ // It saves the comment in the current attendance sheet
+ $criteria = [
+ 'userId' => $userId,
+ 'attendanceSheetId' => $attendanceSheetId,
+ ];
+
+ $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceResultComment');
+ $attendanceResultComment = $repo->findOneBy($criteria);
+
+ /** @var CAttendanceResultComment $attendanceResultComment */
+ if ($attendanceResultComment) {
+ $attendanceResultComment->setComment($comment);
+ $attendanceResultComment->setUpdatedAt(api_get_utc_datetime(null, false, true));
+ $em->persist($attendanceResultComment);
+ $em->flush();
+ } else {
+ $attendanceResultComment = new CAttendanceResultComment();
+ $attendanceResultComment
+ ->setAttendanceSheetId($attendanceSheetId)
+ ->setUserId($userId)
+ ->setComment($comment);
+
+ $em->persist($attendanceResultComment);
+ $em->flush();
+ }
+ }
+
/**
* It saves the user sign from attendance sheet.
*
diff --git a/main/inc/lib/export.lib.inc.php b/main/inc/lib/export.lib.inc.php
index a775cfb796..8ab8ac0278 100755
--- a/main/inc/lib/export.lib.inc.php
+++ b/main/inc/lib/export.lib.inc.php
@@ -90,6 +90,69 @@ class Export
exit;
}
+ /**
+ * Export tabular data to XLS-file included comments.
+ *
+ * @param array $data The comment by cell should be added with the prefix [comment] to be added ($txtCellValue.'[comment]'.$txtComment)
+ */
+ public static function arrayToXlsAndComments(
+ array $data,
+ string $filename = 'export'
+ ) {
+ $filePath = api_get_path(SYS_ARCHIVE_PATH).uniqid('').'.xlsx';
+ $file = new \SplFileObject($filePath, 'w');
+
+ $excel = @new PHPExcel();
+
+ $type = 'Excel2007';
+ $sheet = null;
+ $row = 1;
+ $prependHeaderRow = false;
+ if (null !== $sheet && !$excel->sheetNameExists($sheet)) {
+ $excel->removeSheetByIndex(0);
+ }
+
+ if (null !== $sheet) {
+ if (!$excel->sheetNameExists($sheet)) {
+ $excel->createSheet()->setTitle($sheet);
+ }
+ $excel->setActiveSheetIndexByName($sheet);
+ }
+
+ foreach ($data as $item) {
+ $count = count($item);
+ if ($prependHeaderRow && 1 == $row) {
+ $headers = array_keys($item);
+
+ for ($i = 0; $i < $count; $i++) {
+ @$excel->getActiveSheet()->setCellValueByColumnAndRow($i, $row, $headers[$i]);
+ }
+ $row++;
+ }
+ $values = array_values($item);
+ for ($i = 0; $i < $count; $i++) {
+ $txtComment = '';
+ $txtValue = $values[$i];
+ if (false !== strpos($values[$i], '[comment]')) {
+ list($txtValue, $txtComment) = explode('[comment]', $values[$i]);
+ }
+ @$excel->getActiveSheet()->setCellValueByColumnAndRow($i, $row, $txtValue);
+ if (!empty($txtComment)) {
+ $columnLetter = PHPExcel_Cell::stringFromColumnIndex($i);
+ $coordinate = $columnLetter.$row;
+ @$excel->getActiveSheet()->getComment($coordinate)->getText()->createTextRun($txtComment);
+ }
+ }
+ $row++;
+ }
+
+ $writer = \PHPExcel_IOFactory::createWriter($excel, $type);
+ $writer->save($file->getPathname());
+ DocumentManager::file_send_for_download($filePath, true, $filename.'.xlsx');
+
+ exit;
+ }
+
/**
* Export tabular data to XLS-file (as html table).
*
diff --git a/main/inc/lib/extra_field.lib.php b/main/inc/lib/extra_field.lib.php
index 46facd3b8d..39d59d571a 100755
--- a/main/inc/lib/extra_field.lib.php
+++ b/main/inc/lib/extra_field.lib.php
@@ -174,6 +174,9 @@ class ExtraField extends Model
case 'document':
$this->extraFieldType = EntityExtraField::DOCUMENT_TYPE;
break;
+ case 'attendance_calendar':
+ $this->extraFieldType = EntityExtraField::ATTENDANCE_CALENDAR_TYPE;
+ break;
}
$this->pageUrl = 'extra_fields.php?type='.$this->type;
@@ -208,6 +211,7 @@ class ExtraField extends Model
'course_announcement',
'message',
'document',
+ 'attendance_calendar',
];
if (api_get_configuration_value('allow_scheduled_announcements')) {
diff --git a/main/install/configuration.dist.php b/main/install/configuration.dist.php
index c545d3b4d0..536ddf389f 100644
--- a/main/install/configuration.dist.php
+++ b/main/install/configuration.dist.php
@@ -2337,6 +2337,16 @@ INSERT INTO `extra_field` (`extra_field_type`, `field_type`, `variable`, `displa
'Change or delete this paragraph or add another one'
]]];*/
+// Option to define duration for a calendar in attendance sheet.
+// Create an attendance calendar extra field with field label "duration" of type "text".
+// $_configuration['attendance_calendar_set_duration'] = false;
+
+// Enable comments in attendance sheet for users
+// Require DB changes:
+//CREATE TABLE c_attendance_result_comment (iid int not null PRIMARY KEY AUTO_INCREMENT, attendance_sheet_id int not null, user_id int not null, created_at datetime not null, updated_at datetime not null, comment text not null);
+//CREATE INDEX c_attendance_sheet_user ON track_e_access_complete (attendance_sheet_id, user_id);
+//$_configuration['attendance_allow_comments'] = false;
+
// KEEP THIS AT THE END
// -------- Custom DB changes
// Add user activation by confirmation email
diff --git a/src/Chamilo/CoreBundle/Entity/ExtraField.php b/src/Chamilo/CoreBundle/Entity/ExtraField.php
index 4063440f7a..2305fcc6ac 100644
--- a/src/Chamilo/CoreBundle/Entity/ExtraField.php
+++ b/src/Chamilo/CoreBundle/Entity/ExtraField.php
@@ -42,6 +42,7 @@ class ExtraField extends BaseAttribute
public const COURSE_ANNOUNCEMENT = 21;
public const MESSAGE_TYPE = 22;
public const DOCUMENT_TYPE = 23;
+ public const ATTENDANCE_CALENDAR_TYPE = 24;
/**
* @var int
diff --git a/src/Chamilo/CourseBundle/Entity/CAttendanceResultComment.php b/src/Chamilo/CourseBundle/Entity/CAttendanceResultComment.php
new file mode 100644
index 0000000000..935cfe10f0
--- /dev/null
+++ b/src/Chamilo/CourseBundle/Entity/CAttendanceResultComment.php
@@ -0,0 +1,182 @@
+createdAt = new \DateTime();
+ $this->updatedAt = new \DateTime();
+ }
+
+ /**
+ * Get attendanceSheetId.
+ */
+ public function getAttendanceSheetId(): int
+ {
+ return $this->attendanceSheetId;
+ }
+
+ /**
+ * Set attendanceSheetId.
+ *
+ * @return CAttendanceResultComment
+ */
+ public function setAttendanceSheetId(int $attendanceSheetId)
+ {
+ $this->attendanceSheetId = $attendanceSheetId;
+
+ return $this;
+ }
+
+ /**
+ * Set userId.
+ *
+ * @param int $userId
+ *
+ * @return CAttendanceResultComment
+ */
+ public function setUserId($userId)
+ {
+ $this->userId = $userId;
+
+ return $this;
+ }
+
+ /**
+ * Get userId.
+ *
+ * @return int
+ */
+ public function getUserId()
+ {
+ return $this->userId;
+ }
+
+ /**
+ * @param \DateTime $createdAt
+ *
+ * @return CAttendanceResultComment
+ */
+ public function setCreatedAt($createdAt)
+ {
+ $this->createdAt = $createdAt;
+
+ return $this;
+ }
+
+ /**
+ * @return \DateTime
+ */
+ public function getCreatedAt()
+ {
+ return $this->createdAt;
+ }
+
+ /**
+ * @param \DateTime $updatedAt
+ *
+ * @return CAttendanceResultComment
+ */
+ public function setUpdatedAt($updatedAt)
+ {
+ $this->updatedAt = $updatedAt;
+
+ return $this;
+ }
+
+ /**
+ * @return \DateTime
+ */
+ public function getUpdatedAt()
+ {
+ return $this->updatedAt;
+ }
+
+ /**
+ * Set comment.
+ *
+ * @param string $comment
+ *
+ * @return CAttendanceResultComment
+ */
+ public function setComment($comment)
+ {
+ $this->comment = $comment;
+
+ return $this;
+ }
+
+ /**
+ * Get comment.
+ *
+ * @return string
+ */
+ public function getComment()
+ {
+ return $this->comment;
+ }
+}
diff --git a/src/Chamilo/CourseBundle/Entity/CAttendanceSheet.php b/src/Chamilo/CourseBundle/Entity/CAttendanceSheet.php
index 1035ac2305..fea8a4737c 100644
--- a/src/Chamilo/CourseBundle/Entity/CAttendanceSheet.php
+++ b/src/Chamilo/CourseBundle/Entity/CAttendanceSheet.php
@@ -62,7 +62,7 @@ class CAttendanceSheet
*
* @ORM\Column(name="signature", type="string", nullable=true)
*/
- //protected $signature;
+ protected $signature;
/**
* Set presence.
|