Backend   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 254
Duplicated Lines 12.2 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 2 Features 0
Metric Value
wmc 28
c 2
b 2
f 0
lcom 1
cbo 1
dl 31
loc 254
ccs 0
cts 131
cp 0
rs 10

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A deleteAddressBook() 0 4 1
A lastModifiedAddressBook() 0 4 1
A createCard() 0 4 1
A updateCard() 0 4 1
A deleteCard() 0 4 1
A userIDByPrincipal() 0 4 1
B getAddressBooksForUser() 0 31 5
B updateAddressBook() 15 25 4
B createAddressBook() 16 26 4
A getCards() 0 17 2
A getCard() 0 16 3
A getBackendForAddressBook() 0 9 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * ownCloud - Addressbook
4
 *
5
 * @author Jakob Sack
6
 * @author Thomas Tanghus
7
 * @copyright 2011 Jakob Sack [email protected]
8
 * @copyright 2012-2014 Thomas Tanghus ([email protected])
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
12
 * License as published by the Free Software Foundation; either
13
 * version 3 of the License, or any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public
21
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
25
namespace OCA\Contacts\CardDAV;
26
27
use OCA\Contacts;
28
use \Sabre\DAV\PropPatch;
29
30
/**
31
 * This class exchanges data between SabreDav and the Address book backends.
32
 *
33
 * Address book IDs are a combination of the backend name and the ID it has
34
 * in that backend. For your own address books it can be e.g 'local::1' for
35
 * an address book shared with you it could be 'shared::2' an so forth.
36
 */
37
class Backend extends \Sabre\CardDAV\Backend\AbstractBackend {
38
39
	public function __construct($backends) {
40
		$this->backends = $backends;
41
	}
42
43
	/**
44
	 * Returns the list of addressbooks for a specific user.
45
	 *
46
	 * @param string $principaluri
47
	 * @return array
48
	 */
49
	public function getAddressBooksForUser($principaluri) {
50
51
		$app = new Contacts\App();
52
		$userAddressBooks = array();
53
		foreach($this->backends as $backendName) {
54
			$backend = $app->getBackend($backendName);
55
			$addressBooks = $backend->getAddressBooksForUser();
56
57
			if (is_array($addressBooks)) {
58
				foreach($addressBooks as $addressBook) {
59
					if($addressBook['owner'] != \OC::$server->getUserSession()->getUser()->getUId()) {
60
						$addressBook['uri'] = $addressBook['uri'] . '_shared_by_' . $addressBook['owner'];
61
						$addressBook['displayname'] = $addressBook['displayname'];
62
					}
63
					$userAddressBooks[] = array(
64
						'id'  => $backend->name . '::' . $addressBook['id'],
65
						'uri' => $addressBook['uri'],
66
						'principaluri' => 'principals/'.$addressBook['owner'],
67
						'{DAV:}displayname' => $addressBook['displayname'],
68
						'{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}addressbook-description'
69
								=> $addressBook['description'],
70
						'{http://calendarserver.org/ns/}getctag' => $addressBook['lastmodified'],
71
						'{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}supported-address-data' =>
72
							new \Sabre\CardDAV\Property\SupportedAddressData(),
73
					);
74
				}
75
			}
76
		}
77
78
		return $userAddressBooks;
79
	}
80
81
82
	/**
83
	 * Updates an addressbook's properties
84
	 *
85
	 * See \Sabre\DAV\IProperties for a description of the mutations array, as
86
	 * well as the return value.
87
	 *
88
	 * @param mixed $addressbookid
89
	 * @see \Sabre\DAV\IProperties::updateProperties
90
	 * @return bool|array
91
	 */
92
	public function updateAddressBook($addressbookid, PropPatch $propPatch) {
93
		$changes = array();
94
95
		$mutations = $propPatch->getRemainingMutations();
96
97 View Code Duplication
		foreach($mutations as $property=>$newvalue) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
98
			switch($property) {
99
				case '{DAV:}displayname' :
100
					$changes['displayname'] = $newvalue;
101
					break;
102
				case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV
103
						. '}addressbook-description' :
104
					$changes['description'] = $newvalue;
105
					break;
106
				default :
107
					// If any unsupported values were being updated, we must
108
					// let the entire request fail.
109
					return false;
110
			}
111
		}
112
113
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
114
		return $backend->updateAddressBook($id, $changes);
115
116
	}
117
118
	/**
119
	 * Creates a new address book
120
	 *
121
	 * @param string $principaluri
122
	 * @param string $uri Just the 'basename' of the url.
123
	 * @param array $properties
124
	 * @return void
125
	 */
126
	public function createAddressBook($principaluri, $uri, array $properties) {
127
128 View Code Duplication
		foreach($properties as $property => $newvalue) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
130
			switch($property) {
131
				case '{DAV:}displayname' :
132
					$properties['displayname'] = $newvalue;
133
					break;
134
				case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV
135
						. '}addressbook-description' :
136
					$properties['description'] = $newvalue;
137
					break;
138
				default :
139
					throw new \Sabre\DAV\Exception\BadRequest('Unknown property: '
140
						. $property);
141
			}
142
143
		}
144
145
		$properties['uri'] = $uri;
146
147
		$app = new Contacts\App();
148
		$backend = $app->getBackend('local');
149
150
		$backend->createAddressBook($properties);
151
	}
152
153
	/**
154
	 * Deletes an entire addressbook and all its contents
155
	 *
156
	 * @param mixed $addressbookid
157
	 * @return void
158
	 */
159
	public function deleteAddressBook($addressbookid) {
160
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
161
		$backend->deleteAddressBook($id);
162
	}
163
164
	/**
165
	 * Returns the last modified date if the backend supports it.
166
	 *
167
	 * @param mixed $addressbookid
168
	 * @return void
169
	 */
170
	public function lastModifiedAddressBook($addressbookid) {
171
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
172
		return $backend->lastModifiedAddressBook($id);
173
	}
174
175
	/**
176
	 * Returns all cards for a specific addressbook id.
177
	 *
178
	 * @param mixed $addressbookid
179
	 * @return array
180
	 */
181
	public function getCards($addressbookid) {
182
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
183
		$contacts = $backend->getContacts($id);
184
185
		$cards = array();
186
		foreach($contacts as $contact) {
187
			$cards[] = array(
188
				'id' => $contact['id'],
189
				//'carddata' => $i['carddata'],
190
				'size' => strlen($contact['carddata']),
191
				'etag' => '"' . md5($contact['carddata']) . '"',
192
				'uri' => $contact['uri'],
193
				'lastmodified' => $contact['lastmodified'] );
194
		}
195
196
		return $cards;
197
	}
198
199
	/**
200
	 * Returns a specfic card
201
	 *
202
	 * @param mixed $addressbookid
203
	 * @param string $carduri
204
	 * @return array
205
	 */
206
	public function getCard($addressbookid, $carduri) {
207
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
208
		try {
209
			$contact = $backend->getContact($id, array('uri' => urldecode($carduri)));
210
		} catch(\Exception $e) {
211
			//throw new \Sabre\DAV\Exception\NotFound($e->getMessage());
212
			\OCP\Util::writeLog('contacts', __METHOD__.', Exception: '. $e->getMessage(), \OCP\Util::DEBUG);
213
			return false;
214
		}
215
		if(is_array($contact) ) {
216
			$contact['etag'] = '"' . md5($contact['carddata']) . '"';
217
			return $contact;
218
		}
219
		//throw new \Sabre\DAV\Exception('Error retrieving the card');
220
		return false;
221
	}
222
223
	/**
224
	 * Creates a new card
225
	 *
226
	 * We don't return an Etag as the carddata can have been modified
227
	 * by Plugin::validate()
228
	 *
229
	 * @see Plugin::validate()
230
	 * @param mixed $addressbookid
231
	 * @param string $carduri
232
	 * @param string $carddata
233
	 * @return string|null
234
	 */
235
	public function createCard($addressbookid, $carduri, $carddata) {
236
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
237
		$backend->createContact($id, $carddata, array('uri' => $carduri));
238
	}
239
240
	/**
241
	 * Updates a card
242
	 *
243
	 * @param mixed $addressbookid
244
	 * @param string $carduri
245
	 * @param string $carddata
246
	 * @return null
247
	 */
248
	public function updateCard($addressbookid, $carduri, $carddata) {
249
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
250
		$backend->updateContact($id, array('uri' => $carduri,), $carddata);
251
	}
252
253
	/**
254
	 * Deletes a card
255
	 *
256
	 * @param mixed $addressbookid
257
	 * @param string $carduri
258
	 * @return bool
259
	 */
260
	public function deleteCard($addressbookid, $carduri) {
261
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
262
		return $backend->deleteContact($id, array('uri' => $carduri));
263
	}
264
265
	/**
266
	 * @brief gets the userid from a principal path
267
	 * @param string $principaluri
268
	 * @return string
269
	 */
270
	public function userIDByPrincipal($principaluri) {
271
		list(, $userid) = \Sabre\DAV\URLUtil::splitPath($principaluri);
272
		return $userid;
273
	}
274
275
	/**
276
	 * Get the backend for an address book
277
	 *
278
	 * @param mixed $addressbookid
279
	 * @return array(string, \OCA\Contacts\Backend\AbstractBackend)
0 ignored issues
show
Documentation introduced by
The doc-type array(string, could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
280
	 */
281
	public function getBackendForAddressBook($addressbookid) {
282
		list($backendName, $id) = explode('::', $addressbookid);
283
		$app = new Contacts\App();
284
		$backend = $app->getBackend($backendName);
285
		if($backend->name === $backendName && $backend->hasAddressBook($id)) {
286
			return array($id, $backend);
287
		}
288
		throw new \Sabre\DAV\Exception\NotFound('Backend not found: ' . $addressbookid);
289
	}
290
}
291