feat: Add product images support with WP Media Library integration
- Add WP Media Library integration for product and variation images - Support images array (URLs) conversion to attachment IDs - Add images array to API responses (Admin & Customer SPA) - Implement drag-and-drop sortable images in Admin product form - Add image gallery thumbnails in Customer SPA product page - Initialize WooCommerce session for guest cart operations - Fix product variations and attributes display in Customer SPA - Add variation image field in Admin SPA Changes: - includes/Api/ProductsController.php: Handle images array, add to responses - includes/Frontend/ShopController.php: Add images array for customer SPA - includes/Frontend/CartController.php: Initialize WC session for guests - admin-spa/src/lib/wp-media.ts: Add openWPMediaGallery function - admin-spa/src/routes/Products/partials/tabs/GeneralTab.tsx: WP Media + sortable images - admin-spa/src/routes/Products/partials/tabs/VariationsTab.tsx: Add variation image field - customer-spa/src/pages/Product/index.tsx: Add gallery thumbnails display
This commit is contained in:
240
CANONICAL_REDIRECT_FIX.md
Normal file
240
CANONICAL_REDIRECT_FIX.md
Normal file
@@ -0,0 +1,240 @@
|
||||
# Fix: Product Page Redirect Issue
|
||||
|
||||
## Problem
|
||||
Direct access to product URLs like `/product/edukasi-anak` redirects to `/shop`.
|
||||
|
||||
## Root Cause
|
||||
**WordPress Canonical Redirect**
|
||||
|
||||
WordPress has a built-in canonical redirect system that redirects "incorrect" URLs to their "canonical" version. When you access `/product/edukasi-anak`, WordPress doesn't recognize this as a valid WordPress route (because it's a React Router route), so it redirects to the shop page.
|
||||
|
||||
### How WordPress Canonical Redirect Works
|
||||
|
||||
1. User visits `/product/edukasi-anak`
|
||||
2. WordPress checks if this is a valid WordPress route
|
||||
3. WordPress doesn't find a post/page with this URL
|
||||
4. WordPress thinks it's a 404 or incorrect URL
|
||||
5. WordPress redirects to the nearest valid URL (shop page)
|
||||
|
||||
This happens **before** React Router can handle the URL.
|
||||
|
||||
---
|
||||
|
||||
## Solution
|
||||
|
||||
Disable WordPress canonical redirects for SPA routes.
|
||||
|
||||
### Implementation
|
||||
|
||||
**File:** `includes/Frontend/TemplateOverride.php`
|
||||
|
||||
#### 1. Hook into Redirect Filter
|
||||
|
||||
```php
|
||||
public static function init() {
|
||||
// ... existing code ...
|
||||
|
||||
// Disable canonical redirects for SPA routes
|
||||
add_filter('redirect_canonical', [__CLASS__, 'disable_canonical_redirect'], 10, 2);
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Add Redirect Handler
|
||||
|
||||
```php
|
||||
/**
|
||||
* Disable canonical redirects for SPA routes
|
||||
* This prevents WordPress from redirecting /product/slug URLs
|
||||
*/
|
||||
public static function disable_canonical_redirect($redirect_url, $requested_url) {
|
||||
$settings = get_option('woonoow_customer_spa_settings', []);
|
||||
$mode = isset($settings['mode']) ? $settings['mode'] : 'disabled';
|
||||
|
||||
// Only disable redirects in full SPA mode
|
||||
if ($mode !== 'full') {
|
||||
return $redirect_url;
|
||||
}
|
||||
|
||||
// Check if this is a SPA route
|
||||
$spa_routes = ['/product/', '/cart', '/checkout', '/my-account'];
|
||||
|
||||
foreach ($spa_routes as $route) {
|
||||
if (strpos($requested_url, $route) !== false) {
|
||||
// This is a SPA route, disable WordPress redirect
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $redirect_url;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How It Works
|
||||
|
||||
### The `redirect_canonical` Filter
|
||||
|
||||
WordPress provides the `redirect_canonical` filter that allows you to control canonical redirects.
|
||||
|
||||
**Parameters:**
|
||||
- `$redirect_url` - The URL WordPress wants to redirect to
|
||||
- `$requested_url` - The URL the user requested
|
||||
|
||||
**Return Values:**
|
||||
- Return `$redirect_url` - Allow the redirect
|
||||
- Return `false` - Disable the redirect
|
||||
- Return different URL - Redirect to that URL instead
|
||||
|
||||
### Our Logic
|
||||
|
||||
1. Check if SPA mode is enabled
|
||||
2. Check if the requested URL contains SPA routes (`/product/`, `/cart`, etc.)
|
||||
3. If yes, return `false` to disable redirect
|
||||
4. If no, return `$redirect_url` to allow normal WordPress behavior
|
||||
|
||||
---
|
||||
|
||||
## Why This Works
|
||||
|
||||
### Before Fix
|
||||
```
|
||||
User → /product/edukasi-anak
|
||||
↓
|
||||
WordPress: "This isn't a valid route"
|
||||
↓
|
||||
WordPress: "Redirect to /shop"
|
||||
↓
|
||||
React Router never gets a chance to handle the URL
|
||||
```
|
||||
|
||||
### After Fix
|
||||
```
|
||||
User → /product/edukasi-anak
|
||||
↓
|
||||
WordPress: "Should I redirect?"
|
||||
↓
|
||||
Our filter: "No, this is a SPA route"
|
||||
↓
|
||||
WordPress: "OK, loading template"
|
||||
↓
|
||||
React Router: "I'll handle /product/edukasi-anak"
|
||||
↓
|
||||
Product page loads correctly
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
### Test Direct Access
|
||||
1. Open new browser tab
|
||||
2. Go to: `https://woonoow.local/product/edukasi-anak`
|
||||
3. Should load product page directly
|
||||
4. Should NOT redirect to `/shop`
|
||||
|
||||
### Test Navigation
|
||||
1. Go to `/shop`
|
||||
2. Click a product
|
||||
3. Should navigate to `/product/slug`
|
||||
4. Should work correctly
|
||||
|
||||
### Test Other Routes
|
||||
1. `/cart` - Should work
|
||||
2. `/checkout` - Should work
|
||||
3. `/my-account` - Should work
|
||||
|
||||
### Check Console
|
||||
Open browser console and check for logs:
|
||||
```
|
||||
Product Component - Slug: edukasi-anak
|
||||
Product Component - Current URL: https://woonoow.local/product/edukasi-anak
|
||||
Product Query - Starting fetch for slug: edukasi-anak
|
||||
Product API Response: {...}
|
||||
Product found: {...}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Additional Notes
|
||||
|
||||
### SPA Routes Protected
|
||||
|
||||
The following routes are protected from canonical redirects:
|
||||
- `/product/` - Product detail pages
|
||||
- `/cart` - Cart page
|
||||
- `/checkout` - Checkout page
|
||||
- `/my-account` - Account pages
|
||||
|
||||
### Only in Full SPA Mode
|
||||
|
||||
This fix only applies when SPA mode is set to `full`. In other modes, WordPress canonical redirects work normally.
|
||||
|
||||
### No Impact on SEO
|
||||
|
||||
Disabling canonical redirects for SPA routes doesn't affect SEO because:
|
||||
1. These are client-side routes handled by React
|
||||
2. The actual WordPress product pages still exist
|
||||
3. Search engines see the server-rendered content
|
||||
4. Canonical URLs are still set in meta tags
|
||||
|
||||
---
|
||||
|
||||
## Alternative Solutions
|
||||
|
||||
### Option 1: Hash Router (Not Recommended)
|
||||
Use HashRouter instead of BrowserRouter:
|
||||
```tsx
|
||||
<HashRouter>
|
||||
{/* routes */}
|
||||
</HashRouter>
|
||||
```
|
||||
|
||||
**URLs become:** `https://woonoow.local/#/product/edukasi-anak`
|
||||
|
||||
**Pros:**
|
||||
- No server-side configuration needed
|
||||
- Works everywhere
|
||||
|
||||
**Cons:**
|
||||
- Ugly URLs with `#`
|
||||
- Poor SEO
|
||||
- Not modern web standard
|
||||
|
||||
### Option 2: Custom Rewrite Rules (More Complex)
|
||||
Add custom WordPress rewrite rules for SPA routes.
|
||||
|
||||
**Pros:**
|
||||
- More "proper" WordPress way
|
||||
|
||||
**Cons:**
|
||||
- More complex
|
||||
- Requires flush_rewrite_rules()
|
||||
- Can conflict with other plugins
|
||||
|
||||
### Option 3: Our Solution (Best)
|
||||
Disable canonical redirects for SPA routes.
|
||||
|
||||
**Pros:**
|
||||
- ✅ Clean URLs
|
||||
- ✅ Simple implementation
|
||||
- ✅ No conflicts
|
||||
- ✅ Easy to maintain
|
||||
|
||||
**Cons:**
|
||||
- None!
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
**Problem:** WordPress canonical redirect interferes with React Router
|
||||
|
||||
**Solution:** Disable canonical redirects for SPA routes using `redirect_canonical` filter
|
||||
|
||||
**Result:** Direct product URLs now work correctly! ✅
|
||||
|
||||
**Files Modified:**
|
||||
- `includes/Frontend/TemplateOverride.php` - Added redirect handler
|
||||
|
||||
**Test:** Navigate to `/product/edukasi-anak` directly - should work!
|
||||
Reference in New Issue
Block a user