Problem/Motivation

URL ending forward slash(‘/‘) breaks url alias(pretty url) paths.

Admin area where users are able to make menu edit changes to menu links e.g. /admin/structure/menu/manage/main seem to break core functionality when appending the forward slash to node references. The following steps will recreate the issue.

Steps to recreate:
1. Visit admin/config/search/path
2. Click on the ‘edit’ operation, assuming there are existing menu links created.
3. Append the path field value with the forward slash character ’/‘. e.g. /node/1 will become /node/1/
4. Save the changes.
5. Visit any page that contains the main menu and you’ll notice the url alias no longer working. The link will now reference the node path with the ‘/‘ prepended.

Proposed resolution

Create a post-update hook in the path_alias module to execute scripts that update aliases in batches, removing trailing spaces and slashes.

Issue fork drupal-3145132

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

cm0dit created an issue. See original summary.

cm0dit’s picture

StatusFileSize
new1.61 KB

Status: Needs review » Needs work

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

ankitsingh0188’s picture

Assigned: Unassigned » ankitsingh0188
cm0dit’s picture

StatusFileSize
new1.6 KB

My apologies, while testing, I forgot to uncomment and important piece of the patch!

ankitsingh0188’s picture

Hi @cm0dit,

Please make sure that the issue is assigned to someone else or not before adding a patch or comment. As I am also working on test case failures, but I just saw your comments.

Anyways, please run the test cases for the #5 patch.

hardik_patel_12’s picture

working on it.

ankitsingh0188’s picture

Hi @Hardik_Patel_12,

I have assigned this ticket to myself and you have changed the assignee and assigned to yourself. I think this is not the right approach. Please make sure that the ticket is not assigned to someone before working on that.

Thanks!

hardik_patel_12’s picture

Assigned: hardik_patel_12 » Unassigned
Status: Needs work » Needs review
StatusFileSize
new894 bytes
new896 bytes

Kindly review a new patch.

hardik_patel_12’s picture

Hi @ankit.singh , ticket was assign to you 4 days ago so that's why i thought you are not working on this. At least you should write that i am working on this issue so then only people will understand that not to pick this issue. So its a kindly request that if we are facing some trouble in the issues and spending couple of days then simply unassign the issue so other people can work on it.

Thanks!

ankitsingh0188’s picture

1. Visit admin/config/search/path
2. Append the System path field value '/'

e.g. /node/1 will become /node/1/

Before Patch: It shows a 404 page not found an error.

After Patch: Patch applied successfully and the respective entity page opens up.

Good to move it to RTBC +1

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

ankitsingh0188’s picture

StatusFileSize
new303.52 KB

I have re-run the #9 patch for Drupal version 8.9 and the patch applied successfully.

patch check

hardik_patel_12’s picture

Status: Needs review » Reviewed & tested by the community

Thanks @ankit.singh , for verifying now its looks good to go. Moving to RTBC.

xjm’s picture

Title: Menu and Path Module Issues » PathAlias::preSave() trims the alias -- should it trim the path instead?
Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

Thanks everyone for filing this bug report and for fixing the issue. Bug fixing is very valuable.

@ankit.singh, thank you for looking into to this issue. Posting screenshots of your codebase or CLI does not advance the issue, since the automated testing infrastructure tells us whether the patch applies correctly. However, the before-and-after screenshots of the UI are potentially helpful, so leaving credit for that. Next time, could you crop them only to the relevant part of the screen, and embed them in the issue?

So, I've removed the issue credit for that screenshot. In the future, you can get credit for issues by reading the issue to understand its purpose, and posting your review or testing of that purpose, including whether it completely fixes the issue, whether it is the best fix, and so on. Thank you!

  1. +++ b/core/modules/path_alias/src/Entity/PathAlias.php
    @@ -94,10 +94,13 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    -    // Trim the alias value of whitespace and slashes. Ensure to not trim the
    -    // slash on the left side.
    +    // Trim the alias and path values of whitespace and slashes. Ensure to not trim the
    +    // slash on the left side, but only the trailing slash.
    

    The comments here are not wrapping properly. We need to make sure the new comment is wrapped at 80 characters.

  2. In order to commit a bug fix, we need an automated to test to prove that we've fixed the bug and ensure that we don't break it again in the future. For more information about writing tests in Drupal 8 see the following links:

    1. https://www.drupal.org/docs/8/testing
    2. https://api.drupal.org/api/drupal/core%21core.api.php/group/testing/8.9.x
  3. +++ b/core/modules/path_alias/src/Entity/PathAlias.php
    @@ -94,10 +94,13 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
         $this->setAlias($alias);
    +    $this->setPath($path);
    

    Looks like this is a difficulty between the setAlias() and setPath() methods on PathAlias.

    I checked their relative docs on the interface.

    setAlias() has:

      /**                                                                           
       * Sets the alias for this path.                                              
       *                                                                            
       * @param string $alias                                                       
       *   The path alias.                                                          
       *                                                                            
       * @return $this                                                              
       */
      public function setAlias($alias);
    
      /**                                                                           
       * Sets the source path of the alias.                                         
       *                                                                            
       * @param string $path                                                        
       *   The source path.                                                         
       *                                                                            
       * @return $this                                                              
       */
      public function setPath($path);
    

    ...That's not helpful to our situation, where we are trying to decide if this is an appropriate way to mess around with PathAlias::preSave(). However, it does sound like the trimming is supposed to be done on output, not input. So I'm not totally sure of changing the user's input here.

hardik_patel_12’s picture

Status: Needs work » Needs review
StatusFileSize
new3.37 KB
new3.03 KB

covering points suggested by @xjm .

#15.1 done
#15.2 adding test case for this bug
#15.3 i think changing the user's input here its ok , but yes i am also still not sure about this.

hardik_patel_12’s picture

jungle’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/path_alias/src/Entity/PathAlias.php
    @@ -94,10 +94,14 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    +    // Trim the alias and path values of whitespace and slashes.
    +    //  Ensure to not trim the slash on the left side,
    +    //   but only the trailing slash.
    

    Wrapped too early.

  2. +++ b/core/modules/path_alias/tests/src/Functional/PathWithSlashFunctionalTest.php
    @@ -0,0 +1,84 @@
    +   * Modules to enable.
    +   *
    ...
    +  protected static $modules = ['path'];
    

    Should be {@inheritdoc}

  3. +++ b/core/modules/path_alias/src/Entity/PathAlias.php
    @@ -94,8 +94,9 @@
    +    // Trim the alias and path values of whitespace and slashes.
    +    //  Ensure to not trim the slash on the left side,
    +    //   but only the trailing slash.
    

    Wrapped too early

  4. +++ b/core/modules/path_alias/tests/src/Functional/PathWithSlashFunctionalTest.php
    @@ -0,0 +1,84 @@
    +    $this->drupalPostForm('admin/config/search/path/add', $edit, t('Save'));
    ...
    +    $this->drupalPostForm('admin/config/search/path/edit/' . $pid, $edit, t('Save'));
    

    t() is unnecessary

  5. +++ b/core/modules/path_alias/tests/src/Functional/PathWithSlashFunctionalTest.php
    @@ -0,0 +1,84 @@
    +    // Get last created path alias and update the path,
    +    // new path ends with slash(/).
    

    Wrapped too early.

  6. +++ b/core/modules/path_alias/tests/src/Functional/PathWithSlashFunctionalTest.php
    @@ -0,0 +1,84 @@
    +  public function getPID($alias) {
    

    getPid()?

  7. +++ b/core/modules/path_alias/tests/src/Functional/PathWithSlashFunctionalTest.php
    @@ -0,0 +1,84 @@
    +    return reset($result);
    

    What if it's []

naresh_bavaskar’s picture

Assigned: Unassigned » naresh_bavaskar
naresh_bavaskar’s picture

Assigned: naresh_bavaskar » Unassigned
Status: Needs work » Needs review
StatusFileSize
new1.84 KB
new1.56 KB
new3.85 KB

Added test cases (Kernal).

@xjm Thanks for the suggestion. I think trimming supposed to do on input (not output) othewise every request It needs to trim (performance)

Please review

jungle’s picture

StatusFileSize
new992 bytes

Well, #20 is a kernel test. not a funcational test as #16. So uploading a test only patch based on #20.

(Yeah, It's bad that the last patch is a test-only patch)

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

Status: Needs review » Needs work

The last submitted patch, 21: 3145132-21-test-only.patch, failed testing. View results

jeroent’s picture

Status: Needs work » Needs review
berdir’s picture

+++ b/core/modules/path_alias/src/Entity/PathAlias.php
@@ -94,10 +94,13 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
 
-    // Trim the alias value of whitespace and slashes. Ensure to not trim the
-    // slash on the left side.
+    // Trim the alias and path values of whitespace and slashes. Ensure do not
+    // trim the slash on the left side, but only the trailing slash.

this somehow changed from "to not" to "do not", that's not correct grammar, was right before.

naresh_bavaskar’s picture

Assigned: Unassigned » naresh_bavaskar
Status: Needs review » Needs work

@berdir, Thanks for focusing it out. I think it mistakenly added by me. will correct it

naresh_bavaskar’s picture

Assigned: naresh_bavaskar » Unassigned
Status: Needs work » Needs review
StatusFileSize
new1.84 KB
new668 bytes

Fixed grammatical mistake in comment #20.

hardik_patel_12’s picture

Status: Needs review » Reviewed & tested by the community

Now patch is looks good to me , grammar change is also covered as suggested by @Berdir , moving to RTBC.

catch’s picture

Does this need an update to trim trailing forward slashes from existing data?

amateescu’s picture

Title: PathAlias::preSave() trims the alias -- should it trim the path instead? » PathAlias::preSave() should also trim the path, not just the alias

Yup, I think we need an update function.

catch’s picture

Status: Reviewed & tested by the community » Needs work

OK let's add that here.

mohit_aghera’s picture

Version: 8.9.x-dev » 9.3.x-dev
Status: Needs work » Needs review
StatusFileSize
new2.49 KB
new665 bytes

- Adding an update hook to re-save all the path aliases.

I am wondering if we need more validation around it to save only paths which ends with "/"
As, I'm just re-saving nodes, I haven't added tests for update hook.

@catch, please suggest if we want to refactor the logic to update existing path aliases.

kapilv’s picture

StatusFileSize
new2.49 KB
new552 bytes

Fixed Custom Commands Failed.

catch’s picture

Status: Needs review » Needs work
+++ b/core/modules/path_alias/path_alias.install
@@ -0,0 +1,17 @@
+
+/**
+ * Re-save all the path alias to removing trailing space and slash.
+ */
+function path_alias_update_9100() {
+  $path_aliases = \Drupal::entityTypeManager()->getStorage('path_alias')->loadMultiple();
+  /** @var \Drupal\path_alias\Entity\PathAlias $alias */
+  foreach ($path_aliases as $alias) {
+    $alias->save();
+  }
+}

This could be done in a hook_post_update_NAME(), since it's affecting content rather than schema. Also needs to use batch since there could be millions of aliases on a site.

ankithashetty’s picture

Status: Needs work » Needs review
StatusFileSize
new3.16 KB
new1.69 KB

Updated the patch in #33 addressing the changes suggested in #34, i.e., moved the update_9100() hook in path_alias.install to post_update_Name hook in path_alias.post_update.php.

Also tried to use the batch process within the post_update_Name hook, please review.

Thank you!

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

triggering for 10.1

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative, +Needs issue summary update

Tested this on Drupal 10.1 with a standard install
Followed the steps in the issue summary and confirmed I was able to add a URL alias /node/1/
With node/1 having an alias of /hello-world.
I add a menu link to the main navigation for node/1
When I got to any page I see that the alias works fine.
Unless I missed a step

But agree it should cleanup the trialing /
Can the issue summary be updated with the proposed solution.

Thanks.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

hardik_patel_12’s picture

StatusFileSize
new3.31 KB
new1.56 KB

Added type hinting in the batch process and changed the limit from 25 to 50 in the post_update hook.

hardik_patel_12’s picture

Issue summary: View changes

I've revised the issue description; please feel free to suggest any further changes if you think they are needed.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.