From 320a8110afeae54555cfa1c2949f2e62922bb4fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jer=C3=B4me=20Bakker?= Date: Thu, 17 Nov 2022 15:56:44 +0100 Subject: [PATCH] feat(forms): automatically support sticky forms fixes #11141 --- actions/register.php | 4 - actions/useradd.php | 4 - docs/appendix/upgrade-notes/4.x-to-5.0.rst | 18 ++- docs/guides/actions.rst | 115 +++++++------- docs/guides/events-list.rst | 4 + engine/classes/Elgg/Forms/PrepareFields.php | 47 ++++++ engine/classes/Elgg/Forms/StickyForms.php | 3 + engine/classes/Elgg/FormsService.php | 30 +++- .../Router/Middleware/ActionMiddleware.php | 66 +++++++- engine/events.php | 5 + .../Elgg/Forms/StickyFormsIntegrationTest.php | 17 ++ .../Elgg/FormsServiceIntegrationTest.php | 146 ++++++++++++++++++ .../unit/Elgg/FormsServiceUnitTest.php | 46 +++++- .../views/default/elements/forms/footer.php | 28 +++- .../views/default/forms/foo/bar.html.php | 7 +- .../views/default/resources/index.php | 8 +- mod/blog/actions/blog/save.php | 6 - .../classes/Elgg/Blog/Forms/PrepareFields.php | 74 +++++++++ mod/blog/elgg-plugin.php | 8 +- mod/blog/lib/functions.php | 79 ---------- mod/blog/views/default/resources/blog/add.php | 3 +- .../views/default/resources/blog/edit.php | 19 +-- mod/bookmarks/actions/bookmarks/save.php | 4 - .../Elgg/Bookmarks/Forms/PrepareFields.php | 45 ++++++ mod/bookmarks/elgg-plugin.php | 8 +- mod/bookmarks/lib/functions.php | 43 ------ .../views/default/forms/bookmarks/save.php | 2 +- .../views/default/resources/bookmarks/add.php | 5 +- .../default/resources/bookmarks/edit.php | 4 +- .../views/default/custom_index/content.php | 8 +- mod/discussions/actions/discussion/save.php | 5 - .../Elgg/Discussions/Forms/PrepareFields.php | 45 ++++++ mod/discussions/elgg-plugin.php | 8 +- mod/discussions/lib/functions.php | 44 ------ .../views/default/forms/discussion/save.php | 4 +- .../default/resources/discussion/add.php | 4 +- .../default/resources/discussion/edit.php | 8 +- mod/file/actions/file/upload.php | 5 - .../classes/Elgg/File/Forms/PrepareFields.php | 44 ++++++ mod/file/elgg-plugin.php | 6 + mod/file/lib/functions.php | 40 ----- mod/file/views/default/forms/file/upload.php | 2 +- .../views/default/resources/file/edit.php | 18 +-- .../views/default/resources/file/upload.php | 2 +- .../actions/friends/collections/edit.php | 4 - .../resources/friends/collections/add.php | 9 +- .../resources/friends/collections/edit.php | 16 +- mod/groups/actions/groups/edit.php | 5 - .../Elgg/Groups/Forms/PrepareFields.php | 80 ++++++++++ mod/groups/elgg-plugin.php | 6 + mod/groups/lib/functions.php | 77 --------- mod/groups/views/default/groups/edit.php | 7 +- mod/invitefriends/actions/friends/invite.php | 4 - .../views/default/forms/friends/invite.php | 4 +- .../default/resources/friends/invite.php | 2 +- mod/messages/actions/messages/send.php | 22 ++- .../Elgg/Messages/Forms/PrepareFields.php | 43 ++++++ mod/messages/elgg-plugin.php | 7 + mod/messages/lib/functions.php | 27 ---- .../Elgg/Messages/SendActionTest.php | 12 +- .../views/default/resources/messages/send.php | 10 +- mod/pages/actions/pages/edit.php | 4 - .../Elgg/Pages/Forms/PrepareFields.php | 45 ++++++ mod/pages/elgg-plugin.php | 6 + mod/pages/lib/pages.php | 51 ------ .../views/default/resources/pages/edit.php | 8 +- .../views/default/resources/pages/new.php | 4 +- .../actions/webservices/api_key/edit.php | 4 - .../classes/Elgg/WebServices/ApiKeyForm.php | 58 ------- .../Elgg/WebServices/Forms/PrepareFields.php | 41 +++++ mod/web_services/elgg-plugin.php | 6 + .../resources/webservices/api_key/add.php | 17 +- .../resources/webservices/api_key/edit.php | 17 +- views/default/admin/users/add.php | 8 +- views/default/elements/forms/footer.php | 22 ++- views/default/forms/register.php | 25 +-- views/default/forms/useradd.php | 40 ++--- views/default/resources/account/register.php | 5 + views/default/resources/index.php | 9 +- 79 files changed, 1071 insertions(+), 725 deletions(-) create mode 100644 engine/classes/Elgg/Forms/PrepareFields.php create mode 100644 engine/tests/phpunit/integration/Elgg/FormsServiceIntegrationTest.php create mode 100644 mod/blog/classes/Elgg/Blog/Forms/PrepareFields.php delete mode 100644 mod/blog/lib/functions.php create mode 100644 mod/bookmarks/classes/Elgg/Bookmarks/Forms/PrepareFields.php delete mode 100644 mod/bookmarks/lib/functions.php create mode 100644 mod/discussions/classes/Elgg/Discussions/Forms/PrepareFields.php delete mode 100644 mod/discussions/lib/functions.php create mode 100644 mod/file/classes/Elgg/File/Forms/PrepareFields.php create mode 100644 mod/groups/classes/Elgg/Groups/Forms/PrepareFields.php create mode 100644 mod/messages/classes/Elgg/Messages/Forms/PrepareFields.php create mode 100644 mod/pages/classes/Elgg/Pages/Forms/PrepareFields.php delete mode 100644 mod/web_services/classes/Elgg/WebServices/ApiKeyForm.php create mode 100644 mod/web_services/classes/Elgg/WebServices/Forms/PrepareFields.php diff --git a/actions/register.php b/actions/register.php index 60c9ca9a309..d909c1f21d2 100644 --- a/actions/register.php +++ b/actions/register.php @@ -8,8 +8,6 @@ /* @var $request \Elgg\Request */ -elgg_make_sticky_form('register', ['password', 'password2']); - // Get variables $username = (string) $request->getParam('username'); $password = (string) $request->getParam('password', null, false); @@ -68,8 +66,6 @@ throw $e; } - elgg_clear_sticky_form('register'); - $response_data = [ 'user' => $new_user, ]; diff --git a/actions/useradd.php b/actions/useradd.php index 2d73582a7d2..3d296fe5273 100644 --- a/actions/useradd.php +++ b/actions/useradd.php @@ -5,8 +5,6 @@ use Elgg\Exceptions\Configuration\RegistrationException; -elgg_make_sticky_form('useradd', ['password', 'password2']); - // Get variables $username = get_input('username'); $password = get_input('password', null, false); @@ -50,8 +48,6 @@ $new_user->makeAdmin(); } - elgg_clear_sticky_form('useradd'); - $new_user->admin_created = true; $new_user->created_by_guid = elgg_get_logged_in_user_guid(); diff --git a/docs/appendix/upgrade-notes/4.x-to-5.0.rst b/docs/appendix/upgrade-notes/4.x-to-5.0.rst index 94754801493..711eb92c937 100644 --- a/docs/appendix/upgrade-notes/4.x-to-5.0.rst +++ b/docs/appendix/upgrade-notes/4.x-to-5.0.rst @@ -369,13 +369,29 @@ Deprecated APIs * ``elgg_trigger_plugin_hook`` use ``elgg_trigger_event_result`` * ``elgg_unregister_plugin_hook_handler`` use ``elgg_unregister_event_handler`` +Removed classes +~~~~~~~~~~~~~~~ + +* ``Elgg\WebServices\ApiKeyForm`` + Removed functions ~~~~~~~~~~~~~~~~~ +* ``blog_prepare_form_vars`` +* ``bookmarks_prepare_form_vars`` +* ``discussion_prepare_form_vars`` * ``elgg_get_breadcrumbs`` * ``elgg_pop_breadcrumb`` * ``elgg_trigger_deprecated_plugin_hook`` -* ``\ElggWidget->saveSettings()`` +* ``file_prepare_form_vars`` +* ``groups_prepare_form_vars`` +* ``messages_prepare_form_vars`` +* ``pages_prepare_form_vars`` + +Removed class functions +~~~~~~~~~~~~~~~~~~~~~~~ + +* ``\ElggWidget::saveSettings()`` Removed events ~~~~~~~~~~~~~~ diff --git a/docs/guides/actions.rst b/docs/guides/actions.rst index a912a6c976f..ca70db72dcf 100644 --- a/docs/guides/actions.rst +++ b/docs/guides/actions.rst @@ -462,6 +462,17 @@ The basic flow of using sticky forms is: 2. Use ``elgg_is_sticky_form($name)`` and ``elgg_get_sticky_values($name)`` to get sticky values when rendering a form view. 3. Call ``elgg_clear_sticky_form($name)`` after the action has completed successfully or after data has been loaded by ``elgg_get_sticky_values($name)``. +.. note:: + + As of Elgg 5.0 forms rendered with ``elgg_view_form()`` can set the ``$form_vars['sticky_enabled'] = true`` flag to automatically + get sticky form support. The submitted values to the action will automatically be filled in the ``$body_vars`` when an error occured in the action. + +``elgg_view_form()`` supports the following ``$form_vars`` to help with sticky form support: + +* ``sticky_enabled``: a ``bool`` to enable automatic sticky form support +* ``sticky_form_name``: an optional ``string`` to set where the sticky form values are saved. This defaults to the ``$action_name`` and should only be changed if the ``$action_name`` is different from the actual action +* ``sticky_ignored_fields: an ``array`` with the names fo the form fields that should be saved. For example password fields + Example: User registration -------------------------- @@ -524,15 +535,14 @@ The form view for the save bookmark action uses ``elgg_extract()`` to pull value $guid = elgg_extract('guid', $vars, null); $shares = elgg_extract('shares', $vars, array()); -The page handler scripts prepares the form variables and calls ``elgg_view_form()`` passing the correct values: +The page handler scripts enables sticky form support by passing the correct values to ``elgg_view_form()``: .. code-block:: php // mod/bookmarks/pages/add.php - $vars = bookmarks_prepare_form_vars(); - $content = elgg_view_form('bookmarks/save', array(), $vars); + $content = elgg_view_form('bookmarks/save', ['sticky_enabled' => true]); -Similarly, ``mod/bookmarks/pages/edit.php`` uses the same function, but passes the entity that is being edited as an argument: +Similarly, ``mod/bookmarks/pages/edit.php`` uses the same sticky support, but passes the entity that is being edited: .. code-block:: php @@ -541,64 +551,59 @@ Similarly, ``mod/bookmarks/pages/edit.php`` uses the same function, but passes t ... - $vars = bookmarks_prepare_form_vars($bookmark); - $content = elgg_view_form('bookmarks/save', array(), $vars); + $content = elgg_view_form('bookmarks/save', ['sticky_enabled' => true], ['entity' => $bookmark]); -The library file defines ``bookmarks_prepare_form_vars()``. This function accepts an ``ElggEntity`` as an argument and does 3 things: +The plugin has an event listener on the ``'form:prepare:fields', 'bookmarks/save'`` event and the handler does 2 things: 1. Defines the input names and default values for form inputs. 2. Extracts the values from a bookmark object if it's passed. - 3. Extracts the values from a sticky form if it exists. - -.. code-block:: php - - // mod/bookmarks/lib/bookmarks.php - function bookmarks_prepare_form_vars($bookmark = null) { - // input names => defaults - $values = array( - 'title' => get_input('title', ''), // bookmarklet support - 'address' => get_input('address', ''), - 'description' => '', - 'access_id' => ACCESS_DEFAULT, - 'tags' => '', - 'shares' => array(), - 'container_guid' => elgg_get_page_owner_guid(), - 'guid' => null, - 'entity' => $bookmark, - ); - - if ($bookmark) { - foreach (array_keys($values) as $field) { - if (isset($bookmark->$field)) { - $values[$field] = $bookmark->$field; - } - } - } - - if (elgg_is_sticky_form('bookmarks')) { - $sticky_values = elgg_get_sticky_values('bookmarks'); - foreach ($sticky_values as $key => $value) { - $values[$key] = $value; - } - } - - elgg_clear_sticky_form('bookmarks'); - - return $values; - } - -The save action checks the input, then clears the sticky form upon success: .. code-block:: php - // mod/bookmarks/actions/bookmarks/save.php - elgg_make_sticky_form('bookmarks'); - - ... - - if ($bookmark->save()) { - elgg_clear_sticky_form('bookmarks'); - } + // mod/bookmarks/classes/Elgg/Bookmarks/Forms/PrepareFields.php + /** + * Prepare the fields for the bookmarks/save form + * + * @since 5.0 + */ + class PrepareFields { + + /** + * Prepare fields + * + * @param \Elgg\Event $event 'form:prepare:fields', 'bookmarks/save' + * + * @return array|null + */ + public function __invoke(\Elgg\Event $event): ?array { + $vars = $event->getValue(); + + // input names => defaults + $values = [ + 'title' => get_input('title', ''), // bookmarklet support + 'address' => get_input('address', ''), + 'description' => '', + 'access_id' => ACCESS_DEFAULT, + 'tags' => '', + 'container_guid' => elgg_get_page_owner_guid(), + 'guid' => null, + ]; + + $bookmark = elgg_extract('entity', $vars); + if ($bookmark instanceof \ElggBookmark) { + // load current bookmark values + foreach (array_keys($values) as $field) { + if (isset($bookmark->$field)) { + $values[$field] = $bookmark->$field; + } + } + } + + return array_merge($vars, $values); + } + } + +The save action doesn't need to do anything with sticky form support as this is all handled by the system. Ajax ==== diff --git a/docs/guides/events-list.rst b/docs/guides/events-list.rst index 19eb4a00da3..4863a041d73 100644 --- a/docs/guides/events-list.rst +++ b/docs/guides/events-list.rst @@ -914,6 +914,10 @@ Views **config, htmlawed** |results| Filter the HTMLawed ``$config`` array. +**form:prepare:fields, ** |results| + Prepare field values for use in the form. Eg. when editing a blog, fill this with the current values of the blog. + Sticky form values will automatically be added to the field values (when available). + **head, page** |results| In ``elgg_view_page()``, filters ``$vars['head']`` Return value contains an array with ``title``, ``metas`` and ``links`` keys, diff --git a/engine/classes/Elgg/Forms/PrepareFields.php b/engine/classes/Elgg/Forms/PrepareFields.php new file mode 100644 index 00000000000..d498bab1c42 --- /dev/null +++ b/engine/classes/Elgg/Forms/PrepareFields.php @@ -0,0 +1,47 @@ +getParam('sticky_enabled')) { + return null; + } + + $form_name = $event->getParam('sticky_form_name'); + if (empty($form_name) || !elgg_is_sticky_form($form_name)) { + return null; + } + + $ignored_fields = (array) $event->getParam('sticky_ignored_fields'); + $body_vars = $event->getValue(); + + // merge the sticky values into the fields + $sticky_vars = elgg_get_sticky_values($form_name); + foreach ($sticky_vars as $key => $value) { + if (in_array($key, $ignored_fields)) { + // this shouldn't happen, but just in case + continue; + } + $body_vars[$key] = $value; + } + + // clear the sticky values + elgg_clear_sticky_form($form_name); + + return $body_vars; + } +} diff --git a/engine/classes/Elgg/Forms/StickyForms.php b/engine/classes/Elgg/Forms/StickyForms.php index c48f4a1e472..34c9f490cf7 100644 --- a/engine/classes/Elgg/Forms/StickyForms.php +++ b/engine/classes/Elgg/Forms/StickyForms.php @@ -41,6 +41,9 @@ public function makeStickyForm(string $form_name, array $ignored_field_names = [ $default_ignored_field_names = [ '__elgg_ts', // never store CSRF tokens '__elgg_token', // never store CSRF tokens + '_elgg_sticky_form_name', // from sticky form support + '_elgg_sticky_ignored_fields', // from sticky form support + '_route', // added by router ]; $ignored_field_names = array_merge($default_ignored_field_names, $ignored_field_names); diff --git a/engine/classes/Elgg/FormsService.php b/engine/classes/Elgg/FormsService.php index b9b247e0c3d..c2cd325b765 100644 --- a/engine/classes/Elgg/FormsService.php +++ b/engine/classes/Elgg/FormsService.php @@ -15,28 +15,35 @@ class FormsService { use Loggable; + /** + * @var EventsService + */ + protected $events; + /** * @var ViewsService */ - private $views; + protected $views; /** * @var bool */ - private $rendering; + protected $rendering; /** * @var string */ - private $footer = ''; + protected $footer = ''; /** * Constructor * - * @param ViewsService $views Views service + * @param ViewsService $views Views service + * @param EventsService $events Events service */ - public function __construct(ViewsService $views) { + public function __construct(ViewsService $views, EventsService $events) { $this->views = $views; + $this->events = $events; } /** @@ -80,12 +87,16 @@ public function render(string $action, array $form_vars = [], array $body_vars = 'action' => elgg_generate_action_url($action, [], false), 'method' => 'post', 'ajax' => false, + 'sticky_enabled' => false, + 'sticky_form_name' => $action, + 'sticky_ignored_fields' => [], ]; // append elgg-form class to any class options set - $form_vars['class'] = (array) elgg_extract('class', $form_vars, []); - $form_vars['class'][] = 'elgg-form-' . preg_replace('/[^a-z0-9]/i', '-', $action); - + $form_vars['class'] = elgg_extract_class($form_vars, [ + 'elgg-form-' . preg_replace('/[^a-z0-9]/i', '-', $action)], + ); + $form_vars = array_merge($defaults, $form_vars); if (!isset($form_vars['enctype']) && strtolower($form_vars['method']) == 'post') { @@ -104,6 +115,9 @@ public function render(string $action, array $form_vars = [], array $body_vars = $form_vars['prevent_double_submit'] = (bool) elgg_extract('prevent_double_submit', $form_vars, true); if (!isset($form_vars['body'])) { + // prepare body vars + $body_vars = (array) $this->events->triggerResults('form:prepare:fields', $action, $form_vars, $body_vars); + $this->rendering = true; $this->footer = ''; diff --git a/engine/classes/Elgg/Router/Middleware/ActionMiddleware.php b/engine/classes/Elgg/Router/Middleware/ActionMiddleware.php index 22b920aabe9..b2f4f101d6e 100644 --- a/engine/classes/Elgg/Router/Middleware/ActionMiddleware.php +++ b/engine/classes/Elgg/Router/Middleware/ActionMiddleware.php @@ -3,25 +3,40 @@ namespace Elgg\Router\Middleware; use Elgg\Exceptions\Http\ValidationException; -use Elgg\Http\ResponseBuilder; +use Elgg\Http\OkResponse; /** * Some logic implemented before action is executed */ class ActionMiddleware { + /** + * @var \Elgg\Request + */ + protected $request; + + /** + * @var string + */ + protected $form_name; + /** * Pre-action logic * * @param \Elgg\Request $request Request * - * @return ResponseBuilder|null + * @return void * @throws ValidationException */ - public function __invoke(\Elgg\Request $request) { + public function __invoke(\Elgg\Request $request): void { + $this->request = $request; + $route = $request->getRoute(); - list($prefix, $action) = explode(':', $route, 2); + list(, $action) = explode(':', $route, 2); + // save sticky form values + $this->prepareStickyForm(); + $result = $request->elgg()->events->triggerResults('action:validate', $action, ['request' => $request], true); if ($result === false) { throw new ValidationException(elgg_echo('ValidationException')); @@ -32,8 +47,45 @@ public function __invoke(\Elgg\Request $request) { if (isset($action_timeout)) { set_time_limit($action_timeout); } - - return null; } - + + /** + * Save the action input in sticky form values + * + * @return void + * @since 5.0 + */ + protected function prepareStickyForm(): void { + $this->form_name = $this->request->getParam('_elgg_sticky_form_name'); + + if (empty($this->form_name)) { + return; + } + + // add user and system ignored fields + $ignored_fields = (string) $this->request->getParam('_elgg_sticky_ignored_fields'); + $ignored_fields = elgg_string_to_array($ignored_fields); + + _elgg_services()->stickyForms->makeStickyForm($this->form_name, $ignored_fields); + + // register sticky value cleanup + $this->request->elgg()->events->registerHandler('response', 'all', [$this, 'cleanupStickyValues']); + } + + /** + * Automatically cleanup sticky form values after a successfull action + * + * @param \Elgg\Event $event 'response', 'action:all' + * + * @return void + * @since 5.0 + */ + public function cleanupStickyValues(\Elgg\Event $event): void { + $response = $event->getValue(); + if (!$response instanceof OkResponse) { + return; + } + + _elgg_services()->stickyForms->clearStickyForm($this->form_name); + } } diff --git a/engine/events.php b/engine/events.php index 4f405458225..33e6ac9e6cf 100644 --- a/engine/events.php +++ b/engine/events.php @@ -149,6 +149,11 @@ \Elgg\Widgets\EntityUrlHandler::class => [], ], ], + 'form:prepare:fields' => [ + 'all' => [ + \Elgg\Forms\PrepareFields::class => ['priority' => 9999], + ], + ], 'head' => [ 'page' => [ \Elgg\Page\AddFaviconLinksHandler::class => [], diff --git a/engine/tests/phpunit/integration/Elgg/Forms/StickyFormsIntegrationTest.php b/engine/tests/phpunit/integration/Elgg/Forms/StickyFormsIntegrationTest.php index 3e299d84344..e15e14adca6 100644 --- a/engine/tests/phpunit/integration/Elgg/Forms/StickyFormsIntegrationTest.php +++ b/engine/tests/phpunit/integration/Elgg/Forms/StickyFormsIntegrationTest.php @@ -41,6 +41,23 @@ protected function createService(Request $request): void { ]); } + public function testMakeStickyFormDefaultIgnoredFields() { + // request also container CSRF tokens, which shouldn't be made sticky + $request = $this->prepareHttpRequest('foo', 'POST', [ + 'name' => 'foo', + '_elgg_sticky_form_name' => 'foo', // added by sticky form support + '_elgg_sticky_ignored_fields' => 'password,password2', // added by sticky form support + '_route' => 'action:foo', // added by router + ], 0, true); + + $this->createService($request); + + $this->service->makeStickyForm('foo'); + $this->assertEquals([ + 'name' => 'foo', + ], $this->service->getStickyValues('foo')); + } + public function testMakeStickyFormWithIgnoredFields() { $request = $this->prepareHttpRequest('foo', 'POST', [ 'name' => 'foo', diff --git a/engine/tests/phpunit/integration/Elgg/FormsServiceIntegrationTest.php b/engine/tests/phpunit/integration/Elgg/FormsServiceIntegrationTest.php new file mode 100644 index 00000000000..31da0b1b35e --- /dev/null +++ b/engine/tests/phpunit/integration/Elgg/FormsServiceIntegrationTest.php @@ -0,0 +1,146 @@ +createApplication([ + 'isolate' => true, + ]); + + $views_dir = $this->normalizeTestFilePath('views'); + _elgg_services()->views->autoregisterViews('', "{$views_dir}/default", 'default'); + } + + public function testStickyFormSupportDisabledWithError() { + elgg_register_action('foo/bar', __CLASS__ . '::errorActionController', 'public'); + + $response = $this->executeAction('foo/bar', [ + 'foo' => 'bar', + ]); + + $this->assertInstanceOf(ErrorResponse::class, $response); + $this->assertFalse(elgg_is_sticky_form('foo/bar')); + + $event = $this->registerTestingEvent('form:prepare:fields', 'foo/bar', function(\Elgg\Event $incoming_event) {}); + + elgg_view_form('foo/bar', [ + 'class' => 'foo-bar', + ], [ + 'baz2' => 'bar2', + ]); + + $event->assertNumberOfCalls(1); + $event->assertValueBefore(['baz2' => 'bar2']); + $event->assertValueAfter(['baz2' => 'bar2']); + } + + public function testStickyFormSupportEnabledWithError() { + elgg_register_action('foo/bar', __CLASS__ . '::errorActionController', 'public'); + + $response = $this->executeAction('foo/bar', [ + 'foo' => 'bar', + 'baz2' => 'bar', + '_elgg_sticky_form_name' => 'foo/bar', // this is added by enabling sticky form support + ]); + + $this->assertInstanceOf(ErrorResponse::class, $response); + $this->assertTrue(elgg_is_sticky_form('foo/bar')); + + $event = $this->registerTestingEvent('form:prepare:fields', 'foo/bar', function(\Elgg\Event $incoming_event) {}); + + elgg_view_form('foo/bar', [ + 'class' => 'foo-bar', + 'sticky_enabled' => true, + ], [ + 'baz2' => 'bar2', + ]); + + $event->assertNumberOfCalls(1); + $event->assertValueBefore(['baz2' => 'bar2']); + $event->assertValueAfter([ + 'baz2' => 'bar', // overruled by action + 'foo' => 'bar', + ]); + + // check that sticky form data is cleared after use + $this->assertFalse(elgg_is_sticky_form('foo/bar')); + } + + public function testStickyFormSupportEnabledWithIgnoredFieldsWithError() { + elgg_register_action('foo/bar', __CLASS__ . '::errorActionController', 'public'); + + $response = $this->executeAction('foo/bar', [ + 'foo' => 'bar', + 'baz2' => 'bar', + 'ignored' => 'foo', + '_elgg_sticky_form_name' => 'foo/bar', // this is added by enabling sticky form support + '_elgg_sticky_ignored_fields' => 'baz2,ignored', // this is added by sticky form support + ]); + + $this->assertInstanceOf(ErrorResponse::class, $response); + $this->assertTrue(elgg_is_sticky_form('foo/bar')); + + $event = $this->registerTestingEvent('form:prepare:fields', 'foo/bar', function(\Elgg\Event $incoming_event) {}); + + elgg_view_form('foo/bar', [ + 'class' => 'foo-bar', + 'sticky_enabled' => true, + ], [ + 'baz2' => 'bar2', + ]); + + $event->assertNumberOfCalls(1); + $event->assertValueBefore(['baz2' => 'bar2']); + $event->assertValueAfter([ + 'baz2' => 'bar2', // ignored in action + 'foo' => 'bar', + ]); + + // check that sticky form data is cleared after use + $this->assertFalse(elgg_is_sticky_form('foo/bar')); + } + + public function testStickyFormSupportEnabledWithSuccess() { + elgg_register_action('foo/bar', __CLASS__ . '::okActionController', 'public'); + + $response = $this->executeAction('foo/bar', [ + 'foo' => 'bar', + 'baz2' => 'bar', + '_elgg_sticky_form_name' => 'foo/bar', // this is added by enabling sticky form support + ]); + + $this->assertInstanceOf(OkResponse::class, $response); + $this->assertTrue(_elgg_services()->events->hasHandler('response', 'all')); + $this->assertTrue(elgg_is_sticky_form('foo/bar')); + + _elgg_services()->events->triggerResults('response', 'action:foo/bar', [], $response); // this is normally done by the ResponseFactory + + $this->assertFalse(elgg_is_sticky_form('foo/bar')); + + $event = $this->registerTestingEvent('form:prepare:fields', 'foo/bar', function(\Elgg\Event $incoming_event) {}); + + elgg_view_form('foo/bar', [ + 'class' => 'foo-bar', + 'sticky_enabled' => true, + ], [ + 'baz2' => 'bar2', + ]); + + $event->assertNumberOfCalls(1); + $event->assertValueBefore(['baz2' => 'bar2']); + $event->assertValueAfter(['baz2' => 'bar2']); + } + + public static function errorActionController(\Elgg\Request $request) { + return elgg_error_response(); + } + + public static function okActionController(\Elgg\Request $request) { + return elgg_ok_response(); + } +} diff --git a/engine/tests/phpunit/unit/Elgg/FormsServiceUnitTest.php b/engine/tests/phpunit/unit/Elgg/FormsServiceUnitTest.php index bac419a0230..f234fd1adfd 100644 --- a/engine/tests/phpunit/unit/Elgg/FormsServiceUnitTest.php +++ b/engine/tests/phpunit/unit/Elgg/FormsServiceUnitTest.php @@ -10,13 +10,31 @@ */ class FormsServiceUnitTest extends \Elgg\UnitTestCase { + /** + * @var TestableEvent + */ + protected $event; + public function up() { $views_dir = $this->normalizeTestFilePath('views'); _elgg_services()->views->autoregisterViews('', "{$views_dir}/default", 'default'); } + + public function down() { + if ($this->event instanceof TestableEvent) { + $this->event->unregister(); + } + } public function testCanRenderForm() { - + $this->event = $this->registerTestingEvent('form:prepare:fields', 'foo/bar', function(\Elgg\Event $incoming_event) { + $vars = $incoming_event->getValue(); + + $vars['foo'] = 'bar'; + + return $vars; + }); + $expected = elgg_view('forms/foo/bar.html'); $actual = elgg_view_form('foo/bar', [ 'class' => 'foo-bar', @@ -24,12 +42,38 @@ public function testCanRenderForm() { 'baz2' => 'bar2', ]); + // check form contents $this->assertNotEmpty($expected); $this->assertNotEmpty($actual); $normalize = function ($html) { return preg_replace('~>\s+~', ">", $html); }; $this->assertEquals($normalize($expected), $normalize($actual)); + + // check for triggered event + $this->event->assertNumberOfCalls(1); + $this->event->assertValueBefore(['baz2' => 'bar2']); + $this->event->assertValueAfter(['baz2' => 'bar2', 'foo' => 'bar']); + } + + public function testCanRenderFormWithStickySupport() { + $actual = elgg_view_form('foo/bar', [ + 'class' => 'foo-bar', + 'sticky_enabled' => true, + 'sticky_ignored_fields' => [ + 'password', + 'some-field', + ], + ], [ + 'baz2' => 'bar2', + ]); + + // check form contents + $this->assertNotEmpty($actual); + $this->assertStringContainsString('name="_elgg_sticky_form_name"', $actual); + $this->assertStringContainsString('value="foo/bar"', $actual); + $this->assertStringContainsString('name="_elgg_sticky_ignored_fields"', $actual); + $this->assertStringContainsString('value="password,some-field"', $actual); } public function testCanNotSetFooterOutsideFormView() { diff --git a/engine/tests/test_files/views/default/elements/forms/footer.php b/engine/tests/test_files/views/default/elements/forms/footer.php index b4bd2537f7e..51e38ddcb34 100644 --- a/engine/tests/test_files/views/default/elements/forms/footer.php +++ b/engine/tests/test_files/views/default/elements/forms/footer.php @@ -1,3 +1,29 @@ 'hidden', + 'name' => '_elgg_sticky_form_name', + 'value' => (string) elgg_extract('sticky_form_name', $form_vars), + ]); + + $ignored_fields = (array) elgg_extract('sticky_ignored_fields', $form_vars); + if (!empty($ignored_fields)) { + $footer .= elgg_format_element('input', [ + 'type' => 'hidden', + 'name' => '_elgg_sticky_ignored_fields', + 'value' => implode(',', $ignored_fields), + ]); + } +} + +if (empty($footer)) { + return; +} + +echo $footer; diff --git a/engine/tests/test_files/views/default/forms/foo/bar.html.php b/engine/tests/test_files/views/default/forms/foo/bar.html.php index fbe58ff2f49..7160d862f8f 100644 --- a/engine/tests/test_files/views/default/forms/foo/bar.html.php +++ b/engine/tests/test_files/views/default/forms/foo/bar.html.php @@ -1,5 +1,6 @@ -
+ - bar2 + bar2 + -
\ No newline at end of file + diff --git a/mod/activity/views/default/resources/index.php b/mod/activity/views/default/resources/index.php index 3178ac18451..9f63342d4f1 100644 --- a/mod/activity/views/default/resources/index.php +++ b/mod/activity/views/default/resources/index.php @@ -11,7 +11,13 @@ } if (elgg_get_config('allow_registration')) { - $sidebar = elgg_view_module('aside', elgg_echo('register'), elgg_view_form('register')); + $sidebar = elgg_view_module('aside', elgg_echo('register'), elgg_view_form('register', [ + 'sticky_enabled' => true, + 'sticky_ignored_fields' => [ + 'password', + 'password2', + ], + ])); } else { $sidebar = elgg_view('core/account/login_box'); } diff --git a/mod/blog/actions/blog/save.php b/mod/blog/actions/blog/save.php index 773ca1149e1..c6e46de189c 100644 --- a/mod/blog/actions/blog/save.php +++ b/mod/blog/actions/blog/save.php @@ -9,9 +9,6 @@ * Drafts are saved with the access set to private. */ -// start a new sticky form session in case of failure -elgg_make_sticky_form('blog'); - // save or preview $save = (bool) get_input('save'); @@ -109,9 +106,6 @@ return elgg_error_response(elgg_echo('blog:error:cannot_save')); } -// remove sticky form entries -elgg_clear_sticky_form('blog'); - // remove autosave draft if exists $blog->deleteAnnotations('blog_auto_save'); diff --git a/mod/blog/classes/Elgg/Blog/Forms/PrepareFields.php b/mod/blog/classes/Elgg/Blog/Forms/PrepareFields.php new file mode 100644 index 00000000000..31c66bd618f --- /dev/null +++ b/mod/blog/classes/Elgg/Blog/Forms/PrepareFields.php @@ -0,0 +1,74 @@ +getValue(); + + // input names => defaults + $values = [ + 'title' => null, + 'description' => null, + 'status' => 'published', + 'access_id' => ACCESS_DEFAULT, + 'comments_on' => 'On', + 'excerpt' => null, + 'tags' => null, + 'container_guid' => null, + 'guid' => null, + 'draft_warning' => '', + ]; + + $blog = elgg_extract('entity', $vars); + if ($blog instanceof \ElggBlog) { + // load current blog values + foreach (array_keys($values) as $field) { + if (isset($blog->$field)) { + $values[$field] = $blog->$field; + } + } + + if ($blog->status == 'draft') { + $values['access_id'] = $blog->future_access; + } + + // load the revision annotation if requested + $revision = elgg_extract('revision', $vars); + if ($revision instanceof \ElggAnnotation && $revision->entity_guid == $blog->guid) { + $values['revision'] = $revision; + $values['description'] = $revision->value; + } + + // display a notice if there's an autosaved annotation + // and we're not editing it. + $auto_save = false; + $auto_save_annotations = $blog->getAnnotations([ + 'annotation_name' => 'blog_auto_save', + 'limit' => 1, + ]); + if (!empty($auto_save_annotations)) { + $auto_save = $auto_save_annotations[0]; + } + + if ($auto_save instanceof \ElggAnnotation && $revision instanceof \ElggAnnotation && $auto_save->id !== $revision->id) { + $values['draft_warning'] = elgg_echo('blog:messages:warning:draft'); + } + } + + return array_merge($vars, $values); + } +} diff --git a/mod/blog/elgg-plugin.php b/mod/blog/elgg-plugin.php index fc9a920d255..ef3ae8d728e 100644 --- a/mod/blog/elgg-plugin.php +++ b/mod/blog/elgg-plugin.php @@ -1,10 +1,9 @@ [ 'name' => 'Blog', @@ -109,6 +108,11 @@ GroupToolContainerLogicCheck::class => [], ], ], + 'form:prepare:fields' => [ + 'blog/save' => [ + PrepareFields::class => [], + ], + ], 'register' => [ 'menu:blog_archive' => [ 'Elgg\Blog\Menus\BlogArchive::register' => [], diff --git a/mod/blog/lib/functions.php b/mod/blog/lib/functions.php deleted file mode 100644 index 4beef01be9c..00000000000 --- a/mod/blog/lib/functions.php +++ /dev/null @@ -1,79 +0,0 @@ - defaults - $values = [ - 'title' => null, - 'description' => null, - 'status' => 'published', - 'access_id' => ACCESS_DEFAULT, - 'comments_on' => 'On', - 'excerpt' => null, - 'tags' => null, - 'container_guid' => null, - 'guid' => null, - 'entity' => $post, - 'draft_warning' => '', - ]; - - if ($post) { - foreach (array_keys($values) as $field) { - if (isset($post->$field)) { - $values[$field] = $post->$field; - } - } - - if ($post->status == 'draft') { - $values['access_id'] = $post->future_access; - } - } - - if (elgg_is_sticky_form('blog')) { - $sticky_values = elgg_get_sticky_values('blog'); - foreach ($sticky_values as $key => $value) { - $values[$key] = $value; - } - } - - elgg_clear_sticky_form('blog'); - - if (!$post) { - return $values; - } - - // load the revision annotation if requested - if (isset($revision) && $revision->entity_guid == $post->guid) { - $values['revision'] = $revision; - $values['description'] = $revision->value; - } - - // display a notice if there's an autosaved annotation - // and we're not editing it. - $auto_save_annotations = $post->getAnnotations([ - 'annotation_name' => 'blog_auto_save', - 'limit' => 1, - ]); - if ($auto_save_annotations) { - $auto_save = $auto_save_annotations[0]; - } else { - $auto_save = false; - } - /* @var ElggAnnotation|false $auto_save */ - - if ($auto_save && $revision && $auto_save->id != $revision->id) { - $values['draft_warning'] = elgg_echo('blog:messages:warning:draft'); - } - - return $values; -} diff --git a/mod/blog/views/default/resources/blog/add.php b/mod/blog/views/default/resources/blog/add.php index 0ce74a9f98d..71fff010253 100644 --- a/mod/blog/views/default/resources/blog/add.php +++ b/mod/blog/views/default/resources/blog/add.php @@ -19,9 +19,10 @@ $form_vars = [ 'prevent_double_submit' => false, // action is using the submit buttons to determine type of submission, disabled buttons are not submitted + 'sticky_enabled' => true, ]; -$content = elgg_view_form('blog/save', $form_vars, blog_prepare_form_vars()); +$content = elgg_view_form('blog/save', $form_vars); echo elgg_view_page(elgg_echo('add:object:blog'), [ 'content' => $content, diff --git a/mod/blog/views/default/resources/blog/edit.php b/mod/blog/views/default/resources/blog/edit.php index d039dfe620a..4a148f7f560 100644 --- a/mod/blog/views/default/resources/blog/edit.php +++ b/mod/blog/views/default/resources/blog/edit.php @@ -5,6 +5,7 @@ $guid = (int) elgg_extract('guid', $vars); elgg_entity_gatekeeper($guid, 'object', 'blog', true); +/* @var $blog \ElggBlog */ $blog = get_entity($guid); $vars['entity'] = $blog; @@ -16,28 +17,28 @@ $title = elgg_echo('edit:object:blog'); -if ($revision_id) { +if (!empty($revision_id)) { $revision = elgg_get_annotation_from_id($revision_id); $vars['revision'] = $revision; $title .= ' ' . elgg_echo('blog:edit_revision_notice'); - if (!$revision || !($revision->entity_guid == $guid)) { + if (!$revision instanceof \ElggAnnotation || $revision->entity_guid !== $guid) { throw new EntityNotFoundException(elgg_echo('blog:error:revision_not_found')); } } -$body_vars = blog_prepare_form_vars($blog, $revision); - $form_vars = [ 'prevent_double_submit' => false, // action is using the submit buttons to determine type of submission, disabled buttons are not submitted + 'sticky_enabled' => true, ]; -$content = elgg_view_form('blog/save', $form_vars, $body_vars); - -$sidebar = elgg_view('blog/sidebar/revisions', $vars); +$body_vars = [ + 'entity' => $blog, + 'revision' => $revision, +]; echo elgg_view_page($title, [ - 'content' => $content, - 'sidebar' => $sidebar, + 'content' => elgg_view_form('blog/save', $form_vars, $body_vars), + 'sidebar' => elgg_view('blog/sidebar/revisions', $vars), 'filter_id' => 'blog/edit', ]); diff --git a/mod/bookmarks/actions/bookmarks/save.php b/mod/bookmarks/actions/bookmarks/save.php index 98bd8a6b8c0..03c768e0458 100644 --- a/mod/bookmarks/actions/bookmarks/save.php +++ b/mod/bookmarks/actions/bookmarks/save.php @@ -11,8 +11,6 @@ $guid = (int) get_input('guid'); $container_guid = (int) get_input('container_guid', elgg_get_logged_in_user_guid()); -elgg_make_sticky_form('bookmarks'); - // don't use elgg_normalize_url() because we don't want // relative links resolved to this site. if ($address && !preg_match("#^((ht|f)tps?:)?//#i", $address)) { @@ -49,8 +47,6 @@ return elgg_error_response(elgg_echo('bookmarks:save:failed')); } -elgg_clear_sticky_form('bookmarks'); - //add to river only if new if ($new) { elgg_create_river_item([ diff --git a/mod/bookmarks/classes/Elgg/Bookmarks/Forms/PrepareFields.php b/mod/bookmarks/classes/Elgg/Bookmarks/Forms/PrepareFields.php new file mode 100644 index 00000000000..318481e5afd --- /dev/null +++ b/mod/bookmarks/classes/Elgg/Bookmarks/Forms/PrepareFields.php @@ -0,0 +1,45 @@ +getValue(); + + // input names => defaults + $values = [ + 'title' => (string) get_input('title'), // bookmarklet support + 'address' => (string) get_input('address'), + 'description' => '', + 'access_id' => ACCESS_DEFAULT, + 'tags' => '', + 'container_guid' => elgg_get_page_owner_guid(), + 'guid' => null, + ]; + + $bookmark = elgg_extract('entity', $vars); + if ($bookmark instanceof \ElggBookmark) { + // load current bookmark values + foreach (array_keys($values) as $field) { + if (isset($bookmark->$field)) { + $values[$field] = $bookmark->$field; + } + } + } + + return array_merge($vars, $values); + } +} diff --git a/mod/bookmarks/elgg-plugin.php b/mod/bookmarks/elgg-plugin.php index 4ac62e8440a..ec1878b3066 100644 --- a/mod/bookmarks/elgg-plugin.php +++ b/mod/bookmarks/elgg-plugin.php @@ -1,10 +1,9 @@ [ 'name' => 'Bookmarks', @@ -92,6 +91,11 @@ 'Elgg\Bookmarks\Widgets::widgetURL' => [], ], ], + 'form:prepare:fields' => [ + 'bookmarks/save' => [ + PrepareFields::class => [], + ], + ], 'register' => [ 'menu:footer' => [ 'Elgg\Bookmarks\Menus\Footer::register' => [], diff --git a/mod/bookmarks/lib/functions.php b/mod/bookmarks/lib/functions.php deleted file mode 100644 index de5cd762291..00000000000 --- a/mod/bookmarks/lib/functions.php +++ /dev/null @@ -1,43 +0,0 @@ - defaults - $values = [ - 'title' => get_input('title', ''), // bookmarklet support - 'address' => get_input('address', ''), - 'description' => '', - 'access_id' => ACCESS_DEFAULT, - 'tags' => '', - 'container_guid' => elgg_get_page_owner_guid(), - 'guid' => null, - 'entity' => $bookmark, - ]; - - if ($bookmark) { - foreach (array_keys($values) as $field) { - if (isset($bookmark->$field)) { - $values[$field] = $bookmark->$field; - } - } - } - - if (elgg_is_sticky_form('bookmarks')) { - $sticky_values = elgg_get_sticky_values('bookmarks'); - foreach ($sticky_values as $key => $value) { - $values[$key] = $value; - } - } - - elgg_clear_sticky_form('bookmarks'); - - return $values; -} diff --git a/mod/bookmarks/views/default/forms/bookmarks/save.php b/mod/bookmarks/views/default/forms/bookmarks/save.php index e2f9fc4fbc4..40abde73ee3 100644 --- a/mod/bookmarks/views/default/forms/bookmarks/save.php +++ b/mod/bookmarks/views/default/forms/bookmarks/save.php @@ -41,7 +41,7 @@ '#type' => 'access', 'name' => 'access_id', 'value' => elgg_extract('access_id', $vars, ACCESS_DEFAULT), - 'entity' => get_entity((int) elgg_extract('guid', $vars)), + 'entity' => elgg_extract('entity', $vars), 'entity_type' => 'object', 'entity_subtype' => 'bookmarks', ], diff --git a/mod/bookmarks/views/default/resources/bookmarks/add.php b/mod/bookmarks/views/default/resources/bookmarks/add.php index b52c457fb8f..bad1acea127 100644 --- a/mod/bookmarks/views/default/resources/bookmarks/add.php +++ b/mod/bookmarks/views/default/resources/bookmarks/add.php @@ -16,10 +16,7 @@ elgg_push_collection_breadcrumbs('object', 'bookmarks', $page_owner); -$vars = bookmarks_prepare_form_vars(); - - echo elgg_view_page(elgg_echo('add:object:bookmarks'), [ 'filter_id' => 'bookmarks/edit', - 'content' => elgg_view_form('bookmarks/save', [], $vars), + 'content' => elgg_view_form('bookmarks/save', ['sticky_enabled' => true]), ]); diff --git a/mod/bookmarks/views/default/resources/bookmarks/edit.php b/mod/bookmarks/views/default/resources/bookmarks/edit.php index 4b1f02d985b..8e524911cb8 100644 --- a/mod/bookmarks/views/default/resources/bookmarks/edit.php +++ b/mod/bookmarks/views/default/resources/bookmarks/edit.php @@ -10,9 +10,7 @@ elgg_push_entity_breadcrumbs($bookmark); -$vars = bookmarks_prepare_form_vars($bookmark); - echo elgg_view_page(elgg_echo('edit:object:bookmarks'), [ 'filter_id' => 'bookmarks/edit', - 'content' => elgg_view_form('bookmarks/save', [], $vars), + 'content' => elgg_view_form('bookmarks/save', ['sticky_enabled' => true], ['entity' => $bookmark]), ]); diff --git a/mod/custom_index/views/default/custom_index/content.php b/mod/custom_index/views/default/custom_index/content.php index 959fcee7e9a..67c9dc24014 100644 --- a/mod/custom_index/views/default/custom_index/content.php +++ b/mod/custom_index/views/default/custom_index/content.php @@ -30,7 +30,13 @@ } if (!elgg_is_logged_in() && $is_module_enabled('register') && elgg_get_config('allow_registration')) { - $modules[] = elgg_view_module('featured', elgg_echo('register'), elgg_view_form('register')); + $modules[] = elgg_view_module('featured', elgg_echo('register'), elgg_view_form('register', [ + 'sticky_enabled' => true, + 'sticky_ignored_fields' => [ + 'password', + 'password2', + ], + ])); } if (!elgg_is_logged_in() && $is_module_enabled('login')) { diff --git a/mod/discussions/actions/discussion/save.php b/mod/discussions/actions/discussion/save.php index 8f540f1a340..0624747d1c9 100644 --- a/mod/discussions/actions/discussion/save.php +++ b/mod/discussions/actions/discussion/save.php @@ -11,8 +11,6 @@ $guid = (int) get_input('topic_guid'); $tags = (string) get_input('tags'); -elgg_make_sticky_form('topic'); - // validation of inputs if (!$title || !$desc) { return elgg_error_response(elgg_echo('discussion:error:missing')); @@ -59,9 +57,6 @@ return elgg_error_response(elgg_echo('discussion:error:notsaved')); } -// topic saved so clear sticky form -elgg_clear_sticky_form('topic'); - // handle results differently for new topics and topic edits if (!$new_topic) { return elgg_ok_response('', elgg_echo('discussion:topic:updated'), $topic->getURL()); diff --git a/mod/discussions/classes/Elgg/Discussions/Forms/PrepareFields.php b/mod/discussions/classes/Elgg/Discussions/Forms/PrepareFields.php new file mode 100644 index 00000000000..ae377aa5fdf --- /dev/null +++ b/mod/discussions/classes/Elgg/Discussions/Forms/PrepareFields.php @@ -0,0 +1,45 @@ +getValue(); + + // input names => defaults + $values = [ + 'title' => '', + 'description' => '', + 'status' => '', + 'access_id' => ACCESS_DEFAULT, + 'tags' => '', + 'container_guid' => elgg_get_page_owner_guid(), + 'guid' => null, + ]; + + $discussion = elgg_extract('entity', $vars); + if ($discussion instanceof \ElggDiscussion) { + // load current discussion values + foreach (array_keys($values) as $field) { + if (isset($discussion->$field)) { + $values[$field] = $discussion->$field; + } + } + } + + return array_merge($vars, $values); + } +} diff --git a/mod/discussions/elgg-plugin.php b/mod/discussions/elgg-plugin.php index 7e49dfe5b0b..ebbd682b1d1 100644 --- a/mod/discussions/elgg-plugin.php +++ b/mod/discussions/elgg-plugin.php @@ -1,10 +1,9 @@ [ 'name' => 'Discussions', @@ -88,6 +87,11 @@ 'Elgg\Discussions\Widgets::widgetURL' => [], ], ], + 'form:prepare:fields' => [ + 'discussion/save' => [ + PrepareFields::class => [], + ], + ], 'get' => [ 'subscriptions' => [ 'Elgg\Discussions\Notifications::addGroupSubscribersToCommentOnDiscussionSubscriptions' => [], diff --git a/mod/discussions/lib/functions.php b/mod/discussions/lib/functions.php deleted file mode 100644 index 914f3abafee..00000000000 --- a/mod/discussions/lib/functions.php +++ /dev/null @@ -1,44 +0,0 @@ - defaults - $values = [ - 'title' => '', - 'description' => '', - 'status' => '', - 'access_id' => ACCESS_DEFAULT, - 'tags' => '', - 'container_guid' => elgg_get_page_owner_guid(), - 'guid' => null, - 'topic' => $topic, - 'entity' => $topic, - ]; - - if ($topic) { - foreach (array_keys($values) as $field) { - if (isset($topic->$field)) { - $values[$field] = $topic->$field; - } - } - } - - if (elgg_is_sticky_form('topic')) { - $sticky_values = elgg_get_sticky_values('topic'); - foreach ($sticky_values as $key => $value) { - $values[$key] = $value; - } - } - - elgg_clear_sticky_form('topic'); - - return $values; -} diff --git a/mod/discussions/views/default/forms/discussion/save.php b/mod/discussions/views/default/forms/discussion/save.php index 1ccda03dabe..ba026ed9c95 100644 --- a/mod/discussions/views/default/forms/discussion/save.php +++ b/mod/discussions/views/default/forms/discussion/save.php @@ -1,9 +1,9 @@ 'discussion-access', 'name' => 'access_id', 'value' => $access_id, - 'entity' => get_entity($guid), + 'entity' => elgg_extract('entity', $vars), 'entity_type' => 'object', 'entity_subtype' => 'discussion', ]); diff --git a/mod/discussions/views/default/resources/discussion/add.php b/mod/discussions/views/default/resources/discussion/add.php index 1dd703de3e0..03eaa88ff0d 100644 --- a/mod/discussions/views/default/resources/discussion/add.php +++ b/mod/discussions/views/default/resources/discussion/add.php @@ -15,9 +15,7 @@ elgg_push_collection_breadcrumbs('object', 'discussion', $container); -$body_vars = discussion_prepare_form_vars(); - echo elgg_view_page(elgg_echo('add:object:discussion'), [ - 'content' => elgg_view_form('discussion/save', [], $body_vars), + 'content' => elgg_view_form('discussion/save', ['sticky_enabled' => true]), 'filter_id' => 'discussion/edit', ]); diff --git a/mod/discussions/views/default/resources/discussion/edit.php b/mod/discussions/views/default/resources/discussion/edit.php index 2e621d2d663..6427a66e59b 100644 --- a/mod/discussions/views/default/resources/discussion/edit.php +++ b/mod/discussions/views/default/resources/discussion/edit.php @@ -4,13 +4,11 @@ elgg_entity_gatekeeper($guid, 'object', 'discussion', true); -$topic = get_entity($guid); +$discussion = get_entity($guid); -elgg_push_entity_breadcrumbs($topic); - -$body_vars = discussion_prepare_form_vars($topic); +elgg_push_entity_breadcrumbs($discussion); echo elgg_view_page(elgg_echo('edit:object:discussion'), [ - 'content' => elgg_view_form('discussion/save', [], $body_vars), + 'content' => elgg_view_form('discussion/save', ['sticky_enabled' => true], ['entity' => $discussion]), 'filter_id' => 'discussion/edit', ]); diff --git a/mod/file/actions/file/upload.php b/mod/file/actions/file/upload.php index 6846ed19ee4..600a5ae299a 100644 --- a/mod/file/actions/file/upload.php +++ b/mod/file/actions/file/upload.php @@ -13,8 +13,6 @@ $container_guid = $container_guid ?: elgg_get_logged_in_user_guid(); -elgg_make_sticky_form('file'); - // check if upload attempted and failed $uploaded_file = elgg_get_uploaded_file('upload', false); if ($uploaded_file && !$uploaded_file->isValid()) { @@ -72,9 +70,6 @@ } } -// file saved so clear sticky form -elgg_clear_sticky_form('file'); - $forward = $file->getURL(); // handle results differently for new files and file updates diff --git a/mod/file/classes/Elgg/File/Forms/PrepareFields.php b/mod/file/classes/Elgg/File/Forms/PrepareFields.php new file mode 100644 index 00000000000..85889381c43 --- /dev/null +++ b/mod/file/classes/Elgg/File/Forms/PrepareFields.php @@ -0,0 +1,44 @@ +getValue(); + + // input names => defaults + $values = [ + 'title' => '', + 'description' => '', + 'access_id' => ACCESS_DEFAULT, + 'tags' => '', + 'container_guid' => elgg_get_page_owner_guid(), + 'guid' => null, + ]; + + $file = elgg_extract('entity', $vars); + if ($file instanceof \ElggFile) { + // load current file values + foreach (array_keys($values) as $field) { + if (isset($file->$field)) { + $values[$field] = $file->$field; + } + } + } + + return array_merge($vars, $values); + } +} diff --git a/mod/file/elgg-plugin.php b/mod/file/elgg-plugin.php index 6527a793961..0303a38109f 100644 --- a/mod/file/elgg-plugin.php +++ b/mod/file/elgg-plugin.php @@ -1,5 +1,6 @@ [], ], ], + 'form:prepare:fields' => [ + 'file/upload' => [ + PrepareFields::class => [], + ], + ], 'register' => [ 'menu:owner_block' => [ 'Elgg\File\Menus\OwnerBlock::registerUserItem' => [], diff --git a/mod/file/lib/functions.php b/mod/file/lib/functions.php index 99d6f29978b..5228ffa4098 100644 --- a/mod/file/lib/functions.php +++ b/mod/file/lib/functions.php @@ -28,43 +28,3 @@ function file_register_toggle(): void { 'priority' => 1000, ]); } - -/** - * Prepare the upload/edit form variables - * - * @param \ElggFile $file the file to edit - * - * @return array - */ -function file_prepare_form_vars(\ElggFile $file = null): array { - - // input names => defaults - $values = [ - 'title' => '', - 'description' => '', - 'access_id' => ACCESS_DEFAULT, - 'tags' => '', - 'container_guid' => elgg_get_page_owner_guid(), - 'guid' => null, - 'entity' => $file, - ]; - - if ($file) { - foreach (array_keys($values) as $field) { - if (isset($file->$field)) { - $values[$field] = $file->$field; - } - } - } - - if (elgg_is_sticky_form('file')) { - $sticky_values = elgg_get_sticky_values('file'); - foreach ($sticky_values as $key => $value) { - $values[$key] = $value; - } - } - - elgg_clear_sticky_form('file'); - - return $values; -} diff --git a/mod/file/views/default/forms/file/upload.php b/mod/file/views/default/forms/file/upload.php index d05eb62853b..6929593389b 100644 --- a/mod/file/views/default/forms/file/upload.php +++ b/mod/file/views/default/forms/file/upload.php @@ -58,7 +58,7 @@ '#label' => elgg_echo('access'), 'name' => 'access_id', 'value' => $access_id, - 'entity' => get_entity($guid), + 'entity' => elgg_extract('entity', $vars), 'entity_type' => 'object', 'entity_subtype' => 'file', ], diff --git a/mod/file/views/default/resources/file/edit.php b/mod/file/views/default/resources/file/edit.php index 540519fdb6a..03f458008f4 100644 --- a/mod/file/views/default/resources/file/edit.php +++ b/mod/file/views/default/resources/file/edit.php @@ -3,28 +3,14 @@ * Edit a file */ -use Elgg\Exceptions\Http\EntityNotFoundException; -use Elgg\Exceptions\Http\EntityPermissionsException; - $file_guid = (int) elgg_extract('guid', $vars); +elgg_entity_gatekeeper($file_guid, 'object', 'file', true); $file = get_entity($file_guid); -if (!$file instanceof ElggFile) { - throw new EntityNotFoundException(); -} - -if (!$file->canEdit()) { - throw new EntityPermissionsException(); -} - elgg_push_entity_breadcrumbs($file); -$body_vars = file_prepare_form_vars($file); - -$content = elgg_view_form('file/upload', [], $body_vars); - echo elgg_view_page(elgg_echo('edit:object:file'), [ - 'content' => $content, + 'content' => elgg_view_form('file/upload', ['sticky_enabled' => true], ['entity' => $file]), 'filter_id' => 'file/edit', ]); diff --git a/mod/file/views/default/resources/file/upload.php b/mod/file/views/default/resources/file/upload.php index 9e2b5406c2d..1bfe56d5ce6 100644 --- a/mod/file/views/default/resources/file/upload.php +++ b/mod/file/views/default/resources/file/upload.php @@ -17,6 +17,6 @@ elgg_push_collection_breadcrumbs('object', 'file', $entity); echo elgg_view_page(elgg_echo('add:object:file'), [ - 'content' => elgg_view_form('file/upload', [], file_prepare_form_vars()), + 'content' => elgg_view_form('file/upload', ['sticky_enabled' => true]), 'filter_id' => 'file/edit', ]); diff --git a/mod/friends_collections/actions/friends/collections/edit.php b/mod/friends_collections/actions/friends/collections/edit.php index 1a2847d0c86..9349195234d 100644 --- a/mod/friends_collections/actions/friends/collections/edit.php +++ b/mod/friends_collections/actions/friends/collections/edit.php @@ -3,8 +3,6 @@ * Friends collection edit action */ -elgg_make_sticky_form('friends/collections/edit'); - $collection_name = elgg_get_title_input('collection_name'); $friend_guids = (array) get_input('collection_friends', []); $collection_id = (int) get_input('collection_id'); @@ -39,8 +37,6 @@ return elgg_error_response(elgg_echo('friends:collections:edit:fail')); } -elgg_clear_sticky_form('friends/collections/edit'); - $data = [ 'collection' => $collection, 'count' => $count, diff --git a/mod/friends_collections/views/default/resources/friends/collections/add.php b/mod/friends_collections/views/default/resources/friends/collections/add.php index 65a9748a3cd..86290cb70ad 100644 --- a/mod/friends_collections/views/default/resources/friends/collections/add.php +++ b/mod/friends_collections/views/default/resources/friends/collections/add.php @@ -22,15 +22,8 @@ elgg_push_breadcrumb(elgg_echo('friends'), elgg_generate_url('collection:friends:owner', ['username' => $user->username])); elgg_push_breadcrumb(elgg_echo('friends:collections'), elgg_generate_url('collection:access_collection:friends:owner', ['username' => $user->username])); -$form_name = 'friends/collections/edit'; -$form_vars = []; -if (elgg_is_sticky_form($form_name)) { - $form_vars = elgg_get_sticky_values($form_name); - elgg_clear_sticky_form($form_name); -} - echo elgg_view_page(elgg_echo('friends:collections:add'), [ - 'content' => elgg_view_form($form_name, [], $form_vars), + 'content' => elgg_view_form('friends/collections/edit', ['sticky_enabled' => true]), 'show_owner_block_menu' => false, 'filter_id' => 'friends_collections/edit', ]); diff --git a/mod/friends_collections/views/default/resources/friends/collections/edit.php b/mod/friends_collections/views/default/resources/friends/collections/edit.php index 096253b2fd8..93b35147bb9 100644 --- a/mod/friends_collections/views/default/resources/friends/collections/edit.php +++ b/mod/friends_collections/views/default/resources/friends/collections/edit.php @@ -25,19 +25,11 @@ elgg_push_breadcrumb(elgg_echo('friends:collections'), elgg_generate_url('collection:access_collection:friends:owner', ['username' => $user->username])); elgg_push_breadcrumb($collection->name, $collection->getURL()); -$form_name = 'friends/collections/edit'; -$form_vars = [ - 'collection_id' => $collection->id, - 'collection_name' => $collection->name, -]; - -if (elgg_is_sticky_form($form_name)) { - $form_vars = elgg_get_sticky_values($form_name); - elgg_clear_sticky_form($form_name); -} - echo elgg_view_page(elgg_echo('friends:collections:edit'), [ - 'content' => elgg_view_form($form_name, [], $form_vars), + 'content' => elgg_view_form('friends/collections/edit', ['sticky_enabled' => true], [ + 'collection_id' => $collection->id, + 'collection_name' => $collection->name, + ]), 'show_owner_block_menu' => false, 'filter_id' => 'friends_collections/edit', ]); diff --git a/mod/groups/actions/groups/edit.php b/mod/groups/actions/groups/edit.php index 2df77c2a311..66deeed365a 100644 --- a/mod/groups/actions/groups/edit.php +++ b/mod/groups/actions/groups/edit.php @@ -6,8 +6,6 @@ * elements may be omitted and the corresponding data will be left as is. */ -elgg_make_sticky_form('groups'); - // Get group fields $input = []; @@ -211,9 +209,6 @@ return elgg_error_response(elgg_echo('groups:save_error')); } -// group saved so clear sticky form -elgg_clear_sticky_form('groups'); - // group creator needs to be member of new group and river entry created if ($is_new_group) { // @todo this should not be necessary... diff --git a/mod/groups/classes/Elgg/Groups/Forms/PrepareFields.php b/mod/groups/classes/Elgg/Groups/Forms/PrepareFields.php new file mode 100644 index 00000000000..00db5a812d5 --- /dev/null +++ b/mod/groups/classes/Elgg/Groups/Forms/PrepareFields.php @@ -0,0 +1,80 @@ +getValue(); + + // input names => defaults + $values = [ + 'name' => '', + 'membership' => ACCESS_PUBLIC, + 'vis' => ACCESS_PUBLIC, + 'guid' => null, + 'owner_guid' => elgg_get_logged_in_user_guid(), + 'content_access_mode' => \ElggGroup::CONTENT_ACCESS_MODE_UNRESTRICTED, + 'content_default_access' => '', + ]; + + // handle customizable profile fields + $fields = elgg()->fields->get('group', 'group'); + foreach ($fields as $field) { + $values[$field['name']] = ''; + } + + $group = elgg_extract('entity', $vars); + if ($group instanceof \ElggGroup) { + // load current file values + foreach (array_keys($values) as $field) { + if (isset($group->$field)) { + $values[$field] = $group->$field; + } + } + + if ($group->access_id != ACCESS_PUBLIC && $group->access_id != ACCESS_LOGGED_IN) { + // group only access - this is done to handle access not created when group is created + $values['vis'] = ACCESS_PRIVATE; + } else { + $values['vis'] = $group->access_id; + } + + // The content_access_mode was introduced in 1.9. This method must be + // used for backwards compatibility with groups created before 1.9. + $values['content_access_mode'] = $group->getContentAccessMode(); + } + + // handle tool options + if ($group instanceof \ElggGroup) { + $tools = elgg()->group_tools->group($group); + } else { + $tools = elgg()->group_tools->all(); + } + + foreach ($tools as $tool) { + if ($group instanceof \ElggGroup) { + $enabled = $group->isToolEnabled($tool->name); + } else { + $enabled = $tool->isEnabledByDefault(); + } + + $prop_name = $tool->mapMetadataName(); + $values[$prop_name] = $enabled ? 'yes' : 'no'; + } + + return array_merge($vars, $values); + } +} diff --git a/mod/groups/elgg-plugin.php b/mod/groups/elgg-plugin.php index 340f54920c6..e8e2e81c13c 100644 --- a/mod/groups/elgg-plugin.php +++ b/mod/groups/elgg-plugin.php @@ -1,5 +1,6 @@ [], ], ], + 'form:prepare:fields' => [ + 'groups/edit' => [ + PrepareFields::class => [], + ], + ], 'gatekeeper' => [ 'group:group' => [ 'Elgg\Groups\Access::allowProfilePage' => [], diff --git a/mod/groups/lib/functions.php b/mod/groups/lib/functions.php index 03afdbf2bdc..9ce4f8f7386 100644 --- a/mod/groups/lib/functions.php +++ b/mod/groups/lib/functions.php @@ -113,80 +113,3 @@ function groups_get_invited_groups(int $user_guid, bool $return_guids = false, a return $groups; } - -/** - * Prepares variables for the group edit form view. - * - * @param mixed $group ElggGroup or null. If a group, uses values from the group. - * @return array - */ -function groups_prepare_form_vars($group = null) { - $values = [ - 'name' => '', - 'membership' => ACCESS_PUBLIC, - 'vis' => ACCESS_PUBLIC, - 'guid' => null, - 'entity' => null, - 'owner_guid' => elgg_get_logged_in_user_guid(), - 'content_access_mode' => ElggGroup::CONTENT_ACCESS_MODE_UNRESTRICTED, - 'content_default_access' => '', - ]; - - // handle customizable profile fields - $fields = elgg()->fields->get('group', 'group'); - foreach ($fields as $field) { - $values[$field['name']] = ''; - } - - // get current group settings - if ($group) { - foreach (array_keys($values) as $field) { - if (isset($group->$field)) { - $values[$field] = $group->$field; - } - } - - if ($group->access_id != ACCESS_PUBLIC && $group->access_id != ACCESS_LOGGED_IN) { - // group only access - this is done to handle access not created when group is created - $values['vis'] = ACCESS_PRIVATE; - } else { - $values['vis'] = $group->access_id; - } - - // The content_access_mode was introduced in 1.9. This method must be - // used for backwards compatibility with groups created before 1.9. - $values['content_access_mode'] = $group->getContentAccessMode(); - - $values['entity'] = $group; - } - - // handle tool options - if ($group instanceof ElggGroup) { - $tools = elgg()->group_tools->group($group); - } else { - $tools = elgg()->group_tools->all(); - } - - foreach ($tools as $tool) { - if ($group instanceof ElggGroup) { - $enabled = $group->isToolEnabled($tool->name); - } else { - $enabled = $tool->isEnabledByDefault(); - } - - $prop_name = $tool->mapMetadataName(); - $values[$prop_name] = $enabled ? 'yes' : 'no'; - } - - // get any sticky form settings - if (elgg_is_sticky_form('groups')) { - $sticky_values = elgg_get_sticky_values('groups'); - foreach ($sticky_values as $key => $value) { - $values[$key] = $value; - } - } - - elgg_clear_sticky_form('groups'); - - return $values; -} diff --git a/mod/groups/views/default/groups/edit.php b/mod/groups/views/default/groups/edit.php index 2b5ca34d395..113e5fa1232 100644 --- a/mod/groups/views/default/groups/edit.php +++ b/mod/groups/views/default/groups/edit.php @@ -5,11 +5,12 @@ * @uses $vars['entity'] ElggGroup object */ -$entity = elgg_extract('entity', $vars, null); +$entity = elgg_extract('entity', $vars); $form_vars = [ 'class' => 'elgg-form-alt', - 'prevent_double_submit' => ($entity instanceof ElggGroup), // don't prevent double submit when creating a group. This is to help with navigation + 'prevent_double_submit' => ($entity instanceof \ElggGroup), // don't prevent double submit when creating a group. This is to help with navigation + 'sticky_enabled' => true, ]; -echo elgg_view_form('groups/edit', $form_vars, groups_prepare_form_vars($entity)); +echo elgg_view_form('groups/edit', $form_vars, ['entity' => $entity]); diff --git a/mod/invitefriends/actions/friends/invite.php b/mod/invitefriends/actions/friends/invite.php index 6cc05acaff8..c8ecb9375eb 100644 --- a/mod/invitefriends/actions/friends/invite.php +++ b/mod/invitefriends/actions/friends/invite.php @@ -5,8 +5,6 @@ use Elgg\Email; -elgg_make_sticky_form('invitefriends'); - $site = elgg_get_site_entity(); // create the from address $from = \Elgg\Email\Address::getFormattedEmailAddress($site->getEmailAddress(), $site->getDisplayName()); @@ -83,6 +81,4 @@ return elgg_error_response(); } -elgg_clear_sticky_form('invitefriends'); - return elgg_ok_response('', elgg_echo('invitefriends:success')); diff --git a/mod/invitefriends/views/default/forms/friends/invite.php b/mod/invitefriends/views/default/forms/friends/invite.php index 5c99c4203c6..e2aca4b6496 100644 --- a/mod/invitefriends/views/default/forms/friends/invite.php +++ b/mod/invitefriends/views/default/forms/friends/invite.php @@ -15,7 +15,7 @@ '#label' => elgg_echo('invitefriends:emails'), 'id' => 'invitefriends-emails', 'name' => 'emails', - 'value' => elgg_get_sticky_value('invitefriends', 'emails'), + 'value' => elgg_extract('emails', $vars), 'required' => true, 'rows' => 4, ]); @@ -25,7 +25,7 @@ '#label' => elgg_echo('invitefriends:message'), 'id' => 'invitefriends-emailmessage', 'name' => 'emailmessage', - 'value' => elgg_get_sticky_value('invitefriends', 'emailmessage', $default_message), + 'value' => elgg_extract('emailmessage', $vars, $default_message), ]); $footer = elgg_view_field([ diff --git a/mod/invitefriends/views/default/resources/friends/invite.php b/mod/invitefriends/views/default/resources/friends/invite.php index e07da53a2fa..ade5a53a511 100644 --- a/mod/invitefriends/views/default/resources/friends/invite.php +++ b/mod/invitefriends/views/default/resources/friends/invite.php @@ -4,7 +4,7 @@ */ echo elgg_view_page(elgg_echo('friends:invite'), [ - 'content' => elgg_view_form('friends/invite'), + 'content' => elgg_view_form('friends/invite', ['sticky_enabled' => true]), 'show_owner_block_menu' => false, 'filter_id' => 'friends', 'filter_value' => 'invite', diff --git a/mod/messages/actions/messages/send.php b/mod/messages/actions/messages/send.php index b1b2f5040e5..950269d9b86 100644 --- a/mod/messages/actions/messages/send.php +++ b/mod/messages/actions/messages/send.php @@ -3,34 +3,32 @@ * Ssend a message action */ -$subject = strip_tags(get_input('subject', '')); +$subject = elgg_strip_tags((string) get_input('subject')); $body = get_input('body'); $recipients = (array) get_input('recipients'); $original_msg_guid = (int) get_input('original_guid'); -elgg_make_sticky_form('messages'); - if (empty($recipients)) { - return elgg_error_response(elgg_echo('messages:user:blank'), 'messages/add'); + return elgg_error_response(elgg_echo('messages:user:blank')); } $recipient = (int) elgg_extract(0, $recipients); if ($recipient == elgg_get_logged_in_user_guid()) { - return elgg_error_response(elgg_echo('messages:user:self'), 'messages/add'); + return elgg_error_response(elgg_echo('messages:user:self')); } $user = get_user($recipient); if (!$user) { - return elgg_error_response(elgg_echo('messages:user:nonexist'), 'messages/add'); + return elgg_error_response(elgg_echo('messages:user:nonexist')); } if ((bool) elgg_get_plugin_setting('friends_only', 'messages') && !$user->isFriendOf(elgg_get_logged_in_user_guid())) { - return elgg_error_response(elgg_echo('messages:user:notfriend'), 'messages/add'); + return elgg_error_response(elgg_echo('messages:user:notfriend')); } // Make sure the message field, send to field and title are not blank if (!$body || !$subject) { - return elgg_error_response(elgg_echo('messages:blank'), 'messages/add'); + return elgg_error_response(elgg_echo('messages:blank')); } // Otherwise, 'send' the message @@ -38,12 +36,12 @@ // Save 'send' the message if ($result === false) { - return elgg_error_response(elgg_echo('messages:error'), 'messages/add'); + return elgg_error_response(elgg_echo('messages:error')); } -elgg_clear_sticky_form('messages'); - -$forward = 'messages/inbox/' . elgg_get_logged_in_user_entity()->username; +$forward = elgg_generate_url('collection:object:messages:owner', [ + 'username' => elgg_get_logged_in_user_entity()->username, +]); return elgg_ok_response([ 'sent_guid' => $result, ], elgg_echo('messages:posted'), $forward); diff --git a/mod/messages/classes/Elgg/Messages/Forms/PrepareFields.php b/mod/messages/classes/Elgg/Messages/Forms/PrepareFields.php new file mode 100644 index 00000000000..17edf637907 --- /dev/null +++ b/mod/messages/classes/Elgg/Messages/Forms/PrepareFields.php @@ -0,0 +1,43 @@ +getValue(); + + // input names => defaults + $values = [ + 'subject' => '', + 'body' => '', + 'recipients' => [], + ]; + + $vars = array_merge($vars, $values); + + // make sure the recipients are users + if (!is_array($vars['recipients'])) { + $vars['recipients'] = (array) $vars['recipients']; + } + + $vars['recipients'] = array_filter($vars['recipients'], function ($guid) { + $user = get_user((int) $guid); + return $user instanceof \ElggUser; + }); + + return $vars; + } +} diff --git a/mod/messages/elgg-plugin.php b/mod/messages/elgg-plugin.php index 9362be4bd44..519c1a108d7 100644 --- a/mod/messages/elgg-plugin.php +++ b/mod/messages/elgg-plugin.php @@ -1,5 +1,7 @@ [], ], ], + 'form:prepare:fields' => [ + 'messages/send' => [ + PrepareFields::class => [], + ], + ], 'register' => [ 'menu:page' => [ 'Elgg\Messages\Menus\Page::register' => [], diff --git a/mod/messages/lib/functions.php b/mod/messages/lib/functions.php index 14a13bc77b8..02e8a20d89b 100644 --- a/mod/messages/lib/functions.php +++ b/mod/messages/lib/functions.php @@ -140,30 +140,3 @@ function messages_get_unread(int $user_guid = 0, int $limit = null, int $offset function messages_count_unread(int $user_guid = 0): int { return (int) messages_get_unread($user_guid, 10, 0, true); } - -/** - * Prepare the compose form variables - * - * @param int $recipient_guid new message recipient - * - * @return array - */ -function messages_prepare_form_vars(int $recipient_guid = 0): array { - - $recipients = []; - $recipient = get_user($recipient_guid); - if (!empty($recipient)) { - $recipients[] = $recipient->getGUID(); - } - - // input names => defaults - $values = [ - 'subject' => elgg_get_sticky_value('messages', 'subject', ''), - 'body' => elgg_get_sticky_value('messages', 'body', ''), - 'recipients' => elgg_get_sticky_value('messages', 'recipients', $recipients), - ]; - - elgg_clear_sticky_form('messages'); - - return $values; -} diff --git a/mod/messages/tests/phpunit/integration/Elgg/Messages/SendActionTest.php b/mod/messages/tests/phpunit/integration/Elgg/Messages/SendActionTest.php index a2e5816b094..5faa620f4ed 100644 --- a/mod/messages/tests/phpunit/integration/Elgg/Messages/SendActionTest.php +++ b/mod/messages/tests/phpunit/integration/Elgg/Messages/SendActionTest.php @@ -34,7 +34,7 @@ public function testSendFailsWithoutRecipient() { $this->assertInstanceOf(ErrorResponse::class, $response); $this->assertEquals(elgg_echo('messages:user:blank'), $response->getContent()); - $this->assertEquals('messages/add', $response->getForwardURL()); + $this->assertEquals(REFERRER, $response->getForwardURL()); } public function testSendFailsToSelf() { @@ -53,7 +53,7 @@ public function testSendFailsToSelf() { $this->assertInstanceOf(ErrorResponse::class, $response); $this->assertEquals(elgg_echo('messages:user:self'), $response->getContent()); - $this->assertEquals('messages/add', $response->getForwardURL()); + $this->assertEquals(REFERRER, $response->getForwardURL()); } public function testSendFailsToInvalidUser() { @@ -72,7 +72,7 @@ public function testSendFailsToInvalidUser() { $this->assertInstanceOf(ErrorResponse::class, $response); $this->assertEquals(elgg_echo('messages:user:nonexist'), $response->getContent()); - $this->assertEquals('messages/add', $response->getForwardURL()); + $this->assertEquals(REFERRER, $response->getForwardURL()); } public function testSendFailsWithoutMessageSubject() { @@ -94,7 +94,7 @@ public function testSendFailsWithoutMessageSubject() { $this->assertInstanceOf(ErrorResponse::class, $response); $this->assertEquals(elgg_echo('messages:blank'), $response->getContent()); - $this->assertEquals('messages/add', $response->getForwardURL()); + $this->assertEquals(REFERRER, $response->getForwardURL()); } public function testSendFailsWithoutMessageBody() { @@ -116,7 +116,7 @@ public function testSendFailsWithoutMessageBody() { $this->assertInstanceOf(ErrorResponse::class, $response); $this->assertEquals(elgg_echo('messages:blank'), $response->getContent()); - $this->assertEquals('messages/add', $response->getForwardURL()); + $this->assertEquals(REFERRER, $response->getForwardURL()); } public function testSendSuccess() { @@ -142,7 +142,7 @@ public function testSendSuccess() { $this->assertInstanceOf(OkResponse::class, $response); $this->assertSystemMessageEmitted(elgg_echo('messages:posted', [], $user->language)); - $this->assertEquals('messages/inbox/' . $user->username, $response->getForwardURL()); + $this->assertEquals(elgg_generate_url('collection:object:messages:owner', ['username' => $user->username]), $response->getForwardURL()); elgg_call(ELGG_IGNORE_ACCESS, function () use ($response) { $data = $response->getContent(); diff --git a/mod/messages/views/default/resources/messages/send.php b/mod/messages/views/default/resources/messages/send.php index 439254ada04..73a921e681f 100644 --- a/mod/messages/views/default/resources/messages/send.php +++ b/mod/messages/views/default/resources/messages/send.php @@ -4,14 +4,16 @@ */ $page_owner = elgg_get_logged_in_user_entity(); -elgg_set_page_owner_guid($page_owner->getGUID()); +elgg_set_page_owner_guid($page_owner->guid); elgg_push_collection_breadcrumbs('object', 'messages', $page_owner); -$params = messages_prepare_form_vars((int) get_input('send_to')); - echo elgg_view_page(elgg_echo('messages:add'), [ - 'content' => elgg_view_form('messages/send', [], $params), + 'content' => elgg_view_form('messages/send', ['sticky_enabled' => true], [ + 'recipients' => [ + (int) get_input('send_to'), + ] + ]), 'show_owner_block_menu' => false, 'filter_id' => 'messages/edit', ]); diff --git a/mod/pages/actions/pages/edit.php b/mod/pages/actions/pages/edit.php index 339cf1c1b75..bd38ef42d16 100644 --- a/mod/pages/actions/pages/edit.php +++ b/mod/pages/actions/pages/edit.php @@ -3,8 +3,6 @@ * Create or edit a page */ -elgg_make_sticky_form('page'); - $variables = elgg()->fields->get('object', 'page'); $input = []; foreach ($variables as $field) { @@ -96,8 +94,6 @@ return elgg_error_response(elgg_echo('pages:notsaved')); } -elgg_clear_sticky_form('page'); - // Now save description as an annotation $page->annotate('page', $page->description ?? '', $page->access_id); diff --git a/mod/pages/classes/Elgg/Pages/Forms/PrepareFields.php b/mod/pages/classes/Elgg/Pages/Forms/PrepareFields.php new file mode 100644 index 00000000000..8a7f31cc532 --- /dev/null +++ b/mod/pages/classes/Elgg/Pages/Forms/PrepareFields.php @@ -0,0 +1,45 @@ +getValue(); + + // input names => defaults + $values = [ + 'container_guid' => elgg_get_page_owner_guid(), + ]; + + // handle customizable fields + $fields = elgg()->fields->get('object', 'page'); + foreach ($fields as $field) { + $default_value = $field['#type'] === 'access' ? ACCESS_DEFAULT : ''; + $values[$field['name']] = $default_value; + } + + $page = elgg_extract('entity', $vars); + if ($page instanceof \ElggPage) { + foreach (array_keys($values) as $field) { + if (isset($page->$field)) { + $values[$field] = $page->$field; + } + } + } + + return array_merge($vars, $values); + } +} diff --git a/mod/pages/elgg-plugin.php b/mod/pages/elgg-plugin.php index 862f686548e..11e577b329a 100644 --- a/mod/pages/elgg-plugin.php +++ b/mod/pages/elgg-plugin.php @@ -1,5 +1,6 @@ [], ], ], + 'form:prepare:fields' => [ + 'pages/edit' => [ + PrepareFields::class => [], + ], + ], 'permissions_check' => [ 'object' => [ 'Elgg\Pages\Permissions::allowWriteAccess' => [], diff --git a/mod/pages/lib/pages.php b/mod/pages/lib/pages.php index a6652f29497..4d1afcbd2d0 100644 --- a/mod/pages/lib/pages.php +++ b/mod/pages/lib/pages.php @@ -3,57 +3,6 @@ * Pages function library */ -/** - * Prepare the add/edit form variables - * - * @param \ElggPage $page the page to edit - * @param int $parent_guid parrent page guid - * @param \ElggAnnotation $revision revision - * - * @return array - */ -function pages_prepare_form_vars(\ElggPage $page = null, int $parent_guid = 0, \ElggAnnotation $revision = null): array { - - // input names => defaults - $values = [ - 'title' => '', - 'description' => '', - 'access_id' => ACCESS_DEFAULT, - 'write_access_id' => ACCESS_DEFAULT, - 'tags' => '', - 'container_guid' => elgg_get_page_owner_guid(), - 'guid' => null, - 'entity' => null, - 'parent_guid' => $parent_guid, - ]; - - if ($page instanceof ElggPage) { - foreach (array_keys($values) as $field) { - if (isset($page->$field)) { - $values[$field] = $page->$field; - } - } - - $values['entity'] = $page; - } - - if (elgg_is_sticky_form('page')) { - $sticky_values = elgg_get_sticky_values('page'); - foreach ($sticky_values as $key => $value) { - $values[$key] = $value; - } - - elgg_clear_sticky_form('page'); - } - - // load the revision annotation if requested - if ($revision instanceof ElggAnnotation && $page instanceof ElggPage && $revision->entity_guid === $page->guid) { - $values['description'] = $revision->value; - } - - return $values; -} - /** * Recurses the page tree and adds the breadcrumbs for all ancestors * diff --git a/mod/pages/views/default/resources/pages/edit.php b/mod/pages/views/default/resources/pages/edit.php index 69daeab0bb0..d2485138dc0 100644 --- a/mod/pages/views/default/resources/pages/edit.php +++ b/mod/pages/views/default/resources/pages/edit.php @@ -7,6 +7,7 @@ elgg_entity_gatekeeper($page_guid, 'object', 'page', true); +/* @var $page \ElggPage */ $page = get_entity($page_guid); $container = $page->getContainerEntity(); @@ -17,9 +18,10 @@ pages_prepare_parent_breadcrumbs($page); elgg_push_breadcrumb($page->getDisplayName(), $page->getURL()); -$vars = pages_prepare_form_vars($page, $page->getParentGUID()); - echo elgg_view_page(elgg_echo('edit:object:page'), [ - 'content' => elgg_view_form('pages/edit', [], $vars), + 'content' => elgg_view_form('pages/edit', ['sticky_enabled' => true], [ + 'entity' => $page, + 'parent_guid' => $page->getParentGUID(), + ]), 'filter_id' => 'pages/edit', ]); diff --git a/mod/pages/views/default/resources/pages/new.php b/mod/pages/views/default/resources/pages/new.php index 7a2d4314dd2..31368e7724d 100644 --- a/mod/pages/views/default/resources/pages/new.php +++ b/mod/pages/views/default/resources/pages/new.php @@ -41,9 +41,7 @@ elgg_push_breadcrumb($parent->getDisplayName(), $parent->getURL()); } -$vars = pages_prepare_form_vars(null, $parent_guid); - echo elgg_view_page(elgg_echo('add:object:page'), [ - 'content' => elgg_view_form('pages/edit', [], $vars), + 'content' => elgg_view_form('pages/edit', ['sticky_enabled' => true], ['parent_guid' => $parent_guid]), 'filter_id' => 'pages/edit', ]); diff --git a/mod/web_services/actions/webservices/api_key/edit.php b/mod/web_services/actions/webservices/api_key/edit.php index 701f1b8acce..60f0db10678 100644 --- a/mod/web_services/actions/webservices/api_key/edit.php +++ b/mod/web_services/actions/webservices/api_key/edit.php @@ -3,8 +3,6 @@ * Save action for API key objects */ -elgg_make_sticky_form('webservices/api_key/edit'); - $guid = (int) get_input('guid'); $title = elgg_get_title_input(); @@ -28,6 +26,4 @@ return elgg_error_response(elgg_echo('save:fail')); } -elgg_clear_sticky_form('webservices/api_key/edit'); - return elgg_ok_response('', elgg_echo('webservices:action:api_key:edit:success'), 'admin/configure_utilities/ws_tokens'); diff --git a/mod/web_services/classes/Elgg/WebServices/ApiKeyForm.php b/mod/web_services/classes/Elgg/WebServices/ApiKeyForm.php deleted file mode 100644 index de52198d2c8..00000000000 --- a/mod/web_services/classes/Elgg/WebServices/ApiKeyForm.php +++ /dev/null @@ -1,58 +0,0 @@ -entity = $entity; - } - - /** - * Get form values - * - * @return array - */ - public function __invoke() { - $defaults = [ - 'title' => '', - 'description' => '', - ]; - - // is there an entity to edit - if ($this->entity instanceof \ElggApiKey) { - foreach ($defaults as $name => $value) { - $defaults[$name] = $this->entity->$name; - } - - $defaults['guid'] = $this->entity->guid; - } - - // check sticky form - $sticky_values = elgg_get_sticky_values('webservices/api_key/edit'); - if (!empty($sticky_values)) { - foreach ($sticky_values as $name => $value) { - $defaults[$name] = $value; - } - - elgg_clear_sticky_form('webservices/api_key/edit'); - } - - return $defaults; - } -} diff --git a/mod/web_services/classes/Elgg/WebServices/Forms/PrepareFields.php b/mod/web_services/classes/Elgg/WebServices/Forms/PrepareFields.php new file mode 100644 index 00000000000..dca6c4b32e2 --- /dev/null +++ b/mod/web_services/classes/Elgg/WebServices/Forms/PrepareFields.php @@ -0,0 +1,41 @@ +getValue(); + + // input names => defaults + $values = [ + 'title' => '', + 'description' => '', + 'guid' => null, + ]; + + $entity = elgg_extract('entity', $vars); + if ($entity instanceof \ElggApiKey) { + // load current api key values + foreach (array_keys($values) as $field) { + if (isset($entity->$field)) { + $values[$field] = $entity->$field; + } + } + } + + return array_merge($vars, $values); + } +} diff --git a/mod/web_services/elgg-plugin.php b/mod/web_services/elgg-plugin.php index ff54116cc79..3e2f81faecf 100644 --- a/mod/web_services/elgg-plugin.php +++ b/mod/web_services/elgg-plugin.php @@ -1,6 +1,7 @@ [ + 'form:prepare:fields' => [ + 'webservices/api_key/edit' => [ + PrepareFields::class => [], + ], + ], 'register' => [ 'menu:entity' => [ '\Elgg\WebServices\EntityMenu' => [], diff --git a/mod/web_services/views/default/resources/webservices/api_key/add.php b/mod/web_services/views/default/resources/webservices/api_key/add.php index 1e67456d147..ca14ae19ae1 100644 --- a/mod/web_services/views/default/resources/webservices/api_key/add.php +++ b/mod/web_services/views/default/resources/webservices/api_key/add.php @@ -3,20 +3,17 @@ * Create a new API key object */ -use Elgg\WebServices\ApiKeyForm; - $title = elgg_echo('add:object:api_key'); -$form = new ApiKeyForm(); - -$content = elgg_view_form('webservices/api_key/edit', [], $form()); +$content = elgg_view_form('webservices/api_key/edit', ['sticky_enabled' => true]); if (elgg_is_xhr()) { // in the lightbox echo elgg_view_module('info', $title, $content); -} else { - echo elgg_view_page($title, [ - 'content' => $content, - 'filter' => false, - ]); + return; } + +echo elgg_view_page($title, [ + 'content' => $content, + 'filter' => false, +]); diff --git a/mod/web_services/views/default/resources/webservices/api_key/edit.php b/mod/web_services/views/default/resources/webservices/api_key/edit.php index 0b49226476a..a64a0ec04e2 100644 --- a/mod/web_services/views/default/resources/webservices/api_key/edit.php +++ b/mod/web_services/views/default/resources/webservices/api_key/edit.php @@ -3,24 +3,21 @@ * Edit an existing API key object */ -use Elgg\WebServices\ApiKeyForm; - $guid = (int) elgg_extract('guid', $vars); elgg_entity_gatekeeper($guid, 'object', ElggApiKey::SUBTYPE, true); $entity = get_entity($guid); $title = elgg_echo('edit:object:api_key', [$entity->getDisplayName()]); -$form = new ApiKeyForm($entity); - -$content = elgg_view_form('webservices/api_key/edit', [], $form()); +$content = elgg_view_form('webservices/api_key/edit', ['sticky_enabled' => true], ['entity' => $entity]); if (elgg_is_xhr()) { // in the lightbox echo elgg_view_module('info', $title, $content); -} else { - echo elgg_view_page($title, [ - 'content' => $content, - 'filter' => false, - ]); + return; } + +echo elgg_view_page($title, [ + 'content' => $content, + 'filter' => false, +]); diff --git a/views/default/admin/users/add.php b/views/default/admin/users/add.php index 4d7a9cc550e..d56e0b97324 100644 --- a/views/default/admin/users/add.php +++ b/views/default/admin/users/add.php @@ -3,4 +3,10 @@ * Display an add user form. */ -echo elgg_view_form('useradd'); +echo elgg_view_form('useradd', [ + 'sticky_enabled' => true, + 'sticky_ignored_fields' => [ + 'password', + 'password2', + ], +]); diff --git a/views/default/elements/forms/footer.php b/views/default/elements/forms/footer.php index 8cb19f10c29..7d8b894bbfd 100644 --- a/views/default/elements/forms/footer.php +++ b/views/default/elements/forms/footer.php @@ -8,7 +8,27 @@ * @uses $vars['form_vars'] Vars used to format the form */ -$footer = elgg_extract('footer', $vars); +$footer = (string) elgg_extract('footer', $vars); + +// add automatic sticky form support +$form_vars = (array) elgg_extract('form_vars', $vars); +if ((bool) elgg_extract('sticky_enabled', $form_vars, false)) { + $footer .= elgg_view_field([ + '#type' => 'hidden', + 'name' => '_elgg_sticky_form_name', + 'value' => (string) elgg_extract('sticky_form_name', $form_vars), + ]); + + $ignored_fields = (array) elgg_extract('sticky_ignored_fields', $form_vars); + if (!empty($ignored_fields)) { + $footer .= elgg_view_field([ + '#type' => 'hidden', + 'name' => '_elgg_sticky_ignored_fields', + 'value' => implode(',', $ignored_fields), + ]); + } +} + if (empty($footer)) { return; } diff --git a/views/default/forms/register.php b/views/default/forms/register.php index d54b1ef619a..71bda0203c6 100644 --- a/views/default/forms/register.php +++ b/views/default/forms/register.php @@ -3,23 +3,6 @@ * Elgg register form */ -if (elgg_is_sticky_form('register')) { - $values = elgg_get_sticky_values('register'); - - // Add the sticky values to $vars so views extending - // register/extend also get access to them. - $vars = array_merge($vars, $values); - - elgg_clear_sticky_form('register'); -} else { - $values = []; -} - -$password = $password2 = ''; -$username = elgg_extract('username', $values, get_input('u')); -$email = elgg_extract('email', $values, get_input('e')); -$name = elgg_extract('name', $values, get_input('n')); - $fields = [ [ '#type' => 'hidden', @@ -36,7 +19,7 @@ '#label' => elgg_echo('name'), '#class' => 'mtm', 'name' => 'name', - 'value' => $name, + 'value' => elgg_extract('name', $vars, get_input('n')), 'autofocus' => true, 'required' => true, ], @@ -44,21 +27,20 @@ '#type' => 'email', '#label' => elgg_echo('email'), 'name' => 'email', - 'value' => $email, + 'value' => elgg_extract('email', $vars, get_input('e')), 'required' => true, ], [ '#type' => 'text', '#label' => elgg_echo('username'), 'name' => 'username', - 'value' => $username, + 'value' => elgg_extract('username', $vars, get_input('u')), 'required' => true, ], [ '#type' => 'password', '#label' => elgg_echo('password'), 'name' => 'password', - 'value' => $password, 'required' => true, 'autocomplete' => 'new-password', 'add_security_requirements' => true, @@ -67,7 +49,6 @@ '#type' => 'password', '#label' => elgg_echo('passwordagain'), 'name' => 'password2', - 'value' => $password2, 'required' => true, 'autocomplete' => 'new-password', 'add_security_requirements' => true, diff --git a/views/default/forms/useradd.php b/views/default/forms/useradd.php index e754baf7ddf..d26e5585f5a 100644 --- a/views/default/forms/useradd.php +++ b/views/default/forms/useradd.php @@ -1,62 +1,47 @@ 'text', - 'name' => 'name', - 'value' => $name, '#label' => elgg_echo('name'), + 'name' => 'name', + 'value' => elgg_extract('name', $vars), 'required' => true, ]); echo elgg_view_field([ '#type' => 'text', - 'name' => 'username', - 'value' => $username, '#label' => elgg_echo('username'), + 'name' => 'username', + 'value' => elgg_extract('username', $vars), 'required' => true, ]); echo elgg_view_field([ '#type' => 'email', - 'name' => 'email', - 'value' => $email, '#label' => elgg_echo('email'), + 'name' => 'email', + 'value' => elgg_extract('email', $vars), 'required' => true, ]); echo elgg_view_field([ '#type' => 'checkbox', + '#label' => elgg_echo('autogen_password_option'), 'name' => 'autogen_password', 'value' => 1, 'default' => false, - 'label' => elgg_echo('autogen_password_option'), - 'checked' => (bool) $autogen_password, + 'checked' => (bool) elgg_extract('autogen_password', $vars), ]); echo elgg_view_field([ '#type' => 'password', '#label' => elgg_echo('password'), 'name' => 'password', - 'value' => $password, 'required' => true, 'autocomplete' => 'new-password', 'add_security_requirements' => true, @@ -66,7 +51,6 @@ '#type' => 'password', '#label' => elgg_echo('passwordagain'), 'name' => 'password2', - 'value' => $password2, 'required' => true, 'autocomplete' => 'new-password', 'add_security_requirements' => true, @@ -74,11 +58,11 @@ echo elgg_view_field([ '#type' => 'checkbox', + '#label' => elgg_echo('admin_option'), 'name' => 'admin', 'value' => 1, 'default' => false, - 'label' => elgg_echo('admin_option'), - 'checked' => $admin, + 'checked' => (bool) elgg_extract('admin', $vars), ]); $footer = elgg_view_field([ diff --git a/views/default/resources/account/register.php b/views/default/resources/account/register.php index a06a24b5bac..0cfcc67d468 100644 --- a/views/default/resources/account/register.php +++ b/views/default/resources/account/register.php @@ -15,6 +15,11 @@ $form_params = [ 'class' => 'elgg-form-account', 'ajax' => true, + 'sticky_enabled' => true, + 'sticky_ignored_fields' => [ + 'password', + 'password2', + ], ]; $body_params = [ diff --git a/views/default/resources/index.php b/views/default/resources/index.php index ced7e86cd0b..22213650b81 100644 --- a/views/default/resources/index.php +++ b/views/default/resources/index.php @@ -5,7 +5,14 @@ $content = elgg_echo('index:content'); } elseif (elgg_get_config('allow_registration')) { $title = elgg_echo('register'); - $content = elgg_view_form('register', ['ajax' => true]); + $content = elgg_view_form('register', [ + 'ajax' => true, + 'sticky_enabled' => true, + 'sticky_ignored_fields' => [ + 'password', + 'password2', + ], + ]); } else { $title = elgg_echo('login'); $content = elgg_view_form('login', ['ajax' => true]);