Use PSR container interface and deprecate our own abstraction

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
This commit is contained in:
Christoph Wurst 2020-07-13 11:18:14 +02:00
parent b12d3691c3
commit 4152216bd8
No known key found for this signature in database
GPG Key ID: CC42AC2A7F0E56D8
10 changed files with 249 additions and 145 deletions

@ -1 +1 @@
Subproject commit 8460f552fbf8ee468734225fa6a890cde4beb964 Subproject commit 10acc20198442f3c04bc1abbf9ad540a3afbab40

View File

@ -69,7 +69,11 @@ use OCP\IServerContainer;
use OCP\ISession; use OCP\ISession;
use OCP\IURLGenerator; use OCP\IURLGenerator;
use OCP\IUserSession; use OCP\IUserSession;
use Psr\Container\ContainerInterface;
/**
* @deprecated 20.0.0
*/
class DIContainer extends SimpleContainer implements IAppContainer { class DIContainer extends SimpleContainer implements IAppContainer {
/** /**
@ -116,17 +120,17 @@ class DIContainer extends SimpleContainer implements IAppContainer {
return $this->getServer()->getUserFolder(); return $this->getServer()->getUserFolder();
}); });
$this->registerService(IAppData::class, function (SimpleContainer $c) { $this->registerService(IAppData::class, function (ContainerInterface $c) {
return $this->getServer()->getAppDataDir($c->query('AppName')); return $this->getServer()->getAppDataDir($c->get('AppName'));
}); });
$this->registerService(IL10N::class, function ($c) { $this->registerService(IL10N::class, function (ContainerInterface $c) {
return $this->getServer()->getL10N($c->query('AppName')); return $this->getServer()->getL10N($c->get('AppName'));
}); });
// Log wrapper // Log wrapper
$this->registerService(ILogger::class, function ($c) { $this->registerService(ILogger::class, function (ContainerInterface $c) {
return new OC\AppFramework\Logger($this->server->query(ILogger::class), $c->query('AppName')); return new OC\AppFramework\Logger($this->server->query(ILogger::class), $c->get('AppName'));
}); });
$this->registerService(IServerContainer::class, function () { $this->registerService(IServerContainer::class, function () {
@ -134,40 +138,41 @@ class DIContainer extends SimpleContainer implements IAppContainer {
}); });
$this->registerAlias('ServerContainer', IServerContainer::class); $this->registerAlias('ServerContainer', IServerContainer::class);
$this->registerService(\OCP\WorkflowEngine\IManager::class, function ($c) { $this->registerService(\OCP\WorkflowEngine\IManager::class, function (ContainerInterface $c) {
return $c->query(Manager::class); return $c->get(Manager::class);
}); });
$this->registerService(\OCP\AppFramework\IAppContainer::class, function ($c) { $this->registerService(ContainerInterface::class, function (ContainerInterface $c) {
return $c; return $c;
}); });
$this->registerAlias(IAppContainer::class, ContainerInterface::class);
// commonly used attributes // commonly used attributes
$this->registerService('UserId', function ($c) { $this->registerService('UserId', function (ContainerInterface $c) {
return $c->query(IUserSession::class)->getSession()->get('user_id'); return $c->get(IUserSession::class)->getSession()->get('user_id');
}); });
$this->registerService('WebRoot', function ($c) { $this->registerService('WebRoot', function (ContainerInterface $c) {
return $c->query('ServerContainer')->getWebRoot(); return $c->get(IServerContainer::class)->getWebRoot();
}); });
$this->registerService('OC_Defaults', function ($c) { $this->registerService('OC_Defaults', function (ContainerInterface $c) {
return $c->getServer()->getThemingDefaults(); return $c->get(IServerContainer::class)->getThemingDefaults();
}); });
$this->registerService('Protocol', function ($c) { $this->registerService('Protocol', function (ContainerInterface $c) {
/** @var \OC\Server $server */ /** @var \OC\Server $server */
$server = $c->query('ServerContainer'); $server = $c->get(IServerContainer::class);
$protocol = $server->getRequest()->getHttpProtocol(); $protocol = $server->getRequest()->getHttpProtocol();
return new Http($_SERVER, $protocol); return new Http($_SERVER, $protocol);
}); });
$this->registerService('Dispatcher', function ($c) { $this->registerService('Dispatcher', function (ContainerInterface $c) {
return new Dispatcher( return new Dispatcher(
$c['Protocol'], $c->get('Protocol'),
$c['MiddlewareDispatcher'], $c->get(MiddlewareDispatcher::class),
$c->query(IControllerMethodReflector::class), $c->get(IControllerMethodReflector::class),
$c['Request'] $c->get(IRequest::class)
); );
}); });
@ -181,48 +186,49 @@ class DIContainer extends SimpleContainer implements IAppContainer {
/** /**
* Middleware * Middleware
*/ */
$this->registerService('MiddlewareDispatcher', function (SimpleContainer $c) { $this->registerAlias('MiddlewareDispatcher', MiddlewareDispatcher::class);
$this->registerService(MiddlewareDispatcher::class, function (ContainerInterface $c) {
$server = $this->getServer(); $server = $this->getServer();
$dispatcher = new MiddlewareDispatcher(); $dispatcher = new MiddlewareDispatcher();
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
$c->query(OC\AppFramework\Middleware\CompressionMiddleware::class) $c->get(OC\AppFramework\Middleware\CompressionMiddleware::class)
); );
$dispatcher->registerMiddleware($c->query(OC\AppFramework\Middleware\NotModifiedMiddleware::class)); $dispatcher->registerMiddleware($c->get(OC\AppFramework\Middleware\NotModifiedMiddleware::class));
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
$c->query(OC\AppFramework\Middleware\Security\ReloadExecutionMiddleware::class) $c->get(OC\AppFramework\Middleware\Security\ReloadExecutionMiddleware::class)
); );
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
new OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware( new OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware(
$c->query(IRequest::class), $c->get(IRequest::class),
$c->query(IControllerMethodReflector::class) $c->get(IControllerMethodReflector::class)
) )
); );
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
new CORSMiddleware( new CORSMiddleware(
$c->query(IRequest::class), $c->get(IRequest::class),
$c->query(IControllerMethodReflector::class), $c->get(IControllerMethodReflector::class),
$c->query(IUserSession::class), $c->get(IUserSession::class),
$c->query(OC\Security\Bruteforce\Throttler::class) $c->get(OC\Security\Bruteforce\Throttler::class)
) )
); );
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
new OCSMiddleware( new OCSMiddleware(
$c->query(IRequest::class) $c->get(IRequest::class)
) )
); );
$securityMiddleware = new SecurityMiddleware( $securityMiddleware = new SecurityMiddleware(
$c->query(IRequest::class), $c->get(IRequest::class),
$c->query(IControllerMethodReflector::class), $c->get(IControllerMethodReflector::class),
$c->query(INavigationManager::class), $c->get(INavigationManager::class),
$c->query(IURLGenerator::class), $c->get(IURLGenerator::class),
$server->getLogger(), $server->query(ILogger::class),
$c['AppName'], $c->get('AppName'),
$server->getUserSession()->isLoggedIn(), $server->getUserSession()->isLoggedIn(),
$server->getGroupManager()->isAdmin($this->getUserId()), $server->getGroupManager()->isAdmin($this->getUserId()),
$server->getUserSession()->getUser() !== null && $server->query(ISubAdmin::class)->isSubAdmin($server->getUserSession()->getUser()), $server->getUserSession()->getUser() !== null && $server->query(ISubAdmin::class)->isSubAdmin($server->getUserSession()->getUser()),
@ -242,71 +248,71 @@ class DIContainer extends SimpleContainer implements IAppContainer {
); );
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
new OC\AppFramework\Middleware\Security\PasswordConfirmationMiddleware( new OC\AppFramework\Middleware\Security\PasswordConfirmationMiddleware(
$c->query(IControllerMethodReflector::class), $c->get(IControllerMethodReflector::class),
$c->query(ISession::class), $c->get(ISession::class),
$c->query(IUserSession::class), $c->get(IUserSession::class),
$c->query(ITimeFactory::class) $c->get(ITimeFactory::class)
) )
); );
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
new TwoFactorMiddleware( new TwoFactorMiddleware(
$c->query(OC\Authentication\TwoFactorAuth\Manager::class), $c->get(OC\Authentication\TwoFactorAuth\Manager::class),
$c->query(IUserSession::class), $c->get(IUserSession::class),
$c->query(ISession::class), $c->get(ISession::class),
$c->query(IURLGenerator::class), $c->get(IURLGenerator::class),
$c->query(IControllerMethodReflector::class), $c->get(IControllerMethodReflector::class),
$c->query(IRequest::class) $c->get(IRequest::class)
) )
); );
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
new OC\AppFramework\Middleware\Security\BruteForceMiddleware( new OC\AppFramework\Middleware\Security\BruteForceMiddleware(
$c->query(IControllerMethodReflector::class), $c->get(IControllerMethodReflector::class),
$c->query(OC\Security\Bruteforce\Throttler::class), $c->get(OC\Security\Bruteforce\Throttler::class),
$c->query(IRequest::class) $c->get(IRequest::class)
) )
); );
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
new RateLimitingMiddleware( new RateLimitingMiddleware(
$c->query(IRequest::class), $c->get(IRequest::class),
$c->query(IUserSession::class), $c->get(IUserSession::class),
$c->query(IControllerMethodReflector::class), $c->get(IControllerMethodReflector::class),
$c->query(OC\Security\RateLimiting\Limiter::class) $c->get(OC\Security\RateLimiting\Limiter::class)
) )
); );
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
new OC\AppFramework\Middleware\PublicShare\PublicShareMiddleware( new OC\AppFramework\Middleware\PublicShare\PublicShareMiddleware(
$c->query(IRequest::class), $c->get(IRequest::class),
$c->query(ISession::class), $c->get(ISession::class),
$c->query(\OCP\IConfig::class) $c->get(\OCP\IConfig::class)
) )
); );
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
$c->query(\OC\AppFramework\Middleware\AdditionalScriptsMiddleware::class) $c->get(\OC\AppFramework\Middleware\AdditionalScriptsMiddleware::class)
); );
foreach ($this->middleWares as $middleWare) { foreach ($this->middleWares as $middleWare) {
$dispatcher->registerMiddleware($c->query($middleWare)); $dispatcher->registerMiddleware($c->get($middleWare));
} }
$dispatcher->registerMiddleware( $dispatcher->registerMiddleware(
new SessionMiddleware( new SessionMiddleware(
$c->query(IControllerMethodReflector::class), $c->get(IControllerMethodReflector::class),
$c->query(ISession::class) $c->get(ISession::class)
) )
); );
return $dispatcher; return $dispatcher;
}); });
$this->registerService(IAppConfig::class, function (SimpleContainer $c) { $this->registerService(IAppConfig::class, function (ContainerInterface $c) {
return new OC\AppFramework\Services\AppConfig( return new OC\AppFramework\Services\AppConfig(
$c->query(IConfig::class), $c->get(IConfig::class),
$c->query('AppName') $c->get('AppName')
); );
}); });
$this->registerService(IInitialState::class, function (SimpleContainer $c) { $this->registerService(IInitialState::class, function (ContainerInterface $c) {
return new OC\AppFramework\Services\InitialState( return new OC\AppFramework\Services\InitialState(
$c->query(IInitialStateService::class), $c->get(IInitialStateService::class),
$c->query('AppName') $c->get('AppName')
); );
}); });
} }
@ -396,6 +402,18 @@ class DIContainer extends SimpleContainer implements IAppContainer {
}); });
} }
public function has($id): bool {
if (parent::has($id)) {
return true;
}
if ($this->server->has($id, true)) {
return true;
}
return false;
}
public function query(string $name, bool $autoload = true) { public function query(string $name, bool $autoload = true) {
try { try {
return $this->queryNoFallback($name); return $this->queryNoFallback($name);
@ -421,15 +439,13 @@ class DIContainer extends SimpleContainer implements IAppContainer {
if ($this->offsetExists($name)) { if ($this->offsetExists($name)) {
return parent::query($name); return parent::query($name);
} else { } elseif ($this['AppName'] === 'settings' && strpos($name, 'OC\\Settings\\') === 0) {
if ($this['AppName'] === 'settings' && strpos($name, 'OC\\Settings\\') === 0) {
return parent::query($name); return parent::query($name);
} elseif ($this['AppName'] === 'core' && strpos($name, 'OC\\Core\\') === 0) { } elseif ($this['AppName'] === 'core' && strpos($name, 'OC\\Core\\') === 0) {
return parent::query($name); return parent::query($name);
} elseif (strpos($name, \OC\AppFramework\App::buildAppNamespace($this['AppName']) . '\\') === 0) { } elseif (strpos($name, \OC\AppFramework\App::buildAppNamespace($this['AppName']) . '\\') === 0) {
return parent::query($name); return parent::query($name);
} }
}
throw new QueryException('Could not resolve ' . $name . '!' . throw new QueryException('Could not resolve ' . $name . '!' .
' Class can not be instantiated', 1); ' Class can not be instantiated', 1);

View File

@ -30,20 +30,37 @@
namespace OC\AppFramework\Utility; namespace OC\AppFramework\Utility;
use ArrayAccess;
use Closure; use Closure;
use OCP\AppFramework\QueryException; use OCP\AppFramework\QueryException;
use OCP\IContainer; use OCP\IContainer;
use Pimple\Container; use Pimple\Container;
use Psr\Container\ContainerInterface;
use ReflectionClass; use ReflectionClass;
use ReflectionException; use ReflectionException;
use ReflectionParameter;
use function class_exists;
/** /**
* Class SimpleContainer * SimpleContainer is a simple implementation of a container on basis of Pimple
*
* SimpleContainer is a simple implementation of IContainer on basis of Pimple
*/ */
class SimpleContainer extends Container implements IContainer { class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer {
/** @var Container */
private $container;
public function __construct() {
$this->container = new Container();
}
public function get($id) {
return $this->query($id);
}
public function has($id): bool {
// If a service is no registered but is an existing class, we can probably load it
return isset($this->container[$id]) || class_exists($id);
}
/** /**
* @param ReflectionClass $class the class to instantiate * @param ReflectionClass $class the class to instantiate
@ -54,9 +71,9 @@ class SimpleContainer extends Container implements IContainer {
$constructor = $class->getConstructor(); $constructor = $class->getConstructor();
if ($constructor === null) { if ($constructor === null) {
return $class->newInstance(); return $class->newInstance();
} else { }
$parameters = [];
foreach ($constructor->getParameters() as $parameter) { return $class->newInstanceArgs(array_map(function (ReflectionParameter $parameter) {
$parameterClass = $parameter->getClass(); $parameterClass = $parameter->getClass();
// try to find out if it is a class or a simple parameter // try to find out if it is a class or a simple parameter
@ -68,31 +85,23 @@ class SimpleContainer extends Container implements IContainer {
try { try {
$builtIn = $parameter->hasType() && $parameter->getType()->isBuiltin(); $builtIn = $parameter->hasType() && $parameter->getType()->isBuiltin();
$parameters[] = $this->query($resolveName, !$builtIn); return $this->query($resolveName, !$builtIn);
} catch (QueryException $e) { } catch (QueryException $e) {
// Service not found, use the default value when available // Service not found, use the default value when available
if ($parameter->isDefaultValueAvailable()) { if ($parameter->isDefaultValueAvailable()) {
$parameters[] = $parameter->getDefaultValue(); return $parameter->getDefaultValue();
} elseif ($parameterClass !== null) { }
if ($parameterClass !== null) {
$resolveName = $parameter->getName(); $resolveName = $parameter->getName();
$parameters[] = $this->query($resolveName); return $this->query($resolveName);
} else { }
throw $e; throw $e;
} }
} }, $constructor->getParameters()));
}
return $class->newInstanceArgs($parameters);
}
} }
/**
* 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
* @return \stdClass
* @throws QueryException if the class could not be found or instantiated
*/
public function resolve($name) { public function resolve($name) {
$baseMsg = 'Could not resolve ' . $name . '!'; $baseMsg = 'Could not resolve ' . $name . '!';
try { try {
@ -110,15 +119,18 @@ class SimpleContainer extends Container implements IContainer {
public function query(string $name, bool $autoload = true) { public function query(string $name, bool $autoload = true) {
$name = $this->sanitizeName($name); $name = $this->sanitizeName($name);
if ($this->offsetExists($name)) { if (isset($this->container[$name])) {
return $this->offsetGet($name); return $this->container[$name];
} elseif ($autoload) { }
if ($autoload) {
$object = $this->resolve($name); $object = $this->resolve($name);
$this->registerService($name, function () use ($object) { $this->registerService($name, function () use ($object) {
return $object; return $object;
}); });
return $object; return $object;
} }
throw new QueryException('Could not resolve ' . $name . '!'); throw new QueryException('Could not resolve ' . $name . '!');
} }
@ -140,14 +152,17 @@ class SimpleContainer extends Container implements IContainer {
* @param bool $shared * @param bool $shared
*/ */
public function registerService($name, Closure $closure, $shared = true) { public function registerService($name, Closure $closure, $shared = true) {
$wrapped = function () use ($closure) {
return $closure($this);
};
$name = $this->sanitizeName($name); $name = $this->sanitizeName($name);
if (isset($this[$name])) { if (isset($this[$name])) {
unset($this[$name]); unset($this[$name]);
} }
if ($shared) { if ($shared) {
$this[$name] = $closure; $this[$name] = $wrapped;
} else { } else {
$this[$name] = parent::factory($closure); $this[$name] = $this->container->factory($wrapped);
} }
} }
@ -159,8 +174,8 @@ class SimpleContainer extends Container implements IContainer {
* @param string $target the target that should be resolved instead * @param string $target the target that should be resolved instead
*/ */
public function registerAlias($alias, $target) { public function registerAlias($alias, $target) {
$this->registerService($alias, function (IContainer $container) use ($target) { $this->registerService($alias, function (ContainerInterface $container) use ($target) {
return $container->query($target); return $container->get($target);
}, false); }, false);
} }
@ -174,4 +189,32 @@ class SimpleContainer extends Container implements IContainer {
} }
return $name; return $name;
} }
/**
* @deprecated 20.0.0 use \Psr\Container\ContainerInterface::has
*/
public function offsetExists($id) {
return $this->container->offsetExists($id);
}
/**
* @deprecated 20.0.0 use \Psr\Container\ContainerInterface::get
*/
public function offsetGet($id) {
return $this->container->offsetGet($id);
}
/**
* @deprecated 20.0.0 use \OCP\IContainer::registerService
*/
public function offsetSet($id, $service) {
$this->container->offsetSet($id, $service);
}
/**
* @deprecated 20.0.0
*/
public function offsetUnset($offset) {
$this->container->offsetUnset($offset);
}
} }

View File

@ -139,7 +139,6 @@ use OCA\Theming\ThemingDefaults;
use OCA\Theming\Util; use OCA\Theming\Util;
use OCP\Accounts\IAccountManager; use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager; use OCP\App\IAppManager;
use OCP\AppFramework\QueryException;
use OCP\Authentication\LoginCredentials\IStore; use OCP\Authentication\LoginCredentials\IStore;
use OCP\BackgroundJob\IJobList; use OCP\BackgroundJob\IJobList;
use OCP\Collaboration\AutoComplete\IManager; use OCP\Collaboration\AutoComplete\IManager;
@ -178,7 +177,6 @@ use OCP\IAppConfig;
use OCP\IAvatarManager; use OCP\IAvatarManager;
use OCP\ICache; use OCP\ICache;
use OCP\ICacheFactory; use OCP\ICacheFactory;
use OCP\IContainer;
use OCP\IDateTimeFormatter; use OCP\IDateTimeFormatter;
use OCP\IDateTimeZone; use OCP\IDateTimeZone;
use OCP\IDBConnection; use OCP\IDBConnection;
@ -226,6 +224,8 @@ use OCP\User\Events\UserDeletedEvent;
use OCP\User\Events\UserLoggedInEvent; use OCP\User\Events\UserLoggedInEvent;
use OCP\User\Events\UserLoggedInWithCookieEvent; use OCP\User\Events\UserLoggedInWithCookieEvent;
use OCP\User\Events\UserLoggedOutEvent; use OCP\User\Events\UserLoggedOutEvent;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent; use Symfony\Component\EventDispatcher\GenericEvent;
@ -242,6 +242,7 @@ use OCA\Files_External\Service\BackendService;
* TODO: hookup all manager classes * TODO: hookup all manager classes
*/ */
class Server extends ServerContainer implements IServerContainer { class Server extends ServerContainer implements IServerContainer {
/** @var string */ /** @var string */
private $webRoot; private $webRoot;
@ -256,7 +257,10 @@ class Server extends ServerContainer implements IServerContainer {
// To find out if we are running from CLI or not // To find out if we are running from CLI or not
$this->registerParameter('isCLI', \OC::$CLI); $this->registerParameter('isCLI', \OC::$CLI);
$this->registerService(\OCP\IServerContainer::class, function (IServerContainer $c) { $this->registerService(ContainerInterface::class, function (ContainerInterface $c) {
return $c;
});
$this->registerService(\OCP\IServerContainer::class, function (ContainerInterface $c) {
return $c; return $c;
}); });
@ -2232,16 +2236,16 @@ class Server extends ServerContainer implements IServerContainer {
} }
private function registerDeprecatedAlias(string $alias, string $target) { private function registerDeprecatedAlias(string $alias, string $target) {
$this->registerService($alias, function (IContainer $container) use ($target, $alias) { $this->registerService($alias, function (ContainerInterface $container) use ($target, $alias) {
try { try {
/** @var ILogger $logger */ /** @var ILogger $logger */
$logger = $container->query(ILogger::class); $logger = $container->get(ILogger::class);
$logger->debug('The requested alias "' . $alias . '" is depreacted. Please request "' . $target . '" directly. This alias will be removed in a future Nextcloud version.', ['app' => 'serverDI']); $logger->debug('The requested alias "' . $alias . '" is depreacted. Please request "' . $target . '" directly. This alias will be removed in a future Nextcloud version.', ['app' => 'serverDI']);
} catch (QueryException $e) { } catch (ContainerExceptionInterface $e) {
// Could not get logger. Continue // Could not get logger. Continue
} }
return $container->query($target); return $container->get($target);
}, false); }, false);
} }
} }

View File

@ -31,6 +31,8 @@ use OC\AppFramework\App;
use OC\AppFramework\DependencyInjection\DIContainer; use OC\AppFramework\DependencyInjection\DIContainer;
use OC\AppFramework\Utility\SimpleContainer; use OC\AppFramework\Utility\SimpleContainer;
use OCP\AppFramework\QueryException; use OCP\AppFramework\QueryException;
use function explode;
use function strtolower;
/** /**
* Class ServerContainer * Class ServerContainer
@ -117,19 +119,21 @@ class ServerContainer extends SimpleContainer {
throw new QueryException(); throw new QueryException();
} }
public function has($id, bool $noRecursion = false): bool {
if (!$noRecursion && ($appContainer = $this->getAppContainerForService($id)) !== null) {
return $appContainer->has($id);
}
return parent::has($id);
}
public function query(string $name, bool $autoload = true) { public function query(string $name, bool $autoload = true) {
$name = $this->sanitizeName($name); $name = $this->sanitizeName($name);
if (isset($this[$name])) {
return $this[$name];
}
// In case the service starts with OCA\ we try to find the service in // In case the service starts with OCA\ we try to find the service in
// the apps container first. // the apps container first.
if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) { if (($appContainer = $this->getAppContainerForService($name)) !== null) {
$segments = explode('\\', $name);
try { try {
$appContainer = $this->getAppContainer(strtolower($segments[1]), $segments[1]);
return $appContainer->queryNoFallback($name); return $appContainer->queryNoFallback($name);
} catch (QueryException $e) { } catch (QueryException $e) {
// Didn't find the service or the respective app container, // Didn't find the service or the respective app container,
@ -148,4 +152,17 @@ class ServerContainer extends SimpleContainer {
return parent::query($name, $autoload); return parent::query($name, $autoload);
} }
private function getAppContainerForService(string $id): ?DIContainer {
if (strpos($id, 'OCA\\') !== 0 || substr_count($id, '\\') < 2) {
return null;
}
try {
[,$namespace,] = explode('\\', $id);
return $this->getAppContainer(strtolower($namespace), $namespace);
} catch (QueryException $e) {
return null;
}
}
} }

View File

@ -26,8 +26,9 @@ declare(strict_types=1);
namespace OCP\AppFramework\Bootstrap; namespace OCP\AppFramework\Bootstrap;
use OCP\AppFramework\IAppContainer; use OCP\AppFramework\IAppContainer;
use OCP\AppFramework\QueryException;
use OCP\IServerContainer; use OCP\IServerContainer;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Throwable; use Throwable;
/** /**
@ -40,7 +41,7 @@ interface IBootContext {
* *
* Useful to register and query app-specific services * Useful to register and query app-specific services
* *
* @return IAppContainer * @return IAppContainer|ContainerInterface
* @since 20.0.0 * @since 20.0.0
*/ */
public function getAppContainer(): IAppContainer; public function getAppContainer(): IAppContainer;
@ -68,7 +69,7 @@ interface IBootContext {
* Note: the app container will be queried * Note: the app container will be queried
* *
* @param callable $fn * @param callable $fn
* @throws QueryException if at least one of the parameter can't be resolved * @throws ContainerExceptionInterface if at least one of the parameter can't be resolved
* @throws Throwable any error the function invocation might cause * @throws Throwable any error the function invocation might cause
* @return mixed|null the return value of the invoked function, if any * @return mixed|null the return value of the invoked function, if any
* @since 20.0.0 * @since 20.0.0

View File

@ -34,6 +34,7 @@ use OCP\IContainer;
* *
* This container interface provides short cuts for app developers to access predefined app service. * This container interface provides short cuts for app developers to access predefined app service.
* @since 6.0.0 * @since 6.0.0
* @deprecated 20.0.0 use \Psr\Container\ContainerInterface
*/ */
interface IAppContainer extends IContainer { interface IAppContainer extends IContainer {
@ -41,12 +42,14 @@ interface IAppContainer extends IContainer {
* used to return the appname of the set application * used to return the appname of the set application
* @return string the name of your application * @return string the name of your application
* @since 6.0.0 * @since 6.0.0
* @deprecated 20.0.0
*/ */
public function getAppName(); public function getAppName();
/** /**
* @return \OCP\IServerContainer * @return \OCP\IServerContainer
* @since 6.0.0 * @since 6.0.0
* @deprecated 20.0.0
*/ */
public function getServer(); public function getServer();
@ -54,6 +57,7 @@ interface IAppContainer extends IContainer {
* @param string $middleWare * @param string $middleWare
* @return boolean * @return boolean
* @since 6.0.0 * @since 6.0.0
* @deprecated 20.0.0 use \OCP\AppFramework\Bootstrap\IRegistrationContext::registerMiddleware
*/ */
public function registerMiddleWare($middleWare); public function registerMiddleWare($middleWare);
@ -62,6 +66,7 @@ interface IAppContainer extends IContainer {
* *
* @param string $serviceName e.g. 'OCA\Files\Capabilities' * @param string $serviceName e.g. 'OCA\Files\Capabilities'
* @since 8.2.0 * @since 8.2.0
* @deprecated 20.0.0 use \OCP\AppFramework\Bootstrap\IRegistrationContext::registerCapability
*/ */
public function registerCapability($serviceName); public function registerCapability($serviceName);
} }

View File

@ -1,4 +1,7 @@
<?php <?php
declare(strict_types=1);
/** /**
* @copyright Copyright (c) 2016, ownCloud, Inc. * @copyright Copyright (c) 2016, ownCloud, Inc.
* *
@ -25,12 +28,16 @@
namespace OCP\AppFramework; namespace OCP\AppFramework;
use Exception; use Exception;
use Psr\Container\ContainerExceptionInterface;
/** /**
* Class QueryException * Class QueryException
* *
* The class extends `NotFoundExceptionInterface` since 20.0.0
*
* @package OCP\AppFramework * @package OCP\AppFramework
* @since 8.1.0 * @since 8.1.0
* @deprecated 20.0.0 catch \Psr\Container\ContainerExceptionInterface
*/ */
class QueryException extends Exception { class QueryException extends Exception implements ContainerExceptionInterface {
} }

View File

@ -37,6 +37,8 @@ namespace OCP;
use Closure; use Closure;
use OCP\AppFramework\QueryException; use OCP\AppFramework\QueryException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
/** /**
* Class IContainer * Class IContainer
@ -45,8 +47,9 @@ use OCP\AppFramework\QueryException;
* *
* @package OCP * @package OCP
* @since 6.0.0 * @since 6.0.0
* @deprecated 20.0.0 use \Psr\Container\ContainerInterface
*/ */
interface IContainer { interface IContainer extends ContainerInterface {
/** /**
* If a parameter is not registered in the container try to instantiate it * If a parameter is not registered in the container try to instantiate it
@ -54,6 +57,8 @@ interface IContainer {
* @param string $name the class name to resolve * @param string $name the class name to resolve
* @return \stdClass * @return \stdClass
* @since 8.2.0 * @since 8.2.0
* @deprecated 20.0.0 use \Psr\Container\ContainerInterface::get
* @throws ContainerExceptionInterface if the class could not be found or instantiated
* @throws QueryException if the class could not be found or instantiated * @throws QueryException if the class could not be found or instantiated
*/ */
public function resolve($name); public function resolve($name);
@ -64,8 +69,10 @@ interface IContainer {
* @param string $name * @param 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 * @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 * @return mixed
* @throws ContainerExceptionInterface if the query could not be resolved
* @throws QueryException if the query could not be resolved * @throws QueryException if the query could not be resolved
* @since 6.0.0 * @since 6.0.0
* @deprecated 20.0.0 use \Psr\Container\ContainerInterface::get
*/ */
public function query(string $name, bool $autoload = true); public function query(string $name, bool $autoload = true);
@ -76,6 +83,7 @@ interface IContainer {
* @param mixed $value * @param mixed $value
* @return void * @return void
* @since 6.0.0 * @since 6.0.0
* @deprecated 20.0.0 use \OCP\AppFramework\Bootstrap\IRegistrationContext::registerParameter
*/ */
public function registerParameter($name, $value); public function registerParameter($name, $value);
@ -91,6 +99,7 @@ interface IContainer {
* @param bool $shared * @param bool $shared
* @return void * @return void
* @since 6.0.0 * @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($name, Closure $closure, $shared = true);
@ -101,6 +110,7 @@ interface IContainer {
* @param string $alias the alias that should be registered * @param string $alias the alias that should be registered
* @param string $target the target that should be resolved instead * @param string $target the target that should be resolved instead
* @since 8.2.0 * @since 8.2.0
* @deprecated 20.0.0 use \OCP\AppFramework\Bootstrap\IRegistrationContext::registerServiceAlias
*/ */
public function registerAlias($alias, $target); public function registerAlias($alias, $target);
} }

View File

@ -60,6 +60,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
* *
* This container holds all ownCloud services * This container holds all ownCloud services
* @since 6.0.0 * @since 6.0.0
* @deprecated 20.0.0 use \Psr\Container\ContainerInterface
*/ */
interface IServerContainer extends IContainer { interface IServerContainer extends IContainer {