diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php
index cea960b1a499..b80a6ddab685 100644
--- a/apps/files/appinfo/routes.php
+++ b/apps/files/appinfo/routes.php
@@ -59,6 +59,11 @@
'url' => '/api/v1/showhidden',
'verb' => 'POST'
),
+ [
+ 'name' => 'Search#search',
+ 'url' => '/search',
+ 'verb' => 'GET',
+ ],
[
'name' => 'view#index',
'url' => '/',
diff --git a/apps/files/lib/AppInfo/Application.php b/apps/files/lib/AppInfo/Application.php
index 4ebf67a2374c..e35568e8cd9a 100644
--- a/apps/files/lib/AppInfo/Application.php
+++ b/apps/files/lib/AppInfo/Application.php
@@ -24,6 +24,7 @@
namespace OCA\Files\AppInfo;
use OCA\Files\Controller\ApiController;
+use OCA\Files\Controller\SearchController;
use OCP\AppFramework\App;
use \OCA\Files\Service\TagService;
use \OCP\IContainer;
@@ -50,6 +51,16 @@ public function __construct(array $urlParams=array()) {
);
});
+ $container->registerService('SearchController', function (IContainer $c) use ($server) {
+ return new SearchController(
+ $c->query('AppName'),
+ $c->query('Request'),
+ $server->getUserSession(),
+ $server->getConfig(),
+ $server->getRootFolder()
+ );
+ });
+
$container->registerService('ViewController', function (IContainer $c) use ($server) {
return new ViewController(
$c->query('AppName'),
diff --git a/apps/files/lib/Controller/SearchController.php b/apps/files/lib/Controller/SearchController.php
new file mode 100644
index 000000000000..456bee105731
--- /dev/null
+++ b/apps/files/lib/Controller/SearchController.php
@@ -0,0 +1,152 @@
+
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @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
+ *
+ */
+
+namespace OCA\Files\Controller;
+
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Controller;
+use OCP\Files\NotFoundException;
+use OCP\Files\Search\IIndexer;
+use OCP\IConfig;
+use OCP\IRequest;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\Http\DataDisplayResponse;
+use OCP\AppFramework\Http\Response;
+use OCP\AppFramework\Http\NotFoundResponse;
+use OCP\Files\Folder;
+use OCP\IUserSession;
+use \OCP\Files\IRootFolder;
+use OCP\Search\ScoredResult;
+
+
+/**
+ * Class SearchController
+ *
+ * @package OCA\Files\Controller
+ */
+class SearchController extends Controller {
+
+ /** IUserSession */
+ private $userSession;
+ /** string */
+ private $userId;
+ /** IConfig */
+ private $config;
+ /** IRootFolder */
+ protected $rootFolder;
+
+ /**
+ * SearchController constructor.
+ *
+ * @param string $appName
+ * @param IRequest $request
+ * @param IUserSession $userSession
+ * @param IConfig $config
+ * @param IRootFolder $rootFolder
+ */
+ public function __construct($appName,
+ IRequest $request,
+ IUserSession $userSession,
+ IConfig $config,
+ IRootFolder $rootFolder) {
+ parent::__construct($appName, $request);
+ $this->userSession = $userSession;
+ $this->config = $config;
+ $this->rootFolder = $rootFolder;
+
+ $user = $this->userSession->getUser();
+ if (!$user) {
+ // TODO - throw some exception
+ }
+
+ $this->userId = $user->getUID();
+ }
+
+ /**
+ * @NoCSRFRequired
+ * @NoAdminRequired
+ *
+ * @param string $phrase phrase to search
+ * @param string $path limit path to search
+ * @param integer $page page of pagination
+ * @param integer $size size of pagination
+ */
+ public function search($phrase, $path='/', $page=null, $size=null) {
+ if ($path === '') {
+ $path = '/';
+ }
+ $path = '/' . $this->userId . '/files' . $path;
+
+ $indexStorageMap = [];
+
+ // Collect mounts to search
+ try {
+ $mounts = $this->rootFolder->getMountsIn($path);
+ foreach($mounts as $mount) {
+ /** @var \OCP\Files\Mount\IMountPoint $mount */
+ /** @var \OCP\Files\Storage $storage */
+ $storage = $mount->getStorage();
+ $indexerIdentifier = $storage->getIndexerIdentifier();
+
+ if (!isset($indexStorageMap[$indexerIdentifier])) {
+ $indexStorageMap[$indexerIdentifier] = [];
+ }
+ $indexStorageMap[$indexerIdentifier][] = $storage;
+ }
+ } catch(NotFoundException $ex) {
+
+ }
+
+ $indexers = [];
+ foreach($indexStorageMap as $singleIndexer => $storages) {
+ if (!class_exists($singleIndexer)) {
+ continue;
+ }
+
+ try {
+ /** @var IIndexer $instance */
+ $instance = new $singleIndexer();
+ $instance->setStorages($storages);
+ $indexers[] = $instance;
+ } catch(\Exception $ex) {
+ //TODO
+ }
+ }
+
+ // Search Indexers from 0 to $page + $size
+ // Some better approximation of what $page should look like
+ // should be added in a later version
+ $indexerSize = $page + $size;
+
+ $results = [];
+ foreach($indexers as $indexer) {
+ /** @var IIndexer $indexer */
+ $results = array_merge($results, $indexer->search($phrase, $path, 0, $indexerSize));
+ }
+
+ usort($results, function(ScoredResult $a, ScoredResult $b) {
+ return ($a->score < $b->score) ? -1 : 1;
+ });
+ $results = array_slice($results, $page, $size);
+
+ }
+
+}
diff --git a/lib/private/Files/Search/DatabaseIndixer.php b/lib/private/Files/Search/DatabaseIndixer.php
new file mode 100644
index 000000000000..37467216bcc6
--- /dev/null
+++ b/lib/private/Files/Search/DatabaseIndixer.php
@@ -0,0 +1,50 @@
+
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @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
+ *
+ */
+
+namespace OCA\Files\Search;
+
+use OCP\Files\Search\IIndexer;
+
+class DatabaseIndexer implements IIndexer {
+
+ /**
+ * @var \OCP\Files\Storage\IStorage[]
+ */
+ protected $storages;
+
+ /**
+ * @param \OCP\Files\Storage\IStorage[] $storages
+ */
+ public function setStorages($storages) {
+ $this->storages = $storages;
+ }
+
+ /**
+ * @param $query
+ * @param null|integer $page
+ * @param null|integer $size
+ * @return \OCP\Search\ScoredResult[]
+ */
+ public function search($query, $page=null, $size=null) {
+ return [];
+ }
+
+}
diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php
index cec6a42a2c06..1c0f9c9c118c 100644
--- a/lib/private/Files/Storage/Common.php
+++ b/lib/private/Files/Storage/Common.php
@@ -72,6 +72,7 @@ abstract class Common implements Storage, ILockingStorage {
protected $propagator;
protected $storageCache;
protected $updater;
+ protected $indexerIdentifier;
protected $mountOptions = [];
protected $owner = null;
@@ -343,6 +344,12 @@ public function getWatcher($path = '', $storage = null) {
return $this->watcher;
}
+ public function getIndexerIdentifier() {
+ return $this->indexerIdentifier ?
+ $this->indexerIdentifier :
+ '\OCA\Files\Search\DatabaseIndexer';
+ }
+
/**
* get a propagator instance for the cache
*
diff --git a/lib/private/Files/Storage/Wrapper/Wrapper.php b/lib/private/Files/Storage/Wrapper/Wrapper.php
index 21d7db1099be..fbaf0f93ed9f 100644
--- a/lib/private/Files/Storage/Wrapper/Wrapper.php
+++ b/lib/private/Files/Storage/Wrapper/Wrapper.php
@@ -440,6 +440,13 @@ public function getUpdater($storage = null) {
return $this->storage->getUpdater($storage);
}
+ /**
+ * @return string
+ */
+ public function getIndexerIdentifier() {
+ return $this->storage->getIndexerIdentifier();
+ }
+
/**
* @return \OC\Files\Cache\Storage
*/
diff --git a/lib/public/Files/Storage/IStorage.php b/lib/public/Files/Storage/IStorage.php
index ab1915bb93ec..7ae1f7cc90fc 100644
--- a/lib/public/Files/Storage/IStorage.php
+++ b/lib/public/Files/Storage/IStorage.php
@@ -454,4 +454,10 @@ public function getUpdater();
* @since 9.0.0
*/
public function getWatcher();
+
+ /**
+ * @return string
+ * @since 9.1.0
+ */
+ public function getIndexerIdentifier();
}
diff --git a/lib/public/files/search/IIndexer.php b/lib/public/files/search/IIndexer.php
new file mode 100644
index 000000000000..a4a5d2c4d664
--- /dev/null
+++ b/lib/public/files/search/IIndexer.php
@@ -0,0 +1,48 @@
+
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @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
+ *
+ */
+
+namespace OCP\Files\Search;
+
+/**
+ * indexes storage to provide performant search
+ *
+ * @since 9.1.0
+ */
+interface IIndexer {
+
+ /**
+ * list of storages indexer is supposed to query
+ * @param \OCP\Files\Storage\IStorage[] $storages
+ */
+ public function setStorages($storages);
+
+ /**
+ * search storages for query
+ * @param string $query
+ * @param string $path limit search to a certain subdirectory
+ * @param null|integer $page
+ * @param null|integer $size
+ * @return \OCP\Search\ScoredResult[]
+ * @since 9.1.0
+ */
+ public function search($query, $path, $page=null, $size=null);
+
+}
diff --git a/lib/public/search/ScoredResult.php b/lib/public/search/ScoredResult.php
new file mode 100644
index 000000000000..ea4c2210dc2e
--- /dev/null
+++ b/lib/public/search/ScoredResult.php
@@ -0,0 +1,58 @@
+
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @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
+ *
+ */
+
+namespace OCP\Search;
+
+/**
+ * The generic result of a search
+ * @since 9.1.0
+ */
+class ScoredResult extends Result {
+
+ /**
+ * A score for the result, ranks between 0 and 1
+ * @var float
+ * @since 9.1.0
+ */
+ public $score;
+
+ /**
+ * Highlight to what part of the result matches the search
+ * @var string
+ * @since 9.1.0
+ */
+ public $highlight;
+
+ /**
+ * Create a new scored search result
+ * @param string $id unique identifier from application: '[app_name]/[item_identifier_in_app]'
+ * @param string $name displayed text of result
+ * @param string $link URL to the result within its app
+ * @param float $score score the result
+ * @param string $highlight for little preview of result
+ * @since 9.1.0
+ */
+ public function __construct($id = null, $name = null, $link = null, $score = null, $highlight = null) {
+ parent::__construct($id, $name, $link);
+ $this->score = $score;
+ $this->highlight = $highlight;
+ }
+}