Skip to content

Developer notes

Overview · Installation · Configuration · Usage · FAQ

Auditor::check($product_ids) reads a batch of products with a few queries (product row, descriptions in the audited language, base price, category links, image pairs with sizes and alt texts, SEO names, variation groups, feature values) and returns the issues per product plus three fingerprints: an MD5 of the normalized name, the product code and an MD5 of the plain-text description (30 characters and more). Image files are checked through Storage::instance('images')->isExist(), so remote storage works too.

Store::saveResults() replaces the product’s row and issues. Duplicates are computed afterwards from the fingerprints, within the same company (Store::refreshDuplicates(), one INSERT ... SELECT ... GROUP BY per rule), for the whole catalog at the end of a scan or only for the fingerprints a re-checked product had before and after. Scores are recomputed in SQL from the open issues: 100 - 20 x critical - 8 x warning - 3 x notice, at least 0.

Scanner::start($company_id) creates a scan (0 = whole catalog). Scanner::step($scan_id, $seconds) takes an atomic lock on the scan row (lock_until), checks batches by product ID cursor until the time budget is used, and on the last batch removes rows of products that no longer exist or are no longer audited, rebuilds the duplicates and scores and writes the history points (scope A = all, C = per company, one per day). “Scan now” calls scan_step over AJAX until the scan is done; the cron calls the same code.

Hook Use
update_product_post Re-check after a save (at the end of the request, 25 inline, the rest queued). Minimum score: a vendor product saved as Active is checked at once and set to Disabled below the minimum.
tools_update_status_before_query Minimum score: keeps the old status when a vendor switches a low-score product to Active.
tools_change_status Re-check after a status change in a list.
update_product_amount Stock change: product queued for the cron (never checked during checkout).
delete_product_post Results and ignored issues of a deleted product removed; its duplicates refreshed.
delete_company Results and history of a deleted vendor or storefront removed.

All hook signatures are identical in 4.17.2 and 4.21.2.

Table Content
?:kv_cqa_products One row per audited product: company, main category, status, score, issue counts, fingerprints, check time
?:kv_cqa_issues One row per product and rule: severity, details (JSON), company, category, ignored
?:kv_cqa_ignores Ignored issues (kept across checks)
?:kv_cqa_scans Scans with cursor, counters, lock and status
?:kv_cqa_history Daily score points for the whole catalog and per company
?:kv_cqa_queue Products waiting for a re-check
?:kv_cqa_meta The rule set (JSON) and the last digest time

No ?:storage_data writes.

The admin permission schema maps the controller to view_catalog (GET) and manage_catalog (POST; the Rules page needs manage_catalog). The vendor schema allows the controller only when Vendors see their catalog quality is on and never the Rules page, the test digest or the cron mode. Every query is limited by runtime.company_id; changes check the ownership of each product (Access::ownProducts()).

The add-on has no storefront output. The cron URL is a non-cacheable JSON dispatch (Cache-Control: no-store).

See License. The gate is Access::licensed(): Scan now, scan steps, the cron (scans, queue, digest), the inline re-check after saves (without a license products are only queued), bulk fixes and the minimum-score rule. The dashboard, the issue list, ignore/restore and the CSV export keep working.

The rule definitions are in Config::definitions(); a new rule needs a check in Auditor::check(), a group and the language variables rule_<key>, rule_desc_<key> and optionally detail_<key>.

Path Purpose
app/addons/kv_catalog_quality_audit/addon.xml, init.php, func.php Scheme, settings, tables, digest e-mail template, hooks, settings info
controllers/backend/kv_catalog_quality_audit.php Dashboard, issues, rules, export, scan endpoints (JSON), ignore, fixes, console cron
controllers/frontend/kv_catalog_quality_audit.php Cron URL
Tygh/Addons/KvCatalogQualityAudit/Auditor.php The checks
.../Store.php Tables: results, duplicates, scores, history, queue, dashboard and list queries
.../Scanner.php Scans, re-checks, queue, cron
.../Fixer.php Bulk fixes and meta templates
.../Digest.php Weekly e-mail
.../Config.php, Access.php Rules, settings, scoping, license gate
.../License/*, controllers/backend/kv_catalog_quality_audit_license.php License client and “Check now”
.../Upgrade/Synchronizer.php Self-healing upgrades
schemas/permissions/*, schemas/menu/* Privileges, vendor access, menu
design/backend/templates/addons/kv_catalog_quality_audit/ Dashboard, issue list, rules, components, license UI
js/addons/kv_catalog_quality_audit/admin.js, design/backend/css/addons/kv_catalog_quality_audit/ Admin script and styles
var/langs/en/addons/kv_catalog_quality_audit.po Language variables