From d413e28680f847723b8de0556c0c52e8275ffac6 Mon Sep 17 00:00:00 2001 From: Angel Fernando Quiroz Campos <1697880+AngelFQC@users.noreply.github.com> Date: Tue, 29 Jul 2025 16:12:06 -0500 Subject: [PATCH 01/14] Replacing usage of UrlManager::get_url_data with EntityRepository::findAll - refs BT#22639 --- public/main/admin/access_urls.php | 37 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/public/main/admin/access_urls.php b/public/main/admin/access_urls.php index 1e7e511d98f..f581c16c32d 100644 --- a/public/main/admin/access_urls.php +++ b/public/main/admin/access_urls.php @@ -9,8 +9,10 @@ * @author Yannick Warnier */ +use Chamilo\CoreBundle\Entity\AccessUrl; use Chamilo\CoreBundle\Enums\ActionIcon; use Chamilo\CoreBundle\Enums\StateIcon; +use Chamilo\CoreBundle\Framework\Container; use Symfony\Component\HttpFoundation\Request as HttpRequest; $cidReset = true; @@ -26,7 +28,8 @@ $my_user_url_list = api_get_access_url_from_user(api_get_user_id()); $current_access_url_id = api_get_current_access_url_id(); -$url_list = UrlManager::get_url_data(); +/** @var array $url_list */ +$url_list = Container::getAccessUrlRepository()->findAll(); // Actions if ($httpRequest->query->has('action')) { @@ -55,9 +58,9 @@ if (api_is_platform_admin() && -1 != $current_access_url_id) { $url_str = ''; foreach ($url_list as $u) { - if (!in_array($u['id'], $my_user_url_list)) { - UrlManager::add_user_to_url(api_get_user_id(), $u['id']); - $url_str .= $u['url'] . '
'; + if (!in_array($u->getId(), $my_user_url_list)) { + UrlManager::add_user_to_url(api_get_user_id(), $u->getId()); + $url_str .= $u->getUrl() . '
'; } } echo Display::return_message( @@ -76,8 +79,8 @@ // Checking if the admin is registered in all sites $url_string = ''; foreach ($url_list as $u) { - if (!in_array($u['id'], $my_user_url_list)) { - $url_string .= $u['url'] . '
'; + if (!in_array($u->getId(), $my_user_url_list)) { + $url_string .= $u->getUrl() . '
'; } } if (!empty($url_string)) { @@ -110,8 +113,8 @@ // 1) Find the default URL (ID = 1) $defaultUrl = 'http://localhost/'; foreach ($url_list as $u) { - if ((string)$u['id'] === '1') { - $defaultUrl = trim($u['url']); + if ($u->getId() === 1) { + $defaultUrl = trim($u->getUrl()); break; } } @@ -182,29 +185,29 @@ $rows = []; foreach ($url_list as $u) { - $link = Display::url($u['url'], $u['url'], ['target' => '_blank']); - $desc = $u['description']; - $ts = api_get_local_time($u['tms']); - $active = ($u['active'] === '1'); + $link = Display::url($u->getUrl(), $u->getUrl(), ['target' => '_blank']); + $desc = $u->getDescription(); + $ts = api_get_local_time($u->getTms()); + $active = ($u->getActive() === 1); $iconAction = $active ? 'lock' : 'unlock'; $stateIcon = $active ? StateIcon::ACTIVE : StateIcon::INACTIVE; - if ((string)$u['id'] === '1') { + if ($u->getId() === 1) { $status = Display::getMdiIcon($stateIcon, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang(ucfirst($iconAction))); } else { - $status = '' . + $status = '' . Display::getMdiIcon($stateIcon, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang(ucfirst($iconAction))) . ''; } $rowActions = Display::url( Display::getMdiIcon(ActionIcon::EDIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Edit')), - "access_url_edit.php?url_id={$u['id']}" + "access_url_edit.php?url_id={$u->getId()}" ); - if ((string)$u['id'] !== '1') { - $rowActions .= 'getId() !== 1) { + $rowActions .= '' . Display::getMdiIcon('delete', 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Delete')) . ''; From 330a24603a5747e1930778cbcf32595fa6b582fa Mon Sep 17 00:00:00 2001 From: Angel Fernando Quiroz Campos <1697880+AngelFQC@users.noreply.github.com> Date: Tue, 29 Jul 2025 17:12:54 -0500 Subject: [PATCH 02/14] Replace hardcoded localhost URL with AccessUrl::DEFAULT_ACCESS_URL - refs BT#22639 --- public/main/admin/access_url_edit.php | 3 ++- public/main/admin/access_urls.php | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/public/main/admin/access_url_edit.php b/public/main/admin/access_url_edit.php index dc05aade3eb..a29e1fc91fb 100644 --- a/public/main/admin/access_url_edit.php +++ b/public/main/admin/access_url_edit.php @@ -6,6 +6,7 @@ * @author Julio Montoya */ +use Chamilo\CoreBundle\Entity\AccessUrl; use Chamilo\CoreBundle\Enums\ActionIcon; use Chamilo\CoreBundle\Framework\Container; use Symfony\Component\HttpFoundation\Request as HttpRequest; @@ -44,7 +45,7 @@ // If we're still with localhost (should only happen at the very beginning) // offer the current URL by default. Once this has been saved, no more // magic will happen, ever. - if ($url_data['id'] === 1 && $url_data['url'] === 'http://localhost/') { + if ($url_data['id'] === 1 && $url_data['url'] === AccessUrl::DEFAULT_ACCESS_URL) { $https = api_is_https() ? 'https://' : 'http://'; $url_data['url'] = $https.$_SERVER['HTTP_HOST'].'/'; } diff --git a/public/main/admin/access_urls.php b/public/main/admin/access_urls.php index f581c16c32d..1506ce9ce0d 100644 --- a/public/main/admin/access_urls.php +++ b/public/main/admin/access_urls.php @@ -111,7 +111,7 @@ } // 1) Find the default URL (ID = 1) -$defaultUrl = 'http://localhost/'; +$defaultUrl = AccessUrl::DEFAULT_ACCESS_URL; foreach ($url_list as $u) { if ($u->getId() === 1) { $defaultUrl = trim($u->getUrl()); @@ -121,7 +121,7 @@ // 2) Tooltip message (in English, per spec) $tooltip = 'Adding new URLs requires you to first set the first URL to a value different than localhost.'; -$isLocalhost = ($defaultUrl === 'http://localhost/'); +$isLocalhost = ($defaultUrl === AccessUrl::DEFAULT_ACCESS_URL); // 3) Decide link href and base attributes $attributes = ['id' => 'add-url-button']; From 79c8cf9b899ea1456c1a9a9f2d75ce6dda786275 Mon Sep 17 00:00:00 2001 From: Angel Fernando Quiroz Campos <1697880+AngelFQC@users.noreply.github.com> Date: Tue, 29 Jul 2025 21:05:25 -0500 Subject: [PATCH 03/14] Enhance access URL management to integrate the login-only option - refs BT#22639 --- public/main/admin/access_url_edit.php | 69 +++++++++++++++++++------- public/main/admin/access_urls.php | 16 ++++-- public/main/inc/lib/urlmanager.lib.php | 27 +++++----- 3 files changed, 80 insertions(+), 32 deletions(-) diff --git a/public/main/admin/access_url_edit.php b/public/main/admin/access_url_edit.php index a29e1fc91fb..bf50e55d95d 100644 --- a/public/main/admin/access_url_edit.php +++ b/public/main/admin/access_url_edit.php @@ -18,6 +18,7 @@ api_protect_global_admin_script(); $httpRequest = HttpRequest::createFromGlobals(); +$urlRepo = Container::getAccessUrlRepository(); $form = new FormValidator('add_url'); @@ -30,26 +31,35 @@ $form->addFile('url_image_1', get_lang('Image')); //$form->addElement('file', 'url_image_2', 'URL Image 2 (PNG)'); //$form->addElement('file', 'url_image_3', 'URL Image 3 (PNG)'); +$form->addCheckBox('login_only', get_lang('Login only'), get_lang('Yes')); $defaults['url'] = 'http://'; $form->setDefaults($defaults); if ($httpRequest->query->has('url_id')) { $url_id = $httpRequest->query->getInt('url_id'); - $num_url_id = UrlManager::url_id_exist($url_id); - if (1 != $num_url_id) { + + /** @var AccessUrl $url_data */ + $url_data = $urlRepo->find($url_id); + + if (!$url_data) { header('Location: access_urls.php'); exit(); } - $url_data = UrlManager::get_url_data_from_id($url_id); - $form->addElement('hidden', 'id', $url_data['id']); + $form->addElement('hidden', 'id', $url_data->getId()); // If we're still with localhost (should only happen at the very beginning) // offer the current URL by default. Once this has been saved, no more // magic will happen, ever. - if ($url_data['id'] === 1 && $url_data['url'] === AccessUrl::DEFAULT_ACCESS_URL) { + if ($url_data->getId() === 1 && $url_data->getUrl() === AccessUrl::DEFAULT_ACCESS_URL) { $https = api_is_https() ? 'https://' : 'http://'; - $url_data['url'] = $https.$_SERVER['HTTP_HOST'].'/'; + $url_data->setUrl($https.$_SERVER['HTTP_HOST'].'/'); } - $form->setDefaults($url_data); + $form->setDefaults([ + 'id' => $url_data->getId(), + 'url' => $url_data->getUrl(), + 'description' => $url_data->getDescription(), + 'active' => $url_data->getActive(), + 'login_only' => $url_data->isLoginOnly(), + ]); } $form->addHidden( @@ -71,6 +81,7 @@ $description = Security::remove_XSS($url_array['description']); $active = isset($url_array['active']) ? (int) $url_array['active'] : 0; $url_id = isset($url_array['id']) ? (int) $url_array['id'] : 0; + $isLoginOnly = isset($url_array['login_only']) && (bool) $url_array['login_only']; $url_to_go = 'access_urls.php'; if (!empty($url_id)) { //we can't change the status of the url with id=1 @@ -78,11 +89,22 @@ $active = 1; } // Checking url - if ('/' == substr($url, strlen($url) - 1, strlen($url))) { - UrlManager::update($url_id, $url, $description, $active); - } else { - UrlManager::update($url_id, $url.'/', $description, $active); + if ('/' != substr($url, strlen($url) - 1, strlen($url))) { + $url .= '/'; } + + /** @var AccessUrl $accessUrl */ + $accessUrl = $urlRepo->find($url_id); + + $accessUrl + ->setUrl($url) + ->setDescription($description) + ->setActive($active) + ->setCreatedBy(api_get_user_id()) + ->setTms(api_get_utc_datetime()) + ->setIsLoginOnly($isLoginOnly) + ; + $url_to_go = 'access_urls.php'; $message = get_lang('The URL has been edited'); } else { @@ -91,19 +113,32 @@ $message = get_lang('This URL already exists, please select another URL'); if (0 === $num) { // checking url - if ('/' == substr($url, strlen($url) - 1, strlen($url))) { - $accessUrl = UrlManager::add($url, $description, $active); - } else { - //create - $accessUrl = UrlManager::add($url.'/', $description, $active); + if ('/' != substr($url, strlen($url) - 1, strlen($url))) { + $url .= '/'; } - if (null !== $accessUrl) { + + $accessUrl = $urlRepo->findOneBy(['url' => $url]); + + if (!$accessUrl) { + $accessUrl = new AccessUrl(); + $accessUrl + ->setDescription($description) + ->setActive($active) + ->setUrl($url) + ->setCreatedBy(api_get_user_id()) + ->setIsLoginOnly($isLoginOnly) + ; + + Database::getManager()->persist($accessUrl); + $message = get_lang('The URL has been added'); $url_to_go = 'access_urls.php'; } } } + Database::getManager()->flush(); + Security::clear_token(); $tok = Security::get_token(); Display::addFlash(Display::return_message($message)); diff --git a/public/main/admin/access_urls.php b/public/main/admin/access_urls.php index 1506ce9ce0d..0fdd2ee3506 100644 --- a/public/main/admin/access_urls.php +++ b/public/main/admin/access_urls.php @@ -22,6 +22,8 @@ $httpRequest = HttpRequest::createFromGlobals(); +$translator = Container::$container->get('translator');; + $interbreadcrumb[] = ['url' => 'index.php', 'name' => get_lang('Administration')]; $tool_name = get_lang('Multiple access URL / Branding'); Display :: display_header($tool_name); @@ -213,7 +215,14 @@ ''; } - $rows[] = [$link, $desc, $status, $ts, $rowActions]; + $rows[] = [ + $link, + $desc, + $status, + $u->isLoginOnly() ? $translator->trans('Yes') : $translator->trans('No'), + $ts, + $rowActions, + ]; } $table = new SortableTableFromArrayConfig($rows, 2, 50, 'urls'); @@ -221,8 +230,9 @@ $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('Created at')); -$table->set_header(4, get_lang('Edit'), false); +$table->set_header(3, get_lang('Is login only')); +$table->set_header(4, get_lang('Created at')); +$table->set_header(5, get_lang('Edit'), false); $table->display(); Display::display_footer(); diff --git a/public/main/inc/lib/urlmanager.lib.php b/public/main/inc/lib/urlmanager.lib.php index 5df6279df23..d00c540b0be 100644 --- a/public/main/inc/lib/urlmanager.lib.php +++ b/public/main/inc/lib/urlmanager.lib.php @@ -21,7 +21,7 @@ class UrlManager * @param string $description The description of the site * @param int $active is active or not */ - public static function add($url, $description, $active): ?AccessUrl + public static function add($url, $description, $active, bool $isLoginOnly = false): ?AccessUrl { $repo = Container::getAccessUrlRepository(); @@ -37,6 +37,7 @@ public static function add($url, $description, $active): ?AccessUrl ->setActive($active) ->setUrl($url) ->setCreatedBy(api_get_user_id()) + ->setIsLoginOnly($isLoginOnly) ; $repo->create($accessUrl); @@ -56,23 +57,25 @@ public static function add($url, $description, $active): ?AccessUrl * * @return bool if success */ - public static function update($urlId, $url, $description, $active) + public static function update($urlId, $url, $description, $active, bool $isLoginOnly = false) { $urlId = (int) $urlId; $active = (int) $active; $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL); - $sql = "UPDATE $table - SET url = '".Database::escape_string($url)."', - description = '".Database::escape_string($description)."', - active = '".$active."', - created_by = '".api_get_user_id()."', - tms = '".api_get_utc_datetime()."' - WHERE id = '$urlId'"; - $result = Database::query($sql); - - return $result; + return Database::update( + $table, + [ + 'url' => $url, + 'description' => $description, + 'active' => $active, + 'created_by' => api_get_user_id(), + 'tms' => api_get_utc_datetime(), + 'is_login_only' => $isLoginOnly, + ], + ['id = ?' => [$urlId]] + ); } /** From 10729d8ce9f5570c775d75b77074936c9dc7df11 Mon Sep 17 00:00:00 2001 From: Angel Fernando Quiroz Campos <1697880+AngelFQC@users.noreply.github.com> Date: Wed, 30 Jul 2025 05:48:26 -0500 Subject: [PATCH 04/14] Add access URL chooser for users with multiple active portals - refs BT#22639 --- assets/vue/App.vue | 3 + .../components/accessurl/AccessUrlChooser.vue | 68 +++++++++++++++++++ assets/vue/services/accessurlService.js | 12 ++++ assets/vue/store/securityStore.js | 5 ++ .../Api/UserAccessUrlsController.php | 25 +++++++ .../Controller/SecurityController.php | 4 ++ src/CoreBundle/Entity/AccessUrl.php | 15 +++- src/CoreBundle/Entity/User.php | 3 + src/CoreBundle/EventListener/TwigListener.php | 28 ++++---- .../Repository/Node/AccessUrlRepository.php | 14 ++++ .../views/Layout/vue_js_setup.html.twig | 1 + 11 files changed, 163 insertions(+), 15 deletions(-) create mode 100644 assets/vue/components/accessurl/AccessUrlChooser.vue create mode 100644 assets/vue/services/accessurlService.js create mode 100644 src/CoreBundle/Controller/Api/UserAccessUrlsController.php diff --git a/assets/vue/App.vue b/assets/vue/App.vue index 53c49123fc9..a317e864274 100644 --- a/assets/vue/App.vue +++ b/assets/vue/App.vue @@ -10,6 +10,8 @@ ref="legacyContainer" /> + +