chore: initial snapshot of 2meet-data-optimizer-latepoint-addon v0.1.0
Baseline before backporting wp-data-optimizer v3.0.1-v3.4.6. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
This commit is contained in:
+16
@@ -0,0 +1,16 @@
|
|||||||
|
vendor/
|
||||||
|
node_modules/
|
||||||
|
.phpunit.result.cache
|
||||||
|
.phpcs-cache
|
||||||
|
*.log
|
||||||
|
*.bak
|
||||||
|
*.swp
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
.full-review/
|
||||||
|
.gstack/
|
||||||
|
.playwright-mcp/
|
||||||
|
.claude/
|
||||||
|
dist/
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin Name: 2meet Data Optimizer — Latepoint AddOn
|
||||||
|
* Plugin URI: https://2meet.io/2meet-data-optimizer/latepoint
|
||||||
|
* Description: LatePoint 預約系統 booking 索引同步(4 hook → wp_hpct_latepoint_idx)
|
||||||
|
* Version: 0.1.0
|
||||||
|
* Requires at least: 6.0
|
||||||
|
* Tested up to: 6.9.4
|
||||||
|
* Requires PHP: 8.1
|
||||||
|
* Requires Plugins: 2meet-data-optimizer, latepoint
|
||||||
|
* Author: 2meet
|
||||||
|
* Author URI: https://2meet.io
|
||||||
|
* License: GPL-2.0-or-later
|
||||||
|
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
* Text Domain: tmdo-latepoint
|
||||||
|
* Domain Path: /languages
|
||||||
|
*
|
||||||
|
* @package TMDO_LATEPOINT
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
define( 'TMDO_LATEPOINT_VERSION', '0.1.0' );
|
||||||
|
define( 'TMDO_LATEPOINT_PATH', plugin_dir_path( __FILE__ ) );
|
||||||
|
define( 'TMDO_LATEPOINT_URL', plugin_dir_url( __FILE__ ) );
|
||||||
|
define( 'TMDO_LATEPOINT_FILE', __FILE__ );
|
||||||
|
|
||||||
|
require_once TMDO_LATEPOINT_PATH . 'includes/class-tmdo-latepoint-bootstrap.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Phase 3 任務:完成本 AddOn 的 includes/ 實作。
|
||||||
|
*
|
||||||
|
* @see ~/.claude/plans/wp-data-optimizer-2meet-data-optimizer-zesty-liskov.md
|
||||||
|
*/
|
||||||
|
add_action( 'plugins_loaded', array( 'TMDO_Latepoint_Bootstrap', 'init' ), 6 );
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this AddOn will be documented here.
|
||||||
|
|
||||||
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||||
|
Versioning follows [Semantic Versioning](https://semver.org/).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
- Phase 3 implementation in progress.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [0.1.0] — TBD
|
||||||
|
|
||||||
|
### Added (initial release, scaffold)
|
||||||
|
|
||||||
|
- Plugin scaffold from `wp-data-optimizer v2.16.0` extraction plan.
|
||||||
|
- Plugin Header + bootstrap stub + 7 MD + composer.json.
|
||||||
|
- Requires Plugins: `2meet-data-optimizer`, `latepoint`.
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
# CLAUDE.md — 2meet Data Optimizer Latepoint AddOn
|
||||||
|
|
||||||
|
> 父外掛:`../2meet-data-optimizer/CLAUDE.md`
|
||||||
|
> 父環境:`/var/www/Studio/wp-local-dev30/CLAUDE.md`
|
||||||
|
> 全域:`~/.claude/CLAUDE.md`(含 Karpathy Guidelines)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reset recovery
|
||||||
|
|
||||||
|
1. 讀本檔
|
||||||
|
2. 讀 [PLAN.md](PLAN.md) 看 Phase 3 進度
|
||||||
|
3. 接續下一個未完成步驟
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Plugin 概述
|
||||||
|
|
||||||
|
**2meet-data-optimizer-latepoint-addon** 是 2meet-data-optimizer 的 Latepoint 整合 AddOn。
|
||||||
|
|
||||||
|
- **目標外掛**: `latepoint`
|
||||||
|
- **Phase**: 3
|
||||||
|
- **預估行數**: ~151
|
||||||
|
- **Slug 短碼**: `latepoint`
|
||||||
|
|
||||||
|
簡述:LatePoint 預約系統 booking 索引同步(4 hook)
|
||||||
|
|
||||||
|
完整拆分計畫見 `~/.claude/plans/wp-data-optimizer-2meet-data-optimizer-zesty-liskov.md`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 邊界
|
||||||
|
|
||||||
|
- ✅ 本 AddOn 觸碰:latepoint 相關 schema 註冊(postmeta zone fields / custom tables / entity groups)+ 可選 admin / CLI
|
||||||
|
- ❌ 本 AddOn **不**觸碰:2meet-data-optimizer 核心、其他 AddOn、目標外掛 runtime 邏輯
|
||||||
|
- ❌ 本 AddOn **不**繞過:Hook Bus / TMDO_API(必須走公開合約)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 命名前綴
|
||||||
|
|
||||||
|
- 類別:`TMDO_Latepoint_*`
|
||||||
|
- 函式:`tmdo_latepoint_*`
|
||||||
|
- 常數:`TMDO_LATEPOINT_VERSION` / `TMDO_LATEPOINT_PATH` / `TMDO_LATEPOINT_URL` / `TMDO_LATEPOINT_FILE`
|
||||||
|
- Text-domain:`tmdo-latepoint`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 公開合約消費(從核心)
|
||||||
|
|
||||||
|
```php
|
||||||
|
// 安全消費 API(必加 class_exists guard)
|
||||||
|
if ( class_exists( 'TMDO_API' ) ) {
|
||||||
|
TMDO_API::set_entity( 'user', $id, 'key', $value );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schema 註冊
|
||||||
|
add_action( 'tmdo_register_entity_fields', function ( $registry_class ) {
|
||||||
|
$registry_class::register_group( '...', '...', [ ... ] );
|
||||||
|
} );
|
||||||
|
|
||||||
|
add_action( 'tmdo_register_custom_tables', function ( $registry ) {
|
||||||
|
$registry->register( 'latepoint-addon', [ ... ] );
|
||||||
|
} );
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 進度
|
||||||
|
|
||||||
|
```
|
||||||
|
Phase 0 ✅ 骨架建立 (2026-05-15)
|
||||||
|
Phase 3 ⬜ Implementation v0.1.0
|
||||||
|
```
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# 部署流程
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. `2meet-data-optimizer` 核心 ≥ 0.1.0 已安裝並啟用
|
||||||
|
2. `latepoint` 已安裝並啟用
|
||||||
|
|
||||||
|
> 本 AddOn 透過 WordPress `Requires Plugins:` 強制相依,先決條件未滿足時無法啟用。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 上傳 + 啟用
|
||||||
|
wp plugin install /path/to/2meet-data-optimizer-latepoint-addon-v0.1.0.zip --activate
|
||||||
|
|
||||||
|
# 驗證
|
||||||
|
wp tmdo doctor --provider=latepoint-addon
|
||||||
|
wp tmdo custom-tables --provider=latepoint-addon
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wp plugin deactivate 2meet-data-optimizer-latepoint-addon
|
||||||
|
# 目標外掛 (latepoint) 仍可正常運作,
|
||||||
|
# 讀寫 fall back 到 native meta(失去 zone 加速但功能不受影響)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 整體部署順序建議
|
||||||
|
|
||||||
|
依 Phase 順序:
|
||||||
|
1. `2meet-data-optimizer` 核心
|
||||||
|
2. Phase 2: `2meet-data-optimizer-hub-addon`、`2meet-data-optimizer-spoke-addon`
|
||||||
|
3. Phase 3: HivePress / WooCommerce / LatePoint AddOn
|
||||||
|
4. Phase 4: 6 個 2meet 家族 AddOn
|
||||||
|
|
||||||
|
詳見核心外掛 [DEPLOY.md](../2meet-data-optimizer/DEPLOY.md)。
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# DESIGN — 2meet Data Optimizer Latepoint AddOn
|
||||||
|
|
||||||
|
> 父外掛架構決策見 [`../2meet-data-optimizer/DESIGN.md`](../2meet-data-optimizer/DESIGN.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 角色定位
|
||||||
|
|
||||||
|
本 AddOn 是 `2meet-data-optimizer` 的整合層,負責將 `latepoint` 的 EAV 模式(postmeta / 自訂表)橋接到核心反 EAV 引擎。
|
||||||
|
|
||||||
|
- **不**修改 `latepoint` 本身
|
||||||
|
- **不**繞過 `2meet-data-optimizer` 核心
|
||||||
|
- 只透過公開合約(`TMDO_API`、`tmdo_register_*` hook)參與
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 啟動順序
|
||||||
|
|
||||||
|
```
|
||||||
|
plugins_loaded:4 2meet-data-optimizer (core) 啟動
|
||||||
|
plugins_loaded:5-6 本 AddOn bootstrap → 註冊 hook callback
|
||||||
|
plugins_loaded:6+ latepoint 本體啟動
|
||||||
|
init:0 核心 fire tmdo_register_* → 本 AddOn 的 callback 執行
|
||||||
|
```
|
||||||
|
|
||||||
|
詳見 plan 文件第 3 章「載入順序」。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 為什麼是獨立 AddOn 而非塞進核心
|
||||||
|
|
||||||
|
- 核心 `2meet-data-optimizer` 對外承諾「零依存任何業務外掛」
|
||||||
|
- 整合層發版節奏應跟隨 `latepoint` 而非核心
|
||||||
|
- 站台不用 `latepoint` 時不需被迫載入這段程式碼
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 邊界檢查清單
|
||||||
|
|
||||||
|
- [ ] 不直接 `SELECT FROM wp_*meta`
|
||||||
|
- [ ] 不繞過 Hook Bus
|
||||||
|
- [ ] 所有 SQL 走 `$wpdb->prepare()`
|
||||||
|
- [ ] DB 表名走 `TMDO_DB::table()`
|
||||||
|
- [ ] 對外只 expose `TMDO_Latepoint_*` 命名空間
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# PLAN — 2meet Data Optimizer Latepoint AddOn
|
||||||
|
|
||||||
|
> 完整四階段拆分計畫見 `~/.claude/plans/wp-data-optimizer-2meet-data-optimizer-zesty-liskov.md` (本 AddOn 屬 **Phase 3**)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Current state
|
||||||
|
|
||||||
|
- **Version**: 0.1.0 (in development, scaffold complete 2026-05-15)
|
||||||
|
- **Phase**: Phase 0 → Phase 3 pending
|
||||||
|
- **Source**: 從 `wp-data-optimizer v2.16.0` 提煉
|
||||||
|
- **預估行數**: ~151 行
|
||||||
|
- **目標外掛**: `latepoint`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 0 ✅ — 骨架建立 (2026-05-15)
|
||||||
|
|
||||||
|
- [x] 目錄結構
|
||||||
|
- [x] Plugin Header
|
||||||
|
- [x] Bootstrap stub
|
||||||
|
- [x] 7 件 MD
|
||||||
|
- [x] composer.json / .gitignore / uninstall.php
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3 ⬜ — Implementation v0.1.0
|
||||||
|
|
||||||
|
詳細任務見上層 plan 第 5 章。簡述:
|
||||||
|
|
||||||
|
- [ ] 從 wp-data-optimizer 對應檔案搬入 includes/
|
||||||
|
- [ ] WPDO_ → TMDO_Latepoint_ 重命名
|
||||||
|
- [ ] 移除對 wp-data-optimizer 內部 class 的依存(改走 TMDO_API 公開合約)
|
||||||
|
- [ ] 完善 bootstrap:實作 init() 載入順序
|
||||||
|
- [ ] 補完 7 件 MD 的細節
|
||||||
|
- [ ] 跑 `scripts/package-plugin.sh 2meet-data-optimizer-latepoint-addon` 通過 10 終檢
|
||||||
|
- [ ] dev30 e2e
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Lessons learned
|
||||||
|
|
||||||
|
- (Phase 3 起記錄)
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
# 2meet Data Optimizer — LatePoint AddOn
|
||||||
|
|
||||||
|
> 為 **LatePoint** 預約系統提供 booking 索引同步(最小 AddOn,~151 行)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
監聽 4 個 LatePoint hook,將 booking 摘要寫入 `wp_hpct_latepoint_idx` 自訂索引表,加速跨站查詢與報表:
|
||||||
|
|
||||||
|
| LP Hook | 動作 |
|
||||||
|
|---|---|
|
||||||
|
| `latepoint_booking_created` | INSERT 索引 |
|
||||||
|
| `latepoint_booking_updated` | UPDATE 索引 |
|
||||||
|
| `latepoint_after_booking_save` | UPSERT 索引 |
|
||||||
|
| `latepoint_booking_deleted` | DELETE 索引 |
|
||||||
|
|
||||||
|
索引欄位:`booking_id`, `agent_id`, `service_id`, `customer_id`, `status`, `start_date`, `end_date`, `start_time`, `end_time`, `price`, `created_at`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- WordPress ≥ 6.0
|
||||||
|
- PHP ≥ 8.1
|
||||||
|
- 2meet-data-optimizer ≥ 0.1.0
|
||||||
|
- LatePoint ≥ 3.0(建議現代版本)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wp plugin install /path/to/2meet-data-optimizer-latepoint-addon-v0.1.0.zip --activate
|
||||||
|
|
||||||
|
# 驗證
|
||||||
|
wp tmdo doctor --table=hpct_latepoint_idx
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 為什麼是「索引」而非反 EAV
|
||||||
|
|
||||||
|
LatePoint 自身已用 custom table(`wp_latepoint_bookings`)儲存 booking,無 EAV 問題。本 AddOn 不修改 LP 本體 schema,僅維護一份**輕量索引**供:
|
||||||
|
|
||||||
|
- 跨站台 booking 統計(infocards, 2meet-bookings 等共用聚合)
|
||||||
|
- 高效能 vendor agent 篩選
|
||||||
|
- 過去 / 未來預約快查
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase
|
||||||
|
|
||||||
|
Phase 3 — 與 [HivePress AddOn](../2meet-data-optimizer-hivepress-addon/) 與 [WooCommerce AddOn](../2meet-data-optimizer-woocommerce-addon/) 同期 ship。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
GPL-2.0-or-later
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported versions
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
|---|:-:|
|
||||||
|
| 0.1.x | ✅ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reporting a vulnerability
|
||||||
|
|
||||||
|
請參考核心外掛 [SECURITY.md](../2meet-data-optimizer/SECURITY.md)。
|
||||||
|
|
||||||
|
簡述:
|
||||||
|
- Email: security@2meet.io
|
||||||
|
- 請勿在 public GitHub issue 揭露
|
||||||
|
- 24h 內初步回應、7 天內提供修補時程
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 安全設計
|
||||||
|
|
||||||
|
本 AddOn 完全遵守 2meet-data-optimizer 核心安全設計:
|
||||||
|
|
||||||
|
- SQL prepared statements
|
||||||
|
- Capability check (`manage_options`)
|
||||||
|
- Nonce 驗證
|
||||||
|
- Output escaping
|
||||||
|
- 反序列化走 `TMDO_Safe_Unserialize`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 已知 Risk
|
||||||
|
|
||||||
|
- (本版本暫無已知安全 risk;Phase 3 ship 時補)
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "2meet/2meet-data-optimizer-latepoint-addon",
|
||||||
|
"description": "LatePoint 預約系統 booking 索引同步(4 hook)",
|
||||||
|
"type": "wordpress-plugin",
|
||||||
|
"license": "GPL-2.0-or-later",
|
||||||
|
"keywords": ["wordpress", "2meet-data-optimizer", "addon", "latepoint"],
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^10.5",
|
||||||
|
"wp-coding-standards/wpcs": "^3.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"phpcs": "phpcs --standard=WordPress includes/ 2meet-data-optimizer-latepoint-addon.php"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"allow-plugins": {
|
||||||
|
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||||
|
},
|
||||||
|
"optimize-autoloader": true,
|
||||||
|
"preferred-install": "dist",
|
||||||
|
"sort-packages": true
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+2106
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Bootstrap for 2meet Data Optimizer LatePoint AddOn.
|
||||||
|
*
|
||||||
|
* @package TMDO_LATEPOINT
|
||||||
|
* @since 0.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
final class TMDO_Latepoint_Bootstrap {
|
||||||
|
|
||||||
|
public static function init(): void {
|
||||||
|
if ( ! class_exists( 'TMDO_API' ) && ! class_exists( 'WPDO_API' ) ) {
|
||||||
|
add_action( 'admin_notices', array( __CLASS__, 'missing_core_notice' ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
load_plugin_textdomain(
|
||||||
|
'tmdo-latepoint',
|
||||||
|
false,
|
||||||
|
dirname( plugin_basename( TMDO_LATEPOINT_FILE ) ) . '/languages'
|
||||||
|
);
|
||||||
|
|
||||||
|
require_once TMDO_LATEPOINT_PATH . 'includes/class-tmdo-latepoint-interceptor.php';
|
||||||
|
|
||||||
|
if ( class_exists( 'TMDO_LatePoint_Interceptor' ) ) {
|
||||||
|
( new TMDO_LatePoint_Interceptor() )->register_hooks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function missing_core_notice(): void {
|
||||||
|
echo '<div class="notice notice-error"><p>';
|
||||||
|
echo esc_html__( '2meet Data Optimizer LatePoint AddOn 需要 2meet-data-optimizer 核心外掛,請先安裝並啟用。', 'tmdo-latepoint' );
|
||||||
|
echo '</p></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* LatePoint interceptor for booking index synchronization.
|
||||||
|
*
|
||||||
|
* @package WP_Data_Optimizer
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LatePoint interceptor — maintains booking index in hpct_latepoint_idx.
|
||||||
|
* Syncs from LatePoint custom tables.
|
||||||
|
*/
|
||||||
|
class TMDO_LatePoint_Interceptor extends TMDO_Interceptor_Base {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module identifier.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected string $module = 'latepoint';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers WordPress hooks for this interceptor.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register_hooks(): void {
|
||||||
|
add_action( 'latepoint_booking_created', array( $this, 'action_booking_changed' ), 10, 1 );
|
||||||
|
add_action( 'latepoint_booking_updated', array( $this, 'action_booking_changed' ), 10, 1 );
|
||||||
|
add_action( 'latepoint_after_booking_save', array( $this, 'action_booking_changed' ), 10, 1 );
|
||||||
|
add_action( 'latepoint_booking_deleted', array( $this, 'action_booking_deleted' ), 10, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syncs a booking when it is created or updated.
|
||||||
|
*
|
||||||
|
* @param mixed $booking Booking object, array, or ID.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function action_booking_changed( $booking ): void {
|
||||||
|
if ( ! $this->is_active() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$booking_id = $this->extract_id( $booking );
|
||||||
|
if ( ! $booking_id ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->sync_booking( $booking_id );
|
||||||
|
} catch ( \Throwable $e ) {
|
||||||
|
TMDO_Logger::error( $this->module, 'booking_changed', $e->getMessage() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a booking index record when a booking is deleted.
|
||||||
|
*
|
||||||
|
* @param mixed $booking Booking object, array, or ID.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function action_booking_deleted( $booking ): void {
|
||||||
|
if ( ! $this->is_active() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$booking_id = $this->extract_id( $booking );
|
||||||
|
if ( ! $booking_id ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
global $wpdb;
|
||||||
|
$wpdb->delete( TMDO_DB::table( 'hpct_latepoint_idx' ), array( 'booking_id' => $booking_id ), array( '%d' ) );
|
||||||
|
} catch ( \Throwable $e ) {
|
||||||
|
TMDO_Logger::error( $this->module, 'booking_deleted', $e->getMessage() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts a booking ID from various input types.
|
||||||
|
*
|
||||||
|
* @param mixed $booking Booking object, array, or integer ID.
|
||||||
|
* @return int Booking ID, or 0 if not found.
|
||||||
|
*/
|
||||||
|
private function extract_id( $booking ): int {
|
||||||
|
if ( is_object( $booking ) && isset( $booking->id ) ) {
|
||||||
|
return (int) $booking->id;
|
||||||
|
}
|
||||||
|
if ( is_array( $booking ) && isset( $booking['id'] ) ) {
|
||||||
|
return (int) $booking['id'];
|
||||||
|
}
|
||||||
|
return (int) $booking;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syncs a LatePoint booking to the hpct_latepoint_idx table.
|
||||||
|
*
|
||||||
|
* @param int $booking_id Booking ID.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function sync_booking( int $booking_id ): void {
|
||||||
|
global $wpdb;
|
||||||
|
$table = TMDO_DB::table( 'hpct_latepoint_idx' );
|
||||||
|
$now = TMDO_DB::now();
|
||||||
|
|
||||||
|
// Read from LatePoint's own table.
|
||||||
|
$lp_table = $wpdb->prefix . 'latepoint_bookings';
|
||||||
|
$row = $wpdb->get_row(
|
||||||
|
$wpdb->prepare( "SELECT * FROM `{$lp_table}` WHERE id = %d LIMIT 1", $booking_id ), // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- lp_table is $wpdb->prefix . 'latepoint_bookings', prefix-validated.
|
||||||
|
ARRAY_A
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! $row ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
'booking_id' => $booking_id,
|
||||||
|
'agent_id' => (int) ( $row['agent_id'] ?? 0 ),
|
||||||
|
'service_id' => (int) ( $row['service_id'] ?? 0 ),
|
||||||
|
'customer_id' => (int) ( $row['customer_id'] ?? 0 ),
|
||||||
|
'status' => sanitize_text_field( $row['status'] ?? '' ),
|
||||||
|
'start_date' => $row['start_date'] ?? null,
|
||||||
|
'end_date' => $row['end_date'] ?? null,
|
||||||
|
'start_time' => (int) ( $row['start_time'] ?? 0 ),
|
||||||
|
'end_time' => (int) ( $row['end_time'] ?? 0 ),
|
||||||
|
'price' => $row['payment_amount'] ?? '0',
|
||||||
|
'created_at' => $row['created_at'] ?? $now,
|
||||||
|
);
|
||||||
|
|
||||||
|
$existing = $wpdb->get_var(
|
||||||
|
$wpdb->prepare( "SELECT id FROM `{$table}` WHERE booking_id = %d LIMIT 1", $booking_id ) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name validated by TMDO_DB::table() + sanitize_key().
|
||||||
|
);
|
||||||
|
|
||||||
|
$row_format = array( '%d', '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%d', '%s', '%s' );
|
||||||
|
|
||||||
|
if ( $existing ) {
|
||||||
|
$update_data = $data;
|
||||||
|
unset( $update_data['booking_id'], $update_data['created_at'] );
|
||||||
|
$update_format = array_slice( $row_format, 1, count( $update_data ) );
|
||||||
|
$wpdb->update( $table, $update_data, array( 'booking_id' => $booking_id ), $update_format, array( '%d' ) );
|
||||||
|
} else {
|
||||||
|
$wpdb->insert( $table, $data, $row_format );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Uninstall handler for 2meet Data Optimizer Latepoint AddOn.
|
||||||
|
*
|
||||||
|
* 僅清理本 AddOn 自有 schema(核心 wp_wpdo_* 系統表保留給 core)。
|
||||||
|
*
|
||||||
|
* @package TMDO_LATEPOINT
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase 3 完整實作。Phase 0 stub:保留所有資料以避免誤刪。
|
||||||
Reference in New Issue
Block a user