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

pull/4193/head
Yannick Warnier 4 years ago
commit abf73a9002
  1. 19
      main/inc/lib/api.lib.php
  2. 14
      main/inc/lib/pdf.lib.php
  3. 4
      main/install/configuration.dist.php
  4. 44
      main/lp/learnpathItem.class.php
  5. 85
      main/template/default/course_progress/pdf_general_thematic.tpl

@ -10197,3 +10197,22 @@ function api_protect_webservices()
exit;
}
}
function api_filename_has_blacklisted_stream_wrapper(string $filename) {
if (strpos($filename, '://') > 0) {
$wrappers = stream_get_wrappers();
$allowedWrappers = ['http', 'https', 'file'];
foreach ($wrappers as $wrapper) {
if (in_array($wrapper, $allowedWrappers)) {
continue;
}
if (stripos($filename, $wrapper . '://') === 0) {
return true;
}
}
}
return false;
}

@ -973,11 +973,25 @@ class PDF
$documentPath = $courseInfo ? $sysCoursePath.$courseInfo['path'].'/document/' : '';
$notFoundImagePath = Display::return_icon(
'closed-circle.png',
get_lang('FileNotFound'),
[],
ICON_SIZE_TINY,
false,
true
);
/** @var \DOMElement $element */
foreach ($elements as $element) {
$src = $element->getAttribute('src');
$src = trim($src);
if (api_filename_has_blacklisted_stream_wrapper($src)) {
$element->setAttribute('src', $notFoundImagePath);
continue;
}
if (strpos($src, $protocol) !== false) {
continue;
}

@ -2109,6 +2109,10 @@ INSERT INTO `extra_field` (`extra_field_type`, `field_type`, `variable`, `displa
'INVITEE' => false
];*/
// Allow learnpath prerequisite on quiz to unblock if maximum attempt is reached
//$_configuration['lp_prerequisit_on_quiz_unblock_if_max_attempt_reached'] = false;
// Enables to hide user status when option is true visible only for admins from $_configuration['user_status_option_show_only_for_admin']
//$_configuration['user_status_option_only_for_admin_enabled'] = false;
// The user status is hidden when is false, it requires $_configuration['user_status_option_only_for_admin_enabled'] = true

@ -2342,6 +2342,13 @@ class learnpathItem
$status = $itemToCheck->get_status(true);
$returnstatus = $status == $this->possible_status[2] || $status == $this->possible_status[3];
// Allow learnpath prerequisite on quiz to unblock if maximum attempt is reached
if (true === api_get_configuration_value('lp_prerequisit_on_quiz_unblock_if_max_attempt_reached')) {
$isQuizMaxAttemptReached = $this->isQuizMaxAttemptReached($items[$refs_list[$prereqs_string]]->path, $user_id, $courseId, $this->lp_id, $prereqs_string);
if ($isQuizMaxAttemptReached) {
$returnstatus = true;
}
}
if (!$returnstatus) {
$explanation = sprintf(
get_lang('ItemXBlocksThisElement'),
@ -2435,7 +2442,6 @@ class learnpathItem
$minScore = $masteryScoreAsMin;
}
}
if (isset($minScore) && isset($minScore)) {
// Taking min/max prerequisites values see BT#5776
if ($quiz['exe_result'] >= $minScore &&
@ -2479,6 +2485,13 @@ class learnpathItem
$refs_list
);
}
// Allow learnpath prerequisite on quiz to unblock if maximum attempt is reached
if (true === api_get_configuration_value('lp_prerequisit_on_quiz_unblock_if_max_attempt_reached')) {
$isQuizMaxAttemptReached = $this->isQuizMaxAttemptReached($items[$refs_list[$prereqs_string]]->path, $user_id, $courseId, $this->lp_id, $prereqs_string);
if ($isQuizMaxAttemptReached) {
$returnstatus = true;
}
}
}
return $returnstatus;
@ -2636,6 +2649,35 @@ class learnpathItem
return false;
}
/**
* Check if max quiz attempt is reached.
*
* @param $exerciseId
* @param $userId
* @param $courseId
* @param $lpId
* @param $lpItemId
*
* @return bool
*/
public function isQuizMaxAttemptReached($exerciseId, $userId, $courseId, $lpId, $lpItemId)
{
$objExercise = new Exercise();
$objExercise->read($exerciseId);
$nbAttempts = $objExercise->selectAttempts();
$countAttempts = Tracking::count_student_exercise_attempts(
$userId,
$courseId,
$exerciseId,
$lpId,
$lpItemId,
api_get_session_id()
);
$isMaxAttemptReached = ($nbAttempts > 0 && $countAttempts >= $nbAttempts);
return $isMaxAttemptReached;
}
/**
* Reinits all local values as the learnpath is restarted.
*

@ -1,45 +1,40 @@
<table style="margin-top: 30px;" class="full-width border-thin">
<thead>
<tr>
<th width="30%" style="display:inline-block; padding: 10px; text-align: center; background-color: #E5E5E5;">
{{ "Thematic"|get_lang }}
</th>
<th width="50%" style="display:inline-block; padding: 10px; text-align: center; background-color: #E5E5E5;">
{{ "ThematicPlan"|get_lang }}
</th>
<th width="20%" style="display:inline-block; padding: 10px; text-align: center; background-color: #E5E5E5;">
{{ "ThematicAdvance"|get_lang }}
</th>
</tr>
</thead>
<tbody>
{% for item in data %}
<tr>
<td>
<h4 style="margin-bottom: 10px;">{{ item.title }}</h4>
<br>
{{ item.content }}
</td>
<td>
{% for plan in item.thematic_plan %}
<br>
<h4 style="margin-bottom: 10px;">{{ plan.title }}</h4>
<br>
{{ plan.description }}
{% endfor %}
</td>
<td>
{% for advance in item.thematic_advance %}
<br>
<h4 style="margin-bottom: 10px;">
{{ advance.duration }} {{ "MinHours" | get_lang }}
</h4>
{{ advance.start_date | api_convert_and_format_date(2) }}
<br>
{{ advance.content }}
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div style="border: 1px solid #000;">
<div style="float: left; width: 17%;padding:2%;font-weight: bold;">
{{ "Thematic"|get_lang }}
</div>
<div style="float: left; width: 27%;padding:2%;font-weight: bold;">
{{ "ThematicPlan"|get_lang }}
</div>
<div style="float: left; width: 27%;padding:2%;font-weight: bold;">
{{ "ThematicAdvance"|get_lang }}
</div>
</div>
<hr />
{% for item in data %}
<div style="border: 1px solid #000;">
<div style="float: left; width: 17%;padding:2%;">
<h4 style="margin-bottom: 10px;">{{ item.title }}</h4>
<br>
{{ item.content }}
</div>
<div style="float: left; width: 27%;padding:2%;">
{% for plan in item.thematic_plan %}
<br>
<h4 style="margin-bottom: 10px;">{{ plan.title }}</h4>
<br>
{{ plan.description }}
{% endfor %}
</div>
<div style="float: left; width: 27%;padding:2%;">
{% for advance in item.thematic_advance %}
<br>
<h4 style="margin-bottom: 10px;">
{{ advance.duration }} {{ "MinHours" | get_lang }}
</h4>
{{ advance.start_date | api_convert_and_format_date(2) }}
<br>
{{ advance.content }}
{% endfor %}
</div>
</div>
{% endfor %}
Loading…
Cancel
Save