Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions docs/components/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,88 @@
return $this->handleView($worlds);
}
}

----

.. vale off

API-aware entity locking
****************************

.. vale on

Mautic supports locking for API-editable entities, such as Emails, to prevent overwriting changes while a user is actively editing the entity in the UI.

Check warning on line 110 in docs/components/api.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'.", "location": {"path": "docs/components/api.rst", "range": {"start": {"line": 110, "column": 107}}}, "severity": "INFO"}

This is useful when:

- You want the API to respect the locking behavior already in place in the UI.
- You want to return a `409 Conflict` when a record is locked.

Check warning on line 115 in docs/components/api.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Google.Passive] In general, use active voice instead of passive voice ('is locked'). Raw Output: {"message": "[Google.Passive] In general, use active voice instead of passive voice ('is locked').", "location": {"path": "docs/components/api.rst", "range": {"start": {"line": 115, "column": 53}}}, "severity": "INFO"}

.. vale off

Enable API lock for a model
============================

.. vale on

To make an entity model API-lock-aware:

1. Implement the interface:

.. code-block:: php

use Mautic\ApiBundle\Model\ApiLockAwareInterface;

class MyEntityModel implements ApiLockAwareInterface
{
// ...
}

2. Use the trait to reuse locking logic:

.. code-block:: php

use Mautic\ApiBundle\Model\ApiEntityLockTrait;

class MyEntityModel implements ApiLockAwareInterface
{
use ApiEntityLockTrait;

// Optional: Override `isApiLocked()` if you need custom behavior
}

This ensures your model will be checked by the API when editing.

Check warning on line 150 in docs/components/api.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Google.Passive] In general, use active voice instead of passive voice ('be checked'). Raw Output: {"message": "[Google.Passive] In general, use active voice instead of passive voice ('be checked').", "location": {"path": "docs/components/api.rst", "range": {"start": {"line": 150, "column": 30}}}, "severity": "INFO"}

Check warning on line 150 in docs/components/api.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Google.Will] Avoid using 'will'. Raw Output: {"message": "[Google.Will] Avoid using 'will'.", "location": {"path": "docs/components/api.rst", "range": {"start": {"line": 150, "column": 25}}}, "severity": "WARNING"}

Behind the scenes, the API controller checks:

.. code-block:: php

if ($this->model instanceof ApiLockAwareInterface && $this->model->isApiLocked($entity)) {
....
}

.. vale off

Error message
=============

.. vale on

When an entity is locked, the API returns:

Check warning on line 167 in docs/components/api.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Google.Passive] In general, use active voice instead of passive voice ('is locked'). Raw Output: {"message": "[Google.Passive] In general, use active voice instead of passive voice ('is locked').", "location": {"path": "docs/components/api.rst", "range": {"start": {"line": 167, "column": 16}}}, "severity": "INFO"}

.. code-block:: json

{
"errors": [
{
"message": "{Entity} is currently checked out by {User} (on {Date} at {Time}).",
"code": 409,
"details": {
"checkedOutBy": "{User}",
"checkedOut": "{Date} {Time}"
}
}
]
}

This format helps client apps identify locked records and avoid overwriting.