Problem/Motivation

The prefetch_cache module could be used in such a way that when a user visits node/1 then node/1/edit will be loaded in the background so that we could faster deliver the edit form if the user wants to edit the entity. However being on node view does not mean that the user will always go on node/edit, therefore we need a solution to lock the form only in case the user has clicked on edit.

Proposed resolution

Instead of locking directly in hook_form_alter we could add a hidden button, which is pressed by JS and through submit and ajax response takes care of locking the form.

Remaining tasks

User interface changes

API changes

Data model changes

Comments

hchonov created an issue. See original summary.

tstoeckler’s picture

Status: Needs work » Needs review
StatusFileSize
new11.2 KB

This implements the suggested approach. I originally wanted to make the behavior configurable in some way, but since the behavior ended up being fairly complex on its own, I did not implement this yet so as not to increase the complexity further. Would love some thoughts on whether some way of configurability will be needed and if so, how we should go about that.

Part of the complexity stems from the fact that it is unnecessarily difficult to disable a form in an Ajax request, I will open a core issue to discuss and possibly improve that.

I tried to document all the weird bits in code, so not repeating that here, but would obviously love any input on how to improve the patch and possibly remove some of the weirdness.

Status: Needs review » Needs work

The last submitted patch, 2: 2916745-2.patch, failed testing. View results

tstoeckler’s picture

Status: Needs work » Needs review

Sorry, this one should apply properly.

tstoeckler’s picture

StatusFileSize
new11.19 KB

Grrrr

Status: Needs review » Needs work

The last submitted patch, 5: 2916745-4.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

tstoeckler’s picture

Status: Needs work » Needs review
StatusFileSize
new5.3 KB
new11.73 KB

I realized that rebuilding the form during the Ajax submission somewhat defeats the purpose of Prefetch Cache in the first place. So this one just modifies the form on the fly and sends it back directly. It's a bit less elegant IMO, but should be a lot quicker, especially for bigger forms.

Status: Needs review » Needs work

The last submitted patch, 7: 2916745-7.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

kfritsche’s picture

Status: Needs work » Needs review
StatusFileSize
new15.42 KB

The approach by tstoeckler still has problems when using modules like prefetch_cache, as on the first ajax request the hole form is rebuild anyway. And this is then the first ajax request.

There is an open issue for this #2851251: Forms look at current request method rather than form method for cache check. This breaks AJAX forms because every first visit is GET.

Till then we decided to switch to our own JS/Ajax implementation and not using form API ajax here. This is much faster.
Also new patch includes setting to disable/enable this.

No interdiff as its a different approach and first patch wasn't used at all :/

fyi: we have an experimental branch open on github (https://github.com/attrib/content_lock) which merges the latests patches by hchonov, tstoeckler and me.

Status: Needs review » Needs work

The last submitted patch, 9: 2916745-9.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

chr.fritsch’s picture

Thank you @biologis guys for all the recent contributions. If you could get the test pass and the issues RTBC i am very grateful for all your improvments.

kfritsche’s picture

Status: Needs work » Needs review
StatusFileSize
new1.28 KB
new16.69 KB

This should fix the current tests.

New tests would be nice, but not sure if I get to it soon :/

hchonov’s picture

Status: Needs review » Needs work

It looks good. Thank you! Unfortunately, I have a couple of remarks :)

  1. +++ b/js/content-lock-form.js
    @@ -0,0 +1,63 @@
    +      $form.find('input, textarea, select').attr('disabled', 'disabled').addClass('is-disabled');
    

    According to the jQuery documentation when setting "disabled" we should use the jQuery prop method instead the attr method.

  2. +++ b/src/Controller/LockController.php
    @@ -0,0 +1,90 @@
    + * Created by PhpStorm.
    + * User: karl.fritsche
    

    I think this is not really needed :)

  3. +++ b/src/Controller/LockController.php
    @@ -0,0 +1,90 @@
    +      $container->get('content_lock')
    ...
    +      $messages = \Drupal::service('renderer')->renderRoot($status_messages);
    

    Let's add the renderer service through "dependency injection" :).

  4. +++ b/src/Controller/LockController.php
    @@ -0,0 +1,90 @@
    +   * @param \Symfony\Component\HttpFoundation\Request $request
    ...
    +  public function createLockCall(Request $request, ContentEntityInterface $entity) {
    

    The $request parameter is not used, therefore it should be removed. If it is not present in the method definition then Drupal will not pass it. @see https://www.drupal.org/docs/8/api/routing-system/using-parameters-in-routes

  5. +++ b/src/Controller/LockController.php
    @@ -0,0 +1,90 @@
    +    // Not lockable entity or node creation
    

    -> Not lockable entity or entity creation. :)

  6. +++ b/src/Controller/LockController.php
    @@ -0,0 +1,90 @@
    +      $lock = $lockable ? $this->lockService->locking($entity->id(), $this->currentUser()->id(), $entity->getEntityTypeId(), FALSE, $entity->toUrl('edit-form')->getInternalPath()) : FALSE;
    

    If there are multiple forms on which the content lock is enabled, then regardless of the form for which the lock is being broken the user will always be redirected to the edit-form, instead to the form on which she currently is. We have to find a way to redirect the user to the proper destination.

  7. +++ b/src/Controller/LockController.php
    @@ -0,0 +1,90 @@
    +        $response->addCommand(new AppendCommand('#edit-actions', $unlock_button));
    

    Could we probably add a specific class to the actions in hook_form_alter and use this class as a selector instead of relying on the element ID being '#edit-actions'?

hchonov’s picture

Just nits :

+++ b/config/install/content_lock.settings.yml
@@ -1,2 +1,3 @@
\ No newline at end of file

+++ b/content_lock.libraries.yml
@@ -0,0 +1,7 @@
\ No newline at end of file

+++ b/js/content-lock-form.js
@@ -0,0 +1,63 @@
\ No newline at end of file

+++ b/src/Controller/LockController.php
@@ -0,0 +1,90 @@
\ No newline at end of file

We have to add the new lines.

kfritsche’s picture

Status: Needs work » Needs review
StatusFileSize
new7.72 KB
new16.95 KB

Thanks for the review. I hope I fixed now all the issues.

4. is not fixed as its now used for 6. :)

If there are multiple forms on which the content lock is enabled, then regardless of the form for which the lock is being broken the user will always be redirected to the edit-form, instead to the form on which she currently is. We have to find a way to redirect the user to the proper destination.

Good catch. I add now a destination query when generating the ajax lock url, which then is used here if given. edit-form is now the fallback, if somehow no destination is given.

Regarding new lines, fixed my PHPStorm settings :/

hchonov’s picture

Status: Needs review » Needs work

Regarding 1. - I've missed that there are two lines where disabled is being set. The other line still should be converted to use the prop method instead the attr method when setting the disabled property.

Beside that it looks good.

kfritsche’s picture

Status: Needs work » Needs review
StatusFileSize
new1.73 KB
new16.05 KB

I fixed the following things:

1. Re-roll
2. Fixed attr to prop in JQuery as hchonov mentioned
3. Renamed JS have the same name schema as settings

hchonov’s picture

Thank you. After going through the patch again I found one last questionable change:

+++ b/content_lock.module
@@ -82,6 +83,36 @@ function content_lock_form_alter(&$form, FormStateInterface $form_state, $form_i
+      $form['actions']['#attributes']['class'][] = 'content-lock-actions';
...
+        $form['actions']['delete']['#attributes']['class'][] = 'content-lock-actions';
...
+        $form['actions']['publish']['#attributes']['class'][] = 'content-lock-actions';
...
+        $form['actions']['unpublish']['#attributes']['class'][] = 'content-lock-actions';
...
+        $form['moderation_state']['#attributes']['class'][] = 'content-lock-actions';

As in JS we just remove the element which has the class "content-lock-actions" we do not really have to add the class to each action, but only to the parent element containing all the actions. Do you agree with that or there is probably some other reason for doing this?

kfritsche’s picture

@hchonov:

The class to actions was added later to be able to add the unlock button with the ajax response.

The basic idea at the beginning was to be as close as possible to the none-js version. But you are right, currently we would remove the hole actions.

On the other hand the question is more, if it makes more sense to remove all actions also in none JS version, when content is locked. Are there actions which should be available when locked?

hchonov’s picture

Are there actions which should be available when locked?

Well even if there are actions which should be available then this would be a contrib/custom case, which we don't know. Also currently we would add the class to only core known actions, but not to all actions that have been added through e.g. a form alter hook. Therefore currently I think we should add the class to the parent element and remove or disable (personally I prefer disable with e.g. on hover message that the action is disabled because the form is locked) all the action buttons through JS.

kfritsche’s picture

StatusFileSize
new16.58 KB
new5.59 KB

* Fixed a bad merge in ContentLockController
* In JS action buttons are now only disabled with a tooltip that content is locked and action is not available

hchonov’s picture

Status: Needs review » Reviewed & tested by the community

Thank you, I think that this looks good now.

chr.fritsch’s picture

Status: Reviewed & tested by the community » Needs work
kfritsche’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new17.11 KB

Big thumbs up to @chr.fritsch for getting all the patches so quickly in. I remove my intermediate github repo now.

Here is just the re-roll.

chr.fritsch’s picture

Status: Reviewed & tested by the community » Fixed

Thank you everyone.

  • chr.fritsch committed 1882991 on 8.x-1.x authored by kfritsche
    Issue #2916745 by kfritsche, tstoeckler: Allow for coexistence with the...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.