| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\DataTable; |
|
|
| use Exception; |
| use Piwik\Columns\Dimension; |
| use Piwik\Common; |
| use Piwik\DataTable; |
| use Piwik\Metrics; |
| use Piwik\Piwik; |
| use Piwik\BaseFactory; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| abstract class Renderer extends BaseFactory |
| { |
| protected $table; |
|
|
| |
| |
| |
| protected $exception; |
| protected $renderSubTables = false; |
|
|
| |
| protected $hideIdSubDatatable = false; |
| |
| protected $hideMetadata = false; |
|
|
| |
| |
| |
| |
| public $translateColumnNames = false; |
|
|
| |
| |
| |
| |
| private $columnTranslations = null; |
|
|
| |
| |
| |
| |
| public $apiMethod = null; |
|
|
| |
| |
| |
| |
| private $apiMetaData = null; |
|
|
| |
| |
| |
| |
| public $idSite = 'all'; |
|
|
| public function __construct() |
| { |
| } |
|
|
| |
| |
| |
| public function setRenderSubTables(bool $enableRenderSubTable): void |
| { |
| $this->renderSubTables = $enableRenderSubTable; |
| } |
|
|
| public function setHideIdSubDatableFromResponse(bool $hideIdSubDataTable): void |
| { |
| $this->hideIdSubDatatable = $hideIdSubDataTable; |
| } |
|
|
| public function setHideMetadataFromResponse(bool $hideMetadata): void |
| { |
| $this->hideMetadata = $hideMetadata; |
| } |
|
|
| |
| |
| |
| protected function isRenderSubtables(): bool |
| { |
| return $this->renderSubTables; |
| } |
|
|
| |
| |
| |
| protected function renderHeader() |
| { |
| Common::sendHeader('Content-Type: text/plain; charset=utf-8'); |
| } |
|
|
| |
| |
| |
| |
| |
| abstract public function render(); |
|
|
| |
| |
| |
| public function __toString(): string |
| { |
| return $this->render(); |
| } |
|
|
| |
| |
| |
| |
| |
| public function setTable($table) |
| { |
| if ( |
| !is_array($table) |
| && !($table instanceof DataTableInterface) |
| ) { |
| throw new Exception("DataTable renderers renderer accepts only DataTable, Simple and Map instances, and arrays."); |
| } |
| $this->table = $table; |
| } |
|
|
| |
| |
| |
| protected static $availableRenderers = array('xml', |
| 'json', |
| 'csv', |
| 'tsv', |
| 'html', |
| ); |
|
|
| |
| |
| |
| |
| |
| public static function getRenderers() |
| { |
| return self::$availableRenderers; |
| } |
|
|
| protected static function getClassNameFromClassId($id) |
| { |
| $className = ucfirst(strtolower($id)); |
| $className = 'Piwik\DataTable\Renderer\\' . $className; |
|
|
| return $className; |
| } |
|
|
| protected static function getInvalidClassIdExceptionMessage($id) |
| { |
| $availableRenderers = implode(', ', self::getRenderers()); |
| $klassName = self::getClassNameFromClassId($id); |
|
|
| return Piwik::translate('General_ExceptionInvalidRendererFormat', array($klassName, $availableRenderers)); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public static function formatValueXml($value) |
| { |
| if ( |
| is_string($value) |
| && !is_numeric($value) |
| ) { |
| $value = html_entity_decode($value, ENT_QUOTES, 'UTF-8'); |
| |
| if (function_exists('mb_convert_encoding')) { |
| $value = @mb_convert_encoding($value, 'UTF-8', 'UTF-8'); |
| } |
| $value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); |
|
|
| $htmlentities = array( |
| " ", "¡", "¢", "£", "¤", "¥", "¦", "§", "¨", "©", |
| "ª", "«", "¬", "­", "®", "¯", "°", "±", "²", "³", |
| "´", "µ", "¶", "·", "¸", "¹", "º", "»", "¼", |
| "½", "¾", "¿", "À", "Á", "Â", "Ã", "Ä", "Å", |
| "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î", |
| "Ï", "Ð", "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö", "×", |
| "Ø", "Ù", "Ú", "Û", "Ü", "Ý", "Þ", "ß", "à", |
| "á", "â", "ã", "ä", "å", "æ", "ç", "è", "é", |
| "ê", "ë", "ì", "í", "î", "ï", "ð", "ñ", "ò", |
| "ó", "ô", "õ", "ö", "÷", "ø", "ù", "ú", "û", |
| "ü", "ý", "þ", "ÿ", "€", |
| ); |
| $xmlentities = array( |
| "¢", "£", "¤", "¥", "¦", "§", "¨", "©", "ª", "«", |
| "¬", "­", "®", "¯", "°", "±", "²", "³", "´", "µ", |
| "¶", "·", "¸", "¹", "º", "»", "¼", "½", "¾", "¿", |
| "À", "Á", "Â", "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", |
| "Ê", "Ë", "Ì", "Í", "Î", "Ï", "Ð", "Ñ", "Ò", "Ó", |
| "Ô", "Õ", "Ö", "×", "Ø", "Ù", "Ú", "Û", "Ü", "Ý", |
| "Þ", "ß", "à", "á", "â", "ã", "ä", "å", "æ", "ç", |
| "è", "é", "ê", "ë", "ì", "í", "î", "ï", "ð", "ñ", |
| "ò", "ó", "ô", "õ", "ö", "÷", "ø", "ù", "ú", "û", |
| "ü", "ý", "þ", "ÿ", "€", |
| ); |
| $value = str_replace($htmlentities, $xmlentities, $value); |
| } elseif ($value === false) { |
| $value = 0; |
| } |
|
|
| return $value; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| protected function translateColumnNames($names) |
| { |
| if (!$this->apiMethod) { |
| return $names; |
| } |
|
|
| |
| |
| |
| if ($this->columnTranslations === null) { |
| $meta = $this->getApiMetaData(); |
| if ($meta === false) { |
| return $names; |
| } |
|
|
| $t = Metrics::getDefaultMetricTranslations(); |
| foreach (array('metrics', 'processedMetrics', 'metricsGoal', 'processedMetricsGoal') as $index) { |
| if (isset($meta[$index]) && is_array($meta[$index])) { |
| $t = array_merge($t, $meta[$index]); |
| } |
| } |
|
|
| foreach (Dimension::getAllDimensions() as $dimension) { |
| $dimensionId = str_replace('.', '_', $dimension->getId()); |
| $dimensionName = $dimension->getName(); |
|
|
| if (!empty($dimensionId) && !empty($dimensionName)) { |
| $t[$dimensionId] = $dimensionName; |
| } |
| } |
|
|
| $this->columnTranslations = & $t; |
| } |
|
|
| foreach ($names as &$name) { |
| if (isset($this->columnTranslations[$name])) { |
| $name = $this->columnTranslations[$name]; |
| } |
| } |
|
|
| return $names; |
| } |
|
|
| |
| |
| |
| protected function getApiMetaData() |
| { |
| if ($this->apiMetaData === null) { |
| [$apiModule, $apiAction] = explode('.', $this->apiMethod); |
|
|
| if (!$apiModule || !$apiAction) { |
| $this->apiMetaData = false; |
| } |
|
|
| $api = \Piwik\Plugins\API\API::getInstance(); |
| $meta = $api->getMetadata($this->idSite, $apiModule, $apiAction); |
| if (isset($meta[0]) && is_array($meta[0])) { |
| $meta = $meta[0]; |
| } |
|
|
| $this->apiMetaData = & $meta; |
| } |
|
|
| return $this->apiMetaData; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| protected function translateColumnName($column) |
| { |
| $columns = array($column); |
| $columns = $this->translateColumnNames($columns); |
| return $columns[0]; |
| } |
|
|
| |
| |
| |
| |
| |
| public function setTranslateColumnNames($bool) |
| { |
| $this->translateColumnNames = $bool; |
| } |
|
|
| |
| |
| |
| |
| |
| public function setApiMethod($method) |
| { |
| $this->apiMethod = $method; |
| } |
|
|
| |
| |
| |
| |
| |
| public function setIdSite($idSite) |
| { |
| $this->idSite = $idSite; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| protected static function shouldWrapArrayBeforeRendering( |
| $array, |
| $wrapSingleValues = true, |
| $isAssociativeArray = null |
| ) { |
| if (empty($array)) { |
| return false; |
| } |
|
|
| if ($isAssociativeArray === null) { |
| $isAssociativeArray = Piwik::isAssociativeArray($array); |
| } |
|
|
| $wrap = true; |
| if ($isAssociativeArray) { |
| |
| $firstValue = reset($array); |
| if ( |
| !$wrapSingleValues |
| && count($array) === 1 |
| && (!is_array($firstValue) |
| && !is_object($firstValue)) |
| ) { |
| $wrap = false; |
| } else { |
| foreach ($array as $value) { |
| if ( |
| is_array($value) |
| || is_object($value) |
| ) { |
| $wrap = false; |
| break; |
| } |
| } |
| } |
| } else { |
| $wrap = false; |
| } |
|
|
| return $wrap; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| protected function convertDataTableToArray($dataTable = null) |
| { |
| if (is_null($dataTable)) { |
| $dataTable = $this->table; |
| } |
|
|
| if (is_array($dataTable)) { |
| $flatArray = $dataTable; |
| if (self::shouldWrapArrayBeforeRendering($flatArray)) { |
| $flatArray = array($flatArray); |
| } |
| } elseif ($dataTable instanceof DataTable\Map) { |
| $flatArray = array(); |
| foreach ($dataTable->getDataTables() as $keyName => $table) { |
| $flatArray[$keyName] = $this->convertDataTableToArray($table); |
| } |
| } elseif ($dataTable instanceof Simple) { |
| $flatArray = $this->convertSimpleTable($dataTable); |
|
|
| reset($flatArray); |
| $firstKey = key($flatArray); |
|
|
| |
| |
| if ( |
| count($flatArray) == 1 |
| && $firstKey !== DataTable\Row::COMPARISONS_METADATA_NAME |
| ) { |
| $flatArray = current($flatArray); |
| } |
| } else { |
| |
| $array = $this->convertTable($dataTable); |
| $flatArray = $this->flattenArray($array); |
| } |
|
|
| return $flatArray; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| protected function convertTable($table) |
| { |
| $array = []; |
|
|
| foreach ($table->getRows() as $id => $row) { |
| $newRow = [ |
| 'columns' => $row->getColumns(), |
| 'metadata' => $row->getMetadata(), |
| 'idsubdatatable' => $row->getIdSubDataTable(), |
| ]; |
|
|
| if ($id == DataTable::ID_SUMMARY_ROW) { |
| $newRow['issummaryrow'] = true; |
| } |
|
|
| if (isset($newRow['metadata'][DataTable\Row::COMPARISONS_METADATA_NAME])) { |
| $newRow['metadata'][DataTable\Row::COMPARISONS_METADATA_NAME] = $row->getComparisons(); |
| } |
|
|
| $subTable = $row->getSubtable(); |
| if ( |
| $this->isRenderSubtables() |
| && $subTable |
| ) { |
| $subTable = $this->convertTable($subTable); |
| $newRow['subtable'] = $subTable; |
| if ( |
| $this->hideIdSubDatatable === false |
| && $this->hideMetadata === false |
| && isset($newRow['metadata']['idsubdatatable_in_db']) |
| ) { |
| $newRow['columns']['idsubdatatable'] = $newRow['metadata']['idsubdatatable_in_db']; |
| } |
| unset($newRow['metadata']['idsubdatatable_in_db']); |
| } |
| if ($this->hideIdSubDatatable || $this->hideMetadata) { |
| unset($newRow['idsubdatatable']); |
| } |
|
|
| $array[] = $newRow; |
| } |
| return $array; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| protected function convertSimpleTable($table) |
| { |
| $array = []; |
|
|
| $row = $table->getFirstRow(); |
| if ($row === false) { |
| return $array; |
| } |
| foreach ($row->getColumns() as $columnName => $columnValue) { |
| $array[$columnName] = $columnValue; |
| } |
|
|
| $comparisons = $row->getComparisons(); |
| if (!empty($comparisons)) { |
| $array[DataTable\Row::COMPARISONS_METADATA_NAME] = $comparisons; |
| } |
|
|
| return $array; |
| } |
|
|
| |
| |
| |
| |
| protected function flattenArray($array) |
| { |
| $flatArray = []; |
| foreach ($array as $row) { |
| if ($this->hideMetadata) { |
| $newRow = $row['columns']; |
| } else { |
| $newRow = $row['columns'] + $row['metadata']; |
| } |
|
|
| if ( |
| isset($row['idsubdatatable']) |
| && $this->hideIdSubDatatable === false |
| ) { |
| $newRow += ['idsubdatatable' => $row['idsubdatatable']]; |
| } |
| if (isset($row['subtable'])) { |
| $newRow += ['subtable' => $this->flattenArray($row['subtable'])]; |
| } |
| $flatArray[] = $newRow; |
| } |
| return $flatArray; |
| } |
| } |
|
|