Plugin Hooks ============ Add new API methods ------------------- Kanboard uses this library `JSON-RPC `__ to handle API calls. To add a new method, you can do something like this from your plugin: .. code:: php $this->api->getProcedureHandler()->withCallback('my_method', function() { return 'foobar'; }); ``$this->container['api']`` or ``$this->api`` expose an instance of the object ``JsonRPC\Server``. Read the library documentation for more information. Add new console commands ------------------------ Kanboard uses the library `Symfony Console `__ to handle local command lines. Kanboard exposes an instance of the object ``Symfony\Component\Console\Application`` via ``$this->cli``. You can add new commands from your plugin: .. code:: php $this->cli->add(new MyCommand()); Read the library documentation for more information. Add new task filters -------------------- Since the task lexer is a factory that returns a new instance each time, you have to extend the ``taskLexer`` container with the method ``extend()`` of Pimple. Here is an example: .. code:: php public function initialize() { $this->container->extend('taskLexer', function($taskLexer, $c) { $taskLexer->withFilter(TaskBoardDateFilter::getInstance($c)->setDateParser($c['dateParser'])); return $taskLexer; }); } For the filter class implementation, there are several examples in the source code under the namespace ``Kanboard\Filter``. Application Hooks ----------------- Hooks can extend, replace, filter data or change the default behavior. Each hook is identified with a unique name, example: ``controller:calendar:user:events`` Listen on hook events ~~~~~~~~~~~~~~~~~~~~~ In your ``initialize()`` method you need to call the method ``on()`` of the class ``Kanboard\Core\Plugin\Hook``: .. code:: php $this->hook->on('hook_name', $callable); The first argument is the name of the hook and the second is a PHP callable. Hooks executed only once ~~~~~~~~~~~~~~~~~~~~~~~~ Some hooks can have only one listener: ``model:subtask-time-tracking:calculate:time-spent`` - Override time spent calculation when sub-task timer is stopped - Arguments: - ``$user_id`` (integer) - ``$start`` (DateTime) - ``$end`` (DateTime) Merge hooks ----------- “Merge hooks” act in the same way as the function ``array_merge``. The hook callback must return an array. This array will be merged with the default one. Example to add events in the user calendar: .. code:: php class Plugin extends Base { public function initialize() { $container = $this->container; $this->hook->on('controller:calendar:user:events', function($user_id, $start, $end) use ($container) { $model = new SubtaskForecast($container); return $model->getCalendarEvents($user_id, $end); // Return new events }); } } Example to override default values for task forms: .. code:: php class Plugin extends Base { public function initialize() { $this->hook->on('controller:task:form:default', function (array $default_values) { return empty($default_values['score']) ? array('score' => 4) : array(); }); } } List of merging hooks: ``controller:task:form:default`` - Override default values for task forms - Arguments: - ``$default_values``: actual default values (array) ``controller:calendar:project:events`` - Add more events to the project calendar - Arguments: - ``$project_id`` (integer) - ``$start`` Calendar start date (string, ISO-8601 format) - ``$end`` Calendar end date (string, ISO-8601 format) ``controller:calendar:user:events`` - Add more events to the user calendar - Arguments: - ``$user_id`` (integer) - ``$start`` Calendar start date (string, ISO-8601 format) - ``$end`` Calendar end date (string, ISO-8601 format) Asset Hooks ----------- Asset hooks can be used to add a new stylesheet easily or a new JavaScript file in the layout. You can use this feature to create a theme and override all Kanboard default styles. Example to add a new stylesheet: .. code:: php hook->on('template:layout:css', array('template' => 'plugins/Css/skin.css')); } } List of asset Hooks: - ``template:layout:css`` - ``template:layout:js`` Reference hooks --------------- Reference hooks are passing a variable by reference. Example: .. code:: php $this->hook->on('formatter:board:query', function (\PicoDb\Table &$query) { $query->eq(TaskModel::TABLE.'color_id', 'red'); }); The code above will show only tasks in red on the board. List of reference hooks: +----------------------------------------+---------------------------------------------------------------+ | Hook | Description | +========================================+===============================================================+ | ``formatter:board:query`` | Alter database query before rendering board | +----------------------------------------+---------------------------------------------------------------+ | ``pagination:dashboard:project:query`` | Alter database query for projects pagination on the dashboard | +----------------------------------------+---------------------------------------------------------------+ | ``pagination:dashboard:task:query`` | Alter database query for tasks pagination on the dashboard | +----------------------------------------+---------------------------------------------------------------+ | ``pagination:dashboard:subtask:query`` | Alter database query for subtasks pagination on the dashboard | +----------------------------------------+---------------------------------------------------------------+ | ``model:task:creation:prepare`` | Alter form values before to save a task | +----------------------------------------+---------------------------------------------------------------+ | ``model:task:creation:aftersave`` | Retrieve Task ID after creating a task | +----------------------------------------+---------------------------------------------------------------+ | ``model:task:modification:prepare`` | Alter form values before to edit a task | +----------------------------------------+---------------------------------------------------------------+ | ``model:task:duplication:aftersave`` | After task duplication | +----------------------------------------+---------------------------------------------------------------+ | ``model:color:get-list`` | Alter default_colors values | +----------------------------------------+---------------------------------------------------------------+ | ``model:subtask:modification:prepare`` | Alter form values before to save a subtask | +----------------------------------------+---------------------------------------------------------------+ | ``model:subtask:creation:prepare`` | Alter form values before to edit a subtask | +----------------------------------------+---------------------------------------------------------------+ | ``model:subtask:count:query`` | Alter database query for subtask count | +----------------------------------------+---------------------------------------------------------------+ Template Hooks -------------- Template hooks allow additional content in existing templates. Example to add new content in the dashboard sidebar: .. code:: php $this->template->hook->attach('template:dashboard:sidebar', 'myplugin:dashboard/sidebar'); Example to attach a template with local variables: .. code:: php $this->template->hook->attach('template:dashboard:sidebar', 'myplugin:dashboard/sidebar', [ 'variable' => 'foobar', ]); Example to attach a template with a callable: .. code:: php $this->template->hook->attachCallable('template:dashboard:sidebar', 'myplugin:dashboard/sidebar', function($hook_param1, $hook_param2) { return ['new_template_variable' => 'foobar']; // Inject a new variable into the plugin template }); This call is usually defined in the ``initialize()`` method. The first argument is the name of the hook and the second argument is the template name. Template names prefixed with the plugin name and colon indicate the location of the template. Example with ``myplugin:dashboard/sidebar``: - ``myplugin`` is the name of your plugin (lowercase) - ``dashboard/sidebar`` is the template name - On the filesystem, the plugin will be located here: ``plugins\Myplugin\Template\dashboard\sidebar.php`` - Templates are written in pure PHP (don’t forget to escape data) Template names without prefix are core templates. List of template hooks: +-------------------------------------------------------------------+---------------------------------------+ | Hook | Description | +===================================================================+=======================================+ | ``template:analytic:sidebar`` | Sidebar on analytic pages | +-------------------------------------------------------------------+---------------------------------------+ | ``template:app:filters-helper:before`` | Filter helper dropdown (top) | +-------------------------------------------------------------------+---------------------------------------+ | ``template:app:filters-helper:after`` | Filter helper dropdown (bottom) | +-------------------------------------------------------------------+---------------------------------------+ | ``template:auth:login-form:before`` | Login page (top) | +-------------------------------------------------------------------+---------------------------------------+ | ``template:auth:login-form:after`` | Login page (bottom) | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:private:task:before-title`` | Task in private board: before | | | title | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:private:task:after-title`` | Task in private board: after | | | title | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:public:task:before-title`` | Task in public board: before | | | title | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:public:task:after-title`` | Task in public board: after | | | title | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:task:footer`` | Task in board: footer | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:task:icons`` | Task in board: tooltip icon | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:table:column:before-header-row`` | Row before board column header | | | | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:table:column:after-header-row`` | Row after board column header | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:column:dropdown`` | Dropdown menu in board columns | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:column:header`` | Board column header | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:tooltip:subtasks:header:before-assignee`` | Header of Subtask table on | | | tootip before Assignee | +-------------------------------------------------------------------+---------------------------------------+ | ``template:board:tooltip:subtasks:rows`` | Column on row of Subtask table | | | on tooltip | +-------------------------------------------------------------------+---------------------------------------+ | ``template:config:sidebar`` | Sidebar on settings page | +-------------------------------------------------------------------+---------------------------------------+ | ``template:config:application`` | Application settings form | +-------------------------------------------------------------------+---------------------------------------+ | ``template:config:board`` | Board settings form | +-------------------------------------------------------------------+---------------------------------------+ | ``template:config:email`` | Email settings page | +-------------------------------------------------------------------+---------------------------------------+ | ``template:config:integrations`` | Integration page in global | | | settings | +-------------------------------------------------------------------+---------------------------------------+ | ``template:dashboard:show`` | Main page of the dashboard | +-------------------------------------------------------------------+---------------------------------------+ | ``template:dashboard:page-header:menu`` | Dashboard submenu | +-------------------------------------------------------------------+---------------------------------------+ | ``template:dashboard:project:after-title`` | Dashboard project after title | +-------------------------------------------------------------------+---------------------------------------+ | ``template:dashboard:project:before-title`` | Dashboard project before title | +-------------------------------------------------------------------+---------------------------------------+ | ``template:dashboard:show:after-filter-box`` | Dashboard after filter box | +-------------------------------------------------------------------+---------------------------------------+ | ``template:dashboard:show:before-filter-box`` | Dashboard before filter box | +-------------------------------------------------------------------+---------------------------------------+ | ``template:dashboard:task:footer`` | Task in dashboard: footer | +-------------------------------------------------------------------+---------------------------------------+ | ``template:dashboard:sidebar`` | Dashboard sidebar | +-------------------------------------------------------------------+---------------------------------------+ | ``template:export:header`` | Export header | +-------------------------------------------------------------------+---------------------------------------+ | ``template:header:dropdown`` | Page header dropdown menu | | | (user avatar icon) | +-------------------------------------------------------------------+---------------------------------------+ | ``template:header:creation-dropdown`` | Page header dropdown menu | | | (plus icon) | +-------------------------------------------------------------------+---------------------------------------+ | ``template:layout:head`` | Page layout ```` tag | +-------------------------------------------------------------------+---------------------------------------+ | ``template:layout:top`` | Page layout top header | +-------------------------------------------------------------------+---------------------------------------+ | ``template:layout:bottom`` | Page layout footer | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project:dropdown`` | “Actions” menu on left in | | | different project views | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project:header:before`` | Project filters (before) | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project:header:after`` | Project filters (after) | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project:integrations`` | Integration page in projects | | | settings | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project:sidebar`` | Sidebar in project settings | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project-user:sidebar`` | Sidebar on project user | | | overview page | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project-list:menu:before`` | Project list: before menu | | | entries | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project-list:menu:after`` | Project list: after menu | | | entries | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project-overview:before-description`` | Project overview: before | | | description | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project-overview:images:dropdown`` | Project overview: image dropdown | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project-permission:after-adduser`` | Project permission: after user | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project-header:view-switcher`` | Project view switcher | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project-header:view-switcher-before-project-overview`` | Project view switcher before overview | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project-header:view-switcher-before-board-view`` | Project view switcher before board | +-------------------------------------------------------------------+---------------------------------------+ | ``template:project-header:view-switcher-before-task-list`` | Project view switcher before list | +-------------------------------------------------------------------+---------------------------------------+ | ``template:search:task:footer`` | Task in results: footer | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:layout:top`` | Task layout top (after page | | | header) | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:details:top`` | Task summary top | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:details:bottom`` | Task summary bottom | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:details:first-column`` | Task summary first column | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:details:second-column`` | Task summary second column | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:details:third-column`` | Task summary third column | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:details:fourth-column`` | Task summary fourth column | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:dropdown:before-actions`` | Task dropdown: top of menu | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:dropdown:after-basic-actions`` | Task dropdown: after "add subtask" | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:dropdown:after-add-links`` | Task dropdown: after "add ext. link" | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:dropdown:after-add-comment`` | Task dropdown: after "add comment" | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:dropdown:after-add-attachments`` | Task dropdown: after "add screenshot" | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:dropdown:after-duplicate-task`` | Task dropdown: after "duplicate to .."| +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:dropdown:after-send-mail`` | Task dropdown: after "send by mail" | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:dropdown`` | Task dropdown: bottom of menu | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:sidebar:information`` | Task sidebar: [section] information | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:sidebar:before-actions`` | Task sidebar: [section] actions: top | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:sidebar:after-basic-actions`` | ... as above: after "add subtask" | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:sidebar:after-add-links`` | ... as above: after "add ext. link" | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:sidebar:after-add-comment`` | ... as above: after "add comment" | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:sidebar:after-add-attachments`` | ... as above: after "add screenshot" | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:sidebar:after-duplicate-task`` | ... as above: after "duplicate to .." | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:sidebar:after-send-mail`` | ... as above: after "send by mail" | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:sidebar:actions`` | ... as above: bottom | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task-file:images:dropdown`` | Task image attachment dropdown | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task-file:images:before-thumbnail-description`` | Task image attachment desciption | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:form:first-column`` | 1st column in task form | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:form:second-column`` | 2nd column in task form | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:form:third-column`` | 3nd column in task form | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:form:bottom-before-buttons`` | before form submit/cancel buttons | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:show:top`` | Show task page: top | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:show:bottom`` | Show task page: bottom | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:show:before-description`` | Show task page: before | | | description | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:show:before-tasklinks`` | Show task page: before | | | tasklinks | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:show:before-subtasks`` | Show task page: before | | | subtasks | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:show:before-external-links`` | Show task page: before | | | external links | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:show:before-internal-links`` | Show task page: before | | | internal links | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:show:before-timetracking`` | Show task page: before | | | timetracking | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:show:before-attachments`` | Show task page: before | | | attachments | +-------------------------------------------------------------------+---------------------------------------+ | ``template:task:show:before-comments`` | Show task page: before | | | comments | +-------------------------------------------------------------------+---------------------------------------+ | ``template:subtask:form:create`` | Create Subtask form | +-------------------------------------------------------------------+---------------------------------------+ | ``template:subtask:form:edit`` | Edit Subtask form | +-------------------------------------------------------------------+---------------------------------------+ | ``template:subtask:table:header:before-timetracking`` | Subtask table header before | | | Time Tracking | +-------------------------------------------------------------------+---------------------------------------+ | ``template:subtask:table:rows`` | Column on row of subtasks | | | table | +-------------------------------------------------------------------+---------------------------------------+ | ``template:user:authentication:form`` | “Edit authentication” form in | | | user profile | +-------------------------------------------------------------------+---------------------------------------+ | ``template:user:create-remote:form`` | “Create remote user” form | +-------------------------------------------------------------------+---------------------------------------+ | ``template:user:external`` | “External authentication” page | | | in user profile | +-------------------------------------------------------------------+---------------------------------------+ | ``template:user:integrations`` | Integration page in user | | | profile | +-------------------------------------------------------------------+---------------------------------------+ | ``template:user:sidebar:actions`` | Sidebar in user profile | | | (section actions) | +-------------------------------------------------------------------+---------------------------------------+ | ``template:user:sidebar:information`` | Sidebar in user profile | | | (section information) | +-------------------------------------------------------------------+---------------------------------------+ | ``template:user:show:profile:info`` | User profile information | +-------------------------------------------------------------------+---------------------------------------+