/home/ivoiecob/ivoiceoutsourcing.net/wp-content/plugins/leadconnector/admin/class-lc-admin.php
<?php
/**
* The admin-specific functionality of the plugin.
*
* @link http://example.com
* @since 1.0.0
*
* @package LeadConnector
* @subpackage LeadConnector/admin
*/
/**
* The admin-specific functionality of the plugin.
*
* Defines the plugin name, version, and two examples hooks for how to
* enqueue the admin-specific stylesheet and JavaScript.
*
* @package LeadConnector
* @subpackage LeadConnector/admin
* @author Harsh Kurra
*/
class LeadConnector_Admin
{
/**
* The ID of this plugin.
*
* @since 1.0.0
* @access private
* @var string $plugin_name The ID of this plugin.
*/
private $plugin_name;
/**
* The version of this plugin.
*
* @since 1.0.0
* @access private
* @var string $version The current version of this plugin.
*/
private $version;
/**
* Initialize the class and set its properties.
*
* @since 1.0.0
* @param string $plugin_name The name of this plugin.
* @param string $version The version of this plugin.
*/
public function __construct($plugin_name, $version)
{
require_once plugin_dir_path(dirname(__FILE__)) . 'includes/lc-constants.php';
require_once plugin_dir_path(dirname(__FILE__)) . 'admin/partials/lc-admin-display.php';
require_once plugin_dir_path(dirname(__FILE__)) . 'includes/lc-menu-handler.php';
require_once plugin_dir_path(dirname(__FILE__)) . 'includes/State/StateUpdate.php';
require_once plugin_dir_path(dirname(__FILE__)) . 'includes/Logger/logger.php';
require_once plugin_dir_path(dirname(__FILE__)) . 'includes/CutomValues/CustomValues.php';
$this->plugin_name = $plugin_name;
$this->version = $version;
// Replace admin bar notification with admin notice banner
add_action('admin_notices', array($this, 'display_payment_failed_banner'));
add_action('admin_head', array($this, 'add_payment_notification_styles'));
// Ensure dashicons are loaded in frontend for non-admin users
add_action('wp_enqueue_scripts', array($this, 'enqueue_dashicons'));
}
/**
* Display a payment failed banner at the top of all admin pages
*
* @since 1.0.0
*/
public function display_payment_failed_banner()
{
// Only display the banner if LC_PAYMENT_FAILED is defined and true
if (!defined('LC_PAYMENT_FAILED') || LC_PAYMENT_FAILED !== true) {
return;
}
// Get domain and location ID from constants, or use defaults
$company_domain = defined('LC_COMPANY_DOMAIN') ? LC_COMPANY_DOMAIN : 'app.leadconnectorhq.com';
$location_id = defined('LC_LOCATION_ID') ? LC_LOCATION_ID : '';
// Build the payment URL
$payment_url = $company_domain . '/v2/location/' . $location_id . '/wordpress/dashboard';
// Add https:// if not included in the domain
if (strpos($payment_url, 'http') !== 0) {
$payment_url = 'https://' . $payment_url;
}
?>
<div class="lc-payment-notice-wrapper">
<div class="lc-payment-notice">
<div class="lc-payment-notice-icon">
<img src="https://storage.googleapis.com/preview-production-assets/wordpress/lc-warning-icon.svg"
alt="Warning" />
</div>
<div class="lc-payment-notice-message">
Your recent payment has failed. Please update your billing information.
</div>
<div class="lc-payment-notice-actions">
<a href="<?php echo esc_url($payment_url); ?>" target="_blank" class="lc-update-button">
Update Payment Information
</a>
<button type="button" class="lc-dismiss-button">
<span class="dashicons dashicons-no-alt"></span>
</button>
</div>
</div>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
const dismissButton = document.querySelector('.lc-dismiss-button');
if (dismissButton) {
dismissButton.addEventListener('click', function () {
const banner = document.querySelector('.lc-payment-notice-wrapper');
if (banner) {
banner.style.display = 'none';
}
});
}
});
</script>
<?php
}
/**
* Ensure dashicons are loaded for non-admin users
*/
public function enqueue_dashicons()
{
wp_enqueue_style('dashicons');
}
/**
* Add styles for the payment notification
*
* @since 1.0.0
*/
public function add_payment_notification_styles()
{
?>
<style type="text/css">
/* Payment failed notification banner - Matching design */
.lc-payment-notice-wrapper {
width: 100%;
position: relative;
display: flex;
padding-right: 100px;
border: none;
outline: none;
}
.lc-payment-notice {
display: flex;
align-items: center;
padding: 15px 20px;
flex-grow: 1;
width: 100%;
background-color: #FFFCF5 !important;
margin-right: 20px;
border: none;
outline: none;
}
.lc-payment-notice-icon {
margin-right: 15px;
border: none;
outline: none;
display: flex;
align-items: center;
}
.lc-payment-notice-icon img {
width: 24px;
height: 24px;
outline: none;
border: none;
}
.lc-payment-notice-message {
flex: 1;
font-size: 14px;
color: #B54708 !important;
font-weight: 500;
border: none;
outline: none;
}
.lc-payment-notice-actions {
display: flex;
align-items: center;
border: none;
outline: none;
}
.lc-update-button {
background-color: #d35400;
color: #ffffff;
border: none;
padding: 8px 16px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
text-decoration: none;
font-weight: 500;
margin-right: 15px;
display: inline-block;
outline: none;
}
.lc-update-button:hover,
.lc-update-button:focus {
background-color: #e67e22;
color: #ffffff;
outline: none;
box-shadow: none !important;
}
.lc-dismiss-button {
background: none;
border: none;
cursor: pointer;
padding: 0;
color: #777777;
outline: none;
}
.lc-dismiss-button:hover {
color: #333333;
}
.lc-dismiss-button .dashicons {
font-size: 20px;
width: 20px;
height: 20px;
outline: none;
}
/* Make responsive for smaller screens */
@media screen and (max-width: 782px) {
.lc-payment-notice {
flex-wrap: wrap;
padding: 15px;
}
.lc-payment-notice-message {
margin-bottom: 10px;
width: 100%;
}
.lc-payment-notice-actions {
width: 100%;
justify-content: space-between;
}
.lc-update-button {
padding: 8px 10px;
margin-right: 0;
}
}
</style>
<?php
}
/**
* Setting validation
* This will get called when user click on save button
* @since 1.0.0
* @param object $input user input field's name:value map object
*/
public function lead_connector_setting_validate($input, $forced_save = false)
{
// error_log("called_setting_saved");
// error_log(print_r($input, true));
$options = get_option(LEAD_CONNECTOR_OPTION_NAME);
$api_key = isset($input[lead_connector_constants\lc_options_api_key]) ? $input[lead_connector_constants\lc_options_api_key] : null;
if (!$api_key)
$api_key = isset($options[lead_connector_constants\lc_options_api_key]) ? $options[lead_connector_constants\lc_options_api_key] : null;
$old_api_key = '';
$old_location_id = '';
$old_text_widget_error = "0";
// die('reached 1.1');
if (isset($options[lead_connector_constants\lc_options_api_key])) {
$old_api_key = esc_attr($options[lead_connector_constants\lc_options_api_key]);
}
if (isset($options[lead_connector_constants\lc_options_location_id])) {
$old_location_id = esc_attr($options[lead_connector_constants\lc_options_location_id]);
}
if (isset($options[lead_connector_constants\lc_options_text_widget_error])) {
$old_text_widget_error = esc_attr($options[lead_connector_constants\lc_options_text_widget_error]);
}
// if (!isset($api_key) || (isset($api_key) === true && $api_key === '')) {
// $input[lead_connector_constants\lc_options_text_widget_error] = "1";
// die('reached 1.2');
// return $input;
// }
$input[lead_connector_constants\lc_options_text_widget_warning_text] = "";
$api_key = trim($api_key);
$enabled_text_widget = 0;
if (isset($input[lead_connector_constants\lc_options_enable_text_widget])) {
$enabled_text_widget = esc_attr($input[lead_connector_constants\lc_options_enable_text_widget]);
}
// die('reached 1.3');
if (defined('WP_DEBUG') && true === WP_DEBUG) {
// error_log(print_r($input, true));
}
if ($enabled_text_widget == 1 || $forced_save) {
// die('reached 1.4');
if (defined('WP_DEBUG') && true === WP_DEBUG) {
// error_log('call API here ');
}
if ($input[lead_connector_constants\lc_options_selected_chat_widget_id]) {
$selectedChatWidgetId = $input[lead_connector_constants\lc_options_selected_chat_widget_id];
}
// Change Here
$lcChatResponse = $this->lc_wp_get('get_chat_widget', ['selectedChatWidgetId' => $selectedChatWidgetId]);
if (is_array($lcChatResponse) && isset($lcChatResponse['error']) && $lcChatResponse['error'] === true) {
$input[lead_connector_constants\lc_options_text_widget_error] = "1";
$input[lead_connector_constants\lc_options_text_widget_error_details] = print_r($lcChatResponse, true);
return $input;
}
if (is_array($lcChatResponse) && isset($lcChatResponse['body'])) {
$lcChatResponse = $lcChatResponse['body'];
}
if (@!$lcChatResponse->error) {
$obj = $lcChatResponse;
$input[lead_connector_constants\lc_options_location_id] = $obj->id;
$input[lead_connector_constants\lc_options_text_widget_error] = 0;
$input[lead_connector_constants\lc_options_selected_chat_widget_id] = $obj->chatWidgetId;
} else {
$input[lead_connector_constants\lc_options_text_widget_error] = "1";
$input[lead_connector_constants\lc_options_text_widget_error_details] = print_r($lcChatResponse, true);
}
} else {
$input[lead_connector_constants\lc_options_location_id] = $old_location_id;
}
return $input;
}
/**
* Filter Post information
* This will get on each post to get the fields required at front-end
* @since 1.0.0
* @param string $template_id postID
* @param string $location_id Location ID
*/
public function get_item($template_id, $location_id)
{
$post = get_post($template_id);
$user = get_user_by('id', $post->post_author);
$date = strtotime($post->post_date);
$funnel_step_url = get_post_meta($post->ID, "lc_step_url", true);
$slug = get_post_meta($post->ID, "lc_slug", true);
$lc_funnel_name = get_post_meta($post->ID, "lc_funnel_name", true);
$lc_funnel_id = get_post_meta($post->ID, "lc_funnel_id", true);
$lc_step_id = get_post_meta($post->ID, "lc_step_id", true);
$lc_step_name = get_post_meta($post->ID, "lc_step_name", true);
$lc_display_method = get_post_meta($post->ID, "lc_display_method", true);
$lc_include_tracking_code = get_post_meta($post->ID, "lc_include_tracking_code", true);
$lc_use_site_favicon = get_post_meta($post->ID, "lc_use_site_favicon", true);
$lc_include_wp_headers_and_footers = get_post_meta($post->ID, "lc_include_wp_headers_and_footers", true);
$base_url = get_home_url() . "/";
$data = [
'template_id' => $post->ID,
'title' => $post->post_title,
'thumbnail' => get_the_post_thumbnail_url($post),
'date' => $date,
'human_date' => date_i18n(get_option('date_format'), $date),
'human_modified_date' => date_i18n(get_option('date_format'), strtotime($post->post_modified)),
'author' => $user ? $user->display_name : "undefined",
'status' => $post->post_status,
'url' => $base_url . $slug,
"slug" => $slug,
"funnel_step_url" => $funnel_step_url,
"lc_funnel_name" => $lc_funnel_name,
"lc_funnel_id" => $lc_funnel_id,
"lc_step_id" => $lc_step_id,
"lc_step_name" => $lc_step_name,
"location_id" => $location_id,
"lc_display_method" => $lc_display_method,
"lc_include_tracking_code" => $lc_include_tracking_code,
"lc_use_site_favicon" => $lc_use_site_favicon,
"lc_include_wp_headers_and_footers" => $lc_include_wp_headers_and_footers,
];
return $data;
}
public function lc_disconnect()
{
$newOptions[lead_connector_constants\lc_options_oauth_access_token] = "";
$newOptions[lead_connector_constants\lc_options_oauth_refresh_token] = "";
$newOptions[lead_connector_constants\lc_options_location_id] = "lc_disconnect";
$option_saved = update_option(LEAD_CONNECTOR_OPTION_NAME, $newOptions);
// Clear all caches to ensure widget is removed from cached pages
$this->clear_all_caches();
return array(
"-success" => true,
"options_saved" => $option_saved,
);
}
/**
* Public API handler
* rest API call from front-end will end up here, where endpoint query param will the action or remote API path.
* @since 1.0.0
*/
public function lc_public_api_proxy($request)
{
$options = get_option(LEAD_CONNECTOR_OPTION_NAME);
$params = $request->get_query_params();
$endpoint = $params[lead_connector_constants\lc_rest_api_endpoint_param];
$directEndpoint = $params[lead_connector_constants\lc_rest_api_direct_endpoint_param];
$lc_access_token = "";
$api_key = "";
$authorized_location_id = "";
if (isset($options[lead_connector_constants\lc_options_location_id])) {
$authorized_location_id = $options[lead_connector_constants\lc_options_location_id];
$authorized_location_id = trim($authorized_location_id);
}
if (isset($options[lead_connector_constants\lc_options_api_key])) {
$api_key = $options[lead_connector_constants\lc_options_api_key];
$api_key = trim($api_key);
}
if (isset($options[lead_connector_constants\lc_options_oauth_access_token])) {
$lc_access_token = $options[lead_connector_constants\lc_options_oauth_access_token];
$lc_access_token = $this->lc_decrypt_string($lc_access_token);
}
if ($endpoint == 'wp_regenerate_token') {
return $this->lc_oauth_regenerate_token();
}
if ($endpoint == "wp_validate_auth_state") {
// This should for both api key or oauth
$has_connected_auth = false;
$connection_method = '';
$funnelFetchResponse = array('error' => true);
;
if ($lc_access_token != '' || $api_key != '') {
$has_connected_auth = true;
}
if ($has_connected_auth) {
if ($lc_access_token != '') {
$connection_method = 'oauth';
} else {
$connection_method = 'api_key';
}
$funnelFetchResponse = $this->lc_wp_get('funnels_get_list');
}
$funnelFetchResponse = (array) $funnelFetchResponse;
$is_connection_status_active = false;
if (!array_key_exists("error", $funnelFetchResponse)) {
$is_connection_status_active = true;
}
return array(
"is_connection_status_active" => $is_connection_status_active,
"has_connected_auth" => $has_connected_auth,
"connection_method" => $connection_method,
"access_token" => $lc_access_token,
"api_key" => $api_key,
"authorized_location_id" => $authorized_location_id,
"options" => $options,
"funnelFetchResponse" => $funnelFetchResponse
);
}
if ($endpoint == 'wp_disconnect') {
$event = new StateUpdate("WORDPRESS LC PLUGIN DISCONNECTED", [
"locationId" => $options[lead_connector_constants\lc_options_location_id],
]);
$event->send();
// Reset All Options
$newOptions = array();
// $newOptions[lead_connector_constants\lc_options_oauth_access_token] = "";
// $newOptions[lead_connector_constants\lc_options_oauth_refresh_token] = "";
// $newOptions[lead_connector_constants\lc_options_location_id] = "";
$option_saved = update_option(LEAD_CONNECTOR_OPTION_NAME, $newOptions);
// Clear all caches to ensure widget is removed from cached pages
$this->clear_all_caches();
return array(
"success" => true,
"options_saved" => $option_saved,
);
}
if ($endpoint == 'wp_validate_oauth') {
$body = json_decode($params['data']);
$token_response = $this->lc_perform_oauth_request("validate", $body->code);
$previous_options = get_option(LEAD_CONNECTOR_OPTION_NAME);
if (!is_array($previous_options))
$previous_options = array();
$option_saved = false;
if (!property_exists($token_response, "error")) {
if ($token_response->userType == 'Location') {
$previous_options[lead_connector_constants\lc_options_oauth_access_token] = $this->lc_encrypt_string($token_response->access_token);
$previous_options[lead_connector_constants\lc_options_oauth_refresh_token] = $this->lc_encrypt_string($token_response->refresh_token);
$previous_options[lead_connector_constants\lc_options_location_id] = $token_response->locationId;
}
$option_saved = update_option(LEAD_CONNECTOR_OPTION_NAME, $previous_options);
$event = new StateUpdate("WORDPRESS LC PLUGIN CONNECTED", [
"locationId" => $previous_options[lead_connector_constants\lc_options_location_id],
]);
$event->send();
}
return array(
"previous_options" => $previous_options,
"options_saved" => $option_saved,
"response" => $token_response,
);
}
if ($request->get_method() == 'POST') {
// error_log("current_user");
// error_log(print_r($request, true));
// error_log(print_r($request->get_body(), true));
if ($endpoint == "wp_save_options") {
$body = json_decode($request->get_body());
if (isset($body->enable_text_widget)) {
$options[lead_connector_constants\lc_options_enable_text_widget] = $body->enable_text_widget;
}
if (isset($body->api_key)) {
$options[lead_connector_constants\lc_options_api_key] = $body->api_key;
}
if (isset($body->selected_chat_widget)) {
$options[lead_connector_constants\lc_options_selected_chat_widget_id] = $body->selected_chat_widget;
}
$newOptions = $this->lead_connector_setting_validate($options, true);
$text_widget_error = "0";
$error_details = '';
$warning_msg = "";
$white_label_url = "";
$enable_text_widget = "";
$api_key = "";
$location_id = "";
if (isset($newOptions[lead_connector_constants\lc_options_text_widget_error])) {
$text_widget_error = esc_attr($newOptions[lead_connector_constants\lc_options_text_widget_error]);
}
if (isset($newOptions[lead_connector_constants\lc_options_text_widget_error_details])) {
$error_details = esc_attr($newOptions[lead_connector_constants\lc_options_text_widget_error_details]);
}
if (isset($newOptions[lead_connector_constants\lc_options_text_widget_warning_text])) {
$warning_msg = esc_attr($newOptions[lead_connector_constants\lc_options_text_widget_warning_text]);
}
if (isset($newOptions[lead_connector_constants\lc_options_location_white_label_url])) {
$white_label_url = (esc_attr($newOptions[lead_connector_constants\lc_options_location_white_label_url]));
}
if (isset($newOptions[lead_connector_constants\lc_options_enable_text_widget])) {
$enable_text_widget = (esc_attr($newOptions[lead_connector_constants\lc_options_enable_text_widget]));
}
if (isset($newOptions[lead_connector_constants\lc_options_api_key])) {
$api_key = (esc_attr($newOptions[lead_connector_constants\lc_options_api_key]));
}
if (isset($newOptions[lead_connector_constants\lc_options_location_id])) {
$location_id = (esc_attr($newOptions[lead_connector_constants\lc_options_location_id]));
}
if (isset($newOptions[lead_connector_constants\lc_options_selected_chat_widget_id])) {
$selected_chat_widget_id = (esc_attr($newOptions[lead_connector_constants\lc_options_selected_chat_widget_id]));
}
$option_saved = update_option(LEAD_CONNECTOR_OPTION_NAME, $newOptions);
// Clear all caches when widget settings are updated
$this->clear_all_caches();
if ($text_widget_error == "1") {
return (array(
'error' => true,
'message' => $error_details,
));
}
return (array(
'success' => true,
'warning_msg' => $warning_msg,
'api_key' => $api_key,
"enable_text_widget" => $enable_text_widget,
"selected_chat_widget_id" => $selected_chat_widget_id,
"home_url" => get_home_url(),
"white_label_url" => $white_label_url,
"location_id" => $location_id,
));
}
if ($endpoint == "wp_insert_post") {
$body = json_decode($request->get_body());
if (defined('WP_DEBUG') && true === WP_DEBUG) {
// error_log("wp_insert_post");
// error_log(print_r($body, true));
}
$lc_slug = $body->lc_slug;
$lc_step_id = $body->lc_step_id;
$lc_step_name = $body->lc_step_name;
$lc_funnel_id = $body->lc_funnel_id;
$lc_funnel_name = $body->lc_funnel_name;
$lc_step_url = $body->lc_step_url;
$lc_step_page_id = isset($body->lc_step_page_id) ? $body->lc_step_page_id : null;
$template_id = $body->template_id;
$lc_display_method = $body->lc_display_method;
$lc_step_meta = null;
$lc_step_trackingCode = null;
$lc_funnel_tracking_code = null;
$lc_include_tracking_code = false;
$lc_use_site_favicon = false;
$lc_include_wp_headers_and_footers = false;
if ($body->lc_include_tracking_code == "1") {
$lc_include_tracking_code = true;
}
if ($body->lc_use_site_favicon == "1") {
$lc_use_site_favicon = true;
}
if ($body->lc_include_wp_headers_and_footers == "1") {
$lc_include_wp_headers_and_footers = true;
}
// Old Method provided meta in the body itself - Now we have to fetch it from the backend
$includeMetaTags = true;
if ($includeMetaTags) {
$lc_step_meta_response = $this->lc_oauth_wp_remote_v2(
'get',
sprintf('funnels/page/data?pageId=%s', $lc_step_page_id),
[],
null,
LEAD_CONNECTOR_MARKETPLACE_BACKEND_URL,
true
);
$lc_step_meta = $lc_step_meta_response["body"]->data->pageMeta ?? null;
}
if (isset($body->lc_funnel_tracking_code) && $lc_include_tracking_code) {
if (defined('WP_DEBUG') && true === WP_DEBUG) {
// error_log("lc_funnel_tracking_code");
// error_log(print_r($body->lc_funnel_tracking_code, true));
// error_log(print_r($body->lc_funnel_tracking_code->headerCode, true));
// error_log(print_r($body->lc_funnel_tracking_code->footerCode, true));
}
$lc_funnel_tracking_code = wp_json_encode($body->lc_funnel_tracking_code, JSON_UNESCAPED_UNICODE);
}
if (isset($body->lc_step_page_download_url) && $lc_include_tracking_code) {
if (defined('WP_DEBUG') && true === WP_DEBUG) {
// error_log("wp_insert_post_tracking");
// error_log(print_r($body->lc_include_tracking_code, true));
// error_log(print_r($body->lc_step_page_download_url, true));
}
$args = array(
'timeout' => 60,
);
$response_code = wp_remote_get($body->lc_step_page_download_url, $args);
$http_tracking_code = wp_remote_retrieve_response_code($response_code);
if ($http_tracking_code === 200) {
$body_tracking_code = wp_remote_retrieve_body($response_code);
$tracking_res = json_decode($body_tracking_code, false);
if (isset($tracking_res) && isset($tracking_res->trackingCode)) {
$lc_step_trackingCode = base64_encode(wp_json_encode($tracking_res->trackingCode, JSON_UNESCAPED_UNICODE));
if (defined('WP_DEBUG') && true === WP_DEBUG) {
// error_log(print_r($lc_step_trackingCode, true));
}
}
}
}
$query_args = array(
'meta_key' => 'lc_slug',
'meta_value' => $lc_slug,
'post_type' => lead_connector_constants\lc_custom_post_type,
'compare' => '=',
);
$the_posts = get_posts($query_args);
if (count((array) $the_posts) && $template_id === -1) {
return (array(
'error' => true,
'message' => "slug '" . $lc_slug . "' already exist",
"code" => 1009,
));
}
$user = wp_get_current_user();
$user_id = get_current_user_id();
$user_logged_in = is_user_logged_in();
// error_log("current_user");
// error_log(print_r($user, true));
// error_log(print_r($user_id, true));
// error_log(print_r($user_logged_in, true));
$post_data = [];
$post_data['post_title'] = "LeadConnector_funnel-" . $lc_funnel_name . "-step-" . $lc_step_name;
$post_data['post_content'] = "";
$post_data['post_type'] = lead_connector_constants\lc_custom_post_type;
$post_data['post_status'] = "publish";
if ($template_id !== -1) {
$post_data['ID'] = $template_id;
}
// $post_data['post_author'] = $post_author;
$post_id = wp_insert_post($post_data);
if (is_wp_error($post_id) || $post_id === 0) {
// error_log("fail to save the post");
return (array(
'error' => true,
'message' => "fail to save the post",
));
}
if (isset($lc_slug)) {
update_post_meta($post_id, "lc_slug", $lc_slug);
}
if (isset($lc_step_id)) {
update_post_meta($post_id, "lc_step_id", $lc_step_id);
}
if (isset($lc_step_name)) {
update_post_meta($post_id, "lc_step_name", $lc_step_name);
}
if (isset($lc_funnel_id)) {
update_post_meta($post_id, "lc_funnel_id", $lc_funnel_id);
}
if (isset($lc_funnel_name)) {
update_post_meta($post_id, "lc_funnel_name", $lc_funnel_name);
}
if (isset($lc_step_url)) {
update_post_meta($post_id, "lc_step_url", $lc_step_url);
}
if (isset($lc_display_method)) {
update_post_meta($post_id, "lc_display_method", $lc_display_method);
}
if (isset($lc_step_meta)) {
update_post_meta($post_id, "lc_step_meta", wp_json_encode($lc_step_meta, JSON_UNESCAPED_UNICODE));
}
if (isset($lc_step_trackingCode)) {
update_post_meta($post_id, "lc_step_trackingCode", $lc_step_trackingCode);
}
if (isset($lc_include_tracking_code)) {
update_post_meta($post_id, "lc_include_tracking_code", $lc_include_tracking_code);
}
if (isset($lc_use_site_favicon)) {
update_post_meta($post_id, "lc_use_site_favicon", $lc_use_site_favicon);
}
if (isset($lc_funnel_tracking_code)) {
update_post_meta($post_id, "lc_funnel_tracking_code", $lc_funnel_tracking_code);
}
if (isset($lc_include_wp_headers_and_footers)) {
update_post_meta($post_id, "lc_include_wp_headers_and_footers", $lc_include_wp_headers_and_footers);
}
return (array(
'success' => true,
));
}
return;
}
if ($endpoint == "wp_get_all_posts") {
$body = json_decode($params['data']);
$perPage = $body->per_page;
$page = $body->page;
$query_args = array(
'post_type' => lead_connector_constants\lc_custom_post_type,
'post_status' => 'any',
'compare' => '=',
"posts_per_page" => $perPage,
"paged" => $page
);
$the_posts = new WP_Query($query_args);
$templates = [];
$location_id = "";
if (isset($options[lead_connector_constants\lc_options_location_id])) {
$location_id = esc_attr($options[lead_connector_constants\lc_options_location_id]);
}
if ($the_posts->have_posts()):
while ($the_posts->have_posts()):
$the_posts->the_post();
$templates[] = $this->get_item(get_the_ID(), $location_id);
endwhile;
endif;
$finalOutput = array(
"funnels" => $templates,
"pagination" => [
"total" => count($templates),
"page" => $page,
"per_page" => $perPage,
"total_pages" => $the_posts->max_num_pages,
],
);
return $finalOutput;
}
if ($endpoint == "wp_get_lc_options") {
$enabled_text_widget = 0;
$text_widget_error = "0";
$error_details = '';
$warning_msg = "";
$white_label_url = "";
$location_id = "";
$oauth_access_token = "";
if (isset($options[lead_connector_constants\lc_options_text_widget_error])) {
$text_widget_error = esc_attr($options[lead_connector_constants\lc_options_text_widget_error]);
}
if (isset($options[lead_connector_constants\lc_options_text_widget_error_details])) {
$error_details = esc_attr($options[lead_connector_constants\lc_options_text_widget_error_details]);
}
if (isset($options[lead_connector_constants\lc_options_text_widget_warning_text])) {
$warning_msg = esc_attr($options[lead_connector_constants\lc_options_text_widget_warning_text]);
}
if (isset($options[lead_connector_constants\lc_options_enable_text_widget])) {
$enabled_text_widget = esc_attr($options[lead_connector_constants\lc_options_enable_text_widget]);
}
if (isset($options[lead_connector_constants\lc_options_location_white_label_url])) {
$white_label_url = (esc_attr($options[lead_connector_constants\lc_options_location_white_label_url]));
}
if (isset($options[lead_connector_constants\lc_options_location_id])) {
$location_id = (esc_attr($options[lead_connector_constants\lc_options_location_id]));
}
if (isset($options[lead_connector_constants\lc_options_oauth_access_token])) {
$oauth_access_token = (esc_attr($options[lead_connector_constants\lc_options_oauth_access_token]));
}
if (isset($options[lead_connector_constants\lc_options_selected_chat_widget_id])) {
$selected_chat_widget_id = (esc_attr($options[lead_connector_constants\lc_options_selected_chat_widget_id]));
}
$data = [
'api_key' => $api_key,
"oauth_access_token" => $oauth_access_token,
"enable_text_widget" => $enabled_text_widget,
"text_widget_error" => $text_widget_error == "1" ? true : false,
"error_details" => $error_details,
"warning_msg" => $warning_msg,
"selected_chat_widget_id" => $selected_chat_widget_id ?? null,
"home_url" => get_home_url(),
"white_label_url" => $white_label_url,
"location_id" => $location_id,
"plugin_directory_url" => plugin_dir_url(dirname(__FILE__)),
"all_options" => $options
];
return $data;
}
if ($endpoint == "wp_delete_post") {
$body = json_decode($params['data']);
$post_id = $body->post_id;
$force_delete = $body->force_delete;
$post_info = wp_delete_post($post_id, $force_delete);
if (!$post_info) {
// error_log("fail to delete the post");
return (array(
'error' => true,
'message' => "fail to delete the post",
));
}
return $post_info;
}
if ($directEndpoint == "true") {
$args = array(
'timeout' => 60,
);
$response = wp_remote_get($endpoint, $args);
$http_code = wp_remote_retrieve_response_code($response);
if ($http_code === 200) {
$body = wp_remote_retrieve_body($response);
$obj = json_decode($body, false);
return $obj;
} else {
return (array(
'error' => true,
));
}
}
if ($endpoint == 'funnels_get_list') {
return $this->lc_wp_get($endpoint);
}
if ($endpoint == 'funnels_get_details') {
$body = json_decode($params['data']);
return $this->lc_wp_get($endpoint, $body);
}
if ($endpoint == 'wp_enable_email') {
$body = json_decode($params['data']);
$response = $this->lc_wp_get($endpoint, $body);
$option_saved = false;
if (@!$response->error) {
$newOptions = get_option(LEAD_CONNECTOR_OPTION_NAME);
$newOptions[lead_connector_constants\lc_options_email_smtp_enabled] = 'true';
$newOptions[lead_connector_constants\lc_options_email_smtp_email] = $response->smtpEmail;
$newOptions[lead_connector_constants\lc_options_email_smtp_password] = $response->smtpPassword;
$newOptions[lead_connector_constants\lc_options_email_smtp_port] = $response->smtpPort;
$newOptions[lead_connector_constants\lc_options_email_smtp_server] = $response->smtpServer;
$newOptions[lead_connector_constants\lc_options_email_smtp_provider] = $response->smtpProviderName;
$option_saved = update_option(LEAD_CONNECTOR_OPTION_NAME, $newOptions);
$option_saved = true;
} else {
if ($response->http_code == 400 && $response->error) {
$errorBody = json_decode($response->body);
if ($errorBody->message) {
return array(
'success' => false,
'message' => $errorBody->message
);
}
}
}
return array(
'success' => $option_saved,
);
}
if ($endpoint == 'wp_email_eligibility_check') {
$email_enabled = @$options[lead_connector_constants\lc_options_email_smtp_enabled] == 'true' ? true : false;
$active_email_id = @$options[lead_connector_constants\lc_options_email_smtp_email];
$response = $this->lc_wp_get($endpoint);
return array(
'emailEnabled' => $email_enabled,
'enabledEmailId' => $active_email_id,
'response' => $response
);
}
if ($endpoint == 'wp_disable_email') {
$body = json_decode($params['data']);
$response = $this->lc_wp_get($endpoint, $body);
$option_saved = false;
if (!@$response->error || @$response->http_code == 500) {
$newOptions = get_option(LEAD_CONNECTOR_OPTION_NAME);
$newOptions[lead_connector_constants\lc_options_email_smtp_enabled] = 'false';
$newOptions[lead_connector_constants\lc_options_email_smtp_email] = null;
$newOptions[lead_connector_constants\lc_options_email_smtp_password] = null;
$newOptions[lead_connector_constants\lc_options_email_smtp_port] = null;
$newOptions[lead_connector_constants\lc_options_email_smtp_server] = null;
$newOptions[lead_connector_constants\lc_options_email_smtp_provider] = null;
$option_saved = update_option(LEAD_CONNECTOR_OPTION_NAME, $newOptions);
}
return array(
'success' => true,
'response' => $response,
);
}
if ($endpoint == 'check_smtp_plugin_conflict') {
return $this->check_smtp_plugin_conflict();
}
if (isset($params['data'])) {
$params = json_decode($params['data']);
}
return $this->lc_wp_get($endpoint, $params);
}
private function lc_oauth_regenerate_token()
{
$lcOptions = get_option(LEAD_CONNECTOR_OPTION_NAME);
if (!is_array($lcOptions))
return array(
"success" => false
);
if (!isset($lcOptions[lead_connector_constants\lc_options_oauth_refresh_token]) && $lcOptions[lead_connector_constants\lc_options_oauth_refresh_token] == '')
return array(
"success" => false
);
$lcRefreshToken = $this->lc_decrypt_string($lcOptions[lead_connector_constants\lc_options_oauth_refresh_token]);
$token_response = $this->lc_perform_oauth_request("refresh", $lcRefreshToken, $lcOptions[lead_connector_constants\lc_options_location_id]);
if (!isset($token_response->response->error)) {
if (isset($token_response->userType) && $token_response->userType == 'Location') {
$lcOptions[lead_connector_constants\lc_options_location_id] = $token_response->locationId;
$lcOptions[lead_connector_constants\lc_options_oauth_access_token] = $this->lc_encrypt_string($token_response->access_token);
$lcOptions[lead_connector_constants\lc_options_oauth_refresh_token] = $this->lc_encrypt_string($token_response->refresh_token);
update_option(LEAD_CONNECTOR_OPTION_NAME, $lcOptions);
}
}
return array(
"success" => true,
);
}
public function lc_disable_auto_updates()
{
$lcOptions = get_option(LEAD_CONNECTOR_OPTION_NAME);
if (!isset($lcOptions[lead_connector_constants\lc_options_last_cron_clear_started_at])) {
return;
}
if (time() - $lcOptions[lead_connector_constants\lc_options_last_cron_clear_started_at] > 300) {
return;
}
// Disable WordPress core auto updates
add_filter('auto_update_core', '__return_false');
// Disable plugin auto updates
add_filter('auto_update_plugin', '__return_false');
// Disable theme auto updates
add_filter('auto_update_theme', '__return_false');
// Disable translation auto updates
add_filter('auto_update_translation', '__return_false');
// Disable the automatic updater entirely
add_filter('automatic_updater_disabled', '__return_true');
return array(
'success' => true,
'message' => 'Auto updates disabled successfully'
);
}
private function lc_save_custom_values($response)
{
if (!$response['error'] && isset($response['body']->data)) {
$url = get_rest_url(null, 'lc_internal_api/v1/save_custom_values');
// Collect all cookies including WordPress auth cookies
$cookies = array();
foreach ($_COOKIE as $name => $value) {
$cookies[] = new WP_Http_Cookie(array('name' => $name, 'value' => $value));
}
wp_remote_post($url, array(
'method' => 'POST',
'headers' => array(
'Content-Type' => 'application/json; charset=utf-8',
'X-WP-Nonce' => wp_create_nonce('wp_rest')
),
'body' => json_encode(array('custom_values' => $response['body']->data)),
'blocking' => false,
'timeout' => 1,
'cookies' => $cookies,
'sslverify' => true // Host has to verify the SSL certificate of the site no unsecured connections
));
}
}
private function lc_wp_get($endpoint, $params = array())
{
$params = (object) $params;
$lcOptions = get_option(LEAD_CONNECTOR_OPTION_NAME);
$useV2Request = false;
if ($endpoint == 'wp_get_cron_count') {
$has_cron = wp_next_scheduled('lc_twicedaily_refresh_req');
$maintenance_mode = false;
$is_allowed = false;
if (file_exists(ABSPATH . '.maintenance')) {
$maintenance_mode = true;
}
if ($has_cron) {
$canDoResponse = $this->lc_wp_get("utils_can_do", array("action" => "mass_clear_cron"));
$is_allowed = $canDoResponse->allowed;
}
return array(
'has_cron' => $has_cron,
'maintenance_mode' => $maintenance_mode,
'is_allowed' => $is_allowed
);
}
if ($endpoint == 'wp_clear_cron') {
$lcOptions[lead_connector_constants\lc_options_last_cron_clear_started_at] = time();
update_option(LEAD_CONNECTOR_OPTION_NAME, $lcOptions);
// Reset the cron schedule safely using WordPress functions
update_option('cron', []);
// Delete the 'cron' option from the database (flush all cron jobs)
delete_transient('doing_cron');
delete_option('cron');
// Clear all cron jobs from memory
// wp_clear_scheduled_hook('*');
wp_clear_scheduled_hook('lc_twicedaily_refresh_req');
// Force clear internal cache
wp_cache_delete('cron', 'options');
wp_cache_delete('alloptions', 'options');
return array(
'success' => true,
);
}
$api_key = isset($lcOptions[lead_connector_constants\lc_options_api_key]) ? $lcOptions[lead_connector_constants\lc_options_api_key] : null;
$lcAccessToken = isset($lcOptions[lead_connector_constants\lc_options_oauth_access_token]) ? $lcOptions[lead_connector_constants\lc_options_oauth_access_token] : null;
$lcAccessToken = $this->lc_decrypt_string($lcAccessToken);
$lcLocationId = isset($lcOptions[lead_connector_constants\lc_options_location_id]) ? $lcOptions[lead_connector_constants\lc_options_location_id] : null;
$selectedChatWidgetId = isset($lcOptions[lead_connector_constants\lc_options_selected_chat_widget_id]) ? $lcOptions[lead_connector_constants\lc_options_selected_chat_widget_id] : null;
if (isset($params->selectedChatWidgetId)) {
$selectedChatWidgetId = $params->selectedChatWidgetId;
}
$finalEndpoint = "";
$authMethod = 'api_key';
if ($lcAccessToken != '') {
$authMethod = 'oauth';
}
// die(array('authMethod' => $authMethod, 'lcAccessToken' => $lcAccessToken, 'lcLocationId' => $lcLocationId));
$baseHost = LEAD_CONNECTOR_BASE_URL;
if ($authMethod == 'api_key') {
if ($endpoint == 'funnels_get_list')
$finalEndpoint = "v1/funnels/?includeDomainId=true&includeTrackingCode=true";
if ($endpoint == 'get_chat_widget')
$finalEndpoint = "v1/locations/me?includeWhiteLabelUrl=true";
if ($endpoint == 'funnels_get_details')
$finalEndpoint = "v1/funnels/" . $params->funnelId . "/pages/?includeMeta=true&includePageDataDownloadURL=true";
} else {
$baseHost = LEAD_CONNECTOR_SERVICES_BASE_URL;
if ($endpoint == 'funnels_get_list')
$finalEndpoint = "funnels/funnel/list?locationId=" . $lcLocationId;
if ($endpoint == 'get_chat_widget') {
if ($selectedChatWidgetId) {
$finalEndpoint = "wordpress/lc-plugin/chat-widget/data/" . $lcLocationId . '/' . $selectedChatWidgetId;
} else {
$finalEndpoint = "wordpress/lc-plugin/chat-widget/" . $lcLocationId . '/';
}
}
if ($endpoint == 'wp_email_eligibility_check')
$finalEndpoint = "wordpress/lc-plugin/emails/eligibility/" . $lcLocationId . '/';
if ($endpoint == 'wp_enable_email')
$finalEndpoint = "wordpress/lc-plugin/emails/generate-smtp/" . $lcLocationId . '/?domain=' . $params->domain . '&emailPrefix=' . $params->emailPrefix;
if ($endpoint == 'wp_disable_email')
$finalEndpoint = "wordpress/lc-plugin/emails/delete-smtp/" . $lcLocationId . '/?emailId=' . $params->email;
if ($endpoint == 'forms_get_list')
$finalEndpoint = "wordpress/lc-plugin/forms/" . $lcLocationId . "/?page=" . $params->page . "&perPage=" . $params->per_page;
if ($endpoint == 'phone_numbers_get_list')
$finalEndpoint = "wordpress/lc-plugin/phone-system/pools/" . $lcLocationId;
if ($endpoint == "utils_can_do")
$finalEndpoint = "wordpress/lc-plugin/utils/can-do/$lcLocationId/?action=" . $params->action . "&domain=" . get_home_url();
if ($endpoint == 'get_chat_widgets') {
$finalEndpoint = "wordpress/lc-plugin/chat-widget/list/{$lcLocationId}";
}
if ($endpoint == 'get_custom_values') {
$finalEndpoint = "wordpress/lc-plugin/custom-values/{$lcLocationId}/values?skip={$params->skip}&limit={$params->limit}&query=" . $params->query;
$useV2Request = true;
}
if ($endpoint == 'get_custom_value_folders') {
$finalEndpoint = "wordpress/lc-plugin/custom-values/{$lcLocationId}/values?getFolders=true&skip={$params->skip}&limit={$params->limit}";
$useV2Request = true;
}
if ($endpoint == 'get_surveys') {
$finalEndpoint = "wordpress/lc-plugin/surveys/{$lcLocationId}?skip={$params->skip}&limit={$params->limit}&query=" . $params->query;
$useV2Request = true;
}
if ($endpoint == 'get_quizzes') {
$finalEndpoint = "wordpress/lc-plugin/quizzes/{$lcLocationId}?skip={$params->skip}&limit={$params->limit}&query=" . $params->query;
$useV2Request = true;
}
if ($endpoint == 'clear_cached_custom_values') {
$customValues = new LeadConnector_CustomValues();
$customValues->remove_all_cached_custom_values_transients();
return array(
'success' => true,
'message' => 'Cached custom values cleared successfully',
);
}
if ($endpoint == 'get_reviews_widgets') {
$finalEndpoint = "wordpress/lc-plugin/reviews-widget/{$lcLocationId}?pageNumber={$params->pageNumber}&pageSize={$params->pageSize}";
$useV2Request = true;
}
if ($endpoint == 'get_calendars') {
$finalEndpoint = "wordpress/lc-plugin/calendars/{$lcLocationId}";
$useV2Request = true;
}
if ($endpoint == 'get_calendar_groups') {
$finalEndpoint = "wordpress/lc-plugin/calendars/{$lcLocationId}/groups";
$useV2Request = true;
}
}
if ($finalEndpoint == '') {
return array(
'error' => true,
'message' => 'Invalid Endpoint received',
'endpoint' => $endpoint,
'finalEndpoint' => $finalEndpoint,
'auth' => $authMethod,
);
}
// return array(
// 'finalEndpoint' => $finalEndpoint,
// 'authMethod' => $authMethod,
// 'baseHost' => $baseHost,
// 'lcAccessToken' => $lcAccessToken,
// 'api_key' => $api_key
// );
if ($authMethod == 'oauth' && !$useV2Request) {
return $this->lc_oauth_wp_remote_get($finalEndpoint, $lcAccessToken, $baseHost);
}
if ($authMethod == 'oauth' && $useV2Request) {
$response = $this->lc_oauth_wp_remote_v2('get', $finalEndpoint);
$logger = LeadConnector_Logger::get_instance();
$logger->info('get_custom_values', $response);
if ($endpoint == 'get_custom_values') {
$this->lc_save_custom_values($response);
}
return $response;
}
return $this->lc_wp_remote_get($finalEndpoint, $api_key, $baseHost);
}
/**
* Encrypts a string using WordPress salt and key
* @since 1.0.0
* @param string|object $string String or object to encrypt
* @return string Encrypted string
*/
private function lc_encrypt_string($string)
{
// Convert objects to JSON string before encryption
if (is_object($string) || is_array($string)) {
$string = json_encode($string);
}
$encryption = new LC_Data_Encryption();
return $encryption->encrypt($string);
}
/**
* Decrypts a string using WordPress salt and key
* @since 1.0.0
* @param string $encrypted String to decrypt
* @return string Decrypted string
*/
private function lc_decrypt_string($encrypted)
{
$encryption = new LC_Data_Encryption();
return $encryption->decrypt($encrypted);
}
private function lc_perform_oauth_request($endpoint = "validate", $code = null, $locationId = null)
{
if ($code == null || $code == '')
return array(
"error" => true,
"message" => "Invalid Refresh Token or Auth Code Not Received"
);
$finalEndpoint = "wordpress/lc-plugin/oauth/" . $endpoint . "?lcVersion=" . LEAD_CONNECTOR_VERSION;
$body = array();
if ($endpoint == "validate") {
$body['code'] = $code;
} else {
$body['refresh_token'] = $code;
}
if ($locationId != null && $endpoint == "refresh") {
$finalEndpoint = "wordpress/lc-plugin/oauth/location/:locationId/refresh?locationId=" . $locationId . "&lcVersion=" . LEAD_CONNECTOR_VERSION;
}
$args = array(
'timeout' => 60,
'body' => $body,
'headers' => array(
'X-LC-Version' => LEAD_CONNECTOR_VERSION,
),
);
// LEAD_CONNECTOR_SERVICES_BASE_URL
$response = wp_remote_post(LEAD_CONNECTOR_SERVICES_BASE_URL . $finalEndpoint, $args);
$http_code = wp_remote_retrieve_response_code($response);
$body = wp_remote_retrieve_body($response);
if ($http_code === 200 || $http_code === 201) {
$obj = json_decode($body, false);
return $obj;
} else {
return (object) (array(
'error' => true,
'http_code' => $http_code,
'body' => $body
));
}
}
private function lc_oauth_wp_remote_get($endpoint, $lcAccessToken, $baseHost = LEAD_CONNECTOR_SERVICES_BASE_URL)
{
$attempt = 1;
$lcOptions = get_option(LEAD_CONNECTOR_OPTION_NAME);
$lcAccessToken = $lcOptions[lead_connector_constants\lc_options_oauth_access_token];
$lcAccessToken = $this->lc_decrypt_string($lcAccessToken);
$http_code = 100;
$tokenRegenerationStatus = null;
$all_attempts = array();
while ($attempt <= 2) {
$args = array(
'timeout' => 60,
'headers' => array(
'Authorization' => "Bearer " . $lcAccessToken,
'Accept' => 'application/json',
'version' => '2021-04-15',
'X-LC-Version' => LEAD_CONNECTOR_VERSION,
),
);
if (defined("LC_DEVELOPER_VERSION") && LC_DEVELOPER_VERSION) {
$args['headers']['developer_version'] = LC_DEVELOPER_VERSION;
}
$finalURL = LEAD_CONNECTOR_SERVICES_BASE_URL . $endpoint;
if (strpos($finalURL, '?') !== false) {
$finalURL .= '&lcVersion=' . LEAD_CONNECTOR_VERSION;
} else {
$finalURL .= '?lcVersion=' . LEAD_CONNECTOR_VERSION;
}
$response = wp_remote_get(LEAD_CONNECTOR_SERVICES_BASE_URL . $endpoint, $args);
$http_code = wp_remote_retrieve_response_code($response);
$body = wp_remote_retrieve_body($response);
array_push($all_attempts, array(
'http_code' => $http_code,
'body' => $body,
));
if ($http_code === 200 || $http_code === 201) {
$obj = json_decode($body, false);
return $obj;
} else if ($http_code == 401) {
$tokenRegenerationStatus = $this->lc_oauth_regenerate_token();
} else {
return (object) (array(
'error' => true,
'http_code' => $http_code,
'body' => $body,
'from' => 'oauth_wp_remote_get'
));
}
$attempt++;
}
// if($tokenRegenerationStatus->response->status != 200 && $tokenRegenerationStatus->response->status != 201){
// return $this->lc_disconnect();
// }
return (array(
'error' => true,
'http_code' => $http_code,
"token_refresh_status" => $tokenRegenerationStatus,
"lcAccessToken" => $lcAccessToken,
'attempt' => $attempt,
"all_attempts" => $all_attempts,
));
}
// My Changes ---- Aman
/**
* Performs the actual HTTP request
*/
private function performRequest(string $method, string $url, array $args)
{
switch ($method) {
case 'get':
return wp_remote_get($url, $args);
case 'post':
return wp_remote_post($url, $args);
default:
throw new InvalidArgumentException('Unsupported HTTP method');
}
}
/**
* Checks if response code indicates success
*/
private function isSuccessResponse($code): bool
{
if (is_int($code)) {
return $code >= 200 && $code < 300;
}
return false;
}
/**
* Handles successful API response
*/
private function handleSuccessResponse($response)
{
try {
$body = wp_remote_retrieve_body($response);
return json_decode($body, false);
} catch (Exception $e) {
return null;
}
}
public function lc_oauth_wp_remote_v2(
string $method,
string $endpoint,
array $body = [],
?string $accessToken = null,
string $baseHost = LEAD_CONNECTOR_SERVICES_BASE_URL,
bool $useAuth = true
) {
if ($method != 'get' && $method != 'post') {
throw new InvalidArgumentException('Unsupported HTTP method');
}
$MAX_ATTEMPTS = 2;
$attempt = 1;
$url = $baseHost . $endpoint;
$url = add_query_arg('lcVersion', LEAD_CONNECTOR_VERSION, $url);
// Get Lead Connector options
$leadConnectorOptions = get_option(LEAD_CONNECTOR_OPTION_NAME);
// Validate options
if (empty($leadConnectorOptions)) {
return [
'error' => true,
'http_code' => 500,
'token_refresh_status' => false,
'attempt' => $attempt,
'message' => 'Invalid Lead Connector options'
];
}
$accessToken = $accessToken ? $accessToken : $leadConnectorOptions[lead_connector_constants\lc_options_oauth_access_token];
$accessToken = $this->lc_decrypt_string($accessToken); // Decrypt the access token
// Prepare request arguments
$args = [
'timeout' => 60,
'headers' => [
'Authorization' => $useAuth ? "Bearer " . $accessToken : null,
'Accept' => 'application/json',
'version' => '2021-04-15',
'X-LC-Version' => LEAD_CONNECTOR_VERSION,
'channel' => 'OAUTH',
'content-type' => 'application/json',
]
];
if (defined("LC_DEVELOPER_VERSION") && LC_DEVELOPER_VERSION) {
$args['headers']['developer_version'] = LC_DEVELOPER_VERSION;
}
// Add body for POST requests
if ($method === 'post') {
$args = array_merge($args, array('body' => json_encode($body)));
}
while ($attempt <= $MAX_ATTEMPTS) {
$response = $this->performRequest($method, $url, $args);
$responseCode = wp_remote_retrieve_response_code($response);
// Handle response based on status code
if ($this->isSuccessResponse($responseCode)) {
$response = $this->handleSuccessResponse($response);
return [
'error' => false,
'http_code' => $responseCode,
'body' => $response,
];
}
if ($responseCode === 401) {
$this->lc_oauth_regenerate_token();
$attempt++;
continue;
}
return [
'error' => true,
'http_code' => $responseCode != null ? $responseCode : 500,
'body' => $response
];
}
return [
'error' => true,
'http_code' => $responseCode ?? 500,
'message' => 'Max attempts reached'
];
}
private function lc_wp_remote_get($endpoint, $api_key, $baseHost = LEAD_CONNECTOR_BASE_URL)
{
//else call Remote API here
$args = array(
'timeout' => 60,
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
),
);
if (defined("LC_DEVELOPER_VERSION") && LC_DEVELOPER_VERSION) {
$args['headers']['developer_version'] = LC_DEVELOPER_VERSION;
}
$response = wp_remote_get(LEAD_CONNECTOR_BASE_URL . $endpoint, $args);
$http_code = wp_remote_retrieve_response_code($response);
if ($http_code === 200) {
$body = wp_remote_retrieve_body($response);
$obj = json_decode($body, false);
return $obj;
} else {
return (array(
'error' => true,
'http_code' => $http_code,
'from' => 'wp_remote_get_api'
));
}
}
// My Changes ---- Aman
/**
* Register the stylesheets for the admin area.
*
* @since 1.0.0
*/
public function enqueue_styles($hook)
{
wp_enqueue_style($this->plugin_name, plugin_dir_url(__FILE__) . 'css/lc-admin.css', array(), $this->version, 'all');
if ($hook != 'toplevel_page_lc-plugin') {
return;
}
// // error_log(print_r($_SERVER['REMOTE_ADDR'], true));
/**
* This function is provided for demonstration purposes only.
*
* An instance of this class should be passed to the run() function
* defined LeadConnector_Loader as all of the hooks are defined
* in that particular class.
*
* The LeadConnector_Loader will then create the relationship
* between the defined hooks and the functions defined in this
* class.
*/
$css_to_load = plugin_dir_url(__FILE__) . 'app.css';
$vendor_css_to_load = plugin_dir_url(__FILE__) . 'app2.css';
wp_enqueue_style('vue_lead_connector_app', $css_to_load, array(), $this->version, 'all', false);
// wp_enqueue_style('vue_lead_connector_vendor', $vendor_css_to_load, array(), $this->version, 'all');
}
/**
* Enqueue CDN purge script (used on both admin and frontend)
* This ensures "Purge everything on all domains" appears wherever CDN menu is visible
*
* @since 1.0.0
*/
private function enqueue_cdn_purge_script()
{
// Always load the admin script on all admin pages (includes CDN menu observer)
wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . 'js/lc-admin.js', array('jquery'), $this->version, false);
// Debug: Check if CDN constants are defined
$cdn_site_id = defined('CDN_SITE_ID') ? CDN_SITE_ID : '';
$cdn_site_token = defined('CDN_SITE_TOKEN') ? CDN_SITE_TOKEN : '';
// Localize CDN config values for JavaScript access
wp_localize_script($this->plugin_name, 'cdnConfig', array(
'siteId' => $cdn_site_id,
'siteToken' => $cdn_site_token,
'nonce' => wp_create_nonce('cdn_purge_all_domains_nonce'),
'debug' => array(
'siteIdDefined' => defined('CDN_SITE_ID'),
'siteTokenDefined' => defined('CDN_SITE_TOKEN'),
'scriptName' => $this->plugin_name
)
));
}
/**
* Register the JavaScript for the admin area.
*
* @since 1.0.0
*/
public function enqueue_scripts($hook)
{
// Only load the admin script if user is logged in to WordPress admin
if (!is_admin() || !current_user_can('manage_options')) {
return;
}
// Enqueue CDN purge script for admin pages (where CDN menu appears)
$this->enqueue_cdn_purge_script();
if ($hook != 'toplevel_page_lc-plugin') {
return;
}
// // error_log(print_r($hook, true));
// // error_log(print_r($_SERVER['REMOTE_ADDR'], true));
/**
* This function is provided for demonstration purposes only.
*
* An instance of this class should be passed to the run() function
* defined in LeadConnector_Loader as all of the hooks are defined
* in that particular class.
*
* The LeadConnector_Loader will then create the relationship
* between the defined hooks and the functions defined in this
* class.
*/
if (in_array($_SERVER['REMOTE_ADDR'], array('10.255.0.2', '::1'))) {
// DEV Vue dynamic loading
$js_to_load = plugin_dir_url(__FILE__) . 'app.js';
$vendor_js_to_load = plugin_dir_url(__FILE__) . 'chunk-vendors.js';
// wp_enqueue_script('vue_lead_connector_vendor_js', $vendor_js_to_load, '', wp_rand(11, 1000), true);
} else {
$js_to_load = plugin_dir_url(__FILE__) . 'app.js';
$vendor_js_to_load = plugin_dir_url(__FILE__) . 'chunk-vendors.js';
// wp_enqueue_script('vue_lead_connector_vendor_js', $vendor_js_to_load, '', wp_rand(11, 1000), true);
}
$options = get_option(LEAD_CONNECTOR_OPTION_NAME);
$enabledTextWidget = 0;
if (isset($options[lead_connector_constants\lc_options_enable_text_widget])) {
$enabledTextWidget = esc_attr($options[lead_connector_constants\lc_options_enable_text_widget]);
}
wp_localize_script(
$this->plugin_name,
'lc_admin_settings',
array(
'enable_text-widget' => $enabledTextWidget,
'proxy_url' => get_rest_url(null, 'lc_public_api/v1/proxy'),
'nonce' => wp_create_nonce('wp_rest'),
)
);
wp_localize_script(
$this->plugin_name,
'leadConnectorConfig',
array(
'LEAD_CONNECTOR_VERSION' => LEAD_CONNECTOR_VERSION,
'LEAD_CONNECTOR_PLUGIN_NAME' => LEAD_CONNECTOR_PLUGIN_NAME,
'LEAD_CONNECTOR_SERVICES_BASE_URL' => LEAD_CONNECTOR_SERVICES_BASE_URL,
'LEAD_CONNECTOR_OPTION_NAME' => LEAD_CONNECTOR_OPTION_NAME,
'LEAD_CONNECTOR_CDN_BASE_URL' => LEAD_CONNECTOR_CDN_BASE_URL,
'LEAD_CONNECTOR_OAUTH_CLIENT_ID' => LEAD_CONNECTOR_OAUTH_CLIENT_ID,
'LEAD_CONNECTOR_BASE_URL' => LEAD_CONNECTOR_BASE_URL,
'LEAD_CONNECTOR_DISPLAY_NAME' => LEAD_CONNECTOR_DISPLAY_NAME,
'LC_ROOT_DOMAIN' => LC_ROOT_DOMAIN,
'LC_BASE_URL' => LC_BASE_URL,
'LC_REPUTATION_WIDGET_SCRIPT_URL' => LC_REPUTATION_WIDGET_SCRIPT_URL,
'LC_REPUTATION_WIDGET_BASE_URL' => LC_REPUTATION_WIDGET_BASE_URL,
'LEAD_CONNECTOR_OAUTH_CALLBACK_URL' => LEAD_CONNECTOR_OAUTH_CALLBACK_URL,
)
);
wp_enqueue_script('vue_lead_connector_js', $js_to_load, '', wp_rand(10, 1000), array(
'type' => 'module',
));
function lc_add_type_attribute($tag, $handle, $src)
{
// if not your script, do nothing and return original $tag
if ('vue_lead_connector_js' !== $handle) {
return $tag;
}
// change the script tag by adding type="module" and return it.
$tag = '<script type="module" src="' . esc_url($src) . '"></script>';
return $tag;
}
add_filter('script_loader_tag', 'lc_add_type_attribute', 10, 3);
}
/**
* Enqueue CDN purge script on frontend when admin bar is visible
*
* @since 1.0.0
*/
public function enqueue_cdn_script_frontend()
{
// Only load on frontend when user is logged in and has admin bar visible
if (is_admin() || !is_user_logged_in() || !current_user_can('manage_options')) {
return;
}
// Check if admin bar is showing (WordPress shows admin bar on frontend for logged-in admins)
// The CDN menu only appears when admin bar is visible
if (!is_admin_bar_showing()) {
return;
}
// Enqueue CDN purge script for frontend pages with admin bar (where CDN menu appears)
$this->enqueue_cdn_purge_script();
}
/**
* Top level menu callback function
*/
/**
* Register the JavaScript for the admin area.
*
* @since 1.0.0
*/
public function wporg_options_page()
{
// Add Menu Handler In Place of old handler
new LC_Menu_Handler();
}
/**
* Register the JavaScript for the admin area.
*
* @since 1.0.0
*/
public function register_settings()
{
// add_settings_section('api_settings_inputs', __('leadconnector', 'LeadConnector'), 'lead_connector_section_text1', 'lead_connector_plugin');
register_setting(LEAD_CONNECTOR_OPTION_NAME, LEAD_CONNECTOR_OPTION_NAME, array(
'sanitize_callback' => array($this, 'lead_connector_setting_validate'),
));
}
public function admin_rest_api_init()
{
register_rest_route('lc_public_api/v1', '/proxy', array(
// By using this constant we ensure that when the WP_REST_Server changes our readable endpoints will work as intended.
'methods' => WP_REST_Server::READABLE,
// Here we register our callback. The callback is fired when this endpoint is matched by the WP_REST_Server class.
'callback' => array($this, 'lc_public_api_proxy'),
'permission_callback' => function () {
return current_user_can('manage_options');
},
));
register_rest_route('lc_public_api/v1', 'proxy', array(
// By using this constant we ensure that when the WP_REST_Server changes our readable endpoints will work as intended.
'methods' => WP_REST_Server::CREATABLE,
// Here we register our callback. The callback is fired when this endpoint is matched by the WP_REST_Server class.
'callback' => array($this, 'lc_public_api_proxy'),
'permission_callback' => function () {
return current_user_can('manage_options');
},
));
/**
* This endpoint is used to save custom values - Mainly done for async purposes.
* If we need to save custom values, we will call this endpoint.
*/
register_rest_route('lc_internal_api/v1', '/save_custom_values', array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array($this, 'lc_async_save_custom_values'),
'permission_callback' => function() {
// Allow any logged-in user to save custom values
return is_user_logged_in() && current_user_can('manage_options');
}
));
}
public function refresh_oauth_token()
{
return $this->lc_oauth_regenerate_token();
}
public function register_custom_post()
{
$labels = array(
'name' => _x('Funnels', 'lead connector funnels'),
'singular_name' => _x('Funnel', 'post type singular name'),
'add_new' => _x('Add New', 'Funnel'),
);
$args = array(
'labels' => $labels,
'description' => 'post your CRM account funnels on wordpress',
'public' => false,
'has_archive' => true,
'supports' => array(''),
'rewrite' => array('slug' => 'funnels'),
'register_meta_box_cb' => array($this, "remove_save_box"),
'hide_post_row_actions' => array('trash'),
);
register_post_type(lead_connector_constants\lc_custom_post_type, $args);
}
public function get_meta_fields($lc_post_meta)
{
$default_meta_fields = '
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, user-scalable=no"
/>
<meta
name="description"
content="description"
/>
<meta property="og:type" content="website" />
<meta
property="twitter:type"
content="website"
/>
<meta property="robots" content="noindex" />
';
try {
if (isset($lc_post_meta)) {
$lc_post_meta = json_decode($lc_post_meta);
if (isset($lc_post_meta->title) && $lc_post_meta->title !== '') {
$title_meta = '<title>' . $lc_post_meta->title . '</title>
<meta property="og:title" content="' . $lc_post_meta->title . '" />
';
$default_meta_fields .= $title_meta;
}
if (isset($lc_post_meta->description) && $lc_post_meta->description !== '') {
$description_meta = '<meta property="description" content="' . $lc_post_meta->description . '"/>
<meta property="og:description" content="' . $lc_post_meta->description . '" />
';
$default_meta_fields .= $description_meta;
}
if (isset($lc_post_meta->author) && $lc_post_meta->author !== '') {
$author_meta = '<meta property="author" content="' . $lc_post_meta->author . '"/>
<meta property="og:author" content="' . $lc_post_meta->author . '" />
';
$default_meta_fields .= $author_meta;
}
if (isset($lc_post_meta->imageUrl) && $lc_post_meta->imageUrl !== '') {
$imageUrl_meta = '<meta property="image" content="' . $lc_post_meta->imageUrl . '"/>
<meta property="og:image" content="' . $lc_post_meta->imageUrl . '" />
';
$default_meta_fields .= $imageUrl_meta;
}
if (isset($lc_post_meta->keywords) && $lc_post_meta->keywords !== '') {
$keywords_meta = '<meta property="keywords" content="' . $lc_post_meta->keywords . '"/>
<meta property="og:keywords" content="' . $lc_post_meta->keywords . '" />
';
$default_meta_fields .= $keywords_meta;
}
if (isset($lc_post_meta->customMeta) && count((array) $lc_post_meta->customMeta) > 0) {
foreach ($lc_post_meta->customMeta as $customMeta) {
if (isset($customMeta)) {
if (
isset($customMeta->name) && $customMeta->name !== '' &&
isset($customMeta->content) && $customMeta->content !== ''
) {
$custom_meta = '<meta property="' . $customMeta->name . '" content="' . $customMeta->content . '"/>';
$default_meta_fields .= $custom_meta;
}
}
}
}
}
} catch (Exception $e) {
// error_log("failed to parse the post meta");
// error_log(print_r($e, true));
}
return $default_meta_fields;
}
public function get_tracking_code($lc_post_tracking_code, $is_header, $is_funnel = false)
{
if (defined('WP_DEBUG') && true === WP_DEBUG) {
// error_log("get_tracking_code");
// error_log(print_r($lc_post_tracking_code, true));
}
$default_tracking_code = ' ';
try {
if (isset($lc_post_tracking_code)) {
if (!$is_funnel) {
$lc_post_tracking_code = base64_decode($lc_post_tracking_code);
}
$lc_post_tracking_code = json_decode($lc_post_tracking_code);
if ($is_header && isset($lc_post_tracking_code->headerCode) && $lc_post_tracking_code->headerCode !== '') {
$default_tracking_code = ($lc_post_tracking_code->headerCode);
}
if (!$is_header && isset($lc_post_tracking_code->footerCode) && $lc_post_tracking_code->footerCode !== '') {
$default_tracking_code = $lc_post_tracking_code->footerCode;
}
if ($is_funnel) {
$default_tracking_code = base64_decode($default_tracking_code);
}
}
} catch (Exception $e) {
// error_log("failed to parse the tracking code");
// error_log(print_r($e, true));
}
return $default_tracking_code;
}
public function get_page_iframe($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon)
{
$post_meta_fields = $this->get_meta_fields($lc_post_meta);
$head_tracking_code = $this->get_tracking_code($lc_funnel_tracking_code, true, true);
$head_tracking_code .= $this->get_tracking_code($lc_step_trackingCode, true);
$footer_tracking_code = $this->get_tracking_code($lc_funnel_tracking_code, false, true);
$footer_tracking_code .= $this->get_tracking_code($lc_step_trackingCode, false);
$favicon_code = '';
$widget_url = LEAD_CONNECTOR_CDN_BASE_URL . 'loader.js';
if ($lc_use_site_favicon) {
$favicon_url = get_site_icon_url();
$favicon_code = ' <link rel="icon" type="image/x-icon" href="' . $favicon_url . '">';
}
// wp_enqueue_script($this->plugin_name . ".lc_text_widget", LEAD_CONNECTOR_CDN_BASE_URL . 'loader.js');
// wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . 'js/lc-public.js', array('jquery'), $this->version, false);
// wp_localize_script($this->plugin_name, 'lc_public_js',
// array(
// 'text_widget_location_id' => $location_id,
// 'text_widget_heading' => $heading,
// 'text_widget_sub_heading' => $sub_heading,
// 'text_widget_error' => $text_widget_error,
// 'text_widget_use_email_field' => $use_email_field,
// "text_widget_settings" => $chat_widget_settings,
// ));
return '<!DOCTYPE html>
<head>
' . $favicon_code . '
' . $post_meta_fields . '
' . $head_tracking_code . '
<style>
body {
margin: 0; /* Reset default margin */
}
iframe {
display: block; /* iframes are inline by default */
border: none; /* Reset default border */
height: 100vh; /* Viewport-relative units */
width: 100vw;
}
</style>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<iframe width="100%" height="100%" src="' . $funnel_step_url . '" frameborder="0" allowfullscreen></iframe>
' . $footer_tracking_code . '
</body>
</html>';
}
public function get_page_iframe_native($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon)
{
// Check if funnel step URL is from allowed domain
$funnel_host = parse_url($funnel_step_url, PHP_URL_HOST);
$is_whitelabeled = false;
if ($funnel_host !== 'app.leadconnectorhq.com') {
$is_whitelabeled = true;
}
// Change the host to app.leadconnectorhq.com if it's whitelabeled
if ($is_whitelabeled) {
$funnel_step_url = str_replace($funnel_host, 'app.leadconnectorhq.com', $funnel_step_url);
$funnel_host = 'app.leadconnectorhq.com';
}
// Old Code Do not remove
if ($funnel_host !== 'app.leadconnectorhq.com') {
return sprintf(
'Error: Invalid funnel step URL domain. Expected app.leadconnectorhq.com but got %s',
esc_html($funnel_host)
);
}
// Make request with increased timeout
$response = wp_remote_get($funnel_step_url, array(
'timeout' => 30,
'sslverify' => true,
));
$iframe_content = '';
if (is_wp_error($response)) {
// Log the error for debugging
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('LeadConnector Native Page Error: ' . $response->get_error_message());
error_log('LeadConnector URL attempted: ' . $funnel_step_url);
}
return sprintf(
'<!-- Error fetching content: %s from URL: %s -->',
esc_html($response->get_error_message()),
esc_html($funnel_step_url)
);
}
$response_code = wp_remote_retrieve_response_code($response);
if ($response_code !== 200) {
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('LeadConnector Native Page Error: HTTP ' . $response_code);
error_log('LeadConnector URL attempted: ' . $funnel_step_url);
}
return sprintf(
'<!-- Error: Received HTTP %d from URL: %s -->',
intval($response_code),
esc_html($funnel_step_url)
);
}
$iframe_content = wp_remote_retrieve_body($response);
if (empty($iframe_content)) {
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('LeadConnector Native Page Error: Empty response body');
error_log('LeadConnector URL attempted: ' . $funnel_step_url);
}
return '<!-- Error: Empty response received from funnel URL -->';
}
return $iframe_content;
}
public function process_page_request()
{
$full_request_url = (is_ssl() ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$request_url_parts = explode("?", $full_request_url);
$request_url = $request_url_parts[0];
$base_url = get_home_url() . "/";
$slug = str_replace($base_url, "", $request_url);
$slug = rtrim($slug, '/');
if ($slug != '') {
$query_args = array(
'meta_key' => 'lc_slug',
'meta_value' => $slug,
'post_type' => lead_connector_constants\lc_custom_post_type,
'compare' => '=',
);
$the_posts = get_posts($query_args);
$lc_page = current($the_posts);
if ($lc_page) {
status_header(200);
$post_id = $lc_page->ID;
$funnel_step_url = get_post_meta($post_id, "lc_step_url", true);
$lc_display_method = get_post_meta($post_id, "lc_display_method", true);
$lc_post_meta = get_post_meta($post_id, "lc_step_meta", true);
$lc_step_trackingCode = get_post_meta($post_id, "lc_step_trackingCode", true);
$lc_funnel_tracking_code = get_post_meta($post_id, "lc_funnel_tracking_code", true);
$lc_include_tracking_code = get_post_meta($post_id, "lc_include_tracking_code", true);
$lc_use_site_favicon = get_post_meta($post_id, "lc_use_site_favicon", true);
$lc_include_wp_headers_and_footers = get_post_meta($post_id, "lc_include_wp_headers_and_footers", true);
if (!$lc_include_tracking_code) {
$lc_step_trackingCode = null;
$lc_funnel_tracking_code = null;
}
if ($lc_display_method == "iframe" || $lc_display_method == "native") {
// Check if we should use WordPress headers and footers (for both iframe and native)
if ($lc_include_wp_headers_and_footers && $lc_display_method == "native") {
$this->setup_native_display_with_wp_headers(
$lc_page,
$funnel_step_url,
$lc_post_meta,
$lc_step_trackingCode,
$lc_funnel_tracking_code,
$lc_use_site_favicon
);
return;
}
// Standard rendering without WP headers/footers
if ($lc_display_method == "native") {
$content = $this->get_page_iframe_native($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon);
} else {
$content = $this->get_page_iframe($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon);
}
$allowed_html = array(
'head' => array(),
'style' => array(),
'body' => array(),
'html' => array(),
'title' => array(),
'script' => array(),
'noscript' => array(),
//links
'iframe' => array(
'href' => array(),
'src' => array(),
'width' => array(),
'height' => array(),
'frameborder' => array(),
'allowfullscreen' => array()
),
'meta' => array(
'property' => array(),
'content' => array(),
'name' => array()
),
'link' => array(
'rel' => array(),
'type' => array(),
'href' => array()
)
);
// echo $content;
if ($lc_display_method == "native") {
// Outputting unescaped HTML from a trusted internal source.please check function get_page_iframe_native it has restriction that the host should be app.leadconnectorhq.com
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Trusted internal HTML source
echo $content;
} else {
echo wp_kses($content, $allowed_html);
}
} else {
wp_redirect($funnel_step_url, 301);
}
exit();
}
}
}
public function check_smtp_plugin_conflict()
{
if (!function_exists('get_plugins')) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$plugins = get_plugins();
$could_have_conflict = false;
$plugins_with_conflict = "";
$active_plugins = get_option('active_plugins');
foreach ($plugins as $plugin_key => $plugin) { // get the key of array plugins aswell
if (strpos($plugin['Name'], 'SMTP') !== false) {
if (in_array($plugin_key, $active_plugins)) {
$could_have_conflict = true;
if ($plugins_with_conflict == "") {
$plugins_with_conflict .= $plugin['Name'];
} else {
$plugins_with_conflict .= ", " . $plugin['Name'] . ", ";
}
}
}
}
return array(
'could_have_conflict' => $could_have_conflict,
'plugins' => $plugins_with_conflict,
);
}
public function lc_async_save_custom_values($request) {
$data = $request->get_json_params();
// Fallback for non-blocking requests where get_json_params can fail
if (empty($data)) {
$raw_body = $request->get_body();
$data = json_decode($raw_body, true);
}
if (!empty($data) && isset($data['custom_values'])) {
$custom_values_manager = new LeadConnector_CustomValues();
$custom_values_manager->store_custom_values($data['custom_values']);
}
return new WP_REST_Response(array('status' => 'success'), 200);
}
/**
* Setup native display with WordPress headers and footers
* For theme-agnostic header/footer support, using the content filter approach
* instead of custom template loading. This works with ALL themes including
*
* @param WP_Post $lc_page The page post object
* @param string $funnel_step_url The funnel step URL
* @param string $lc_post_meta Post meta data
* @param string $lc_step_trackingCode Step tracking code
* @param string $lc_funnel_tracking_code Funnel tracking code
* @param bool $lc_use_site_favicon Whether to use site favicon
*/
private function setup_native_display_with_wp_headers($lc_page, $funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon) {
// Setup WordPress query to treat this as a valid page
$this->setup_wp_query_for_native_page($lc_page, $lc_post_meta);
// Add content filter to inject native HTML into the page content
$this->add_native_content_filter($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon);
// Add head content via wp_head action
$this->add_native_head_content($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon);
// Add footer tracking code
$this->add_native_footer_tracking($lc_step_trackingCode, $lc_funnel_tracking_code);
// Add body class for styling
$this->add_native_body_class();
}
/**
* Setup WordPress query variables for native page display
*
* @param WP_Post $lc_page The page post object
* @param string $lc_post_meta Post meta data containing title and other SEO fields
*/
private function setup_wp_query_for_native_page($lc_page, $lc_post_meta = '') {
global $wp_query, $post;
// Reset query vars to treat this as a valid page
$wp_query->is_404 = false;
$wp_query->is_page = true;
$wp_query->is_singular = true;
$wp_query->is_home = false;
$wp_query->found_posts = 1;
$wp_query->post_count = 1;
$wp_query->max_num_pages = 1;
// Set the current post
$post = $lc_page;
$wp_query->post = $post;
$wp_query->posts = array($post);
$wp_query->queried_object = $post;
$wp_query->queried_object_id = $post->ID;
// Setup post data properly
setup_postdata($post);
}
/**
* Add content filter to inject native HTML content
*
* @param string $funnel_step_url The funnel step URL
* @param string $lc_post_meta Post meta data
* @param string $lc_step_trackingCode Step tracking code
* @param string $lc_funnel_tracking_code Funnel tracking code
* @param bool $lc_use_site_favicon Whether to use site favicon
*/
private function add_native_content_filter($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon) {
add_filter('the_content', function($content) use ($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon) {
// Fetch and return native content
$native_html_content = $this->get_page_iframe_native($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon);
if (!empty($native_html_content)) {
// Parse HTML to extract body content
$native_body_content = $this->extract_body_content($native_html_content);
return '<div class="lc-native-content">' . $native_body_content . '</div>';
}
return '<div style="padding: 2em; text-align: center;"><h2>Error: Failed to load funnel content.</h2><p>Please check if the funnel URL is valid.</p></div>';
}, 10);
}
/**
* Extract body content from HTML
*
* Uses regex-based extraction to preserve HTML5 elements like video, source, etc.
* DOMDocument has issues with HTML5 self-closing tags like <source>
*
* @param string $html_content The full HTML content
* @return string The body content
*/
private function extract_body_content($html_content) {
// Extract BODY content using regex to preserve HTML5 elements (video, source, etc.)
if (preg_match('/<body[^>]*>(.*)<\/body>/is', $html_content, $body_matches)) {
return $body_matches[1];
}
// If no body tag found, try to strip doctype/html/head wrapper if present
$body_content = preg_replace('/^.*?<body[^>]*>/is', '', $html_content);
$body_content = preg_replace('/<\/body>.*$/is', '', $body_content);
// If still no body content extracted, use original content
if (empty(trim($body_content))) {
return $html_content;
}
return $body_content;
}
/**
* Add native head content via wp_head action
*
* @param string $funnel_step_url The funnel step URL
* @param string $lc_post_meta Post meta data
* @param string $lc_step_trackingCode Step tracking code
* @param string $lc_funnel_tracking_code Funnel tracking code
* @param bool $lc_use_site_favicon Whether to use site favicon
*/
private function add_native_head_content($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon) {
add_action('wp_head', function() use ($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon) {
// Get native HTML and extract head content
$native_html_content = $this->get_page_iframe_native($funnel_step_url, $lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code, $lc_use_site_favicon);
if (!empty($native_html_content)) {
$this->output_head_content($native_html_content);
}
// Add meta fields and tracking codes
$this->output_meta_and_tracking($lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code);
// Add favicon
$this->output_favicon($lc_use_site_favicon);
// Add styling for full-width display
$this->output_native_page_styles();
}, 10);
}
/**
* Output head content from native HTML
*
* Uses regex-based extraction to preserve JavaScript and HTML5 elements.
* DOMDocument corrupts inline JavaScript which breaks Lead Connector's config (baseURL, etc.)
*
* @param string $html_content The full HTML content
*/
private function output_head_content($html_content) {
// Add crypto.randomUUID polyfill for embeds like Loom that require it
echo '<script>
if (typeof crypto !== "undefined" && typeof crypto.randomUUID !== "function") {
crypto.randomUUID = function() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c === "x" ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
};
}
</script>';
// Extract HEAD content using regex to preserve JavaScript exactly as-is
// DOMDocument corrupts inline JS which breaks Lead Connector's configuration
if (preg_match('/<head[^>]*>(.*?)<\/head>/is', $html_content, $head_matches)) {
$head_content = $head_matches[1];
// Remove title tags as WordPress handles those
$head_content = preg_replace('/<title[^>]*>.*?<\/title>/is', '', $head_content);
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Trusted internal source from Lead Connector
echo $head_content;
}
}
/**
* Output meta fields and tracking codes in head
*
* @param string $lc_post_meta Post meta data
* @param string $lc_step_trackingCode Step tracking code
* @param string $lc_funnel_tracking_code Funnel tracking code
*/
private function output_meta_and_tracking($lc_post_meta, $lc_step_trackingCode, $lc_funnel_tracking_code) {
$post_meta_fields = $this->get_meta_fields($lc_post_meta);
$head_tracking_code = $this->get_tracking_code($lc_funnel_tracking_code, true, true);
$head_tracking_code .= $this->get_tracking_code($lc_step_trackingCode, true);
if (!empty($post_meta_fields)) {
echo $post_meta_fields;
}
if (!empty($head_tracking_code)) {
echo $head_tracking_code;
}
}
/**
* Output favicon if enabled
*
* @param bool $lc_use_site_favicon Whether to use site favicon
*/
private function output_favicon($lc_use_site_favicon) {
if ($lc_use_site_favicon) {
$favicon_url = get_site_icon_url();
if ($favicon_url) {
echo '<link rel="icon" type="image/x-icon" href="' . esc_url($favicon_url) . '">';
}
}
}
/**
* Output native page styles for full-width display
*/
private function output_native_page_styles() {
echo '<style>
/* Hide admin bar */
#wpadminbar { display: none !important; }
html { margin-top: 0 !important; }
/* Hide the post title for native pages */
body.lc-native-page .entry-header,
body.lc-native-page .page-header,
body.lc-native-page h1.entry-title,
body.lc-native-page h1.page-title,
body.lc-native-page .wp-block-post-title {
display: none !important;
}
/* Make content full width - theme agnostic */
body.lc-native-page .lc-native-content {
width: 100vw !important;
max-width: 100vw !important;
margin-left: calc(50% - 50vw) !important;
margin-right: calc(50% - 50vw) !important;
}
/* Remove all padding/margins from content containers */
body.lc-native-page .entry-content,
body.lc-native-page .post-content,
body.lc-native-page article,
body.lc-native-page main {
padding: 0 !important;
margin: 0 !important;
max-width: none !important;
}
/* Override theme container constraints */
body.lc-native-page .wp-block-post-content,
body.lc-native-page .has-global-padding,
body.lc-native-page .is-layout-constrained {
padding-left: 0 !important;
padding-right: 0 !important;
}
/* Reduce excessive top/bottom padding on block groups */
body.lc-native-page .wp-block-group {
padding-top: 5px !important;
padding-bottom: 5px !important;
}
/* Ensure container doesn\'t limit width */
body.lc-native-page .site-main,
body.lc-native-page .content-area {
max-width: none !important;
}
</style>';
}
/**
* Add footer tracking codes
*
* @param string $lc_step_trackingCode Step tracking code
* @param string $lc_funnel_tracking_code Funnel tracking code
*/
private function add_native_footer_tracking($lc_step_trackingCode, $lc_funnel_tracking_code) {
add_action('wp_footer', function() use ($lc_step_trackingCode, $lc_funnel_tracking_code) {
$footer_tracking_code = $this->get_tracking_code($lc_funnel_tracking_code, false, true);
$footer_tracking_code .= $this->get_tracking_code($lc_step_trackingCode, false);
if (!empty($footer_tracking_code)) {
echo $footer_tracking_code;
}
}, 10);
}
/**
* Add body class for native pages
*/
private function add_native_body_class() {
add_filter('body_class', function($classes) {
$classes[] = 'lc-native-page';
return $classes;
});
}
private function clear_host_cache(){
// Get The Site ID and the Cache Token
$cdn_site_id = defined('CDN_SITE_ID') ? CDN_SITE_ID : '';
$cdn_site_token = defined('CDN_SITE_TOKEN') ? CDN_SITE_TOKEN : '';
// Return the function if the siteId and siteToken are not set
if(empty($cdn_site_id) || empty($cdn_site_token)){
return false;
}
// Make API Call to Clear the Cache
$response = wp_remote_post('https://api.rocket.net/v1/sites/' . $cdn_site_id . '/cache/purge_everything', array(
'headers' => array(
'Authorization' => 'Bearer ' . $cdn_site_token,
),
));
if(is_wp_error($response)){
return false;
}
return true;
}
/**
* Conditionally clear caches on save_post, skipping autosaves,
* revisions, and non-public post types to avoid excessive cache purges.
*
* @since 1.0.0
* @param int $post_id
* @param WP_Post $post
*/
public function maybe_clear_all_caches($post_id, $post) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
return;
}
if ($post->post_status !== 'publish') {
return;
}
$public_types = get_post_types(array('public' => true));
if (!in_array($post->post_type, $public_types, true)) {
return;
}
$this->clear_all_caches();
}
/**
* Clear cache from popular caching plugins
* This ensures that changes (like widget enable/disable) are reflected immediately
*
* @since 1.0.0
* @return array Array of results with plugin names and success status
*/
public function clear_all_caches() {
$results = array();
// Define cache clearing methods for popular plugins
// Easy to add more plugins to this array
$cache_plugins = array(
// 1. WP Rocket
'wp_rocket' => array(
'name' => 'WP Rocket',
'check' => function() {
return function_exists('rocket_clean_domain');
},
'clear' => function() {
rocket_clean_domain();
// Also clear minified CSS and JS
if (function_exists('rocket_clean_minify')) {
rocket_clean_minify();
}
}
),
// 2. W3 Total Cache
'w3_total_cache' => array(
'name' => 'W3 Total Cache',
'check' => function() {
return function_exists('w3tc_flush_all');
},
'clear' => function() {
w3tc_flush_all();
}
),
// 3. WP Super Cache
'wp_super_cache' => array(
'name' => 'WP Super Cache',
'check' => function() {
return function_exists('wp_cache_clear_cache');
},
'clear' => function() {
global $file_prefix;
wp_cache_clear_cache();
}
),
// 4. LiteSpeed Cache
'litespeed_cache' => array(
'name' => 'LiteSpeed Cache',
'check' => function() {
return class_exists('LiteSpeed\Purge');
},
'clear' => function() {
do_action('litespeed_purge_all');
}
),
// 5. WP Fastest Cache
'wp_fastest_cache' => array(
'name' => 'WP Fastest Cache',
'check' => function() {
return class_exists('WpFastestCache');
},
'clear' => function() {
if (class_exists('WpFastestCache')) {
$wpfc = new WpFastestCache();
$wpfc->deleteCache();
}
}
),
// 6. Cache Enabler
'cache_enabler' => array(
'name' => 'Cache Enabler',
'check' => function() {
return class_exists('Cache_Enabler');
},
'clear' => function() {
if (class_exists('Cache_Enabler')) {
Cache_Enabler::clear_total_cache();
}
}
),
// 7. Comet Cache
'comet_cache' => array(
'name' => 'Comet Cache',
'check' => function() {
return class_exists('comet_cache');
},
'clear' => function() {
if (class_exists('comet_cache')) {
comet_cache::clear();
}
}
),
// 8. Hummingbird
'hummingbird' => array(
'name' => 'Hummingbird',
'check' => function() {
return class_exists('Hummingbird\WP_Hummingbird');
},
'clear' => function() {
do_action('wphb_clear_page_cache');
}
),
// 9. SiteGround Optimizer
'siteground_optimizer' => array(
'name' => 'SiteGround Optimizer',
'check' => function() {
return function_exists('sg_cachepress_purge_cache');
},
'clear' => function() {
sg_cachepress_purge_cache();
}
),
// 10. Autoptimize
'autoptimize' => array(
'name' => 'Autoptimize',
'check' => function() {
return class_exists('autoptimizeCache');
},
'clear' => function() {
if (class_exists('autoptimizeCache')) {
autoptimizeCache::clearall();
}
}
),
// 11. Swift Performance
'swift_performance' => array(
'name' => 'Swift Performance',
'check' => function() {
return class_exists('Swift_Performance_Cache');
},
'clear' => function() {
if (class_exists('Swift_Performance_Cache')) {
Swift_Performance_Cache::clear_all_cache();
}
}
),
// 12. Breeze (Cloudways)
'breeze' => array(
'name' => 'Breeze',
'check' => function() {
return class_exists('Breeze_PurgeCache');
},
'clear' => function() {
if (class_exists('Breeze_PurgeCache')) {
Breeze_PurgeCache::breeze_cache_flush();
}
}
),
// Add more caching plugins here as needed
// Template:
// 'plugin_key' => array(
// 'name' => 'Plugin Display Name',
// 'check' => function() {
// return function_exists('plugin_function') || class_exists('Plugin_Class');
// },
// 'clear' => function() {
// // Code to clear cache
// }
// ),
);
// Try to clear cache for each detected plugin
foreach ($cache_plugins as $key => $plugin) {
try {
if (call_user_func($plugin['check'])) {
call_user_func($plugin['clear']);
$results[$key] = array(
'name' => $plugin['name'],
'success' => true,
'message' => 'Cache cleared successfully'
);
}
} catch (Exception $e) {
$results[$key] = array(
'name' => $plugin['name'],
'success' => false,
'message' => 'Error: ' . $e->getMessage()
);
}
}
// Also clear WordPress object cache if available
if (function_exists('wp_cache_flush')) {
wp_cache_flush();
$results['wp_object_cache'] = array(
'name' => 'WordPress Object Cache',
'success' => true,
'message' => 'Object cache flushed'
);
}
// Clear opcache if available
if (function_exists('opcache_reset')) {
opcache_reset();
$results['opcache'] = array(
'name' => 'PHP OPcache',
'success' => true,
'message' => 'OPcache cleared'
);
}
// Clear System Cache -- Internal
$host_cache_clear_response = $this->clear_host_cache();
if($host_cache_clear_response){
$results['host_cache'] = array(
'name' => 'Host Cache',
'success' => true,
'message' => 'Host cache cleared'
);
}
return $results;
}
/**
* Clear cache with admin notice feedback
* Wrapper function that can be called from hooks
*
* @since 1.0.0
*/
public function clear_cache_with_notice() {
$results = $this->clear_all_caches();
$cleared_plugins = array_filter($results, function($result) {
return $result['success'];
});
echo '<pre>';
print_r($results);
echo '</pre>';
if (!empty($cleared_plugins)) {
$plugin_names = array_map(function($result) {
return $result['name'];
}, $cleared_plugins);
$message = sprintf(
'LeadConnector: Cache cleared for %d plugin(s): %s',
count($cleared_plugins),
implode(', ', $plugin_names)
);
add_action('admin_notices', function() use ($message) {
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html($message) . '</p></div>';
});
}
return $results;
}
}