logger = $logger; } /** * Get an array of al the capabilities that are registered at this manager * * @param bool $public get public capabilities only * @throws \InvalidArgumentException * @return array */ public function getCapabilities(bool $public = false, bool $initialState = false) : array { $capabilities = []; foreach ($this->capabilities as $capability) { try { $c = $capability(); } catch (QueryException $e) { $this->logger->error('CapabilitiesManager', [ 'exception' => $e, ]); continue; } if ($c instanceof ICapability) { if (!$public || $c instanceof IPublicCapability) { if ($initialState && ($c instanceof IInitialStateExcludedCapability)) { // Remove less important capabilities information that are expensive to query // that we would otherwise inject to every page load continue; } $startTime = microtime(true); $capabilities = array_replace_recursive($capabilities, $c->getCapabilities()); $endTime = microtime(true); $timeSpent = $endTime - $startTime; if ($timeSpent > self::ACCEPTABLE_LOADING_TIME) { $logLevel = match (true) { $timeSpent > self::ACCEPTABLE_LOADING_TIME * 16 => \OCP\ILogger::FATAL, $timeSpent > self::ACCEPTABLE_LOADING_TIME * 8 => \OCP\ILogger::ERROR, $timeSpent > self::ACCEPTABLE_LOADING_TIME * 4 => \OCP\ILogger::WARN, $timeSpent > self::ACCEPTABLE_LOADING_TIME * 2 => \OCP\ILogger::INFO, default => \OCP\ILogger::DEBUG, }; $this->logger->log( $logLevel, 'Capabilities of {className} took {duration} seconds to generate.', [ 'className' => get_class($c), 'duration' => round($timeSpent, 2), ] ); } } } else { throw new \InvalidArgumentException('The given Capability (' . get_class($c) . ') does not implement the ICapability interface'); } } return $capabilities; } /** * In order to improve lazy loading a closure can be registered which will be called in case * capabilities are actually requested * * $callable has to return an instance of OCP\Capabilities\ICapability * * @param \Closure $callable */ public function registerCapability(\Closure $callable) { $this->capabilities[] = $callable; } }