matomo / plugins /Dashboard /API.php
Leon4gr45's picture
Upload source files chunk 17
58ce155 verified
Raw
History Blame Contribute Delete
8.51 kB
<?php
/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
namespace Piwik\Plugins\Dashboard;
use Piwik\API\Request;
use Piwik\Piwik;
/**
* The Dashboard API lets you manage user dashboards and retrieve their widget configurations.
*
* @method static \Piwik\Plugins\Dashboard\API getInstance()
*
* @phpstan-type DashboardWidget array{module: string, action: string}
* @phpstan-type DashboardInfo array{name: string, id: int, widgets: list<DashboardWidget>}
* @phpstan-type DashboardRecord array{name: string, iddashboard: int, layout: mixed}
*/
class API extends \Piwik\Plugin\API
{
/**
* @var Dashboard
*/
private $dashboard;
/**
* @var Model
*/
private $model;
public function __construct(Dashboard $dashboard, Model $model)
{
$this->dashboard = $dashboard;
$this->model = $model;
}
/**
* Returns the dashboards available to a user, including the widgets in each dashboard.
*
* @param string $login Login of the user to load dashboards for. Defaults to the current user.
* @param bool $returnDefaultIfEmpty Whether to return the default dashboard when the user has none.
* @return list<DashboardInfo> List of dashboards, each containing name, id, and widgets keys.
*/
public function getDashboards(string $login = '', bool $returnDefaultIfEmpty = true): array
{
$login = $login ?: Piwik::getCurrentUserLogin();
$dashboards = [];
if (!Piwik::isUserIsAnonymous()) {
Piwik::checkUserHasSuperUserAccessOrIsTheUser($login);
$dashboards = $this->getUserDashboards($login);
}
if (empty($dashboards) && $returnDefaultIfEmpty) {
$dashboards = [$this->getDefaultDashboard()];
}
return $dashboards;
}
/**
* Creates a new dashboard for a user.
*
* @param string $login Login of the user the dashboard should be created for.
* @param string $dashboardName Name of the new dashboard.
* @param bool $addDefaultWidgets Whether to populate the dashboard with the default widget layout.
* @return int|string ID of the newly created dashboard.
*/
public function createNewDashboardForUser(string $login, string $dashboardName = '', bool $addDefaultWidgets = true)
{
$this->checkLoginIsNotAnonymous($login);
Piwik::checkUserHasSuperUserAccessOrIsTheUser($login);
$layout = '{}';
if ($addDefaultWidgets) {
$layout = $this->dashboard->getDefaultLayout();
}
return $this->model->createNewDashboardForUser($login, $dashboardName, $layout);
}
/**
* Removes a dashboard for a user.
*
* Note: Deleting the first dashboard (ID = 1) is allowed but will cause buggy behavior
* unless a new dashboard is immediately added. This should only be done for automation purposes.
*
* @param int $idDashboard ID of the dashboard to remove.
* @param string $login Login of the dashboard owner. Defaults to the current user.
*/
public function removeDashboard(int $idDashboard, string $login = ''): void
{
$login = $login ?: Piwik::getCurrentUserLogin();
$this->checkLoginIsNotAnonymous($login);
Piwik::checkUserHasSuperUserAccessOrIsTheUser($login);
$this->model->deleteDashboardForUser($idDashboard, $login);
}
/**
* Copies one of the current user's dashboards to another user. Requires admin access.
*
* @param int $idDashboard ID of the dashboard to copy.
* @param string $copyToUser Login of the user that should receive the dashboard copy.
* @param string $dashboardName Name for the copied dashboard.
* @return int|string ID of the newly created dashboard copy.
*/
public function copyDashboardToUser(int $idDashboard, string $copyToUser, string $dashboardName = '')
{
Piwik::checkUserHasSomeAdminAccess();
// get users only returns users of sites the current user has at least admin access to
/** @var array $users */
$users = Request::processRequest('UsersManager.getUsers', ['filter_limit' => -1]);
$userFound = false;
foreach ($users as $user) {
if ($user['login'] === $copyToUser) {
$userFound = true;
break;
}
}
if (!$userFound) {
throw new \Exception(sprintf('Cannot copy dashboard to user %s, user not found.', $copyToUser));
}
$login = Piwik::getCurrentUserLogin();
$layout = $this->dashboard->getLayoutForUser($login, $idDashboard);
if ($layout !== false) {
return $this->model->createNewDashboardForUser($copyToUser, $dashboardName, $layout);
}
throw new \Exception('Dashboard not found');
}
/**
* Resets a dashboard to the default widget layout.
*
* @param int $idDashboard ID of the dashboard to reset.
* @param string $login Login of the dashboard owner. Defaults to the current user.
*/
public function resetDashboardLayout(int $idDashboard, string $login = ''): void
{
$login = $login ?: Piwik::getCurrentUserLogin();
$this->checkLoginIsNotAnonymous($login);
Piwik::checkUserHasSuperUserAccessOrIsTheUser($login);
$layout = $this->dashboard->getDefaultLayout();
$this->model->updateLayoutForUser($login, $idDashboard, $layout);
}
/**
* @return DashboardInfo
*/
private function getDefaultDashboard(): array
{
$defaultLayout = $this->dashboard->getDefaultLayout();
$defaultLayout = $this->dashboard->decodeLayout($defaultLayout);
$defaultDashboard = ['name' => Piwik::translate('Dashboard_Dashboard'), 'layout' => $defaultLayout, 'iddashboard' => 1];
$widgets = $this->getVisibleWidgetsWithinDashboard($defaultDashboard);
return $this->buildDashboard($defaultDashboard, $widgets);
}
/**
* @return list<DashboardInfo>
*/
private function getUserDashboards(string $userLogin): array
{
$userDashboards = $this->dashboard->getAllDashboards($userLogin);
$dashboards = [];
foreach ($userDashboards as $userDashboard) {
$widgets = $this->getVisibleWidgetsWithinDashboard($userDashboard);
$dashboards[] = $this->buildDashboard($userDashboard, $widgets);
}
return $dashboards;
}
/**
* @param DashboardRecord $dashboard
* @return list<DashboardWidget>
*/
private function getVisibleWidgetsWithinDashboard(array $dashboard): array
{
$columns = $this->getColumnsFromDashboard($dashboard);
$widgets = [];
$columns = array_filter($columns);
foreach ($columns as $column) {
foreach ($column as $widget) {
if ($this->widgetIsNotHidden($widget) && !empty($widget->parameters->module)) {
$module = $widget->parameters->module;
$action = $widget->parameters->action;
$widgets[] = ['module' => $module, 'action' => $action];
}
}
}
return $widgets;
}
private function checkLoginIsNotAnonymous(string $login): void
{
Piwik::checkUserIsNotAnonymous();
if (strtolower($login) === 'anonymous') {
throw new \Exception('This method can\'t be performed for anonymous user');
}
}
/**
* @param DashboardRecord $dashboard
*/
private function getColumnsFromDashboard(array $dashboard): array
{
if (empty($dashboard['layout'])) {
return [];
}
if (is_array($dashboard['layout'])) {
return $dashboard['layout'];
}
if (!empty($dashboard['layout']->columns)) {
return $dashboard['layout']->columns;
}
return [];
}
/**
* @param DashboardRecord $dashboard
* @param list<DashboardWidget> $widgets
* @return DashboardInfo
*/
private function buildDashboard(array $dashboard, array $widgets): array
{
return ['name' => $dashboard['name'], 'id' => (int)$dashboard['iddashboard'], 'widgets' => $widgets];
}
private function widgetIsNotHidden(object $widget): bool
{
return empty($widget->isHidden);
}
}