1<?php 2/** 3 * Matomo - free/libre analytics platform 4 * 5 * @link https://matomo.org 6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later 7 * 8 */ 9namespace Piwik\DataTable\Filter; 10 11use Piwik\DataTable\BaseFilter; 12use Piwik\DataTable; 13use Piwik\DataTable\Row; 14 15/** 16 * Replaces one or more column values in each row of a DataTable with the results 17 * of a callback. 18 * 19 * **Basic usage example** 20 * 21 * $truncateString = function ($value, $truncateLength) { 22 * if (strlen($value) > $truncateLength) { 23 * return substr(0, $truncateLength); 24 * } else { 25 * return $value; 26 * } 27 * }; 28 * 29 * // label, url and truncate_length are columns in $dataTable 30 * $dataTable->filter('ColumnCallbackReplace', array('label', 'url'), $truncateString, null, array('truncate_length')); 31 * 32 * @api 33 */ 34class ColumnCallbackReplace extends BaseFilter 35{ 36 private $columnsToFilter; 37 private $functionToApply; 38 private $functionParameters; 39 private $extraColumnParameters; 40 41 /** 42 * Constructor. 43 * 44 * @param DataTable $table The DataTable to filter. 45 * @param array|string $columnsToFilter The columns whose values should be passed to the callback 46 * and then replaced with the callback's result. 47 * @param callable $functionToApply The function to execute. Must take the column value as a parameter 48 * and return a value that will be used to replace the original. 49 * @param array|null $functionParameters deprecated - use an [anonymous function](http://php.net/manual/en/functions.anonymous.php) 50 * instead. 51 * @param array $extraColumnParameters Extra column values that should be passed to the callback, but 52 * shouldn't be replaced. 53 */ 54 public function __construct($table, $columnsToFilter, $functionToApply, $functionParameters = null, 55 $extraColumnParameters = array()) 56 { 57 parent::__construct($table); 58 $this->functionToApply = $functionToApply; 59 $this->functionParameters = $functionParameters; 60 61 if (!is_array($columnsToFilter)) { 62 $columnsToFilter = array($columnsToFilter); 63 } 64 65 $this->columnsToFilter = $columnsToFilter; 66 $this->extraColumnParameters = $extraColumnParameters; 67 } 68 69 /** 70 * See {@link ColumnCallbackReplace}. 71 * 72 * @param DataTable $table 73 */ 74 public function filter($table) 75 { 76 foreach ($table->getRows() as $row) { 77 $extraColumnParameters = array(); 78 foreach ($this->extraColumnParameters as $columnName) { 79 $extraColumnParameters[] = $row->getColumn($columnName); 80 } 81 82 foreach ($this->columnsToFilter as $column) { 83 84 // when a value is not defined, we set it to zero by default (rather than displaying '-') 85 $value = $this->getElementToReplace($row, $column); 86 if ($value === false) { 87 $value = 0; 88 } 89 90 $parameters = array_merge(array($value), $extraColumnParameters); 91 92 if (!is_null($this->functionParameters)) { 93 $parameters = array_merge($parameters, $this->functionParameters); 94 } 95 96 $newValue = call_user_func_array($this->functionToApply, $parameters); 97 $this->setElementToReplace($row, $column, $newValue); 98 $this->filterSubTable($row); 99 } 100 } 101 102 if (in_array('label', $this->columnsToFilter)) { 103 // we need to force rebuilding the index 104 $table->setLabelsHaveChanged(); 105 } 106 } 107 108 /** 109 * Replaces the given column within given row with the given value 110 * 111 * @param Row $row 112 * @param string $columnToFilter 113 * @param mixed $newValue 114 */ 115 protected function setElementToReplace($row, $columnToFilter, $newValue) 116 { 117 $row->setColumn($columnToFilter, $newValue); 118 } 119 120 /** 121 * Returns the element that should be replaced 122 * 123 * @param Row $row 124 * @param string $columnToFilter 125 * @return mixed 126 */ 127 protected function getElementToReplace($row, $columnToFilter) 128 { 129 return $row->getColumn($columnToFilter); 130 } 131} 132