Compare commits
13 Commits
c3904cc064
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7394d2f213 | ||
|
|
f77c9b828e | ||
|
|
61825c9ade | ||
|
|
7e87e18a43 | ||
|
|
3b3e3bd0ad | ||
|
|
c1db133ffa | ||
|
|
7a967c3399 | ||
|
|
28593b8a1b | ||
|
|
547cb6c4c5 | ||
|
|
b61d74fb8e | ||
|
|
e1768a075a | ||
|
|
57ce0a4e50 | ||
|
|
056cad44f9 |
234
DEPLOYMENT_GUIDE.md
Normal file
234
DEPLOYMENT_GUIDE.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# Deployment Guide
|
||||
|
||||
## Server Deployment Steps
|
||||
|
||||
### 1. Pull Latest Code
|
||||
```bash
|
||||
cd /home/dewepw/woonoow.dewe.pw/wp-content/plugins/woonoow
|
||||
git pull origin main
|
||||
```
|
||||
|
||||
### 2. Clear All Caches
|
||||
|
||||
#### WordPress Object Cache
|
||||
```bash
|
||||
wp cache flush
|
||||
```
|
||||
|
||||
#### OPcache (PHP)
|
||||
Create a file `clear-opcache.php` in plugin root:
|
||||
```php
|
||||
<?php
|
||||
if (function_exists('opcache_reset')) {
|
||||
opcache_reset();
|
||||
echo "OPcache cleared!";
|
||||
} else {
|
||||
echo "OPcache not available";
|
||||
}
|
||||
```
|
||||
|
||||
Then visit: `https://woonoow.dewe.pw/wp-content/plugins/woonoow/clear-opcache.php`
|
||||
|
||||
Or via command line:
|
||||
```bash
|
||||
php -r "opcache_reset();"
|
||||
```
|
||||
|
||||
#### Browser Cache
|
||||
- Hard refresh: `Ctrl+Shift+R` (Windows/Linux) or `Cmd+Shift+R` (Mac)
|
||||
- Or clear browser cache completely
|
||||
|
||||
### 3. Verify Files
|
||||
```bash
|
||||
# Check if Routes.php has correct namespace
|
||||
grep "use WooNooW" includes/Api/Routes.php
|
||||
|
||||
# Should show:
|
||||
# use WooNooW\Api\PaymentsController;
|
||||
# use WooNooW\Api\StoreController;
|
||||
# use WooNooW\Api\DeveloperController;
|
||||
# use WooNooW\Api\SystemController;
|
||||
|
||||
# Check if Assets.php has correct is_dev_mode()
|
||||
grep -A 5 "is_dev_mode" includes/Admin/Assets.php
|
||||
|
||||
# Should show:
|
||||
# defined('WOONOOW_ADMIN_DEV') && WOONOOW_ADMIN_DEV === true
|
||||
```
|
||||
|
||||
### 4. Check File Permissions
|
||||
```bash
|
||||
# Plugin files should be readable
|
||||
find . -type f -exec chmod 644 {} \;
|
||||
find . -type d -exec chmod 755 {} \;
|
||||
```
|
||||
|
||||
### 5. Test Endpoints
|
||||
|
||||
#### Test API
|
||||
```bash
|
||||
curl -I https://woonoow.dewe.pw/wp-json/woonoow/v1/store/settings
|
||||
```
|
||||
|
||||
Should return `200 OK`, not `500 Internal Server Error`.
|
||||
|
||||
#### Test Admin SPA
|
||||
Visit: `https://woonoow.dewe.pw/wp-admin/admin.php?page=woonoow`
|
||||
|
||||
Should load the SPA, not show blank page or errors.
|
||||
|
||||
#### Test Standalone
|
||||
Visit: `https://woonoow.dewe.pw/admin`
|
||||
|
||||
Should load standalone admin interface.
|
||||
|
||||
---
|
||||
|
||||
## Common Issues & Solutions
|
||||
|
||||
### Issue 1: SPA Not Loading (Blank Page)
|
||||
|
||||
**Symptoms:**
|
||||
- Blank page in wp-admin
|
||||
- Console errors about `@react-refresh` or `localhost:5173`
|
||||
|
||||
**Cause:**
|
||||
- Server is in dev mode
|
||||
- Trying to load from Vite dev server
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check wp-config.php - remove or set to false:
|
||||
define('WOONOOW_ADMIN_DEV', false);
|
||||
|
||||
# Or remove the line completely
|
||||
```
|
||||
|
||||
### Issue 2: API 500 Errors
|
||||
|
||||
**Symptoms:**
|
||||
- All API endpoints return 500
|
||||
- Error: `Class "WooNooWAPIPaymentsController" not found`
|
||||
|
||||
**Cause:**
|
||||
- Namespace case mismatch
|
||||
- Old code cached
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# 1. Pull latest code
|
||||
git pull origin main
|
||||
|
||||
# 2. Clear OPcache
|
||||
php -r "opcache_reset();"
|
||||
|
||||
# 3. Clear WordPress cache
|
||||
wp cache flush
|
||||
|
||||
# 4. Verify namespace fix
|
||||
grep "use WooNooW\\\\Api" includes/Api/Routes.php
|
||||
```
|
||||
|
||||
### Issue 3: WordPress Media Not Loading (Standalone)
|
||||
|
||||
**Symptoms:**
|
||||
- "WordPress Media library is not loaded" error
|
||||
- Image upload doesn't work
|
||||
|
||||
**Cause:**
|
||||
- Missing wp.media scripts
|
||||
|
||||
**Solution:**
|
||||
- Already fixed in latest code
|
||||
- Pull latest: `git pull origin main`
|
||||
- Clear cache
|
||||
|
||||
### Issue 4: Changes Not Reflecting
|
||||
|
||||
**Symptoms:**
|
||||
- Code changes don't appear
|
||||
- Still seeing old errors
|
||||
|
||||
**Cause:**
|
||||
- Multiple cache layers
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# 1. Clear PHP OPcache
|
||||
php -r "opcache_reset();"
|
||||
|
||||
# 2. Clear WordPress object cache
|
||||
wp cache flush
|
||||
|
||||
# 3. Clear browser cache
|
||||
# Hard refresh: Ctrl+Shift+R
|
||||
|
||||
# 4. Restart PHP-FPM (if needed)
|
||||
sudo systemctl restart php8.1-fpm
|
||||
# or
|
||||
sudo systemctl restart php-fpm
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
After deployment, verify:
|
||||
|
||||
- [ ] Git pull completed successfully
|
||||
- [ ] OPcache cleared
|
||||
- [ ] WordPress cache cleared
|
||||
- [ ] Browser cache cleared
|
||||
- [ ] API endpoints return 200 OK
|
||||
- [ ] WP-Admin SPA loads correctly
|
||||
- [ ] Standalone admin loads correctly
|
||||
- [ ] No console errors
|
||||
- [ ] Dashboard displays data
|
||||
- [ ] Settings pages work
|
||||
- [ ] Image upload works
|
||||
|
||||
---
|
||||
|
||||
## Rollback Procedure
|
||||
|
||||
If deployment causes issues:
|
||||
|
||||
```bash
|
||||
# 1. Check recent commits
|
||||
git log --oneline -5
|
||||
|
||||
# 2. Rollback to previous commit
|
||||
git reset --hard <commit-hash>
|
||||
|
||||
# 3. Clear caches
|
||||
php -r "opcache_reset();"
|
||||
wp cache flush
|
||||
|
||||
# 4. Verify
|
||||
curl -I https://woonoow.dewe.pw/wp-json/woonoow/v1/store/settings
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Production Checklist
|
||||
|
||||
Before going live:
|
||||
|
||||
- [ ] All features tested
|
||||
- [ ] No console errors
|
||||
- [ ] No PHP errors in logs
|
||||
- [ ] Performance tested
|
||||
- [ ] Security reviewed
|
||||
- [ ] Backup created
|
||||
- [ ] Rollback plan ready
|
||||
- [ ] Monitoring in place
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
If issues persist:
|
||||
1. Check error logs: `/home/dewepw/woonoow.dewe.pw/wp-content/debug.log`
|
||||
2. Check PHP error logs: `/var/log/php-fpm/error.log`
|
||||
3. Enable WP_DEBUG temporarily to see detailed errors
|
||||
4. Contact development team with error details
|
||||
170
MARKDOWN_SYNTAX_AND_VARIABLES.md
Normal file
170
MARKDOWN_SYNTAX_AND_VARIABLES.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# Markdown Syntax & Variables - Analysis & Recommendations
|
||||
|
||||
## Current Issues
|
||||
|
||||
### 1. Card & Button Syntax
|
||||
**Current:**
|
||||
```markdown
|
||||
[card type="hero"]
|
||||
Content here
|
||||
[/card]
|
||||
|
||||
[button url="https://example.com" style="solid"]Click me[/button]
|
||||
```
|
||||
|
||||
**Problem:** Not standard Markdown - uses WordPress-style shortcodes
|
||||
|
||||
### 2. Variable Naming Mismatch
|
||||
**Template uses:** `{order_item_table}` (singular)
|
||||
**Preview defines:** `order_items_table` (plural)
|
||||
**Result:** Variable not replaced, shows as `{orderitemtable}` (underscores removed by some HTML sanitizer)
|
||||
|
||||
---
|
||||
|
||||
## All Variables Used in Templates
|
||||
|
||||
### Order Variables
|
||||
- `{order_number}` - Order ID
|
||||
- `{order_date}` - Order date
|
||||
- `{order_total}` - Total amount
|
||||
- `{order_status}` - Current status
|
||||
- `{order_url}` - Link to view order
|
||||
- `{order_item_table}` ⚠️ **MISMATCH** - Should be `order_items_table`
|
||||
|
||||
### Customer Variables
|
||||
- `{customer_name}` - Customer full name
|
||||
- `{customer_email}` - Customer email
|
||||
- `{customer_username}` - Username (for new accounts)
|
||||
- `{customer_password}` - Temporary password (for new accounts)
|
||||
|
||||
### Store Variables
|
||||
- `{store_name}` - Store name
|
||||
- `{store_url}` - Store URL
|
||||
- `{store_email}` - Store contact email
|
||||
|
||||
### Payment Variables
|
||||
- `{payment_method}` - Payment method used
|
||||
- `{payment_status}` - Payment status
|
||||
- `{transaction_id}` - Transaction ID
|
||||
|
||||
### Shipping Variables
|
||||
- `{shipping_address}` - Full shipping address
|
||||
- `{tracking_number}` - Shipment tracking number
|
||||
- `{carrier}` - Shipping carrier
|
||||
|
||||
### Date Variables
|
||||
- `{completion_date}` - Order completion date
|
||||
- `{cancellation_date}` - Order cancellation date
|
||||
|
||||
---
|
||||
|
||||
## Recommendations
|
||||
|
||||
### Option 1: Keep Current Syntax (Easiest)
|
||||
**Pros:**
|
||||
- No changes needed
|
||||
- Users already familiar
|
||||
- Clear boundaries for cards
|
||||
|
||||
**Cons:**
|
||||
- Not standard Markdown
|
||||
- Verbose
|
||||
|
||||
**Action:** Just fix the variable mismatch
|
||||
|
||||
### Option 2: Simplified Shortcode
|
||||
```markdown
|
||||
[card:hero]
|
||||
Content here
|
||||
[/card]
|
||||
|
||||
[button:solid](https://example.com)Click me[/button]
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
- Shorter, cleaner
|
||||
- Still clear
|
||||
|
||||
**Cons:**
|
||||
- Still not standard Markdown
|
||||
- Requires converter changes
|
||||
|
||||
### Option 3: HTML + Markdown (Hybrid)
|
||||
```html
|
||||
<div class="card card-hero">
|
||||
|
||||
**Content** with markdown
|
||||
|
||||
</div>
|
||||
|
||||
<a href="url" class="button">Click me</a>
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
- Standard Markdown allows inline HTML
|
||||
- No custom parsing needed
|
||||
|
||||
**Cons:**
|
||||
- Verbose
|
||||
- Less user-friendly
|
||||
|
||||
### Option 4: Attributes Syntax (Most Markdown-like)
|
||||
```markdown
|
||||
> **Order Number:** #{order_number}
|
||||
> **Order Date:** {order_date}
|
||||
{: .card .card-hero}
|
||||
|
||||
[Click me](https://example.com){: .button .button-solid}
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
- More Markdown-like
|
||||
- Compact
|
||||
|
||||
**Cons:**
|
||||
- Complex to parse
|
||||
- Not widely supported
|
||||
- Users may not understand
|
||||
|
||||
---
|
||||
|
||||
## Recommended Action Plan
|
||||
|
||||
### Immediate Fixes (Priority 1)
|
||||
1. ✅ **Fix `<br>` rendering** - DONE!
|
||||
2. ⚠️ **Fix variable mismatch:**
|
||||
- Change `order_item_table` → `order_items_table` in DefaultTemplates.php
|
||||
- OR change `order_items_table` → `order_item_table` in EditTemplate.tsx preview
|
||||
3. **Add all missing variables to preview sample data**
|
||||
|
||||
### Short-term (Priority 2)
|
||||
1. **Document all variables** - Create user-facing documentation
|
||||
2. **Add variable autocomplete** in markdown editor
|
||||
3. **Add variable validation** - warn if variable doesn't exist
|
||||
|
||||
### Long-term (Priority 3)
|
||||
1. **Consider syntax improvements** - Get user feedback first
|
||||
2. **Add visual card/button inserter** - UI buttons to insert syntax
|
||||
3. **Add syntax highlighting** in markdown editor
|
||||
|
||||
---
|
||||
|
||||
## Variable Replacement Issue
|
||||
|
||||
The underscore removal (`{order_item_table}` → `{orderitemtable}`) suggests HTML sanitization is happening somewhere. Need to check:
|
||||
|
||||
1. **Frontend:** DOMPurify or similar sanitizer?
|
||||
2. **Backend:** WordPress `wp_kses()` or similar?
|
||||
3. **Email client:** Some email clients strip underscores?
|
||||
|
||||
**Solution:** Use consistent naming without underscores OR fix sanitizer to preserve variable syntax.
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Fix variable naming mismatch
|
||||
2. Test all variables in preview
|
||||
3. Document syntax for users
|
||||
4. Get feedback on syntax preferences
|
||||
5. Consider improvements based on feedback
|
||||
26
PHASE_COMPLETE.md
Normal file
26
PHASE_COMPLETE.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Phase Complete ✅
|
||||
|
||||
**Date:** November 15, 2025
|
||||
|
||||
## Completed
|
||||
|
||||
### 1. Email Queue ✅
|
||||
- Already implemented via MailQueue + WooEmailOverride
|
||||
- Prevents 30s timeout
|
||||
|
||||
### 2. Documentation ✅
|
||||
- Reduced 56 → 27 files (52% reduction)
|
||||
- Created NOTIFICATION_SYSTEM.md (consolidated)
|
||||
- Deleted 30 obsolete docs
|
||||
|
||||
### 3. Git Push ✅
|
||||
- 3 commits pushed to main
|
||||
- Remote: git.backoffice.biz.id
|
||||
|
||||
### 4. Plugin Zip ✅
|
||||
- File: woonoow.zip
|
||||
- Size: 1.4MB
|
||||
- Location: /wp-content/plugins/woonoow.zip
|
||||
- Guide: PLUGIN_ZIP_GUIDE.md
|
||||
|
||||
## Ready for Distribution! 🚀
|
||||
222
PLUGIN_ZIP_GUIDE.md
Normal file
222
PLUGIN_ZIP_GUIDE.md
Normal file
@@ -0,0 +1,222 @@
|
||||
# Plugin Zip Guide
|
||||
|
||||
## Overview
|
||||
This guide explains how to properly zip the WooNooW plugin for distribution.
|
||||
|
||||
---
|
||||
|
||||
## What to Include
|
||||
|
||||
### ✅ Include
|
||||
- All PHP files (`includes/`, `*.php`)
|
||||
- Admin SPA build (`admin-spa/dist/`)
|
||||
- Assets (`assets/`)
|
||||
- Languages (`languages/`)
|
||||
- README.md
|
||||
- LICENSE (if exists)
|
||||
- woonoow.php (main plugin file)
|
||||
|
||||
### ❌ Exclude
|
||||
- `node_modules/`
|
||||
- `admin-spa/src/` (source files, only include dist)
|
||||
- `.git/`
|
||||
- `.gitignore`
|
||||
- All `.md` documentation files (except README.md)
|
||||
- `composer.json`, `composer.lock`
|
||||
- `package.json`, `package-lock.json`
|
||||
- `.DS_Store`, `Thumbs.db`
|
||||
- Development/testing files
|
||||
|
||||
---
|
||||
|
||||
## Step-by-Step Process
|
||||
|
||||
### 1. Build Admin SPA
|
||||
```bash
|
||||
cd admin-spa
|
||||
npm run build
|
||||
```
|
||||
|
||||
This creates optimized production files in `admin-spa/dist/`.
|
||||
|
||||
### 2. Create Zip (Automated)
|
||||
```bash
|
||||
# From plugin root directory
|
||||
zip -r woonoow.zip . \
|
||||
-x "*.git*" \
|
||||
-x "*node_modules*" \
|
||||
-x "admin-spa/src/*" \
|
||||
-x "*.md" \
|
||||
-x "!README.md" \
|
||||
-x "composer.json" \
|
||||
-x "composer.lock" \
|
||||
-x "package.json" \
|
||||
-x "package-lock.json" \
|
||||
-x "*.DS_Store" \
|
||||
-x "Thumbs.db"
|
||||
```
|
||||
|
||||
### 3. Verify Zip Contents
|
||||
```bash
|
||||
unzip -l woonoow.zip | head -50
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Required Structure
|
||||
|
||||
```
|
||||
woonoow/
|
||||
├── admin-spa/
|
||||
│ └── dist/ # ✅ Built files only
|
||||
├── assets/
|
||||
│ ├── css/
|
||||
│ ├── js/
|
||||
│ └── images/
|
||||
├── includes/
|
||||
│ ├── Admin/
|
||||
│ ├── Api/
|
||||
│ ├── Core/
|
||||
│ └── ...
|
||||
├── languages/
|
||||
├── README.md # ✅ Only this MD file
|
||||
├── woonoow.php # ✅ Main plugin file
|
||||
└── LICENSE (optional)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Size Optimization
|
||||
|
||||
### Before Zipping
|
||||
1. ✅ Build admin SPA (`npm run build`)
|
||||
2. ✅ Remove source maps if not needed
|
||||
3. ✅ Ensure no dev dependencies
|
||||
|
||||
### Expected Size
|
||||
- **Uncompressed:** ~5-10 MB
|
||||
- **Compressed (zip):** ~2-4 MB
|
||||
|
||||
---
|
||||
|
||||
## Testing the Zip
|
||||
|
||||
### 1. Extract to Test Environment
|
||||
```bash
|
||||
unzip woonoow.zip -d /path/to/test/wp-content/plugins/
|
||||
```
|
||||
|
||||
### 2. Verify
|
||||
- [ ] Plugin activates without errors
|
||||
- [ ] Admin SPA loads correctly
|
||||
- [ ] All features work
|
||||
- [ ] No console errors
|
||||
- [ ] No missing files
|
||||
|
||||
### 3. Check File Permissions
|
||||
```bash
|
||||
find woonoow -type f -exec chmod 644 {} \;
|
||||
find woonoow -type d -exec chmod 755 {} \;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Distribution Checklist
|
||||
|
||||
- [ ] Admin SPA built (`admin-spa/dist/` exists)
|
||||
- [ ] No `node_modules/` in zip
|
||||
- [ ] No `.git/` in zip
|
||||
- [ ] No source files (`admin-spa/src/`) in zip
|
||||
- [ ] No documentation (except README.md) in zip
|
||||
- [ ] Plugin version updated in `woonoow.php`
|
||||
- [ ] README.md updated with latest info
|
||||
- [ ] Tested in clean WordPress install
|
||||
- [ ] All features working
|
||||
- [ ] No errors in console/logs
|
||||
|
||||
---
|
||||
|
||||
## Version Management
|
||||
|
||||
### Before Creating Zip
|
||||
1. Update version in `woonoow.php`:
|
||||
```php
|
||||
* Version: 1.0.0
|
||||
```
|
||||
|
||||
2. Update version in `admin-spa/package.json`:
|
||||
```json
|
||||
"version": "1.0.0"
|
||||
```
|
||||
|
||||
3. Tag in Git:
|
||||
```bash
|
||||
git tag -a v1.0.0 -m "Release v1.0.0"
|
||||
git push origin v1.0.0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Automated Zip Script
|
||||
|
||||
Save as `create-zip.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Build admin SPA
|
||||
echo "Building admin SPA..."
|
||||
cd admin-spa
|
||||
npm run build
|
||||
cd ..
|
||||
|
||||
# Create zip
|
||||
echo "Creating zip..."
|
||||
zip -r woonoow.zip . \
|
||||
-x "*.git*" \
|
||||
-x "*node_modules*" \
|
||||
-x "admin-spa/src/*" \
|
||||
-x "*.md" \
|
||||
-x "!README.md" \
|
||||
-x "composer.json" \
|
||||
-x "composer.lock" \
|
||||
-x "package.json" \
|
||||
-x "package-lock.json" \
|
||||
-x "*.DS_Store" \
|
||||
-x "Thumbs.db" \
|
||||
-x "create-zip.sh"
|
||||
|
||||
echo "✅ Zip created: woonoow.zip"
|
||||
echo "📦 Size: $(du -h woonoow.zip | cut -f1)"
|
||||
```
|
||||
|
||||
Make executable:
|
||||
```bash
|
||||
chmod +x create-zip.sh
|
||||
./create-zip.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: Zip too large
|
||||
**Solution:** Ensure `node_modules/` is excluded
|
||||
|
||||
### Issue: Admin SPA not loading
|
||||
**Solution:** Verify `admin-spa/dist/` is included and built
|
||||
|
||||
### Issue: Missing files error
|
||||
**Solution:** Check all required files are included (use `unzip -l`)
|
||||
|
||||
### Issue: Permission errors
|
||||
**Solution:** Set correct permissions (644 for files, 755 for dirs)
|
||||
|
||||
---
|
||||
|
||||
## Final Notes
|
||||
|
||||
- Always test the zip in a clean WordPress environment
|
||||
- Keep source code in Git, distribute only production-ready zip
|
||||
- Document any special installation requirements in README.md
|
||||
- Include changelog in README.md for version tracking
|
||||
340
TROUBLESHOOTING.md
Normal file
340
TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,340 @@
|
||||
# Troubleshooting Guide
|
||||
|
||||
## Quick Diagnosis
|
||||
|
||||
### Step 1: Run Installation Checker
|
||||
Upload `check-installation.php` to your server and visit:
|
||||
```
|
||||
https://yoursite.com/wp-content/plugins/woonoow/check-installation.php
|
||||
```
|
||||
|
||||
This will show you exactly what's wrong.
|
||||
|
||||
---
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Issue 1: Blank Page in WP-Admin
|
||||
|
||||
**Symptoms:**
|
||||
- Blank white page when visiting `/wp-admin/admin.php?page=woonoow`
|
||||
- Or shows "Please Configure Marketing Setup first"
|
||||
- No SPA loads
|
||||
|
||||
**Diagnosis:**
|
||||
1. Open browser console (F12)
|
||||
2. Check Network tab
|
||||
3. Look for `app.js` and `app.css`
|
||||
|
||||
**Possible Causes & Solutions:**
|
||||
|
||||
#### A. Files Not Found (404)
|
||||
```
|
||||
❌ admin-spa/dist/app.js → 404 Not Found
|
||||
❌ admin-spa/dist/app.css → 404 Not Found
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# The dist files are missing!
|
||||
# Re-extract the zip file:
|
||||
cd /path/to/wp-content/plugins
|
||||
rm -rf woonoow
|
||||
unzip woonoow.zip
|
||||
|
||||
# Verify files exist:
|
||||
ls -la woonoow/admin-spa/dist/
|
||||
# Should show: app.js (2.4MB) and app.css (70KB)
|
||||
```
|
||||
|
||||
#### B. Wrong Extraction Path
|
||||
If you extracted into `plugins/woonoow/woonoow/`, the paths will be wrong.
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Correct structure:
|
||||
wp-content/plugins/woonoow/woonoow.php ✓
|
||||
wp-content/plugins/woonoow/admin-spa/dist/app.js ✓
|
||||
|
||||
# Wrong structure:
|
||||
wp-content/plugins/woonoow/woonoow/woonoow.php ✗
|
||||
wp-content/plugins/woonoow/woonoow/admin-spa/dist/app.js ✗
|
||||
|
||||
# Fix:
|
||||
cd /path/to/wp-content/plugins
|
||||
rm -rf woonoow
|
||||
unzip woonoow.zip
|
||||
# This creates: plugins/woonoow/ (correct!)
|
||||
```
|
||||
|
||||
#### C. Dev Mode Enabled
|
||||
```
|
||||
❌ Trying to load from localhost:5173
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
Edit `wp-config.php` and remove or set to false:
|
||||
```php
|
||||
// Remove this line:
|
||||
define('WOONOOW_ADMIN_DEV', true);
|
||||
|
||||
// Or set to false:
|
||||
define('WOONOOW_ADMIN_DEV', false);
|
||||
```
|
||||
|
||||
Then clear caches:
|
||||
```bash
|
||||
php -r "opcache_reset();"
|
||||
wp cache flush
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue 2: API 500 Errors
|
||||
|
||||
**Symptoms:**
|
||||
- All API endpoints return 500
|
||||
- Console shows: "Internal Server Error"
|
||||
- Error log: `Class "WooNooWAPIPaymentsController" not found`
|
||||
|
||||
**Cause:**
|
||||
Namespace case mismatch (old code)
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check if you have the fix:
|
||||
grep "use WooNooW" includes/Api/Routes.php
|
||||
|
||||
# Should show (lowercase 'i'):
|
||||
# use WooNooW\Api\PaymentsController;
|
||||
|
||||
# If it shows (uppercase 'I'):
|
||||
# use WooNooW\API\PaymentsController;
|
||||
# Then you need to update!
|
||||
|
||||
# Update:
|
||||
git pull origin main
|
||||
# Or re-upload the latest zip
|
||||
|
||||
# Clear caches:
|
||||
php -r "opcache_reset();"
|
||||
wp cache flush
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue 3: WordPress Media Not Loading (Standalone)
|
||||
|
||||
**Symptoms:**
|
||||
- Error: "WordPress Media library is not loaded"
|
||||
- "Choose from Media Library" button doesn't work
|
||||
- Only in standalone mode (`/admin`)
|
||||
|
||||
**Cause:**
|
||||
Missing wp.media scripts
|
||||
|
||||
**Solution:**
|
||||
Already fixed in latest code. Update:
|
||||
```bash
|
||||
git pull origin main
|
||||
# Or re-upload the latest zip
|
||||
|
||||
php -r "opcache_reset();"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue 4: Changes Not Reflecting
|
||||
|
||||
**Symptoms:**
|
||||
- Uploaded new code but still seeing old errors
|
||||
- Fixed files but issues persist
|
||||
|
||||
**Cause:**
|
||||
Multiple cache layers
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# 1. Clear PHP OPcache (MOST IMPORTANT!)
|
||||
php -r "opcache_reset();"
|
||||
|
||||
# Or visit:
|
||||
# https://yoursite.com/wp-content/plugins/woonoow/check-installation.php?action=clear_opcache
|
||||
|
||||
# 2. Clear WordPress object cache
|
||||
wp cache flush
|
||||
|
||||
# 3. Restart PHP-FPM (if above doesn't work)
|
||||
sudo systemctl restart php8.1-fpm
|
||||
# or
|
||||
sudo systemctl restart php-fpm
|
||||
|
||||
# 4. Clear browser cache
|
||||
# Hard refresh: Ctrl+Shift+R (Windows/Linux)
|
||||
# Hard refresh: Cmd+Shift+R (Mac)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue 5: File Permissions
|
||||
|
||||
**Symptoms:**
|
||||
- 403 Forbidden errors
|
||||
- Can't access files
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
cd /path/to/wp-content/plugins/woonoow
|
||||
|
||||
# Set correct permissions:
|
||||
find . -type f -exec chmod 644 {} \;
|
||||
find . -type d -exec chmod 755 {} \;
|
||||
|
||||
# Verify:
|
||||
ls -la admin-spa/dist/
|
||||
# Should show: -rw-r--r-- (644) for files
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verification Steps
|
||||
|
||||
After fixing, verify everything works:
|
||||
|
||||
### 1. Check Files
|
||||
```bash
|
||||
cd /path/to/wp-content/plugins/woonoow
|
||||
|
||||
# These files MUST exist:
|
||||
ls -lh woonoow.php # Main plugin file
|
||||
ls -lh includes/Admin/Assets.php # Assets handler
|
||||
ls -lh includes/Api/Routes.php # API routes
|
||||
ls -lh admin-spa/dist/app.js # SPA JS (2.4MB)
|
||||
ls -lh admin-spa/dist/app.css # SPA CSS (70KB)
|
||||
```
|
||||
|
||||
### 2. Test API
|
||||
```bash
|
||||
curl -I https://yoursite.com/wp-json/woonoow/v1/store/settings
|
||||
|
||||
# Should return:
|
||||
# HTTP/2 200 OK
|
||||
```
|
||||
|
||||
### 3. Test Assets
|
||||
```bash
|
||||
curl -I https://yoursite.com/wp-content/plugins/woonoow/admin-spa/dist/app.js
|
||||
|
||||
# Should return:
|
||||
# HTTP/2 200 OK
|
||||
# Content-Length: 2489867
|
||||
```
|
||||
|
||||
### 4. Test WP-Admin
|
||||
Visit: `https://yoursite.com/wp-admin/admin.php?page=woonoow`
|
||||
|
||||
**Should see:**
|
||||
- ✓ WooNooW dashboard loads
|
||||
- ✓ No console errors
|
||||
- ✓ Navigation works
|
||||
|
||||
**Should NOT see:**
|
||||
- ✗ Blank page
|
||||
- ✗ "Please Configure Marketing Setup"
|
||||
- ✗ Errors about localhost:5173
|
||||
|
||||
### 5. Test Standalone
|
||||
Visit: `https://yoursite.com/admin`
|
||||
|
||||
**Should see:**
|
||||
- ✓ Standalone admin loads
|
||||
- ✓ Login page (if not logged in)
|
||||
- ✓ Dashboard (if logged in)
|
||||
|
||||
---
|
||||
|
||||
## Emergency Rollback
|
||||
|
||||
If everything breaks:
|
||||
|
||||
```bash
|
||||
# 1. Deactivate plugin
|
||||
wp plugin deactivate woonoow
|
||||
|
||||
# 2. Remove plugin
|
||||
rm -rf /path/to/wp-content/plugins/woonoow
|
||||
|
||||
# 3. Re-upload fresh zip
|
||||
unzip woonoow.zip -d /path/to/wp-content/plugins/
|
||||
|
||||
# 4. Reactivate
|
||||
wp plugin activate woonoow
|
||||
|
||||
# 5. Clear all caches
|
||||
php -r "opcache_reset();"
|
||||
wp cache flush
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Getting Help
|
||||
|
||||
If issues persist, gather this info:
|
||||
|
||||
1. **Run installation checker:**
|
||||
```
|
||||
https://yoursite.com/wp-content/plugins/woonoow/check-installation.php
|
||||
```
|
||||
Take screenshot of results
|
||||
|
||||
2. **Check error logs:**
|
||||
```bash
|
||||
tail -50 /path/to/wp-content/debug.log
|
||||
tail -50 /var/log/php-fpm/error.log
|
||||
```
|
||||
|
||||
3. **Browser console:**
|
||||
- Open DevTools (F12)
|
||||
- Go to Console tab
|
||||
- Take screenshot of errors
|
||||
|
||||
4. **Network tab:**
|
||||
- Open DevTools (F12)
|
||||
- Go to Network tab
|
||||
- Reload page
|
||||
- Take screenshot showing failed requests
|
||||
|
||||
5. **File structure:**
|
||||
```bash
|
||||
ls -la /path/to/wp-content/plugins/woonoow/
|
||||
ls -la /path/to/wp-content/plugins/woonoow/admin-spa/dist/
|
||||
```
|
||||
|
||||
Send all this info when requesting help.
|
||||
|
||||
---
|
||||
|
||||
## Prevention
|
||||
|
||||
To avoid issues in the future:
|
||||
|
||||
1. **Always clear caches after updates:**
|
||||
```bash
|
||||
php -r "opcache_reset();"
|
||||
wp cache flush
|
||||
```
|
||||
|
||||
2. **Verify files after extraction:**
|
||||
```bash
|
||||
ls -lh admin-spa/dist/app.js
|
||||
# Should be ~2.4MB
|
||||
```
|
||||
|
||||
3. **Use installation checker:**
|
||||
Run it after every deployment
|
||||
|
||||
4. **Keep backups:**
|
||||
Before updating, backup the working version
|
||||
|
||||
5. **Test in staging first:**
|
||||
Don't deploy directly to production
|
||||
244
check-installation.php
Normal file
244
check-installation.php
Normal file
@@ -0,0 +1,244 @@
|
||||
<?php
|
||||
/**
|
||||
* WooNooW Installation Checker
|
||||
*
|
||||
* Upload this file to: wp-content/plugins/woonoow/check-installation.php
|
||||
* Then visit: https://yoursite.com/wp-content/plugins/woonoow/check-installation.php
|
||||
*/
|
||||
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>WooNooW Installation Check</title>
|
||||
<style>
|
||||
body { font-family: monospace; padding: 20px; background: #1e1e1e; color: #d4d4d4; }
|
||||
.pass { color: #4ec9b0; }
|
||||
.fail { color: #f48771; }
|
||||
.warn { color: #dcdcaa; }
|
||||
h1 { color: #569cd6; }
|
||||
h2 { color: #4ec9b0; margin-top: 30px; }
|
||||
pre { background: #2d2d2d; padding: 10px; border-radius: 4px; overflow-x: auto; }
|
||||
.status { display: inline-block; width: 60px; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>WooNooW Installation Checker</h1>
|
||||
|
||||
<h2>1. File Structure</h2>
|
||||
<?php
|
||||
$plugin_dir = __DIR__;
|
||||
$required_files = [
|
||||
'woonoow.php' => 'Main plugin file',
|
||||
'includes/Admin/Assets.php' => 'Assets handler',
|
||||
'includes/Api/Routes.php' => 'API routes',
|
||||
'admin-spa/dist/app.js' => 'SPA JavaScript',
|
||||
'admin-spa/dist/app.css' => 'SPA Stylesheet',
|
||||
];
|
||||
|
||||
foreach ($required_files as $file => $desc) {
|
||||
$path = $plugin_dir . '/' . $file;
|
||||
$exists = file_exists($path);
|
||||
$size = $exists ? filesize($path) : 0;
|
||||
$status = $exists ? '<span class="pass">✓ PASS</span>' : '<span class="fail">✗ FAIL</span>';
|
||||
|
||||
echo "<div>$status - $desc</div>";
|
||||
echo "<pre> Path: $file\n";
|
||||
if ($exists) {
|
||||
echo " Size: " . number_format($size) . " bytes\n";
|
||||
echo " Modified: " . date('Y-m-d H:i:s', filemtime($path)) . "</pre>";
|
||||
} else {
|
||||
echo " <span class='fail'>FILE NOT FOUND!</span></pre>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>2. PHP Configuration</h2>
|
||||
<?php
|
||||
$php_checks = [
|
||||
'PHP Version' => phpversion(),
|
||||
'OPcache Enabled' => function_exists('opcache_get_status') && opcache_get_status() ? 'Yes' : 'No',
|
||||
'Memory Limit' => ini_get('memory_limit'),
|
||||
'Max Execution Time' => ini_get('max_execution_time') . 's',
|
||||
'Upload Max Filesize' => ini_get('upload_max_filesize'),
|
||||
];
|
||||
|
||||
foreach ($php_checks as $check => $value) {
|
||||
echo "<div><span class='status'>INFO</span> $check: <strong>$value</strong></div>";
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>3. WordPress Detection</h2>
|
||||
<?php
|
||||
$wp_load = dirname(dirname(dirname(dirname(__DIR__)))) . '/wp-load.php';
|
||||
if (file_exists($wp_load)) {
|
||||
require_once $wp_load;
|
||||
echo "<div><span class='pass'>✓ PASS</span> WordPress loaded</div>";
|
||||
echo "<pre> WP Version: " . get_bloginfo('version') . "\n";
|
||||
echo " Site URL: " . home_url() . "\n";
|
||||
echo " Admin URL: " . admin_url() . "</pre>";
|
||||
|
||||
// Check if plugin is active
|
||||
if (function_exists('is_plugin_active')) {
|
||||
$is_active = is_plugin_active('woonoow/woonoow.php');
|
||||
$status = $is_active ? '<span class="pass">✓ ACTIVE</span>' : '<span class="warn">⚠ INACTIVE</span>';
|
||||
echo "<div>$status - Plugin Status</div>";
|
||||
}
|
||||
} else {
|
||||
echo "<div><span class='fail'>✗ FAIL</span> WordPress not found</div>";
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>4. Constants Check</h2>
|
||||
<?php
|
||||
if (defined('WOONOOW_ADMIN_DEV')) {
|
||||
$dev_mode = WOONOOW_ADMIN_DEV;
|
||||
$status = $dev_mode ? '<span class="warn">⚠ WARN</span>' : '<span class="pass">✓ PASS</span>';
|
||||
echo "<div>$status - WOONOOW_ADMIN_DEV = " . ($dev_mode ? 'true (DEV MODE!)' : 'false') . "</div>";
|
||||
} else {
|
||||
echo "<div><span class='pass'>✓ PASS</span> - WOONOOW_ADMIN_DEV not defined (production mode)</div>";
|
||||
}
|
||||
|
||||
if (defined('WP_DEBUG')) {
|
||||
$debug = WP_DEBUG;
|
||||
$status = $debug ? '<span class="warn">⚠ WARN</span>' : '<span class="pass">✓ PASS</span>';
|
||||
echo "<div>$status - WP_DEBUG = " . ($debug ? 'true' : 'false') . "</div>";
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>5. Namespace Check (Routes.php)</h2>
|
||||
<?php
|
||||
$routes_file = $plugin_dir . '/includes/Api/Routes.php';
|
||||
if (file_exists($routes_file)) {
|
||||
$content = file_get_contents($routes_file);
|
||||
$has_correct_namespace = strpos($content, 'use WooNooW\\Api\\PaymentsController') !== false;
|
||||
$has_wrong_namespace = strpos($content, 'use WooNooW\\API\\PaymentsController') !== false;
|
||||
|
||||
if ($has_correct_namespace) {
|
||||
echo "<div><span class='pass'>✓ PASS</span> - Correct namespace (WooNooW\\Api\\)</div>";
|
||||
} elseif ($has_wrong_namespace) {
|
||||
echo "<div><span class='fail'>✗ FAIL</span> - Wrong namespace (WooNooW\\API\\) - needs update!</div>";
|
||||
} else {
|
||||
echo "<div><span class='warn'>⚠ WARN</span> - Could not detect namespace</div>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>5b. Dev Mode Filter Check (woonoow.php)</h2>
|
||||
<?php
|
||||
$main_file = $plugin_dir . '/woonoow.php';
|
||||
if (file_exists($main_file)) {
|
||||
$content = file_get_contents($main_file);
|
||||
$has_dev_filter = strpos($content, "add_filter('woonoow/admin_is_dev', '__return_true')") !== false;
|
||||
|
||||
if ($has_dev_filter) {
|
||||
echo "<div><span class='fail'>✗ FAIL</span> - Hardcoded dev mode filter found in woonoow.php!</div>";
|
||||
echo "<pre> This forces dev mode ON for everyone.\n";
|
||||
echo " Remove this line from woonoow.php:\n";
|
||||
echo " add_filter('woonoow/admin_is_dev', '__return_true');</pre>";
|
||||
} else {
|
||||
echo "<div><span class='pass'>✓ PASS</span> - No hardcoded dev mode filters</div>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>6. Asset URLs</h2>
|
||||
<?php
|
||||
if (function_exists('plugins_url')) {
|
||||
$base_url = plugins_url('', $plugin_dir . '/woonoow.php');
|
||||
$css_url = $base_url . '/admin-spa/dist/app.css';
|
||||
$js_url = $base_url . '/admin-spa/dist/app.js';
|
||||
|
||||
echo "<pre>CSS URL: $css_url\n";
|
||||
echo "JS URL: $js_url</pre>";
|
||||
|
||||
// Test if URLs are accessible
|
||||
echo "<div>Testing URL accessibility...</div>";
|
||||
$ch = curl_init($css_url);
|
||||
curl_setopt($ch, CURLOPT_NOBODY, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_exec($ch);
|
||||
$css_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
$status = ($css_code == 200) ? '<span class="pass">✓ PASS</span>' : '<span class="fail">✗ FAIL</span>';
|
||||
echo "<div>$status - app.css (HTTP $css_code)</div>";
|
||||
|
||||
$ch = curl_init($js_url);
|
||||
curl_setopt($ch, CURLOPT_NOBODY, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_exec($ch);
|
||||
$js_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
$status = ($js_code == 200) ? '<span class="pass">✓ PASS</span>' : '<span class="fail">✗ FAIL</span>';
|
||||
echo "<div>$status - app.js (HTTP $js_code)</div>";
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>7. Recommendations</h2>
|
||||
<?php
|
||||
$issues = [];
|
||||
|
||||
if (!file_exists($plugin_dir . '/admin-spa/dist/app.js')) {
|
||||
$issues[] = "❌ Missing admin-spa/dist/app.js - Re-extract the zip file";
|
||||
}
|
||||
|
||||
if (defined('WOONOOW_ADMIN_DEV') && WOONOOW_ADMIN_DEV) {
|
||||
$issues[] = "⚠️ Dev mode is enabled - Remove WOONOOW_ADMIN_DEV from wp-config.php";
|
||||
}
|
||||
|
||||
if (isset($has_wrong_namespace) && $has_wrong_namespace) {
|
||||
$issues[] = "❌ Wrong namespace in Routes.php - Update to latest code";
|
||||
}
|
||||
|
||||
if (isset($css_code) && $css_code != 200) {
|
||||
$issues[] = "❌ CSS file not accessible - Check file permissions";
|
||||
}
|
||||
|
||||
if (isset($js_code) && $js_code != 200) {
|
||||
$issues[] = "❌ JS file not accessible - Check file permissions";
|
||||
}
|
||||
|
||||
if (empty($issues)) {
|
||||
echo "<div><span class='pass'>✓ All checks passed!</span></div>";
|
||||
echo "<div>If SPA still not loading, try:</div>";
|
||||
echo "<pre>1. Clear browser cache (Ctrl+Shift+R)\n";
|
||||
echo "2. Clear OPcache: php -r \"opcache_reset();\"\n";
|
||||
echo "3. Clear WordPress cache: wp cache flush</pre>";
|
||||
} else {
|
||||
echo "<div><span class='fail'>Issues found:</span></div>";
|
||||
echo "<ul>";
|
||||
foreach ($issues as $issue) {
|
||||
echo "<li>$issue</li>";
|
||||
}
|
||||
echo "</ul>";
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>8. Quick Actions</h2>
|
||||
<div>
|
||||
<a href="?action=clear_opcache" style="color: #4ec9b0;">Clear OPcache</a> |
|
||||
<a href="?action=phpinfo" style="color: #4ec9b0;">View PHP Info</a>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
if (isset($_GET['action'])) {
|
||||
if ($_GET['action'] == 'clear_opcache' && function_exists('opcache_reset')) {
|
||||
opcache_reset();
|
||||
echo "<div style='margin-top: 20px;'><span class='pass'>✓ OPcache cleared!</span></div>";
|
||||
} elseif ($_GET['action'] == 'phpinfo') {
|
||||
echo "<div style='margin-top: 20px;'>";
|
||||
phpinfo();
|
||||
echo "</div>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #444; color: #888;">
|
||||
Generated: <?php echo date('Y-m-d H:i:s'); ?> |
|
||||
Server: <?php echo $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown'; ?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -12,6 +12,11 @@ class Assets {
|
||||
}
|
||||
|
||||
public static function enqueue($hook) {
|
||||
// Debug logging
|
||||
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||
error_log('[WooNooW Assets] Hook: ' . $hook);
|
||||
}
|
||||
|
||||
if ($hook !== 'toplevel_page_woonoow') {
|
||||
return;
|
||||
}
|
||||
@@ -21,6 +26,12 @@ class Assets {
|
||||
|
||||
// Decide dev vs prod
|
||||
$is_dev = self::is_dev_mode();
|
||||
|
||||
// Debug logging
|
||||
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||
error_log('[WooNooW Assets] Dev mode: ' . ($is_dev ? 'true' : 'false'));
|
||||
}
|
||||
|
||||
if ($is_dev) {
|
||||
self::enqueue_dev();
|
||||
} else {
|
||||
@@ -126,8 +137,10 @@ class Assets {
|
||||
* PROD MODE (built assets in admin-spa/dist)
|
||||
* -------------------------------------- */
|
||||
private static function enqueue_prod(): void {
|
||||
$dist_dir = plugin_dir_path(__FILE__) . '../admin-spa/dist/';
|
||||
$base_url = plugins_url('../admin-spa/dist/', __FILE__);
|
||||
// Get plugin root directory (2 levels up from includes/Admin/)
|
||||
$plugin_dir = dirname(dirname(__DIR__));
|
||||
$dist_dir = $plugin_dir . '/admin-spa/dist/';
|
||||
$base_url = plugins_url('admin-spa/dist/', $plugin_dir . '/woonoow.php');
|
||||
|
||||
$css = 'app.css';
|
||||
$js = 'app.js';
|
||||
@@ -135,8 +148,30 @@ class Assets {
|
||||
$ver_css = file_exists($dist_dir . $css) ? (string) filemtime($dist_dir . $css) : self::asset_version();
|
||||
$ver_js = file_exists($dist_dir . $js) ? (string) filemtime($dist_dir . $js) : self::asset_version();
|
||||
|
||||
// Debug logging
|
||||
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||
error_log('[WooNooW Assets] Dist dir: ' . $dist_dir);
|
||||
error_log('[WooNooW Assets] CSS exists: ' . (file_exists($dist_dir . $css) ? 'yes' : 'no'));
|
||||
error_log('[WooNooW Assets] JS exists: ' . (file_exists($dist_dir . $js) ? 'yes' : 'no'));
|
||||
error_log('[WooNooW Assets] CSS URL: ' . $base_url . $css);
|
||||
error_log('[WooNooW Assets] JS URL: ' . $base_url . $js);
|
||||
}
|
||||
|
||||
if (file_exists($dist_dir . $css)) {
|
||||
wp_enqueue_style('wnw-admin', $base_url . $css, [], $ver_css);
|
||||
|
||||
// Fix icon rendering in WP-Admin (prevent WordPress admin styles from overriding)
|
||||
$icon_fix_css = '
|
||||
/* Fix Lucide icons in WP-Admin - force outlined style */
|
||||
#woonoow-admin-app svg {
|
||||
fill: none !important;
|
||||
stroke: currentColor !important;
|
||||
stroke-width: 2 !important;
|
||||
stroke-linecap: round !important;
|
||||
stroke-linejoin: round !important;
|
||||
}
|
||||
';
|
||||
wp_add_inline_style('wnw-admin', $icon_fix_css);
|
||||
}
|
||||
|
||||
if (file_exists($dist_dir . $js)) {
|
||||
@@ -225,25 +260,46 @@ class Assets {
|
||||
}
|
||||
|
||||
/** Determine dev mode:
|
||||
* - WP environment 'development'
|
||||
* - or constant WOONOOW_ADMIN_DEV=true
|
||||
* - ONLY enabled if constant WOONOOW_ADMIN_DEV=true is explicitly set
|
||||
* - or filter override (woonoow/admin_is_dev)
|
||||
*
|
||||
* Note: We don't check WP_ENV to avoid accidentally enabling dev mode
|
||||
* in Local by Flywheel or other local dev environments.
|
||||
*/
|
||||
private static function is_dev_mode(): bool {
|
||||
$env_is_dev = function_exists('wp_get_environment_type') && wp_get_environment_type() === 'development';
|
||||
// Only enable dev mode if explicitly set via constant
|
||||
$const_dev = defined('WOONOOW_ADMIN_DEV') && WOONOOW_ADMIN_DEV === true;
|
||||
$is_dev = $env_is_dev || $const_dev;
|
||||
|
||||
/**
|
||||
* Filter: force dev/prod mode for WooNooW admin assets.
|
||||
* Return true to use Vite dev server, false to use built assets.
|
||||
*
|
||||
* IMPORTANT: This filter should NOT be used in production!
|
||||
* Only use it during development.
|
||||
*/
|
||||
return (bool) apply_filters('woonoow/admin_is_dev', $is_dev);
|
||||
$filtered = apply_filters('woonoow/admin_is_dev', $const_dev);
|
||||
|
||||
// Debug logging (only if WP_DEBUG is enabled)
|
||||
if (defined('WP_DEBUG') && WP_DEBUG && $filtered !== $const_dev) {
|
||||
error_log('[WooNooW Assets] Dev mode changed by filter: ' . ($filtered ? 'true' : 'false'));
|
||||
}
|
||||
|
||||
return (bool) $filtered;
|
||||
}
|
||||
|
||||
/** Dev server URL (filterable) */
|
||||
private static function dev_server_url(): string {
|
||||
$default = 'http://localhost:5173';
|
||||
// Auto-detect based on current host (for Local by Flywheel compatibility)
|
||||
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
|
||||
$protocol = is_ssl() ? 'https' : 'http';
|
||||
|
||||
// If using *.local domain (Local by Flywheel), use HTTPS
|
||||
if (strpos($host, '.local') !== false) {
|
||||
$protocol = 'https';
|
||||
}
|
||||
|
||||
$default = $protocol . '://' . $host . ':5173';
|
||||
|
||||
/** Filter: change dev server URL if needed */
|
||||
return (string) apply_filters('woonoow/admin_dev_server', $default);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,9 @@ class StandaloneAdmin {
|
||||
* Render standalone admin interface
|
||||
*/
|
||||
private static function render_standalone_admin() {
|
||||
// Enqueue WordPress media library (needed for image uploads)
|
||||
wp_enqueue_media();
|
||||
|
||||
// Check if user is logged in and has permissions
|
||||
$is_logged_in = is_user_logged_in();
|
||||
$has_permission = $is_logged_in && current_user_can( 'manage_woocommerce' );
|
||||
@@ -105,7 +108,17 @@ class StandaloneAdmin {
|
||||
}
|
||||
?>
|
||||
|
||||
<!-- WooNooW Assets Only - NO wp_head() -->
|
||||
<?php
|
||||
// Print WordPress media library styles (complete set for proper modal)
|
||||
wp_print_styles( 'media-views' );
|
||||
wp_print_styles( 'imgareaselect' );
|
||||
wp_print_styles( 'buttons' );
|
||||
wp_print_styles( 'dashicons' );
|
||||
wp_print_styles( 'wp-admin' );
|
||||
wp_print_styles( 'common' );
|
||||
?>
|
||||
|
||||
<!-- WooNooW Assets -->
|
||||
<link rel="stylesheet" href="<?php echo esc_url( $css_url ); ?>">
|
||||
</head>
|
||||
<body class="woonoow-standalone">
|
||||
@@ -137,13 +150,25 @@ class StandaloneAdmin {
|
||||
|
||||
// Navigation tree (single source of truth from PHP)
|
||||
window.WNW_NAV_TREE = <?php echo wp_json_encode( \WooNooW\Compat\NavigationRegistry::get_frontend_nav_tree() ); ?>;
|
||||
|
||||
// WordPress REST API settings (for media upload compatibility)
|
||||
window.wpApiSettings = {
|
||||
root: <?php echo wp_json_encode( untrailingslashit( rest_url() ) ); ?>,
|
||||
nonce: <?php echo wp_json_encode( $nonce ); ?>,
|
||||
versionString: 'wp/v2/'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script type="module" src="<?php echo esc_url( $js_url ); ?>"></script>
|
||||
|
||||
<?php
|
||||
// NO wp_footer() - we don't want theme/plugin scripts
|
||||
// Print WordPress media library scripts (needed for wp.media)
|
||||
wp_print_scripts( 'media-editor' );
|
||||
wp_print_scripts( 'media-audiovideo' );
|
||||
|
||||
// Print media templates (required for media modal to work)
|
||||
wp_print_media_templates();
|
||||
?>
|
||||
|
||||
<script type="module" src="<?php echo esc_url( $js_url ); ?>"></script>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
|
||||
@@ -7,14 +7,14 @@ use WooNooW\Api\CheckoutController;
|
||||
use WooNooW\Api\OrdersController;
|
||||
use WooNooW\Api\AnalyticsController;
|
||||
use WooNooW\Api\AuthController;
|
||||
use WooNooW\API\PaymentsController;
|
||||
use WooNooW\API\StoreController;
|
||||
use WooNooW\Api\PaymentsController;
|
||||
use WooNooW\Api\StoreController;
|
||||
use WooNooW\Api\ShippingController;
|
||||
use WooNooW\Api\TaxController;
|
||||
use WooNooW\Api\PickupLocationsController;
|
||||
use WooNooW\Api\EmailController;
|
||||
use WooNooW\API\DeveloperController;
|
||||
use WooNooW\API\SystemController;
|
||||
use WooNooW\Api\DeveloperController;
|
||||
use WooNooW\Api\SystemController;
|
||||
use WooNooW\Api\NotificationsController;
|
||||
use WooNooW\Api\ActivityLogController;
|
||||
|
||||
|
||||
@@ -115,19 +115,33 @@ class EmailManager {
|
||||
* @param WC_Order $order
|
||||
*/
|
||||
public function send_order_processing_email($order_id, $order = null) {
|
||||
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||
error_log('[EmailManager] send_order_processing_email triggered for order #' . $order_id);
|
||||
}
|
||||
|
||||
if (!$order) {
|
||||
$order = wc_get_order($order_id);
|
||||
}
|
||||
|
||||
if (!$order) {
|
||||
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||
error_log('[EmailManager] Order not found for ID: ' . $order_id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if event is enabled
|
||||
if (!$this->is_event_enabled('order_processing', 'email', 'customer')) {
|
||||
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||
error_log('[EmailManager] order_processing email is disabled in settings');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||
error_log('[EmailManager] Sending order_processing email for order #' . $order_id);
|
||||
}
|
||||
|
||||
// Send email
|
||||
$this->send_email('order_processing', 'customer', $order);
|
||||
}
|
||||
@@ -364,6 +378,10 @@ class EmailManager {
|
||||
* @param array $extra_data
|
||||
*/
|
||||
private function send_email($event_id, $recipient_type, $data, $extra_data = []) {
|
||||
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||
error_log('[EmailManager] send_email called - Event: ' . $event_id . ', Recipient: ' . $recipient_type);
|
||||
}
|
||||
|
||||
// Get email renderer
|
||||
$renderer = EmailRenderer::instance();
|
||||
|
||||
@@ -371,16 +389,27 @@ class EmailManager {
|
||||
$email = $renderer->render($event_id, $recipient_type, $data, $extra_data);
|
||||
|
||||
if (!$email) {
|
||||
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||
error_log('[EmailManager] Email rendering failed for event: ' . $event_id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||
error_log('[EmailManager] Email rendered successfully - To: ' . $email['to'] . ', Subject: ' . $email['subject']);
|
||||
}
|
||||
|
||||
// Send email via wp_mail
|
||||
$headers = [
|
||||
'Content-Type: text/html; charset=UTF-8',
|
||||
'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>',
|
||||
];
|
||||
|
||||
wp_mail($email['to'], $email['subject'], $email['body'], $headers);
|
||||
$sent = wp_mail($email['to'], $email['subject'], $email['body'], $headers);
|
||||
|
||||
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||
error_log('[EmailManager] wp_mail called - Result: ' . ($sent ? 'success' : 'failed'));
|
||||
}
|
||||
|
||||
// Log email sent
|
||||
do_action('woonoow_email_sent', $event_id, $recipient_type, $email);
|
||||
|
||||
255
test-email-flow.php
Normal file
255
test-email-flow.php
Normal file
@@ -0,0 +1,255 @@
|
||||
<?php
|
||||
/**
|
||||
* Email Flow Diagnostic Tool
|
||||
*
|
||||
* Usage: Visit https://yoursite.com/wp-content/plugins/woonoow/test-email-flow.php
|
||||
*/
|
||||
|
||||
// Load WordPress
|
||||
require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/wp-load.php';
|
||||
|
||||
if (!current_user_can('manage_options')) {
|
||||
die('Access denied');
|
||||
}
|
||||
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Email Flow Diagnostic</title>
|
||||
<style>
|
||||
body { font-family: monospace; padding: 20px; background: #1e1e1e; color: #d4d4d4; }
|
||||
.pass { color: #4ec9b0; }
|
||||
.fail { color: #f48771; }
|
||||
.warn { color: #dcdcaa; }
|
||||
h1 { color: #569cd6; }
|
||||
h2 { color: #4ec9b0; margin-top: 30px; }
|
||||
pre { background: #2d2d2d; padding: 10px; border-radius: 4px; overflow-x: auto; }
|
||||
.status { display: inline-block; width: 60px; font-weight: bold; }
|
||||
button { background: #0e639c; color: white; border: none; padding: 10px 20px; cursor: pointer; border-radius: 4px; margin: 10px 5px; }
|
||||
button:hover { background: #1177bb; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Email Flow Diagnostic Tool</h1>
|
||||
|
||||
<h2>1. System Status</h2>
|
||||
<?php
|
||||
// Check notification system mode
|
||||
$system_mode = get_option('woonoow_notification_system_mode', 'woonoow');
|
||||
$status = ($system_mode === 'woonoow') ? '<span class="pass">✓ ENABLED</span>' : '<span class="fail">✗ DISABLED</span>';
|
||||
echo "<div>$status - Notification System Mode: <strong>$system_mode</strong></div>";
|
||||
|
||||
// Check email channel
|
||||
$email_enabled = get_option('woonoow_email_notifications_enabled', false);
|
||||
$status = $email_enabled ? '<span class="pass">✓ ENABLED</span>' : '<span class="fail">✗ DISABLED</span>';
|
||||
echo "<div>$status - Email Channel: <strong>" . ($email_enabled ? 'enabled' : 'disabled') . "</strong></div>";
|
||||
|
||||
// Check Action Scheduler
|
||||
$as_exists = function_exists('as_enqueue_async_action');
|
||||
$status = $as_exists ? '<span class="pass">✓ AVAILABLE</span>' : '<span class="warn">⚠ NOT AVAILABLE</span>';
|
||||
echo "<div>$status - Action Scheduler: <strong>" . ($as_exists ? 'available' : 'not available (using wp-cron)') . "</strong></div>";
|
||||
?>
|
||||
|
||||
<h2>2. Event Configuration</h2>
|
||||
<?php
|
||||
$settings = get_option('woonoow_notification_settings', []);
|
||||
$events = $settings['events'] ?? [];
|
||||
|
||||
if (empty($events)) {
|
||||
echo "<div><span class='fail'>✗ FAIL</span> - No events configured!</div>";
|
||||
} else {
|
||||
echo "<div><span class='pass'>✓ PASS</span> - " . count($events) . " events configured</div>";
|
||||
echo "<pre>";
|
||||
foreach ($events as $event_id => $event_data) {
|
||||
$email_enabled = $event_data['channels']['email']['enabled'] ?? false;
|
||||
$status_icon = $email_enabled ? '✓' : '✗';
|
||||
echo "$status_icon $event_id: email " . ($email_enabled ? 'enabled' : 'disabled') . "\n";
|
||||
}
|
||||
echo "</pre>";
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>3. Email Queue Status</h2>
|
||||
<?php
|
||||
// Check for queued emails in wp_options
|
||||
global $wpdb;
|
||||
$queued_emails = $wpdb->get_results(
|
||||
"SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name LIKE 'woonoow_mail_%' LIMIT 10"
|
||||
);
|
||||
|
||||
if (empty($queued_emails)) {
|
||||
echo "<div><span class='warn'>⚠ INFO</span> - No emails currently queued</div>";
|
||||
} else {
|
||||
echo "<div><span class='pass'>✓ INFO</span> - " . count($queued_emails) . " emails in queue</div>";
|
||||
echo "<pre>";
|
||||
foreach ($queued_emails as $email) {
|
||||
$payload = maybe_unserialize($email->option_value);
|
||||
echo "ID: {$email->option_name}\n";
|
||||
echo "To: " . ($payload['to'] ?? 'unknown') . "\n";
|
||||
echo "Subject: " . ($payload['subject'] ?? 'unknown') . "\n";
|
||||
echo "---\n";
|
||||
}
|
||||
echo "</pre>";
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>4. Action Scheduler Queue</h2>
|
||||
<?php
|
||||
if ($as_exists) {
|
||||
$pending = $wpdb->get_var(
|
||||
"SELECT COUNT(*) FROM {$wpdb->prefix}actionscheduler_actions
|
||||
WHERE hook = 'woonoow/mail/send' AND status = 'pending'"
|
||||
);
|
||||
$failed = $wpdb->get_var(
|
||||
"SELECT COUNT(*) FROM {$wpdb->prefix}actionscheduler_actions
|
||||
WHERE hook = 'woonoow/mail/send' AND status = 'failed'"
|
||||
);
|
||||
$complete = $wpdb->get_var(
|
||||
"SELECT COUNT(*) FROM {$wpdb->prefix}actionscheduler_actions
|
||||
WHERE hook = 'woonoow/mail/send' AND status = 'complete'
|
||||
ORDER BY action_id DESC LIMIT 10"
|
||||
);
|
||||
|
||||
echo "<div><span class='pass'>✓ INFO</span> - Pending: <strong>$pending</strong></div>";
|
||||
echo "<div><span class='pass'>✓ INFO</span> - Completed (last 10): <strong>$complete</strong></div>";
|
||||
|
||||
if ($failed > 0) {
|
||||
echo "<div><span class='fail'>✗ WARN</span> - Failed: <strong>$failed</strong></div>";
|
||||
|
||||
// Show failed actions
|
||||
$failed_actions = $wpdb->get_results(
|
||||
"SELECT * FROM {$wpdb->prefix}actionscheduler_actions
|
||||
WHERE hook = 'woonoow/mail/send' AND status = 'failed'
|
||||
ORDER BY action_id DESC LIMIT 5"
|
||||
);
|
||||
|
||||
if ($failed_actions) {
|
||||
echo "<pre>Recent failures:\n";
|
||||
foreach ($failed_actions as $action) {
|
||||
echo "ID: {$action->action_id}\n";
|
||||
echo "Args: {$action->args}\n";
|
||||
echo "Scheduled: {$action->scheduled_date_gmt}\n";
|
||||
echo "---\n";
|
||||
}
|
||||
echo "</pre>";
|
||||
}
|
||||
} else {
|
||||
echo "<div><span class='pass'>✓ PASS</span> - Failed: <strong>0</strong></div>";
|
||||
}
|
||||
} else {
|
||||
echo "<div><span class='warn'>⚠ WARN</span> - Action Scheduler not available, using wp-cron</div>";
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>5. Recent Email Logs</h2>
|
||||
<?php
|
||||
// Check debug log for email activity
|
||||
$debug_log = WP_CONTENT_DIR . '/debug.log';
|
||||
if (file_exists($debug_log)) {
|
||||
$log_lines = file($debug_log);
|
||||
$email_logs = array_filter($log_lines, function($line) {
|
||||
return strpos($line, '[WooNooW MailQueue]') !== false ||
|
||||
strpos($line, 'woonoow_email_sent') !== false;
|
||||
});
|
||||
|
||||
if (empty($email_logs)) {
|
||||
echo "<div><span class='warn'>⚠ INFO</span> - No email logs found (enable WP_DEBUG to see logs)</div>";
|
||||
} else {
|
||||
echo "<div><span class='pass'>✓ INFO</span> - " . count($email_logs) . " email log entries found</div>";
|
||||
echo "<pre>";
|
||||
echo implode('', array_slice($email_logs, -10)); // Last 10 entries
|
||||
echo "</pre>";
|
||||
}
|
||||
} else {
|
||||
echo "<div><span class='warn'>⚠ INFO</span> - Debug log not found (enable WP_DEBUG_LOG)</div>";
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>6. Test Actions</h2>
|
||||
|
||||
<?php
|
||||
if (isset($_GET['action'])) {
|
||||
echo "<div style='margin: 20px 0; padding: 15px; background: #2d2d2d; border-left: 4px solid #4ec9b0;'>";
|
||||
|
||||
if ($_GET['action'] === 'test_email') {
|
||||
echo "<h3>Testing Email Queue...</h3>";
|
||||
|
||||
// Queue a test email
|
||||
$test_payload = [
|
||||
'to' => get_option('admin_email'),
|
||||
'subject' => 'WooNooW Test Email - ' . date('Y-m-d H:i:s'),
|
||||
'html' => '<h1>Test Email</h1><p>This is a test email from WooNooW email queue system.</p><p>Time: ' . date('Y-m-d H:i:s') . '</p>',
|
||||
'headers' => ['Content-Type: text/html; charset=UTF-8'],
|
||||
'attachments' => [],
|
||||
];
|
||||
|
||||
\WooNooW\Core\Mail\MailQueue::enqueue($test_payload);
|
||||
|
||||
echo "<p><span class='pass'>✓ SUCCESS</span> - Test email queued to: " . get_option('admin_email') . "</p>";
|
||||
echo "<p>Check your inbox in a few moments. Also check Action Scheduler queue above.</p>";
|
||||
}
|
||||
|
||||
if ($_GET['action'] === 'process_queue') {
|
||||
echo "<h3>Processing Email Queue...</h3>";
|
||||
|
||||
if (function_exists('as_run_queue')) {
|
||||
as_run_queue();
|
||||
echo "<p><span class='pass'>✓ SUCCESS</span> - Action Scheduler queue processed</p>";
|
||||
} else {
|
||||
echo "<p><span class='warn'>⚠ WARN</span> - Action Scheduler not available</p>";
|
||||
}
|
||||
}
|
||||
|
||||
if ($_GET['action'] === 'test_order_email') {
|
||||
echo "<h3>Testing Order Email...</h3>";
|
||||
|
||||
// Get a recent order
|
||||
$orders = wc_get_orders(['limit' => 1, 'orderby' => 'date', 'order' => 'DESC']);
|
||||
|
||||
if (empty($orders)) {
|
||||
echo "<p><span class='fail'>✗ FAIL</span> - No orders found. Create a test order first.</p>";
|
||||
} else {
|
||||
$order = $orders[0];
|
||||
echo "<p>Using order #" . $order->get_id() . "</p>";
|
||||
|
||||
// Trigger order processing email
|
||||
$email_manager = \WooNooW\Core\Notifications\EmailManager::instance();
|
||||
$email_manager->send_order_processing_email($order->get_id(), $order);
|
||||
|
||||
echo "<p><span class='pass'>✓ SUCCESS</span> - Order processing email triggered</p>";
|
||||
echo "<p>Check Action Scheduler queue and email logs above.</p>";
|
||||
}
|
||||
}
|
||||
|
||||
echo "</div>";
|
||||
}
|
||||
?>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<button onclick="window.location.href='?action=test_email'">Queue Test Email</button>
|
||||
<button onclick="window.location.href='?action=process_queue'">Process Queue Now</button>
|
||||
<button onclick="window.location.href='?action=test_order_email'">Test Order Email</button>
|
||||
<button onclick="window.location.reload()">Refresh</button>
|
||||
</div>
|
||||
|
||||
<h2>7. Troubleshooting</h2>
|
||||
<div>
|
||||
<h3>If emails are not sending:</h3>
|
||||
<ol>
|
||||
<li>Check that "Notification System Mode" is set to "woonoow" (not "woocommerce")</li>
|
||||
<li>Check that "Email Channel" is enabled</li>
|
||||
<li>Check that specific events have email enabled in configuration</li>
|
||||
<li>Check Action Scheduler for failed actions</li>
|
||||
<li>Enable WP_DEBUG and WP_DEBUG_LOG to see detailed logs</li>
|
||||
<li>Check your server's mail configuration (SMTP, sendmail, etc.)</li>
|
||||
<li>Test with "Queue Test Email" button above</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #444; color: #888;">
|
||||
Generated: <?php echo date('Y-m-d H:i:s'); ?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -43,5 +43,6 @@ register_activation_hook(__FILE__, function () {
|
||||
update_option('woocommerce_custom_orders_table_migration_enabled', 'yes');
|
||||
});
|
||||
|
||||
add_filter('woonoow/admin_is_dev', '__return_true');
|
||||
add_filter('woonoow/admin_dev_server', fn() => 'https://woonoow.local:5173');
|
||||
// Dev mode filters removed - use wp-config.php if needed:
|
||||
// add_filter('woonoow/admin_is_dev', '__return_true');
|
||||
// add_filter('woonoow/admin_dev_server', fn() => 'https://woonoow.local:5173');
|
||||
Reference in New Issue
Block a user