Introduce a comprehensive address management system allowing users to
save, manage, and reuse sender and receiver addresses during the
ordering process. This feature bridges the WordPress frontend with the
Laravel backend API.
Key changes:
- Backend (Laravel):
- Added `AddressBookEntry` model and migration for storing addresses
with role (sender/receiver), usage tracking, and default status.
- Implemented `AddressBookController` with full CRUD functionality
secured via Sanctum and ownership validation.
- Integrated address usage tracking and upsert logic into the
`CustomerOrderController` to prevent duplicate entries.
- Added 18 new feature tests covering ownership, limits, and
validation.
- Frontend (WordPress):
- Added a new "Address Book" tab in the user dashboard with card-based
UI, filtering, and SweetAlert2 integration.
- Enhanced the order form with dropdown selectors for saved addresses
and "save this address" checkboxes for both sender and receiver.
- Implemented secure AJAX proxies in `user-bridge.php` with nonce
and sanitization.
- Documentation:
- Updated `AGENT.md` and `CLIENT_DELIVERY.md` to reflect phase 3.9
completion and updated the project roadmap.
- Removed obsolete `README-INSTALL.md`.
120 lines
6.7 KiB
PHP
120 lines
6.7 KiB
PHP
<?php
|
||
/**
|
||
* Plugin Name: IFNEX Logistics Bridge
|
||
* Description: اتصال فرانتاند سایت ایفنکس به API لاراول
|
||
* Version: 1.0
|
||
* Author: VernaSoft group (Kazem Alghasi)
|
||
*/
|
||
|
||
if ( ! defined( 'ABSPATH' ) ) {
|
||
exit;
|
||
}
|
||
|
||
// ─── نسخهٔ پلاگین + cache-busting سالم assetها (سختسازی Production) ───
|
||
// قبلاً اینجا opcache_reset() و header('Cache-Control: no-store') بود که فقط برای دیباگ
|
||
// لوکال مناسب است و در Production باعث header error و شکستن کش CDN/مرورگر میشد — حذف شد.
|
||
if ( ! defined( 'IFNEX_BRIDGE_VERSION' ) ) {
|
||
define( 'IFNEX_BRIDGE_VERSION', '2.1.0' );
|
||
}
|
||
|
||
/**
|
||
* نسخهٔ asset بر اساس آخرین زمان تغییر فایل.
|
||
* کش مرورگر فقط وقتی فایل واقعاً عوض شود باطل میشود — جایگزین استاندارد time().
|
||
*/
|
||
if ( ! function_exists( 'ifnex_asset_version' ) ) {
|
||
function ifnex_asset_version( string $relative_path ): string {
|
||
$file = plugin_dir_path( __FILE__ ) . ltrim( $relative_path, '/' );
|
||
$mtime = file_exists( $file ) ? (string) filemtime( $file ) : '0';
|
||
|
||
return IFNEX_BRIDGE_VERSION . '.' . $mtime;
|
||
}
|
||
}
|
||
|
||
// لود کردن فایلهای پلاگین
|
||
require_once plugin_dir_path( __FILE__ ) . 'includes/api-client.php';
|
||
require_once plugin_dir_path( __FILE__ ) . 'includes/user-bridge.php';
|
||
require_once plugin_dir_path( __FILE__ ) . 'includes/shortcodes.php';
|
||
require_once plugin_dir_path( __FILE__ ) . 'includes/tracking-form.php';
|
||
|
||
// لود کردن استایلهای و اسکریپتهای پلاگین
|
||
add_action('wp_enqueue_scripts', 'ifnex_enqueue_scripts');
|
||
function ifnex_enqueue_scripts() {
|
||
global $post;
|
||
if (is_a($post, 'WP_Post') &&
|
||
(has_shortcode($post->post_content, 'ifnex_tracking_form') ||
|
||
has_shortcode($post->post_content, 'ifnex_wallet_balance') ||
|
||
has_shortcode($post->post_content, 'ifnex_transactions') ||
|
||
has_shortcode($post->post_content, 'ifnex_tracking_status') ||
|
||
has_shortcode($post->post_content, 'ifnex_order_form') ||
|
||
has_shortcode($post->post_content, 'ifnex_user_profile') ||
|
||
has_shortcode($post->post_content, 'ifnex_orders_list') ||
|
||
has_shortcode($post->post_content, 'ifnex_order_detail') ||
|
||
has_shortcode($post->post_content, 'ifnex_order_payment') ||
|
||
has_shortcode($post->post_content, 'ifnex_customer_dashboard'))) {
|
||
wp_enqueue_style('ifnex-bridge-css', plugin_dir_url(__FILE__) . 'assets/css/ifnex-bridge.css', array('ifnex-main'), ifnex_asset_version('assets/css/ifnex-bridge.css'));
|
||
// SweetAlert2 — پاپآپ خطاها (فاز ۳.۸) — باندل محلی، بدون وابستگی به CDN
|
||
wp_enqueue_script('sweetalert2', plugin_dir_url(__FILE__) . 'assets/js/sweetalert2.all.min.js', array(), '11.14.5', true);
|
||
wp_enqueue_script('ifnex-order-form-js', plugin_dir_url(__FILE__) . 'assets/js/ifnex-order-form.js', array('jquery', 'sweetalert2'), ifnex_asset_version('assets/js/ifnex-order-form.js'), true);
|
||
// دفترچه آدرس (فاز ۳.۹) — تب اختصاصی در پنل کاربری
|
||
wp_enqueue_script('ifnex-address-book-js', plugin_dir_url(__FILE__) . 'assets/js/ifnex-address-book.js', array('jquery', 'sweetalert2'), ifnex_asset_version('assets/js/ifnex-address-book.js'), true);
|
||
}
|
||
}
|
||
|
||
// اضافه کردن لینک به منوی پیشخوان وردپرس
|
||
add_action( 'admin_menu', 'ifnex_plugin_setup_menu' );
|
||
function ifnex_plugin_setup_menu() {
|
||
add_menu_page( 'تنظیمات IFNEX', 'IFNEX', 'manage_options', 'ifnex-settings', 'ifnex_settings_page_html', 'dashicons-location-alt', 30 );
|
||
}
|
||
|
||
function ifnex_settings_page_html() {
|
||
if (isset($_POST['ifnex_api_url']) && check_admin_referer('ifnex_settings_save')) {
|
||
update_option('ifnex_api_url', sanitize_url($_POST['ifnex_api_url']));
|
||
update_option('ifnex_api_key', sanitize_text_field($_POST['ifnex_api_key']));
|
||
update_option('ifnex_bridge_api_key', sanitize_text_field($_POST['ifnex_bridge_api_key'] ?? ''));
|
||
echo '<div class="notice notice-success"><p>تنظیمات ذخیره شد.</p></div>';
|
||
}
|
||
|
||
$api_url = get_option('ifnex_api_url', 'http://localhost:8000/api/v1');
|
||
$api_key = get_option('ifnex_api_key', '');
|
||
$bridge_api_key = get_option('ifnex_bridge_api_key', '');
|
||
?>
|
||
<div class="wrap">
|
||
<h1>تنظیمات IFNEX Logistics Bridge</h1>
|
||
<form method="post">
|
||
<?php wp_nonce_field('ifnex_settings_save'); ?>
|
||
<table class="form-table">
|
||
<tr>
|
||
<th scope="row"><label for="ifnex_api_url">API URL</label></th>
|
||
<td>
|
||
<input type="text" id="ifnex_api_url" name="ifnex_api_url" value="<?php echo esc_attr($api_url); ?>" class="regular-text" placeholder="http://localhost:8000/api/v1">
|
||
<p class="description">آدرس پایه API لاراول</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><label for="ifnex_api_key">API Key (عمومی)</label></th>
|
||
<td>
|
||
<input type="text" id="ifnex_api_key" name="ifnex_api_key" value="<?php echo esc_attr($api_key); ?>" class="regular-text">
|
||
<p class="description">برای APIهای عمومی مثل Tracking</p>
|
||
</td>
|
||
</tr>
|
||
<tr style="background: #fff3cd;">
|
||
<th scope="row"><label for="ifnex_bridge_api_key">🔐 Bridge API Key</label></th>
|
||
<td>
|
||
<input type="text" id="ifnex_bridge_api_key" name="ifnex_bridge_api_key" value="<?php echo esc_attr($bridge_api_key); ?>" class="regular-text">
|
||
<p class="description"><strong>مهم:</strong> باید با مقدار <code>IFNEX_BRIDGE_API_KEY</code> در فایل <code>.env</code> لاراول یکسان باشد.</p>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<?php submit_button('ذخیره تنظیمات'); ?>
|
||
</form>
|
||
|
||
<hr>
|
||
<h2>راهنمای راهاندازی</h2>
|
||
<ol>
|
||
<li>در فایل <code>.env</code> لاراول، خط <code>IFNEX_BRIDGE_API_KEY=your-secret-key</code> را تنظیم کنید</li>
|
||
<li>همان مقدار را در فیلد "Bridge API Key" بالا وارد کنید</li>
|
||
<li>کاربران وردپرس باید در لاراول با همان ایمیل موجود باشند (از <code>php artisan ifnex:sync-wp-users</code> استفاده کنید)</li>
|
||
</ol>
|
||
</div>
|
||
<?php
|
||
}
|