Merge pull request #3977 from nextcloud/di_ng2

Make DI work for all apps
This commit is contained in:
blizzz 2017-03-22 15:36:52 +01:00 committed by GitHub
commit 0b5e1814be
7 changed files with 65 additions and 19 deletions

View File

@ -61,11 +61,12 @@ class App {
$appInfo = \OC_App::getAppInfo($appId);
if (isset($appInfo['namespace'])) {
return $topNamespace . trim($appInfo['namespace']);
self::$nameSpaceCache[$appId] = trim($appInfo['namespace']);
} else {
// if the tag is not found, fall back to uppercasing the first letter
self::$nameSpaceCache[$appId] = ucfirst($appId);
}
// if the tag is not found, fall back to uppercasing the first letter
self::$nameSpaceCache[$appId] = ucfirst($appId);
return $topNamespace . self::$nameSpaceCache[$appId];
}

View File

@ -49,6 +49,7 @@ use OC\ServerContainer;
use OCP\AppFramework\Http\IOutput;
use OCP\AppFramework\IApi;
use OCP\AppFramework\IAppContainer;
use OCP\AppFramework\QueryException;
use OCP\Files\Folder;
use OCP\Files\IAppData;
use OCP\IL10N;
@ -373,24 +374,40 @@ class DIContainer extends SimpleContainer implements IAppContainer {
});
}
/**
* @param string $name
* @return mixed
* @throws QueryException if the query could not be resolved
*/
public function query($name) {
try {
return $this->queryNoFallback($name);
} catch (QueryException $e) {
return $this->getServer()->query($name);
}
}
/**
* @param string $name
* @return mixed
* @throws QueryException if the query could not be resolved
*/
public function queryNoFallback($name) {
$name = $this->sanitizeName($name);
if ($this->offsetExists($name)) {
return parent::query($name);
} else {
if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) {
$segments = explode('\\', $name);
if (strtolower($segments[1]) === strtolower($this['AppName'])) {
return parent::query($name);
}
} else if ($this['AppName'] === 'settings' && strpos($name, 'OC\\Settings\\') === 0) {
if ($this['AppName'] === 'settings' && strpos($name, 'OC\\Settings\\') === 0) {
return parent::query($name);
} else if ($this['AppName'] === 'core' && strpos($name, 'OC\\Core\\') === 0) {
return parent::query($name);
} else if (strpos($name, \OC\AppFramework\App::buildAppNamespace($this['AppName']) . '\\') === 0) {
return parent::query($name);
}
}
return $this->getServer()->query($name);
throw new QueryException('Could not resolve ' . $name . '!' .
' Class can not be instantiated');
}
}

View File

@ -37,12 +37,26 @@ class ServerContainer extends SimpleContainer {
/** @var DIContainer[] */
protected $appContainers;
/** @var string[] */
protected $namespaces;
/**
* ServerContainer constructor.
*/
public function __construct() {
parent::__construct();
$this->appContainers = [];
$this->namespaces = [];
}
/**
* @param string $appName
* @param string $appNamespace
*/
public function registerNamespace($appName, $appNamespace) {
// Cut of OCA\ and lowercase
$appNamespace = strtolower(substr($appNamespace, strrpos($appNamespace, '\\') + 1));
$this->namespaces[$appNamespace] = $appName;
}
/**
@ -54,15 +68,19 @@ class ServerContainer extends SimpleContainer {
}
/**
* @param string $appName
* @param string $namespace
* @return DIContainer
* @throws QueryException
*/
public function getAppContainer($appName) {
if (isset($this->appContainers[$appName])) {
return $this->appContainers[$appName];
protected function getAppContainer($namespace) {
if (isset($this->appContainers[$namespace])) {
return $this->appContainers[$namespace];
}
return new DIContainer($appName);
if (isset($this->namespaces[$namespace])) {
return new DIContainer($this->namespaces[$namespace]);
}
throw new QueryException();
}
/**
@ -77,11 +95,11 @@ class ServerContainer extends SimpleContainer {
// the apps container first.
if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) {
$segments = explode('\\', $name);
$appContainer = $this->getAppContainer(strtolower($segments[1]));
try {
return $appContainer->query($name);
$appContainer = $this->getAppContainer(strtolower($segments[1]));
return $appContainer->queryNoFallback($name);
} catch (QueryException $e) {
// Didn't find the service in the respective app container,
// Didn't find the service or the respective app container,
// ignore it and fall back to the core container.
}
}

View File

@ -189,6 +189,7 @@ class OC_App {
self::$alreadyRegistered[$key] = true;
// Register on PSR-4 composer autoloader
$appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
\OC::$server->registerNamespace($app, $appNamespace);
\OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
\OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);

View File

@ -62,6 +62,7 @@ interface IContainer {
*
* @param string $name
* @return mixed
* @throws QueryException if the query could not be resolved
* @since 6.0.0
*/
public function query($name);

View File

@ -68,7 +68,7 @@ class ManagerTest extends TestCase {
parent::setUp();
$this->user = $this->createMock(IUser::class);
$this->appManager = $this->createMock('\OC\App\AppManager');
$this->appManager = $this->createMock(AppManager::class);
$this->session = $this->createMock(ISession::class);
$this->config = $this->createMock(IConfig::class);
$this->activityManager = $this->createMock(IManager::class);

View File

@ -63,6 +63,14 @@ class InfoXmlTest extends TestCase {
$appPath = \OC_App::getAppPath($app);
\OC_App::registerAutoloading($app, $appPath);
//Add the appcontainer
$applicationClassName = \OCP\AppFramework\App::buildAppNamespace($app) . '\\AppInfo\\Application';
if (class_exists($applicationClassName)) {
$application = new $applicationClassName();
} else {
$application = new \OCP\AppFramework\App($app);
}
if (isset($appInfo['background-jobs'])) {
foreach ($appInfo['background-jobs'] as $job) {
$this->assertTrue(class_exists($job), 'Asserting background job "' . $job . '" exists');