From 229209decbed5cebf9d1608a9de438b371db513a Mon Sep 17 00:00:00 2001 From: Angel Fernando Quiroz Campos <1697880+AngelFQC@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:31:37 -0500 Subject: [PATCH] Language: Use parent ISO code + self ID for new sub languages - refs BT#21568 --- public/main/admin/sub_language_add.php | 280 +++++++++--------- public/main/inc/lib/sub_language.class.php | 45 +-- src/CoreBundle/Entity/Language.php | 13 +- .../Entity/Listener/LanguageListener.php | 20 ++ src/CoreBundle/Resources/config/listeners.yml | 4 + 5 files changed, 195 insertions(+), 167 deletions(-) create mode 100644 src/CoreBundle/Entity/Listener/LanguageListener.php diff --git a/public/main/admin/sub_language_add.php b/public/main/admin/sub_language_add.php index e754ab42c96..ee8a818b423 100644 --- a/public/main/admin/sub_language_add.php +++ b/public/main/admin/sub_language_add.php @@ -17,6 +17,7 @@ api_protect_admin_script(); $request = Container::getRequest(); +$em = Database::getManager(); $requestAction = $request->query->get('action'); @@ -32,181 +33,172 @@ $interbreadcrumb[] = ['url' => 'index.php', 'name' => get_lang('Administration')]; $interbreadcrumb[] = ['url' => 'languages.php', 'name' => get_lang('Chamilo Portal Languages')]; -$sub_language_id_exist = SubLanguageManager::languageExistsById($request->query->getInt('sub_language_id')); -$language_id_exist = SubLanguageManager::languageExistsById($request->query->getInt('id')); -$language_name = ''; -$language_details = []; +$parent_id = $request->query->getInt('id'); -//add data -if ($sub_language_id_exist) { - $language_name = SubLanguageManager::get_name_of_language_by_id($_GET['sub_language_id']); - $sub_language_id = $request->query->getInt('sub_language_id'); +if (!SubLanguageManager::languageExistsById($parent_id)) { + Display::addFlash( + Display::return_message(get_lang('The parent language does not exist.')) + ); + api_location(api_get_path(WEB_CODE_PATH).'admin/languages.php'); } -if ($language_id_exist) { - $language_details = SubLanguageManager::get_all_information_of_language($_GET['id']); - $language_name = $language_details['original_name']; - $parent_id = $request->query->getInt('id'); -} +$language_details = SubLanguageManager::get_all_information_of_language($parent_id); +$language_name = $language_details['original_name']; -//removed and register -if ($language_id_exist && $sub_language_id_exist) { - $get_all_information = SubLanguageManager::getAllInformationOfSubLanguage($parent_id, $sub_language_id); - $original_name = $get_all_information->getOriginalName(); - $english_name = $get_all_information->getEnglishName(); - $isocode = $get_all_information->getIsocode(); -} +if ('definenewsublanguage' === $requestAction) { + $form = new FormValidator( + 'addsublanguage', + 'post', + 'sub_language_add.php?id='.Security::remove_XSS($_GET['id']).'&action=definenewsublanguage' + ); + $form->addHeader( + get_lang('Create sub-languageForLanguage').' ( '.strtolower($language_name).' )' + ); + $form->addText('original_name', get_lang('Original name'), true, ['class' => 'input_titles']); + $form->addText('english_name', get_lang('English name'), true, ['class' => 'input_titles']); + $form->addText('isocode', get_lang('ISO code'), true, ['class' => 'input_titles']); + $form->addElement('static', null, ' ', 'en, es, fr'); + $form->addCheckBox('sub_language_is_visible', '', get_lang('Visibility')); + $form->addButtonCreate(get_lang('Create sub-language'), 'SubmitAddNewLanguage'); + $form->protect(); -$language_name = get_lang('Create sub-languageForLanguage').' ( '.strtolower($language_name).' )'; + if ($form->validate()) { + $values = $form->exportValues(); + $values['english_name'] = str_replace(' ', '_', $values['english_name']); + $values['isocode'] = str_replace(' ', '_', $values['isocode']); -if ($request->request->has('SubmitAddNewLanguage')) { - $original_name = $request->request->get('original_name'); - $english_name = str_replace(' ', '_', $request->request->get('english_name')); - $isocode = str_replace(' ', '_', $request->request->get('isocode')); + $check_information = SubLanguageManager::checkIfLanguageExists( + $values['original_name'], + $values['english_name'], + $values['isocode'] + ); + $allow_insert_info = $check_information['execute_add'] ?? false; - $sublanguage_available = $request->request->getInt('sub_language_is_visible'); - $check_information = SubLanguageManager::checkIfLanguageExists($original_name, $english_name, $isocode); - $allow_insert_info = $check_information['execute_add'] ?? false; + if ($check_information['original_name'] ) { + Display::addFlash( + Display::return_message( + sprintf( + '%s "%s (%s)', + get_lang('Already exists'), + get_lang('Original name'), + $values['original_name'] + ), + 'error' + ) + ); + } + if ($check_information['english_name'] ) { + Display::addFlash( + Display::return_message( + get_lang('Already exists').' "'.get_lang('English name').'" '.'('.$values['english_name'].')', + 'error' + ) + ); + } + if ($check_information['isocode'] ) { + Display::addFlash( + Display::return_message(get_lang('This code does not exist').': '.$values['isocode'], 'error') + ); + } - if ($check_information['original_name'] ) { - Display::addFlash( - Display::return_message( - get_lang('Already exists').' "'.get_lang('Original name').'" '.'('.$original_name.')', - 'error' - ) - ); - } - if ($check_information['english_name'] ) { - Display::addFlash( - Display::return_message( - get_lang('Already exists').' "'.get_lang('English name').'" '.'('.$english_name.')', - 'error' - ) - ); - } - if ($check_information['isocode'] ) { - Display::addFlash( - Display::return_message(get_lang('This code does not exist').': '.$isocode.'', 'error') - ); - } + if (strlen($values['original_name']) > 0 && strlen($values['english_name']) > 0 && strlen($values['isocode']) > 0) { + if ($allow_insert_info) { + //$values['english_name'] = str_replace(' ', '_', $values['english_name']); + //Fixes BT#1636 + $values['english_name'] = api_strtolower($values['english_name']); + + try { + $newSubLanguage = SubLanguageManager::addSubLanguage( + $values['original_name'], + $values['english_name'], + $values['sub_language_is_visible'] ?? false, + $parent_id, + $language_details['isocode'] + ); - if (strlen($original_name) > 0 && strlen($english_name) > 0 && strlen($isocode) > 0) { - if ($allow_insert_info && $language_id_exist) { - $english_name = str_replace(' ', '_', $english_name); - //Fixes BT#1636 - $english_name = api_strtolower($english_name); - - $firstIso = substr($language_details['isocode'], 0, 2); - //$english_name = str_starts_with($english_name, $firstIso.'_') ? $english_name : $firstIso.'_'.$english_name; - - $isocode = SubLanguageManager::generateSublanguageCode($firstIso, $request->request->get('english_name')); - $str_info = '
'.get_lang('Original name').' : ' - .$original_name.'
'.get_lang('English name').' : ' - .$english_name.'
'.get_lang('Character set').' : '.$isocode; - - $mkdir_result = SubLanguageManager::addPoFileForSubLanguage($isocode); - if ($mkdir_result) { - $sl_id = SubLanguageManager::addSubLanguage( - $original_name, - $english_name, - $sublanguage_available, - $parent_id, - $isocode - ); - if (false === $sl_id) { - SubLanguageManager::removePoFileForSubLanguage($isocode); + if (SubLanguageManager::addPoFileForSubLanguage($newSubLanguage->getIsocode())) { + $str_info = '
'.get_lang('Original name').' : ' + .$values['original_name'].'
'.get_lang('English name').' : ' + .$values['english_name'].'
'.get_lang('Character set').' : '.$newSubLanguage->getIsocode(); + + Display::addFlash( + Display::return_message(get_lang('The new sub-language has been added').$str_info, 'normal', false) + ); + api_location(api_get_path(WEB_CODE_PATH).'admin/languages.php?sub_language_id='.$newSubLanguage->getId()); + } else { + $em->remove($newSubLanguage); + $em->flush(); + + throw new Exception(); + } + } catch (Exception $e) { Display::addFlash( Display::return_message( get_lang('The /main/lang directory, used on this portal to store the languages, is not writable. Please contact your platform administrator and report this message.'), 'error' ) ); - } else { - Display::addFlash( - Display::return_message(get_lang('The new sub-language has been added').$str_info, null, false) - ); - api_location(api_get_path(WEB_CODE_PATH).'admin/languages.php?sub_language_id='.$sl_id); } - } else { - Display::addFlash( - Display::return_message( - get_lang('The /main/lang directory, used on this portal to store the languages, is not writable. Please contact your platform administrator and report this message.'), - 'error' - ) - ); } - } elseif (false === $language_id_exist) { + } else { Display::addFlash( - Display::return_message(get_lang('The parent language does not exist.'), 'error') + Display::return_message( + get_lang('The form contains incorrect or incomplete data. Please check your input.'), + 'error' + ) ); } - } else { - Display::addFlash( - Display::return_message( - get_lang('The form contains incorrect or incomplete data. Please check your input.'), - 'error' - ) - ); - } -} - -if (isset($_POST['SubmitAddDeleteLanguage'])) { - $removed = SubLanguageManager::removeSubLanguage($_GET['id'], $_GET['sub_language_id']); - if ($removed) { - Display::addFlash( - Display::return_message(get_lang('The sub language has been removed.')) - ); - api_location(api_get_path(WEB_CODE_PATH).'admin/languages.php'); } -} -if ('definenewsublanguage' === $requestAction) { - $form = new FormValidator( - 'addsublanguage', - 'post', - 'sub_language_add.php?id='.Security::remove_XSS($_GET['id']).'&action=definenewsublanguage' - ); - $class = 'add'; - $form->addHeader($language_name); - $form->addText('original_name', get_lang('Original name'), true, ['class' => 'input_titles']); - $form->addText('english_name', get_lang('English name'), true, ['class' => 'input_titles']); - $form->addText('isocode', get_lang('ISO code'), true, ['class' => 'input_titles']); - $form->addElement('static', null, ' ', 'en, es, fr'); - $form->addCheckBox('sub_language_is_visible', '', get_lang('Visibility')); - $form->addButtonCreate(get_lang('Create sub-language'), 'SubmitAddNewLanguage'); $form->setDefaults([ //'original_name' => $language_details['original_name'].'...'; -> cannot be used because of quickform filtering (freeze), 'english_name' => $language_details['english_name'].'2', 'isocode' => $language_details['isocode'], ]); $content .= $form->returnForm(); -} else { - if (true === SubLanguageManager::isParentOfSubLanguage($parent_id) - && 'deletesublanguage' === $requestAction - ) { - $language_name = get_lang('Delete sub-language'); - - $form = new FormValidator( - 'deletesublanguage', - 'post', - 'sub_language_add.php?id='.http_build_query([ - 'id' => $request->query->getInt('id'), - 'sub_language_id' => $request->query->getInt('sub_language_id'), - ]) - ); - $class = 'minus'; - $form->addHeader($language_name); - $form->addElement('static', '', get_lang('Original name'), $original_name); - $form->addElement('static', '', get_lang('English name'), $english_name); - $form->addElement('static', '', get_lang('Character set'), $isocode); - $form->addButtonCreate(get_lang('Delete sub-language'), 'SubmitAddDeleteLanguage'); - $content .= $form->returnForm(); - } - if ('definenewsublanguage' == $requestAction) { +} elseif (true === SubLanguageManager::isParentOfSubLanguage($parent_id) + && 'deletesublanguage' === $requestAction +) { + $sub_language_id = $request->query->getInt('sub_language_id'); + + if (!SubLanguageManager::languageExistsById($sub_language_id)) { Display::addFlash( - Display::return_message(get_lang('The sub-language of this language has been added')) + Display::return_message(get_lang('The sub-language does not exist.')) ); + + api_location(api_get_path(WEB_CODE_PATH).'admin/languages.php'); + } + + $language_name = SubLanguageManager::get_name_of_language_by_id($sub_language_id); + $get_all_information = SubLanguageManager::getAllInformationOfSubLanguage($parent_id, $sub_language_id); + + $form = new FormValidator( + 'deletesublanguage', + 'post', + 'sub_language_add.php?id='.http_build_query([ + 'id' => $parent_id, + 'sub_language_id' => $sub_language_id, + ]) + ); + $form->addHeader(get_lang('Delete sub-language')); + $form->addElement('static', '', get_lang('Original name'), $get_all_information->getOriginalName()); + $form->addElement('static', '', get_lang('English name'), $get_all_information->getEnglishName()); + $form->addElement('static', '', get_lang('Character set'), $get_all_information->getIsocode()); + $form->addButtonCreate(get_lang('Delete sub-language'), 'SubmitAddDeleteLanguage'); + $form->protect(); + + if ($form->validate()) { + $removed = SubLanguageManager::removeSubLanguage($parent_id, $sub_language_id); + + if ($removed) { + Display::addFlash( + Display::return_message(get_lang('The sub language has been removed.')) + ); + api_location(api_get_path(WEB_CODE_PATH).'admin/languages.php'); + } } + + $content .= $form->returnForm(); } /** * Footer. diff --git a/public/main/inc/lib/sub_language.class.php b/public/main/inc/lib/sub_language.class.php index 9807b376a6d..480fc7647dd 100644 --- a/public/main/inc/lib/sub_language.class.php +++ b/public/main/inc/lib/sub_language.class.php @@ -691,13 +691,15 @@ public static function removeSubLanguage(int $parentId, int $subLanguageId): boo /** * Add a sub-language. + * + * @throws Exception */ - public static function addSubLanguage(string $originalName, string $englishName, bool $isAvailable, int $parentId, string $isoCode): bool|int + public static function addSubLanguage(string $originalName, string $englishName, bool $isAvailable, int $parentId, string $isoCode): Language { $entityManager = Database::getManager(); $parentLanguage = $entityManager->getRepository(Language::class)->find($parentId); if (!$parentLanguage) { - return false; + throw new Exception(); } $subLanguage = new Language(); @@ -707,15 +709,10 @@ public static function addSubLanguage(string $originalName, string $englishName, ->setAvailable($isAvailable) ->setParent($parentLanguage); - try { - $entityManager->persist($subLanguage); - $entityManager->flush(); - } catch (\Exception $e) { - // Handle exception if needed - return false; - } + $entityManager->persist($subLanguage); + $entityManager->flush(); - return $subLanguage->getId(); + return $subLanguage; } /** @@ -744,15 +741,17 @@ public static function removePoFileForSubLanguage(string $isoCode): bool /** * Check if a language exists by its ID. - * - * @throws NotSupported */ public static function languageExistsById(int $languageId): bool { $entityManager = Database::getManager(); - $language = $entityManager->getRepository(Language::class)->find($languageId); + try { + $language = $entityManager->getRepository(Language::class)->find($languageId); - return $language !== null; + return $language !== null; + } catch (NotSupported) { + return false; + } } /** @@ -770,18 +769,20 @@ public static function isParentOfSubLanguage(int $parentId): bool /** * Get all information of a sub-language. - * - * @throws NotSupported */ public static function getAllInformationOfSubLanguage(int $parentId, int $subLanguageId): ?Language { $entityManager = Database::getManager(); - $languageRepository = $entityManager->getRepository(Language::class); + try { + $languageRepository = $entityManager->getRepository(Language::class); - return $languageRepository->findOneBy([ - 'parent' => $parentId, - 'id' => $subLanguageId - ]); + return $languageRepository->findOneBy([ + 'parent' => $parentId, + 'id' => $subLanguageId + ]); + } catch (NotSupported) { + return null; + } } /** @@ -857,7 +858,7 @@ public static function getParentLocale(string $childIsoCode): ?string return null; // No parent language } - public static function generateSublanguageCode(string $parentCode, string $variant, int $maxLength = 10): string + public static function generateSublanguageCode(string $parentCode, string $variant, int $maxLength = Language::ISO_MAX_LENGTH): string { $parentCode = strtolower(trim($parentCode)); $variant = strtolower(trim($variant)); diff --git a/src/CoreBundle/Entity/Language.php b/src/CoreBundle/Entity/Language.php index cbe2fed1677..024d3dccc29 100644 --- a/src/CoreBundle/Entity/Language.php +++ b/src/CoreBundle/Entity/Language.php @@ -10,6 +10,7 @@ use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; +use Chamilo\CoreBundle\Entity\Listener\LanguageListener; use Chamilo\CoreBundle\Repository\LanguageRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -25,8 +26,11 @@ #[ApiFilter(OrderFilter::class, properties: ['english_name' => 'DESC'])] #[ORM\Table(name: 'language', options: ['row_format' => 'DYNAMIC'])] #[ORM\Entity(repositoryClass: LanguageRepository::class)] +#[ORM\EntityListeners([LanguageListener::class])] class Language { + public const ISO_MAX_LENGTH = 8; + #[Groups(['language:read'])] #[ORM\Column(name: 'id', type: 'integer')] #[ORM\Id] @@ -45,7 +49,7 @@ class Language #[Groups(['language:read', 'language:write'])] #[Assert\NotBlank] - #[ORM\Column(name: 'isocode', type: 'string', length: 10)] + #[ORM\Column(name: 'isocode', type: 'string', length: self::ISO_MAX_LENGTH)] protected string $isocode; #[Groups(['language:read', 'language:write'])] @@ -167,4 +171,11 @@ public function removeSub(self $sub): static return $this; } + + public function generateIsoCodeForChild(): string + { + $isoCode = explode('_', $this->getParent()->getIsocode()); + + return $isoCode[0].'_'.$this->getId(); + } } diff --git a/src/CoreBundle/Entity/Listener/LanguageListener.php b/src/CoreBundle/Entity/Listener/LanguageListener.php new file mode 100644 index 00000000000..ee2c9d6542e --- /dev/null +++ b/src/CoreBundle/Entity/Listener/LanguageListener.php @@ -0,0 +1,20 @@ +getParent()) { + $newIsoCode = $language->generateIsoCodeForChild(); + + $language->setIsocode($newIsoCode); + + $args->getObjectManager()->flush(); + } + } +} \ No newline at end of file diff --git a/src/CoreBundle/Resources/config/listeners.yml b/src/CoreBundle/Resources/config/listeners.yml index 7e5a5f54987..3c51cb90c33 100644 --- a/src/CoreBundle/Resources/config/listeners.yml +++ b/src/CoreBundle/Resources/config/listeners.yml @@ -102,6 +102,10 @@ services: tags: - {name: doctrine.orm.entity_listener, entity_manager: default, lazy: true} + Chamilo\CoreBundle\Entity\Listener\LanguageListener: + tags: + - { name: doctrine.orm.entity_listener, entity_manager: default, lazy: true } + Chamilo\CoreBundle\EventListener\MessageStatusListener: ~ Chamilo\CoreBundle\EventListener\ResourceLinkListener: ~