site-accueil-insa/matomo/plugins/API/WidgetMetadata.php

321 lines
11 KiB
PHP

<?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\Plugins\API;
use Piwik\Category\CategoryList;
use Piwik\Piwik;
use Piwik\Plugins\CoreHome\CoreHome;
use Piwik\Report\ReportWidgetConfig;
use Piwik\Category\Category;
use Piwik\Category\Subcategory;
use Piwik\Widget\WidgetContainerConfig;
use Piwik\Widget\WidgetConfig;
use Piwik\Widget\WidgetsList;
class WidgetMetadata
{
public function getPagesMetadata(CategoryList $categoryList, WidgetsList $widgetsList)
{
$this->createMissingCategoriesAndSubcategories($categoryList, $widgetsList->getWidgetConfigs());
return $this->buildPagesMetadata($categoryList, $widgetsList);
}
public function getWidgetMetadata(CategoryList $categoryList, WidgetsList $widgetsList)
{
$this->createMissingCategoriesAndSubcategories($categoryList, $widgetsList->getWidgetConfigs());
$flat = array();
foreach ($widgetsList->getWidgetConfigs() as $widgetConfig) {
$metadataOverrides = [];
/** @var WidgetConfig[] $widgets */
$widgets = array($widgetConfig);
if ($widgetConfig instanceof WidgetContainerConfig) {
// so far we go only one level down, in theory these widgetConfigs could have again containers containing configs
$widgets = array_merge($widgets, $widgetConfig->getWidgetConfigs());
}
foreach ($widgets as $widget) {
// make sure to include only widgetizable widgets
if (!$widget->isWidgetizeable() || !$widget->getName()) {
continue;
}
// widgets in containers with ByDimension layout have a special, unrecognized category/subcategory
// (eg, "Sales by Referrer Type"). we change it to the container's category/subcategory so the widget
// will appear in the dashboard manager.
if ($widgetConfig instanceof WidgetContainerConfig
&& $widgetConfig->getLayout() == CoreHome::WIDGET_CONTAINER_LAYOUT_BY_DIMENSION
) {
$metadataOverrides = [
'category' => $widgetConfig->getCategoryId(),
'subcategory' => $widgetConfig->getSubcategoryId(),
'name' => Piwik::translate($widget->getCategoryId()) . ': '
. Piwik::translate($widget->getName()),
];
}
$flat[] = $this->buildWidgetMetadata($widget, $categoryList, $metadataOverrides);
}
}
usort($flat, array($this, 'sortWidgets'));
return $flat;
}
/**
* @param WidgetConfig $widget
* @param CategoryList|null $categoryList If null, no category information will be added to the widgets in first
* level (they will be added to nested widgets as potentially needed eg for
* widgets in ByDimensionView where they are needed to build the left menu)
* @param array $metadataOverrides Overrides for data in `$widget`. Currently only 'name', 'category', 'subcategory'
* are recognized.
* @return array
*/
public function buildWidgetMetadata(WidgetConfig $widget, $categoryList = null, array $metadataOverrides = [])
{
$widgetName = !empty($metadataOverrides['name']) ? $metadataOverrides['name'] : $widget->getName();
$item = array(
'name' => Piwik::translate($widgetName),
);
if (isset($categoryList)) {
$widgetCategory = !empty($metadataOverrides['category'])
? $metadataOverrides['category'] : $widget->getCategoryId();
$widgetSubcategory = !empty($metadataOverrides['subcategory'])
? $metadataOverrides['subcategory'] : $widget->getSubcategoryId();
$category = $categoryList->getCategory($widgetCategory);
$subcategory = $category ? $category->getSubcategory($widgetSubcategory) : null;
$item['category'] = $this->buildCategoryMetadata($category);
$item['subcategory'] = $this->buildSubcategoryMetadata($subcategory);
}
$item['module'] = $widget->getModule();
$item['action'] = $widget->getAction();
$item['order'] = $widget->getOrder();
$item['parameters'] = $widget->getParameters();
$item['uniqueId'] = $widget->getUniqueId();
$item['isWide'] = $widget->isWide();
$middleware = $widget->getMiddlewareParameters();
if (!empty($middleware)) {
$item['middlewareParameters'] = $middleware;
}
if ($widget instanceof ReportWidgetConfig) {
$item['viewDataTable'] = $widget->getViewDataTable();
$item['isReport'] = true;
}
if ($widget instanceof WidgetContainerConfig) {
$item['layout'] = $widget->getLayout();
$item['isContainer'] = true;
// we do not want to create categories to the initial categoryList. Otherwise we'd maybe display more pages
// etc.
$subCategoryList = new CategoryList();
$this->createMissingCategoriesAndSubcategories($subCategoryList, $widget->getWidgetConfigs());
$children = array();
foreach ($widget->getWidgetConfigs() as $widgetConfig) {
$children[] = $this->buildWidgetMetadata($widgetConfig, $subCategoryList);
}
$item['widgets'] = $children;
}
return $item;
}
private function sortWidgets($widgetA, $widgetB) {
$orderA = $widgetA['category']['order'];
$orderB = $widgetB['category']['order'];
if ($orderA === $orderB) {
if (!empty($widgetA['subcategory']['order']) && !empty($widgetB['subcategory']['order'])) {
$subOrderA = $widgetA['subcategory']['order'];
$subOrderB = $widgetB['subcategory']['order'];
if ($subOrderA === $subOrderB) {
return $this->compareWidgetIds($widgetA, $widgetB);
}
return $subOrderA > $subOrderB ? 1 : -1;
} else if (empty($widgetA['subcategory']['order']) && empty($widgetB['subcategory']['order'])) {
return $this->compareWidgetIds($widgetA, $widgetB);
} elseif (!empty($widgetA['subcategory']['order'])) {
return 1;
}
return -1;
}
return $orderA > $orderB ? 1 : -1;
}
private function compareWidgetIds($widgetA, $widgetB)
{
if ($widgetA['uniqueId'] == $widgetB['uniqueId']) {
return 0;
}
return $widgetA['uniqueId'] > $widgetB['uniqueId'] ? 1 : -1;
}
/**
* @param Category|null $category
* @return array
*/
private function buildCategoryMetadata($category)
{
if (!isset($category)) {
return null;
}
return array(
'id' => (string) $category->getId(),
'name' => $category->getDisplayName(),
'order' => $category->getOrder(),
'icon' => $category->getIcon(),
'help' => Piwik::translate($category->getHelp()),
);
}
/**
* @param Subcategory|null $subcategory
* @return array
*/
private function buildSubcategoryMetadata($subcategory)
{
if (!isset($subcategory)) {
return null;
}
return array(
'id' => (string) $subcategory->getId(),
'name' => Piwik::translate($subcategory->getName()),
'order' => $subcategory->getOrder(),
'help' => Piwik::translate($subcategory->getHelp()),
);
}
/**
* @param CategoryList $categoryList
* @param WidgetConfig[] $widgetConfigs
*/
private function createMissingCategoriesAndSubcategories($categoryList, $widgetConfigs)
{
// move reports into categories/subcategories and create missing ones if needed
foreach ($widgetConfigs as $widgetConfig) {
$categoryId = $widgetConfig->getCategoryId();
$subcategoryId = $widgetConfig->getSubcategoryId();
if (!$categoryId) {
continue;
}
if ($widgetConfig instanceof WidgetContainerConfig && !$widgetConfig->getWidgetConfigs()) {
// if a container does not contain any widgets, ignore it
continue;
}
if (!$categoryList->hasCategory($categoryId)) {
$categoryList->addCategory($this->createCategory($categoryId));
}
if (!$subcategoryId) {
continue;
}
$category = $categoryList->getCategory($categoryId);
if (!$category->hasSubcategory($subcategoryId)) {
$category->addSubcategory($this->createSubcategory($categoryId, $subcategoryId));
}
}
}
private function createCategory($categoryId)
{
$category = new Category();
$category->setId($categoryId);
return $category;
}
private function createSubcategory($categoryId, $subcategoryId)
{
$subcategory = new Subcategory();
$subcategory->setCategoryId($categoryId);
$subcategory->setId($subcategoryId);
return $subcategory;
}
/**
* @param CategoryList $categoryList
* @param WidgetsList $widgetsList
* @return array
*/
private function buildPagesMetadata(CategoryList $categoryList, WidgetsList $widgetsList)
{
$pages = array();
$widgets = array();
foreach ($widgetsList->getWidgetConfigs() as $config) {
$pageId = $this->buildPageId($config->getCategoryId(), $config->getSubcategoryId());
if (!isset($widgets[$pageId])) {
$widgets[$pageId] = array();
}
$widgets[$pageId][] = $config;
}
foreach ($categoryList->getCategories() as $category) {
foreach ($category->getSubcategories() as $subcategory) {
$pageId = $this->buildPageId($category->getId(), $subcategory->getId());
if (!empty($widgets[$pageId])) {
$pages[] = $this->buildPageMetadata($category, $subcategory, $widgets[$pageId]);
}
}
}
return $pages;
}
private function buildPageId($categoryId, $subcategoryId)
{
return $categoryId . '.' . $subcategoryId;
}
public function buildPageMetadata(Category $category, Subcategory $subcategory, $widgetConfigs)
{
$ca = array(
'uniqueId' => $this->buildPageId($category->getId(), $subcategory->getId()),
'category' => $this->buildCategoryMetadata($category),
'subcategory' => $this->buildSubcategoryMetadata($subcategory),
'widgets' => array()
);
foreach ($widgetConfigs as $config) {
$ca['widgets'][] = $this->buildWidgetMetadata($config);
}
return $ca;
}
}