Skip to content

Commit

Permalink
Merge pull request #1014 from chennyxie/feature/coupon-syncer
Browse files Browse the repository at this point in the history
Feature/coupon syncer
  • Loading branch information
layoutd committed Nov 8, 2021
2 parents f5f4217 + 2a4def9 commit 23c1d29
Show file tree
Hide file tree
Showing 31 changed files with 3,729 additions and 44 deletions.
3 changes: 2 additions & 1 deletion composer.json
Expand Up @@ -10,6 +10,7 @@
"automattic/jetpack-config": "^1.4",
"automattic/jetpack-connection": "^1.20",
"google/apiclient": "^2.10",
"google/apiclient-services": "~0.216",
"googleads/google-ads-php": "^10.0",
"league/container": "^3.3",
"league/iso3166": "^3.0",
Expand Down Expand Up @@ -81,4 +82,4 @@
"SiteVerification"
]
}
}
}
38 changes: 20 additions & 18 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

201 changes: 201 additions & 0 deletions src/Admin/MetaBox/CouponChannelVisibilityMetaBox.php
@@ -0,0 +1,201 @@
<?php
declare( strict_types=1 );

namespace Automattic\WooCommerce\GoogleListingsAndAds\Admin\MetaBox;

use Automattic\WooCommerce\GoogleListingsAndAds\Admin\Admin;
use Automattic\WooCommerce\GoogleListingsAndAds\Exception\InvalidValue;
use Automattic\WooCommerce\GoogleListingsAndAds\Coupon\CouponHelper;
use Automattic\WooCommerce\GoogleListingsAndAds\Coupon\CouponMetaHandler;
use Automattic\WooCommerce\GoogleListingsAndAds\Coupon\CouponSyncer;
use Automattic\WooCommerce\GoogleListingsAndAds\MerchantCenter\MerchantCenterService;
use Automattic\WooCommerce\GoogleListingsAndAds\Value\ChannelVisibility;
use WC_Coupon;
use WP_Post;

defined( 'ABSPATH' ) || exit;

/**
* Class CouponChannelVisibilityMetaBox
*
* @package Automattic\WooCommerce\GoogleListingsAndAds\Admin\MetaBox
*/
class CouponChannelVisibilityMetaBox extends SubmittableMetaBox {

/**
* @var CouponMetaHandler
*/
protected $meta_handler;

/**
* @var CouponHelper
*/
protected $coupon_helper;

/**
* @var MerchantCenterService
*/
protected $merchant_center;

/**
* CouponChannelVisibilityMetaBox constructor.
*
* @param Admin $admin
* @param CouponMetaHandler $meta_handler
* @param CouponHelper $coupon_helper
* @param MerchantCenterService $merchant_center
*/
public function __construct( Admin $admin, CouponMetaHandler $meta_handler, CouponHelper $coupon_helper, MerchantCenterService $merchant_center ) {
$this->meta_handler = $meta_handler;
$this->coupon_helper = $coupon_helper;
$this->merchant_center = $merchant_center;
parent::__construct( $admin );
}

/**
* Meta box ID (used in the 'id' attribute for the meta box).
*
* @return string
*/
public function get_id(): string {
return 'coupon_channel_visibility';
}

/**
* Title of the meta box.
*
* @return string
*/
public function get_title(): string {
return __( 'Channel visibility', 'google-listings-and-ads' );
}

/**
* The screen on which to show the box (such as a post type, 'link', or 'comment').
*
* Default is the current screen.
*
* @return string
*/
public function get_screen(): string {
return self::SCREEN_COUPON;
}

/**
* The context within the screen where the box should display. Available contexts vary from screen to
* screen. Post edit screen contexts include 'normal', 'side', and 'advanced'. Comments screen contexts
* include 'normal' and 'side'. Menus meta boxes (accordion sections) all use the 'side' context.
*
* Global default is 'advanced'.
*
* @return string
*/
public function get_context(): string {
return self::CONTEXT_SIDE;
}

/**
* Returns an array of CSS classes to apply to the box.
*
* @return array
*/
public function get_classes(): array {
$shown_types = array_map(
function ( string $coupon_type ) {
return "show_if_${coupon_type}";
},
CouponSyncer::get_supported_coupon_types()
);

$hidden_types = array_map(
function ( string $coupon_type ) {
return "hide_if_${coupon_type}";
},
CouponSyncer::get_hidden_coupon_types()
);

return array_merge( $shown_types, $hidden_types );
}

/**
* Returns an array of variables to be used in the view.
*
* @param WP_Post $post The WordPress post object the box is loaded for.
* @param array $args Array of data passed to the callback. Defined by `get_callback_args`.
*
* @return array
*/
protected function get_view_context( WP_Post $post, array $args ): array {
$coupon_id = absint( $post->ID );
$coupon = $this->coupon_helper->get_wc_coupon( $coupon_id );
$target_country = $this->merchant_center->get_main_target_country();

return [
'field_id' => $this->get_visibility_field_id(),
'coupon_id' => $coupon_id,
'coupon' => $coupon,
'channel_visibility' => $this->coupon_helper->get_channel_visibility( $coupon ),
'sync_status' => $this->meta_handler->get_sync_status( $coupon ),
'issues' => $this->coupon_helper->get_validation_errors( $coupon ),
'is_setup_complete' => $this->merchant_center->is_setup_complete(),
'is_channel_supported' => $this->merchant_center->is_promotion_supported_country( $target_country ),
'get_started_url' => $this->get_start_url(),
];
}

/**
* Register a service.
*/
public function register(): void {
add_action( 'woocommerce_new_coupon', [ $this, 'handle_submission' ], 10, 2 );
add_action( 'woocommerce_update_coupon', [ $this, 'handle_submission' ], 10, 2 );
}

/**
* @param int $coupon_id
* @param WC_Coupon $coupon
*/
public function handle_submission( int $coupon_id, WC_Coupon $coupon ) {
/**
* Array of `true` values for each coupon IDs already handled by this method. Used to prevent double submission.
*
* @var bool[] $already_updated
*/
static $already_updated = [];

$field_id = $this->get_visibility_field_id();
// phpcs:disable WordPress.Security.NonceVerification
// nonce is verified by self::verify_nonce
if ( ! $this->verify_nonce() || ! isset( $_POST[ $field_id ] ) || isset( $already_updated[ $coupon_id ] ) ) {
return;
}

// Only update the value for supported coupon types
if ( ! CouponSyncer::is_coupon_supported( $coupon ) ) {
return;
}

try {
$visibility = empty( $_POST[ $field_id ] ) ?
ChannelVisibility::cast( ChannelVisibility::DONT_SYNC_AND_SHOW ) :
ChannelVisibility::cast( sanitize_key( $_POST[ $field_id ] ) );
// phpcs:enable WordPress.Security.NonceVerification

$this->meta_handler->update_visibility( $coupon, $visibility );

$already_updated[ $coupon_id ] = true;
} catch ( InvalidValue $exception ) {
// silently log the exception and do not set the coupon's visibility if an invalid visibility value is sent.
do_action( 'woocommerce_gla_exception', $exception, __METHOD__ );
}
}

/**
* @return string
*
* @since 1.1.0
*/
protected function get_visibility_field_id(): string {
return $this->prefix_field_id( 'visibility' );
}
}
1 change: 1 addition & 0 deletions src/Admin/MetaBox/MetaBoxInterface.php
Expand Up @@ -11,6 +11,7 @@

interface MetaBoxInterface extends Service, Conditional, Renderable {
public const SCREEN_PRODUCT = 'product';
public const SCREEN_COUPON = 'shop_coupon';

public const CONTEXT_NORMAL = 'normal';
public const CONTEXT_SIDE = 'side';
Expand Down

0 comments on commit 23c1d29

Please sign in to comment.