gravityforms-freescout/gravityforms-freescout.php

213 lines
8.4 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Plugin Name: Gravity Forms to FreeScout
* Description: 表单提交后通过 FreeScout API 创建工单feibisi 自维护,替代 freescout.net/neoboffin 付费插件的免费实现)。
* Version: 1.0.0
* Author: feibisi
* Requires Plugins: gravityforms
* Text Domain: gravityforms-freescout
*/
if (!defined('ABSPATH')) {
exit;
}
define('GFFS_VERSION', '1.0.0');
define('GFFS_OPT', 'gffs_settings');
add_action('admin_menu', function () {
add_options_page(
'Gravity Forms → FreeScout',
'GF → FreeScout',
'manage_options',
'gffs-settings',
'gffs_render_settings_page'
);
});
add_action('admin_init', function () {
register_setting('gffs_settings_group', GFFS_OPT, [
'type' => 'array',
'sanitize_callback' => 'gffs_sanitize_settings',
'default' => [],
]);
});
function gffs_sanitize_settings($input) {
$out = [];
$out['api_url'] = isset($input['api_url']) ? esc_url_raw(rtrim($input['api_url'], '/')) : '';
$out['api_key'] = isset($input['api_key']) ? sanitize_text_field($input['api_key']) : '';
$out['mailbox_id'] = isset($input['mailbox_id']) ? absint($input['mailbox_id']) : 1;
$out['enabled_forms'] = isset($input['enabled_forms']) ? array_map('absint', (array) $input['enabled_forms']) : [];
$out['email_field_id'] = isset($input['email_field_id']) ? sanitize_text_field($input['email_field_id']) : '';
$out['subject_prefix'] = isset($input['subject_prefix']) ? sanitize_text_field($input['subject_prefix']) : '[网站表单]';
return $out;
}
function gffs_get_settings() {
$s = get_option(GFFS_OPT, []);
return wp_parse_args(is_array($s) ? $s : [], [
'api_url' => 'https://support.weixiaoduo.com',
'api_key' => '',
'mailbox_id' => 1,
'enabled_forms' => [],
'email_field_id' => '',
'subject_prefix' => '[网站表单]',
]);
}
function gffs_render_settings_page() {
if (!current_user_can('manage_options')) {
return;
}
$s = gffs_get_settings();
$forms = [];
if (class_exists('GFAPI')) {
$forms = GFAPI::get_forms(true);
}
?>
<div class="wrap">
<h1>Gravity Forms → FreeScout</h1>
<p>提交表单后调用 FreeScout REST API 创建工单。需要 FreeScout 已安装 <strong>API &amp; Webhooks</strong> 模块。</p>
<form method="post" action="options.php">
<?php settings_fields('gffs_settings_group'); ?>
<table class="form-table" role="presentation">
<tr>
<th><label for="gffs_api_url">FreeScout URL</label></th>
<td><input name="<?php echo esc_attr(GFFS_OPT); ?>[api_url]" id="gffs_api_url" type="url" class="regular-text" value="<?php echo esc_attr($s['api_url']); ?>" placeholder="https://support.example.com"></td>
</tr>
<tr>
<th><label for="gffs_api_key">API Key</label></th>
<td><input name="<?php echo esc_attr(GFFS_OPT); ?>[api_key]" id="gffs_api_key" type="text" class="regular-text" value="<?php echo esc_attr($s['api_key']); ?>" autocomplete="off"></td>
</tr>
<tr>
<th><label for="gffs_mailbox_id">Mailbox ID</label></th>
<td><input name="<?php echo esc_attr(GFFS_OPT); ?>[mailbox_id]" id="gffs_mailbox_id" type="number" min="1" value="<?php echo esc_attr($s['mailbox_id']); ?>"> <span class="description">默认 1薇晓朵客服</span></td>
</tr>
<tr>
<th><label for="gffs_subject_prefix">主题前缀</label></th>
<td><input name="<?php echo esc_attr(GFFS_OPT); ?>[subject_prefix]" id="gffs_subject_prefix" type="text" class="regular-text" value="<?php echo esc_attr($s['subject_prefix']); ?>"></td>
</tr>
<tr>
<th>启用的表单</th>
<td>
<?php if (!$forms) : ?>
<p class="description">未找到 Gravity Forms 表单。</p>
<?php else : ?>
<?php foreach ($forms as $form) :
$id = (int) $form['id'];
$checked = in_array($id, $s['enabled_forms'], true) ? 'checked' : '';
?>
<label style="display:block;margin:4px 0">
<input type="checkbox" name="<?php echo esc_attr(GFFS_OPT); ?>[enabled_forms][]" value="<?php echo $id; ?>" <?php echo $checked; ?>>
#<?php echo $id; ?> — <?php echo esc_html($form['title']); ?>
</label>
<?php endforeach; ?>
<p class="description">不勾选任何表单 = 全部表单启用。</p>
<?php endif; ?>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}
/**
* After GF submit → FreeScout conversation.
*/
add_action('gform_after_submission', 'gffs_after_submission', 20, 2);
function gffs_after_submission($entry, $form) {
$s = gffs_get_settings();
if (empty($s['api_url']) || empty($s['api_key'])) {
return;
}
$form_id = (int) ($form['id'] ?? 0);
if (!empty($s['enabled_forms']) && !in_array($form_id, $s['enabled_forms'], true)) {
return;
}
$email = gffs_find_email($entry, $form);
if (!$email) {
// FreeScout API requires customer_email
$email = 'form+' . $form_id . '@noreply.local';
}
$title = $form['title'] ?? ('Form #' . $form_id);
$subject = trim(($s['subject_prefix'] ? $s['subject_prefix'] . ' ' : '') . $title);
$body = gffs_build_body($entry, $form);
$payload = [
'mailbox_id' => (int) $s['mailbox_id'] ?: 1,
'subject' => mb_substr($subject, 0, 200),
'customer_email' => $email,
'body' => $body,
'status' => 'active',
'type' => 'email',
];
$url = rtrim($s['api_url'], '/') . '/api/v1/conversations';
$resp = wp_remote_post($url, [
'timeout' => 20,
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'X-Api-Key' => $s['api_key'],
],
'body' => wp_json_encode($payload),
]);
if (is_wp_error($resp)) {
error_log('[GFFS] FreeScout error: ' . $resp->get_error_message());
return;
}
$code = wp_remote_retrieve_response_code($resp);
$body_r = wp_remote_retrieve_body($resp);
if ($code < 200 || $code >= 300) {
error_log('[GFFS] FreeScout HTTP ' . $code . ' ' . substr($body_r, 0, 300));
}
}
function gffs_find_email($entry, $form) {
foreach ($form['fields'] as $field) {
$type = is_object($field) ? $field->type : ($field['type'] ?? '');
$id = is_object($field) ? $field->id : ($field['id'] ?? '');
if ($type === 'email' && !empty($entry[$id])) {
return sanitize_email($entry[$id]);
}
}
// common: field 1 is email
foreach ($entry as $k => $v) {
if (is_string($v) && is_email($v)) {
return sanitize_email($v);
}
}
return '';
}
function gffs_build_body($entry, $form) {
$lines = [];
$lines[] = '<p><strong>Gravity Form:</strong> ' . esc_html($form['title'] ?? '') . ' (#' . (int) $form['id'] . ')</p>';
$lines[] = '<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse">';
foreach ($form['fields'] as $field) {
$type = is_object($field) ? $field->type : ($field['type'] ?? '');
$id = is_object($field) ? $field->id : ($field['id'] ?? '');
$label = is_object($field) ? $field->label : ($field['label'] ?? ('Field ' . $id));
if (in_array($type, ['html', 'section', 'page', 'captcha', 'honeypot'], true)) {
continue;
}
$val = rgar($entry, (string) $id);
if ($val === '' || $val === null) {
continue;
}
if (is_array($val)) {
$val = implode(', ', $val);
}
$lines[] = '<tr><th align="left">' . esc_html($label) . '</th><td>' . nl2br(esc_html((string) $val)) . '</td></tr>';
}
$lines[] = '</table>';
$lines[] = '<p style="color:#888;font-size:12px">via Gravity Forms to FreeScout ' . GFFS_VERSION . '</p>';
return implode("\n", $lines);
}