Skip to content

Developer notes

Overview · Installation · Configuration · Usage · FAQ

The add-on never modifies core files. It uses PHP hooks, its own controllers, a template hook at checkout, .post schemas and three e-mail templates.

Table Content
?:kv_rre_requests One row per request: order, company (vendor in MV, storefront company in Ultimate), storefront, customer, language, status (Q scheduled, S sent, R reminded, D reviewed, C cancelled, U unsubscribed, F failed, X skipped) and reason, 40-character random token, test flag, send/sent/reminded/opened/clicked/reviewed times and counters, reward state (P waiting, A active, U used, E expired), coupon code, promotion, expiry, last error
?:kv_rre_items Products of a request: product, vendor, name, review source (P product_reviews, D discussion, X another add-on), review id, rating, moderation state (D pending, A approved, X deleted), reviewed and clicked times
?:kv_rre_contacts Consent per e-mail address: N unsubscribed / unticked at checkout, Y opted in
?:kv_rre_exclusions Excluded categories (C), products (P), user groups (G) and vendors (V) per storefront company (0 = all)

Run marks (last run, lock, last purge, last errors) use the add-on’s StorageData class: ?:storage_data, or files in var/kv_storage/kv_review_request_emails/ while the full page cache is active.

Hook Where (4.21.2 / 4.17.2) What the add-on does
change_order_status_post fn.cart.php 3038 / 2911 Queues the request of an order that reached a trigger status (child orders only in MV). One INSERT, errors are caught.
place_order fn.cart.php 1678 / 1585 Stores the checkout checkbox for the order’s e-mail.
place_order_post fn.cart.php 1725 / 1632 Marks reward codes used in the order and withdraws them from the promotion.
product_reviews_create_post product_reviews Repository.php 410 / 410 Counts reviews written elsewhere (product page, other add-ons) for a matching request.
add_discussion_post_post discussion func.php 706 / 706 The same for Comments and reviews.
mailer_send_pre Mailer.php 240 / 240 Adds the open-tracking pixel after the core built the message (the core downloads and embeds every image of a message; a pixel in the template would be fetched by the server and counted as an open).
delete_order, delete_user Remove the requests of deleted orders and customers.
before_dispatch Admin fallback run (shutdown, at most every 10 minutes).
init_templater_post Only while an upgrade synchronization is pending.

All arguments are identical in 4.17.2 and 4.21.2.

Dispatch Area Purpose
kv_review_request_emails.review?t=TOKEN[&p=PRODUCT&r=1-5] storefront Review page; POST (CSRF-validated) saves one review
kv_review_request_emails.go?t=TOKEN&p=PRODUCT storefront Counts the click and redirects to the product’s reviews tab (“product page” mode)
kv_review_request_emails.open?t=TOKEN storefront 1×1 GIF, counts the open
kv_review_request_emails.unsubscribe?t=TOKEN&h=SIGNATURE storefront Confirmation page; POST (CSRF-validated) unsubscribes or subscribes again
kv_review_request_emails.cron?key=KEY storefront Cron URL (JSON summary)
kv_review_request_emails.dashboard / manage / view / preview / exclusions admin, vendor Admin pages (vendors: dashboard, manage, view, preview of their own requests)
admin.php --dispatch=kv_review_request_emails.cron console Cron command
admin.php --dispatch=kv_review_request_emails_license.check console License check

The token is 20 random bytes (hex). It is the credential of the review page: whoever has the e-mail can review the products of that order, nothing else. The unsubscribe link carries an additional HMAC signature.

Reviews are created through the store’s own review system:

  • Product reviews: Service::prepareReviewData() → Repository::create() (fires product_reviews_create_post for other add-ons) → actualizeProductPreparedData() → the core product_reviews.new_post notification. is_buyer is Y (the signed request proves the purchase, also for guests); the status follows the core Review approval setting.
  • Comments and reviews: fn_add_discussion_post() for product threads of type Rating or Communication and rating.

The moderation state of pending reviews is re-read by every queue run, so approving a review in Products → Product reviews releases a waiting reward without any hook.

Other add-ons (for example Kavio Labs Photo & Video Reviews) can plug in without changing this add-on:

  • Template hooks on the review page: kv_review_request_emails:review_item inside each product form (the form is multipart/form-data; variables $kv_rre_item with product_id, name, selected, preset, and $kv_page.token) and kv_review_request_emails:review_page after the cards. Fields added there are posted with the review; since the review is created through the core repository, a handler of product_reviews_create_post sees them in $_REQUEST / $_FILES.
  • PHP hook kv_review_request_emails_review_url ($request, $item, $rating, &$url): change the link of each star (and of the product name) in the e-mails, for example to an add-on’s own review form. Keep the token in the URL.
  • Reviews stored in an add-on’s own tables: call
    if (function_exists('fn_kv_review_request_emails_register_review')) {
    fn_kv_review_request_emails_register_review($product_id, $user_id, $email, $review_id, $rating, $approved);
    }
    It finds the customer’s latest sent request for that product and counts the review (statistics, reminder stop, reward). Reviews stored in core ?:product_reviews need no call.

The add-on prints nothing on cacheable pages (home, categories, products, pages). Its storefront output is limited to its own dispatches and the checkout, which the full page cache never stores. Opens and clicks write only to the add-on’s tables, which schemas/full_page_cache/varnish.post.php adds to ignore_cache_tags, so they never purge cached pages; run marks use StorageData (no ?:storage_data writes from storefront requests). Saving a review writes ?:product_reviews like the core form, which refreshes the product’s cached page as intended.

Tygh\Addons\KvReviewRequestEmails\License\Client (generated) verifies the license. Gate points (fn_kv_review_request_emails_is_licensed() / …_is_licensed_for_storefront(), wrapped by Gate in class code):

  • queueing in change_order_status_post (per storefront host in Ultimate),
  • sending requests and reminders in Sender::run() and sendNow(), test e-mails and “queue past orders”,
  • the checkout checkbox.

Not gated (they complete what an e-mail already sent asked for): the review page and saving reviews, the click redirect and open pixel, unsubscribe, reward e-mails customers already earned, the admin pages and data.

A development store can capture the e-mails as files instead of sending them: define KV_REVIEW_REQUEST_EMAILS_MAIL_CAPTURE_DIR (an existing directory) in local_conf.php. The add-on then passes its own file transport to the core mailer for its e-mails only. Never define it on a live store.

Path Purpose
app/addons/kv_review_request_emails/addon.xml Settings, tables, e-mail templates
init.php, func.php Hook registration and handlers, install/uninstall, settings info handlers, public API
Tygh/Addons/KvReviewRequestEmails/Config.php Settings (per storefront in Ultimate) and constants
Queue.php Queueing, eligibility, “queue past orders”, test requests
Sender.php Queue runner: requests, reminders, approvals, rewards, purge
Emails.php, MailCapture.php Template variables, sending, previews, pixel, development capture
Reviews.php, Flow.php, ReviewPage.php Review backends, opens/clicks/reviews/attribution, review page data
Coupons.php Reward codes in auto-coupon promotions
Stats.php, Repository.php, Links.php, Gate.php, Logger.php, StorageData.php Statistics, data access, signed links, license gate, error log, run marks
License/Client.php, License/Ed25519.php, controllers/backend/kv_review_request_emails_license.php License check (generated)
Upgrade/Synchronizer.php Self-healing upgrades (generated)
controllers/backend/kv_review_request_emails.php Admin and vendor pages
controllers/frontend/kv_review_request_emails.php, checkout.pre.php, checkout.post.php Storefront pages, checkout checkbox
schemas/ Menu, permissions (admin, vendor), CSRF, GDPR, full page cache, settings variants
design/backend/templates/addons/kv_review_request_emails/ Admin templates, license card/bar/badge (license/info.tpl for the License tab)
var/themes_repository/responsive/templates/addons/kv_review_request_emails/ Review page, unsubscribe page, checkout checkbox