Ticket Organisation Hooks

1 views Markdown

The seven hooks over merging, splitting and moving tickets.

Overview

The operations that reorganise tickets live here: merging, splitting, and changing the department, priority or linked service.

The first two cannot be undone. A merge deletes everything but the target; a split moves replies into a new ticket. That is what makes the gates valuable.

Reference

Stopping a ticket merge

gateticket.merge
AdminTickets the others are deleted

Runs before tickets are merged. A merge cannot be undone: everything but the target is deleted.

Parameters 2
$primary_idintThe target ticket; the others move into it.
$merge_idsarrayThe other tickets; the target is not in this list.
Return 1
string|nullA non-empty text blocks the operation and is shown as the error. An empty return lets it carry on.
Listener
Hook::add('gate:ticket.merge', 10, function ($primary_id, $merge_ids) {
    // Everything but the target is DELETED: this cannot be undone.
    foreach ($merge_ids as $id)
        if (Acme::underLegalHold((int) $id)) return 'A ticket under legal hold cannot be merged.';

    return null;
});

Following a merge

actionticket.merged
AdminTickets after the merge

Runs after the tickets are merged.

Parameters 2
$primary_idintThe target ticket.
$merged_idsarrayThe ids merged in and deleted. Those ids no longer exist: point them at the target in your own records.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:ticket.merged', 10, function ($primary_id, $merged_ids) {
    // Those ids are gone: point them at the target.
    foreach ($merged_ids as $id) Acme::redirectRef((int) $id, $primary_id);
});

Stopping a ticket split

gateticket.split
AdminTickets an unverified list

Runs before some replies of a ticket are moved into a new one.

Parameters 2
$sourcearrayThe source ticket being split.
$reply_idsarrayThe ids of the replies to move. They are cleaned but not yet checked against the database: an id here may not really belong to that ticket.
Return 1
string|nullA non-empty text blocks the operation and is shown as the error. An empty return lets it carry on.
Listener
Hook::add('gate:ticket.split', 10, function ($source, $reply_ids) {
    // The list has not been checked against the database yet.
    if (count($reply_ids) > 50) return 'At most 50 replies can move at once.';

    return null;
});

Following a split

actionticket.split
AdminTickets a verified list

Runs after the new ticket is created and the replies have moved.

Parameters 3
$sourcearrayThe source ticket.
$new_ticketarrayThe newly created ticket.
$moved_reply_idsarrayThe ids that actually moved. Unlike in the gate this list is verified: anything asked for but not moved is absent.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:ticket.split', 10, function ($source, $new_ticket, $moved_reply_ids) {
    // This list is verified: what really moved.
    Acme::reindexSplit((int) ($new_ticket['id'] ?? 0), $moved_reply_ids);
});

Following a department change

actionticket.department_changed
AdminTickets zero means none

Runs after a ticket moves to another department. The department decides who sees the ticket.

Parameters 3
$ticketarrayThe record before the change.
$oldDepartmentIdintThe previous department; a zero means none.
$newDepartmentIdintThe new department.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:ticket.department_changed', 10,
    function ($ticket, $oldDepartmentId, $newDepartmentId) {
        // The department decides who sees it.
        Acme::notifyDepartment($newDepartmentId, (int) ($ticket['id'] ?? 0));
    });

Following a priority change

actionticket.priority_changed
AdminTickets four levels

Runs after the priority of a ticket changes.

Parameters 3
$ticketarrayThe record before the change.
$oldPriorityintThe previous level.
$newPriorityintThe new level.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:ticket.priority_changed', 10,
    function ($ticket, $oldPriority, $newPriority) {
        if ($newPriority > $oldPriority) Acme::escalate((int) ($ticket['id'] ?? 0));
    });

Following the linked service changing

actionticket.service_changed
AdminTickets zero means unlinked

Runs after the service a ticket is linked to changes.

Parameters 3
$ticketarrayThe record before the change.
$oldServiceIdintThe previous service; a zero means it was not linked.
$newServiceIdintThe new service; a zero means the link was removed.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:ticket.service_changed', 10,
    function ($ticket, $oldServiceId, $newServiceId) {
        // Zero means the link was removed.
        if (!$newServiceId) return;

        Acme::attachServiceContext((int) ($ticket['id'] ?? 0), $newServiceId);
    });

Pitfalls

A merge deletes the other tickets

In a merge everything but the target is deleted, not merely moved. The ids in the event hook are records that no longer exist: point them at the target on your side, or you are left with broken references.

The list in the split gate is not verified yet

The reply ids reaching the gate are cleaned but not matched against the database: the list may hold an id that does not belong to that ticket. To see what really moved, read the list in the event hook.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.