Skip to content

Commit

Permalink
feat: use Http facade for DavClient (#5573)
Browse files Browse the repository at this point in the history
  • Loading branch information
asbiin authored Oct 7, 2021
1 parent 93acd48 commit a669e98
Show file tree
Hide file tree
Showing 24 changed files with 551 additions and 652 deletions.
10 changes: 5 additions & 5 deletions app/Jobs/Dav/GetMultipleVCard.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use Sabre\CardDAV\Plugin as CardDAVPlugin;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Models\Account\AddressBookSubscription;
use App\Services\DavClient\Utils\Dav\DavClient;
use App\Services\DavClient\Utils\Model\ContactUpdateDto;

class GetMultipleVCard implements ShouldQueue
Expand Down Expand Up @@ -51,10 +50,11 @@ public function handle(): void
return;
}

$datas = app(DavClient::class)->addressbookMultiget($this->subscription->getRequest(), [
'{DAV:}getetag',
$this->getAddressDataProperty(),
], $this->hrefs);
$datas = $this->subscription->getClient()
->addressbookMultiget([
'{DAV:}getetag',
$this->getAddressDataProperty(),
], $this->hrefs);

collect($datas)
->filter(function (array $contact): bool {
Expand Down
6 changes: 2 additions & 4 deletions app/Jobs/Dav/GetVCard.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,8 @@ public function handle(): void

Log::info(__CLASS__.' '.$this->contact->uri);

$response = $this->subscription->getRequest()
->get($this->contact->uri);

$response->throw();
$response = $this->subscription->getClient()
->request('GET', $this->contact->uri);

$this->chainUpdateVCard($response->body());
}
Expand Down
7 changes: 2 additions & 5 deletions app/Jobs/Dav/PushVCard.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,8 @@ public function handle(): void
$headers['If-Match'] = '*';
}

$response = $this->subscription->getRequest()
->withHeaders($headers)
->put($this->contact->uri, [$this->contact->card]);

$response->throw();
$response = $this->subscription->getClient()
->request('PUT', $this->contact->uri, $this->contact->card, $headers);

if (! empty($etag = $response->header('Etag')) && $etag !== $this->contact->etag) {
Log::warning(__CLASS__.' wrong etag when updating contact. Expected '.$this->contact->etag.', get '.$etag);
Expand Down
15 changes: 7 additions & 8 deletions app/Models/Account/AddressBookSubscription.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
use App\Models\User\User;
use function safe\json_decode;
use function safe\json_encode;
use Illuminate\Support\Facades\Http;
use App\Models\ModelBinding as Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Client\PendingRequest;
use App\Services\DavClient\Utils\Dav\DavClient;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;

Expand Down Expand Up @@ -153,14 +152,14 @@ public function scopeActive($query)
}

/**
* Get a pending request.
* Get a new client.
*
* @return PendingRequest
* @return DavClient
*/
public function getRequest(): PendingRequest
public function getClient(): DavClient
{
return Http::withBasicAuth($this->username, $this->password)
->baseUrl($this->uri)
->withUserAgent('Monica DavClient '.config('monica.app_version'));
return app(DavClient::class)
->setBaseUri($this->uri)
->setCredentials($this->username, $this->password);
}
}
22 changes: 8 additions & 14 deletions app/Services/DavClient/CreateAddressBookSubscription.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use App\Services\BaseService;
use function Safe\preg_replace;
use App\Models\Account\AddressBook;
use GuzzleHttp\Client as GuzzleClient;
use App\Models\Account\AddressBookSubscription;
use App\Services\DavClient\Utils\Dav\DavClient;
use App\Services\DavClient\Utils\AddressBookGetter;
Expand Down Expand Up @@ -34,14 +33,13 @@ public function rules()
* Add a new Adress Book.
*
* @param array $data
* @param GuzzleClient|null $httpClient
* @return AddressBookSubscription|null
*/
public function execute(array $data, GuzzleClient $httpClient = null): ?AddressBookSubscription
public function execute(array $data): ?AddressBookSubscription
{
$this->validate($data);

$addressBookData = $this->getAddressBookData($data, $httpClient);
$addressBookData = $this->getAddressBookData($data);
if (! $addressBookData) {
throw new DavClientException(__('Could not get address book data.'));
}
Expand Down Expand Up @@ -76,22 +74,18 @@ public function execute(array $data, GuzzleClient $httpClient = null): ?AddressB
return $subscription;
}

private function getAddressBookData(array $data, ?GuzzleClient $httpClient): ?array
private function getAddressBookData(array $data): ?array
{
$client = $this->getClient($data, $httpClient);
$client = $this->getClient($data);

return app(AddressBookGetter::class)
->execute($client);
}

private function getClient(array $data, ?GuzzleClient $client): DavClient
private function getClient(array $data): DavClient
{
$settings = Arr::only($data, [
'base_uri',
'username',
'password',
]);

return app(DavClient::class)->init($settings, $client);
return app(DavClient::class)
->setBaseUri(Arr::get($data, 'base_uri'))
->setCredentials(Arr::get($data, 'username'), Arr::get($data, 'password'));
}
}
18 changes: 7 additions & 11 deletions app/Services/DavClient/SynchronizeAddressBook.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use App\Helpers\AccountHelper;
use App\Models\Account\Account;
use Illuminate\Support\Facades\Log;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Exception\ClientException;
use App\Models\Account\AddressBookSubscription;
use App\Services\DavClient\Utils\Dav\DavClient;
Expand Down Expand Up @@ -37,7 +36,7 @@ public function rules()
* @param array $data
* @return void
*/
public function execute(array $data, GuzzleClient $httpClient = null)
public function execute(array $data)
{
$this->validate($data);

Expand All @@ -57,7 +56,7 @@ public function execute(array $data, GuzzleClient $httpClient = null)
$backend = new CardDAVBackend($user);

try {
$this->sync($data, $subscription, $backend, $httpClient);
$this->sync($data, $subscription, $backend);
} catch (ClientException $e) {
Log::error(__CLASS__.' execute: '.$e->getMessage(), [$e]);
if ($e->hasResponse()) {
Expand All @@ -66,23 +65,20 @@ public function execute(array $data, GuzzleClient $httpClient = null)
}
}

private function sync(array $data, AddressBookSubscription $subscription, CardDAVBackend $backend, ?GuzzleClient $httpClient)
private function sync(array $data, AddressBookSubscription $subscription, CardDAVBackend $backend)
{
$client = $this->getDavClient($subscription, $httpClient);
$client = $this->getDavClient($subscription);
$sync = new SyncDto($subscription, $client, $backend);
$force = Arr::get($data, 'force', false);

app(AddressBookSynchronizer::class)
->execute($sync, $force);
}

private function getDavClient(AddressBookSubscription $subscription, ?GuzzleClient $client): DavClient
private function getDavClient(AddressBookSubscription $subscription): DavClient
{
return app(DavClient::class)
->init([
'base_uri' => $subscription->uri,
'username' => $subscription->username,
'password' => $subscription->password,
], $client);
->setBaseUri($subscription->uri)
->setCredentials($subscription->username, $subscription->password);
}
}
4 changes: 2 additions & 2 deletions app/Services/DavClient/Utils/AddressBookContactsPush.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private function preparePushAddedContacts(array $contacts): Collection
$card = $this->sync->backend->getCard($this->sync->addressBookName(), $uri);

return $card !== false
? new PushVCard($this->sync->subscription, new ContactPushDto($uri, $card['etag'], $card['carddata'], 0))
? new PushVCard($this->sync->subscription, new ContactPushDto($uri, $card['etag'], $card['carddata']))
: null;
});
}
Expand Down Expand Up @@ -79,7 +79,7 @@ private function preparePushChangedContacts(Collection $changes, array $contacts
$card = $this->sync->backend->getCard($this->sync->addressBookName(), $uri);

return $card !== false
? new PushVCard($this->sync->subscription, new ContactPushDto($uri, $card['etag'], $card['carddata'], 1))
? new PushVCard($this->sync->subscription, new ContactPushDto($uri, $card['etag'], $card['carddata'], ContactPushDto::MODE_MATCH_ETAG))
: null;
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private function preparePushMissedContacts(array $added, Collection $distContact
})->map(function (Contact $contact): PushVCard {
$card = $this->sync->backend->prepareCard($contact);

return new PushVCard($this->sync->subscription, new ContactPushDto($card['uri'], $card['etag'], $card['carddata'], 2));
return new PushVCard($this->sync->subscription, new ContactPushDto($card['uri'], $card['etag'], $card['carddata'], ContactPushDto::MODE_MATCH_ANY));
});
}
}
4 changes: 2 additions & 2 deletions app/Services/DavClient/Utils/AddressBookGetter.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ private function getAddressBookBaseUri(): string
throw new DavClientException('No address book found');
}

return $this->client->getBaseUri($addressBook);
return $this->client->path($addressBook);
}

/**
Expand Down Expand Up @@ -181,7 +181,7 @@ private function getAddressBookUrl(string $principal): ?string
{
$home = $this->getAddressBookHome($principal);

$books = $this->client->propfind($home, '{DAV:}resourcetype', 1);
$books = $this->client->propfind('{DAV:}resourcetype', 1, [], $home);

foreach ($books as $book => $properties) {
if ($book == $home) {
Expand Down
99 changes: 37 additions & 62 deletions app/Services/DavClient/Utils/AddressBookSynchronizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
use Illuminate\Bus\Batch;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use GuzzleHttp\Promise\Promise;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Bus;
use GuzzleHttp\Promise\PromiseInterface;
use App\Services\DavClient\Utils\Model\SyncDto;
use App\Services\DavClient\Utils\Model\ContactDto;
use App\Services\DavClient\Utils\Traits\HasCapability;
Expand Down Expand Up @@ -106,17 +104,13 @@ private function forcesync()
*/
private function getDistantChanges(): Collection
{
return $this->getDistantEtags()
->then(function ($collection) {
return collect($collection)
->filter(function ($contact, $href): bool {
return $this->filterDistantContacts($contact, $href);
})
->map(function ($contact, $href): ContactDto {
return new ContactDto($href, Arr::get($contact, '200.{DAV:}getetag'));
});
})
->wait();
return collect($this->getDistantEtags())
->filter(function ($contact, $href): bool {
return $this->filterDistantContacts($contact, $href);
})
->map(function ($contact, $href): ContactDto {
return new ContactDto($href, Arr::get($contact, '200.{DAV:}getetag'));
});
}

/**
Expand All @@ -142,16 +136,16 @@ private function filterDistantContacts($contact, $href): bool
/**
* Get refreshed etags.
*
* @return PromiseInterface
* @return array
*/
private function getDistantEtags(): PromiseInterface
private function getDistantEtags(): array
{
if ($this->hasCapability('syncCollection')) {
// With sync-collection
return $this->callSyncCollectionWhenNeeded();
} else {
// With PROPFIND
return $this->sync->client->propFindAsync('', [
return $this->sync->propFind([
'{DAV:}getcontenttype',
'{DAV:}getetag',
], 1);
Expand All @@ -161,46 +155,43 @@ private function getDistantEtags(): PromiseInterface
/**
* Make sync-collection request if sync-token has changed.
*
* @return PromiseInterface
* @return array
*/
private function callSyncCollectionWhenNeeded(): PromiseInterface
private function callSyncCollectionWhenNeeded(): array
{
// get the current distant syncToken
return $this->sync->client->getPropertyAsync('{DAV:}sync-token')
->then(function ($distantSyncToken) {
$syncToken = $this->sync->subscription->syncToken ?? '';
$distantSyncToken = $this->sync->getProperty('{DAV:}sync-token');

if ($syncToken === $distantSyncToken) {
// no change at all
return $this->emptyPromise();
}
if (($this->sync->subscription->syncToken ?? '') === $distantSyncToken) {
// no change at all
return [];
}

return $this->callSyncCollection();
});
return $this->callSyncCollection();
}

/**
* Make sync-collection request.
*
* @return PromiseInterface
* @return array
*/
private function callSyncCollection(): PromiseInterface
private function callSyncCollection(): array
{
$syncToken = $this->sync->subscription->syncToken ?? '';

// get sync
return $this->sync->client->syncCollectionAsync('', [
$collection = $this->sync->syncCollection([
'{DAV:}getcontenttype',
'{DAV:}getetag',
], $syncToken)->then(function ($collection) {
// save the new syncToken as current one
if ($newSyncToken = Arr::get($collection, 'synctoken')) {
$this->sync->subscription->syncToken = $newSyncToken;
$this->sync->subscription->save();
}
], $syncToken);

// save the new syncToken as current one
if ($newSyncToken = Arr::get($collection, 'synctoken')) {
$this->sync->subscription->syncToken = $newSyncToken;
$this->sync->subscription->save();
}

return $collection;
});
return $collection;
}

/**
Expand All @@ -214,30 +205,14 @@ private function getAllContactsEtag(): Collection
return collect();
}

return $this->sync->client->addressbookQueryAsync('', '{DAV:}getetag')
->then(function ($datas) {
return collect($datas)
->filter(function ($contact) {
return isset($contact[200]);
})
->map(function ($contact, $href): ContactDto {
return new ContactDto($href, Arr::get($contact, '200.{DAV:}getetag'));
});
})
->wait();
}
$datas = $this->sync->addressbookQuery('{DAV:}getetag');

/**
* Get an empty Promise.
*
* @return PromiseInterface
*/
private function emptyPromise(): PromiseInterface
{
$promise = new Promise(function () use (&$promise) {
$promise->resolve([]);
});

return $promise;
return collect($datas)
->filter(function ($contact) {
return isset($contact[200]);
})
->map(function ($contact, $href): ContactDto {
return new ContactDto($href, Arr::get($contact, '200.{DAV:}getetag'));
});
}
}
Loading

0 comments on commit a669e98

Please sign in to comment.