diff --git a/app/Migrations/Schema/V111/Version111.php b/app/Migrations/Schema/V111/Version111.php
index 94088f936e..eb453f2670 100644
--- a/app/Migrations/Schema/V111/Version111.php
+++ b/app/Migrations/Schema/V111/Version111.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
diff --git a/documentation/dependencies.html b/documentation/dependencies.html
index 39420f07e0..f02439bd28 100755
--- a/documentation/dependencies.html
+++ b/documentation/dependencies.html
@@ -63,7 +63,7 @@ We recommend using HTML5-compatible technology.
PC with a minimum of 512MB or any tablet or smartphone
We recommend a Pentium-I as a minimum processor capability for PCs
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
- Any modern browser (IE8 and inferior *excluded*).
+ Any modern browser (IE10 and inferior *excluded*).
Optional: Flash plugin (only required for a few features like the videoconference plugins)
Optional: Java applet capability (only required for some plugins)
diff --git a/documentation/readme.html b/documentation/readme.html
index 831674369d..f9460c4e8e 100755
--- a/documentation/readme.html
+++ b/documentation/readme.html
@@ -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.
Client side, Chamilo runs on any browser : Firefox, Internet Explorer
- (9+), Chrome, Safari, Opera, ...
+ (11+), Chrome, Safari, Opera, ...
For better user experience, we recommend Firefox (you can download it
freely from http://getfirefox.com).
diff --git a/main/admin/course_list.php b/main/admin/course_list.php
index 9ba9a80a71..08226d8ece 100755
--- a/main/admin/course_list.php
+++ b/main/admin/course_list.php
@@ -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]).
- ''.
- Security::remove_XSS($course[1]).
- ' '.
- $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 = ''.
- Display::return_icon('info2.png', get_lang('Info')).' '.
- ''.
- Display::return_icon('course_home.png', get_lang('CourseHomepage')).' '.
- ''.
- Display::return_icon('statistics.png', get_lang('Tracking')).' '.
- ''.
- Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).' '.
- ''.
- Display::return_icon('backup.png', get_lang('CreateBackup')).' '.
- ''.
- Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'';
+ $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;
}
diff --git a/main/exercise/exercise.class.php b/main/exercise/exercise.class.php
index 411fded084..bb005dba84 100755
--- a/main/exercise/exercise.class.php
+++ b/main/exercise/exercise.class.php
@@ -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;
- }
}
}
diff --git a/main/exercise/exercise_submit.php b/main/exercise/exercise_submit.php
index 94ad621fb4..faf6e081db 100755
--- a/main/exercise/exercise_submit.php
+++ b/main/exercise/exercise_submit.php
@@ -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
);
diff --git a/main/exercise/overview.php b/main/exercise/overview.php
index 7ddd3a9511..435869bfb5 100755
--- a/main/exercise/overview.php
+++ b/main/exercise/overview.php
@@ -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,
diff --git a/main/exercise/question.class.php b/main/exercise/question.class.php
index 7780319d24..850619acba 100755
--- a/main/exercise/question.class.php
+++ b/main/exercise/question.class.php
@@ -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++;
diff --git a/main/inc/ajax/social.ajax.php b/main/inc/ajax/social.ajax.php
index f740e1dc2d..c8d34bfe30 100755
--- a/main/inc/ajax/social.ajax.php
+++ b/main/inc/ajax/social.ajax.php
@@ -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);
diff --git a/main/inc/lib/exercise.lib.php b/main/inc/lib/exercise.lib.php
index 3e2cf92089..03f2e9ca11 100644
--- a/main/inc/lib/exercise.lib.php
+++ b/main/inc/lib/exercise.lib.php
@@ -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;
}
/**
diff --git a/main/inc/lib/message.lib.php b/main/inc/lib/message.lib.php
index 232355ef2e..d39de3fa62 100755
--- a/main/inc/lib/message.lib.php
+++ b/main/inc/lib/message.lib.php
@@ -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 '';
}
diff --git a/main/install/configuration.dist.php b/main/install/configuration.dist.php
index 2bf12b255b..97a95deac0 100755
--- a/main/install/configuration.dist.php
+++ b/main/install/configuration.dist.php
@@ -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;
diff --git a/main/install/data.sql b/main/install/data.sql
index c158acc015..2937eb032d 100644
--- a/main/install/data.sql
+++ b/main/install/data.sql
@@ -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'),
@@ -1959,4 +1959,12 @@ VALUES
INSERT INTO settings_current (variable, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable)
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');
\ No newline at end of file
+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');
diff --git a/main/template/default/layout/main.js.tpl b/main/template/default/layout/main.js.tpl
index 0ebd34171e..830609e667 100644
--- a/main/template/default/layout/main.js.tpl
+++ b/main/template/default/layout/main.js.tpl
@@ -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();
diff --git a/src/Chamilo/CoreBundle/Entity/Message.php b/src/Chamilo/CoreBundle/Entity/Message.php
index 72aef99601..a6e2d3cc87 100644
--- a/src/Chamilo/CoreBundle/Entity/Message.php
+++ b/src/Chamilo/CoreBundle/Entity/Message.php
@@ -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;
diff --git a/src/Chamilo/CoreBundle/Entity/MessageLikes.php b/src/Chamilo/CoreBundle/Entity/MessageFeedback.php
similarity index 88%
rename from src/Chamilo/CoreBundle/Entity/MessageLikes.php
rename to src/Chamilo/CoreBundle/Entity/MessageFeedback.php
index f3075727fa..a77b126c9a 100644
--- a/src/Chamilo/CoreBundle/Entity/MessageLikes.php
+++ b/src/Chamilo/CoreBundle/Entity/MessageFeedback.php
@@ -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)
{