diff --git a/main/mySpace/session_filter.php b/main/mySpace/session_filter.php
index f7c3b53095a..0feed39ab96 100644
--- a/main/mySpace/session_filter.php
+++ b/main/mySpace/session_filter.php
@@ -9,12 +9,21 @@
require_once __DIR__.'/../inc/global.inc.php';
$this_section = SECTION_TRACKING;
+// CSRF token for delete action.
+$token = Security::get_token();
+
if (!api_is_allowed_to_create_course() && !api_is_drh()) {
api_not_allowed(true);
}
$allowCustomCertificate = 'true' === api_get_plugin_setting('customcertificate', 'enable_plugin_customcertificate');
-$plugin = CustomCertificatePlugin::create();
+
+/** @var CustomCertificatePlugin|null $plugin */
+// Create plugin instance only when the plugin is enabled.
+$plugin = null;
+if ($allowCustomCertificate) {
+ $plugin = CustomCertificatePlugin::create();
+}
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
$tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
@@ -39,7 +48,7 @@
$whereCondictionMultiUrl = " AND session_rel_user.user_id = ".api_get_user_id();
}
-// Select of sessions.
+// Select sessions.
$sql = "SELECT s.id, name FROM $tblSession s
$innerJoinSessionRelUser
$whereCondictionDRH
@@ -51,7 +60,7 @@
if ($accessUrlId != -1) {
$sql = "SELECT s.id, name FROM $tblSession s
INNER JOIN $tblSessionRelAccessUrl as session_rel_url
- ON (s.id = session_rel_url.session_id)
+ ON (s.id = session_rel_url.session_id)
$innerJoinSessionRelUser
WHERE access_url_id = $accessUrlId
$whereCondictionMultiUrl
@@ -66,7 +75,18 @@
$options[$enreg['id']] = $enreg['name'];
}
-$form->addElement('select', 'session_id', get_lang('SessionList'), $options, ['id' => 'session-id']);
+// Multi-select to allow selecting several sessions at once.
+$form->addElement(
+ 'select',
+ 'session_id',
+ get_lang('SessionList'),
+ $options,
+ [
+ 'id' => 'session-id',
+ 'multiple' => 'multiple',
+ 'size' => 10,
+ ]
+);
$form->addDatePicker('date_begin', get_lang('DateStart'), ['id' => 'date-begin']);
$form->addDatePicker('date_end', get_lang('DateEnd'), ['id' => 'date-end']);
@@ -87,14 +107,48 @@
$form->addElement('hidden', 'formSent', 1);
$form->addButtonSearch(get_lang('Search'));
-$form->addButtonExport(get_lang('ExportAsCSV'), 'export');
+// We keep all export actions (CSV, PDF, ZIP) near the result table, so no form-level export button.
+// Decide how to get values: normal search submit or CSV export icon.
+$values = null;
+$exportToCsv = false;
+
+// Case 1: user clicked "Search" button (normal form submit).
if ($form->validate()) {
$values = $form->getSubmitValues();
- $exportToCsv = isset($values['export']);
- $sessionId = (int) $_REQUEST['session_id'];
- $dateBegin = isset($_REQUEST['date_begin']) ? strtotime($_REQUEST['date_begin']) : null;
- $dateEnd = isset($_REQUEST['date_end']) ? strtotime($_REQUEST['date_end'].' 23:59:59') : null;
+ $exportToCsv = false;
+} elseif (isset($_GET['export'])) {
+ // Case 2: CSV export icon was clicked.
+ // Use raw GET parameters as the form values so filters are preserved.
+ $values = $_GET;
+ $exportToCsv = true;
+}
+
+// Process filters and build result list only when we have values (search or export).
+if (!empty($values)) {
+ // Normalize session ids from the form to an integer array.
+ $sessionIds = [];
+ if (!empty($values['session_id'])) {
+ if (is_array($values['session_id'])) {
+ foreach ($values['session_id'] as $sessionIdValue) {
+ $sessionIdValue = (int) $sessionIdValue;
+ if ($sessionIdValue > 0) {
+ $sessionIds[] = $sessionIdValue;
+ }
+ }
+ } else {
+ $sessionIdValue = (int) $values['session_id'];
+ if ($sessionIdValue > 0) {
+ $sessionIds[] = $sessionIdValue;
+ }
+ }
+ }
+
+ $dateBeginRaw = isset($values['date_begin']) ? $values['date_begin'] : null;
+ $dateEndRaw = isset($values['date_end']) ? $values['date_end'] : null;
+
+ $dateBegin = !empty($dateBeginRaw) ? strtotime($dateBeginRaw) : null;
+ $dateEnd = !empty($dateEndRaw) ? strtotime($dateEndRaw.' 23:59:59') : null;
$filterDate = 0;
if (!empty($dateBegin)) {
@@ -104,91 +158,117 @@
$filterDate += DATE_END_FILTER;
}
+ // Build extra-field filter list.
$filterCheckList = [];
$extraField = new ExtraField('user');
$extraFieldsAll = $extraField->get_all(['filter = ?' => 1], 'option_order');
foreach ($extraFieldsAll as $field) {
- if (!empty($_REQUEST['extra_'.$field['variable']])) {
+ $fieldName = 'extra_'.$field['variable'];
+ if (!empty($values[$fieldName])) {
$filterCheckList[$field['id']] = $field;
}
}
- $result = Database::select(
- 'c.id, c.code',
- "$tbl_course c INNER JOIN $tblSessionRelCourse r ON c.id = r.c_id",
- [
- 'where' => [
- "r.session_id = ? " => [$sessionId],
- ],
- ]
- );
+ // Build certificate list for all selected sessions.
+ $certificateList = [];
+ if (!empty($sessionIds)) {
+ foreach ($sessionIds as $sessionId) {
+ $courseResult = Database::select(
+ 'c.id, c.code',
+ "$tbl_course c INNER JOIN $tblSessionRelCourse r ON c.id = r.c_id",
+ [
+ 'where' => [
+ "r.session_id = ? " => [$sessionId],
+ ],
+ ]
+ );
- foreach ($result as $value) {
- $courseId = $value['id'];
- $courseCode = $value['code'];
-
- $cats = Category::load(
- null,
- null,
- $courseCode,
- null,
- null,
- $sessionId,
- 'ORDER BY id'
- );
+ if (empty($courseResult)) {
+ continue;
+ }
- if (empty($cats)) {
- // first time
- $cats = Category::load(
- 0,
- null,
- $courseCode,
- null,
- null,
- $sessionId,
- 'ORDER BY id'
- );
- }
+ $sessionInfo = api_get_session_info($sessionId);
- $selectCat = (int) $cats[0]->get_id();
- $certificateListAux = [];
- if (!empty($selectCat)) {
- $certificateListAux = GradebookUtils::get_list_users_certificates($selectCat);
- }
+ foreach ($courseResult as $course) {
+ $courseId = $course['id'];
+ $courseCode = $course['code'];
- foreach ($certificateListAux as $value) {
- $createdAt = strtotime(api_get_local_time($value['created_at']));
- $value['category_id'] = $selectCat;
- $value['c_id'] = $courseId;
- $value['course_code'] = $courseCode;
- switch ($filterDate) {
- case NO_DATE_FILTER:
- $certificateList[] = $value;
- break;
- case DATE_BEGIN_FILTER:
- if ($createdAt >= $dateBegin) {
- $certificateList[] = $value;
- }
- break;
- case DATE_END_FILTER:
- if ($createdAt <= $dateEnd) {
- $certificateList[] = $value;
+ $cats = Category::load(
+ null,
+ null,
+ $courseCode,
+ null,
+ null,
+ $sessionId,
+ 'ORDER BY id'
+ );
+
+ if (empty($cats)) {
+ // First time load with default category id = 0.
+ $cats = Category::load(
+ 0,
+ null,
+ $courseCode,
+ null,
+ null,
+ $sessionId,
+ 'ORDER BY id'
+ );
+ }
+
+ if (empty($cats)) {
+ continue;
+ }
+
+ $selectCat = (int) $cats[0]->get_id();
+ if ($selectCat <= 0) {
+ continue;
+ }
+
+ $certificateListAux = GradebookUtils::get_list_users_certificates($selectCat);
+ if (empty($certificateListAux)) {
+ continue;
+ }
+
+ foreach ($certificateListAux as $certificate) {
+ $createdAt = strtotime(api_get_local_time($certificate['created_at']));
+ $certificate['category_id'] = $selectCat;
+ $certificate['c_id'] = $courseId;
+ $certificate['course_code'] = $courseCode;
+ $certificate['session_id'] = $sessionId;
+ $certificate['session_name'] = isset($sessionInfo['name']) ? $sessionInfo['name'] : '';
+
+ $includeCertificate = false;
+ switch ($filterDate) {
+ case NO_DATE_FILTER:
+ $includeCertificate = true;
+ break;
+ case DATE_BEGIN_FILTER:
+ $includeCertificate = $createdAt >= $dateBegin;
+ break;
+ case DATE_END_FILTER:
+ $includeCertificate = $createdAt <= $dateEnd;
+ break;
+ case ALL_DATE_FILTER:
+ $includeCertificate = $createdAt >= $dateBegin && $createdAt <= $dateEnd;
+ break;
}
- break;
- case ALL_DATE_FILTER:
- if ($createdAt >= $dateBegin && $createdAt <= $dateEnd) {
- $certificateList[] = $value;
+
+ if ($includeCertificate) {
+ $certificateList[] = $certificate;
}
- break;
+ }
}
}
+ }
- // Filter extra field
- foreach ($certificateList as $key => $value) {
+ // Filter by extra fields after building the global list.
+ if (!empty($filterCheckList) && !empty($certificateList)) {
+ foreach ($certificateList as $key => $certificate) {
foreach ($filterCheckList as $fieldId => $field) {
$extraFieldValue = new ExtraFieldValue('user');
$extraFieldValueData = $extraFieldValue->get_values_by_handler_and_field_id(
- $value['user_id'],
+ $certificate['user_id'],
$fieldId
);
@@ -197,43 +277,78 @@
break;
}
+ $fieldName = 'extra_'.$field['variable'];
+
switch ($field['field_type']) {
case ExtraField::FIELD_TYPE_TEXT:
case ExtraField::FIELD_TYPE_ALPHANUMERIC:
- $pos = stripos($extraFieldValueData['value'], $_REQUEST['extra_'.$field['variable']]);
- if ($pos === false) {
- unset($certificateList[$key]);
+ $filterValue = isset($values[$fieldName]) ? $values[$fieldName] : '';
+ if ($filterValue !== '') {
+ $pos = stripos($extraFieldValueData['value'], (string) $filterValue);
+ if ($pos === false) {
+ unset($certificateList[$key]);
+ }
}
break;
case ExtraField::FIELD_TYPE_RADIO:
- $valueRadio = $_REQUEST['extra_'.$field['variable']]['extra_'.$field['variable']];
- if ($extraFieldValueData['value'] != $valueRadio) {
+ $filterValue = '';
+ if (isset($values[$fieldName][$fieldName])) {
+ $filterValue = $values[$fieldName][$fieldName];
+ }
+ if ($extraFieldValueData['value'] != $filterValue) {
unset($certificateList[$key]);
}
break;
case ExtraField::FIELD_TYPE_SELECT:
- if ($extraFieldValueData['value'] != $_REQUEST['extra_'.$field['variable']]) {
+ $filterValue = isset($values[$fieldName]) ? $values[$fieldName] : null;
+ if ($filterValue !== null && $extraFieldValueData['value'] != $filterValue) {
unset($certificateList[$key]);
}
break;
- }
+ }
}
}
+
+ // Reindex after unsetting items.
+ $certificateList = array_values($certificateList);
+ }
+
+ // Build URL parameters used by the export (PDF / ZIP / CSV) buttons.
+ $params = [];
+
+ if (!empty($sessionIds)) {
+ foreach ($sessionIds as $sessionId) {
+ $params['session_id'][] = $sessionId;
+ }
}
- $params = [
- 'session_id' => (int) $_REQUEST['session_id'],
- 'date_begin' => Security::remove_XSS($_REQUEST['date_begin']),
- 'date_end' => Security::remove_XSS($_REQUEST['date_end']),
- ];
+ // Mark that form has been submitted, so filters can be reused.
+ $params['formSent'] = 1;
+
+ $params['date_begin'] = Security::remove_XSS((string) $dateBeginRaw);
+ $params['date_end'] = Security::remove_XSS((string) $dateEndRaw);
foreach ($filterCheckList as $field) {
- $params['extra_'.$field['variable']] = Security::remove_XSS($_REQUEST['extra_'.$field['variable']]);
+ $fieldName = 'extra_'.$field['variable'];
+ if (!isset($values[$fieldName])) {
+ continue;
+ }
+
+ if (is_array($values[$fieldName])) {
+ $cleanArray = [];
+ foreach ($values[$fieldName] as $key => $val) {
+ $cleanArray[$key] = is_string($val) ? Security::remove_XSS($val) : $val;
+ }
+ $params[$fieldName] = $cleanArray;
+ } else {
+ $params[$fieldName] = Security::remove_XSS((string) $values[$fieldName]);
+ }
}
$urlParam = http_build_query($params);
- $dataToExport = [];
+ // Build CSV data when export is requested.
if ($exportToCsv) {
+ $dataToExport = [];
$headers = [
get_lang('Session'),
get_lang('Course'),
@@ -249,7 +364,6 @@
}
$dataToExport[] = $headers;
- $sessionInfo = api_get_session_info($sessionId);
foreach ($certificateList as $index => $value) {
$categoryId = $value['category_id'];
$courseCode = $value['course_code'];
@@ -274,7 +388,7 @@
$list = GradebookUtils::get_list_gradebook_certificates_by_user_id($value['user_id'], $categoryId);
foreach ($list as $valueCertificate) {
$item = [];
- $item[] = $sessionInfo['name'];
+ $item[] = !empty($value['session_name']) ? $value['session_name'] : '';
$item[] = $courseInfo['title'];
$item[] = $value['firstname'];
$item[] = $value['lastname'];
@@ -285,79 +399,97 @@
}
}
Export::arrayToCsv($dataToExport, 'export');
+
+ // Stop further HTML output when exporting CSV.
+ exit;
}
}
-$htmlHeadXtra[] = "";
+}
$interbreadcrumb[] = ['url' => 'index.php', 'name' => get_lang('MySpace')];
Display::display_header(get_lang('CertificatesSessions'));
echo Display::page_header(get_lang('CertificatesSessions'));
-$actions = '';
-$actions .= Display::url(
+
+// Top toolbar: only back button, always visible.
+$topActions = '';
+$topActions .= Display::url(
Display::return_icon('back.png', get_lang('Back'), [], 32),
api_get_path(WEB_CODE_PATH).'mySpace'
);
+echo Display::toolbarAction('actions', [$topActions]);
-if ($allowCustomCertificate) {
- $url = api_get_path(WEB_PLUGIN_PATH).'customcertificate/src/export_pdf_all_in_one.php';
- $actions .= Display::url(
- Display::return_icon('pdf.png', get_lang('ExportAllCertificatesToPDF'), [], ICON_SIZE_MEDIUM),
- $url,
- ['id' => 'export_pdf']
- );
-
- $actions .= Display::url(
- Display::return_icon('file_zip.png', get_lang('ExportAllCertificatesToZIP'), [], ICON_SIZE_MEDIUM),
- $url,
- ['id' => 'export_zip']
- );
-}
-
-echo Display::toolbarAction('actions', [$actions]);
+// Show search form.
echo $form->returnForm();
if (0 == count($certificateList)) {
echo Display::return_message(get_lang('NoResultsAvailable'), 'warning');
} else {
- echo '
';
+ // Actions related to the result list (CSV, PDF, ZIP) shown just above the table.
+ $resultActions = '';
+
+ // CSV export uses the same page with current filters.
+ $csvUrl = api_get_self().'?'.$urlParam.'&export=1';
+ $resultActions .= Display::url(
+ Display::return_icon('excel.png', get_lang('ExportAsCSV'), [], ICON_SIZE_MEDIUM),
+ $csvUrl
+ );
+
+ if ($allowCustomCertificate) {
+ $pluginUrl = api_get_path(WEB_PLUGIN_PATH).'customcertificate/src/export_pdf_all_in_one.php';
+ $pluginUrlWithParams = $pluginUrl.'?'.$urlParam;
+
+ // Open PDF export in a new tab so the filter form remains visible.
+ $resultActions .= Display::url(
+ Display::return_icon('pdf.png', get_lang('ExportAllCertificatesToPDF'), [], ICON_SIZE_MEDIUM),
+ $pluginUrlWithParams.'&export_pdf=1',
+ [
+ 'id' => 'export_pdf',
+ 'target' => '_blank',
+ ]
+ );
+
+ // Open ZIP export in a new tab so the filter form remains visible.
+ $resultActions .= Display::url(
+ Display::return_icon('file_zip.png', get_lang('ExportAllCertificatesToZIP'), [], ICON_SIZE_MEDIUM),
+ $pluginUrlWithParams.'&export_zip=1',
+ [
+ 'id' => 'export_zip',
+ 'target' => '_blank',
+ ]
+ );
+ }
+
+ // Render result actions toolbar right above the table.
+ echo Display::toolbarAction('result-actions', [$resultActions]);
+
+ // Render table with certificates.
+ echo '';
echo '';
foreach ($certificateList as $index => $value) {
$categoryId = $value['category_id'];
@@ -370,9 +502,9 @@
echo '';
echo '| '.$courseInfo['title'].' | ';
echo '';
- echo '
-
- ';
+ echo '';
+ echo '';
+ echo '';
$list = GradebookUtils::get_list_gradebook_certificates_by_user_id($value['user_id'], $categoryId);
foreach ($list as $valueCertificate) {
@@ -392,10 +524,10 @@
);
echo $certificateUrl.PHP_EOL;
- $url .= '&action=export';
+ $urlExport = $url.'&action=export';
$pdf = Display::url(
Display::return_icon('pdf.png', get_lang('Download')),
- $url,
+ $urlExport,
['target' => '_blank']
);
echo $pdf.PHP_EOL;
@@ -405,9 +537,10 @@
'&'.api_get_cidreq().
'&action=delete'.
'&cat_id='.$categoryId.
- '&certificate_id='.$valueCertificate['id'].'">
- '.Display::return_icon('delete.png', get_lang('Delete')).'
- '.PHP_EOL;
+ '&certificate_id='.$valueCertificate['id'].'">'.
+ Display::return_icon('delete.png', get_lang('Delete')).
+ ''.PHP_EOL;
+
echo '';
}
echo '';
diff --git a/plugin/customcertificate/src/export_pdf_all_in_one.php b/plugin/customcertificate/src/export_pdf_all_in_one.php
index 759cd0f3886..a7bb38617e5 100644
--- a/plugin/customcertificate/src/export_pdf_all_in_one.php
+++ b/plugin/customcertificate/src/export_pdf_all_in_one.php
@@ -8,6 +8,8 @@
require_once __DIR__.'/../config.php';
api_block_anonymous_users();
+
+/** @var CustomCertificatePlugin $plugin */
$plugin = CustomCertificatePlugin::create();
$enable = $plugin->get('enable_plugin_customcertificate') === 'true';
$tblProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
@@ -27,18 +29,63 @@
$currentLocalTime = api_get_local_time();
$accessUrlId = api_get_current_access_url_id();
-$sessionId = isset($_GET['session_id']) ? (int) $_GET['session_id'] : null;
-$dateBegin = isset($_GET['date_begin']) ? strtotime($_GET['date_begin']) : null;
-$dateEnd = isset($_GET['date_end']) ? strtotime($_GET['date_end'].' 23:59:59') : null;
+/*
+ * Support single or multiple session_id parameters:
+ * - session_id=3
+ * - session_id[0]=3&session_id[1]=5
+ */
+$sessionIds = [];
+if (isset($_GET['session_id'])) {
+ if (is_array($_GET['session_id'])) {
+ foreach ($_GET['session_id'] as $rawId) {
+ $id = (int) $rawId;
+ if ($id > 0) {
+ $sessionIds[] = $id;
+ }
+ }
+ } else {
+ $id = (int) $_GET['session_id'];
+ if ($id > 0) {
+ $sessionIds[] = $id;
+ }
+ }
+}
+
+// Remove duplicates just in case.
+$sessionIds = array_values(array_unique($sessionIds));
+
+if (empty($sessionIds)) {
+ // No session selected: nothing to export.
+ Display::display_header($plugin->get_lang('PrintCertificate'));
+ echo Display::return_message(get_lang('NoResultsAvailable'), 'warning');
+ Display::display_footer();
+ exit;
+}
+
+// Date filters (same logic as session_filter.php)
+$dateBeginRaw = isset($_GET['date_begin']) ? $_GET['date_begin'] : null;
+$dateEndRaw = isset($_GET['date_end']) ? $_GET['date_end'] : null;
+
+$dateBegin = !empty($dateBeginRaw) ? strtotime($dateBeginRaw) : null;
+$dateEnd = !empty($dateEndRaw) ? strtotime($dateEndRaw.' 23:59:59') : null;
+
+$filterDate = 0;
+if (!empty($dateBegin)) {
+ $filterDate += DATE_BEGIN_FILTER;
+}
+if (!empty($dateEnd)) {
+ $filterDate += DATE_END_FILTER;
+}
-if (api_is_multiple_url_enabled()) {
- if ($accessUrlId != -1) {
+// Multi-URL protection: every session must belong to the current URL.
+if (api_is_multiple_url_enabled() && $accessUrlId != -1) {
+ foreach ($sessionIds as $sessionId) {
$result = Database::select(
'*',
- "$tblSessionRelAccessUrl",
+ $tblSessionRelAccessUrl,
[
'where' => [
- "access_url_id = ? AND session_id = ?" => [$accessUrlId, $sessionId],
+ 'access_url_id = ? AND session_id = ?' => [$accessUrlId, $sessionId],
],
]
);
@@ -52,51 +99,42 @@
$exportAllInOne = isset($_GET['export_pdf']) ? (int) $_GET['export_pdf'] : false;
$exportZip = isset($_GET['export_zip']) ? (int) $_GET['export_zip'] : false;
-$filterDate = 0;
-if (!empty($dateBegin)) {
- $filterDate += DATE_BEGIN_FILTER;
-}
-if (!empty($dateEnd)) {
- $filterDate += DATE_END_FILTER;
-}
-
+// Build extra fields filter (same approach as session_filter.php).
$filterCheckList = [];
$extraField = new ExtraField('user');
$extraFieldsAll = $extraField->get_all(['filter = ?' => 1], 'option_order');
foreach ($extraFieldsAll as $field) {
- if (!empty($_GET['extra_'.$field['variable']])) {
+ $paramName = 'extra_'.$field['variable'];
+ if (!empty($_GET[$paramName])) {
$filterCheckList[$field['id']] = $field;
}
}
-$result = Database::select(
- 'c.id, c.code',
- "$tblCourse c INNER JOIN $tblSessionRelCourse r ON c.id = r.c_id",
- [
- 'where' => [
- "r.session_id = ? " => [$sessionId],
- ],
- ]
-);
-
-foreach ($result as $value) {
- $courseId = $value['id'];
- $courseCode = $value['code'];
-
- $cats = Category::load(
- null,
- null,
- $courseCode,
- null,
- null,
- $sessionId,
- 'ORDER BY id'
+// Collect all certificates from all selected sessions and their courses (same logic as session_filter.php).
+$certificateList = [];
+
+foreach ($sessionIds as $sessionId) {
+ $courseResult = Database::select(
+ 'c.id, c.code',
+ "$tblCourse c INNER JOIN $tblSessionRelCourse r ON c.id = r.c_id",
+ [
+ 'where' => [
+ 'r.session_id = ? ' => [$sessionId],
+ ],
+ ]
);
- if (empty($cats)) {
- // first time
+ if (empty($courseResult)) {
+ continue;
+ }
+
+ foreach ($courseResult as $value) {
+ $courseId = (int) $value['id'];
+ $courseCode = $value['code'];
+
+ // Load gradebook categories for this course + session.
$cats = Category::load(
- 0,
+ null,
null,
$courseCode,
null,
@@ -104,40 +142,72 @@
$sessionId,
'ORDER BY id'
);
- }
- $selectCat = (int) $cats[0]->get_id();
- $certificateList = [];
- $certificateListAux = GradebookUtils::get_list_users_certificates($selectCat);
-
- foreach ($certificateListAux as $value) {
- $created_at = strtotime(api_get_local_time($value['created_at']));
- $value['category_id'] = $selectCat;
- $value['c_id'] = $courseId;
- $value['course_code'] = $courseCode;
- switch ($filterDate) {
- case NO_DATE_FILTER:
- $certificateList[] = $value;
- break;
- case DATE_BEGIN_FILTER:
- if ($created_at >= $dateBegin) {
- $certificateList[] = $value;
- }
- break;
- case DATE_END_FILTER:
- if ($created_at <= $dateEnd) {
- $certificateList[] = $value;
- }
- break;
- case ALL_DATE_FILTER:
- if ($created_at >= $dateBegin && $created_at <= $dateEnd) {
- $certificateList[] = $value;
- }
- break;
+ if (empty($cats)) {
+ // First time, try with default category id = 0 (same as session_filter.php).
+ $cats = Category::load(
+ 0,
+ null,
+ $courseCode,
+ null,
+ null,
+ $sessionId,
+ 'ORDER BY id'
+ );
+ }
+
+ if (empty($cats)) {
+ // No gradebook category for this course/session.
+ continue;
+ }
+
+ $selectCat = (int) $cats[0]->get_id();
+ if ($selectCat <= 0) {
+ continue;
+ }
+
+ // Get all certificates for this category.
+ $certificateListAux = GradebookUtils::get_list_users_certificates($selectCat);
+ if (empty($certificateListAux)) {
+ continue;
+ }
+
+ foreach ($certificateListAux as $certRow) {
+ $createdAt = strtotime(api_get_local_time($certRow['created_at']));
+
+ // Base row with extra metadata.
+ $row = $certRow;
+ $row['category_id'] = $selectCat;
+ $row['c_id'] = $courseId;
+ $row['course_code'] = $courseCode;
+ $row['session_id'] = $sessionId;
+
+ // Apply date filter (same logic as session_filter.php).
+ $include = false;
+ switch ($filterDate) {
+ case NO_DATE_FILTER:
+ $include = true;
+ break;
+ case DATE_BEGIN_FILTER:
+ $include = $createdAt >= $dateBegin;
+ break;
+ case DATE_END_FILTER:
+ $include = $createdAt <= $dateEnd;
+ break;
+ case ALL_DATE_FILTER:
+ $include = $createdAt >= $dateBegin && $createdAt <= $dateEnd;
+ break;
+ }
+
+ if ($include) {
+ $certificateList[] = $row;
+ }
}
}
+}
- // Filter extra field
+// Apply extra fields filtering to the global certificate list (same idea as session_filter.php).
+if (!empty($filterCheckList) && !empty($certificateList)) {
foreach ($certificateList as $key => $value) {
foreach ($filterCheckList as $fieldId => $field) {
$extraFieldValue = new ExtraFieldValue('user');
@@ -151,42 +221,73 @@
break;
}
+ $paramName = 'extra_'.$field['variable'];
+
switch ($field['field_type']) {
case ExtraField::FIELD_TYPE_TEXT:
case ExtraField::FIELD_TYPE_ALPHANUMERIC:
- $pos = stripos($extraFieldValueData['value'], $_GET['extra_'.$field['variable']]);
- if ($pos === false) {
- unset($certificateList[$key]);
+ $filterValue = isset($_GET[$paramName]) ? (string) $_GET[$paramName] : '';
+ if ($filterValue !== '') {
+ $pos = stripos($extraFieldValueData['value'], $filterValue);
+ if ($pos === false) {
+ unset($certificateList[$key]);
+ }
}
break;
case ExtraField::FIELD_TYPE_RADIO:
- $valueRadio = $_GET['extra_'.$field['variable']]['extra_'.$field['variable']];
- if ($extraFieldValueData['value'] != $valueRadio) {
+ $filterValue = '';
+ if (isset($_GET[$paramName][$paramName])) {
+ $filterValue = $_GET[$paramName][$paramName];
+ }
+ if ($extraFieldValueData['value'] != $filterValue) {
unset($certificateList[$key]);
}
break;
case ExtraField::FIELD_TYPE_SELECT:
- if ($extraFieldValueData['value'] != $_GET['extra_'.$field['variable']]) {
+ $filterValue = isset($_GET[$paramName]) ? $_GET[$paramName] : null;
+ if ($filterValue !== null && $extraFieldValueData['value'] != $filterValue) {
unset($certificateList[$key]);
}
break;
}
+
+ // Stop checking other fields if this one already disqualified the record.
+ if (!isset($certificateList[$key])) {
+ break;
+ }
}
}
}
+// Re-index the array after unsetting elements.
+$certificateList = array_values($certificateList);
+
+// If no certificates pass the filters, show a friendly message.
+if (empty($certificateList)) {
+ Display::display_header($plugin->get_lang('PrintCertificate'));
+ echo Display::return_message(get_lang('NoResultsAvailable'), 'warning');
+ Display::display_footer();
+ exit;
+}
+
+// Build user list + session mapping.
$userList = [];
-foreach ($certificateList as $index => $value) {
+$sessionInfoPerSession = [];
+
+foreach ($certificateList as $value) {
$infoUser = api_get_user_info($value['user_id']);
$infoUser['category_id'] = $value['category_id'];
$infoUser['c_id'] = $value['c_id'];
$infoUser['course_code'] = $value['course_code'];
+ $infoUser['session_id'] = $value['session_id'];
$userList[] = $infoUser;
}
-$sessionInfo = [];
-if ($sessionId > 0) {
- $sessionInfo = SessionManager::fetch($sessionId);
+// Preload session info for all involved sessions (used in dates).
+foreach ($sessionIds as $sessionId) {
+ if ($sessionId > 0) {
+ $sessionInfoPerSession[$sessionId] = SessionManager::fetch($sessionId);
+ }
}
$path = api_get_path(WEB_UPLOAD_PATH).'certificates/';
@@ -196,14 +297,17 @@
$courseId = $userInfo['c_id'];
$courseCode = $userInfo['course_code'];
$studentId = $userInfo['user_id'];
+ $sessionId = !empty($userInfo['session_id']) ? (int) $userInfo['session_id'] : 0;
$courseInfo = api_get_course_info($courseCode);
- $allowCustomCertificate = api_get_course_setting('customcertificate_course_enable', $courseInfo);
- if (!$allowCustomCertificate) {
+ $allowCustomCertificateCourse = api_get_course_setting('customcertificate_course_enable', $courseInfo);
+
+ if (!$allowCustomCertificateCourse) {
+ // Skip courses where the custom certificate plugin is not enabled at course level.
continue;
}
- // Get info certificate
+ // Get info certificate for this course + session.
$infoCertificate = CustomCertificatePlugin::getInfoCertificate($courseId, $sessionId, $accessUrlId);
if (!is_array($infoCertificate)) {
@@ -221,8 +325,8 @@
}
}
- $workSpace = intval(297 - $infoCertificate['margin_left'] - $infoCertificate['margin_right']);
- $widthCell = intval($workSpace / 6);
+ $workSpace = (int) (297 - $infoCertificate['margin_left'] - $infoCertificate['margin_right']);
+ $widthCell = (int) ($workSpace / 6);
$htmlText = '';
if (!$exportAllInOne) {
@@ -237,7 +341,6 @@
href="'.api_get_path(WEB_CSS_PATH).'document.css">';
$htmlText .= '';
}
- $studentId = $userInfo['user_id'];
if (empty($infoCertificate['background'])) {
$htmlText .= '';
@@ -262,7 +365,7 @@ class="caraA"
if (!empty($infoCertificate['logo_center'])) {
$logoCenter = '
 ';
}
@@ -282,11 +385,11 @@ class="caraA"
"
border="0">';
$htmlText .= ' ';
- $htmlText .= '| '.$logoLeft.' | ';
- $htmlText .= '';
+ $htmlText .= ' | '.$logoLeft.' | ';
+ $htmlText .= '';
$htmlText .= $logoCenter;
$htmlText .= ' | ';
- $htmlText .= ''.$logoRight.' | ';
+ $htmlText .= ''.$logoRight.' | ';
$htmlText .= ' ';
$htmlText .= ' ';
@@ -307,15 +410,18 @@ class="caraA"
$myContentHtml
);
+ // Use session-specific dates when available.
+ $currentSessionInfo = isset($sessionInfoPerSession[$sessionId]) ? $sessionInfoPerSession[$sessionId] : [];
+
$startDate = '';
$endDate = '';
switch ($infoCertificate['date_change']) {
case 0:
- if (!empty($sessionInfo['access_start_date'])) {
- $startDate = date("d/m/Y", strtotime(api_get_local_time($sessionInfo['access_start_date'])));
+ if (!empty($currentSessionInfo['access_start_date'])) {
+ $startDate = date("d/m/Y", strtotime(api_get_local_time($currentSessionInfo['access_start_date'])));
}
- if (!empty($sessionInfo['access_end_date'])) {
- $endDate = date("d/m/Y", strtotime(api_get_local_time($sessionInfo['access_end_date'])));
+ if (!empty($currentSessionInfo['access_end_date'])) {
+ $endDate = date("d/m/Y", strtotime(api_get_local_time($currentSessionInfo['access_end_date'])));
}
break;
case 1:
@@ -364,8 +470,8 @@ class="caraA"
} elseif ($infoCertificate['type_date_expediction'] == 4) {
$dateExpediction .= $plugin->get_lang('to').$infoToReplaceInContentHtml[9]; //date_certificate_no_time
} else {
- if (!empty($sessionInfo)) {
- $dateInfo = api_get_local_time($sessionInfo['access_end_date']);
+ if (!empty($currentSessionInfo)) {
+ $dateInfo = api_get_local_time($currentSessionInfo['access_end_date']);
$dateExpediction .= $plugin->get_lang('to').api_format_date($dateInfo, DATE_FORMAT_LONG);
}
}
@@ -571,12 +677,12 @@ class="caraA"
$htmlText .= '';
$htmlText .= '';
$htmlText .= '| ';
- $myContentHtml = strip_tags(
+ $myContentHtmlBack = strip_tags(
$infoCertificate['contents'],
' ';
@@ -591,6 +697,15 @@ class="caraA"
$htmlList[$fileName] = $htmlText;
}
+// If for some reason we ended up with no HTML (e.g. all courses had the plugin disabled),
+// show a message instead of a blank page.
+if (empty($htmlList)) {
+ Display::display_header($plugin->get_lang('PrintCertificate'));
+ echo Display::return_message(get_lang('NoResultsAvailable'), 'warning');
+ Display::display_footer();
+ exit;
+}
+
$fileList = [];
$archivePath = api_get_path(SYS_ARCHIVE_PATH).'certificates/';
if (!is_dir($archivePath)) {
| | |