Plugin weight attribute is not respected

Created on 31 January 2024, 5 months ago
Updated 3 April 2024, 3 months ago

This module has a weight field in its plugin. But then uses the default plugin manager to retrieve the plugins. The default manager does not sort by weight. Weight is currently therefore not used.

I suggest overwriting the default plugin manager implementation of the getDefinitions method.

πŸ› Bug report
Status

Active

Version

1.0

Component

Code

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @Hikkypo
  • πŸ‡³πŸ‡±Netherlands MegaChriz

    Alright. I see that the ordering of plugins currently happens in Drupal\userprotect\Plugin\UserProtection\UserProtectionPluginCollection in several methods using uasort($this->pluginInstances, [$this, 'pluginInstancesSort']);

    So the weight property is at least used there. With the suggested change, would that make the sorting in UserProtectionPluginCollection obsolete?

  • πŸ‡³πŸ‡±Netherlands MegaChriz

    Hm. Maybe the code in UserProtectionPluginCollection should stay because pluginInstancesSort() does more than just sorting by weight:

    /**
     * Sorts plugin instances based on weight, label, provider or id.
     *
     * @param \Drupal\userprotect\Plugin\UserProtection\UserProtectionInterface $a
     *   The first plugin in the comparison.
     * @param \Drupal\userprotect\Plugin\UserProtection\UserProtectionInterface $b
     *   The second plugin in the comparison.
     *
     * @return int
     *   -1 if $a should go first.
     *   1 if $b should go first.
     *   0 if it's unknown which should go first.
     */
    public function pluginInstancesSort(UserProtectionInterface $a, UserProtectionInterface $b) {
      if ($a->getWeight() != $b->getWeight()) {
        return $a->getWeight() < $b->getWeight() ? -1 : 1;
      }
      if ($a->label() != $b->label()) {
        return strnatcasecmp($a->label(), $b->label());
      }
      if ($a->provider != $b->provider) {
        return strnatcasecmp($a->provider, $b->provider);
      }
      return strnatcasecmp($a->getPluginId(), $b->getPluginId());
    }
    
  • Thanks megachriss I hadnt seem that. It seems that this sorting is however only used for the settings form. So i do still think my solution is correct. But maybe the sorting needs to be expanded to be similar to the behaviour in pluginInstanceSort. However since this current implementation requires instances it seems difficult to adopt this behaviour without a second version of it that uses the definition arrays or a new sorting function. I also question if sorting by label is relevant for general use since the weight should be the primary sorting label sorting does not seem logical for this kind of functionality except for when presenting to a user.

  • πŸ‡³πŸ‡±Netherlands MegaChriz

    Yes, sorting is only required to be able to display the protection plugins in a logical order on the settings form. I see that this mentioned in \Drupal\userprotect\Annotation\UserProtection:

    /**
     * A default weight used for presentation in the user interface only.
     *
     * @var int
     */
    public $weight = 0;
    

    I think that the order in which protections are evaluated is not relevant, so when a protection rule gets applied, the weight value doesn't contribute to the functionality.

    The weight property was added in commit 634349b7 and the commit message says "by MegaChriz: worked on user interface.".

Production build 0.69.0 2024