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

pull/2990/head
Alex Aragón 6 years ago
commit 5a8fa4c124
  1. 35
      main/cron/import_csv.php
  2. 24
      main/exercise/exercise.class.php
  3. 7
      main/inc/lib/formvalidator/FormValidator.class.php
  4. 25
      main/inc/lib/javascript/ckeditor/plugins/oembed/plugin.js
  5. 109
      main/inc/lib/javascript/ckeditor/plugins/video/dialogs/video.js
  6. 15
      main/inc/lib/javascript/ckeditor/plugins/video/plugin.js
  7. 2
      main/lp/learnpath.class.php
  8. 105
      main/lp/lp_controller.php

@ -1429,20 +1429,39 @@ class ImportCsv
$courseTitle = $courseInfo['title']; $courseTitle = $courseInfo['title'];
// Get the value of the "careerid" extra field of this
// session
$sessionExtraFieldValue = new ExtraFieldValue('session'); $sessionExtraFieldValue = new ExtraFieldValue('session');
$values = $sessionExtraFieldValue->get_values_by_handler_and_field_variable( $externalCareerIdList = $sessionExtraFieldValue->get_values_by_handler_and_field_variable(
$event['session_id'], $event['session_id'],
$this->extraFieldIdNameList['session_career'] 'careerid'
); );
$externalCareerIdList = $externalCareerIdList['value'];
$externalCareerIds = [];
if (substr($externalCareerIdList, 0, 1) === '[') {
$externalCareerIdList = substr($externalCareerIdList, 1, -1);
$externalCareerIds = preg_split('/,/',$externalCareerIdList);
} else {
$externalCareerIds = [$externalCareerIdList];
}
$careerExtraFieldValue = new ExtraFieldValue('career');
$career = new Career();
$careerName = ''; $careerName = '';
if (!empty($values)) {
foreach ($values as $value) { // Concat the names of each career linked to this session
if (isset($value['value'])) { foreach ($externalCareerIds as $externalCareerId) {
$careerName = $value['value']; // Using the external_career_id field (from above),
} // find the career ID
} $careerValue = $careerExtraFieldValue->get_item_id_from_field_variable_and_field_value(
'external_career_id',
$externalCareerId
);
$career = $career->find($careerValue['item_id']);
$careerName .= $career['name'].', ';
} }
// Remove trailing comma
$careerName = substr($careerName, 0, -2);
$subject = sprintf( $subject = sprintf(
get_lang('WelcomeToPortalXInCourseSessionX'), get_lang('WelcomeToPortalXInCourseSessionX'),

@ -1048,18 +1048,18 @@ class Exercise
switch ($questionSelectionType) { switch ($questionSelectionType) {
case EX_Q_SELECTION_ORDERED: case EX_Q_SELECTION_ORDERED:
$questionList = $this->getQuestionOrderedList(); $questionList = $this->getQuestionOrderedList($adminView);
break; break;
case EX_Q_SELECTION_RANDOM: case EX_Q_SELECTION_RANDOM:
// Not a random exercise, or if there are not at least 2 questions // Not a random exercise, or if there are not at least 2 questions
if ($this->random == 0 || $nbQuestions < 2) { if ($this->random == 0 || $nbQuestions < 2) {
$questionList = $this->getQuestionOrderedList(); $questionList = $this->getQuestionOrderedList($adminView);
} else { } else {
$questionList = $this->getRandomList($adminView); $questionList = $this->getRandomList($adminView);
} }
break; break;
default: default:
$questionList = $this->getQuestionOrderedList(); $questionList = $this->getQuestionOrderedList($adminView);
$result = $this->getQuestionListWithCategoryListFilteredByCategorySettings( $result = $this->getQuestionListWithCategoryListFilteredByCategorySettings(
$questionList, $questionList,
$questionSelectionType $questionSelectionType
@ -1730,9 +1730,6 @@ class Exercise
$this->save_categories_in_exercise($this->categories); $this->save_categories_in_exercise($this->categories);
// Updates the question position
$this->update_question_positions();
return $this->iId; return $this->iId;
} }
@ -9147,7 +9144,7 @@ class Exercise
} }
$currentRow = [ $currentRow = [
$row['iid'], $row['id'],
$currentRow['title'], $currentRow['title'],
$currentRow['count_questions'], $currentRow['count_questions'],
$actions, $actions,
@ -9655,9 +9652,11 @@ class Exercise
/** /**
* Gets the question list ordered by the question_order setting (drag and drop). * Gets the question list ordered by the question_order setting (drag and drop).
* *
* @param bool $adminView Optional.
*
* @return array * @return array
*/ */
private function getQuestionOrderedList() private function getQuestionOrderedList($adminView = false)
{ {
$TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION); $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
@ -9693,8 +9692,13 @@ class Exercise
$counter = 1; $counter = 1;
$questionList = []; $questionList = [];
while ($new_object = Database::fetch_object($result)) { while ($new_object = Database::fetch_object($result)) {
// Correct order. if (!$adminView) {
$questionList[$new_object->question_order] = $new_object->question_id; // Correct order.
$questionList[$new_object->question_order] = $new_object->question_id;
} else {
$questionList[$counter] = $new_object->question_id;
}
// Just in case we save the order in other array // Just in case we save the order in other array
$temp_question_list[$counter] = $new_object->question_id; $temp_question_list[$counter] = $new_object->question_id;
$counter++; $counter++;

@ -262,14 +262,17 @@ EOT;
* @param array $options * @param array $options
* @param array $attributes * @param array $attributes
* *
* @throws * @throws Exception
*
* @return HTML_QuickForm_element
*/ */
public function addSelectAjax($name, $label, $options = [], $attributes = []) public function addSelectAjax($name, $label, $options = [], $attributes = [])
{ {
if (!isset($attributes['url'])) { if (!isset($attributes['url'])) {
throw new \Exception('select_ajax needs an URL'); throw new \Exception('select_ajax needs an URL');
} }
$this->addElement(
return $this->addElement(
'select_ajax', 'select_ajax',
$name, $name,
$label, $label,

@ -148,6 +148,12 @@
} }
function embedCode(url, instance, closeDialog, maxWidth, maxHeight, responsiveResize, widget) { function embedCode(url, instance, closeDialog, maxWidth, maxHeight, responsiveResize, widget) {
var extraProviderParams = {};
if (responsiveResize) {
extraProviderParams.responsive = true;
}
jQuery('body').oembed(url, { jQuery('body').oembed(url, {
onEmbed: function(e) { onEmbed: function(e) {
var codeElement, var codeElement,
@ -197,7 +203,7 @@
} }
if (elementAdded) { if (elementAdded) {
if (closeDialog) { if (closeDialog && CKEDITOR.dialog.getCurrent()) {
CKEDITOR.dialog.getCurrent().hide(); CKEDITOR.dialog.getCurrent().hide();
} }
} }
@ -213,7 +219,8 @@
maxHeight: maxHeight, maxHeight: maxHeight,
maxWidth: maxWidth, maxWidth: maxWidth,
useResponsiveResize: responsiveResize, useResponsiveResize: responsiveResize,
embedMethod: 'editor' embedMethod: 'editor',
'vimeo': extraProviderParams
}); });
} }
@ -223,9 +230,9 @@
minWidth: CKEDITOR.env.ie && CKEDITOR.env.quirks ? 568 : 550, minWidth: CKEDITOR.env.ie && CKEDITOR.env.quirks ? 568 : 550,
minHeight: 155, minHeight: 155,
onShow: function() { onShow: function() {
var resizetype = this.getContentElement('general', 'resizeType').getValue(), var resizetype = CKEDITOR.dialog.getCurrent().getContentElement('general', 'resizeType').getValue(),
maxSizeBox = this.getContentElement('general', 'maxSizeBox').getElement(), maxSizeBox = CKEDITOR.dialog.getCurrent().getContentElement('general', 'maxSizeBox').getElement(),
sizeBox = this.getContentElement('general', 'sizeBox').getElement(); sizeBox = CKEDITOR.dialog.getCurrent().getContentElement('general', 'sizeBox').getElement();
if (resizetype == 'noresize') { if (resizetype == 'noresize') {
maxSizeBox.hide(); maxSizeBox.hide();
@ -284,19 +291,19 @@
responsiveResize = false; responsiveResize = false;
} else { } else {
if (resizetype == "responsive") { if (resizetype == "responsive") {
maxWidth = this.getContentElement('general', 'maxWidth'). maxWidth = CKEDITOR.dialog.getCurrent().getContentElement('general', 'maxWidth').
getInputElement(). getInputElement().
getValue(); getValue();
maxHeight = this.getContentElement('general', 'maxHeight'). maxHeight = CKEDITOR.dialog.getCurrent().getContentElement('general', 'maxHeight').
getInputElement(). getInputElement().
getValue(); getValue();
responsiveResize = true; responsiveResize = true;
} else if (resizetype == "custom") { } else if (resizetype == "custom") {
maxWidth = this.getContentElement('general', 'width'). maxWidth = CKEDITOR.dialog.getCurrent().getContentElement('general', 'width').
getInputElement(). getInputElement().
getValue(); getValue();
maxHeight = this.getContentElement('general', 'height'). maxHeight = CKEDITOR.dialog.getCurrent().getContentElement('general', 'height').
getInputElement(). getInputElement().
getValue(); getValue();

@ -38,14 +38,17 @@ CKEDITOR.dialog.add( 'video', function ( editor )
return; return;
switch( this.id ) switch( this.id )
{ {
case 'responsive':
videoNode.addClass('embed-responsive-item');
break;
case 'poster': case 'poster':
extraStyles.backgroundImage = 'url(' + value + ')'; extraStyles.backgroundImage = 'url(' + value + ')';
break; break;
case 'width': case 'width':
extraStyles.width = value + 'px'; extraStyles.width = value.indexOf('%') > 0 ? '100%' : ( value + 'px');
break; break;
case 'height': case 'height':
extraStyles.height = value + 'px'; extraStyles.height = value.indexOf('%') > 0 ? '100%' : ( value + 'px');
break; break;
} }
} }
@ -176,6 +179,15 @@ CKEDITOR.dialog.add( 'video', function ( editor )
} }
var extraStyles = {}, videos = []; var extraStyles = {}, videos = [];
var responsive = this.getValueOf('info', 'responsive');
videoNode.removeClass('embed-responsive-item');
if (responsive) {
this.setValueOf('info', 'width', '100%');
this.setValueOf('info', 'height', '100%');
}
this.commitContent( videoNode, extraStyles, videos ); this.commitContent( videoNode, extraStyles, videos );
var innerHtml = '', links = '', var innerHtml = '', links = '',
@ -191,6 +203,7 @@ CKEDITOR.dialog.add( 'video', function ( editor )
} }
videoNode.setHtml( innerHtml + fallbackTemplate.replace( '%links%', links ) ); videoNode.setHtml( innerHtml + fallbackTemplate.replace( '%links%', links ) );
var responsiveParent = null;
// Refresh the fake image. // Refresh the fake image.
var newFakeImage = editor.createFakeElement( videoNode, 'cke_video', 'video', false ); var newFakeImage = editor.createFakeElement( videoNode, 'cke_video', 'video', false );
newFakeImage.setStyles( extraStyles ); newFakeImage.setStyles( extraStyles );
@ -198,6 +211,13 @@ CKEDITOR.dialog.add( 'video', function ( editor )
{ {
newFakeImage.replace( this.fakeImage ); newFakeImage.replace( this.fakeImage );
editor.getSelection().selectElement( newFakeImage ); editor.getSelection().selectElement( newFakeImage );
if (responsive) {
responsiveParent = newFakeImage.getParent();
responsiveParent.removeClass('embed-responsive');
responsiveParent.removeClass('embed-responsive-16by9');
responsiveParent.removeClass('embed-responsive-4by3');
}
} }
else else
{ {
@ -205,6 +225,21 @@ CKEDITOR.dialog.add( 'video', function ( editor )
var div = new CKEDITOR.dom.element( 'DIV', editor.document ); var div = new CKEDITOR.dom.element( 'DIV', editor.document );
editor.insertElement( div ); editor.insertElement( div );
div.append( newFakeImage ); div.append( newFakeImage );
responsiveParent = div;
}
if (responsive) {
responsiveParent.addClass('embed-responsive');
switch (responsive) {
case '16by9':
responsiveParent.addClass('embed-responsive-16by9');
break;
case '4by3':
responsiveParent.addClass('embed-responsive-4by3');
break;
}
} }
}, },
onHide : function() onHide : function()
@ -226,37 +261,6 @@ CKEDITOR.dialog.add( 'video', function ( editor )
label: lang.infoLabel, label: lang.infoLabel,
elements : elements :
[ [
{
type : 'hbox',
widths: [ '33%', '33%', '33%'],
children : [
{
type : 'text',
id : 'width',
label : editor.lang.common.width,
'default' : 400,
validate : CKEDITOR.dialog.validate.notEmpty( lang.widthRequired ),
commit : commitValue,
setup : loadValue
},
{
type : 'text',
id : 'height',
label : editor.lang.common.height,
'default' : 300,
//validate : CKEDITOR.dialog.validate.notEmpty(lang.heightRequired ),
commit : commitValue,
setup : loadValue
},
{
type : 'text',
id : 'id',
label : 'Id',
commit : commitValue,
setup : loadValue
}
]
},
{ {
type : 'hbox', type : 'hbox',
widths: [ '', '100px', '75px'], widths: [ '', '100px', '75px'],
@ -375,6 +379,45 @@ CKEDITOR.dialog.add( 'video', function ( editor )
}, },
label : editor.lang.common.browseServer label : editor.lang.common.browseServer
}] }]
},
{
type : 'hbox',
widths: [ '33%', '33%', '33%'],
children : [
{
type : 'text',
id : 'width',
label : editor.lang.common.width,
'default' : 400,
validate : CKEDITOR.dialog.validate.notEmpty( lang.widthRequired ),
commit : commitValue,
setup : loadValue
},
{
type : 'text',
id : 'height',
label : editor.lang.common.height,
'default' : 300,
//validate : CKEDITOR.dialog.validate.notEmpty(lang.heightRequired ),
commit : commitValue,
setup : loadValue
},
{
type : 'text',
id : 'id',
label : 'Id',
commit : commitValue,
setup : loadValue
}
]
},
{
type: 'radio',
id: 'responsive',
label: lang.responsive,
items: [ [ lang.ratio16by9, '16by9' ], [ lang.ratio4by3, '4by3' ] ],
commit : commitValue,
setup : loadValue
} }
] ]
}, },

@ -183,7 +183,10 @@ var en = {
infoLabel: 'Information', infoLabel: 'Information',
html360: 'This feature (only MP4 videos) is currently still in BETA mode.<br />It only works on dynamic pages, not inside documents created<br />in the documents tool or seen through learning paths.<br />Please do not add more than one 360° video on a single page<br /> as more than one on the same page might generate conflicts.', html360: 'This feature (only MP4 videos) is currently still in BETA mode.<br />It only works on dynamic pages, not inside documents created<br />in the documents tool or seen through learning paths.<br />Please do not add more than one 360° video on a single page<br /> as more than one on the same page might generate conflicts.',
video360: 'Enable 360° video player', video360: 'Enable 360° video player',
video360stereo: 'Stereo video (1:1 aspect ratio)' video360stereo: 'Stereo video (1:1 aspect ratio)',
responsive: 'Resposive size (mobile-optimized)',
ratio16by9: '16:9 aspect ratio',
ratio4by3: '4:3 aspect ratio'
}; };
var es = { var es = {
@ -201,7 +204,10 @@ var es = {
infoLabel: 'Información', infoLabel: 'Información',
html360: 'Esta funcionalidad (sólo MP4) todavía se encuentra en modo BETA.<br />Sólo funciona en páginas dinámicas, mas no dentro de documentos<br />creados en la herramienta de documentos o visualizados a través<br />de las lecciones.<br />Por favor no colocar más de un vídeo 360° en una misma página<br />ya que puede provocar conflictos y bloquearlos todos.', html360: 'Esta funcionalidad (sólo MP4) todavía se encuentra en modo BETA.<br />Sólo funciona en páginas dinámicas, mas no dentro de documentos<br />creados en la herramienta de documentos o visualizados a través<br />de las lecciones.<br />Por favor no colocar más de un vídeo 360° en una misma página<br />ya que puede provocar conflictos y bloquearlos todos.',
video360: 'Habilitar reproductor de vídeo 360°', video360: 'Habilitar reproductor de vídeo 360°',
video360stereo: 'Vídeo estéreo (relación de aspecto 1:1)' video360stereo: 'Vídeo estéreo (relación de aspecto 1:1)',
responsive: 'Tamaño adaptable (tamaño optimizado para móviles)',
ratio16by9: 'Relación de aspecto 16:9',
ratio4by3: 'Relación de aspecto 4:3'
}; };
var fr = { var fr = {
@ -219,7 +225,10 @@ var fr = {
infoLabel: 'Information', infoLabel: 'Information',
html360: 'Cette fonctionnalité (MP4 uniquement) est actuellement en mode BETA.<br />Elle ne fonctionne que sur les pages dynamiques, et pas<br />dans les documents créés à partir de l\'outil document ou visualisés<br />au travers de l\'outil parcours.<br />Merci de ne pas placer plus d\'une vidéo 360° par page. Cela<br />peut causer des conflits et toutes les rendre inactives.', html360: 'Cette fonctionnalité (MP4 uniquement) est actuellement en mode BETA.<br />Elle ne fonctionne que sur les pages dynamiques, et pas<br />dans les documents créés à partir de l\'outil document ou visualisés<br />au travers de l\'outil parcours.<br />Merci de ne pas placer plus d\'une vidéo 360° par page. Cela<br />peut causer des conflits et toutes les rendre inactives.',
video360: 'Activer la visualisation 360°', video360: 'Activer la visualisation 360°',
video360stereo: 'Vidéo stéréo (proportions 1:1 / apparence de 2 vidéos superposées)' video360stereo: 'Vidéo stéréo (proportions 1:1 / apparence de 2 vidéos superposées)',
responsive: 'Resposive',
ratio16by9: '16:9 aspect ratio',
ratio4by3: '4:3 aspect ratio'
}; };
// v3 // v3

@ -6535,7 +6535,7 @@ class learnpath
$sub_list = ''; $sub_list = '';
if (isset($item['type']) && $item['type'] == 'dir') { if (isset($item['type']) && $item['type'] == 'dir') {
// empty value // empty value
$sub_list = Display::tag('li', '', ['class' => 'sub_item empty record li_container']); $sub_list = Display::tag('li', '', ['class' => 'sub_item empty']);
} }
if (empty($item['children'])) { if (empty($item['children'])) {
$sub_list = Display::tag('ul', $sub_list, ['id' => 'UL_'.$key, 'class' => 'record li_container']); $sub_list = Display::tag('ul', $sub_list, ['id' => 'UL_'.$key, 'class' => 'record li_container']);

@ -103,35 +103,126 @@ $htmlHeadXtra[] = '
var jItem = $("#"+ itemId); var jItem = $("#"+ itemId);
var index = jItems.index(jItem); var index = jItems.index(jItem);
var total = jItems.length; var total = jItems.length;
//console.log("total " + total);
//console.log("current " + index);
switch (dir) { switch (dir) {
case "up": case "up":
if (index != 0 && jItems[index - 1]) { if (index != 0 && jItems[index - 1]) {
var subItems = $(jItems[index - 1]).find("li.sub_item"); /*var subItems = $(jItems[index - 1]).find("li.sub_item");
if (subItems.length >= 0) { if (subItems.length >= 0) {
index = index - 1; index = index - 1;
}*/
var subItems = $(jItems[index - 1]).find("li.sub_item");
var parentClass = $(jItems[index - 1]).parent().parent().attr("class");
var parentId = $(jItems[index]).parent().parent().attr("id");
var myParentId = $(jItems[index - 1]).parent().parent().attr("id");
//console.log(parentId + " - " + myParentId);
// We are brothers!
if (parentId == myParentId) {
console.log("Brothers");
console.log(subItems.length);
if (subItems.length > 0) {
var lastItem = $(jItems[index - 1]).find("li.sub_item");
parentIndex = jItems.index(lastItem);
console.log(parentIndex);
jItem.detach().insertAfter(lastItem);
//console.log("not classic");
} else {
//console.log("classic");
jItem.detach().insertBefore(jItems[index - 1]);
}
break;
}
//console.log(parentClass);
if (parentClass == "record li_container") {
// previous is a chapter
var lastItem = $(jItems[index - 1]).parent().parent().find("li.li_container").last();
parentIndex = jItems.index(lastItem);
//console.log(parentIndex);
jItem.detach().insertAfter(jItems[parentIndex]);
} else {
jItem.detach().insertBefore(jItems[index - 1]);
} }
jItem.detach().insertBefore(jItems[index - 1]);
} }
break; break;
case "down": case "down":
if (index != jItems.length - 1) { if (index != total - 1) {
const originIndex = index;
// The element is a chapter with items
var subItems = jItem.find("li.li_container"); var subItems = jItem.find("li.li_container");
if (subItems.length >= 0) { if (subItems.length > 0) {
index = subItems.length + index; index = subItems.length + index;
//console.log("element is a chapter with items");
//console.log("new index = " + index);
} }
// is a chapter?
var subItems = $(jItems[index + 1]).find("li.sub_item"); var subItems = $(jItems[index + 1]).find("li.sub_item");
if (subItems.length >= 0) { //console.log("next subItems.length: "+subItems.length);
index = index + 1; // This is an element entering in a chapter
if (subItems.length > 0) {
// Check if im a child
var parentClass = jItem.parent().parent().attr("class");
//console.log(parentClass);
if (parentClass == "record li_container") {
// Parent position
var parentIndex = jItems.index(jItem.parent().parent());
//console.log(jItem.parent().parent().attr("id"));
//console.log(parentIndex);
jItem.detach().insertAfter(jItems[parentIndex]);
} else {
jItem.detach().insertAfter(subItems);
}
break;
} }
var currentSubItems = $(jItems[index]).parent().find("li.sub_item");
//console.log("currentSubItems"+currentSubItems.length);
var parentId = $(jItems[originIndex]).parent().parent().attr("id");
var myParentId = $(jItems[index + 1]).parent().parent().attr("id");
//console.log("parent ids: "+ parentId + " - " + myParentId);
// We are brothers!
if (parentId == myParentId) {
if ((index + 1) < total) {
//console.log(index + 1);
//console.log("We are brothers");
jItem.detach().insertAfter(jItems[index + 1]);
}
break;
}
if (currentSubItems.length > 0) {
var parentIndex = jItems.index(jItem.parent().parent());
//console.log("has currentSubItems");
//console.log("id " + jItem.parent().parent().attr("id"));
//console.log("parentIndex: " + parentIndex);
if (parentIndex >= 0) {
jItem.detach().insertAfter(jItems[parentIndex]);
break;
}
//jItem.detach().insertAfter($(jItems[index]).parent().parent());
}
//var lastItem = $(jItems[index + 1]).parent().parent().find("li.li_container").last();
if (subItems.length > 0) {
index = originIndex;
}
if ((index + 1) < total) { if ((index + 1) < total) {
//console.log(index + 1);
//console.log("changed");
jItem.detach().insertAfter(jItems[index + 1]); jItem.detach().insertAfter(jItems[index + 1]);
} }
} }
break; break;
} }
//console.log("rebuild");
buildLPtree($("#lp_item_list"), 0); buildLPtree($("#lp_item_list"), 0);
var order = "new_order="+ newOrderData + "&a=update_lp_item_order"; var order = "new_order="+ newOrderData + "&a=update_lp_item_order";

Loading…
Cancel
Save