From ad761d412d4ea9ebb3d28b423cac56fb3b1b126a Mon Sep 17 00:00:00 2001 From: Christian Beeznest Date: Sat, 23 May 2026 14:23:56 -0500 Subject: [PATCH] Plugin: Improve Dictionary plugin integration --- assets/vue/composables/sidebarMenu.js | 75 ++++ public/main/admin/settings.lib.php | 1 + public/plugin/Dictionary/DictionaryPlugin.php | 350 ++++++++++++++++-- public/plugin/Dictionary/admin.php | 5 + public/plugin/Dictionary/index.php | 45 ++- public/plugin/Dictionary/install.php | 9 +- public/plugin/Dictionary/lang/en_US.php | 17 +- public/plugin/Dictionary/lang/es.php | 19 +- public/plugin/Dictionary/plugin.php | 4 +- public/plugin/Dictionary/terms.php | 152 +++++--- public/plugin/Dictionary/uninstall.php | 15 + public/plugin/Dictionary/view/terms.html.twig | 145 ++++++-- public/plugin/Rss/lib/rss_plugin.class.php | 31 +- .../lib/search_course_plugin.class.php | 16 +- .../PlatformConfigurationController.php | 74 ++++ 15 files changed, 793 insertions(+), 165 deletions(-) create mode 100644 public/plugin/Dictionary/admin.php create mode 100644 public/plugin/Dictionary/uninstall.php diff --git a/assets/vue/composables/sidebarMenu.js b/assets/vue/composables/sidebarMenu.js index 6f971918399..e8ac2e614c0 100644 --- a/assets/vue/composables/sidebarMenu.js +++ b/assets/vue/composables/sidebarMenu.js @@ -226,6 +226,9 @@ export function useSidebarMenu() { securityStore.isAdmin || securityStore.isTeacher || securityStore.isHRM || securityStore.isSessionAdmin const buyCoursesConfig = computed(() => platformConfigStore.plugins?.buycourses || {}) + const searchCourseConfig = computed(() => platformConfigStore.plugins?.searchcourse || {}) + const rssConfig = computed(() => platformConfigStore.plugins?.rss || {}) + const dictionaryConfig = computed(() => platformConfigStore.plugins?.dictionary || {}) const showBuyCoursesMenuItem = computed(() => { if (!securityStore.isAuthenticated) { @@ -239,6 +242,54 @@ export function useSidebarMenu() { return buyCoursesConfig.value?.indexPath || "/plugin/BuyCourses/index.php" }) + const showSearchCourseMenuItem = computed(() => { + if (!securityStore.isAuthenticated) { + return false + } + + return normalizeBooleanFlag(searchCourseConfig.value?.enabled) + }) + + const searchCourseIndexPath = computed(() => { + return searchCourseConfig.value?.indexPath || "/plugin/SearchCourse/index.php" + }) + + const searchCourseMenuTitle = computed(() => { + return searchCourseConfig.value?.title || t("Search courses") + }) + + const showRssMenuItem = computed(() => { + if (!securityStore.isAuthenticated) { + return false + } + + return normalizeBooleanFlag(rssConfig.value?.enabled) + }) + + const rssIndexPath = computed(() => { + return rssConfig.value?.indexPath || "/plugin/Rss/index.php" + }) + + const rssMenuTitle = computed(() => { + return rssConfig.value?.title || t("RSS feed") + }) + + const showDictionaryMenuItem = computed(() => { + if (!securityStore.isAuthenticated) { + return false + } + + return normalizeBooleanFlag(dictionaryConfig.value?.enabled) + }) + + const dictionaryIndexPath = computed(() => { + return dictionaryConfig.value?.indexPath || "/plugin/Dictionary/index.php" + }) + + const dictionaryMenuTitle = computed(() => { + return dictionaryConfig.value?.title || t("Dictionary") + }) + const allowStudentCatalogue = computed(() => { if (isAnonymous) { return platformConfigStore.getSetting("catalog.course_catalog_published") !== "false" @@ -348,6 +399,30 @@ export function useSidebarMenu() { }) } + if (showSearchCourseMenuItem.value) { + items.push({ + icon: "mdi mdi-book-search-outline", + label: searchCourseMenuTitle.value, + url: searchCourseIndexPath.value, + }) + } + + if (showDictionaryMenuItem.value) { + items.push({ + icon: "mdi mdi-book-open-page-variant-outline", + label: dictionaryMenuTitle.value, + url: dictionaryIndexPath.value, + }) + } + + if (showRssMenuItem.value) { + items.push({ + icon: "mdi mdi-rss", + label: rssMenuTitle.value, + url: rssIndexPath.value, + }) + } + items.push(createMenuItem("my_agenda", "mdi-calendar-text", "Agenda", "CCalendarEventList")) if (allowSearchFeature.value && isMenuTabEnabled("search")) { diff --git a/public/main/admin/settings.lib.php b/public/main/admin/settings.lib.php index 3d014f3a5b9..4583c008def 100644 --- a/public/main/admin/settings.lib.php +++ b/public/main/admin/settings.lib.php @@ -335,6 +335,7 @@ function getStablePluginAllowList(): array 'EmbedRegistry', 'SearchCourse', 'Rss', + 'Dictionary', ]; } diff --git a/public/plugin/Dictionary/DictionaryPlugin.php b/public/plugin/Dictionary/DictionaryPlugin.php index 965663fa83e..766351391db 100644 --- a/public/plugin/Dictionary/DictionaryPlugin.php +++ b/public/plugin/Dictionary/DictionaryPlugin.php @@ -3,54 +3,344 @@ /* For licensing terms, see /license.txt */ /** - * Class DictionaryPlugin. + * Dictionary plugin. */ class DictionaryPlugin extends Plugin { - /** - * DictionaryPlugin constructor. - */ + public const TABLE_DICTIONARY = 'plugin_dictionary'; + public const PLUGIN_NAME = 'Dictionary'; + public const DEFAULT_REGION_LIMIT = 5; + protected function __construct() { - parent::__construct( - '1.0', - 'Julio Montoya', + parent::__construct('1.1', 'Julio Montoya'); + + $this->isAdminPlugin = true; + } + + public static function create(): self + { + static $instance = null; + + return $instance ??= new self(); + } + + public function get_info(): array + { + $info = parent::get_info(); + $info['supports_regions'] = false; + + return $info; + } + + public function getDictionaryPageUrl(array $params = []): string + { + $url = api_get_path(WEB_PATH).'plugin/'.self::PLUGIN_NAME.'/index.php'; + + if ([] !== $params) { + $url .= '?'.http_build_query($params); + } + + return $url; + } + + public function getAdminUrl() + { + return api_get_path(WEB_PLUGIN_PATH).self::PLUGIN_NAME.'/admin.php'; + } + + public function install(): void + { + $this->ensureTableExists(); + } + + public function uninstall(): void + { + Database::query('DROP TABLE IF EXISTS '.self::TABLE_DICTIONARY); + } + + public function renderRegion($region): string + { + return ''; + } + + public function renderBlock(): string + { + $terms = $this->getTerms('', self::DEFAULT_REGION_LIMIT); + + $html = '
'; + $html .= '
'; + $html .= '

'.$this->escape($this->get_lang('Dictionary')).'

'; + $html .= '

'.$this->escape($this->get_title()).'

'; + $html .= '
'; + + $html .= $this->renderSearchForm('region'); + + if ([] === $terms) { + $html .= '
'; + $html .= $this->escape($this->get_lang('NoTermsAvailable')); + $html .= '
'; + $html .= '
'; + + return $html; + } + + $html .= '
'; + + foreach ($terms as $term) { + $html .= $this->renderTermPreview($term); + } + + $html .= '
'; + $html .= '
'; + $html .= ''; + $html .= ''; + $html .= $this->escape($this->get_lang('ViewFullDictionary')); + $html .= ''; + $html .= '
'; + $html .= ''; + + return $html; + } + + public function renderFullPage(string $keyword = ''): string + { + $this->ensureTableExists(); + + $terms = $this->getTerms($keyword); + + $html = ' + + '; + + $html .= '
'; + $html .= '
'; + $html .= '
'; + $html .= '

'.$this->escape($this->get_lang('Dictionary')).'

'; + $html .= '

'.$this->escape($this->get_title()).'

'; + $html .= '

'.$this->escape($this->get_comment()).'

'; + $html .= '
'; + $html .= $this->renderSearchForm('full', $keyword); + $html .= '
'; + + $html .= '
'; + $html .= '
'; + $html .= '

'.$this->escape($this->get_lang('Terms')).'

'; + $html .= ''.count($terms).''; + $html .= '
'; + + if ([] === $terms) { + $html .= '
'; + $html .= $this->escape($this->get_lang('NoTermsFound')); + $html .= '
'; + $html .= '
'; + + return $html; + } + + $html .= '
'; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + + foreach ($terms as $term) { + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + } + + $html .= '
'.$this->escape($this->get_lang('Term')).''.$this->escape($this->get_lang('Definition')).'
'.$this->escape((string) $term['term']).''.nl2br($this->escape((string) $term['definition'])).'
'; + $html .= ''; + $html .= ''; + + return $html; + } + + public function renderSearchForm(string $context, string $keyword = ''): string + { + $inputId = 'dictionary-search-'.$context; + + $html = '
'; + $html .= '
'; + $html .= ''; + $html .= 'escape($this->get_lang('SearchPlaceholder')).'">'; + $html .= '
'; + $html .= ''; + + if ('' !== $keyword) { + $html .= ''; + $html .= ''; + $html .= $this->escape($this->get_lang('ClearSearch')); + $html .= ''; + } + + $html .= '
'; + + return $html; + } + + public function getTerms(string $keyword = '', int $limit = 0): array + { + $this->ensureTableExists(); + + $conditions = []; + + if ('' !== trim($keyword)) { + $keyword = Database::escape_string(trim($keyword)); + $conditions[] = "(term LIKE '%$keyword%' OR definition LIKE '%$keyword%')"; + } + + $where = [] === $conditions ? '' : ' WHERE '.implode(' AND ', $conditions); + $sql = 'SELECT id, term, definition FROM '.self::TABLE_DICTIONARY.$where.' ORDER BY term'; + + if ($limit > 0) { + $sql .= ' LIMIT '.(int) $limit; + } + + $result = Database::query($sql); + + if (!$result) { + return []; + } + + return Database::store_result($result, 'ASSOC'); + } + + public function getTermById(int $id): ?array + { + if ($id <= 0) { + return null; + } + + $this->ensureTableExists(); + + $sql = 'SELECT id, term, definition FROM '.self::TABLE_DICTIONARY.' WHERE id = '.(int) $id.' LIMIT 1'; + $result = Database::query($sql); + $term = Database::fetch_assoc($result); + + return empty($term) ? null : $term; + } + + public function addTerm(string $term, string $definition): bool + { + $this->ensureTableExists(); + + $term = trim(Security::remove_XSS($term)); + $definition = trim(Security::remove_XSS($definition)); + + if ('' === $term || '' === $definition) { + return false; + } + + return (bool) Database::insert( + self::TABLE_DICTIONARY, [ - 'enable_plugin_dictionary' => 'boolean', + 'term' => $term, + 'definition' => $definition, ] ); } - /** - * @return DictionaryPlugin|null - */ - public static function create() + public function updateTerm(int $id, string $term, string $definition): bool { - static $result = null; + $this->ensureTableExists(); + + if ($id <= 0) { + return false; + } - return $result ?: $result = new self(); + $term = trim(Security::remove_XSS($term)); + $definition = trim(Security::remove_XSS($definition)); + + if ('' === $term || '' === $definition) { + return false; + } + + return (bool) Database::update( + self::TABLE_DICTIONARY, + [ + 'term' => $term, + 'definition' => $definition, + ], + ['id = ?' => $id] + ); } - /** - * Installation process. - */ - public function install() + public function deleteTerm(int $id): bool { - $sql = 'CREATE TABLE IF NOT EXISTS plugin_dictionary ( - id INT NOT NULL AUTO_INCREMENT, - term VARCHAR(255) NOT NULL, - definition LONGTEXT NOT NULL, - PRIMARY KEY (id)); - '; - Database::query($sql); + $this->ensureTableExists(); + + if ($id <= 0) { + return false; + } + + return (bool) Database::delete(self::TABLE_DICTIONARY, ['id = ?' => $id]); } - /** - * Uninstall process. - */ - public function uninstall() + public function ensureTableExists(): void { - $sql = 'DROP TABLE IF EXISTS plugin_dictionary'; + $sql = 'CREATE TABLE IF NOT EXISTS '.self::TABLE_DICTIONARY.' ( + id INT NOT NULL AUTO_INCREMENT, + term VARCHAR(255) NOT NULL, + definition LONGTEXT NOT NULL, + PRIMARY KEY (id), + INDEX idx_plugin_dictionary_term (term) + ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci'; + Database::query($sql); } + + public function isCurrentDictionaryPage(): bool + { + $scriptName = (string) ($_SERVER['SCRIPT_NAME'] ?? ''); + $phpSelf = (string) ($_SERVER['PHP_SELF'] ?? ''); + $requestUri = (string) ($_SERVER['REQUEST_URI'] ?? ''); + + $pluginPath = '/plugin/'.self::PLUGIN_NAME.'/'; + + return str_contains($scriptName, $pluginPath) + || str_contains($phpSelf, $pluginPath) + || str_contains($requestUri, $pluginPath); + } + + private function renderTermPreview(array $term): string + { + $definition = (string) ($term['definition'] ?? ''); + $definition = trim(strip_tags($definition)); + + if (api_strlen($definition) > 160) { + $definition = api_substr($definition, 0, 157).'...'; + } + + return ' +
+

'.$this->escape((string) ($term['term'] ?? '')).'

+

'.$this->escape($definition).'

+
'; + } + + private function escape(string $value): string + { + return htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); + } } diff --git a/public/plugin/Dictionary/admin.php b/public/plugin/Dictionary/admin.php new file mode 100644 index 00000000000..24835edf798 --- /dev/null +++ b/public/plugin/Dictionary/admin.php @@ -0,0 +1,5 @@ +isEnabled()) { + if ($isDirectRequest && !$isRenderingOwnFullPage) { + api_not_allowed(true); + } + + return; +} + +if ($isRenderingOwnFullPage) { + return; +} + +if (!$isDirectRequest) { + echo $plugin->renderBlock(); + + return; +} + +define('DICTIONARY_FULL_PAGE_RENDERING', true); + +$keyword = isset($_GET['q']) ? trim(Security::remove_XSS((string) $_GET['q'])) : ''; + +$content = $plugin->renderFullPage($keyword); + +$template = new Template($plugin->get_title()); +$template->assign('header', $plugin->get_title()); +$template->assign('content', $content); +$template->display_one_col_template(); diff --git a/public/plugin/Dictionary/install.php b/public/plugin/Dictionary/install.php index 4ae0dbbf227..88d88f6b321 100644 --- a/public/plugin/Dictionary/install.php +++ b/public/plugin/Dictionary/install.php @@ -1,8 +1,15 @@ install(); diff --git a/public/plugin/Dictionary/lang/en_US.php b/public/plugin/Dictionary/lang/en_US.php index 85e9d9cc61a..ae31934cd1d 100644 --- a/public/plugin/Dictionary/lang/en_US.php +++ b/public/plugin/Dictionary/lang/en_US.php @@ -1,8 +1,19 @@ get_info(); diff --git a/public/plugin/Dictionary/terms.php b/public/plugin/Dictionary/terms.php index 680914addb9..6714b63a4e7 100644 --- a/public/plugin/Dictionary/terms.php +++ b/public/plugin/Dictionary/terms.php @@ -3,84 +3,130 @@ /* For licensing terms, see /license.txt */ require_once __DIR__.'/../../main/inc/global.inc.php'; +require_once __DIR__.'/DictionaryPlugin.php'; api_protect_admin_script(); $plugin = DictionaryPlugin::create(); -$table = 'plugin_dictionary'; -$sql = "SELECT * FROM $table ORDER BY TERM"; -$result = Database::query($sql); -$terms = Database::store_result($result, 'ASSOC'); +if (!$plugin->isEnabled()) { + api_not_allowed(true); +} + +$plugin->ensureTableExists(); -$action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : 'add'; +$action = isset($_GET['action']) ? Security::remove_XSS((string) $_GET['action']) : 'list'; $id = isset($_GET['id']) ? (int) $_GET['id'] : 0; +if (!in_array($action, ['list', 'add', 'edit', 'delete'], true)) { + $action = 'list'; +} + +$currentUrl = api_get_self(); + +if ('delete' === $action) { + if ('POST' !== ($_SERVER['REQUEST_METHOD'] ?? '')) { + api_not_allowed(true); + } + + if (false === Security::check_token('post')) { + Security::clear_token(); + Display::addFlash(Display::return_message(get_lang('Invalid security token'), 'error')); + header('Location: '.$currentUrl); + exit; + } + + if ($plugin->deleteTerm($id)) { + Display::addFlash(Display::return_message(get_lang('Deleted'))); + } else { + Display::addFlash(Display::return_message(get_lang('The item could not be deleted'), 'error')); + } + + Security::clear_token(); + header('Location: '.$currentUrl); + exit; +} + $term = null; -if (!empty($id)) { - $sql = "SELECT * FROM $table WHERE id = $id"; - $result = Database::query($sql); - $term = Database::fetch_assoc($result); + +if ('edit' === $action) { + $term = $plugin->getTermById($id); + if (empty($term)) { api_not_allowed(true); } } -$form = new FormValidator('dictionary', 'post', api_get_self().'?action='.$action.'&id='.$id); -$form->addText('term', $plugin->get_lang('Term'), true); -$form->addTextarea('definition', $plugin->get_lang('Definition'), [], true); -//$form->addHtmlEditor('definition', get_lang('Definition'), true); -$form->addButtonSave(get_lang('Save')); - -switch ($action) { - case 'add': - if ($form->validate()) { - $values = $form->getSubmitValues(); - $params = [ - 'term' => $values['term'], - 'definition' => $values['definition'], - ]; - $result = Database::insert($table, $params); - if ($result) { - Display::addFlash(Display::return_message(get_lang('Added'))); - } - header('Location: '.api_get_self()); - exit; - } +$form = null; +$formHtml = ''; + +if (in_array($action, ['add', 'edit'], true)) { + $formUrl = api_get_self().'?action='.$action; + + if ('edit' === $action) { + $formUrl .= '&id='.$id; + } - break; - case 'edit': + $form = new FormValidator('dictionary', 'post', $formUrl); + $form->addHeader('add' === $action ? $plugin->get_lang('AddTerm') : $plugin->get_lang('EditTerm')); + $form->addText('term', $plugin->get_lang('Term'), true); + $form->addTextarea('definition', $plugin->get_lang('Definition'), [], true); + + if ('add' === $action) { + $form->addButtonCreate($plugin->get_lang('AddTerm')); + } else { + $form->addButtonUpdate($plugin->get_lang('UpdateTerm')); + } + + if ('edit' === $action && !empty($term)) { $form->setDefaults($term); - if ($form->validate()) { - $values = $form->getSubmitValues(); - $params = [ - 'term' => $values['term'], - 'definition' => $values['definition'], - ]; - Database::update($table, $params, ['id = ?' => $id]); - Display::addFlash(Display::return_message(get_lang('Update successful'))); - - header('Location: '.api_get_self()); + } + + if ($form->validate()) { + if (false === Security::check_token('post')) { + Security::clear_token(); + Display::addFlash(Display::return_message(get_lang('Invalid security token'), 'error')); + header('Location: '.$currentUrl); exit; } - break; - case 'delete': - if (!empty($term)) { - Database::delete($table, ['id = ?' => $id]); - Display::addFlash(Display::return_message(get_lang('Deleted'))); - header('Location: '.api_get_self()); - exit; + $values = $form->getSubmitValues(); + $submittedTerm = isset($values['term']) ? (string) $values['term'] : ''; + $submittedDefinition = isset($values['definition']) ? (string) $values['definition'] : ''; + + if ('add' === $action) { + $result = $plugin->addTerm($submittedTerm, $submittedDefinition); + $message = $result ? get_lang('Added') : get_lang('The item could not be added'); + } else { + $result = $plugin->updateTerm($id, $submittedTerm, $submittedDefinition); + $message = $result ? get_lang('Update successful') : get_lang('The item could not be updated'); } - break; + Display::addFlash(Display::return_message($message, $result ? 'success' : 'error')); + Security::clear_token(); + header('Location: '.$currentUrl); + exit; + } + + $token = Security::get_token(); + $form->addElement('hidden', 'sec_token'); + $form->setConstants(['sec_token' => $token]); + $formHtml = $form->returnForm(); } +$terms = $plugin->getTerms(); +$deleteToken = 'list' === $action ? Security::get_token() : ''; + $tpl = new Template($plugin->get_lang('plugin_title')); +$tpl->assign('mode', in_array($action, ['add', 'edit'], true) ? 'form' : 'list'); $tpl->assign('terms', $terms); -$tpl->assign('form', $form->returnForm()); +$tpl->assign('form', $formHtml); +$tpl->assign('delete_token', $deleteToken); +$tpl->assign('admin_url', api_get_self()); +$tpl->assign('add_url', api_get_self().'?action=add'); +$tpl->assign('back_url', api_get_self()); + $content = $tpl->fetch('/'.$plugin->get_name().'/view/terms.html.twig'); -// Assign into content + $tpl->assign('content', $content); -// Display $tpl->display_one_col_template(); diff --git a/public/plugin/Dictionary/uninstall.php b/public/plugin/Dictionary/uninstall.php new file mode 100644 index 00000000000..0fece6bd456 --- /dev/null +++ b/public/plugin/Dictionary/uninstall.php @@ -0,0 +1,15 @@ +uninstall(); diff --git a/public/plugin/Dictionary/view/terms.html.twig b/public/plugin/Dictionary/view/terms.html.twig index 8cdcb546b9d..7c48a7a624f 100644 --- a/public/plugin/Dictionary/view/terms.html.twig +++ b/public/plugin/Dictionary/view/terms.html.twig @@ -1,35 +1,112 @@ -{% autoescape false %} -{{ form }} +
+
+
+
+

+ {{ 'Dictionary' | get_plugin_lang('DictionaryPlugin') }} +

+

+ {{ 'plugin_title' | get_plugin_lang('DictionaryPlugin') }} +

+

+ {{ 'plugin_comment' | get_plugin_lang('DictionaryPlugin') }} +

+
- - - - - - -{% for term in terms %} - - - - - -{% endfor %} -
- {{ 'Term' | get_plugin_lang('DictionaryPlugin') }} - - {{ 'Definition' | get_plugin_lang('DictionaryPlugin') }} - - {{ 'Actions' | get_lang }} -
- {{ term.term }} - - {{ term.definition }} - - - {{ 'Edit'|get_lang }} - - - {{ 'Delete'|get_lang }} - -
-{% endautoescape %} + +
+
+ + {% if mode == 'form' %} +
+ {{ form|raw }} +
+ {% else %} +
+
+

+ {{ 'Terms' | get_plugin_lang('DictionaryPlugin') }} +

+ + {{ terms|length }} + +
+ + {% if terms is empty %} +
+ {{ 'NoTermsAvailable' | get_plugin_lang('DictionaryPlugin') }} +
+ {% else %} +
+ + + + + + + + + + {% for term in terms %} + + + + + + {% endfor %} + +
+ {{ 'Term' | get_plugin_lang('DictionaryPlugin') }} + + {{ 'Definition' | get_plugin_lang('DictionaryPlugin') }} + + {{ 'Actions' | get_lang }} +
+ {{ term.term }} + + {{ term.definition|nl2br }} + +
+ + + + +
+ + +
+
+
+
+ {% endif %} +
+ {% endif %} +
diff --git a/public/plugin/Rss/lib/rss_plugin.class.php b/public/plugin/Rss/lib/rss_plugin.class.php index 711533d04c9..cfde22ca993 100644 --- a/public/plugin/Rss/lib/rss_plugin.class.php +++ b/public/plugin/Rss/lib/rss_plugin.class.php @@ -33,7 +33,7 @@ public static function create(): self public function get_info(): array { $info = parent::get_info(); - $info['supports_regions'] = true; + $info['supports_regions'] = false; return $info; } @@ -55,22 +55,15 @@ public function getFeedPageUrl(): string public function renderRegion($region): string { - if (!$this->isEnabled()) { - return ''; - } - - if (defined('RSS_FULL_PAGE_RENDERING') && RSS_FULL_PAGE_RENDERING) { - return ''; - } - - return $this->renderBlock(); + return ''; } - public function renderBlock(): string + public function renderBlock(bool $isRegionBlock = true): string { $url = $this->get_rss(); + $regionAttribute = $isRegionBlock ? ' data-rss-region-block="1"' : ''; - $content = '
'; + $content = '
'; $content .= $this->renderHeader(); if ('' === $url) { @@ -118,18 +111,8 @@ public function renderBlock(): string public function renderFullPage(): string { - $content = ' - - '; - - $content .= '
'; - $content .= $this->renderBlock(); + $content = '
'; + $content .= $this->renderBlock(false); $content .= '
'; return $content; diff --git a/public/plugin/SearchCourse/lib/search_course_plugin.class.php b/public/plugin/SearchCourse/lib/search_course_plugin.class.php index 9c70f53a80c..af3db3cb0b2 100644 --- a/public/plugin/SearchCourse/lib/search_course_plugin.class.php +++ b/public/plugin/SearchCourse/lib/search_course_plugin.class.php @@ -20,7 +20,7 @@ public static function create(): self public function get_info(): array { $info = parent::get_info(); - $info['supports_regions'] = true; + $info['supports_regions'] = false; return $info; } @@ -32,19 +32,7 @@ public function getSearchPageUrl(): string public function renderRegion($region): string { - if (!$this->isEnabled()) { - return ''; - } - - if ($this->isCurrentSearchCoursePage()) { - return ''; - } - - if (!class_exists('SearchCourseWidget')) { - require_once __DIR__.'/search_course_widget.class.php'; - } - - return SearchCourseWidget::factory()->renderBlock(); + return ''; } public function isCurrentSearchCoursePage(): bool diff --git a/src/CoreBundle/Controller/PlatformConfigurationController.php b/src/CoreBundle/Controller/PlatformConfigurationController.php index 46f60fe29d6..eeb7e208dbd 100644 --- a/src/CoreBundle/Controller/PlatformConfigurationController.php +++ b/src/CoreBundle/Controller/PlatformConfigurationController.php @@ -8,6 +8,7 @@ use Bbb; use BuyCoursesPlugin; +use DictionaryPlugin; use Chamilo\CoreBundle\Helpers\AuthenticationConfigHelper; use Chamilo\CoreBundle\Helpers\ThemeHelper; use Chamilo\CoreBundle\Helpers\TicketProjectHelper; @@ -19,6 +20,8 @@ use Chamilo\CourseBundle\Settings\SettingsCourseManager; use Doctrine\ORM\EntityManagerInterface; use OnlyofficePlugin; +use RssPlugin; +use SearchCoursePlugin; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; @@ -114,6 +117,9 @@ public function list( $configuration['plugins']['buycourses'] = $this->getBuyCoursesFrontendConfig(); $configuration['plugins']['tour'] = $this->getTourFrontendConfig(); + $configuration['plugins']['searchcourse'] = $this->getSearchCourseFrontendConfig(); + $configuration['plugins']['rss'] = $this->getRssFrontendConfig(); + $configuration['plugins']['dictionary'] = $this->getDictionaryFrontendConfig(); if ($this->isGranted('ROLE_USER')) { $variables = [ @@ -391,6 +397,74 @@ private function decodeSetting(mixed $setting): mixed return []; } + + private function getSearchCourseFrontendConfig(): array + { + if (!$this->loadLegacyPluginClass('SearchCourse/lib/search_course_plugin.class.php') + || !class_exists('SearchCoursePlugin') + ) { + return ['enabled' => false]; + } + + $plugin = SearchCoursePlugin::create(); + $enabled = $plugin->isEnabled(); + + return [ + 'enabled' => $enabled, + 'title' => $enabled ? $plugin->get_title() : '', + 'indexPath' => '/plugin/SearchCourse/index.php', + ]; + } + + private function getRssFrontendConfig(): array + { + if (!$this->loadLegacyPluginClass('Rss/lib/rss_plugin.class.php') + || !class_exists('RssPlugin') + ) { + return ['enabled' => false]; + } + + $plugin = RssPlugin::create(); + $enabled = $plugin->isEnabled(); + + return [ + 'enabled' => $enabled, + 'title' => $enabled ? $plugin->get_title() : '', + 'indexPath' => '/plugin/Rss/index.php', + ]; + } + + private function getDictionaryFrontendConfig(): array + { + if (!$this->loadLegacyPluginClass('Dictionary/DictionaryPlugin.php') + || !class_exists('DictionaryPlugin') + ) { + return ['enabled' => false]; + } + + $plugin = DictionaryPlugin::create(); + $enabled = $plugin->isEnabled(); + + return [ + 'enabled' => $enabled, + 'title' => $enabled ? $plugin->get_title() : '', + 'indexPath' => '/plugin/Dictionary/index.php', + ]; + } + + private function loadLegacyPluginClass(string $relativePath): bool + { + $filePath = dirname(__DIR__, 3).'/public/plugin/'.$relativePath; + + if (!is_file($filePath)) { + return false; + } + + require_once $filePath; + + return true; + } + private function getOnlyofficeFrontendConfig(): array { $onlyoffice = OnlyofficePlugin::create();