| Server IP : 213.186.33.4 / Your IP : 216.73.216.193 Web Server : Apache System : Linux webm006.cluster103.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : awebpaca ( 35430) PHP Version : 8.5.0 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/awebpaca/piwik/core/DataTable/Filter/ |
Upload File : |
<?php
/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.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;
/**
* Filter that will remove columns from a {@link DataTable} using either a blacklist,
* allowlist or both.
*
* This filter is used to handle the **hideColumn** and **showColumn** query parameters.
*
* **Basic usage example**
*
* $columnsToRemove = array('nb_hits', 'nb_pageviews');
* $dataTable->filter('ColumnDelete', array($columnsToRemove));
*
* $columnsToKeep = array('nb_visits');
* $dataTable->filter('ColumnDelete', array(array(), $columnsToKeep));
*
* @api
*/
class ColumnDelete extends BaseFilter
{
/**
* The columns that should be removed from DataTable rows.
*
* @var array
*/
private $columnsToRemove;
/**
* The columns that should be kept in DataTable rows. All other columns will be
* removed. If a column is in $columnsToRemove and this variable, it will NOT be kept.
*
* @var array
*/
private $columnsToKeep;
/**
* Hack: when specifying "showColumns", sometimes we'd like to also keep columns that "look" like a given column,
* without manually specifying all these columns (which may not be possible if column names are generated dynamically)
*
* Column will be kept, if they match any name in the $columnsToKeep, or if they look like anyColumnToKeep__anythingHere
*/
const APPEND_TO_COLUMN_NAME_TO_KEEP = '__';
/**
* Delete the column, only if the value was zero
*
* @var bool
*/
private $deleteIfZeroOnly;
/**
* Delete the column recursively in all nested arrays as well
*
* @var bool
*/
private $deleteRecursive;
/**
* Constructor.
*
* @param DataTable $table The DataTable instance that will eventually be filtered.
* @param array|string $columnsToRemove An array of column names or a comma-separated list of
* column names. These columns will be removed.
* @param array|string $columnsToKeep An array of column names that should be kept or a
* comma-separated list of column names. Columns not in
* this list will be removed.
* @param bool $deleteIfZeroOnly If true, columns will be removed only if their value is 0.
* @param bool $deleteRecursive If true, columns will be removed in nested arrays.
*/
public function __construct($table, $columnsToRemove, $columnsToKeep = array(), $deleteIfZeroOnly = false, $deleteRecursive = false)
{
parent::__construct($table);
if (is_string($columnsToRemove)) {
$columnsToRemove = $columnsToRemove === '' ? array() : explode(',', $columnsToRemove);
}
if (is_string($columnsToKeep)) {
$columnsToKeep = $columnsToKeep === '' ? array() : explode(',', $columnsToKeep);
}
$this->columnsToRemove = $columnsToRemove;
$this->columnsToKeep = array_flip($columnsToKeep); // flip so we can use isset instead of in_array
$this->deleteIfZeroOnly = $deleteIfZeroOnly;
$this->deleteRecursive = $deleteRecursive;
}
/**
* See {@link ColumnDelete}.
*
* @param DataTable $table
* @return DataTable
*/
public function filter($table)
{
// always do recursive filter
$this->enableRecursive(true);
$recurse = false; // only recurse if there are columns to remove/keep
// remove columns specified in $this->columnsToRemove
if (!empty($this->columnsToRemove)) {
$this->removeColumnsFromTable($table);
$recurse = true;
}
// remove columns not specified in $columnsToKeep
if (!empty($this->columnsToKeep)) {
foreach ($table as $index => $row) {
$columnsToDelete = array();
foreach ($row as $name => $value) {
$keep = false;
// @see self::APPEND_TO_COLUMN_NAME_TO_KEEP
foreach ($this->columnsToKeep as $nameKeep => $true) {
if (strpos($name, $nameKeep . self::APPEND_TO_COLUMN_NAME_TO_KEEP) === 0) {
$keep = true;
}
}
if (!$keep
&& $name !== 'label' // label cannot be removed via allowlisting
&& !isset($this->columnsToKeep[$name])
) {
// we cannot remove row directly to prevent notice "ArrayIterator::next(): Array was modified
// outside object and internal position is no longer valid in /var/www..."
$columnsToDelete[] = $name;
}
}
foreach ($columnsToDelete as $columnToDelete) {
unset($table[$index][$columnToDelete]);
}
}
$recurse = true;
}
// recurse
if ($recurse && !is_array($table)) {
foreach ($table as $row) {
$this->filterSubTable($row);
}
}
return $table;
}
/**
* @param $table
*/
protected function removeColumnsFromTable(&$table)
{
if (!$this->isArrayAccess($table)) {
return;
}
foreach ($table as $index => $row) {
if (!$this->isArrayAccess($row)) {
continue;
}
foreach ($this->columnsToRemove as $column) {
if (is_array($row)) {
if (!array_key_exists($column, $row)) {
continue;
}
} elseif ($row instanceof \ArrayAccess) {
if (!$row->offsetExists($column)) {
continue;
}
}
if ($this->deleteIfZeroOnly) {
$value = $row[$column];
if ($value === false || !empty($value)) {
continue;
}
}
unset($table[$index][$column]);
}
if ($this->deleteRecursive) {
$this->removeColumnsFromTable($table[$index]);
}
}
}
/**
* @param $table
* @return bool
*/
protected function isArrayAccess(&$table)
{
return is_array($table) || $table instanceof \ArrayAccess;
}
}