diff --git a/PluginTemplatePlugin.php b/PluginTemplatePlugin.php index 69e0135..bba322c 100644 --- a/PluginTemplatePlugin.php +++ b/PluginTemplatePlugin.php @@ -2,8 +2,8 @@ /** * @file PluginTemplatePlugin.php * - * Copyright (c) 2017-2023 Simon Fraser University - * Copyright (c) 2017-2023 John Willinsky + * Copyright (c) 2017-2026 Simon Fraser University + * Copyright (c) 2017-2026 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * * @class PluginTemplatePlugin @@ -12,25 +12,41 @@ namespace APP\plugins\generic\pluginTemplate; -use APP\core\Request; +use APP\core\Application; use APP\plugins\generic\pluginTemplate\classes\FrontEnd\ArticleDetails; -use APP\plugins\generic\pluginTemplate\classes\Settings\Actions; -use APP\plugins\generic\pluginTemplate\classes\Settings\Manage; -use PKP\core\JSONMessage; +use PKP\core\APIRouter; +use PKP\linkAction\LinkAction; +use PKP\linkAction\request\VueModal; use PKP\plugins\GenericPlugin; use PKP\plugins\Hook; class PluginTemplatePlugin extends GenericPlugin { + private PluginTemplateSettingsController $controller; + /** @copydoc GenericPlugin::register() */ public function register($category, $path, $mainContextId = null): bool { - $success = parent::register($category, $path); + $success = parent::register($category, $path, $mainContextId); + + if (Application::isUnderMaintenance()) { + return $success; + } - if ($success && $this->getEnabled()) { + if ($success && $this->getEnabled($mainContextId)) { // Display the publication statement on the article details page $articleDetails = new ArticleDetails($this); Hook::add('Templates::Article::Main', $articleDetails->addPublicationStatement(...)); + + // Register the settings API controller + $this->controller = new PluginTemplateSettingsController($this); + + Hook::add('APIHandler::endpoints::plugin', function (string $hookName, APIRouter $apiRouter): bool { + $apiRouter->registerPluginApiControllers([ + $this->controller, + ]); + return Hook::CONTINUE; + }); } return $success; @@ -61,26 +77,42 @@ public function getDescription(): string /** * Add a settings action to the plugin's entry in the plugins list. * - * @param Request $request + * @param \APP\core\Request $request * @param array $actionArgs */ public function getActions($request, $actionArgs): array { - $actions = new Actions($this); - return $actions->execute($request, $actionArgs, parent::getActions($request, $actionArgs)); - } + $actions = parent::getActions($request, $actionArgs); - /** - * Load a form when the `settings` button is clicked and - * save the form when the user saves it. - * - * @param array $args - * @param Request $request - */ - public function manage($args, $request): JSONMessage - { - $manage = new Manage($this); - return $manage->execute($args, $request); + if (!$this->getEnabled()) { + return $actions; + } + + $context = $request->getContext(); + $apiUrl = $request->getDispatcher()->url( + $request, + Application::ROUTE_API, + $context->getPath(), + $this->controller->getHandlerPath() + ); + + $form = new PluginTemplateSettingsForm($apiUrl); + + array_unshift($actions, new LinkAction( + 'settings', + new VueModal( + 'PkpFormModal', + [ + 'title' => $this->getDisplayName(), + 'formConfig' => $form->getConfig(), + 'getApiUrl' => $apiUrl, + ] + ), + __('manager.plugins.settings'), + null + )); + + return $actions; } } diff --git a/PluginTemplateSettingsController.php b/PluginTemplateSettingsController.php new file mode 100644 index 0000000..f01798b --- /dev/null +++ b/PluginTemplateSettingsController.php @@ -0,0 +1,48 @@ +getRequest()->getContext()->getId(); + + return response()->json( + [Constants::PUBLICATION_STATEMENT => $this->plugin->getSetting($contextId, Constants::PUBLICATION_STATEMENT) ?? ''], + Response::HTTP_OK + ); + } + + public function edit(EditPluginTemplateSettings $illuminateRequest): JsonResponse + { + $contextId = $this->getRequest()->getContext()->getId(); + $publicationStatement = $illuminateRequest->validated()[Constants::PUBLICATION_STATEMENT]; + + $this->plugin->updateSetting($contextId, Constants::PUBLICATION_STATEMENT, $publicationStatement); + + return response()->json( + [Constants::PUBLICATION_STATEMENT => $publicationStatement], + Response::HTTP_OK + ); + } +} diff --git a/PluginTemplateSettingsForm.php b/PluginTemplateSettingsForm.php new file mode 100644 index 0000000..e72ed6d --- /dev/null +++ b/PluginTemplateSettingsForm.php @@ -0,0 +1,36 @@ +action = $action; + + $this->addField(new FieldText(Constants::PUBLICATION_STATEMENT, [ + 'label' => __('plugins.generic.pluginTemplate.publicationStatement'), + 'description' => __('plugins.generic.pluginTemplate.publicationStatement.description'), + 'value' => '', + ])); + } +} diff --git a/classes/Constants.php b/classes/Constants.php index 48361b4..5648157 100644 --- a/classes/Constants.php +++ b/classes/Constants.php @@ -14,11 +14,6 @@ class Constants { - /** - * The file name of the settings template - */ - public const SETTINGS_TEMPLATE = 'settings.tpl'; - /** * The name of the publication statement, * used to save to the database and to show on the front end. diff --git a/classes/Settings/Actions.php b/classes/Settings/Actions.php deleted file mode 100644 index cf9c362..0000000 --- a/classes/Settings/Actions.php +++ /dev/null @@ -1,75 +0,0 @@ -plugin = &$plugin; - } - - /** - * Add a settings action to the plugin's entry in the plugins list. - * - * @param Request $request - * @param array $actionArgs - * @param array $parentActions - */ - public function execute(Request $request, array $actionArgs, array $parentActions): array - { - // Only add the settings action when the plugin is enabled - if (!$this->plugin->getEnabled()) return $parentActions; - - // Create a LinkAction that will make a request to the - // plugin's `manage` method with the `settings` verb. - $router = $request->getRouter(); - - $linkAction = new LinkAction( - 'settings', - new AjaxModal( - $router->url( - $request, - null, - null, - 'manage', - null, - [ - 'verb' => 'settings', - 'plugin' => $this->plugin->getName(), - 'category' => 'generic' - ] - ), - $this->plugin->getDisplayName() - ), - __('manager.plugins.settings'), - null - ); - - // Add the LinkAction to the existing actions. - // Make it the first action to be consistent with - // other plugins. - array_unshift($parentActions, $linkAction); - - return $parentActions; - } -} diff --git a/classes/Settings/Manage.php b/classes/Settings/Manage.php deleted file mode 100644 index 08d2e6a..0000000 --- a/classes/Settings/Manage.php +++ /dev/null @@ -1,62 +0,0 @@ -plugin = &$plugin; - } - - /** - * Load a form when the `settings` button is clicked and - * save the form when the user saves it. - * - * @param array $args - * @param Request $request - */ - public function execute(array $args, Request $request): JSONMessage - { - switch ($request->getUserVar('verb')) { - case 'settings': - - // Load the custom form - $form = new SettingsForm($this->plugin); - - // Fetch the form the first time it loads, before - // the user has tried to save it - if (!$request->getUserVar('save')) { - $form->initData(); - return new JSONMessage(true, $form->fetch($request)); - } - - // Validate and save the form data - $form->readInputData(); - if ($form->validate()) { - $form->execute(); - return new JSONMessage(true); - } - } - - return new JSONMessage(false); - } -} \ No newline at end of file diff --git a/classes/Settings/SettingsForm.php b/classes/Settings/SettingsForm.php deleted file mode 100644 index deeb406..0000000 --- a/classes/Settings/SettingsForm.php +++ /dev/null @@ -1,122 +0,0 @@ -plugin = &$plugin; - - parent::__construct($this->plugin->getTemplateResource(Constants::SETTINGS_TEMPLATE)); - - $this->addCheck(new FormValidatorPost($this)); - $this->addCheck(new FormValidatorCSRF($this)); - } - - /** - * Load settings already saved in the database - * - * Settings are stored by context, so that each journal, press, - * or preprint server can have different settings. - */ - public function initData(): void - { - $context = Application::get() - ->getRequest() - ->getContext(); - - $this->setData( - Constants::PUBLICATION_STATEMENT, - $this->plugin->getSetting( - $context->getId(), - Constants::PUBLICATION_STATEMENT - ) - ); - - parent::initData(); - } - - /** - * Load data that was submitted with the form - */ - public function readInputData(): void - { - $this->readUserVars([Constants::PUBLICATION_STATEMENT]); - - parent::readInputData(); - } - - /** - * Fetch any additional data needed for your form. - * - * Data assigned to the form using $this->setData() during the - * initData() or readInputData() methods will be passed to the - * template. - * - * In the example below, the plugin name is passed to the - * template so that it can be used in the URL that the form is - * submitted to. - */ - public function fetch($request, $template = null, $display = false): ?string - { - $templateMgr = TemplateManager::getManager($request); - $templateMgr->assign('pluginName', $this->plugin->getName()); - - return parent::fetch($request, $template, $display); - } - - /** - * Save the plugin settings and notify the user - * that the save was successful - */ - public function execute(...$functionArgs): mixed - { - $context = Application::get() - ->getRequest() - ->getContext(); - - $this->plugin->updateSetting( - $context->getId(), - Constants::PUBLICATION_STATEMENT, - $this->getData(Constants::PUBLICATION_STATEMENT) - ); - - $notificationMgr = new NotificationManager(); - $notificationMgr->createTrivialNotification( - Application::get()->getRequest()->getUser()->getId(), - Notification::NOTIFICATION_TYPE_SUCCESS, - ['contents' => __('common.changesSaved')] - ); - - return parent::execute(); - } -} diff --git a/cypress/tests/functional/PluginTemplatePlugin.cy.js b/cypress/tests/functional/PluginTemplatePlugin.cy.js index 114dbf9..f30deb3 100644 --- a/cypress/tests/functional/PluginTemplatePlugin.cy.js +++ b/cypress/tests/functional/PluginTemplatePlugin.cy.js @@ -1,8 +1,8 @@ /** * @file cypress/tests/functional/PluginTemplatePlugin.cy.js * - * Copyright (c) 2014-2023 Simon Fraser University - * Copyright (c) 2000-2023 John Willinsky + * Copyright (c) 2014-2026 Simon Fraser University + * Copyright (c) 2000-2026 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file LICENSE. * */ @@ -11,7 +11,8 @@ describe('Plugin template plugin tests', function() { it('Sets up the testing environment', function() { cy.login('admin', 'admin', 'publicknowledge'); - cy.get('.app__nav a').contains('Website').click(); + cy.get('nav').contains('Settings').click(); + cy.get('nav').contains('Website').click({force: true}); cy.get('button[id="plugins-button"]').click(); // Find and enable the plugin @@ -21,16 +22,26 @@ describe('Plugin template plugin tests', function() { it('Configures the plugin', function() { cy.login('admin', 'admin', 'publicknowledge'); - cy.get('.app__nav a').contains('Website').click(); + cy.get('nav').contains('Settings').click(); + cy.get('nav').contains('Website').click({force: true}); cy.get('button[id="plugins-button"]').click(); cy.get('a[id^="component-grid-settings-plugins-settingsplugingrid-category-generic-row-plugintemplateplugin-settings-button-"]', {timeout: 20_000}).as('settings'); cy.waitJQuery(); cy.wait(2000); cy.get('@settings').click({force: true}); - cy.get('input[id^="publicationStatement-"]').clear().type('Test publication statement', {delay: 0}); - cy.get('form[id="pluginTemplateSettings"] button[id^="submitFormButton"]').click(); - cy.waitJQuery(); + + // Wait for the Vue.js side modal to appear + cy.get('[role="dialog"]').should('be.visible'); + + // Fill in the publication statement field + cy.get('[role="dialog"]').within(() => { + cy.get('input[name="publicationStatement"]').clear().type('Test publication statement', {delay: 0}); + cy.get('button:contains("Save")').click(); + }); + + // Wait for the modal to close + cy.get('[role="dialog"]').should('not.exist'); }); it('Tests the article view', function() { // Visit homepage @@ -38,4 +49,3 @@ describe('Plugin template plugin tests', function() { cy.get('p:contains("Test publication statement")'); }); }) - diff --git a/formRequests/EditPluginTemplateSettings.php b/formRequests/EditPluginTemplateSettings.php new file mode 100644 index 0000000..a4c26e5 --- /dev/null +++ b/formRequests/EditPluginTemplateSettings.php @@ -0,0 +1,32 @@ + [ + 'nullable', + 'string', + 'max:500', + ], + ]; + } +} diff --git a/templates/settings.tpl b/templates/settings.tpl deleted file mode 100644 index d4bc2b6..0000000 --- a/templates/settings.tpl +++ /dev/null @@ -1,34 +0,0 @@ -{** - * templates/settings.tpl - * - * Copyright (c) 2014-2023 Simon Fraser University - * Copyright (c) 2003-2023 John Willinsky - * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. - * - * Settings form for the pluginTemplate plugin. - *} - - -