Passed
Push — master ( 5cdc85...37718d )
by Morris
38:53 queued 21:57
created

AddressBook   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 176
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 68
dl 0
loc 176
rs 10
c 0
b 0
f 0
wmc 28

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getShares() 0 5 2
A updateShares() 0 5 2
A delete() 0 17 3
A canWrite() 0 5 2
A propPatch() 0 5 2
A getChild() 0 8 2
A __construct() 0 6 3
A getResourceId() 0 2 1
A getContactsGroups() 0 2 1
A isShared() 0 6 2
A getOwner() 0 5 2
A getACL() 0 39 5
A getChildACL() 0 2 1
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 * @author Thomas Müller <[email protected]>
7
 *
8
 * @license AGPL-3.0
9
 *
10
 * This code is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License, version 3,
12
 * as published by the Free Software Foundation.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License, version 3,
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
21
 *
22
 */
23
namespace OCA\DAV\CardDAV;
24
25
use OCA\DAV\DAV\Sharing\IShareable;
26
use OCP\IL10N;
27
use Sabre\CardDAV\Backend\BackendInterface;
28
use Sabre\CardDAV\Card;
29
use Sabre\DAV\Exception\Forbidden;
30
use Sabre\DAV\Exception\NotFound;
31
use Sabre\DAV\PropPatch;
32
33
/**
34
 * Class AddressBook
35
 *
36
 * @package OCA\DAV\CardDAV
37
 * @property BackendInterface|CardDavBackend $carddavBackend
38
 */
39
class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable {
40
41
	/**
42
	 * AddressBook constructor.
43
	 *
44
	 * @param BackendInterface $carddavBackend
45
	 * @param array $addressBookInfo
46
	 * @param IL10N $l10n
47
	 */
48
	public function __construct(BackendInterface $carddavBackend, array $addressBookInfo, IL10N $l10n) {
49
		parent::__construct($carddavBackend, $addressBookInfo);
50
51
		if ($this->addressBookInfo['{DAV:}displayname'] === CardDavBackend::PERSONAL_ADDRESSBOOK_NAME &&
52
			$this->getName() === CardDavBackend::PERSONAL_ADDRESSBOOK_URI) {
53
			$this->addressBookInfo['{DAV:}displayname'] = $l10n->t('Contacts');
54
		}
55
	}
56
57
	/**
58
	 * Updates the list of shares.
59
	 *
60
	 * The first array is a list of people that are to be added to the
61
	 * addressbook.
62
	 *
63
	 * Every element in the add array has the following properties:
64
	 *   * href - A url. Usually a mailto: address
65
	 *   * commonName - Usually a first and last name, or false
66
	 *   * summary - A description of the share, can also be false
67
	 *   * readOnly - A boolean value
68
	 *
69
	 * Every element in the remove array is just the address string.
70
	 *
71
	 * @param array $add
72
	 * @param array $remove
73
	 * @return void
74
	 * @throws Forbidden
75
	 */
76
	public function updateShares(array $add, array $remove) {
77
		if ($this->isShared()) {
78
			throw new Forbidden();
79
		}
80
		$this->carddavBackend->updateShares($this, $add, $remove);
0 ignored issues
show
Bug introduced by
The method updateShares() does not exist on Sabre\CardDAV\Backend\BackendInterface. Did you maybe mean updateCard()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

80
		$this->carddavBackend->/** @scrutinizer ignore-call */ 
81
                         updateShares($this, $add, $remove);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
81
	}
82
83
	/**
84
	 * Returns the list of people whom this addressbook is shared with.
85
	 *
86
	 * Every element in this array should have the following properties:
87
	 *   * href - Often a mailto: address
88
	 *   * commonName - Optional, for example a first + last name
89
	 *   * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
90
	 *   * readOnly - boolean
91
	 *   * summary - Optional, a description for the share
92
	 *
93
	 * @return array
94
	 */
95
	public function getShares() {
96
		if ($this->isShared()) {
97
			return [];
98
		}
99
		return $this->carddavBackend->getShares($this->getResourceId());
0 ignored issues
show
Bug introduced by
The method getShares() does not exist on Sabre\CardDAV\Backend\BackendInterface. It seems like you code against a sub-type of Sabre\CardDAV\Backend\BackendInterface such as OCA\DAV\CardDAV\CardDavBackend or OCA\DAV\CardDAV\CardDavBackend. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

99
		return $this->carddavBackend->/** @scrutinizer ignore-call */ getShares($this->getResourceId());
Loading history...
100
	}
101
102
	public function getACL() {
103
		$acl =  [
104
			[
105
				'privilege' => '{DAV:}read',
106
				'principal' => $this->getOwner(),
107
				'protected' => true,
108
			]];
109
		$acl[] = [
110
				'privilege' => '{DAV:}write',
111
				'principal' => $this->getOwner(),
112
				'protected' => true,
113
			];
114
		if ($this->getOwner() !== parent::getOwner()) {
115
			$acl[] =  [
116
					'privilege' => '{DAV:}read',
117
					'principal' => parent::getOwner(),
118
					'protected' => true,
119
				];
120
			if ($this->canWrite()) {
121
				$acl[] = [
122
					'privilege' => '{DAV:}write',
123
					'principal' => parent::getOwner(),
124
					'protected' => true,
125
				];
126
			}
127
		}
128
		if ($this->getOwner() === 'principals/system/system') {
129
			$acl[] = [
130
					'privilege' => '{DAV:}read',
131
					'principal' => '{DAV:}authenticated',
132
					'protected' => true,
133
			];
134
		}
135
136
		if ($this->isShared()) {
137
			return $acl;
138
		}
139
140
		return $this->carddavBackend->applyShareAcl($this->getResourceId(), $acl);
0 ignored issues
show
Bug introduced by
The method applyShareAcl() does not exist on Sabre\CardDAV\Backend\BackendInterface. It seems like you code against a sub-type of Sabre\CardDAV\Backend\BackendInterface such as OCA\DAV\CardDAV\CardDavBackend or OCA\DAV\CardDAV\CardDavBackend. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

140
		return $this->carddavBackend->/** @scrutinizer ignore-call */ applyShareAcl($this->getResourceId(), $acl);
Loading history...
141
	}
142
143
	public function getChildACL() {
144
		return $this->getACL();
145
	}
146
147
	public function getChild($name) {
148
149
		$obj = $this->carddavBackend->getCard($this->addressBookInfo['id'], $name);
150
		if (!$obj) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $obj of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
151
			throw new NotFound('Card not found');
152
		}
153
		$obj['acl'] = $this->getChildACL();
154
		return new Card($this->carddavBackend, $this->addressBookInfo, $obj);
155
156
	}
157
158
	/**
159
	 * @return int
160
	 */
161
	public function getResourceId() {
162
		return $this->addressBookInfo['id'];
163
	}
164
165
	public function getOwner() {
166
		if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) {
167
			return $this->addressBookInfo['{http://owncloud.org/ns}owner-principal'];
168
		}
169
		return parent::getOwner();
170
	}
171
172
	public function delete() {
173
		if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) {
174
			$principal = 'principal:' . parent::getOwner();
175
			$shares = $this->carddavBackend->getShares($this->getResourceId());
176
			$shares = array_filter($shares, function($share) use ($principal){
177
				return $share['href'] === $principal;
178
			});
179
			if (empty($shares)) {
180
				throw new Forbidden();
181
			}
182
183
			$this->carddavBackend->updateShares($this, [], [
184
				$principal
185
			]);
186
			return;
187
		}
188
		parent::delete();
189
	}
190
191
	public function propPatch(PropPatch $propPatch) {
192
		if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) {
193
			throw new Forbidden();
194
		}
195
		parent::propPatch($propPatch);
196
	}
197
198
	public function getContactsGroups() {
199
		return $this->carddavBackend->collectCardProperties($this->getResourceId(), 'CATEGORIES');
0 ignored issues
show
Bug introduced by
The method collectCardProperties() does not exist on Sabre\CardDAV\Backend\BackendInterface. It seems like you code against a sub-type of Sabre\CardDAV\Backend\BackendInterface such as OCA\DAV\CardDAV\CardDavBackend or OCA\DAV\CardDAV\CardDavBackend. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

199
		return $this->carddavBackend->/** @scrutinizer ignore-call */ collectCardProperties($this->getResourceId(), 'CATEGORIES');
Loading history...
200
	}
201
202
	private function isShared() {
203
		if (!isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) {
204
			return false;
205
		}
206
207
		return $this->addressBookInfo['{http://owncloud.org/ns}owner-principal'] !== $this->addressBookInfo['principaluri'];
208
	}
209
210
	private function canWrite() {
211
		if (isset($this->addressBookInfo['{http://owncloud.org/ns}read-only'])) {
212
			return !$this->addressBookInfo['{http://owncloud.org/ns}read-only'];
213
		}
214
		return true;
215
	}
216
}
217