PHPackages                             clesson-de/silverstripe-contacts - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. clesson-de/silverstripe-contacts

ActiveSilverstripe-vendormodule[Utility &amp; Helpers](/categories/utility)

clesson-de/silverstripe-contacts
================================

All contacts and addresses at one place.

1.1.6(1mo ago)096BSD-3-ClausePHP

Since Apr 28Pushed 1mo agoCompare

[ Source](https://github.com/clesson-de/silverstripe-contacts)[ Packagist](https://packagist.org/packages/clesson-de/silverstripe-contacts)[ RSS](/packages/clesson-de-silverstripe-contacts/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (18)Versions (14)Used By (0)

Silverstripe Contacts Module
============================

[](#silverstripe-contacts-module)

A central, flexible contact management system for Silverstripe 6. Manage companies, persons, and employees in a unified type hierarchy — complete with addresses, tags, customer numbers, payment accounts, avatars, and vCard export.

Features
--------

[](#features)

- **Contact type hierarchy** — abstract base class `Contact` with concrete subclasses `Company`, `Person`, and `Employee`
- **Company** — stores company name and optional suffix
- **Person** — stores gender, title, first/last name, nickname, birthday, marital status, and more
- **Employee** — links a `Person` to a `Company`, representing a working relationship
- **One address per contact** — each contact type has a single `has_one Address` relation; the semantic address type (home, business, work) is implied by the contact type
- **Tag system** — assign contacts to one or more groups via `ContactTag`
- **Payment accounts** — link bank accounts, credit cards, and online accounts via `ContactPaymentAccountsExtension` (requires `clesson-de/silverstripe-payment-accounts`)
- **Customer numbers** — auto-generated from a configurable template with date parts and random segments; only assigned to contacts in the CUSTOMER tag group
- **Avatar upload** — image upload with initials fallback
- **vCard download** — export any contact as a `.vcf` file (requires `DOWNLOAD_CONTACTS` permission)
- **CMS member linking** — optionally link a contact to a Silverstripe `Member` account
- **Website owner** — designate one contact as the site owner, accessible globally in templates
- **Permissions** — fine-grained CMS permissions (`USE_CONTACTS`, `DOWNLOAD_CONTACTS`)
- **Extensible CMS layout** — sidebar + main tabs layout with extension hooks
- **Delete protection** — `Company` and `Person` records linked to an `Employee` cannot be deleted

---

Requirements
------------

[](#requirements)

DependencyVersionPHP`^8.1`silverstripe/framework`^6`clesson-de/silverstripe-geocoding`^1`clesson-de/silverstripe-payment-accounts`^1`jeroendesloovere/vcard`^1.7`giggsey/libphonenumber-for-php`^8.13`lekoala/silverstripe-cms-actions`^2`symbiote/silverstripe-gridfieldextensions`^5`clesson-de/silverstripe-gridfield-pro`^1`---

Installation
------------

[](#installation)

```
composer require clesson-de/silverstripe-contacts
```

```
composer vendor-expose
```

Then run `/dev/build?flush=all`.

---

Data Model
----------

[](#data-model)

### Contact hierarchy

[](#contact-hierarchy)

```
Contact (base class)
├── Company        — Name1, Name2, Address (business)
├── Person         — Gender, Title, FirstName, LastName, …, Address (home)
└── Employee       — has_one Person, has_one Company, Address (work)

```

`Contact` is not declared with PHP's `abstract` keyword because Silverstripe's ORM requires concrete instantiation for `has_one` stubs. An Injector mapping in `_config/config.yml` maps `Contact` → `Person` as a fallback.

The CMS uses `GridFieldAddNewMultiClass` to offer `Company`, `Person`, and `Employee` as creation options.

### Shared fields (on `Contact`)

[](#shared-fields-on-contact)

FieldTypeDescription`Name``Varchar(255)`Computed display name`SortingName``Varchar(255)`Computed sorting key`Slug``Varchar(100)`URL-safe unique slug`Initials``Varchar(10)`Computed initials`Note``Text`Free-text note`CustomerNumber``Varchar(50)`Auto-generated customer number`CustomerSince``Date`Date when customer number was assigned### Relations (on `Contact`)

[](#relations-on-contact)

RelationTypeTarget`Account``has_one``Member``Avatar``has_one``Image``Address``has_one``Address``Tags``many_many``ContactTag`### Extensions registered by this module

[](#extensions-registered-by-this-module)

ExtensionApplied toAdds`ContactPaymentAccountsExtension``Contact``has_many PaymentAccounts``PaymentAccountContactExtension``PaymentAccount``has_one Contact``ContactableMember``Member`Reverse link to `Contact``SiteConfigOwner``SiteConfig``has_one SiteOwner → Contact`---

Configuration
-------------

[](#configuration)

### Website owner

[](#website-owner)

The module adds a dropdown to your `SiteConfig` for selecting a contact as the website owner. The selected contact is available as a global template variable:

```

        &copy; All rights reserved by $Name

```

Or via PHP:

```
$owner = Contact::current_site_owner();
```

### Customer number template

[](#customer-number-template)

The customer number template is configured in **Settings → Contacts**. The default is `K-{Y}-{N:3}`.

Available placeholders:

PlaceholderDescriptionExample`{Y}`Year (4-digit)`2026``{y}`Year (2-digit)`26``{m}`Month`04``{d}`Day`23``{H}`Hour`14``{i}`Minute`07``{s}`Second`52``{N:3}`Random digits (length 3)`047``{A:2}`Random uppercase letters (length 2)`KX``{X:4}`Random uppercase letters + digits (length 4)`A3K9`Customer numbers are only auto-generated for contacts that belong to the `CUSTOMER` tag group and do not yet have a customer number.

### Contact tags

[](#contact-tags)

Define tags that are created automatically on `/dev/build`:

```
Clesson\Silverstripe\Contacts\Models\ContactTag:
  default_tags:
    client: 'Clients'
    customer: 'Customers'
```

### Address types

[](#address-types)

Address types are managed by the `clesson-de/silverstripe-geocoding` module. Configure default types in your project's `_config/config.yml`:

```
Clesson\Silverstripe\Geocoding\Models\AddressType:
  default_tags:
    invoice-address: 'Invoice address'
    delivery-address: 'Delivery address'
```

---

Developer Documentation
-----------------------

[](#developer-documentation)

### Query helpers

[](#query-helpers)

```
use Clesson\Silverstripe\Contacts\Models\Contact;

// Get a single contact by its URL slug
$contact = Contact::get_by_slug('roy-orbison');

// Get all contacts with a specific tag (by unique key)
$clients = Contact::get_by_tag('client');

// Get the site owner
$owner = Contact::current_site_owner();
```

### Working with contact types

[](#working-with-contact-types)

```
use Clesson\Silverstripe\Contacts\Models\Company;
use Clesson\Silverstripe\Contacts\Models\Person;
use Clesson\Silverstripe\Contacts\Models\Employee;

// Create a company
$company = Company::create();
$company->Name1 = 'Acme Inc.';
$company->write();

// Create a person
$person = Person::create();
$person->FirstName = 'Jane';
$person->LastName  = 'Doe';
$person->write();

// Create an employee linking person and company
$employee = Employee::create();
$employee->PersonID  = $person->ID;
$employee->CompanyID = $company->ID;
$employee->write();

// Each contact type returns a formatted full name
echo $company->getFullName();  // "Acme Inc."
echo $person->getFullName();   // "Jane Doe"
echo $employee->getFullName(); // "Jane Doe (Acme Inc.)"
```

### vCard download

[](#vcard-download)

The module exposes a public route for vCard downloads:

```
/contact/vcard/{slug}

```

Requires the `DOWNLOAD_CONTACTS` permission. The `Contact` model provides a `getvCardLink()` method and a CMS action button.

### CMS structure

[](#cms-structure)

The **Contacts** CMS section is a `SingleRecordAdmin` backed by the `ContactConfig` singleton. It renders three top-level tabs:

TabContent**Contacts**Full list of all `Contact` records (Company, Person, Employee)**Addresses**Full list of all `Address` records**Administration**Inner tabs for `ContactTag` and `AddressType` records### CMS extension hooks

[](#cms-extension-hooks)

The contact detail form can be extended via Silverstripe extension hooks:

HookDescription`updateMainTabSet(TabSet $tabSet)`Add or modify main tabs`updateMarginalCMSFields(FieldList $fields)`Add fields to the sidebar`updateFixedMarginalCMSFields(FieldList $fields)`Add fields to the fixed sidebar area`updateSlug(string &$slug)`Modify the auto-generated slug before it is saved### Permissions

[](#permissions)

PermissionDescription`USE_CONTACTS`View, create, edit, and delete contacts`DOWNLOAD_CONTACTS`Download contacts as vCard files---

Frontend Assets
---------------

[](#frontend-assets)

The module ships with compiled admin CSS and JavaScript in `client/admin/dist/`.
If you want to modify the styles, you need to recompile them.

The source files are in `client/admin/src/`.

#### Prerequisites

[](#prerequisites)

The required Node.js version is specified in `.nvmrc` (currently Node 22).
If you use [nvm](https://github.com/nvm-sh/nvm), switch to the correct version with:

```
nvm use
```

#### Install dependencies

[](#install-dependencies)

```
npm install
```

#### Build

[](#build)

```
npm run build
```

ScriptInputOutput`build:js``client/admin/src/index.js``client/admin/dist/bundle.js``build:css``client/admin/src/scss/ss-contacts.scss``client/admin/dist/bundle.css`#### Watch mode (during development)

[](#watch-mode-during-development)

```
npm run watch
```

> **Note:** The output filenames `bundle.js` and `bundle.css` are **static** and must not be renamed — they are referenced by name in PHP.

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance90

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~3 days

Total

12

Last Release

50d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/52702628?v=4)[Clesson](/maintainers/clesson-de)[@clesson-de](https://github.com/clesson-de)

---

Top Contributors

[![clesson-de](https://avatars.githubusercontent.com/u/52702628?v=4)](https://github.com/clesson-de "clesson-de (8 commits)")

---

Tags

addresssilverstripeextensioncontactmember

### Embed Badge

![Health badge](/badges/clesson-de-silverstripe-contacts/health.svg)

```
[![Health](https://phpackages.com/badges/clesson-de-silverstripe-contacts/health.svg)](https://phpackages.com/packages/clesson-de-silverstripe-contacts)
```

###  Alternatives

[silverstripe/userforms

UserForms enables CMS users to create dynamic forms via a drag and drop interface and without getting involved in any PHP code

1321.1M86](/packages/silverstripe-userforms)[skeeks/cms

SkeekS CMS — control panel and tools based on php framework Yii2

13725.8k63](/packages/skeeks-cms)[lekoala/silverstripe-softdelete

Soft delete extension for SilverStripe

11236.3k](/packages/lekoala-silverstripe-softdelete)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
