Newer
Older
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
* @category Piwik
* @package Piwik
*/
namespace Piwik\Plugin;
use Piwik\API\Request;
use Piwik\Common;
use Piwik\DataTable;
use Piwik\Date;
use Piwik\MetricsFormatter;
use Piwik\Period;
use Piwik\Period\Range;
use Piwik\Piwik;
use Piwik\Plugins\PrivacyManager\PrivacyManager;
use Piwik\Site;
use Piwik\View;
use Piwik\ViewDataTable\Config as VizConfig;
Thomas Steur
a validé
use Piwik\ViewDataTable\Manager as ViewDataTableManager;
Thomas Steur
a validé
use Piwik\ViewDataTable\Request as ViewDataTableRequest;
use Piwik\ViewDataTable\RequestConfig as VizRequest;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
* This class is used to load (from the API) and customize the output of a given DataTable.
* The main() method will create an object implementing ViewInterface
* You can customize the dataTable using the disable* methods.
*
* You can also customize the dataTable rendering using row metadata:
* - 'html_label_prefix': If this metadata is present on a row, it's contents will be prepended
* the label in the HTML output.
* - 'html_label_suffix': If this metadata is present on a row, it's contents will be appended
* after the label in the HTML output.
*
* Example:
* In the Controller of the plugin VisitorInterest
* <pre>
* function getNumberOfVisitsPerVisitDuration( $fetch = false)
* {
* $view = ViewDataTable::factory( 'cloud' );
* $view->init( $this->pluginName, __FUNCTION__, 'VisitorInterest.getNumberOfVisitsPerVisitDuration' );
* $view->setColumnsToDisplay( array('label','nb_visits') );
* $view->disableSort();
* $view->disableExcludeLowPopulation();
* $view->disableOffsetInformation();
*
* return $this->renderView($view, $fetch);
* }
* </pre>
*
* @see factory() for all the available output (cloud tags, html table, pie chart, vertical bar chart)
* @package Piwik
* @subpackage ViewDataTable
*
* @api
*/
abstract class ViewDataTable implements ViewInterface
Thomas Steur
a validé
const ID = '';
/**
* DataTable loaded from the API for this ViewDataTable.
*
* @var DataTable
*/
protected $dataTable = null;
/**
*/
public $requestConfig;
/**
*/
protected $request;
/**
* Default constructor.
*/
Thomas Steur
a validé
public function __construct($controllerAction, $apiMethodToRequestDataTable)
list($controllerName, $controllerAction) = explode('.', $controllerAction);
Thomas Steur
a validé
$this->requestConfig = static::getDefaultRequestConfig();
$this->config = static::getDefaultConfig();
$this->config->subtable_controller_action = $controllerAction;
$this->config->setController($controllerName, $controllerAction);
Thomas Steur
a validé
$this->request = new ViewDataTableRequest($this->requestConfig);
$this->requestConfig->idSubtable = Common::getRequestVar('idSubtable', false, 'int');
$this->config->self_url = Request::getBaseReportUrl($controllerName, $controllerAction);
$this->requestConfig->apiMethodToRequestDataTable = $apiMethodToRequestDataTable;
Thomas Steur
a validé
/**
* This event is triggered to gather the report display properties for each available report. If you define
* your own report, you want to subscribe to this event to define how your report shall be displayed in the
* Piwik UI.
*
* public function configureViewDataTable(ViewDataTable $view)
* {
* switch ($view->requestConfig->apiMethodToRequestDataTable) {
* case 'VisitTime.getVisitInformationPerServerTime':
* $view->config->enable_sort = true;
* $view->requestConfig->filter_limit = 10;
* break;
* }
* }
*/
Piwik::postEvent('ViewDataTable.configure', array($this));
$this->config->show_footer_icons = (false == $this->requestConfig->idSubtable);
// the exclude low population threshold value is sometimes obtained by requesting data.
// to avoid issuing unecessary requests when display properties are determined by metadata,
// we allow it to be a closure.
if (isset($this->requestConfig->filter_excludelowpop_value)
&& $this->requestConfig->filter_excludelowpop_value instanceof \Closure
) {
$function = $this->requestConfig->filter_excludelowpop_value;
$this->requestConfig->filter_excludelowpop_value = $function();
}
$this->overrideViewPropertiesWithQueryParams();
}
Thomas Steur
a validé
public static function getDefaultConfig()
Thomas Steur
a validé
return new VizConfig();
}
Thomas Steur
a validé
public static function getDefaultRequestConfig()
Thomas Steur
a validé
{
return new VizRequest();
protected function loadDataTableFromAPI()
{
if (!is_null($this->dataTable)) {
// data table is already there
// this happens when setDataTable has been used
return $this->dataTable;
}
Thomas Steur
a validé
$this->dataTable = $this->request->loadDataTableFromAPI();
return $this->dataTable;
}
/**
* Returns the viewDataTable ID for this DataTable visualization. Derived classes
* should declare a const ID field with the viewDataTable ID.
*
Thomas Steur
a validé
* @throws \Exception
Thomas Steur
a validé
$id = static::ID;
if (empty($id)) {
$message = sprintf('ViewDataTable %s does not define an ID. Set the ID constant to fix this issue', get_called_class());
throw new \Exception($message);
Thomas Steur
a validé
return $id;
Thomas Steur
a validé
public function isViewDataTableId($viewDataTableId)
$myIds = ViewDataTableManager::getIdsWithInheritance(get_called_class());
Thomas Steur
a validé
return in_array($viewDataTableId, $myIds);
/**
* Returns the DataTable loaded from the API
*
* @return DataTable
* @throws \Exception if not yet defined
*/
public function getDataTable()
{
if (is_null($this->dataTable)) {
throw new \Exception("The DataTable object has not yet been created");
}
Thomas Steur
a validé
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
return $this->dataTable;
}
/**
* To prevent calling an API multiple times, the DataTable can be set directly.
* It won't be loaded again from the API in this case
*
* @param $dataTable
* @return void $dataTable DataTable
*/
public function setDataTable($dataTable)
{
$this->dataTable = $dataTable;
}
/**
* Checks that the API returned a normal DataTable (as opposed to DataTable\Map)
* @throws \Exception
* @return void
*/
protected function checkStandardDataTable()
{
Piwik::checkObjectTypeIs($this->dataTable, array('\Piwik\DataTable'));
}
/**
* Convenience function. Calls main() & renders the view that gets built.
*
* @return string The result of rendering.
*/
public function render()
{
$view = $this->buildView();
return $view->render();
}
protected function getDefaultFooterIconsToShow()
Thomas Steur
a validé
ViewDataTableManager::configureFooterIcons($result, $this);
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
/**
* This event is called when determining the default set of footer icons to display
* below a report.
*
* Plugins can use this event to modify the default set of footer icons. You can
* add new icons or remove existing ones.
*
* $result must have the following format:
*
* ```
* array(
* array( // footer icon group 1
* 'class' => 'footerIconGroup1CssClass',
* 'buttons' => array(
* 'id' => 'myid',
* 'title' => 'My Tooltip',
* 'icon' => 'path/to/my/icon.png'
* )
* ),
* array( // footer icon group 2
* 'class' => 'footerIconGroup2CssClass',
* 'buttons' => array(...)
* ),
* ...
* )
* ```
*/
Piwik::postEvent('ViewDataTable.configureFooterIcons', array(&$result, $viewDataTable = $this));
{
return 'dataTableViz' . Piwik::getUnnamespacedClassName(get_class($this));
}
/**
* Returns the list of view properties that can be overriden by query parameters.
*
* @return array
*/
return array_merge($this->config->overridableProperties, $this->requestConfig->overridableProperties);
}
private function overrideViewPropertiesWithQueryParams()
{
$properties = $this->getOverridableProperties();
Thomas Steur
a validé
foreach ($properties as $name) {
if (property_exists($this->requestConfig, $name)) {
$this->requestConfig->name = $this->getPropertyFromQueryParam($name, $this->requestConfig->$name);
} elseif (property_exists($this->config, $name)) {
$this->config->name = $this->getPropertyFromQueryParam($name, $this->config->$name);
}
}
// handle special 'columns' query parameter
$columns = Common::getRequestVar('columns', false);
Thomas Steur
a validé
if (false !== $columns) {
$this->config->columns_to_display = Piwik::getArrayFromApiParameter($columns);
array_unshift($this->config->columns_to_display, 'label');
}
}
protected function getPropertyFromQueryParam($name, $defaultValue)
{
$type = is_numeric($defaultValue) ? 'int' : null;
return Common::getRequestVar($name, $defaultValue, $type);
}
public function isRequestingSingleDataTable()
{
$requestArray = $this->request->getRequestArray() + $_GET + $_POST;
$date = Common::getRequestVar('date', null, 'string', $requestArray);
$period = Common::getRequestVar('period', null, 'string', $requestArray);
$idSite = Common::getRequestVar('idSite', null, 'string', $requestArray);
if (Period::isMultiplePeriod($date, $period)
|| strpos($idSite, ',') !== false
|| $idSite == 'all'
) {
return false;
}
return true;
}