Problem/Motivation

Four methods on DisplayBuildableInterface are still static: checkAccess(), checkInstanceId(), getUrlFromInstanceId() and getDisplayUrlFromInstanceId(). They exist because nothing can answer "which plugin owns this instance ID", so every caller walks the plugin definitions and pokes a class string.

Being static, they cannot receive injected services — every remaining \Drupal::service() call in the buildable plugins is inside one of them — and they cannot be mocked in tests. Two of them also duplicate instance methods that already exist: checkAccess($id, $account) asks what isAllowed($account) asks, and getUrlFromInstanceId($id) returns what getBuilderUrl() returns.

Proposed resolution

  • Add a resolver to DisplayBuildablePluginManager that maps an instance ID to a configured plugin, matching on the instance_prefix the plugin definition already carries.
  • Move callers onto it, then delete checkAccess(), checkInstanceId() and getUrlFromInstanceId() from the interface.
  • Turn getDisplayUrlFromInstanceId() into an instance getSettingsUrl(), and let DisplayReference::$settingsUrl read from it instead of each collectDisplays() passing its own.
  • Fix EntityViewOverride's stub, which returns Url::fromRoute('<front>') — BackButton and InstanceListBuilder send overrides to the front page today.

Remaining tasks

  • Each plugin needs a way to turn an instance ID into plugin configuration. checkInstanceId() returns route parameters, which are not the same shape as the constructor's configuration keys.
  • Call sites: InstanceAccessControlHandler, BackButton, InstanceListBuilder, ViewsManagementController, ConfirmViewsBuilderDeleteForm, StateButtons, EntityViewDisplayTrait.

API changes

Four methods removed from DisplayBuildableInterface, one added as an instance method. Follows the same de-static work done for collectDisplays(), collectDisplaysBound() and collectInstances() in #3615031.

Comments

mogtofu33 created an issue. See original summary.

pdureau’s picture

They exist because nothing can answer "which plugin owns this instance ID", so every caller walks the plugin definitions and pokes a class string⋅

Indeed, and another reason of their introduction was a little "mistake" during the early days of the development: instead of considering Instance entity ID as an opaque string, we have put meaning into it, and we rely on this meaning in DisplayBuildableInterface::checkInstanceId(), ::getDisplayUrlFromInstanceId(), ::getUrlFromInstanceId().

It is not necessary anymore since the introduction of this field in Instance entity:

    $fields['buildable'] = BaseFieldDefinition::create('plugin')
      ->setSetting('plugin_manager_id', 'plugin.manager.display_buildable')
      ->setRequired(TRUE)
      ->setReadOnly(TRUE);

We can load the buildable directly now. Let's consider this Instance enttiy ID string opaque, as it must be.

pdureau’s picture

This task was also in the scope of #3573905: Replace DisplayBuildableInterface::checkAccess() by AccessibleInterface::access() but this specific part has not been started yet, so we are not overlapping.

mogtofu33’s picture

Assigned: mogtofu33 » Unassigned
Status: Needs work » Active
mogtofu33’s picture

mogtofu33’s picture