]> source.dussan.org Git - nextcloud-server.git/commitdiff
add icewind/searchdav
authorRobin Appelman <robin@icewind.nl>
Thu, 2 Feb 2017 17:19:16 +0000 (18:19 +0100)
committerRobin Appelman <robin@icewind.nl>
Tue, 28 Feb 2017 13:24:18 +0000 (14:24 +0100)
Signed-off-by: Robin Appelman <robin@icewind.nl>
13 files changed:
3rdparty
apps/dav/lib/Files/FileSearchBackend.php [new file with mode: 0644]
lib/private/Files/Cache/QuerySearchHelper.php [new file with mode: 0644]
lib/private/Files/Search/SearchBinaryOperator.php [new file with mode: 0644]
lib/private/Files/Search/SearchComparison.php [new file with mode: 0644]
lib/private/Files/Search/SearchOrder.php [new file with mode: 0644]
lib/private/Files/Search/SearchQuery.php [new file with mode: 0644]
lib/public/Files/Search/ISearchBinaryOperator.php [new file with mode: 0644]
lib/public/Files/Search/ISearchComparison.php [new file with mode: 0644]
lib/public/Files/Search/ISearchOperator.php [new file with mode: 0644]
lib/public/Files/Search/ISearchOrder.php [new file with mode: 0644]
lib/public/Files/Search/ISearchQuery.php [new file with mode: 0644]
tests/lib/Files/Cache/QuerySearchHelperTest.php [new file with mode: 0644]

index 489bcf4f81e462f4d74f0b76f58caeabd58e75de..2838fa6777b1427c6c912a5e599a96639ac2b31f 160000 (submodule)
--- a/3rdparty
+++ b/3rdparty
@@ -1 +1 @@
-Subproject commit 489bcf4f81e462f4d74f0b76f58caeabd58e75de
+Subproject commit 2838fa6777b1427c6c912a5e599a96639ac2b31f
diff --git a/apps/dav/lib/Files/FileSearchBackend.php b/apps/dav/lib/Files/FileSearchBackend.php
new file mode 100644 (file)
index 0000000..2a89c75
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\DAV\Files;
+
+use OCA\DAV\Connector\Sabre\Directory;
+use Sabre\DAV\Exception\NotFound;
+use Sabre\DAV\Tree;
+use SearchDAV\Backend\ISearchBackend;
+use SearchDAV\Backend\SearchPropertyDefinition;
+
+class FileSearchBackend implements ISearchBackend {
+       /** @var Tree */
+       private $tree;
+
+       /**
+        * FileSearchBackend constructor.
+        *
+        * @param Tree $tree
+        */
+       public function __construct(Tree $tree) {
+               $this->tree = $tree;
+       }
+
+       /**
+        * Search endpoint will be remote.php/dav/files
+        *
+        * @return string
+        */
+       public function getArbiterPath() {
+               return 'files';
+       }
+
+       public function isValidScope($href, $depth, $path) {
+               // only allow scopes inside the dav server
+               if (is_null($path)) {
+                       return false;
+               }
+
+               try {
+                       $node = $this->tree->getNodeForPath($path);
+                       return $node instanceof Directory;
+               } catch (NotFound $e) {
+                       return false;
+               }
+       }
+
+       public function getPropertyDefinitionsForScope($href, $path) {
+               // all valid scopes support the same schema
+
+               return [
+                       new SearchPropertyDefinition('{DAV:}getcontentlength', true, true, true, SearchPropertyDefinition::DATATYPE_NONNEGATIVE_INTEGER),
+                       new SearchPropertyDefinition('{DAV:}getcontenttype', true, true, true),
+                       new SearchPropertyDefinition('{DAV:}displayname', true, true, true),
+                       new SearchPropertyDefinition('{http://ns.nextcloud.com:}fileid', false, true, true, SearchPropertyDefinition::DATATYPE_NONNEGATIVE_INTEGER),
+               ];
+       }
+}
diff --git a/lib/private/Files/Cache/QuerySearchHelper.php b/lib/private/Files/Cache/QuerySearchHelper.php
new file mode 100644 (file)
index 0000000..60f4e48
--- /dev/null
@@ -0,0 +1,155 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Files\Cache;
+
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\Files\IMimeTypeLoader;
+use OCP\Files\Search\ISearchBinaryOperator;
+use OCP\Files\Search\ISearchComparison;
+use OCP\Files\Search\ISearchOperator;
+
+/**
+ * Tools for transforming search queries into database queries
+ */
+class QuerySearchUtil {
+       static protected $searchOperatorMap = [
+               ISearchComparison::COMPARE_LIKE => 'iLike',
+               ISearchComparison::COMPARE_EQUAL => 'eq',
+               ISearchComparison::COMPARE_GREATER_THAN => 'gt',
+               ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'gte',
+               ISearchComparison::COMPARE_LESS_THAN => 'lt',
+               ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lte'
+       ];
+
+       static protected $searchOperatorNegativeMap = [
+               ISearchComparison::COMPARE_LIKE => 'notLike',
+               ISearchComparison::COMPARE_EQUAL => 'neq',
+               ISearchComparison::COMPARE_GREATER_THAN => 'lte',
+               ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'lt',
+               ISearchComparison::COMPARE_LESS_THAN => 'gte',
+               ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lt'
+       ];
+
+       /** @var IMimeTypeLoader */
+       private $mimetypeLoader;
+
+       /**
+        * QuerySearchUtil constructor.
+        *
+        * @param IMimeTypeLoader $mimetypeLoader
+        */
+       public function __construct(IMimeTypeLoader $mimetypeLoader) {
+               $this->mimetypeLoader = $mimetypeLoader;
+       }
+
+       public function searchOperatorToDBExpr(IQueryBuilder $builder, ISearchOperator $operator) {
+               $expr = $builder->expr();
+               if ($operator instanceof ISearchBinaryOperator) {
+                       switch ($operator->getType()) {
+                               case ISearchBinaryOperator::OPERATOR_NOT:
+                                       $negativeOperator = $operator->getArguments()[0];
+                                       if ($negativeOperator instanceof ISearchComparison) {
+                                               return $this->searchComparisonToDBExpr($builder, $negativeOperator, self::$searchOperatorNegativeMap);
+                                       } else {
+                                               throw new \InvalidArgumentException('Binary operators inside "not" is not supported');
+                                       }
+                               case ISearchBinaryOperator::OPERATOR_AND:
+                                       return $expr->andX($this->searchOperatorToDBExpr($operator->getArguments()[0], $operator->getArguments()[1]));
+                               case ISearchBinaryOperator::OPERATOR_OR:
+                                       return $expr->orX($this->searchOperatorToDBExpr($operator->getArguments()[0], $operator->getArguments()[1]));
+                               default:
+                                       throw new \InvalidArgumentException('Invalid operator type: ' . $operator->getType());
+                       }
+               } else if ($operator instanceof ISearchComparison) {
+                       return $this->searchComparisonToDBExpr($builder, $operator, self::$searchOperatorMap);
+               } else {
+                       throw new \InvalidArgumentException('Invalid operator type: ' . get_class($operator));
+               }
+       }
+
+       private function searchComparisonToDBExpr(IQueryBuilder $builder, ISearchComparison $comparison, array $operatorMap) {
+               if (!$this->isValidComparison($comparison)) {
+                       throw new \InvalidArgumentException('Invalid comparison ' . $operator->getType() . ' on field ' . $operator->getField());
+               }
+
+               list($field, $value) = $this->getOperatorFieldAndValue($comparison);
+               if (isset($operatorMap[$comparison->getType()])) {
+                       $queryOperator = $operatorMap[$comparison->getType()];
+                       return $builder->expr()->$queryOperator($field, $this->getParameterForValue($builder, $value));
+               } else {
+                       throw new \InvalidArgumentException('Invalid operator type: ' . $comparison->getType());
+               }
+       }
+
+       private function getOperatorFieldAndValue(ISearchComparison $operator) {
+               $field = $operator->getField();
+               $value = $operator->getValue();
+               if ($field === 'mimetype') {
+                       if ($operator->getType() === ISearchComparison::COMPARE_EQUAL) {
+                               $value = $this->mimetypeLoader->getId($value);
+                       } else if ($operator->getType() === ISearchComparison::COMPARE_LIKE) {
+                               // transform "mimetype='foo/%'" to "mimepart='foo'"
+                               if (preg_match('|(.+)/%|', $value, $matches)) {
+                                       $field = 'mimepart';
+                                       $value = $this->mimetypeLoader->getId($matches[1]);
+                               }
+                       }
+               }
+               return [$field, $value];
+       }
+
+       private function isValidComparison(ISearchComparison $operator) {
+               $types = [
+                       'mimetype' => 'string',
+                       'mtime' => \DateTime::class,
+                       'name' => 'string',
+                       'size' => 'integer'
+               ];
+               $comparisons = [
+                       'mimetype' => ['eq', 'like'],
+                       'mtime' => ['eq', 'gt', 'lt', 'gte', 'lte'],
+                       'name' => ['eq', 'like'],
+                       'size' => ['eq', 'gt', 'lt', 'gte', 'lte']
+               ];
+
+               if (!isset($types[$operator->getField()])) {
+                       return false;
+               }
+               $type = $types[$operator->getField()];
+               if (gettype($operator->getValue()) !== $type && !(is_a($operator->getValue(), $type))) {
+                       return false;
+               }
+               return in_array($operator->getType(), $comparisons[$operator->getField()]);
+       }
+
+       private function getParameterForValue(IQueryBuilder $builder, $value) {
+               if ($value instanceof \DateTime) {
+                       $value = $value->getTimestamp();
+               }
+               if (is_numeric($value)) {
+                       $type = IQueryBuilder::PARAM_INT;
+               } else {
+                       $type = IQueryBuilder::PARAM_STR;
+               }
+               return $builder->createNamedParameter($value, $type);
+       }
+}
diff --git a/lib/private/Files/Search/SearchBinaryOperator.php b/lib/private/Files/Search/SearchBinaryOperator.php
new file mode 100644 (file)
index 0000000..15944e2
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
diff --git a/lib/private/Files/Search/SearchComparison.php b/lib/private/Files/Search/SearchComparison.php
new file mode 100644 (file)
index 0000000..32c4ad0
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Files\Search;
+
+use OCP\Files\Search\ISearchComparison;
+
+class SearchComparison implements ISearchComparison {
+       /** @var string */
+       private $type;
+       /** @var string */
+       private $field;
+       /** @var string|integer|\DateTime */
+       private $value;
+
+       /**
+        * SearchComparison constructor.
+        *
+        * @param string $type
+        * @param string $field
+        * @param \DateTime|int|string $value
+        */
+       public function __construct($type, $field, $value) {
+               $this->type = $type;
+               $this->field = $field;
+               $this->value = $value;
+       }
+
+       /**
+        * @return string
+        */
+       public function getType() {
+               return $this->type;
+       }
+
+       /**
+        * @return string
+        */
+       public function getField() {
+               return $this->field;
+       }
+
+       /**
+        * @return \DateTime|int|string
+        */
+       public function getValue() {
+               return $this->value;
+       }
+}
diff --git a/lib/private/Files/Search/SearchOrder.php b/lib/private/Files/Search/SearchOrder.php
new file mode 100644 (file)
index 0000000..c76d6f2
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Files\Search;
+
+
+use OCP\Files\Search\ISearchOrder;
+
+class SearchOrder implements ISearchOrder {
+       /** @var  string */
+       private $direction;
+       /** @var  string */
+       private $field;
+
+       /**
+        * SearchOrder constructor.
+        *
+        * @param string $direction
+        * @param string $field
+        */
+       public function __construct($direction, $field) {
+               $this->direction = $direction;
+               $this->field = $field;
+       }
+
+       /**
+        * @return string
+        */
+       public function getDirection() {
+               return $this->direction;
+       }
+
+       /**
+        * @return string
+        */
+       public function getField() {
+               return $this->field;
+       }
+}
diff --git a/lib/private/Files/Search/SearchQuery.php b/lib/private/Files/Search/SearchQuery.php
new file mode 100644 (file)
index 0000000..a017d3e
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Files\Search;
+
diff --git a/lib/public/Files/Search/ISearchBinaryOperator.php b/lib/public/Files/Search/ISearchBinaryOperator.php
new file mode 100644 (file)
index 0000000..248e3de
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Files\Search;
+
+interface ISearchBinaryOperator extends ISearchOperator {
+       const OPERATOR_AND = 'and';
+       const OPERATOR_OR = 'or';
+       const OPERATOR_NOT = 'not';
+
+       /**
+        * The type of binary operator
+        *
+        * One of the ISearchBinaryOperator::OPERATOR_* constants
+        *
+        * @return string
+        */
+       public function getType();
+
+       /**
+        * The arguments for the binary operator
+        *
+        * One argument for the 'not' operator and two for 'and' and 'or'
+        *
+        * @return ISearchOperator[]
+        */
+       public function getArguments();
+}
diff --git a/lib/public/Files/Search/ISearchComparison.php b/lib/public/Files/Search/ISearchComparison.php
new file mode 100644 (file)
index 0000000..0534221
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Files\Search;
+
+interface ISearchComparison extends ISearchOperator {
+       const COMPARE_EQUAL = 'eq';
+       const COMPARE_GREATER_THAN = 'gt';
+       const COMPARE_GREATER_THAN_EQUAL = 'gte';
+       const COMPARE_LESS_THAN = 'lt';
+       const COMPARE_LESS_THAN_EQUAL = 'lte';
+       const COMPARE_LIKE = 'like';
+
+       /**
+        * Get the type of comparison, one of the ISearchComparison::COMPARE_* constants
+        *
+        * @return string
+        */
+       public function getType();
+
+       /**
+        * Get the name of the field to compare with
+        *
+        * i.e. 'size', 'name' or 'mimetype'
+        *
+        * @return string
+        */
+       public function getField();
+
+       /**
+        * Get the value to compare the field with
+        *
+        * @return string|integer|\DateTime
+        */
+       public function getValue();
+}
diff --git a/lib/public/Files/Search/ISearchOperator.php b/lib/public/Files/Search/ISearchOperator.php
new file mode 100644 (file)
index 0000000..fc1db57
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Files\Search;
+
+interface ISearchCondition {
+
+}
diff --git a/lib/public/Files/Search/ISearchOrder.php b/lib/public/Files/Search/ISearchOrder.php
new file mode 100644 (file)
index 0000000..1abfd75
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Files\Search;
+
+/**
+ * @since 12.0.0
+ */
+interface ISearchOrder {
+       const DIRECTION_ASCENDING = 'asc';
+       const DIRECTION_DESCENDING = 'desc';
+
+       /**
+        * The direction to sort in, either ISearchOrder::DIRECTION_ASCENDING or ISearchOrder::DIRECTION_DESCENDING
+        *
+        * @return string
+        * @since 12.0.0
+        */
+       public function getDirection();
+
+       /**
+        * The field to sort on
+        *
+        * @return string
+        * @since 12.0.0
+        */
+       public function getField();
+}
diff --git a/lib/public/Files/Search/ISearchQuery.php b/lib/public/Files/Search/ISearchQuery.php
new file mode 100644 (file)
index 0000000..f9c0753
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Files\Search;
+
+/**
+ * @since 12.0.0
+ */
+interface ISearchQuery {
+       /**
+        * @return ISearchOperator
+        * @since 12.0.0
+        */
+       public function getSearchOperation();
+}
diff --git a/tests/lib/Files/Cache/QuerySearchHelperTest.php b/tests/lib/Files/Cache/QuerySearchHelperTest.php
new file mode 100644 (file)
index 0000000..bdf3d79
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Test\Files\Cache;
+
+use Test\TestCase;
+
+class QuerySearchHelperTest extends TestCase {
+
+}