Skip to content

Developer notes

Table Contents
?:kv_prs_templates template_id, company_id (MV vendor / ULT storefront, 0 = marketplace / all), name, status, approval, position, timestamps
?:kv_prs_links object_type (P product / C category / V vendor), object_id, company_id, template_id. A product link with template 0 means “No personalization”
?:kv_prs_views view_id, template_id, image_source (P main image / A additional image / C own image), image_index
?:kv_prs_areas area_id, view_id, x, y, w, h (percent of the image), rotation (degrees, clockwise)
?:kv_prs_fields field_id, template_id, area_id, type (T text / I image / C choice), code, required, settings (JSON), price_mode, price, free_chars, formula
?:kv_prs_variants variant_id, field_id, surcharge, value
?:kv_prs_descriptions object_type (F field / V variant / W view), object_id, lang_code, name, help
?:kv_prs_uploads token (32 hex), file (sha1), mime, ext, width, height, size, original_name, user_id, owner (hash of the session id), product_id, field_id, status (T temporary / O ordered), created_at
?:kv_prs_items order_id, item_id, product_id, company_id, template_id, data (JSON: values, display lines, proofs), unit_surcharge, approval (‘’ / P / A / C), approval_note, anonymized

Own view images are core image pairs with the object type kv_prs_view.

?:order_details.extra and the cart line carry extra.kv_prs:

v, template_id, version, hash (sha1 of the normalised values), values {field_id: {type, text, font, color | token, file, ext, mime, width, height, name | variant_id}},
approved, unit (surcharge per item), lines (price breakdown), display (label/value lines), proofs {view_id: {name, file, thumb, width, height}}

Only CartBridge writes it. A value posted as product_data[..][extra][kv_prs] is always discarded: the personalization comes from product_data[..][kv_prs] (f, font, color, approve), is validated against the template and stored by the server.

  • Files live in var/kv_product_personalizer/ as <sha1>.bin: tmp/<2>/ for uploads and cart proofs, orders/<order_id>/ for ordered items. The folder gets a deny-all .htaccess and an index.php. Paths are built only from 40-hex hashes and integer ids.
  • Uploads: allow-list JPG/PNG/WebP; the extension, the magic bytes, finfo and the image header must agree; markup (<svg, <?xml, <html, <script, <?php) in the first KB is refused; size limits; at most 10,000 px per side and 25 megapixels, checked before decoding; GD decodes, applies the EXIF orientation and encodes again (no metadata, nothing appended). 30 uploads per visitor and hour.
  • An upload token is usable only by the session or account that uploaded it, for the same product and field.
  • Downloads: storefront kv_product_personalizer.file checks fn_is_order_allowed() and that the item references the requested hash; cart proofs (kv_product_personalizer.proof) only for lines of the visitor’s own cart. Responses send X-Content-Type-Options: nosniff and a restrictive Content-Security-Policy.
  • The storefront upload and preview requests require the form security hash.

Renderer::render() draws the view image (scaled to the proof width) and every field of the view into its area: text with imagettftext() in the bundled font, fitted by a binary search on the font size; images with imagecopyresampled() (contain or cover); rotated areas with imagerotate(). The PNG contains no timestamp, so the same input always gives the same bytes; the file name is the sha1 of the bytes. Proofs are rendered when the item is added to the cart and copied into the order folder when the order is placed (rendered again from the stored values if a copy is missing).

Hook Use
pre_add_to_cart Validation and storage of the personalization of new lines
generate_cart_id The personalization hash makes separate cart lines
apply_option_modifiers_post The surcharge per item joins the unit price (cart, checkout, orders, order editing)
exclude_products_from_calculation Storefront carts: expired uploads, changed or removed templates, changed surcharges
gather_additional_products_data_post Product page data (static per product); “Select options” in lists
place_order, get_order_info, delete_order Ordered items and files, option lines and links in orders
update_product_post, clone_product, delete_product_post, delete_category_post, delete_company Assignments
before_dispatch Hourly cleanup on back-end GET requests

The add-on fires kv_product_personalizer_notify_pre($data) before the proof review e-mail.

GDPR: schemas/gdpr/user_data.post.php exports the personalization of a customer’s orders and, on anonymization, deletes the texts, uploads and proofs (the order lines keep their prices).

  • Advanced Product Options & Price Formulas (kv_product_options_pricing): when active and licensed, the price mode Formula evaluates with its Expression engine. Nothing is required: without it the mode is hidden.
  • Booking & Reservations (kv_booking_reservations) and Auctions (kv_auction_bidding): their products never get the personalizer (checked through their tables/classes while those add-ons are active).
  • Core product options keep working next to the personalizer.
app/addons/kv_product_personalizer/
addon.xml init.php func.php
controllers/backend/kv_product_personalizer.php, products.post.php, kv_product_personalizer_license.php
controllers/frontend/kv_product_personalizer.php, checkout.post.php
schemas/block_manager/blocks.post.php product page cache keys
schemas/gdpr/user_data.post.php
schemas/menu/menu.post.php, menu_vendor.post.php, actions.post.php
schemas/notifications/events.post.php
schemas/permissions/admin.post.php, vendor_multivendor.post.php
schemas/security/csrf_validation.post.php
Tygh/Addons/KvProductPersonalizer/
CartBridge.php cart lines, surcharge, product page data
Cleanup.php abandoned uploads
Compat.php options pricing formulas, booking/auction exclusion
Config.php settings, licence gate, constants
Files.php private file store
Fonts.php bundled fonts
Gdpr.php export and anonymization
ImageTools.php upload validation and re-encoding
Notifier.php, ProofDataProvider.php proof review e-mail
Orders.php ordered items, files, approval, production data
Personalization.php validation, prices, hashes, display lines
Renderer.php proofs (GD)
StorageData.php run marks (full page cache safe)
Templates.php templates, resolution, editor save
Uploads.php upload records and ownership
License/ Upgrade/ license client, self-healing upgrades
design/backend/templates/addons/kv_product_personalizer/ template editor, lists, production sheet, hooks
var/themes_repository/responsive/templates/addons/kv_product_personalizer/ personalizer panel, cart and order hooks
js/addons/kv_product_personalizer/func.js, backend.js
js/addons/kv_product_personalizer/fonts/ six OFL fonts + license texts
var/langs/en/addons/kv_product_personalizer.po