Passed
Push — master ( 34463b...78da95 )
by Morris
13:56 queued 11s
created
apps/dav/lib/CardDAV/AddressBookImpl.php 1 patch
Indentation   +300 added lines, -300 removed lines patch added patch discarded remove patch
@@ -40,304 +40,304 @@
 block discarded – undo
40 40
 
41 41
 class AddressBookImpl implements IAddressBook {
42 42
 
43
-	/** @var CardDavBackend */
44
-	private $backend;
45
-
46
-	/** @var array */
47
-	private $addressBookInfo;
48
-
49
-	/** @var AddressBook */
50
-	private $addressBook;
51
-
52
-	/** @var IURLGenerator */
53
-	private $urlGenerator;
54
-
55
-	/**
56
-	 * AddressBookImpl constructor.
57
-	 *
58
-	 * @param AddressBook $addressBook
59
-	 * @param array $addressBookInfo
60
-	 * @param CardDavBackend $backend
61
-	 * @param IUrlGenerator $urlGenerator
62
-	 */
63
-	public function __construct(
64
-			AddressBook $addressBook,
65
-			array $addressBookInfo,
66
-			CardDavBackend $backend,
67
-			IURLGenerator $urlGenerator) {
68
-		$this->addressBook = $addressBook;
69
-		$this->addressBookInfo = $addressBookInfo;
70
-		$this->backend = $backend;
71
-		$this->urlGenerator = $urlGenerator;
72
-	}
73
-
74
-	/**
75
-	 * @return string defining the technical unique key
76
-	 * @since 5.0.0
77
-	 */
78
-	public function getKey() {
79
-		return $this->addressBookInfo['id'];
80
-	}
81
-
82
-	/**
83
-	 * @return string defining the unique uri
84
-	 * @since 16.0.0
85
-	 */
86
-	public function getUri(): string {
87
-		return $this->addressBookInfo['uri'];
88
-	}
89
-
90
-	/**
91
-	 * In comparison to getKey() this function returns a human readable (maybe translated) name
92
-	 *
93
-	 * @return mixed
94
-	 * @since 5.0.0
95
-	 */
96
-	public function getDisplayName() {
97
-		return $this->addressBookInfo['{DAV:}displayname'];
98
-	}
99
-
100
-	/**
101
-	 * @param string $pattern which should match within the $searchProperties
102
-	 * @param array $searchProperties defines the properties within the query pattern should match
103
-	 * @param array $options Options to define the output format and search behavior
104
-	 * 	- 'types' boolean (since 15.0.0) If set to true, fields that come with a TYPE property will be an array
105
-	 *    example: ['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['type => 'HOME', 'value' => '[email protected]']]
106
-	 * 	- 'escape_like_param' - If set to false wildcards _ and % are not escaped
107
-	 * 	- 'limit' - Set a numeric limit for the search results
108
-	 * 	- 'offset' - Set the offset for the limited search results
109
-	 * @return array an array of contacts which are arrays of key-value-pairs
110
-	 *  example result:
111
-	 *  [
112
-	 *		['id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => '[email protected]', 'GEO' => '37.386013;-122.082932'],
113
-	 *		['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['[email protected]', '[email protected]']]
114
-	 *	]
115
-	 * @since 5.0.0
116
-	 */
117
-	public function search($pattern, $searchProperties, $options) {
118
-		$results = $this->backend->search($this->getKey(), $pattern, $searchProperties, $options);
119
-
120
-		$withTypes = \array_key_exists('types', $options) && $options['types'] === true;
121
-
122
-		$vCards = [];
123
-		foreach ($results as $result) {
124
-			$vCards[] = $this->vCard2Array($result['uri'], $this->readCard($result['carddata']), $withTypes);
125
-		}
126
-
127
-		return $vCards;
128
-	}
129
-
130
-	/**
131
-	 * @param array $properties this array if key-value-pairs defines a contact
132
-	 * @return array an array representing the contact just created or updated
133
-	 * @since 5.0.0
134
-	 */
135
-	public function createOrUpdate($properties) {
136
-		$update = false;
137
-		if (!isset($properties['URI'])) { // create a new contact
138
-			$uid = $this->createUid();
139
-			$uri = $uid . '.vcf';
140
-			$vCard = $this->createEmptyVCard($uid);
141
-		} else { // update existing contact
142
-			$uri = $properties['URI'];
143
-			$vCardData = $this->backend->getCard($this->getKey(), $uri);
144
-			$vCard = $this->readCard($vCardData['carddata']);
145
-			$update = true;
146
-		}
147
-
148
-		foreach ($properties as $key => $value) {
149
-			if (is_array($value)) {
150
-				$vCard->remove($key);
151
-				foreach ($value as $entry) {
152
-					if (($key === "ADR" || $key === "PHOTO") && is_string($entry["value"])) {
153
-						$entry["value"] = stripslashes($entry["value"]);
154
-						$entry["value"] = explode(';', $entry["value"]);
155
-					}
156
-					$property = $vCard->createProperty($key, $entry["value"]);
157
-					if (isset($entry["type"])) {
158
-						$property->add('TYPE', $entry["type"]);
159
-					}
160
-					$vCard->add($property);
161
-				}
162
-			} elseif ($key !== 'URI') {
163
-				$vCard->$key = $vCard->createProperty($key, $value);
164
-			}
165
-		}
166
-
167
-		if ($update) {
168
-			$this->backend->updateCard($this->getKey(), $uri, $vCard->serialize());
169
-		} else {
170
-			$this->backend->createCard($this->getKey(), $uri, $vCard->serialize());
171
-		}
172
-
173
-		return $this->vCard2Array($uri, $vCard);
174
-	}
175
-
176
-	/**
177
-	 * @return mixed
178
-	 * @since 5.0.0
179
-	 */
180
-	public function getPermissions() {
181
-		$permissions = $this->addressBook->getACL();
182
-		$result = 0;
183
-		foreach ($permissions as $permission) {
184
-			switch ($permission['privilege']) {
185
-				case '{DAV:}read':
186
-					$result |= Constants::PERMISSION_READ;
187
-					break;
188
-				case '{DAV:}write':
189
-					$result |= Constants::PERMISSION_CREATE;
190
-					$result |= Constants::PERMISSION_UPDATE;
191
-					break;
192
-				case '{DAV:}all':
193
-					$result |= Constants::PERMISSION_ALL;
194
-					break;
195
-			}
196
-		}
197
-
198
-		return $result;
199
-	}
200
-
201
-	/**
202
-	 * @param object $id the unique identifier to a contact
203
-	 * @return bool successful or not
204
-	 * @since 5.0.0
205
-	 */
206
-	public function delete($id) {
207
-		$uri = $this->backend->getCardUri($id);
208
-		return $this->backend->deleteCard($this->addressBookInfo['id'], $uri);
209
-	}
210
-
211
-	/**
212
-	 * read vCard data into a vCard object
213
-	 *
214
-	 * @param string $cardData
215
-	 * @return VCard
216
-	 */
217
-	protected function readCard($cardData) {
218
-		return  Reader::read($cardData);
219
-	}
220
-
221
-	/**
222
-	 * create UID for contact
223
-	 *
224
-	 * @return string
225
-	 */
226
-	protected function createUid() {
227
-		do {
228
-			$uid = $this->getUid();
229
-			$contact = $this->backend->getContact($this->getKey(), $uid . '.vcf');
230
-		} while (!empty($contact));
231
-
232
-		return $uid;
233
-	}
234
-
235
-	/**
236
-	 * getUid is only there for testing, use createUid instead
237
-	 */
238
-	protected function getUid() {
239
-		return UUIDUtil::getUUID();
240
-	}
241
-
242
-	/**
243
-	 * create empty vcard
244
-	 *
245
-	 * @param string $uid
246
-	 * @return VCard
247
-	 */
248
-	protected function createEmptyVCard($uid) {
249
-		$vCard = new VCard();
250
-		$vCard->UID = $uid;
251
-		return $vCard;
252
-	}
253
-
254
-	/**
255
-	 * create array with all vCard properties
256
-	 *
257
-	 * @param string $uri
258
-	 * @param VCard $vCard
259
-	 * @param boolean $withTypes (optional) return the values as arrays of value/type pairs
260
-	 * @return array
261
-	 */
262
-	protected function vCard2Array($uri, VCard $vCard, $withTypes = false) {
263
-		$result = [
264
-			'URI' => $uri,
265
-		];
266
-
267
-		foreach ($vCard->children() as $property) {
268
-			if ($property->name === 'PHOTO' && $property->getValueType() === 'BINARY') {
269
-				$url = $this->urlGenerator->getAbsoluteURL(
270
-					$this->urlGenerator->linkTo('', 'remote.php') . '/dav/');
271
-				$url .= implode('/', [
272
-					'addressbooks',
273
-					substr($this->addressBookInfo['principaluri'], 11), //cut off 'principals/'
274
-					$this->addressBookInfo['uri'],
275
-					$uri
276
-				]) . '?photo';
277
-
278
-				$result['PHOTO'] = 'VALUE=uri:' . $url;
279
-			} elseif (in_array($property->name, ['URL', 'GEO', 'CLOUD', 'ADR', 'EMAIL', 'IMPP', 'TEL', 'X-SOCIALPROFILE', 'RELATED', 'LANG', 'X-ADDRESSBOOKSERVER-MEMBER'])) {
280
-				if (!isset($result[$property->name])) {
281
-					$result[$property->name] = [];
282
-				}
283
-
284
-				$type = $this->getTypeFromProperty($property);
285
-				if ($withTypes) {
286
-					$result[$property->name][] = [
287
-						'type' => $type,
288
-						'value' => $property->getValue()
289
-					];
290
-				} else {
291
-					$result[$property->name][] = $property->getValue();
292
-				}
293
-			} else {
294
-				$result[$property->name] = $property->getValue();
295
-			}
296
-		}
297
-
298
-		if ($this->isSystemAddressBook()) {
299
-			$result['isLocalSystemBook'] = true;
300
-		}
301
-		return $result;
302
-	}
303
-
304
-	/**
305
-	 * Get the type of the current property
306
-	 *
307
-	 * @param Property $property
308
-	 * @return null|string
309
-	 */
310
-	protected function getTypeFromProperty(Property $property) {
311
-		$parameters = $property->parameters();
312
-		// Type is the social network, when it's empty we don't need this.
313
-		if (isset($parameters['TYPE'])) {
314
-			/** @var \Sabre\VObject\Parameter $type */
315
-			$type = $parameters['TYPE'];
316
-			return $type->getValue();
317
-		}
318
-
319
-		return null;
320
-	}
321
-
322
-	/**
323
-	 * @inheritDoc
324
-	 */
325
-	public function isShared(): bool {
326
-		if (!isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) {
327
-			return false;
328
-		}
329
-
330
-		return $this->addressBookInfo['principaluri']
331
-			!== $this->addressBookInfo['{http://owncloud.org/ns}owner-principal'];
332
-	}
333
-
334
-	/**
335
-	 * @inheritDoc
336
-	 */
337
-	public function isSystemAddressBook(): bool {
338
-		return $this->addressBookInfo['principaluri'] === 'principals/system/system' && (
339
-			$this->addressBookInfo['uri'] === 'system' ||
340
-			$this->addressBookInfo['{DAV:}displayname'] === $this->urlGenerator->getBaseUrl()
341
-		);
342
-	}
43
+    /** @var CardDavBackend */
44
+    private $backend;
45
+
46
+    /** @var array */
47
+    private $addressBookInfo;
48
+
49
+    /** @var AddressBook */
50
+    private $addressBook;
51
+
52
+    /** @var IURLGenerator */
53
+    private $urlGenerator;
54
+
55
+    /**
56
+     * AddressBookImpl constructor.
57
+     *
58
+     * @param AddressBook $addressBook
59
+     * @param array $addressBookInfo
60
+     * @param CardDavBackend $backend
61
+     * @param IUrlGenerator $urlGenerator
62
+     */
63
+    public function __construct(
64
+            AddressBook $addressBook,
65
+            array $addressBookInfo,
66
+            CardDavBackend $backend,
67
+            IURLGenerator $urlGenerator) {
68
+        $this->addressBook = $addressBook;
69
+        $this->addressBookInfo = $addressBookInfo;
70
+        $this->backend = $backend;
71
+        $this->urlGenerator = $urlGenerator;
72
+    }
73
+
74
+    /**
75
+     * @return string defining the technical unique key
76
+     * @since 5.0.0
77
+     */
78
+    public function getKey() {
79
+        return $this->addressBookInfo['id'];
80
+    }
81
+
82
+    /**
83
+     * @return string defining the unique uri
84
+     * @since 16.0.0
85
+     */
86
+    public function getUri(): string {
87
+        return $this->addressBookInfo['uri'];
88
+    }
89
+
90
+    /**
91
+     * In comparison to getKey() this function returns a human readable (maybe translated) name
92
+     *
93
+     * @return mixed
94
+     * @since 5.0.0
95
+     */
96
+    public function getDisplayName() {
97
+        return $this->addressBookInfo['{DAV:}displayname'];
98
+    }
99
+
100
+    /**
101
+     * @param string $pattern which should match within the $searchProperties
102
+     * @param array $searchProperties defines the properties within the query pattern should match
103
+     * @param array $options Options to define the output format and search behavior
104
+     * 	- 'types' boolean (since 15.0.0) If set to true, fields that come with a TYPE property will be an array
105
+     *    example: ['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['type => 'HOME', 'value' => '[email protected]']]
106
+     * 	- 'escape_like_param' - If set to false wildcards _ and % are not escaped
107
+     * 	- 'limit' - Set a numeric limit for the search results
108
+     * 	- 'offset' - Set the offset for the limited search results
109
+     * @return array an array of contacts which are arrays of key-value-pairs
110
+     *  example result:
111
+     *  [
112
+     *		['id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => '[email protected]', 'GEO' => '37.386013;-122.082932'],
113
+     *		['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['[email protected]', '[email protected]']]
114
+     *	]
115
+     * @since 5.0.0
116
+     */
117
+    public function search($pattern, $searchProperties, $options) {
118
+        $results = $this->backend->search($this->getKey(), $pattern, $searchProperties, $options);
119
+
120
+        $withTypes = \array_key_exists('types', $options) && $options['types'] === true;
121
+
122
+        $vCards = [];
123
+        foreach ($results as $result) {
124
+            $vCards[] = $this->vCard2Array($result['uri'], $this->readCard($result['carddata']), $withTypes);
125
+        }
126
+
127
+        return $vCards;
128
+    }
129
+
130
+    /**
131
+     * @param array $properties this array if key-value-pairs defines a contact
132
+     * @return array an array representing the contact just created or updated
133
+     * @since 5.0.0
134
+     */
135
+    public function createOrUpdate($properties) {
136
+        $update = false;
137
+        if (!isset($properties['URI'])) { // create a new contact
138
+            $uid = $this->createUid();
139
+            $uri = $uid . '.vcf';
140
+            $vCard = $this->createEmptyVCard($uid);
141
+        } else { // update existing contact
142
+            $uri = $properties['URI'];
143
+            $vCardData = $this->backend->getCard($this->getKey(), $uri);
144
+            $vCard = $this->readCard($vCardData['carddata']);
145
+            $update = true;
146
+        }
147
+
148
+        foreach ($properties as $key => $value) {
149
+            if (is_array($value)) {
150
+                $vCard->remove($key);
151
+                foreach ($value as $entry) {
152
+                    if (($key === "ADR" || $key === "PHOTO") && is_string($entry["value"])) {
153
+                        $entry["value"] = stripslashes($entry["value"]);
154
+                        $entry["value"] = explode(';', $entry["value"]);
155
+                    }
156
+                    $property = $vCard->createProperty($key, $entry["value"]);
157
+                    if (isset($entry["type"])) {
158
+                        $property->add('TYPE', $entry["type"]);
159
+                    }
160
+                    $vCard->add($property);
161
+                }
162
+            } elseif ($key !== 'URI') {
163
+                $vCard->$key = $vCard->createProperty($key, $value);
164
+            }
165
+        }
166
+
167
+        if ($update) {
168
+            $this->backend->updateCard($this->getKey(), $uri, $vCard->serialize());
169
+        } else {
170
+            $this->backend->createCard($this->getKey(), $uri, $vCard->serialize());
171
+        }
172
+
173
+        return $this->vCard2Array($uri, $vCard);
174
+    }
175
+
176
+    /**
177
+     * @return mixed
178
+     * @since 5.0.0
179
+     */
180
+    public function getPermissions() {
181
+        $permissions = $this->addressBook->getACL();
182
+        $result = 0;
183
+        foreach ($permissions as $permission) {
184
+            switch ($permission['privilege']) {
185
+                case '{DAV:}read':
186
+                    $result |= Constants::PERMISSION_READ;
187
+                    break;
188
+                case '{DAV:}write':
189
+                    $result |= Constants::PERMISSION_CREATE;
190
+                    $result |= Constants::PERMISSION_UPDATE;
191
+                    break;
192
+                case '{DAV:}all':
193
+                    $result |= Constants::PERMISSION_ALL;
194
+                    break;
195
+            }
196
+        }
197
+
198
+        return $result;
199
+    }
200
+
201
+    /**
202
+     * @param object $id the unique identifier to a contact
203
+     * @return bool successful or not
204
+     * @since 5.0.0
205
+     */
206
+    public function delete($id) {
207
+        $uri = $this->backend->getCardUri($id);
208
+        return $this->backend->deleteCard($this->addressBookInfo['id'], $uri);
209
+    }
210
+
211
+    /**
212
+     * read vCard data into a vCard object
213
+     *
214
+     * @param string $cardData
215
+     * @return VCard
216
+     */
217
+    protected function readCard($cardData) {
218
+        return  Reader::read($cardData);
219
+    }
220
+
221
+    /**
222
+     * create UID for contact
223
+     *
224
+     * @return string
225
+     */
226
+    protected function createUid() {
227
+        do {
228
+            $uid = $this->getUid();
229
+            $contact = $this->backend->getContact($this->getKey(), $uid . '.vcf');
230
+        } while (!empty($contact));
231
+
232
+        return $uid;
233
+    }
234
+
235
+    /**
236
+     * getUid is only there for testing, use createUid instead
237
+     */
238
+    protected function getUid() {
239
+        return UUIDUtil::getUUID();
240
+    }
241
+
242
+    /**
243
+     * create empty vcard
244
+     *
245
+     * @param string $uid
246
+     * @return VCard
247
+     */
248
+    protected function createEmptyVCard($uid) {
249
+        $vCard = new VCard();
250
+        $vCard->UID = $uid;
251
+        return $vCard;
252
+    }
253
+
254
+    /**
255
+     * create array with all vCard properties
256
+     *
257
+     * @param string $uri
258
+     * @param VCard $vCard
259
+     * @param boolean $withTypes (optional) return the values as arrays of value/type pairs
260
+     * @return array
261
+     */
262
+    protected function vCard2Array($uri, VCard $vCard, $withTypes = false) {
263
+        $result = [
264
+            'URI' => $uri,
265
+        ];
266
+
267
+        foreach ($vCard->children() as $property) {
268
+            if ($property->name === 'PHOTO' && $property->getValueType() === 'BINARY') {
269
+                $url = $this->urlGenerator->getAbsoluteURL(
270
+                    $this->urlGenerator->linkTo('', 'remote.php') . '/dav/');
271
+                $url .= implode('/', [
272
+                    'addressbooks',
273
+                    substr($this->addressBookInfo['principaluri'], 11), //cut off 'principals/'
274
+                    $this->addressBookInfo['uri'],
275
+                    $uri
276
+                ]) . '?photo';
277
+
278
+                $result['PHOTO'] = 'VALUE=uri:' . $url;
279
+            } elseif (in_array($property->name, ['URL', 'GEO', 'CLOUD', 'ADR', 'EMAIL', 'IMPP', 'TEL', 'X-SOCIALPROFILE', 'RELATED', 'LANG', 'X-ADDRESSBOOKSERVER-MEMBER'])) {
280
+                if (!isset($result[$property->name])) {
281
+                    $result[$property->name] = [];
282
+                }
283
+
284
+                $type = $this->getTypeFromProperty($property);
285
+                if ($withTypes) {
286
+                    $result[$property->name][] = [
287
+                        'type' => $type,
288
+                        'value' => $property->getValue()
289
+                    ];
290
+                } else {
291
+                    $result[$property->name][] = $property->getValue();
292
+                }
293
+            } else {
294
+                $result[$property->name] = $property->getValue();
295
+            }
296
+        }
297
+
298
+        if ($this->isSystemAddressBook()) {
299
+            $result['isLocalSystemBook'] = true;
300
+        }
301
+        return $result;
302
+    }
303
+
304
+    /**
305
+     * Get the type of the current property
306
+     *
307
+     * @param Property $property
308
+     * @return null|string
309
+     */
310
+    protected function getTypeFromProperty(Property $property) {
311
+        $parameters = $property->parameters();
312
+        // Type is the social network, when it's empty we don't need this.
313
+        if (isset($parameters['TYPE'])) {
314
+            /** @var \Sabre\VObject\Parameter $type */
315
+            $type = $parameters['TYPE'];
316
+            return $type->getValue();
317
+        }
318
+
319
+        return null;
320
+    }
321
+
322
+    /**
323
+     * @inheritDoc
324
+     */
325
+    public function isShared(): bool {
326
+        if (!isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) {
327
+            return false;
328
+        }
329
+
330
+        return $this->addressBookInfo['principaluri']
331
+            !== $this->addressBookInfo['{http://owncloud.org/ns}owner-principal'];
332
+    }
333
+
334
+    /**
335
+     * @inheritDoc
336
+     */
337
+    public function isSystemAddressBook(): bool {
338
+        return $this->addressBookInfo['principaluri'] === 'principals/system/system' && (
339
+            $this->addressBookInfo['uri'] === 'system' ||
340
+            $this->addressBookInfo['{DAV:}displayname'] === $this->urlGenerator->getBaseUrl()
341
+        );
342
+    }
343 343
 }
Please login to merge, or discard this patch.