File: /var/www/vhosts/uyarreklam.com.tr/httpdocs/SyncerHooks.php.tar
uyarreklam.com.tr/httpdocs/wp-content/plugins/google-listings-and-ads/src/Product/SyncerHooks.php 0000644 00000034471 15154737264 0032244 0 ustar 00 var/www/vhosts <?php
declare( strict_types=1 );
namespace Automattic\WooCommerce\GoogleListingsAndAds\Product;
use Automattic\WooCommerce\GoogleListingsAndAds\Google\BatchProductIDRequestEntry;
use Automattic\WooCommerce\GoogleListingsAndAds\API\WP\NotificationsService;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Registerable;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\DeleteProducts;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\JobRepository;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\Notifications\ProductNotificationJob;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\UpdateProducts;
use Automattic\WooCommerce\GoogleListingsAndAds\MerchantCenter\MerchantCenterService;
use Automattic\WooCommerce\GoogleListingsAndAds\PluginHelper;
use Automattic\WooCommerce\GoogleListingsAndAds\Proxies\WC;
use Automattic\WooCommerce\GoogleListingsAndAds\Value\NotificationStatus;
use WC_Product;
use WC_Product_Variable;
defined( 'ABSPATH' ) || exit;
/**
* Class SyncerHooks
*
* Hooks to various WooCommerce and WordPress actions to provide automatic product sync functionality.
*
* @package Automattic\WooCommerce\GoogleListingsAndAds\Product
*/
class SyncerHooks implements Service, Registerable {
use PluginHelper;
protected const SCHEDULE_TYPE_UPDATE = 'update';
protected const SCHEDULE_TYPE_DELETE = 'delete';
/**
* Array of strings mapped to product IDs indicating that they have been already
* scheduled for update or delete during current request. Used to avoid scheduling
* duplicate jobs.
*
* @var string[]
*/
protected $already_scheduled = [];
/**
* @var BatchProductIDRequestEntry[][]
*/
protected $delete_requests_map;
/**
* @var BatchProductHelper
*/
protected $batch_helper;
/**
* @var ProductHelper
*/
protected $product_helper;
/**
* @var JobRepository
*/
protected $job_repository;
/**
* @var MerchantCenterService
*/
protected $merchant_center;
/**
* @var NotificationsService
*/
protected $notifications_service;
/**
* @var WC
*/
protected $wc;
/**
* SyncerHooks constructor.
*
* @param BatchProductHelper $batch_helper
* @param ProductHelper $product_helper
* @param JobRepository $job_repository
* @param MerchantCenterService $merchant_center
* @param NotificationsService $notifications_service
* @param WC $wc
*/
public function __construct(
BatchProductHelper $batch_helper,
ProductHelper $product_helper,
JobRepository $job_repository,
MerchantCenterService $merchant_center,
NotificationsService $notifications_service,
WC $wc
) {
$this->batch_helper = $batch_helper;
$this->product_helper = $product_helper;
$this->job_repository = $job_repository;
$this->merchant_center = $merchant_center;
$this->notifications_service = $notifications_service;
$this->wc = $wc;
}
/**
* Register a service.
*/
public function register(): void {
// only register the hooks if Merchant Center is connected correctly.
if ( ! $this->merchant_center->is_ready_for_syncing() ) {
return;
}
// when a product is added / updated, schedule an "update" job.
add_action( 'woocommerce_new_product', [ $this, 'update_by_id' ], 90 );
add_action( 'woocommerce_new_product_variation', [ $this, 'update_by_id' ], 90 );
add_action( 'woocommerce_update_product', [ $this, 'update_by_object' ], 90, 2 );
add_action( 'woocommerce_update_product_variation', [ $this, 'update_by_object' ], 90, 2 );
// if we don't attach to these we miss product gallery updates.
add_action( 'woocommerce_process_product_meta', [ $this, 'update_by_id' ], 90 );
// when a product is trashed or removed, schedule a "delete" job.
add_action( 'wp_trash_post', [ $this, 'pre_delete' ], 90 );
add_action( 'before_delete_post', [ $this, 'pre_delete' ], 90 );
add_action( 'woocommerce_before_delete_product_variation', [ $this, 'pre_delete' ], 90 );
add_action( 'trashed_post', [ $this, 'delete' ], 90 );
add_action( 'deleted_post', [ $this, 'delete' ], 90 );
// when a product is restored from the trash, schedule an "update" job.
add_action( 'untrashed_post', [ $this, 'update_by_id' ], 90 );
// exclude the sync metadata when duplicating the product
add_filter(
'woocommerce_duplicate_product_exclude_meta',
[ $this, 'duplicate_product_exclude_meta' ],
90
);
}
/**
* Update a Product by WC_Product
*
* @param int $product_id
* @param WC_Product $product
*/
public function update_by_object( int $product_id, WC_Product $product ) {
$this->handle_update_products( [ $product ] );
}
/**
* Update a Product by the ID
*
* @param int $product_id
*/
public function update_by_id( int $product_id ) {
$product = $this->wc->maybe_get_product( $product_id );
$this->handle_update_products( [ $product ] );
}
/**
* Pre delete a Product by the ID
*
* @param int $product_id
*/
public function pre_delete( int $product_id ) {
$this->handle_pre_delete_product( $product_id );
}
/**
* Delete a Product by the ID
*
* @param int $product_id
*/
public function delete( int $product_id ) {
$this->handle_delete_product( $product_id );
}
/**
* Filters woocommerce_duplicate_product_exclude_meta adding some custom prefix
*
* @param array $exclude_meta
* @return array
*/
public function duplicate_product_exclude_meta( array $exclude_meta ): array {
return $this->get_duplicated_product_excluded_meta( $exclude_meta );
}
/**
* Handle updating of a product.
*
* @param WC_Product[] $products The products being saved.
* @param bool $notify If true. It will try to handle notifications.
*
* @return void
*/
protected function handle_update_products( array $products, $notify = true ) {
$products_to_update = [];
$products_to_delete = [];
foreach ( $products as $product ) {
if ( ! $product instanceof WC_Product ) {
continue;
}
$product_id = $product->get_id();
// Avoid to handle variations directly. We handle them from the parent.
if ( $this->notifications_service->is_ready() && $notify ) {
$this->handle_update_product_notification( $product );
}
// Bail if an event is already scheduled for this product in the current request
if ( $this->is_already_scheduled_to_update( $product_id ) ) {
continue;
}
// If it's a variable product we handle each variation separately
if ( $product instanceof WC_Product_Variable ) {
// This is only for MC Push mechanism. We don't handle notifications here.
$this->handle_update_products( $product->get_available_variations( 'objects' ), false );
continue;
}
// Schedule an update job if product sync is enabled.
if ( $this->product_helper->is_sync_ready( $product ) ) {
$this->product_helper->mark_as_pending( $product );
$products_to_update[] = $product->get_id();
$this->set_already_scheduled_to_update( $product_id );
} elseif ( $this->product_helper->is_product_synced( $product ) ) {
// Delete the product from Google Merchant Center if it's already synced BUT it is not sync ready after the edit.
$products_to_delete[] = $product;
$this->set_already_scheduled_to_delete( $product_id );
do_action(
'woocommerce_gla_debug_message',
sprintf( 'Deleting product (ID: %s) from Google Merchant Center because it is not ready to be synced.', $product->get_id() ),
__METHOD__
);
} else {
$this->product_helper->mark_as_unsynced( $product );
}
}
if ( ! empty( $products_to_update ) ) {
$this->job_repository->get( UpdateProducts::class )->schedule( [ $products_to_update ] );
}
if ( ! empty( $products_to_delete ) ) {
$request_entries = $this->batch_helper->generate_delete_request_entries( $products_to_delete );
$this->job_repository->get( DeleteProducts::class )->schedule( [ BatchProductIDRequestEntry::convert_to_id_map( $request_entries )->get() ] );
}
}
/**
* Schedules notifications for an updated product
*
* @param WC_Product $product
*/
protected function handle_update_product_notification( WC_Product $product ) {
if ( $this->product_helper->should_trigger_create_notification( $product ) ) {
$this->product_helper->set_notification_status( $product, NotificationStatus::NOTIFICATION_PENDING_CREATE );
$this->job_repository->get( ProductNotificationJob::class )->schedule(
[
'item_id' => $product->get_id(),
'topic' => NotificationsService::TOPIC_PRODUCT_CREATED,
]
);
} elseif ( $this->product_helper->should_trigger_update_notification( $product ) ) {
$this->product_helper->set_notification_status( $product, NotificationStatus::NOTIFICATION_PENDING_UPDATE );
$this->job_repository->get( ProductNotificationJob::class )->schedule(
[
'item_id' => $product->get_id(),
'topic' => NotificationsService::TOPIC_PRODUCT_UPDATED,
]
);
} elseif ( $this->product_helper->should_trigger_delete_notification( $product ) ) {
$this->schedule_delete_notification( $product );
// Schedule variation deletion when the parent is deleted.
if ( $product instanceof WC_Product_Variable ) {
foreach ( $product->get_available_variations( 'objects' ) as $variation ) {
$this->handle_update_product_notification( $variation );
}
}
}
}
/**
* Handle deleting of a product.
*
* @param int $product_id
*/
protected function handle_delete_product( int $product_id ) {
if ( isset( $this->delete_requests_map[ $product_id ] ) ) {
$product_id_map = BatchProductIDRequestEntry::convert_to_id_map( $this->delete_requests_map[ $product_id ] )->get();
if ( ! empty( $product_id_map ) && ! $this->is_already_scheduled_to_delete( $product_id ) ) {
$this->job_repository->get( DeleteProducts::class )->schedule( [ $product_id_map ] );
$this->set_already_scheduled_to_delete( $product_id );
}
}
}
/**
* Maybe send the product deletion notification
* and mark the product as un-synced after.
*
* @since 2.8.0
* @param int $product_id
*/
protected function maybe_send_delete_notification( int $product_id ) {
$product = $this->wc->maybe_get_product( $product_id );
if ( $product instanceof WC_Product && $this->product_helper->has_notified_creation( $product ) ) {
$result = $this->notifications_service->notify( NotificationsService::TOPIC_PRODUCT_DELETED, $product_id, [ 'offer_id' => $this->product_helper->get_offer_id( $product_id ) ] );
if ( $result ) {
$this->product_helper->set_notification_status( $product, NotificationStatus::NOTIFICATION_DELETED );
$this->product_helper->mark_as_unsynced( $product );
}
}
}
/**
* Schedules a job to send the product deletion notification
*
* @since 2.8.0
* @param WC_Product $product
*/
protected function schedule_delete_notification( $product ) {
$this->product_helper->set_notification_status( $product, NotificationStatus::NOTIFICATION_PENDING_DELETE );
$this->job_repository->get( ProductNotificationJob::class )->schedule(
[
'item_id' => $product->get_id(),
'topic' => NotificationsService::TOPIC_PRODUCT_DELETED,
]
);
}
/**
* Create request entries for the product (containing its Google ID) so that we can schedule a delete job when the
* product is actually trashed / deleted.
*
* @param int $product_id
*/
protected function handle_pre_delete_product( int $product_id ) {
if ( $this->notifications_service->is_ready() ) {
/**
* For deletions, we do send directly the notification instead of scheduling it.
* This is because we want to avoid that the product is not in the database anymore when the scheduled action runs.
*/
$this->maybe_send_delete_notification( $product_id );
}
$product = $this->wc->maybe_get_product( $product_id );
// each variation is passed to this method separately so we don't need to delete the variable product
if ( $product instanceof WC_Product && ! $product instanceof WC_Product_Variable && $this->product_helper->is_product_synced( $product ) ) {
$this->delete_requests_map[ $product_id ] = $this->batch_helper->generate_delete_request_entries( [ $product ] );
}
}
/**
* Return the list of metadata keys to be excluded when duplicating a product.
*
* @param array $exclude_meta The keys to exclude from the duplicate.
*
* @return array
*/
protected function get_duplicated_product_excluded_meta( array $exclude_meta ): array {
$exclude_meta[] = $this->prefix_meta_key( ProductMetaHandler::KEY_SYNCED_AT );
$exclude_meta[] = $this->prefix_meta_key( ProductMetaHandler::KEY_GOOGLE_IDS );
$exclude_meta[] = $this->prefix_meta_key( ProductMetaHandler::KEY_ERRORS );
$exclude_meta[] = $this->prefix_meta_key( ProductMetaHandler::KEY_FAILED_SYNC_ATTEMPTS );
$exclude_meta[] = $this->prefix_meta_key( ProductMetaHandler::KEY_SYNC_FAILED_AT );
$exclude_meta[] = $this->prefix_meta_key( ProductMetaHandler::KEY_SYNC_STATUS );
$exclude_meta[] = $this->prefix_meta_key( ProductMetaHandler::KEY_MC_STATUS );
return $exclude_meta;
}
/**
* @param int $product_id
* @param string $schedule_type
*
* @return bool
*/
protected function is_already_scheduled( int $product_id, string $schedule_type ): bool {
return isset( $this->already_scheduled[ $product_id ] ) && $this->already_scheduled[ $product_id ] === $schedule_type;
}
/**
* @param int $product_id
*
* @return bool
*/
protected function is_already_scheduled_to_update( int $product_id ): bool {
return $this->is_already_scheduled( $product_id, self::SCHEDULE_TYPE_UPDATE );
}
/**
* @param int $product_id
*
* @return bool
*/
protected function is_already_scheduled_to_delete( int $product_id ): bool {
return $this->is_already_scheduled( $product_id, self::SCHEDULE_TYPE_DELETE );
}
/**
* @param int $product_id
* @param string $schedule_type
*
* @return void
*/
protected function set_already_scheduled( int $product_id, string $schedule_type ): void {
$this->already_scheduled[ $product_id ] = $schedule_type;
}
/**
* @param int $product_id
*
* @return void
*/
protected function set_already_scheduled_to_update( int $product_id ): void {
$this->set_already_scheduled( $product_id, self::SCHEDULE_TYPE_UPDATE );
}
/**
* @param int $product_id
*
* @return void
*/
protected function set_already_scheduled_to_delete( int $product_id ): void {
$this->set_already_scheduled( $product_id, self::SCHEDULE_TYPE_DELETE );
}
}
uyarreklam.com.tr/httpdocs/wp-content/plugins/google-listings-and-ads/src/Coupon/SyncerHooks.php 0000644 00000032770 15154763510 0032060 0 ustar 00 var/www/vhosts <?php
declare(strict_types = 1);
namespace Automattic\WooCommerce\GoogleListingsAndAds\Coupon;
use Automattic\WooCommerce\GoogleListingsAndAds\Google\DeleteCouponEntry;
use Automattic\WooCommerce\GoogleListingsAndAds\API\WP\NotificationsService;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Registerable;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\JobRepository;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\DeleteCoupon;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\Notifications\CouponNotificationJob;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\UpdateCoupon;
use Automattic\WooCommerce\GoogleListingsAndAds\MerchantCenter\MerchantCenterService;
use Automattic\WooCommerce\GoogleListingsAndAds\PluginHelper;
use Automattic\WooCommerce\GoogleListingsAndAds\Proxies\WC;
use Automattic\WooCommerce\GoogleListingsAndAds\Proxies\WP;
use Automattic\WooCommerce\GoogleListingsAndAds\Value\NotificationStatus;
use WC_Coupon;
defined( 'ABSPATH' ) || exit();
/**
* Class SyncerHooks
*
* Hooks to various WooCommerce and WordPress actions to provide automatic coupon sync functionality.
*
* @package Automattic\WooCommerce\GoogleListingsAndAds\Coupon
*/
class SyncerHooks implements Service, Registerable {
use PluginHelper;
protected const SCHEDULE_TYPE_UPDATE = 'update';
protected const SCHEDULE_TYPE_DELETE = 'delete';
/**
* Array of strings mapped to coupon IDs indicating that they have been already
* scheduled for update or delete during current request.
* Used to avoid scheduling
* duplicate jobs.
*
* @var string[]
*/
protected $already_scheduled = [];
/**
*
* @var DeleteCouponEntry[][]
*/
protected $delete_requests_map;
/**
*
* @var CouponHelper
*/
protected $coupon_helper;
/**
* @var JobRepository
*/
protected $job_repository;
/**
*
* @var MerchantCenterService
*/
protected $merchant_center;
/**
* @var NotificationsService
*/
protected $notifications_service;
/**
*
* @var WC
*/
protected $wc;
/**
* WP Proxy
*
* @var WP
*/
protected WP $wp;
/**
* SyncerHooks constructor.
*
* @param CouponHelper $coupon_helper
* @param JobRepository $job_repository
* @param MerchantCenterService $merchant_center
* @param NotificationsService $notifications_service
* @param WC $wc
* @param WP $wp
*/
public function __construct(
CouponHelper $coupon_helper,
JobRepository $job_repository,
MerchantCenterService $merchant_center,
NotificationsService $notifications_service,
WC $wc,
WP $wp
) {
$this->coupon_helper = $coupon_helper;
$this->job_repository = $job_repository;
$this->merchant_center = $merchant_center;
$this->notifications_service = $notifications_service;
$this->wc = $wc;
$this->wp = $wp;
}
/**
* Register a service.
*/
public function register(): void {
// only register the hooks if Merchant Center is set up correctly.
if ( ! $this->merchant_center->is_ready_for_syncing() ) {
return;
}
// when a coupon is added / updated, schedule a update job.
add_action( 'woocommerce_new_coupon', [ $this, 'update_by_id' ], 90, 2 );
add_action( 'woocommerce_update_coupon', [ $this, 'update_by_id' ], 90, 2 );
add_action( 'woocommerce_gla_bulk_update_coupon', [ $this, 'update_by_id' ], 90 );
// when a coupon is trashed or removed, schedule a delete job.
add_action( 'wp_trash_post', [ $this, 'pre_delete' ], 90 );
add_action( 'before_delete_post', [ $this, 'pre_delete' ], 90 );
add_action( 'trashed_post', [ $this, 'delete_by_id' ], 90 );
add_action( 'deleted_post', [ $this, 'delete_by_id' ], 90 );
add_action( 'woocommerce_delete_coupon', [ $this, 'delete_by_id' ], 90, 2 );
add_action( 'woocommerce_trash_coupon', [ $this, 'delete_by_id' ], 90, 2 );
// when a coupon is restored from trash, schedule a update job.
add_action( 'untrashed_post', [ $this, 'update_by_id' ], 90 );
// Update coupons when object terms get updated.
add_action( 'set_object_terms', [ $this, 'maybe_update_by_id_when_terms_updated' ], 90, 6 );
}
/**
* Update a coupon by the ID
*
* @param int $coupon_id
*/
public function update_by_id( int $coupon_id ) {
$coupon = $this->wc->maybe_get_coupon( $coupon_id );
if ( $coupon instanceof WC_Coupon ) {
$this->handle_update_coupon( $coupon );
}
}
/**
* Update a coupon by the ID when the terms get updated.
*
* @param int $object_id The object ID.
* @param array $terms An array of object term IDs or slugs.
* @param array $tt_ids An array of term taxonomy IDs.
* @param string $taxonomy The taxonomy slug.
* @param bool $append Whether to append new terms to the old terms.
* @param array $old_tt_ids Old array of term taxonomy IDs.
*/
public function maybe_update_by_id_when_terms_updated( int $object_id, array $terms, array $tt_ids, string $taxonomy, bool $append, array $old_tt_ids ) {
$this->handle_update_coupon_when_product_brands_updated( $taxonomy, $tt_ids, $old_tt_ids );
}
/**
* Delete a coupon by the ID
*
* @param int $coupon_id
*/
public function delete_by_id( int $coupon_id ) {
$this->handle_delete_coupon( $coupon_id );
}
/**
* Pre Delete a coupon by the ID
*
* @param int $coupon_id
*/
public function pre_delete( int $coupon_id ) {
$this->handle_pre_delete_coupon( $coupon_id );
}
/**
* Handle updating of a coupon.
*
* @param WC_Coupon $coupon
* The coupon being saved.
*
* @return void
*/
protected function handle_update_coupon( WC_Coupon $coupon ) {
$coupon_id = $coupon->get_id();
if ( $this->notifications_service->is_ready() ) {
$this->handle_update_coupon_notification( $coupon );
}
// Schedule an update job if product sync is enabled.
if ( $this->coupon_helper->is_sync_ready( $coupon ) ) {
$this->coupon_helper->mark_as_pending( $coupon );
$this->job_repository->get( UpdateCoupon::class )->schedule(
[
[ $coupon_id ],
]
);
} elseif ( $this->coupon_helper->is_coupon_synced( $coupon ) ) {
// Delete the coupon from Google Merchant Center if it's already synced BUT it is not sync ready after the edit.
$coupon_to_delete = new DeleteCouponEntry(
$coupon_id,
$this->get_coupon_to_delete( $coupon ),
$this->coupon_helper->get_synced_google_ids( $coupon )
);
$this->job_repository->get( DeleteCoupon::class )->schedule(
[
$coupon_to_delete,
]
);
do_action(
'woocommerce_gla_debug_message',
sprintf(
'Deleting coupon (ID: %s) from Google Merchant Center because it is not ready to be synced.',
$coupon->get_id()
),
__METHOD__
);
} else {
$this->coupon_helper->mark_as_unsynced( $coupon );
}
}
/**
* Create request entries for the coupon (containing its Google ID),
* so we can schedule a delete job when it is actually trashed / deleted.
*
* @param int $coupon_id
*/
protected function handle_pre_delete_coupon( int $coupon_id ) {
$coupon = $this->wc->maybe_get_coupon( $coupon_id );
if ( $coupon instanceof WC_Coupon &&
$this->coupon_helper->is_coupon_synced( $coupon ) ) {
$this->delete_requests_map[ $coupon_id ] = new DeleteCouponEntry(
$coupon_id,
$this->get_coupon_to_delete( $coupon ),
$this->coupon_helper->get_synced_google_ids( $coupon )
);
}
}
/**
* @param WC_Coupon $coupon
*
* @return WCCouponAdapter
*/
protected function get_coupon_to_delete( WC_Coupon $coupon ): WCCouponAdapter {
$adapted_coupon_to_delete = new WCCouponAdapter(
[
'wc_coupon' => $coupon,
]
);
// Promotion stored in Google can only be soft-deleted to keep historical records.
// Instead of 'delete', we update the promotion with effective dates expired.
// Here we reset an expiring date based on WooCommerce coupon source.
$adapted_coupon_to_delete->disable_promotion( $coupon );
return $adapted_coupon_to_delete;
}
/**
* Handle deleting of a coupon.
*
* @param int $coupon_id
*/
protected function handle_delete_coupon( int $coupon_id ) {
if ( $this->notifications_service->is_ready() ) {
$this->maybe_send_delete_notification( $coupon_id );
}
if ( ! isset( $this->delete_requests_map[ $coupon_id ] ) ) {
return;
}
$coupon_to_delete = $this->delete_requests_map[ $coupon_id ];
if ( ! empty( $coupon_to_delete->get_synced_google_ids() ) &&
! $this->is_already_scheduled_to_delete( $coupon_id ) ) {
$this->job_repository->get( DeleteCoupon::class )->schedule(
[
$coupon_to_delete,
]
);
$this->set_already_scheduled_to_delete( $coupon_id );
}
}
/**
* Send the notification for coupon deletion
*
* @since 2.8.0
* @param int $coupon_id
*/
protected function maybe_send_delete_notification( int $coupon_id ): void {
$coupon = $this->wc->maybe_get_coupon( $coupon_id );
if ( $coupon instanceof WC_Coupon && $this->coupon_helper->should_trigger_delete_notification( $coupon ) ) {
$this->coupon_helper->set_notification_status( $coupon, NotificationStatus::NOTIFICATION_PENDING_DELETE );
$this->job_repository->get( CouponNotificationJob::class )->schedule(
[
'item_id' => $coupon->get_id(),
'topic' => NotificationsService::TOPIC_COUPON_DELETED,
]
);
}
}
/**
*
* @param int $coupon_id
* @param string $schedule_type
*
* @return bool
*/
protected function is_already_scheduled(
int $coupon_id,
string $schedule_type
): bool {
return isset( $this->already_scheduled[ $coupon_id ] ) &&
$this->already_scheduled[ $coupon_id ] === $schedule_type;
}
/**
*
* @param int $coupon_id
*
* @return bool
*/
protected function is_already_scheduled_to_update( int $coupon_id ): bool {
return $this->is_already_scheduled(
$coupon_id,
self::SCHEDULE_TYPE_UPDATE
);
}
/**
*
* @param int $coupon_id
*
* @return bool
*/
protected function is_already_scheduled_to_delete( int $coupon_id ): bool {
return $this->is_already_scheduled(
$coupon_id,
self::SCHEDULE_TYPE_DELETE
);
}
/**
*
* @param int $coupon_id
* @param string $schedule_type
*
* @return void
*/
protected function set_already_scheduled(
int $coupon_id,
string $schedule_type
): void {
$this->already_scheduled[ $coupon_id ] = $schedule_type;
}
/**
*
* @param int $coupon_id
*
* @return void
*/
protected function set_already_scheduled_to_update( int $coupon_id ): void {
$this->set_already_scheduled( $coupon_id, self::SCHEDULE_TYPE_UPDATE );
}
/**
*
* @param int $coupon_id
*
* @return void
*/
protected function set_already_scheduled_to_delete( int $coupon_id ): void {
$this->set_already_scheduled( $coupon_id, self::SCHEDULE_TYPE_DELETE );
}
/**
* Schedules notifications for an updated coupon
*
* @param WC_Coupon $coupon
*/
protected function handle_update_coupon_notification( WC_Coupon $coupon ) {
if ( $this->coupon_helper->should_trigger_create_notification( $coupon ) ) {
$this->coupon_helper->set_notification_status( $coupon, NotificationStatus::NOTIFICATION_PENDING_CREATE );
$this->job_repository->get( CouponNotificationJob::class )->schedule(
[
'item_id' => $coupon->get_id(),
'topic' => NotificationsService::TOPIC_COUPON_CREATED,
]
);
} elseif ( $this->coupon_helper->should_trigger_update_notification( $coupon ) ) {
$this->coupon_helper->set_notification_status( $coupon, NotificationStatus::NOTIFICATION_PENDING_UPDATE );
$this->job_repository->get( CouponNotificationJob::class )->schedule(
[
'item_id' => $coupon->get_id(),
'topic' => NotificationsService::TOPIC_COUPON_UPDATED,
]
);
} elseif ( $this->coupon_helper->should_trigger_delete_notification( $coupon ) ) {
$this->coupon_helper->set_notification_status( $coupon, NotificationStatus::NOTIFICATION_PENDING_DELETE );
$this->job_repository->get( CouponNotificationJob::class )->schedule(
[
'item_id' => $coupon->get_id(),
'topic' => NotificationsService::TOPIC_COUPON_DELETED,
]
);
}
}
/**
* If product to brands relationship is updated, update the coupons that are related to the brands.
*
* @param string $taxonomy The taxonomy slug.
* @param array $tt_ids An array of term taxonomy IDs.
* @param array $old_tt_ids Old array of term taxonomy IDs.
*/
protected function handle_update_coupon_when_product_brands_updated( string $taxonomy, array $tt_ids, array $old_tt_ids ) {
if ( 'product_brand' !== $taxonomy ) {
return;
}
// Convert term taxonomy IDs to integers.
$tt_ids = array_map( 'intval', $tt_ids );
$old_tt_ids = array_map( 'intval', $old_tt_ids );
// Find the difference between the new and old term taxonomy IDs.
$diff1 = array_diff( $tt_ids, $old_tt_ids );
$diff2 = array_diff( $old_tt_ids, $tt_ids );
$diff = array_merge( $diff1, $diff2 );
if ( empty( $diff ) ) {
return;
}
// Serialize the diff to use in the meta query.
// This is needed because the meta value is serialized.
$serialized_diff = maybe_serialize( $diff );
$args = [
'post_type' => 'shop_coupon',
'meta_query' => [
'relation' => 'OR',
[
'key' => 'product_brands',
'value' => $serialized_diff,
'compare' => 'LIKE',
],
[
'key' => 'exclude_product_brands',
'value' => $serialized_diff,
'compare' => 'LIKE',
],
],
];
// Get coupon posts based on the above query args.
$posts = $this->wp->get_posts( $args );
if ( empty( $posts ) ) {
return;
}
foreach ( $posts as $post ) {
$this->update_by_id( $post->ID );
}
}
}
uyarreklam.com.tr/httpdocs/wp-content/plugins/google-listings-and-ads/src/Settings/SyncerHooks.php 0000644 00000005335 15155010704 0032401 0 ustar 00 var/www/vhosts <?php
declare( strict_types=1 );
namespace Automattic\WooCommerce\GoogleListingsAndAds\Settings;
use Automattic\WooCommerce\GoogleListingsAndAds\API\WP\NotificationsService;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Registerable;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\JobRepository;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\Notifications\SettingsNotificationJob;
defined( 'ABSPATH' ) || exit;
/**
* Class SyncerHooks
*
* Hooks to various WooCommerce and WordPress actions to automatically sync WooCommerce General Settings.
*
* @package Automattic\WooCommerce\GoogleListingsAndAds\Settings
*
* @since 2.8.0
*/
class SyncerHooks implements Service, Registerable {
/**
* @var NotificationsService $notifications_service
*/
protected $notifications_service;
/**
* @var JobRepository
*/
protected $job_repository;
/**
* WooCommerce General Settings IDs
* Copied from https://github.com/woocommerce/woocommerce/blob/af03815134385c72feb7a70abc597eca57442820/plugins/woocommerce/includes/admin/settings/class-wc-settings-general.php#L34
*/
protected const ALLOWED_SETTINGS = [
'store_address',
'woocommerce_store_address',
'woocommerce_store_address_2',
'woocommerce_store_city',
'woocommerce_default_country',
'woocommerce_store_postcode',
'store_address',
'general_options',
'woocommerce_allowed_countries',
'woocommerce_all_except_countries',
'woocommerce_specific_allowed_countries',
'woocommerce_ship_to_countries',
'woocommerce_specific_ship_to_countries',
'woocommerce_default_customer_address',
'woocommerce_calc_taxes',
'woocommerce_enable_coupons',
'woocommerce_calc_discounts_sequentially',
'general_options',
'pricing_options',
'woocommerce_currency',
'woocommerce_currency_pos',
'woocommerce_price_thousand_sep',
'woocommerce_price_decimal_sep',
'woocommerce_price_num_decimals',
'pricing_options',
];
/**
* SyncerHooks constructor.
*
* @param JobRepository $job_repository
* @param NotificationsService $notifications_service
*/
public function __construct( JobRepository $job_repository, NotificationsService $notifications_service ) {
$this->job_repository = $job_repository;
$this->notifications_service = $notifications_service;
}
/**
* Register the service.
*/
public function register(): void {
if ( ! $this->notifications_service->is_ready( false ) ) {
return;
}
$update_rest = function ( $option ) {
if ( in_array( $option, self::ALLOWED_SETTINGS, true ) ) {
$this->job_repository->get( SettingsNotificationJob::class )->schedule();
}
};
add_action( 'update_option', $update_rest, 90, 1 );
}
}
uyarreklam.com.tr/httpdocs/wp-content/plugins/google-listings-and-ads/src/Shipping/SyncerHooks.php 0000644 00000012174 15155041726 0032371 0 ustar 00 var/www/vhosts <?php
declare( strict_types=1 );
namespace Automattic\WooCommerce\GoogleListingsAndAds\Shipping;
use Automattic\WooCommerce\GoogleListingsAndAds\API\Google\Settings as GoogleSettings;
use Automattic\WooCommerce\GoogleListingsAndAds\API\WP\NotificationsService;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Registerable;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\JobRepository;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\Notifications\ShippingNotificationJob;
use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\UpdateShippingSettings;
use Automattic\WooCommerce\GoogleListingsAndAds\MerchantCenter\MerchantCenterService;
defined( 'ABSPATH' ) || exit;
/**
* Class SyncerHooks
*
* Hooks to various WooCommerce and WordPress actions to automatically sync shipping settings.
*
* @package Automattic\WooCommerce\GoogleListingsAndAds\Shipping
*
* @since 2.1.0
*/
class SyncerHooks implements Service, Registerable {
/**
* This property is used to avoid scheduling duplicate jobs in the same request.
*
* @var bool
*/
protected $already_scheduled = false;
/**
* @var GoogleSettings
*/
protected $google_settings;
/**
* @var MerchantCenterService
*/
protected $merchant_center;
/**
* @var JobRepository
*/
protected $job_repository;
/**
* @var NotificationsService $notifications_service
*/
protected $notifications_service;
/**
* SyncerHooks constructor.
*
* @param MerchantCenterService $merchant_center
* @param GoogleSettings $google_settings
* @param JobRepository $job_repository
* @param NotificationsService $notifications_service
*/
public function __construct( MerchantCenterService $merchant_center, GoogleSettings $google_settings, JobRepository $job_repository, NotificationsService $notifications_service ) {
$this->google_settings = $google_settings;
$this->merchant_center = $merchant_center;
$this->job_repository = $job_repository;
$this->notifications_service = $notifications_service;
}
/**
* Register the service.
*/
public function register(): void {
// only register the hooks if Merchant Center account is connected and the user has chosen for the shipping rates to be synced from WooCommerce settings.
if ( ! $this->merchant_center->is_connected() || ! $this->google_settings->should_get_shipping_rates_from_woocommerce() ) {
return;
}
$update_settings = function () {
$this->handle_update_shipping_settings();
};
// After a shipping zone object is saved to database.
add_action( 'woocommerce_after_shipping_zone_object_save', $update_settings, 90 );
// After a shipping zone is deleted.
add_action( 'woocommerce_delete_shipping_zone', $update_settings, 90 );
// After a shipping method is added to or deleted from a shipping zone.
add_action( 'woocommerce_shipping_zone_method_added', $update_settings, 90 );
add_action( 'woocommerce_shipping_zone_method_deleted', $update_settings, 90 );
// After a shipping method is enabled or disabled.
add_action( 'woocommerce_shipping_zone_method_status_toggled', $update_settings, 90 );
// After a shipping class is updated/deleted.
add_action( 'woocommerce_shipping_classes_save_class', $update_settings, 90 );
add_action( 'saved_product_shipping_class', $update_settings, 90 );
add_action( 'delete_product_shipping_class', $update_settings, 90 );
// After free_shipping and flat_rate method options are updated.
add_action( 'woocommerce_update_options_shipping_free_shipping', $update_settings, 90 );
add_action( 'woocommerce_update_options_shipping_flat_rate', $update_settings, 90 );
// The shipping options can also be updated using other methods (e.g. by calling WC_Shipping_Method::process_admin_options).
// Those methods may not fire any hooks, so we need to watch the base WordPress hooks for when those options are updated.
$on_option_change = function ( $option ) {
/**
* This Regex checks for the shipping options key generated by the `WC_Shipping_Method::get_instance_option_key` method.
* We check for the shipping method IDs supported by GLA (flat_rate or free_shipping), and an integer instance_id.
*
* @see \WC_Shipping_Method::get_instance_option_key for more information about this key.
*/
if ( preg_match( '/^woocommerce_(flat_rate|free_shipping)_\d+_settings$/', $option ) ) {
$this->handle_update_shipping_settings();
}
};
add_action(
'updated_option',
$on_option_change,
90
);
add_action(
'added_option',
$on_option_change,
90
);
}
/**
* Handle updating of Merchant Center shipping settings.
*
* @return void
*/
protected function handle_update_shipping_settings() {
// Bail if an event is already scheduled in the current request
if ( $this->already_scheduled ) {
return;
}
if ( $this->notifications_service->is_ready() ) {
$this->job_repository->get( ShippingNotificationJob::class )->schedule( [ 'topic' => NotificationsService::TOPIC_SHIPPING_UPDATED ] );
}
$this->job_repository->get( UpdateShippingSettings::class )->schedule();
$this->already_scheduled = true;
}
}