In order to better define what it means to be a views handler, we can stop using the generic @Plugin in favor of a specific @ViewsHandler.

Handlers are pretty straightforward, and actually don't need anything other than their ID.

This will also let us document the annotation keys better (even more important for non-handlers, I'll open that issue tomorrow).

Now that services are in YAML, we can individually swap out each handler type as we go. I've converted relationships, since there are so few of them.

This is mostly @msonnabaum's idea, but I happen to agree with him.

This will also prevent people from tacking on arbitrary data to the annotation.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dawehner’s picture

One problem I do have with this is the fact, that a random developer can no longer apply exactly what he has learned so far on plugins,
and write @Plugin etc. Does this mean that each plugin type has it's own class here?

What would happen if they actually want to add additional metadata. For example :

 * @Plugin(
 *   id = "date_fulldate",
 *   arg_format = "Ymd",
 *   format = "F j, Y",
 *   module = "views"
 * )

Would you need to specify a new annotation class, or use @Plugin() again?

If we think this is a good idea I think we should name it ViewsPlugin() because the main reason why people get confused about handlers in the firstplace is that we call them different. If people understand the plugins concept, having another name feels really counterproductive.

dawehner’s picture

Handlers are pretty straightforward, and actually don't need anything other than their ID.

Handlers are plugins, that's it. Noone should stop you from using additional metadata, if you think it's a good idea.

tim.plunkett’s picture

Views is the owner of the API, and as the consumer should define up front what metadata is appropriate for each plugin type. Any of that information is not metadata, and is only useful with an instantiated object.

And there is still an important distinction between a handler and a plugin (in the views sense), even the base class points this out.

dawehner’s picture

Views is the owner of the API, and as the consumer should define up front what metadata is appropriate for each plugin type. Any of that information is not metadata, and is only useful with an instantiated object.

Good point, so I will open a follow up to get this cleaned up now.

And there is still an important distinction between a handler and a plugin (in the views sense), even the base class points this out.

Please let avoid that different naming in the first place. A dev don't need the name "handler" to know. Filter is just another plugin type provided by views.

I guess with moving to yml files we don't need this anyway.

tim.plunkett’s picture

FileSize
44.44 KB
45.42 KB

Yeah, we're not switching this to YAML.

I figured out how to remove the "id=" bit, this is much nicer.

Left to do are arguments and fields. There are 33 argument handlers and 70 field handlers... So I'll wait for another review first :)

Only non-handlers need other metadata, so this enforces that it only has an ID.

chx’s picture

  /**
   * The plugin ID.
   *
   * @var string
   */
  public $value;

we definitely need no stinkin' comments on why do we store the ID in $value. No.

Status: Needs review » Needs work

The last submitted patch, vdc-1965164-5.patch, failed testing.

tim.plunkett’s picture

Status: Needs work » Needs review
FileSize
45.07 KB
49.56 KB

Okay, after further discussion, we realized that an annotation that only has a plugin ID is generically useful.

So I've moved it to Component, as PluginID. When the namespaces fix went in for managers, we no longer needed the 'module' key, so those that use just id and module can switch to this as well.

Converted Join, argument will have to wait on #1965842: Move date argument annotations to properties

I added a comment per chx's request.

damiankloip’s picture

@tim, I was going to ask about the module key. What issue was that?

xjm’s picture

tim.plunkett’s picture

It was #1836008: Remove drupal_classloader() use in Drupal\Core\AnnotatedClassDiscovery. Those were added in to work around simpletest loading all namespaces, and plugin discovery using the global namespace list

dawehner’s picture

+++ b/core/modules/user/lib/Drupal/user/Plugin/views/filter/Roles.phpundefined
@@ -15,10 +15,7 @@
- * @Plugin(
- *   id = "user_roles",
- *   module = "user"
- * )
+ * @PluginID("user_roles")

I'm wondering whether we should still have the module information somewhere stored. I guess some layer could add them in later.

+++ b/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.phpundefined
@@ -0,0 +1,58 @@
+    $annotation_namespaces = array(
+      'Drupal\views\Annotation' => DRUPAL_ROOT . '/core/modules/views/lib',
+    );

Now that we have the @PluginID one, can't we now inherit from the Core/ one?, as we don't need the constructor anymore? I don't see an advantage to not reuse the other one.

+++ b/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.phpundefined
@@ -0,0 +1,58 @@
+    array_walk($definitions, function (&$definition, $key, $type) {
...
+    }, $this->type);

Can't we just use function (&$definition, $key) use ($type)?

+++ b/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.phpundefined
@@ -0,0 +1,58 @@
+      $definition['plugin_type'] = $type;

Can't we still add this as default value on the manager?

+++ b/core/modules/views/lib/Drupal/views/Plugin/ViewsHandlerManager.phpundefined
@@ -0,0 +1,35 @@
+    $this->discovery = new ViewsHandlerDiscovery($type, $namespaces);
+    $this->discovery = new CacheDecorator($this->discovery, "views:$type", 'views_info');
+
+    $this->factory = new DefaultFactory($this->discovery);

I think, that we can't know whether someone wants to use the alter decorator, etc., which then at the end of the day would all fallback to use just the ViewsPluginManager as it is.

xjm’s picture

Status: Needs review » Needs work

The last submitted patch, vdc-1965164-7.patch, failed testing.

damiankloip’s picture

Nice. I still like the idea of us storing the plugin module.

tim.plunkett’s picture

Status: Needs work » Needs review
FileSize
826 bytes
49.55 KB

Yes, handlers don't currently need to know about the module. If they do, we should bake that into the Discovery class, not force plugin implementors to specify it.

We can't use the core one, since we have to set Drupal\Component\Annotation\PluginID as the $pluginDefinitionAnnotationName (see the Drupal\Component\Plugin\Discovery\AnnotatedClassDiscovery::__construct()

array_walk specifically has a third param, and I don't think you can do use ($this->type) with the property.

I've moved plugin_type here, since it skips the entire layer of ProcessDecorator, call_user_func_array(), and NestedArray::mergeDeep().

The alter decorator isn't needed for handlers, since only the ID is checked. hook_views_data()/hook_views_data_alter() is where that should take place.

Fixed the $annotation_namespaces.

msonnabaum’s picture

I like @PluginID ok. A single annotation is nicer than a hash when possible.

Patch looks pretty good, although I think the array_walk is not necessary. It's less readable than foreach in this context since you have to pass around the reference.

One thing I wanted to address:

One problem I do have with this is the fact, that a random developer can no longer apply exactly what he has learned so far on plugins,
and write @Plugin etc. Does this mean that each plugin type has it's own class here?

For me, this is the goal. Developers should know that Entity types require an annotation and Views handlers require an annotation, but it's not necessary to know that they are using the Plugin system. Plugins are very difficult to understand in the abstract, so I think the best possible DX we can offer is to treat them like an implementation detail.

Status: Needs review » Needs work

The last submitted patch, vdc-1965164-16.patch, failed testing.

tim.plunkett’s picture

Status: Needs work » Needs review
FileSize
49.54 KB
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/join/Subquery.php b/core/modules/views/lib/Drupal/views/Plugin/views/join/Subquery.php
index 5faa8dc..1249f94 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/join/Subquery.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/join/Subquery.php
@@ -17,7 +17,7 @@
  *   same as Join class above, except:
  *   - left_query: The subquery to use in the left side of the join clause.
  *
- * @PluginID"subquery")
+ * @PluginID("subquery")
  */
 class Subquery extends JoinPluginBase {
 
diff --git a/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.php b/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.php
index 619acf8..fd8a45a 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.php
@@ -49,9 +49,9 @@ function __construct($type, array $root_namespaces = array()) {
   public function getDefinitions() {
     // Add the plugin_type to the definition.
     $definitions = parent::getDefinitions();
-    array_walk($definitions, function (&$definition, $key, $type) {
-      $definition['plugin_type'] = $type;
-    }, $this->type);
+    foreach ($definitions as $key => $definition) {
+      $definitions[$key]['plugin_type'] = $this->type;
+    }
     return $definitions;
   }
 
tim.plunkett’s picture

FileSize
53.05 KB
102.18 KB

Converting arguments is blocked on #1965842: Move date argument annotations to properties.
Here's fields.

dawehner’s picture

Looks fine, let's wait for arguments.

tim.plunkett’s picture

FileSize
24.45 KB
126.22 KB

Awesome, that went in.

So this is "done" now, needs some full reviews.

dawehner’s picture

If thinks this is RTBC beside this small nitpick.

+++ b/core/modules/views/lib/Drupal/views/Plugin/Discovery/ViewsHandlerDiscovery.phpundefined
@@ -0,0 +1,58 @@
+   *   (optional) Array of root paths keyed by the corresponding namespace to
+   *   look for plugin implementations, \Plugin\views\$type will be appended to
+   *   each namespace.

Defaults to array()

tim.plunkett’s picture

Okay. I've also attached a patch with all but one conversion removed, to help highlight the real changes.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Awesome!

tim.plunkett’s picture

Issue tags: +Avoid commit conflicts

This touches every views handler, is tedious, and is not easily automated. So, please don't break it.

Status: Reviewed & tested by the community » Needs work
Issue tags: -DX (Developer Experience), -Avoid commit conflicts, -VDC, -Plugin system

The last submitted patch, vdc-1965164-24.patch, failed testing.

tim.plunkett’s picture

Status: Needs work » Needs review
Issue tags: +DX (Developer Experience), +Avoid commit conflicts, +VDC, +Plugin system

#24: vdc-1965164-24.patch queued for re-testing.

tim.plunkett’s picture

Status: Needs review » Reviewed & tested by the community

Bot--

xjm’s picture

Priority: Normal » Major
alexpott’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Avoid commit conflicts

Committed ee1c53e and pushed to 8.x. Thanks!

xjm’s picture

YAY!

andypost’s picture

Please update issue summary or file change notice to how to use it now!

xjm’s picture

Title: Add dedicated annotations for Views handlers » Change notice: Add dedicated annotations for Views handlers
Priority: Major » Critical
Status: Fixed » Active
Issue tags: +Needs change record

Yeah, this actually needs both a core change notice (for the core API addition) and a views one. (The views one being added on top of the major views plugin conversion one we haven't written yet.) ;)

tim.plunkett’s picture

Title: Change notice: Add dedicated annotations for Views handlers » Add a @PluginID annotation for plugins that only need an ID, like Views handlers
Priority: Critical » Major
Status: Active » Fixed
Issue tags: -Needs change record

Expanded http://drupal.org/node/1704454 to include PluginID.

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