@@ -155,6 +155,7 @@ public function getContactList(string $userId): Generator {
155155 * @return array
156156 */
157157 public function importContacts (string $ userId , ?string $ uri , int $ key , ?string $ newAddrBookName ): array {
158+ $ existingAddressBook = null ;
158159 if ($ key === 0 ) {
159160 $ addressBooks = $ this ->contactsManager ->getUserAddressBooks ();
160161 foreach ($ addressBooks as $ k => $ ab ) {
@@ -180,19 +181,48 @@ public function importContacts(string $userId, ?string $uri, int $key, ?string $
180181 if (!$ addressBook ) {
181182 return ['error ' => 'no such address book ' ];
182183 }
184+ $ existingAddressBook = $ addressBook ;
183185 }
184186
185187 $ groupsById = $ this ->getContactGroupsById ($ userId );
186188 $ contacts = $ this ->getContactList ($ userId );
187189 $ nbAdded = 0 ;
190+ $ nbUpdated = 0 ;
188191 $ totalContactNumber = 0 ;
189192 foreach ($ contacts as $ k => $ c ) {
190193 $ totalContactNumber ++;
191- // avoid existing contacts
192- if ($ this ->contactExists ($ c , $ key )) {
193- $ this ->logger ->debug ('Skipping contact which already exists ' , ['contact ' => $ c , 'app ' => Application::APP_ID ]);
194+
195+ $ googleResourceName = $ c ['resourceName ' ] ?? null ;
196+ if ($ googleResourceName === null ) {
197+ $ this ->logger ->debug ('Skipping contact with no resourceName ' , ['contact ' => $ c , 'app ' => Application::APP_ID ]);
194198 continue ;
195199 }
200+ // contacts are not displayed in the Contacts app if there are slashes in their URI...
201+ $ googleResourceName = str_replace ('/ ' , '_ ' , $ googleResourceName );
202+
203+ // check if contact exists and needs to be updated
204+ $ existingContact = null ;
205+ if ($ existingAddressBook !== null ) {
206+ $ existingContact = $ this ->cdBackend ->getCard ($ key , $ googleResourceName );
207+ if ($ existingContact ) {
208+ $ googleUpdateTime = $ c ['metadata ' ]['sources ' ][0 ]['updateTime ' ] ?? null ;
209+ if ($ googleUpdateTime === null ) {
210+ $ googleUpdateTimestamp = 0 ;
211+ } else {
212+ try {
213+ $ googleUpdateTimestamp = (new Datetime ($ googleUpdateTime ))->getTimestamp ();
214+ } catch (Exception | Throwable $ e ) {
215+ $ googleUpdateTimestamp = 0 ;
216+ }
217+ }
218+
219+ if ($ googleUpdateTimestamp <= $ existingContact ['lastmodified ' ]) {
220+ $ this ->logger ->debug ('Skipping existing contact which is up-to-date ' , ['contact ' => $ c , 'app ' => Application::APP_ID ]);
221+ continue ;
222+ }
223+ }
224+ }
225+
196226 $ vCard = new VCard ();
197227
198228 $ displayName = '' ;
@@ -406,11 +436,20 @@ public function importContacts(string $userId, ?string $uri, int $key, ?string $
406436 }
407437 }
408438
409- try {
410- $ this ->cdBackend ->createCard ($ key , 'goog ' . $ k , $ vCard ->serialize ());
411- $ nbAdded ++;
412- } catch (Throwable | Exception $ e ) {
413- $ this ->logger ->warning ('Error when creating contact ' , ['exception ' => $ e , 'app ' => Application::APP_ID ]);
439+ if ($ existingContact === null || $ existingContact === false ) {
440+ try {
441+ $ this ->cdBackend ->createCard ($ key , $ googleResourceName , $ vCard ->serialize ());
442+ $ nbAdded ++;
443+ } catch (Throwable |Exception $ e ) {
444+ $ this ->logger ->warning ('Error when creating contact ' , ['exception ' => $ e , 'contact ' => $ c , 'app ' => Application::APP_ID ]);
445+ }
446+ } else {
447+ try {
448+ $ this ->cdBackend ->updateCard ($ key , $ googleResourceName , $ vCard ->serialize ());
449+ $ nbUpdated ++;
450+ } catch (Throwable |Exception $ e ) {
451+ $ this ->logger ->warning ('Error when updating contact ' , ['exception ' => $ e , 'contact ' => $ c , 'app ' => Application::APP_ID ]);
452+ }
414453 }
415454 }
416455 $ this ->logger ->debug ($ totalContactNumber . ' contacts seen ' , ['app ' => Application::APP_ID ]);
@@ -419,34 +458,10 @@ public function importContacts(string $userId, ?string $uri, int $key, ?string $
419458 if (isset ($ contactGeneratorReturn ['error ' ])) {
420459 return $ contactGeneratorReturn ;
421460 }
422- return ['nbAdded ' => $ nbAdded ];
423- }
424-
425- /**
426- * @param array $contact
427- * @param int $addressBookKey
428- * @return bool
429- */
430- private function contactExists (array $ contact , int $ addressBookKey ): bool {
431- $ displayName = null ;
432- // $familyName = null;
433- // $firstName = null;
434- if (isset ($ contact ['names ' ]) && is_array ($ contact ['names ' ])) {
435- foreach ($ contact ['names ' ] as $ n ) {
436- $ displayName = $ n ['displayName ' ] ?? '' ;
437- // $familyName = $n['familyName'] ?? '';
438- // $firstName = $n['givenName'] ?? '';
439- break ;
440- }
441- if ($ displayName ) {
442- $ searchResult = $ this ->contactsManager ->search ($ displayName , ['FN ' ]);
443- foreach ($ searchResult as $ resContact ) {
444- if ($ resContact ['FN ' ] === $ displayName && (int )$ resContact ['addressbook-key ' ] === $ addressBookKey ) {
445- return true ;
446- }
447- }
448- }
449- }
450- return false ;
461+ return [
462+ 'nbSeen ' => $ totalContactNumber ,
463+ 'nbAdded ' => $ nbAdded ,
464+ 'nbUpdated ' => $ nbUpdated ,
465+ ];
451466 }
452467}
0 commit comments