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) {