Skip to content

Developer notes

Overview · Installation · Configuration · Usage · FAQ

All tables are InnoDB, created with CREATE TABLE IF NOT EXISTS and dropped on uninstall.

Table Contents
?:kv_pqa_questions question_id, product_id, company_id (Multi-Vendor: owner of the product; Ultimate: storefront), user_id, name, email, question, status (P waiting, A published, D declined, S spam), notify, is_buyer, answers_count (published), helpful_total, lang_code, ip_hash (HMAC), flag (spam guard reason), ext_ref (imported rows), created_at, updated_at, answered_at
?:kv_pqa_answers answer_id, question_id, product_id, user_id, author_type (A store, V seller, C customer), company_id (seller), name, answer, is_buyer, status (P/A/D), helpful_count, ip_hash, flag, ext_ref, timestamps
?:kv_pqa_votes answer_id + voter (HMAC of the customer id, or of a random browser id and the IP address)
?:kv_pqa_rate rate limit buckets (HMAC key, hits, window start)

IP addresses are never stored in clear. The product tab is a core product tab (blocks/product_tabs/kv_pqa.tpl, html id kv_pqa); privileges view_kv_pqa / manage_kv_pqa (group kv_pqa).

Storefront endpoints (kv_product_questions_answers.*, never cached by the full page cache)

Section titled “Storefront endpoints (kv_product_questions_answers.*, never cached by the full page cache)”
Dispatch Method Purpose
ask_form GET (AJAX) Ask dialog with a signed time stamp, honeypot and the captcha template
ask POST Validates, runs the spam guard and the captcha (fn_image_verification('kv_product_questions', …)), stores, e-mails
answer_form / answer GET (AJAX) / POST Customer answers (verified buyers or registered customers)
vote POST Helpful vote; returns kv_pqa_vote {ok, count, already, error}
list GET (AJAX) Q&A list fragment (result_ids=kv_pqa_list_<product_id>) for search, sorting, pages; without AJAX it redirects to the product page with the same parameters
state GET (AJAX) Per-visitor state {active, logged_in, can_answer, voted[]}, Cache-Control: no-store
unsubscribe GET Signed link from the answer e-mail (t = HMAC of question id + e-mail)
  • The product page output depends only on the product, the storefront, the language and the list parameters (kv_pqa_page, kv_pqa_sort, kv_pqa_q). Per-visitor parts (votes given, “Answer” links, forms) come from the endpoints above after the page is shown; no session data is printed and nothing is written to the session or ?:storage_data on GET requests.
  • Data is read through Registry::getOrSetCache() with kv_pqa_questions and kv_pqa_answers as conditions. On 4.21 these tables become cache tags of the page, so a new, edited, moderated or voted question purges the cached product pages; the block cache of the product page (main block on products.view) and of our block is refreshed the same way and carries the licence state (callable_handlers).
  • The visitor id cookie kv_pqa_vid is set by the script only when a guest votes.
Hook Use
dispatch_before_display FAQPage structured data on products.view: merged into Kavio SEO Pro Suite’s kv_faq_page item when present, otherwise added to the core SEO markup list (schema_org_markup_items), otherwise printed by hooks/index/meta.post.tpl. Priority 3200 (after SEO 1800 and SEO Pro Suite 2900).
delete_product_post Deletes the product’s questions, answers and votes
post_delete_user Keeps the user’s questions and answers without personal data
settings_variants_image_verification_use_for Adds the captcha scenario kv_product_questions

Template hooks: products:main_info_title (post, “N answered questions”), index:meta (post), index:styles, index:scripts.

honeypot (silently dropped) → signed time stamp (minimum seconds, 2 hours lifetime) → rate limit per IP and per guest e-mail (hourly) → duplicate (questions, 24 hours) → blocked words (spam) → links (held) → captcha → auto-publishing rule.

Classes (Tygh\Addons\KvProductQuestionsAnswers)

Section titled “Classes (Tygh\Addons\KvProductQuestionsAnswers)”

Config (settings, licence gate storefrontActive()), Access (ask/answer/moderate rules, verified buyer), SpamGuard, Questions, Answers, Votes, Captcha (antibot service, Captcha Pro state), Notifier (e-mails), Storefront (cached view data), Markup (FAQPage), Importer (Photo & Video Reviews), Admin (back office lists and scoping), License\Client, Upgrade\Synchronizer.

app/addons/kv_product_questions_answers/
addon.xml init.php func.php
controllers/frontend/kv_product_questions_answers.php storefront endpoints
controllers/frontend/products.post.php product page data
controllers/backend/kv_product_questions_answers.php queue, question page, bulk actions
controllers/backend/kv_product_questions_answers_license.php
schemas/block_manager/blocks.post.php schemas/menu/{menu,menu_vendor,actions}.post.php
schemas/permissions/{admin,vendor_multivendor}.post.php
Tygh/Addons/KvProductQuestionsAnswers/*.php
design/backend/templates/addons/kv_product_questions_answers/{views,components,settings,license,hooks}/
design/backend/css/addons/kv_product_questions_answers/{styles,license}.less
var/themes_repository/responsive/templates/addons/kv_product_questions_answers/
blocks/product_tabs/kv_pqa.tpl blocks/{latest_questions,product_questions}.tpl
components/{qa,list}.tpl views/kv_product_questions_answers/{ask_form,answer_form,list}.tpl
hooks/products/main_info_title.post.tpl hooks/index/{meta,styles,scripts}.post.tpl
var/themes_repository/responsive/css/addons/kv_product_questions_answers/styles.less
js/addons/kv_product_questions_answers/func.js
var/langs/en/addons/kv_product_questions_answers.po

Storefront CSS is scoped under .kv-pqa*; templates and styles ship for the Responsive theme and reach Bright, Nova and other child themes by inheritance.