Skip to content

Developer guide

Back to overview · Previous: Usage · Next: FAQ

app/addons/kv_product_labels_stickers/
addon.xml, init.php, func.php
Tygh/Addons/KvProductLabelsStickers/Badge.php options, normalization, CSS classes, placeholders
Tygh/Addons/KvProductLabelsStickers/RuleEngine.php cached badge loading and batch rule evaluation
Tygh/Addons/KvProductLabelsStickers/Presets.php the preset gallery and the demo set
controllers/backend/kv_product_labels_stickers.php list, editor, presets, bulk tools (admin + vendor panel)
controllers/backend/products.post.php the "Labels" product tab
controllers/backend/kv_product_labels_stickers_license.php "Check now" / cron license check
Tygh/Addons/KvProductLabelsStickers/License/Client.php license check client (generated from the shared Kavio Labs template)
Tygh/Addons/KvProductLabelsStickers/Upgrade/Synchronizer.php self-healing in-place upgrades
schemas/menu/menu.post.php, menu_vendor.post.php
schemas/permissions/admin.post.php (view_catalog / manage_catalog), vendor_multivendor.post.php
schemas/exim/products.post.php + products.functions.php the "Product labels" column
schemas/block_manager/block_cache_properties.post.php block cache invalidation, license state in the cache key
var/themes_repository/responsive/templates/addons/kv_product_labels_stickers/
hooks/products/product_data.post.tpl injects the overlay into the theme's label capture
hooks/index/styles.post.tpl, scripts.post.tpl
components/badges.tpl, badge.tpl, icon.tpl
var/themes_repository/responsive/css/addons/kv_product_labels_stickers/styles.less
js/addons/kv_product_labels_stickers/func.js storefront: fits the product page overlay to the main image
js/addons/kv_product_labels_stickers/backend.js admin: live preview, rule blocks, feature variants
design/backend/... admin templates and styles (license/info.tpl: License tab)
Table Columns
cscart_kv_pls_badges badge_id, company_id (0 = admin badge, otherwise the Multi-Vendor vendor), status, position, badge_type (text/image), shape, placement, size, color_mode, bg_color, text_color, effect, font, text_style, icon, image_width, show_in (B/L/P), date_from, date_to, rule_match (A = all, O = any), conditions (JSON), preset, timestamps
cscart_kv_pls_badge_descriptions badge_id, lang_code, name, text
cscart_kv_pls_badge_products badge_id, product_id (manual assignment; indexed by product)

Graphic badges are stored as CS-Cart image pairs with the object type kv_pls_badge.

Example conditions:

{"discount":{"min":20,"max":0},"categories":{"ids":[166,170],"subcats":true},"feature":{"feature_id":18,"variant_ids":[29]}}

The keys are discount, new, stock, price, free_shipping, bestseller, categories, feature and vendors. Category IDs are expanded with their subcategories when badges are loaded.

  1. PHP hook gather_additional_products_data_post. For storefront requests, RuleEngine::apply() adds kv_pls_badges (a ready-to-render list) to every product of the list. Discounts are already calculated at that point.
  2. Template hook products:product_data (post). This is the last hook in common/product_data.tpl. Core builds the product_labels_<obj_prefix><obj_id> capture there, and every core list, the product page and quick view print it inside the image container. The hook prepends our overlay to that capture. No core template is overridden.
  3. The theme labels setting. Hide the discount label adds a marker class. The CSS rule .kv-pls--hide-theme-discount ~ .ty-product-labels .ty-product-labels__item--discount hides the theme’s discount label. Hide all theme labels drops the theme’s labels from the capture.

The product page is detected by products.view / products.quick_view with the requested product_id. There the overlay gets kv-pls--detail, and func.js fits it to .cm-preview-wrapper.

  • Active badges, with their texts, images, product counts and expanded categories, are cached per language in the Registry cache (kv_pls_badges_<lang>). The cache is invalidated automatically when kv_pls_*, images, images_links or categories change.
  • Per product list, RuleEngine::collectFacts() runs at most these batch queries, and only when an active badge needs them:
    • products (by primary key): for new, stock, vendor, free shipping and vendor badges;
    • products_categories: for category rules;
    • product_features_values: for feature rules;
    • kv_pls_badge_products: only for badges that have manual products.
  • Bestseller counts come from one aggregate query over paid orders per period, cached for the configured time (Registry::cacheLevel('time')).
  • Block cache: our tables are added to the global update_handlers. A callable handler (fn_kv_product_labels_stickers_get_schedule_cache_key) changes the cache key when a scheduled badge starts or ends, and another one (fn_kv_product_labels_stickers_is_licensed) when the license state changes.

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

  • fn_kv_product_labels_stickers_is_licensed() is the storefront gate. When it returns false, fn_kv_product_labels_stickers_is_enabled() returns false, so gather_additional_products_data_post adds neither kv_pls_badges nor the kv_pls_on flag, and hooks/products/product_data.post.tpl (which reads only that flag, never an add-on function) leaves the theme’s label capture untouched (no overlay, Theme’s own product labels not applied). It reads the stored state only (one storage read per request) and never contacts the server.
  • The admin and vendor badge editor, the product tab, import/export and the data are not gated.
  • Product lists and product pages are printed inside blocks that CS-Cart may cache. The license state is part of every block cache key (block_cache_properties.post.php, callable_handlers kv_pls_license), so badges appear or disappear at once.
  • Client::boot() (init.php) registers a before_dispatch handler for the admin area and the console only. On admin page views and console requests it runs the check when it is due (key changed, or 24 hours after the last check; 1 hour after a failure) and shows the admin notice once per session.
  • Admin license UI (generated): the License card at the top of the add-on page (license/card.tpl through the addons:tabs_content pre hook), the badge in Add-ons > Manage (license/badge.tpl, addons:manage post hook), the status bar (license/status_bar.tpl, first line inside the mainbox capture of views/kv_product_labels_stickers/{manage,update,presets}.tpl; nothing for vendors) and css/addons/kv_product_labels_stickers/license.less (index:styles post hook). The off-effect sentence is the language variable kv_product_labels_stickers.license_off_effect.
  • 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_product_labels_stickers (?:storage_data), or var/kv_storage/kv_product_labels_stickers/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_product_labels_stickers_license.check.
  • 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_product_labels_stickers_license.check) accepts only CSRF-protected POST requests of administrators, and console requests. Vendors cannot use it.

gather_additional_products_data_post, update_product_post, delete_product_post, clone_product (copies manual badges to the clone) and delete_company (removes a vendor’s badges). The license client adds a static before_dispatch handler (License\Client::onBeforeDispatch) for the admin area and the console only: it runs the due license check and shows the license notices.

Hook Arguments
kv_product_labels_stickers_update_badge_pre &$data, &$badge_id, &$lang_code
kv_product_labels_stickers_update_badge_post $data, $badge_id, $lang_code, $record
kv_product_labels_stickers_delete_badge_pre $badge_id
fn_kv_product_labels_stickers_update_badge(array $data, $badge_id = 0, $lang_code = DESCR_SL); // returns badge_id
fn_kv_product_labels_stickers_delete_badge($badge_id);
fn_kv_product_labels_stickers_get_badge($badge_id, $lang_code = DESCR_SL);
fn_kv_product_labels_stickers_set_badge_products($badge_id, $product_ids);
fn_kv_product_labels_stickers_create_from_preset($preset_key, $status = 'A', $position = 0);
\Tygh\Addons\KvProductLabelsStickers\RuleEngine::apply($products, $lang_code); // adds kv_pls_badges
<div class="kv-product-labels-stickers kv-pls kv-pls--list|kv-pls--detail" style="--kv-pls-scale: 0.9;">
<div class="kv-pls__pos kv-pls__pos--top-left">
<span class="kv-pls-badge kv-pls-badge--ribbon kv-pls-badge--size-m kv-pls-badge--custom
kv-pls-badge--effect-gradient kv-pls-badge--font-inherit kv-pls-badge--text-bold-upper"
style="--kv-pls-bg: #e03131; --kv-pls-soft: #fbe0e0; --kv-pls-fg: #ffffff;" data-kv-pls-badge="1">
<span class="kv-pls-badge__inner"><span class="kv-pls-badge__text">Sale -25%</span></span>
</span>
</div>
</div>

You can override the look in your theme’s CSS through these custom properties:

  • on .kv-product-labels-stickers: --kv-pls-inset (distance from the edge), --kv-pls-gap (space between stacked badges) and --kv-pls-scale;
  • on .kv-pls-badge: --kv-pls-fs (base font size).

Theme colors come from the Responsive LESS variables @discount_label, @product_label, @primary_button, @shipping_label and @headings_font.

A theme that is based on Responsive and keeps common/product_data.tpl and the product_labels_* capture needs no changes. If your theme prints product images without that capture, print it inside the image container:

{$product_labels = "product_labels_`$obj_prefix``$obj_id`"}
{$smarty.capture.$product_labels nofilter}

The container must be positioned (position: relative).

Tygh/Addons/KvProductLabelsStickers/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.