Your IP : 216.73.216.1
<?php
/**
* Pinterest for WooCommerce Feed Registration.
*
* @package Pinterest_For_WooCommerce/Classes/
* @version 1.0.10
*/
namespace Automattic\WooCommerce\Pinterest;
use Automattic\WooCommerce\Pinterest\Notes\AccountFailure;
use Exception;
use Throwable;
use Automattic\WooCommerce\Pinterest\Utilities\ProductFeedLogger;
use Automattic\WooCommerce\Pinterest\Exception\PinterestApiLocaleException;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class Handling feed files registration.
*/
class FeedRegistration {
use ProductFeedLogger;
const ACTION_HANDLE_FEED_REGISTRATION = PINTEREST_FOR_WOOCOMMERCE_PREFIX . '-handle-feed-registration';
/**
* Local Feed Configurations class.
*
* @var LocalFeedConfigs of local feed configurations;
*/
private $configurations;
/**
* Feed File Operations Instance
*
* @var $feed_file_operations FeedFileOperations
*/
private $feed_file_operations;
/**
* Feed Registration.
*
* @since 1.0.10
* @param LocalFeedConfigs $local_feeds_configurations Locations configuration class.
* @param FeedFileOperations $feed_file_operations Feed file operations class.
*/
public function __construct( $local_feeds_configurations, $feed_file_operations ) {
$this->configurations = $local_feeds_configurations;
$this->feed_file_operations = $feed_file_operations;
}
/**
* Initialize FeedRegistration actions and Action Scheduler hooks.
*
* @since 1.0.10
*/
public function init() {
add_action( self::ACTION_HANDLE_FEED_REGISTRATION, array( $this, 'handle_feed_registration' ) );
if ( false === as_has_scheduled_action( self::ACTION_HANDLE_FEED_REGISTRATION, array(), PINTEREST_FOR_WOOCOMMERCE_PREFIX ) ) {
as_schedule_recurring_action( time() + 10, 10 * MINUTE_IN_SECONDS, self::ACTION_HANDLE_FEED_REGISTRATION, array(), PINTEREST_FOR_WOOCOMMERCE_PREFIX );
}
// We do not want to disconnect the merchant if the authentication fails, since it running action can not be unscheduled.
add_filter( 'pinterest_for_woocommerce_disconnect_on_authentication_failure', '__return_false' );
add_action( 'pinterest_for_woocommerce_show_admin_notice_for_api_exception', array( self::class, 'maybe_account_failure_notice' ), 10, 3 );
add_action( 'pinterest_for_woocommerce_disconnect', array( AccountFailure::class, 'delete_note' ) );
}
/**
* Check if the feed is registered based on the plugin's settings.
* If not, try to register it,
* Log issues.
* Potentially report issues.
*
* Should be run on demand when settings change,
* and on a scheduled basis.
*
* @return bool
*
* @throws PinterestApiLocaleException Pinterest API does not support the locale.
* @throws PinterestApiException Pinterest API exception.
* @throws Throwable Any other exception.
*/
public function handle_feed_registration(): bool {
// Clean merchants error code.
$this->clear_merchant_error_code();
if ( ! self::feed_file_exists() ) {
self::log( 'Feed did not fully generate yet. Retrying later.' );
// Feed is not generated yet, lets wait a bit longer.
return true;
}
try {
return self::register_feed();
} catch ( PinterestApiLocaleException $e ) {
Pinterest_For_Woocommerce()::save_data( 'merchant_locale_not_valid', true );
// translators: %s: Error message.
$error_message = "Could not register the feed. Error: {$e->getMessage()}";
self::log( $error_message, 'error' );
throw $e;
} catch ( PinterestApiException $e ) {
throw $e;
} catch ( Throwable $th ) {
self::log( $th->getMessage(), 'error' );
throw $th;
}
}
/**
* Clear merchant error code.
*
* @since 1.2.13
* @return void
*/
private function clear_merchant_error_code() {
Pinterest_For_Woocommerce()::save_data( 'merchant_connected_diff_platform', false );
Pinterest_For_Woocommerce()::save_data( 'merchant_locale_not_valid', false );
}
/**
* Handles feed registration using the given arguments.
* Will try to create a merchant if none exists.
* Also, if a different feed is registered, it will update using the URL in the
* $feed_args.
*
* @return boolean
*
* @throws PinterestApiException PHP Exception.
*/
private static function register_feed(): bool {
$feed_id = Feeds::match_local_feed_configuration_to_registered_feeds();
// If no matching registered feed found try to create it.
if ( ! $feed_id ) {
$feed_id = Feeds::create_feed();
}
Pinterest_For_Woocommerce()::save_data( 'feed_registered', $feed_id );
if ( ! $feed_id ) {
return false;
}
static::maybe_delete_stale_feeds_for_merchant( $feed_id );
return true;
}
/**
* Check if there are stale feeds that are registered but not in the local feed configurations.
* Deregister them if they are registered as WooCommerce integration.
*
* @param string $feed_id Feed ID.
* @return void
*
* @since 1.2.13
*/
public static function maybe_delete_stale_feeds_for_merchant( string $feed_id ) {
$feeds = Feeds::get_feeds();
if ( empty( $feeds ) ) {
return;
}
$invalidate_cache = false;
foreach ( $feeds as $feed ) {
// Local feed should not be deleted.
if ( $feed_id === $feed['id'] ) {
continue;
}
// Delete the feed if it belongs to the current website.
$is_woocommerce_feed = 0 === strpos( $feed['location'], get_site_url() );
if ( $is_woocommerce_feed ) {
Feeds::delete_feed( $feed['id'] );
$invalidate_cache = true;
}
}
if ( $invalidate_cache ) {
Feeds::invalidate_feeds_cache();
}
}
/**
* Checks if the feed file for the configured (In $state var) feed exists.
* This could be true as the feed is being generated, if it's not the 1st time
* it's been generated.
*
* @return bool
*/
public function feed_file_exists(): bool {
return $this->feed_file_operations->check_if_feed_file_exists();
}
/**
* Returns the feed profile ID stored locally if it's registered.
* Returns `false` otherwise.
* If everything is configured correctly, this feed profile id will match
* the setup that the merchant has in Pinterest.
*
* @return string|boolean
*/
public static function get_locally_stored_registered_feed_id() {
return Pinterest_For_Woocommerce()::get_data( 'feed_registered' ) ?? false;
}
/**
* Stop feed generator jobs.
*/
public static function cancel_jobs() {
as_unschedule_all_actions( self::ACTION_HANDLE_FEED_REGISTRATION, array(), PINTEREST_FOR_WOOCOMMERCE_PREFIX );
}
/**
* Cleanup registration data.
*/
public static function deregister() {
Pinterest_For_Woocommerce()::save_data( 'feed_registered', false );
self::cancel_jobs();
}
/**
* Maybe show admin notice about account being disapproved.
*
* @since 1.4.13
*
* @param int $http_code Pinterest API HTTP response code.
* @param int $pinterest_api_code Pinterest API error code.
* @param string $pinterest_api_message Pinterest API error message.
*
* @return void
*/
public static function maybe_account_failure_notice( int $http_code, int $pinterest_api_code, string $pinterest_api_message ): void {
if ( 403 === $http_code ) {
AccountFailure::maybe_add_note( $pinterest_api_message );
}
}
}