Controllers are the glue of the application. They collect the request data and manipulate business objects (Models) accordingly and pass results to View renderer to generate page output. The Controller creates a Response object that contains all the data that is being passed to View.
Such architecture allows to easily plug in additional filter plugins for any Action of any Controller. The plugins would simply modify the Response object to make any changes. The plugins can of course do more work than just changing the Response data - since a plugin is being run in LiveCart's context, the whole LiveCart API is available and practically everything is possible in terms of modifying or extending the application functionality.
Each plugin class must extend the abstract ControllerPlugin class. The only method that needs to be implemented is process(). The process() method would do all the actual work.
These variables are protected, so they can be accessed within the Plugin classes.
The plugin class file must have the same name as the plugin class. So, if the class name is TestPlugin, the file name would have to be TestPlugin.php
The plugins are mapped directly to controller actions, so to install a plugin, simply add the plugin class file to /plugin/controller/controllerName/action/ directory. For example, if you wanted to create a plugin to the index action of ProductController, the plugin class file would have to be added to the /plugin/controller/product/index/ directory. There can be multiple plugins assigned to the same action.
For example, you would like to integrate LiveCart with your favorite bulletin board system. Every time a user logs in her LiveCart account, you would like the user to be logged into your forum as well. This example doesn't modify the Response object, so the View is not affected. The plugin just does some task behind the scenes. Instead of integrating a 3rd party application login, it could be just about anything - your imagination is the limit, since the whole LiveCart API is accessible to your plugins.
<?php
class LoginForum extends ControllerPlugin
{
public function process()
{
// get the User that is currently logged in
if ($user = $this->controller->getUser())
{
// a pseudo-code for processing login for 3rd party application
include 'forum/api.php';
$api->loginUser($user->email->get());
}
}
}
?>
Amazon has this nice and overly useful feature of telling you that you have already purchased this product in the past when visiting a page of book, which you indeed purchased 5 years ago. Then you start digging through your bookshelves, find the book and Amazon loses a sale. OK, so you would like to have this feature in your webshop as well then.
To achieve this, we would have to create a plugin for ProductController's index action. This example is a bit more complex and uses LiveCart models to retrieve data from database as well as passes additional data with response.
<?php
class InstantOrderUpdate extends ControllerPlugin
{
public function process()
{
/*
make sure that the Controller returns an ActionResponse (instead of ActionRedirectResponse, for example)
we also need to check if the user has logged in
*/
if (($this->response instanceof ActionResponse) && ($user = SessionUser::getUser()))
{
/*
next we do not know what variables are there in the response, so most likely
you'll do a var_dump to list those variables when starting to write the code
...
var_dump($this->response->getData());
...
we find out that the product data has been put in the $product array, so...
*/
$product = $this->response->get('product');
// we'll also need to load the OrderedItem class
ClassLoader::import('application.model.order.OrderedItem');
// next we build a database query to check if the user has made an order that includes this product
$filter = new ARSelectFilter(new EqualsCond(new ARFieldHandle('OrderedItem', 'productID'),$product['ID']));
$filter->mergeCondition(new EqualsCond(new ARFieldHandle('CustomerOrder', 'userID'), $user->getID()));
// we only need to know the last order if there were several
$filter->setOrder(new ARFieldHandle('CustomerOrder', 'ID'), 'DESC');
$filter->setLimit(1);
// retrieve recordset from database
if ($order = CustomerOrder::getRecordSetArray('CustomerOrder', $filter))
{
// here we pass the order data to view
$this->response->set('instantOrderUpdate', $order[0]);
}
/*
That's it. The only thing that's left is to edit the product page template file to
add a check for the $instantOrderUpdate variable and notification message
*/
}
}
}
?>