course_edit.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CoreBundle\Entity\CourseCategory;
  4. use Chamilo\CoreBundle\Repository\CourseCategoryRepository;
  5. use Chamilo\UserBundle\Entity\User;
  6. /**
  7. * @package chamilo.admin
  8. */
  9. $cidReset = true;
  10. require_once __DIR__.'/../inc/global.inc.php';
  11. $this_section = SECTION_PLATFORM_ADMIN;
  12. api_protect_admin_script();
  13. $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
  14. $em = Database::getManager();
  15. /** @var CourseCategoryRepository $courseCategoriesRepo */
  16. $courseCategoriesRepo = $em->getRepository('ChamiloCoreBundle:CourseCategory');
  17. // Get all possible teachers.
  18. $urlId = api_get_current_access_url_id();
  19. $courseId = isset($_GET['id']) ? $_GET['id'] : null;
  20. if (empty($courseId)) {
  21. api_not_allowed(true);
  22. }
  23. $courseInfo = api_get_course_info_by_id($courseId);
  24. if (empty($courseInfo)) {
  25. api_not_allowed(true);
  26. }
  27. $tool_name = get_lang('Edit course information');
  28. $interbreadcrumb[] = ["url" => 'index.php', "name" => get_lang('Administration')];
  29. $interbreadcrumb[] = ["url" => "course_list.php", "name" => get_lang('Course list')];
  30. // Get all course categories
  31. $table_user = Database::get_main_table(TABLE_MAIN_USER);
  32. $course_code = $courseInfo['code'];
  33. $courseId = $courseInfo['real_id'];
  34. // Get course teachers
  35. $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
  36. $order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname' : ' ORDER BY lastname, firstname';
  37. $sql = "SELECT user.user_id,lastname,firstname
  38. FROM $table_user as user,$table_course_user as course_user
  39. WHERE
  40. course_user.status='1' AND
  41. course_user.user_id=user.user_id AND
  42. course_user.c_id ='".$courseId."'".
  43. $order_clause;
  44. $res = Database::query($sql);
  45. $course_teachers = [];
  46. while ($obj = Database::fetch_object($res)) {
  47. $course_teachers[] = $obj->user_id;
  48. }
  49. // Get all possible teachers without the course teachers
  50. if (api_is_multiple_url_enabled()) {
  51. $access_url_rel_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
  52. $sql = "SELECT u.user_id,lastname,firstname
  53. FROM $table_user as u
  54. INNER JOIN $access_url_rel_user_table url_rel_user
  55. ON (u.user_id=url_rel_user.user_id)
  56. WHERE
  57. url_rel_user.access_url_id = $urlId AND
  58. status = 1".$order_clause;
  59. } else {
  60. $sql = "SELECT user_id, lastname, firstname
  61. FROM $table_user WHERE status='1'".$order_clause;
  62. }
  63. $courseInfo['tutor_name'] = null;
  64. $res = Database::query($sql);
  65. $teachers = [];
  66. $allTeachers = [];
  67. $platform_teachers[0] = '-- '.get_lang('No administrator').' --';
  68. while ($obj = Database::fetch_object($res)) {
  69. $allTeachers[$obj->user_id] = api_get_person_name($obj->firstname, $obj->lastname);
  70. if (!array_key_exists($obj->user_id, $course_teachers)) {
  71. $teachers[$obj->user_id] = api_get_person_name($obj->firstname, $obj->lastname);
  72. }
  73. if (isset($course_teachers[$obj->user_id]) &&
  74. $courseInfo['tutor_name'] == $course_teachers[$obj->user_id]
  75. ) {
  76. $courseInfo['tutor_name'] = $obj->user_id;
  77. }
  78. // We add in the array platform teachers
  79. $platform_teachers[$obj->user_id] = api_get_person_name($obj->firstname, $obj->lastname);
  80. }
  81. // Case where there is no teacher in the course
  82. if (count($course_teachers) == 0) {
  83. $sql = 'SELECT tutor_name FROM '.$course_table.' WHERE code="'.$course_code.'"';
  84. $res = Database::query($sql);
  85. $tutor_name = Database::result($res, 0, 0);
  86. $courseInfo['tutor_name'] = array_search($tutor_name, $platform_teachers);
  87. }
  88. // Build the form
  89. $form = new FormValidator(
  90. 'update_course',
  91. 'post',
  92. api_get_self().'?id='.$courseId
  93. );
  94. $form->addElement('header', get_lang('Course').' #'.$courseInfo['real_id'].' '.$course_code);
  95. $form->addElement('hidden', 'code', $course_code);
  96. //title
  97. $form->addText('title', get_lang('Title'), true);
  98. $form->applyFilter('title', 'html_filter');
  99. $form->applyFilter('title', 'trim');
  100. // Code
  101. $element = $form->addElement(
  102. 'text',
  103. 'real_code',
  104. [get_lang('Code'), get_lang('This value can\'t be changed.')]
  105. );
  106. $element->freeze();
  107. // Visual code
  108. $form->addText(
  109. 'visual_code',
  110. [
  111. get_lang('visual code'),
  112. get_lang('Only letters (a-z) and numbers (0-9)'),
  113. get_lang('This value is used in the course URL'),
  114. ],
  115. true,
  116. [
  117. 'maxlength' => CourseManager::MAX_COURSE_LENGTH_CODE,
  118. 'pattern' => '[a-zA-Z0-9]+',
  119. 'title' => get_lang('Only letters (a-z) and numbers (0-9)'),
  120. ]
  121. );
  122. $form->applyFilter('visual_code', 'strtoupper');
  123. $form->applyFilter('visual_code', 'html_filter');
  124. $countCategories = $courseCategoriesRepo->countAllInAccessUrl(
  125. $urlId,
  126. api_get_configuration_value('allow_base_course_category')
  127. );
  128. if ($countCategories >= 100) {
  129. // Category code
  130. $url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=search_category';
  131. $categorySelect = $form->addElement(
  132. 'select_ajax',
  133. 'category_code',
  134. get_lang('Category'),
  135. null,
  136. ['url' => $url]
  137. );
  138. if (!empty($courseInfo['categoryCode'])) {
  139. $data = \CourseCategory::getCategory($courseInfo['categoryCode']);
  140. $categorySelect->addOption($data['name'], $data['code']);
  141. }
  142. } else {
  143. $courseInfo['category_code'] = $courseInfo['categoryCode'];
  144. $categories = $courseCategoriesRepo->findAllInAccessUrl(
  145. $urlId,
  146. api_get_configuration_value('allow_base_course_category')
  147. );
  148. $categoriesOptions = [null => get_lang('none')];
  149. /** @var CourseCategory $category */
  150. foreach ($categories as $category) {
  151. $categoriesOptions[$category->getCode()] = (string) $category;
  152. }
  153. $form->addSelect(
  154. 'category_code',
  155. get_lang('Category'),
  156. $categoriesOptions
  157. );
  158. }
  159. $courseTeacherNames = [];
  160. foreach ($course_teachers as $courseTeacherId) {
  161. /** @var User $courseTeacher */
  162. $courseTeacher = UserManager::getRepository()->find($courseTeacherId);
  163. $courseTeacherNames[$courseTeacher->getUserId()] = UserManager::formatUserFullName($courseTeacher, true);
  164. }
  165. $form->addSelectAjax(
  166. 'course_teachers',
  167. get_lang('Teachers'),
  168. $courseTeacherNames,
  169. ['url' => api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=teacher_to_basis_course', 'multiple' => 'multiple']
  170. );
  171. $courseInfo['course_teachers'] = $course_teachers;
  172. if (array_key_exists('add_teachers_to_sessions_courses', $courseInfo)) {
  173. $form->addElement(
  174. 'checkbox',
  175. 'add_teachers_to_sessions_courses',
  176. null,
  177. get_lang('Teachers will be added as a coach in all course sessions.')
  178. );
  179. }
  180. $allowEditSessionCoaches = api_get_configuration_value('disabled_edit_session_coaches_course_editing_course') === false;
  181. $coursesInSession = SessionManager::get_session_by_course($courseInfo['real_id']);
  182. if (!empty($coursesInSession) && $allowEditSessionCoaches) {
  183. foreach ($coursesInSession as $session) {
  184. $sessionId = $session['id'];
  185. $coaches = SessionManager::getCoachesByCourseSession(
  186. $sessionId,
  187. $courseInfo['real_id']
  188. );
  189. $teachers = $allTeachers;
  190. $sessionTeachers = [];
  191. foreach ($coaches as $coachId) {
  192. $sessionTeachers[] = $coachId;
  193. if (isset($teachers[$coachId])) {
  194. unset($teachers[$coachId]);
  195. }
  196. }
  197. $groupName = 'session_coaches_'.$sessionId;
  198. $sessionUrl = api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$sessionId;
  199. $form->addElement(
  200. 'advmultiselect',
  201. $groupName,
  202. Display::url(
  203. $session['name'],
  204. $sessionUrl,
  205. ['target' => '_blank']
  206. ).' - '.get_lang('Coaches'),
  207. $allTeachers
  208. );
  209. $courseInfo[$groupName] = $sessionTeachers;
  210. }
  211. }
  212. $form->addText('department_name', get_lang('Department'), false, ['size' => '60']);
  213. $form->applyFilter('department_name', 'html_filter');
  214. $form->applyFilter('department_name', 'trim');
  215. $form->addText('department_url', get_lang('DepartmentURL'), false, ['size' => '60']);
  216. $form->applyFilter('department_url', 'html_filter');
  217. $form->applyFilter('department_url', 'trim');
  218. $form->addSelectLanguage('course_language', get_lang('Course language'));
  219. $group = [];
  220. $group[] = $form->createElement('radio', 'visibility', get_lang("Course access"), get_lang('Public - access allowed for the whole world'), COURSE_VISIBILITY_OPEN_WORLD);
  221. $group[] = $form->createElement('radio', 'visibility', null, get_lang(' Open - access allowed for users registered on the platform'), COURSE_VISIBILITY_OPEN_PLATFORM);
  222. $group[] = $form->createElement('radio', 'visibility', null, get_lang('Private access (access authorized to group members only)'), COURSE_VISIBILITY_REGISTERED);
  223. $group[] = $form->createElement('radio', 'visibility', null, get_lang('Closed - the course is only accessible to the teachers'), COURSE_VISIBILITY_CLOSED);
  224. $group[] = $form->createElement('radio', 'visibility', null, get_lang('Hidden - Completely hidden to all users except the administrators'), COURSE_VISIBILITY_HIDDEN);
  225. $form->addGroup($group, '', get_lang('Course access'));
  226. $group = [];
  227. $group[] = $form->createElement('radio', 'subscribe', get_lang('Subscription'), get_lang('Allowed'), 1);
  228. $group[] = $form->createElement('radio', 'subscribe', null, get_lang('This function is only available to trainers'), 0);
  229. $form->addGroup($group, '', get_lang('Subscription'));
  230. $group = [];
  231. $group[] = $form->createElement('radio', 'unsubscribe', get_lang('Unsubscribe'), get_lang('Users are allowed to unsubscribe from this course'), 1);
  232. $group[] = $form->createElement('radio', 'unsubscribe', null, get_lang('NotUsers are allowed to unsubscribe from this course'), 0);
  233. $form->addGroup($group, '', get_lang('Unsubscribe'));
  234. $form->addElement('text', 'disk_quota', [get_lang('Disk Space'), null, get_lang('MB')]);
  235. $form->addRule('disk_quota', get_lang('Required field'), 'required');
  236. $form->addRule('disk_quota', get_lang('This field should be numeric'), 'numeric');
  237. // Extra fields
  238. $extra_field = new ExtraField('course');
  239. $extra = $extra_field->addElements(
  240. $form,
  241. $courseId,
  242. [],
  243. false,
  244. false,
  245. [],
  246. [],
  247. [],
  248. false,
  249. true
  250. );
  251. $htmlHeadXtra[] = '
  252. <script>
  253. $(function() {
  254. '.$extra['jquery_ready_content'].'
  255. });
  256. </script>';
  257. $form->addButtonUpdate(get_lang('Edit course information'));
  258. // Set some default values
  259. $courseInfo['disk_quota'] = round(DocumentManager::get_course_quota($courseInfo['code']) / 1024 / 1024, 1);
  260. $courseInfo['real_code'] = $courseInfo['code'];
  261. $courseInfo['add_teachers_to_sessions_courses'] = isset($courseInfo['add_teachers_to_sessions_courses']) ? $courseInfo['add_teachers_to_sessions_courses'] : 0;
  262. $form->setDefaults($courseInfo);
  263. // Validate form
  264. if ($form->validate()) {
  265. $course = $form->getSubmitValues();
  266. $visibility = $course['visibility'];
  267. global $_configuration;
  268. if (isset($_configuration[$urlId]) &&
  269. isset($_configuration[$urlId]['hosting_limit_active_courses']) &&
  270. $_configuration[$urlId]['hosting_limit_active_courses'] > 0
  271. ) {
  272. // Check if
  273. if ($courseInfo['visibility'] == COURSE_VISIBILITY_HIDDEN &&
  274. $visibility != $courseInfo['visibility']
  275. ) {
  276. $num = CourseManager::countActiveCourses($urlId);
  277. if ($num >= $_configuration[$urlId]['hosting_limit_active_courses']) {
  278. api_warn_hosting_contact('hosting_limit_active_courses');
  279. Display::addFlash(
  280. Display::return_message(get_lang('Sorry, this installation has an active courses limit, which has now been reached. You can still create new courses, but only if you hide/disable at least one existing active course. To do this, edit a course from the administration courses list, and change the visibility to \'hidden\', then try creating this course again. To increase the maximum number of active courses allowed on this Chamilo installation, please contact your hosting provider or, if available, upgrade to a superior hosting plan.'))
  281. );
  282. header('Location: course_list.php');
  283. exit;
  284. }
  285. }
  286. }
  287. $visual_code = $course['visual_code'];
  288. $visual_code = CourseManager::generate_course_code($visual_code);
  289. // Check if the visual code is already used by *another* course
  290. $visual_code_is_used = false;
  291. $warn = get_lang('TheFollowingCoursesAlreadyUseThisvisual code');
  292. if (!empty($visual_code)) {
  293. $list = CourseManager::get_courses_info_from_visual_code($visual_code);
  294. foreach ($list as $course_temp) {
  295. if ($course_temp['code'] != $course_code) {
  296. $visual_code_is_used = true;
  297. $warn .= ' '.$course_temp['title'].' ('.$course_temp['code'].'),';
  298. }
  299. }
  300. $warn = substr($warn, 0, -1);
  301. }
  302. $teachers = isset($course['course_teachers']) ? $course['course_teachers'] : '';
  303. $title = $course['title'];
  304. $category_code = isset($course['category_code']) ? $course['category_code'] : '';
  305. $department_name = $course['department_name'];
  306. $department_url = $course['department_url'];
  307. $course_language = $course['course_language'];
  308. $course['disk_quota'] = $course['disk_quota'] * 1024 * 1024;
  309. $disk_quota = $course['disk_quota'];
  310. $subscribe = $course['subscribe'];
  311. $unsubscribe = $course['unsubscribe'];
  312. $course['course_code'] = $course_code;
  313. if (!stristr($department_url, 'http://')) {
  314. $department_url = 'http://'.$department_url;
  315. }
  316. Database::query($sql);
  317. $title = str_replace('&amp;', '&', $title);
  318. $params = [
  319. 'course_language' => $course_language,
  320. 'title' => $title,
  321. 'category_code' => $category_code,
  322. 'visual_code' => $visual_code,
  323. 'department_name' => $department_name,
  324. 'department_url' => $department_url,
  325. 'disk_quota' => $disk_quota,
  326. 'visibility' => $visibility,
  327. 'subscribe' => $subscribe,
  328. 'unsubscribe' => $unsubscribe,
  329. ];
  330. Database::update($course_table, $params, ['id = ?' => $courseId]);
  331. // update the extra fields
  332. $courseFieldValue = new ExtraFieldValue('course');
  333. $courseFieldValue->saveFieldValues($course);
  334. $addTeacherToSessionCourses = isset($course['add_teachers_to_sessions_courses']) && !empty($course['add_teachers_to_sessions_courses']) ? 1 : 0;
  335. // Updating teachers
  336. if ($addTeacherToSessionCourses) {
  337. foreach ($coursesInSession as $session) {
  338. $sessionId = $session['id'];
  339. // Updating session coaches
  340. $sessionCoaches = isset($course['session_coaches_'.$sessionId]) ? $course['session_coaches_'.$sessionId] : [];
  341. if (!empty($sessionCoaches)) {
  342. foreach ($sessionCoaches as $teacherInfo) {
  343. $coachesToSubscribe = isset($teacherInfo['coaches_by_session']) ? $teacherInfo['coaches_by_session'] : [];
  344. SessionManager::updateCoaches(
  345. $sessionId,
  346. $courseId,
  347. $coachesToSubscribe,
  348. true
  349. );
  350. }
  351. }
  352. }
  353. CourseManager::updateTeachers(
  354. $courseInfo,
  355. $teachers,
  356. true,
  357. true,
  358. false
  359. );
  360. } else {
  361. // Normal behaviour
  362. CourseManager::updateTeachers($courseInfo, $teachers, true, false);
  363. foreach ($coursesInSession as $session) {
  364. $sessionId = $session['id'];
  365. // Updating session coaches
  366. $sessionCoaches = isset($course['session_coaches_'.$sessionId]) ? $course['session_coaches_'.$sessionId] : [];
  367. if (!empty($sessionCoaches)) {
  368. SessionManager::updateCoaches(
  369. $sessionId,
  370. $courseId,
  371. $sessionCoaches,
  372. true
  373. );
  374. }
  375. }
  376. }
  377. if (array_key_exists('add_teachers_to_sessions_courses', $courseInfo)) {
  378. $sql = "UPDATE $course_table SET
  379. add_teachers_to_sessions_courses = '$addTeacherToSessionCourses'
  380. WHERE id = ".$courseInfo['real_id'];
  381. Database::query($sql);
  382. }
  383. $courseInfo = api_get_course_info($courseInfo['code']);
  384. $message = Display::url($courseInfo['title'], $courseInfo['course_public_url']);
  385. Display::addFlash(Display::return_message(get_lang('Item updated').': '.$message, 'info', false));
  386. if ($visual_code_is_used) {
  387. Display::addFlash(Display::return_message($warn));
  388. header('Location: course_list.php');
  389. } else {
  390. header('Location: course_list.php');
  391. }
  392. exit;
  393. }
  394. Display::display_header($tool_name);
  395. echo '<div class="actions">';
  396. echo Display::url(Display::return_icon('back.png', get_lang('Back')), api_get_path(WEB_CODE_PATH).'admin/course_list.php');
  397. echo Display::url(Display::return_icon('course_home.png', get_lang('Course homepage')), $courseInfo['course_public_url'], ['target' => '_blank']);
  398. echo '</div>';
  399. echo "<script>
  400. function moveItem(origin , destination) {
  401. for (var i = 0 ; i<origin.options.length ; i++) {
  402. if (origin.options[i].selected) {
  403. destination.options[destination.length] = new Option(origin.options[i].text,origin.options[i].value);
  404. origin.options[i]=null;
  405. i = i-1;
  406. }
  407. }
  408. destination.selectedIndex = -1;
  409. sortOptions(destination.options);
  410. }
  411. function sortOptions(options) {
  412. newOptions = new Array();
  413. for (i = 0 ; i<options.length ; i++) {
  414. newOptions[i] = options[i];
  415. }
  416. newOptions = newOptions.sort(mysort);
  417. options.length = 0;
  418. for (i = 0 ; i < newOptions.length ; i++) {
  419. options[i] = newOptions[i];
  420. }
  421. }
  422. function mysort(a, b) {
  423. if (a.text.toLowerCase() > b.text.toLowerCase()) {
  424. return 1;
  425. }
  426. if (a.text.toLowerCase() < b.text.toLowerCase()) {
  427. return -1;
  428. }
  429. return 0;
  430. }
  431. function valide() {
  432. // Checking all multiple
  433. $('select').filter(function() {
  434. if ($(this).attr('multiple')) {
  435. $(this).find('option').each(function() {
  436. $(this).attr('selected', true);
  437. });
  438. }
  439. });
  440. }
  441. </script>";
  442. // Display the form
  443. $form->display();
  444. Display :: display_footer();