Skip to content

Developer notes

Technical reference for developers who customize Help Desk & Support Tickets.

Item Value
Add-on id kv_support_tickets
Function prefix fn_kv_support_tickets_
Language variables kv_support_tickets.*
CSS scope .kv-support-tickets (storefront), .kv-st-* (admin)
PHP namespace Tygh\Addons\KvSupportTickets
Controller kv_support_tickets (storefront and back end)

PHP: before_dispatch (hourly auto-close fallback in the admin panel; plus, in the admin area and console only, the static handler License\Client::onBeforeDispatch, which runs the due license check and shows license notices), delete_user (tickets stay as guest tickets), delete_company (vendor tickets move to the marketplace), settings_variants_image_verification_use_for (CAPTCHA scenario), init_templater_post (only while an upgrade sync is pending).

Templates: storefront profiles:my_account_menu.post, orders:details_bullets.post, index:styles.post, index:scripts.post; admin orders:details_tools.post, index:styles.post (also license.less), index:scripts.post, addons:tabs_content.pre (license card at the top of the add-on page), addons:manage.post (license badge, moved into the add-on’s row).

Schemas: menu/menu.post.php, menu/menu_vendor.post.php, menu/actions.post.php (4.18+), permissions/admin.post.php, permissions/vendor_multivendor.post.php, notifications/events.post.php, notifications/events_multivendor.post.php, security/csrf_validation.post.php, security/antibot_rules.post.php, gdpr/user_data.post.php.

Hook Arguments When
kv_support_tickets_create_ticket_pre &$data, $auth, &$errors, &$company_id Before a ticket is saved; add errors to block it.
kv_support_tickets_create_ticket_post $ticket, $message_id, $data, $auth After a ticket and its first message are saved.
kv_support_tickets_reply_post $ticket, $message_id, $by_staff, $is_internal After a reply or note.
kv_support_tickets_change_status_post $ticket, $old_status, $by_staff After a status change.
kv_support_tickets_delete_ticket_post $ticket_id After a ticket was deleted.
kv_support_tickets_notify_pre $event, &$data, &$rules Before a notification event is dispatched.

Example (another add-on attaches its own data when a ticket is created):

fn_register_hooks('kv_support_tickets_create_ticket_post');
function fn_my_addon_kv_support_tickets_create_ticket_post($ticket, $message_id, $data, $auth)
{
// $data holds the submitted ticket_data[...] fields, including your own extra fields.
}

kv_support_tickets.ticket_created, kv_support_tickets.customer_replied, kv_support_tickets.staff_replied, kv_support_tickets.status_changed (group kv_support_tickets). Data provider: Tygh\Addons\KvSupportTickets\TicketDataProvider. E-mail templates: kv_support_tickets_created_customer, _created_admin, _reply_customer, _reply_admin, _status_customer, _access_link. They use only Twig features available in both Twig 2.14 (CS-Cart 4.17/4.18) and Twig 3 (4.21).

Core skips event e-mails to @example.com addresses (fn_checkout_is_email_address_fake), so test with a real domain.

Table Content
?:kv_st_tickets Tickets (company, storefront, customer, subject, department, priority, status, order, product, assignee, rating, access key).
?:kv_st_messages Messages and internal notes (is_internal), system events (author_type = Y).
?:kv_st_attachments Attachment metadata; files in the custom_files storage under kv_support_tickets/<ticket_id>/.
?:kv_st_departments, ?:kv_st_department_descriptions Departments and their names per language.
?:kv_st_canned Canned responses (company_id 0 = shared).
?:kv_st_secrets Encrypted access details (fn_encrypt_text).

All tables are InnoDB. Uninstall drops them and deletes the stored files.

Guest links carry key = HMAC-SHA256(ticket_id | email | per-ticket secret, crypt_key) (first 40 hex characters). The per-ticket secret is regenerated on GDPR anonymization, which invalidates old links. Ticket pages send X-Robots-Tag: noindex and Referrer-Policy: same-origin.

The ticket pages (kv_support_tickets.*) are not in the full page cache dispatch list, and the account menu link sits in the session-dependent “My account” block, so no per-visitor content ends up in cached guest pages.

/api/kv_support_tickets (see the class header of Tygh/Api/Entities/KvSupportTickets.php): administrators use the “View/Manage support tickets” privileges; vendor administrators work with their company’s tickets; customers with a token work with their own tickets.

Files:

app/addons/kv_support_tickets/
├── controllers/backend/kv_support_tickets_license.php "Check now" / cron license check
└── Tygh/Addons/KvSupportTickets/License/Client.php license check client (generated from the shared Kavio Labs template)
design/backend/templates/addons/kv_support_tickets/license/info.tpl License tab (points to the card)
design/backend/templates/addons/kv_support_tickets/license/card.tpl License card (add-on page) / banner
design/backend/templates/addons/kv_support_tickets/license/status_bar.tpl status chip/banner for own admin pages
design/backend/templates/addons/kv_support_tickets/license/badge.tpl badge in Add-ons > Manage add-ons
design/backend/templates/addons/kv_support_tickets/hooks/addons/ tabs_content.pre.tpl (card), manage.post.tpl (badge)
design/backend/css/addons/kv_support_tickets/license.less card, chip and badge styles (admin LESS variables)

Tygh\Addons\KvSupportTickets\License\Client verifies the license against the Kavio Labs license server.

  • fn_kv_support_tickets_is_licensed() is the storefront gate. It reads the stored state only (one storage read per request) and never contacts the server. fn_kv_support_tickets_storefront_enabled() combines it with the “Enabled” setting. The storefront hook templates read the same value from $kv_st_storefront_on, assigned in the before_dispatch handler, so they never call an add-on function as a Smarty modifier (safe while files are replaced during an upgrade). When the license is not valid:
    • the storefront controller kv_support_tickets (every mode except cron) redirects to fn_kv_support_tickets_fallback_url(): the first active Form builder page whose name contains “contact” (for example the default “Contact us”), otherwise index.index. No ticket is created or answered, no access-link e-mail is sent;
    • the “My tickets” link (profiles:my_account_menu.post) and the “Get help with this order” button (orders:details_bullets.post) are hidden, and fn_kv_support_tickets_get_awaiting_count() returns 0;
    • the REST API refuses customer (token) access in privilegesCustomer(); administrators and vendor administrators keep access.
  • Not gated (ticket management): the admin and vendor panel controller, notifications of staff actions (replies, status changes, tickets opened on behalf of customers), the auto-close job (kv_support_tickets.cron, admin fallback), GDPR export/anonymization, uninstall.
  • No core-cached block shows add-on output: the “My account” block is not cached and the order page is not cached, so no callable_handlers are needed.
  • Request: POST https://cs-cart.kaviolabs.com/index.php?dispatch=kv_licenses.check with JSON {"v":1, "license", "addon", "version", "hosts":[…], "platform":{"version", "edition"}, "nonce"}, sent through Tygh\Http (3 s connect, 5 s total; kept out of the CS-Cart request log). The answer is accepted only when its Ed25519 signature matches a public key embedded in the client and it echoes the nonce.
  • State: storage key kv_license_kv_support_tickets (?:storage_data), or var/kv_storage/kv_support_tickets/license.json while the full page cache is active, protected by an HMAC with the store’s crypt key.
  • Cron: php admin.php --dispatch=kv_support_tickets_license.check.
  • Admin UI: License\Client assigns the view data of the license card to $kv_lic_kv_support_tickets in its before_dispatch handler, only for administrators with the Manage settings privilege (update_settings); vendors never get it. The templates only read this variable, so they render nothing (and no error) while an older version of the PHP code is loaded, for example in the request that uploads a new zip over the installed add-on. PHP code can call fn_kv_support_tickets_license_ui($context). Every full page of the add-on’s own admin controllers (ticket list, ticket page, new ticket page, departments, canned responses) includes license/status_bar.tpl as the first line of its mainbox: a green chip when licensed, the card as a compact banner otherwise. The add-on’s license notice is not shown on these pages (the bar shows the status); it appears on the next other admin page.
  • Development stores only (http_host and https_host are development hosts): the constants KV_LICENSE_SERVER_URL, KV_LICENSE_TEST_HOST (act as if the development storefronts ran on that host) and KV_LICENSE_TEST_TIME_OFFSET (seconds). They are ignored on production hosts.
  • The license check endpoint (kv_support_tickets_license.check) accepts only CSRF-protected POST requests of administrators, and console requests. Vendors cannot use it.

Storefront templates live in design/themes/<theme>/templates/addons/kv_support_tickets/. To customize one, copy it to your own theme’s folder; do not edit the add-on’s files, they are replaced on update.

Tygh/Addons/KvSupportTickets/License/Ed25519.php (checks the signature of the license server’s answers on servers whose PHP has no sodium extension) is derived from paragonie/sodium_compat, ISC License, Copyright (c) 2016-2023 Paragon Initiative Enterprises and Copyright (c) 2013-2019 Frank Denis. The full license notice is in the file header.