((currentValue - pastValue) / pastValue) * 100 */ class CalculateEvolutionFilter extends ColumnCallbackAddColumnPercentage { /** * The the DataTable that contains past data. */ private $pastDataTable; /** * Tells if column being added is the revenue evolution column. */ private $isRevenueEvolution = null; /** * Constructor. * * @param DataTable $table The DataTable being filtered. * @param string $pastDataTable * @param string $columnToAdd * @param string $columnToRead * @param int $quotientPrecision */ function __construct($table, $pastDataTable, $columnToAdd, $columnToRead, $quotientPrecision = 0) { parent::__construct( $table, $columnToAdd, $columnToRead, $columnToRead, $quotientPrecision, $shouldSkipRows = true); $this->pastDataTable = $pastDataTable; $this->isRevenueEvolution = $columnToAdd == 'revenue_evolution'; } /** * Returns the difference between the column in the specific row and its * sister column in the past DataTable. * * @param Row $row * @return int|float */ protected function getDividend($row) { $currentValue = $row->getColumn($this->columnValueToRead); // if the site this is for doesn't support ecommerce & this is for the revenue_evolution column, // we don't add the new column if ($currentValue === false && $this->isRevenueEvolution && !Site::isEcommerceEnabledFor($row->getColumn('label')) ) { return false; } $pastRow = $this->getPastRowFromCurrent($row); if ($pastRow) { $pastValue = $pastRow->getColumn($this->columnValueToRead); } else { $pastValue = 0; } return $currentValue - $pastValue; } /** * Returns the value of the column in $row's sister row in the past * DataTable. * * @param Row $row * @return int|float */ protected function getDivisor($row) { $pastRow = $this->getPastRowFromCurrent($row); if (!$pastRow) return 0; return $pastRow->getColumn($this->columnNameUsedAsDivisor); } /** * Calculates and formats a quotient based on a divisor and dividend. * * Unlike ColumnCallbackAddColumnPercentage's, * version of this method, this method will return 100% if the past * value of a metric is 0, and the current value is not 0. For a * value representative of an evolution, this makes sense. * * @param int|float $value The dividend. * @param int|float $divisor * @return string */ protected function formatValue($value, $divisor) { $value = self::getPercentageValue($value, $divisor, $this->quotientPrecision); $value = self::appendPercentSign($value); return $value; } /** * Utility function. Returns the current row in the past DataTable. * * @param Row $row The row in the 'current' DataTable. */ private function getPastRowFromCurrent($row) { return $this->pastDataTable->getRowFromLabel($row->getColumn('label')); } /** * Calculates the evolution percentage for two arbitrary values. * * @param float|int $currentValue The current metric value. * @param float|int $pastValue The value of the metric in the past. We measure the % change * from this value to $currentValue. * @param float|int $quotientPrecision The quotient precision to round to. * * @return string The evolution percent 15% */ public static function calculate($currentValue, $pastValue, $quotientPrecision = 0) { $number = self::getPercentageValue($currentValue - $pastValue, $pastValue, $quotientPrecision); $number = self::appendPercentSign($number); return $number; } public static function appendPercentSign($number) { $number = $number . '%'; return $number; } public static function prependPlusSignToNumber($number) { if ($number > 0) { $number = '+' . $number; } return $number; } /** * Returns an evolution percent based on a value & divisor. */ private static function getPercentageValue($value, $divisor, $quotientPrecision) { if ($value == 0) { $evolution = 0; } elseif ($divisor == 0) { $evolution = 100; } else { $evolution = ($value / $divisor) * 100; } $evolution = round($evolution, $quotientPrecision); return $evolution; } }