Rentiva v4.34.0 — Popular Transfer Routes Showcase
The homepage now has a proper sales surface for VIP transfer routes. v4.34.0 ships a [rentiva_popular_routes] shortcode + Gutenberg block + Elementor widget — three surfaces sharing one canonical renderer — that show A → B route cards (origin → destination, average duration, distance, starting price) with an admin "🌟 Vitrine Koy" pin checkbox to control which routes appear.
Why this release exists
Rentiva's transfer module has been quietly capable for months: vendors set per-route pricing, the search engine joins endpoints with vehicle eligibility, the cart honors fixed and per-km pricing methods. But the homepage didn't surface any of that. A visitor landing on the rental marketplace had to dig into the search form to discover that VIP transfer was even on offer, let alone what it costs.
v4.34.0 closes that gap. The new section sits on the landing page, shows the strongest routes pinned first, and answers the only question a transfer customer actually asks before clicking "Book": how much, how long, how far?
What's in the release
[rentiva_popular_routes] — three surfaces, one renderer
The shortcode is the canonical implementation. The Gutenberg block (mhm-rentiva/popular-routes) and the Elementor widget (mhm_rentiva_popular_routes) both delegate to it via do_shortcode(), which is Rentiva's render-parity contract: whatever you can render with a shortcode renders identically through any of the three surfaces. No drift, no double codepath.
The shortcode supports 16 attributes:
| Attribute | Default | Purpose |
|---|---|---|
limit | 6 | Max cards (capped to Mode::maxTransferRoutes() on Lite plans) |
columns | 3 | Desktop grid columns (2/3/4) |
order | featured | featured / price_asc / price_desc / alphabetical / newest |
heading | "Popular Routes" | Section title (i18n) |
subheading | "Most preferred VIP transfer routes" | Section subtitle |
show_view_all | true | Show the "View all" link in the header |
view_all_url | empty | Override the link target (else uses the mhm_rentiva_popular_routes_view_all_url filter) |
show_duration / show_distance / show_traffic_note / show_price | true | Per-element visibility toggles |
currency_symbol | ₺ | Price prefix |
filter_origin_city | empty | e.g. Istanbul |
filter_origin_type | empty | airport / train / hotel / marina / city_center |
featured_only | false | When true, render only pinned routes |
theme | light | light / dark |
Admin "🌟 Vitrine Koy" checkbox
The Transfer Routes admin form gets a new checkbox: 🌟 Vitrine Koy (popüler rotalar bloğuna sabitle). Pinned routes appear first when order="featured" (the default) and exclusively when featured_only="true". The route list table shows a "🌟 Showcase" badge next to pinned rows so admins can scan-verify what the homepage will render.
Save and delete actions automatically invalidate the TransferRouteProvider transient cache, so changes go live on the next page request without any cache-clearing dance.
TransferRouteProvider repository
A new single-source-of-truth class for popular-route queries, modeled after the existing LocationProvider pattern: 1-hour transient cache, JOIN-based eligibility filter (origin and destination must both be is_active=1 AND allow_transfer=1), composable filter set (city / type / featured-only). Cache keys hash the full filter set so distinct shortcode invocations don't share cache.
TransferRouteProvider::get_popular_routes([
'limit' => 6,
'order' => 'featured',
'featured_only' => false,
'filter_origin_city' => 'Istanbul',
'filter_origin_type' => 'airport',
]);
Rows come back as objects with origin/destination data already joined: origin_name, origin_city, origin_type, destination_name, destination_city, destination_type, plus all the route columns (distance_km, duration_min, min_price, is_featured, etc.).
Database migration
{prefix}rentiva_transfer_routes gains an is_featured tinyint(1) NOT NULL DEFAULT 0 column with an index. The migration uses dbDelta and is idempotent — existing installations upgrade in place with no downtime, and re-running the migration on a current schema is a no-op.
Lite vs Pro
Lite plans render up to 3 cards. This is enforced through the existing Mode::maxTransferRoutes() quota — the same one that already caps how many routes a Lite admin can define. Pro plans render up to the configured limit (default 6). The shortcode's resolve_limit() is min($requested, $tier_max), so a limit="20" attribute on a Lite site quietly clamps to 3 instead of erroring.
Empty state
Silent no-op. When zero routes match the filters (or the routes table is empty, or all eligible endpoints are inactive), the section doesn't render at all — no "Coming soon..." placeholder, no empty grid, no console noise. New installations look clean; populated sites surface what they have.
Two filter hooks
// Themes/integrations supply the transfer-search URL when no
// explicit view_all_url is set.
add_filter('mhm_rentiva_popular_routes_view_all_url', function ($url) {
return home_url('/transfer/');
});
// Override the icon shown for a given location type.
add_filter('mhm_rentiva_popular_routes_type_icon', function ($icon, $type) {
return $type === 'airport' ? '🛫' : $icon;
}, 10, 2);
Tests and quality gates
- PHPUnit: 824 → 837 (+13). New tests cover empty state, single/multi-card render, origin city + origin type filters, featured ordering (pinned-first), price-ascending sort, hidden routes for inactive endpoints, duration/distance/price visibility flags, and the invalid
columnsfallback. - PHPCS: 0 errors.
composer phpcsclean across all changed files. - SchemaParityTest: Bumped to 20 block.json files, validated end-to-end (block attribute names round-trip through
AllowlistRegistryto canonical shortcode attributes). - i18n: 35+ new TR strings — frontend card labels (Popüler Rotalar, Yaklaşık X dk, Trafiğe göre değişebilir, Başlangıç fiyatı), admin form (🌟 Vitrine Koy), full block + widget editor controls (Sorting & Filters, Card Display panels).
.potregenerated,tr_TR.pomsgmerged,.moand.l10n.phprecompiled. - Runtime smoke test: Real admin → frontend round-trip via Chrome DevTools MCP. Edit form checkbox, save, navigate to a page rendering the shortcode, verify all 6 cards (4 featured pinned first), TR translations correct, CSS loaded, zero console errors.
What's next
The roadmap continues with the transfer wave: v4.36.0 adds context-aware add-ons (extending the existing vehicle_addon CPT with an addon_context taxonomy), v4.37.0 adds a transfer-locations map view (porting pinning code from another project). After that the vendor wave picks up — directory page (v4.38.0) and the long-deferred Phase 5 vendor public profile (v4.39.0).
