update Piwik to version 2.16 (fixes #91)
This commit is contained in:
parent
9abe039dc8
commit
47263617c5
52 changed files with 418860 additions and 226988 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -9,12 +9,11 @@
|
|||
namespace Piwik\DataTable;
|
||||
|
||||
use Piwik\DataTable;
|
||||
use Piwik\DataTable\Row;
|
||||
|
||||
/**
|
||||
* A filter is set of logic that manipulates a DataTable. Existing filters do things like,
|
||||
*
|
||||
* - remove rows
|
||||
*
|
||||
* - add/remove rows
|
||||
* - change column values (change string to lowercase, truncate, etc.)
|
||||
* - add/remove columns or metadata (compute percentage values, add an 'icon' metadata based on the label, etc.)
|
||||
* - add/remove/edit subtable associated with rows
|
||||
|
|
@ -22,10 +21,10 @@ use Piwik\DataTable\Row;
|
|||
*
|
||||
* Filters are called with a DataTable instance and extra parameters that are specified
|
||||
* in {@link Piwik\DataTable::filter()} and {@link Piwik\DataTable::queueFilter()}.
|
||||
*
|
||||
*
|
||||
* To see examples of Filters look at the existing ones in the Piwik\DataTable\BaseFilter
|
||||
* namespace.
|
||||
*
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
abstract class BaseFilter
|
||||
|
|
@ -37,7 +36,7 @@ abstract class BaseFilter
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param DataTable $table
|
||||
*/
|
||||
public function __construct(DataTable $table)
|
||||
|
|
@ -73,8 +72,8 @@ abstract class BaseFilter
|
|||
if (!$this->enableRecursive) {
|
||||
return;
|
||||
}
|
||||
if ($row->isSubtableLoaded()) {
|
||||
$subTable = Manager::getInstance()->getTable($row->getIdSubDataTable());
|
||||
$subTable = $row->getSubtable();
|
||||
if ($subTable) {
|
||||
$this->filter($subTable);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -13,8 +13,8 @@
|
|||
*/
|
||||
namespace {
|
||||
|
||||
use Piwik\DataTable\Row\DataTableSummaryRow;
|
||||
use Piwik\DataTable\Row;
|
||||
use Piwik\DataTable\Row\DataTableSummaryRow;
|
||||
|
||||
class Piwik_DataTable_Row_DataTableSummary extends DataTableSummaryRow
|
||||
{
|
||||
|
|
@ -24,5 +24,11 @@ namespace {
|
|||
{
|
||||
}
|
||||
|
||||
}
|
||||
// only used for BC to unserialize old archived Row instances. We cannot unserialize Row directly as it implements
|
||||
// the Serializable interface and it would fail on PHP5.6+ when userializing the Row instance directly.
|
||||
class Piwik_DataTable_SerializedRow
|
||||
{
|
||||
public $c;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -9,30 +9,33 @@
|
|||
namespace Piwik\DataTable\Filter;
|
||||
|
||||
use Piwik\DataTable\BaseFilter;
|
||||
use Piwik\DataTable\Row;
|
||||
use Piwik\DataTable;
|
||||
use Piwik\Metrics;
|
||||
use Piwik\Plugin\Metric;
|
||||
use Piwik\Plugins\CoreHome\Columns\Metrics\ActionsPerVisit;
|
||||
use Piwik\Plugins\CoreHome\Columns\Metrics\AverageTimeOnSite;
|
||||
use Piwik\Plugins\CoreHome\Columns\Metrics\BounceRate;
|
||||
use Piwik\Plugins\CoreHome\Columns\Metrics\ConversionRate;
|
||||
|
||||
/**
|
||||
* Adds processed metrics columns to a {@link DataTable} using metrics that already exist.
|
||||
*
|
||||
* Columns added are:
|
||||
*
|
||||
*
|
||||
* - **conversion_rate**: percent value of `nb_visits_converted / nb_visits
|
||||
* - **nb_actions_per_visit**: `nb_actions / nb_visits`
|
||||
* - **avg_time_on_site**: in number of seconds, `round(visit_length / nb_visits)`. Not
|
||||
* pretty formatted.
|
||||
* - **bounce_rate**: percent value of `bounce_count / nb_visits`
|
||||
*
|
||||
*
|
||||
* Adding the **filter_add_columns_when_show_all_columns** query parameter to
|
||||
* an API request will trigger the execution of this Filter.
|
||||
*
|
||||
*
|
||||
* _Note: This filter must be called before {@link ReplaceColumnNames} is called._
|
||||
*
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
*
|
||||
* $dataTable->filter('AddColumnsProcessedMetrics');
|
||||
*
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class AddColumnsProcessedMetrics extends BaseFilter
|
||||
|
|
@ -43,7 +46,7 @@ class AddColumnsProcessedMetrics extends BaseFilter
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param DataTable $table The table to eventually filter.
|
||||
* @param bool $deleteRowsWithNoVisit Whether to delete rows with no visits or not.
|
||||
*/
|
||||
|
|
@ -61,89 +64,32 @@ class AddColumnsProcessedMetrics extends BaseFilter
|
|||
*/
|
||||
public function filter($table)
|
||||
{
|
||||
$rowsIdToDelete = array();
|
||||
if ($this->deleteRowsWithNoVisit) {
|
||||
$this->deleteRowsWithNoVisit($table);
|
||||
}
|
||||
|
||||
$extraProcessedMetrics = $table->getMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME);
|
||||
|
||||
$extraProcessedMetrics[] = new ConversionRate();
|
||||
$extraProcessedMetrics[] = new ActionsPerVisit();
|
||||
$extraProcessedMetrics[] = new AverageTimeOnSite();
|
||||
$extraProcessedMetrics[] = new BounceRate();
|
||||
|
||||
$table->setMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME, $extraProcessedMetrics);
|
||||
}
|
||||
|
||||
private function deleteRowsWithNoVisit(DataTable $table)
|
||||
{
|
||||
foreach ($table->getRows() as $key => $row) {
|
||||
$nbVisits = $this->getColumn($row, Metrics::INDEX_NB_VISITS);
|
||||
$nbActions = $this->getColumn($row, Metrics::INDEX_NB_ACTIONS);
|
||||
$nbVisits = Metric::getMetric($row, 'nb_visits');
|
||||
$nbActions = Metric::getMetric($row, 'nb_actions');
|
||||
|
||||
if ($nbVisits == 0
|
||||
&& $nbActions == 0
|
||||
&& $this->deleteRowsWithNoVisit
|
||||
) {
|
||||
// case of keyword/website/campaign with a conversion for this day,
|
||||
// but no visit, we don't show it
|
||||
$rowsIdToDelete[] = $key;
|
||||
continue;
|
||||
// case of keyword/website/campaign with a conversion for this day, but no visit, we don't show it
|
||||
$table->deleteRow($key);
|
||||
}
|
||||
|
||||
$nbVisitsConverted = (int)$this->getColumn($row, Metrics::INDEX_NB_VISITS_CONVERTED);
|
||||
if ($nbVisitsConverted > 0) {
|
||||
$conversionRate = round(100 * $nbVisitsConverted / $nbVisits, $this->roundPrecision);
|
||||
try {
|
||||
$row->addColumn('conversion_rate', $conversionRate . "%");
|
||||
} catch (\Exception $e) {
|
||||
// conversion_rate can be defined upstream apparently? FIXME
|
||||
}
|
||||
}
|
||||
|
||||
if ($nbVisits == 0) {
|
||||
$actionsPerVisit = $averageTimeOnSite = $bounceRate = $this->invalidDivision;
|
||||
} else {
|
||||
// nb_actions / nb_visits => Actions/visit
|
||||
// sum_visit_length / nb_visits => Avg. Time on Site
|
||||
// bounce_count / nb_visits => Bounce Rate
|
||||
$actionsPerVisit = round($nbActions / $nbVisits, $this->roundPrecision);
|
||||
$visitLength = $this->getColumn($row, Metrics::INDEX_SUM_VISIT_LENGTH);
|
||||
$averageTimeOnSite = round($visitLength / $nbVisits, $rounding = 0);
|
||||
$bounceRate = round(100 * $this->getColumn($row, Metrics::INDEX_BOUNCE_COUNT) / $nbVisits, $this->roundPrecision);
|
||||
}
|
||||
try {
|
||||
$row->addColumn('nb_actions_per_visit', $actionsPerVisit);
|
||||
$row->addColumn('avg_time_on_site', $averageTimeOnSite);
|
||||
// It could be useful for API users to have raw sum length value.
|
||||
//$row->addMetadata('sum_visit_length', $visitLength);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
try {
|
||||
$row->addColumn('bounce_rate', $bounceRate . "%");
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
$this->filterSubTable($row);
|
||||
}
|
||||
$table->deleteRows($rowsIdToDelete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns column from a given row.
|
||||
* Will work with 2 types of datatable
|
||||
* - raw datatables coming from the archive DB, which columns are int indexed
|
||||
* - datatables processed resulting of API calls, which columns have human readable english names
|
||||
*
|
||||
* @param Row|array $row
|
||||
* @param int $columnIdRaw see consts in Archive::
|
||||
* @param bool|array $mappingIdToName
|
||||
* @return mixed Value of column, false if not found
|
||||
*/
|
||||
protected function getColumn($row, $columnIdRaw, $mappingIdToName = false)
|
||||
{
|
||||
if (empty($mappingIdToName)) {
|
||||
$mappingIdToName = Metrics::$mappingFromIdToName;
|
||||
}
|
||||
$columnIdReadable = $mappingIdToName[$columnIdRaw];
|
||||
if ($row instanceof Row) {
|
||||
$raw = $row->getColumn($columnIdRaw);
|
||||
if ($raw !== false) {
|
||||
return $raw;
|
||||
}
|
||||
return $row->getColumn($columnIdReadable);
|
||||
}
|
||||
if (isset($row[$columnIdRaw])) {
|
||||
return $row[$columnIdRaw];
|
||||
}
|
||||
if (isset($row[$columnIdReadable])) {
|
||||
return $row[$columnIdReadable];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -8,16 +8,23 @@
|
|||
*/
|
||||
namespace Piwik\DataTable\Filter;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Archive\DataTableFactory;
|
||||
use Piwik\DataTable;
|
||||
use Piwik\Metrics;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Tracker\GoalManager;
|
||||
use Piwik\Plugin\Metric;
|
||||
use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\AverageOrderRevenue;
|
||||
use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\ConversionRate;
|
||||
use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\Conversions;
|
||||
use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\ItemsCount;
|
||||
use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\Revenue;
|
||||
use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\RevenuePerVisit as GoalSpecificRevenuePerVisit;
|
||||
use Piwik\Plugins\Goals\Columns\Metrics\RevenuePerVisit;
|
||||
|
||||
/**
|
||||
* Adds goal related metrics to a {@link DataTable} using metrics that already exist.
|
||||
*
|
||||
* Metrics added are:
|
||||
*
|
||||
* - **revenue_per_visit**: total goal and ecommerce revenue / nb_visits
|
||||
* - **goal_%idGoal%_conversion_rate**: the conversion rate. There will be one of
|
||||
* these columns for each goal that exists
|
||||
|
|
@ -36,17 +43,17 @@ use Piwik\Tracker\GoalManager;
|
|||
* reports.
|
||||
* - **goal_%idGoal%_items**: number of items. Only for ecommerce order and abandoned cart
|
||||
* reports.
|
||||
*
|
||||
*
|
||||
* Adding the **filter_update_columns_when_show_all_goals** query parameter to
|
||||
* an API request will trigger the execution of this Filter.
|
||||
*
|
||||
*
|
||||
* _Note: This filter must be called before {@link ReplaceColumnNames} is called._
|
||||
*
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
*
|
||||
* $dataTable->filter('AddColumnsProcessedMetricsGoal',
|
||||
* array($enable = true, $idGoal = Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER));
|
||||
*
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class AddColumnsProcessedMetricsGoal extends AddColumnsProcessedMetrics
|
||||
|
|
@ -68,7 +75,7 @@ class AddColumnsProcessedMetricsGoal extends AddColumnsProcessedMetrics
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param DataTable $table The table that will eventually filtered.
|
||||
* @param bool $enable Always set to true.
|
||||
* @param string $processOnlyIdGoal Defines what metrics to add (don't process metrics when you don't display them).
|
||||
|
|
@ -76,13 +83,14 @@ class AddColumnsProcessedMetricsGoal extends AddColumnsProcessedMetrics
|
|||
* If self::GOALS_OVERVIEW, only the main goal metrics will be added.
|
||||
* If an int > 0, then will process only metrics for this specific Goal.
|
||||
*/
|
||||
public function __construct($table, $enable = true, $processOnlyIdGoal)
|
||||
public function __construct($table, $enable = true, $processOnlyIdGoal, $goalsToProcess = null)
|
||||
{
|
||||
$this->processOnlyIdGoal = $processOnlyIdGoal;
|
||||
$this->isEcommerce = $this->processOnlyIdGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER || $this->processOnlyIdGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART;
|
||||
parent::__construct($table);
|
||||
// Ensure that all rows with no visit but conversions will be displayed
|
||||
$this->deleteRowsWithNoVisit = false;
|
||||
$this->goalsToProcess = $goalsToProcess;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -95,132 +103,63 @@ class AddColumnsProcessedMetricsGoal extends AddColumnsProcessedMetrics
|
|||
{
|
||||
// Add standard processed metrics
|
||||
parent::filter($table);
|
||||
$roundingPrecision = GoalManager::REVENUE_PRECISION;
|
||||
$expectedColumns = array();
|
||||
foreach ($table->getRows() as $key => $row) {
|
||||
$currentColumns = $row->getColumns();
|
||||
$newColumns = array();
|
||||
|
||||
// visits could be undefined when there is a conversion but no visit
|
||||
$nbVisits = (int)$this->getColumn($row, Metrics::INDEX_NB_VISITS);
|
||||
$conversions = (int)$this->getColumn($row, Metrics::INDEX_NB_CONVERSIONS);
|
||||
$goals = $this->getColumn($currentColumns, Metrics::INDEX_GOALS);
|
||||
if ($goals) {
|
||||
$revenue = 0;
|
||||
foreach ($goals as $goalId => $goalMetrics) {
|
||||
if ($goalId == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART) {
|
||||
continue;
|
||||
}
|
||||
if ($goalId >= GoalManager::IDGOAL_ORDER
|
||||
|| $goalId == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER
|
||||
) {
|
||||
$revenue += (int)$this->getColumn($goalMetrics, Metrics::INDEX_GOAL_REVENUE, Metrics::$mappingFromIdToNameGoal);
|
||||
}
|
||||
}
|
||||
$goals = $this->getGoalsInTable($table);
|
||||
if (!empty($this->goalsToProcess)) {
|
||||
$goals = array_unique(array_merge($goals, $this->goalsToProcess));
|
||||
sort($goals);
|
||||
}
|
||||
|
||||
if ($revenue == 0) {
|
||||
$revenue = (int)$this->getColumn($currentColumns, Metrics::INDEX_REVENUE);
|
||||
}
|
||||
if (!isset($currentColumns['revenue_per_visit'])) {
|
||||
// If no visit for this metric, but some conversions, we still want to display some kind of "revenue per visit"
|
||||
// even though it will actually be in this edge case "Revenue per conversion"
|
||||
$revenuePerVisit = $this->invalidDivision;
|
||||
if ($nbVisits > 0
|
||||
|| $conversions > 0
|
||||
) {
|
||||
$revenuePerVisit = round($revenue / ($nbVisits == 0 ? $conversions : $nbVisits), $roundingPrecision);
|
||||
}
|
||||
$newColumns['revenue_per_visit'] = $revenuePerVisit;
|
||||
}
|
||||
if ($this->processOnlyIdGoal == self::GOALS_MINIMAL_REPORT) {
|
||||
$row->addColumns($newColumns);
|
||||
$idSite = DataTableFactory::getSiteIdFromMetadata($table);
|
||||
|
||||
$extraProcessedMetrics = $table->getMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME);
|
||||
|
||||
$extraProcessedMetrics[] = new RevenuePerVisit();
|
||||
if ($this->processOnlyIdGoal != self::GOALS_MINIMAL_REPORT) {
|
||||
foreach ($goals as $idGoal) {
|
||||
if (($this->processOnlyIdGoal > self::GOALS_FULL_TABLE
|
||||
|| $this->isEcommerce)
|
||||
&& $this->processOnlyIdGoal != $idGoal
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
// Display per goal metrics
|
||||
// - conversion rate
|
||||
// - conversions
|
||||
// - revenue per visit
|
||||
foreach ($goals as $goalId => $goalMetrics) {
|
||||
$goalId = str_replace("idgoal=", "", $goalId);
|
||||
if (($this->processOnlyIdGoal > self::GOALS_FULL_TABLE
|
||||
|| $this->isEcommerce)
|
||||
&& $this->processOnlyIdGoal != $goalId
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
$conversions = (int)$this->getColumn($goalMetrics, Metrics::INDEX_GOAL_NB_CONVERSIONS, Metrics::$mappingFromIdToNameGoal);
|
||||
|
||||
// Goal Conversion rate
|
||||
$name = 'goal_' . $goalId . '_conversion_rate';
|
||||
if ($nbVisits == 0) {
|
||||
$value = $this->invalidDivision;
|
||||
} else {
|
||||
$value = round(100 * $conversions / $nbVisits, $roundingPrecision);
|
||||
}
|
||||
$newColumns[$name] = $value . "%";
|
||||
$expectedColumns[$name] = true;
|
||||
$extraProcessedMetrics[] = new ConversionRate($idSite, $idGoal); // PerGoal\ConversionRate
|
||||
|
||||
// When the table is displayed by clicking on the flag icon, we only display the columns
|
||||
// Visits, Conversions, Per goal conversion rate, Revenue
|
||||
if ($this->processOnlyIdGoal == self::GOALS_OVERVIEW) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Goal Conversions
|
||||
$name = 'goal_' . $goalId . '_nb_conversions';
|
||||
$newColumns[$name] = $conversions;
|
||||
$expectedColumns[$name] = true;
|
||||
|
||||
// Goal Revenue per visit
|
||||
$name = 'goal_' . $goalId . '_revenue_per_visit';
|
||||
// See comment above for $revenuePerVisit
|
||||
$goalRevenue = (float)$this->getColumn($goalMetrics, Metrics::INDEX_GOAL_REVENUE, Metrics::$mappingFromIdToNameGoal);
|
||||
$revenuePerVisit = round($goalRevenue / ($nbVisits == 0 ? $conversions : $nbVisits), $roundingPrecision);
|
||||
$newColumns[$name] = $revenuePerVisit;
|
||||
$expectedColumns[$name] = true;
|
||||
|
||||
// Total revenue
|
||||
$name = 'goal_' . $goalId . '_revenue';
|
||||
$newColumns[$name] = $goalRevenue;
|
||||
$expectedColumns[$name] = true;
|
||||
|
||||
if ($this->isEcommerce) {
|
||||
|
||||
// AOV Average Order Value
|
||||
$name = 'goal_' . $goalId . '_avg_order_revenue';
|
||||
$newColumns[$name] = $goalRevenue / $conversions;
|
||||
$expectedColumns[$name] = true;
|
||||
|
||||
// Items qty
|
||||
$name = 'goal_' . $goalId . '_items';
|
||||
$newColumns[$name] = $this->getColumn($goalMetrics, Metrics::INDEX_GOAL_ECOMMERCE_ITEMS, Metrics::$mappingFromIdToNameGoal);
|
||||
$expectedColumns[$name] = true;
|
||||
}
|
||||
// When the table is displayed by clicking on the flag icon, we only display the columns
|
||||
// Visits, Conversions, Per goal conversion rate, Revenue
|
||||
if ($this->processOnlyIdGoal == self::GOALS_OVERVIEW) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// conversion_rate can be defined upstream apparently? FIXME
|
||||
try {
|
||||
$row->addColumns($newColumns);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
$expectedColumns['revenue_per_visit'] = true;
|
||||
$extraProcessedMetrics[] = new Conversions($idSite, $idGoal); // PerGoal\Conversions or GoalSpecific\
|
||||
$extraProcessedMetrics[] = new GoalSpecificRevenuePerVisit($idSite, $idGoal); // PerGoal\Revenue
|
||||
$extraProcessedMetrics[] = new Revenue($idSite, $idGoal); // PerGoal\Revenue
|
||||
|
||||
// make sure all goals values are set, 0 by default
|
||||
// if no value then sorting would put at the end
|
||||
$expectedColumns = array_keys($expectedColumns);
|
||||
$rows = $table->getRows();
|
||||
foreach ($rows as &$row) {
|
||||
foreach ($expectedColumns as $name) {
|
||||
if (false === $row->getColumn($name)) {
|
||||
$value = 0;
|
||||
if (strpos($name, 'conversion_rate') !== false) {
|
||||
$value = '0%';
|
||||
}
|
||||
$row->addColumn($name, $value);
|
||||
if ($this->isEcommerce) {
|
||||
$extraProcessedMetrics[] = new AverageOrderRevenue($idSite, $idGoal);
|
||||
$extraProcessedMetrics[] = new ItemsCount($idSite, $idGoal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$table->setMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME, $extraProcessedMetrics);
|
||||
}
|
||||
|
||||
private function getGoalsInTable(DataTable $table)
|
||||
{
|
||||
$result = array();
|
||||
foreach ($table->getRows() as $row) {
|
||||
$goals = Metric::getMetric($row, 'goals');
|
||||
if (!$goals) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($goals as $goalId => $goalMetrics) {
|
||||
$goalId = str_replace("idgoal=", "", $goalId);
|
||||
$result[] = $goalId;
|
||||
}
|
||||
}
|
||||
return array_unique($result);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
99
www/analytics/core/DataTable/Filter/AddSegmentByLabel.php
Normal file
99
www/analytics/core/DataTable/Filter/AddSegmentByLabel.php
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\DataTable\Filter;
|
||||
|
||||
use Piwik\DataTable;
|
||||
use Piwik\DataTable\BaseFilter;
|
||||
use Piwik\Development;
|
||||
|
||||
/**
|
||||
* Executes a filter for each row of a {@link DataTable} and generates a segment filter for each row.
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
* $dataTable->filter('AddSegmentByLabel', array('segmentName'));
|
||||
* $dataTable->filter('AddSegmentByLabel', array(array('segmentName1', 'segment2'), ';');
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class AddSegmentByLabel extends BaseFilter
|
||||
{
|
||||
private $segments;
|
||||
private $delimiter;
|
||||
|
||||
/**
|
||||
* Generates a segment filter based on the label column and the given segment names
|
||||
*
|
||||
* @param DataTable $table
|
||||
* @param string|array $segmentOrSegments Either one segment or an array of segments.
|
||||
* If more than one segment is given a delimter has to be defined.
|
||||
* @param string $delimiter The delimiter by which the label should be splitted.
|
||||
*/
|
||||
public function __construct($table, $segmentOrSegments, $delimiter = '')
|
||||
{
|
||||
parent::__construct($table);
|
||||
|
||||
if (!is_array($segmentOrSegments)) {
|
||||
$segmentOrSegments = array($segmentOrSegments);
|
||||
}
|
||||
|
||||
$this->segments = $segmentOrSegments;
|
||||
$this->delimiter = $delimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link AddSegmentByLabel}.
|
||||
*
|
||||
* @param DataTable $table
|
||||
*/
|
||||
public function filter($table)
|
||||
{
|
||||
if (empty($this->segments)) {
|
||||
$msg = 'AddSegmentByLabel is called without having any segments defined';
|
||||
Development::error($msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (count($this->segments) === 1) {
|
||||
$segment = reset($this->segments);
|
||||
|
||||
foreach ($table->getRowsWithoutSummaryRow() as $key => $row) {
|
||||
$label = $row->getColumn('label');
|
||||
|
||||
if (!empty($label)) {
|
||||
$row->setMetadata('segment', $segment . '==' . urlencode($label));
|
||||
}
|
||||
}
|
||||
} elseif (!empty($this->delimiter)) {
|
||||
$numSegments = count($this->segments);
|
||||
$conditionAnd = ';';
|
||||
|
||||
foreach ($table->getRowsWithoutSummaryRow() as $key => $row) {
|
||||
$label = $row->getColumn('label');
|
||||
if (!empty($label)) {
|
||||
$parts = explode($this->delimiter, $label);
|
||||
|
||||
if (count($parts) === $numSegments) {
|
||||
$filter = array();
|
||||
foreach ($this->segments as $index => $segment) {
|
||||
if (!empty($segment)) {
|
||||
$filter[] = $segment . '==' . urlencode($parts[$index]);
|
||||
}
|
||||
}
|
||||
$row->setMetadata('segment', implode($conditionAnd, $filter));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$names = implode(', ', $this->segments);
|
||||
$msg = 'Multiple segments are given but no delimiter defined. Segments: ' . $names;
|
||||
Development::error($msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\DataTable\Filter;
|
||||
|
||||
use Piwik\DataTable;
|
||||
use Piwik\DataTable\BaseFilter;
|
||||
|
||||
/**
|
||||
* Executes a filter for each row of a {@link DataTable} and generates a segment filter for each row.
|
||||
* It will map the label column to a segmentValue by searching for the label in the index of the given
|
||||
* mapping array.
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
* $dataTable->filter('AddSegmentByLabelMapping', array('segmentName', array('1' => 'smartphone, '2' => 'desktop')));
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class AddSegmentByLabelMapping extends BaseFilter
|
||||
{
|
||||
private $segment;
|
||||
private $mapping;
|
||||
|
||||
/**
|
||||
* @param DataTable $table
|
||||
* @param string $segment
|
||||
* @param array $mapping
|
||||
*/
|
||||
public function __construct($table, $segment, $mapping)
|
||||
{
|
||||
parent::__construct($table);
|
||||
|
||||
$this->segment = $segment;
|
||||
$this->mapping = $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link AddSegmentByLabelMapping}.
|
||||
*
|
||||
* @param DataTable $table
|
||||
*/
|
||||
public function filter($table)
|
||||
{
|
||||
if (empty($this->segment) || empty($this->mapping)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($table->getRows() as $row) {
|
||||
$label = $row->getColumn('label');
|
||||
|
||||
if (!empty($this->mapping[$label])) {
|
||||
$label = $this->mapping[$label];
|
||||
$row->setMetadata('segment', $this->segment . '==' . urlencode($label));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\DataTable\Filter;
|
||||
|
||||
use Piwik\DataTable\BaseFilter;
|
||||
use Piwik\DataTable;
|
||||
|
||||
/**
|
||||
* Converts for each row of a {@link DataTable} a segmentValue to a segment (expression). The name of the segment
|
||||
* is automatically detected based on the given report.
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
* $dataTable->filter('AddSegmentBySegmentValue', array($reportInstance));
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class AddSegmentBySegmentValue extends BaseFilter
|
||||
{
|
||||
/**
|
||||
* @var \Piwik\Plugin\Report
|
||||
*/
|
||||
private $report;
|
||||
|
||||
/**
|
||||
* @param DataTable $table
|
||||
* @param $report
|
||||
*/
|
||||
public function __construct($table, $report)
|
||||
{
|
||||
parent::__construct($table);
|
||||
$this->report = $report;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link AddSegmentBySegmentValue}.
|
||||
*
|
||||
* @param DataTable $table
|
||||
* @return int The number of deleted rows.
|
||||
*/
|
||||
public function filter($table)
|
||||
{
|
||||
if (empty($this->report) || !$table->getRowsCount()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dimension = $this->report->getDimension();
|
||||
|
||||
if (empty($dimension)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$segments = $dimension->getSegments();
|
||||
|
||||
if (empty($segments)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var \Piwik\Plugin\Segment $segment */
|
||||
$segment = reset($segments);
|
||||
$segmentName = $segment->getSegment();
|
||||
|
||||
foreach ($table->getRows() as $row) {
|
||||
$value = $row->getMetadata('segmentValue');
|
||||
$filter = $row->getMetadata('segment');
|
||||
|
||||
if ($value !== false && $filter === false) {
|
||||
$row->setMetadata('segment', sprintf('%s==%s', $segmentName, urlencode($value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
www/analytics/core/DataTable/Filter/AddSegmentValue.php
Normal file
32
www/analytics/core/DataTable/Filter/AddSegmentValue.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\DataTable\Filter;
|
||||
|
||||
use Piwik\DataTable;
|
||||
|
||||
/**
|
||||
* Executes a filter for each row of a {@link DataTable} and generates a segment filter for each row.
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
* $dataTable->filter('AddSegmentValue', array());
|
||||
* $dataTable->filter('AddSegmentValue', array(function ($label) {
|
||||
* $transformedValue = urldecode($transformedValue);
|
||||
* return $transformedValue;
|
||||
* });
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class AddSegmentValue extends ColumnCallbackAddMetadata
|
||||
{
|
||||
public function __construct($table, $callback = null)
|
||||
{
|
||||
parent::__construct($table, 'label', 'segmentValue', $callback, null, false);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -16,12 +16,12 @@ use Piwik\DataTable\Row\DataTableSummaryRow;
|
|||
* Adds a summary row to {@link DataTable}s that contains the sum of all other table rows.
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
*
|
||||
* $dataTable->filter('AddSummaryRow');
|
||||
*
|
||||
*
|
||||
* // use a human readable label for the summary row (instead of '-1')
|
||||
* $dataTable->filter('AddSummaryRow', array($labelSummaryRow = Piwik::translate('General_Total')));
|
||||
*
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class AddSummaryRow extends BaseFilter
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -28,11 +28,11 @@ use Piwik\Piwik;
|
|||
* This filter can be extended to vary exactly how ranges are prettified based
|
||||
* on the range values found in the DataTable. To see an example of this,
|
||||
* take a look at the {@link BeautifyTimeRangeLabels} filter.
|
||||
*
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
*
|
||||
* $dataTable->queueFilter('BeautifyRangeLabels', array("1 visit", "%s visits"));
|
||||
*
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class BeautifyRangeLabels extends ColumnCallbackReplace
|
||||
|
|
@ -65,7 +65,7 @@ class BeautifyRangeLabels extends ColumnCallbackReplace
|
|||
parent::__construct($table, 'label', array($this, 'beautify'), array());
|
||||
|
||||
$this->labelSingular = $labelSingular;
|
||||
$this->labelPlural = $labelPlural;
|
||||
$this->labelPlural = $labelPlural;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -17,11 +17,11 @@ use Piwik\DataTable;
|
|||
* This filter customizes the behavior of the {@link BeautifyRangeLabels} filter
|
||||
* so range values that are less than one minute are displayed in seconds but
|
||||
* other ranges are displayed in minutes.
|
||||
*
|
||||
*
|
||||
* **Basic usage**
|
||||
*
|
||||
*
|
||||
* $dataTable->filter('BeautifyTimeRangeLabels', array("%1$s-%2$s min", "1 min", "%s min"));
|
||||
*
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class BeautifyTimeRangeLabels extends BeautifyRangeLabels
|
||||
|
|
@ -70,7 +70,7 @@ class BeautifyTimeRangeLabels extends BeautifyRangeLabels
|
|||
{
|
||||
if ($lowerBound < 60) {
|
||||
return sprintf($this->labelSecondsPlural, $lowerBound, $lowerBound);
|
||||
} else if ($lowerBound == 60) {
|
||||
} elseif ($lowerBound == 60) {
|
||||
return $this->labelSingular;
|
||||
} else {
|
||||
return sprintf($this->labelPlural, ceil($lowerBound / 60));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -8,8 +8,10 @@
|
|||
*/
|
||||
namespace Piwik\DataTable\Filter;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\DataTable;
|
||||
use Piwik\DataTable\Row;
|
||||
use Piwik\NumberFormatter;
|
||||
use Piwik\Site;
|
||||
|
||||
/**
|
||||
|
|
@ -17,15 +19,16 @@ use Piwik\Site;
|
|||
* it to each row as a percentage.
|
||||
*
|
||||
* **This filter cannot be used as an argument to {@link Piwik\DataTable::filter()}** since
|
||||
* it requires corresponding data from another DataTable. Instead,
|
||||
* it requires corresponding data from another DataTable. Instead,
|
||||
* you must manually perform a binary filter (see the **MultiSites** API for an
|
||||
* example).
|
||||
*
|
||||
* The evolution metric is calculated as:
|
||||
*
|
||||
*
|
||||
* ((currentValue - pastValue) / pastValue) * 100
|
||||
*
|
||||
* @api
|
||||
* @deprecated since v2.10.0
|
||||
*/
|
||||
class CalculateEvolutionFilter extends ColumnCallbackAddColumnPercentage
|
||||
{
|
||||
|
|
@ -100,7 +103,9 @@ class CalculateEvolutionFilter extends ColumnCallbackAddColumnPercentage
|
|||
protected function getDivisor($row)
|
||||
{
|
||||
$pastRow = $this->getPastRowFromCurrent($row);
|
||||
if (!$pastRow) return 0;
|
||||
if (!$pastRow) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $pastRow->getColumn($this->columnNameUsedAsDivisor);
|
||||
}
|
||||
|
|
@ -121,6 +126,9 @@ class CalculateEvolutionFilter extends ColumnCallbackAddColumnPercentage
|
|||
{
|
||||
$value = self::getPercentageValue($value, $divisor, $this->quotientPrecision);
|
||||
$value = self::appendPercentSign($value);
|
||||
|
||||
$value = Common::forceDotAsSeparatorForDecimalPoint($value);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
|
@ -150,9 +158,10 @@ class CalculateEvolutionFilter extends ColumnCallbackAddColumnPercentage
|
|||
{
|
||||
$number = self::getPercentageValue($currentValue - $pastValue, $pastValue, $quotientPrecision);
|
||||
if ($appendPercentSign) {
|
||||
$number = self::appendPercentSign($number);
|
||||
return NumberFormatter::getInstance()->formatPercent($number, $quotientPrecision);
|
||||
}
|
||||
return $number;
|
||||
|
||||
return NumberFormatter::getInstance()->format($number, $quotientPrecision);
|
||||
}
|
||||
|
||||
public static function appendPercentSign($number)
|
||||
|
|
@ -165,6 +174,7 @@ class CalculateEvolutionFilter extends ColumnCallbackAddColumnPercentage
|
|||
if ($number > 0) {
|
||||
$number = '+' . $number;
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -10,16 +10,17 @@ namespace Piwik\DataTable\Filter;
|
|||
|
||||
use Piwik\DataTable;
|
||||
use Piwik\DataTable\BaseFilter;
|
||||
use Piwik\Plugins\CoreHome\Columns\Metrics\CallableProcessedMetric;
|
||||
|
||||
/**
|
||||
* Adds a new column to every row of a {@link DataTable} based on the result of callback.
|
||||
*
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
*
|
||||
* $callback = function ($visits, $timeSpent) {
|
||||
* return round($timeSpent / $visits, 2);
|
||||
* };
|
||||
*
|
||||
*
|
||||
* $dataTable->filter('ColumnCallbackAddColumn', array(array('nb_visits', 'sum_time_spent'), 'avg_time_on_site', $callback));
|
||||
*
|
||||
* @api
|
||||
|
|
@ -79,17 +80,33 @@ class ColumnCallbackAddColumn extends BaseFilter
|
|||
*/
|
||||
public function filter($table)
|
||||
{
|
||||
foreach ($table->getRows() as $row) {
|
||||
$columns = $this->columns;
|
||||
$functionParams = $this->functionParameters;
|
||||
$functionToApply = $this->functionToApply;
|
||||
|
||||
$extraProcessedMetrics = $table->getMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME);
|
||||
|
||||
if (empty($extraProcessedMetrics)) {
|
||||
$extraProcessedMetrics = array();
|
||||
}
|
||||
|
||||
$metric = new CallableProcessedMetric($this->columnToAdd, function (DataTable\Row $row) use ($columns, $functionParams, $functionToApply) {
|
||||
|
||||
$columnValues = array();
|
||||
foreach ($this->columns as $column) {
|
||||
foreach ($columns as $column) {
|
||||
$columnValues[] = $row->getColumn($column);
|
||||
}
|
||||
|
||||
$parameters = array_merge($columnValues, $this->functionParameters);
|
||||
$value = call_user_func_array($this->functionToApply, $parameters);
|
||||
$parameters = array_merge($columnValues, $functionParams);
|
||||
|
||||
$row->setColumn($this->columnToAdd, $value);
|
||||
return call_user_func_array($functionToApply, $parameters);
|
||||
}, $columns);
|
||||
$extraProcessedMetrics[] = $metric;
|
||||
|
||||
$table->setMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME, $extraProcessedMetrics);
|
||||
|
||||
foreach ($table->getRows() as $row) {
|
||||
$row->setColumn($this->columnToAdd, $metric->compute($row));
|
||||
$this->filterSubTable($row);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -13,11 +13,11 @@ use Piwik\Piwik;
|
|||
/**
|
||||
* Calculates a percentage value for each row of a {@link DataTable} and adds the result
|
||||
* to each row.
|
||||
*
|
||||
*
|
||||
* See {@link ColumnCallbackAddColumnQuotient} for more information.
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
*
|
||||
* $nbVisits = // ... get the visits for a period ...
|
||||
* $dataTable->queueFilter('ColumnCallbackAddColumnPercentage', array('nb_visits', 'nb_visits_percentage', $nbVisits, 1));
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -15,14 +15,14 @@ use Piwik\DataTable\Row;
|
|||
/**
|
||||
* Calculates the quotient of two columns and adds the result as a new column
|
||||
* for each row of a DataTable.
|
||||
*
|
||||
*
|
||||
* This filter is used to calculate rate values (eg, `'bounce_rate'`), averages
|
||||
* (eg, `'avg_time_on_page'`) and other types of values.
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
*
|
||||
* $dataTable->queueFilter('ColumnCallbackAddColumnQuotient', array('bounce_rate', 'bounce_count', 'nb_visits', $precision = 2));
|
||||
*
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ColumnCallbackAddColumnQuotient extends BaseFilter
|
||||
|
|
@ -38,7 +38,7 @@ class ColumnCallbackAddColumnQuotient extends BaseFilter
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param DataTable $table The DataTable that will eventually be filtered.
|
||||
* @param string $columnNameToAdd The name of the column to add the quotient value to.
|
||||
* @param string $columnValueToRead The name of the column that holds the dividend.
|
||||
|
|
@ -75,7 +75,7 @@ class ColumnCallbackAddColumnQuotient extends BaseFilter
|
|||
*/
|
||||
public function filter($table)
|
||||
{
|
||||
foreach ($table->getRows() as $key => $row) {
|
||||
foreach ($table->getRows() as $row) {
|
||||
$value = $this->getDividend($row);
|
||||
if ($value === false && $this->shouldSkipRows) {
|
||||
continue;
|
||||
|
|
@ -109,6 +109,7 @@ class ColumnCallbackAddColumnQuotient extends BaseFilter
|
|||
if ($divisor > 0 && $value > 0) {
|
||||
$quotient = round($value / $divisor, $this->quotientPrecision);
|
||||
}
|
||||
|
||||
return $quotient;
|
||||
}
|
||||
|
||||
|
|
@ -135,7 +136,7 @@ class ColumnCallbackAddColumnQuotient extends BaseFilter
|
|||
{
|
||||
if (!is_null($this->totalValueUsedAsDivisor)) {
|
||||
return $this->totalValueUsedAsDivisor;
|
||||
} else if ($this->getDivisorFromSummaryRow) {
|
||||
} elseif ($this->getDivisorFromSummaryRow) {
|
||||
$summaryRow = $this->table->getRowFromId(DataTable::ID_SUMMARY_ROW);
|
||||
return $summaryRow->getColumn($this->columnNameUsedAsDivisor);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -14,11 +14,11 @@ use Piwik\DataTable\BaseFilter;
|
|||
/**
|
||||
* Executes a callback for each row of a {@link DataTable} and adds the result as a new
|
||||
* row metadata value.
|
||||
*
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
*
|
||||
* $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'logo', 'Piwik\Plugins\MyPlugin\getLogoFromLabel'));
|
||||
*
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ColumnCallbackAddMetadata extends BaseFilter
|
||||
|
|
@ -31,7 +31,7 @@ class ColumnCallbackAddMetadata extends BaseFilter
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param DataTable $table The DataTable instance that will be filtered.
|
||||
* @param string|array $columnsToRead The columns to read from each row and pass on to the callback.
|
||||
* @param string $metadataToAdd The name of the metadata field that will be added to each row.
|
||||
|
|
@ -48,12 +48,12 @@ class ColumnCallbackAddMetadata extends BaseFilter
|
|||
if (!is_array($columnsToRead)) {
|
||||
$columnsToRead = array($columnsToRead);
|
||||
}
|
||||
$this->columnsToRead = $columnsToRead;
|
||||
|
||||
$this->functionToApply = $functionToApply;
|
||||
$this->columnsToRead = $columnsToRead;
|
||||
$this->functionToApply = $functionToApply;
|
||||
$this->functionParameters = $functionParameters;
|
||||
$this->metadataToAdd = $metadataToAdd;
|
||||
$this->applyToSummaryRow = $applyToSummaryRow;
|
||||
$this->metadataToAdd = $metadataToAdd;
|
||||
$this->applyToSummaryRow = $applyToSummaryRow;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -63,11 +63,13 @@ class ColumnCallbackAddMetadata extends BaseFilter
|
|||
*/
|
||||
public function filter($table)
|
||||
{
|
||||
foreach ($table->getRows() as $key => $row) {
|
||||
if (!$this->applyToSummaryRow && $key == DataTable::ID_SUMMARY_ROW) {
|
||||
continue;
|
||||
}
|
||||
if ($this->applyToSummaryRow) {
|
||||
$rows = $table->getRows();
|
||||
} else {
|
||||
$rows = $table->getRowsWithoutSummaryRow();
|
||||
}
|
||||
|
||||
foreach ($rows as $key => $row) {
|
||||
$parameters = array();
|
||||
foreach ($this->columnsToRead as $columnsToRead) {
|
||||
$parameters[] = $row->getColumn($columnsToRead);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\DataTable\Filter;
|
||||
|
||||
use Piwik\DataTable;
|
||||
use Piwik\DataTable\BaseFilter;
|
||||
|
||||
/**
|
||||
* Executes a callback for each row of a {@link DataTable} and removes the defined metadata column from each row.
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
* $dataTable->filter('ColumnCallbackDeleteMetadata', array('segmentValue'));
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ColumnCallbackDeleteMetadata extends BaseFilter
|
||||
{
|
||||
private $metadataToRemove;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param DataTable $table The DataTable instance that will be filtered.
|
||||
* @param string $metadataToRemove The name of the metadata field that will be removed from each row.
|
||||
*/
|
||||
public function __construct($table, $metadataToRemove)
|
||||
{
|
||||
parent::__construct($table);
|
||||
|
||||
$this->metadataToRemove = $metadataToRemove;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link ColumnCallbackDeleteMetadata}.
|
||||
*
|
||||
* @param DataTable $table
|
||||
*/
|
||||
public function filter($table)
|
||||
{
|
||||
$this->enableRecursive(true);
|
||||
|
||||
foreach ($table->getRows() as $row) {
|
||||
$row->deleteMetadata($this->metadataToRemove);
|
||||
|
||||
$this->filterSubTable($row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -15,23 +15,22 @@ use Piwik\DataTable\BaseFilter;
|
|||
* Deletes all rows for which a callback returns true.
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
*
|
||||
* $labelsToRemove = array('label1', 'label2', 'label2');
|
||||
* $dataTable->filter('ColumnCallbackDeleteRow', array('label', function ($label) use ($labelsToRemove) {
|
||||
* return in_array($label, $labelsToRemove);
|
||||
* }));
|
||||
*
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ColumnCallbackDeleteRow extends BaseFilter
|
||||
{
|
||||
private $columnToFilter;
|
||||
private $function;
|
||||
private $functionParams;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param DataTable $table The DataTable that will be filtered eventually.
|
||||
* @param array|string $columnsToFilter The column or array of columns that should be
|
||||
* passed to the callback.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -15,9 +15,9 @@ use Piwik\DataTable\Row;
|
|||
/**
|
||||
* Replaces one or more column values in each row of a DataTable with the results
|
||||
* of a callback.
|
||||
*
|
||||
*
|
||||
* **Basic usage example**
|
||||
*
|
||||
*
|
||||
* $truncateString = function ($value, $truncateLength) {
|
||||
* if (strlen($value) > $truncateLength) {
|
||||
* return substr(0, $truncateLength);
|
||||
|
|
@ -25,10 +25,11 @@ use Piwik\DataTable\Row;
|
|||
* return $value;
|
||||
* }
|
||||
* };
|
||||
*
|
||||
*
|
||||
* // label, url and truncate_length are columns in $dataTable
|
||||
* $dataTable->filter('ColumnCallbackReplace', array('label', 'url'), $truncateString, null, array('truncate_length'));
|
||||
*
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ColumnCallbackReplace extends BaseFilter
|
||||
{
|
||||
|
|
@ -39,7 +40,7 @@ class ColumnCallbackReplace extends BaseFilter
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param DataTable $table The DataTable to filter.
|
||||
* @param array|string $columnsToFilter The columns whose values should be passed to the callback
|
||||
* and then replaced with the callback's result.
|
||||
|
|
@ -54,14 +55,14 @@ class ColumnCallbackReplace extends BaseFilter
|
|||
$extraColumnParameters = array())
|
||||
{
|
||||
parent::__construct($table);
|
||||
$this->functionToApply = $functionToApply;
|
||||
$this->functionToApply = $functionToApply;
|
||||
$this->functionParameters = $functionParameters;
|
||||
|
||||
if (!is_array($columnsToFilter)) {
|
||||
$columnsToFilter = array($columnsToFilter);
|
||||
}
|
||||
|
||||
$this->columnsToFilter = $columnsToFilter;
|
||||
$this->columnsToFilter = $columnsToFilter;
|
||||
$this->extraColumnParameters = $extraColumnParameters;
|
||||
}
|
||||
|
||||
|
|
@ -72,13 +73,14 @@ class ColumnCallbackReplace extends BaseFilter
|
|||
*/
|
||||
public function filter($table)
|
||||
{
|
||||
foreach ($table->getRows() as $key => $row) {
|
||||
foreach ($table->getRows() as $row) {
|
||||
$extraColumnParameters = array();
|
||||
foreach ($this->extraColumnParameters as $columnName) {
|
||||
$extraColumnParameters[] = $row->getColumn($columnName);
|
||||
}
|
||||
|
||||
foreach ($this->columnsToFilter as $column) {
|
||||
|
||||
// when a value is not defined, we set it to zero by default (rather than displaying '-')
|
||||
$value = $this->getElementToReplace($row, $column);
|
||||
if ($value === false) {
|
||||
|
|
@ -86,14 +88,21 @@ class ColumnCallbackReplace extends BaseFilter
|
|||
}
|
||||
|
||||
$parameters = array_merge(array($value), $extraColumnParameters);
|
||||
|
||||
if (!is_null($this->functionParameters)) {
|
||||
$parameters = array_merge($parameters, $this->functionParameters);
|
||||
}
|
||||
|
||||
$newValue = call_user_func_array($this->functionToApply, $parameters);
|
||||
$this->setElementToReplace($row, $column, $newValue);
|
||||
$this->filterSubTable($row);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array('label', $this->columnsToFilter)) {
|
||||
// we need to force rebuilding the index
|
||||
$table->setLabelsHaveChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue