Skip to content

Plugin Development Part 6 Dispatcher and Routing

MK edited this page Dec 8, 2015 · 3 revisions

Part 6 Dispatcher and Routing

In Part 3 we were talking about dispatching and routing. OSTicket has pretty decent routing functionality that is undocumented and is located in class.dispatch.php. This function populates a collection of URLs and their patterns and stuffs them into dispatcher.

Dispatching allows to route all URLs directed to our plugin through our controllers. This way we don't need to copy any files to the OSTicket core directories. This functionality makes plugins very powerful and easy to maintain.

This function is activated in response to the app.scp callback, an event that is called when our app is activated:

Signal::connect ( 'apps.scp', array (
    'EquipmentPlugin',
    'callbackDispatch'
));

The callback looks like this:

static public function callbackDispatch($object, $data) {
    $search_url = url ( '^/equipment.*search', 
        patterns ( 'controller\EquipmentItem', 
            url_post ( '^.*', 'searchAction' )
        )
    );

    $categories_url = url ( '^/equipment.*categories/', 
        patterns ( 'controller\EquipmentCategory', 
            url_get ( '^list$', 'listAction' ), 
            url_get ( '^listJson$', 'listJsonAction' ), 
            url_get ( '^listJsonTree$', 'listJsonTreeAction' ), 
            url_get ( '^view/(?P<id>\d+)$', 'viewAction' ), 
            url_get ( '^openTicketsJson/(?P<item_id>\d+)$', 'openTicketsJsonAction' ), 
            url_get ( '^closedTicketsJson/(?P<item_id>\d+)$', 'closedTicketsJsonAction' ), 
            url_get ( '^getItemsJson/(?P<category_id>\d+)$', 'categoryItemsJsonAction' ), 
            url_post ( '^save', 'saveAction' ), 
            url_post ( '^delete', 'deleteAction' )
        )
    );

...     

    $media_url = url ( '^/equipment.*assets/', 
        patterns ( 'controller\MediaController', 
            url_get ( '^(?P<url>.*)$', 'defaultAction' )
        )
    );

    $object->append ( $search_url );
    $object->append ( $media_url );
...
    $object->append ( $categories_url );
...
}

The url function takes two arguments:

  • base URL pattern
  • list of patterns that will follow that URL

In turn the list of patterns can be as long as you want:

  • First item is your class, in this case it is controller\EquipmentCategory
  • The following items are various URL patterns and functions that will be called in response to this URL
url ( '^/equipment.*categories/',  //Base URL
    patterns ( 'controller\EquipmentCategory', //URL handling class
        url_get ( '^list$', 'listAction' ),  //GET request, the example URL for this to trigger would be .../equipment_categories/list
        url_get ( '^listJson$', 'listJsonAction' ), 
        url_get ( '^listJsonTree$', 'listJsonTreeAction' ), 
        url_get ( '^view/(?P<id>\d+)$', 'viewAction' ), //This one specifies an argument, one digit in this case
        url_get ( '^openTicketsJson/(?P<item_id>\d+)$', 'openTicketsJsonAction' ), 
        url_get ( '^closedTicketsJson/(?P<item_id>\d+)$', 'closedTicketsJsonAction' ), 
        url_get ( '^getItemsJson/(?P<category_id>\d+)$', 'categoryItemsJsonAction' ), 
        url_post ( '^save', 'saveAction' ), //this is a POST request, no arguments.
        url_post ( '^delete', 'deleteAction' )
    )
);

You can build all kinds of URLs using regular expression patterns.

Once you built your URL object you can add it to dispatcher:

$object->append ( $search_url );
$object->append ( $media_url );

The dispatcher will evaluate them from top to bottom. The first match will be executed and rest will be ignored.

$media_url = url ( '^/equipment.*assets/', 
    patterns ( 'controller\MediaController', 
        url_get ( '^(?P<url>.*)$', 'defaultAction' )
    )
);

This one is used to fetch JavaScript files, CSS and images from our plugin directory. This is how the controller handles these types of requests:

public function defaultAction($request_path) {

    $file = EQUIPMENT_ASSETS_DIR . $request_path;

    if (file_exists($file)) {

        if ($this->endsWith($file, '.js')) {
            header('Content-type: text/javascript');
        } else if ($this->endsWith($file, '.css')) {
            header('Content-type: text/css');
        } else if ($this->endsWith($file, '.png')) {
            header('Content-type: image/png');
        }
        echo file_get_contents($file);
    } else {
        echo 'File does not exist';
    }
}

Once you finish populating URLs, you can make calls to your plugin pages like so: http://[OSTicketWebRoot]/scp/dispatcher.php/my_plugin/my_controller/arguments


Part 1 Getting Started

Part 2 Configuration Page

Part 3 Plugin Class

Part 4 Staff Panel Links

Part 5 Signals

Part 6 Dispatcher and Routing