Merge pull request #58355 from nextcloud/fix/ocp/container

fix(IRegistrationContext): Use IContainer in registerService factory
This commit is contained in:
Kate 2026-02-16 13:36:37 +01:00 committed by GitHub
commit 35f24bcd38
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 46 additions and 47 deletions

View file

@ -11,6 +11,7 @@ return (require __DIR__ . '/rector-shared.php')
->withPaths([
$nextcloudDir . '/build/rector-strict.php',
$nextcloudDir . '/core/BackgroundJobs/ExpirePreviewsJob.php',
$nextcloudDir . '/lib/public/IContainer.php',
])
->withPreparedSets(
deadCode: true,

View file

@ -326,7 +326,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
* @inheritDoc
* @param list<class-string> $chain
*/
public function query(string $name, bool $autoload = true, array $chain = []) {
public function query(string $name, bool $autoload = true, array $chain = []): mixed {
if ($name === 'AppName' || $name === 'appName') {
return $this->appName;
}

View file

@ -120,7 +120,7 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer {
* @inheritDoc
* @param list<class-string> $chain
*/
public function resolve($name, array $chain = []) {
public function resolve(string $name, array $chain = []): mixed {
$baseMsg = 'Could not resolve ' . $name . '!';
try {
$class = new ReflectionClass($name);
@ -140,7 +140,7 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer {
* @inheritDoc
* @param list<class-string> $chain
*/
public function query(string $name, bool $autoload = true, array $chain = []) {
public function query(string $name, bool $autoload = true, array $chain = []): mixed {
$name = $this->sanitizeName($name);
if (isset($this->container[$name])) {
return $this->container[$name];
@ -161,15 +161,11 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer {
throw new QueryNotFoundException('Could not resolve ' . $name . '!');
}
/**
* @param string $name
* @param mixed $value
*/
public function registerParameter($name, $value) {
public function registerParameter(string $name, mixed $value): void {
$this[$name] = $value;
}
public function registerService($name, Closure $closure, $shared = true) {
public function registerService(string $name, Closure $closure, bool $shared = true): void {
$wrapped = function () use ($closure) {
return $closure($this);
};
@ -191,7 +187,7 @@ 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): void {
public function registerAlias(string $alias, string $target): void {
$this->registerService($alias, function (ContainerInterface $container) use ($target): mixed {
return $container->get($target);
}, false);

View file

@ -119,7 +119,7 @@ class ServerContainer extends SimpleContainer {
* @throws QueryException
* @deprecated 20.0.0 use \Psr\Container\ContainerInterface::get
*/
public function query(string $name, bool $autoload = true, array $chain = []) {
public function query(string $name, bool $autoload = true, array $chain = []): mixed {
$name = $this->sanitizeName($name);
if (str_starts_with($name, 'OCA\\')) {

View file

@ -9,7 +9,6 @@ declare(strict_types=1);
namespace OCP\AppFramework\Bootstrap;
use OC\AppFramework\Utility\SimpleContainer;
use OCP\AppFramework\IAppContainer;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Calendar\ICalendarProvider;
@ -69,7 +68,7 @@ interface IRegistrationContext {
*
* @param string $name
* @param callable $factory
* @psalm-param callable(SimpleContainer): mixed $factory
* @psalm-param callable(IContainer): mixed $factory
* @param bool $shared If set to true the factory result will be cached otherwise every query will call the factory again
*
* @return void

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@ -7,11 +9,9 @@
*/
// use OCP namespace for all classes that are considered public.
// This means that they should be used by apps instead of the internal Nextcloud classes
namespace OCP;
use Closure;
use OC\AppFramework\Utility\SimpleContainer;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
@ -22,51 +22,56 @@ use Psr\Container\NotFoundExceptionInterface;
* IContainer is the basic interface to be used for any internal dependency injection mechanism
*
* @since 6.0.0
* @deprecated 20.0.0 use \Psr\Container\ContainerInterface
*/
interface IContainer extends ContainerInterface {
/**
* Finds an entry of the container by its identifier and returns it.
*
* @template T
* @param class-string<T>|string $id Identifier of the entry to look for.
*
* @throws NotFoundExceptionInterface No entry was found for **this** identifier.
* @throws ContainerExceptionInterface Error while retrieving the entry.
*
* @return ($id is class-string<T> ? T : mixed) Entry.
* @since 34.0.0
*/
public function get(string $id);
/**
* @template T
*
* If a parameter is not registered in the container try to instantiate it
* by using reflection to find out how to build the class
* @param string $name the class name to resolve
* @psalm-param string|class-string<T> $name
* @return \stdClass
* @psalm-return ($name is class-string ? T : mixed)
* @param class-string<T>|string $name
* @return ($name is class-string<T> ? T : mixed)
* @since 8.2.0
* @deprecated 20.0.0 use \Psr\Container\ContainerInterface::get
* @deprecated 20.0.0 use {@see self::get()}
* @throws ContainerExceptionInterface if the class could not be found or instantiated
*/
public function resolve($name);
public function resolve(string $name): mixed;
/**
* Look up a service for a given name in the container.
*
* @template T
*
* @param string $name
* @psalm-param string|class-string<T> $name
* @param class-string<T>|string $name
* @param bool $autoload Should we try to autoload the service. If we are trying to resolve built in types this makes no sense for example
* @return mixed
* @psalm-return ($name is class-string ? T : mixed)
* @return ($name is class-string<T> ? T : mixed)
* @throws ContainerExceptionInterface if the query could not be resolved
* @throws NotFoundExceptionInterface if the name could not be found within the container
* @since 6.0.0
* @deprecated 20.0.0 use \Psr\Container\ContainerInterface::get
* @deprecated 20.0.0 use {@see self::get()}
*/
public function query(string $name, bool $autoload = true);
public function query(string $name, bool $autoload = true): mixed;
/**
* A value is stored in the container with it's corresponding name
*
* @param string $name
* @param mixed $value
* @return void
* @since 6.0.0
* @deprecated 20.0.0 use \OCP\AppFramework\Bootstrap\IRegistrationContext::registerParameter
*/
public function registerParameter($name, $value);
public function registerParameter(string $name, mixed $value): void;
/**
* A service is registered in the container where a closure is passed in which will actually
@ -75,14 +80,11 @@ interface IContainer extends ContainerInterface {
* memory and be reused on subsequent calls.
* In case the parameter is false the service will be recreated on every call.
*
* @param string $name
* @param \Closure(SimpleContainer): mixed $closure
* @param bool $shared
* @return void
* @param \Closure(IContainer): mixed $closure
* @since 6.0.0
* @deprecated 20.0.0 use \OCP\AppFramework\Bootstrap\IRegistrationContext::registerService
*/
public function registerService($name, Closure $closure, $shared = true);
public function registerService(string $name, Closure $closure, bool $shared = true): void;
/**
* Shortcut for returning a service from a service under a different key,
@ -93,5 +95,5 @@ interface IContainer extends ContainerInterface {
* @since 8.2.0
* @deprecated 20.0.0 use \OCP\AppFramework\Bootstrap\IRegistrationContext::registerServiceAlias
*/
public function registerAlias($alias, $target);
public function registerAlias(string $alias, string $target): void;
}

View file

@ -17,6 +17,7 @@
>
<projectFiles>
<file name="core/BackgroundJobs/ExpirePreviewsJob.php"/>
<file name="lib/public/IContainer.php"/>
<ignoreFiles>
<directory name="apps/**/composer"/>
<directory name="apps/**/tests"/>

View file

@ -91,22 +91,22 @@ class SearchTest extends TestCase {
->willReturnCallback(function ($class) use ($searchResult, $userPlugin, $groupPlugin, $remotePlugin, $mailPlugin) {
if ($class === SearchResult::class) {
return $searchResult;
} elseif ($class === $userPlugin) {
} elseif ($class === 'user') {
return $userPlugin;
} elseif ($class === $groupPlugin) {
} elseif ($class === 'group') {
return $groupPlugin;
} elseif ($class === $remotePlugin) {
} elseif ($class === 'remote') {
return $remotePlugin;
} elseif ($class === $mailPlugin) {
} elseif ($class === 'mail') {
return $mailPlugin;
}
return null;
});
$this->search->registerPlugin(['shareType' => 'SHARE_TYPE_USER', 'class' => $userPlugin]);
$this->search->registerPlugin(['shareType' => 'SHARE_TYPE_GROUP', 'class' => $groupPlugin]);
$this->search->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE', 'class' => $remotePlugin]);
$this->search->registerPlugin(['shareType' => 'SHARE_TYPE_EMAIL', 'class' => $mailPlugin]);
$this->search->registerPlugin(['shareType' => 'SHARE_TYPE_USER', 'class' => 'user']);
$this->search->registerPlugin(['shareType' => 'SHARE_TYPE_GROUP', 'class' => 'group']);
$this->search->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE', 'class' => 'remote']);
$this->search->registerPlugin(['shareType' => 'SHARE_TYPE_EMAIL', 'class' => 'mail']);
[$results, $moreResults] = $this->search->search($searchTerm, $shareTypes, false, $perPage, $perPage * ($page - 1));