Julio 9 år sedan
förälder
incheckning
82041f4739
50 ändrade filer med 1316 tillägg och 508 borttagningar
  1. 0 1
      app/Migrations/AbstractMigrationChamilo.php
  2. 15 0
      app/Migrations/Schema/V110/Version110.php
  3. 18 20
      app/Migrations/Schema/V20/Version20151019163400.php
  4. 43 0
      app/Migrations/Schema/V20/Version20151020142700.php
  5. 13 0
      documentation/optimization.html
  6. 1 1
      index.php
  7. 74 55
      main/admin/legal_add.php
  8. 3 3
      main/attendance/attendance_calendar.php
  9. 5 3
      main/auth/inscription.php
  10. 57 6
      main/badge/issued.php
  11. 1 1
      main/chat/chat.php
  12. 2 2
      main/chat/chat_chat.php
  13. 1 1
      main/chat/chat_whoisonline.php
  14. 7 2
      main/chat/header_frame.inc.php
  15. 6 6
      main/course_progress/thematic.php
  16. 36 36
      main/course_progress/thematic_plan.php
  17. 7 5
      main/inc/lib/api.lib.php
  18. 3 3
      main/inc/lib/attendance.lib.php
  19. 4 2
      main/inc/lib/extra_field.lib.php
  20. 13 4
      main/inc/lib/fileManage.lib.php
  21. 7 7
      main/inc/lib/group_portal_manager.lib.php
  22. 1 1
      main/inc/lib/javascript/jquery-scrollbar/jquery.scrollbar.css
  23. 51 0
      main/inc/lib/skill.lib.php
  24. 9 9
      main/inc/lib/usergroup.lib.php
  25. 54 54
      main/inc/lib/usermanager.lib.php
  26. 80 66
      main/install/install.lib.php
  27. 1 1
      main/install/update-files-1.9.0-1.10.0.inc.php
  28. 73 70
      main/lang/english/trad4all.inc.php
  29. 57 57
      main/lang/spanish/trad4all.inc.php
  30. 3 3
      main/mySpace/myStudents.php
  31. 10 1
      main/mySpace/student.php
  32. 218 0
      main/mySpace/user_edit.php
  33. 2 2
      main/social/group_view.php
  34. 6 1
      main/social/profile.php
  35. 6 6
      main/social/search.php
  36. 10 2
      main/survey/fillsurvey.php
  37. 47 0
      main/survey/survey.lib.php
  38. 2 2
      main/template/default/learnpath/view.tpl
  39. 41 1
      main/template/default/skill/issued.tpl
  40. 4 2
      plugin/dashboard/block_daily/block_daily.class.php
  41. 1 1
      src/Chamilo/CoreBundle/Entity/Legal.php
  42. 4 4
      src/Chamilo/CoreBundle/Entity/Repository/SkillRepository.php
  43. 2 3
      src/Chamilo/CoreBundle/Entity/SettingsCurrent.php
  44. 54 1
      src/Chamilo/CoreBundle/Entity/SkillRelUser.php
  45. 175 0
      src/Chamilo/CoreBundle/Entity/SkillRelUserComment.php
  46. 18 1
      src/Chamilo/CoreBundle/Resources/public/css/base.css
  47. 0 58
      src/Chamilo/CoreBundle/Resources/public/css/chat.css
  48. 5 0
      src/Chamilo/UserBundle/Entity/User.php
  49. 63 3
      src/Chamilo/UserBundle/Repository/UserRepository.php
  50. 3 1
      user_portal.php

+ 0 - 1
app/Migrations/AbstractMigrationChamilo.php

@@ -100,7 +100,6 @@ abstract class AbstractMigrationChamilo extends AbstractMigration
             ->setAccessUrlLocked($accessUrlLocked);
 
         $this->getEntityManager()->persist($setting);
-        //$this->getEntityManager()->flush();
 
         if (count($options) > 0) {
             foreach ($options as $option) {

+ 15 - 0
app/Migrations/Schema/V110/Version110.php

@@ -487,6 +487,21 @@ class Version110 extends AbstractMigrationChamilo
 
         $this->addSql("UPDATE settings_current SET selected_value = 'UTF-8' WHERE variable = 'platform_charset'");
 
+        $this->addSql("ALTER TABLE course_rel_user DROP PRIMARY KEY");
+        $this->addSql("ALTER TABLE course_rel_user ADD COLUMN id INT NOT NULL PRIMARY KEY AUTO_INCREMENT");
+        $this->addSql("ALTER TABLE course_rel_user MODIFY COLUMN user_id INT NULL");
+
+        $this->addSql("ALTER TABLE user MODIFY COLUMN user_id INT NULL");
+
+        $this->addSql("ALTER TABLE access_url_rel_course DROP PRIMARY KEY");
+        $this->addSql("ALTER TABLE access_url_rel_course ADD COLUMN id INT NOT NULL PRIMARY KEY AUTO_INCREMENT");
+        $this->addSql("ALTER TABLE access_url_rel_course DROP COLUMN course_code");
+        $this->addSql("ALTER TABLE access_url_rel_course ADD INDEX idx_select_c (c_id)");
+        $this->addSql("ALTER TABLE access_url_rel_course ADD INDEX idx_select_u (access_url_id)");
+
+        $this->addSql("ALTER TABLE access_url ADD COLUMN url_type TINYINT(1) NULL");
+
+        $this->addSql("ALTER TABLE course_rel_user ADD INDEX idx_select_c (c_id)");
     }
 
     /**

+ 18 - 20
app/Migrations/Schema/V20/Version20151019163400.php

@@ -17,19 +17,15 @@ class Version20151019163400 extends AbstractMigrationChamilo
      */
     public function up(Schema $schema)
     {
-        $user = $schema->getTable('user');
-        $skill = $schema->getTable('skill');
-        $course = $schema->getTable('course');
-        $session = $schema->getTable('session');
-
-        $skillRelUser = $schema->getTable('skill_rel_user');
-        $skillRelUser->getColumn('session_id')->setNotnull(false);
-        $skillRelUser->addForeignKeyConstraint($user, ['user_id'], ['id'], [], 'FK_su_user');
-        $skillRelUser->addForeignKeyConstraint($skill, ['skill_id'], ['id'], [], 'FK_su_skill');
-        $skillRelUser->addForeignKeyConstraint($course, ['course_id'], ['id'], [], 'FK_su_course');
-        $skillRelUser->addForeignKeyConstraint($session, ['session_id'], ['id'], [], 'FK_su_session');
-        $skillRelUser->addIndex(['session_id', 'course_id', 'user_id'], 'idx_select_s_c_u');
-        $skillRelUser->addIndex(['skill_id', 'user_id'], 'idx_select_sk_u');
+        $this->addSql("ALTER TABLE skill_rel_user CHANGE session_id session_id INT DEFAULT NULL");
+        $this->addSql("UPDATE skill_rel_user SET course_id = NULL WHERE course_id = 0");
+        $this->addSql("UPDATE skill_rel_user SET session_id = NULL WHERE session_id = 0");
+        $this->addSql("ALTER TABLE skill_rel_user ADD CONSTRAINT FK_su_user FOREIGN KEY (user_id) REFERENCES user (id)");
+        $this->addSql("ALTER TABLE skill_rel_user ADD CONSTRAINT FK_su_skill FOREIGN KEY (skill_id) REFERENCES skill (id)");
+        $this->addSql("ALTER TABLE skill_rel_user ADD CONSTRAINT FK_su_course FOREIGN KEY (course_id) REFERENCES course (id)");
+        $this->addSql("ALTER TABLE skill_rel_user ADD CONSTRAINT FK_su_session FOREIGN KEY (session_id) REFERENCES session (id)");
+        $this->addSql("CREATE INDEX idx_select_s_c_u ON skill_rel_user (session_id, course_id, user_id)");
+        $this->addSql("CREATE INDEX idx_select_sk_u ON skill_rel_user (skill_id, user_id)");
     }
 
     /**
@@ -37,12 +33,14 @@ class Version20151019163400 extends AbstractMigrationChamilo
      */
     public function down(Schema $schema)
     {
-        $skillRelUser = $schema->getTable('skill_rel_user');
-        $skillRelUser->removeForeignKey('FK_su_user');
-        $skillRelUser->removeForeignKey('FK_su_skill');
-        $skillRelUser->removeForeignKey('FK_su_course');
-        $skillRelUser->removeForeignKey('FK_su_session');
-        $skillRelUser->dropIndex('idx_select_s_c_u');
-        $skillRelUser->dropIndex('idx_select_sk_u');
+        $this->addSql("ALTER TABLE skill_rel_user DROP FOREIGN KEY FK_su_session");
+        $this->addSql("ALTER TABLE skill_rel_user DROP FOREIGN KEY FK_su_course");
+        $this->addSql("ALTER TABLE skill_rel_user DROP FOREIGN KEY FK_su_skill");
+        $this->addSql("ALTER TABLE skill_rel_user DROP FOREIGN KEY FK_su_user");
+        $this->addSql("DROP INDEX idx_select_s_c_u ON skill_rel_user");
+        $this->addSql("DROP INDEX idx_select_sk_u ON skill_rel_user");
+        $this->addSql("ALTER TABLE skill_rel_user CHANGE session_id session_id INT NOT NULL");
+        $this->addSql("UPDATE skill_rel_user SET course_id = 0 WHERE course_id IS NULL");
+        $this->addSql("UPDATE skill_rel_user SET session_id = 0 WHERE session_id IS NULL");
     }
 }

+ 43 - 0
app/Migrations/Schema/V20/Version20151020142700.php

@@ -0,0 +1,43 @@
+<?php
+/* For licensing terms, see /license.txt */
+namespace Application\Migrations\Schema\V20;
+
+use Application\Migrations\AbstractMigrationChamilo;
+use Doctrine\DBAL\Schema\Schema;
+
+/**
+ * Migrations for skills feedback
+ *
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ */
+class Version20151020142700 extends AbstractMigrationChamilo
+{
+    /**
+     * @param Schema $schema
+     */
+    public function up(Schema $schema)
+    {
+        $skillUser = $schema->getTable('skill_rel_user');
+        $user = $schema->getTable('user');
+
+        $skillUserComment = $schema->createTable('skill_rel_user_comment');
+        $skillUserComment->addColumn('id', \Doctrine\DBAL\Types\Type::INTEGER, ['autoincrement' => true]);
+        $skillUserComment->addColumn('skill_rel_user_id', \Doctrine\DBAL\Types\Type::INTEGER);
+        $skillUserComment->addColumn('feedback_giver_id', \Doctrine\DBAL\Types\Type::INTEGER);
+        $skillUserComment->addColumn('feedback_text', \Doctrine\DBAL\Types\Type::TEXT);
+        $skillUserComment->addColumn('feedback_value', \Doctrine\DBAL\Types\Type::INTEGER, ['notnull' => false]);
+        $skillUserComment->addColumn('feedback_datetime', \Doctrine\DBAL\Types\Type::DATETIME);
+        $skillUserComment->setPrimaryKey(['id']);
+        $skillUserComment->addForeignKeyConstraint($skillUser, ['skill_rel_user_id'], ['id']);
+        $skillUserComment->addForeignKeyConstraint($user, ['feedback_giver_id'], ['id']);
+        $skillUserComment->addIndex(['skill_rel_user_id', 'feedback_giver_id']);
+    }
+
+    /**
+     * @param Schema $schema
+     */
+    public function down(Schema $schema)
+    {
+        $schema->dropTable('skill_rel_user_comment');
+    }
+}

+ 13 - 0
documentation/optimization.html

@@ -337,6 +337,19 @@ To solve this performance issue, you can execute the following query manually in
 <pre>
 ALTER TABLE user_rel_tag ADD INDEX idx_user_rel_tag_user (user_id);
 </pre>
+<br /><br />
+In Chamilo 1.10.0 (the first version of the serie), many indexes were forgotten, so you can boost your database by adding the following indexes:<br />
+<pre>
+alter table extra_field_values add index idx_extra_field_values (field_id, item_id);
+alter table usergroup_rel_user add index idx_usergroup_ru (group_id);
+alter table usergroup_rel_user add index idx_usergroup_ru_u (user_id);
+alter table c_student_publication add index idxstudpub_cid (c_id);
+alter table c_student_publication add index idxstudpub_uid (user_id);
+alter table c_quiz_question add index idx_cqq_cid (c_id);
+alter table c_quiz_rel_question ADD INDEX idx_cqrq_qid (question_id);
+alter table c_quiz_rel_question ADD INDEX idx_cqrq_cid (c_id);
+alter table c_quiz_answer add index idx_qa_cidqid (c_id, question_id);
+</pre>
 <hr />
 <h2><a name="3.Indexes-caching"></a>3. Indexes caching</h2>
 One good reference: <a href="http://dev.mysql.com/doc/refman/5.1/en/multiple-key-caches.html">MySQL documentation on multiple key caches</a><br />

+ 1 - 1
index.php

@@ -70,7 +70,7 @@ if (isset($_GET['submitAuth']) && $_GET['submitAuth'] == 1) {
     die();
 }
 
-// Delete session neccesary for legal terms
+// Delete session item necessary to check for legal terms
 if (api_get_setting('allow_terms_conditions') == 'true') {
     Session::erase('term_and_condition');
 }

+ 74 - 55
main/admin/legal_add.php

@@ -16,82 +16,101 @@ api_protect_admin_script();
 // Create the form
 $form = new FormValidator('addlegal');
 
-$defaults=array();
-if( $form->validate()) {
+$defaults = array();
+$term_preview = array(
+	'type' => 0,
+	'content' => '',
+	'changes' => '',
+);
+if ($form->validate()) {
 	$check = Security::check_token('post');
-		if ($check) {
-			$values  = $form->getSubmitValues();
-			$lang 	 = $values['language'];
-			//language id
-			$lang = api_get_language_id($lang);
+	if ($check) {
+		$values  = $form->getSubmitValues();
+		$lang 	 = $values['language'];
+		//language id
+		$lang = api_get_language_id($lang);
 
+		if (isset($values['type'])) {
 			$type 	 = $values['type'];
+		} else {
+			$type = 0;
+		}
+		if (isset($values['content'])) {
 			$content = $values['content'];
+		} else {
+			$content = '';
+		}
+		if (isset($values['changes'])) {
 			$changes = $values['changes'];
-			$navigator_info = api_get_navigator();
-
-			if ($navigator_info['name']=='Internet Explorer' &&  $navigator_info['version']=='6') {
-				if (isset($values['preview'])) {
-					$submit	='preview';
-				} elseif (isset($values['save'])) {
-					$submit	='save';
-				} elseif (isset($values['back'])) {
-					$submit	='back';
-				}
-			} else {
-				$submit  = $values['send'];
+		} else {
+			$changes = '';
+		}
+		$navigator_info = api_get_navigator();
+
+		if ($navigator_info['name']=='Internet Explorer' &&  $navigator_info['version']=='6') {
+			if (isset($values['preview'])) {
+				$submit	='preview';
+			} elseif (isset($values['save'])) {
+				$submit	='save';
+			} elseif (isset($values['back'])) {
+				$submit	='back';
 			}
+		} else {
+			$submit  = $values['send'];
+		}
 
-			$default['content']=$content;
-			if (isset($values['language'])) {
-				if($submit=='back') {
-					header('Location: legal_add.php');
-					exit;
-				} elseif($submit=='save') {
-					$insert_result = LegalManager::add($lang,$content,$type,$changes);
-					if ($insert_result )
-						$message = get_lang('TermAndConditionSaved');
-					else
-						$message = get_lang('TermAndConditionNotSaved');
-					Security::clear_token();
-					$tok = Security::get_token();
-					header('Location: legal_list.php?action=show_message&message='.urlencode($message).'&sec_token='.$tok);
-					exit();
-				} elseif($submit=='preview') {
-					$defaults['type']=$type;
-					$defaults['content']=$content;
-					$defaults['changes']=$changes;
-					$term_preview = $defaults;
-					$term_preview['type'] = intval($_POST['type']);
+		$default['content'] = $content;
+		if (isset($values['language'])) {
+			if ($submit == 'back') {
+				header('Location: legal_add.php');
+				exit;
+			} elseif ($submit == 'save') {
+				$insert_result = LegalManager::add($lang, $content, $type, $changes);
+				if ($insert_result ) {
+					$message = get_lang('TermAndConditionSaved');
 				} else {
-					$my_lang = $_POST['language'];
-					if (isset($_POST['language'])){
-						$all_langs = api_get_languages();
-						if (in_array($my_lang, $all_langs['folder'])){
-							$language = api_get_language_id($my_lang);
-							$term_preview = LegalManager::get_last_condition($language);
-							$defaults = $term_preview;
-							if (!$term_preview) {
-								// there are not terms and conditions
-								$term_preview['type']=-1;
-								$defaults['type']=0;
-							}
+					$message = get_lang('TermAndConditionNotSaved');
+				}
+				Security::clear_token();
+				$tok = Security::get_token();
+				header('Location: legal_list.php?action=show_message&message='.urlencode($message).'&sec_token='.$tok);
+				exit();
+			} elseif ($submit=='preview') {
+				$defaults['type'] = $type;
+				$defaults['content'] = $content;
+				$defaults['changes'] = $changes;
+				$term_preview = $defaults;
+				$term_preview['type'] = intval($_POST['type']);
+			} else {
+				$my_lang = $_POST['language'];
+				if (isset($_POST['language'])){
+					$all_langs = api_get_languages();
+					if (in_array($my_lang, $all_langs['folder'])){
+						$language = api_get_language_id($my_lang);
+						$term_preview = LegalManager::get_last_condition($language);
+						$defaults = $term_preview;
+						if (!$term_preview) {
+							// there are not terms and conditions
+							$term_preview['type']=-1;
+							$defaults['type']=0;
 						}
 					}
 				}
 			}
 		}
+	}
 }
 
-$form->setDefaults($default);
+$form->setDefaults($defaults);
 
-if(isset($_POST['send'])) {
+if (isset($_POST['send'])) {
 	Security::clear_token();
 }
 $token = Security::get_token();
 
 $form->addElement('hidden','sec_token');
-$form->setConstants(array('sec_token' => $token));
+//$form->setConstants(array('sec_token' => $token));
+$defaults['sec_token'] = $token;
 $form->addElement('header', get_lang('DisplayTermsConditions'));
 
 if (isset($_POST['language'])) {

+ 3 - 3
main/attendance/attendance_calendar.php

@@ -58,18 +58,18 @@ if (isset($action) && $action == 'calendar_add') {
     $form = new FormValidator(
         'attendance_calendar_add',
         'POST',
-        'index.php?action=calendar_add&attendance_id='.$attendance_id.'&' . api_get_cidreq(),
+        'index.php?action=calendar_add&attendance_id=' . $attendance_id . '&' . api_get_cidreq(),
         ''
     );
     $form->addElement('header', get_lang('AddADateTime'));
     //$form->addElement('date_time_picker', 'date_time');
-    
+
     $form->addDateTimePicker(
             'date_time',
             array(get_lang('StartDate')),
             array('id' => 'date_time')
         );
-    
+
     $defaults['date_time'] = date('Y-m-d H:i', api_strtotime(api_get_local_time()));
 
     $form->addElement(

+ 5 - 3
main/auth/inscription.php

@@ -309,7 +309,7 @@ if (!CustomPages::enabled()) {
     if (api_get_setting('allow_terms_conditions') == 'true') {
         $get = array_keys($_GET);
         if (isset($get)) {
-            if ($get[0] == 'legal') {
+            if (isset($get[0]) && $get[0] == 'legal') {
                 $language = api_get_interface_language();
                 $language = api_get_language_id($language);
                 $term_preview = LegalManager::get_last_condition($language);
@@ -421,13 +421,15 @@ $course_code_redirect = Session::read('course_redirect');
 if ($form->validate()) {
     $values = $form->getSubmitValues(1);
     // Make *sure* the login isn't too long
-    $values['username'] = api_substr($values['username'], 0, USERNAME_MAX_LENGTH);
+    if (isset($values['username'])) {
+        $values['username'] = api_substr($values['username'], 0, USERNAME_MAX_LENGTH);
+    }
 
     if (api_get_setting('allow_registration_as_teacher') == 'false') {
         $values['status'] = STUDENT;
     }
 
-    if (empty($values['official_code'])) {
+    if (empty($values['official_code']) && !empty($values['username'])) {
         $values['official_code'] = api_strtoupper($values['username']);
     }
 

+ 57 - 6
main/badge/issued.php

@@ -7,13 +7,13 @@
  */
 require_once '../inc/global.inc.php';
 
-if (!isset($_GET['user'], $_GET['issue'])) {
+if (!isset($_REQUEST['user'], $_REQUEST['issue'])) {
     header('Location: ' . api_get_path(WEB_PATH));
     exit;
 }
 
 $entityManager = Database::getManager();
-$skillIssue = $entityManager->find('ChamiloCoreBundle:SkillRelUser', $_GET['issue']);
+$skillIssue = $entityManager->find('ChamiloCoreBundle:SkillRelUser', $_REQUEST['issue']);
 
 if (!$skillIssue) {
     Display::addFlash(
@@ -24,7 +24,7 @@ if (!$skillIssue) {
     exit;
 }
 
-if ($skillIssue->getUser()->getId() !== intval($_GET['user'])) {
+if ($skillIssue->getUser()->getId() !== intval($_REQUEST['user'])) {
     Display::addFlash(
         Display::return_message(get_lang('NoResults'), 'error')
     );
@@ -33,6 +33,10 @@ if ($skillIssue->getUser()->getId() !== intval($_GET['user'])) {
     exit;
 }
 
+$currentUserId = api_get_user_id();
+$currentUser = $entityManager->find('ChamiloUserBundle:User', $currentUserId);
+$allowExport = $currentUser ? $currentUser->getId() === $skillIssue->getUser()->getId() : false;
+$allowComment = $currentUser ? Skill::userCanAddFeedbackToUser($currentUser, $skillIssue->getUser()) : false;
 $skillIssueDate = api_get_local_time($skillIssue->getAcquiredSkillAt());
 
 $skillIssueInfo = [
@@ -40,16 +44,61 @@ $skillIssueInfo = [
     'datetime' => api_format_date($skillIssueDate, DATE_TIME_FORMAT_SHORT),
     'argumentation' => $skillIssue->getArgumentation(),
     'source_name' => $skillIssue->getSourceName(),
+    'user_id' => $skillIssue->getUser()->getId(),
     'user_complete_name' => $skillIssue->getUser()->getCompleteName(),
     'skill_badge_image' => $skillIssue->getSkill()->getWebIconPath(),
     'skill_name' => $skillIssue->getSkill()->getName(),
     'skill_short_code' => $skillIssue->getSkill()->getShortCode(),
     'skill_description' => $skillIssue->getSkill()->getDescription(),
     'skill_criteria' => $skillIssue->getSkill()->getCriteria(),
-    'badge_asserion' => [$skillIssue->getAssertionUrl()]
+    'badge_asserion' => [$skillIssue->getAssertionUrl()],
+    'comments' => [],
+    'feedback_average' => $skillIssue->getAverage()
 ];
 
-$allowExport = api_get_user_id() === $skillIssue->getUser()->getId();
+$skillIssueComments = $skillIssue->getComments(true);
+
+foreach ($skillIssueComments as $comment) {
+    $commentDate = api_get_local_time($comment->getFeedbackDateTime());
+
+    $skillIssueInfo['comments'][] = [
+        'text' => $comment->getFeedbackText(),
+        'value' => $comment->getFeedbackValue(),
+        'giver_complete_name' => $comment->getFeedbackGiver()->getCompleteName(),
+        'datetime' => api_format_date($commentDate, DATE_TIME_FORMAT_SHORT)
+    ];
+}
+
+$form = new FormValidator('comment');
+$form->addTextarea('comment', get_lang('NewComment'), ['rows' => 4]);
+$form->applyFilter('comment', 'trim');
+$form->addRule('comment', get_lang('ThisFieldIsRequired'), 'required');
+$form->addSelect(
+    'value',
+    [get_lang('Value'), get_lang('RateTheSkillInPractice')],
+    ['-', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+);
+$form->addHidden('user', $skillIssue->getUser()->getId());
+$form->addHidden('issue', $skillIssue->getId());
+$form->addButtonSend(get_lang('Send'));
+
+if ($form->validate() && $allowComment) {
+    $values = $form->exportValues();
+
+    $skillUserComment = new Chamilo\CoreBundle\Entity\SkillRelUserComment();
+    $skillUserComment
+        ->setFeedbackDateTime(new DateTime)
+        ->setFeedbackGiver($currentUser)
+        ->setFeedbackText($values['comment'])
+        ->setFeedbackValue($values['value'] ? $values['value'] : null)
+        ->setSkillRelUser($skillIssue);
+
+    $entityManager->persist($skillUserComment);
+    $entityManager->flush();
+
+    header("Location: " . $skillIssue->getIssueUrl());
+    exit;
+}
 
 if ($allowExport) {
     $backpack = 'https://backpack.openbadges.org/';
@@ -63,9 +112,11 @@ if ($allowExport) {
     $htmlHeadXtra[] = '<script src="' . $backpack . 'issuer.js"></script>';
 }
 
-$template = new Template('');
+$template = new Template(get_lang('IssuedBadgeInformation'));
 $template->assign('issue_info', $skillIssueInfo);
+$template->assign('allow_comment', $allowComment);
 $template->assign('allow_export', $allowExport);
+$template->assign('comment_form', $form->returnForm());
 
 $content = $template->fetch(
     $template->get_template('skill/issued.tpl')

+ 1 - 1
main/chat/chat.php

@@ -84,7 +84,7 @@ echo '<div class="page-chat">';
 echo '<iframe src="'.$url.'chat_whoisonline.php?'.$params.'" name="chat_whoisonline" scrolling="no" style="height:550px; width:35%; border: 0px none; float:left"></iframe>';
 echo '<iframe src="'.$url.'chat_chat.php?origin='.$origin.'&target='.$target.'&'.$params.'" name="chat_chat" id="chat_chat" scrolling="auto" height="380" style="width:65%; border: 0px none; float:right"></iframe>';
 echo '<iframe src="'.$url.'chat_message.php?'.$params.'" name="chat_message" scrolling="no" height="182px" style="width:65%; border: 0px none; float:right"></iframe>';
-echo '<iframe src="'.$url.'chat_hidden.php?'.$params.'" name="chat_hidden" height="" style="border: 0px none"></iframe>';
+echo '<iframe src="'.$url.'chat_hidden.php?'.$params.'" name="chat_hidden" height="0px" style="height:0px; border: 0px none"></iframe>';
 echo '</div>';
 
 if (empty($open_chat_window)) {

+ 2 - 2
main/chat/chat_chat.php

@@ -193,8 +193,8 @@ if (!empty($course)) {
 		        WHERE (user_id = ".$userId.")";
 		$result = Database::query($sql);
 	}
-
-	echo '<div id="content-chat markdown-body">';
+        
+	echo '<div id="content-chat"';
 	foreach ($content as & $this_line) {
         echo $this_line;
 	}

+ 1 - 1
main/chat/chat_whoisonline.php

@@ -123,7 +123,7 @@ if (!empty($course)) {
 	<div id="user-online-scroll" class="user-online">
 		<div class="title"><?php echo get_lang('Users'); ?> <?php echo get_lang('Connected'); ?></div>
 		<div class="scrollbar"><div class="track"><div class="thumb"><div class="end"></div></div></div></div>
-		<div class="viewport"><div id="hidden" class="overview">
+		<div class="scrollbar-inner viewport"><div id="hidden" class="overview">
 		<ul class="profile list-group">
 			<?php
             foreach ($users as & $user) {

+ 7 - 2
main/chat/header_frame.inc.php

@@ -126,6 +126,7 @@ header('Content-Type: text/html; charset=UTF-8');
 <link rel="stylesheet" type="text/css" href="<?php echo api_get_path(WEB_PATH); ?>web/assets/bootstrap/dist/css/bootstrap.css">
 <link rel="stylesheet" type="text/css" href="<?php echo api_get_path(WEB_LIBRARY_PATH); ?>javascript/jquery-emojiarea/jquery.emojiarea.css">
 <link rel="stylesheet" type="text/css" href="<?php echo api_get_path(WEB_CSS_PATH); ?>chat.css">
+<link rel="stylesheet" type="text/css" href="<?php echo api_get_path(WEB_LIBRARY_PATH); ?>/javascript/jquery-scrollbar/jquery.scrollbar.css">
 <link rel="stylesheet" type="text/css" href="<?php echo api_get_path(WEB_CSS_PATH); ?>markdown.css">
 <link rel="stylesheet" type="text/css" href="<?php echo api_get_path(WEB_LIBRARY_PATH); ?>javascript/jquery-textcomplete/jquery.textcomplete.css">
 <link rel="stylesheet" type="text/css" href="<?php echo api_get_path(WEB_LIBRARY_PATH); ?>javascript/emojione/css/emojione.min.css">
@@ -137,7 +138,8 @@ header('Content-Type: text/html; charset=UTF-8');
 <?php echo api_get_js('jquery-textcomplete/jquery.textcomplete.js'); ?>
 <?php echo api_get_js('emojione/js/emojione.min.js'); ?>
 <?php echo api_get_js('jquery-emojiarea/jquery.emojiarea.js'); ?>
-<?php echo api_get_js('jquery.tinyscrollbar.js'); ?>
+<?php echo api_get_js('jquery-scrollbar/jquery.scrollbar.min.js'); ?>
+<?php // echo api_get_js('jquery.tinyscrollbar.js'); ?>
 <script type="text/javascript">
     hljs.initHighlightingOnLoad();
     emojione.ascii = true;
@@ -218,7 +220,6 @@ header('Content-Type: text/html; charset=UTF-8');
         ],{
             //footer: '<a href="http://www.emoji.codes" target="_blank">Browse All<span class="arrow">»</span></a>'
         });
-		$('#user-online-scroll').tinyscrollbar();
 	});
 
 	function play_notification()
@@ -264,6 +265,10 @@ header('Content-Type: text/html; charset=UTF-8');
 			document.formMessage.submit();
 		}
 	}
+    jQuery(document).ready(function(){
+       jQuery('.scrollbar-inner').scrollbar();
+    });
+    
 </script>
 </head>
 <body <?php echo $bodyXtra; ?> >

+ 6 - 6
main/course_progress/thematic.php

@@ -14,7 +14,7 @@ api_protect_course_script(true);
 $token = Security::get_token();
 $url_token = "&sec_token=".$token;
 $user_info = api_get_user_info();
-$urlParam = '&'.api_get_cidreq();
+$params = '&'.api_get_cidreq();
 
 if (api_is_allowed_to_edit(null, true)) {
     echo '<div class="actions">';
@@ -115,24 +115,24 @@ if ($action == 'thematic_list') {
                 // Thematic title
                 $actions_first_col  = Display::url(
                     Display::return_icon('cd.gif', get_lang('Copy')),
-                    'index.php?'.api_get_cidreq().'&action=thematic_copy&thematic_id='.$my_thematic_id.$urlParam.$url_token
+                    'index.php?'.api_get_cidreq().'&action=thematic_copy&thematic_id='.$my_thematic_id.$params.$url_token
                 );
                 if (api_get_session_id() == 0 ) {
 
                     if ($thematic['display_order'] > 1) {
-                        $actions_first_col .= ' <a href="'.api_get_self().'?action=moveup&'.api_get_cidreq().'&thematic_id='.$my_thematic_id.$urlParam.$url_token.'">'.Display::return_icon('up.png', get_lang('Up'),'',ICON_SIZE_SMALL).'</a>';
+                        $actions_first_col .= ' <a href="'.api_get_self().'?action=moveup&'.api_get_cidreq().'&thematic_id='.$my_thematic_id.$params.$url_token.'">'.Display::return_icon('up.png', get_lang('Up'),'',ICON_SIZE_SMALL).'</a>';
                     } else {
                         $actions_first_col .= ' '.Display::return_icon('up_na.png','&nbsp;','',ICON_SIZE_SMALL);
                     }
                     if (isset($thematic['max_thematic_item']) && $thematic['display_order'] < $thematic['max_thematic_item']) {
-                        $actions_first_col .= ' <a href="'.api_get_self().'?action=movedown&a'.api_get_cidreq().'&thematic_id='.$my_thematic_id.$urlParam.$url_token.'">'.Display::return_icon('down.png',get_lang('Down'),'',ICON_SIZE_SMALL).'</a>';
+                        $actions_first_col .= ' <a href="'.api_get_self().'?action=movedown&a'.api_get_cidreq().'&thematic_id='.$my_thematic_id.$params.$url_token.'">'.Display::return_icon('down.png',get_lang('Down'),'',ICON_SIZE_SMALL).'</a>';
                     } else {
                         $actions_first_col .= ' '.Display::return_icon('down_na.png','&nbsp;','',ICON_SIZE_SMALL);
                     }
                 }
                 if (api_get_session_id() == $thematic['session_id']) {
-                    $actions_first_col .= '<a href="index.php?'.api_get_cidreq().'&action=thematic_edit&thematic_id='.$my_thematic_id.$urlParam.$url_token.'">'.Display::return_icon('edit.png',get_lang('Edit'),'',ICON_SIZE_SMALL).'</a>';
-                    $actions_first_col .= '<a onclick="javascript:if(!confirm(\''.get_lang('AreYouSureToDelete').'\')) return false;" href="index.php?'.api_get_cidreq().'&action=thematic_delete&thematic_id='.$my_thematic_id.$urlParam.$url_token.'">'.Display::return_icon('delete.png',get_lang('Delete'),'',ICON_SIZE_SMALL).'</a>';
+                    $actions_first_col .= '<a href="index.php?'.api_get_cidreq().'&action=thematic_edit&thematic_id='.$my_thematic_id.$params.$url_token.'">'.Display::return_icon('edit.png',get_lang('Edit'),'',ICON_SIZE_SMALL).'</a>';
+                    $actions_first_col .= '<a onclick="javascript:if(!confirm(\''.get_lang('AreYouSureToDelete').'\')) return false;" href="index.php?'.api_get_cidreq().'&action=thematic_delete&thematic_id='.$my_thematic_id.$params.$url_token.'">'.Display::return_icon('delete.png',get_lang('Delete'),'',ICON_SIZE_SMALL).'</a>';
                 }
 
                 $actions_first_col = Display::div($actions_first_col, array('id'=>'thematic_id_content_'.$thematic['id'], 'class'=>'thematic_tools'));

+ 36 - 36
main/course_progress/thematic_plan.php

@@ -34,45 +34,45 @@ if (isset($message) && $message == 'ok') {
 }
 
 if ($action == 'thematic_plan_list') {
-        $form = new FormValidator(
-            'thematic_plan_add',
-            'POST',
-            'index.php?action=thematic_plan_list&thematic_id='.$thematic_id.'&'.api_get_cidreq()
-        );
-        $form->addElement('hidden', 'action', 'thematic_plan_add');
-        //$form->addElement('hidden', 'thematic_plan_token', $token);
-        $form->addElement('hidden', 'thematic_id', $thematic_id);
+    $form = new FormValidator(
+        'thematic_plan_add',
+        'POST',
+        'index.php?action=thematic_plan_list&thematic_id='.$thematic_id.'&'.api_get_cidreq()
+    );
+    $form->addElement('hidden', 'action', 'thematic_plan_add');
+    //$form->addElement('hidden', 'thematic_plan_token', $token);
+    $form->addElement('hidden', 'thematic_id', $thematic_id);
 
-        foreach ($default_thematic_plan_title as $id => $title) {
-            $form->addElement('hidden', 'description_type['.$id.']', $id);
-            $form->addText('title['.$id.']', get_lang('Title'), false, array('size'=>'50'));
-            $form->addHtmlEditor(
-               'description['.$id.']',
-               get_lang('Description'),
-               false,
-               false,
-               array(
-                   'ToolbarStartExpanded' => 'false',
-                   'ToolbarSet' => 'TrainingDescription',
-                   'Height' => '150'
-               )
-            );
+    foreach ($default_thematic_plan_title as $id => $title) {
+        $form->addElement('hidden', 'description_type['.$id.']', $id);
+        $form->addText('title['.$id.']', get_lang('Title'), false, array('size'=>'50'));
+        $form->addHtmlEditor(
+           'description['.$id.']',
+           get_lang('Description'),
+           false,
+           false,
+           array(
+               'ToolbarStartExpanded' => 'false',
+               'ToolbarSet' => 'TrainingDescription',
+               'Height' => '150'
+           )
+        );
 
-            if (!empty($thematic_simple_list) && in_array($id, $thematic_simple_list)) {
-                $thematic_plan = $new_thematic_plan_data[$id];
-                // set default values
-                $default['title['.$id.']']       = $thematic_plan['title'];
-                $default['description['.$id.']'] = $thematic_plan['description'];
-                $thematic_plan = null;
-            } else {
-                $thematic_plan = null;
-                $default['title['.$id.']']       = $title;
-                $default['description['.$id.']']= '';
-            }
-            $form->setDefaults($default);
+        if (!empty($thematic_simple_list) && in_array($id, $thematic_simple_list)) {
+            $thematic_plan = $new_thematic_plan_data[$id];
+            // set default values
+            $default['title['.$id.']']       = $thematic_plan['title'];
+            $default['description['.$id.']'] = $thematic_plan['description'];
+            $thematic_plan = null;
+        } else {
+            $thematic_plan = null;
+            $default['title['.$id.']']       = $title;
+            $default['description['.$id.']']= '';
         }
-        $form->addButtonSave(get_lang('Save'));
-        $form->display();
+        $form->setDefaults($default);
+    }
+    $form->addButtonSave(get_lang('Save'));
+    $form->display();
 } elseif ($action == 'thematic_plan_add' || $action == 'thematic_plan_edit') {
     if ($description_type >= ADD_THEMATIC_PLAN) {
         $header_form = get_lang('NewBloc');

+ 7 - 5
main/inc/lib/api.lib.php

@@ -1455,7 +1455,9 @@ function _api_format_user($user, $add_password = false)
         'theme',
         'language',
         'creator_id',
-        'registration_date'
+        'registration_date',
+        'hr_dept_id',
+        'expiration_date'
     );
 
     foreach ($attributes as $attribute) {
@@ -6130,9 +6132,9 @@ function api_get_tools_lists($my_tool = null) {
  * @param int user id
  * @return bool true if we pass false otherwise
  */
-function api_check_term_condition($user_id) {
+function api_check_term_condition($user_id)
+{
     if (api_get_setting('allow_terms_conditions') == 'true') {
-
         //check if exists terms and conditions
         if (LegalManager::count() == 0) {
             return true;
@@ -6144,8 +6146,8 @@ function api_check_term_condition($user_id) {
             'legal_accept'
         );
 
-        if (!empty($data) && isset($data[0])) {
-            $rowv = $data[0];
+        if (!empty($data) && isset($data['value'])) {
+            $rowv = $data['value'];
             $user_conditions = explode(':', $rowv);
             $version = $user_conditions[0];
             $lang_id = $user_conditions[1];

+ 3 - 3
main/inc/lib/attendance.lib.php

@@ -135,7 +135,7 @@ class Attendance
 				LIMIT $from,$number_of_items ";
 
 		$res = Database::query($sql);
-		$attendances = array ();
+		$attendances = array();
 		$user_info = api_get_user_info();
 		$allowDelete = api_get_setting('allow_delete_attendance');
 
@@ -191,7 +191,7 @@ class Attendance
 						$attendance[2] = '<span class="muted">'.$attendance[2].'</span>';
 					}
 					if ($allowDelete === 'true') {
-						$actions .= '<a href="index.php?' . api_get_cidreq() . '&action=attendance_delete&attendance_id=' . $attendance[0]. '">' .
+						$actions .= '<a href="index.php?' . api_get_cidreq() . '&action=attendance_delete&attendance_id=' . $attendance[0].'">' .
 							Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
 					}
 				} else {
@@ -230,7 +230,7 @@ class Attendance
 							$message_alert = get_lang('UnlockMessageInformation');
 						}
 						$actions .= '&nbsp;<a onclick="javascript:if(!confirm(\''.$message_alert.'\')) return false;" href="index.php?'.api_get_cidreq().'&action=lock_attendance&attendance_id='.$attendance[0].'">'.
-                            Display::return_icon('unlock.png', get_lang('LockAttendance')).'</a>';
+								Display::return_icon('unlock.png', get_lang('LockAttendance')).'</a>';
 					} else {
 						if (api_is_platform_admin()) {
 							$actions .= '&nbsp;<a onclick="javascript:if(!confirm(\''.get_lang('AreYouSureToUnlockTheAttendance').'\')) return false;" href="index.php?'.api_get_cidreq().'&action=unlock_attendance&attendance_id='.$attendance[0].'">'.

+ 4 - 2
main/inc/lib/extra_field.lib.php

@@ -1286,9 +1286,11 @@ EOF;
                         break;
                     case ExtraField::FIELD_TYPE_SOCIAL_PROFILE:
                         // get the social network's favicon
+                        $extra_data_variable = isset($extraData['extra_'.$field_details['variable']]) ? $extraData['extra_'.$field_details['variable']] : null;
+                        $field_default_value = isset($field_details['field_default_value']) ? $field_details['field_default_value'] : null;
                         $icon_path = UserManager::get_favicon_from_url(
-                            $extraData['extra_'.$field_details['variable']],
-                            $field_details['field_default_value']
+                            $extra_data_variable,
+                            $field_default_value
                         );
                         // special hack for hi5
                         $leftpad = '1.7';

+ 13 - 4
main/inc/lib/fileManage.lib.php

@@ -209,23 +209,32 @@ function my_rename($file_path, $new_file_name) {
  * @author - Hugues Peeters <peeters@ipm.ucl.ac.be>
  * @param  - $source (String) - the path of file or directory to move
  * @param  - $target (String) - the path of the new area
+ * @param  bool $forceMove Whether to force a move or to make a copy (safer but slower) and then delete the original
  * @return - bolean - true if the move succeed
  *           bolean - false otherwise.
  * @see    - move() uses check_name_exist() and copyDirTo() functions
  */
-function move($source, $target)
+function move($source, $target, $forceMove = false)
 {
 	if (check_name_exist($source)) {
 		$file_name = basename($source);
 
 		/* File case */
 		if (is_file($source)) {
-			copy($source , $target.'/'.$file_name);
-			unlink($source);
+			if ($forceMove) {
+				rename($source, $target . '/' . $file_name);
+			} else {
+				copy($source, $target . '/' . $file_name);
+				unlink($source);
+			}
 			return true;
 		} elseif (is_dir($source)) {
 			/* Directory */
-			copyDirTo($source, $target);
+			if ($forceMove) {
+				rename($source, $target);
+			} else {
+				copyDirTo($source, $target);
+			}
 			return true;
 		}
 	} else {

+ 7 - 7
main/inc/lib/group_portal_manager.lib.php

@@ -569,12 +569,12 @@ class GroupPortalManager
 
         $sql = "SELECT
                     picture_uri as image,
-                    u.user_id,
+                    u.id,
                     u.firstname,
                     u.lastname,
                     relation_type
     		    FROM $tbl_user u INNER JOIN $table_group_rel_user gu
-    			ON (gu.user_id = u.user_id)
+    			ON (gu.user_id = u.id)
     			WHERE
     			    gu.group_id= $group_id
     			    $where_relation_condition
@@ -584,10 +584,10 @@ class GroupPortalManager
         $array = array();
         while ($row = Database::fetch_array($result, 'ASSOC')) {
             if ($with_image) {
-                $picture = UserManager::getUserPicture($row['user_id']);
+                $picture = UserManager::getUserPicture($row['id']);
                 $row['image'] = '<img src="'.$picture.'" />';
             }
-            $array[$row['user_id']] = $row;
+            $array[$row['id']] = $row;
         }
 
         return $array;
@@ -607,17 +607,17 @@ class GroupPortalManager
         if (empty($group_id)) {
             return array();
         }
-        $sql = "SELECT u.user_id, u.firstname, u.lastname, relation_type
+        $sql = "SELECT u.id, u.firstname, u.lastname, relation_type
                 FROM $tbl_user u
                 INNER JOIN $table_group_rel_user gu
-                ON (gu.user_id = u.user_id)
+                ON (gu.user_id = u.id)
                 WHERE gu.group_id= $group_id
                 ORDER BY relation_type, firstname";
 
         $result = Database::query($sql);
         $array = array();
         while ($row = Database::fetch_array($result, 'ASSOC')) {
-            $array[$row['user_id']] = $row;
+            $array[$row['id']] = $row;
         }
         return $array;
     }

+ 1 - 1
main/inc/lib/javascript/jquery-scrollbar/jquery.scrollbar.css

@@ -14,7 +14,7 @@
     margin: 0;
     max-height: none;
     max-width: none !important;
-    overflow: scroll !important;
+    /* overflow: scroll !important; */
     padding: 0;
     position: relative !important;
     top: 0;

+ 51 - 0
main/inc/lib/skill.lib.php

@@ -1,5 +1,6 @@
 <?php
 /* For licensing terms, see /license.txt */
+use Chamilo\UserBundle\Entity\User;
 
 /**
  * Class SkillProfile
@@ -1491,4 +1492,54 @@ class Skill extends Model
         return Database::store_result($result, 'ASSOC');
     }
 
+    /**
+     * Check if the $fromUser can comment the $toUser skill issue 
+     * @param Chamilo\UserBundle\Entity\User $fromUser
+     * @param Chamilo\UserBundle\Entity\User $toUser
+     * @return boolean
+     */
+    public static function userCanAddFeedbackToUser(User $fromUser, User $toUser)
+    {
+        if (api_is_platform_admin()) {
+            return true;
+        }
+
+        $entityManager = Database::getManager();
+        $userRepo = $entityManager->getRepository('ChamiloUserBundle:User');
+        $fromUserStatus = $fromUser->getStatus();
+
+        switch ($fromUserStatus) {
+            case SESSIONADMIN:
+                if (api_get_setting('allow_session_admins_to_manage_all_sessions') === 'true') {
+                    if ($toUser->getCreatorId() === $fromUser->getId()) {
+                        return true;
+                    }
+                }
+
+                $sessionAdmins = $userRepo->getSessionAdmins($toUser);
+
+                foreach ($sessionAdmins as $sessionAdmin) {
+                    if ($sessionAdmin->getId() !== $fromUser->getId()) {
+                        continue;
+                    }
+
+                    return true;
+                }
+                break;
+            case STUDENT_BOSS:
+                $studentBosses = $userRepo->getStudentBosses($toUser);
+
+                foreach ($studentBosses as $studentBoss) {
+                    if ($studentBoss->getId() !== $fromUser->getId()) {
+                        continue;
+                    }
+
+                    return true;
+                }
+            case DRH:
+                return UserManager::is_user_followed_by_drh($toUser->getId(), $fromUser->getId());
+        }
+
+        return false;
+    }
 }

+ 9 - 9
main/inc/lib/usergroup.lib.php

@@ -1269,7 +1269,7 @@ class UserGroup extends Model
         $id = intval($id);
         $sql = "SELECT u.* FROM ".$this->table_user." u
                 INNER JOIN ".$this->usergroup_rel_user_table." c
-                ON c.user_id = u.user_id
+                ON c.user_id = u.id
                 WHERE c.usergroup_id = $id"
                 ;
         $result = Database::query($sql);
@@ -1905,10 +1905,10 @@ class UserGroup extends Model
                 $where_relation_condition = "AND gu.relation_type IN ($relation_type) ";
         }
 
-        $sql = "SELECT picture_uri as image, u.user_id, u.firstname, u.lastname, relation_type
+        $sql = "SELECT picture_uri as image, u.id, u.firstname, u.lastname, relation_type
     		    FROM $tbl_user u
     		    INNER JOIN $table_group_rel_user gu
-    			ON (gu.user_id = u.user_id)
+    			ON (gu.user_id = u.id)
     			WHERE
     			    gu.usergroup_id= $group_id
     			    $where_relation_condition
@@ -1919,13 +1919,13 @@ class UserGroup extends Model
         $array  = array();
         while ($row = Database::fetch_array($result, 'ASSOC')) {
             if ($with_image) {
-                $userInfo = api_get_user_info($row['user_id']);
-                $userPicture = UserManager::getUserPicture($row['user_id']);
+                $userInfo = api_get_user_info($row['id']);
+                $userPicture = UserManager::getUserPicture($row['id']);
 
                 $row['image'] = '<img src="'.$userPicture.'"  />';
                 $row['user_info'] = $userInfo;
             }
-            $array[$row['user_id']] = $row;
+            $array[$row['id']] = $row;
         }
         return $array;
     }
@@ -1946,17 +1946,17 @@ class UserGroup extends Model
             return array();
         }
 
-        $sql = "SELECT u.user_id, u.firstname, u.lastname, relation_type
+        $sql = "SELECT u.id, u.firstname, u.lastname, relation_type
                 FROM $tbl_user u
 			    INNER JOIN $table_group_rel_user gu
-			    ON (gu.user_id = u.user_id)
+			    ON (gu.user_id = u.id)
 			    WHERE gu.usergroup_id= $group_id
 			    ORDER BY relation_type, firstname";
 
         $result=Database::query($sql);
         $array = array();
         while ($row = Database::fetch_array($result, 'ASSOC')) {
-            $array[$row['user_id']] = $row;
+            $array[$row['id']] = $row;
         }
         return $array;
     }

+ 54 - 54
main/inc/lib/usermanager.lib.php

@@ -486,10 +486,10 @@ class UserManager
             return false;
         }
         $sql = "SELECT * FROM $table_course_user
-                WHERE status = '1' AND user_id = '".$user_id."'";
+                WHERE status = '1' AND id = '".$user_id."'";
         $res = Database::query($sql);
         while ($course = Database::fetch_object($res)) {
-            $sql = "SELECT user_id FROM $table_course_user
+            $sql = "SELECT id FROM $table_course_user
                     WHERE status='1' AND c_id ='".Database::escape_string($course->c_id)."'";
             $res2 = Database::query($sql);
             if (Database::num_rows($res2) == 1) {
@@ -593,7 +593,7 @@ class UserManager
         Database::query($sql);
 
         // Delete user from database
-        $sql = "DELETE FROM $table_user WHERE user_id = '".$user_id."'";
+        $sql = "DELETE FROM $table_user WHERE id = '".$user_id."'";
         Database::query($sql);
 
         // Delete user from the admin table
@@ -709,7 +709,7 @@ class UserManager
         $ids = array_map('intval', $ids);
         $ids = implode(',', $ids);
 
-        $sql = "UPDATE $table_user SET active = 0 WHERE user_id IN ($ids)";
+        $sql = "UPDATE $table_user SET active = 0 WHERE id IN ($ids)";
         $r = Database::query($sql);
         if ($r !== false) {
             Event::addEvent(LOG_USER_DISABLE, LOG_USER_ID, $ids);
@@ -739,7 +739,7 @@ class UserManager
         $ids = array_map('intval', $ids);
         $ids = implode(',', $ids);
 
-        $sql = "UPDATE $table_user SET active = 1 WHERE user_id IN ($ids)";
+        $sql = "UPDATE $table_user SET active = 1 WHERE id IN ($ids)";
         $r = Database::query($sql);
         if ($r !== false) {
             Event::addEvent(LOG_USER_ENABLE,LOG_USER_ID,$ids);
@@ -764,7 +764,7 @@ class UserManager
             return false;
         $sql = "UPDATE $table_user SET
                 openid='".Database::escape_string($openid)."'";
-        $sql .= " WHERE user_id='$user_id'";
+        $sql .= " WHERE id= $user_id";
         return Database::query($sql);
     }
 
@@ -963,7 +963,7 @@ class UserManager
         }
         $user_id = intval($user_id);
         $table_user = Database :: get_main_table(TABLE_MAIN_USER);
-        $sql = "UPDATE $table_user SET active = '$active' WHERE user_id = '$user_id';";
+        $sql = "UPDATE $table_user SET active = '$active' WHERE id = $user_id";
         $r = Database::query($sql);
         $ev = LOG_USER_DISABLE;
         if ($active == 1) {
@@ -1231,7 +1231,7 @@ class UserManager
         $ids = implode(',', $ids);
 
         $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
-        $sql = "SELECT * FROM $tbl_user WHERE user_id IN ($ids)";
+        $sql = "SELECT * FROM $tbl_user WHERE id IN ($ids)";
         if (!is_null($active)) {
             $sql .= ' AND active='.($active ? '1' : '0');
         }
@@ -1371,7 +1371,7 @@ class UserManager
         if (empty($userInfo)) {
             $user_table = Database:: get_main_table(TABLE_MAIN_USER);
             $sql = "SELECT email, picture_uri FROM $user_table
-                    WHERE user_id=".$id;
+                    WHERE id=".$id;
             $res = Database::query($sql);
 
             if (!Database::num_rows($res)) {
@@ -2582,7 +2582,7 @@ class UserManager
                         INNER JOIN $tbl_session as session
                             ON session.id = session_course_user.session_id
                         LEFT JOIN $tbl_user as user
-                            ON user.user_id = session_course_user.user_id OR session.id_coach = user.user_id
+                            ON user.id = session_course_user.user_id OR session.id_coach = user.id
                     WHERE
                         session_course_user.session_id = $id_session AND (
                             (session_course_user.user_id = $user_id AND session_course_user.status = 2)
@@ -2624,7 +2624,7 @@ class UserManager
                 INNER JOIN $tbl_course AS course
                 ON course.id = session_course_user.c_id AND session_course_user.session_id = $session_id
                 INNER JOIN $tbl_session as session ON session_course_user.session_id = session.id
-                LEFT JOIN $tbl_user as user ON user.user_id = session_course_user.user_id
+                LEFT JOIN $tbl_user as user ON user.id = session_course_user.user_id
             WHERE session_course_user.user_id = $user_id
             ORDER BY i";
 
@@ -2779,7 +2779,7 @@ class UserManager
         $username = trim($username);
         $username = Database::escape_string($username);
         $t_user = Database::get_main_table(TABLE_MAIN_USER);
-        $sql = "SELECT user_id FROM $t_user WHERE username = '$username'";
+        $sql = "SELECT id FROM $t_user WHERE username = '$username'";
         $res = Database::query($sql);
         if ($res === false) {
             return false;
@@ -2788,7 +2788,7 @@ class UserManager
             return false;
         }
         $row = Database::fetch_array($res);
-        return $row['user_id'];
+        return $row['id'];
     }
 
     /**
@@ -3015,7 +3015,7 @@ class UserManager
         }
         if (!empty($access_url_id) && $access_url_id == intval($access_url_id)) {
             $sql .= ", $t_a a ";
-            $sql2 .= " AND a.access_url_id = $access_url_id AND u.user_id = a.user_id ";
+            $sql2 .= " AND a.access_url_id = $access_url_id AND u.id = a.user_id ";
         }
         $sql = $sql.$sql2;
         $res = Database::query($sql);
@@ -3073,12 +3073,12 @@ class UserManager
         $content = api_utf8_decode($content);
         $email_administrator = Database::escape_string($email_administrator);
         //message in inbox
-        $sql_message_outbox = 'SELECT user_id from '.$table_user.' WHERE email="'.$email_administrator.'" ';
+        $sql_message_outbox = 'SELECT id from '.$table_user.' WHERE email="'.$email_administrator.'" ';
         //$num_row_query = Database::num_rows($sql_message_outbox);
         $res_message_outbox = Database::query($sql_message_outbox);
         $array_users_administrator = array();
         while ($row_message_outbox = Database::fetch_array($res_message_outbox, 'ASSOC')) {
-            $array_users_administrator[] = $row_message_outbox['user_id'];
+            $array_users_administrator[] = $row_message_outbox['id'];
         }
         //allow to insert messages in outbox
         for ($i = 0; $i < count($array_users_administrator); $i++) {
@@ -3417,13 +3417,13 @@ class UserManager
                     INNER JOIN $table_admin as admin
                     ON (admin.user_id=url.user_id)
                     INNER JOIN $table_user u
-                    ON (u.user_id=admin.user_id)
+                    ON (u.id=admin.user_id)
                     WHERE access_url_id ='".$access_url_id."'";
         } else {
             $sql = "SELECT admin.user_id, username, firstname, lastname, email, active
                     FROM $table_admin as admin
                     INNER JOIN $table_user u
-                    ON (u.user_id=admin.user_id)";
+                    ON (u.id=admin.user_id)";
         }
         $result = Database::query($sql);
         $return = array();
@@ -3470,17 +3470,17 @@ class UserManager
         // all the information of the field
 
         if ($getCount) {
-            $select = "SELECT count(DISTINCT u.user_id) count";
+            $select = "SELECT count(DISTINCT u.id) count";
         } else {
-            $select = "SELECT DISTINCT u.user_id, u.username, firstname, lastname, email, tag, picture_uri";
+            $select = "SELECT DISTINCT u.id, u.username, firstname, lastname, email, tag, picture_uri";
         }
 
         $sql = " $select
                 FROM $user_table u
                 INNER JOIN $access_url_rel_user_table url_rel_user
-                ON (u.user_id = url_rel_user.user_id)
+                ON (u.id = url_rel_user.user_id)
                 LEFT JOIN $table_user_tag_values uv
-                ON (u.user_id AND uv.user_id AND uv.user_id = url_rel_user.user_id)
+                ON (u.id AND uv.user_id AND uv.user_id = url_rel_user.user_id)
                 LEFT JOIN $table_user_tag ut ON (uv.tag_id = ut.id)
                 WHERE
                     ($where_field tag LIKE '".Database::escape_string($tag."%")."') OR
@@ -3514,8 +3514,8 @@ class UserManager
                 return $row['count'];
             }
             while ($row = Database::fetch_array($result, 'ASSOC')) {
-                if (isset($return[$row['user_id']]) &&
-                    !empty($return[$row['user_id']]['tag'])
+                if (isset($return[$row['id']]) &&
+                    !empty($return[$row['id']]['tag'])
                 ) {
                     $url = Display::url(
                         $row['tag'],
@@ -3524,7 +3524,7 @@ class UserManager
                     );
                     $row['tag'] = $url;
                 }
-                $return[$row['user_id']] = $row;
+                $return[$row['id']] = $row;
             }
         }
 
@@ -3595,10 +3595,10 @@ class UserManager
             }
 
             if (is_array($finalResult) && count($finalResult)>0) {
-                $whereFilter = " AND u.user_id IN  ('".implode("','", $finalResult)."') ";
+                $whereFilter = " AND u.id IN  ('".implode("','", $finalResult)."') ";
             } else {
                 //no results
-                $whereFilter = " AND u.user_id  = -1 ";
+                $whereFilter = " AND u.id  = -1 ";
             }
 
             return $whereFilter;
@@ -3809,10 +3809,10 @@ class UserManager
             $orderBy .= " ORDER BY lastname, firstname ";
         }
 
-        $sql = "SELECT u.user_id, username, u.firstname, u.lastname
+        $sql = "SELECT u.id, username, u.firstname, u.lastname
                 FROM $tblUser u
-                INNER JOIN $tblUserRelUser uru ON (uru.friend_user_id = u.user_id)
-                INNER JOIN $tblUserRelAccessUrl a ON (a.user_id = u.user_id)
+                INNER JOIN $tblUserRelUser uru ON (uru.friend_user_id = u.id)
+                INNER JOIN $tblUserRelAccessUrl a ON (a.user_id = u.id)
                 WHERE
                     access_url_id = ".api_get_current_access_url_id()." AND
                     uru.user_id = '$userId' AND
@@ -3931,16 +3931,16 @@ class UserManager
             $userConditions .= ' AND u.status = '.intval($userStatus);
         }
 
-        $select = " SELECT DISTINCT u.user_id, u.username, u.lastname, u.firstname, u.email ";
+        $select = " SELECT DISTINCT u.id user_id, u.username, u.lastname, u.firstname, u.email ";
         if ($getOnlyUserId) {
-            $select = " SELECT DISTINCT u.user_id";
+            $select = " SELECT DISTINCT u.id user_id";
         }
 
         $masterSelect = "SELECT DISTINCT * FROM ";
 
         if ($getCount) {
-            $masterSelect = "SELECT COUNT(DISTINCT(user_id)) as count FROM ";
-            $select = " SELECT DISTINCT(u.user_id) ";
+            $masterSelect = "SELECT COUNT(DISTINCT(u.id)) as count FROM ";
+            $select = " SELECT DISTINCT(u.id) user_id";
         }
 
         if (!is_null($active)) {
@@ -3999,7 +3999,7 @@ class UserManager
                 "UNION ALL (
                         $select
                         FROM $tbl_user u
-                        INNER JOIN $tbl_session_rel_user sru ON (sru.user_id = u.user_id)
+                        INNER JOIN $tbl_session_rel_user sru ON (sru.user_id = u.id)
                         WHERE
                             sru.session_id IN (
                                 SELECT DISTINCT(s.id) FROM $tbl_session s INNER JOIN
@@ -4021,7 +4021,7 @@ class UserManager
                     UNION ALL(
                         $select
                         FROM $tbl_user u
-                        INNER JOIN $tbl_course_user cu ON (cu.user_id = u.user_id)
+                        INNER JOIN $tbl_course_user cu ON (cu.user_id = u.id)
                         WHERE cu.c_id IN (
                             SELECT DISTINCT(c_id) FROM $tbl_course_user
                             WHERE user_id = $userId AND status = ".COURSEMANAGER."
@@ -4042,8 +4042,8 @@ class UserManager
                     (
                         $select
                         FROM $tbl_user u
-                        INNER JOIN $tbl_user_rel_user uru ON (uru.user_id = u.user_id)
-                        LEFT JOIN $tbl_user_rel_access_url a ON (a.user_id = u.user_id)
+                        INNER JOIN $tbl_user_rel_user uru ON (uru.user_id = u.id)
+                        LEFT JOIN $tbl_user_rel_access_url a ON (a.user_id = u.id)
                         $join
                         WHERE
                             access_url_id = ".api_get_current_access_url_id()."
@@ -4174,8 +4174,8 @@ class UserManager
 
         $sql = "SELECT user_id FROM $tbl_user_rel_user
                 WHERE
-                    user_id='$user_id' AND
-                    friend_user_id='$hr_dept_id' AND
+                    user_id = $user_id AND
+                    friend_user_id = $hr_dept_id AND
                     relation_type = ".USER_RELATION_TYPE_RRHH;
         $rs = Database::query($sql);
         if (Database::num_rows($rs) > 0) {
@@ -4200,9 +4200,9 @@ class UserManager
         $courseCode = $courseInfo['code'];
 
         if ($session == 0 || is_null($session)) {
-            $sql = 'SELECT u.user_id FROM '.$table_user.' u
+            $sql = 'SELECT u.id uid FROM '.$table_user.' u
                     INNER JOIN '.$table_course_user.' ru
-                    ON ru.user_id=u.user_id
+                    ON ru.user_id = u.id
                     WHERE
                         ru.status = 1 AND
                         ru.c_id = "'.$courseId.'" ';
@@ -4210,23 +4210,23 @@ class UserManager
             $num_rows = Database::num_rows($rs);
             if ($num_rows == 1) {
                 $row = Database::fetch_array($rs);
-                return $row['user_id'];
+                return $row['uid'];
             } else {
                 $my_num_rows = $num_rows;
-                $my_user_id = Database::result($rs, $my_num_rows - 1, 'user_id');
+                $my_user_id = Database::result($rs, $my_num_rows - 1, 'uid');
                 return $my_user_id;
             }
         } elseif ($session > 0) {
-            $sql = 'SELECT u.user_id FROM '.$table_user.' u
+            $sql = 'SELECT u.id uid FROM '.$table_user.' u
                     INNER JOIN '.$table_session_course_user.' sru
-                    ON sru.user_id=u.user_id
+                    ON sru.user_id=u.id
                     WHERE
                         sru.c_id="'.$courseId.'" AND
                         sru.status=2';
             $rs = Database::query($sql);
             $row = Database::fetch_array($rs);
 
-            return $row['user_id'];
+            return $row['uid'];
         }
     }
 
@@ -4315,7 +4315,7 @@ class UserManager
         }
         $sql = "SELECT tc.path_certificate,tc.cat_id,tgc.course_code,tgc.name
                 FROM $table_certificate tc, $table_gradebook_category tgc
-                WHERE tgc.id = tc.cat_id AND tc.user_id='$user_id'
+                WHERE tgc.id = tc.cat_id AND tc.user_id = $user_id
                 ORDER BY tc.date_certificate DESC limit 5";
 
         $rs = Database::query($sql);
@@ -4344,8 +4344,8 @@ class UserManager
 
         $sql = "SELECT session_id FROM $tbl_session_course_rel_user
                 WHERE
-                  session_id=$session_id AND
-                  c_id='$courseId' AND
+                  session_id = $session_id AND
+                  c_id = $courseId AND
                   user_id = $user_id AND
                   status = 2 ";
         $res = Database::query($sql);
@@ -4751,7 +4751,7 @@ EOF;
         $user_id = intval($user_id);
 
         if (!self::is_admin($user_id)) {
-            $sql = "INSERT INTO $table_admin SET user_id = '".$user_id."'";
+            $sql = "INSERT INTO $table_admin SET user_id = $user_id";
             Database::query($sql);
         }
     }
@@ -4764,7 +4764,7 @@ EOF;
         $table_admin = Database :: get_main_table(TABLE_MAIN_ADMIN);
         $user_id = intval($user_id);
         if (self::is_admin($user_id)) {
-            $sql = "DELETE FROM $table_admin WHERE user_id = '".$user_id."'";
+            $sql = "DELETE FROM $table_admin WHERE user_id = user_id";
             Database::query($sql);
         }
     }
@@ -4881,7 +4881,7 @@ EOF;
         $user = Database::get_main_table(TABLE_MAIN_USER);
         $officialCode = Database::escape_string($officialCode);
 
-        $sql = "SELECT DISTINCT user_id
+        $sql = "SELECT DISTINCT id
                 FROM $user
                 WHERE official_code = '$officialCode'
                 ";
@@ -4889,7 +4889,7 @@ EOF;
 
         $users = array();
         while ($row = Database::fetch_array($result)) {
-            $users[] = $row['user_id'];
+            $users[] = $row['id'];
         }
         return $users;
     }

+ 80 - 66
main/install/install.lib.php

@@ -766,8 +766,8 @@ function display_requirements(
                 <td class="requirements-item"><a href="http://xapian.org/" target="_blank">Xapian</a> '.get_lang('support').' ('.get_lang('Optional').')</td>
                 <td class="requirements-value">'.checkExtension('xapian', get_lang('Yes'), get_lang('No'), true).'</td>
             </tr>
-          </table>';
-    echo '  </div>';
+        </table>';
+    echo '</div>';
     echo '</div>';
 
     // RECOMMENDED SETTINGS
@@ -2231,67 +2231,67 @@ function fixIds(EntityManager $em)
 
         foreach ($result as $item) {
             //$courseId = $item['c_id'];
-        $sessionId = intval($item['session_id']);
-        $groupId = intval($item['to_group_id']);
-        $iid = $item['iid'];
-        $ref = $item['ref'];
-        // Fix group id
-
-        if (!empty($groupId)) {
-            $sql = "SELECT * FROM c_group_info
-                    WHERE c_id = $courseId AND id = $groupId";
-            $data = $connection->fetchAssoc($sql);
-            if (!empty($data)) {
-                $newGroupId = $data['iid'];
-                $sql = "UPDATE c_item_property SET to_group_id = $newGroupId
-                        WHERE iid = $iid";
-                $connection->executeQuery($sql);
-            } else {
-                // The group does not exists clean this record
-                $sql = "DELETE FROM c_item_property WHERE iid = $iid";
-                $connection->executeQuery($sql);
+            $sessionId = intval($item['session_id']);
+            $groupId = intval($item['to_group_id']);
+            $iid = $item['iid'];
+            $ref = $item['ref'];
+
+            // Fix group id
+            if (!empty($groupId)) {
+                $sql = "SELECT * FROM c_group_info
+                        WHERE c_id = $courseId AND id = $groupId";
+                $data = $connection->fetchAssoc($sql);
+                if (!empty($data)) {
+                    $newGroupId = $data['iid'];
+                    $sql = "UPDATE c_item_property SET to_group_id = $newGroupId
+                            WHERE iid = $iid";
+                    $connection->executeQuery($sql);
+                } else {
+                    // The group does not exists clean this record
+                    $sql = "DELETE FROM c_item_property WHERE iid = $iid";
+                    $connection->executeQuery($sql);
+                }
             }
-        }
 
-        $sql = '';
-        $newId = '';
-        switch ($item['tool']) {
-            case TOOL_LINK:
-                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
-                break;
-            case TOOL_STUDENTPUBLICATION:
-                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
-                break;
-            case TOOL_QUIZ:
-                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
-                break;
-            case TOOL_DOCUMENT:
-                $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
-                break;
-            case TOOL_FORUM:
-                $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND id = $ref";
-                break;
-            case 'thread':
-                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND id = $ref";
-                break;
-        }
+            $sql = '';
+            $newId = '';
+            switch ($item['tool']) {
+                case TOOL_LINK:
+                    $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
+                    break;
+                case TOOL_STUDENTPUBLICATION:
+                    $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
+                    break;
+                case TOOL_QUIZ:
+                    $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
+                    break;
+                case TOOL_DOCUMENT:
+                    $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
+                    break;
+                case TOOL_FORUM:
+                    $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND id = $ref";
+                    break;
+                case 'thread':
+                    $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND id = $ref";
+                    break;
+            }
 
-        if (!empty($sql) && !empty($newId)) {
-            $data = $connection->fetchAssoc($sql);
-            if (isset($data['iid'])) {
-                $newId = $data['iid'];
+            if (!empty($sql) && !empty($newId)) {
+                $data = $connection->fetchAssoc($sql);
+                if (isset($data['iid'])) {
+                    $newId = $data['iid'];
+                }
+                $sql = "UPDATE c_item_property SET ref = $newId WHERE iid = $iid";
+                error_log($sql);
+                $connection->executeQuery($sql);
             }
-            $sql = "UPDATE c_item_property SET ref = $newId WHERE iid = $iid";
-            error_log($sql);
-            $connection->executeQuery($sql);
-        }
 
             if ($debug) {
                 // Print a status in the log once in a while
-        error_log("Process item #$counter");
+                error_log("Process item #$counter/$totalCourse");
             }
-        $counter++;
-    }
+            $counter++;
+        }
     }
 
     if ($debug) {
@@ -2352,7 +2352,7 @@ function fixIds(EntityManager $em)
 
     $oldGroups = array();
 
-    if (!empty($groups )) {
+    if (!empty($groups)) {
         foreach ($groups as $group) {
             if (empty($group['name'])) {
                 continue;
@@ -2374,7 +2374,7 @@ function fixIds(EntityManager $em)
                 'created_at' => $group['created_on']
             ];
             $connection->insert('usergroup', $params);
-
+            //$connection->executeQuery($sql);
             $id = $connection->lastInsertId('id');
             $oldGroups[$group['id']] = $id;
         }
@@ -2541,7 +2541,6 @@ function fixIds(EntityManager $em)
             }
 
             if (!empty($optionTable)) {
-
                 $sql = "SELECT * FROM $optionTable WHERE field_id = $originalId ";
                 $result = $connection->query($sql);
                 $options = $result->fetchAll();
@@ -2569,19 +2568,34 @@ function fixIds(EntityManager $em)
                 if ($debug) {
                     error_log("Saving field value in new table");
                 }
+                $k = 0;
                 foreach ($values as $value) {
                     if (isset($value[$handlerId])) {
-                    $extraFieldValue = new ExtraFieldValues();
-                    $extraFieldValue
-                        ->setValue($value['field_value'])
-                        ->setField($extraField)
-                        ->setItemId($value[$handlerId]);
-                    $em->persist($extraFieldValue);
-                    $em->flush();
+                        /*
+                        $extraFieldValue = new ExtraFieldValues();
+                        $extraFieldValue
+                            ->setValue($value['field_value'])
+                            ->setField($extraField)
+                            ->setItemId($value[$handlerId]);
+                        $em->persist($extraFieldValue);
+                        $em->flush();
+                        */
+                        // Insert without the use of the entity as it reduces
+                        // speed to 2 records per second (much too slow)
+                        $params = [
+                            'field_id' => $extraField->getId(),
+                            'value' => $value['field_value'],
+                            'item_id' => $value[$handlerId]
+                        ];
+                        $connection->insert('extra_field_values', $params);
+                        if ($debug && ($k % 10000 == 0)) {
+                            error_log("Saving field $k");
+                    }
+                        $k++;
+                    }
                 }
             }
         }
-        }
     }
 
     if ($debug) {

+ 1 - 1
main/install/update-files-1.9.0-1.10.0.inc.php

@@ -186,7 +186,7 @@ if (defined('SYSTEM_INSTALLATION')) {
 
     foreach ($movePathList as $origin => $destination) {
         if (is_dir($origin)) {
-            move($origin, $destination);
+            move($origin, $destination, true);
             error_log("$origin to $destination");
         }
     }

+ 73 - 70
main/lang/english/trad4all.inc.php

@@ -325,18 +325,18 @@ $DeleteUsersNotInList = "Unsubscribe students which are not in the imported list
 $IfSessionExistsUpdate = "If a session exists, update it";
 $CreatedByXYOnZ = "Create by <a href=\"%s\">%s</a> on %s";
 $LoginWithExternalAccount = "Login without an institutional account";
-$ImportAikenQuizExplanationExample = "This is the text for question 1
-A. Answer 1
-B. Answer 2
-C. Answer 3
-ANSWER: B
-
-This is the text for question 2
-A. Answer 1
-B. Answer 2
-C. Answer 3
-D. Answer 4
-ANSWER: D
+$ImportAikenQuizExplanationExample = "This is the text for question 1
+A. Answer 1
+B. Answer 2
+C. Answer 3
+ANSWER: B
+
+This is the text for question 2
+A. Answer 1
+B. Answer 2
+C. Answer 3
+D. Answer 4
+ANSWER: D
 ANSWER_EXPLANATION: this is an optional feedback comment that will appear next to the correct answer.";
 $ImportAikenQuizExplanation = "The Aiken format comes in a simple text (.txt) file, with several question blocks, each separated by a blank line. The first line is the question, the answer lines are prefixed by a letter and a dot, and the correct answer comes next with the ANSWER: prefix. See example below.";
 $ExerciseAikenErrorNoAnswerOptionGiven = "The imported file has at least one question without any answer (or the answers do not include the required prefix letter). Please make sure each question has at least one answer and that it is prefixed by a letter and a dot or a parenthesis, like this: A. answer one";
@@ -425,18 +425,18 @@ $VersionUpToDate = "Your version is up-to-date";
 $LatestVersionIs = "The latest version is";
 $YourVersionNotUpToDate = "Your version is not up-to-date";
 $Hotpotatoes = "Hotpotatoes";
-$ZeroMeansNoQuestionWillBeSelectedMinusOneMeansThatAllQuestionsWillBeSelected = "-1 = All questions will be selected.
+$ZeroMeansNoQuestionWillBeSelectedMinusOneMeansThatAllQuestionsWillBeSelected = "-1 = All questions will be selected.
  0 = No questions will be selected.";
-$EmailNotificationTemplateDescription = "You can customize the email sent to users when they finished the exercise. You can use tags like these:
-
-1. {{ student.username }}
-2. {{ student.firstname }}
-3. {{ student.lastname }}
-4. {{ student.official_code }}
-5. {{ exercise.title }}
-6. {{ exercise.start_time }}
-7. {{ exercise.end_time }}
-8. {{ course.title }}
+$EmailNotificationTemplateDescription = "You can customize the email sent to users when they finished the exercise. You can use tags like these:
+
+1. {{ student.username }}
+2. {{ student.firstname }}
+3. {{ student.lastname }}
+4. {{ student.official_code }}
+5. {{ exercise.title }}
+6. {{ exercise.start_time }}
+7. {{ exercise.end_time }}
+8. {{ course.title }}
 9. {{ course.code }}";
 $EmailNotificationTemplate = "Email notification template";
 $ExerciseEndButtonDisconnect = "Logout";
@@ -844,10 +844,10 @@ $AllowVisitors = "Allow visitors";
 $EnableIframeInclusionComment = "Allowing arbitrary iframes in the HTML Editor will enhance the edition capabilities of the users, but it can represent a security risk. Please make sure you can rely on your users (i.e. you know who they are) before enabling this feature.";
 $AddedToLPCannotBeAccessed = "This exercise has been included in a learning path, so it cannot be accessed by students directly from here. If you want to put the same exercise available through the exercises tool, please make a copy of the current exercise using the copy icon.";
 $EnableIframeInclusionTitle = "Allow iframes in HTML Editor";
-$MailTemplateRegistrationMessage = "Dear ((firstname)) ((lastname)),\n\nYou are registered on
-((sitename)) with the following settings:\n\nUsername :
-((username))\nPass : ((password))\n\nThe address of ((sitename)) is :
-((url))\n\nIn case of trouble, contact us.\n\nYours sincerely
+$MailTemplateRegistrationMessage = "Dear ((firstname)) ((lastname)),\n\nYou are registered on
+((sitename)) with the following settings:\n\nUsername :
+((username))\nPass : ((password))\n\nThe address of ((sitename)) is :
+((url))\n\nIn case of trouble, contact us.\n\nYours sincerely
 \n((admin_name)) ((admin_surname)).";
 $Explanation = "Once you click on \"Create a course\", a course is created with a section for Tests, Project based learning, Assessments, Courses, Dropbox, Agenda and much more. Logging in as teacher provides you with editing privileges for this course.";
 $CodeTaken = "This training code is already in use.  <br>Use the <b>Back</b> button on your browser and try again";
@@ -1345,7 +1345,7 @@ $DeleteSelectedClasses = "Delete selected classes";
 $DeleteSelectedGroups = "Delete selected groups";
 $Administrator = "Administrator";
 $ChangePicture = "Change picture";
-$myCoursesSessionView = "Session view";
+$XComments = "%s comments";
 $AddUsers = "Add a user";
 $AddGroups = "Add groups";
 $AddClasses = "Add classes";
@@ -2640,16 +2640,16 @@ $NoPosts = "No posts";
 $WithoutAchievedSkills = "Without achieved skills";
 $TypeMessage = "Please type your message!";
 $ConfirmReset = "Do you really want to delete all messages?";
-$MailCronCourseExpirationReminderBody = "Dear %s,
-
-It has come to our attention that you have not completed the course %s although its expiration date had been set on %s, remaining %s days to finish it.
-
-We remind you that you have only the possibility to follow this course once a year, that is why we invite you insistently to complete your course on time.
-
-You can return to the course connecting to the platform through this address: %s
-
-Best Regards,
-
+$MailCronCourseExpirationReminderBody = "Dear %s,
+
+It has come to our attention that you have not completed the course %s although its expiration date had been set on %s, remaining %s days to finish it.
+
+We remind you that you have only the possibility to follow this course once a year, that is why we invite you insistently to complete your course on time.
+
+You can return to the course connecting to the platform through this address: %s
+
+Best Regards,
+
 %s Team";
 $MailCronCourseExpirationReminderSubject = "Urgent: %s course expiration reminder";
 $ExerciseAndLearningPath = "Exercise and learning path";
@@ -5778,8 +5778,8 @@ $CheckThatYouHaveEnoughQuestionsInYourCategories = "Make sure you have enough qu
 $PortalCoursesLimitReached = "Sorry, this installation has a courses limit, which has now been reached. To increase the number of courses allowed on this Chamilo installation, please contact your hosting provider or, if available, upgrade to a superior hosting plan.";
 $PortalTeachersLimitReached = "Sorry, this installation has a teachers limit, which has now been reached. To increase the number of teachers allowed on this Chamilo installation, please contact your hosting provider or, if available, upgrade to a superior hosting plan.";
 $PortalUsersLimitReached = "Sorry, this installation has a users limit, which has now been reached. To increase the number of users allowed on this Chamilo installation, please contact your hosting provider or, if available, upgrade to a superior hosting plan.";
-$GenerateSurveyAccessLinkExplanation = "By copying the link below and pasting it in an e-mail or on a website, you will allow any anonymous person to enter and answer this survey.
-You can test this feature by clicking the link above and answering the survey.
+$GenerateSurveyAccessLinkExplanation = "By copying the link below and pasting it in an e-mail or on a website, you will allow any anonymous person to enter and answer this survey.
+You can test this feature by clicking the link above and answering the survey.
 This is particularly useful if you want to allow anyone on a forum to answer you survey and you don't know their e-mail addresses.";
 $LinkOpenSelf = "Open self";
 $LinkOpenBlank = "Open blank";
@@ -5832,8 +5832,8 @@ $Item = "Item";
 $ConfigureDashboardPlugin = "Configure Dashboard Plugin";
 $EditBlocks = "Edit blocks";
 $Never = "Never";
-$YourAccountIsActiveYouCanLoginAndCheckYourCourses = "Dear user, 
-
+$YourAccountIsActiveYouCanLoginAndCheckYourCourses = "Dear user, 
+
 Your account has now been activated on the platform. Please login and enjoy your courses.";
 $SessionFields = "Session fields";
 $CopyLabelSuffix = "Copy";
@@ -5895,7 +5895,7 @@ $CourseSettingsRegisterDirectLink = "If your course is public or open, you can u
 $DirectLink = "Direct link";
 $here = "here";
 $GoAheadAndBrowseOurCourseCatalogXOnceRegisteredYouWillSeeTheCourseHereX = "<p>Go ahead and browse our course catalog %s to register to any course you like. Once registered, you will see the course appear right %s, instead of this message.</p>";
-$HelloXAsYouCanSeeYourCourseListIsEmpty = "<p>Hello <strong>%s</strong> and welcome,</p>
+$HelloXAsYouCanSeeYourCourseListIsEmpty = "<p>Hello <strong>%s</strong> and welcome,</p>
 <p>As you can see, your courses list is still empty. That's because you are not registered to any course yet! </p>";
 $UnsubscribeUsersAlreadyAddedInCourse = "Unsubscribe users already added";
 $ImportUsers = "Import users";
@@ -6159,7 +6159,7 @@ $AverageScore = "Average score";
 $LastConnexionDate = "Last connexion date";
 $ToolVideoconference = "Videoconference";
 $BigBlueButtonEnableTitle = "BigBlueButton videoconference tool";
-$BigBlueButtonEnableComment = "Choose whether you want to enable the BigBlueButton videoconference tool. Once enabled, it will show as an additional course tool in all courses' homepage, and teachers will be able to launch a conference at any time. Learners will not be able to launch a conference, only join one. If you don't have a BigBlueButton server, please <a href=\"http://bigbluebutton.org/\" target=\"_blank\">set one up</a> or ask the <a href=\"http://www.chamilo.org/en/providers\" target=\"_blank\">Chamilo official providers</a> for a quote.
+$BigBlueButtonEnableComment = "Choose whether you want to enable the BigBlueButton videoconference tool. Once enabled, it will show as an additional course tool in all courses' homepage, and teachers will be able to launch a conference at any time. Learners will not be able to launch a conference, only join one. If you don't have a BigBlueButton server, please <a href=\"http://bigbluebutton.org/\" target=\"_blank\">set one up</a> or ask the <a href=\"http://www.chamilo.org/en/providers\" target=\"_blank\">Chamilo official providers</a> for a quote.
 BigBlueButton is a free (as in freedom *and* beer), but its installation requires a set of technical skills that might not be immediately available to all. You can install it on your own or seek professional help to assist you or do it for you. This help, however, will generate a certain cost. In the pure logic of the free software, we offer you the tools to make your work easier and recommend professionals (the Chamilo Official Providers) that will be able to help you if this were too difficult.";
 $BigBlueButtonHostTitle = "BigBlueButton server host";
 $BigBlueButtonHostComment = "This is the name of the server where your BigBlueButton server is running. Might be <i>localhost</i>, an IP address (e.g. 192.168.13.54) or a domain name (e.g. my.video.com).";
@@ -6170,14 +6170,14 @@ $OnlyAccessFromYourGroup = "Only accessible from your group";
 $CreateAssignmentPage = "This will create a special wiki page in which the teacher can describe the task and which will be automatically linked to the wiki pages where learners perform the task. Both the teacher's and the learners' pages are created automatically. In these tasks, learners can only edit and view theirs pages, but this can be changed easily if you need to.";
 $UserFolders = "Folders of users";
 $UserFolder = "User folder";
-$HelpUsersFolder = "INFORMATION VISIBLE TO THE TEACHER ONLY:\nThe users folder contains a folder for each user who has accessed it through the documents tool, or when any file has been sent in the course through the online editor. If neither circumstances has occurred, then no user folder will have been created. In the case of groups, files that are sent through the editor will be added in the folder of each group, which is only accessible by students from this group.
-<br /><br />
-The users folder and each of the included folders will be hidden by default in for all students, but each student can see the contents of his/her directory through the online editor. However, if a student knows the address of a file or folder of another student, he may be able to access it.
-<br /><br />
-If the folder of a student is visible, other students can see what it contains. In this case, the student that owns the folder can also (from the documents tool and only in his/her folder): create and edit web documents, convert a document into a template for personal use, create and edit drawings in SVG and PNG formats, record audio files in WAV format, make audio files in MP3 from a text, make snapshops from a webcam, send documents, create folders, move folders and files, delete folders and files, and download backup of his/her folder.
-<br /><br />
-Moreover, the documents tool is synchronized with the file manager of the online editor, so changes in the documents triggered in any one of these will affect both.
-<br /><br />
+$HelpUsersFolder = "INFORMATION VISIBLE TO THE TEACHER ONLY:\nThe users folder contains a folder for each user who has accessed it through the documents tool, or when any file has been sent in the course through the online editor. If neither circumstances has occurred, then no user folder will have been created. In the case of groups, files that are sent through the editor will be added in the folder of each group, which is only accessible by students from this group.
+<br /><br />
+The users folder and each of the included folders will be hidden by default in for all students, but each student can see the contents of his/her directory through the online editor. However, if a student knows the address of a file or folder of another student, he may be able to access it.
+<br /><br />
+If the folder of a student is visible, other students can see what it contains. In this case, the student that owns the folder can also (from the documents tool and only in his/her folder): create and edit web documents, convert a document into a template for personal use, create and edit drawings in SVG and PNG formats, record audio files in WAV format, make audio files in MP3 from a text, make snapshops from a webcam, send documents, create folders, move folders and files, delete folders and files, and download backup of his/her folder.
+<br /><br />
+Moreover, the documents tool is synchronized with the file manager of the online editor, so changes in the documents triggered in any one of these will affect both.
+<br /><br />
 As such, the user folder is not only a place to deposit files, it becomes a complete manager of the documents students use during the course. Also, remember that any user can copy a file that is visible from any folder in the documents tool (whether or not he is the owner) to his/her portfolios or personal documents area of social network, which will be available to him/her for use in other courses.";
 $HelpFolderChat = "INFORMATION VISIBLE TO THE TEACHER ONLY:\nThis folder contains all sessions that have been opened in the chat. Although the chat sessions can often be trivial, others can be really interesting and worthy of being incorporated as an additional work document. To do this without changing the visibility of this folder, make the file visible and link it from where you deem appropriate. It is not recommended to make this folder visible to all.";
 $HelpFolderCertificates = "INFORMATION VISIBLE TO THE TEACHER ONLY:\nThis folder contains the various certificates templates that have been created for the rating tool. It is not recommended to make this folder visible to all.";
@@ -6226,8 +6226,8 @@ $Pediaphon = "Use Pediaphon audio services";
 $HelpPediaphon = "Supports text with several thousands characters, in various types of male and female voices (depending on the language). Audio files will be generated and automatically saved to the Chamilo directory in which you are.";
 $FirstSelectALanguage = "Please select a language";
 $MoveUserStats = "Move users results from/to a session";
-$CompareUserResultsBetweenCoursesAndCoursesInASession = "This advanced tool allows you to manually improve the tracking of users results when moving from courses methodology to sessions methodology. In most cases, you won't need to use it.<br />
-On this screen, you can compare results of users between the context of a standalone course, and the context of the same course inside a session.<br />
+$CompareUserResultsBetweenCoursesAndCoursesInASession = "This advanced tool allows you to manually improve the tracking of users results when moving from courses methodology to sessions methodology. In most cases, you won't need to use it.<br />
+On this screen, you can compare results of users between the context of a standalone course, and the context of the same course inside a session.<br />
 Once you are sure about what to do, you can choose to move the tracking data of the students (exercises results and learning paths tracking) from a course to a session.";
 $PDFExportWatermarkEnableTitle = "Enable watermark in PDF export";
 $PDFExportWatermarkEnableComment = "By enabling this option, you can upload an image or a text that will be automatically added as watermark to all PDF exports of documents on the system.";
@@ -6362,8 +6362,8 @@ $MailNotifyInvitation = "Notify by mail on new invitation received";
 $MailNotifyMessage = "Notify by mail on new personal message received";
 $MailNotifyGroupMessage = "Notify by mail on new message received in group";
 $SearchEnabledTitle = "Fulltext search";
-$SearchEnabledComment = "This feature allows you to index most of the documents uploaded to your portal, then provide a search feature for users.<br />
-This feature will not index documents that have already been uploaded, so it is important to enable (if wanted) at the beginning of your implementation.<br />
+$SearchEnabledComment = "This feature allows you to index most of the documents uploaded to your portal, then provide a search feature for users.<br />
+This feature will not index documents that have already been uploaded, so it is important to enable (if wanted) at the beginning of your implementation.<br />
 Once enabled, a search box will appear in the courses list of every user. Searching for a specific term will bring a list of corresponding documents, exercises or forum topics, filtered depending on the availability of these contents to the user.";
 $SpecificSearchFieldsAvailable = "Available custom search fields";
 $XapianModuleInstalled = "Xapian module installed";
@@ -7439,12 +7439,12 @@ $AreYouSureToSubscribe = "Are you sure to subscribe?";
 $CheckYourEmailAndFollowInstructions = "Check your email and follow the instructions.";
 $LinkExpired = "Link expired, please try again.";
 $ResetPasswordInstructions = "Instructions for the password change procedure";
-$ResetPasswordCommentWithUrl = "You are receiving this message because you (or someone pretending to be you) have requested a new password to be generated for you.
-
-To set a the new password you need to activate it. To do this, please click this link:
-
-%s
-
+$ResetPasswordCommentWithUrl = "You are receiving this message because you (or someone pretending to be you) have requested a new password to be generated for you.
+
+To set a the new password you need to activate it. To do this, please click this link:
+
+%s
+
 If you did not request this procedure, then please ignore this message. If you keep receiving it, please contact the portal administrator.";
 $CronRemindCourseExpirationActivateTitle = "Remind Course Expiration cron";
 $CronRemindCourseExpirationActivateComment = "Enable the Remind Course Expiration cron";
@@ -7453,14 +7453,14 @@ $CronRemindCourseExpirationFrequencyComment = "Number of days before the expirat
 $CronCourseFinishedActivateText = "Course Finished cron";
 $CronCourseFinishedActivateComment = "Activate the Course Finished cron";
 $MailCronCourseFinishedSubject = "End of course %s";
-$MailCronCourseFinishedBody = "Dear %s,
-
-Thank you for your participation to course %s. We hope you've acquired new relevant knowledge and enjoyed the course.
-
-You can check your performance in the course through the My Progress section.
-
-Best regards,
-
+$MailCronCourseFinishedBody = "Dear %s,
+
+Thank you for your participation to course %s. We hope you've acquired new relevant knowledge and enjoyed the course.
+
+You can check your performance in the course through the My Progress section.
+
+Best regards,
+
 %s Team";
 $GenerateDefaultContent = "Generate default content";
 $ThanksForYourSubscription = "Thanks for your subscription";
@@ -7574,4 +7574,7 @@ $SkillXAssignedToUserY = "The skill %s has been assigned to user %s";
 $AssignSkill = "Assign skill";
 $AddressField = "Address";
 $Geolocalization = "Geolocalization";
+$RateTheSkillInPractice = "On a grade of 1 to 10, how well did you observe that this person could put this skill in practice?";
+$AverageRatingX = "Average rating %s";
+$AverageRating = "Average rating";
 ?>

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 57 - 57
main/lang/spanish/trad4all.inc.php


+ 3 - 3
main/mySpace/myStudents.php

@@ -640,12 +640,12 @@ if (!empty($student_id)) {
             if (empty($sessionId)) {
                 $title = Display::return_icon('course.png', get_lang('Courses'), array(), ICON_SIZE_SMALL).' '.get_lang('Courses');
             } else {
-                //$title = Display::return_icon('session.png', get_lang('Session'), array(), ICON_SIZE_SMALL).' '.$session_name.($date_session?' ('.$date_session.')':'');
+                $title = Display::return_icon('session.png', get_lang('Session'), array(), ICON_SIZE_SMALL).' '.$session_name.($date_session?' ('.$date_session.')':'');
             }
 
             // Courses
             echo '<h3>'.$title.'</h3>';
-            echo '<table class="data_table">';
+            echo '<table class="data_table courses-tracking">';
             echo '<tr>
 				<th>'.get_lang('Course').'</th>
 				<th>'.get_lang('Time').'</th>
@@ -712,7 +712,7 @@ if (!empty($student_id)) {
                         );
 
                         echo '<tr>
-                        <td >'.$course_info['title'].'</td>
+                        <td ><a href="' . api_get_path(WEB_COURSE_PATH) . $course_info['directory'] .'/?id_session=' . $sessionId . '">'.$course_info['title'].'</a></td>
                         <td >'.$time_spent_on_course .'</td>
                         <td >'.$progress.'</td>
                         <td >'.$score.'</td>

+ 10 - 1
main/mySpace/student.php

@@ -164,7 +164,16 @@ function get_users($from, $limit, $column, $direction)
             $detailsLink =  '<a href="myStudents.php?student='.$student_id.'">
 				             <img src="'.api_get_path(WEB_IMG_PATH).'2rightarrow.gif" border="0" /></a>';
         }
-        $row[] = $detailsLink;
+
+        $lostPasswordLink = '';
+        if (api_is_drh() || api_is_platform_admin()) {
+            $lostPasswordLink = '&nbsp;'.Display::url(
+                    Display::return_icon('edit.png', get_lang('Edit')),
+                    api_get_path(WEB_CODE_PATH).'mySpace/user_edit.php?user_id='.$student_id
+                );
+        }
+
+        $row[] = $lostPasswordLink.$detailsLink;
         $all_datas[] = $row;
     }
     return $all_datas;

+ 218 - 0
main/mySpace/user_edit.php

@@ -0,0 +1,218 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+// including necessary libraries
+$language_file = array('admin', 'registration');
+$cidReset = true;
+require_once '../inc/global.inc.php';
+$libpath = api_get_path(LIBRARY_PATH);
+require_once $libpath.'fileManage.lib.php';
+require_once $libpath.'fileUpload.lib.php';
+
+// user permissions
+api_block_anonymous_users();
+
+if (!api_is_platform_admin()) {
+    if (!api_is_drh()) {
+        api_not_allowed(true);
+    }
+} else {
+    api_protect_admin_script();
+}
+
+// Database table definitions
+$table_admin = Database:: get_main_table(TABLE_MAIN_ADMIN);
+$table_user = Database:: get_main_table(TABLE_MAIN_USER);
+$database = Database::get_main_database();
+
+$userId = isset($_REQUEST['user_id']) ? intval($_REQUEST['user_id']) : '';
+
+$userInfo = api_get_user_info($userId);
+if (empty($userInfo)) {
+    api_not_allowed(true);
+}
+
+$userIsFollowed = UserManager::is_user_followed_by_drh($userId, api_get_user_id());
+
+if (api_drh_can_access_all_session_content()) {
+    $students = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus(
+        'drh_all',
+        api_get_user_id(),
+        false,
+        0, //$from,
+        null, //$limit,
+        null, //$column,
+        'desc', //$direction,
+        null, //$keyword,
+        null, //$active,
+        null, //$lastConnectionDate,
+        null,
+        null,
+        STUDENT
+    );
+
+    if (empty($students)) {
+        api_not_allowed(true);
+    }
+    $userIdList = array();
+    foreach ($students as $student) {
+        $userIdList[] = $student['user_id'];
+    }
+
+    if (!in_array($userId, $userIdList)) {
+        api_not_allowed(true);
+    }
+} else {
+    if (!$userIsFollowed) {
+        api_not_allowed(true);
+    }
+}
+
+$url = api_get_self().'?user_id='.$userId;
+$tool_name = get_lang('ModifyUserInfo');
+// Create the form
+$form = new FormValidator('user_edit', 'post', $url);
+// Username
+$usernameInput = $form->addElement('text', 'username', get_lang('LoginName'));
+$usernameInput->freeze();
+
+// Password
+$group = array();
+$auth_sources = 0; //make available wider as we need it in case of form reset (see below)
+/*if (count($extAuthSource) > 0) {
+	$group[] =& $form->createElement('radio', 'password_auto', null, get_lang('ExternalAuthentication').' ', 2);
+	$auth_sources = array();
+	foreach ($extAuthSource as $key => $info) {
+		$auth_sources[$key] = $key;
+	}
+	$group[] =& $form->createElement('select', 'auth_source', null, $auth_sources);
+	$group[] =& $form->createElement('static', '', '', '<br />');
+}*/
+$group[] =& $form->createElement('radio', 'password_auto', get_lang('Password'), get_lang('AutoGeneratePassword').'<br />', 1);
+$group[] =& $form->createElement('radio', 'password_auto', 'id="radio_user_password"', null, 0);
+$group[] =& $form->createElement('password', 'password', null, array('onkeydown' => 'javascript: password_switch_radio_button(document.user_add,"password[password_auto]");'));
+$form->addGroup($group, 'password', get_lang('Password'), '');
+
+// Send email
+$group = array();
+$group[] =& $form->createElement('radio', 'send_mail', null, get_lang('Yes'), 1);
+$group[] =& $form->createElement('radio', 'send_mail', null, get_lang('No'), 0);
+$form->addGroup($group, 'mail', get_lang('SendMailToNewUser'), '&nbsp;');
+
+// Set default values
+$defaults = array();
+$defaults['username'] = $userInfo['username'];
+$defaults['mail']['send_mail'] = 0;
+$defaults['password']['password_auto'] = 1;
+
+$form->setDefaults($defaults);
+// Submit button
+$select_level = array ();
+$html_results_enabled[] = $form->addButtonUpdate(get_lang('Update'), 'submit', true);
+$form->addGroup($html_results_enabled);
+// Validate form
+if ($form->validate()) {
+	$check = Security::check_token('post');
+	if ($check) {
+		$user = $form->exportValues();
+		$email = $userInfo['email'];
+        $username = $userInfo['username'];
+		$send_mail = intval($user['mail']['send_mail']);
+        $auth_source = PLATFORM_AUTH_SOURCE;
+
+        $resetPassword = $user['password']['password_auto'] == '1' ? 0 : 2;
+
+		if (count($extAuthSource) > 0 && $user['password']['password_auto'] == '2') {
+			//$auth_source = $user['password']['auth_source'];
+			//$password = 'PLACEHOLDER';
+		} else {
+			//$auth_source = PLATFORM_AUTH_SOURCE;
+			//$password = $user['password']['password_auto'] == '1' ? api_generate_password() : $user['password']['password'];
+		}
+
+        $auth_source = $userInfo['auth_source'];
+        $password = $user['password']['password_auto'] == '1' ? api_generate_password() : $user['password']['password'];
+
+        UserManager::update_user(
+            $userId,
+            $userInfo['firstname'],
+            $userInfo['lastname'],
+            $userInfo['username'],
+            $password,
+            $auth_source,
+            $userInfo['email'],
+            $userInfo['status'],
+            $userInfo['official_code'],
+            $userInfo['phone'],
+            $userInfo['picture_uri'],
+            $userInfo['expiration_date'],
+            $userInfo['active'],
+            $userInfo['creator_id'],
+            $userInfo['hr_dept_id'],
+            null, //$extra =
+            $userInfo['language'],
+            null, //$encrypt_method
+            false,
+            $resetPassword
+        );
+
+		if (!empty($email) && $send_mail) {
+			$emailsubject = '['.api_get_setting('siteName').'] '.get_lang('YourReg').' '.api_get_setting('siteName');
+			$portal_url = api_get_path(WEB_PATH);
+			if (api_is_multiple_url_enabled()) {
+				$access_url_id = api_get_current_access_url_id();
+				if ($access_url_id != -1) {
+					$url = api_get_access_url($access_url_id);
+					$portal_url = $url['url'];
+				}
+			}
+
+			$emailbody = get_lang('Dear')." ".stripslashes(api_get_person_name($userInfo['firstname'], $userInfo['lastname'])).",\n\n".
+                get_lang('YouAreReg')." ". api_get_setting('siteName') ." ".get_lang('WithTheFollowingSettings')."\n\n".
+                get_lang('Username')." : ". $username ."\n". get_lang('Pass')." : ".stripslashes($password)."\n\n" .
+                get_lang('Address') ." ". api_get_setting('siteName') ." ".
+                get_lang('Is') ." : ".$portal_url."\n\n".
+                get_lang('Problem'). "\n\n".
+                get_lang('SignatureFormula').",\n\n".
+                api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n".
+                get_lang('Manager'). " ".
+                api_get_setting('siteName')."\nT. ".
+                api_get_setting('administratorTelephone')."\n" .
+                get_lang('Email') ." : ".api_get_setting('emailAdministrator');
+
+			api_mail_html(
+                api_get_person_name($userInfo['firstname'], $userInfo['lastname'], null, PERSON_NAME_EMAIL_ADDRESS),
+                $email,
+                $emailsubject,
+                $emailbody
+            );
+		}
+
+		Security::clear_token();
+        $tok = Security::get_token();
+        header('Location: '.$url.'&message=1');
+        exit();
+	}
+} else {
+	if (isset($_POST['submit'])) {
+		Security::clear_token();
+	}
+	$token = Security::get_token();
+	$form->addElement('hidden', 'sec_token');
+	$form->setConstants(array('sec_token' => $token));
+}
+
+$interbreadcrumb[] = array(
+    'url' => api_get_path(WEB_CODE_PATH)."mySpace/student.php",
+    "name" => get_lang('UserList'),
+);
+
+// Display form
+Display::display_header($tool_name);
+
+if (isset($_REQUEST['message'])) {
+	Display::display_normal_message(get_lang('Updated'));
+}
+$form->display();
+
+Display::display_footer();

+ 2 - 2
main/social/group_view.php

@@ -255,11 +255,11 @@ if ($is_group_member || $group_info['visibility'] == GROUP_PERMISSION_OPEN) {
                     $icon= '';
                 }
 
-                $userPicture = UserManager::getUserPicture($member['user_id']);
+                $userPicture = UserManager::getUserPicture($member['id']);
 
                 $member_content .= '<div class="">';
                 $member_name = Display::url(api_get_person_name(cut($member['firstname'],15),cut($member['lastname'],15)).'&nbsp;'.$icon, $member['user_info']['profile_url']);
-                $member_content .= Display::div('<img class="social-groups-image" src="'.$userPicture.'"/>&nbsp'.$member_name);
+                $member_content .= Display::div('<img class="social-groups-image img-circle" src="'.$userPicture.'"/>&nbsp'.$member_name);
                 $member_content .= '</div>';
             }
         }

+ 6 - 1
main/social/profile.php

@@ -399,6 +399,9 @@ if ($show_full_profile) {
                         break;
                     case ExtraField::FIELD_TYPE_SOCIAL_PROFILE:
                         $icon_path = UserManager::get_favicon_from_url($data);
+                        if (SocialManager::verifyUrl($icon_path) == false) {
+                            break;
+                        }
                         $bottom = '0.2';
                         //quick hack for hi5
                         $domain = parse_url($icon_path, PHP_URL_HOST);
@@ -417,8 +420,10 @@ if ($show_full_profile) {
                             $extra_field_title = ucfirst($extraFieldInfo['display_text']);
                             if ($extra_field_title == 'Skype') {
                                 $data = '<a href="skype:' . $data . '?chat">' . get_lang('Chat') . '</a>';
+                                $extra_information_value .= '<li class="list-group-item">'.Display::return_icon('skype.png', $extraFieldInfo['display_text'], null, ICON_SIZE_TINY, false) . ' ' . $data.'</li>';
+                            } else {
+                                $extra_information_value .= '<dt>'.ucfirst($extraFieldInfo['display_text']).':</dt><dd>'.$data.'</dd>';
                             }
-                            $extra_information_value .= '<li class="list-group-item">'.Display::return_icon('skype.png', $extraFieldInfo['display_text'], null, ICON_SIZE_TINY, false) . ' ' . $data.'</li>';
                         }
                     break;
                 }

+ 6 - 6
main/social/search.php

@@ -77,14 +77,14 @@ if ($query != '' || ($query_vars['search_type']=='1' && count($query_vars)>2) )
         $results .= '<div class="row">';
         $buttonClass = 'btn btn-default btn-sm';
         foreach ($users as $user) {
+            $user_info = api_get_user_info($user['id'], true);
             $send_inv = '<button class="'.$buttonClass.' disabled "><em class="fa fa-user"></em> '.get_lang('SendInvitation').'</button>';
-            $relation_type = intval(SocialManager::get_relation_between_contacts(api_get_user_id(), $user['user_id']));
-            $user_info = api_get_user_info($user['user_id'], true);
-            $url = api_get_path(WEB_PATH).'main/social/profile.php?u='.$user['user_id'];
+            $relation_type = intval(SocialManager::get_relation_between_contacts(api_get_user_id(), $user_info['user_id']));
+            $url = api_get_path(WEB_PATH).'main/social/profile.php?u='.$user_info['user_id'];
 
             // Show send invitation icon if they are not friends yet
-            if ($relation_type != 3 && $relation_type != 4 && $user['user_id'] != api_get_user_id()) {
-                $send_inv = '<a href="#" class="'.$buttonClass.' btn-to-send-invitation" data-send-to="' . $user['user_id'] . '">
+            if ($relation_type != 3 && $relation_type != 4 && $user_info['user_id'] != api_get_user_id()) {
+                $send_inv = '<a href="#" class="'.$buttonClass.' btn-to-send-invitation" data-send-to="' . $user_info['user_id'] . '">
                              <em class="fa fa-user"></em> '.get_lang('SendInvitation').'</a>';
             }
 
@@ -92,7 +92,7 @@ if ($query != '' || ($query_vars['search_type']=='1' && count($query_vars)>2) )
                 . 'user_manager.ajax.php?'
                 . http_build_query([
                     'a' => 'get_user_popup',
-                    'user_id' => $user['user_id']
+                    'user_id' => $user_info['user_id']
                 ]);
             $send_msg = Display::toolbarButton(
                 get_lang('SendMessage'),

+ 10 - 2
main/survey/fillsurvey.php

@@ -139,8 +139,13 @@ if (Database::num_rows($result) < 1) {
 $survey_invitation = Database::fetch_array($result, 'ASSOC');
 
 // Now we check if the user already filled the survey
-if ( !isset($_POST['finish_survey']) &&
-    ($isAnonymous && isset($_SESSION['surveyuser'])) ||
+if (
+    !isset($_POST['finish_survey']) &&
+    (
+        $isAnonymous &&
+        isset($_SESSION['surveyuser']) &&
+        SurveyUtil::isSurveyAnsweredFlagged($survey_invitation['survey_code'], $survey_invitation['c_id'])
+    ) ||
     ($survey_invitation['answered'] == 1 && !isset($_GET['user_id']))
 ) {
     api_not_allowed(true, get_lang('YouAlreadyFilledThisSurvey'));
@@ -576,6 +581,9 @@ if (isset($_POST['finish_survey'])) {
         $survey_invitation['user'],
         $survey_invitation['survey_code']
     );
+
+    SurveyUtil::flagSurveyAsAnswered($survey_invitation['survey_code'], $survey_invitation['c_id']);
+
     unset($_SESSION['paged_questions']);
     unset($_SESSION['page_questions_sec']);
     Display :: display_footer();

+ 47 - 0
main/survey/survey.lib.php

@@ -4906,4 +4906,51 @@ class SurveyUtil
         }
         return $htmlChart;
     }
+
+    /**
+     * Set a flag to the current survey as answered by the current user
+     * @param string $surveyCode The survey code
+     * @param int $courseId The course ID
+     */
+    public static function flagSurveyAsAnswered($surveyCode, $courseId)
+    {
+        $currenUserId = api_get_user_id();
+        $flag = sprintf("%s-%s-%d", $courseId, $surveyCode, $currenUserId);
+
+        if (!isset($_SESSION['filled_surveys'])) {
+            $_SESSION['filled_surveys'] = array();
+        }
+
+        $_SESSION['filled_surveys'][] = $flag;
+    }
+
+    /**
+     * Check whether a survey was answered by the current user
+     * @param string $surveyCode The survey code
+     * @param int $courseId The course ID
+     * @return boolean
+     */
+    public static function isSurveyAnsweredFlagged($surveyCode, $courseId)
+    {
+        $currenUserId = api_get_user_id();
+        $flagToCheck = sprintf("%s-%s-%d", $courseId, $surveyCode, $currenUserId);
+
+        if (!isset($_SESSION['filled_surveys'])) {
+            return false;
+        }
+
+        if (!is_array($_SESSION['filled_surveys'])) {
+            return false;
+        }
+
+        foreach ($_SESSION['filled_surveys'] as $flag) {
+            if ($flagToCheck != $flag) {
+                continue;
+            }
+
+            return true;
+        }
+
+        return false;
+    }
 }

+ 2 - 2
main/template/default/learnpath/view.tpl

@@ -139,10 +139,10 @@
         var innerHeight = $(window).height();
 
         if (innerHeight <= 640) {
-            $('.scrollbar-light').css('height', innerHeight - heightTop + "px");
+            $('.scrollbar-light').css('height', innerHeight - heightTop - 5 + "px");
             $('#content_id').css('height', innerHeight - heightControl + "px");
         } else {
-            $('.scrollbar-light').css('height', innerHeight - heightBreadcrumb - heightTop + "px");
+            $('.scrollbar-light').css('height', innerHeight - heightBreadcrumb - heightTop - 5 + "px");
             $('#content_id').css('height', innerHeight - heightControl + "px");
         }
         

+ 41 - 1
main/template/default/skill/issued.tpl

@@ -37,14 +37,54 @@
                 {% endif %}
             </li>
         </ul>
-        <hr>
         {% if allow_export %}
+            <hr>
             <p class="text-center">
                 <a href="#" class="btn btn-success" id="badge-export-button">
                     <em class="fa fa-external-link-square fa-fw"></em> {{ 'ExportBadge'|get_lang }}
                 </a>
             </p>
         {% endif %}
+        {% if allow_comment %}
+            <hr>
+            <div class="panel panel-info">
+                <div class="panel-heading">
+                    <em class="fa fa-comment-o fa-fw" aria-hidden="true"></em> {{ 'XComments'|get_lang|format(issue_info.comments|length) }}
+                    /
+                    <em class="fa fa-thumbs-o-up fa-fw" aria-hidden="true"></em> {{ 'AverageRatingX'|get_lang|format(issue_info.feedback_average) }}
+                </div>
+                <div class="panel-body">
+                    {{ comment_form }}
+                    <hr>
+                    {% for comment in issue_info.comments %}
+                        <article class="media">
+                            <div class="media-body">
+                                <h4 class="media-heading">{{ comment.giver_complete_name }}</h4>
+                                <p><small>{{ comment.datetime }}</small></p>
+                                <p>{{ comment.text }}</p>
+                            </div>
+                            <div class="media-right text-right">
+                                <div style="width: 80px;">
+                                    {% if comment.value %}
+                                        <em class="fa fa-certificate fa-fw" aria-label="{{ 'AverageRating' }}"></em>
+                                        <span class="sr-only">{{ 'AverageRating' }}</span> {{ comment.value }}
+                                    {% endif %}
+                                </div>
+                            </div>
+                        </article>
+                    {% else %}
+                        <p>{{ 'WithoutComment'|get_lang }}</p>
+                    {% endfor %}
+                </div>
+            </div>
+        {% else %}
+            <hr>
+            <p class="lead">
+                <em class="fa fa-comment-o fa-fw" aria-hidden="true"></em> {{ 'XComments'|get_lang|format(issue_info.comments|length) }}
+                /
+                <em class="fa fa-thumbs-o-up fa-fw" aria-hidden="true"></em> {{ 'AverageRatingX'|get_lang|format(issue_info.feedback_average) }}
+            </p>
+        {% endif %}
     </div>
 </div>
 {% if allow_export %}

+ 4 - 2
plugin/dashboard/block_daily/block_daily.class.php

@@ -187,7 +187,8 @@ class BlockDaily extends Block
                 $attendance['course_code'] = $course_info['code'];
 
                 if ($attendance['done'] != '0') {
-                    $attendances[] = '<a href="' . api_get_path(WEB_PATH).'main/attendance/index.php?cidReq=' . $attendance['course_code'] . '&action=attendance_sheet_print&attendance_id=' . $attendance['id']. '">' . Display::return_icon('printmgr.gif', get_lang('Print')).'</a>';
+                    $attendances[] = '<a href="' . api_get_path(WEB_PATH).'main/attendance/index.php?' . api_get_cidreq(). '&action=attendance_sheet_print&attendance_id=' . $attendance['id'].'">' .
+                        Display::return_icon('printmgr.gif', get_lang('Print')).'</a>';
                 } else {
                     $attendances[] = get_lang("NotAvailable");
                 }
@@ -237,7 +238,8 @@ class BlockDaily extends Block
                 if (count($eval) > 0) {
                     $i = 0;
                     foreach ($eval as $item) {
-                        $score .= '<a href="' . api_get_path(WEB_PATH).'main/gradebook/gradebook_view_result.php?export=pdf&cat_code=' . $cat[0]->get_id() . '&official_code=' . $cat[0]->get_course_code() . '&selecteval=' . $item->get_id().$param_gradebook . '">' . $item->get_name() . '</a>';
+                        $score .= '<a href="' . api_get_path(WEB_PATH).'main/gradebook/gradebook_view_result.php?export=pdf&cat_code=' . $cat[0]->get_id() . '&official_code=' . $cat[0]->get_course_code() . '&selecteval=' . $item->get_id(). '&'.api_get_cidreq().'">' .
+                            $item->get_name() . '</a>';
                         if (count($eval) - 1 != $i) {
                             $score .= ', ';
                         }

+ 1 - 1
src/Chamilo/CoreBundle/Entity/Legal.php

@@ -52,7 +52,7 @@ class Legal
      *
      * @ORM\Column(name="legal_id", type="integer")
      * @ORM\Id
-     * @ORM\GeneratedValue(strategy="NONE")
+     * @ORM\GeneratedValue(strategy="AUTO")
      */
     private $legalId;
 

+ 4 - 4
src/Chamilo/CoreBundle/Entity/Repository/SkillRepository.php

@@ -30,21 +30,21 @@ class SkillRepository extends EntityRepository{
             'ChamiloCoreBundle:SkillRelUser',
             'su',
             Join::WITH,
-            's.id = su.skill'
+            $qb->expr()->eq('s', 'su.skill')
         )
         ->where(
-            $qb->expr()->eq('su.userId', $user->getId())
+            $qb->expr()->eq('su.user', $user->getId())
         );
 
         if ($course) {
             $qb->andWhere(
-                $qb->expr()->eq('su.courseId', $course->getId())
+                $qb->expr()->eq('su.course', $course->getId())
             );
         }
 
         if ($session) {
             $qb->andWhere(
-                $qb->expr()->eq('su.sessionId', $session->getId())
+                $qb->expr()->eq('su.session', $session->getId())
             );
         }
 

+ 2 - 3
src/Chamilo/CoreBundle/Entity/SettingsCurrent.php

@@ -104,11 +104,10 @@ class SettingsCurrent implements ParameterInterface
     /**
      * @var integer
      *
-     * @ORM\Column(name="access_url_locked", type="integer", nullable=false)
+     * @ORM\Column(name="access_url_locked", type="integer", nullable=false, options={"default": 0 } )
      */
     private $accessUrlLocked;
 
-
     /**
      * Set variable
      *
@@ -382,7 +381,7 @@ class SettingsCurrent implements ParameterInterface
      */
     public function setAccessUrlLocked($accessUrlLocked)
     {
-        $this->accessUrlLocked = $accessUrlLocked;
+        $this->accessUrlLocked = intval($accessUrlLocked);
 
         return $this;
     }

+ 54 - 1
src/Chamilo/CoreBundle/Entity/SkillRelUser.php

@@ -1,5 +1,5 @@
 <?php
-
+/* For licensing terms, see /license.txt */
 namespace Chamilo\CoreBundle\Entity;
 
 use Doctrine\ORM\Mapping as ORM;
@@ -73,6 +73,16 @@ class SkillRelUser
      */
     private $argumentation;
 
+    /**
+     * @ORM\OneToMany(targetEntity="SkillRelUserComment", mappedBy="skillRelUser")
+     */
+    protected $comments;
+
+    public function __construct()
+    {
+        $this->comments = new \Doctrine\Common\Collections\ArrayCollection();
+    }
+
     /**
      * Set user
      * @param \Chamilo\UserBundle\Entity\User $user
@@ -279,4 +289,47 @@ class SkillRelUser
 
         return $url;
     }
+
+    /**
+     * Get comments
+     * @param boolean $sortDescByDateTime
+     * @return ArrayCollection
+     */
+    public function getComments($sortDescByDateTime = false)
+    {
+        if ($sortDescByDateTime) {
+            $criteria = \Doctrine\Common\Collections\Criteria::create();
+            $criteria->orderBy([
+                'feedbackDateTime' => \Doctrine\Common\Collections\Criteria::DESC
+            ]);
+
+            return $this->comments->matching($criteria);
+        }
+
+        return $this->comments;
+    }
+
+    /**
+     * Calculate the average value from the feedback comments
+     * @return type
+     */
+    public function getAverage()
+    {
+        $sum = 0;
+        $average = 0;
+        $countValues = 0;
+
+        foreach ($this->comments as $comment) {
+            if (!$comment->getFeedbackValue()) {
+                continue;
+            }
+
+            $sum += $comment->getFeedbackValue();
+            $countValues++;
+        }
+
+        $average = $countValues > 0 ? $sum / $countValues : 0;
+
+        return number_format($average, 2);
+    }
 }

+ 175 - 0
src/Chamilo/CoreBundle/Entity/SkillRelUserComment.php

@@ -0,0 +1,175 @@
+<?php
+/* For licensing terms, see /license.txt */
+namespace Chamilo\CoreBundle\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * SkillRelUserComment class
+ *
+ * @ORM\Table(
+ *  name="skill_rel_user_comment",
+ *  indexes={
+ *      @ORM\Index(name="idx_select_su_giver", columns={"skill_rel_user_id", "feedback_giver_id"})
+ *  }
+ * )
+ * @ORM\Entity(repositoryClass="Chamilo\CoreBundle\Entity\Repository\SkillRelUserCommentRepository")
+ */
+class SkillRelUserComment
+{
+    /**
+     * @var integer
+     *
+     * @ORM\Column(name="id", type="integer")
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="IDENTITY")
+     */
+    private $id;
+
+    /**
+     * @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\SkillRelUser", inversedBy="comments")
+     * @ORM\JoinColumn(name="skill_rel_user_id", referencedColumnName="id")
+     */
+    private $skillRelUser;
+
+    /**
+     * @ORM\ManyToOne(targetEntity="Chamilo\UserBundle\Entity\User", inversedBy="commentedUserSkills")
+     * @ORM\JoinColumn(name="feedback_giver_id", referencedColumnName="id")
+     */
+    private $feedbackGiver;
+
+    /**
+     * @var string
+     *
+     * @ORM\Column(name="feedback_text", type="text")
+     */
+    private $feedbackText;
+
+    /**
+     * @var int
+     *
+     * @ORM\Column(name="feedback_value", type="integer", nullable=true, options={"default":1})
+     */
+    private $feedbackValue;
+
+    /**
+     * @var \DateTime
+     *
+     * @ORM\Column(name="feedback_datetime", type="datetime")
+     */
+    private $feedbackDateTime;
+
+    /**
+     * Get id
+     * @return int
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    /**
+     * Get skillRelUser
+     * @return Chamilo\CoreBundle\Entity\SkillRelUser
+     */
+    public function getSkillRelUser()
+    {
+        return $this->skillRelUser;
+    }
+
+    /**
+     * Get feedbackGiver
+     * @return Chamilo\UserBundle\Entity\User
+     */
+    public function getFeedbackGiver()
+    {
+        return $this->feedbackGiver;
+    }
+
+    /**
+     * Get feedbackText
+     * @return string
+     */
+    public function getFeedbackText()
+    {
+        return $this->feedbackText;
+    }
+
+    /**
+     * Get feedbackValue
+     * @return int
+     */
+    public function getFeedbackValue()
+    {
+        return $this->feedbackValue;
+    }
+
+    /**
+     * Get feedbackDateTime
+     * @return type
+     */
+    public function getFeedbackDateTime()
+    {
+        return $this->feedbackDateTime;
+    }
+
+    /**
+     * Set skillRelUser
+     * @param \Chamilo\CoreBundle\Entity\SkillRelUser $skillRelUser
+     * @return \Chamilo\CoreBundle\Entity\SkillRelUserComment
+     */
+    public function setSkillRelUser(SkillRelUser $skillRelUser)
+    {
+        $this->skillRelUser = $skillRelUser;
+
+        return $this;
+    }
+
+    /**
+     * Set feedbackGiver
+     * @param \Chamilo\UserBundle\Entity\User $feedbackGiver
+     * @return \Chamilo\CoreBundle\Entity\SkillRelUserComment
+     */
+    public function setFeedbackGiver(\Chamilo\UserBundle\Entity\User $feedbackGiver)
+    {
+        $this->feedbackGiver = $feedbackGiver;
+
+        return $this;
+    }
+
+    /**
+     * Set feedbackText
+     * @param string $feedbackText
+     * @return \Chamilo\CoreBundle\Entity\SkillRelUserComment
+     */
+    public function setFeedbackText($feedbackText)
+    {
+        $this->feedbackText = $feedbackText;
+
+        return $this;
+    }
+
+    /**
+     * Set feebackValue
+     * @param int $feedbackValue
+     * @return \Chamilo\CoreBundle\Entity\SkillRelUserComment
+     */
+    public function setFeedbackValue($feedbackValue)
+    {
+        $this->feedbackValue = $feedbackValue;
+
+        return $this;
+    }
+
+    /**
+     * Set feedbackDateTime
+     * @param \DateTime $feedbackDateTime
+     * @return \Chamilo\CoreBundle\Entity\SkillRelUserComment
+     */
+    public function setFeedbackDateTime(\DateTime $feedbackDateTime)
+    {
+        $this->feedbackDateTime = $feedbackDateTime;
+
+        return $this;
+    }
+}

+ 18 - 1
src/Chamilo/CoreBundle/Resources/public/css/base.css

@@ -95,6 +95,21 @@ a.thumbnail:hover{
   padding-top: 10px;
   margin-top: 5px;
 }
+.blackboard_show {
+    float:left;
+    position:absolute;
+    border:1px solid #000;
+    width: 200px;
+    padding: 5px;
+    border-radius: 5px;
+    background-color:#000;
+    z-index:99; padding: 3px;
+    display: inline;
+    color: #fff;
+}
+.blackboard_hide {
+   display: none;
+}
 .section-page .page-header h3{
     font-size:22px;
     margin-top:5px;
@@ -998,7 +1013,9 @@ button.next.disabled {
     cursor:default;
 
 }
-
+.content-chat{
+    height: 200px;
+}
 /* Note */
 .note {
     margin: 6px;

+ 0 - 58
src/Chamilo/CoreBundle/Resources/public/css/chat.css

@@ -213,63 +213,6 @@ li.list-group-item:hover a{
 	float: left;
 	margin-right: 5px;
 }
-
-#user-online-scroll .viewport {
-    width: 260px;
-    height: 550px;
-    min-height: 550px;
-    overflow: hidden;
-    position: relative;
-    padding-left: 8px;
-}
-
-#user-online-scroll .overview {
-    list-style: none;
-    position: relative;
-    left: 0;
-    top: 0;
-    padding: 0;
-    margin: 0;
-}
-
-#user-online-scroll .scrollbar {
-    background: transparent url(bg-scrollbar-track-y.png) no-repeat 0 0;
-    position: relative;
-    background-position: 0 0;
-    float: right;
-    width: 15px;
-}
-
-#user-online-scroll .track {
-    background: transparent url(bg-scrollbar-trackend-y.png) no-repeat 0 100%;
-    height: 100%;
-    width: 13px;
-    position: relative;
-    padding: 0 1px;
-}
-
-#user-online-scroll .thumb {
-    background: transparent url(bg-scrollbar-thumb-y.png) no-repeat 50% 100%;
-    height: 20px;
-    width: 25px;
-    cursor: pointer;
-    overflow: hidden;
-    position: absolute;
-    top: 0;
-    left: -5px;
-}
-
-#user-online-scroll .thumb .end {
-    background: transparent url(bg-scrollbar-thumb-y.png) no-repeat 50% 0;
-    overflow: hidden;
-    height: 5px;
-    width: 25px;
-}
-
-#user-online-scroll .disable {
-    display: none;
-}
-
 .noSelect {
     user-select: none;
     -o-user-select: none;
@@ -277,7 +220,6 @@ li.list-group-item:hover a{
     -khtml-user-select: none;
     -webkit-user-select: none;
 }
-
 .btn-send {
 	background: #87e0fd; /* Old browsers */
 	background: -moz-linear-gradient(top, #87e0fd 0%, #53cbf1 40%, #05abe0 100%); /* FF3.6+ */

+ 5 - 0
src/Chamilo/UserBundle/Entity/User.php

@@ -390,6 +390,11 @@ class User extends BaseUser //implements ParticipantInterface, ThemeUser
      */
     protected $achievedSkills;
 
+    /**
+     * @ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\SkillRelUserComment", mappedBy="feedbackGiver")
+     */
+    protected $commentedUserSkills;
+
     /**
      * Constructor
      */

+ 63 - 3
src/Chamilo/UserBundle/Repository/UserRepository.php

@@ -9,6 +9,7 @@ use \Chamilo\CoreBundle\Entity\Session;
 use \Chamilo\CoreBundle\Entity\Course;
 use \Doctrine\ORM\Query\Expr\Join;
 use \Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
+use \Chamilo\UserBundle\Entity\User;
 
 //use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
 //use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
@@ -25,10 +26,10 @@ class UserRepository extends EntityRepository
 {
 
     /**
-     * @param string $keyword
+    * @param string $keyword
      *
-     * @return mixed
-     */
+    * @return mixed
+    */
     public function searchUserByKeyword($keyword)
     {
         $qb = $this->createQueryBuilder('a');
@@ -180,6 +181,7 @@ class UserRepository extends EntityRepository
 
     }
 
+
     /**
      * Get course user relationship based in the course_rel_user table.
      * @return array
@@ -240,4 +242,62 @@ class UserRepository extends EntityRepository
 
         return $query->execute();
     }*/
+
+    /**
+     * Get the sessions admins for a user
+     * @param \Chamilo\UserBundle\Entity\User $user The user
+     * @return array
+     */
+    public function getSessionAdmins(User $user)
+    {
+        $queryBuilder = $this->createQueryBuilder('u');
+        $queryBuilder
+            ->distinct()
+            ->innerJoin(
+                'ChamiloCoreBundle:SessionRelUser',
+                'su',
+                Join::WITH,
+                $queryBuilder->expr()->eq('u', 'su.user')
+            )
+            ->innerJoin(
+                'ChamiloCoreBundle:SessionRelCourseRelUser',
+                'scu',
+                Join::WITH,
+                $queryBuilder->expr()->eq('su.session', 'scu.session')
+            )
+            ->where(
+                $queryBuilder->expr()->eq('scu.user', $user->getId())
+            )
+            ->andWhere(
+                $queryBuilder->expr()->eq('su.relationType', SESSION_RELATION_TYPE_RRHH)
+            );
+
+        return $queryBuilder->getQuery()->getResult();
+    }
+
+    /**
+     * Get the student bosses for a user
+     * @param User $user The user
+     * @return array
+     */
+    public function getStudentBosses(User $user)
+    {
+        $queryBuilder = $this->createQueryBuilder('u');
+        $queryBuilder
+            ->distinct()
+            ->innerJoin(
+                'ChamiloCoreBundle:UserRelUser',
+                'uu',
+                Join::WITH,
+                $queryBuilder->expr()->eq('u.id', 'uu.friendUserId')
+            )
+            ->where(
+                $queryBuilder->expr()->eq('uu.relationType', USER_RELATION_TYPE_BOSS)
+            )
+            ->andWhere(
+                $queryBuilder->expr()->eq('uu.userId', $user->getId())
+            );
+
+        return $queryBuilder->getQuery()->getResult();
+    }
 }

+ 3 - 1
user_portal.php

@@ -21,7 +21,9 @@ use ChamiloSession as Session;
 $cidReset = true;
 
 // For HTML editor repository.
-Session::erase('this_section');
+if (isset($_SESSION['this_section'])) {
+    unset($_SESSION['this_section']);
+}
 
 /* Included libraries */
 require_once './main/inc/global.inc.php';

Vissa filer visades inte eftersom för många filer har ändrats