Completed
Push — master ( 1e7efd...5c2a3f )
by Robin
02:13
created

DiscoverHandler::handelDiscoverRequest()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 25
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 21
nc 2
nop 3
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Robin Appelman <[email protected]>
4
 *
5
 * @license GNU AGPL version 3 or any later version
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Affero General Public License as
9
 * published by the Free Software Foundation, either version 3 of the
10
 * License, or (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 */
21
22
namespace SearchDAV\DAV;
23
24
use Sabre\DAV\Exception\BadRequest;
25
use Sabre\DAV\Xml\Response\MultiStatus;
26
use Sabre\HTTP\RequestInterface;
27
use Sabre\HTTP\ResponseInterface;
28
use SearchDAV\Backend\ISearchBackend;
29
use SearchDAV\Backend\SearchPropertyDefinition;
30
use SearchDAV\XML\BasicSearch;
31
use SearchDAV\XML\BasicSearchSchema;
32
use SearchDAV\XML\PropDesc;
33
use SearchDAV\XML\QueryDiscoverResponse;
34
use SearchDAV\XML\Scope;
35
36
class DiscoverHandler {
37
	/** @var ISearchBackend */
38
	private $searchBackend;
39
40
	/** @var PathHelper */
41
	private $pathHelper;
42
43
	/** @var QueryParser */
44
	private $queryParser;
45
46
	/**
47
	 * @param ISearchBackend $searchBackend
48
	 * @param PathHelper $pathHelper
49
	 * @param QueryParser $queryParser
50
	 */
51
	public function __construct(ISearchBackend $searchBackend, PathHelper $pathHelper, QueryParser $queryParser) {
52
		$this->searchBackend = $searchBackend;
53
		$this->pathHelper = $pathHelper;
54
		$this->queryParser = $queryParser;
55
	}
56
57
	public function handelDiscoverRequest($xml, RequestInterface $request, ResponseInterface $response) {
58
		if (!isset($xml['{DAV:}basicsearch'])) {
59
			$response->setStatus(400);
60
			$response->setBody('Unexpected xml content for query-schema-discovery, expected basicsearch');
61
			return false;
62
		}
63
		/** @var BasicSearch $query */
64
		$query = $xml['{DAV:}basicsearch'];
65
		$scopes = $query->from;
66
		$results = array_map(function (Scope $scope) {
67
			$scope->path = $this->pathHelper->getPathFromUri($scope->href);
68
			if ($this->searchBackend->isValidScope($scope->href, $scope->depth, $scope->path)) {
69
				$searchProperties = $this->searchBackend->getPropertyDefinitionsForScope($scope->href, $scope->path);
70
				$searchSchema = $this->getBasicSearchForProperties($searchProperties);
71
				return new QueryDiscoverResponse($scope->href, $searchSchema, 200);
72
			} else {
73
				return new QueryDiscoverResponse($scope->href, null, 404); // TODO something other than 404? 403 maybe
74
			}
75
		}, $scopes);
76
		$multiStatus = new MultiStatus($results);
77
		$response->setStatus(207);
78
		$response->setHeader('Content-Type', 'application/xml; charset="utf-8"');
79
		$response->setBody($this->queryParser->write('{DAV:}multistatus', $multiStatus, $request->getUrl()));
80
		return false;
81
	}
82
83
	private function hashDefinition(SearchPropertyDefinition $definition) {
84
		return $definition->dataType
85
			. (($definition->searchable) ? '1' : '0')
86
			. (($definition->sortable) ? '1' : '0')
87
			. (($definition->selectable) ? '1' : '0');
88
	}
89
90
	/**
91
	 * @param SearchPropertyDefinition[] $propertyDefinitions
92
	 * @return BasicSearchSchema
93
	 */
94
	private function getBasicSearchForProperties(array $propertyDefinitions) {
95
		/** @var PropDesc[] $groups */
96
		$groups = [];
97
		foreach ($propertyDefinitions as $propertyDefinition) {
98
			$key = $this->hashDefinition($propertyDefinition);
99
			if (!isset($groups[$key])) {
100
				$desc = new PropDesc();
101
				$desc->dataType = $propertyDefinition->dataType;
102
				$desc->sortable = $propertyDefinition->sortable;
103
				$desc->selectable = $propertyDefinition->selectable;
104
				$desc->searchable = $propertyDefinition->searchable;
105
				$groups[$key] = $desc;
106
			}
107
			$groups[$key]->properties[] = $propertyDefinition->name;
108
		}
109
110
		return new BasicSearchSchema(array_values($groups));
111
	}
112
}
113