From b2310e95d32d9c526d1be336fea7fa19958049d9 Mon Sep 17 00:00:00 2001 From: Angel Fernando Quiroz Campos <angelfqc.18@gmail.com> Date: Fri, 1 Nov 2019 13:39:03 -0500 Subject: [PATCH 1/2] Database: Add course category as foreign key to course - refs BT#15992 --- src/CoreBundle/Entity/Course.php | 18 ++++----- src/CoreBundle/Entity/CourseCategory.php | 36 ++++++++++++++++++ .../Schema/V200/Version20191101132000.php | 37 +++++++++++++++++++ 3 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 src/CoreBundle/Migrations/Schema/V200/Version20191101132000.php diff --git a/src/CoreBundle/Entity/Course.php b/src/CoreBundle/Entity/Course.php index 328635236f..f3f4457201 100644 --- a/src/CoreBundle/Entity/Course.php +++ b/src/CoreBundle/Entity/Course.php @@ -22,7 +22,6 @@ use Symfony\Component\Validator\Constraints as Assert; * @ORM\Table( * name="course", * indexes={ - * @ORM\Index(name="category_code", columns={"category_code"}), * @ORM\Index(name="directory", columns={"directory"}), * } * ) @@ -205,11 +204,12 @@ class Course extends AbstractResource implements ResourceInterface protected $description; /** - * @var string + * @var CourseCategory * - * @ORM\Column(name="category_code", type="string", length=40, nullable=true, unique=false) + * @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\CourseCategory", inversedBy="courses") + * @ORM\JoinColumn(name="category", referencedColumnName="id") */ - protected $categoryCode; + protected $category; /** * @var int @@ -772,13 +772,13 @@ class Course extends AbstractResource implements ResourceInterface /** * Set categoryCode. * - * @param string $categoryCode + * @param string $category * * @return Course */ - public function setCategoryCode($categoryCode) + public function setCategory($category) { - $this->categoryCode = $categoryCode; + $this->category = $category; return $this; } @@ -788,9 +788,9 @@ class Course extends AbstractResource implements ResourceInterface * * @return string */ - public function getCategoryCode() + public function getCategory() { - return $this->categoryCode; + return $this->category; } /** diff --git a/src/CoreBundle/Entity/CourseCategory.php b/src/CoreBundle/Entity/CourseCategory.php index 99ce8dd45c..ad483c254f 100644 --- a/src/CoreBundle/Entity/CourseCategory.php +++ b/src/CoreBundle/Entity/CourseCategory.php @@ -104,6 +104,13 @@ class CourseCategory */ protected $urls; + /** + * @var ArrayCollection + * + * @ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\Course", mappedBy="category") + */ + protected $courses; + /** * Constructor. */ @@ -111,6 +118,7 @@ class CourseCategory { $this->childrenCount = 0; $this->children = new ArrayCollection(); + $this->courses = new ArrayCollection(); } /** @@ -373,4 +381,32 @@ class CourseCategory return $this; } + + /** + * @return ArrayCollection + */ + public function getCourses(): ArrayCollection + { + return $this->courses; + } + + /** + * @param ArrayCollection $courses + * + * @return CourseCategory + */ + public function setCourses(ArrayCollection $courses): CourseCategory + { + $this->courses = $courses; + + return $this; + } + + /** + * @param Course $course + */ + public function addCourse(Course $course) + { + $this->courses[] = $course; + } } diff --git a/src/CoreBundle/Migrations/Schema/V200/Version20191101132000.php b/src/CoreBundle/Migrations/Schema/V200/Version20191101132000.php new file mode 100644 index 0000000000..97d7686734 --- /dev/null +++ b/src/CoreBundle/Migrations/Schema/V200/Version20191101132000.php @@ -0,0 +1,37 @@ +<?php +/* For licensing terms, see /license.txt */ + +namespace Chamilo\CoreBundle\Migrations\Schema\V200; + +use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo; +use Doctrine\DBAL\Schema\Schema; + +/** + * Class Version20191101132000. + * + * @package Chamilo\CoreBundle\Migrations\Schema\V200 + */ +class Version20191101132000 extends AbstractMigrationChamilo +{ + /** + * @param Schema $schema + */ + public function up(Schema $schema) + { + $this->getEntityManager(); + + $this->addSql('ALTER TABLE course ADD category INT DEFAULT NULL'); + $this->addSql('UPDATE course co SET co.category = (SELECT cat.id FROM course_category cat WHERE cat.code = co.category_code)'); + $this->addSql('DROP INDEX category_code ON course'); + $this->addSql('ALTER TABLE course DROP category_code'); + $this->addSql('ALTER TABLE course ADD CONSTRAINT FK_169E6FB964C19C1 FOREIGN KEY (category) REFERENCES course_category (id)'); + $this->addSql('CREATE INDEX IDX_169E6FB964C19C1 ON course (category)'); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + } +} From b59c35836a943b8a3e57b50ab246944dc3aee9bb Mon Sep 17 00:00:00 2001 From: Angel Fernando Quiroz Campos <angelfqc.18@gmail.com> Date: Fri, 1 Nov 2019 14:00:12 -0500 Subject: [PATCH 2/2] Use course category ID in courses - refs BT#15992 --- main/admin/course_add.php | 10 +++++----- main/admin/course_edit.php | 13 ++++++------- main/admin/course_list.php | 18 ++++++++++-------- main/inc/lib/add_course.lib.inc.php | 15 ++++++++++----- main/inc/lib/api.lib.php | 8 ++++---- main/inc/lib/course.lib.php | 2 +- main/inc/lib/course_category.lib.php | 4 ++-- src/CoreBundle/Entity/Course.php | 2 +- src/CoreBundle/Framework/Container.php | 9 +++++++++ src/GraphQlBundle/Map/MutationMap.php | 6 +++++- 10 files changed, 53 insertions(+), 34 deletions(-) diff --git a/main/admin/course_add.php b/main/admin/course_add.php index 1b43660090..9a5195a6be 100755 --- a/main/admin/course_add.php +++ b/main/admin/course_add.php @@ -69,7 +69,7 @@ if ($countCategories >= 100) { $form->addElement( 'select_ajax', - 'category_code', + 'category_id', get_lang('Category'), null, ['url' => $url] @@ -79,13 +79,13 @@ if ($countCategories >= 100) { $accessUrlId, api_get_configuration_value('allow_base_course_category') ); - $categoriesOptions = [null => get_lang('none')]; + $categoriesOptions = [0 => get_lang('None')]; /** @var CourseCategory $category */ foreach ($categories as $category) { - $categoriesOptions[$category->getCode()] = (string) $category; + $categoriesOptions[$category->getId()] = (string) $category; } $form->addSelect( - 'category_code', + 'category_id', get_lang('Category'), $categoriesOptions ); @@ -230,7 +230,7 @@ if ($form->validate()) { $course['wanted_code'] = $course['visual_code']; $course['gradebook_model_id'] = isset($course['gradebook_model_id']) ? $course['gradebook_model_id'] : null; // Fixing category code - $course['course_category'] = isset($course['category_code']) ? $course['category_code'] : ''; + $course['category_id'] = isset($course['category_id']) ? (int) $course['category_id'] : ''; include_once api_get_path(SYS_CODE_PATH).'lang/english/trad4all.inc.php'; $file_to_include = api_get_path(SYS_CODE_PATH).'lang/'.$course['course_language'].'/trad4all.inc.php'; diff --git a/main/admin/course_edit.php b/main/admin/course_edit.php index ec51c40d0f..a87f4b3da4 100755 --- a/main/admin/course_edit.php +++ b/main/admin/course_edit.php @@ -153,7 +153,7 @@ if ($countCategories >= 100) { $categorySelect = $form->addElement( 'select_ajax', - 'category_code', + 'category_id', get_lang('Category'), null, ['url' => $url] @@ -164,20 +164,19 @@ if ($countCategories >= 100) { $categorySelect->addOption($data['name'], $data['code']); } } else { - $courseInfo['category_code'] = $courseInfo['categoryCode']; $categories = $courseCategoriesRepo->findAllInAccessUrl( $urlId, api_get_configuration_value('allow_base_course_category') ); - $categoriesOptions = [null => get_lang('none')]; + $categoriesOptions = [0 => get_lang('None')]; /** @var CourseCategory $category */ foreach ($categories as $category) { - $categoriesOptions[$category->getCode()] = (string) $category; + $categoriesOptions[$category->getId()] = (string) $category; } $form->addSelect( - 'category_code', + 'category_id', get_lang('Category'), $categoriesOptions ); @@ -355,7 +354,7 @@ if ($form->validate()) { $teachers = isset($course['course_teachers']) ? $course['course_teachers'] : ''; $title = $course['title']; - $category_code = isset($course['category_code']) ? $course['category_code'] : ''; + $category_code = isset($course['category_id']) ? (int) $course['category_id'] : ''; $department_name = $course['department_name']; $department_url = $course['department_url']; $course_language = $course['course_language']; @@ -375,7 +374,7 @@ if ($form->validate()) { $params = [ 'course_language' => $course_language, 'title' => $title, - 'category_code' => $category_code, + 'category' => $category_code, 'visual_code' => $visual_code, 'department_name' => $department_name, 'department_url' => $department_url, diff --git a/main/admin/course_list.php b/main/admin/course_list.php index 8e19af1e48..9ce71fd4c3 100755 --- a/main/admin/course_list.php +++ b/main/admin/course_list.php @@ -94,22 +94,24 @@ function get_number_of_courses() function get_course_data($from, $number_of_items, $column, $direction) { $course_table = Database::get_main_table(TABLE_MAIN_COURSE); + $tblCourseCategory = Database::get_main_table(TABLE_MAIN_CATEGORY); $sql = "SELECT - code AS col0, + course.code AS col0, title AS col1, - code AS col2, + course.code AS col2, course_language AS col3, - category_code AS col4, + category.code AS col4, subscribe AS col5, unsubscribe AS col6, - code AS col7, + course.code AS col7, visibility AS col8, directory as col9, visual_code, directory, course.id - FROM $course_table course"; + FROM $course_table course + LEFT JOIN $tblCourseCategory category ON course.category = category.id "; if ((api_is_platform_admin() || api_is_session_admin()) && api_is_multiple_url_enabled() && api_get_current_access_url_id() != -1 @@ -123,7 +125,7 @@ function get_course_data($from, $number_of_items, $column, $direction) $keyword = Database::escape_string("%".trim($_GET['keyword'])."%"); $sql .= " WHERE ( title LIKE '".$keyword."' OR - code LIKE '".$keyword."' OR + course.code LIKE '".$keyword."' OR visual_code LIKE '".$keyword."' ) "; @@ -139,7 +141,7 @@ function get_course_data($from, $number_of_items, $column, $direction) $keyword_unsubscribe = Database::escape_string($_GET['keyword_unsubscribe']); $sql .= " WHERE - (code LIKE '".$keyword_code."' OR visual_code LIKE '".$keyword_code."') AND + (course.code LIKE '".$keyword_code."' OR visual_code LIKE '".$keyword_code."') AND title LIKE '".$keyword_title."' AND course_language LIKE '".$keyword_language."' AND visibility LIKE '".$keyword_visibility."' AND @@ -147,7 +149,7 @@ function get_course_data($from, $number_of_items, $column, $direction) unsubscribe LIKE '".$keyword_unsubscribe."'"; if (!empty($keyword_category)) { - $sql .= " AND category_code LIKE '".$keyword_category."' "; + $sql .= " AND category.code LIKE '".$keyword_category."' "; } } diff --git a/main/inc/lib/add_course.lib.inc.php b/main/inc/lib/add_course.lib.inc.php index 778d618de2..d50e985725 100755 --- a/main/inc/lib/add_course.lib.inc.php +++ b/main/inc/lib/add_course.lib.inc.php @@ -786,7 +786,7 @@ class AddCourse $visual_code = $params['visual_code']; $directory = $params['directory']; $tutor_name = isset($params['tutor_name']) ? $params['tutor_name'] : null; - $category_code = isset($params['course_category']) ? $params['course_category'] : ''; + $categoryId = isset($params['category_id']) ? (int) $params['category_id'] : ''; $course_language = isset($params['course_language']) && !empty($params['course_language']) ? $params['course_language'] : api_get_setting( 'platformLanguage' ); @@ -870,6 +870,8 @@ class AddCourse if ($ok_to_register_course) { $repo = Container::getCourseRepository(); $course = new \Chamilo\CoreBundle\Entity\Course(); + /** @var \Chamilo\CoreBundle\Entity\CourseCategory $courseCategory */ + $courseCategory = Container::getCourseCategoryRepository()->find($categoryId); $urlId = 1; if (api_get_current_access_url_id() !== -1) { $urlId = api_get_current_access_url_id(); @@ -882,7 +884,7 @@ class AddCourse ->setCourseLanguage($course_language) ->setTitle($title) ->setDescription(get_lang('Course Description')) - ->setCategoryCode($category_code) + ->setCategory($courseCategory) ->setVisibility($visibility) ->setShowScore(1) ->setDiskQuota($disk_quota) @@ -984,9 +986,12 @@ class AddCourse 'MessageOfNewCourseToAdmin' ).' '.$siteName.' - '.$iname."\n"; $message .= get_lang('Course name').' '.$title."\n"; - $message .= get_lang( - 'Category' - ).' '.$category_code."\n"; + + if ($courseCategory) { + $message .= get_lang( + 'Category' + ).' '.$courseCategory->getCode()."\n"; + } $message .= get_lang('Coach').' '.$tutor_name."\n"; $message .= get_lang('Language').' '.$course_language; diff --git a/main/inc/lib/api.lib.php b/main/inc/lib/api.lib.php index 6b46436533..5f8484d0f8 100644 --- a/main/inc/lib/api.lib.php +++ b/main/inc/lib/api.lib.php @@ -2200,16 +2200,16 @@ function api_format_course_array(Course $course) return []; } - $categoryCode = $course->getCategoryCode(); + $category = $course->getCategory(); $courseData = []; $courseData['categoryCode'] = ''; $courseData['categoryName'] = ''; - if (!empty($categoryCode)) { - $categoryRepo = Database::getManager()->getRepository('ChamiloCoreBundle:CourseCategory'); - $category = $categoryRepo->findOneBy(['code' => $categoryCode]); + $courseData['category_id'] = 0; + if ($category) { $courseData['categoryCode'] = $category->getCode(); $courseData['categoryName'] = $category->getName(); + $courseData['category_id'] = $category->getId(); } $courseData['id'] = $courseData['real_id'] = $course->getId(); diff --git a/main/inc/lib/course.lib.php b/main/inc/lib/course.lib.php index 016a93033b..3429a32a1c 100755 --- a/main/inc/lib/course.lib.php +++ b/main/inc/lib/course.lib.php @@ -2893,7 +2893,7 @@ class CourseManager $sql = "SELECT DISTINCT(course.code), course.id as real_id, - course.category_code AS category, + course.category, course.title FROM $tbl_course course INNER JOIN $tbl_course_user cru diff --git a/main/inc/lib/course_category.lib.php b/main/inc/lib/course_category.lib.php index c4be863c68..0b85b203ac 100755 --- a/main/inc/lib/course_category.lib.php +++ b/main/inc/lib/course_category.lib.php @@ -96,7 +96,7 @@ class CourseCategory LEFT JOIN $tbl_category t2 ON t1.id = t2.parent_id LEFT JOIN $tbl_course t3 - ON t3.category_code=t1.code + ON t3.category = t1.id WHERE 1 = 1 $parentIdCondition @@ -263,7 +263,7 @@ class CourseCategory ); Database::query("UPDATE $tbl_category SET parent_id='".$row['parent_id']."' WHERE parent_id='$node'"); } else { - Database::query("UPDATE $tbl_course SET category_code='' WHERE category_code='$node'"); + Database::query("UPDATE $tbl_course SET category = NULL WHERE category = ".$category['id']); Database::query("UPDATE $tbl_category SET parent_id=NULL WHERE parent_id='$node'"); } diff --git a/src/CoreBundle/Entity/Course.php b/src/CoreBundle/Entity/Course.php index f3f4457201..44996d6adc 100644 --- a/src/CoreBundle/Entity/Course.php +++ b/src/CoreBundle/Entity/Course.php @@ -786,7 +786,7 @@ class Course extends AbstractResource implements ResourceInterface /** * Get categoryCode. * - * @return string + * @return CourseCategory */ public function getCategory() { diff --git a/src/CoreBundle/Framework/Container.php b/src/CoreBundle/Framework/Container.php index 0a261b5712..99f9c188a0 100644 --- a/src/CoreBundle/Framework/Container.php +++ b/src/CoreBundle/Framework/Container.php @@ -6,6 +6,7 @@ namespace Chamilo\CoreBundle\Framework; use Chamilo\CoreBundle\Component\Editor\Editor; use Chamilo\CoreBundle\Hook\Interfaces\HookEventInterface; use Chamilo\CoreBundle\Repository\AccessUrlRepository; +use Chamilo\CoreBundle\Repository\CourseCategoryRepository; use Chamilo\CoreBundle\Repository\CourseRepository; use Chamilo\CoreBundle\Repository\IllustrationRepository; use Chamilo\CoreBundle\ToolChain; @@ -382,6 +383,14 @@ class Container return self::$container->get('Chamilo\CoreBundle\Repository\CourseRepository'); } + /** + * @return CourseCategoryRepository|object|null + */ + public static function getCourseCategoryRepository() + { + return self::$container->get('Chamilo\CoreBundle\Repository\CourseCategoryRepository'); + } + /** * @return IllustrationRepository */ diff --git a/src/GraphQlBundle/Map/MutationMap.php b/src/GraphQlBundle/Map/MutationMap.php index bae03ed2a6..7458e26881 100644 --- a/src/GraphQlBundle/Map/MutationMap.php +++ b/src/GraphQlBundle/Map/MutationMap.php @@ -228,7 +228,11 @@ class MutationMap extends ResolverMap implements ContainerAwareInterface } if (isset($courseInput['categoryCode'])) { - $course->setCategoryCode($courseInput['categoryCode']); + $courseCategory = $this->em + ->getRepository('ChamiloCoreBundle:CourseCategory') + ->findOneBy(['code' => $courseInput['categoryCode']]); + + $course->setCategory($courseCategory); } if (!empty($courseInput['visualCode'])) {