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

pull/2874/head
Julio 7 years ago
commit 2c86afe507
  1. 2
      app/Migrations/Schema/V111/Version111.php
  2. 2
      documentation/dependencies.html
  3. 2
      documentation/readme.html
  4. 52
      main/admin/course_list.php
  5. 13
      main/exercise/exercise.class.php
  6. 2
      main/exercise/exercise_submit.php
  7. 21
      main/exercise/overview.php
  8. 3
      main/exercise/question.class.php
  9. 8
      main/inc/ajax/social.ajax.php
  10. 5
      main/inc/lib/exercise.lib.php
  11. 8
      main/inc/lib/message.lib.php
  12. 12
      main/install/configuration.dist.php
  13. 10
      main/install/data.sql
  14. 2
      main/template/default/layout/main.js.tpl
  15. 4
      src/Chamilo/CoreBundle/Entity/Message.php
  16. 22
      src/Chamilo/CoreBundle/Entity/MessageFeedback.php

@ -432,7 +432,7 @@ class Version111 extends AbstractMigrationChamilo
$this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('show_glossary_in_extra_tools', 'none', 'None')");
$this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('show_glossary_in_extra_tools', 'exercise', 'Exercise')");
$this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('show_glossary_in_extra_tools', 'lp', 'LearningPath')");
$this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('show_glossary_in_extra_tools', 'lp', 'LearningPaths')");
$this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('show_glossary_in_extra_tools', 'exercise_and_lp', 'ExerciseAndLearningPath')");
// Fixes from 1.10.x

@ -63,7 +63,7 @@ We recommend using HTML5-compatible technology.
<li>PC with a minimum of 512MB or any tablet or smartphone</li>
<li>We recommend a Pentium-I as a minimum processor capability for PCs</li>
<li>Works on Windows XP (SP3 recommended) and later versions, Linux (any version with a graphical interface), Mac OS (any version), FreeBSD, Android, iOS and pretty much any other operating system with a graphical interface you might think about</li>
<li>Any modern browser (IE8 and inferior *excluded*).</li>
<li>Any modern browser (IE10 and inferior *excluded*).</li>
<li>Optional: Flash plugin (only required for a few features like the videoconference plugins)</li>
<li>Optional: Java applet capability (only required for some plugins)</li>
</ul>

@ -114,7 +114,7 @@ We officially recommend Debian and Ubuntu operating systems for their security,
authentication and replace it by connecting to a LDAP directory.</p>
<p>Client side, Chamilo runs on any browser : Firefox, Internet Explorer
(9+), Chrome, Safari, Opera, ...<br />
(11+), Chrome, Safari, Opera, ...<br />
For better user experience, we recommend Firefox (you can download it
freely from <a href="http://getfirefox.com">http://getfirefox.com</a>).</p>

@ -173,12 +173,9 @@ function get_course_data($from, $number_of_items, $column, $direction)
while ($course = Database::fetch_array($res)) {
// Place colour icons in front of courses.
$show_visual_code = $course['visual_code'] != $course[2] ? Display::label($course['visual_code'], 'info') : null;
$course[1] = get_course_visibility_icon($course[8]).
'<a href="'.$coursePath.$course[9].'/index.php">'.
Security::remove_XSS($course[1]).
'</a> '.
$show_visual_code
;
$course[1] = get_course_visibility_icon($course[8]).PHP_EOL
.Display::url(Security::remove_XSS($course[1]), $coursePath.$course[9].'/index.php').PHP_EOL
.$show_visual_code;
$course[5] = $course[5] == SUBSCRIBE_ALLOWED ? get_lang('Yes') : get_lang('No');
$course[6] = $course[6] == UNSUBSCRIBE_ALLOWED ? get_lang('Yes') : get_lang('No');
$language = isset($languages[$course[3]]) ? $languages[$course[3]] : $course[3];
@ -186,18 +183,35 @@ function get_course_data($from, $number_of_items, $column, $direction)
$courseCode = $course[0];
$courseId = $course['id'];
$actions = '<a href="course_information.php?code='.$courseCode.'">'.
Display::return_icon('info2.png', get_lang('Info')).'</a>&nbsp;'.
'<a href="'.$coursePath.$course['directory'].'/index.php">'.
Display::return_icon('course_home.png', get_lang('CourseHomepage')).'</a>&nbsp;'.
'<a href="'.$path.'tracking/courseLog.php?'.api_get_cidreq_params($courseCode).'">'.
Display::return_icon('statistics.png', get_lang('Tracking')).'</a>&nbsp;'.
'<a href="'.$path.'admin/course_edit.php?id='.$courseId.'">'.
Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>&nbsp;'.
'<a href="'.$path.'coursecopy/create_backup.php?'.api_get_cidreq_params($courseCode).'">'.
Display::return_icon('backup.png', get_lang('CreateBackup')).'</a>&nbsp;'.
'<a href="'.$path.'admin/course_list.php?delete_course='.$courseCode.'" onclick="javascript: if (!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;">'.
Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'</a>';
$actions = [];
$actions[] = Display::url(
Display::return_icon('info2.png', get_lang('Info')),
"course_information.php?code=$courseCode"
);
$actions[] = Display::url(
Display::return_icon('course_home.png', get_lang('CourseHomepage')),
$coursePath.$course['directory'].'/index.php'
);
$actions[] = Display::url(
Display::return_icon('statistics.png', get_lang('Tracking')),
$path.'tracking/courseLog.php?'.api_get_cidreq_params($courseCode)
);
$actions[] = Display::url(
Display::return_icon('edit.png', get_lang('Edit')),
$path.'admin/course_edit.php?id='.$courseId
);
$actions[] = Display::url(
Display::return_icon('backup.png', get_lang('CreateBackup')),
$path.'coursecopy/create_backup.php?'.api_get_cidreq_params($courseCode)
);
$actions[] = Display::url(
Display::return_icon('delete.png', get_lang('Delete')),
$path.'admin/course_list.php?delete_course='.$courseCode,
[
'onclick' => "javascript: if (!confirm('"
.addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."')) return false;"
]
);
$courseItem = [
$course[0],
@ -207,7 +221,7 @@ function get_course_data($from, $number_of_items, $column, $direction)
$course[4],
$course[5],
$course[6],
$actions,
implode(PHP_EOL, $actions),
];
$courses[] = $courseItem;
}

@ -6284,19 +6284,6 @@ class Exercise
);
$isVisible = false;
}
} else {
$isLimitReached = ExerciseLib::isQuestionsLimitPerDayReached(
api_get_user_id(),
$this->selectNbrQuestions(),
api_get_course_int_id(),
api_get_session_id()
);
if ($isLimitReached) {
$maxQuestionsAnswered = (int) api_get_course_setting('quiz_question_limit_per_day');
$message = sprintf(get_lang('QuizQuestionsLimitPerDayXReached'), $maxQuestionsAnswered);
$isVisible = false;
}
}
}

@ -247,7 +247,7 @@ if ($objExercise->selectAttempts() > 0) {
if (!empty($exercise_stat_info)) {
$isQuestionsLimitReached = ExerciseLib::isQuestionsLimitPerDayReached(
$user_id,
$objExercise->selectNbrQuestions(),
count($objExercise->get_validated_question_list()),
$courseId,
$sessionId
);

@ -28,7 +28,7 @@ $sessionId = api_get_session_id();
$exercise_id = isset($_REQUEST['exerciseId']) ? intval($_REQUEST['exerciseId']) : 0;
$objExercise = new Exercise();
$result = $objExercise->read($exercise_id, false);
$result = $objExercise->read($exercise_id, true);
if (!$result) {
api_not_allowed(true);
@ -392,7 +392,14 @@ if ($disable && empty($exercise_stat_info)) {
$exercise_url_button = Display::return_message(get_lang('NewExerciseAttemptDisabled'));
}
if (!empty($exercise_url_button)) {
$isLimitReached = ExerciseLib::isQuestionsLimitPerDayReached(
api_get_user_id(),
count($objExercise->get_validated_question_list()),
api_get_course_int_id(),
api_get_session_id()
);
if (!empty($exercise_url_button) && !$isLimitReached) {
$html .= Display::div(
Display::div(
$exercise_url_button,
@ -402,6 +409,16 @@ if (!empty($exercise_url_button)) {
);
}
if ($isLimitReached) {
$maxQuestionsAnswered = (int) api_get_course_setting('quiz_question_limit_per_day');
$html .= Display::return_message(
sprintf(get_lang('QuizQuestionsLimitPerDayXReached'), $maxQuestionsAnswered),
'warning',
false
);
}
$html .= Display::tag(
'div',
$table_content,

@ -1264,7 +1264,8 @@ abstract class Question
// checks if the exercise ID is not in the list
if (!in_array($exerciseId, $this->exerciseList)) {
$this->exerciseList[] = $exerciseId;
$newExercise = new Exercise();
$courseId = isset($this->course['real_id']) ? $this->course['real_id'] : 0;
$newExercise = new Exercise($courseId);
$newExercise->read($exerciseId, false);
$count = $newExercise->getQuestionCount();
$count++;

@ -2,7 +2,7 @@
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Message;
use Chamilo\CoreBundle\Entity\MessageLikes;
use Chamilo\CoreBundle\Entity\MessageFeedback;
use ChamiloSession as Session;
/**
@ -339,7 +339,7 @@ switch ($action) {
if (
api_is_anonymous() ||
!api_get_configuration_value('social_enable_likes_messages')
!api_get_configuration_value('social_enable_messages_feedback')
) {
echo json_encode(false);
exit;
@ -356,7 +356,7 @@ switch ($action) {
$em = Database::getManager();
$messageRepo = $em->getRepository('ChamiloCoreBundle:Message');
$messageLikesRepo = $em->getRepository('ChamiloCoreBundle:MessageLikes');
$messageLikesRepo = $em->getRepository('ChamiloCoreBundle:MessageFeedback');
/** @var Message $message */
$message = $messageRepo->find($messageId);
@ -393,7 +393,7 @@ switch ($action) {
$userLike = $messageLikesRepo->findOneBy(['message' => $message, 'user' => $user]);
if (empty($userLike)) {
$userLike = new MessageLikes();
$userLike = new MessageFeedback();
$userLike
->setMessage($message)
->setUser($user);

@ -5299,12 +5299,11 @@ EOT;
SELECT COUNT(ea) FROM ChamiloCoreBundle:TrackEAttempt ea
WHERE ea.userId = :user AND ea.cId = :course AND ea.sessionId = :session
AND ea.tms > :time
GROUP BY ea.questionId
')
->setParameters(['user' => $userId, 'course' => $courseId, 'session' => $sessionId, 'time' => $time])
->getResult();
->getSingleScalarResult();
return count($result);
return $result;
}
/**

@ -2740,7 +2740,7 @@ class MessageManager
*/
public static function countLikesAndDislikes($messageId, $userId)
{
if (!api_get_configuration_value('social_enable_likes_messages')) {
if (!api_get_configuration_value('social_enable_messages_feedback')) {
return [];
}
@ -2750,7 +2750,7 @@ class MessageManager
$em = Database::getManager();
$query = $em
->createQuery('
SELECT SUM(l.liked) AS likes, SUM(l.disliked) AS dislikes FROM ChamiloCoreBundle:MessageLikes l
SELECT SUM(l.liked) AS likes, SUM(l.disliked) AS dislikes FROM ChamiloCoreBundle:MessageFeedback l
WHERE l.message = :message
')
->setParameters(['message' => $messageId]);
@ -2762,7 +2762,7 @@ class MessageManager
}
$userLike = $em
->getRepository('ChamiloCoreBundle:MessageLikes')
->getRepository('ChamiloCoreBundle:MessageFeedback')
->findOneBy(['message' => $messageId, 'user' => $userId]);
return [
@ -2782,7 +2782,7 @@ class MessageManager
*/
public static function getLikesButton($messageId, $userId, $groupId = 0)
{
if (!api_get_configuration_value('social_enable_likes_messages')) {
if (!api_get_configuration_value('social_enable_messages_feedback')) {
return '';
}

@ -1151,17 +1151,17 @@ ALTER TABLE gradebook_evaluation ADD score_weight DOUBLE PRECISION DEFAULT NULL,
// Avoid add a reply-to header when a no-reply address is set.
//$_configuration['mail_no_reply_avoid_reply_to'] = false;
// Allows to user add likes or dislikes to posts in social wall. Requires DB changes:
// CREATE TABLE message_likes (id BIGINT AUTO_INCREMENT NOT NULL, message_id BIGINT NOT NULL, user_id INT NOT NULL, liked TINYINT(1) DEFAULT '0' NOT NULL, disliked TINYINT(1) DEFAULT '0' NOT NULL, updated_at DATETIME NOT NULL, INDEX IDX_B66CB196537A1329 (message_id), INDEX IDX_B66CB196A76ED395 (user_id), INDEX idx_message_likes_uid_mid (message_id, user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
// ALTER TABLE message_likes ADD CONSTRAINT FK_B66CB196537A1329 FOREIGN KEY (message_id) REFERENCES message (id) ON DELETE CASCADE;
// ALTER TABLE message_likes ADD CONSTRAINT FK_B66CB196A76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE;
// Allows to user add feedback (likes or dislikes) to posts in social wall. Requires DB changes:
// CREATE TABLE message_feedback (id BIGINT AUTO_INCREMENT NOT NULL, message_id BIGINT NOT NULL, user_id INT NOT NULL, liked TINYINT(1) DEFAULT '0' NOT NULL, disliked TINYINT(1) DEFAULT '0' NOT NULL, updated_at DATETIME NOT NULL, INDEX IDX_DB0F8049537A1329 (message_id), INDEX IDX_DB0F8049A76ED395 (user_id), INDEX idx_message_feedback_uid_mid (message_id, user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
// ALTER TABLE message_feedback ADD CONSTRAINT FK_DB0F8049537A1329 FOREIGN KEY (message_id) REFERENCES message (id) ON DELETE CASCADE;
// ALTER TABLE message_feedback ADD CONSTRAINT FK_DB0F8049A76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE;
// In 1.11.8, before enabling this feature, you also need to:
// - edit src/Chamilo/CoreBundle/Entity/MessageLikes.php
// - edit src/Chamilo/CoreBundle/Entity/MessageFeedback.php
// and follow the instructions about the @ORM\Entity() line
// - edit src/Chamilo/CoreBundle/Entity/Message.php
// and fllow the instruccions about the @ORM\OneToMany line for the $likes property
// - launch composer install to rebuild the autoload.php
//$_configuration['social_enable_likes_messages'] = false;
//$_configuration['social_enable_messages_feedback'] = false;
// Block student's access to the course documents when using the ckeditor "Browse server" button
//$_configuration['block_editor_file_manager_for_students'] = false;

@ -457,7 +457,7 @@ VALUES
('allow_coach_to_edit_course_session','false','No'),
('show_glossary_in_extra_tools', 'none', 'None'),
('show_glossary_in_extra_tools', 'exercise', 'Exercise'),
('show_glossary_in_extra_tools', 'lp', 'Learning path'),
('show_glossary_in_extra_tools', 'lp', 'LearningPaths'),
('show_glossary_in_extra_tools', 'exercise_and_lp', 'ExerciseAndLearningPath'),
('send_email_to_admin_when_create_course','true','Yes'),
('send_email_to_admin_when_create_course','false','No'),
@ -1960,3 +1960,11 @@ INSERT INTO settings_current (variable, type, category, selected_value, title, c
VALUES ('allow_download_documents_by_api_key', 'radio', 'WebServices', 'false', 'AllowDownloadDocumentsByApiKeyTitle', 'AllowDownloadDocumentsByApiKeyComment', '', NULL, 1);
INSERT INTO settings_options (variable, value, display_text) VALUES ('allow_download_documents_by_api_key', 'true', 'Yes');
INSERT INTO settings_options (variable, value, display_text) VALUES ('allow_download_documents_by_api_key', 'false', 'No');
INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('exercise_invisible_in_session',NULL,'radio','Session','false','ExerciseInvisibleInSessionTitle','ExerciseInvisibleInSessionComment','',NULL, 1);
INSERT INTO settings_options (variable, value, display_text) VALUES ('exercise_invisible_in_session','true','Yes');
INSERT INTO settings_options (variable, value, display_text) VALUES ('exercise_invisible_in_session','false','No');
INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('configure_exercise_visibility_in_course',NULL,'radio','Session','false','ConfigureExerciseVisibilityInCourseTitle','ConfigureExerciseVisibilityInCourseComment','',NULL, 1);
INSERT INTO settings_options (variable, value, display_text) VALUES ('configure_exercise_visibility_in_course','true','Yes');
INSERT INTO settings_options (variable, value, display_text) VALUES ('configure_exercise_visibility_in_course','false','No');

@ -325,7 +325,7 @@ $(function() {
$('video:not(.skip)').attr('preload', 'metadata');
function socialLikes() {
{% if 'social_enable_likes_messages'|api_get_configuration_value %}
{% if 'social_enable_messages_feedback'|api_get_configuration_value %}
$('body').on('click', '.social-like', function (e) {
e.preventDefault();

@ -103,8 +103,8 @@ class Message
/**
* @var ArrayCollection
*
* Add @ to the next line if api_get_configuration_value('social_enable_likes_messages') is true
* ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\MessageLikes", mappedBy="message", orphanRemoval=true)
* Add @ to the next line if api_get_configuration_value('social_enable_messages_feedback') is true
* ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\MessageFeedback", mappedBy="message", orphanRemoval=true)
*/
protected $likes;

@ -8,20 +8,20 @@ use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Index;
/**
* Class MessageLikes.
* Class MessageFeedback.
*
* @package Chamilo\CoreBundle\Entity
*
* @ORM\Table(
* name="message_likes",
* name="message_feedback",
* indexes={
* @Index(name="idx_message_likes_uid_mid", columns={"message_id", "user_id"})
* @Index(name="idx_message_feedback_uid_mid", columns={"message_id", "user_id"})
* }
* )
* Add @ to the next line if api_get_configuration_value('social_enable_likes_messages') is true
* Add @ to the next line if api_get_configuration_value('social_enable_messages_feedback') is true
* ORM\Entity()
*/
class MessageLikes
class MessageFeedback
{
/**
* @var int
@ -75,7 +75,7 @@ class MessageLikes
/**
* @param int $id
*
* @return MessageLikes
* @return MessageFeedback
*/
public function setId($id)
{
@ -95,7 +95,7 @@ class MessageLikes
/**
* @param Message $message
*
* @return MessageLikes
* @return MessageFeedback
*/
public function setMessage(Message $message)
{
@ -115,7 +115,7 @@ class MessageLikes
/**
* @param User $user
*
* @return MessageLikes
* @return MessageFeedback
*/
public function setUser(User $user)
{
@ -135,7 +135,7 @@ class MessageLikes
/**
* @param bool $liked
*
* @return MessageLikes
* @return MessageFeedback
*/
public function setLiked($liked)
{
@ -155,7 +155,7 @@ class MessageLikes
/**
* @param bool $disliked
*
* @return MessageLikes
* @return MessageFeedback
*/
public function setDisliked($disliked)
{
@ -175,7 +175,7 @@ class MessageLikes
/**
* @param \DateTime $updatedAt
*
* @return MessageLikes
* @return MessageFeedback
*/
public function setUpdatedAt(\DateTime $updatedAt)
{
Loading…
Cancel
Save