dolibarr/htdocs/user
VIAL-GOUTEYRON Quentin 2d44fdf49c
CLOSE #29244 Feature to merge contacts (#39512)
Add the ability to merge two contacts, the same way third parties and members
can already be merged. The merged contact is absorbed by the current one, all
its satellite data is moved, then it is deleted.

Contact::mergeContact() orchestrates everything in a single transaction, using
the new CommonObject::commonReplaceContact() helper and the replaceContact()
static methods of Contact, ActionComm and User. A replaceContact hook lets the
external modules move their own data. No schema change, no migration.

Three specific traps of this table are handled:
- llx_element_contact.fk_socpeople references llx_socpeople only when
  c_type_contact.source is 'external', and llx_user when it is 'internal', so
  both queries filter on it. Without that filter the internal assignments of
  the users would silently be moved to the merged contact.
- Contact::updateRoles(), called by update(), deletes then reinserts every
  societe_contacts row of the contact from $this->roles. It is neutralised by
  setting roles to null, and update() is called before the links are moved.
- Every table having a unique index on the contact id is deduplicated before
  its update, so the update cannot violate it. $ignoreerrors is never used:
  the FIXME of commonReplaceThirdparty() documents the links it loses.

The files are moved after the commit and not before, unlike mergeCompany() and
mergeMembers(): a failure after the move leaves them with the database rolled
back but the files already gone. A name collision renames the file instead of
losing it, and a failure is reported to the user instead of being ignored.

Access guards live in the class and not in the page, so the REST API, the
scheduled jobs and the modules benefit from them too. They cover both contacts,
fetch() by rowid applying neither an entity nor a permission filter: entity,
private contact of another user, external user, sales representative perimeter,
absorbing a shared contact into a private one, and a contact linked to a user
account (moving llx_user.fk_socpeople would let the email of that user be
rewritten from the contact card, so it requires the permission to create users).

Form::select_contact() gets a one line fix on the way: it accepts a $filter
parameter, documents it, forwards it to the ajax branch, but dropped it when
building the combo, so the merge popup could not exclude the current contact.

Known limitations, out of the scope of this pull request: merging contacts of
different entities is refused, Contact::update() neither writes url, no_email,
fk_parent nor import_key while its $nosyncuser parameter is declared but never
read, and with CONTACT_USE_SEARCH_TO_SELECT set the current contact is still
offered in the popup, contact/ajax/contact.php overwriting the filter it gets.
2026-08-19 02:26:34 +02:00
..
api_token
class CLOSE #29244 Feature to merge contacts (#39512) 2026-08-19 02:26:34 +02:00
group Qual: Fix 'SqlInjection' notices (#39223) 2026-07-20 02:51:42 +02:00
notify Fix edit of notification need write permission on users. 2026-07-20 15:49:39 +02:00
agenda.php
agenda_extsites.php
bank.php Fix AISLE-2026-0340-0087 IDOR in user bank account edit flow - reported 2026-08-14 18:10:58 +02:00
card.php Fix editing api key must follow same permissions than editing password. 2026-08-07 18:41:23 +02:00
clicktodial.php
credentials.php clean code (#38784) 2026-06-14 01:09:51 +02:00
document.php FIX: Translate French code comments to English in user, ticket, modulebuilder and compta modules 2026-06-28 09:42:08 +02:00
hierarchy.php Qual: Fix 'SqlInjection' notices (#39223) 2026-07-20 02:51:42 +02:00
home.php Qual: Fix 'SqlInjection' notices (#39223) 2026-07-20 02:51:42 +02:00
ldap.php FIX: Translate French code comments to English in user, ticket, modulebuilder and compta modules 2026-06-28 09:42:08 +02:00
list.php Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-06-27 00:18:09 +02:00
logout.php
messaging.php
note.php Automated merge from 22.0 to 23.0 by tool pullmerge.sh 2026-07-15 01:26:14 +02:00
param_ihm.php FIX: Translate French code comments to English in user, ticket, modulebuilder and compta modules 2026-06-28 09:42:08 +02:00
passwordforgotten.php Qual: Fix PHPStan notices (#38064) 2026-05-11 01:26:15 +02:00
perms.php
vcard.php
virtualcard.php