Completed
Push — master ( d60977...1e7efd )
by Robin
02:37
created

DiscoverHandler::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
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 (!$xml['{DAV:}basicsearch']) {
59
			throw new BadRequest('Unexpected xml content for query-schema-discovery, expected basicsearch');
60
		}
61
		/** @var BasicSearch $query */
62
		$query = $xml['{DAV:}basicsearch'];
63
		$scopes = $query->from;
64
		$results = array_map(function (Scope $scope) {
65
			$scope->path = $this->pathHelper->getPathFromUri($scope->href);
66
			if ($this->searchBackend->isValidScope($scope->href, $scope->depth, $scope->path)) {
67
				$searchProperties = $this->searchBackend->getPropertyDefinitionsForScope($scope->href, $scope->path);
68
				$searchSchema = $this->getBasicSearchForProperties($searchProperties);
69
				return new QueryDiscoverResponse($scope->href, $searchSchema, 200);
70
			} else {
71
				return new QueryDiscoverResponse($scope->href, null, 404); // TODO something other than 404? 403 maybe
72
			}
73
		}, $scopes);
74
		$multiStatus = new MultiStatus($results);
75
		$response->setStatus(207);
76
		$response->setHeader('Content-Type', 'application/xml; charset="utf-8"');
77
		$response->setBody($this->queryParser->write('{DAV:}multistatus', $multiStatus, $request->getUrl()));
78
		return false;
79
	}
80
81
	private function hashDefinition(SearchPropertyDefinition $definition) {
82
		return $definition->dataType
83
			. (($definition->searchable) ? '1' : '0')
84
			. (($definition->sortable) ? '1' : '0')
85
			. (($definition->selectable) ? '1' : '0');
86
	}
87
88
	/**
89
	 * @param SearchPropertyDefinition[] $propertyDefinitions
90
	 * @return BasicSearchSchema
91
	 */
92
	private function getBasicSearchForProperties(array $propertyDefinitions) {
93
		/** @var PropDesc[] $groups */
94
		$groups = [];
95
		foreach ($propertyDefinitions as $propertyDefinition) {
96
			$key = $this->hashDefinition($propertyDefinition);
97
			if (!isset($groups[$key])) {
98
				$desc = new PropDesc();
99
				$desc->dataType = $propertyDefinition->dataType;
100
				$desc->sortable = $propertyDefinition->sortable;
101
				$desc->selectable = $propertyDefinition->selectable;
102
				$desc->searchable = $propertyDefinition->searchable;
103
				$groups[$key] = $desc;
104
			}
105
			$groups[$key]->properties[] = $propertyDefinition->name;
106
		}
107
108
		return new BasicSearchSchema(array_values($groups));
109
	}
110
}
111