plugin updates

This commit is contained in:
Tony Volpe
2024-06-17 15:33:26 -04:00
parent 3751a5a1a6
commit e4e274a9a7
2674 changed files with 0 additions and 507851 deletions

View File

@@ -1,206 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\data\Filters;
use Leadin\admin\Links;
use Leadin\admin\Routing;
use Leadin\auth\OAuth;
use Leadin\utils\Versions;
use Leadin\data\User;
use Leadin\data\Portal_Options;
use Leadin\admin\Connection;
use Leadin\admin\Impact;
use Leadin\data\User_Metadata;
/**
* Class containing all the constants used for admin script localization.
*/
class AdminConstants {
/**
* Return utm_campaign to add to the signup link.
*/
private static function get_utm_campaign() {
$wpe_template = get_option( 'wpe_template' );
if ( 'hubspot' === $wpe_template ) {
return 'wp-engine-site-template';
}
}
/**
* Return an array with the utm parameters for signup
*/
private static function get_utm_query_params_array() {
$utm_params = array(
'utm_source' => 'wordpress-plugin',
'utm_medium' => 'marketplaces',
);
$utm_campaign = self::get_utm_campaign();
if ( ! empty( $utm_campaign ) ) {
$utm_params['utm_campaign'] = $utm_campaign;
}
return $utm_params;
}
/**
* Return a nonce used on the connection class
*/
private static function get_connection_nonce() {
return wp_create_nonce( 'hubspot-nonce' );
}
/**
* Return an array with the user's pre-fill info for signup
*/
private static function get_signup_prefill_params_array() {
$wp_user = wp_get_current_user();
$user_info = array(
'firstName' => $wp_user->user_firstname,
'lastName' => $wp_user->user_lastname,
'email' => $wp_user->user_email,
'company' => get_bloginfo( 'name' ),
);
return $user_info;
}
/**
* Return an array of properties to be included in the signup search string
*/
public static function get_signup_query_params_array() {
$signup_params = array();
$signup_params['leadinPluginVersion'] = constant( 'LEADIN_PLUGIN_VERSION' );
$signup_params['trackConsent'] = User_Metadata::get_track_consent();
$user_prefill_params = self::get_signup_prefill_params_array();
$signup_params = array_merge( $signup_params, $user_prefill_params );
return $signup_params;
}
/**
* Return query params array for the iframe.
*/
public static function get_hubspot_query_params_array() {
$wp_user = wp_get_current_user();
$hubspot_config = array(
'l' => get_locale(),
'php' => Versions::get_php_version(),
'v' => LEADIN_PLUGIN_VERSION,
'wp' => Versions::get_wp_version(),
'theme' => get_option( 'stylesheet' ),
'adminUrl' => admin_url(),
'websiteName' => get_bloginfo( 'name' ),
'domain' => parse_url( get_site_url(), PHP_URL_HOST ),
'wp_user' => $wp_user->first_name ? $wp_user->first_name : $wp_user->user_nicename,
'nonce' => self::get_connection_nonce(),
'accountName' => Portal_Options::get_account_name(),
'hsdio' => Portal_Options::get_device_id(),
'portalDomain' => Portal_Options::get_portal_domain(),
);
$utm_params = self::get_utm_query_params_array();
$hubspot_config = array_merge( $hubspot_config, $utm_params );
if ( User::is_admin() ) {
$hubspot_config['admin'] = '1';
}
if ( Routing::has_just_connected_with_oauth() ) {
$hubspot_config['justConnected'] = true;
}
if ( Routing::is_new_portal_with_oauth() ) {
$hubspot_config['isNewPortal'] = true;
}
if ( ! Connection::is_connected() ) {
$signup_params = self::get_signup_query_params_array();
$hubspot_config = array_merge( $hubspot_config, $signup_params, Impact::get_params() );
}
return $hubspot_config;
}
/**
* Returns information about Content embed plugin necessary for user guide to determine if/how to install & activate
*/
public static function get_content_embed_config() {
$content_embed_config = array_merge(
array(
'userCanInstall' => current_user_can( 'install_plugins' ),
'userCanActivate' => current_user_can( 'activate_plugins' ),
'nonce' => wp_create_nonce( ContentEmbedInstaller::INSTALL_ARG ),
),
ContentEmbedInstaller::is_content_embed_active_installed()
);
return $content_embed_config;
}
/**
* Returns a minimal version of leadinConfig, containing the data needed by the background iframe.
*/
public static function get_background_leadin_config() {
$wp_user_id = get_current_user_id();
$background_config = array(
'adminUrl' => admin_url(),
'activationTime' => Portal_Options::get_activation_time(),
'deviceId' => Portal_Options::get_device_id(),
'formsScript' => Filters::apply_forms_script_url_filters(),
'formsScriptPayload' => Filters::apply_forms_payload_filters(),
'meetingsScript' => Filters::apply_meetings_script_url_filters(),
'hublet' => Filters::apply_hublet_filters(),
'hubspotBaseUrl' => Filters::apply_base_url_filters( Connection::is_connected() ),
'leadinPluginVersion' => constant( 'LEADIN_PLUGIN_VERSION' ),
'locale' => get_locale(),
'restUrl' => get_rest_url(),
'restNonce' => wp_create_nonce( 'wp_rest' ),
'redirectNonce' => wp_create_nonce( Routing::REDIRECT_NONCE ),
'phpVersion' => Versions::get_php_version(),
'pluginPath' => constant( 'LEADIN_PATH' ),
'plugins' => get_plugins(),
'portalId' => Portal_Options::get_portal_id(),
'accountName' => Portal_Options::get_account_name(),
'portalDomain' => Portal_Options::get_portal_domain(),
'portalEmail' => get_user_meta( $wp_user_id, 'leadin_email', true ),
'reviewSkippedDate' => User_Metadata::get_skip_review(),
'theme' => get_option( 'stylesheet' ),
'wpVersion' => Versions::get_wp_version(),
'leadinQueryParams' => self::get_hubspot_query_params_array(),
'connectionStatus' => Connection::is_connected() ? 'Connected' : 'NotConnected',
'contentEmbed' => self::get_content_embed_config(),
'requiresContentEmbedScope' => is_plugin_active( 'hubspot-content-embed/content-embed.php' ) ? '1' : '0',
'lastAuthorizeTime' => Portal_Options::get_last_authorize_time(),
'lastDeauthorizeTime' => Portal_Options::get_last_deauthorize_time(),
'lastDisconnectTime' => Portal_Options::get_last_disconnect_time(),
'refreshTokenError' => Portal_Options::get_refresh_token_error(),
);
if ( Connection::is_connected() ) {
$background_config['refreshToken'] = OAuth::get_refresh_token();
}
return $background_config;
}
/**
* Returns leadinConfig, containing all the data needed by the leadin javascript.
*/
public static function get_leadin_config() {
$leadin_config = self::get_background_leadin_config();
if ( ! Connection::is_connected() ) {
if ( ! Impact::has_params() ) {
$impact_link = Impact::get_affiliate_link();
if ( ! empty( $impact_link ) ) {
$leadin_config['impactLink'] = Impact::get_affiliate_link();
}
}
}
return $leadin_config;
}
}

View File

@@ -1,168 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\data\Portal_Options;
use Leadin\data\User;
use Leadin\utils\QueryParameters;
use Leadin\auth\OAuth;
/**
* Handles portal connection to the plugin.
*/
class Connection {
const CONNECT_KEYS = array(
'refresh_token',
'expires_in',
'portal_id',
'portal_domain',
'portal_name',
'hublet',
);
const CONNECT_NONCE_ARG = 'leadin_connect';
const DISCONNECT_NONCE_ARG = 'leadin_disconnect';
/**
* Returns true if a portal has been connected to the plugin
*/
public static function is_connected() {
return ! empty( Portal_Options::get_portal_id() ) && ! empty( OAuth::get_refresh_token() );
}
/**
* Returns true if the current request is for the plugin to connect to a portal
*/
public static function is_connection_requested() {
$maybe_leadin_connect = QueryParameters::get_param( self::CONNECT_NONCE_ARG, 'hubspot-nonce', self::CONNECT_NONCE_ARG );
$maybe_refresh_token = QueryParameters::get_param( 'refresh_token', 'hubspot-nonce', self::CONNECT_NONCE_ARG );
return isset( $maybe_leadin_connect ) && isset( $maybe_refresh_token );
}
/**
* Returns true if the current request is for the plugin to connect to a portal
*/
public static function is_new_portal() {
$maybe_is_new_portal = QueryParameters::get_param( 'is_new_portal', 'hubspot-nonce', self::CONNECT_NONCE_ARG );
return isset( $maybe_is_new_portal );
}
/**
* Returns true if the current request is to disconnect the plugin from the portal
*/
public static function is_disconnection_requested() {
$maybe_leadin_disconnect = QueryParameters::get_param( self::DISCONNECT_NONCE_ARG, 'hubspot-nonce', self::DISCONNECT_NONCE_ARG );
return isset( $maybe_leadin_disconnect );
}
/**
* Retrieves user ID and create new metadata
*
* @param Array $user_meta array of pairs metadata - value.
*/
private static function add_metadata( $user_meta ) {
$wp_user = wp_get_current_user();
$wp_user_id = $wp_user->ID;
foreach ( $user_meta as $key => $value ) {
add_user_meta( $wp_user_id, $key, $value );
}
}
/**
* Retrieves user ID and deletes a piece of the users meta data.
*
* @param String $meta_key is the key of the data you want to delete.
*/
private static function delete_metadata( $meta_key ) {
$wp_user = wp_get_current_user();
$wp_user_id = $wp_user->ID;
delete_user_meta( $wp_user_id, $meta_key );
}
/**
* Connect portal id, domain, name to WordPress options and HubSpot email to user meta data.
*
* @param Number $portal_id HubSpot account id.
* @param String $portal_name HubSpot account name.
* @param String $portal_domain HubSpot account domain.
* @param String $hs_user_email HubSpot user email.
* @param String $hublet HubSpot account's hublet.
*/
public static function connect( $portal_id, $portal_name, $portal_domain, $hs_user_email, $hublet ) {
self::disconnect();
self::store_portal_info( $portal_id, $portal_name, $portal_domain, $hublet );
self::add_metadata( array( 'leadin_email' => $hs_user_email ) );
}
/**
* Connect the plugin with OAuthorization. Storing OAuth tokens and metadata for the connected portal.
*/
public static function oauth_connect() {
$connect_params = QueryParameters::get_parameters( self::CONNECT_KEYS, 'hubspot-nonce', self::CONNECT_NONCE_ARG );
self::disconnect();
self::store_portal_info(
$connect_params['portal_id'],
$connect_params['portal_name'],
$connect_params['portal_domain'],
$connect_params['hublet']
);
OAuth::authorize( $connect_params['refresh_token'] );
}
/**
* Removes portal id and domain from the WordPress options.
*/
public static function disconnect() {
Portal_Options::set_last_disconnect_time();
self::delete_portal_info();
$users = get_users(
array( 'role__in' => array( 'administrator', 'editor' ) ),
array( 'fields' => array( 'ID' ) )
);
foreach ( $users as $user ) {
delete_user_meta( $user->ID, 'leadin_email' );
delete_user_meta( $user->ID, 'leadin_skip_review' );
delete_user_meta( $user->ID, 'leadin_review_banner_last_call' );
delete_user_meta( $user->ID, 'leadin_has_min_contacts' );
delete_user_meta( $user->ID, 'leadin_track_consent' );
}
OAuth::deauthorize();
}
/**
* Store the portal metadata for connecting the plugin in the options table
*
* @param String $portal_id ID for connecting portal.
* @param String $portal_name Name of the connecting portal.
* @param String $portal_domain Domain for the connecting portal.
* @param String $hublet Hublet for the connecting portal.
*/
public static function store_portal_info( $portal_id, $portal_name, $portal_domain, $hublet ) {
Portal_Options::set_portal_id( $portal_id );
Portal_Options::set_account_name( $portal_name );
Portal_Options::set_portal_domain( $portal_domain );
Portal_Options::set_hublet( $hublet );
Portal_Options::set_disable_internal_tracking();
}
/**
* Delete stored portal metadata for disconnecting the plugin from the options table
*/
private static function delete_portal_info() {
Portal_Options::delete_portal_id();
Portal_Options::delete_account_name();
Portal_Options::delete_portal_domain();
Portal_Options::delete_hublet();
Portal_Options::delete_disable_internal_tracking();
Portal_Options::delete_business_unit_id();
}
}

View File

@@ -1,154 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\utils\QueryParameters;
/**
* Class used to install the Content embed plugin
*/
class ContentEmbedInstaller {
const CONTENT_EMBED_LINK = 'https://api.hubapi.com/content-embed/v1/plugin/download/content-hub-embed.zip';
const INSTALL_ARG = 'contentembed_install';
const INSTALL_OPTION = LEADIN_PREFIX . '_content_embed_ui_install';
/**
* Class constructor, adds the necessary hooks.
*/
public function __construct() {
if ( is_admin() ) {
add_action( 'wp_ajax_content_embed_install', array( $this, 'wp_ajax_install_content_embed' ) );
}
}
/**
* AJAX to install Content embed plugin by downloading from URL in Content embed API.
* Modified from: https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-admin/includes/ajax-actions.php#L4444
*/
public function wp_ajax_install_content_embed() {
$nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( ( $_REQUEST['_wpnonce'] ) ) ) : '';
if ( ! current_user_can( 'install_plugins' ) || ! wp_verify_nonce( $nonce, self::INSTALL_ARG ) ) {
$status['errorCode'] = 'PERMISSIONS_ERROR';
$status['errorMessage'] = 'User does not have permission to install or activate plugins.';
return wp_send_json_error( $status, 403 );
}
$active_or_installed = self::is_content_embed_active_installed();
$activated = $active_or_installed['active'];
$installed = $active_or_installed['installed'];
if ( $activated || $installed ) {
$status['errorCode'] = $activated ? 'ALREADY_ACTIVATED' : 'ALREADY_INSTALLED';
$status['errorMessage'] = 'Content embed already installed or activated';
wp_send_json_error( $status );
}
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
require_once ABSPATH . 'wp-admin/includes/plugin.php';
$skin = new \WP_Ajax_Upgrader_Skin();
$upgrader = new \Plugin_Upgrader( $skin );
$result = $upgrader->install( self::CONTENT_EMBED_LINK );
if ( is_wp_error( $result ) ) {
$status['errorCode'] = 'GENERIC_ERROR';
$status['errorMessage'] = $result->get_error_message();
wp_send_json_error( $status );
}
if ( is_wp_error( $skin->result ) ) {
$status['errorCode'] = 'GENERIC_ERROR';
$status['errorMessage'] = $skin->result->get_error_message();
wp_send_json_error( $status );
}
if ( $skin->get_errors()->has_errors() ) {
$status['errorCode'] = 'GENERIC_ERROR';
$status['errorMessage'] = $skin->get_error_messages();
wp_send_json_error( $status );
}
if ( is_null( $result ) ) {
global $wp_filesystem;
$status['errorCode'] = 'FILESYSTEM_ERROR';
$status['errorMessage'] = 'Unable to connect to the filesystem. Please confirm your credentials.';
// Pass through the error from WP_Filesystem if one was raised.
if ( $wp_filesystem instanceof \WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
}
wp_send_json_error( $status );
}
$plugin_info = $upgrader->plugin_info();
if ( ! $plugin_info ) {
return wp_send_json_error(
array(
'errorCode' => 'INFO_FETCH_ERROR',
'errorMessage' => 'Plugin installation failed, could not retrieve plugin info',
),
500
);
}
$status = array(
'message' => 'Plugin installed and activated successfully',
'plugin_info' => $plugin_info,
'activated' => false,
);
if ( current_user_can( 'activate_plugins' ) ) {
$activation_response = activate_plugin( $plugin_info );
if ( is_wp_error( $activation_response ) ) {
$status['errorCode'] = 'ACTIVATION_ERROR';
$status['errorMessage'] = $activation_response->get_error_message();
} else {
$status['activated'] = true;
}
}
update_option( self::INSTALL_OPTION, true );
return wp_send_json_success( $status );
}
/**
* Determine if there is a copy of Content embed installed, and if so, if it is active.
* Checks for path names with junk at the end to handle multiple installs
*/
public static function is_content_embed_active_installed() {
$content_embed_regex = '/hubspot-content-embed((-.*)?)\/content-embed.php/';
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
// Filter based on regex in case there are multiple copies installed for some reason.
$all_plugins = array_keys( get_plugins() );
$content_embed_paths = array_filter(
$all_plugins,
function ( $plugin_path ) use ( $content_embed_regex ) {
return preg_match( $content_embed_regex, $plugin_path );
}
);
$installed = ! empty( $content_embed_paths );
$active = ! empty(
array_filter(
$content_embed_paths,
function ( $plugin_path ) {
return is_plugin_active( $plugin_path );
}
)
);
return array(
'installed' => $installed,
'active' => $active,
);
}
}

View File

@@ -1,100 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\data\Portal_Options;
use \Leadin\includes\utils as utils;
/**
* Class responsible for rendering the deactivation feedback form.
*/
class DeactivationForm {
/**
* Class constructor, adds necessary hooks.
*/
public function __construct() {
add_action( 'admin_footer', array( $this, 'add_feedback_form' ) );
}
/**
* Render deactivation feedback form on plugin page.
*/
public function add_feedback_form() {
if ( get_current_screen()->id === 'plugins' ) {
// handlers and logic are added via jQuery in the frontend.
?>
<div id="leadin-feedback-container" style="display: none;">
<div class="leadin-feedback-header">
<h2><?php echo esc_html( __( "We're sorry to see you go", 'leadin' ) ); ?></h2>
<div class="leadin-modal-close">
<svg class="leadin-close-svg" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
<path class="leadin-close-path" d="M14.5,1.5l-13,13m0-13,13,13" transform="translate(-1 -1)"></path>
</svg>
</div>
</div>
<div class="leadin-feedback-body">
<div>
<strong>
<?php echo esc_html( __( "If you have a moment, please let us know why you're deactivating the plugin", 'leadin' ) ); ?>
</strong>
</div>
<form id='leadin-deactivate-form' class="leadin-deactivate-form">
<?php
$radio_buttons = array(
"I can't sign up or log in",
'The plugin is impacting website performance',
"The plugin isn't working",
"The plugin isn't useful",
'Temporarily disabling or troubleshooting',
'Other',
);
$radio_button_translations = array(
__( "I can't sign up or log in", 'leadin' ),
__( 'The plugin is impacting website performance', 'leadin' ),
__( "The plugin isn't working", 'leadin' ),
__( "The plugin isn't useful", 'leadin' ),
__( 'Temporarily disabling or troubleshooting', 'leadin' ),
__( 'Other', 'leadin' ),
);
$buttons_count = count( $radio_buttons );
for ( $i = 0; $i < $buttons_count; $i++ ) {
?>
<div class="leadin-radio-input-container">
<input
type="radio"
id="leadinFeedback<?php echo esc_attr( $i ); ?>"
name="feedback"
value="<?php echo esc_attr( $radio_buttons[ $i ] ); ?>"
class="leadin-feedback-radio"
required
>
<label for="leadinFeedback<?php echo esc_attr( $i ); ?>">
<?php echo esc_html( $radio_button_translations[ $i ] ); ?>
</label>
</div>
<?php
}
?>
<textarea name="details" class="leadin-feedback-text-area leadin-feedback-text-control" placeholder="<?php echo esc_html( __( 'Feedback', 'leadin' ) ); ?>"></textarea>
<input type="hidden" name="portal_id" value="<?php echo esc_html( Portal_Options::get_portal_id() ); ?>">
<div class="leadin-button-container">
<button type="submit" id="leadin-feedback-submit" class="leadin-button leadin-primary-button leadin-loader-button">
<div class="leadin-loader-button-content">
<?php echo esc_html( __( 'Submit & deactivate', 'leadin' ) ); ?>
</div>
<div class="leadin-loader"></div>
</button>
<button type="button" id="leadin-feedback-skip" class="leadin-button leadin-secondary-button">
<?php echo esc_html( __( 'Skip & deactivate', 'leadin' ) ); ?>
</button>
</div>
</form>
</div>
</div>
<?php
}
}
}

View File

@@ -1,53 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\AssetsManager;
use Leadin\utils\Versions;
/**
* Contains all the methods used to initialize Gutenberg blocks.
*/
class Gutenberg {
/**
* Class constructor, register Gutenberg blocks.
*/
public function __construct() {
if ( ! function_exists( 'register_block_type' ) ) {
// Gutenberg is not active.
return;
}
add_action( 'init', array( $this, 'register_gutenberg_block' ) );
add_filter( 'block_categories_all', array( $this, 'add_hubspot_category' ) );
}
/**
* Add HubSpot category to Gutenberg blocks.
*
* @param Array $categories Array of block categories.
*/
public function add_hubspot_category( $categories ) {
return array_merge(
$categories,
array(
array(
'slug' => 'leadin-blocks',
'title' => __( 'HubSpot', 'leadin' ),
),
)
);
}
/**
* Register HubSpot Form Gutenberg block.
*/
public function register_gutenberg_block() {
AssetsManager::localize_gutenberg();
register_block_type(
'leadin/hubspot-blocks',
array(
'editor_script' => AssetsManager::GUTENBERG,
)
);
}
}

View File

@@ -1,46 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\data\Filters;
const IR_CLICK_ID = 'irclickid';
const MPID = 'mpid';
/**
* Class containing the logic to get Impact affiliate information when necessary
*/
class Impact {
/**
* Apply leadin_impact_code filter.
*/
public static function get_affiliate_link() {
return Filters::apply_impact_code_filters();
}
/**
* Get impact properties from query parameters.
*/
public static function get_params() {
$params = array();
// phpcs:disable WordPress.Security.NonceVerification.Recommended
if ( isset( $_GET['leadin_irclickid'] ) ) {
$params[ IR_CLICK_ID ] = sanitize_text_field( \wp_unslash( $_GET['leadin_irclickid'] ) );
}
if ( isset( $_GET['leadin_mpid'] ) ) {
$params[ MPID ] = sanitize_text_field( \wp_unslash( $_GET['leadin_mpid'] ) );
}
// phpcs:enable
return $params;
}
/**
* Return true if the function `get_params` returns both irclickid and mpid.
*/
public static function has_params() {
return 2 === \count( self::get_params() );
}
}

View File

@@ -1,286 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\AssetsManager;
use Leadin\data\User;
use Leadin\admin\Connection;
use Leadin\data\User_Metadata;
use Leadin\admin\MenuConstants;
use Leadin\admin\Gutenberg;
use Leadin\admin\NoticeManager;
use Leadin\admin\PluginActionsManager;
use Leadin\admin\DeactivationForm;
use Leadin\admin\Links;
use Leadin\admin\ContentEmbedInstaller;
use Leadin\auth\OAuth;
use Leadin\admin\utils\Background;
use Leadin\utils\QueryParameters;
use Leadin\utils\Versions;
use Leadin\includes\utils as utils;
use Leadin\data\Portal_Options;
use Leadin\data\Filters;
/**
* Class responsible for initializing the admin side of the plugin.
*/
class LeadinAdmin {
const REDIRECT_TRANSIENT = 'leadin_redirect_after_activation';
/**
* Class constructor, adds all the hooks and instantiate the APIs.
*/
public function __construct() {
add_action( 'plugins_loaded', array( $this, 'load_languages' ), 14 );
add_action( 'admin_init', array( $this, 'redirect_after_activation' ) );
add_action( 'admin_init', array( $this, 'store_activation_time' ) );
add_action( 'admin_init', array( $this, 'authorize' ) );
add_action( 'admin_init', array( $this, 'check_review_requested' ) );
add_action( 'admin_menu', array( $this, 'build_menu' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
register_activation_hook( LEADIN_BASE_PATH, array( $this, 'do_activate_action' ) );
/**
* The following hooks are public APIs.
*/
add_action( 'leadin_redirect', array( $this, 'set_redirect_transient' ) );
add_action( 'leadin_activate', array( $this, 'do_redirect_action' ), 100 );
new PluginActionsManager();
new DeactivationForm();
new NoticeManager();
new Gutenberg();
new ContentEmbedInstaller();
add_action( 'elementor/documents/register_controls', array( $this, 'register_document_controls' ) );
}
/**
* Register additional document controls.
*
* @param \Elementor\Core\DocumentTypes\PageBase $document The PageBase document instance.
*/
public function register_document_controls( $document ) {
if ( ! $document instanceof \Elementor\Core\DocumentTypes\PageBase || ! $document::get_property( 'has_elements' ) ) {
return;
}
$document->start_controls_section(
'hubspot',
array(
'label' => esc_html__( 'Hubspot', 'leadin' ),
'tab' => \Elementor\Controls_Manager::TAB_SETTINGS,
)
);
$document->add_control(
'content_type',
array(
'label' => esc_html__( 'Select the content type HubSpot Analytics uses to track this page', 'leadin' ),
'label_block' => true,
'type' => \Elementor\Controls_Manager::SELECT,
'options' => array(
'' => esc_html__( 'Detect Automatically', 'leadin' ),
'blog-post' => esc_html__( 'Blog Post', 'leadin' ),
'knowledge-article' => esc_html__( 'Knowledge Article', 'leadin' ),
'landing-page' => esc_html__( 'Landing Page', 'leadin' ),
'listing-page' => esc_html__( 'Listing Page', 'leadin' ),
'standard-page' => esc_html__( 'Standard Page', 'leadin' ),
),
'default' => '',
)
);
$document->end_controls_section();
}
/**
* Load the .mo language files.
*/
public function load_languages() {
load_plugin_textdomain( 'leadin', false, '/leadin/languages' );
}
/**
* Handler called on plugin activation.
*/
public function do_activate_action() {
\do_action( 'leadin_activate' );
}
/**
* Handler for the leadin_activate action.
*/
public function do_redirect_action() {
\do_action( 'leadin_redirect' );
}
/**
* Set transient after activating the plugin.
*/
public function set_redirect_transient() {
set_transient( self::REDIRECT_TRANSIENT, true, 60 );
}
/**
* Redirect to the dashboard after activation.
*/
public function redirect_after_activation() {
if ( get_transient( self::REDIRECT_TRANSIENT ) ) {
delete_transient( self::REDIRECT_TRANSIENT );
wp_safe_redirect( admin_url( 'admin.php?page=leadin' ) );
exit;
}
}
/**
* Connect/disconnect the plugin
*/
public function authorize() {
if ( User::is_admin() ) {
if ( Connection::is_connection_requested() ) {
$redirect_params = array();
Connection::oauth_connect();
$redirect_params['leadin_just_connected'] = 1;
if ( Connection::is_new_portal() ) {
$redirect_params['is_new_portal'] = 1;
}
Routing::redirect( MenuConstants::USER_GUIDE, $redirect_params );
} elseif ( Connection::is_disconnection_requested() ) {
Connection::disconnect();
Routing::redirect( MenuConstants::ROOT );
}
}
}
/**
* Check if query parameter for review is present on the request
* then add user metadata to persist review time
* Redirects if value is equal to true
*/
public function check_review_requested() {
if ( Connection::is_connected() && Routing::has_review_request() ) {
User_Metadata::set_skip_review( time() );
if ( Routing::is_review_request() ) {
header( 'Location: https://survey.hsforms.com/1ILAEu_k_Ttiy344dpHM--w1h' );
exit();
}
}
}
/**
* Store activation time in a WP option.
*/
public function store_activation_time() {
if ( empty( Portal_Options::get_activation_time() ) ) {
Portal_Options::set_activation_time();
}
}
/**
* Adds scripts for the admin section.
*/
public function enqueue_scripts() {
AssetsManager::register_assets();
AssetsManager::enqueue_admin_assets();
if ( get_current_screen()->id === 'plugins' ) {
AssetsManager::enqueue_feedback_assets();
}
}
/**
* Adds Leadin menu to admin sidebar
*/
public function build_menu() {
if ( Connection::is_connected() ) {
add_menu_page( __( 'HubSpot', 'leadin' ), __( 'HubSpot', 'leadin' ), Filters::apply_view_plugin_menu_capability_filters(), MenuConstants::ROOT, array( $this, 'build_integrated_app' ), 'dashicons-sprocket', '25.100713' );
add_submenu_page( MenuConstants::ROOT, __( 'User Guide', 'leadin' ), __( 'User Guide', 'leadin' ), Filters::apply_view_plugin_menu_capability_filters(), MenuConstants::USER_GUIDE, array( $this, 'build_integrated_app' ) );
add_submenu_page( MenuConstants::ROOT, __( 'Forms', 'leadin' ), __( 'Forms', 'leadin' ), Filters::apply_view_plugin_menu_capability_filters(), MenuConstants::FORMS, array( $this, 'build_integrated_app' ) );
add_submenu_page( MenuConstants::ROOT, __( 'Live Chat', 'leadin' ), __( 'Live Chat', 'leadin' ), Filters::apply_view_plugin_menu_capability_filters(), MenuConstants::CHATFLOWS, array( $this, 'build_integrated_app' ) );
add_submenu_page( MenuConstants::ROOT, __( 'Contacts', 'leadin' ), self::make_external_link( Links::get_iframe_src( MenuConstants::CONTACTS ), __( 'Contacts', 'leadin' ), 'leadin_contacts_link' ), Filters::apply_view_plugin_menu_capability_filters(), MenuConstants::CONTACTS, array( $this, 'build_app' ) );
add_submenu_page( MenuConstants::ROOT, __( 'Email', 'leadin' ), self::make_external_link( Links::get_iframe_src( MenuConstants::EMAIL ), __( 'Email', 'leadin' ), 'leadin_email_link' ), Filters::apply_view_plugin_menu_capability_filters(), MenuConstants::EMAIL, array( $this, 'build_app' ) );
add_submenu_page( MenuConstants::ROOT, __( 'Lists', 'leadin' ), self::make_external_link( Links::get_iframe_src( MenuConstants::LISTS ), __( 'Lists', 'leadin' ), 'leadin_lists_link' ), Filters::apply_view_plugin_menu_capability_filters(), MenuConstants::LISTS, array( $this, 'build_app' ) );
add_submenu_page( MenuConstants::ROOT, __( 'Reporting', 'leadin' ), self::make_external_link( Links::get_iframe_src( MenuConstants::REPORTING ), __( 'Reporting', 'leadin' ), 'leadin_reporting_link' ), Filters::apply_view_plugin_menu_capability_filters(), MenuConstants::REPORTING, array( $this, 'build_app' ) );
add_submenu_page( MenuConstants::ROOT, __( 'Settings', 'leadin' ), __( 'Settings', 'leadin' ), Filters::apply_view_plugin_menu_capability_filters(), MenuConstants::SETTINGS, array( $this, 'build_integrated_app' ) );
add_submenu_page( MenuConstants::ROOT, __( 'Upgrade', 'leadin' ), self::make_external_link( Links::get_iframe_src( MenuConstants::PRICING ), __( 'Upgrade', 'leadin' ), 'leadin_pricing_link' ), Filters::apply_view_plugin_menu_capability_filters(), MenuConstants::PRICING, array( $this, 'build_app' ) );
remove_submenu_page( MenuConstants::ROOT, MenuConstants::ROOT );
} else {
$notification_icon = ' <span class="update-plugins count-1"><span class="plugin-count">!</span></span>';
add_menu_page( __( 'HubSpot', 'leadin' ), __( 'HubSpot', 'leadin' ) . $notification_icon, Filters::apply_connect_plugin_capability_filters(), MenuConstants::ROOT, array( $this, 'build_integrated_app' ), 'dashicons-sprocket', '25.100713' );
}
}
/**
* Wraps external link.
*
* @param String $href link destination.
* @param String $content link content.
* @param String $class class for ATs.
*/
public function make_external_link( $href, $content, $class ) {
return "<a href=\"$href\" class=\"external_link $class\" target=\"_blank\" onclick=\"blur()\">$content</a>";
}
/**
* Renders the leadin admin page.
*/
public function build_app() {
AssetsManager::enqueue_bridge_assets();
self::render_app();
}
/**
* Renders the integrated forms app.
*/
public function build_integrated_app() {
AssetsManager::enqueue_integrated_app_assets();
self::render_app();
}
/**
* Render app container
*/
public function render_app() {
$error_message = '';
if ( Versions::is_php_version_not_supported() ) {
$error_message = sprintf(
__( 'HubSpot All-In-One Marketing %1$s requires PHP %2$s or higher Please upgrade WordPress first', 'leadin' ),
LEADIN_PLUGIN_VERSION,
LEADIN_REQUIRED_PHP_VERSION
);
} elseif ( Versions::is_wp_version_not_supported() ) {
$error_message = sprintf(
__( 'HubSpot All-In-One Marketing %1$s requires PHP %2$s or higher Please upgrade WordPress first', 'leadin' ),
LEADIN_PLUGIN_VERSION,
LEADIN_REQUIRED_WP_VERSION
);
}
if ( $error_message ) {
?>
<div class='notice notice-warning'>
<p>
<?php echo esc_html( $error_message ); ?>
</p>
</div>
<?php
} else {
?>
<div id="leadin-iframe-fallback-container"></div>
<div id="leadin-iframe-container"></div>
<?php
}
}
}

View File

@@ -1,192 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\data\Filters;
use Leadin\data\Portal_Options;
use Leadin\admin\MenuConstants;
use Leadin\admin\utils\Background;
use Leadin\data\User;
use Leadin\utils\QueryParameters;
use Leadin\utils\Versions;
use Leadin\auth\OAuth;
use Leadin\admin\Connection;
use Leadin\admin\Impact;
use Leadin\admin\AdminConstants;
use Leadin\includes\utils as utils;
use Leadin\auth\OAuthCrypto;
/**
* Class containing all the functions to generate links to HubSpot.
*/
class Links {
/**
* Deprecated for OAuth2 routes
*
* Get a map of <admin_page, url>
* Where
* - admin_page is a string
* - url is either a string or another map <route, string_url>, both strings
*/
public static function get_routes_mapping() {
$portal_id = Portal_Options::get_portal_id();
$reporting_page = "/reports-dashboard/$portal_id";
$user_guide = "/wordpress-plugin-ui/$portal_id/onboarding/start";
return array(
MenuConstants::ROOT => $user_guide,
MenuConstants::USER_GUIDE => $user_guide,
MenuConstants::REPORTING => $reporting_page,
MenuConstants::CONTACTS => "/contacts/$portal_id",
MenuConstants::LISTS => array(
'' => "/contacts/$portal_id/objectLists/all",
'default' => "/contacts/$portal_id/objectLists",
'lists' => "/contacts/$portal_id/lists",
),
MenuConstants::EMAIL => array(
'' => "/email/$portal_id",
'cms' => "/content/$portal_id/create/email",
),
MenuConstants::SETTINGS => array(
'' => "/wordpress-plugin-ui/$portal_id/settings",
'forms' => "/settings/$portal_id/marketing/form",
),
MenuConstants::PRICING => "/pricing/$portal_id/marketing",
);
}
/**
* Get page name from the current page id.
* E.g. "hubspot_page_leadin_forms" => "forms"
*/
private static function get_page_id() {
$screen_id = get_current_screen()->id;
return preg_replace( '/^(hubspot_page_|toplevel_page_)/', '', $screen_id );
}
/**
* Get the parsed `leadin_route` from the query string.
*/
private static function get_iframe_route() {
$iframe_route = QueryParameters::get_param_array( 'leadin_route', 'hubspot-route' );
return is_array( $iframe_route ) ? $iframe_route : array();
}
/**
* Get the parsed `leadin_search` from the query string.
*/
private static function get_iframe_search_string() {
return QueryParameters::get_param( 'leadin_search', 'hubspot-route' );
}
/**
* Return query string from object
*
* @param array $arr query parameters to stringify.
*/
private static function http_build_query( $arr ) {
if ( ! is_array( $arr ) ) {
return '';
}
return http_build_query( $arr, '', ini_get( 'arg_separator.output' ), PHP_QUERY_RFC3986 );
}
/**
* Validate static version.
*
* @param String $version version of the static bundle.
*/
private static function is_static_version_valid( $version ) {
preg_match( '/static-\d+\.\d+/', $version, $match );
return ! empty( $match );
}
/**
* Return a string query parameters to add to the iframe src.
*/
public static function get_query_params() {
$config_array = AdminConstants::get_hubspot_query_params_array();
\array_merge( $config_array, Impact::get_params() );
return self::http_build_query( $config_array );
}
/**
* This function computes the right iframe src based on query params and current page.
*
* The `page` query param is used as a key to get the url from the get_routes_mapping
* This query param will get ignored if $page_id function param is present
* The `leadin_route[]` query params are added to the url
*
* e.g.:
* ?page=leadin_forms&leadin_route[]=foo&leadin_route[]=bar will redirect to /forms/$portal_id/foo/bar
*
* If the value of get_routes_mapping is an array, the first value of `leadin_route` will be used as key.
* If the key isn't found, it will fall back to ''
*
* e.g.:
* ?page=leadin_settings&leadin=route[]=forms&leadin_route[]=bar will redirect to /settings/$portal_id/forms/bar
* ?page=leadin_settings&leadin=route[]=foo&leadin_route[]=bar will redirect to /wordpress_plugin_ui/$portal_id/settings/foo/bar
*
* @param String $page_id is used as a key to get the url from the get_routes_mapping by overriding the query param.
*
* Returns the right iframe src.
*/
public static function get_iframe_src( $page_id = '' ) {
$leadin_onboarding = 'leadin_onboarding';
$leadin_new_portal = 'leadin_new_portal';
$browser_search_string = '';
if ( get_transient( $leadin_onboarding ) ) {
delete_transient( $leadin_onboarding );
$browser_search_string = '&justConnected=true';
if ( get_transient( $leadin_new_portal ) ) {
delete_transient( $leadin_new_portal );
$browser_search_string = $browser_search_string . '&isNewPortal=true';
}
}
$sub_routes_array = self::get_iframe_route();
$inframe_search_string = self::get_iframe_search_string();
$browser_search_string = $browser_search_string . $inframe_search_string;
if ( empty( Portal_Options::get_portal_id() ) ) {
$wp_user = wp_get_current_user();
$wp_user_id = $wp_user->ID;
set_transient( $leadin_onboarding, 'true' );
} else {
if ( '' === $page_id ) {
$page_id = self::get_page_id();
}
$routes = self::get_routes_mapping();
$is_external = MenuConstants::PRICING === $page_id || MenuConstants::REPORTING === $page_id || MenuConstants::LISTS === $page_id || MenuConstants::CONTACTS === $page_id || MenuConstants::EMAIL === $page_id;
if ( empty( $route ) && isset( $routes[ $page_id ] ) ) {
$route = $routes[ $page_id ];
if ( \is_array( $route ) && isset( $sub_routes_array[0] ) ) {
$first_sub_route = $sub_routes_array[0];
if ( isset( $route[ $first_sub_route ] ) ) {
$route = $route[ $first_sub_route ];
array_shift( $sub_routes_array );
}
}
if ( \is_array( $route ) ) {
$route = $route[''];
}
}
}
$sub_routes = join( '/', $sub_routes_array );
$sub_routes = empty( $sub_routes ) ? $sub_routes : "/$sub_routes";
// Query string separator "?" may have been added to the URL already.
$add_separator = strpos( $sub_routes, '?' ) ? '&' : '?';
$additional_query_params = Filters::apply_query_params_filters();
return Filters::apply_base_url_filters() . "$route$sub_routes" . $add_separator . self::get_query_params() . $browser_search_string . $additional_query_params;
}
}

View File

@@ -1,19 +0,0 @@
<?php
namespace Leadin\admin;
/**
* Static class containing the id of each menu item.
*/
class MenuConstants {
const ROOT = 'leadin';
const USER_GUIDE = 'leadin_user_guide';
const REPORTING = 'leadin_reporting';
const EMAIL = 'leadin_email';
const FORMS = 'leadin_forms';
const CONTACTS = 'leadin_contacts';
const LISTS = 'leadin_lists';
const SETTINGS = 'leadin_settings';
const PRICING = 'leadin_pricing';
const CHATFLOWS = 'leadin_chatflows';
}

View File

@@ -1,78 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\data\User;
use Leadin\admin\Connection;
use Leadin\data\User_Metadata;
use Leadin\admin\AdminConstants;
use Leadin\admin\ReviewBanner;
/**
* Class responsible for rendering the admin notices.
*/
class NoticeManager {
/**
* Class constructor, adds the necessary hooks.
*/
public function __construct() {
add_action( 'admin_notices', array( $this, 'leadin_action_required_notice' ) );
}
/**
* Render the disconnected banner.
*/
private function leadin_render_disconnected_banner() {
?>
<div id="leadin-disconnected-banner" class="leadin-banner notice notice-warning is-dismissible">
<p>
<img src="<?php echo esc_attr( LEADIN_ASSETS_PATH . '/images/sprocket.svg' ); ?>" height="16" style="margin-bottom: -3px" />
&nbsp;
<?php
echo sprintf(
esc_html( __( 'The HubSpot plugin is not connected right now To use HubSpot tools on your WordPress site, %1$sconnect the plugin now%2$s', 'leadin' ) ),
'<a class="leadin-banner__link" href="admin.php?page=leadin&bannerClick=true">',
'</a>'
);
?>
</p>
</div>
<?php
}
/**
* Find what notice (if any) needs to be rendered
*/
public function leadin_action_required_notice() {
$current_screen = get_current_screen();
if ( User::is_admin() ) {
if ( self::should_show_disconnected_notice() ) {
$this->leadin_render_disconnected_banner();
} elseif ( self::should_show_review_notice() ) {
$review_banner = new ReviewBanner();
$review_banner->leadin_render_review_banner();
}
}
}
/**
* Find if disconnected notice should be shown
*/
public function should_show_disconnected_notice() {
$current_screen = get_current_screen();
return ! Connection::is_connected() && 'leadin' !== $current_screen->parent_base;
}
/**
* Find if review notice should be shown
*/
public function should_show_review_notice() {
$current_screen = get_current_screen();
$is_dashboard = 'index' === $current_screen->parent_base;
$is_not_skipped = empty( User_Metadata::get_skip_review() );
return $is_dashboard && Connection::is_connected() && $is_not_skipped;
}
}

View File

@@ -1,55 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\data\Filters;
use Leadin\admin\Links;
use Leadin\admin\Connection;
use Leadin\data\Portal_Options;
/**
* Class responsible for the custom functionalities inside the plugins.php page.
*/
class PluginActionsManager {
/**
* Class constructor, adds the necessary hooks.
*/
public function __construct() {
add_filter( 'plugin_action_links_leadin/leadin.php', array( $this, 'add_plugin_settings_link' ) );
add_filter( 'plugin_action_links_leadin/leadin.php', array( $this, 'leadin_plugin_advanced_features_link' ) );
}
/**
* Adds setting link for Leadin to plugins management page.
*
* @param array $links Return the links for the settings page.
* @return array
*/
public function add_plugin_settings_link( $links ) {
if ( Connection::is_connected() ) {
$page = 'leadin_settings';
} else {
$page = 'leadin';
}
$url = get_admin_url( get_current_blog_id(), "admin.php?page=$page" );
$settings_link = '<a href="' . $url . '">' . __( 'Settings', 'leadin' ) . '</a>';
array_unshift( $links, $settings_link );
return $links;
}
/**
* Adds upgrade link for Leadin to plugins management page
*
* @param array $links Return the links for the upgrade page.
* @return array
*/
public function leadin_plugin_advanced_features_link( $links ) {
if ( Connection::is_connected() ) {
$portal_id = Portal_Options::get_portal_id();
$url = Filters::apply_base_url_filters() . '/pricing/' . $portal_id . '/marketing?' . Links::get_query_params();
$advanced_features_link = '<a class="hubspot-menu-pricing" target="_blank" rel="noopener" href="' . esc_attr( $url ) . '">' . esc_html( __( 'Upgrade', 'leadin' ) ) . '</a>';
array_push( $links, $advanced_features_link );
}
return $links;
}
}

View File

@@ -1,89 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\data\User_Metadata;
use Leadin\admin\AdminConstants;
use Leadin\AssetsManager;
/**
* Class responsible for rendering the review banner
*/
class ReviewBanner {
/**
* Constructor enqueues scripts for tracking events and creates background leadin iframe
*/
public function __construct() {
AssetsManager::enqueue_review_banner_tracking_script();
}
/**
* Render the review banner.
*/
public function leadin_render_review_banner() {
$nonce = wp_create_nonce( 'leadin-review' );
$dismiss_notice_text = __( 'Dismiss this notice', 'leadin' );
$hello_text = sprintf(
__( 'Hey %1$s,', 'leadin' ),
User_Metadata::get_first_name() ? User_Metadata::get_first_name() : User_Metadata::get_nickname()
);
$notice_text = __( 'Have you got 2 minutes to complete %1$sthis survey%2$s about the HubSpot for WordPress plugin?', 'leadin' );
$feedback_text = __( 'We read every response Your feedback helps our team make the improvements that you need the most', 'leadin' );
$from_hubspot_text = __( 'HubSpot for WordPress Team', 'leadin' );
$thanks_message = __( 'Thanks,', 'leadin' );
?>
<div id="leadin-review-banner" class="leadin-banner leadin-review-banner leadin-review-banner--hide notice notice-warning">
<a href="?leadin_review=false&_wpnonce=<?php echo esc_html( $nonce ); ?>"
id="dismiss-review-banner-button">
<button class="leadin-review-banner__dismiss notice-dismiss">
<span class="screen-reader-text">
<?php echo esc_html( $dismiss_notice_text ); ?>
</span>
</button>
</a>
<div class="leadin-review-banner__content">
<p class="leadin-review-banner__text">
<?php echo esc_html( $hello_text ); ?>
</p>
<div class="leadin-review-banner__content-body">
<p class="leadin-review-banner__text">
<?php
echo sprintf(
esc_html( $notice_text ),
'<a class="leadin-banner__link" id="leave-review-button" target="_blank" href="?leadin_review=true&_wpnonce=' . esc_html( $nonce ) . '" aria-label="' . esc_html( __( 'Leave us a review | link opens in a new tab', 'leadin' ) ) . '" >',
'</a>'
);
?>
</p>
<p class="leadin-review-banner__text">
<?php echo esc_html( $feedback_text ); ?>
</p>
</div>
<div class="leadin-review-banner__content-body">
<p class="leadin-review-banner__text">
<?php echo esc_html( $thanks_message ); ?>
</p>
</div>
</div>
<div class="leadin-review-banner__author">
<img src="<?php echo esc_attr( LEADIN_ASSETS_PATH . '/images/hubspot-team-profile.png' ); ?>" height="48" />
<p class="leadin-review-banner__text">
Kelly
<br/>
<?php echo esc_html( $from_hubspot_text ); ?>
</p>
</div>
</div>
<?php
}
}

View File

@@ -1,78 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\data\Portal_Options;
use Leadin\data\User_Metadata;
use Leadin\admin\client\Contacts_Api_Client;
/**
* Class responsible for controlling if review banner should show.
*/
class ReviewController {
const CONTACTS_CREATED_SINCE_ACTIVATION = 5;
const REVIEW_BANNER_INTRO_PERIOD = 15;
const DAYS_SINCE_LAST_FETCH = 1;
/**
* Checks if user has enough contacts created since plugin activation.
*/
public static function has_contacts_created_since_activation() {
if ( self::has_min_contacts() ) {
return true;
} elseif ( ! self::should_fetch_contacts() ) {
return false;
}
try {
User_Metadata::set_review_banner_last_call( time() );
$client = new Contacts_Api_Client();
$contacts = $client->get_contacts_from_timestamp( Portal_Options::get_activation_time() );
$has_min_contacts = count( $contacts->results ) >= self::CONTACTS_CREATED_SINCE_ACTIVATION;
User_Metadata::set_has_min_contacts( $has_min_contacts );
return $has_min_contacts;
} catch ( \Exception $e ) {
return false;
}
}
/**
* Check to see if current time is after introductary period.
*/
public static function is_after_introductary_period() {
$activation_time = new \DateTime();
$activation_time->setTimestamp( Portal_Options::get_activation_time() );
$diff = $activation_time->diff( new \DateTime() );
return $diff->days >= self::REVIEW_BANNER_INTRO_PERIOD;
}
/**
* Check SKIP_REVIEW meta data for a user.
*/
public static function is_reviewed_or_skipped() {
return ! empty( User_Metadata::get_skip_review() );
}
/**
* Check if contacts have been fetched at the current day.
*/
public static function should_fetch_contacts() {
$last_call_ts = User_Metadata::get_review_banner_last_call();
if ( empty( $last_call_ts ) ) {
return true;
}
$last_call_date = new \DateTime();
$last_call_date->setTimestamp( $last_call_ts );
$diff = $last_call_date->diff( new \DateTime() );
return $diff->days >= self::DAYS_SINCE_LAST_FETCH;
}
/**
* Check if contacts minimun have already been fulfilled .
*/
public static function has_min_contacts() {
return User_Metadata::get_has_min_contacts();
}
}

View File

@@ -1,101 +0,0 @@
<?php
namespace Leadin\admin;
use Leadin\utils\QueryParameters;
/**
* Class for helping route around the plugin in OAuth mode.
*/
class Routing {
const EXPIRED = 'leadin_expired';
const JUST_CONNECTED = 'leadin_just_connected';
const IS_NEW_PORTAL = 'is_new_portal';
const REDIRECT_NONCE = 'leadin_redirect';
const REVIEW = 'leadin_review';
/**
* Redirect to the root of the leadin plugin with optional query parameters.
* Verified with a redirect nonce.
*
* @param string $page the WordPress page parameter to redirect to.
* @param array $extra_params Associative array of parameters to add to the redirected URL.
*/
public static function redirect( $page, $extra_params = array() ) {
$redirect_params = array_merge(
array( 'page' => $page ),
array( self::REDIRECT_NONCE => wp_create_nonce( self::REDIRECT_NONCE ) ),
$extra_params
);
$redirect_url = add_query_arg(
urlencode_deep( $redirect_params ),
admin_url( 'admin.php' )
);
nocache_headers();
wp_safe_redirect( $redirect_url );
exit;
}
/**
* Return a boolean if the plugin has just been connected.
* Signified by query parameter flag `leadin_just_connected`.
*
* @return bool True if the plugin has just connected.
*/
public static function has_just_connected_with_oauth() {
$just_connected_param = QueryParameters::get_param(
self::JUST_CONNECTED,
self::REDIRECT_NONCE,
self::REDIRECT_NONCE
);
return null !== $just_connected_param;
}
/**
* Return a boolean if the plugin is being used with a new portal.
* Signified by query parameter flag `is_new_portal`.
*
* @return bool True if the plugin has just connected using a new portal.
*/
public static function is_new_portal_with_oauth() {
$just_connected_param = QueryParameters::get_param(
self::IS_NEW_PORTAL,
self::REDIRECT_NONCE,
self::REDIRECT_NONCE
);
return null !== $just_connected_param;
}
/**
* Reads query param to see if request has review request query params
*
* @return bool True if the `leadin_review` query parameter is not empty
*/
public static function has_review_request() {
$is_review_request = QueryParameters::get_param(
self::REVIEW,
'leadin-review'
);
return ! empty( $is_review_request );
}
/**
* Reads query param to see if request has review request query params set to true
*
* @return bool True if the `leadin_review` query parameter is true
*/
public static function is_review_request() {
$is_review_request = QueryParameters::get_param(
self::REVIEW,
'leadin-review'
);
return 'true' === $is_review_request;
}
}

View File

@@ -1,40 +0,0 @@
<?php
namespace Leadin\admin\api;
use Leadin\api\Base_Api_Controller;
use Leadin\data\Portal_Options;
/**
* Hublet Api. Used to fetch portal's hublet and update in case of region migration
*/
class Hublet_Api_Controller extends Base_Api_Controller {
/**
* Class constructor, register route.
*/
public function __construct() {
self::register_leadin_admin_route(
'/hublet',
\WP_REST_Server::EDITABLE,
array( $this, 'update_hublet' )
);
}
/**
* Get's correct hublet and updates it in Options
*
* @param array $request Request body.
*/
public function update_hublet( $request ) {
$data = json_decode( $request->get_body(), true );
$hublet = $data['hublet'];
if ( ! $hublet ) {
return new \WP_REST_Response( 'Hublet is required', 400 );
}
Portal_Options::set_hublet( $hublet );
return new \WP_REST_Response( $hublet, 200 );
}
}

View File

@@ -1,50 +0,0 @@
<?php
namespace Leadin\admin\api;
use Leadin\api\Base_Api_Controller;
use Leadin\data\Portal_Options;
/**
* Disable Internal Tracking Api. Used to exclude internal users to appear in HS analytics
*/
class Internal_Tracking_Api_Controller extends Base_Api_Controller {
/**
* Class constructor, register route.
*/
public function __construct() {
self::register_leadin_admin_route(
'/internal-tracking',
\WP_REST_Server::READABLE,
array( $this, 'get_internal_tracking_option' )
);
self::register_leadin_admin_route(
'/internal-tracking',
\WP_REST_Server::EDITABLE,
array( $this, 'set_internal_tracking_option' )
);
}
/**
* Get the disable internal tracking option.
*
* @return bool Internal tracking option value.
*/
public function get_internal_tracking_option() {
return new \WP_REST_Response( Portal_Options::get_disable_internal_tracking(), 200 );
}
/**
* Set the disable internal tracking option.
*
* @param array $request Request body.
*
* @return string OK response message.
*/
public function set_internal_tracking_option( $request ) {
Portal_Options::set_disable_internal_tracking( json_decode( $request->get_body(), true ) );
return new \WP_REST_Response( 'OK', 200 );
}
}

View File

@@ -1,53 +0,0 @@
<?php
namespace Leadin\admin\api;
use Leadin\api\Base_Api_Controller;
use Leadin\admin\Connection;
use Leadin\data\Portal_Options;
/**
* Portal Api, used to clean portal id and domain from the WordPress options.
*/
class Portal_Api_Controller extends Base_Api_Controller {
/**
* Class constructor, register route.
*/
public function __construct() {
self::register_leadin_admin_route(
'/business-unit',
\WP_REST_Server::READABLE,
array( $this, 'get_business_unit_option' )
);
self::register_leadin_admin_route(
'/business-unit',
\WP_REST_Server::EDITABLE,
array( $this, 'set_business_unit_option' )
);
}
/**
* Get business unit id option.
*
* @return string Business Unit Id
*/
public function get_business_unit_option() {
return new \WP_REST_Response( Portal_Options::get_business_unit_id(), 200 );
}
/**
* Set business unit id option.
*
* @param number $request Request body.
*
* @return string OK response message.
*/
public function set_business_unit_option( $request ) {
$data = json_decode( $request->get_body(), true );
$business_unit_id = $data['businessUnitId'];
Portal_Options::set_business_unit_id( $business_unit_id );
return new \WP_REST_Response( 'OK', 200 );
}
}

View File

@@ -1,54 +0,0 @@
<?php
namespace Leadin\admin\api;
use Leadin\api\Base_Api_Controller;
use Leadin\data\User_Metadata;
/**
* User meta review Api, used to set the user metadata.
*/
class User_Meta_Api_Controller extends Base_Api_Controller {
/**
* Class constructor, register route.
*/
public function __construct() {
self::register_leadin_route(
'/skip-review',
\WP_REST_Server::CREATABLE,
array( $this, 'skip_review' )
);
self::register_leadin_route(
'/track-consent',
\WP_REST_Server::CREATABLE,
array( $this, 'track_consent' )
);
}
/**
* Skip Review. Sets SKIP_REVIEW meta data for a user with current datetime.
*/
public function skip_review() {
User_Metadata::set_skip_review( time() );
return new \WP_REST_Response( 'OK', 200 );
}
/**
* Used to set user consent on HubSpot anonymous tracking.
*
* @param array $request Request body.
*/
public function track_consent( $request ) {
$data = json_decode( $request->get_body(), true );
if ( array_key_exists( 'canTrack', $data ) ) {
$consent = $data['canTrack'];
User_Metadata::set_track_consent( $consent ? 'true' : 'false' );
}
return new \WP_REST_Response(
json_encode( User_Metadata::get_track_consent(), true ),
200
);
}
}

View File

@@ -1,129 +0,0 @@
<?php
namespace Leadin\admin\widgets;
use Leadin\data\Filters;
use Elementor\Plugin;
use Elementor\Widget_Base;
/**
* ElementorForm Widget
*/
class ElementorForm extends Widget_Base {
/**
* Widget internal name.
*/
public function get_name() {
return 'hubspot-form';
}
/**
* Widget title.
*/
public function get_title() {
return esc_html( 'HubSpot Form' );
}
/**
* Widget display icon.
*/
public function get_icon() {
return 'eicon-form-horizontal';
}
/**
* Widget help url.
*/
public function get_custom_help_url() {
return 'https://wordpress.org/support/plugin/leadin/';
}
/**
* Widget category.
*/
public function get_categories() {
return array( 'general', 'hubspot' );
}
/**
* Widget keywords.
*/
public function get_keywords() {
return array( 'hubspot', 'form', 'leadin' );
}
/**
* Widget style.
*/
public function get_style_depends() {
wp_register_style( 'leadin-elementor', LEADIN_JS_BASE_PATH . '/elementor.css', array(), LEADIN_PLUGIN_VERSION );
wp_register_style( 'leadin-css', LEADIN_ASSETS_PATH . '/style/leadin.css', array(), LEADIN_PLUGIN_VERSION );
return array( 'leadin-elementor', 'leadin-css' );
}
/**
* Widget script.
*/
public function get_script_depends() {
wp_register_script(
'leadin-forms-v2',
Filters::apply_forms_script_url_filters(),
array(),
LEADIN_PLUGIN_VERSION,
true
);
return array( 'leadin-forms-v2' );
}
/**
* Widget controls.
*/
protected function register_controls() {
$this->start_controls_section(
'content_section',
array(
'label' => esc_html( __( 'Form', 'leadin' ) ),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
)
);
$this->add_control(
'content',
array(
'type' => 'leadinformselect',
)
);
$this->end_controls_section();
}
/**
* Render the widget
*/
protected function render() {
$settings = $this->get_settings_for_display();
$content = $settings['content'];
if ( Plugin::$instance->editor->is_edit_mode() ) {
?>
<div class="hubspot-form-edit-mode" data-attributes="<?php echo esc_attr( json_encode( $content ) ); ?>">
&nbsp;
</div>
<?php
if ( empty( $content ) ) {
?>
<div class="hubspot-widget-empty">
</div>
<?php
}
}
if ( ! empty( $content ) ) {
$portal_id = $content['portalId'];
$form_id = $content['formId'];
echo do_shortcode( '[hubspot portal="' . $portal_id . '" id="' . $form_id . '" type="form"]' );
}
}
}

View File

@@ -1,47 +0,0 @@
<?php
namespace Leadin\admin\widgets;
use Leadin\AssetsManager;
/**
* Class for Elementor form selector control
*/
class ElementorFormSelect extends \Elementor\Base_Data_Control {
/**
* Returns control internal name
*/
public function get_type() {
return 'leadinformselect';
}
/**
* Load assets needed for control
*/
public function enqueue() {
AssetsManager::enqueue_elementor_script();
}
/**
* Default settings for control
*/
protected function get_default_settings() {
return array(
'label_block' => true,
'rows' => 3,
'hsptform_options' => array(),
);
}
/**
* Render Function
*/
public function content_template() {
$control_uid = $this->get_control_uid();
?>
<div class="elementor-hbspt-form-selector" data-id="<?php echo esc_html( $control_uid ); ?>"></div>
<?php
}
}

View File

@@ -1,127 +0,0 @@
<?php
namespace Leadin\admin\widgets;
use Elementor\Plugin;
use Elementor\Widget_Base;
/**
* ElementorMeeting Widget
*/
class ElementorMeeting extends Widget_Base {
/**
* Widget internal name.
*/
public function get_name() {
return 'hubspot-meeting';
}
/**
* Widget title.
*/
public function get_title() {
return esc_html( 'HubSpot Meeting' );
}
/**
* Widget display icon.
*/
public function get_icon() {
return 'eicon-calendar';
}
/**
* Widget help url.
*/
public function get_custom_help_url() {
return 'https://wordpress.org/support/plugin/leadin/';
}
/**
* Widget category.
*/
public function get_categories() {
return array( 'general', 'hubspot' );
}
/**
* Widget keywords.
*/
public function get_keywords() {
return array( 'hubspot', 'meeting', 'leadin' );
}
/**
* Widget style.
*/
public function get_style_depends() {
wp_register_style( 'leadin-elementor', LEADIN_JS_BASE_PATH . '/elementor.css', array(), LEADIN_PLUGIN_VERSION );
wp_register_style( 'leadin-css', LEADIN_ASSETS_PATH . '/style/leadin.css', array(), LEADIN_PLUGIN_VERSION );
return array( 'leadin-elementor', 'leadin-css' );
}
/**
* Widget script.
*/
public function get_script_depends() {
wp_register_script(
'leadin-meeting',
'https://static.hsappstatic.net/MeetingsEmbed/ex/MeetingsEmbedCode.js',
array(),
LEADIN_PLUGIN_VERSION,
true
);
return array( 'leadin-meeting' );
}
/**
* Widget controls.
*/
protected function register_controls() {
$this->start_controls_section(
'content_section',
array(
'label' => esc_html( __( 'Meetings Scheduler', 'leadin' ) ),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
)
);
$this->add_control(
'content',
array(
'type' => 'leadinmeetingselect',
)
);
$this->end_controls_section();
}
/**
* Render the widget
*/
protected function render() {
$settings = $this->get_settings_for_display();
$content = $settings['content'];
if ( Plugin::$instance->editor->is_edit_mode() ) {
?>
<div class="hubspot-meeting-edit-mode" data-attributes=<?php echo json_encode( $content ); ?>>
&nbsp;
</div>
<?php
if ( empty( $content ) ) {
?>
<div class="hubspot-widget-empty">
</div>
<?php
}
}
if ( ! empty( $content ) ) {
$url = $content['url'];
echo do_shortcode( '[hubspot url="' . $url . '" type="meeting"]' );
}
}
}

View File

@@ -1,47 +0,0 @@
<?php
namespace Leadin\admin\widgets;
use Leadin\AssetsManager;
/**
* Class for Elementor form selector control
*/
class ElementorMeetingSelect extends \Elementor\Base_Data_Control {
/**
* Returns control internal name
*/
public function get_type() {
return 'leadinmeetingselect';
}
/**
* Load assets needed for control
*/
public function enqueue() {
AssetsManager::enqueue_elementor_script();
}
/**
* Default settings for control
*/
protected function get_default_settings() {
return array(
'label_block' => true,
'rows' => 3,
'hsptmeeting_options' => array(),
);
}
/**
* Render Function
*/
public function content_template() {
$control_uid = $this->get_control_uid();
?>
<div class="elementor-hbspt-meeting-selector" data-id="<?php echo esc_html( $control_uid ); ?>"></div>
<?php
}
}