category |
---|
Develop |
In Part II you created a plugin that defines and displays a new report. In this guide, we'll enhance that plugin by making it configurable and internationalized. You'll learn:
- how to add settings to your plugin
- how to make your plugin available in multiple languages
Guide Assumptions
This guide assumes that you've completed Part II of this guide.
The report we've defined is interesting, but we could easily aggregate on another visit property. For example, the report could be getLastVisitsByScreenType
or getLastVisitsByCity
. In this section, we're going to make it possible for users to change what the report displays.
We'll create a plugin setting which will control which visit property the plugin uses to generate our report. For this, we need to create a Settings
class at the root of your plugin's directory:
namespace Piwik\Plugins\MyPlugin;
class Settings extends \Piwik\Plugin\Settings
{
protected function init()
{
// ...
}
}
The Settings
class is a special class that is automatically detected by Piwik. Piwik uses the information it sets to add a new section for your plugin in the Plugins > Settings admin page.
We're going to create one setting that can be set differently by each user. Our setting will determine the column of the Live.getLastVisitsDetails
that we'll aggregate by. So it's a string and has a limited number of valid values. We'll use a single select dropdown (just a normal <select>
) for it.
Let's add an attribute and new method for this setting:
class Settings extends \Piwik\Plugin\Settings
{
public $realtimeReportDimension;
protected function init()
{
$this->realtimeReportDimension = $this->createRealtimeReportDimensionSetting();
$this->addSetting($this->realtimeReportDimension);
}
private function createRealtimeReportDimensionSetting()
{
// ...
}
}
Then we'll implement the createRealtimeReportDimensionSetting()
method:
private function createRealtimeReportDimensionSetting()
{
$setting = new \Piwik\Settings\UserSetting('reportDimension', 'Report Dimension');
$setting->type = self::TYPE_STRING;
$setting->uiControlType = self::CONTROL_SINGLE_SELECT;
$setting->description = 'Choose the dimension to aggregate by';
$setting->availableValues = MyPlugin::$availableDimensionsForAggregation;
$setting->defaultValue = 'browserName';
return $setting;
}
Notice how $settings->availableValues
is set from MyPlugin::$availableDimensionsForAggregation
. The availableValues property should be set to an array mapping column values with their appropriate display text. This array will probably come in handy later so we'll put it in a static class attribute.
In your plugin class add the following code:
public static $availableDimensionsForAggregation = array(
'browserName' => 'Browser',
'visitIp' => 'IP',
'visitorId' => 'Visitor ID',
'searches' => 'Number of Site Searches',
'events' => 'Number of Events',
'actions' => 'Number of Actions',
'visitDurationPretty' => 'Visit Duration',
'country' => 'Country',
'region' => 'Region',
'city' => 'City',
'operatingSystem' => 'Operating System',
'screenType' => 'Screen Type',
'resolution' => 'Resolution'
// we could add more, but let's not waste time.
);
If you go to the Plugins > Settings admin page you should see this new setting:
To use the setting, we first need to get the setting value in our API method and then aggregate using it. Change your API method to this:
public function getLastVisitsByBrowser($idSite, $period, $date, $segment = false)
{
// get realtime visit data
$data = \Piwik\Plugins\Live\API::getInstance()->getLastVisitsDetails(
$idSite,
$period,
$date,
$segment,
$numLastVisitorsToFetch = 100,
$minTimestamp = false,
$flat = false,
$doNotFetchActions = true
);
$data->applyQueuedFilters();
// read the setting value that contains the column value to aggregate by
$settings = new Settings('MyPlugin');
$columnName = $settings->realtimeReportDimension->getValue();
// we could create a new instance by using new DataTable(),
// but we would loose DataTable metadata, which can be useful.
$result = $data->getEmptyClone($keepFilters = false);
foreach ($data->getRows() as $visitRow) {
$columnValue = $visitRow->getColumn($columnName);
$resultRow = $result->getRowFromLabel($columnValue);
// if there is no row for this browser, create it
if ($resultRow === false) {
$result->addRowFromSimpleArray(array(
'label' => $columnValue,
'nb_visits' => 1
));
} else { // if there is a row, increment the counter
$counter = $resultRow->getColumn('nb_visits');
$resultRow->setColumn('nb_visits', $counter + 1);
}
}
return $result;
}
Now we'll want to make sure the column heading in the report display has the correct text. Right now, it will display Browser no matter what the setting value is:
Change the configureView()
method in the getLastVisitsByBrowser report to the following:
public function configureView(ViewDataTable $view)
{
// The ViewDataTable must be configured so the display is perfect for the report.
// This is done by setting properties of the ViewDataTable::$config object.
$view->config->show_table_all_columns = false;
$settings = new Settings('MyPlugin');
$columnToAggregate = $settings->realtimeReportDimension->getValue();
$columnLabel = MyPlugin::$availableDimensionsForAggregation[$columnToAggregate];
$view->config->addTranslation('label', $columnLabel);
$view->config->columns_to_display = array_merge(array('label'), $this->metrics);
}
Open the report and you'll now see:
Finally, we'll rename the report. After all, it can do more than just aggregate the last 100 visits by browser now. Rename all occurences of getLastVisitsByBrowser
to getLastVisitsByDimension
. Make sure you replace it in the following files:
- API.php
- Reports/GetLastVisitsByBrowser.php (The filename has to be renamed to GetLastVisitsByDimension.php as well)
- plugin.js
The other improvement we'll make to our plugin is to use Piwik's internationalization system so our plugin can be made available in multiple languages.
Internationalization is achieved in Piwik by replacing translated text, like "Realtime Analytics"
, with unique identifiers, like "MyPlugin_RealtimeAnalytics"
called translation tokens.
Translation tokens are associated with translated text in multiple JSON files, one for each supported language. In the code, the translation tokens are converted into translated text based on the user's selected language.
To internationalize our plugin, an english language file to hold our translated text is needed. This file is already created for you by the report generator. It is located in your plugin's lang/
directory. In that folder, a file named en.json
should exist containing translations:
{
"MyPlugin": {
"LastVisitsByBrowser":"Last Visits By Browser"
}
}
We're going to move all of the translated text of our plugin into this file.
We use one piece of translated text in our report: "Real-time reports"
. First, we'll add entries for it in the en.json
file we just located. We'll use the RealtimeReports translation token:
{
"MyPlugin": {
"RealtimeReports": "Real-time reports"
}
}
Then replace the text in your report class GetLastVisitsByDimension
with the following:
$this->menuTitle = 'MyPlugin_RealtimeReports';
$this->widgetTitle = $this->menuTitle;
Let's internationalize the text we use in our Settings
class. First, we'll add entries for the text we use:
{
"MyPlugin": {
"RealtimeReports": "Real-time reports"
"ReportDimensionSettingDescription" : "Choose the dimension to aggregate by"
}
}
Then we'll use the new translation token in the createRealtimeReportDimensionSetting()
method:
$setting->description = \Piwik::translate('MyPlugin_ReportDimensionSettingDescription');
We also need to internationalize the names of each possible setting value. We'll do this by using translated text in the MyPlugin::$availableDimensionsForAggregation
static variable. Of course, we can't call Piwik::translate when setting a static field, so we'll have to add a new method that returns the array.
We're not going to add any translation tokens to en.json
this time because the translations already exist in core plugins. Replace MyPlugin::$availableDimensionsForAggregation
field with this:
public static $availableDimensionsForAggregation = array(
'browser' => 'UserSettings_ColumnBrowser',
'visitIp' => 'General_IP',
'visitorId' => 'General_VisitorID',
'searches' => 'General_NbSearches',
'events' => 'Events_NbEvents',
'actions' => 'General_NbActions',
'visitDurationPretty' => 'VisitorInterest_ColumnVisitDuration',
'country' => 'UserCountry_Country',
'region' => 'UserCountry_Region',
'city' => 'UserCountry_City',
'operatingSystem' => 'UserSettings_ColumnOperatingSystem',
'screenType' => 'UserSettings_ColumnTypeOfScreen',
'resolution' => 'UserSettings_ColumnResolution'
// we could add more, but let's not waste time.
);
Then, add this method to your plugin's plugin descriptor class:
public static function getAvailableDimensionsForAggregation()
{
return array_map(array('Piwik', 'translate'), self::$availableDimensionsForAggregation);
}
Finally in the createRealtimeReportDimensionSetting()
method, replace MyPlugin::$availableDimensionsForAggregation
by MyPlugin::getAvailableDimensionsForAggregation()
.
Since we already use translation tokens in the MyPlugin::$availableDimensionsForAggregation
field, and the column headers are set using the same data, all we have to do is use MyPlugin::getAvailableDimensionsForAggregation
in the configureView()
report method:
$columnTranslations = MyPlugin::getAvailableDimensionsForAggregation();
$columnLabel = $columnTranslations[$columnToAggregate];