The problem this solves
Earlier versions inserted app reviews as bare WordPress comments with wp_insert_comment(). That call does not fire comment_post, the hook GeoDirectory and WooCommerce listen on to recompute their rating aggregates — so app reviews became orphans: stored, but invisible to native averages and to the website. The web and the app disagreed about a listing’s rating.
The provider model fixes this by making one rule absolute: core never touches review storage directly. It resolves exactly one provider per post and delegates every read and write to it. The provider knows the post type’s native store and writes through the native path (so aggregates recompute). The result is read/write symmetry — what the app shows and what the app saves are the same data the website shows and saves.
The pieces
mam-reviews-manager (core orchestrator)
├─ envelope: auth, rate-limit, photos, tips, payload decode (ajax-handler.php)
├─ sections: reviews_header / reviews / add_review (content-sections.php)
└─ provider registry + resolution (class-mam-reviews-provider-registry.php)
resolves ONE provider per post ↓
┌──────────────────┬──────────────────────┬─────────────────────┐
▼ ▼ ▼
GD provider Woo provider Default provider
(mam-geodirectory)(mam-woocommerce) (mam-reviews-manager, built in)
wp_geodir_post_review comment_type 'review' wp_comments + 'rating' meta
+ rating categories + _wc_average_rating single-star
MULTI-CRITERIA single-star
MAM_Reviews_Provider(interface-mam-reviews-provider.php) — the contract:supports(),get_criteria(),get_aggregates(),get_reviews(),get_user_review(),save_review(),get_all_reviews().MAM_Reviews_Provider_Base(abstract-mam-reviews-provider-base.php) — shared helpers: theoverallcriterion, reviewer-name formatting, photo loading, the defaultget_all_reviews()loop. Concrete providers implement only the storage-specific reads and writes.MAM_Reviews_Provider_Registry— collects providers from themam_reviews_providersfilter and resolves one per post.mam_reviews_provider_for( int $post_id ): MAM_Reviews_Provider— the helper everything calls to get the owning provider.
Resolution
- Core resolves
$post_type = get_post_type( $post_id ). - It walks registered providers by descending priority.
- The first provider whose
supports( $post_id, $post_type )returnstruewins. - The default provider registers at priority
0and supports everything — so there is always exactly one match.
Resolution is memoized per request per post id. Registration is lazy/booted once on first resolution, so sibling-plugin providers (loaded later) are all present.
| Provider | Registered by | Priority | Owns |
|---|---|---|---|
mam_gd_reviews_provider |
mam-geodirectory | 20 | GD post types with ratings enabled |
mam_wc_reviews_provider |
mam-woocommerce | 20 | product post type |
mam_reviews_default_provider |
mam-reviews-manager | 0 | everything else (fallback) |
To add your own (e.g. a bespoke post type), register on the filter — see Hook: mam_reviews_providers.
Where the rating data actually lives
If you’re building a feature that consumes ratings (recommendations, “my ratings”, analytics), prefer reading through the provider so you stay storage-agnostic:
$provider = mam_reviews_provider_for( $post_id );
$aggregates = $provider->get_aggregates( $post_id ); // average, count, distribution, per-criterion
$reviews = $provider->get_reviews( $post_id ); // normalized list
$mine = $provider->get_user_review( $post_id, $user_id );
$criteria = $provider->get_criteria( $post_id );
If you need the raw native store directly, this is where each provider keeps it:
| Store | GeoDirectory | WooCommerce | Default |
|---|---|---|---|
| Per-review row | wp_geodir_post_review (rating overall + serialized ratings multi-criteria) |
comment with comment_type = 'review' + rating comment meta |
comment + rating comment meta |
| Overall average | geodir_get_post_rating() |
_wc_average_rating postmeta |
computed from rating meta |
| Count | geodir_get_review_count_total() |
_wc_review_count postmeta |
count of rated comments |
| Distribution | GeoDir_Comments::get_post_review_rating_counts() |
_wc_rating_count postmeta |
computed |
| Criteria config | geodir_reviewrating_rating_categories() (Review Rating Manager) |
n/a | n/a |
The write path (why it stays native)
save_review() must write so native aggregates update. The providers do this by reconstructing the request the native handler expects and submitting through wp_new_comment() (which fires comment_post), not wp_insert_comment():
- GeoDirectory populates
$_REQUEST/$_POST['geodir_overallrating'],['geodir_rating'](multi-criteria), and['comment_images'], sets the global$user_ID, guardspre_comment_approved/wp_is_comment_flood, then callswp_new_comment()soGeoDir_Comments::save_rating()runs. It temporarily removes GeoDirectory’s Dynamic Emailscomment_postaction around the insert so app submissions don’t trigger the “your comment was approved” email, then restores it. - WooCommerce inserts a
comment_type = 'review'comment withratingmeta and lets WooCommerce recompute_wc_average_rating/_wc_review_count/_wc_rating_count.
Each provider also ships a backfill_orphans() routine; the one-time migration uses these to fold pre-existing orphaned app comments into the native stores.
Hooks to consume after a rating is recorded
| Hook | When | Args |
|---|---|---|
mam_reviews_review_submitted |
after any full review is saved | $payload, $submission, $result |
mam_reviews_swipe_submitted |
after a swipe rating | $swipe, $result |
mam_reviews_add_vendor_review |
after a shop_order review (vendor/tips) |
$payload |
See the individual hook pages for contracts and examples.
Back-compat
The pre-refactor read filters (mam_reviews_get_reviews_for_post, mam_reviews_has_user_commented_on_post, mam_reviews_get_all_reviews_array, and the mam_content_section_* builders) are retained as thin shims that call the resolved provider, so existing external consumers keep working unchanged.
Related articles
- Plugin: mam-reviews-manager
- Hook:
mam_reviews_providers - Hook:
mam_reviews_review_submitted - Hook:
mam_reviews_swipe_submitted - Reviews content sections
Metadata
| Field | Value |
|---|---|
| Article type | Integration / Architecture |
| Plugin slug | mam-reviews-manager |
| Applies to plugin version | 26.23.0+ |
| Category | Extending MAM Suite |
| Audience | PHP developer |
| Last verified | 2026-06-04 |
