Merge pull request #53523 from nextcloud/fix/cleanup-dicontainer

chore: Cleanup DIContainer class
This commit is contained in:
Côme Chilliet 2025-07-08 15:48:47 +02:00 committed by GitHub
commit b1e58ba1b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 164 additions and 297 deletions

View file

@ -23,8 +23,8 @@ use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IGroupManager;
use OCP\IRequest;
use OCP\IServerContainer;
use OCP\IUserManager;
use OCP\Server;
use OCP\Share\Exceptions\GenericShareException;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager as ShareManager;
@ -44,7 +44,6 @@ class DeletedShareAPIController extends OCSController {
private IGroupManager $groupManager,
private IRootFolder $rootFolder,
private IAppManager $appManager,
private IServerContainer $serverContainer,
) {
parent::__construct($appName, $request);
}
@ -202,7 +201,7 @@ class DeletedShareAPIController extends OCSController {
throw new QueryException();
}
return $this->serverContainer->get('\OCA\Talk\Share\Helper\DeletedShareAPIController');
return Server::get('\OCA\Talk\Share\Helper\DeletedShareAPIController');
}
/**
@ -219,7 +218,7 @@ class DeletedShareAPIController extends OCSController {
throw new QueryException();
}
return $this->serverContainer->get('\OCA\Deck\Sharing\ShareAPIHelper');
return Server::get('\OCA\Deck\Sharing\ShareAPIHelper');
}
/**
@ -236,6 +235,6 @@ class DeletedShareAPIController extends OCSController {
throw new QueryException();
}
return $this->serverContainer->get('\OCA\ScienceMesh\Sharing\ShareAPIHelper');
return Server::get('\OCA\ScienceMesh\Sharing\ShareAPIHelper');
}
}

View file

@ -39,7 +39,7 @@ class ApplicationTest extends TestCase {
public function testContainerAppName(): void {
$this->app = new Application();
$this->assertEquals('settings', $this->container->getAppName());
$this->assertEquals('settings', $this->container->get('appName'));
}
public static function dataContainerQuery(): array {

View file

@ -1581,9 +1581,6 @@
<code><![CDATA[new QueryException()]]></code>
<code><![CDATA[new QueryException()]]></code>
</DeprecatedClass>
<DeprecatedInterface>
<code><![CDATA[private]]></code>
</DeprecatedInterface>
</file>
<file src="apps/files_sharing/lib/Controller/ShareAPIController.php">
<DeprecatedClass>
@ -3364,18 +3361,12 @@
</UndefinedMethod>
</file>
<file src="lib/private/AppFramework/DependencyInjection/DIContainer.php">
<ImplementedReturnTypeMismatch>
<code><![CDATA[boolean|null]]></code>
</ImplementedReturnTypeMismatch>
<InvalidReturnStatement>
<code><![CDATA[$this->server]]></code>
</InvalidReturnStatement>
<InvalidReturnType>
<code><![CDATA[\OCP\IServerContainer]]></code>
</InvalidReturnType>
<UndefinedInterfaceMethod>
<code><![CDATA[getAppDataDir]]></code>
</UndefinedInterfaceMethod>
</file>
<file src="lib/private/AppFramework/Http/Dispatcher.php">
<NullArgument>

View file

@ -101,7 +101,7 @@ class App {
$profiler->setEnabled($profiler->isEnabled() && !is_null($urlParams) && isset($urlParams['_route']) && !str_starts_with($urlParams['_route'], 'profiler.'));
if ($profiler->isEnabled()) {
\OC::$server->get(IEventLogger::class)->activate();
$profiler->add(new RoutingDataCollector($container['AppName'], $controllerName, $methodName));
$profiler->add(new RoutingDataCollector($container['appName'], $controllerName, $methodName));
}
$eventLogger->start('app:controller:params', 'Gather controller parameters');
@ -115,7 +115,7 @@ class App {
$request = $container->get(IRequest::class);
$request->setUrlParameters($container['urlParams']);
}
$appName = $container['AppName'];
$appName = $container['appName'];
$eventLogger->end('app:controller:params');

View file

@ -1,21 +1,33 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\AppFramework\DependencyInjection;
use OC;
use OC\AppFramework\Http;
use OC\AppFramework\Http\Dispatcher;
use OC\AppFramework\Http\Output;
use OC\AppFramework\Middleware\AdditionalScriptsMiddleware;
use OC\AppFramework\Middleware\CompressionMiddleware;
use OC\AppFramework\Middleware\FlowV2EphemeralSessionsMiddleware;
use OC\AppFramework\Middleware\MiddlewareDispatcher;
use OC\AppFramework\Middleware\NotModifiedMiddleware;
use OC\AppFramework\Middleware\OCSMiddleware;
use OC\AppFramework\Middleware\PublicShare\PublicShareMiddleware;
use OC\AppFramework\Middleware\Security\BruteForceMiddleware;
use OC\AppFramework\Middleware\Security\CORSMiddleware;
use OC\AppFramework\Middleware\Security\CSPMiddleware;
use OC\AppFramework\Middleware\Security\FeaturePolicyMiddleware;
use OC\AppFramework\Middleware\Security\PasswordConfirmationMiddleware;
use OC\AppFramework\Middleware\Security\RateLimitingMiddleware;
use OC\AppFramework\Middleware\Security\ReloadExecutionMiddleware;
use OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware;
use OC\AppFramework\Middleware\Security\SecurityMiddleware;
use OC\AppFramework\Middleware\SessionMiddleware;
use OC\AppFramework\ScopedPsrLogger;
@ -25,7 +37,6 @@ use OC\Diagnostics\EventLogger;
use OC\Log\PsrLoggerAdapter;
use OC\ServerContainer;
use OC\Settings\AuthorizedGroupMapper;
use OC\User\Manager as UserManager;
use OCA\WorkflowEngine\Manager;
use OCP\AppFramework\Http\IOutput;
use OCP\AppFramework\IAppContainer;
@ -33,14 +44,13 @@ use OCP\AppFramework\QueryException;
use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Services\IInitialState;
use OCP\AppFramework\Utility\IControllerMethodReflector;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Files\AppData\IAppDataFactory;
use OCP\Files\Folder;
use OCP\Files\IAppData;
use OCP\Group\ISubAdmin;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IInitialStateService;
use OCP\IL10N;
use OCP\INavigationManager;
use OCP\IRequest;
@ -48,40 +58,24 @@ use OCP\IServerContainer;
use OCP\ISession;
use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\Security\Bruteforce\IThrottler;
use OCP\Security\Ip\IRemoteAddress;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
/**
* @deprecated 20.0.0
*/
class DIContainer extends SimpleContainer implements IAppContainer {
private string $appName;
private array $middleWares = [];
private ServerContainer $server;
/**
* @var array
*/
private $middleWares = [];
/** @var ServerContainer */
private $server;
/**
* Put your class dependencies in here
* @param string $appName the name of the app
* @param array $urlParams
* @param ServerContainer|null $server
*/
public function __construct(string $appName, array $urlParams = [], ?ServerContainer $server = null) {
parent::__construct();
$this->appName = $appName;
$this['appName'] = $appName;
$this['urlParams'] = $urlParams;
$this->registerParameter('appName', $appName);
$this->registerParameter('urlParams', $urlParams);
$this->registerAlias('Request', IRequest::class);
/** @deprecated 32.0.0 */
$this->registerDeprecatedAlias('Request', IRequest::class);
/** @var \OC\ServerContainer $server */
if ($server === null) {
$server = \OC::$server;
}
@ -90,74 +84,73 @@ class DIContainer extends SimpleContainer implements IAppContainer {
// aliases
/** @deprecated 26.0.0 inject $appName */
$this->registerAlias('AppName', 'appName');
$this->registerDeprecatedAlias('AppName', 'appName');
/** @deprecated 26.0.0 inject $webRoot*/
$this->registerAlias('WebRoot', 'webRoot');
$this->registerDeprecatedAlias('WebRoot', 'webRoot');
/** @deprecated 26.0.0 inject $userId */
$this->registerAlias('UserId', 'userId');
$this->registerDeprecatedAlias('UserId', 'userId');
/**
* Core services
*/
$this->registerService(IOutput::class, function () {
return new Output($this->getServer()->getWebRoot());
});
/* Cannot be an alias because Output is not in OCA */
$this->registerService(IOutput::class, fn (ContainerInterface $c): IOutput => new Output($c->get('webRoot')));
$this->registerService(Folder::class, function () {
return $this->getServer()->getUserFolder();
});
$this->registerService(IAppData::class, function (ContainerInterface $c) {
return $this->getServer()->getAppDataDir($c->get('AppName'));
$this->registerService(IAppData::class, function (ContainerInterface $c): IAppData {
return $c->get(IAppDataFactory::class)->get($c->get('appName'));
});
$this->registerService(IL10N::class, function (ContainerInterface $c) {
return $this->getServer()->getL10N($c->get('AppName'));
return $this->getServer()->getL10N($c->get('appName'));
});
// Log wrappers
$this->registerService(LoggerInterface::class, function (ContainerInterface $c) {
/* Cannot be an alias because it uses LoggerInterface so it would infinite loop */
return new ScopedPsrLogger(
$c->get(PsrLoggerAdapter::class),
$c->get('AppName')
$c->get('appName')
);
});
$this->registerService(IServerContainer::class, function () {
return $this->getServer();
});
$this->registerAlias('ServerContainer', IServerContainer::class);
/** @deprecated 32.0.0 */
$this->registerDeprecatedAlias('ServerContainer', IServerContainer::class);
$this->registerService(\OCP\WorkflowEngine\IManager::class, function (ContainerInterface $c) {
return $c->get(Manager::class);
});
$this->registerAlias(\OCP\WorkflowEngine\IManager::class, Manager::class);
$this->registerService(ContainerInterface::class, function (ContainerInterface $c) {
return $c;
});
$this->registerAlias(IAppContainer::class, ContainerInterface::class);
$this->registerService(ContainerInterface::class, fn (ContainerInterface $c) => $c);
$this->registerDeprecatedAlias(IAppContainer::class, ContainerInterface::class);
// commonly used attributes
$this->registerService('userId', function (ContainerInterface $c) {
return $c->get(IUserSession::class)->getSession()->get('user_id');
$this->registerService('userId', function (ContainerInterface $c): ?string {
return $c->get(ISession::class)->get('user_id');
});
$this->registerService('webRoot', function (ContainerInterface $c) {
$this->registerService('webRoot', function (ContainerInterface $c): string {
return $c->get(IServerContainer::class)->getWebRoot();
});
$this->registerService('OC_Defaults', function (ContainerInterface $c) {
$this->registerService('OC_Defaults', function (ContainerInterface $c): object {
return $c->get(IServerContainer::class)->get('ThemingDefaults');
});
$this->registerService('Protocol', function (ContainerInterface $c) {
/** @var \OC\Server $server */
$server = $c->get(IServerContainer::class);
$protocol = $server->getRequest()->getHttpProtocol();
/** @deprecated 32.0.0 */
$this->registerDeprecatedAlias('Protocol', Http::class);
$this->registerService(Http::class, function (ContainerInterface $c) {
$protocol = $c->get(IRequest::class)->getHttpProtocol();
return new Http($_SERVER, $protocol);
});
$this->registerService('Dispatcher', function (ContainerInterface $c) {
/** @deprecated 32.0.0 */
$this->registerDeprecatedAlias('Dispatcher', Dispatcher::class);
$this->registerService(Dispatcher::class, function (ContainerInterface $c) {
return new Dispatcher(
$c->get('Protocol'),
$c->get(MiddlewareDispatcher::class),
@ -181,42 +174,19 @@ class DIContainer extends SimpleContainer implements IAppContainer {
/**
* Middleware
*/
$this->registerAlias('MiddlewareDispatcher', MiddlewareDispatcher::class);
/** @deprecated 32.0.0 */
$this->registerDeprecatedAlias('MiddlewareDispatcher', MiddlewareDispatcher::class);
$this->registerService(MiddlewareDispatcher::class, function (ContainerInterface $c) {
$server = $this->getServer();
$dispatcher = new MiddlewareDispatcher();
$dispatcher->registerMiddleware(
$c->get(OC\AppFramework\Middleware\CompressionMiddleware::class)
);
$dispatcher->registerMiddleware($c->get(OC\AppFramework\Middleware\NotModifiedMiddleware::class));
$dispatcher->registerMiddleware(
$c->get(OC\AppFramework\Middleware\Security\ReloadExecutionMiddleware::class)
);
$dispatcher->registerMiddleware(
new OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware(
$c->get(IRequest::class),
$c->get(IControllerMethodReflector::class)
)
);
$dispatcher->registerMiddleware(
new CORSMiddleware(
$c->get(IRequest::class),
$c->get(IControllerMethodReflector::class),
$c->get(IUserSession::class),
$c->get(IThrottler::class),
$c->get(LoggerInterface::class)
)
);
$dispatcher->registerMiddleware(
new OCSMiddleware(
$c->get(IRequest::class)
)
);
$dispatcher->registerMiddleware($c->get(CompressionMiddleware::class));
$dispatcher->registerMiddleware($c->get(NotModifiedMiddleware::class));
$dispatcher->registerMiddleware($c->get(ReloadExecutionMiddleware::class));
$dispatcher->registerMiddleware($c->get(SameSiteCookieMiddleware::class));
$dispatcher->registerMiddleware($c->get(CORSMiddleware::class));
$dispatcher->registerMiddleware($c->get(OCSMiddleware::class));
$dispatcher->registerMiddleware($c->get(FlowV2EphemeralSessionsMiddleware::class));
@ -225,75 +195,31 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$c->get(IControllerMethodReflector::class),
$c->get(INavigationManager::class),
$c->get(IURLGenerator::class),
$server->get(LoggerInterface::class),
$c->get('AppName'),
$c->get(LoggerInterface::class),
$c->get('appName'),
$server->getUserSession()->isLoggedIn(),
$c->get(IGroupManager::class),
$c->get(ISubAdmin::class),
$server->getAppManager(),
$server->getL10N('lib'),
$c->get(AuthorizedGroupMapper::class),
$server->get(IUserSession::class),
$c->get(IUserSession::class),
$c->get(IRemoteAddress::class),
);
$dispatcher->registerMiddleware($securityMiddleware);
$dispatcher->registerMiddleware(
new OC\AppFramework\Middleware\Security\CSPMiddleware(
$server->query(OC\Security\CSP\ContentSecurityPolicyManager::class),
$server->query(OC\Security\CSP\ContentSecurityPolicyNonceManager::class),
)
);
$dispatcher->registerMiddleware(
$server->query(OC\AppFramework\Middleware\Security\FeaturePolicyMiddleware::class)
);
$dispatcher->registerMiddleware(
new OC\AppFramework\Middleware\Security\PasswordConfirmationMiddleware(
$c->get(IControllerMethodReflector::class),
$c->get(ISession::class),
$c->get(IUserSession::class),
$c->get(ITimeFactory::class),
$c->get(\OC\Authentication\Token\IProvider::class),
$c->get(LoggerInterface::class),
$c->get(IRequest::class),
$c->get(UserManager::class),
)
);
$dispatcher->registerMiddleware(
new TwoFactorMiddleware(
$c->get(OC\Authentication\TwoFactorAuth\Manager::class),
$c->get(IUserSession::class),
$c->get(ISession::class),
$c->get(IURLGenerator::class),
$c->get(IControllerMethodReflector::class),
$c->get(IRequest::class)
)
);
$dispatcher->registerMiddleware(
new OC\AppFramework\Middleware\Security\BruteForceMiddleware(
$c->get(IControllerMethodReflector::class),
$c->get(IThrottler::class),
$c->get(IRequest::class),
$c->get(LoggerInterface::class)
)
);
$dispatcher->registerMiddleware($c->get(CSPMiddleware::class));
$dispatcher->registerMiddleware($c->get(FeaturePolicyMiddleware::class));
$dispatcher->registerMiddleware($c->get(PasswordConfirmationMiddleware::class));
$dispatcher->registerMiddleware($c->get(TwoFactorMiddleware::class));
$dispatcher->registerMiddleware($c->get(BruteForceMiddleware::class));
$dispatcher->registerMiddleware($c->get(RateLimitingMiddleware::class));
$dispatcher->registerMiddleware(
new OC\AppFramework\Middleware\PublicShare\PublicShareMiddleware(
$c->get(IRequest::class),
$c->get(ISession::class),
$c->get(IConfig::class),
$c->get(IThrottler::class)
)
);
$dispatcher->registerMiddleware(
$c->get(\OC\AppFramework\Middleware\AdditionalScriptsMiddleware::class)
);
$dispatcher->registerMiddleware($c->get(PublicShareMiddleware::class));
$dispatcher->registerMiddleware($c->get(AdditionalScriptsMiddleware::class));
/** @var \OC\AppFramework\Bootstrap\Coordinator $coordinator */
$coordinator = $c->get(\OC\AppFramework\Bootstrap\Coordinator::class);
$registrationContext = $coordinator->getRegistrationContext();
if ($registrationContext !== null) {
$appId = $this->getAppName();
$appId = $this->get('appName');
foreach ($registrationContext->getMiddlewareRegistrations() as $middlewareRegistration) {
if ($middlewareRegistration->getAppId() === $appId
|| $middlewareRegistration->isGlobal()) {
@ -305,28 +231,12 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$dispatcher->registerMiddleware($c->get($middleWare));
}
$dispatcher->registerMiddleware(
new SessionMiddleware(
$c->get(IControllerMethodReflector::class),
$c->get(ISession::class)
)
);
$dispatcher->registerMiddleware($c->get(SessionMiddleware::class));
return $dispatcher;
});
$this->registerService(IAppConfig::class, function (ContainerInterface $c) {
return new OC\AppFramework\Services\AppConfig(
$c->get(IConfig::class),
$c->get(\OCP\IAppConfig::class),
$c->get('AppName')
);
});
$this->registerService(IInitialState::class, function (ContainerInterface $c) {
return new OC\AppFramework\Services\InitialState(
$c->get(IInitialStateService::class),
$c->get('AppName')
);
});
$this->registerAlias(IAppConfig::class, \OC\AppFramework\Services\AppConfig::class);
$this->registerAlias(IInitialState::class, \OC\AppFramework\Services\InitialState::class);
}
/**
@ -338,13 +248,13 @@ class DIContainer extends SimpleContainer implements IAppContainer {
/**
* @param string $middleWare
* @return boolean|null
*/
public function registerMiddleWare($middleWare) {
public function registerMiddleWare($middleWare): bool {
if (in_array($middleWare, $this->middleWares, true) !== false) {
return false;
}
$this->middleWares[] = $middleWare;
return true;
}
/**
@ -352,7 +262,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
* @return string the name of your application
*/
public function getAppName() {
return $this->query('AppName');
return $this->query('appName');
}
/**
@ -372,7 +282,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
return \OC_User::isAdminUser($uid);
}
private function getUserId() {
private function getUserId(): string {
return $this->getServer()->getSession()->get('user_id');
}
@ -439,6 +349,12 @@ class DIContainer extends SimpleContainer implements IAppContainer {
return parent::query($name);
} elseif (str_starts_with($name, \OC\AppFramework\App::buildAppNamespace($this->appName) . '\\')) {
return parent::query($name);
} elseif (
str_starts_with($name, 'OC\\AppFramework\\Services\\')
|| str_starts_with($name, 'OC\\AppFramework\\Middleware\\')
) {
/* AppFramework services are scoped to the application */
return parent::query($name);
}
throw new QueryException('Could not resolve ' . $name . '!'

View file

@ -64,7 +64,8 @@ class Dispatcher {
* @param LoggerInterface $logger
* @param IEventLogger $eventLogger
*/
public function __construct(Http $protocol,
public function __construct(
Http $protocol,
MiddlewareDispatcher $middlewareDispatcher,
ControllerMethodReflector $reflector,
IRequest $request,
@ -72,7 +73,8 @@ class Dispatcher {
ConnectionAdapter $connection,
LoggerInterface $logger,
IEventLogger $eventLogger,
ContainerInterface $appContainer) {
ContainerInterface $appContainer,
) {
$this->protocol = $protocol;
$this->middlewareDispatcher = $middlewareDispatcher;
$this->reflector = $reflector;

View file

@ -13,14 +13,9 @@ use OCP\AppFramework\Http\IOutput;
* Very thin wrapper class to make output testable
*/
class Output implements IOutput {
/** @var string */
private $webRoot;
/**
* @param $webRoot
*/
public function __construct($webRoot) {
$this->webRoot = $webRoot;
public function __construct(
private string $webRoot,
) {
}
/**

View file

@ -14,16 +14,10 @@ use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Middleware;
class SameSiteCookieMiddleware extends Middleware {
/** @var Request */
private $request;
/** @var ControllerMethodReflector */
private $reflector;
public function __construct(Request $request,
ControllerMethodReflector $reflector) {
$this->request = $request;
$this->reflector = $reflector;
public function __construct(
private Request $request,
private ControllerMethodReflector $reflector,
) {
}
public function beforeController($controller, $methodName) {
@ -59,7 +53,7 @@ class SameSiteCookieMiddleware extends Middleware {
throw $exception;
}
protected function setSameSiteCookie() {
protected function setSameSiteCookie(): void {
$cookieParams = $this->request->getCookieParams();
$secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
$policies = [

View file

@ -14,6 +14,7 @@ use OCP\IContainer;
use Pimple\Container;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use ReflectionClass;
use ReflectionException;
use ReflectionNamedType;
@ -185,8 +186,21 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer {
* @param string $alias the alias that should be registered
* @param string $target the target that should be resolved instead
*/
public function registerAlias($alias, $target) {
$this->registerService($alias, function (ContainerInterface $container) use ($target) {
public function registerAlias($alias, $target): void {
$this->registerService($alias, function (ContainerInterface $container) use ($target): mixed {
return $container->get($target);
}, false);
}
protected function registerDeprecatedAlias(string $alias, string $target): void {
$this->registerService($alias, function (ContainerInterface $container) use ($target, $alias): mixed {
try {
$logger = $container->get(LoggerInterface::class);
$logger->debug('The requested alias "' . $alias . '" is deprecated. Please request "' . $target . '" directly. This alias will be removed in a future Nextcloud version.', ['app' => 'serverDI']);
} catch (ContainerExceptionInterface $e) {
// Could not get logger. Continue
}
return $container->get($target);
}, false);
}

View file

@ -14,7 +14,7 @@ use OCP\Broadcast\Events\IBroadcastEvent;
use OCP\EventDispatcher\ABroadcastedEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IServerContainer;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcher as SymfonyDispatcher;
use function get_class;
@ -22,7 +22,7 @@ use function get_class;
class EventDispatcher implements IEventDispatcher {
public function __construct(
private SymfonyDispatcher $dispatcher,
private IServerContainer $container,
private ContainerInterface $container,
private LoggerInterface $logger,
) {
// inject the event dispatcher into the logger

View file

@ -12,7 +12,7 @@ namespace OC\EventDispatcher;
use OCP\AppFramework\QueryException;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IServerContainer;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use function sprintf;
@ -23,24 +23,13 @@ use function sprintf;
* created by the service container
*/
final class ServiceEventListener {
/** @var IServerContainer */
private $container;
private ?IEventListener $service = null;
/** @var string */
private $class;
/** @var LoggerInterface */
private $logger;
/** @var null|IEventListener */
private $service;
public function __construct(IServerContainer $container,
string $class,
LoggerInterface $logger) {
$this->container = $container;
$this->class = $class;
$this->logger = $logger;
public function __construct(
private ContainerInterface $container,
private string $class,
private LoggerInterface $logger,
) {
}
public function __invoke(Event $event) {
@ -49,7 +38,7 @@ final class ServiceEventListener {
// TODO: fetch from the app containers, otherwise any custom services,
// parameters and aliases won't be resolved.
// See https://github.com/nextcloud/server/issues/27793 for details.
$this->service = $this->container->query($this->class);
$this->service = $this->container->get($this->class);
} catch (QueryException $e) {
$this->logger->error(
sprintf(

View file

@ -238,7 +238,6 @@ use OCP\User\Events\UserLoggedInEvent;
use OCP\User\Events\UserLoggedInWithCookieEvent;
use OCP\User\Events\UserLoggedOutEvent;
use OCP\User\IAvailabilityCoordinator;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
@ -268,9 +267,7 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService(ContainerInterface::class, function (ContainerInterface $c) {
return $c;
});
$this->registerService(\OCP\IServerContainer::class, function (ContainerInterface $c) {
return $c;
});
$this->registerDeprecatedAlias(\OCP\IServerContainer::class, ContainerInterface::class);
$this->registerAlias(\OCP\Calendar\IManager::class, \OC\Calendar\Manager::class);
@ -874,7 +871,7 @@ class Server extends ServerContainer implements IServerContainer {
$c->get(IMimeTypeDetector::class)
);
});
$this->registerService(\OCP\IRequest::class, function (ContainerInterface $c) {
$this->registerService(Request::class, function (ContainerInterface $c) {
if (isset($this['urlParams'])) {
$urlParams = $this['urlParams'];
} else {
@ -908,6 +905,7 @@ class Server extends ServerContainer implements IServerContainer {
$stream
);
});
$this->registerAlias(\OCP\IRequest::class, Request::class);
$this->registerService(IRequestId::class, function (ContainerInterface $c): IRequestId {
return new RequestId(
@ -1682,7 +1680,6 @@ class Server extends ServerContainer implements IServerContainer {
* @deprecated 20.0.0 Use get(\OCP\Files\AppData\IAppDataFactory::class)->get($app) instead
*/
public function getAppDataDir($app) {
/** @var \OC\Files\AppData\Factory $factory */
$factory = $this->get(\OC\Files\AppData\Factory::class);
return $factory->get($app);
}
@ -1694,18 +1691,4 @@ class Server extends ServerContainer implements IServerContainer {
public function getCloudIdManager() {
return $this->get(ICloudIdManager::class);
}
private function registerDeprecatedAlias(string $alias, string $target) {
$this->registerService($alias, function (ContainerInterface $container) use ($target, $alias) {
try {
/** @var LoggerInterface $logger */
$logger = $container->get(LoggerInterface::class);
$logger->debug('The requested alias "' . $alias . '" is deprecated. Please request "' . $target . '" directly. This alias will be removed in a future Nextcloud version.', ['app' => 'serverDI']);
} catch (ContainerExceptionInterface $e) {
// Could not get logger. Continue
}
return $container->get($target);
}, false);
}
}

View file

@ -6,11 +6,12 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Support\CrashReport;
use Exception;
use OCP\AppFramework\QueryException;
use OCP\IServerContainer;
use OCP\Server;
use OCP\Support\CrashReport\ICollectBreadcrumbs;
use OCP\Support\CrashReport\IMessageReporter;
use OCP\Support\CrashReport\IRegistry;
@ -26,17 +27,8 @@ class Registry implements IRegistry {
/** @var IReporter[] */
private $reporters = [];
/** @var IServerContainer */
private $serverContainer;
public function __construct(IServerContainer $serverContainer) {
$this->serverContainer = $serverContainer;
}
/**
* Register a reporter instance
*
* @param IReporter $reporter
*/
public function register(IReporter $reporter): void {
$this->reporters[] = $reporter;
@ -49,10 +41,6 @@ class Registry implements IRegistry {
/**
* Delegate breadcrumb collection to all registered reporters
*
* @param string $message
* @param string $category
* @param array $context
*
* @since 15.0.0
*/
public function delegateBreadcrumb(string $message, string $category, array $context = []): void {
@ -69,7 +57,6 @@ class Registry implements IRegistry {
* Delegate crash reporting to all registered reporters
*
* @param Exception|Throwable $exception
* @param array $context
*/
public function delegateReport($exception, array $context = []): void {
$this->loadLazyProviders();
@ -82,9 +69,6 @@ class Registry implements IRegistry {
/**
* Delegate a message to all reporters that implement IMessageReporter
*
* @param string $message
* @param array $context
*
* @return void
*/
public function delegateMessage(string $message, array $context = []): void {
@ -101,13 +85,13 @@ class Registry implements IRegistry {
while (($class = array_shift($this->lazyReporters)) !== null) {
try {
/** @var IReporter $reporter */
$reporter = $this->serverContainer->query($class);
$reporter = Server::get($class);
} catch (QueryException $e) {
/*
* There is a circular dependency between the logger and the registry, so
* we can not inject it. Thus the static call.
*/
\OC::$server->get(LoggerInterface::class)->critical('Could not load lazy crash reporter: ' . $e->getMessage(), [
Server::get(LoggerInterface::class)->critical('Could not load lazy crash reporter: ' . $e->getMessage(), [
'exception' => $e,
]);
return;
@ -123,7 +107,7 @@ class Registry implements IRegistry {
* There is a circular dependency between the logger and the registry, so
* we can not inject it. Thus the static call.
*/
\OC::$server->get(LoggerInterface::class)->critical('Could not register lazy crash reporter: ' . $e->getMessage(), [
Server::get(LoggerInterface::class)->critical('Could not register lazy crash reporter: ' . $e->getMessage(), [
'exception' => $e,
]);
}

View file

@ -29,7 +29,7 @@ function rrmdir($directory) {
class AppTest extends \Test\TestCase {
private $container;
private DIContainer $container;
private $io;
private $api;
private $controller;
@ -55,8 +55,8 @@ class AppTest extends \Test\TestCase {
$this->controllerMethod = 'method';
$this->container[$this->controllerName] = $this->controller;
$this->container['Dispatcher'] = $this->dispatcher;
$this->container['OCP\\AppFramework\\Http\\IOutput'] = $this->io;
$this->container[Dispatcher::class] = $this->dispatcher;
$this->container[IOutput::class] = $this->io;
$this->container['urlParams'] = ['_route' => 'not-profiler'];
$this->appPath = __DIR__ . '/../../../apps/namespacetestapp';
@ -165,7 +165,7 @@ class AppTest extends \Test\TestCase {
}
public function testCoreApp(): void {
$this->container['AppName'] = 'core';
$this->container['appName'] = 'core';
$this->container['OC\Core\Controller\Foo'] = $this->controller;
$this->container['urlParams'] = ['_route' => 'not-profiler'];
@ -183,7 +183,7 @@ class AppTest extends \Test\TestCase {
}
public function testSettingsApp(): void {
$this->container['AppName'] = 'settings';
$this->container['appName'] = 'settings';
$this->container['OCA\Settings\Controller\Foo'] = $this->controller;
$this->container['urlParams'] = ['_route' => 'not-profiler'];
@ -201,7 +201,7 @@ class AppTest extends \Test\TestCase {
}
public function testApp(): void {
$this->container['AppName'] = 'bar';
$this->container['appName'] = 'bar';
$this->container['OCA\Bar\Controller\Foo'] = $this->controller;
$this->container['urlParams'] = ['_route' => 'not-profiler'];

View file

@ -18,13 +18,13 @@ use OCP\AppFramework\Middleware;
use OCP\AppFramework\QueryException;
use OCP\IConfig;
use OCP\IRequestId;
use PHPUnit\Framework\MockObject\MockObject;
/**
* @group DB
*/
class DIContainerTest extends \Test\TestCase {
/** @var DIContainer|\PHPUnit\Framework\MockObject\MockObject */
private $container;
private DIContainer&MockObject $container;
protected function setUp(): void {
parent::setUp();
@ -45,11 +45,13 @@ class DIContainerTest extends \Test\TestCase {
public function testProvidesAppName(): void {
$this->assertTrue(isset($this->container['AppName']));
$this->assertTrue(isset($this->container['appName']));
}
public function testAppNameIsSetCorrectly(): void {
$this->assertEquals('name', $this->container['AppName']);
$this->assertEquals('name', $this->container['appName']);
}
public function testMiddlewareDispatcherIncludesSecurityMiddleware(): void {

View file

@ -12,27 +12,18 @@ namespace Test\Support\CrashReport;
use Exception;
use OC\Support\CrashReport\Registry;
use OCP\AppFramework\QueryException;
use OCP\IServerContainer;
use OCP\Support\CrashReport\ICollectBreadcrumbs;
use OCP\Support\CrashReport\IMessageReporter;
use OCP\Support\CrashReport\IReporter;
use Test\TestCase;
class RegistryTest extends TestCase {
/** @var IServerContainer|\PHPUnit\Framework\MockObject\MockObject */
private $serverContainer;
/** @var Registry */
private $registry;
private Registry $registry;
protected function setUp(): void {
parent::setUp();
$this->serverContainer = $this->createMock(IServerContainer::class);
$this->registry = new Registry(
$this->serverContainer
);
$this->registry = new Registry();
}
/**
@ -45,13 +36,10 @@ class RegistryTest extends TestCase {
$this->addToAssertionCount(1);
}
public function testRegisterLazyCantLoad(): void {
public function testRegisterLazy(): void {
$reporterClass = '\OCA\MyApp\Reporter';
$reporter = $this->createMock(IReporter::class);
$this->serverContainer->expects($this->once())
->method('query')
->with($reporterClass)
->willReturn($reporter);
$this->overwriteService($reporterClass, $reporter);
$reporter->expects($this->once())
->method('report');
$exception = new Exception('test');
@ -60,16 +48,17 @@ class RegistryTest extends TestCase {
$this->registry->delegateReport($exception);
}
public function testRegisterLazy(): void {
/**
* Doesn't assert anything, just checks whether anything "explodes"
*/
public function testRegisterLazyCantLoad(): void {
$reporterClass = '\OCA\MyApp\Reporter';
$this->serverContainer->expects($this->once())
->method('query')
->with($reporterClass)
->willThrowException(new QueryException());
/* We do not register reporterClass in DI, so it will throw a QueryException queried */
$exception = new Exception('test');
$this->registry->registerLazy($reporterClass);
$this->registry->delegateReport($exception);
$this->addToAssertionCount(1);
}
public function testDelegateBreadcrumbCollection(): void {

View file

@ -21,6 +21,7 @@ use OC\Files\ObjectStore\PrimaryObjectStoreConfig;
use OC\Files\SetupManager;
use OC\Files\View;
use OC\Template\Base;
use OCP\AppFramework\QueryException;
use OCP\Command\IBus;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Defaults;
@ -91,7 +92,11 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase {
return false;
}
$this->services[$name] = Server::get($name);
try {
$this->services[$name] = Server::get($name);
} catch (QueryException $e) {
$this->services[$name] = false;
}
$container = \OC::$server->getAppContainerForService($name);
$container = $container ?? \OC::$server;
@ -113,9 +118,13 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase {
$container = \OC::$server->getAppContainerForService($name);
$container = $container ?? \OC::$server;
$container->registerService($name, function () use ($oldService) {
return $oldService;
});
if ($oldService !== false) {
$container->registerService($name, function () use ($oldService) {
return $oldService;
});
} else {
unset($container[$oldService]);
}
unset($this->services[$name]);