Skip to content

Commit

Permalink
Let apps register Sabre plugins or collections
Browse files Browse the repository at this point in the history
  • Loading branch information
Vincent Petry committed Dec 5, 2016
1 parent 2098afb commit 07d43a5
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 3 deletions.
1 change: 1 addition & 0 deletions apps/comments/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
</dependencies>
<types>
<logging/>
<dav/>
</types>
</info>
1 change: 1 addition & 0 deletions apps/dav/appinfo/v2/remote.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
/**
* @author Thomas Müller <[email protected]>
* @author Vincent Petry <[email protected]>
*
* @copyright Copyright (c) 2016, ownCloud GmbH.
* @license AGPL-3.0
Expand Down
169 changes: 169 additions & 0 deletions apps/dav/lib/AppInfo/PluginManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<?php
/**
* @author Vincent Petry <[email protected]>
*
* @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;

/**
* 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 (is_null($this->plugins)) {
$this->populate();
}
return $this->plugins;
}

/**
* Returns an array of app-registered collections
*
* @return array
*/
public function getAppCollections() {
if (is_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'])) {
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) {
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) {
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($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($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");
}
}
};
}

}
15 changes: 14 additions & 1 deletion apps/dav/lib/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
use Sabre\CardDAV\VCFExportPlugin;
use Sabre\DAV\Auth\Plugin;
use OCA\DAV\Connector\Sabre\TagsPlugin;
use OCA\DAV\AppInfo\PluginManager;

class Server {

Expand Down Expand Up @@ -155,7 +156,7 @@ public function __construct(IRequest $request, $baseUri) {
}

// 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
$userSession = \OC::$server->getUserSession();
$user = $userSession->getUser();
Expand Down Expand Up @@ -214,6 +215,18 @@ public function __construct(IRequest $request, $baseUri) {
));
}
}

// 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);
}
});
}

Expand Down
104 changes: 104 additions & 0 deletions apps/dav/tests/unit/AppInfo/PluginManagerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php
/**
* @author Vincent Petry <[email protected]>
*
* @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());
}
}
4 changes: 2 additions & 2 deletions apps/dav/tests/unit/ServerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

use OCA\DAV\Server;
use OCP\IRequest;
use OCA\DAV\AppInfo\PluginManager;

/**
* Class ServerTest
Expand All @@ -36,8 +37,7 @@ class ServerTest extends \Test\TestCase {

public function test() {
/** @var IRequest $r */
$r = $this->getMockBuilder('\OCP\IRequest')
->disableOriginalConstructor()->getMock();
$r = $this->createMock(IRequest::class);
$s = new Server($r, '/');
$this->assertNotNull($s->server);
}
Expand Down

0 comments on commit 07d43a5

Please sign in to comment.