PHPackages                             locomotivemtl/charcoal-attachment - 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. [File &amp; Storage](/categories/file-storage)
4. /
5. locomotivemtl/charcoal-attachment

ActiveLibrary[File &amp; Storage](/categories/file-storage)

locomotivemtl/charcoal-attachment
=================================

Charcoal Attachments Module

0.11.0(3y ago)17.5k3MITPHPPHP  &gt;=7.1CI failing

Since Aug 30Pushed 2y ago14 watchersCompare

[ Source](https://github.com/locomotivemtl/charcoal-attachment)[ Packagist](https://packagist.org/packages/locomotivemtl/charcoal-attachment)[ Docs](https://charcoal.locomotive.ca)[ RSS](/packages/locomotivemtl-charcoal-attachment/feed)WikiDiscussions master Synced today

READMEChangelog (10)Dependencies (9)Versions (65)Used By (3)

Charcoal Attachment
===================

[](#charcoal-attachment)

Attachments add support for working with relationships between models. Also provided are a usable set of basic attachments: Document, Embed, Image, Gallery, Link Video, amongst others.

How to install
--------------

[](#how-to-install)

The preferred (and only supported) way of installing \_charcoal-attachment is with **composer**:

```
★ composer require locomotivemtl/charcoal-attachment
```

Dependencies
------------

[](#dependencies)

- [PHP 7.1+](http://php.net)
- [`locomotivemtl/charcoal-core`](https://github.com/locomotivemtl/charcoal-core)
- [`locomotivemtl/charcoal-base`](https://github.com/locomotivemtl/charcoal-base)
- [`locomotivemtl/charcoal-admin`](https://github.com/locomotivemtl/charcoal-admin)
- [`locomotivemtl/charcoal-ui`](https://github.com/locomotivemtl/charcoal-ui)
- [`locomotivemtl/charcoal-translation`](https://github.com/locomotivemtl/charcoal-translation)

Objects
-------

[](#objects)

Objects in the `charcoal-attachments` module extends `Content`, from `charcoal-object`, which is an `AbstractModel`, from `charcoal-core`.

In addition from the default metadata provided by `Content`, the following properties are default for all `Attachment` objects:

**Standard properties** (used by all attachments objects):

PropertyTypeDescription**id**`id`A uniqid, for referencing.**title**`string` (l10n)**show\_title**`boolean`**categorie**`object (multiple)By default, categories are `charcoal/attachment/object/category/generic` objects.**subtitle**`string` (l10n)**description**`text` (l10n)**keywords**`string` (l10n, multiple)Typically used for searching purpose.**type**`string`**Specialized properties** which can be used differently, depending on context:

PropertyTypeDescription**link**`string` (l10n)URL.**file**`file` (l10n)Uploadable file, or "document".**file\_size**`string`The uploaded file size, in bytes (auto-generated).**file\_type**`string`The uploaded file mimetype (auto-generated).**thumbnail**`image` (l10n)**embed**`text` (l10n)Typically a video.All attachments are assumed to have a `title`, `subtitle`, `description` and `keywords`. Some attachments also

> Read the [`charcoal-object`](https://github.com/locomotivemtl/charcoal-object) documentation for the other default properties provided by the `Content` object (and `RevisionableInterface`).

> Read the [`charcoal-core`](https://github.com/locomotivemtl/charcoal-core) documention for the other default properties provided by `AbstractModel` (and `DescribableInterface` and `StorableInterface`).

### Type of Attachment objects

[](#type-of-attachment-objects)

- **Accordion**
    - A `Container` (grouping) attachment, used for accordion type of display.
    - By default, support `text`, `image`, `gallery` and `embed` attachments.
- **Attachment**
    - The most generic attachment, can be anything.
- **Container**
    - Base "grouping" attachment.
- **Embed**
    - Embedded content, typically video embed code.
    - Force the `file` property to be an `image`, and `description` to be `html`.
- **File**
    - An uploadable *Document*.
- **Link**
    - A URL (link to a resource).
- **Image**
    - An uploadable image
    - Force the `file` property to be an `image`.
- **Gallery**
    - A `Container` (grouping) attachment, used for a gallery of multiple images.
    - Is limited to `image` attachments.
- **Text**
    - Text (HTML) content.
- **Video**

Widgets
-------

[](#widgets)

The module provides his own admin widgets namespaced as Charcoal\\Admin.

BUT HOW
-------

[](#but-how)

The setup is fairly easy, but you need to remember a few things in order for it to work.

### Configurations

[](#configurations)

Add the views path and metadata path to the config file.

```
"metadata": {
    "paths": [
        "...",
        "vendor/locomotivemtl/charcoal-attachment/metadata/"
    ]
},
"view": {
    "paths": [
        "...",
        "vendor/locomotivemtl/charcoal-attachment/templates/"
    ]
},
"translations": {
    "paths": [
        "...",
        "vendor/locomotivemtl/charcoal-attachment/translations/"
    ]
}
```

Then, we need to add the necessary routes for the widgets in admin.json config file.

```
"routes": {
    "actions": {
        "join": {
            "ident": "charcoal/admin/action/join",
            "methods": [ "POST" ]
        },
        "add-join": {
            "ident": "charcoal/admin/action/add-join",
            "methods": [ "POST" ]
        },
        "remove-join": {
            "ident": "charcoal/admin/action/remove-join",
            "methods": [ "POST" ]
        }
    }
}
```

### Usage

[](#usage)

You need to make your object(s) "Attachment Aware", so that it knows it can have attachments. To do that, use/implement attachmentAware:

```
use Charcoal\Attachment\Traits\AttachmentAwareTrait;
use Charcoal\Attachment\Interfaces\AttachmentAwareInterface;
```

Then, just add in the widget in the edit dashboard or the form like this:

```
"attachment": {
    "title": "Documents",
    "type": "charcoal/admin/widget/attachment",
    "group": "main",
    "attachable_objects": {
        "charcoal/attachment/object/file": {
            "label": "Document / File"
        }
    }
}
```

Available attachable objects as provided by the current modile are:

- `charcoal/attachment/object/image`
- `charcoal/attachment/object/gallery`
- `charcoal/attachment/object/file`
- `charcoal/attachment/object/link`
- `charcoal/attachment/object/text`
- `charcoal/attachment/object/video`

To create a new attachment, you need to extend the base Attachment object `charcoal/attachment/object/attachment` and provide a "quick" form.

To remove unnecessary join when deleting an object, you need to add this to your object:

```
public function preDelete()
{
    // AttachmentAwareTrait
    $this->removeJoins();
    return parent::preDelete();
}
```

Documentation
-------------

[](#documentation)

Attachment widget can be use more than once in a form. In order for it to work properly, you need to define a group ident `group` different for each instanciated widgets.

```
"attachment": {
    "type": "charcoal/admin/widget/attachment",
    "group": "main"
}
```

In this case, we set the group to "main". If none defined, the default group will be "generic". Without those ident, widgets won't be able to know which attachments are his.

You can than access a perticular "group" attachments calling the object's method "attachments(group\_ident)". In this case, `$object->attachments('main')` will return attachments associated with the widgets that has the group set to "main".

Attachment creation
-------------------

[](#attachment-creation)

The one thing you need to know about the attachment is that it is all in a single table. You can't associate custom objects with other objects if they are not `attachments`.

Then, how could you create new attachments? It all depends on what you want.

### Adding or modifying properties

[](#adding-or-modifying-properties)

IF you need to add properties to an existing attachment, you can always extend it. Let's say you want to change the editor options for the description field given with the attachments. The first step is to create a new object that will extend the existing one.

```
/**
 * Extended text class.
 */
namespace My\Namespace;

use Charcoal\Attachment\Object\Text as AttachmentText;

class Text extends AttachmentText
{
}
```

Now that we have the extend, let's add to the JSON by creating a `my/namespace/text.json` file.

```
{
    "properties": {
        "description": {
            "editor_options": {
                "style_formats": [],
                "body_class": "s-wysiwyg",
                "content_css": "../../../../../styles/main.css"
            }
        }
    },
    "data": {
        "type": "my/namespace/text"
    }
}
```

In that case, the editor options are changed to remove the base style formats, change the body class and add the appropriate css. The important part is to set the data type to the current object. This is used in live edit and delete features.

If you added some extra properties, you can use the alter script to add them into the table.

`vendor/bin/charcoal admin/object/table/alter --obj-type=my/namespace/text`

Notes
-----

[](#notes)

**Don't use "attachments" method directly in mustache template**. This will return ALL attachments without considering the group.

Custom templates for the attachment preview in the backend widget is on the to-do list.

Other actions such quick view are on the to-do list as well.

For a complete project example using `charcoal-attachment`, see the [charcoal-project-boilerplate](https://github.com/locomotivemtl/charcoal-project-boilerplate).

Development
===========

[](#development)

To install the development environment:

```
★ composer install --prefer-source
```

Run the code checkers and unit tests with:

```
★ composer test
```

API documentation
-----------------

[](#api-documentation)

- The auto-generated `phpDocumentor` API documentation is available at
- The auto-generated `apigen` API documentation is available at

Development dependencies
------------------------

[](#development-dependencies)

- `phpunit/phpunit`
- `squizlabs/php_codesniffer`
- `satooshi/php-coveralls`

Continuous Integration
----------------------

[](#continuous-integration)

ServiceBadgeDescription[Travis](https://travis-ci.org/locomotivemtl/charcoal-attachment)[![Build Status](https://camo.githubusercontent.com/bf9e8d0393364050199e1a86dd058535cc8846712b9033b2ebc0cf39b3f84a60/68747470733a2f2f7472617669732d63692e6f72672f6c6f636f6d6f746976656d746c2f63686172636f616c2d6174746163686d656e742e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/locomotivemtl/charcoal-attachment)Runs code sniff check and unit tests. Auto-generates API documentaation.[Scrutinizer](https://scrutinizer-ci.com/g/locomotivemtl/charcoal-attachment/)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/1bd6d2ea5ff556c268254d985f2545b85fcbaf8e5636e439d9937a9fd1868f3a/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6c6f636f6d6f746976656d746c2f63686172636f616c2d6174746163686d656e742f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/locomotivemtl/charcoal-attachment/?branch=master)Code quality checker. Also validates API documentation quality.[Coveralls](https://coveralls.io/github/locomotivemtl/charcoal-attachment)[![Coverage Status](https://camo.githubusercontent.com/9146dbab057f99d97aab749b864252db468e2357c6eb29e93cbdba8a88a90da4/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6c6f636f6d6f746976656d746c2f63686172636f616c2d6174746163686d656e742f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/locomotivemtl/charcoal-attachment?branch=master)Unit Tests code coverage.[Sensiolabs](https://insight.sensiolabs.com/projects/09876d95-da9d-4c23-896f-904be3368c99)[![SensioLabsInsight](https://camo.githubusercontent.com/a4b1346c92ce5d381ef5ca4c0b650dde3b0930cf422c35c36d0c85905803e1c1/68747470733a2f2f696e73696768742e73656e73696f6c6162732e636f6d2f70726f6a656374732f30393837366439352d646139642d346332332d383936662d3930346265333336386339392f6d696e692e706e67)](https://insight.sensiolabs.com/projects/09876d95-da9d-4c23-896f-904be3368c99)Another code quality checker, focused on PHP.Coding Style
------------

[](#coding-style)

The Charcoal-Attachment module follows the Charcoal coding-style:

- [*PSR-1*](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md)
- [*PSR-2*](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
- [*PSR-4*](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md), autoloading is therefore provided by *Composer*.
- [*phpDocumentor*](http://phpdoc.org/) comments.
- Read the [phpcs.xml](phpcs.xml) file for all the details on code style.

> Coding style validation / enforcement can be performed with `composer phpcs`. An auto-fixer is also available with `composer phpcbf`.

Authors
=======

[](#authors)

- Mathieu Ducharme
- Chauncey McAskill
- Benjamin Roch

License
=======

[](#license)

Charcoal is licensed under the MIT license. See [LICENSE](LICENSE) for details.

###  Health Score

34

—

LowBetter than 75% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity22

Limited adoption so far

Community23

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~35 days

Recently: every ~168 days

Total

60

Last Release

1451d ago

PHP version history (2 changes)0.9.3PHP &gt;=5.6.0 || &gt;=7.0

0.10.3PHP  &gt;=7.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/cfb071c0ff7ce9500c528a003a2c53124248debc3e5bf367c17f89f5e6136125?d=identicon)[mducharme](/maintainers/mducharme)

![](https://www.gravatar.com/avatar/0a4f39523b4b2837562ba0848a0327b8d340118d1ba87cb0f5d59b1d5cb6beba?d=identicon)[mcaskill](/maintainers/mcaskill)

---

Top Contributors

[![mcaskill](https://avatars.githubusercontent.com/u/29353?v=4)](https://github.com/mcaskill "mcaskill (110 commits)")[![JoelAlphonso](https://avatars.githubusercontent.com/u/10762266?v=4)](https://github.com/JoelAlphonso "JoelAlphonso (39 commits)")[![BeneRoch](https://avatars.githubusercontent.com/u/3017380?v=4)](https://github.com/BeneRoch "BeneRoch (38 commits)")[![dominiclord](https://avatars.githubusercontent.com/u/1775204?v=4)](https://github.com/dominiclord "dominiclord (22 commits)")[![mducharme](https://avatars.githubusercontent.com/u/12157?v=4)](https://github.com/mducharme "mducharme (13 commits)")[![losted](https://avatars.githubusercontent.com/u/165665?v=4)](https://github.com/losted "losted (2 commits)")[![veve40](https://avatars.githubusercontent.com/u/7537381?v=4)](https://github.com/veve40 "veve40 (2 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/locomotivemtl-charcoal-attachment/health.svg)

```
[![Health](https://phpackages.com/badges/locomotivemtl-charcoal-attachment/health.svg)](https://phpackages.com/packages/locomotivemtl-charcoal-attachment)
```

###  Alternatives

[locomotivemtl/charcoal-cms

Charcoal CMS (Content Management System) Module

529.1k3](/packages/locomotivemtl-charcoal-cms)[ericnorris/amazon-s3-php

A lightweight and fast S3 client for PHP.

2147.0k](/packages/ericnorris-amazon-s3-php)[locomotivemtl/charcoal-admin

The Charcoal Administration Dashboard

1110.9k12](/packages/locomotivemtl-charcoal-admin)

PHPackages © 2026

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