Problem/Motivation

#2807785: Move global constants from *.module files into interfaces deprecated a bunch of constants but it did not actually replace their usage. We should do this. This issue handles MENU_MAX_MENU_NAME_LENGTH_UI. This is a bug because we've deprecated something but we've not completed the task.

The original deprecation was to use ConfigEntityStorage::MAX_ID_LENGTH instead but this does not work and produces fatal SQL errors due to the menu_tree:menu column only being a varchar(32).

Proposed resolution

Use MenuStorage::MAX_ID_LENGTH instead. This size is determined by the smallest of:

  • menu_tree table schema definition for menu - 32
  • \Drupal\Core\Config\Entity\ConfigEntityStorage::MAX_ID_LENGTH - 166
  • menu_name base field on the Menu Link content entity - 255

Remaining tasks

User interface changes

Users can now enter menu names of 32 characters long - up from 27.

API changes

Add a storage handler for Menu config entities so that they can override the ConfigEntityStorage::MAX_ID_LENGTH and limit it to 32 which is the column size of the menu_tree:menu column.

Data model changes

None

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

alexpott created an issue. See original summary.

alexpott’s picture

Status: Active » Needs review
FileSize
5.9 KB

The patch leaves the one remaining instance in core.

grep -R MENU_MAX_MENU_NAME_LENGTH_UI ./core                                                               365ms  Fri 23 Nov 09:36:12 2018
./core/modules/menu_ui/menu_ui.module:const MENU_MAX_MENU_NAME_LENGTH_UI = ConfigEntityStorage::MAX_ID_LENGTH;

This one is a bit interesting because the new value is 166 and the old value is 27 so if you actually followed the advice of the existing deprecation you possibly would create menus with too long IDs for the UI.

Status: Needs review » Needs work

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

alexpott’s picture

Status: Needs work » Needs review
FileSize
521 bytes
5.9 KB

Whoops

Status: Needs review » Needs work

The last submitted patch, 4: 3015699-4.patch, failed testing. View results

alexpott’s picture

Hmmm.... okay so this is a false deprecation :(

The menu entity machine name is not only limited by configuration ID it is also limited by \Drupal\Core\Menu\MenuTreeStorage::schemaDefinition(). It has to be able to fit into

        'menu_name' => [
          'description' => "The menu name. All links with the same menu name (such as 'tools') are part of the same menu.",
          'type' => 'varchar_ascii',
          'length' => 32,
          'not null' => TRUE,
          'default' => '',
        ],

One solution is to add an update function and increase the size of this field. The other is to change the deprecation to use a specific constant.

alexpott’s picture

Here's the Drupal 7 code.

/**
 * Maximum length of menu name as entered by the user. Database length is 32
 * and we add a menu- prefix.
 */
define('MENU_MAX_MENU_NAME_LENGTH_UI', 27);

So we no longer add the menu- prefix on the front of custom menus created via the UI. But as noted in #6 we still have the 32 character limit due to the menu_tree table. The other place this appears in the db is in the menu_link_content_data table. There is defined as:

    $fields['menu_name'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Menu name'))
      ->setDescription(t('The menu name. All links with the same menu name (such as "tools") are part of the same menu.'))
      ->setDefaultValue('tools')
      ->setSetting('is_ascii', TRUE);

So it gets the default string length which is defined in MenuItem as 255. A length it can never be because menu names are part of the config entity ID and therefore subject to ConfigEntityStorage::MAX_ID_LENGTH - ie 166.

Discussed with @catch and @dawehner or slack. @catch wondered if there are other reasons for the 32 character limit - for example performance. @dawehner seemed in favour of increasing the menu_tree column size.

I think the safest course of action is to add a new \Drupal\system\MenuInterface::MENU_MAX_ID_LENGTH constant set to 32 and deprecate MENU_MAX_MENU_NAME_LENGTH_UI in favour of it. We can open a followup issue to discuss changing it to 166 and using ConfigEntityStorage::MAX_ID_LENGTH and that issue could also handle the base field.

alexpott’s picture

Status: Needs work » Needs review
FileSize
7.15 KB

Here's an approach where \Drupal\Core\Config\Entity\ConfigEntityStorage::save() will protect people from breaking their sites when menu names are too long.

alexpott’s picture

Adding a test which shows we need late static binding FTW.

Status: Needs review » Needs work

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

alexpott’s picture

Status: Needs work » Needs review
FileSize
470 bytes
9.4 KB

Argh.

alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes

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

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

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

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

johnwebdev’s picture

Rerolled. Updated the deprecation message per the core policy, but not sure which branch it should be targeted at. Happy to be given some clarity on the subject :D

Status: Needs review » Needs work

The last submitted patch, 16: 3015699-16.patch, failed testing. View results

longwave’s picture

Rerolled, and fixed the deprecation in the test. Interdiff is for the fix.

Berdir’s picture

The trick with overriding the class and constant with that is neat, took me a while to understand that, first thought we could instaed also add it to \Drupal\Core\Menu\MenuTreeStorageInterface but this makes sense then.

Patch looks fine to me but I wonder if we can change a deprecation like that and keep the D9 deprecation, since the replacement only exists in D8.9? Do we need to change it to D10?

alexpott’s picture

Well if you follow the deprecation in HEAD you'd actually cause bugs in your code so I think we should commit this to 8.8.x and up and therefore changing the deprecation now is fine.

Berdir’s picture

Yes, I'm not saying we shouldn't change it, just that wondering if we should really remove it in D9. The few uses in contrib then wouldn't be able to be compatible with 8.8 and 9.0.

Alternatively, we could backport it to 8.8, as a bugfix?

alexpott’s picture

@Berdir yep our options are to either undeprecate in Drupal 8 and do this in Drupal 9.1 or to backport this to 8.8. I'd be in favour of moving forward instead of backward then forward.

Berdir’s picture

Status: Needs review » Reviewed & tested by the community

Discussed a bit with Slack, the options are:

1. Commit it like this as a bugfix for 8.8, still remove in D9. The argument why it is OK is that we only support 8.8.latest anyway, so the very few modules that use this constant can be compatible with 8.8.latest and 9.0.0 (but not 8.8.0). I guess this is fine, and we need to backport *something* to 8.8 anyway to not have a wrong deprecation message there.

2. Remove the deprecation in 8.8, re-deprecate in 9.1 for 10.

3. Commit this to 8.8.x and change the deprecation to remove it only in 10. So a combination of 1 & 2. This is kind of against https://groups.drupal.org/node/535670, but this is a special case as it is already deprecated, we're just changing it.

I think if the assumption in 1 is OK (that we can fix deprecation in 8.8 and still remove it in 9.0) then this patch is ready.

catch’s picture

I think option #1 is OK here, we have to commit something to 8.8.x anyway to fix the incorrect deprecation, and updating has a better chance of informing someone who's already followed the bad advice in the existing message.


+<?php
+
+namespace Drupal\system;
+
+use Drupal\Core\Config\Entity\ConfigEntityStorage;
+
+/**
+ * Defines the storage class for menu configuration entities.
+ */
+class MenuStorage extends ConfigEntityStorage {
+
+  /**

Why not use Drupal\system\Entity namespace here?

alexpott’s picture

Because we don't put entity storage classes there - see UserStorage, TermStorage, NodeStorage... they are all in the main src folder. The entity folder is like a plugin folder where the entity class exists.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 18: 3015699-18.patch, failed testing. View results

Berdir’s picture

Status: Needs work » Reviewed & tested by the community
1) Drupal\Tests\media_library\FunctionalJavascript\WidgetUploadTest::testWidgetUploadAdvancedUi
"image-1.png" not found
Failed asserting that a boolean is not empty.

That looks quite unrelated.

longwave’s picture

That fail is being tracked at #3103492: Random fail in WidgetUploadTest

  • catch committed a575a5b on 9.0.x
    Issue #3015699 by alexpott, longwave, johndevman, Berdir: Properly...

  • catch committed 6ee0528 on 8.9.x
    Issue #3015699 by alexpott, longwave, johndevman, Berdir: Properly...

  • catch committed b381bce on 8.8.x
    Issue #3015699 by alexpott, longwave, johndevman, Berdir: Properly...
catch’s picture

Version: 8.9.x-dev » 8.8.x-dev
Status: Reviewed & tested by the community » Fixed

Committed/pushed to 9.0.x, 8.9.x and 8.8.x, thanks!

Status: Fixed » Closed (fixed)

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