1407 lines
43 KiB
PHP
1407 lines
43 KiB
PHP
<?php
|
|
/**
|
|
* Installation related functions and actions.
|
|
*
|
|
* @package Pinterest_For_Woocommerce
|
|
* @version 1.0.0
|
|
*/
|
|
|
|
use Automattic\WooCommerce\Grow\Tools\CompatChecker\v0_0_1\Checker;
|
|
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
|
|
use Automattic\WooCommerce\Admin\Notes\NotesUnavailableException;
|
|
use Automattic\WooCommerce\Pinterest;
|
|
use Automattic\WooCommerce\Pinterest\AdCredits;
|
|
use Automattic\WooCommerce\Pinterest\AdCreditsCoupons;
|
|
use Automattic\WooCommerce\Pinterest\AdsCreditCurrency;
|
|
use Automattic\WooCommerce\Pinterest\Admin\Tasks\Onboarding;
|
|
use Automattic\WooCommerce\Pinterest\API\UserInteraction;
|
|
use Automattic\WooCommerce\Pinterest\Billing;
|
|
use Automattic\WooCommerce\Pinterest\FeedRegistration;
|
|
use Automattic\WooCommerce\Pinterest\Heartbeat;
|
|
use Automattic\WooCommerce\Pinterest\Logger;
|
|
use Automattic\WooCommerce\Pinterest\Notes\MarketingNotifications;
|
|
use Automattic\WooCommerce\Pinterest\Notes\TokenExchangeFailure;
|
|
use Automattic\WooCommerce\Pinterest\Notes\TokenInvalidFailure;
|
|
use Automattic\WooCommerce\Pinterest\PinterestApiException;
|
|
use Automattic\WooCommerce\Pinterest\ProductFeedStatus;
|
|
use Automattic\WooCommerce\Pinterest\Tracking;
|
|
use Automattic\WooCommerce\Pinterest\Tracking\Conversions;
|
|
use Automattic\WooCommerce\Pinterest\Tracking\Data\User;
|
|
use Automattic\WooCommerce\Pinterest\Tracking\Tag;
|
|
use Automattic\WooCommerce\Pinterest\Utilities\Tracks;
|
|
|
|
if ( ! class_exists( 'Pinterest_For_Woocommerce' ) ) :
|
|
|
|
/**
|
|
* Base Plugin class holding generic functionality
|
|
*/
|
|
final class Pinterest_For_Woocommerce {
|
|
|
|
use Tracks;
|
|
|
|
/**
|
|
* Tos IDs and URLs per country.
|
|
*/
|
|
const TOS_PER_COUNTRY = array(
|
|
'US' => array(
|
|
'tos_id' => 8,
|
|
'terms_url' => 'https://business.pinterest.com/en/pinterest-advertising-services-agreement',
|
|
),
|
|
'CA' => array(
|
|
'tos_id' => 8,
|
|
'terms_url' => 'https://business.pinterest.com/en/pinterest-advertising-services-agreement',
|
|
),
|
|
'FR' => array(
|
|
'tos_id' => 11,
|
|
'terms_url' => 'https://business.pinterest.com/fr/pinterest-advertising-services-agreement',
|
|
),
|
|
'BR' => array(
|
|
'tos_id' => 15,
|
|
'terms_url' => 'https://business.pinterest.com/pt-br/pinterest-advertising-services-agreement/',
|
|
),
|
|
'MX' => array(
|
|
'tos_id' => 16,
|
|
'terms_url' => 'https://business.pinterest.com/es/pinterest-advertising-services-agreement/mexico/',
|
|
),
|
|
'*' => array(
|
|
'tos_id' => 9,
|
|
'terms_url' => 'https://business.pinterest.com/en-gb/pinterest-advertising-services-agreement/',
|
|
),
|
|
);
|
|
|
|
/**
|
|
* Set the minimum required versions for the plugin.
|
|
*/
|
|
const PLUGIN_REQUIREMENTS = array(
|
|
'php_version' => '7.4',
|
|
'wp_version' => '5.6',
|
|
'wc_version' => '5.3',
|
|
'action_scheduler' => '3.3.0',
|
|
);
|
|
|
|
/**
|
|
* Pinterest_For_Woocommerce version.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $version = PINTEREST_FOR_WOOCOMMERCE_VERSION;
|
|
|
|
/**
|
|
* The single instance of the class.
|
|
*
|
|
* @var Pinterest_For_Woocommerce
|
|
* @since 1.0.0
|
|
*/
|
|
protected static $instance = null;
|
|
|
|
/**
|
|
* The initialized state of the class.
|
|
*
|
|
* @var Pinterest_For_Woocommerce
|
|
* @since 1.0.0
|
|
*/
|
|
protected static $initialized = false;
|
|
|
|
/**
|
|
* Heartbeat instance.
|
|
*
|
|
* @var Heartbeat
|
|
* @since 1.1.0
|
|
*/
|
|
protected $heartbeat = null;
|
|
|
|
/**
|
|
* When set to true, the settings have been
|
|
* changed and the runtime cached must be flushed
|
|
*
|
|
* @var Pinterest_For_Woocommerce
|
|
* @since 1.0.0
|
|
*/
|
|
protected static $dirty_settings = array();
|
|
|
|
/**
|
|
* The default settings that will be created
|
|
* with the given values, if they don't exist.
|
|
*
|
|
* @var array
|
|
* @since 1.0.0
|
|
*/
|
|
protected static $default_settings = array(
|
|
'track_conversions' => true,
|
|
'track_conversions_capi' => false,
|
|
'enhanced_match_support' => true,
|
|
'automatic_enhanced_match_support' => true,
|
|
'save_to_pinterest' => true,
|
|
'rich_pins_on_posts' => true,
|
|
'rich_pins_on_products' => true,
|
|
'product_sync_enabled' => true,
|
|
'enable_debug_logging' => false,
|
|
'erase_plugin_data' => false,
|
|
);
|
|
|
|
/**
|
|
* Main Pinterest_For_Woocommerce Instance.
|
|
*
|
|
* Ensures only one instance of Pinterest_For_Woocommerce is loaded or can be loaded.
|
|
*
|
|
* @since 1.0.0
|
|
* @static
|
|
* @see Pinterest_For_Woocommerce()
|
|
* @return Pinterest_For_Woocommerce - Main instance.
|
|
*/
|
|
public static function instance() {
|
|
if ( is_null( self::$instance ) ) {
|
|
self::$instance = new self();
|
|
self::$instance->maybe_init_plugin();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Cloning is forbidden.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function __clone() {
|
|
_doing_it_wrong( __FUNCTION__, esc_html__( 'Cloning this class is forbidden.', 'pinterest-for-woocommerce' ), '1.0.0' );
|
|
}
|
|
|
|
/**
|
|
* Deserializing instances of this class is forbidden.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function __wakeup() {
|
|
_doing_it_wrong( __FUNCTION__, esc_html__( 'Deserializing instances of this class is forbidden.', 'pinterest-for-woocommerce' ), '1.0.0' );
|
|
}
|
|
|
|
/**
|
|
* Pinterest_For_Woocommerce Initializer.
|
|
*/
|
|
public function maybe_init_plugin() {
|
|
if ( self::$initialized ) {
|
|
_doing_it_wrong( __FUNCTION__, esc_html__( 'Only a single instance of this class is allowed. Use singleton.', 'pinterest-for-woocommerce' ), '1.0.0' );
|
|
return;
|
|
}
|
|
|
|
self::$initialized = true;
|
|
|
|
$this->define_constants();
|
|
|
|
add_action( 'plugins_loaded', array( $this, 'init_plugin' ) );
|
|
|
|
/**
|
|
* Plugin loaded action.
|
|
* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment
|
|
*/
|
|
do_action( 'pinterest_for_woocommerce_loaded' );
|
|
}
|
|
|
|
|
|
/**
|
|
* Define Pinterest_For_Woocommerce Constants.
|
|
*/
|
|
private function define_constants() {
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_PREFIX', 'pinterest-for-woocommerce' );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_PLUGIN_BASENAME', plugin_basename( PINTEREST_FOR_WOOCOMMERCE_PLUGIN_FILE ) );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_OPTION_NAME', 'pinterest_for_woocommerce' );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_DATA_NAME', 'pinterest_for_woocommerce_data' );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_LOG_PREFIX', 'pinterest-for-woocommerce' );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_WOO_CONNECT_URL', 'https://api.woocommerce.com/' );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_WOO_CONNECT_SERVICE', 'pinterest-v5' );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_API_NAMESPACE', 'pinterest' );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_CONNECT_NONCE', 'wp_rest' );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_API_VERSION', '1' );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_API_AUTH_ENDPOINT', 'oauth/callback' );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_TRACKER_PREFIX', 'pfw' );
|
|
define( 'PINTEREST_FOR_WOOCOMMERCE_PINTEREST_API_VERSION', PINTEREST_FOR_WOOCOMMERCE_OPTION_NAME . '_pinterest_api_version' );
|
|
}
|
|
|
|
|
|
/**
|
|
* What type of request is this?
|
|
*
|
|
* @param string $type admin, ajax, cron or frontend.
|
|
* @return bool
|
|
*/
|
|
private function is_request( $type ) {
|
|
switch ( $type ) {
|
|
case 'admin':
|
|
return is_admin();
|
|
case 'ajax':
|
|
return defined( 'DOING_AJAX' );
|
|
case 'cron':
|
|
return defined( 'DOING_CRON' );
|
|
case 'frontend':
|
|
return ( ! is_admin() || defined( 'DOING_AJAX' ) ) && ! defined( 'DOING_CRON' );
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Include required core files used in admin and on the frontend.
|
|
*/
|
|
private function includes() {
|
|
|
|
include_once 'includes/class-pinterest-for-woocommerce-ads-supported-countries.php';
|
|
|
|
if ( $this->is_request( 'admin' ) ) {
|
|
include_once 'includes/admin/class-pinterest-for-woocommerce-admin.php';
|
|
}
|
|
|
|
if ( $this->is_request( 'frontend' ) ) {
|
|
include_once 'includes/class-pinterest-for-woocommerce-frontend-assets.php';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Include plugins files and hook into actions and filters.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function init_plugin() {
|
|
|
|
if ( ! Checker::instance()->is_compatible( PINTEREST_FOR_WOOCOMMERCE_PLUGIN_FILE, PINTEREST_FOR_WOOCOMMERCE_VERSION ) || ! $this->check_plugin_requirements() ) {
|
|
return;
|
|
}
|
|
|
|
$this->includes();
|
|
|
|
add_action( 'admin_init', array( $this, 'admin_init' ), 0 );
|
|
add_action( 'rest_api_init', array( $this, 'init_api_endpoints' ) );
|
|
add_action( 'wp_head', array( $this, 'maybe_inject_verification_code' ) );
|
|
add_action( 'wp_head', array( Pinterest\RichPins::class, 'maybe_inject_rich_pins_opengraph_tags' ) );
|
|
add_action( 'wp', array( Pinterest\SaveToPinterest::class, 'maybe_init' ) );
|
|
|
|
add_action( 'init', array( $this, 'init' ), 0 );
|
|
|
|
// ActionScheduler is activated on init 1 so lets make sure we are updating after that.
|
|
add_action( 'init', array( $this, 'maybe_update_plugin' ), 5 );
|
|
add_action( 'init', array( self::class, 'init_tracking' ) );
|
|
add_action( 'init', array( Pinterest\Heartbeat::class, 'schedule_events' ) );
|
|
add_action( 'init', array( Pinterest\ProductSync::class, 'maybe_init' ) );
|
|
add_action( 'init', array( Pinterest\TrackerSnapshot::class, 'maybe_init' ) );
|
|
add_action( 'init', array( Pinterest\Billing::class, 'schedule_event' ) );
|
|
add_action( 'init', array( Pinterest\AdCredits::class, 'schedule_event' ) );
|
|
add_action( 'init', array( Pinterest\RefreshToken::class, 'schedule_event' ) );
|
|
add_action( 'init', array( Pinterest\CommerceIntegration::class, 'init' ) );
|
|
|
|
// Register the marketing channel if the feature is included.
|
|
if ( defined( 'WC_MCM_EXISTS' ) ) {
|
|
add_action(
|
|
'init',
|
|
array( Pinterest\MultichannelMarketing\MarketingChannelRegistrar::class, 'register' )
|
|
);
|
|
}
|
|
|
|
// Verify that the ads_campaign is active or not.
|
|
add_action( 'admin_init', array( Pinterest\AdCredits::class, 'check_if_ads_campaign_is_active' ) );
|
|
|
|
// Append credits info to account data.
|
|
add_action( 'init', array( $this, 'add_currency_credits_info_to_account_data' ) );
|
|
|
|
add_action( 'pinterest_for_woocommerce_token_saved', array( self::class, 'set_default_settings' ) );
|
|
add_action( 'pinterest_for_woocommerce_token_saved', array( self::class, 'create_commerce_integration' ) );
|
|
add_action( 'pinterest_for_woocommerce_token_saved', array( self::class, 'update_account_data' ) );
|
|
add_action( 'pinterest_for_woocommerce_token_saved', array( self::class, 'update_linked_businesses' ) );
|
|
add_action( 'pinterest_for_woocommerce_token_saved', array( self::class, 'post_update_cleanup' ) );
|
|
add_action( 'pinterest_for_woocommerce_token_saved', array( TokenInvalidFailure::class, 'possibly_delete_note' ) );
|
|
|
|
add_action( 'pinterest_for_woocommerce_disconnect', array( self::class, 'reset_connection' ) );
|
|
|
|
// Handle the Pinterest verification URL.
|
|
add_action( 'parse_request', array( $this, 'verification_request' ) );
|
|
|
|
// Init marketing notifications.
|
|
add_action( Heartbeat::DAILY, array( $this, 'init_marketing_notifications' ) );
|
|
|
|
// Hook the setup task. The hook admin_init is not triggered when the WC fetches the tasks using the endpoint: wp-json/wc-admin/onboarding/tasks and hence hooking into init.
|
|
add_action( 'init', array( $this, 'add_onboarding_task' ), 20 );
|
|
}
|
|
|
|
/**
|
|
* Initialize Tracker and add trackers to it.
|
|
*
|
|
* @since 1.4.0
|
|
*
|
|
* @return Pinterest\Tracking|false
|
|
*/
|
|
public static function init_tracking() {
|
|
|
|
// Init WP Consent API integration.
|
|
new Pinterest\WPConsentAPI();
|
|
|
|
/**
|
|
* Filters whether to disable tracking based on user consent.
|
|
*
|
|
* @since 1.4.21 Added to provide granular user consent control for tracking.
|
|
*
|
|
* @param bool $disable_tracking Whether to disable tracking due to user consent.
|
|
*/
|
|
$is_tracking_disabled_user_consent = apply_filters( 'woocommerce_pinterest_disable_tracking_user_consent', false );
|
|
$is_tracking_conversions_disabled = ! Pinterest_For_Woocommerce()::get_setting( 'track_conversions' );
|
|
$is_not_a_site = wp_doing_cron() || is_admin();
|
|
$should_disable_tracking = $is_tracking_disabled_user_consent || $is_tracking_conversions_disabled || $is_not_a_site;
|
|
|
|
/**
|
|
* Filters whether to disable tracking.
|
|
*
|
|
* @since 1.4.0
|
|
*
|
|
* @param bool $disable_tracking Whether to disable tracking based on consent conditions.
|
|
*/
|
|
if ( apply_filters( 'woocommerce_pinterest_disable_tracking', $should_disable_tracking ) ) {
|
|
return false;
|
|
}
|
|
|
|
$tracking = new Tracking( array( new Tag() ) );
|
|
|
|
if ( Pinterest_For_Woocommerce()::get_setting( 'track_conversions_capi' ) ) {
|
|
$user = new User( WC_Geolocation::get_ip_address(), wc_get_user_agent() );
|
|
$conversions_tracker = new Conversions( $user );
|
|
$tracking->add_tracker( $conversions_tracker );
|
|
}
|
|
|
|
return $tracking;
|
|
}
|
|
|
|
/**
|
|
* Init Pinterest_For_Woocommerce when WordPress initializes.
|
|
*/
|
|
public function init() {
|
|
/**
|
|
* Before init action.
|
|
* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment
|
|
*/
|
|
do_action( 'before_pinterest_for_woocommerce_init' );
|
|
|
|
// Set up localization.
|
|
$this->load_plugin_textdomain();
|
|
|
|
/**
|
|
* Init action.
|
|
* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment
|
|
*/
|
|
do_action( 'pinterest_for_woocommerce_init' );
|
|
}
|
|
|
|
/**
|
|
* Init classes for admin interface.
|
|
*/
|
|
public function admin_init() {
|
|
$view_factory = new Pinterest\View\PHPViewFactory();
|
|
$admin = new Pinterest\Admin\Admin( $view_factory );
|
|
$attributes_tab = new Pinterest\Admin\Product\Attributes\AttributesTab( $admin );
|
|
$activation_redirect = new Pinterest\Admin\ActivationRedirect();
|
|
$variation_attributes = new Pinterest\Admin\Product\Attributes\VariationsAttributes( $admin );
|
|
|
|
$admin->register();
|
|
$attributes_tab->register();
|
|
$activation_redirect->register();
|
|
$variation_attributes->register();
|
|
}
|
|
|
|
/**
|
|
* Init marketing notifications.
|
|
*
|
|
* @since 1.1.0
|
|
*/
|
|
public function init_marketing_notifications() {
|
|
$notifications = new MarketingNotifications();
|
|
$notifications->init_notifications();
|
|
}
|
|
|
|
/**
|
|
* Checks all plugin requirements. If run in admin context also adds a notice.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function check_plugin_requirements() {
|
|
|
|
$errors = array();
|
|
global $wp_version;
|
|
|
|
if ( ! version_compare( PHP_VERSION, self::PLUGIN_REQUIREMENTS['php_version'], '>=' ) ) {
|
|
/* Translators: The minimum PHP version */
|
|
$errors[] = sprintf( esc_html__( 'Pinterest for WooCommerce requires a minimum PHP version of %s.', 'pinterest-for-woocommerce' ), self::PLUGIN_REQUIREMENTS['php_version'] );
|
|
}
|
|
|
|
if ( ! version_compare( $wp_version, self::PLUGIN_REQUIREMENTS['wp_version'], '>=' ) ) {
|
|
/* Translators: The minimum WP version */
|
|
$errors[] = sprintf( esc_html__( 'Pinterest for WooCommerce requires a minimum WordPress version of %s.', 'pinterest-for-woocommerce' ), self::PLUGIN_REQUIREMENTS['wp_version'] );
|
|
}
|
|
|
|
if ( ! defined( 'WC_VERSION' ) || ! version_compare( WC_VERSION, self::PLUGIN_REQUIREMENTS['wc_version'], '>=' ) ) {
|
|
/* Translators: The minimum WC version */
|
|
$errors[] = sprintf( esc_html__( 'Pinterest for WooCommerce requires a minimum WooCommerce version of %s.', 'pinterest-for-woocommerce' ), self::PLUGIN_REQUIREMENTS['wc_version'] );
|
|
}
|
|
|
|
/**
|
|
* Check if WooCommerce Admin is enabled.
|
|
* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment
|
|
*/
|
|
if ( apply_filters( 'woocommerce_admin_disabled', false ) ) {
|
|
$errors[] = esc_html__( 'Pinterest for WooCommerce requires WooCommerce Admin to be enabled.', 'pinterest-for-woocommerce' );
|
|
}
|
|
|
|
if ( ! function_exists( 'as_has_scheduled_action' ) ) {
|
|
/* Translators: The minimum Action Scheduler version */
|
|
$errors[] = sprintf( esc_html__( 'Pinterest for WooCommerce requires a minimum Action Scheduler package of %s. It can be caused by old version of the WooCommerce extensions.', 'pinterest-for-woocommerce' ), self::PLUGIN_REQUIREMENTS['action_scheduler'] );
|
|
}
|
|
|
|
if ( empty( $errors ) ) {
|
|
return true;
|
|
}
|
|
|
|
if ( $this->is_request( 'admin' ) ) {
|
|
add_action(
|
|
'admin_notices',
|
|
function () use ( $errors ) {
|
|
?>
|
|
<div class="notice notice-error">
|
|
<?php
|
|
foreach ( $errors as $error ) {
|
|
echo '<p>' . esc_html( $error ) . '</p>';
|
|
}
|
|
?>
|
|
</div>
|
|
<?php
|
|
}
|
|
);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Plugin update entry point.
|
|
*
|
|
* @since 1.0.9
|
|
* @return void
|
|
*/
|
|
public function maybe_update_plugin() {
|
|
$plugin_update = new Pinterest\PluginUpdate();
|
|
$plugin_update->maybe_update();
|
|
}
|
|
|
|
/**
|
|
* Load localization files.
|
|
*
|
|
* Note: the first-loaded translation file overrides any following ones if the same translation is present.
|
|
*
|
|
* Locales found in:
|
|
* - WP_LANG_DIR/pinterest-for-woocommerce/pinterest-for-woocommerce-LOCALE.mo
|
|
* - WP_LANG_DIR/plugins/pinterest-for-woocommerce-LOCALE.mo
|
|
*/
|
|
private function load_plugin_textdomain() {
|
|
/**
|
|
* Get plugin locale.
|
|
* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment
|
|
*/
|
|
$locale = apply_filters( 'plugin_locale', get_locale(), 'pinterest-for-woocommerce' );
|
|
|
|
load_textdomain( 'pinterest-for-woocommerce', WP_LANG_DIR . '/pinterest-for-woocommerce/pinterest-for-woocommerce-' . $locale . '.mo' );
|
|
load_plugin_textdomain( 'pinterest-for-woocommerce', false, plugin_basename( __DIR__ ) . '/i18n/languages' );
|
|
}
|
|
|
|
/**
|
|
* Get the plugin url.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function plugin_url() {
|
|
return untrailingslashit( plugins_url( '/', __FILE__ ) );
|
|
}
|
|
|
|
/**
|
|
* Get the plugin path.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function plugin_path() {
|
|
return untrailingslashit( plugin_dir_path( __FILE__ ) );
|
|
}
|
|
|
|
/**
|
|
* Get the template path.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function template_path() {
|
|
/**
|
|
* Returns template path.
|
|
* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment
|
|
*/
|
|
return apply_filters( 'pinterest_for_woocommerce_template_path', 'pinterest-for-woocommerce/' );
|
|
}
|
|
|
|
/**
|
|
* Get Ajax URL.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function ajax_url() {
|
|
return admin_url( 'admin-ajax.php', 'relative' );
|
|
}
|
|
|
|
|
|
/**
|
|
* Return APP Settings
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param boolean $force Controls whether to force getting a fresh value instead of one from the runtime cache.
|
|
* @param string $option Controls which option to read/write to.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_settings( $force = false, $option = PINTEREST_FOR_WOOCOMMERCE_OPTION_NAME ) {
|
|
|
|
static $settings;
|
|
|
|
if ( $force || is_null( $settings ) || ! isset( $settings[ $option ] ) || ( isset( self::$dirty_settings[ $option ] ) && self::$dirty_settings[ $option ] ) ) {
|
|
$settings[ $option ] = get_option( $option );
|
|
}
|
|
|
|
return $settings[ $option ];
|
|
}
|
|
|
|
|
|
/**
|
|
* Return APP Setting based on its key
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $key The key of specific option to retrieve.
|
|
* @param boolean $force Controls whether to force getting a fresh value instead of one from the runtime cache.
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public static function get_setting( $key, $force = false ) {
|
|
|
|
$settings = self::get_settings( $force );
|
|
|
|
return empty( $settings[ $key ] ) ? false : $settings[ $key ];
|
|
}
|
|
|
|
|
|
/**
|
|
* Save APP Setting
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $key The key of specific option to retrieve.
|
|
* @param mixed $data The data to save for this option key.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function save_setting( $key, $data ) {
|
|
|
|
$settings = self::get_settings( true );
|
|
// Handle possible false value.
|
|
if ( ! is_array( $settings ) ) {
|
|
$settings = array();
|
|
}
|
|
$settings[ $key ] = $data;
|
|
|
|
return self::save_settings( $settings );
|
|
}
|
|
|
|
|
|
/**
|
|
* Save APP Settings
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param array $settings The array of settings to save.
|
|
* @param string $option Controls which option to read/write to.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function save_settings( $settings, $option = PINTEREST_FOR_WOOCOMMERCE_OPTION_NAME ) {
|
|
self::$dirty_settings[ $option ] = true;
|
|
return update_option( $option, $settings );
|
|
}
|
|
|
|
/**
|
|
* Set API version used by the plugin.
|
|
*
|
|
* @since 1.4.0
|
|
*
|
|
* @param string $version The API version.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function set_api_version( $version ) {
|
|
return update_option( PINTEREST_FOR_WOOCOMMERCE_PINTEREST_API_VERSION, $version );
|
|
}
|
|
|
|
/**
|
|
* Get API version used by the plugin.
|
|
*
|
|
* @since 1.4.0
|
|
*
|
|
* @return string The API version.
|
|
*/
|
|
public static function get_api_version() {
|
|
return get_option( PINTEREST_FOR_WOOCOMMERCE_PINTEREST_API_VERSION, '' );
|
|
}
|
|
|
|
/**
|
|
* Return APP Data based on its key
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $key The key of specific data to retrieve.
|
|
* @param boolean $force Controls whether to force getting a fresh value instead of one from the runtime cache.
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public static function get_data( $key, $force = false ) {
|
|
|
|
$settings = self::get_settings( $force, PINTEREST_FOR_WOOCOMMERCE_DATA_NAME );
|
|
|
|
return $settings[ $key ] ?? null;
|
|
}
|
|
|
|
|
|
/**
|
|
* Save APP Data
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $key The key of specific data to retrieve.
|
|
* @param mixed $data The data to save for this option key.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function save_data( $key, $data ) {
|
|
|
|
$settings = self::get_settings( true, PINTEREST_FOR_WOOCOMMERCE_DATA_NAME );
|
|
// Handle possible false value.
|
|
if ( ! is_array( $settings ) ) {
|
|
$settings = array();
|
|
}
|
|
$settings[ $key ] = $data;
|
|
|
|
return self::save_settings( $settings, PINTEREST_FOR_WOOCOMMERCE_DATA_NAME );
|
|
}
|
|
|
|
/**
|
|
* Remove APP Data key.
|
|
*
|
|
* @param string $key - The key of specific data to retrieve.
|
|
*
|
|
* @since 1.3.1
|
|
*
|
|
* @return bool - True if the data was removed, false otherwise.
|
|
*/
|
|
public static function remove_data( string $key ) {
|
|
$settings = self::get_settings( true, PINTEREST_FOR_WOOCOMMERCE_DATA_NAME );
|
|
unset( $settings[ $key ] );
|
|
return self::save_settings( $settings, PINTEREST_FOR_WOOCOMMERCE_DATA_NAME );
|
|
}
|
|
|
|
/**
|
|
* Add API endpoints
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function init_api_endpoints() {
|
|
new Pinterest\API\Advertisers();
|
|
new Pinterest\API\AdvertiserConnect();
|
|
new Pinterest\API\Auth();
|
|
new Pinterest\API\AuthDisconnect();
|
|
new Pinterest\API\Businesses();
|
|
new Pinterest\API\DomainVerification();
|
|
new Pinterest\API\FeedState();
|
|
new Pinterest\API\FeedIssues();
|
|
new Pinterest\API\Tags();
|
|
new Pinterest\API\Health();
|
|
new Pinterest\API\Settings();
|
|
new Pinterest\API\SyncSettings();
|
|
new Pinterest\API\UserInteraction();
|
|
}
|
|
|
|
/**
|
|
* Get decrypted token data.
|
|
*
|
|
* The Access token and Crypto key live in the data option in the following form:
|
|
* data: {
|
|
* ...
|
|
* token: {
|
|
* access_token: ${encrypted_token},
|
|
* },
|
|
* crypto_encoded_key: ${encryption_key},
|
|
* ...
|
|
* }
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @return array {
|
|
* Access Token.
|
|
*
|
|
* @type string $access_token Decrypted Access Token
|
|
* }
|
|
*/
|
|
public static function get_access_token() {
|
|
|
|
$token_data = self::get_data( 'token_data', true );
|
|
$token = array();
|
|
|
|
try {
|
|
$token['access_token'] = empty( $token_data['access_token'] ) ? '' : Pinterest\Crypto::decrypt( $token_data['access_token'] );
|
|
} catch ( \Exception $th ) {
|
|
/* Translators: The error description */
|
|
Logger::log( sprintf( esc_html__( 'Could not decrypt the Pinterest API access token. Try reconnecting to Pinterest. [%s]', 'pinterest-for-woocommerce' ), $th->getMessage() ), 'error' );
|
|
}
|
|
|
|
return $token;
|
|
}
|
|
|
|
|
|
/**
|
|
* Save encrypted token data. See the documentation of the get_token() method for the expected format of the related data variables.
|
|
*
|
|
* @since 1.0.0
|
|
* @since 1.4.0 Added refresh token and tokens expiration.
|
|
*
|
|
* @param array $token The array containing the token values to save.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function save_token_data( $token ) {
|
|
$token['access_token'] = empty( $token['access_token'] ) ? '' : Pinterest\Crypto::encrypt( $token['access_token'] );
|
|
$token['expires_in'] = $token['expires_in'] ?? '';
|
|
$token['refresh_token'] = empty( $token['refresh_token'] ) ? '' : Pinterest\Crypto::encrypt( $token['refresh_token'] );
|
|
$token['refresh_token_expires_in'] = $token['refresh_token_expires_in'] ?? '';
|
|
$token['scopes'] = empty( $token['scopes'] ) ? '' : $token['scopes'];
|
|
$token['refresh_time'] = time();
|
|
|
|
return self::save_data( 'token_data', $token );
|
|
}
|
|
|
|
/**
|
|
* Save connection info data.
|
|
*
|
|
* @since 1.4.0
|
|
*
|
|
* @param array $connection_info_data The array containing the connection info data.
|
|
* @return bool True if the data was saved successfully.
|
|
*/
|
|
public static function save_connection_info_data( array $connection_info_data ): bool {
|
|
return self::save_data( 'connection_info_data', $connection_info_data );
|
|
}
|
|
|
|
/**
|
|
* Saves the integration data.
|
|
*
|
|
* @param array $integration_data The array containing the integration data.
|
|
* @return bool True if the data was saved successfully.
|
|
*/
|
|
public static function save_integration_data( array $integration_data ): bool {
|
|
return self::save_data( 'integration_data', $integration_data );
|
|
}
|
|
|
|
/**
|
|
* Disconnect by clearing the Token and any other data that we should gather from scratch.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @return bool True if disconnection was successful.
|
|
*/
|
|
public static function disconnect(): bool {
|
|
// Reset Feed file generation telemetry.
|
|
ProductFeedStatus::deregister();
|
|
Pinterest\CommerceIntegration::maybe_unregister_retries();
|
|
|
|
/*
|
|
* If there is no business connected, disconnecting merchant will throw error.
|
|
* Just need to clean account data in these cases.
|
|
*/
|
|
if ( ! self::is_business_connected() ) {
|
|
self::flush_options();
|
|
// At this point we're disconnected.
|
|
return true;
|
|
}
|
|
|
|
try {
|
|
// Delete all the feeds for the merchant.
|
|
FeedRegistration::maybe_delete_stale_feeds_for_merchant( '' );
|
|
// Delete Commerce Integration.
|
|
self::delete_commerce_integration();
|
|
// Remove stored data.
|
|
self::flush_options();
|
|
// At this point we're disconnected.
|
|
return true;
|
|
} catch ( Exception $th ) {
|
|
// There was an error disconnecting merchant.
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resets the connection by clearing the local connection data.
|
|
*
|
|
* @since 1.4.4
|
|
*
|
|
* @return void
|
|
* @throws \Automattic\WooCommerce\Admin\Notes\NotesUnavailableException If the notes API is not available.
|
|
*/
|
|
public static function reset_connection() {
|
|
self::disconnect();
|
|
|
|
TokenInvalidFailure::possibly_add_note();
|
|
}
|
|
|
|
/**
|
|
* Flush data option and remove settings.
|
|
*
|
|
* @return void
|
|
*/
|
|
private static function flush_options() {
|
|
// Flush the whole data option.
|
|
delete_option( PINTEREST_FOR_WOOCOMMERCE_DATA_NAME );
|
|
UserInteraction::flush_options();
|
|
|
|
// Remove settings that may cause issues if stale on disconnect.
|
|
self::save_setting( 'account_data', null );
|
|
self::save_setting( 'tracking_advertiser', null );
|
|
self::save_setting( 'tracking_tag', null );
|
|
|
|
// Cancel scheduled jobs.
|
|
Pinterest\ProductSync::cancel_jobs();
|
|
Heartbeat::cancel_jobs();
|
|
}
|
|
|
|
/**
|
|
* Return WooConnect Bridge URL
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function get_connection_proxy_url() {
|
|
return (string) trailingslashit(
|
|
/**
|
|
* Filters the proxy URL.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $proxy_url the connection proxy URL
|
|
*/
|
|
apply_filters(
|
|
'pinterest_for_woocommerce_connection_proxy_url',
|
|
PINTEREST_FOR_WOOCOMMERCE_WOO_CONNECT_URL
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
* Return The Middleware URL based on the given context
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $context The context parameter.
|
|
* @param string $args Additional arguments like 'view' or 'business_id'.
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function get_middleware_url( $context = 'login', $args = array() ) {
|
|
|
|
$nonce = wp_create_nonce( PINTEREST_FOR_WOOCOMMERCE_CONNECT_NONCE );
|
|
set_transient( PINTEREST_FOR_WOOCOMMERCE_CONNECT_NONCE, $nonce, 10 * MINUTE_IN_SECONDS );
|
|
|
|
$rest_url = get_rest_url( null, PINTEREST_FOR_WOOCOMMERCE_API_NAMESPACE . '/v' . PINTEREST_FOR_WOOCOMMERCE_API_VERSION . '/' . PINTEREST_FOR_WOOCOMMERCE_API_AUTH_ENDPOINT );
|
|
|
|
$state_params = array(
|
|
'redirect' => $rest_url,
|
|
'nonce' => $nonce,
|
|
);
|
|
|
|
switch ( $context ) {
|
|
case 'create_business':
|
|
$state_params['create-business'] = true;
|
|
break;
|
|
case 'switch_business':
|
|
$state_params['switch-to-business'] = $args['business_id'];
|
|
break;
|
|
}
|
|
|
|
$state = http_build_query( $state_params );
|
|
|
|
// phpcs:ignore Squiz.Commenting.InlineComment.InvalidEndChar
|
|
// nosemgrep: audit.php.wp.security.xss.query-arg
|
|
return self::get_connection_proxy_url() . 'integrations/connect/' . PINTEREST_FOR_WOOCOMMERCE_WOO_CONNECT_SERVICE . '?' . $state;
|
|
}
|
|
|
|
|
|
/**
|
|
* Injects needed meta tags to the site's header
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function maybe_inject_verification_code() {
|
|
|
|
$verification_data = self::get_data( 'verification_data' );
|
|
|
|
if ( $verification_data ) {
|
|
printf( '<meta name="p:domain_verify" content="%s"/>', esc_attr( $verification_data['verification_code'] ) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Connects WC to Pinterest.
|
|
*
|
|
* @return array the result of APIV5::create_commerce_integration.
|
|
* @throws Exception In case of 404, 409 and 500 errors from Pinterest.
|
|
* @see Pinterest\API\APIV5::create_commerce_integration
|
|
* @since 1.4.0
|
|
*/
|
|
public static function create_commerce_integration(): array {
|
|
$connection_data = self::get_data( 'connection_info_data', true );
|
|
|
|
// It does not make any sense to create integration without Advertiser ID.
|
|
if ( empty( $connection_data['advertiser_id'] ) ) {
|
|
throw new Exception(
|
|
sprintf(
|
|
esc_html__(
|
|
'Commerce Integration cannot be created: Advertiser ID is missing.',
|
|
'pinterest-for-woocommerce'
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
return Pinterest\CommerceIntegration::handle_create();
|
|
}
|
|
|
|
/**
|
|
* Updates WC integration parameters with Pinterest.
|
|
*
|
|
* @since 1.4.0
|
|
*
|
|
* @param string $external_business_id External business ID for the integration.
|
|
* @param array $data Integration data to update with Pinterest.
|
|
*
|
|
* @see Pinterest\API\APIV5::update_commerce_integration
|
|
* @return array the result of APIV5::update_commerce_integration.
|
|
* @throws PinterestApiException In case of 404, 409 and 500 errors from Pinterest.
|
|
*/
|
|
public static function update_commerce_integration( string $external_business_id, array $data ): array {
|
|
return Pinterest\API\APIV5::update_commerce_integration( $external_business_id, $data );
|
|
}
|
|
|
|
/**
|
|
* Disconnects WC from Pinterest.
|
|
*
|
|
* @since 1.4.0
|
|
*
|
|
* @return bool
|
|
* @throws PinterestApiException In case of 500 unexpected error from Pinterest.
|
|
*/
|
|
public static function delete_commerce_integration(): bool {
|
|
try {
|
|
$external_business_id = self::get_data( 'integration_data' )['external_business_id'] ?? '';
|
|
if ( empty( $external_business_id ) ) {
|
|
return true;
|
|
}
|
|
Pinterest\API\APIV5::delete_commerce_integration( $external_business_id );
|
|
self::remove_data( 'integration_data' );
|
|
return true;
|
|
} catch ( PinterestApiException $e ) {
|
|
Logger::log( $e->getMessage(), 'error' );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches the account_data parameters from Pinterest's API
|
|
* Saves it to the plugin options and returns it.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @return array Account data from Pinterest.
|
|
*
|
|
* @throws Exception PHP Exception.
|
|
*/
|
|
public static function update_account_data() {
|
|
try {
|
|
$account_data = Pinterest\API\APIV5::get_account_info();
|
|
|
|
$data = array(
|
|
'username' => $account_data['username'] ?? '',
|
|
'full_name' => '',
|
|
'id' => $account_data['id'] ?? '',
|
|
'image_medium_url' => $account_data['profile_image'] ?? '',
|
|
// Partner is a user who is a business account not a pinner ('BUSINESS', 'PINNER' account types).
|
|
'is_partner' => 'BUSINESS' === ( $account_data['account_type'] ?? '' ),
|
|
);
|
|
|
|
$verified_websites = array_reduce(
|
|
Pinterest\API\APIV5::get_user_websites()['items'] ?? array(),
|
|
function ( $carry, $item ) {
|
|
if ( 'verified' === $item['status'] ) {
|
|
$carry[] = $item['website'];
|
|
}
|
|
return $carry;
|
|
},
|
|
array()
|
|
);
|
|
|
|
$data += array(
|
|
// Array of verified website domain names.
|
|
'verified_user_websites' => $verified_websites,
|
|
// Indicates if any of the verified websites is verified true or false.
|
|
'is_any_website_verified' => 0 < count( $verified_websites ),
|
|
);
|
|
|
|
/*
|
|
* For now we assume that the billing is not setup and credits are not redeemed.
|
|
* We will be able to check that only when the advertiser will be connected.
|
|
* The billing is tied to advertiser.
|
|
*/
|
|
$data['is_billing_setup'] = false;
|
|
$data['coupon_redeem_info'] = array( 'redeem_status' => false );
|
|
$data['currency_credit_info'] = AdsCreditCurrency::get_currency_credits();
|
|
|
|
Pinterest_For_Woocommerce()::save_setting( 'account_data', $data );
|
|
return $data;
|
|
} catch ( Throwable $th ) {
|
|
self::disconnect();
|
|
throw new Exception( esc_html__( 'There was an error getting the account data.', 'pinterest-for-woocommerce' ) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates linked businesses.
|
|
*
|
|
* @since 1.4.0
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function update_linked_businesses() {
|
|
self::get_linked_businesses( true );
|
|
}
|
|
|
|
/**
|
|
* Cleanup after the token update.
|
|
*
|
|
* @since 1.4.0
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function post_update_cleanup() {
|
|
TokenExchangeFailure::delete_failure_note();
|
|
|
|
// Update completed successfully.
|
|
Pinterest_For_Woocommerce()::set_api_version( 'v5' );
|
|
}
|
|
|
|
/**
|
|
* Maybe check billing setup.
|
|
*
|
|
* @since 1.2.5
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function maybe_check_billing_setup() {
|
|
$account_data = Pinterest_For_Woocommerce()::get_setting( 'account_data' );
|
|
$has_billing_setup_old = is_array( $account_data ) && ( $account_data['is_billing_setup'] ?? false );
|
|
if ( Billing::should_check_billing_setup_often() ) {
|
|
$has_billing_setup_new = Billing::update_billing_information();
|
|
// Detect change in billing setup to true and try to redeem.
|
|
if ( $has_billing_setup_new && ! $has_billing_setup_old ) {
|
|
AdCredits::handle_redeem_credit();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get billing setup information from the account data option.
|
|
*
|
|
* @since 1.2.5
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function get_billing_setup_info_from_account_data() {
|
|
$account_data = self::get_setting( 'account_data' );
|
|
|
|
return (bool) $account_data['is_billing_setup'];
|
|
}
|
|
|
|
/**
|
|
* Add redeem credits information to the account data option.
|
|
* Using this function makes sense only when we have a connected advertiser and the billing data is set up.
|
|
*
|
|
* @since 1.2.5
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function add_redeem_credits_info_to_account_data() {
|
|
$account_data = self::get_setting( 'account_data' );
|
|
$offer_code = AdCreditsCoupons::get_coupon_for_merchant();
|
|
|
|
// Redeem the coupon.
|
|
$error_code = false;
|
|
$error_message = '';
|
|
$redeem_status = AdCredits::redeem_credits( $offer_code, $error_code, $error_message );
|
|
|
|
$redeem_information = array(
|
|
'redeem_status' => $redeem_status,
|
|
'offer_code' => $offer_code,
|
|
'advertiser_id' => Pinterest_For_Woocommerce()::get_setting( 'tracking_advertiser' ),
|
|
'username' => $account_data['username'],
|
|
'id' => $account_data['id'],
|
|
'error_id' => $error_code,
|
|
'error_message' => $error_message,
|
|
);
|
|
|
|
/*
|
|
* Track the redeemed offer code.
|
|
*/
|
|
self::record_event(
|
|
'pfw_ads_redeem_credits',
|
|
array(
|
|
'redeem_status' => $redeem_information['redeem_status'],
|
|
'offer_code' => $redeem_information['offer_code'],
|
|
'error_id' => $redeem_information['error_id'],
|
|
)
|
|
);
|
|
|
|
$account_data['coupon_redeem_info'] = $redeem_information;
|
|
|
|
self::save_setting( 'account_data', $account_data );
|
|
}
|
|
|
|
/**
|
|
* Add currency_credit_info information to the account data option.
|
|
*
|
|
* @since 1.3.9
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function add_currency_credits_info_to_account_data() {
|
|
$account_data = self::get_setting( 'account_data' );
|
|
if ( ! isset( $account_data['currency_credit_info'] ) ) {
|
|
// Handle possible false value.
|
|
if ( ! is_array( $account_data ) ) {
|
|
$account_data = array();
|
|
}
|
|
$account_data['currency_credit_info'] = AdsCreditCurrency::get_currency_credits();
|
|
self::save_setting( 'account_data', $account_data );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add available credits information to the account data option.
|
|
*
|
|
* @since 1.2.5
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function add_available_credits_info_to_account_data() {
|
|
$account_data = self::get_setting( 'account_data' );
|
|
|
|
try {
|
|
// Check for available discounts.
|
|
$account_data['available_discounts'] = AdCredits::process_available_discounts();
|
|
self::save_setting( 'account_data', $account_data );
|
|
} catch ( Exception $e ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches a fresh copy (if needed or explicitly requested), of the authenticated user's linked business accounts.
|
|
*
|
|
* @param bool $force_refresh Whether to refresh the data from the API.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_linked_businesses( bool $force_refresh = false ): array {
|
|
$linked_businesses = ! $force_refresh ? Pinterest_For_Woocommerce()::get_data( 'linked_businesses' ) : null;
|
|
if ( null === $linked_businesses ) {
|
|
$account_data = Pinterest_For_Woocommerce()::get_setting( 'account_data' );
|
|
$fetch_linked_businesses = ! empty( $account_data ) && array_key_exists( 'is_partner', $account_data ) && ! $account_data['is_partner'];
|
|
|
|
try {
|
|
$fetched_businesses = $fetch_linked_businesses ? Pinterest\API\APIV5::get_linked_businesses() : array();
|
|
|
|
if ( ! empty( $fetched_businesses ) && 'success' === $fetched_businesses['status'] ) {
|
|
$linked_businesses = $fetched_businesses['data'];
|
|
}
|
|
|
|
$linked_businesses = $linked_businesses ?? array();
|
|
|
|
self::save_data( 'linked_businesses', $linked_businesses );
|
|
} catch ( PinterestApiException $e ) {
|
|
Logger::log( $e->getMessage(), 'error' );
|
|
$linked_businesses = array();
|
|
}
|
|
}
|
|
|
|
return $linked_businesses;
|
|
}
|
|
|
|
/**
|
|
* Returns the Pinterest AccountID from the database.
|
|
*
|
|
* @return string|false
|
|
*/
|
|
public static function get_account_id() {
|
|
$account_data = Pinterest_For_Woocommerce()::get_setting( 'account_data' );
|
|
return $account_data['id'] ?? false;
|
|
}
|
|
|
|
/**
|
|
* Sets the default settings based on the
|
|
* given values in self::$default_settings
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function set_default_settings() {
|
|
$settings = self::get_settings( true );
|
|
$settings = wp_parse_args( $settings, self::$default_settings );
|
|
|
|
return self::save_settings( $settings );
|
|
}
|
|
|
|
/**
|
|
* Hook the parse_request action and serve the html
|
|
*
|
|
* @param WP $wp Current WordPress environment instance.
|
|
*/
|
|
public function verification_request( $wp ) {
|
|
$verification_data = self::get_data( 'verification_data' );
|
|
if ( ! $verification_data || ! array_key_exists( 'filename', $verification_data ) ) {
|
|
return;
|
|
}
|
|
|
|
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
|
$request = trim( $wp->request ?? $_SERVER['PHP_SELF'] ?? '', '/' );
|
|
if ( $verification_data['filename'] === $request ) {
|
|
wc_nocache_headers();
|
|
header( 'Content-Type: text/html' );
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<meta name="p:domain_verify" content="<?php echo esc_attr( $verification_data['verification_code'] ); ?>"/>
|
|
<title></title>
|
|
</head>
|
|
<body><?php esc_html_e( 'Pinterest for WooCommerce verification page', 'pinterest-for-woocommerce' ); ?></body>
|
|
</html>
|
|
<?php
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if setup is completed and all requirements are set.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function is_setup_complete() {
|
|
return self::is_business_connected() && self::is_domain_verified();
|
|
}
|
|
|
|
|
|
/**
|
|
* Checks if connected by checking if there is an access token in the data store.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function is_connected() {
|
|
return boolval( self::get_access_token()['access_token'] ?? '' );
|
|
}
|
|
|
|
|
|
/**
|
|
* Checks if connected and on a Business account.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function is_business_connected() {
|
|
if ( ! self::is_connected() ) {
|
|
return false;
|
|
}
|
|
|
|
$account_data = self::get_setting( 'account_data' );
|
|
|
|
return isset( $account_data['is_partner'] ) ? (bool) $account_data['is_partner'] : false;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Checks whether we have verified our current domain, by checking account_data as
|
|
* returned by Pinterest.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function is_domain_verified(): bool {
|
|
$account_data = self::get_setting( 'account_data' );
|
|
$verified_domains = $account_data['verified_user_websites'] ?? array();
|
|
return in_array( wp_parse_url( get_home_url() )['host'] ?? '', $verified_domains ); // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
|
|
}
|
|
|
|
/**
|
|
* Checks if tracking is configured properly and enabled.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function is_tracking_configured() {
|
|
return false !== Pinterest\Tracking\Tag::get_active_tag();
|
|
}
|
|
|
|
/**
|
|
* Returns the Terms object for the currently configured base country.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_applicable_tos() {
|
|
|
|
$base_country = self::get_base_country( null );
|
|
|
|
return $base_country && isset( self::TOS_PER_COUNTRY[ $base_country ] ) ? self::TOS_PER_COUNTRY[ $base_country ] : self::TOS_PER_COUNTRY['*'];
|
|
}
|
|
|
|
/**
|
|
* Helper function to return the country set in WC's settings using wc_get_base_location().
|
|
*
|
|
* @param string $default_country Default country code to return if no country is set.
|
|
*
|
|
* @return mixed|string|null
|
|
*/
|
|
public static function get_base_country( $default_country = 'US' ) {
|
|
if ( ! function_exists( 'wc_get_base_location' ) ) {
|
|
return null;
|
|
}
|
|
|
|
$base_location = wc_get_base_location();
|
|
|
|
return ! empty( $base_location['country'] ) ? $base_location['country'] : $default_country;
|
|
}
|
|
|
|
/**
|
|
* Adds the onboarding task to the Tasklists.
|
|
*
|
|
* @since 1.2.11
|
|
*/
|
|
public function add_onboarding_task() {
|
|
if ( class_exists( TaskLists::class ) ) { // compatibility-code "< WC 5.9". This is added for backward compatibility.
|
|
TaskLists::add_task(
|
|
'extended',
|
|
new Onboarding(
|
|
TaskLists::get_list( 'extended' )
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
endif;
|