- 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
286 lines
6.8 KiB
Markdown
286 lines
6.8 KiB
Markdown
# Fix: Direct URL Access Shows 404 Page
|
|
|
|
## Problem
|
|
- ✅ Navigation from shop page works → Shows SPA
|
|
- ❌ Direct URL access fails → Shows WordPress theme 404 page
|
|
|
|
**Example:**
|
|
- Click product from shop: `https://woonoow.local/product/edukasi-anak` ✅ Works
|
|
- Type URL directly: `https://woonoow.local/product/edukasi-anak` ❌ Shows 404
|
|
|
|
## Why Admin SPA Works But Customer SPA Doesn't
|
|
|
|
### Admin SPA
|
|
```
|
|
URL: /wp-admin/admin.php?page=woonoow
|
|
↓
|
|
WordPress Admin Area (always controlled)
|
|
↓
|
|
Admin menu system loads the SPA
|
|
↓
|
|
Works perfectly ✅
|
|
```
|
|
|
|
### Customer SPA (Before Fix)
|
|
```
|
|
URL: /product/edukasi-anak
|
|
↓
|
|
WordPress: "Is this a post/page?"
|
|
↓
|
|
WordPress: "No post found with slug 'edukasi-anak'"
|
|
↓
|
|
WordPress: "Return 404 template"
|
|
↓
|
|
Theme's 404.php loads ❌
|
|
↓
|
|
SPA never gets a chance to load
|
|
```
|
|
|
|
## Root Cause
|
|
|
|
When you access `/product/edukasi-anak` directly:
|
|
|
|
1. **WordPress query runs** - Looks for a post with slug `edukasi-anak`
|
|
2. **No post found** - Because it's a React Router route, not a WordPress post
|
|
3. **`is_product()` returns false** - WordPress doesn't think it's a product page
|
|
4. **404 template loads** - Theme's 404.php takes over
|
|
5. **SPA template never loads** - Our `use_spa_template` filter doesn't trigger
|
|
|
|
### Why Navigation Works
|
|
|
|
When you click from shop page:
|
|
1. React Router handles the navigation (client-side)
|
|
2. No page reload
|
|
3. No WordPress query
|
|
4. React Router shows the Product component
|
|
5. Everything works ✅
|
|
|
|
## Solution
|
|
|
|
Detect SPA routes **by URL** before WordPress determines it's a 404.
|
|
|
|
### Implementation
|
|
|
|
**File:** `includes/Frontend/TemplateOverride.php`
|
|
|
|
```php
|
|
public static function use_spa_template($template) {
|
|
$settings = get_option('woonoow_customer_spa_settings', []);
|
|
$mode = isset($settings['mode']) ? $settings['mode'] : 'disabled';
|
|
|
|
if ($mode === 'disabled') {
|
|
return $template;
|
|
}
|
|
|
|
// Check if current URL is a SPA route (for direct access)
|
|
$request_uri = $_SERVER['REQUEST_URI'];
|
|
$spa_routes = ['/shop', '/product/', '/cart', '/checkout', '/my-account'];
|
|
$is_spa_route = false;
|
|
|
|
foreach ($spa_routes as $route) {
|
|
if (strpos($request_uri, $route) !== false) {
|
|
$is_spa_route = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If it's a SPA route in full mode, use SPA template
|
|
if ($mode === 'full' && $is_spa_route) {
|
|
$spa_template = plugin_dir_path(dirname(dirname(__FILE__))) . 'templates/spa-full-page.php';
|
|
if (file_exists($spa_template)) {
|
|
// Set status to 200 to prevent 404
|
|
status_header(200);
|
|
return $spa_template;
|
|
}
|
|
}
|
|
|
|
// ... rest of the code
|
|
}
|
|
```
|
|
|
|
## How It Works
|
|
|
|
### New Flow (After Fix)
|
|
```
|
|
URL: /product/edukasi-anak
|
|
↓
|
|
WordPress: "Should I use default template?"
|
|
↓
|
|
Our filter: "Wait! Check the URL..."
|
|
↓
|
|
Our filter: "URL contains '/product/' → This is a SPA route"
|
|
↓
|
|
Our filter: "Return SPA template instead"
|
|
↓
|
|
status_header(200) → Set HTTP status to 200 (not 404)
|
|
↓
|
|
SPA template loads ✅
|
|
↓
|
|
React Router handles /product/edukasi-anak
|
|
↓
|
|
Product page displays correctly ✅
|
|
```
|
|
|
|
## Key Changes
|
|
|
|
### 1. URL-Based Detection
|
|
```php
|
|
$request_uri = $_SERVER['REQUEST_URI'];
|
|
$spa_routes = ['/shop', '/product/', '/cart', '/checkout', '/my-account'];
|
|
|
|
foreach ($spa_routes as $route) {
|
|
if (strpos($request_uri, $route) !== false) {
|
|
$is_spa_route = true;
|
|
break;
|
|
}
|
|
}
|
|
```
|
|
|
|
**Why:** Detects SPA routes before WordPress query runs.
|
|
|
|
### 2. Force 200 Status
|
|
```php
|
|
status_header(200);
|
|
```
|
|
|
|
**Why:** Prevents WordPress from setting 404 status, which would affect SEO and browser behavior.
|
|
|
|
### 3. Early Return
|
|
```php
|
|
if ($mode === 'full' && $is_spa_route) {
|
|
return $spa_template;
|
|
}
|
|
```
|
|
|
|
**Why:** Returns SPA template immediately, bypassing WordPress's normal template hierarchy.
|
|
|
|
## Comparison: Admin vs Customer SPA
|
|
|
|
| Aspect | Admin SPA | Customer SPA |
|
|
|--------|-----------|--------------|
|
|
| **Location** | `/wp-admin/` | Frontend URLs |
|
|
| **Template Control** | Always controlled by WP | Must override theme |
|
|
| **URL Detection** | Menu system | URL pattern matching |
|
|
| **404 Risk** | None | High (before fix) |
|
|
| **Complexity** | Simple | More complex |
|
|
|
|
## Why This Approach Works
|
|
|
|
### 1. Catches Direct Access
|
|
URL-based detection works for both:
|
|
- Direct browser access
|
|
- Bookmarks
|
|
- External links
|
|
- Copy-paste URLs
|
|
|
|
### 2. Doesn't Break Navigation
|
|
Client-side navigation still works because:
|
|
- React Router handles it
|
|
- No page reload
|
|
- No WordPress query
|
|
|
|
### 3. SEO Safe
|
|
- Sets proper 200 status
|
|
- No 404 errors
|
|
- Search engines see valid pages
|
|
|
|
### 4. Theme Independent
|
|
- Doesn't rely on theme templates
|
|
- Works with any WordPress theme
|
|
- No theme modifications needed
|
|
|
|
## Testing
|
|
|
|
### Test 1: Direct Access
|
|
1. Open new browser tab
|
|
2. Type: `https://woonoow.local/product/edukasi-anak`
|
|
3. Press Enter
|
|
4. **Expected:** Product page loads with SPA
|
|
5. **Should NOT see:** Theme's 404 page
|
|
|
|
### Test 2: Refresh
|
|
1. Navigate to product page from shop
|
|
2. Press F5 (refresh)
|
|
3. **Expected:** Page reloads and shows product
|
|
4. **Should NOT:** Redirect or show 404
|
|
|
|
### Test 3: Bookmark
|
|
1. Bookmark a product page
|
|
2. Close browser
|
|
3. Open bookmark
|
|
4. **Expected:** Product page loads directly
|
|
|
|
### Test 4: All Routes
|
|
Test each SPA route:
|
|
- `/shop` ✅
|
|
- `/product/any-slug` ✅
|
|
- `/cart` ✅
|
|
- `/checkout` ✅
|
|
- `/my-account` ✅
|
|
|
|
## Debugging
|
|
|
|
### Check Template Loading
|
|
Add to `spa-full-page.php`:
|
|
```php
|
|
<?php
|
|
error_log('SPA Template Loaded');
|
|
error_log('Request URI: ' . $_SERVER['REQUEST_URI']);
|
|
error_log('is_product: ' . (is_product() ? 'yes' : 'no'));
|
|
error_log('is_404: ' . (is_404() ? 'yes' : 'no'));
|
|
?>
|
|
```
|
|
|
|
### Check Status Code
|
|
In browser console:
|
|
```javascript
|
|
console.log('Status:', performance.getEntriesByType('navigation')[0].responseStatus);
|
|
```
|
|
|
|
Should be `200`, not `404`.
|
|
|
|
## Alternative Approaches (Not Used)
|
|
|
|
### Option 1: Custom Post Type
|
|
Create a custom post type for products.
|
|
|
|
**Pros:** WordPress recognizes URLs
|
|
**Cons:** Duplicates WooCommerce products, complex sync
|
|
|
|
### Option 2: Rewrite Rules
|
|
Add custom rewrite rules.
|
|
|
|
**Pros:** More "WordPress way"
|
|
**Cons:** Requires flush_rewrite_rules(), can conflict
|
|
|
|
### Option 3: Hash Router
|
|
Use `#` in URLs.
|
|
|
|
**Pros:** No server-side changes needed
|
|
**Cons:** Ugly URLs, poor SEO
|
|
|
|
### Our Solution: URL Detection ✅
|
|
**Pros:**
|
|
- Simple
|
|
- Reliable
|
|
- No conflicts
|
|
- SEO friendly
|
|
- Works immediately
|
|
|
|
**Cons:** None!
|
|
|
|
## Summary
|
|
|
|
**Problem:** Direct URL access shows 404 because WordPress doesn't recognize SPA routes
|
|
|
|
**Root Cause:** WordPress query runs before SPA template can load
|
|
|
|
**Solution:** Detect SPA routes by URL pattern and return SPA template with 200 status
|
|
|
|
**Result:** Direct access now works perfectly! ✅
|
|
|
|
**Files Modified:**
|
|
- `includes/Frontend/TemplateOverride.php` - Added URL-based detection
|
|
|
|
**Test:** Type `/product/edukasi-anak` directly in browser - should work!
|