Convert D7 input filter into D8 plugin for Graph API

Trivial Graph Format for Graph API
G FilterTrivialGraphFormat FilterTrivialGraphFormat @Filter @Filter FilterTrivialGraphFormat->@Filter FilterBase FilterBase FilterTrivialGraphFormat->FilterBase FilterInterface FilterInterface PluginBase PluginBase FilterBase->PluginBase FilterBase->FilterInterface

For Graph API the Trivial Graph Format submodule introduced into 7.x-1.x needed an upgrade to Drupal 8 lingo. My initial thought was to upgrade the sub module to discover hook_filter_info was gone.

Checking the filter.api.php there is more gone then kept.

Change Records

So what to do? Check for change records! Two items for hook_filter_info currently where


Once you know it's a plugin it is almost trivial apart from the annotated part.

Being a plugin means you are building a class which resides into sites/all/graphapi/lib/Drupal/graphapi/ directory tree somewhere. (Note this is PSR-0 tree and probably will change into PSR-4 tree. See PSR-4: Putting it all together)

Thanks to almaudoh's remark I learned we have an enforced directory tree.

Plugins belong to the Plugin and filter plugins in the Filter so the full path is now lib/Drupal/graphapi/Plugin/Filter.

Let's make a copy of the core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php and we have lib/Drupal/graphapi/Plugin/Filter/FilterTrivialGraphFormat.php ... almost that is as we need proper annotations.


These were defined for FilterTrivialGraphFormat like this (still buggy)

 * Provides a filter for rendering Trivial Graph Format.
 * @Filter(
 *   id = "filter_tgf",
 *   module = "graphapi",
 *   title = @Translation("Trivial Graph Format"),
 *   settings = {
 *     "formats" = "",
 *     "filter_html_help" = 1,
 *     "filter_html_nofollow" = 0
 *   },
 *   weight = -10
 * )
class FilterTrivialGraphFormat extends FilterBase {

This class documentation is trying to tell the discovery mechanism build into Drupal 8 to use the @Filter as it's annotation template.

This is as we now have learned located in core/modules/filter/lib/Drupal/filter/Annotation/Filter.php

Reading that files documentation explains the existence of all attributes as seen above apart from type.


Checking for the word type leads to Filterbase.php which has a

  public function getType() {
    return $this->pluginDefinition['type'];

Type is documented in FilterInterface. But what do these mean? And why are it's values documented that weird?

Digging further leads to WYSIWYG in core: round one — filter types

  1. FILTER_TYPE_MARKUP_LANGUAGE: The filter converts something that's not HTML to HTML in a way that is not compatible with WYSIWYG editing.
  2. FILTER_TYPE_HTML_RESTRICTOR: The filter restricts the HTML allowed, for example, to protect against XSS.
  3. FILTER_TYPE_TRANSFORM_REVERSIBLE: The filter performs a transform for which a WYSIWYG plugin exists to perform the same transformation (and its reverse) client-side. For example, may be (reversibly!) transformed to
  4. FILTER_TYPE_TRANSFORM_IRREVERSIBLE: The filter performs a transform for which a WYSIWYG plugin does not exist to perform the transformation client-side (especially, the reverse of it); instead, the WYSIWYG editor displays the unfiltered text. For example, Token Filter.

Trivial Graph Format (extended version)

The image above is generated by the following filter input

[tgf engine:graphapi_svg
FilterTrivialGraphFormat @Filter
FilterTrivialGraphFormat FilterBase
FilterBase PluginBase
FilterBase FilterInterface

Next the resulting image done by Graph API (which is data encoded) is viewed (View image)

Finally it's SVG is copied into this blog.

A shorter version would without the links looks way shorter and easier to learn.

[tgf engine:graphapi_svg
FilterTrivialGraphFormat @Filter
FilterTrivialGraphFormat FilterBase
FilterBase PluginBase
FilterBase FilterInterface

Lessons learned

  1. Check the change notice @
  2. Check the API as a whole @
  3. Search for the class name @