Merge branch 'master' into ui

pull/2715/head
Alex Aragón 8 years ago
commit f9c9db2984
  1. 17
      .gitignore
  2. 8
      composer.json
  3. 1
      config/packages/framework.yaml
  4. 26
      main/admin/access_urls.php
  5. 51
      main/admin/configure_homepage.php
  6. 3
      main/admin/configure_plugin.php
  7. 8
      main/admin/settings.lib.php
  8. 2
      main/admin/user_add.php
  9. 26
      main/announcements/announcements.php
  10. 2
      main/course_info/about.php
  11. 16
      main/cron/import_csv.php
  12. 2
      main/document/show_content.php
  13. 24
      main/exercise/exercise.class.php
  14. 10
      main/exercise/exercise_submit.php
  15. 2
      main/gradebook/lib/GradebookUtils.php
  16. 40
      main/gradebook/lib/fe/gradebooktable.class.php
  17. 2
      main/gradebook/my_certificates.php
  18. 28
      main/inc/lib/AnnouncementEmail.php
  19. 91
      main/inc/lib/AnnouncementManager.php
  20. 4
      main/inc/lib/api.lib.php
  21. 288
      main/inc/lib/banner.lib.php
  22. 33
      main/inc/lib/chat.lib.php
  23. 15
      main/inc/lib/course.lib.php
  24. 38
      main/inc/lib/course_home.lib.php
  25. 1
      main/inc/lib/database.constants.inc.php
  26. 2
      main/inc/lib/groupmanager.lib.php
  27. 1
      main/inc/lib/javascript/chat/js/chat.js
  28. 63
      main/inc/lib/javascript/ckeditor/plugins/video/dialogs/video.js
  29. 93
      main/inc/lib/javascript/ckeditor/plugins/video/plugin.js
  30. 12
      main/inc/lib/message.lib.php
  31. 4
      main/inc/lib/sessionmanager.lib.php
  32. 2
      main/inc/lib/urlmanager.lib.php
  33. 2
      main/lp/learnpath.class.php
  34. 20
      main/mySpace/myStudents.php
  35. 2
      main/template/default/social/personal_data.html.twig
  36. 4
      src/AdminBundle/ChamiloAdminBundle.php
  37. 6
      src/ApiBundle/GraphQL/Resolver/CourseResolver.php
  38. 10
      src/ApiBundle/GraphQL/Resources/config/Enum.types.yaml
  39. 22
      src/ApiBundle/GraphQL/Resources/config/Query.types.yaml
  40. 8
      src/CoreBundle/Entity/Listener/CourseListener.php
  41. 222
      src/CoreBundle/Entity/Resource/ResourceFile.php
  42. 92
      src/CoreBundle/Entity/Resource/ResourceLink.php
  43. 116
      src/CoreBundle/Entity/Resource/ResourceNode.php
  44. 2
      src/CoreBundle/Entity/Resource/ResourceRight.php
  45. 80
      src/CoreBundle/Entity/Resource/ResourceType.php
  46. 4
      src/CoreBundle/Migrations/Schema/V200/Version20.php
  47. 12
      src/CoreBundle/Migrations/Schema/V200/Version20170904145500.php
  48. 6
      src/CoreBundle/Repository/ResourceRepository.php
  49. 75
      src/CourseBundle/Entity/CGroupInfo.php
  50. 43
      src/CourseBundle/Entity/CGroupRelTutor.php
  51. 43
      src/CourseBundle/Entity/CGroupRelUser.php
  52. 22
      src/CourseBundle/Entity/Manager/AnnouncementManager.php
  53. 62
      src/CourseBundle/Resources/config/services.yml
  54. 23
      src/CourseBundle/Tool/BaseTool.php
  55. 13
      src/CourseBundle/ToolChain.php
  56. 38
      src/ThemeBundle/Resources/views/Macros/box.html.twig
  57. 69
      src/UserBundle/Entity/User.php
  58. 2
      src/UserBundle/Repository/UserRepository.php
  59. 141
      tests/scripts/migrate_item_property.php

17
.gitignore vendored

@ -1,3 +1,9 @@
# Chamilo 1.x
app
courses
web/assets/*
# Cache directories
var/cache/*
@ -9,15 +15,8 @@ var/log/*
/node_modules/
# Chamilo configuration
/app/config/parameters.yml
/app/config/add_course.conf.php
/app/config/auth.conf.php
/app/config/course_info.conf.php
/app/config/events.conf.php
/app/config/mail.conf.php
/app/config/profile.conf.php
/config/configuration.php
/app/config/configuration.php
/main/inc/conf/configuration.php
# Courses
@ -25,7 +24,6 @@ var/courses/*
!var/courses/.gitkeep
# Home
app/home/*
components/*
# Upload content
@ -53,7 +51,6 @@ plugin/vchamilo/templates/*
# Stuff updated through composer - Remove just before release
vendor
web/assets/*
###> symfony/framework-bundle ###
.env

@ -3,7 +3,7 @@
"description": "E-learning and collaboration software",
"type": "project",
"homepage": "http://www.chamilo.org",
"license": "GPL-3.0",
"license": "GPL-3.0-or-later",
"support": {
"forum": "https://chamilo.org/forum",
"irc": "irc://irc.freenode.org/chamilo",
@ -13,8 +13,7 @@
},
"autoload": {
"psr-4": {
"Chamilo\\": "src/",
"Application\\": "app/"
"Chamilo\\": "src/"
},
"classmap": [
"main/auth",
@ -71,7 +70,6 @@
"symfony/annotations-pack": "^1.0",
"symfony/webpack-encore-pack": "^1.0",
"symfony/apache-pack": "^1.0",
"symfony/var-dumper": "^4.0",
"apy/datagrid-bundle" : "dev-master",
@ -103,7 +101,6 @@
"sunra/php-simple-html-dom-parser": "~1.5.0",
"sylius/resource-bundle": "1.2.*",
"friendsofsymfony/jsrouting-bundle": "~2.0",
"gedmo/doctrine-extensions": "~2.4",
"gregwar/captcha-bundle": "^2.0",
@ -160,6 +157,7 @@
"firebase/php-jwt": "^5.0"
},
"require-dev": {
"symfony/var-dumper": "^4.0",
"friendsofphp/php-cs-fixer": "^2.7",
"symfony/browser-kit": "^4.0",
"symfony/css-selector": "^4.0",

@ -1,4 +1,5 @@
framework:
form: ~
secret: '%env(APP_SECRET)%'
default_locale: '%env(APP_LOCALE)%'
translator:

@ -102,7 +102,8 @@ if ($current_access_url_id == -1) {
);
if ($quant == 0) {
echo Display::return_message(
'<a href="'.api_get_self().'?action=register&sec_token='.$parameters['sec_token'].'">'.get_lang('ClickToRegisterAdmin').'</a>',
'<a href="'.api_get_self().'?action=register&sec_token='.$parameters['sec_token'].'">'.
get_lang('ClickToRegisterAdmin').'</a>',
'warning',
false
);
@ -139,23 +140,22 @@ echo Display::url(
echo '</div>';
$sortable_data = UrlManager::get_url_data();
$data = UrlManager::get_url_data();
$urls = [];
foreach ($sortable_data as $row) {
//title
foreach ($data as $row) {
// Title
$url = Display::url($row['url'], $row['url'], ['target' => '_blank']);
$description = $row['description'];
$createdAt = api_get_local_time($row['tms']);
//Status
$active = $row['active'];
$action = 'unlock';
$image = 'wrong';
if ($active == '1') {
$action = 'lock';
$image = 'right';
}
if ($active == '0') {
$action = 'unlock';
$image = 'wrong';
}
// you cannot lock the default
if ($row['id'] == '1') {
$status = Display::return_icon($image.'.gif', get_lang(ucfirst($action)));
@ -165,12 +165,15 @@ foreach ($sortable_data as $row) {
}
// Actions
$url_id = $row['id'];
$actions = Display::url(Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL), "access_url_edit.php?url_id=$url_id");
$actions = Display::url(
Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL),
"access_url_edit.php?url_id=$url_id"
);
if ($url_id != '1') {
$actions .= '<a href="access_urls.php?action=delete_url&amp;url_id='.$url_id.'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"), ENT_QUOTES, $charset))."'".')) return false;">'.
Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'</a>';
}
$urls[] = [$url, $description, $status, $actions];
$urls[] = [$url, $description, $status, $createdAt, $actions];
}
$table = new SortableTableFromArrayConfig($urls, 2, 50, 'urls');
@ -178,7 +181,8 @@ $table->set_additional_parameters($parameters);
$table->set_header(0, 'URL');
$table->set_header(1, get_lang('Description'));
$table->set_header(2, get_lang('Active'));
$table->set_header(3, get_lang('Modify'), false);
$table->set_header(3, get_lang('CreatedAt'));
$table->set_header(4, get_lang('Modify'), false);
$table->display();
Display :: display_footer();

@ -217,56 +217,6 @@ if (!empty($action)) {
// for news file, $topf for top file, $noticef for noticefile,
// $ext for '.html'
switch ($action) {
case 'edit_top':
// Filter
$home_top = trim(stripslashes($_POST['home_top']));
// Write
if (is_writable($homep)) {
// Default
if (is_writable($homep.$topf.'_'.$lang.$ext)) {
$fp = fopen($homep.$topf.'_'.$lang.$ext, 'w');
fputs($fp, $home_top);
fclose($fp);
// Language
foreach ($_languages['name'] as $key => $value) {
$lang_name = $_languages['folder'][$key];
if (isset($_POST[$lang_name])) {
$fp = fopen($homep.$topf.'_'.$lang_name.$ext, 'w');
fputs($fp, $home_top);
fclose($fp);
}
}
} else {
$errorMsg = get_lang('HomePageFilesNotWritable');
}
} else {
//File does not exist
$fp = fopen($homep.$topf.'_'.$lang.$ext, 'w');
fputs($fp, $home_top);
fclose($fp);
foreach ($_languages['name'] as $key => $value) {
$lang_name = $_languages['folder'][$key];
if (isset($_POST[$lang_name])) {
if (file_exists($homep.$topf.'_'.$lang_name.$ext)) {
$fp = fopen($homep.$topf.'_'.$lang_name.$ext, 'w');
fputs($fp, $home_top);
fclose($fp);
}
}
}
}
Event::addEvent(
LOG_HOMEPAGE_CHANGED,
'edit_top',
cut(strip_tags($home_top), 254),
api_get_utc_datetime(),
api_get_user_id()
);
break;
case 'edit_notice':
// Filter
$notice_title = trim(strip_tags(stripslashes($_POST['notice_title'])));
@ -1009,7 +959,6 @@ switch ($action) {
<!-- login block -->
<div id="login-block" class="panel panel-default">
<div class="panel-body">
<?php echo api_display_language_form(false, true); ?>
<form id="form-login" class="form-horizontal">
<div class="input-group">
<div class="input-group-addon"><em class="fa fa-user"></em></div>

@ -43,12 +43,13 @@ if (isset($pluginInfo['settings_form'])) {
Display::return_message(get_lang('NoConfigurationSettingsForThisPlugin'), 'warning')
);
}
if (isset($form)) {
if ($form->validate()) {
$values = $form->getSubmitValues();
// Fix only for bbb
if ($pluginName === 'bbb') {
if ($pluginName == 'bbb') {
if (!isset($values['global_conference_allow_roles'])) {
$values['global_conference_allow_roles'] = [];
}

@ -197,12 +197,12 @@ function handlePlugins()
$pluginRow .= Display::url(
'<em class="fa fa-cogs"></em> '.get_lang('Configure'),
'configure_plugin.php?name='.$pluginName,
['class' => 'btn btn-secondary']
['class' => 'btn btn-default']
);
$pluginRow .= Display::url(
'<em class="fa fa-th-large"></em> '.get_lang('Regions'),
'settings.php?category=Regions&name='.$pluginName,
['class' => 'btn btn-secondary']
['class' => 'btn btn-default']
);
}
@ -211,7 +211,7 @@ function handlePlugins()
"<em class='fa fa-file-text-o'></em> readme.txt",
api_get_path(WEB_PLUGIN_PATH).$pluginName."/readme.txt",
[
'class' => 'btn btn-secondary ajax',
'class' => 'btn btn-default ajax',
'data-title' => $plugin_info['title'],
'data-size' => 'lg',
'_target' => '_blank',
@ -225,7 +225,7 @@ function handlePlugins()
"<em class='fa fa-file-text-o'></em> README.md",
api_get_path(WEB_AJAX_PATH).'plugin.ajax.php?a=md_to_html&plugin='.$pluginName,
[
'class' => 'btn btn-secondary ajax',
'class' => 'btn btn-default ajax',
'data-title' => $plugin_info['title'],
'data-size' => 'lg',
'_target' => '_blank',

@ -245,7 +245,7 @@ $form->addElement(
);
//drh list (display only if student)
$display = isset($_POST['status']) && $_POST['status'] == STUDENT || !isset($_POST['status']) ? 'block' : 'none';
$display = (isset($_POST['status']) && $_POST['status'] == STUDENT) || !isset($_POST['status']) ? 'block' : 'none';
//@todo remove the drh list here. This code is unused
$form->addElement('html', '<div id="drh_list" style="display:'.$display.';">');

@ -450,7 +450,7 @@ switch ($action) {
);
// when we want to remind the users who have never been active
// then we have a different subject and content for the announcement
if ($_GET['since'] == 'never') {
if ($_GET['since'] === 'never') {
$title_to_modify = sprintf(
get_lang('RemindInactiveLearnersMailSubject'),
api_get_setting('siteName')
@ -475,6 +475,7 @@ switch ($action) {
$announcementInfo = AnnouncementManager::get_by_id($courseId, $id);
if (isset($announcementInfo) && !empty($announcementInfo)) {
$to = AnnouncementManager::load_edit_users('announcement', $id);
$defaults = [
'title' => $announcementInfo['title'],
'content' => $announcementInfo['content'],
@ -545,6 +546,8 @@ switch ($action) {
$form->addCheckBox('send_to_hrm_users', null, get_lang('SendAnnouncementCopyToDRH'));
}
$form->addCheckBox('send_me_a_copy_by_email', null, get_lang('SendAnnouncementCopyToMyself'));
$defaults['send_me_a_copy_by_email'] = true;
$form->addButtonSave(get_lang('ButtonPublishAnnouncement'));
$form->setDefaults($defaults);
@ -552,6 +555,7 @@ switch ($action) {
$data = $form->getSubmitValues();
$data['users'] = isset($data['users']) ? $data['users'] : [];
$sendToUsersInSession = isset($data['send_to_users_in_session']) ? true : false;
$sendMeCopy = isset($data['send_me_a_copy_by_email']) ? true : false;
if (isset($id) && $id) {
// there is an Id => the announcement already exists => update mode
@ -570,8 +574,9 @@ switch ($action) {
);
// Send mail
$messageSentTo = [];
if (isset($_POST['email_ann']) && empty($_POST['onlyThoseMails'])) {
AnnouncementManager::sendEmail(
$messageSentTo = AnnouncementManager::sendEmail(
api_get_course_info(),
api_get_session_id(),
$id,
@ -580,6 +585,11 @@ switch ($action) {
);
}
if ($sendMeCopy && !in_array(api_get_user_id(), $messageSentTo)) {
$email = new AnnouncementEmail(api_get_course_info(), api_get_session_id(), $id);
$email->sendAnnouncementEmailToMySelf();
}
Display::addFlash(
Display::return_message(
get_lang('AnnouncementModified'),
@ -612,13 +622,14 @@ switch ($action) {
$insert_id = AnnouncementManager::add_group_announcement(
$data['title'],
$data['content'],
['GROUP:'.$group_id],
$group_id,
$data['users'],
$file,
$file_comment,
$sendToUsersInSession
);
}
if ($insert_id) {
Display::addFlash(
Display::return_message(
@ -628,14 +639,21 @@ switch ($action) {
);
// Send mail
$messageSentTo = [];
if (isset($data['email_ann']) && $data['email_ann']) {
AnnouncementManager::sendEmail(
$messageSentTo = AnnouncementManager::sendEmail(
api_get_course_info(),
api_get_session_id(),
$insert_id,
$sendToUsersInSession
);
}
if ($sendMeCopy && !in_array(api_get_user_id(), $messageSentTo)) {
$email = new AnnouncementEmail(api_get_course_info(), api_get_session_id(), $insert_id);
$email->sendAnnouncementEmailToMySelf();
}
Security::clear_token();
header('Location: '.$homeUrl);
exit;

@ -154,7 +154,7 @@ $courseItem = [
$metaInfo = '<meta property="og:url" content="'.$urlCourse.'" />';
$metaInfo .= '<meta property="og:type" content="website" />';
$metaInfo .= '<meta property="og:title" content="'.$courseItem['title'].'" />';
$metaInfo .= '<meta property="og:description" content="'.$courseDescription.'" />';
$metaInfo .= '<meta property="og:description" content="'.strip_tags($courseDescription).'" />';
$metaInfo .= '<meta property="og:image" content="'.$courseItem['image'].'" />';
$htmlHeadXtra[] = $metaInfo;

@ -240,11 +240,11 @@ class ImportCsv
'teachers-static',
'courses-static',
'sessions-static',
'calendar-static',
'sessionsextid-static',
'unsubscribe-static',
'unsubsessionsextid-static',
'subsessionsextid-static',
'calendar-static',
];
foreach ($sections as $section) {
@ -667,6 +667,10 @@ class ImportCsv
false //$send_mail = false
);
$row['extra_mail_notify_invitation'] = 1;
$row['extra_mail_notify_message'] = 1;
$row['extra_mail_notify_group_message'] = 1;
if ($userId) {
foreach ($row as $key => $value) {
if (substr($key, 0, 6) == 'extra_') {
@ -832,6 +836,10 @@ class ImportCsv
false //$send_mail = false
);
$row['extra_mail_notify_invitation'] = 1;
$row['extra_mail_notify_message'] = 1;
$row['extra_mail_notify_group_message'] = 1;
if ($result) {
foreach ($row as $key => $value) {
if (substr($key, 0, 6) === 'extra_') {
@ -1026,6 +1034,11 @@ class ImportCsv
if (empty($courseInfo)) {
$this->logger->addInfo("Course '$courseCode' does not exists");
} else {
if ($courseInfo['visibility'] == COURSE_VISIBILITY_HIDDEN) {
$this->logger->addInfo("Course '".$courseInfo['code']."' has hidden visiblity. Skip");
$errorFound = true;
}
}
if (empty($sessionId)) {
@ -1035,7 +1048,6 @@ class ImportCsv
$sessionInfo = [];
if (!empty($sessionId) && !empty($courseInfo)) {
$sessionInfo = api_get_session_info($sessionId);
$courseIncluded = SessionManager::relation_session_course_exist(
$sessionId,
$courseInfo['real_id']

@ -94,7 +94,7 @@ header('Last-Modified: Wed, 01 Jan 2100 00:00:00 GMT');
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
$browser_display_title = 'Documents - '.Security::remove_XSS($_GET['cidReq']).' - '.$file;
$file_url_web = api_get_path(WEB_COURSE_PATH).$_course['path'].'/document'.$header_file.'?'.api_get_cidreq();
$file_url_web = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/document'.$header_file.'?'.api_get_cidreq();
$pathinfo = pathinfo($header_file);
if ($pathinfo['extension'] == 'swf') {

@ -962,29 +962,38 @@ class Exercise
$result['question_list'] = isset($question_list) ? $question_list : [];
$result['category_with_questions_list'] = isset($questions_by_category) ? $questions_by_category : [];
$parentsLoaded = [];
// Adding category info in the category list with question list:
if (!empty($questions_by_category)) {
$newCategoryList = [];
$em = Database::getManager();
foreach ($questions_by_category as $categoryId => $questionList) {
$cat = new TestCategory();
$cat = $cat->getCategory($categoryId);
$cat = (array) $cat;
$cat['iid'] = $cat['id'];
if ($cat) {
$cat = (array) $cat;
$cat['iid'] = $cat['id'];
}
$categoryParentInfo = null;
// Parent is not set no loop here
if (!empty($cat['parent_id'])) {
if (isset($cat['parent_id']) && !empty($cat['parent_id'])) {
/** @var \Chamilo\CourseBundle\Entity\CQuizCategory $categoryEntity */
if (!isset($parentsLoaded[$cat['parent_id']])) {
$categoryEntity = $em->find('ChamiloCoreBundle:CQuizCategory', $cat['parent_id']);
$parentsLoaded[$cat['parent_id']] = $categoryEntity;
} else {
$categoryEntity = $parentsLoaded[$cat['parent_id']];
}
$repo = $em->getRepository('ChamiloCoreBundle:CQuizCategory');
$path = $repo->getPath($categoryEntity);
$index = 0;
if ($this->categoryMinusOne) {
//$index = 1;
}
/** @var \Chamilo\CourseBundle\Entity\CQuizCategory $categoryParent */
foreach ($path as $categoryParent) {
$visibility = $categoryParent->getVisibility();
@ -3229,7 +3238,11 @@ class Exercise
*/
public function showTimeControlJS($time_left)
{
$time_left = intval($time_left);
$time_left = (int) $time_left;
$script = "redirectExerciseToResult();";
if ($this->type == ALL_ON_ONE_PAGE) {
$script = "save_now_all('validate');";
}
return "<script>
function openClockWarning() {
@ -3247,6 +3260,7 @@ class Exercise
send_form();
}
});
$('#clock_warning').dialog('open');
$('#counter_to_redirect').epiclock({
mode: $.epiclock.modes.countdown,
@ -3259,7 +3273,7 @@ class Exercise
function send_form() {
if ($('#exercise_form').length) {
save_now_all('validate');
$script
} else {
// In exercise_reminder.php
final_submit();

@ -1201,8 +1201,13 @@ if (!empty($error)) {
//$("#save_for_now_"+question_id).html(\''.Display::return_icon('save.png', get_lang('Saved'), [], ICON_SIZE_SMALL).'\');
window.location = url;
}
function redirectExerciseToResult()
{
window.location = "'.$script_php.'?'.$params.'";
}
function save_now(question_id, url_extra) {
function save_now(question_id, url_extra, validate) {
//1. Normal choice inputs
var my_choice = $(\'*[name*="choice[\'+question_id+\']"]\').serialize();
@ -1245,7 +1250,7 @@ if (!empty($error)) {
success: function(return_value) {
if (return_value == "ok") {
$("#save_for_now_"+question_id).html(\''.
Display::return_icon('save.png', get_lang('Saved'), [], ICON_SIZE_SMALL).'\');
Display::return_icon('save.png', get_lang('Saved'), [], ICON_SIZE_SMALL).'\');
} else if (return_value == "error") {
$("#save_for_now_"+question_id).html(\''.
Display::return_icon('error.png', get_lang('Error'), [], ICON_SIZE_SMALL).'\');
@ -1311,7 +1316,6 @@ if (!empty($error)) {
data: "'.$params.'&type=all&"+my_choice+"&"+hotspot+"&"+free_answers+"&"+remind_list,
success: function(return_value) {
if (return_value == "ok") {
//$("#save_all_response").html(\''.Display::return_icon('accept.png').'\');
if (validate == "validate") {
window.location = "'.$script_php.'?'.$params.'";
} else {

@ -1641,7 +1641,7 @@ class GradebookUtils
$gradebooktable->userId = $userId;
if (api_is_allowed_to_edit()) {
if (api_is_allowed_to_edit(null, true)) {
/*$gradebooktable->td_attributes = [
4 => 'class=centered',
];*/

@ -104,28 +104,28 @@ class GradebookTable extends SortableTable
$model = ExerciseLib::getCourseScoreModel();
if ($this->teacherView) {
$this->set_header(
$column++,
get_lang('Weight'),
'',
'width="100px"'
);
} else {
$this->set_header($column++, get_lang('Weight'), false);
$this->set_header($column++, get_lang('Result'), false);
if (empty($model)) {
if (in_array(1, $this->loadStats)) {
$this->set_header($column++, get_lang('Ranking'), false);
}
if (in_array(2, $this->loadStats)) {
$this->set_header($column++, get_lang('BestScore'), false);
}
if (in_array(3, $this->loadStats)) {
$this->set_header($column++, get_lang('Average'), false);
}
$this->set_header(
$column++,
get_lang('Weight'),
'',
'width="100px"'
);
$this->set_header($column++, get_lang('Result'), false);
if (empty($model)) {
if (in_array(1, $this->loadStats)) {
$this->set_header($column++, get_lang('Ranking'), false);
}
if (in_array(2, $this->loadStats)) {
$this->set_header($column++, get_lang('BestScore'), false);
}
if (in_array(3, $this->loadStats)) {
$this->set_header($column++, get_lang('Average'), false);
}
}
if ($this->teacherView) {
} else {
if (!empty($cats)) {
if ($this->exportToPdf == false) {
$this->set_header($column++, get_lang('Actions'), false);

@ -39,7 +39,7 @@ if (api_get_setting('allow_public_certificates') === 'true') {
'actions',
Display::toolbarButton(
get_lang('SearchCertificates'),
api_get_path(WEB_CODE_PATH)."gradebook/search.php",
api_get_path(WEB_CODE_PATH).'gradebook/search.php',
'search',
'info'
)

@ -274,12 +274,32 @@ class AnnouncementEmail
return $result;
}
/**
* Send announcement by email to myself.
*/
public function sendAnnouncementEmailToMySelf()
{
$userId = api_get_user_id();
$subject = $this->subject();
$message = $this->message($userId);
MessageManager::send_message_simple(
$userId,
$subject,
$message,
api_get_user_id(),
false,
true
);
}
/**
* Send emails to users.
*
* @param bool $sendToUsersInSession
* @param bool $sendToDrhUsers send a copy of the message to the DRH users
* @param int $senderId related to the main user
*
* @return array
*/
public function send($sendToUsersInSession = false, $sendToDrhUsers = false, $senderId = 0)
{
@ -296,7 +316,7 @@ class AnnouncementEmail
if (empty($users) && !empty($this->logger)) {
$this->logger->addInfo('User list is empty. No emails will be sent.');
}
$messageSentTo = [];
foreach ($users as $user) {
$message = $this->message($user['user_id']);
$wasSent = MessageManager::messageWasAlreadySent($senderId, $user['user_id'], $subject, $message);
@ -306,6 +326,8 @@ class AnnouncementEmail
'Announcement: #'.$this->announcement('id').'. Send email to user: #'.$user['user_id']
);
}
$messageSentTo[] = $user['user_id'];
MessageManager::send_message_simple(
$user['user_id'],
$subject,
@ -342,6 +364,7 @@ class AnnouncementEmail
);
if (!empty($userList)) {
foreach ($userList as $user) {
$messageSentTo[] = $user['user_id'];
MessageManager::send_message_simple(
$user['user_id'],
$subject,
@ -357,6 +380,9 @@ class AnnouncementEmail
}
$this->logMailSent();
$messageSentTo = array_unique($messageSentTo);
return $messageSentTo;
}
/**

@ -114,7 +114,7 @@ class AnnouncementManager
$extraFields = $extraField->get_all(['filter = ?' => 1]);
if (!empty($extraFields)) {
foreach ($extraFields as $extra) {
$data["extra_".$extra['variable']] = '';
$data['extra_'.$extra['variable']] = '';
}
}
@ -123,7 +123,12 @@ class AnnouncementManager
if (isset($extra['value'])) {
/** @var \Chamilo\CoreBundle\Entity\ExtraFieldValues $value */
$value = $extra['value'];
$data['extra_'.$value->getField()->getVariable()] = $value->getValue();
if ($value instanceof ExtraFieldValues) {
$field = $value->getField();
if ($field) {
$data['extra_'.$field->getVariable()] = $value->getValue();
}
}
}
}
}
@ -693,7 +698,7 @@ class AnnouncementManager
public static function add_group_announcement(
$title,
$newContent,
$to,
$groupId,
$to_users,
$file = [],
$file_comment = '',
@ -734,13 +739,27 @@ class AnnouncementManager
);
}
$send_to_groups = CourseManager::separateUsersGroups($to);
$send_to_users = CourseManager::separateUsersGroups($to_users);
// Store in item_property (first the groups, then the users)
if (empty($to_users) || (isset($to_users[0]) && $to_users[0] === 'everyone')) {
// when no user is selected we send it to everyone
$send_to = CourseManager::separateUsersGroups($to);
// storing the selected groups
if (is_array($send_to['groups'])) {
foreach ($send_to['groups'] as $group) {
$sentToAllGroup = false;
if (empty($send_to_users['groups']) && empty($send_to_users['users'])) {
$groupInfo = GroupManager::get_group_properties($groupId);
api_item_property_update(
$courseInfo,
TOOL_ANNOUNCEMENT,
$last_id,
'AnnouncementAdded',
api_get_user_id(),
$groupInfo
);
$sentToAllGroup = true;
}
if ($sentToAllGroup === false) {
if (!empty($send_to_users['groups'])) {
foreach ($send_to_users['groups'] as $group) {
$groupInfo = GroupManager::get_group_properties($group);
api_item_property_update(
$courseInfo,
@ -752,26 +771,19 @@ class AnnouncementManager
);
}
}
} else {
$send_to_groups = CourseManager::separateUsersGroups($to);
$send_to_users = CourseManager::separateUsersGroups($to_users);
$to_groups = $send_to_groups['groups'];
$to_users = $send_to_users['users'];
// storing the selected users
if (is_array($to_users) && is_array($to_groups)) {
foreach ($to_groups as $group) {
$groupInfo = GroupManager::get_group_properties($group);
foreach ($to_users as $user) {
api_item_property_update(
$courseInfo,
TOOL_ANNOUNCEMENT,
$last_id,
'AnnouncementAdded',
api_get_user_id(),
$groupInfo,
$user
);
}
$groupInfo = GroupManager::get_group_properties($groupId);
if (!empty($send_to_users['users'])) {
foreach ($send_to_users['users'] as $user) {
api_item_property_update(
$courseInfo,
TOOL_ANNOUNCEMENT,
$last_id,
'AnnouncementAdded',
api_get_user_id(),
$groupInfo,
$user
);
}
}
}
@ -1068,6 +1080,7 @@ class AnnouncementManager
ip.tool='announcement' AND
announcement.id = $id
";
$result = Database::query($sql);
if (Database::num_rows($result)) {
return Database::fetch_array($result);
@ -1118,6 +1131,7 @@ class AnnouncementManager
$sql = "SELECT to_user_id, to_group_id FROM $table
WHERE c_id = $courseId AND tool='$tool' AND ref = $id";
$result = Database::query($sql);
$to = [];
while ($row = Database::fetch_array($result)) {
@ -1127,7 +1141,9 @@ class AnnouncementManager
// it was send to one specific user
case null:
if (isset($row['to_user_id']) && !empty($row['to_user_id'])) {
$to[] = 'USER:'.$row['to_user_id'];
if (!in_array('USER:'.$row['to_user_id'], $to)) {
$to[] = 'USER:'.$row['to_user_id'];
}
}
break;
// it was sent to everyone
@ -1135,7 +1151,15 @@ class AnnouncementManager
return 'everyone';
break;
default:
$to[] = 'GROUP:'.$toGroup;
if (isset($row['to_user_id']) && !empty($row['to_user_id'])) {
if (!in_array('USER:'.$row['to_user_id'], $to)) {
$to[] = 'USER:'.$row['to_user_id'];
}
}
if (!in_array('GROUP:'.$toGroup, $to)) {
$to[] = 'GROUP:'.$toGroup;
}
break;
}
}
@ -1462,6 +1486,8 @@ class AnnouncementManager
* @param bool $sendToDrhUsers
* @param Monolog\Handler\HandlerInterface logger
* @param int $senderId
*
* @return array
*/
public static function sendEmail(
$courseInfo,
@ -1473,7 +1499,8 @@ class AnnouncementManager
$senderId = 0
) {
$email = new AnnouncementEmail($courseInfo, $sessionId, $announcementId, $logger);
$email->send($sendToUsersInSession, $sendToDrhUsers, $senderId);
return $email->send($sendToUsersInSession, $sendToDrhUsers, $senderId);
}
/**

@ -8292,7 +8292,7 @@ function api_is_allowed_in_course()
}
$user = api_get_current_user();
if ($user) {
if ($user instanceof User) {
if ($user->hasRole('ROLE_CURRENT_SESSION_COURSE_STUDENT') ||
$user->hasRole('ROLE_CURRENT_SESSION_COURSE_TEACHER') ||
$user->hasRole('ROLE_CURRENT_COURSE_STUDENT') ||
@ -8303,8 +8303,6 @@ function api_is_allowed_in_course()
}
return false;
return Session::read('is_allowed_in_course');
}
/**

@ -12,142 +12,6 @@ use ChamiloSession as Session;
* @package chamilo.include
*/
/**
* Determines the possible tabs (=sections) that are available.
* This function is used when creating the tabs in the third header line and
* all the sections that do not appear there (as determined by the
* platform admin on the Dokeos configuration settings page)
* will appear in the right hand menu that appears on several other pages.
*
* @return array containing all the possible tabs
*
* @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
*/
function get_tabs($courseId = null)
{
$courseInfo = api_get_course_info($courseId);
$navigation = [];
// Campus Homepage
$navigation[SECTION_CAMPUS]['url'] = api_get_path(WEB_PATH).'index.php';
$navigation[SECTION_CAMPUS]['title'] = get_lang('CampusHomepage');
$navigation[SECTION_CAMPUS]['key'] = 'homepage';
$navigation[SECTION_CAMPUS]['icon'] = 'homepage.png';
$navigation[SECTION_CATALOG]['url'] = api_get_path(WEB_PATH).'main/auth/courses.php';
$navigation[SECTION_CATALOG]['title'] = get_lang('Courses');
$navigation[SECTION_CATALOG]['key'] = 'catalog';
$navigation[SECTION_CATALOG]['icon'] = 'catalog.png';
// My Courses
if (api_is_allowed_to_create_course()) {
// Link to my courses for teachers
$navigation['mycourses']['url'] = api_get_path(WEB_PATH).'user_portal.php?nosession=true';
} else {
// Link to my courses for students
$navigation['mycourses']['url'] = api_get_path(WEB_PATH).'user_portal.php';
}
$navigation['mycourses']['title'] = get_lang('MyCourses');
$navigation['mycourses']['key'] = 'my-course';
$navigation['mycourses']['icon'] = 'my-course.png';
// My Profile
$navigation['myprofile']['url'] = api_get_path(WEB_CODE_PATH).'auth/profile.php'
.(!empty($courseInfo['path']) ? '?coursePath='.$courseInfo['path'].'&amp;courseCode='.$courseInfo['official_code'] : '');
$navigation['myprofile']['title'] = get_lang('ModifyProfile');
$navigation['myprofile']['key'] = 'profile';
$navigation['myprofile']['icon'] = 'profile.png';
// Link to my agenda
$navigation['myagenda']['url'] = api_get_path(WEB_CODE_PATH).'calendar/agenda_js.php?type=personal';
$navigation['myagenda']['title'] = get_lang('MyAgenda');
$navigation['myagenda']['key'] = 'agenda';
$navigation['myagenda']['icon'] = 'agenda.png';
// Gradebook
if (api_get_setting('gradebook_enable') == 'true') {
$navigation['mygradebook']['url'] = api_get_path(WEB_CODE_PATH)
.'gradebook/gradebook.php'
.(!empty($courseInfo['path']) ? '?coursePath='.$courseInfo['path'].'&amp;courseCode='.$courseInfo['official_code'] : '');
$navigation['mygradebook']['title'] = get_lang('MyGradebook');
$navigation['mygradebook']['key'] = 'gradebook';
$navigation['mygradebook']['icon'] = 'gradebook.png';
}
// Reporting
if (api_is_teacher() || api_is_drh() || api_is_session_admin()) {
// Link to my space
$navigation['session_my_space']['url'] = api_get_path(WEB_CODE_PATH).'mySpace/'
.(api_is_drh() ? 'session.php' : '');
$navigation['session_my_space']['title'] = get_lang('MySpace');
$navigation['session_my_space']['key'] = 'my-space';
$navigation['session_my_space']['icon'] = 'my-space.png';
} else {
if (api_is_student_boss()) {
$navigation['session_my_space']['url'] = api_get_path(WEB_CODE_PATH).'mySpace/student.php';
$navigation['session_my_space']['title'] = get_lang('MySpace');
$navigation['session_my_space']['key'] = 'my-space';
$navigation['session_my_space']['icon'] = 'my-space.png';
} else {
$navigation['session_my_progress']['url'] = api_get_path(WEB_CODE_PATH);
// Link to my progress
switch (api_get_setting('gamification_mode')) {
case 1:
$navigation['session_my_progress']['url'] .= 'gamification/my_progress.php';
break;
default:
$navigation['session_my_progress']['url'] .= 'auth/my_progress.php';
}
$navigation['session_my_progress']['title'] = get_lang('MyProgress');
$navigation['session_my_progress']['key'] = 'my-progress';
$navigation['session_my_progress']['icon'] = 'my-progress.png';
}
}
// Social
if (api_get_setting('allow_social_tool') == 'true') {
$navigation['social']['url'] = api_get_path(WEB_CODE_PATH).'social/home.php';
$navigation['social']['title'] = get_lang('SocialNetwork');
$navigation['social']['key'] = 'social-network';
$navigation['social']['icon'] = 'social-network.png';
}
// Dashboard
if (api_is_platform_admin() || api_is_drh() || api_is_session_admin()) {
$navigation['dashboard']['url'] = api_get_path(WEB_CODE_PATH).'dashboard/index.php';
$navigation['dashboard']['title'] = get_lang('Dashboard');
$navigation['dashboard']['key'] = 'dashboard';
$navigation['dashboard']['icon'] = 'dashboard.png';
}
// Custom Tabs See BT#7180
$customTabs = getCustomTabs();
if (!empty($customTabs)) {
foreach ($customTabs as $tab) {
if (api_get_setting($tab['variable'], $tab['subkey']) == 'true') {
if (!empty($tab['comment']) && $tab['comment'] !== 'ShowTabsComment') {
$navigation[$tab['subkey']]['url'] = $tab['comment'];
// $tab['title'] value must be included in trad4all.inc.php
$navigation[$tab['subkey']]['title'] = get_lang($tab['title']);
$navigation[$tab['subkey']]['key'] = $tab['subkey'];
}
}
}
}
// End Custom Tabs
// Platform administration
if (api_is_platform_admin(true)) {
$navigation['platform_admin']['url'] = api_get_path(WEB_CODE_PATH).'admin/';
$navigation['platform_admin']['title'] = get_lang('PlatformAdmin');
$navigation['platform_admin']['key'] = 'admin';
$navigation['platform_admin']['icon'] = 'admin.png';
}
return $navigation;
}
/**
* This function returns the custom tabs.
*
@ -210,9 +74,9 @@ function accessToWhoIsOnline()
$user_id = api_get_user_id();
$course_id = api_get_course_int_id();
$access = false;
if ((api_get_setting('showonline', 'world') == 'true' && !$user_id) ||
(api_get_setting('showonline', 'users') == 'true' && $user_id) ||
(api_get_setting('showonline', 'course') == 'true' && $user_id && $course_id)
if ((api_get_setting('showonline', 'world') === 'true' && !$user_id) ||
(api_get_setting('showonline', 'users') === 'true' && $user_id) ||
(api_get_setting('showonline', 'course') === 'true' && $user_id && $course_id)
) {
$access = true;
}
@ -439,152 +303,6 @@ function return_navigation_array()
];
}
/**
* Return the navigation menu elements as a flat array.
*
* @return array
*/
function menuArray()
{
$mainNavigation = return_navigation_array();
unset($mainNavigation['possible_tabs']);
unset($mainNavigation['menu_navigation']);
//$navigation = $navigation['navigation'];
// Get active language
$lang = api_get_setting('platformLanguage');
if (!empty($_SESSION['user_language_choice'])) {
$lang = $_SESSION['user_language_choice'];
} elseif (!empty($_SESSION['_user']['language'])) {
$lang = $_SESSION['_user']['language'];
}
// Preparing home folder for multiple urls
if (api_get_multiple_access_url()) {
$access_url_id = api_get_current_access_url_id();
if ($access_url_id != -1) {
// If not a dead URL
$urlInfo = api_get_access_url($access_url_id);
$url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $urlInfo['url']));
$cleanUrl = api_replace_dangerous_char($url);
$cleanUrl = str_replace('/', '-', $cleanUrl);
$cleanUrl .= '/';
$homepath = api_get_path(SYS_HOME_PATH).$cleanUrl; //homep for Home Path
//we create the new dir for the new sites
if (!is_dir($homepath)) {
mkdir($homepath, api_get_permissions_for_new_directories());
}
}
} else {
$homepath = api_get_path(SYS_HOME_PATH);
}
$ext = '.html';
$menuTabs = 'home_tabs';
$menuTabsLoggedIn = 'home_tabs_logged_in';
$pageContent = '';
// Get the extra page content, containing the links to add to the tabs
if (is_file($homepath.$menuTabs.'_'.$lang.$ext) && is_readable($homepath.$menuTabs.'_'.$lang.$ext)) {
$pageContent = @(string) file_get_contents($homepath.$menuTabs.'_'.$lang.$ext);
} elseif (is_file($homepath.$menuTabs.$lang.$ext) && is_readable($homepath.$menuTabs.$lang.$ext)) {
$pageContent = @(string) file_get_contents($homepath.$menuTabs.$lang.$ext);
}
// Sanitize page content
$pageContent = api_to_system_encoding($pageContent, api_detect_encoding(strip_tags($pageContent)));
$open = str_replace('{rel_path}', api_get_path(REL_PATH), $pageContent);
$open = api_to_system_encoding($open, api_detect_encoding(strip_tags($open)));
// Get the extra page content, containing the links to add to the tabs
// that are only for users already logged in
$openMenuTabsLoggedIn = '';
if (api_get_user_id() && !api_is_anonymous()) {
if (is_file($homepath.$menuTabsLoggedIn.'_'.$lang.$ext) && is_readable(
$homepath.$menuTabsLoggedIn.'_'.$lang.$ext
)
) {
$pageContent = @(string) file_get_contents($homepath.$menuTabsLoggedIn.'_'.$lang.$ext);
$pageContent = str_replace('::private', '', $pageContent);
} elseif (is_file($homepath.$menuTabsLoggedIn.$lang.$ext) && is_readable(
$homepath.$menuTabsLoggedIn.$lang.$ext
)
) {
$pageContent = @(string) file_get_contents($homepath.$menuTabsLoggedIn.$lang.$ext);
$pageContent = str_replace('::private', '', $pageContent);
}
$pageContent = api_to_system_encoding($pageContent, api_detect_encoding(strip_tags($pageContent)));
$openMenuTabsLoggedIn = str_replace('{rel_path}', api_get_path(REL_PATH), $pageContent);
$openMenuTabsLoggedIn = api_to_system_encoding(
$openMenuTabsLoggedIn,
api_detect_encoding(strip_tags($openMenuTabsLoggedIn))
);
}
if (!empty($open) || !empty($openMenuTabsLoggedIn)) {
if (strpos($open.$openMenuTabsLoggedIn, 'show_menu') === false) {
if (api_is_anonymous()) {
$mainNavigation['navigation'][SECTION_CAMPUS] = null;
}
} else {
$list = explode("\n", api_get_user_id() && !api_is_anonymous() ? $openMenuTabsLoggedIn : $open);
foreach ($list as $link) {
if (strpos($link, 'class="hide_menu"') !== false) {
continue;
}
$matches = [];
$match = preg_match('$href="([^"]*)" target="([^"]*)">([^<]*)</a>$', $link, $matches);
if (!$match) {
continue;
}
$mainNavigation['navigation'][$matches[3]] = [
'url' => $matches[1],
'target' => $matches[2],
'title' => $matches[3],
'key' => 'page-'.str_replace(' ', '-', strtolower($matches[3])),
];
}
}
}
if (count($mainNavigation['navigation']) > 0) {
//$pre_lis = '';
$activeSection = '';
foreach ($mainNavigation['navigation'] as $section => $navigation_info) {
$key = (!empty($navigation_info['key']) ? 'tab-'.$navigation_info['key'] : '');
if (isset($GLOBALS['this_section'])) {
$tempSection = $section;
if ($section == 'social') {
$tempSection = 'social-network';
}
if ($tempSection == $GLOBALS['this_section']) {
$activeSection = $section;
}
// If we're on the index page and a specific extra link has been
// loaded
if ($GLOBALS['this_section'] == SECTION_CAMPUS) {
if (!empty($_GET['include'])) {
$name = str_replace(' ', '-', strtolower($navigation_info['title'])).'_'.$lang.$ext;
if (strtolower($_GET['include']) == $name) {
$activeSection = $section;
}
}
}
} else {
$current = '';
}
$mainNavigation['navigation'][$section]['current'] = '';
}
if (!empty($activeSection)) {
$mainNavigation['navigation'][$activeSection]['current'] = 'active';
}
}
unset($mainNavigation['navigation']['myprofile']);
return $mainNavigation['navigation'];
}
/**
* Return the breadcrumb menu elements as an array of <li> items.
*

@ -158,7 +158,7 @@ class Chat extends Model
/**
* @param int $fromUserId
* @param int $toUserId
* @param int $visibleMessages
* @param int $messagesAlreadyPrint
* @param int $previousMessageCount messages to show
*
* @return array
@ -166,24 +166,33 @@ class Chat extends Model
public function getPreviousMessages(
$fromUserId,
$toUserId,
$visibleMessages = 1,
$messagesAlreadyPrint = 1,
$previousMessageCount = 5
) {
$currentUserId = api_get_user_id();
$toUserId = (int) $toUserId;
$fromUserId = (int) $fromUserId;
$previousMessageCount = (int) $previousMessageCount;
if (empty($toUserId) || empty($fromUserId)) {
return [];
}
$total = self::getCountMessagesExchangeBetweenUsers(
$fromUserId,
$toUserId
);
$show = $total - $visibleMessages;
if (empty($total)) {
return [];
}
$show = $total - $messagesAlreadyPrint;
$from = $show - $previousMessageCount;
if ($from < 0) {
return [];
$from = 0;
$previousMessageCount = $show;
}
$sql = "SELECT * FROM ".$this->table."
@ -199,6 +208,7 @@ class Chat extends Model
ORDER BY id ASC
LIMIT $from, $previousMessageCount
";
$result = Database::query($sql);
$rows = Database::store_result($result);
$fromUserInfo = api_get_user_info($fromUserId, true);
@ -218,6 +228,12 @@ class Chat extends Model
}
$chat['message'] = Security::remove_XSS($chat['message']);
$sql = "UPDATE ".$this->table."
SET recd = 1
WHERE to_user = '".$toUserId."' AND recd = 0 AND id = ".$chat['id'];
Database::query($sql);
$item = [
'id' => $chat['id'],
's' => '0',
@ -235,7 +251,6 @@ class Chat extends Model
$items[] = $item;
$_SESSION['openChatBoxes'][$fromUserId] = api_strtotime($chat['sent'], 'UTC');
}
//array_unshift($_SESSION['chatHistory'][$fromUserId]['items'], $items);
return $items;
}
@ -248,7 +263,7 @@ class Chat extends Model
$to_user_id = api_get_user_id();
$sql = "SELECT * FROM ".$this->table."
WHERE to_user = '".intval($to_user_id)."' AND (recd = 0)
WHERE to_user = '".intval($to_user_id)."' AND recd = 0
ORDER BY id ASC";
$result = Database::query($sql);
@ -313,11 +328,6 @@ class Chat extends Model
}
}
$sql = "UPDATE ".$this->table."
SET recd = 1
WHERE to_user = '".$to_user_id."' AND recd = 0";
Database::query($sql);
echo json_encode(['items' => $items]);
}
@ -388,6 +398,7 @@ class Chat extends Model
$params['from_user'] = intval($fromUserId);
$params['to_user'] = intval($to_user_id);
$params['message'] = $message;
$params['recd'] = '0';
$params['sent'] = api_get_utc_datetime();
if (!empty($fromUserId) && !empty($to_user_id)) {

@ -6105,7 +6105,7 @@ class CourseManager
public static function addGroupMultiSelect($form, $groupInfo, $to = [])
{
$group_users = GroupManager::get_subscribed_users($groupInfo);
$array = self::buildSelectOptions(null, $group_users, $to);
$array = self::buildSelectOptions([$groupInfo], $group_users, $to);
$result = [];
foreach ($array as $content) {
@ -6143,14 +6143,19 @@ class CourseManager
"GROUP:".$groupId,
$alreadySelected
)
) { // $alreadySelected is the array containing the groups (and users) that are already selected
$user_label = ($thisGroup['userNb'] > 0) ? get_lang('Users') : get_lang('LowerCaseUser');
$user_disabled = ($thisGroup['userNb'] > 0) ? "" : "disabled=disabled";
) {
$userCount = isset($thisGroup['userNb']) ? $thisGroup['userNb'] : 0;
if (empty($userCount)) {
$userCount = isset($thisGroup['count_users']) ? $thisGroup['count_users'] : 0;
}
// $alreadySelected is the array containing the groups (and users) that are already selected
$user_label = ($userCount > 0) ? get_lang('Users') : get_lang('LowerCaseUser');
$user_disabled = ($userCount > 0) ? "" : "disabled=disabled";
$result[] = [
'disabled' => $user_disabled,
'value' => "GROUP:".$groupId,
// The space before "G" is needed in order to advmultiselect.php js puts groups first
'content' => " G: ".$thisGroup['name']." - ".$thisGroup['userNb']." ".$user_label,
'content' => " G: ".$thisGroup['name']." - ".$userCount." ".$user_label,
];
}
}

@ -529,11 +529,6 @@ class CourseHome
)';
}
/*$sql = "SELECT *
FROM $course_tool_table t
$conditions AND
c_id = $course_id $condition_session
";*/
// Add order if there are LPs
$sql = "SELECT t.* FROM $course_tool_table t
LEFT JOIN $lpTable l
@ -544,9 +539,6 @@ class CourseHome
$orderBy = '';
break;
case TOOL_AUTHORING:
/*$sql = "SELECT * FROM $course_tool_table t
WHERE category = 'authoring' AND c_id = $course_id $condition_session
";*/
$sql = "SELECT t.* FROM $course_tool_table t
LEFT JOIN $lpTable l
ON (t.c_id = l.c_id AND link LIKE concat('%/lp_controller.php?action=view&lp_id=', l.id, '&%'))
@ -657,12 +649,16 @@ class CourseHome
);
$path = $lp->get_preview_image_path(ICON_SIZE_BIG);
$add = learnpath::is_lp_visible_for_student(
$lpId,
$userId,
api_get_course_id(),
api_get_session_id()
);
if (api_is_allowed_to_edit(null, true)) {
$add = true;
} else {
$add = learnpath::is_lp_visible_for_student(
$lpId,
$userId,
api_get_course_id(),
api_get_session_id()
);
}
if ($path) {
$temp_row['custom_image'] = $path;
}
@ -1246,6 +1242,13 @@ class CourseHome
$courseInfo = api_get_course_info();
$sessionId = api_get_session_id();
$conditionSession = api_get_session_condition(
$sessionId,
true,
true,
'session_id'
);
if (!empty($course_id)) {
$course_tools_table = Database::get_course_table(TABLE_TOOL_LIST);
/* Link to the Course homepage */
@ -1254,7 +1257,11 @@ class CourseHome
$navigation_items['home']['name'] = get_lang('CourseHomepageLink');
$sql = "SELECT * FROM $course_tools_table
WHERE c_id = $course_id AND visibility='1' and admin='0'
WHERE
c_id = $course_id AND
visibility = '1' AND
admin = '0'
$conditionSession
ORDER BY id ASC";
$result = Database::query($sql);
@ -1335,6 +1342,7 @@ class CourseHome
public static function show_navigation_menu()
{
$navigation_items = self::get_navigation_items(true);
$course_id = api_get_course_id();
$class = null;

@ -54,6 +54,7 @@ define('TABLE_MAIN_GRADEBOOK_LINK', 'gradebook_link');
define('TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY', 'gradebook_score_display');
define('TABLE_MAIN_GRADEBOOK_CERTIFICATE', 'gradebook_certificate');
define('TABLE_MAIN_GRADEBOOK_SCORE_LOG', 'gradebook_score_log');
define('TABLE_MAIN_GRADEBOOK_RESULT_ATTEMPT', 'gradebook_result_attempt');
// Profiling
define('TABLE_EXTRA_FIELD', 'extra_field');

@ -1339,7 +1339,7 @@ class GroupManager
/** @var CGroupRelUser $subscription */
foreach ($subscriptions as $subscription) {
$users[] = api_get_user_info($subscription->getUserId());
$users[] = api_get_user_info($subscription->getUser()->getId());
}
return $users;

@ -41,6 +41,7 @@ var widthBox = 320; // see css class .chatbox
function set_user_status(status)
{
if (status == 1) {
stopChatHeartBeat();
startChatHeartBeat();
$('.user_status_main').html(online_button);
$('#chatboxtitlemain').html(connect_lang);

@ -10,10 +10,29 @@ CKEDITOR.dialog.add( 'video', function ( editor )
value = generateId();
if (value == '') {
return;
// return;
}
videoNode.setAttribute( this.id, value);
switch (this.id) {
case '360video':
if (value) {
videoNode.setAttribute( 'data-360video', 'true' );
} else {
videoNode.removeAttribute( 'data-360video' );
}
break;
case '360videostereo':
if (videoNode.getAttribute( 'data-360video' ) === 'true') {
if (!value) {
videoNode.setAttribute( 'data-360video-stereo', 'false' );
} else {
videoNode.removeAttribute( 'data-360video-stereo' );
}
}
break;
default:
videoNode.setAttribute( this.id, value);
}
if ( !value )
return;
@ -43,8 +62,18 @@ CKEDITOR.dialog.add( 'video', function ( editor )
function loadValue( videoNode )
{
if ( videoNode )
this.setValue( videoNode.getAttribute( this.id ) );
if ( videoNode ) {
switch (this.id) {
case '360video':
this.setValue(videoNode.getAttribute( 'data-360video' ) === 'true');
break;
case '360videostereo':
this.setValue(videoNode.getAttribute( 'data-360video-stereo' ) !== 'false');
break;
default:
this.setValue( videoNode.getAttribute( this.id ) );
}
}
else
{
if ( this.id == 'id')
@ -194,6 +223,7 @@ CKEDITOR.dialog.add( 'video', function ( editor )
[
{
id : 'info',
label: lang.infoLabel,
elements :
[
{
@ -347,6 +377,31 @@ CKEDITOR.dialog.add( 'video', function ( editor )
}]
}
]
},
{
id: '360',
label: '360°',
elements: [
{
type : 'html',
html : lang.html360
},
{
type : 'checkbox',
id : '360video',
label: lang.video360,
commit : commitValue,
setup : loadValue
},
{
type : 'checkbox',
id : '360videostereo',
label : lang.video360stereo,
'default': 'checked',
commit : commitValue,
setup : loadValue
}
]
}
]

@ -169,43 +169,70 @@ CKEDITOR.plugins.add( 'video',
var en = {
toolbar : 'Video',
dialogTitle : 'Video properties',
fakeObject : 'Video',
properties : 'Edit video',
widthRequired : 'Width field cannot be empty',
heightRequired : 'Height field cannot be empty',
poster: 'Poster image',
sourceVideo: 'Source video',
sourceType : 'Video type',
linkTemplate : '<a href="%src%">%type%</a> ',
fallbackTemplate : 'Your browser doesn\'t support video.<br>Please download the file: %links%'
};
toolbar: 'Video',
dialogTitle: 'Video properties',
fakeObject: 'Video',
properties: 'Edit video',
widthRequired: 'Width field cannot be empty',
heightRequired: 'Height field cannot be empty',
poster: 'Poster image',
sourceVideo: 'Source video',
sourceType: 'Video type',
linkTemplate: '<a href="%src%">%type%</a> ',
fallbackTemplate: 'Your browser doesn\'t support video.<br>Please download the file: %links%',
infoLabel: 'Information',
html360: 'This feature (only MP4 videos) is currently still in BETA mode.<br />It only works on dynamic pages, not inside documents created<br />in the documents tool or seen through learning paths.<br />Please do not add more than one 360° video on a single page<br /> as more than one on the same page might generate conflicts.',
video360: 'Enable 360° video player',
video360stereo: 'Stereo video (1:1 aspect ratio)'
};
var es = {
toolbar : 'Video',
dialogTitle : 'Propiedades de video',
fakeObject : 'Video',
properties : 'Editar el video',
widthRequired : 'La anchura no se puede dejar en blanco',
heightRequired : 'La altura no se puede dejar en blanco',
poster: 'Imagen de presentación',
sourceVideo: 'Archivo de video',
sourceType : 'Tipo',
linkTemplate : '<a href="%src%">%type%</a> ',
fallbackTemplate : 'Su navegador no soporta VIDEO.<br>Por favor, descargue el fichero: %links%'
};
// v3
if (CKEDITOR.skins)
{
en = { video : en} ;
es = { video : es} ;
}
toolbar: 'Vídeo',
dialogTitle: 'Propiedades del vídeo',
fakeObject: 'Vídeo',
properties: 'Editar el vídeo',
widthRequired: 'La anchura no se puede dejar en blanco',
heightRequired: 'La altura no se puede dejar en blanco',
poster: 'Imagen de presentación',
sourceVideo: 'Archivo de vídeo',
sourceType: 'Tipo',
linkTemplate: '<a href="%src%">%type%</a> ',
fallbackTemplate: 'Su navegador no soporta el tag video.<br>Por favor, descargue el fichero: %links%',
infoLabel: 'Información',
html360: 'Esta funcionalidad (sólo MP4) todavía se encuentra en modo BETA.<br />Sólo funciona en páginas dinámicas, mas no dentro de documentos<br />creados en la herramienta de documentos o visualizados a través<br />de las lecciones.<br />Por favor no colocar más de un vídeo 360° en una misma página<br />ya que puede provocar conflictos y bloquearlos todos.',
video360: 'Habilitar reproductor de vídeo 360°',
video360stereo: 'Vídeo estéreo (relación de aspecto 1:1)'
};
var fr = {
toolbar: 'Vidéo',
dialogTitle: 'Propiétés de la vidéo',
fakeObject: 'Vidéo',
properties: 'Éditer la vidéo',
widthRequired: 'La largeur ne peut pas être vide',
heightRequired: 'La hauteur ne peut pas être vide',
poster: 'Image de prévisualisation',
sourceVideo: 'Fichier vidéo',
sourceType: 'Type',
linkTemplate: '<a href="%src%">%type%</a> ',
fallbackTemplate: 'Votre navigateur ne supporte pas le tag video.<br>Merci de télécharger la vidéo ici: %links%',
infoLabel: 'Information',
html360: 'Cette fonctionnalité (MP4 uniquement) est actuellement en mode BETA.<br />Elle ne fonctionne que sur les pages dynamiques, et pas<br />dans les documents créés à partir de l\'outil document ou visualisés<br />au travers de l\'outil parcours.<br />Merci de ne pas placer plus d\'une vidéo 360° par page. Cela<br />peut causer des conflits et toutes les rendre inactives.',
video360: 'Activer la visualisation 360°',
video360stereo: 'Vidéo stéréo (proportions 1:1 / apparence de 2 vidéos superposées)'
};
// v3
if (CKEDITOR.skins)
{
en = { video : en} ;
es = { video : es} ;
fr = { video : fr} ;
}
// Translations
CKEDITOR.plugins.setLang( 'video', 'en', en );
CKEDITOR.plugins.setLang( 'video', 'es', es );
CKEDITOR.plugins.setLang( 'video', 'fr', fr );
})();
})();

@ -1294,12 +1294,13 @@ class MessageManager
{
$table = Database::get_main_table(TABLE_MESSAGE);
$messageId = (int) $messageId;
$currentUserId = api_get_user_id();
if ($source == 'outbox') {
if (isset($messageId) && is_numeric($messageId)) {
$query = "SELECT * FROM $table
WHERE
user_sender_id = ".api_get_user_id()." AND
user_sender_id = ".$currentUserId." AND
id = $messageId AND
msg_status = ".MESSAGE_STATUS_OUTBOX;
$result = Database::query($query);
@ -1309,19 +1310,24 @@ class MessageManager
$query = "UPDATE $table SET
msg_status = '".MESSAGE_STATUS_NEW."'
WHERE
user_receiver_id=".api_get_user_id()." AND
user_receiver_id=".$currentUserId." AND
id='".$messageId."'";
Database::query($query);
$query = "SELECT * FROM $table
WHERE
msg_status<> ".MESSAGE_STATUS_OUTBOX." AND
user_receiver_id=".api_get_user_id()." AND
user_receiver_id=".$currentUserId." AND
id='".$messageId."'";
$result = Database::query($query);
}
}
$row = Database::fetch_array($result, 'ASSOC');
if (empty($row)) {
return '';
}
$user_sender_id = $row['user_sender_id'];
// get file attachments by message id

@ -1779,6 +1779,8 @@ class SessionManager
}
}
$sessionInfo = api_get_session_info($id_checked);
// Delete documents inside a session
$courses = self::getCoursesInSession($id_checked);
foreach ($courses as $courseId) {
@ -1834,7 +1836,7 @@ class SessionManager
Event::addEvent(
LOG_SESSION_DELETE,
LOG_SESSION_ID,
$id_checked,
$sessionInfo['name'].' - id:'.$id_checked,
api_get_utc_datetime(),
$userId
);

@ -168,7 +168,7 @@ class UrlManager
$table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
$orderBy = empty($orderBy) ? ' id ' : Database::escape_string($orderBy);
$sql = "SELECT id, url, description, active
$sql = "SELECT id, url, description, active, tms
FROM $table
ORDER BY $orderBy";

@ -11957,7 +11957,7 @@ EOD;
*/
public static function getCountCategories($courseId)
{
if (empty($course_id)) {
if (empty($courseId)) {
return 0;
}
$em = Database::getManager();

@ -34,6 +34,12 @@ if (empty($student_id)) {
// user info
$user_info = api_get_user_info($student_id);
$allowToQualify = api_is_allowed_to_edit(null, true) ||
api_is_course_tutor() ||
api_is_session_admin() ||
api_is_drh() ||
api_is_student_boss();
$allowedToTrackUser = true;
if (!api_is_session_admin() &&
!api_is_drh() &&
@ -1536,11 +1542,17 @@ if (empty($details)) {
if (Database::num_rows($result_last_attempt) > 0) {
$id_last_attempt = Database::result($result_last_attempt, 0, 0);
if ($count_attempts > 0) {
echo '<a href="../exercise/exercise_show.php?id='.$id_last_attempt.'&cidReq='.$course_code
$qualifyLink = '';
if ($allowToQualify) {
$qualifyLink = '&action=qualify';
}
$attemptLink = '../exercise/exercise_show.php?id='.$id_last_attempt.'&cidReq='.$course_code
.'&id_session='.$sessionId.'&session_id='.$sessionId.'&student='.$student_id.'&origin='
.(empty($origin) ? 'tracking' : $origin).'">'
.Display::return_icon('quiz.png')
.'</a>';
.(empty($origin) ? 'tracking' : $origin).$qualifyLink;
echo Display::url(
Display::return_icon('quiz.png', get_lang('Exercise')),
$attemptLink
);
}
}
echo '</td>';

@ -12,7 +12,7 @@
</div>
<div class="col-md-9">
{{ macro.panel('PersonalDataIntroductionTitle' | get_lang , 'PersonalDataIntroductionText' | get_lang) }}
{{ macro.panel('PersonalDataKeptOnYou' | get_lang, personal_data.data) }}
{{ display.collapse('', 'PersonalDataKeptOnYou' | get_lang, personal_data.data, false, 'false') }}
{% if personal_data.responsible %}
{{ macro.panel('PersonalDataResponsibleOrganizationTitle' | get_lang , personal_data.responsible ) }}

@ -6,9 +6,9 @@ namespace Chamilo\AdminBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
/**
* Class ApplicationSonataAdminBundle.
* Class ChamiloAdminBundle.
*
* @package Application\Sonata\AdminBundle
* @package Chamilo\AdminBundle
*/
class ChamiloAdminBundle extends Bundle
{

@ -120,6 +120,12 @@ class CourseResolver implements ResolverInterface, ContainerAwareInterface
}
});
if (!empty($args['type'])) {
$tools = array_filter($tools, function ($tool) use ($args) {
return $tool['name'] === $args['type'];
});
}
$ids = array_column($tools, 'iid');
$qb = $this->em->createQueryBuilder();

@ -39,3 +39,13 @@ ImageSize:
SIZE_HUGE:
description: 'Image in small size: 128px.'
value: '@=constant("ICON_SIZE_HUGE")'
CourseToolType:
type: enum
config:
description: 'One of the types of course tool'
values:
TOOL_DESCRIPTION:
value: '@=constant("TOOL_COURSE_DESCRIPTION")'
TOOL_ANNOUNCEMENT:
value: '@=constant("TOOL_ANNOUNCEMENT")'

@ -135,6 +135,10 @@ Course:
tools:
description: 'List of available tools for student view.'
type: '[CourseTool]'
args:
type:
description: 'Filter by one type of tool'
type: 'CourseToolType'
SessionCategory:
type: object
@ -191,27 +195,16 @@ Session:
type: '[Course]'
CourseTool:
type: interface
type: union
config:
description: 'A course tool.'
description: 'Course tools'
resolveType: '@=resolver("Chamilo\\ApiBundle\\GraphQL\\Resolver\\CourseToolResolver", [value])'
fields:
name:
type: 'String'
category:
type: 'String'
image:
type: 'String'
customIcon:
type: 'String'
isVisible:
type: 'Boolean'
types: [ToolDescription, ToolAnnouncements]
ToolDescription:
type: object
config:
description: 'Global summary of the course.'
interfaces: [CourseTool]
resolveField: '@=resolver("Chamilo\\ApiBundle\\GraphQL\\Resolver\\ToolDescriptionResolver", [value, args, info, context])'
fields:
name:
@ -246,7 +239,6 @@ ToolAnnouncements:
type: object
config:
description: 'Announcements related to the course.'
interfaces: [CourseTool]
resolveField: '@=resolver("Chamilo\\ApiBundle\\GraphQL\\Resolver\\ToolAnnouncementsResolver", [value, args, info, context])'
fields:
name:

@ -58,13 +58,6 @@ class CourseListener
$this->checkLimit($repo, $course, $url);
$this->toolChain->addToolsInCourse($course, $this->settingsManager);
}
/*
error_log('ddd');
$course->setDescription( ' dq sdqs dqs dqs ');
$args->getEntityManager()->persist($course);
$args->getEntityManager()->flush();*/
}
/**
@ -79,7 +72,6 @@ class CourseListener
{
if ($course) {
$url = $course->getCurrentUrl();
$repo = $args->getEntityManager()->getRepository('ChamiloCoreBundle:Course');
$this->checkLimit($repo, $course, $url);

@ -100,7 +100,7 @@ class ResourceFile
protected $resourceNode;
/**
* @var string
* @var bool
*
* @ORM\Column(name="enabled", type="boolean")
*/
@ -124,4 +124,224 @@ class ResourceFile
public function __construct()
{
}
/**
* @return mixed
*/
public function getName()
{
return $this->name;
}
/**
* @param mixed $name
*
* @return ResourceFile
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return string
*/
public function getHash(): string
{
return $this->hash;
}
/**
* @param string $hash
*
* @return ResourceFile
*/
public function setHash(string $hash): ResourceFile
{
$this->hash = $hash;
return $this;
}
/**
* @return string
*/
public function getOriginalFilename(): string
{
return $this->originalFilename;
}
/**
* @param string $originalFilename
*
* @return ResourceFile
*/
public function setOriginalFilename(string $originalFilename): ResourceFile
{
$this->originalFilename = $originalFilename;
return $this;
}
/**
* @return string
*/
public function getSize(): string
{
return $this->size;
}
/**
* @param string $size
*
* @return ResourceFile
*/
public function setSize(string $size): ResourceFile
{
$this->size = $size;
return $this;
}
/**
* @return string
*/
public function getWidth(): string
{
return $this->width;
}
/**
* @param string $width
*
* @return ResourceFile
*/
public function setWidth(string $width): ResourceFile
{
$this->width = $width;
return $this;
}
/**
* @return string
*/
public function getHeight(): string
{
return $this->height;
}
/**
* @param string $height
*
* @return ResourceFile
*/
public function setHeight(string $height): ResourceFile
{
$this->height = $height;
return $this;
}
/**
* @return string
*/
public function getCopyright(): string
{
return $this->copyright;
}
/**
* @param string $copyright
*
* @return ResourceFile
*/
public function setCopyright(string $copyright): ResourceFile
{
$this->copyright = $copyright;
return $this;
}
/**
* @return string
*/
public function getContentType(): string
{
return $this->contentType;
}
/**
* @param string $contentType
*
* @return ResourceFile
*/
public function setContentType(string $contentType): ResourceFile
{
$this->contentType = $contentType;
return $this;
}
/**
* @return string
*/
public function getExtension(): string
{
return $this->extension;
}
/**
* @param string $extension
*
* @return ResourceFile
*/
public function setExtension(string $extension): ResourceFile
{
$this->extension = $extension;
return $this;
}
/**
* @return ResourceNode
*/
public function getResourceNode(): ResourceNode
{
return $this->resourceNode;
}
/**
* @param ResourceNode $resourceNode
*
* @return ResourceFile
*/
public function setResourceNode(ResourceNode $resourceNode): ResourceFile
{
$this->resourceNode = $resourceNode;
return $this;
}
/**
* @return bool
*/
public function isEnabled(): bool
{
return $this->enabled;
}
/**
* @param bool $enabled
*
* @return ResourceFile
*/
public function setEnabled(bool $enabled): ResourceFile
{
$this->enabled = $enabled;
return $this;
}
}

@ -18,6 +18,11 @@ use Doctrine\ORM\Mapping as ORM;
*/
class ResourceLink implements ResourceInterface
{
public const VISIBILITY_DRAFT = 0;
public const VISIBILITY_PENDING = 1;
public const VISIBILITY_PUBLISHED = 2;
public const VISIBILITY_DELETED = 3;
/**
* @ORM\Id
* @ORM\Column(type="integer")
@ -26,7 +31,7 @@ class ResourceLink implements ResourceInterface
protected $id;
/**
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Resource\ResourceNode", inversedBy="links")
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Resource\ResourceNode", inversedBy="resourceLinks")
* @ORM\JoinColumn(name="resource_node_id", referencedColumnName="id")
*/
protected $resourceNode;
@ -67,18 +72,11 @@ class ResourceLink implements ResourceInterface
protected $resourceRight;
/**
* @var bool
*
* @ORM\Column(name="private", type="boolean", nullable=true, unique=false)
*/
protected $private;
/**
* @var bool
* @var int
*
* @ORM\Column(name="public", type="boolean", nullable=true, unique=false)
* @ORM\Column(name="visibility", type="integer", nullable=false)
*/
protected $public;
protected $visibility;
/**
* @ORM\Column(name="start_visibility_at", type="datetime", nullable=true)
@ -95,7 +93,7 @@ class ResourceLink implements ResourceInterface
*/
public function __construct()
{
$this->rights = new ArrayCollection();
$this->resourceRight = new ArrayCollection();
}
/**
@ -146,57 +144,17 @@ class ResourceLink implements ResourceInterface
return $this;
}
/**
* @return bool
*/
public function isPrivate()
{
return $this->private;
}
/**
* @param bool $private
*/
public function setPrivate($private)
{
$this->private = $private;
}
/**
* @return bool
*/
public function isPublic()
{
return $this->public;
}
/**
* @param bool $public
*/
public function setPublic($public)
{
$this->public = $public;
}
/**
* @return ArrayCollection
*/
public function getRights()
{
return $this->rights;
}
/**
* @param ArrayCollection $rights
*
* @return $this
*/
public function setRights(ArrayCollection $rights)
public function setResourceRight(ArrayCollection $rights)
{
$this->rights = new ArrayCollection();
$this->resourceRight = new ArrayCollection();
foreach ($rights as $right) {
$this->addRight($right);
$this->addResourceRight($right);
}
return $this;
@ -207,10 +165,10 @@ class ResourceLink implements ResourceInterface
*
* @return $this
*/
public function addRight(ResourceRight $right)
public function addResourceRight(ResourceRight $right)
{
$right->setResourceLink($this);
$this->rights[] = $right;
$this->resourceRight[] = $right;
return $this;
}
@ -349,6 +307,26 @@ class ResourceLink implements ResourceInterface
return $this->resourceNode;
}
/**
* @return int
*/
public function getVisibility(): int
{
return $this->visibility;
}
/**
* @param int $visibility
*
* @return ResourceLink
*/
public function setVisibility(int $visibility): ResourceLink
{
$this->visibility = $visibility;
return $this;
}
/**
* @return $this
*/

@ -3,7 +3,6 @@
namespace Chamilo\CoreBundle\Entity\Resource;
use Chamilo\CoreBundle\Entity\Tool;
use Chamilo\UserBundle\Entity\User;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
@ -30,11 +29,20 @@ class ResourceNode
/**
* @Gedmo\TreePathSource
*
* @ORM\Column()
*
* @Assert\NotBlank()
*/
protected $name;
/**
* @var string
*
* @ORM\Column(name="description", type="text", nullable = true)
*/
protected $description;
/**
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Resource\ResourceType", inversedBy="resourceNodes")
* @ORM\JoinColumn(name="resource_type_id", referencedColumnName="id")
@ -44,7 +52,7 @@ class ResourceNode
/**
* @ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\Resource\ResourceLink", mappedBy="resourceNode", cascade={"remove"})
*/
protected $links;
protected $resourceLinks;
/**
* @ORM\ManyToOne(
@ -58,6 +66,7 @@ class ResourceNode
/**
* @Gedmo\TreeParent
*
* @ORM\ManyToOne(
* targetEntity="Chamilo\CoreBundle\Entity\Resource\ResourceNode",
* inversedBy="children"
@ -114,7 +123,6 @@ class ResourceNode
*/
public function __construct()
{
$this->rights = new ArrayCollection();
$this->children = new ArrayCollection();
}
@ -154,6 +162,8 @@ class ResourceNode
public function setUpdatedAt(\DateTime $updatedAt = null)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
@ -170,6 +180,8 @@ class ResourceNode
public function setCreatedAt(\DateTime $createdAt = null)
{
$this->createdAt = $createdAt;
return $this;
}
/**
@ -180,30 +192,6 @@ class ResourceNode
return $this->createdAt;
}
/**
* Returns the tool.
*
* @return Tool
*/
public function getTool()
{
return $this->tool;
}
/**
* Returns the resource type.
*
* @param Tool $tool
*
* @return $this
*/
public function setTool(Tool $tool)
{
$this->tool = $tool;
return $this;
}
/**
* Returns the resource creator.
*
@ -372,22 +360,82 @@ class ResourceNode
}
/**
* @param $resource
* @return ResourceType
*/
public function getResourceType()
{
return $this->resourceType;
}
/**
* @param ResourceType $resourceType
*
* @return $this
* @return ResourceNode
*/
public function setResource($resource)
public function setResourceType($resourceType)
{
$this->resource = $resource;
$this->resourceType = $resourceType;
return $this;
}
/**
* @return ArrayCollection
* @return mixed
*/
public function getLinks()
public function getResourceLinks()
{
return $this->links;
return $this->resourceLinks;
}
/**
* @param mixed $resourceLinks
*
* @return ResourceNode
*/
public function setResourceLinks($resourceLinks)
{
$this->resourceLinks = $resourceLinks;
return $this;
}
/**
* @return ResourceFile
*/
public function getResourceFile(): ResourceFile
{
return $this->resourceFile;
}
/**
* @param ResourceFile $resourceFile
*
* @return ResourceNode
*/
public function setResourceFile(ResourceFile $resourceFile): ResourceNode
{
$this->resourceFile = $resourceFile;
return $this;
}
/**
* @return string
*/
public function getDescription(): string
{
return $this->description;
}
/**
* @param string $description
*
* @return ResourceNode
*/
public function setDescription(string $description): ResourceNode
{
$this->description = $description;
return $this;
}
}

@ -19,7 +19,7 @@ class ResourceRight
protected $id;
/**
* @ORM\OneToOne(targetEntity="Chamilo\CoreBundle\Entity\Resource\ResourceLink", inversedBy="rights")
* @ORM\OneToOne(targetEntity="Chamilo\CoreBundle\Entity\Resource\ResourceLink", inversedBy="resourceRight")
* @ORM\JoinColumn(name="resource_link_id", referencedColumnName="id")
*/
protected $resourceLink;

@ -56,4 +56,84 @@ class ResourceType
public function __construct()
{
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
*
* @return ResourceType
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
*
* @return ResourceType
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return Tool
*/
public function getTool()
{
return $this->tool;
}
/**
* @param Tool $tool
*
* @return ResourceType
*/
public function setTool($tool)
{
$this->tool = $tool;
return $this;
}
/**
* @return mixed
*/
public function getResourceNodes()
{
return $this->resourceNodes;
}
/**
* @param mixed $resourceNodes
*
* @return ResourceType
*/
public function setResourceNodes($resourceNodes)
{
$this->resourceNodes = $resourceNodes;
return $this;
}
}

@ -541,8 +541,8 @@ class Version20 extends AbstractMigrationChamilo
$this->addSql('CREATE TABLE resource_type (id INT AUTO_INCREMENT NOT NULL, tool_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, INDEX IDX_83FEF7938F7B22CC (tool_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT = DYNAMIC');
$this->addSql('CREATE TABLE resource_right (id INT AUTO_INCREMENT NOT NULL, resource_link_id INT DEFAULT NULL, role VARCHAR(255) NOT NULL, mask INT NOT NULL, UNIQUE INDEX UNIQ_C99C3BF9F004E599 (resource_link_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT = DYNAMIC');
$this->addSql('CREATE TABLE resource_link (id INT AUTO_INCREMENT NOT NULL, resource_node_id INT DEFAULT NULL, session_id INT DEFAULT NULL, user_id INT DEFAULT NULL, c_id INT DEFAULT NULL, group_id INT DEFAULT NULL, usergroup_id INT DEFAULT NULL, private TINYINT(1) DEFAULT NULL, public TINYINT(1) DEFAULT NULL, start_visibility_at DATETIME DEFAULT NULL, end_visibility_at DATETIME DEFAULT NULL, INDEX IDX_398C394B1BAD783F (resource_node_id), INDEX IDX_398C394B613FECDF (session_id), INDEX IDX_398C394BA76ED395 (user_id), INDEX IDX_398C394B91D79BD3 (c_id), INDEX IDX_398C394BFE54D947 (group_id), INDEX IDX_398C394BD2112630 (usergroup_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT = DYNAMIC');
$this->addSql('CREATE TABLE resource_node (id INT AUTO_INCREMENT NOT NULL, resource_type_id INT DEFAULT NULL, creator_id INT NOT NULL, parent_id INT DEFAULT NULL, resource_file_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, level INT DEFAULT NULL, path VARCHAR(3000) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, INDEX IDX_8A5F48FF98EC6B7B (resource_type_id), INDEX IDX_8A5F48FF61220EA6 (creator_id), INDEX IDX_8A5F48FF727ACA70 (parent_id), UNIQUE INDEX UNIQ_8A5F48FFCE6B9E84 (resource_file_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT = DYNAMIC');
$this->addSql('CREATE TABLE resource_link (id INT AUTO_INCREMENT NOT NULL, resource_node_id INT DEFAULT NULL, session_id INT DEFAULT NULL, user_id INT DEFAULT NULL, c_id INT DEFAULT NULL, group_id INT DEFAULT NULL, usergroup_id INT DEFAULT NULL, visibility INT NOT NULL, start_visibility_at DATETIME DEFAULT NULL, end_visibility_at DATETIME DEFAULT NULL, INDEX IDX_398C394B1BAD783F (resource_node_id), INDEX IDX_398C394B613FECDF (session_id), INDEX IDX_398C394BA76ED395 (user_id), INDEX IDX_398C394B91D79BD3 (c_id), INDEX IDX_398C394BFE54D947 (group_id), INDEX IDX_398C394BD2112630 (usergroup_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT = DYNAMIC');
$this->addSql('CREATE TABLE resource_node (id INT AUTO_INCREMENT NOT NULL, resource_type_id INT DEFAULT NULL, creator_id INT NOT NULL, parent_id INT DEFAULT NULL, resource_file_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, description LONGTEXT DEFAULT NULL, level INT DEFAULT NULL, path VARCHAR(3000) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, INDEX IDX_8A5F48FF98EC6B7B (resource_type_id), INDEX IDX_8A5F48FF61220EA6 (creator_id), INDEX IDX_8A5F48FF727ACA70 (parent_id), UNIQUE INDEX UNIQ_8A5F48FFCE6B9E84 (resource_file_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT = DYNAMIC');
$this->addSql('CREATE TABLE resource_file (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, original_filename VARCHAR(255) NOT NULL, size VARCHAR(255) NOT NULL, width VARCHAR(255) DEFAULT NULL, height VARCHAR(255) DEFAULT NULL, copyright VARCHAR(255) DEFAULT NULL, contentType VARCHAR(255) DEFAULT NULL, extension VARCHAR(255) NOT NULL, enabled TINYINT(1) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT = DYNAMIC');
$this->addSql('CREATE TABLE c_document (iid INT AUTO_INCREMENT NOT NULL, c_id INT DEFAULT NULL, session_id INT DEFAULT NULL, resource_node_id INT DEFAULT NULL, id INT DEFAULT NULL, path VARCHAR(255) NOT NULL, comment LONGTEXT DEFAULT NULL, title VARCHAR(255) DEFAULT NULL, filetype VARCHAR(10) NOT NULL, size INT NOT NULL, readonly TINYINT(1) NOT NULL, INDEX IDX_C9FA0CBD613FECDF (session_id), UNIQUE INDEX UNIQ_C9FA0CBD1BAD783F (resource_node_id), INDEX course (c_id), PRIMARY KEY(iid)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT = DYNAMIC');
$this->addSql('ALTER TABLE resource_type ADD CONSTRAINT FK_83FEF7938F7B22CC FOREIGN KEY (tool_id) REFERENCES tool (id)');

@ -19,6 +19,18 @@ class Version20170904145500 extends AbstractMigrationChamilo
public function up(Schema $schema)
{
$this->addSql('DELETE FROM c_group_rel_user WHERE user_id NOT IN (SELECT id FROM user)');
$this->addSql('DELETE FROM c_group_rel_user WHERE group_id NOT IN (SELECT iid FROM c_group_info)');
$this->addSql('ALTER TABLE c_group_rel_user ADD CONSTRAINT FK_C5D3D49FA76ED395 FOREIGN KEY (user_id) REFERENCES user (id)');
$this->addSql('ALTER TABLE c_group_rel_user ADD CONSTRAINT FK_C5D3D49FFE54D947 FOREIGN KEY (group_id) REFERENCES c_group_info (iid)');
$this->addSql('CREATE INDEX IDX_C5D3D49FA76ED395 ON c_group_rel_user (user_id)');
$this->addSql('CREATE INDEX IDX_C5D3D49FFE54D947 ON c_group_rel_user (group_id)');
$this->addSql('DELETE FROM c_group_rel_tutor WHERE user_id NOT IN (SELECT id FROM user)');
$this->addSql('DELETE FROM c_group_rel_tutor WHERE group_id NOT IN (SELECT iid FROM c_group_info)');
$this->addSql('ALTER TABLE c_group_rel_tutor ADD CONSTRAINT FK_F6FF71ABA76ED395 FOREIGN KEY (user_id) REFERENCES user (id)');
$this->addSql('ALTER TABLE c_group_rel_tutor ADD CONSTRAINT FK_F6FF71ABFE54D947 FOREIGN KEY (group_id) REFERENCES c_group_info (iid)');
$this->addSql('CREATE INDEX IDX_F6FF71ABA76ED395 ON c_group_rel_tutor (user_id)');
$this->addSql('CREATE INDEX IDX_F6FF71ABFE54D947 ON c_group_rel_tutor (group_id)');
}
/**

@ -86,7 +86,7 @@ class ResourceRepository extends EntityRepository
$resourceLink = new ResourceLink();
$resourceLink
->setResourceNode($resourceNode)
->addRight($right)
->addResourceRight($right)
->setPublic(true);
$this->getEntityManager()->persist($resourceLink);
@ -108,7 +108,7 @@ class ResourceRepository extends EntityRepository
$resourceLink
->setResourceNode($resourceNode)
->setCourse($course)
->addRight($right);
->addResourceRight($right);
$this->getEntityManager()->persist($resourceLink);
$this->getEntityManager()->flush();
@ -229,7 +229,7 @@ class ResourceRepository extends EntityRepository
$resourceLink
->setResourceNode($resourceNode)
->setUserGroup($group)
->addRight($right);
->addResourceRight($right);
return $resourceLink;
}

@ -5,6 +5,7 @@ namespace Chamilo\CourseBundle\Entity;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Traits\CourseTrait;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
@ -173,6 +174,20 @@ class CGroupInfo
*/
protected $course;
/**
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="Chamilo\CourseBundle\Entity\CGroupRelUser", mappedBy="group")
*/
protected $members;
/**
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="Chamilo\CourseBundle\Entity\CGroupRelTutor", mappedBy="group")
*/
protected $tutors;
/**
* Set name.
*
@ -600,4 +615,64 @@ class CGroupInfo
return $this;
}
/**
* @return int
*/
public function getDocAccess(): int
{
return $this->docAccess;
}
/**
* @param int $docAccess
*
* @return CGroupInfo
*/
public function setDocAccess(int $docAccess): CGroupInfo
{
$this->docAccess = $docAccess;
return $this;
}
/**
* @return ArrayCollection
*/
public function getMembers(): ArrayCollection
{
return $this->members;
}
/**
* @param ArrayCollection $members
*
* @return CGroupInfo
*/
public function setMembers(ArrayCollection $members): CGroupInfo
{
$this->members = $members;
return $this;
}
/**
* @return ArrayCollection
*/
public function getTutors(): ArrayCollection
{
return $this->tutors;
}
/**
* @param ArrayCollection $tutors
*
* @return CGroupInfo
*/
public function setTutors(ArrayCollection $tutors): CGroupInfo
{
$this->tutors = $tutors;
return $this;
}
}

@ -3,6 +3,7 @@
namespace Chamilo\CourseBundle\Entity;
use Chamilo\UserBundle\Entity\User;
use Doctrine\ORM\Mapping as ORM;
/**
@ -42,29 +43,31 @@ class CGroupRelTutor
protected $id;
/**
* @var int
* @var User
*
* @ORM\Column(name="user_id", type="integer", nullable=false)
* @ORM\ManyToOne(targetEntity="Chamilo\UserBundle\Entity\User", inversedBy="courseGroupsAsTutor")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
*/
protected $userId;
protected $user;
/**
* @var int
* @var CGroupInfo
*
* @ORM\Column(name="group_id", type="integer", nullable=false)
* @ORM\ManyToOne(targetEntity="Chamilo\CourseBundle\Entity\CGroupInfo", inversedBy="tutors")
* @ORM\JoinColumn(name="group_id", referencedColumnName="iid", nullable=false)
*/
protected $groupId;
protected $group;
/**
* Set userId.
*
* @param int $userId
* @param User $user
*
* @return CGroupRelTutor
*/
public function setUserId($userId)
public function setUser(User $user)
{
$this->userId = $userId;
$this->user = $user;
return $this;
}
@ -72,35 +75,35 @@ class CGroupRelTutor
/**
* Get userId.
*
* @return int
* @return User
*/
public function getUserId()
public function getUser()
{
return $this->userId;
return $this->user;
}
/**
* Set groupId.
* Set group.
*
* @param int $groupId
* @param CGroupInfo $group
*
* @return CGroupRelTutor
*/
public function setGroupId($groupId)
public function setGroup(CGroupInfo $group)
{
$this->groupId = $groupId;
$this->group = $group;
return $this;
}
/**
* Get groupId.
* Get group.
*
* @return int
* @return CGroupInfo
*/
public function getGroupId()
public function getGroup()
{
return $this->groupId;
return $this->group;
}
/**

@ -3,6 +3,7 @@
namespace Chamilo\CourseBundle\Entity;
use Chamilo\UserBundle\Entity\User;
use Doctrine\ORM\Mapping as ORM;
/**
@ -42,18 +43,20 @@ class CGroupRelUser
protected $id;
/**
* @var int
* @var User
*
* @ORM\Column(name="user_id", type="integer", nullable=false)
* @ORM\ManyToOne(targetEntity="Chamilo\UserBundle\Entity\User", inversedBy="courseGroupsAsMember")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
*/
protected $userId;
protected $user;
/**
* @var int
* @var CGroupInfo
*
* @ORM\Column(name="group_id", type="integer", nullable=false)
* @ORM\ManyToOne(targetEntity="Chamilo\CourseBundle\Entity\CGroupInfo", inversedBy="members")
* @ORM\JoinColumn(name="group_id", referencedColumnName="iid", nullable=false)
*/
protected $groupId;
protected $group;
/**
* @var int
@ -72,13 +75,13 @@ class CGroupRelUser
/**
* Set userId.
*
* @param int $userId
* @param int $user
*
* @return CGroupRelUser
*/
public function setUserId($userId)
public function setUser($user)
{
$this->userId = $userId;
$this->user = $user;
return $this;
}
@ -86,35 +89,35 @@ class CGroupRelUser
/**
* Get userId.
*
* @return int
* @return User
*/
public function getUserId()
public function getUser()
{
return $this->userId;
return $this->user;
}
/**
* Set groupId.
* Set group.
*
* @param int $groupId
* @param CGroupInfo $group
*
* @return CGroupRelUser
*/
public function setGroupId($groupId)
public function setGroup(CGroupInfo $group)
{
$this->groupId = $groupId;
$this->group = $group;
return $this;
}
/**
* Get groupId.
* Get group.
*
* @return int
* @return CGroupInfo
*/
public function getGroupId()
public function getGroup()
{
return $this->groupId;
return $this->group;
}
/**

@ -9,6 +9,11 @@ use Chamilo\CourseBundle\Entity\CGroupInfo;
use Chamilo\UserBundle\Entity\User;
use Sonata\CoreBundle\Model\BaseEntityManager;
/**
* Class AnnouncementManager.
*
* @package Chamilo\CourseBundle\Entity\Manager
*/
class AnnouncementManager extends BaseEntityManager
{
/**
@ -87,33 +92,36 @@ class AnnouncementManager extends BaseEntityManager
$extraGroupCondition";
}
} else {
$groupMemberships = \GroupManager::get_group_ids(
$course->getId(),
$user->getId()
);
$groupMemberships = $user->getCourseGroupsAsMemberFromCourse($course);
$tutoredGroups = $user->getCourseGroupsAsTutorFromCourse($course);
$memberships = array_merge($groupMemberships->toArray(), $tutoredGroups->toArray());
if (is_array($groupMemberships) && count($groupMemberships) > 0) {
if (!empty($memberships)) {
if ($allowUserEditSetting && !api_is_anonymous()) {
$parameters['memberships'] = $memberships;
$condUserId = " AND (
ip.lasteditUserId = ".$user->getId()." OR(
(ip.toUser = ".$user->getId()." OR ip.toUser IS NULL) OR
(ip.group IS NULL OR ip.group IN (0, ".implode(', ', $groupMemberships)."))
(ip.group IS NULL OR ip.group = 0 OR ip.group IN :memberships)
)
) ";
if (!empty($group)) {
unset($parameters['memberships']);
$condUserId = " AND (
ip.lasteditUserId = ".$user->getId()." OR ip.group IS NULL OR ip.group IN (0, ".$group->getId()
.")
) ".$extraGroupCondition;
}
} else {
$parameters['memberships'] = $memberships;
$condUserId = " AND (
(ip.toUser = ".$user->getId().") OR ip.toUser IS NULL) AND
(ip.group IS NULL OR ip.group IN (0, ".implode(', ', $groupMemberships)."))
(ip.group IS NULL OR ip.group = 0 OR ip.group IN :memberships)
) ";
if (!empty($group)) {
unset($parameters['memberships']);
$condUserId = " AND (
(ip.toUser = ".$user->getId().") OR ip.toUser IS NULL) AND
(ip.group IS NULL OR ip.group IN (0, ".$group->getId()."))

@ -126,6 +126,8 @@ services:
- calendar/agenda.php
- agenda.gif
- chamilo_course.settings.agenda
- [calendar_event, calendar_event_attachment]
-
tags:
- {name: chamilo_course.tool}
@ -144,6 +146,8 @@ services:
- announcements/announcements.php
- valves.gif
- chamilo_course.settings.announcement
- [announcement]
-
tags:
- {name: chamilo_course.tool}
@ -161,6 +165,8 @@ services:
- work/work.php
- works.gif
- chamilo_course.settings.assignment
- [work]
-
tags:
- {name: chamilo_course.tool}
@ -178,6 +184,8 @@ services:
- attendance/index.php
- attendance.gif
- '@chamilo_course.settings.attendance'
- [attendance]
-
tags:
- {name: chamilo_course.tool}
@ -195,6 +203,8 @@ services:
- blog/blog_admin.php
- blog_admin.gif
- '@chamilo_course.settings.blog'
- [blog_management]
-
tags:
- {name: chamilo_course.tool}
@ -212,6 +222,8 @@ services:
- course_description/index.php
- info.gif
- '@chamilo_course.settings.course_description'
- [course_description]
-
tags:
- {name: chamilo_course.tool}
@ -229,6 +241,8 @@ services:
- chat/chat.php
- chat.gif
- '@chamilo_course.settings.chat'
-
-
tags:
- {name: chamilo_course.tool}
@ -246,7 +260,8 @@ services:
- course_progress/index.php
- course_progress.gif
- '@chamilo_course.settings.course_progress'
- [thematic, thematic_advance, thematic_plan]
-
tags:
- {name: chamilo_course.tool}
@ -264,6 +279,8 @@ services:
- document/document.php
- folder_document.gif
- '@chamilo_course.settings.document'
- [document]
-
tags:
- {name: chamilo_course.tool}
@ -281,7 +298,8 @@ services:
- dropbox/index.php
- dropbox.gif
- '@chamilo_course.settings.dropbox'
- [dropbox]
-
tags:
- {name: chamilo_course.tool}
@ -299,7 +317,8 @@ services:
- exercise/exercise.php
- quiz.gif
- '@chamilo_course.settings.exercise'
- [quiz, test_category]
-
tags:
- {name: chamilo_course.tool}
@ -317,7 +336,8 @@ services:
- forum/index.php
- forum.gif
- '@chamilo_course.settings.forum'
- [forum, forum_attachment, forum_category, forum_post, forum_thread]
-
tags:
- {name: chamilo_course.tool}
@ -335,7 +355,8 @@ services:
- glossary/index.php
- glossary.gif
- '@chamilo_course.settings.glossary'
- [glossary]
-
tags:
- {name: chamilo_course.tool}
@ -353,7 +374,8 @@ services:
- gradebook/index.php
- gradebook.gif
- '@chamilo_course.settings.gradebook'
-
-
tags:
- {name: chamilo_course.tool}
@ -371,7 +393,8 @@ services:
- group/group.php
- group.gif
- '@chamilo_course.settings.group'
-
-
tags:
- {name: chamilo_course.tool}
@ -389,6 +412,8 @@ services:
- lp/lp_controller.php
- scorms.gif
- '@chamilo_course.settings.learning_path'
- [learnpath, learnpath_category]
-
tags:
- {name: chamilo_course.tool}
@ -406,7 +431,8 @@ services:
- link/link.php
- links.gif
- '@chamilo_course.settings.link'
- [link, link_category]
-
tags:
- {name: chamilo_course.tool}
@ -429,6 +455,8 @@ services:
- course_info/maintenance.php
- backup.gif
- '@chamilo_course.settings.maintenance'
-
-
tags:
- {name: chamilo_course.tool}
@ -446,6 +474,8 @@ services:
- notebook/index.php
- notebook.gif
- '@chamilo_course.settings.notebook'
- [notebook]
-
tags:
- {name: chamilo_course.tool}
@ -457,7 +487,8 @@ services:
- course_info/infocours.php
- reference.gif
- '@chamilo_course.settings.settings'
-
-
tags:
- {name: chamilo_course.tool}
@ -466,7 +497,7 @@ services:
class: Chamilo\CourseBundle\Settings\SettingsCourseSettingsSchema
tags:
- {name: chamilo_course.settings_schema, alias: chamilo_course.settings.settings, namespace: settings}
# Survey
# Survey
chamilo_course.tool.survey:
class: Chamilo\CourseBundle\Tool\Survey
arguments:
@ -475,6 +506,8 @@ services:
- survey/survey_list.php
- survey.gif
- '@chamilo_course.settings.survey'
- [survey]
-
tags:
- {name: chamilo_course.tool}
@ -491,7 +524,8 @@ services:
- tracking/courseLog.php
- statistics.gif
- '@chamilo_course.settings.tracking'
-
-
tags:
- {name: chamilo_course.tool}
@ -509,7 +543,8 @@ services:
- user/user.php
- members.gif
- '@chamilo_course.settings.user'
-
-
tags:
- {name: chamilo_course.tool}
# Course settings
@ -526,7 +561,8 @@ services:
- wiki/index.php
- wiki.gif
- '@chamilo_course.settings.wiki'
- [wiki]
-
tags:
- {name: chamilo_course.tool}

@ -22,6 +22,7 @@ abstract class BaseTool implements ToolInterface
protected $courseSettings;
protected $platformSettings;
protected $manager;
protected $types;
/**
* @param string $name
@ -30,7 +31,7 @@ abstract class BaseTool implements ToolInterface
* @param string $image
* @param $courseSettings
*/
public function __construct($name, $category, $link, $image, $courseSettings, $manager = null)
public function __construct($name, $category, $link, $image, $courseSettings, $types, $manager = null)
{
$this->name = $name;
$this->category = $category;
@ -38,7 +39,7 @@ abstract class BaseTool implements ToolInterface
$this->image = $image;
$this->admin = 0;
$this->courseSettings = $courseSettings;
$this->manager = $manager;
$this->types = $types;
}
/**
@ -106,6 +107,8 @@ abstract class BaseTool implements ToolInterface
}
/**
* @param $settings
*
* @return int
*/
public function setCourseSettings($settings)
@ -121,6 +124,22 @@ abstract class BaseTool implements ToolInterface
return $this->courseSettings;
}
/**
* @param string $type
*/
public function addType($type)
{
$this->types[] = $type;
}
/**
* @return array
*/
public function getTypes()
{
return $this->types;
}
/**
* {@inheritdoc}
*/

@ -4,6 +4,7 @@
namespace Chamilo\CourseBundle;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\Resource\ResourceType;
use Chamilo\CoreBundle\Entity\Tool;
use Chamilo\CoreBundle\Entity\ToolResourceRight;
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
@ -11,6 +12,7 @@ use Chamilo\CourseBundle\Entity\CTool;
use Chamilo\CourseBundle\Tool\BaseTool;
use Chamilo\SettingsBundle\Manager\SettingsManager;
use Doctrine\Common\Persistence\ObjectManager;
use Sonata\AdminBundle\Form\Type\ModelReferenceType;
/**
* Class ToolChain.
@ -89,6 +91,17 @@ class ToolChain
;
$this->setToolPermissions($toolEntity);
$manager->persist($toolEntity);
$types = $tool->getTypes();
if (!empty($types)) {
foreach ($types as $type) {
$resourceType = new ResourceType();
$resourceType->setName($type);
$resourceType->setTool($toolEntity);
$manager->persist($resourceType);
}
}
$manager->flush();
}
}

@ -50,30 +50,30 @@
</li>
{% endmacro %}
{% macro collapse(name, title, content, list = false) %}
{% macro collapse(name, title, content, list = false, expanded = 'true') %}
{% autoescape false %}
<div class="panel-group" id="{{ name }}" role="tablist" aria-multiselectable="true">
<div class="panel panel-default" id="{{ name }}_block">
<div class="panel-heading" role="tab">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#{{ name }}" href="#{{ name }}Collapse" aria-expanded="true" aria-controls="{{ name }}Collapse">
{{ title }}
</a>
</h4>
</div>
<div style="" aria-expanded="true" id="{{ name }}Collapse" class="panel-collapse collapse in" role="tabpanel">
<div class="panel-body">
{% if list %}
<ul class="nav nav-pills nav-stacked">
{{ content }}
</ul>
{% else %}
<div class="panel-group" id="{{ name }}" role="tablist" aria-multiselectable="true">
<div class="panel panel-default" id="{{ name }}_block">
<div class="panel-heading" role="tab">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#{{ name }}" href="#{{ name }}Collapse" aria-expanded="{{ expanded }}" aria-controls="{{ name }}Collapse">
{{ title }}
</a>
</h4>
</div>
<div style="" aria-expanded="{{ expanded }}" id="{{ name }}Collapse" class="panel-collapse collapse {{ expanded == 'true' ? 'in' : '' }}" role="tabpanel">
<div class="panel-body">
{% if list %}
<ul class="nav nav-pills nav-stacked">
{{ content }}
{% endif %}
</div>
</ul>
{% else %}
{{ content }}
{% endif %}
</div>
</div>
</div>
</div>
{% endautoescape %}
{% endmacro %}

@ -6,10 +6,12 @@ namespace Chamilo\UserBundle\Entity;
//use Chamilo\CoreBundle\Entity\UserFieldValues;
use Chamilo\CoreBundle\Entity\AccessUrl;
use Chamilo\CoreBundle\Entity\AccessUrlRelUser;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\Skill;
use Chamilo\CoreBundle\Entity\UsergroupRelUser;
use Chamilo\ThemeBundle\Model\UserInterface as ThemeUser;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Mapping as ORM;
//use FOS\UserBundle\Model\GroupInterface;
@ -133,12 +135,14 @@ class User extends BaseUser implements ThemeUser, EquatableInterface //implement
/**
* @var bool
*
* @ORM\Column(name="locked", type="boolean")
*/
protected $locked;
/**
* @var bool
*
* @ORM\Column(name="enabled", type="boolean")
*/
//protected $enabled;
@ -157,12 +161,14 @@ class User extends BaseUser implements ThemeUser, EquatableInterface //implement
/**
* @var \DateTime
*
* @ORM\Column(name="credentials_expire_at", type="datetime", nullable=true, unique=false)
*/
protected $credentialsExpireAt;
/**
* @var \DateTime
*
* @ORM\Column(name="expires_at", type="datetime", nullable=true, unique=false)
*/
protected $expiresAt;
@ -467,6 +473,20 @@ class User extends BaseUser implements ThemeUser, EquatableInterface //implement
*/
private $receivedMessages;
/**
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="Chamilo\CourseBundle\Entity\CGroupRelUser", mappedBy="user")
*/
protected $courseGroupsAsMember;
/**
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="Chamilo\CourseBundle\Entity\CGroupRelTutor", mappedBy="user")
*/
protected $courseGroupsAsTutor;
/**
* Constructor.
*/
@ -495,6 +515,9 @@ class User extends BaseUser implements ThemeUser, EquatableInterface //implement
$this->expired = false;
$this->roles = [];
$this->credentialsExpired = false;
$this->courseGroupsAsMember = new ArrayCollection();
$this->courseGroupsAsTutor = new ArrayCollection();
}
/**
@ -1931,4 +1954,50 @@ class User extends BaseUser implements ThemeUser, EquatableInterface //implement
{
return $this->receivedMessages;
}
/**
* @return ArrayCollection
*/
public function getCourseGroupsAsMember(): ArrayCollection
{
return $this->courseGroupsAsMember;
}
/**
* @return ArrayCollection
*/
public function getCourseGroupsAsTutor(): ArrayCollection
{
return $this->courseGroupsAsTutor;
}
/**
* @param Course $course
*
* @return ArrayCollection
*/
public function getCourseGroupsAsMemberFromCourse(Course $course): ArrayCollection
{
$criteria = Criteria::create();
$criteria->where(
Criteria::expr()->eq('cId', $course)
);
return $this->courseGroupsAsMember->matching($criteria);
}
/**
* @param Course $course
*
* @return ArrayCollection
*/
public function getCourseGroupsAsTutorFromCourse(Course $course): ArrayCollection
{
$criteria = Criteria::create();
$criteria->where(
Criteria::expr()->eq('cId', $course->getId())
);
return $this->courseGroupsAsTutor->matching($criteria);
}
}

@ -877,7 +877,7 @@ class UserRepository extends EntityRepository
foreach ($result as $item) {
$list = [
'Course # '.$item->getCId(),
'Group #'.$item->getGroupId(),
'Group #'.$item->getGroup()->getId(),
'Role: '.$item->getStatus(),
];
$cGroupRelUser[] = implode(', ', $list);

@ -0,0 +1,141 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Resource\ResourceNode;
use Chamilo\CoreBundle\Entity\Resource\ResourceLink;
use Chamilo\CoreBundle\Entity\Resource\ResourceFile;
use Chamilo\CoreBundle\Entity\Resource\ResourceRight;
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
require_once __DIR__.'/../../main/inc/global.inc.php';
$sql = "SELECT * FROM c_item_property WHERE tool = 'document' LIMIT 1";
$result = Database::query($sql);
while ($row = Database::fetch_array($result, 'ASSOC')) {
$row['iid'];
$courseId = $row['c_id'];
$sessionId = $row['session_id'];
$groupId = $row['to_group_id'];
$toUserId = $row['to_user_id'];
$toUser = api_get_user_entity($toUserId);
$author = api_get_user_entity($row['insert_user_id']);
$createdAt = api_get_utc_datetime($row['insert_date'], true, true);
$lastUpdatedAt = api_get_utc_datetime($row['lastedit_date'], true, true);
$em = Database::getManager();
switch ($row['tool']) {
case 'document':
$course = api_get_course_entity($courseId);
$session = api_get_course_entity($sessionId);
$group = api_get_group_entity($groupId);
$documentData = DocumentManager::get_document_data_by_id($row['ref'], $course->getCode(), $sessionId);
if (!$documentData) {
error_log('Skipped');
continue 2;
}
$file = new ResourceFile();
$file
->setName($documentData['title'])
->setOriginalFilename(basename($documentData['path']))
->setSize($documentData['size'])
;
$resourceType = $em->getRepository('ChamiloCoreBundle:ResourceType')->findOneBy(['name' => 'document']);
$node = new ResourceNode();
$node
->setName($documentData['title'])
->setDescription($documentData['comment'])
->setResourceFile($file)
->setCreator($author)
->setResourceFile($file)
->setResourceType($resourceType)
->setCreatedAt($createdAt)
->setUpdatedAt($lastUpdatedAt)
;
$em->persist($node);
$em->flush();
$rights = [];
switch ($row['visibility']) {
case '0':
$newVisibility = ResourceLink::VISIBILITY_DRAFT;
$readerMask = ResourceNodeVoter::getReaderMask();
$editorMask = ResourceNodeVoter::getEditorMask();
$resourceRight = new ResourceRight();
$resourceRight
->setMask($editorMask)
->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
;
$rights[] = $resourceRight;
break;
case '1':
$newVisibility = ResourceLink::VISIBILITY_PUBLISHED;
break;
case '2':
$newVisibility = ResourceLink::VISIBILITY_DELETED;
break;
}
$link = new ResourceLink();
$link
->setCourse($course)
->setSession($session)
->setGroup($group)
->setUser($toUser)
->setResourceNode($node)
->setVisibility($newVisibility)
;
if (!empty($rights)) {
foreach ($rights as $right) {
$link->addResourceRight($right);
}
}
$em->persist($link);
$em->flush();
break;
}
}
/**
default resource type list
| announcement |
| attendance |
| blog_management |
| calendar_event |
| calendar_event_attachment |
| course_description |
| document |
| dropbox |
| forum |
| forum_attachment |
| forum_category |
| forum_post |
| forum_thread |
| glossary |
| learnpath |
| learnpath_category |
| link |
| link_category |
| notebook |
| quiz |
| survey |
| test_category |
| thematic |
| thematic_advance |
| thematic_plan |
| wiki |
| work |
*/
Loading…
Cancel
Save