Skip to content

cdav: allow excluding contact categories from CardDAV sync via a global setting #77

Description

@infogm

Context

We needed a way to exclude some Dolibarr contacts from CardDAV synchronization in the cdav module, based on their contact categories.

Typical use case: exclude all contacts tagged with category label anglais from the CardDAV addressbook.

The native module already supports CDAV_CONTACT_TAG to restrict synchronization to one category ID, but there is no native way to exclude contacts by category label.

Current behavior

In CardDAVDolibarr.php, method _getSqlContacts($sqlWhere='') already builds:

  • category_label with GROUP_CONCAT(DISTINCT cat.label ...)
  • category_ids with GROUP_CONCAT(DISTINCT cc.fk_categorie ...)

The native logic can include contacts with:

if (!empty($conf->global->CDAV_CONTACT_TAG) && (int) $conf->global->CDAV_CONTACT_TAG > 0) {
    $having[] = "CONCAT(',', COALESCE(category_ids,''), ',') LIKE '%,".$this->db->escape($conf->global->CDAV_CONTACT_TAG).",%'";
}

But there is no equivalent exclusion filter.

Proposal

Add a new module setting:

  • CDAV_EXCLUDE_CONTACT_CATEGORIES

This setting contains a comma-separated list of category labels to exclude from CardDAV sync, for example:

anglais

or

anglais,interne,test

Important implementation detail

For the new custom setting, using:

getDolGlobalString('CDAV_EXCLUDE_CONTACT_CATEGORIES')

worked correctly, while direct access with:

$conf->global->CDAV_EXCLUDE_CONTACT_CATEGORIES

did not work reliably in this patch context.

So the following block worked:

$excludeLabels = trim(getDolGlobalString('CDAV_EXCLUDE_CONTACT_CATEGORIES'));

if ($excludeLabels !== '') {
    $labels = array_map('trim', explode(',', $excludeLabels));
    $parts = array();

    foreach ($labels as $label) {
        if ($label === '') continue;
        $esc = $this->db->escape($label);
        $parts[] = "COALESCE(category_label,'') NOT LIKE '%".$esc."%'";
    }

    if (!empty($parts)) {
        $having[] = '('.implode(' AND ', $parts).')';
    }
}

and then:

if (!empty($having)) {
    $sql .= ' HAVING '.implode(' AND ', $having);
}

Suggested patch location

File:

  • custom/cdav/class/CardDAVDolibarr.php

Method:

  • _getSqlContacts($sqlWhere='')

The idea is to keep the native CDAV_CONTACT_TAG logic unchanged, and only add an extra exclusion filter based on labels.

Admin setup

A matching setup field can be added in admin/setup.php with:

dolibarr_set_const($db, "CDAV_EXCLUDE_CONTACT_CATEGORIES", GETPOST('CDAV_EXCLUDE_CONTACT_CATEGORIES', 'alphanohtml'), 'chaine', 0, '', $conf->entity);

and displayed as a text input such as:

Comma separated category names to exclude from contact synchronization

Result

After applying this change:

  • CardDAV sync still works
  • contacts with category label anglais are no longer synchronized
  • native CDAV_CONTACT_TAG behavior remains unchanged

Reproduction example

  1. Create a contact category named anglais
  2. Assign this category to some contacts
  3. Set CDAV_EXCLUDE_CONTACT_CATEGORIES = anglais
  4. Sync CardDAV addressbook
  5. Contacts with anglais should not be exposed anymore

Environment

  • Dolibarr: 22.0.3
  • cdav module on custom install (3.1.4)
  • Use case tested on production after backup of modified files

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions