Skip to content
Open
Changes from 2 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:

Check warning on line 3 in docs/components/reports.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Reports' instead of 'reports'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Reports' instead of 'reports'.", "location": {"path": "docs/components/reports.rst", "range": {"start": {"line": 3, "column": 26}}}, "severity": "INFO"}

Check warning on line 3 in docs/components/reports.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Plugin' instead of 'plugin'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Plugin' instead of 'plugin'.", "location": {"path": "docs/components/reports.rst", "range": {"start": {"line": 3, "column": 50}}}, "severity": "INFO"}

Check failure on line 3 in docs/components/reports.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Vale.Terms] Use 'Plugin' instead of 'plugin'. Raw Output: {"message": "[Vale.Terms] Use 'Plugin' instead of 'plugin'.", "location": {"path": "docs/components/reports.rst", "range": {"start": {"line": 3, "column": 50}}}, "severity": "ERROR"}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
To add and render custom reports in Mautic, your plugin needs to listen to three events:
To add and render custom Reports in Mautic, your Plugin needs to listen to three events:

Copy link
Author

Choose a reason for hiding this comment

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

Thank you, I have fixed this.


- ``\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.

Check warning on line 9 in docs/components/reports.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Report' instead of 'report'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Report' instead of 'report'.", "location": {"path": "docs/components/reports.rst", "range": {"start": {"line": 9, "column": 48}}}, "severity": "INFO"}

Check warning on line 9 in docs/components/reports.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Report' instead of 'report'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Report' instead of 'report'.", "location": {"path": "docs/components/reports.rst", "range": {"start": {"line": 9, "column": 67}}}, "severity": "INFO"}
Copy link
Member

Choose a reason for hiding this comment

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

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

Copy link
Author

Choose a reason for hiding this comment

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

Thank you for this, I have fixed this


Defining the Report

Check warning on line 11 in docs/components/reports.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Google.Headings] 'Defining the Report' should use sentence-style capitalization. Raw Output: {"message": "[Google.Headings] 'Defining the Report' should use sentence-style capitalization.", "location": {"path": "docs/components/reports.rst", "range": {"start": {"line": 11, "column": 1}}}, "severity": "WARNING"}
-------------------
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 ^^^


Use the ``ReportEvents::REPORT_ON_BUILD`` event to define:

- The report context

Check warning on line 16 in docs/components/reports.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Report' instead of 'report'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Report' instead of 'report'.", "location": {"path": "docs/components/reports.rst", "range": {"start": {"line": 16, "column": 7}}}, "severity": "INFO"}
- Available columns
- Available filters (defaults to columns)

Check warning on line 18 in docs/components/reports.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Google.Parens] Use parentheses judiciously. Raw Output: {"message": "[Google.Parens] Use parentheses judiciously.", "location": {"path": "docs/components/reports.rst", "range": {"start": {"line": 18, "column": 21}}}, "severity": "INFO"}
- Available graphs

Column Definition

Check warning on line 21 in docs/components/reports.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Google.Headings] 'Column Definition' should use sentence-style capitalization. Raw Output: {"message": "[Google.Headings] 'Column Definition' should use sentence-style capitalization.", "location": {"path": "docs/components/reports.rst", "range": {"start": {"line": 21, "column": 1}}}, "severity": "WARNING"}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Column Definition
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 conjuction with ``formula``.

Check failure on line 46 in docs/components/reports.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'conjuction'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'conjuction'?", "location": {"path": "docs/components/reports.rst", "range": {"start": {"line": 46, "column": 52}}}, "severity": "ERROR"}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
- An alias for the returned value. Useful in conjuction with ``formula``.
- An alias for the returned value. Useful in conjunction with ``formula``.

Vale picked up the typo - @OfficialJhimmy please use Vale within your editor to save reviewers having to snag these issues. Shout if you need help with setting that up, VSCode should work out of the box with Vale.

* - formula
- OPTIONAL
- string
- SQL formula instead of a column. e.g. ``SUBSTRING_INDEX(e.type, \'.\', 1)``.

Check failure on line 50 in docs/components/reports.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Google.Latin] Use 'for example' instead of 'e.g.'. Raw Output: {"message": "[Google.Latin] Use 'for example' instead of 'e.g.'.", "location": {"path": "docs/components/reports.rst", "range": {"start": {"line": 50, "column": 42}}}, "severity": "ERROR"}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
- SQL formula instead of a column. e.g. ``SUBSTRING_INDEX(e.type, \'.\', 1)``.
- 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
-----------------

Filters are optional. If not defined, Mautic will default to using the column definitions. However, filters can provide additional options such as dropdown select lists.
Copy link
Member

Choose a reason for hiding this comment

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

This will need reformatting into active voice. The vale off has hidden the error.


Additional filter keys include:

.. vale on
.. 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 ``ReportEvents::REPORT_ON_GENERATE`` event is dispatched when a report is to be generated and displayed. In this function, the plugin should define the ``QueryBuilder`` object used to generate the table data.

Use ``$event->checkContext()`` to determine if the report requested is the subscribers report.

Note that the ``ReportEvents::REPORT_ON_GENERATE`` event should use Doctrine’s DBAL layer QueryBuilder obtained via ``$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;
}
}
}
}
Loading