Merge pull request #6835 from nextcloud/dav-plugins-from-apps-only
Let apps register Sabre plugins or collections (v2)
This commit is contained in:
commit
3a3e6c34d0
|
@ -3,6 +3,7 @@
|
||||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||||
*
|
*
|
||||||
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
||||||
|
* @author Vincent Petry <pvince81@owncloud.com>
|
||||||
*
|
*
|
||||||
* @license AGPL-3.0
|
* @license AGPL-3.0
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Vincent Petry <pvince81@owncloud.com>
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2016, ownCloud GmbH.
|
||||||
|
* @license AGPL-3.0
|
||||||
|
*
|
||||||
|
* This code is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
namespace OCA\DAV\AppInfo;
|
||||||
|
|
||||||
|
use OCP\App\IAppManager;
|
||||||
|
use OC\ServerContainer;
|
||||||
|
use OCP\AppFramework\QueryException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manager for DAV plugins from apps, used to register them
|
||||||
|
* to the Sabre server.
|
||||||
|
*/
|
||||||
|
class PluginManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ServerContainer
|
||||||
|
*/
|
||||||
|
private $container;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var IAppManager
|
||||||
|
*/
|
||||||
|
private $appManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App plugins
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $plugins = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App collections
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $collections = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contstruct a PluginManager
|
||||||
|
*
|
||||||
|
* @param ServerContainer $container server container for resolving plugin classes
|
||||||
|
* @param IAppManager $appManager app manager to loading apps and their info
|
||||||
|
*/
|
||||||
|
public function __construct(ServerContainer $container, IAppManager $appManager) {
|
||||||
|
$this->container = $container;
|
||||||
|
$this->appManager = $appManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of app-registered plugins
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAppPlugins() {
|
||||||
|
if (null === $this->plugins) {
|
||||||
|
$this->populate();
|
||||||
|
}
|
||||||
|
return $this->plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of app-registered collections
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAppCollections() {
|
||||||
|
if (null === $this->collections) {
|
||||||
|
$this->populate();
|
||||||
|
}
|
||||||
|
return $this->collections;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve plugin and collection list and populate attributes
|
||||||
|
*/
|
||||||
|
private function populate() {
|
||||||
|
$this->plugins = [];
|
||||||
|
$this->collections = [];
|
||||||
|
foreach ($this->appManager->getInstalledApps() as $app) {
|
||||||
|
// load plugins and collections from info.xml
|
||||||
|
$info = $this->appManager->getAppInfo($app);
|
||||||
|
if (!isset($info['types']) || !in_array('dav', $info['types'], true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// FIXME: switch to public API once available
|
||||||
|
// load app to make sure its classes are available
|
||||||
|
\OC_App::loadApp($app);
|
||||||
|
$this->loadSabrePluginsFromInfoXml($this->extractPluginList($info));
|
||||||
|
$this->loadSabreCollectionsFromInfoXml($this->extractCollectionList($info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function extractPluginList(array $array) {
|
||||||
|
if (isset($array['sabre']) && is_array($array['sabre'])) {
|
||||||
|
if (isset($array['sabre']['plugins']) && is_array($array['sabre']['plugins'])) {
|
||||||
|
if (isset($array['sabre']['plugins']['plugin'])) {
|
||||||
|
$items = $array['sabre']['plugins']['plugin'];
|
||||||
|
if (!is_array($items)) {
|
||||||
|
$items = [$items];
|
||||||
|
}
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function extractCollectionList(array $array) {
|
||||||
|
if (isset($array['sabre']) && is_array($array['sabre'])) {
|
||||||
|
if (isset($array['sabre']['collections']) && is_array($array['sabre']['collections'])) {
|
||||||
|
if (isset($array['sabre']['collections']['collection'])) {
|
||||||
|
$items = $array['sabre']['collections']['collection'];
|
||||||
|
if (!is_array($items)) {
|
||||||
|
$items = [$items];
|
||||||
|
}
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadSabrePluginsFromInfoXml(array $plugins) {
|
||||||
|
foreach ($plugins as $plugin) {
|
||||||
|
try {
|
||||||
|
$this->plugins[] = $this->container->query($plugin);
|
||||||
|
} catch (QueryException $e) {
|
||||||
|
if (class_exists($plugin)) {
|
||||||
|
$this->plugins[] = new $plugin();
|
||||||
|
} else {
|
||||||
|
throw new \Exception("Sabre plugin class '$plugin' is unknown and could not be loaded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadSabreCollectionsFromInfoXml(array $collections) {
|
||||||
|
foreach ($collections as $collection) {
|
||||||
|
try {
|
||||||
|
$this->collections[] = $this->container->query($collection);
|
||||||
|
} catch (QueryException $e) {
|
||||||
|
if (class_exists($collection)) {
|
||||||
|
$this->collections[] = new $collection();
|
||||||
|
} else {
|
||||||
|
throw new \Exception("Sabre collection class '$collection' is unknown and could not be loaded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -55,8 +55,8 @@ use OCP\SabrePluginEvent;
|
||||||
use Sabre\CardDAV\VCFExportPlugin;
|
use Sabre\CardDAV\VCFExportPlugin;
|
||||||
use Sabre\DAV\Auth\Plugin;
|
use Sabre\DAV\Auth\Plugin;
|
||||||
use OCA\DAV\Connector\Sabre\TagsPlugin;
|
use OCA\DAV\Connector\Sabre\TagsPlugin;
|
||||||
use Sabre\HTTP\Auth\Bearer;
|
|
||||||
use SearchDAV\DAV\SearchPlugin;
|
use SearchDAV\DAV\SearchPlugin;
|
||||||
|
use OCA\DAV\AppInfo\PluginManager;
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ class Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait with registering these until auth is handled and the filesystem is setup
|
// wait with registering these until auth is handled and the filesystem is setup
|
||||||
$this->server->on('beforeMethod', function () {
|
$this->server->on('beforeMethod', function () use ($root) {
|
||||||
// custom properties plugin must be the last one
|
// custom properties plugin must be the last one
|
||||||
$userSession = \OC::$server->getUserSession();
|
$userSession = \OC::$server->getUserSession();
|
||||||
$user = $userSession->getUser();
|
$user = $userSession->getUser();
|
||||||
|
@ -252,6 +252,18 @@ class Server {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// register plugins from apps
|
||||||
|
$pluginManager = new PluginManager(
|
||||||
|
\OC::$server,
|
||||||
|
\OC::$server->getAppManager()
|
||||||
|
);
|
||||||
|
foreach ($pluginManager->getAppPlugins() as $appPlugin) {
|
||||||
|
$this->server->addPlugin($appPlugin);
|
||||||
|
}
|
||||||
|
foreach ($pluginManager->getAppCollections() as $appCollection) {
|
||||||
|
$root->addChild($appCollection);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Vincent Petry <pvince81@owncloud.com>
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2016, ownCloud GmbH.
|
||||||
|
* @license AGPL-3.0
|
||||||
|
*
|
||||||
|
* This code is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\DAV\Tests\unit\AppInfo;
|
||||||
|
|
||||||
|
use Test\TestCase;
|
||||||
|
use OCP\App\IAppManager;
|
||||||
|
use OC\ServerContainer;
|
||||||
|
use OCA\DAV\AppInfo\PluginManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PluginManagerTest
|
||||||
|
*
|
||||||
|
* @package OCA\DAV\Tests\Unit\AppInfo
|
||||||
|
*/
|
||||||
|
class PluginManagerTest extends TestCase {
|
||||||
|
public function test() {
|
||||||
|
$server = $this->createMock(ServerContainer::class);
|
||||||
|
|
||||||
|
|
||||||
|
$appManager = $this->createMock(IAppManager::class);
|
||||||
|
$appManager->method('getInstalledApps')
|
||||||
|
->willReturn(['adavapp', 'adavapp2']);
|
||||||
|
|
||||||
|
$appInfo1 = [
|
||||||
|
'types' => ['dav'],
|
||||||
|
'sabre' => [
|
||||||
|
'plugins' => [
|
||||||
|
'plugin' => [
|
||||||
|
'\OCA\DAV\ADavApp\PluginOne',
|
||||||
|
'\OCA\DAV\ADavApp\PluginTwo',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'collections' => [
|
||||||
|
'collection' => [
|
||||||
|
'\OCA\DAV\ADavApp\CollectionOne',
|
||||||
|
'\OCA\DAV\ADavApp\CollectionTwo',
|
||||||
|
]
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
$appInfo2 = [
|
||||||
|
'types' => ['logging', 'dav'],
|
||||||
|
'sabre' => [
|
||||||
|
'plugins' => [
|
||||||
|
'plugin' => '\OCA\DAV\ADavApp2\PluginOne',
|
||||||
|
],
|
||||||
|
'collections' => [
|
||||||
|
'collection' => '\OCA\DAV\ADavApp2\CollectionOne',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$appManager->method('getAppInfo')
|
||||||
|
->will($this->returnValueMap([
|
||||||
|
['adavapp', $appInfo1],
|
||||||
|
['adavapp2', $appInfo2],
|
||||||
|
]));
|
||||||
|
|
||||||
|
$pluginManager = new PluginManager($server, $appManager);
|
||||||
|
|
||||||
|
$server->method('query')
|
||||||
|
->will($this->returnValueMap([
|
||||||
|
['\OCA\DAV\ADavApp\PluginOne', 'dummyplugin1'],
|
||||||
|
['\OCA\DAV\ADavApp\PluginTwo', 'dummyplugin2'],
|
||||||
|
['\OCA\DAV\ADavApp\CollectionOne', 'dummycollection1'],
|
||||||
|
['\OCA\DAV\ADavApp\CollectionTwo', 'dummycollection2'],
|
||||||
|
['\OCA\DAV\ADavApp2\PluginOne', 'dummy2plugin1'],
|
||||||
|
['\OCA\DAV\ADavApp2\CollectionOne', 'dummy2collection1'],
|
||||||
|
]));
|
||||||
|
|
||||||
|
$expectedPlugins = [
|
||||||
|
'dummyplugin1',
|
||||||
|
'dummyplugin2',
|
||||||
|
'dummy2plugin1',
|
||||||
|
];
|
||||||
|
$expectedCollections = [
|
||||||
|
'dummycollection1',
|
||||||
|
'dummycollection2',
|
||||||
|
'dummy2collection1',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->assertEquals($expectedPlugins, $pluginManager->getAppPlugins());
|
||||||
|
$this->assertEquals($expectedCollections, $pluginManager->getAppCollections());
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ namespace OCA\DAV\Tests\unit;
|
||||||
|
|
||||||
use OCA\DAV\Server;
|
use OCA\DAV\Server;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
|
use OCA\DAV\AppInfo\PluginManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ServerTest
|
* Class ServerTest
|
||||||
|
@ -38,8 +39,7 @@ class ServerTest extends \Test\TestCase {
|
||||||
|
|
||||||
public function test() {
|
public function test() {
|
||||||
/** @var IRequest $r */
|
/** @var IRequest $r */
|
||||||
$r = $this->getMockBuilder('\OCP\IRequest')
|
$r = $this->createMock(IRequest::class);
|
||||||
->disableOriginalConstructor()->getMock();
|
|
||||||
$s = new Server($r, '/');
|
$s = new Server($r, '/');
|
||||||
$this->assertInstanceOf('OCA\DAV\Server', $s);
|
$this->assertInstanceOf('OCA\DAV\Server', $s);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue