Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 216 additions & 0 deletions docs/components/reports.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,220 @@
Reports
#######
To add and render custom Reports in Mautic, your Plugin needs to listen to three events:

- ``\Mautic\ReportBundle\ReportEvents::REPORT_ON_BUILD``
- ``ReportEvents::REPORT_ON_GENERATE``
- ``ReportEvents::REPORT_ON_GRAPH_GENERATE``

This guide walks you through defining a custom Report, generating Report data, and rendering graphs.

.. vale off
Defining the Report
-------------------
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix your headings throughout the whole doc.

H1 ###
H2 ***
H3 ===
H4 ---
H5 ~~~
H6 ^^^


.. vale on
Use the ``ReportEvents::REPORT_ON_BUILD`` event to define:

- The Report context
- Available columns
- Available filters - defaults to columns
- Available graphs

Column definition
-----------------

Each column array can include the following properties:

.. vale on

.. list-table::
:header-rows: 1

* - Key
- Required?
- Type
- Description
* - ``label``
- REQUIRED
- string
- The language string for the column.
* - type
- REQUIRED
- string
- Column type.
* - alias
- OPTIONAL
- string
- An alias for the returned value. Useful in conjunction with ``formula``.
* - formula
- OPTIONAL
- string
- SQL formula instead of a column. for example. ``SUBSTRING_INDEX(e.type, \'.\', 1)``.
* - link
- OPTIONAL
- string
- Route name to convert the value into a hyperlink. Used usually with an ID of an Entity. The route must accept ``objectAction`` and ``objectId`` parameters.

.. vale off
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not use vale off. This has hidden some problems with the grammar. Remove them everywhere except where I've suggested to use, and we'll tell you where you can use them if needed.


Filter Definition
-----------------

.. vale on
Filters are optional. If you don't define them, the system defaults to using the column definitions. However, filters can provide additional options such as dropdown select lists.

Additional filter keys include:

.. list-table::
:header-rows: 1

* - Key
- Required?
- Type
- Description
* - list
- OPTIONAL
- array
- Used when ``type`` is select for a filter. Provides the dropdown options for a select input. Format should be ``value => label``.
* - operators
- OPTIONAL
- array
- Custom list of operators to allow for this filter. See ``Mautic\ReportBundle\Builder\MauticReportBuilder::OPERATORS`` for a examples.

.. vale off

Generate the QueryBuilder
---------------------------

The system dispatches the ``ReportEvents::REPORT_ON_GENERATE`` event when it needs to generate and display a report. In this function, the plugin defines the QueryBuilder object used to generate the table data.
Call ``$event->checkContext()`` to determine if the requested report is the subscriber's report.

Use Doctrine’s DBAL layer QueryBuilder for the ``ReportEvents::REPORT_ON_GENERATE`` event by obtaining it with ``$qb = $event->getQueryBuilder();``.
There are a number of helper functions to append joins for commonly used relationships such as category, leads, ip address, etc. Refer to the ``ReportGeneratorEvent`` class for more details.

Generating Graphs
-----------------

Use the ``ReportEvents::REPORT_ON_GRAPH_GENERATE`` event to render graphs for your report.

- Check the report context with ``$event->checkContext()``.
- Clone the base ``QueryBuilder`` to manipulate queries safely.
- Use classes like ``LineChart`` and ``ChartQuery`` to generate and render graph data.

For supported chart types and options, refer to the ``ChartQuery`` and ``LineChart`` helper classes in the Mautic codebase.

Example: HelloWorld Report Subscriber
-------------------------------------

Below is an example Plugin file located at::

plugins\HelloWorldBundle\EventListener\ReportSubscriber.php

This file subscribes to Report events and provides custom logic for adding new tables, columns, filters, and graphs.

.. code-block:: php

namespace MauticPlugin\HelloWorldBundle\EventListener;

use Mautic\CoreBundle\EventListener\CommonSubscriber;
use Mautic\CoreBundle\Helper\GraphHelper;
use Mautic\ReportBundle\Event\ReportBuilderEvent;
use Mautic\ReportBundle\Event\ReportGeneratorEvent;
use Mautic\ReportBundle\Event\ReportGraphEvent;
use Mautic\ReportBundle\ReportEvents;
use Mautic\CoreBundle\Helper\Chart\ChartQuery;
use Mautic\CoreBundle\Helper\Chart\LineChart;

class ReportSubscriber extends CommonSubscriber
{
public static function getSubscribedEvents()
{
return [
ReportEvents::REPORT_ON_BUILD => ['onReportBuilder', 0],
ReportEvents::REPORT_ON_GENERATE => ['onReportGenerate', 0],
ReportEvents::REPORT_ON_GRAPH_GENERATE => ['onReportGraphGenerate', 0],
];
}

public function onReportBuilder(ReportBuilderEvent $event)
{
if ($event->checkContext(['worlds'])) {
$prefix = 'w.';
$columns = [
$prefix . 'visit_count' => [
'label' => 'mautic.hellobundle.report.visit_count',
'type' => 'int',
],
$prefix . 'world' => [
'label' => 'mautic.hellobundle.report.world',
'type' => 'text',
],
];

$columns = $filters = array_merge(
$columns,
$event->getStandardColumns($prefix),
$event->getCategoryColumns()
);

$filters[$prefix . 'world']['type'] = 'select';
$filters[$prefix . 'world']['list'] = [
'earth' => 'Earth',
'mars' => 'Mars',
];

$event->addTable('worlds', [
'display_name' => 'mautic.helloworld.worlds',
'columns' => $columns,
'filters' => $filters,
]);

$event->addGraph('worlds', 'line', 'mautic.hellobundle.graph.line.visits');
}
}

public function onReportGenerate(ReportGeneratorEvent $event)
{
$context = $event->getContext();
if ($context == 'worlds') {
$qb = $event->getQueryBuilder();
$qb->from(MAUTIC_TABLE_PREFIX . 'worlds', 'w');
$event->addCategoryLeftJoin($qb, 'w');
$event->setQueryBuilder($qb);
}
}

public function onReportGraphGenerate(ReportGraphEvent $event)
{
if (!$event->checkContext('worlds')) {
return;
}

$graphs = $event->getRequestedGraphs();
$qb = $event->getQueryBuilder();

foreach ($graphs as $graph) {
$queryBuilder = clone $qb;
$options = $event->getOptions($graph);
$chartQuery = clone $options['chartQuery'];
$chartQuery->applyDateFilters($queryBuilder, 'date_added', 'v');

switch ($graph) {
case 'mautic.hellobundle.graph.line.visits':
$chart = new LineChart(null, $options['dateFrom'], $options['dateTo']);
$chartQuery->modifyTimeDataQuery($queryBuilder, 'date_added', 'v');
$visits = $chartQuery->loadAndBuildTimeData($queryBuilder);
$chart->setDataset(
$options['translator']->trans('mautic.hellobundle.graph.line.visits'),
$visits
);
$data = $chart->render();
$data['name'] = $graph;
$data['iconClass'] = 'fa-tachometer';
$event->setGraph($graph, $data);
break;
}
}
}
}

1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ There are several ways to support Mautic other than contributing with code.
rest_api/point_groups
rest_api/reports
rest_api/text_messages
rest_api/stages

.. toctree::
:maxdepth: 2
Expand Down
Loading
Loading