NewsFeaturesDownloadsDevelopmentSupportAbout Us
Filters and the Pipeline

Filters and the Pipeline

From LifeType Wiki


Contents

[edit] Introduction

The security and the pipeline framework is a concept that has been in LifeType since the 0.3 series but only in 1.0 was it made generic and possible for plugins to register new filters at run time. The idea behind the Pipeline is that any number chained filters can be attached to it. When a request is made to LifeType to carry out *any* operation, the front-controller will first feed the request into the pipeline and leave it up to the filters what to do with it. The output of the pipeline (and of every filter in particular) is a boolean value: True or False, Yes or No. If the result of processing the request through the pipeline is negative (False), the core will stop processing the request and throw an error message. If the result is positive (True) the process will continue as normal.

In order for the pipeline to return a positive result, all filters must have returned a positive result. Or in other words, if only one filter returns a negative result the process will be inmediately stopped and the error message will be generated. Therefore, the pipeline is useful for the implementation of things such as security filters, the bayesian filter, etc.

[edit] PipelineFilter, PipelineRequest and PipelineResult

PipelineFilter is the base class that all filters have to extend in order to have the same interface as the Pipeline is expecting. The main methods are PipelineFilter::PipelineFilter($pipelineRequest) and PipelineRequest::filter(). The first one only needs to be reimplemented if we're planning to do anything in the constructor. If that's not the case, implementing the second mehod is enough.

The PipelineRequest::filter() method is the main method of a filter. It should return a PipelineResult object with a positive value (see [PipelineResult]), depending on the what the filter is supposed to do and check. The most stupid filter would do nothing and always return positive result, while the nastiest filter of all would always return a negative result and no request would be further processed by the core. Hence, this is not very advisable :)

[edit] Dynamically registering a new filter

New filters can be dynamically registered by using the static method Pipeline::registerFilter($filterClass) This method takes only one parameter which is the name of the class that is going to take act as the filter. Needless to say, this class must implement the filter() method as described above. The class should have already been loaded via either include() or include_once() and the Pipeline itself will take care of dynamically creating an object of its type if necessary. Therefore, please be careful to just give the name of the class and not a reference to an object.

  include_once( "myexamplefilter.class.php" );
  ...
  Pipeline::registerFilter( "myExampleFilter" );
  ...

If registering filters from a PluginBase class, there is a commodity method called PluginBase::registerFilter($filterName) that will do exactly the same for you. If your plugin class needs to register a filter, it is advisable to do it in the constructor.

[edit] Returning results

Results are returned via a PipelineResult object. If the object is initialized via a 'false' value, we should also provide a unique error code and an error message and the meaning is that the request should be blocked. In that case, the core will display a standard ErrorView view with the message that was provided via the PipelineResult object. In case we'd like to provide our own view (since LifeType 1.1) we can use the PipelineResult::setView() method and provide our own class extendinv View or BlogView. This allows filters to provide more meaningful and less frightening messages without a big "Error" heading at the top:

$result = new PipelineResult( false, 550, "Error executing filter" );
$result->setView( new MyPluginErrorView( $this->_blogInfo ));
return( $result );

In case the result is positive, there really is no need to do anything:

$result = new PipelineResult( true );
return( $result );

[edit] Example filter

We will show an example of a filter that will inspect the request received by LifeType and if a parameter called "stopMe" is set to "1", execution will be cancelled. If not, execution of the current request will continue. For example a URL such as http://yourserver.com/index.php?op=Default&Date=200405&stopMe=1 would be blocked but one such ashttp://yourserver.com/index.php?op=ViewArticle&blogId=2&articleId=45 would not.

   include_once( PLOG_CLASS_PATH."class/security/pipelinefilter.class.php" );
 
   class SampleFilter extends PipelineFilter {
 
          function SampleFilter( $pipelineRequest )
       {
            $this->PipelineFilter( $pipelineRequest );
       }
  
       function filter()
       {
            // get the PipelineRequest object received as parameter
            $pipelineRequest = $this->getPipelineRequest();
            // get the HTTP request included in that object
            $httRequest = $pipelineRequest->getHttpRequest();
  
            // check to see if we can find out parameter
            if( $httpRequest["stopMe"] == "1" ) {
                 $result = new PipelineResult( false, 0, "You triggered the magic keyword!" );
            }
            else {
                 $result = new PipelineResult( true );
            }
   
            return $result;
       }
   }

It is as easy as it seems :) Once we have finished executing the filter() method, the Pipeline will check the resulting PipelineResult object first of all to see if the processing was successful (first parameter of the constructor was 'true', or not) If it was, processing will continue as normal.

If it wasn't, '0' will be used as the error code (error codes can be defined in the most suitable way and depend totally on the implementation) and most important is the error string that will be sent to the user.

[edit] Notes

[edit] $request in filter

The AddComment action will remove $_REQUEST["userName"] after it added comment into LifeType. It is becasue the varialbe name "userName" also used in ViewArticle action. To keep the $_REQUEST["userName"] still working after added comment, we just change the variable name to $_REQUEST["commentUserName"].

Therefore, if you want to use the userName in filter/pipeline plugins, you can use:

$request = $this->_pipelineRequest->getHttpRequest();
$userName = $request->getValue("commentUserName");

to get userName from comment form, instead of

$userName = $request->getValue("UserName");