<?php

/**
 * custom CF7 to Pardot Form Handler
 *
 * @package   custom-cf7-pardot-form-handler
 * @copyright 2023 Derak Kilgo
 * @license   GPL v2 or later
 *
 * Plugin Name:  custom CF7 to Pardot Form Handler
 * Description:  Relay form data from a Contact Form 7 form to a Pardot Custom Form Handler endpoint.
 * Version:      0.0.1
 * Author:       Derak Kilgo
 * Requires PHP: 5.6
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

if (!defined('ABSPATH')) {
    exit;
}

add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), 'custom_cf7pfh_add_action_links' );

function custom_cf7pfh_add_action_links ( $actions ) {
    $mylinks = array(
        '<a href="https://gist.github.com/derak-kilgo/d561ca19764058a9d40a9dd9b11ed817">Docs</a>',
    );
    $actions = array_merge( $actions, $mylinks );
    return $actions;
}

add_action('wpcf7_submit','custom_cf7pfh_send',10,2);
/**
 *  Action to hook into when contact 7 forms are submitted. Form must include a "custom_pardot_form_action_url" arg.
 *  Example $result - {"contact_form_id":9999,"status":"mail_sent","message":"Thank you for your message. It has been sent.","posted_data_hash":"a685e3d41dxxxxxxxxxxxxxxxxx"}
 *
 * @param WPCF7_ContactForm $contact_form
 * @param array $result The result of submitting the form along with status and result messaging.
 * @return void
 */
function custom_cf7pfh_send($contact_form,$result){

    //based on flamingo.php by Takayuki Miyoshi
    $submission = WPCF7_Submission::get_instance();
    if ( ! $submission or ! $posted_data = $submission->get_posted_data() ) {
        //do nothing. No submission obj means we can't get posted data.
        return;
    }

    $tmpSettings = $contact_form->additional_setting('custom_pardot_form_action_url',1);
    if(empty($tmpSettings[0])){
        //do nothing. We don't have an action to take.
        return;
    }
    $pardot_action_url = (string) $tmpSettings[0];
    unset($tmpSettings);

    //Send data to the form endpoint.
    //@see https://help.salesforce.com/s/articleView?id=000383081&type=1
//    $wp_remote_post_result = wp_remote_post($pardot_action_url,array(
//        'method' => 'POST',
//        'headers' => array('Content-Type' => 'application/x-www-form-urlencoded'),
//        'body' => $posted_data
//    ));
    $wp_remote_post_result = custom_post_to_url($pardot_action_url,$posted_data);

    if(defined('WP_DEBUG') && WP_DEBUG === true) {
        $data = [
            'timestamp' => microtime(true),
            'posted_data' => $posted_data,
            'pardot_action_url' => $pardot_action_url,
            'remote_post_result' => $wp_remote_post_result
        ];
        $json = print_r($data, true);
        file_put_contents(__DIR__ . '/output.log', $json . "\n\n\n", FILE_APPEND);
        /* end debugging */
    }
}

/**
 * Send POST form data to pardot.
 * WordPress wp_remote_post() doesn't seem to work with pardot.
 *
 * @param $target_url
 * @param $post_data
 * @return array
 */
function custom_post_to_url ($target_url,$post_data){

    //This works around some gotchas with pardot form handlers.
    //pardot does not support multi-part form.
    //@see https://help.salesforce.com/s/articleView?id=000383081&type=1
    //@see http://php.net/manual/en/function.curl-setopt.php CURLOPT_POSTFIELDS
    //Portions of this code generated by insomnia/2023.5.8

    $curl = curl_init();
    $post_string = http_build_query($post_data);
    curl_setopt_array($curl, [
        CURLOPT_URL => $target_url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING => "",
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 30,
        CURLINFO_HEADER_OUT=>true,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => "POST",
        CURLOPT_POSTFIELDS => $post_string,
        CURLOPT_HTTPHEADER => [
            "Content-Type: application/x-www-form-urlencoded",
            "User-Agent: customPardotFormRelay/0.0.1"
        ],
    ]);


    //Capture response headers safely. See RFC822 RFC2616 RFC7230
    //@see https://stackoverflow.com/a/41135574
    $response_headers = [];
    // this function is called by curl for each header received
    curl_setopt($curl, CURLOPT_HEADERFUNCTION,
        function($curl, $header) use (&$response_headers)
        {
            $len = strlen($header);
            $header = explode(':', $header, 2);
            if (count($header) < 2) // ignore invalid headers
                return $len;

            $response_headers[strtolower(trim($header[0]))][] = trim($header[1]);

            return $len;
        }
    );

    //Make request
    $response = curl_exec($curl);
    $err = curl_error($curl);

    //Collect output
    $out = array();
    $out['response_body'] = curl_exec($curl);
    //NOTE: this may need to be updated in the future to use CURLINFO_RESPONSE_CODE instead.
    $out['response_code'] = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    $out['response_headers'] = $response_headers;
    $out['error'] = curl_error($curl);
    $out['request_headers'] = curl_getinfo($curl,CURLINFO_HEADER_OUT);

    curl_close($curl);

    return $out;
}