Skip to content
This repository has been archived by the owner on Jun 24, 2020. It is now read-only.

Rework 'Building Filters' from 'Template System' into a tutorial #9

Open
tomjanssens opened this issue Jan 23, 2015 · 0 comments
Open
Labels
Milestone

Comments

@tomjanssens
Copy link
Member

There is a nice tutorial piece inside what @oligriffiths wrote that should go into the guides.

Storing here for now:

Building filters

A filter must implement at least 1 of 2 interfaces. These interfaces are: KTemplateFilterRead and KTemplateFilterWrite,
and correspond to enabling the filter for read and/or write mode respectively.

So, building on the example above, suppose we wanted to create a filter that would automatically create a hyperlink whenever
anybody referenced another user in their comment (twitter style).

Let's define how the filter will work:

  1. Parse all mentions using the @username syntax
  2. Usernames must be at least 3 characters long
  3. Usernames can only contain letters in lowercase and uppercase, and numbers
  4. When finding a username match from the users table, replace with a link to the users' profile

This is a fairly straight forward process:

class ComCommentsTemplateFilterMention extends KTemplateFilterAbstract implements KTemplateFilterWrite
{
/*
@param string
@return ComCommentsTemplateFilterMention
*/
public function write(&$text)
{
//Check for the username syntax
if(preg_match_all('#@[a-zA-Z0-9]{3,}#mis', $text, $matches))
{
//Loop through all the usernames
foreach($matches AS $username)
{
//Attempt to get the user
if($user = $this->getUser($username))
{
//Replace the username with a link to the users profile
$text = preg_replace('#@[a-zA-Z0-9]{3,}#mis', '<a href="'.$user->profile_url.'">'.$username.'</a>', $text);
}
}
}

return $this;
}

//Sample getUser function
protected function getUser($username)
{
//lookup user and return user object or null for no match
}
}

Simple as that!

Ok, to explain the above a bit:

  1. The class must extend the abstract filter class and implement the "write" interface as we're operating on the data in the evaluated template.
  2. Implement the write(&$text) method, this is a requirement of the write interface. $text contains the evaluated template as a string. Notice that $text$ is referenced, we'll get to that in a moment.
  3. Run a regular expression match on the evaluated template to find all @mentions
  4. Loop through each match and attempt to find a corresponding user. Note: the getUser() function is dummy and for explanatory purposes only, in the real world, this would do some kind of DB lookup.
  5. If a user is found, replace the @mention text with a hyperlink to the users profile. Note: $user->profile_url is for explanatory purposes only.
  6. As $text is referenced, meaning any changes we make to it will affect the original variable passed to this function, and any other filters for that matter.

And that's it, pop the above code in /components/com_comments/templates/filters/mention.php and you'd be good to go.

Filters advanced

Filters are stacked in a chain in the order they're added to the template. Filters also have a priority that allows you to set where in the chain the filter will be placed. By default there are 5 priorities:

  1. KCommand::PRIORITY_LOWEST
  2. KCommand::PRIORITY_LOW
  3. KCommand::PRIORITY_NORMAL
  4. KCommand::PRIORITY_HIGH
  5. KCommand::PRIORITY_HIGHEST

The number corresponds to priority value. Priorities run from lowest to highest, highest being run first, lowest being run last. The priority can be set in the _initialize() method:

class ComCommentsTemplateFilterMention extends KTemplateFilterAbstract implements KTemplateFilterWrite
{
protected function _initialize(KConfig $config)
{
$config->append(array(
'priority' => KCommand::PRIORITY_HIGH,
));

parent::_initialize($config);
}

If you need to get a reference to the template object that the filter belongs to, you can call $this->getTemplate(). This may be useful if you need to gain access to other functions in the template, the original data passed to the template, or even the view, for example to generate a url $this->getTemplate()->getView()->createRoute($url) as would be the correct way from the example above, instead of $user->profile_url. See KTemplateFilterAbstract and KTemplateAbstract for a list of all public methods.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants