Freelinking ver. 3 uses a plugin system to enhance the freelinking syntax and enable different kinds of links. Plugins can be simple URL constructors, or can use more sophisticated methods and have complete control over the link and target text. The output of plugins can also be customized through various hooks and theme functions for better integration with other modules and site design.

Having a small set of generally useful “easy-linking” plugins bundled with the project is only the first step Freelinking takes to help authors create links. Freelinking also has a framework that help developers quickly create new “easy-linking” plugins for custom websites.

Plugins can be created in two different ways. The recommended method is to create a new module, as a submodule of freelinking. However, you may also create a plugin as an include file.

Submodule

By packaging your plugin as a module, you may distribute it as a project through Drupal.org, make use of other modules with proper tracking of requirements, and make use of any Drupal hook functions without worrying about collisions with Freelinking's own behavior.

If you publish your submodule on Drupal.org, post a message in the Freelinking issue queue, calling attention to your project so it can be linked to from Freelinking's project page.

A submodule can create a plugin for Freelinking by implementing hook_freelinking() to return the definition of your plugin as an element of an array, like so:

function mymodule_freelinking() {
  $freelinking['myplugin'] => array(
    'indicator' => '/myplugin/',
    'translate' => array(' ' => '_'),
    'replacement' => 'http://example.com/node/%1',
  );
  return $freelinking;
}

Include file

To create a simple freelinking plugin, just drop a “.inc” file in the plugins/ directory under Freelinking. By convention, these should be named “freelinking_plugin.inc”, where “plugin” is the name of the plugin.

Each file should at least define one indicator, where the long version of the indicator is identical to the name of the plugin. However, it is possible to define multiple plugin indicators per file to denote slightly changed semantics. See for example freelinking_wiki.inc for an example of this.

The only difference in structure between an include file and a submodule is the lack of a hook_freelinking() function wrapper around the freelinking array that defines your plugin. In an include file, the example above would simple be:

$freelinking['myplugin'] => array(
  'indicator' => '/myplugin/',
  'translate' => array(' ' => '_'),
  'replacement' => 'http://example.com/node/%1',
);

This functionality primarily exists for the ease of packaging default plugins with the Freelinking module, and to allow developers to add custom plugins to their site without going to the trouble of wrapping it in a module.

However, if you create a format you think others may want to use, please create a new issue (“Contributed plugin …”) and upload the plugin code to the Freelinking issue queue. If it passes community review, it will be included as a plugin with the next release of Freelinking.

The $freelinking array

The plugin's element in the $freelinking array is named after the plugin. In the example above of a plugin called “myplugin”, the element your plugin would add to the array would be $freelinking['myplugin']. Your element defines an array, with the following elements:

So, a simple freelinking plugin only needs to include this array. Here's an entire plugin one might see in a very simple .inc file to link to a wiki page and some specific site:

$freelinking['myplugin'] => array(
  'indicator' => '/my(plugin)/',
  'translate' => array(' ' => '-'),
  'replacement' => 'http://example.org/wiki/%1',
  'tip' => t('Click to visit a wiki page at example.org.'),
);

The plugins in freelinking_wiki.inc are examples of this type of plugin.

More complex plugins

The callback element of your $freelinking['plugin'] array can define a PHP function that will be used to create the link. This function will get the target value for the link, and is expected to return a link. Freelinking will make the substition based on the return value of this function.

By default, the target value passed to the callback function looks like this:

array(
  'target' => target,
  'dest' => target,
);

However, if the text uses the vertical bar (“|”) to separate the elements, it more elements is added to the array. This is the expanded usage:

array(
  'target' => target match,
  'dest' => destination,
  'text' => anchor link text,
  'tooltip' => tool tip (title attribute),
  'other' => array(miscellaneous arguments),
);

The syntax is:

[[indicator:target|title|tooltip|arg1|arg2|…]]

Most of the plugins that ship with freelinking use the callback. You may want to look at them to learn from example.

Failover

Your plugin callback may specify a “failover” or fallback action in the event they choke. For example: If the specified node title cannot be found in the database, a link to create a node with that title can be put in place as a failover fallback action.

Plugins specify failover by returning;

array(
  'plugin' => 'failover plugin'
);

When lookup fails or access is denied. the failover plugin is triggered to take over trying to process the target. You can pass a modified target in this way by just adding 'target' => $target to the return array. You may also specify:

array(
  'error' => 'error message'
);

to provide an error message.

You can use variable_get('freelinking_pluginname_failover', '…') to get the preferred failover for your plugin. This is based on the failover element in the plugin definition or on creating a form element by that name in your settings.

Settings

If your plugin will require some settings, they can be defined in a “freelinking_plugin_settings” function in your include file, or explicitly using the settings element of the plugin's freelinking array (necessary for modules). This function should return a Drupal FormAPI array of the various settings your plugin will need. The module will add these form controls to the project' settings page. Your plugin can use these settings in the $freelinking array, or the callback function, as necessary.

A simple example of how to use settings is part of the wiki plugins (freelinking_wiki.inc). It uses one setting to control the language code that the URL to Wikipedia should use. The setting is used in the $freelinking['wikipedia']['replacement'] element, using the language code as part of the URL.

The freelinking_nodetitle.inc plugin also uses the settings array. This plugin has settings to control what happens when a link cannot be found, and is able to restrict the lookup of content to certain content types. This is an example of using settings within the callback function.

The freelinking API

The Freelinking API allows you to customize freelinking plugins you create specfically for your site.

For API functions and examples of their use, see freelinking.api.php. They are also suumarized below:

hook_freelink_alter()

By implementing this function, you can adjust the elements of the link array before it is rendered into an HTML link. For example:

function mymodule_freelink_alter(&$link, $target, $plugin_name, $plugin) {
  static $count;
  $link[2]['attributes']['name'] = 'freelink-' . $count++;
}

This function will alter every link created by freelinking to insert the number of links found in the filtered text as an anchor. You might also make a more targeted alteration:

function mymodule_freelink_alter(&$link, $target, $plugin_name, $plugin) {
  if ($plugin_name == 'google') {
    $link[2]['attributes']['title'] .= ' Isn't Google nifty?';
  }
}

For documentation on the structure of the $link array here, read up on the API entry for the l() function.

Theme functions

theme('freelink', $plugin, $link);

This is the function that renders the $link array we “altered” above into HTML. You can override this, like any theme function.

theme('freelink_error', $plugin, $message);

This function renders an error message provided by a plugin for display in the page.