Skip to content

Commit

Permalink
Enhance CardDAV query report to return a selective list of vcard prop…
Browse files Browse the repository at this point in the history
…erties - fixes sabre-io#889
  • Loading branch information
DeepDiver1975 committed Nov 16, 2016
1 parent df1c8f6 commit c1bb682
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 7 deletions.
17 changes: 15 additions & 2 deletions lib/CardDAV/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,8 @@ protected function addressbookQueryReport($report) {

$props[200]['{' . self::NS_CARDDAV . '}address-data'] = $this->convertVCard(
$props[200]['{' . self::NS_CARDDAV . '}address-data'],
$vcardType
$vcardType,
$report->addressDataProperties
);

}
Expand Down Expand Up @@ -846,14 +847,26 @@ protected function negotiateVCard($input, &$mimeType = null) {
*
* @param string|resource $data
* @param string $target
* @param array $propertiesFilter
* @return string
*/
protected function convertVCard($data, $target) {
protected function convertVCard($data, $target, array $propertiesFilter = null) {

if (is_resource($data)) {
$data = stream_get_contents($data);
}
$input = VObject\Reader::read($data);
if (!empty($propertiesFilter)) {
$propertiesFilter = array_merge(['UID', 'VERSION', 'FN'], $propertiesFilter);
$keys = array_unique(array_map(function($child) {
return $child->name;
}, $input->children()));
$keys = array_diff($keys, $propertiesFilter);
foreach ($keys as $key) {
unset($input->$key);
}
$data = $input->serialize();
}
$output = null;
try {

Expand Down
5 changes: 5 additions & 0 deletions lib/CardDAV/Xml/Filter/AddressData.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ static function xmlDeserialize(Reader $reader) {
'version' => $reader->getAttribute('version') ?: '3.0',
];

$elems = (array)$reader->parseInnerTree();
$result['addressDataProperties'] = array_map(function($element) {
return $element['attributes']['name'];
}, $elems);

$reader->next();
return $result;

Expand Down
7 changes: 7 additions & 0 deletions lib/CardDAV/Xml/Request/AddressBookQueryReport.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ class AddressBookQueryReport implements XmlDeserializable {
*/
public $properties;

/**
* An array with requested vcard properties.
*
* @var array
*/
public $addressDataProperties = [];

/**
* List of property/component filters.
*
Expand Down
4 changes: 2 additions & 2 deletions tests/Sabre/CardDAV/AddressBookHomeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ function testGetChild404() {
function testGetChildren() {

$children = $this->s->getChildren();
$this->assertEquals(1, count($children));
$this->assertEquals(2, count($children));
$this->assertInstanceOf('Sabre\\CardDAV\\AddressBook', $children[0]);
$this->assertEquals('book1', $children[0]->getName());

Expand All @@ -109,7 +109,7 @@ function testCreateExtendedCollection() {
'uri' => 'book2',
'{DAV:}displayname' => 'a-book 2',
'principaluri' => 'principals/user1',
], $this->backend->addressBooks[1]);
], $this->backend->addressBooks[2]);

}

Expand Down
49 changes: 47 additions & 2 deletions tests/Sabre/CardDAV/AddressBookQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -288,14 +288,14 @@ function testAddressBookDepth0() {
);

$request->setBody(
'<?xml version="1.0"?>
'<?xml version="1.0"?>
<c:addressbook-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:carddav">
<d:prop>
<c:address-data content-type="application/vcard+json" />
<d:getetag />
</d:prop>
</c:addressbook-query>'
);
);

$response = new HTTP\ResponseMock();

Expand All @@ -305,6 +305,51 @@ function testAddressBookDepth0() {
$this->server->exec();

$this->assertEquals(415, $response->status, 'Incorrect status code. Full response body:' . $response->body);
}

function testAddressBookProperties() {

$request = new HTTP\Request(
'REPORT',
'/addressbooks/user1/book3',
['Depth' => '1']
);

$request->setBody(
'<?xml version="1.0"?>
<c:addressbook-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:carddav">
<d:prop>
<c:address-data>
<c:prop name="FN"/>
<c:prop name="BDAY"/>
</c:address-data>
<d:getetag />
</d:prop>
</c:addressbook-query>'
);

$response = new HTTP\ResponseMock();

$this->server->httpRequest = $request;
$this->server->httpResponse = $response;

$this->server->exec();

$this->assertEquals(207, $response->status, 'Incorrect status code. Full response body:' . $response->body);

// using the client for parsing
$client = new DAV\Client(['baseUri' => '/']);

$result = $client->parseMultiStatus($response->body);

$this->assertEquals([
'/addressbooks/user1/book3/card3' => [
200 => [
'{DAV:}getetag' => '"' . md5("BEGIN:VCARD\nVERSION:3.0\nUID:12345\nFN:Test-Card\nEMAIL;TYPE=home:bar@example.org\nEND:VCARD") . '"',
'{urn:ietf:params:xml:ns:carddav}address-data' => "BEGIN:VCARD\r\nVERSION:3.0\r\nUID:12345\r\nFN:Test-Card\r\nEND:VCARD\r\n",
],
],
], $result);

}
}
2 changes: 1 addition & 1 deletion tests/Sabre/CardDAV/AddressBookTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ function testCreateFile() {
function testDelete() {

$this->ab->delete();
$this->assertEquals([], $this->backend->addressBooks);
$this->assertEquals(1, count($this->backend->addressBooks));

}

Expand Down
9 changes: 9 additions & 0 deletions tests/Sabre/CardDAV/Backend/Mock.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ function __construct($addressBooks = null, $cards = null) {
'principaluri' => 'principals/user1',
'{DAV:}displayname' => 'd-name',
],
[
'id' => 'bar',
'uri' => 'book3',
'principaluri' => 'principals/user1',
'{DAV:}displayname' => 'd-name',
],
];

$card2 = fopen('php://memory', 'r+');
Expand All @@ -30,6 +36,9 @@ function __construct($addressBooks = null, $cards = null) {
'card1' => "BEGIN:VCARD\nVERSION:3.0\nUID:12345\nEND:VCARD",
'card2' => $card2,
],
'bar' => [
'card3' => "BEGIN:VCARD\nVERSION:3.0\nUID:12345\nFN:Test-Card\nEMAIL;TYPE=home:bar@example.org\nEND:VCARD",
],
];
}

Expand Down
47 changes: 47 additions & 0 deletions tests/Sabre/CardDAV/Xml/Request/AddressBookQueryReportTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -300,4 +300,51 @@ function testDeserializeDoubleFilter() {
$this->parse($xml);

}

function testDeserializeAddressbookElements() {

$xml = <<<XML
<?xml version="1.0"?>
<c:addressbook-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:carddav">
<d:prop>
<d:getetag />
<c:address-data>
<c:prop name="VERSION"/>
<c:prop name="UID"/>
<c:prop name="NICKNAME"/>
<c:prop name="EMAIL"/>
<c:prop name="FN"/>
<c:prop name="TEL"/>
</c:address-data>
</d:prop>
</c:addressbook-query>
XML;

$result = $this->parse($xml);
$addressBookQueryReport = new AddressBookQueryReport();
$addressBookQueryReport->properties = [
'{DAV:}getetag',
'{urn:ietf:params:xml:ns:carddav}address-data'
];
$addressBookQueryReport->filters = [];
$addressBookQueryReport->test = 'anyof';
$addressBookQueryReport->contentType = 'text/vcard';
$addressBookQueryReport->version = '3.0';
$addressBookQueryReport->addressDataProperties = [
'VERSION',
'UID',
'NICKNAME',
'EMAIL',
'FN',
'TEL',
];

$this->assertEquals(
$addressBookQueryReport,
$result['value']
);

}


}

0 comments on commit c1bb682

Please sign in to comment.