2020-05-27 03:07:17 -04:00
< ? php
2020-07-10 08:13:29 -04:00
declare ( strict_types = 1 );
2020-05-27 03:07:17 -04:00
/**
2024-05-23 03:26:56 -04:00
* SPDX - FileCopyrightText : 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX - License - Identifier : AGPL - 3.0 - or - later
2020-05-27 03:07:17 -04:00
*/
namespace OC\Dashboard ;
2020-06-26 10:01:52 -04:00
use InvalidArgumentException ;
2022-06-22 09:53:12 -04:00
use OCP\App\IAppManager ;
2022-10-27 01:25:01 -04:00
use OCP\Dashboard\IConditionalWidget ;
2020-05-27 03:07:17 -04:00
use OCP\Dashboard\IManager ;
2020-08-04 09:20:05 -04:00
use OCP\Dashboard\IWidget ;
2022-06-22 09:53:12 -04:00
use Psr\Container\ContainerExceptionInterface ;
use Psr\Container\ContainerInterface ;
2022-03-29 16:25:26 -04:00
use Psr\Log\LoggerInterface ;
2020-06-26 10:01:52 -04:00
use Throwable ;
2020-05-27 03:07:17 -04:00
class Manager implements IManager {
2020-06-23 09:23:28 -04:00
/** @var array */
2020-08-04 09:20:05 -04:00
private $lazyWidgets = [];
2020-06-23 09:23:28 -04:00
2023-09-19 11:14:02 -04:00
/** @var array<string, IWidget> */
private array $widgets = [];
2020-05-27 03:07:17 -04:00
2022-06-22 12:19:00 -04:00
private ? IAppManager $appManager = null ;
2020-06-23 09:23:28 -04:00
2024-07-11 07:24:10 -04:00
public function __construct (
private ContainerInterface $serverContainer ,
private LoggerInterface $logger ,
) {
2020-06-23 09:23:28 -04:00
}
2020-08-04 09:20:05 -04:00
private function registerWidget ( IWidget $widget ) : void {
if ( array_key_exists ( $widget -> getId (), $this -> widgets )) {
throw new InvalidArgumentException ( 'Dashboard widget with this id has already been registered' );
2020-05-27 03:07:17 -04:00
}
2024-07-11 07:24:10 -04:00
if ( ! preg_match ( '/^[a-z][a-z0-9\-_]*$/' , $widget -> getId ())) {
$this -> logger -> debug ( 'Deprecated dashboard widget ID provided: "' . $widget -> getId () . '" [ ' . get_class ( $widget ) . ' ]. Please use a-z, 0-9, - and _ only, starting with a-z' );
}
2020-08-04 09:20:05 -04:00
$this -> widgets [ $widget -> getId ()] = $widget ;
2020-05-27 03:07:17 -04:00
}
2022-06-22 09:53:12 -04:00
public function lazyRegisterWidget ( string $widgetClass , string $appId ) : void {
$this -> lazyWidgets [] = [ 'class' => $widgetClass , 'appId' => $appId ];
2020-06-23 09:23:28 -04:00
}
public function loadLazyPanels () : void {
2022-06-22 12:19:00 -04:00
if ( $this -> appManager === null ) {
$this -> appManager = $this -> serverContainer -> get ( IAppManager :: class );
}
2022-06-22 09:53:12 -04:00
$services = $this -> lazyWidgets ;
foreach ( $services as $service ) {
/** @psalm-suppress InvalidCatch */
2020-06-23 09:23:28 -04:00
try {
2022-06-22 09:53:12 -04:00
if ( ! $this -> appManager -> isEnabledForUser ( $service [ 'appId' ])) {
// all apps are registered, but some may not be enabled for the user
continue ;
}
2020-08-04 09:20:05 -04:00
/** @var IWidget $widget */
2022-06-22 09:53:12 -04:00
$widget = $this -> serverContainer -> get ( $service [ 'class' ]);
} catch ( ContainerExceptionInterface $e ) {
2020-06-23 09:23:28 -04:00
/*
* There is a circular dependency between the logger and the registry , so
* we can not inject it . Thus the static call .
*/
2022-03-29 16:25:26 -04:00
\OC :: $server -> get ( LoggerInterface :: class ) -> critical (
2022-10-27 01:10:57 -04:00
'Could not load lazy dashboard widget: ' . $service [ 'class' ],
[ 'exception' => $e ]
2022-03-29 16:25:26 -04:00
);
2022-10-27 01:10:57 -04:00
continue ;
2020-06-23 09:23:28 -04:00
}
/**
* Try to register the loaded reporter . Theoretically it could be of a wrong
* type , so we might get a TypeError here that we should catch .
*/
try {
2022-10-27 01:25:01 -04:00
if ( $widget instanceof IConditionalWidget && ! $widget -> isEnabled ()) {
continue ;
}
2020-08-04 09:20:05 -04:00
$this -> registerWidget ( $widget );
2020-06-23 09:23:28 -04:00
} catch ( Throwable $e ) {
/*
* There is a circular dependency between the logger and the registry , so
* we can not inject it . Thus the static call .
*/
2022-03-29 16:25:26 -04:00
\OC :: $server -> get ( LoggerInterface :: class ) -> critical (
2022-10-27 01:10:57 -04:00
'Could not register lazy dashboard widget: ' . $service [ 'class' ],
2022-06-22 09:53:12 -04:00
[ 'exception' => $e ]
2022-03-29 16:25:26 -04:00
);
2022-10-27 01:10:57 -04:00
continue ;
2020-06-23 09:23:28 -04:00
}
2020-06-26 10:01:52 -04:00
try {
2020-09-23 06:14:01 -04:00
$startTime = microtime ( true );
2020-08-04 09:20:05 -04:00
$widget -> load ();
2020-09-23 06:14:01 -04:00
$endTime = microtime ( true );
$duration = $endTime - $startTime ;
if ( $duration > 1 ) {
2024-01-15 03:29:22 -05:00
\OC :: $server -> get ( LoggerInterface :: class ) -> info (
2022-03-30 03:31:45 -04:00
'Dashboard widget {widget} took {duration} seconds to load.' ,
[
'widget' => $widget -> getId (),
'duration' => round ( $duration , 2 ),
]
);
2020-09-23 06:14:01 -04:00
}
2020-06-26 10:01:52 -04:00
} catch ( Throwable $e ) {
2022-03-29 16:25:26 -04:00
\OC :: $server -> get ( LoggerInterface :: class ) -> critical (
2022-10-27 01:10:57 -04:00
'Error during dashboard widget loading: ' . $service [ 'class' ],
2022-06-22 09:53:12 -04:00
[ 'exception' => $e ]
2022-03-29 16:25:26 -04:00
);
2022-10-27 01:10:57 -04:00
continue ;
2020-06-26 10:01:52 -04:00
}
2020-06-23 09:23:28 -04:00
}
2020-08-04 09:20:05 -04:00
$this -> lazyWidgets = [];
2020-06-23 09:23:28 -04:00
}
2023-09-19 11:14:02 -04:00
/**
* @ return array < string , IWidget >
*/
2020-08-04 09:20:05 -04:00
public function getWidgets () : array {
2020-06-23 09:23:28 -04:00
$this -> loadLazyPanels ();
2020-08-04 09:20:05 -04:00
return $this -> widgets ;
2020-05-27 03:07:17 -04:00
}
}