Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,271 @@
<?php
final class BWFAN_WCS_Add_Coupon extends BWFAN_Action {
private static $ins = null;
protected function __construct() {
$this->action_name = __( 'Add Coupon', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'Assign a coupon to discount future payments for a subscriptions', 'wp-marketing-automations-pro' );
$this->required_fields = array( 'subscription_id', 'subscription_coupon_id' );
$this->action_priority = 1;
// Excluded events which this action does not support.
$this->included_events = array(
'wcs_before_end',
'wcs_note_added',
'wcs_before_renewal',
'wcs_card_expiry',
'wcs_created',
'wcs_renewal_payment_complete',
'wcs_renewal_payment_failed',
'wcs_status_changed',
'wcs_trial_end',
'wc_new_order',
'wc_order_note_added',
'wc_order_status_change',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced',
);
$this->support_v2 = true;
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
/**
* Localize data for html fields for the current action.
*/
public function admin_enqueue_assets() {
if ( BWFAN_Common::is_load_admin_assets( 'automation' ) ) {
$data = $this->get_view_data();
BWFAN_Core()->admin->set_actions_js_data( $this->get_class_slug(), 'subscription_add_coupon', $data );
}
}
public function get_view_data( $search = '' ) {
$get_coupon_list = BWFAN_Common::get_coupon( $search );
if ( empty( $get_coupon_list['results'] ) ) {
return array();
}
$coupon_list = array();
foreach ( $get_coupon_list['results'] as $index => $code ) {
$discount_type = get_post_meta( $code['id'], 'discount_type', true );
if ( in_array( $discount_type, array( 'recurring_fee', 'recurring_percent' ), true ) ) {
$coupon_list[ $code['id'] ] = $code['text'];
}
}
return $coupon_list;
}
/**
* Show the html fields for the current action.
*/
public function get_view() {
?>
<script type="text/html" id="tmpl-action-<?php echo esc_html__( $this->get_slug() ); ?>">
<#
selected_subscription_add_coupon = (_.has(data.actionSavedData, 'data') && _.has(data.actionSavedData.data, 'selected_subscription_add_coupon')) ? data.actionSavedData.data.selected_subscription_add_coupon : '';
#>
<div class="bwfan-input-form clearfix">
<label for="" class="bwfan-label-title"><?php echo esc_html__( 'Coupon', 'wp-marketing-automations-pro' ); ?></label>
<select required id="" class="bwfan-input-wrapper" name="bwfan[{{data.action_id}}][data][selected_subscription_add_coupon]">
<option value=""><?php echo esc_html__( 'Choose Coupon', 'wp-marketing-automations-pro' ); ?></option>
<#
if(_.has(data.actionFieldsOptions, 'subscription_add_coupon') && _.isObject(data.actionFieldsOptions.subscription_add_coupon) ) {
_.each( data.actionFieldsOptions.subscription_add_coupon, function( value, key ){
selected = (key == selected_subscription_add_coupon) ? 'selected' : '';
#>
<option value="{{key}}" {{selected}}>{{value}}</option>
<# })
}
#>
</select>
</div>
</script>
<?php
}
/**
* Make all the data which is required by the current action.
* This data will be used while executing the task of this action.
*
* @param $integration_object
* @param $task_meta
*
* @return array|void
*/
public function make_data( $integration_object, $task_meta ) {
$data_to_set = array();
$data_to_set['subscription_coupon_id'] = $task_meta['data']['selected_subscription_add_coupon'];
$data_to_set['subscription_id'] = $task_meta['global']['wc_subscription_id'];
return $data_to_set;
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = array();
$data_to_set['subscription_coupon_id'] = isset( $step_data['selected_subscription_add_coupon'][0]['id'] ) ? $step_data['selected_subscription_add_coupon'][0]['id'] : 0;
$data_to_set['subscription_id'] = isset( $automation_data['global']['wc_subscription_id'] ) ? $automation_data['global']['wc_subscription_id'] : 0;
$data_to_set['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : 0;
return $data_to_set;
}
/**
* Execute the current action.
* Return 3 for successful execution , 4 for permanent failure.
*
* @param $action_data
*
* @return array
*/
public function execute_action( $action_data ) {
$this->set_data( $action_data['processed_data'] );
$result = $this->process();
if ( true === $result ) {
return array(
'status' => 3,
);
}
return array(
'status' => $result['status'],
'message' => $result['msg'],
);
}
/**
* Process and do the actual processing for the current action.
* This function is present in every action class.
*/
public function process() {
$is_required_fields_present = $this->check_fields( $this->data, $this->required_fields );
if ( false === $is_required_fields_present ) {
return $this->show_fields_error();
}
return $this->add_coupon();
}
/**
* add coupon to subscription.
*
* subscription_id, subscription_coupon_id are required.
*
* @return array|bool
*/
public function add_coupon() {
$result = [];
$subscription = wcs_get_subscription( $this->data['subscription_id'] );
$automation_data = BWFAN_Core()->automations->get_automation_data_meta( $this->automation_id );
$automation_title = isset( $automation_data['title'] ) ? $automation_data['title'] : '';
$coupon = new WC_Coupon( $this->data['subscription_coupon_id'] );
if ( ! $subscription || ! $coupon ) {
$result['msg'] = __( 'Subscription or Coupon does not exists', 'wp-marketing-automations-pro' );
$result['status'] = 4;
return $result;
}
$response = $subscription->apply_coupon( $coupon );
if ( is_wp_error( $response ) ) {
$result['msg'] = $response->get_error_message();
$result['status'] = 4;
return $result;
}
$subscription->add_order_note( sprintf( __( '%1$s automation run: added coupon %2$s to subscription. (Automation ID: %3$d)', 'wp-marketing-automations-pro' ), $automation_title, $coupon->get_code(), $this->automation_id ), false, false );
return true;
}
public function process_v2() {
$subscription = wcs_get_subscription( $this->data['subscription_id'] );
$automation_data = BWFAN_Core()->automations->get_automation_data_meta( $this->automation_id );
$automation_title = isset( $automation_data['title'] ) ? $automation_data['title'] : '';
$coupon = new WC_Coupon( $this->data['subscription_coupon_id'] );
$order_id = $this->data['order_id'];
/** then will get it using the order id */
if ( ! $subscription ) {
$subscriptions = BWFAN_PRO_Common::order_contains_subscriptions( $order_id );
/** if still no subscriptions exists with order then skipped */
if ( false === $subscriptions ) {
return $this->skipped_response( __( 'No subscription associated with order.', 'wp-marketing-automations-pro' ) );
}
$subscriptions = array_values( $subscriptions );
$subscription = $subscriptions[0];
}
if ( ! $subscription instanceof WC_Subscription || ! $coupon ) {
return $this->skipped_response( __( 'Subscription or Coupon does not exists.', 'wp-marketing-automations-pro' ) );
}
$response = $subscription->apply_coupon( $coupon );
if ( is_wp_error( $response ) ) {
return $this->error_response( $response->get_error_message() );
}
$subscription->add_order_note( sprintf( __( '%1$s automation run: added coupon %2$s to subscription. (Automation ID: %3$d)', 'wp-marketing-automations-pro' ), $automation_title, $coupon->get_code(), $this->automation_id ), false, false );
return $this->success_message( __( 'Coupon added.', 'wp-marketing-automations-pro' ) );
}
public function get_fields_schema() {
return [
[
"id" => 'selected_subscription_add_coupon',
"label" => __( 'Coupon', 'wp-marketing-automations-pro' ),
"type" => 'custom_search',
'autocompleterOption' => [
'path' => 'wcs_coupons',
'slug' => 'wcs_coupons',
'labelText' => 'Coupon'
],
"allowFreeTextSearch" => false,
"required" => false,
"errorMsg" => "",
"multiple" => false
],
];
}
public function get_desc_text( $data ) {
$data = json_decode( wp_json_encode( $data ), true );
if ( ! isset( $data['selected_subscription_add_coupon'] ) || empty( $data['selected_subscription_add_coupon'] ) ) {
return '';
}
$coupons = [];
foreach ( $data['selected_subscription_add_coupon'] as $coupon ) {
if ( ! isset( $coupon['name'] ) || empty( $coupon['name'] ) ) {
continue;
}
$coupons[] = $coupon['name'];
}
return $coupons;
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WCS_Add_Coupon';

View File

@@ -0,0 +1,154 @@
<?php
final class BWFAN_WCS_Add_Custom_Field extends BWFAN_Action {
private static $ins = null;
private function __construct() {
$this->action_name = __( 'Add Custom Fields', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This action adds/ updates the custom fields', 'wp-marketing-automations-pro' );
$this->action_priority = 20;
$this->support_v2 = true;
$this->support_v1 = false;
$this->included_events = array(
'wcs_before_end',
'wcs_before_renewal',
'wcs_card_expiry',
'wcs_created',
'wcs_renewal_payment_complete',
'wcs_renewal_payment_failed',
'wcs_status_changed',
'wcs_trial_end',
'wc_new_order',
'wc_order_note_added',
'wc_order_status_change',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced'
);
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = array();
$custom_fields = array();
$custom_fields_value = array();
$data_to_set['subscription_id'] = isset( $automation_data['global']['wc_subscription_id'] ) ? $automation_data['global']['wc_subscription_id'] : 0;
$data_to_set['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : 0;
$custom_field_array = isset( $step_data['custom_fields'] ) ? $step_data['custom_fields'] : [];
if ( ! empty( $custom_field_array ) && is_array( $custom_field_array ) ) {
$custom_fields = array_column( $custom_field_array, 'field' );
$custom_fields_value = array_column( $custom_field_array, 'field_value' );
}
$meta_fields = array();
if ( is_array( $custom_fields ) && ! empty( $custom_fields ) ) {
foreach ( $custom_fields as $key => $field_alias ) {
if ( empty( $field_alias ) ) {
continue;
}
$meta_fields[ $field_alias ] = BWFAN_Common::decode_merge_tags( $custom_fields_value[ $key ] );
}
}
$data_to_set['subscription_metas'] = $meta_fields;
return $data_to_set;
}
public function process_v2() {
$subscription = wcs_get_subscription( intval( $this->data['subscription_id'] ) );
$order_id = intval( $this->data['order_id'] );
/** if not subscription then get it using the order id */
if ( ! $subscription ) {
$subscriptions = BWFAN_PRO_Common::order_contains_subscriptions( $order_id );
/** if still no subscriptions exists with order then skipped */
if ( false === $subscriptions ) {
return $this->skipped_response( __( 'No subscription associated with order.', 'wp-marketing-automations-pro' ) );
}
$subscriptions = array_values( $subscriptions );
$subscription = $subscriptions[0];
}
if ( ! $subscription ) {
return $this->skipped_response( __( 'Subscription does not exists', 'wp-marketing-automations-pro' ) );
}
if ( empty( $this->data['subscription_metas'] ) ) {
return $this->skipped_response( __( 'Custom field(s) are required.', 'wp-marketing-automations-pro' ) );
}
foreach ( $this->data['subscription_metas'] as $meta_key => $meta_value ) {
$subscription->update_meta_data( $meta_key, $meta_value );
}
$subscription->save();
return $this->success_message( __( 'Custom Field added/updated.', 'wp-marketing-automations-pro' ) );
}
/**
* v2 Method: Get field Schema
*
* @return array[]
*/
public function get_fields_schema() {
return [
[
'id' => 'custom_fields',
'type' => 'repeater',
'label' => __( 'Enter Custom Field Key/ values', 'wp-marketing-automations-pro' ),
"fields" => [
[
'id' => 'field',
'type' => 'text',
'label' => "",
'tip' => "",
"description" => "",
"required" => false,
],
[
"id" => 'field_value',
"label" => "",
"type" => 'text',
"class" => 'bwfan-input-wrapper',
"description" => "",
"required" => false,
]
],
'tip' => "",
"description" => ""
]
];
}
public function get_desc_text( $data ) {
$data = json_decode( wp_json_encode( $data ), true );
if ( ! isset( $data['custom_fields'] ) || empty( $data['custom_fields'] ) ) {
return '';
}
$count = count( $data['custom_fields'] );
return ( $count > 1 ) ? $count . ' fields' : $count . ' field';
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WCS_Add_Custom_Field';

View File

@@ -0,0 +1,267 @@
<?php
final class BWFAN_WCS_Add_Note extends BWFAN_Action {
private static $ins = null;
private $wcs_note_types = [];
protected function __construct() {
$this->action_name = __( 'Add Note', 'wp-marketing-automations-pro' );
$this->action_desc = __( "Added note to the subscription", 'wp-marketing-automations-pro' );
$this->required_fields = array( 'subscription_id', 'note_type', 'notes' );
$this->action_priority = 1;
$this->wcs_note_types = [
'private' => __( 'Private', 'wp-marketing-automations-pro' ),
'public' => __( 'Customer', 'wp-marketing-automations-pro' ),
];
// Excluded events which this action does not support.
$this->included_events = array(
'wcs_before_end',
'wcs_note_added',
'wcs_before_renewal',
'wcs_card_expiry',
'wcs_created',
'wcs_renewal_payment_complete',
'wcs_renewal_payment_failed',
'wcs_status_changed',
'wcs_trial_end',
'wc_new_order',
'wc_order_note_added',
'wc_order_status_change',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced'
);
$this->support_v2 = true;
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
/**
* Localize data for html fields for the current action.
*/
public function admin_enqueue_assets() {
if ( BWFAN_Common::is_load_admin_assets( 'automation' ) ) {
BWFAN_Core()->admin->set_actions_js_data( $this->get_class_slug(), 'wcs_note_types', $this->wcs_note_types );
}
}
/**
* Show the html fields for the current action.
*/
public function get_view() {
?>
<script type="text/html" id="tmpl-action-<?php echo esc_html__( $this->get_slug() ); ?>">
<#
wcs_note_type = (_.has(data.actionSavedData, 'data') && _.has(data.actionSavedData.data, 'wcs_note_type')) ? data.actionSavedData.data.wcs_note_type : '';
wcs_notes = (_.has(data.actionSavedData, 'data') && _.has(data.actionSavedData.data, 'wcs_notes')) ? data.actionSavedData.data.wcs_notes : '';
#>
<div class="bwfan-input-form clearfix">
<label for="" class="bwfan-label-title"><?php echo esc_html__( 'Note Type', 'wp-marketing-automations-pro' ); ?></label>
<select required id="" class="bwfan-input-wrapper" name="bwfan[{{data.action_id}}][data][wcs_note_type]">
<option value=""><?php echo esc_html__( 'Select', 'wp-marketing-automations-pro' ); ?></option>
<#
if(_.has(data.actionFieldsOptions, 'wcs_note_types') && _.isObject(data.actionFieldsOptions.wcs_note_types) ) {
_.each( data.actionFieldsOptions.wcs_note_types, function( value, key ){
selected = (key == wcs_note_type) ? 'selected' : '';
#>
<option value="{{key}}" {{selected}}>{{value}}</option>
<# })
}
#>
</select>
</div>
<div class="bwfan-input-form clearfix">
<label for="" class="bwfan-label-title"><?php echo esc_html__( 'Notes', 'wp-marketing-automations-pro' ); ?></label>
<textarea required="" class="bwfan-input-wrapper" rows="3" placeholder="Subscription Notes" name="bwfan[{{data.action_id}}][data][wcs_notes]" spellcheck="false">{{wcs_notes}}</textarea>
</div>
</script>
<?php
}
/**
* Make all the data which is required by the current action.
* This data will be used while executing the task of this action.
*
* @param $integration_object
* @param $task_meta
*
* @return array|void
*/
public function make_data( $integration_object, $task_meta ) {
$data_to_set = array();
$data_to_set['note_type'] = $task_meta['data']['wcs_note_type'];
$data_to_set['subscription_id'] = $task_meta['global']['wc_subscription_id'];
$data_to_set['notes'] = $task_meta['data']['wcs_notes'];
return $data_to_set;
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = array();
$data_to_set['note_types'] = $step_data['wcs_note_type'];
$data_to_set['notes'] = BWFAN_Common::decode_merge_tags( $step_data['wcs_notes'] );
$data_to_set['subscription_id'] = isset( $automation_data['global']['wc_subscription_id'] ) ? $automation_data['global']['wc_subscription_id'] : 0;
$data_to_set['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : 0;
return $data_to_set;
}
/**
* Execute the current action.
* Return 3 for successful execution , 4 for permanent failure.
*
* @param $action_data
*
* @return array
*/
public function execute_action( $action_data ) {
$this->set_data( $action_data['processed_data'] );
$result = $this->process();
if ( true === $result ) {
return array(
'status' => 3,
);
}
return array(
'status' => $result['status'],
'message' => $result['msg'],
);
}
/**
* Process and do the actual processing for the current action.
* This function is present in every action class.
*/
public function process() {
$is_required_fields_present = $this->check_fields( $this->data, $this->required_fields );
if ( false === $is_required_fields_present ) {
return $this->show_fields_error();
}
return $this->add_notes();
}
/**
* add notes to subscription.
*
* subscription_id, subscription_coupon_id are required.
*
* @return array|bool
*/
public function add_notes() {
$result = [];
$subscription = wcs_get_subscription( $this->data['subscription_id'] );
$is_customer_note = $this->data['note_types'] === 'public' ? true : false;
$note = $this->data['notes'];
if ( ! $subscription ) {
$result['msg'] = __( 'Subscription does not exists', 'wp-marketing-automations-pro' );
$result['status'] = 4;
return $result;
}
if ( empty( $this->data['notes'] ) ) {
$result['msg'] = __( 'Notes is required', 'wp-marketing-automations-pro' );
$result['status'] = 4;
return $result;
}
$subscription->add_order_note( $note, $is_customer_note, false );
return true;
}
public function process_v2() {
$subscription = wcs_get_subscription( $this->data['subscription_id'] );
$is_customer_note = $this->data['note_types'] === 'public' ? true : false;
$note = $this->data['notes'];
$order_id = $this->data['order_id'];
/** then will get it using the order id */
if ( ! $subscription ) {
$subscriptions = BWFAN_PRO_Common::order_contains_subscriptions( $order_id );
/** if still no subscriptions exists with order then skipped */
if ( false === $subscriptions ) {
return $this->skipped_response( __( 'No subscription associated with order.', 'wp-marketing-automations-pro' ) );
}
$subscriptions = array_values( $subscriptions );
$subscription = $subscriptions[0];
}
if ( ! $subscription ) {
return $this->skipped_response( __( 'Subscription does not exists', 'wp-marketing-automations-pro' ) );
}
if ( empty( $this->data['notes'] ) ) {
return $this->skipped_response( __( 'Note is required, missing.', 'wp-marketing-automations-pro' ) );
}
$subscription->add_order_note( $note, $is_customer_note, false );
return $this->success_message( __( 'Note added.', 'wp-marketing-automations-pro' ) );
}
public function get_fields_schema() {
$options = BWFAN_PRO_Common::prepared_field_options( $this->wcs_note_types );
return [
[
'id' => 'wcs_note_type',
'label' => __( "Note Type", 'wp-marketing-automations-pro' ),
'type' => 'wp_select',
'options' => $options,
'placeholder' => __( 'Choose note type', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper',
'tip' => "",
"description" => "",
"required" => false,
],
[
'id' => 'wcs_notes',
'type' => 'textarea',
'label' => __( 'Note', 'wp-marketing-automations-pro' ),
'tip' => "",
'placeholder' => __( "Note", 'wp-marketing-automations-pro' ),
"description" => "",
"required" => false,
]
];
}
/** set default values */
public function get_default_values() {
return [
'wcs_note_type' => 'private',
];
}
public function get_desc_text( $data ) {
$data = json_decode( wp_json_encode( $data ), true );
if ( ! isset( $data['wcs_notes'] ) || empty( $data['wcs_notes'] ) ) {
return '';
}
return $data['wcs_notes'];
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WCS_Add_Note';

View File

@@ -0,0 +1,187 @@
<?php
final class BWFAN_WCS_Add_Product extends BWFAN_Action {
private static $ins = null;
private function __construct() {
$this->action_name = __( 'Add Product In Subscription', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This adds a product in the subscription', 'wp-marketing-automations-pro' );
$this->action_priority = 20;
$this->support_v2 = true;
$this->support_v1 = false;
$this->included_events = array(
'wcs_before_end',
'wcs_before_renewal',
'wcs_card_expiry',
'wcs_created',
'wcs_renewal_payment_complete',
'wcs_renewal_payment_failed',
'wcs_status_changed',
'wcs_trial_end',
'wcs_note_added',
'wc_new_order',
'wc_order_note_added',
'wc_order_status_change',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced'
);
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set['subscription_id'] = isset( $automation_data['global']['wc_subscription_id'] ) ? $automation_data['global']['wc_subscription_id'] : 0;
$data_to_set['product_qty'] = isset( $step_data['product_qty'] ) ? $step_data['product_qty'] : 1;
$data_to_set['custom_product_price'] = isset( $step_data['custom_product_price'] ) ? $step_data['custom_product_price'] : '';
$data_to_set['custom_product_name'] = isset( $step_data['custom_product_name'] ) ? $step_data['custom_product_name'] : '';
$data_to_set['products'] = isset( $step_data['products'][0] ) ? $step_data['products'][0] : [];
$data_to_set['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : 0;
return $data_to_set;
}
public function process_v2() {
if ( ! isset( $this->data['subscription_id'] ) && ! isset( $this->data['order_id'] ) ) {
return $this->skipped_response( __( 'Subscription not found.', 'wp-marketing-automations-pro' ) );
}
$sub_id = $this->data['subscription_id'];
if ( empty( $sub_id ) && ! empty( $this->data['order_id'] ) ) {
$subscriptions = wcs_get_subscriptions_for_order( $this->data['order_id'], array( 'order_type' => 'any' ) );
if ( ! empty( $subscriptions ) ) {
$subscription_keys = array_keys( $subscriptions );
$sub_id = reset( $subscription_keys );
}
}
if ( empty( $sub_id ) ) {
return $this->skipped_response( __( 'Subscription not found.', 'wp-marketing-automations-pro' ) );
}
$subscription = wcs_get_subscription( $sub_id );
if ( ! $subscription instanceof WC_Subscription ) {
return $this->skipped_response( __( 'Subscription not found.', 'wp-marketing-automations-pro' ) );
}
$product_id = $this->data['products']['id'];
$product_ids = array_map( function ( $item ) {
/** @var $item WC_Order_Item_Product */
return $item->get_product_id();
}, $subscription->get_items() );
if ( in_array( intval( $product_id ), $product_ids, true ) ) {
return $this->skipped_response( __( 'Product already exists in the subscription.', 'wp-marketing-automations-pro' ) );
}
$product = wc_get_product( $product_id );
if ( ! $product ) {
return $this->skipped_response( __( 'Product not found.', 'wp-marketing-automations-pro' ) );
}
$add_product_args = array();
$add_product_args['name'] = isset( $this->data['custom_product_name'] ) && ! empty( $this->data['custom_product_name'] ) ? $this->data['custom_product_name'] : $product->get_title();
$quantity = isset( $this->data['product_qty'] ) ? $this->data['product_qty'] : 1;
$custom_product_price = isset( $this->data['custom_product_price'] ) && $this->data['custom_product_price'] !== '' ? $this->data['custom_product_price'] : $product->get_price();
$custom_product_price = empty( $custom_product_price ) ? 0 : $custom_product_price;
$add_product_args['subtotal'] = 0;
$add_product_args['total'] = 0;
if ( ! empty( $custom_product_price ) ) {
$add_product_args['subtotal'] = wc_get_price_excluding_tax( $product, array(
'price' => $custom_product_price,
'qty' => $quantity,
) );
$add_product_args['total'] = $add_product_args['subtotal'];
}
$item_id = $subscription->add_product( $product, $quantity, $add_product_args );
$item = $subscription->get_item( $item_id );
if ( $item instanceof WC_Order_Item ) {
$item->add_meta_data( '_fk_automation', 'yes' );
$item->save();
}
$subscription->calculate_totals();
$subscription->save();
if ( $item_id ) {
return $this->success_message( __( 'Product added to the subscription.', 'wp-marketing-automations-pro' ) );
}
return $this->error_response( __( 'Some error occurred.', 'wp-marketing-automations-pro' ) );
}
/**
* v2 Method: Get field Schema
*
* @return array[]
*/
public function get_fields_schema() {
return [
[
'id' => 'products',
'label' => __( 'Select Product', 'wp-marketing-automations-pro' ),
"type" => 'custom_search',
'autocompleterOption' => [
'path' => 'wcs_products',
'slug' => 'wcs_products',
'labelText' => 'WooCommerce Subscription products '
],
'class' => '',
'placeholder' => '',
'required' => true,
'multiple' => false,
'hint' => __( 'Action will be skipped if product already exists in the subscription', 'wp-marketing-automations-pro' ),
],
[
'id' => 'product_qty',
'label' => __( 'Product Quantity', 'wp-marketing-automations-pro' ),
"type" => 'number',
'min' => '0',
'placeholder' => __( 'Enter Quantity', 'wp-marketing-automations-pro' ),
'required' => true,
],
[
'id' => 'custom_product_price',
'label' => __( 'Product Price', 'wp-marketing-automations-pro' ),
"type" => 'text',
'placeholder' => __( 'Enter Price', 'wp-marketing-automations-pro' ),
'hint' => __( 'Leave empty to keep the default product price', 'wp-marketing-automations-pro' ),
],
[
'id' => 'custom_product_name',
'label' => __( 'Product Name', 'wp-marketing-automations-pro' ),
"type" => 'text',
'placeholder' => __( 'Enter Name', 'wp-marketing-automations-pro' ),
'hint' => __( 'Leave empty to keep the default product name', 'wp-marketing-automations-pro' ),
],
];
}
/**
* Set default values
*
* @return string[]
*/
public function get_default_values() {
return [
'product_qty' => 1,
];
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WCS_Add_Product';

View File

@@ -0,0 +1,192 @@
<?php
final class BWFAN_WCS_Cancel_Order_Subscriptions extends BWFAN_Action {
private static $ins = null;
protected function __construct() {
$this->action_name = __( 'Cancel Order Associated Subscriptions', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This action cancels the WooCommerce Subscription associated with the order.', 'wp-marketing-automations-pro' );
$this->required_fields = array( 'order_id' );
$this->action_priority = 20;
// Excluded events which this action does not support.
$this->included_events = array(
'wc_order_status_change',
'wc_new_order',
'wc_order_note_added',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced'
);
$this->support_v2 = true;
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
public function get_view() {
$unique_slug = $this->get_slug();
?>
<script type="text/html" id="tmpl-action-<?php echo esc_attr__( $unique_slug ); ?>">
<div class="clearfix bwfan_field_desc bwfan-pt-5 bwfan-mb10">
Note: This action will cancel the active associated subscriptions with the order.
</div>
</script>
<?php
}
/**
* Make all the data which is required by the current action.
* This data will be used while executing the task of this action.
*
* @param $integration_object
* @param $task_meta
*
* @return array|void
*/
public function make_data( $integration_object, $task_meta ) {
return [];
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = array();
$data_to_set['order_id'] = $automation_data['global']['order_id'];
return $data_to_set;
}
/**
* Execute the current action.
* Return 3 for successful execution , 4 for permanent failure.
*
* @param $action_data
*
* @return array
*/
public function execute_action( $action_data ) {
$this->set_data( $action_data['processed_data'] );
$result = $this->process();
/** Required fields missing */
if ( isset( $result['bwfan_response'] ) ) {
return array(
'status' => 4,
'message' => $result['bwfan_response'],
);
}
return array(
'status' => $result['status'],
'message' => isset( $result['msg'] ) ? $result['msg'] : __( 'Unknown Error Occurred', 'wp-marketing-automations-pro' ),
);
}
/**
* Process and do the actual processing for the current action.
* This function is present in every action class.
*/
public function process() {
$is_required_fields_present = $this->check_fields( $this->data, $this->required_fields );
if ( false === $is_required_fields_present ) {
return $this->show_fields_error();
}
return $this->cancel_order_associated_subscriptions();
}
/**
* cancelled subscription.
*
* order_id is required.
*
* @return array|bool
*/
public function cancel_order_associated_subscriptions() {
$result = [];
$order = wc_get_order( $this->data['order_id'] );
/** check order instance */
if ( ! $order instanceof WC_Order ) {
$result['msg'] = __( 'Order does not exists.', 'wp-marketing-automations-pro' );
$result['status'] = 4;
return $result;
}
if ( false === wcs_order_contains_subscription( $order, array( 'parent', 'renewal' ) ) ) {
$result['msg'] = __( 'Order does not contains any subscription.', 'wp-marketing-automations-pro' );
$result['status'] = 4;
return $result;
}
$subscriptions = wcs_get_subscriptions_for_order( wcs_get_objects_property( $order, 'id' ), array( 'order_type' => array( 'parent', 'renewal' ) ) );
foreach ( $subscriptions as $subscription ) {
if ( ! $subscription->has_status( 'active' ) ) {
$result['msg'] = __( 'Subscription is not active.', 'wp-marketing-automations-pro' );
$result['status'] = 4;
return $result;
}
try {
$subscription->update_status( 'cancelled', sprintf( __( 'Subscription status cancelled by FunnelKit automation #%s.', 'wp-marketing-automations-pro' ), $this->data['automation_id'] ) );
$result['msg'] = sprintf( __( 'Subscription #%s is cancelled.', 'wp-marketing-automations-pro' ), $subscription->get_id() );
$result['status'] = 3;
} catch ( Exception $error ) {
$result['msg'] = $error->getMessage();
$result['status'] = 4;
}
}
return $result;
}
public function process_v2() {
$order = wc_get_order( $this->data['order_id'] );
/** check order instance */
if ( ! $order instanceof WC_Order ) {
return $this->skipped_response( __( 'Order does not exists', 'wp-marketing-automations-pro' ) );
}
if ( false === wcs_order_contains_subscription( $order, array( 'parent', 'renewal' ) ) ) {
return $this->skipped_response( __( 'Order does not contains any subscription.', 'wp-marketing-automations-pro' ) );
}
$subscriptions = wcs_get_subscriptions_for_order( wcs_get_objects_property( $order, 'id' ), array( 'order_type' => array( 'parent', 'renewal' ) ) );
$message = '';
foreach ( $subscriptions as $subscription ) {
if ( ! $subscription->has_status( 'active' ) ) {
return $this->skipped_response( __( 'Subscription is not active.', 'wp-marketing-automations-pro' ) );
}
try {
$subscription->update_status( 'cancelled', sprintf( __( 'Subscription status cancelled by FunnelKit automation #%s.', 'wp-marketing-automations-pro' ), $this->data['automation_id'] ) );
$message = sprintf( __( 'Subscription #%s is cancelled.', 'wp-marketing-automations-pro' ), $subscription->get_id() );
} catch ( Exception $error ) {
$message = $error->getMessage();
}
}
return $this->success_message( $message );
}
public function get_fields_schema() {
return [];
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WCS_Cancel_Order_Subscriptions';

View File

@@ -0,0 +1,177 @@
<?php
final class BWFAN_WCS_Cancel_Product_Subscription extends BWFAN_Action {
private static $ins = null;
private function __construct() {
$this->action_name = __( 'Cancel Product Subscriptions', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This action cancels the user\'s subscription contains the given product', 'wp-marketing-automations-pro' );
$this->action_priority = 20;
$this->support_v2 = true;
$this->support_v1 = false;
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set['subscription_id'] = isset( $automation_data['global']['wc_subscription_id'] ) ? $automation_data['global']['wc_subscription_id'] : 0;
$data_to_set['products'] = isset( $step_data['products'] ) ? $step_data['products'] : [];
$data_to_set['subscription-contains'] = isset( $step_data['subscription-contains'] ) ? $step_data['subscription-contains'] : 'wcs_latest';
$data_to_set['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : 0;
$data_to_set['email'] = ( isset( $automation_data['global']['email'] ) && is_email( $automation_data['global']['email'] ) ) ? $automation_data['global']['email'] : '';
return $data_to_set;
}
public function process_v2() {
if ( empty( $this->data['products'] ) ) {
return $this->skipped_response( __( 'No product selected.', 'wp-marketing-automations-pro' ) );
}
$email = $this->get_user_email();
if ( empty( $email ) ) {
return $this->skipped_response( __( 'Contact not found.', 'wp-marketing-automations-pro' ) );
}
$product_ids = array_column( $this->data['products'], 'id' );
$subscription_ids = $this->get_subscriptions( $email, $product_ids );
if ( empty( $subscription_ids ) ) {
return $this->skipped_response( __( 'Subscription not found.', 'wp-marketing-automations-pro' ) );
}
foreach ( $subscription_ids as $subscription_id ) {
$this->cancel_subscription_by_id( $subscription_id );
}
return $this->success_message( __( 'Subscription(s) canceled.', 'wp-marketing-automations-pro' ) );
}
protected function get_user_email() {
/** Subscription */
$id = $this->data['subscription_id'];
if ( ! empty( $id ) ) {
$subscription = wcs_get_subscription( $id );
if ( $subscription instanceof WC_Subscription ) {
return $subscription->get_billing_email();
}
}
/** Order */
$id = $this->data['order_id'];
if ( ! empty( $id ) ) {
$order = wc_get_order( $id );
if ( $order instanceof WC_Order ) {
return $order->get_billing_email();
}
}
/** cid */
$id = $this->data['cid'];
if ( ! empty( $id ) ) {
$contact = bwf_get_contact( '', $id );
if ( $contact instanceof WooFunnels_Contact ) {
return $contact->get_email();
}
}
return $this->data['email'];
}
protected function get_subscriptions( $email, $product_ids ) {
global $wpdb;
$product_ids_placeholder = implode( ', ', array_fill( 0, count( $product_ids ), '%s' ) );
if ( BWF_WC_Compatibility::is_hpos_enabled() ) {
$query = $wpdb->prepare( "SELECT DISTINCT orders.id FROM {$wpdb->prefix}wc_orders AS orders
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON orders.id = woi.order_id
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
WHERE orders.billing_email = %s AND orders.status IN ('wc-active', 'wc-on-hold') AND woi.order_item_type = 'line_item' AND orders.type = 'shop_subscription'
AND orders.status != 'trash' AND woim.meta_key = '_product_id' AND woim.meta_value IN ($product_ids_placeholder)
ORDER BY `id` DESC", array_merge( [ $email ], $product_ids ) );
} else {
$query = $wpdb->prepare( "SELECT DISTINCT p.ID AS id FROM {$wpdb->prefix}posts AS p INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON p.ID = woi.order_id INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
WHERE pm.meta_key = '_billing_email' AND pm.meta_value = %s AND p.post_type = 'shop_subscription' AND p.post_status IN ('wc-active', 'wc-on-hold') AND woi.order_item_type = 'line_item'
AND woim.meta_key = '_product_id' AND woim.meta_value IN ($product_ids_placeholder)
ORDER BY `ID` DESC", array_merge( [ $email ], $product_ids ) );
}
if ( 'wcs_latest' === $this->data['subscription-contains'] ) {
$query .= " LIMIT 0,1";
}
return $wpdb->get_col( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
/**
* Cancel subscription by ID
*
* @param $subscription_id
*
* @return void
*/
public function cancel_subscription_by_id( $subscription_id ) {
$subscription = wcs_get_subscription( $subscription_id );
if ( ! $subscription instanceof WC_Subscription ) {
return;
}
try {
$subscription->update_status( 'cancelled', sprintf( __( 'Subscription cancelled by FunnelKit Automation #%s.', 'wp-marketing-automations-pro' ), $this->data['automation_id'] ) );
} catch ( Exception $error ) {
}
}
public function get_fields_schema() {
return [
[
'id' => 'products',
'label' => __( 'Select Products', 'wp-marketing-automations-pro' ),
"type" => 'custom_search',
'autocompleterOption' => [
'path' => 'wcs_products',
'slug' => 'wcs_products',
'labelText' => __( 'WooCommerce Subscription products', 'wp-marketing-automations-pro' ),
],
'class' => '',
'placeholder' => '',
'required' => true,
'multiple' => true,
"hint" => __( "Subscriptions with Active or On-hold status will be fetched.", 'wp-marketing-automations-pro' ),
],
[
'id' => 'subscription-contains',
'label' => __( 'Cancel Subscription(s)', 'wp-marketing-automations-pro' ),
'type' => 'radio',
'options' => [
[
'label' => __( 'Recent', 'wp-marketing-automations-pro' ),
'value' => 'wcs_latest',
],
[
'label' => __( 'All', 'wp-marketing-automations-pro' ),
'value' => 'wcs_all',
],
],
"class" => 'bwfan-input-wrapper',
"tip" => "",
"required" => false,
"hint" => __( "<b>Recent</b> option will cancel the latest active subscription.</br><b>All</b> option will cancel all the active subscriptions.", 'wp-marketing-automations-pro' ),
],
];
}
public function get_default_values() {
return [
'subscription-contains' => 'wcs_latest',
];
}
}
return 'BWFAN_WCS_Cancel_Product_Subscription';

View File

@@ -0,0 +1,240 @@
<?php
final class BWFAN_WCS_Change_Subscription_Status extends BWFAN_Action {
private static $ins = null;
protected function __construct() {
$this->action_name = __( 'Change Subscription Status', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This action changes the WooCommerce Subscription status', 'wp-marketing-automations-pro' );
$this->required_fields = array( 'subscription_id', 'subs_status' );
$this->action_priority = 1;
// Excluded events which this action does not support.
$this->included_events = array(
'wcs_before_end',
'wcs_before_renewal',
'wcs_note_added',
'wcs_card_expiry',
'wcs_created',
'wcs_renewal_payment_complete',
'wcs_renewal_payment_failed',
'wcs_status_changed',
'wcs_trial_end',
'wc_new_order',
'wc_order_note_added',
'wc_order_status_change',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced'
);
$this->support_v2 = true;
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
/**
* Localize data for html fields for the current action.
*/
public function admin_enqueue_assets() {
if ( BWFAN_Common::is_load_admin_assets( 'automation' ) ) {
$data = $this->get_view_data();
BWFAN_Core()->admin->set_actions_js_data( $this->get_class_slug(), 'subscription_status_options', $data );
}
}
public function get_view_data() {
return wcs_get_subscription_statuses();
}
/**
* Show the html fields for the current action.
*/
public function get_view() {
?>
<script type="text/html" id="tmpl-action-<?php echo esc_html__( $this->get_slug() ); ?>">
<#
selected_subscription_status = (_.has(data.actionSavedData, 'data') && _.has(data.actionSavedData.data, 'subscription_status')) ? data.actionSavedData.data.subscription_status : '';
#>
<div class="bwfan-input-form clearfix">
<label for="" class="bwfan-label-title"><?php echo esc_html__( 'Status', 'woocommerce' ); ?></label>
<select required id="" class="bwfan-input-wrapper" name="bwfan[{{data.action_id}}][data][subscription_status]">
<option value=""><?php echo esc_html__( 'Choose Status', 'wp-marketing-automations-pro' ); ?></option>
<#
if(_.has(data.actionFieldsOptions, 'subscription_status_options') && _.isObject(data.actionFieldsOptions.subscription_status_options) ) {
_.each( data.actionFieldsOptions.subscription_status_options, function( value, key ){
selected = (key == selected_subscription_status) ? 'selected' : '';
#>
<option value="{{key}}" {{selected}}>{{value}}</option>
<# })
}
#>
</select>
</div>
</script>
<?php
}
/**
* Make all the data which is required by the current action.
* This data will be used while executing the task of this action.
*
* @param $integration_object
* @param $task_meta
*
* @return array|void
*/
public function make_data( $integration_object, $task_meta ) {
$data_to_set = array();
$data_to_set['subs_status'] = $task_meta['data']['subscription_status'];
$data_to_set['subscription_id'] = $task_meta['global']['wc_subscription_id'];
return $data_to_set;
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = array();
$data_to_set['subs_status'] = $step_data['subscription_status'];
$data_to_set['subscription_id'] = isset( $automation_data['global']['wc_subscription_id'] ) ? $automation_data['global']['wc_subscription_id'] : 0;
$data_to_set['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : 0;
return $data_to_set;
}
/**
* Execute the current action.
* Return 3 for successful execution , 4 for permanent failure.
*
* @param $action_data
*
* @return array
*/
public function execute_action( $action_data ) {
$this->set_data( $action_data['processed_data'] );
$result = $this->process();
if ( $result ) {
return array(
'status' => 3,
);
}
return array(
'status' => $result['status'],
'message' => $result['msg'],
);
}
/**
* Process and do the actual processing for the current action.
* This function is present in every action class.
*/
public function process() {
$is_required_fields_present = $this->check_fields( $this->data, $this->required_fields );
if ( false === $is_required_fields_present ) {
return $this->show_fields_error();
}
return $this->change_status();
}
/**
* Change subscription status.
*
* subscription_id, status are required.
*
* @return array|bool
*/
public function change_status() {
$result = [];
$subscription = wcs_get_subscription( $this->data['subscription_id'] );
if ( ! $subscription ) {
$result['msg'] = __( 'Subscription does not exists', 'wp-marketing-automations-pro' );
$result['status'] = 4;
return $result;
}
try {
$subscription->update_status( $this->data['subs_status'], sprintf( __( 'Subscription status changed by FunnelKit automation #%s.', 'wp-marketing-automations-pro' ), $this->data['automation_id'] ) );
$result = true;
} catch ( Exception $error ) {
$result['msg'] = $error->getMessage();
$result['status'] = 4;
}
return $result;
}
public function process_v2() {
$subscription = wc_get_order( $this->data['subscription_id'] );
$subscriptions = [];
$order_id = $this->data['order_id'];
/** then will get it using the order id */
if ( ! $subscription ) {
$subscriptions = BWFAN_PRO_Common::order_contains_subscriptions( $order_id );
/** if still no subscriptions exists with order then skipped */
if ( false === $subscriptions ) {
return $this->skipped_response( __( 'No subscription associated with order.', 'wp-marketing-automations-pro' ) );
}
$subscriptions = array_values( $subscriptions );
$subscription = $subscriptions[0];
}
if ( ! $subscription ) {
return $this->skipped_response( __( 'Subscription does not exists', 'wp-marketing-automations-pro' ) );
}
try {
$subscription->update_status( $this->data['subs_status'], sprintf( __( 'Subscription status changed by FunnelKit automation #%s.', 'wp-marketing-automations-pro' ), $this->data['automation_id'] ) );
return $this->success_message( __( 'Subscription status changed.', 'wp-marketing-automations-pro' ) );
} catch ( Exception $error ) {
return $this->error_response( $error->getMessage() );
}
}
public function get_fields_schema() {
$options = array_replace( [ '' => 'Select' ], $this->get_view_data() );
$options = BWFAN_PRO_Common::prepared_field_options( $options );
return [
[
'id' => 'subscription_status',
'label' => __( "Status", 'wp-marketing-automations-pro' ),
'type' => 'wp_select',
'options' => $options,
'placeholder' => __( 'Choose Status', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper',
'tip' => "",
"description" => "",
"required" => false,
],
];
}
public function get_desc_text( $data ) {
$data = json_decode( wp_json_encode( $data ), true );
$status = $this->get_view_data();
if ( ! is_array( $data ) || ! isset( $data['subscription_status'] ) ) {
return reset( $status );
}
return $status[ $data['subscription_status'] ];
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WCS_Change_Subscription_Status';

View File

@@ -0,0 +1,265 @@
<?php
final class BWFAN_WCS_Remove_Coupon extends BWFAN_Action {
private static $ins = null;
protected function __construct() {
$this->action_name = __( 'Remove Coupon', 'wp-marketing-automations-pro' );
$this->action_desc = __( "Remove a coupon line item or items from a subscription, if any line items match the chosen coupon code.", 'wp-marketing-automations-pro' );
$this->required_fields = array( 'subscription_id', 'subscription_coupon_id' );
$this->action_priority = 1;
// Excluded events which this action does not support.
$this->included_events = array(
'wcs_before_end',
'wcs_before_renewal',
'wcs_card_expiry',
'wcs_created',
'wcs_note_added',
'wcs_renewal_payment_complete',
'wcs_renewal_payment_failed',
'wcs_status_changed',
'wcs_trial_end',
'wc_new_order',
'wc_order_note_added',
'wc_order_status_change',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced'
);
$this->support_v2 = true;
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
/**
* Localize data for html fields for the current action.
*/
public function admin_enqueue_assets() {
if ( BWFAN_Common::is_load_admin_assets( 'automation' ) ) {
$data = $this->get_view_data();
BWFAN_Core()->admin->set_actions_js_data( $this->get_class_slug(), 'subscription_remove_coupon', $data );
}
}
public function get_view_data() {
$get_coupon_list = BWFAN_Common::get_coupon( '' );
if ( empty( $get_coupon_list['results'] ) ) {
return array();
}
$coupon_list = array();
foreach ( $get_coupon_list['results'] as $index => $code ) {
$discount_type = get_post_meta( $code['id'], 'discount_type', true );
if ( in_array( $discount_type, array( 'recurring_fee', 'recurring_percent' ), true ) ) {
$coupon_list[ $code['id'] ] = $code['text'];
}
}
return $coupon_list;
}
/**
* Show the html fields for the current action.
*/
public function get_view() {
?>
<script type="text/html" id="tmpl-action-<?php echo esc_html__( $this->get_slug() ); ?>">
<#
selected_subscription_remove_coupon = (_.has(data.actionSavedData, 'data') && _.has(data.actionSavedData.data, 'selected_subscription_remove_coupon')) ? data.actionSavedData.data.selected_subscription_remove_coupon : '';
#>
<div class="bwfan-input-form clearfix">
<label for="" class="bwfan-label-title"><?php echo esc_html__( 'Coupon', 'wp-marketing-automations-pro' ); ?></label>
<select required id="" class="bwfan-input-wrapper" name="bwfan[{{data.action_id}}][data][selected_subscription_remove_coupon]">
<option value=""><?php echo esc_html__( 'Choose Coupon', 'wp-marketing-automations-pro' ); ?></option>
<#
if(_.has(data.actionFieldsOptions, 'subscription_remove_coupon') && _.isObject(data.actionFieldsOptions.subscription_remove_coupon) ) {
_.each( data.actionFieldsOptions.subscription_remove_coupon, function( value, key ){
selected = (key == selected_subscription_remove_coupon) ? 'selected' : '';
#>
<option value="{{key}}" {{selected}}>{{value}}</option>
<# })
}
#>
</select>
</div>
</script>
<?php
}
/**
* Make all the data which is required by the current action.
* This data will be used while executing the task of this action.
*
* @param $integration_object
* @param $task_meta
*
* @return array|void
*/
public function make_data( $integration_object, $task_meta ) {
$data_to_set = array();
$data_to_set['subscription_coupon_id'] = $task_meta['data']['selected_subscription_remove_coupon'];
$data_to_set['subscription_id'] = $task_meta['global']['wc_subscription_id'];
return $data_to_set;
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = array();
$data_to_set['subscription_coupon_id'] = isset( $step_data['selected_subscription_remove_coupon'][0]['id'] ) ? $step_data['selected_subscription_remove_coupon'][0]['id'] : 0;
$data_to_set['subscription_id'] = isset( $automation_data['global']['wc_subscription_id'] ) ? $automation_data['global']['wc_subscription_id'] : 0;
$data_to_set['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : 0;
return $data_to_set;
}
/**
* Execute the current action.
* Return 3 for successful execution , 4 for permanent failure.
*
* @param $action_data
*
* @return array
*/
public function execute_action( $action_data ) {
$this->set_data( $action_data['processed_data'] );
$result = $this->process();
if ( true === $result ) {
return array(
'status' => 3,
);
}
return array(
'status' => $result['status'],
'message' => $result['msg'],
);
}
/**
* Process and do the actual processing for the current action.
* This function is present in every action class.
*/
public function process() {
$is_required_fields_present = $this->check_fields( $this->data, $this->required_fields );
if ( false === $is_required_fields_present ) {
return $this->show_fields_error();
}
return $this->remove_coupon();
}
/**
* add coupon to subscription.
*
* subscription_id, subscription_coupon_id are required.
*
* @return array|bool
*/
public function remove_coupon() {
$result = [];
$subscription = wcs_get_subscription( $this->data['subscription_id'] );
$automation_id = $this->data['automation_id'];
$automation_data = BWFAN_Core()->automations->get_automation_data_meta( $automation_id );
$automation_title = isset( $automation_data['title'] ) ? $automation_data['title'] : '';
$coupon = new WC_Coupon( $this->data['subscription_coupon_id'] );
if ( ! $subscription || ! $coupon ) {
$result['msg'] = __( 'Subscription or Coupon does not exists', 'wp-marketing-automations-pro' );
$result['status'] = 4;
return $result;
}
foreach ( $subscription->get_items( 'coupon' ) as $item ) {
if ( $item->get_code() === $coupon->get_code() ) {
$subscription->remove_coupon( $coupon->get_code() );
$subscription->add_order_note( sprintf( __( '%1$s automation run: removed coupon %2$s to subscription. (Automation ID: %3$d)', 'wp-marketing-automations-pro' ), $automation_title, $coupon->get_code(), $this->automation_id ), false, false );
}
}
return true;
}
public function process_v2() {
$subscription = wcs_get_subscription( $this->data['subscription_id'] );
$coupon = new WC_Coupon( $this->data['subscription_coupon_id'] );
$order_id = $this->data['order_id'];
/** then will get it using the order id */
if ( ! $subscription ) {
$subscriptions = BWFAN_PRO_Common::order_contains_subscriptions( $order_id );
/** if still no subscriptions exists with order then skipped */
if ( false === $subscriptions ) {
return $this->skipped_response( __( 'No subscription associated with order.', 'wp-marketing-automations-pro' ) );
}
$subscriptions = array_values( $subscriptions );
$subscription = $subscriptions[0];
}
if ( ! $subscription instanceof WC_Subscription || ! $coupon ) {
return $this->skipped_response( __( 'Subscription or Coupon does not exists.', 'wp-marketing-automations-pro' ) );
}
foreach ( $subscription->get_items( 'coupon' ) as $item ) {
if ( $item->get_code() === $coupon->get_code() ) {
$subscription->remove_coupon( $coupon->get_code() );
$subscription->add_order_note( sprintf( __( '%1$s automation run: removed coupon %2$s to subscription. (Automation ID: %3$d)', 'wp-marketing-automations-pro' ), $automation_title, $coupon->get_code(), $this->automation_id ), false, false );
}
}
return $this->success_message( __( 'Coupon removed', 'wp-marketing-automations-pro' ) );
}
public function get_fields_schema() {
return [
[
"id" => 'selected_subscription_remove_coupon',
"label" => __( 'Coupon', 'wp-marketing-automations-pro' ),
"type" => 'custom_search',
'autocompleterOption' => [
'path' => 'wcs_coupons',
'slug' => 'wcs_coupons',
'labelText' => 'Coupon'
],
"allowFreeTextSearch" => false,
"required" => false,
"errorMsg" => "",
"multiple" => false
],
];
}
public function get_desc_text( $data ) {
$data = json_decode( wp_json_encode( $data ), true );
if ( ! isset( $data['selected_subscription_remove_coupon'] ) || empty( $data['selected_subscription_remove_coupon'] ) ) {
return '';
}
$coupons = [];
foreach ( $data['selected_subscription_remove_coupon'] as $coupon ) {
if ( ! isset( $coupon['name'] ) || empty( $coupon['name'] ) ) {
continue;
}
$coupons[] = $coupon['name'];
}
return $coupons;
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WCS_Remove_Coupon';

View File

@@ -0,0 +1,122 @@
<?php
final class BWFAN_WCS_Remove_Product extends BWFAN_Action {
private static $ins = null;
private function __construct() {
$this->action_name = __( 'Remove Product From Subscription', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This removes a product from the subscription', 'wp-marketing-automations-pro' );
$this->action_priority = 20;
$this->support_v2 = true;
$this->support_v1 = false;
$this->included_events = array(
'wcs_before_end',
'wcs_before_renewal',
'wcs_card_expiry',
'wcs_created',
'wcs_renewal_payment_complete',
'wcs_renewal_payment_failed',
'wcs_status_changed',
'wcs_trial_end',
'wcs_note_added',
'wc_new_order',
'wc_order_note_added',
'wc_order_status_change',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced'
);
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set['subscription_id'] = isset( $automation_data['global']['wc_subscription_id'] ) ? $automation_data['global']['wc_subscription_id'] : 0;
$data_to_set['products'] = isset( $step_data['products'][0] ) ? $step_data['products'][0] : [];
$data_to_set['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : 0;
return $data_to_set;
}
public function process_v2() {
if ( ! isset( $this->data['subscription_id'] ) && ! isset( $this->data['order_id'] ) ) {
return $this->skipped_response( __( 'Subscription not found.', 'wp-marketing-automations-pro' ) );
}
$sub_id = $this->data['subscription_id'];
if ( empty( $sub_id ) && ! empty( $this->data['order_id'] ) ) {
$subscriptions = wcs_get_subscriptions_for_order( $this->data['order_id'], array( 'order_type' => 'any' ) );
if ( ! empty( $subscriptions ) ) {
$subscription_keys = array_keys( $subscriptions );
$sub_id = reset( $subscription_keys );
}
}
if ( empty( $sub_id ) ) {
return $this->skipped_response( __( 'Subscription not found.', 'wp-marketing-automations-pro' ) );
}
$subscription = wcs_get_subscription( $sub_id );
if ( ! $subscription instanceof WC_Subscription ) {
return $this->skipped_response( __( 'Subscription not found.', 'wp-marketing-automations-pro' ) );
}
$product_id = $this->data['products']['id'];
$product_ids = array_map( function ( $item ) {
/** @var $item WC_Order_Item_Product */
return $item->get_product_id();
}, $subscription->get_items() );
if ( ! in_array( intval( $product_id ), $product_ids, true ) ) {
return $this->skipped_response( __( 'Product does not exist in the subscription.', 'wp-marketing-automations-pro' ) );
}
$item_key = array_search( $product_id, $product_ids );
if ( false !== $item_key ) {
$subscription->remove_item( $item_key );
$subscription->calculate_totals();
$subscription->save();
return $this->success_message( __( 'Product removed from the subscription.', 'wp-marketing-automations-pro' ) );
}
return $this->error_response( __( 'Some error occurred.', 'wp-marketing-automations-pro' ) );
}
/**
* v2 Method: Get field Schema
*
* @return array[]
*/
public function get_fields_schema() {
return [
[
'id' => 'products',
'label' => __( 'Select Product', 'wp-marketing-automations-pro' ),
"type" => 'custom_search',
'autocompleterOption' => [
'path' => 'wcs_products',
'slug' => 'wcs_products',
'labelText' => 'WooCommerce Subscription products '
],
'class' => '',
'placeholder' => '',
'required' => true,
'multiple' => false,
]
];
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WCS_Remove_Product';

View File

@@ -0,0 +1,173 @@
<?php
final class BWFAN_WCS_Send_Subscription_Invoice extends BWFAN_Action {
private static $ins = null;
protected function __construct() {
$this->action_name = __( 'Send Subscription Invoice', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This action sends the subscription invoice email to the user', 'wp-marketing-automations-pro' );
$this->required_fields = array( 'subscription_id' );
$this->action_priority = 2;
// Excluded events which this action does not support.
$this->included_events = array(
'wcs_before_end',
'wcs_before_renewal',
'wcs_note_added',
'wcs_card_expiry',
'wcs_created',
'wcs_renewal_payment_complete',
'wcs_renewal_payment_failed',
'wcs_status_changed',
'wcs_trial_end',
'wc_new_order',
'wc_order_note_added',
'wc_order_status_change',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced'
);
$this->support_v2 = true;
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
/**
* Make all the data which is required by the current action.
* This data will be used while executing the task of this action.
*
* @param $integration_object
* @param $task_meta
*
* @return array|void
*/
public function make_data( $integration_object, $task_meta ) {
$data_to_set = array();
$data_to_set['subscription_id'] = $task_meta['global']['wc_subscription_id'];
return $data_to_set;
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = array();
$data_to_set['subscription_id'] = isset( $automation_data['global']['wc_subscription_id'] ) ? $automation_data['global']['wc_subscription_id'] : 0;
$data_to_set['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : 0;
return $data_to_set;
}
/**
* Execute the current action.
* Return 3 for successful execution , 4 for permanent failure.
*
* @param $action_data
*
* @return array
*/
public function execute_action( $action_data ) {
$this->set_data( $action_data['processed_data'] );
$result = $this->process();
if ( $result ) {
return array(
'status' => 3,
);
}
$status = array(
'status' => $result['status'],
'message' => $result['msg'],
);
return $status;
}
/**
* Process and do the actual processing for the current action.
* This function is present in every action class.
*/
public function process() {
$is_required_fields_present = $this->check_fields( $this->data, $this->required_fields );
if ( false === $is_required_fields_present ) {
return $this->show_fields_error();
}
return $this->send_invoice();
}
/**
* Change subscription status.
*
* subscription_id, status are required.
*
* @return array|bool
*/
public function send_invoice() {
$result = [];
$subscription = wcs_get_subscription( $this->data['subscription_id'] );
if ( ! $subscription ) {
$result['msg'] = __( 'Subscription does not exists', 'wp-marketing-automations-pro' );
$result['status'] = 4;
return $result;
}
do_action( 'woocommerce_before_resend_order_emails', $subscription, 'customer_invoice' );
WC()->payment_gateways();
WC()->shipping();
WC()->mailer()->customer_invoice( $subscription );
do_action( 'woocommerce_after_resend_order_email', $subscription, 'customer_invoice' );
return true;
}
public function process_v2() {
$subscription = wcs_get_subscription( $this->data['subscription_id'] );
$order_id = $this->data['order_id'];
/** then will get it using the order id */
if ( ! $subscription ) {
$subscriptions = BWFAN_PRO_Common::order_contains_subscriptions( $order_id );
/** if still no subscriptions exists with order then skipped */
if ( false === $subscriptions ) {
return $this->skipped_response( __( 'No subscription associated with order.', 'wp-marketing-automations-pro' ) );
}
$subscriptions = array_values( $subscriptions );
$subscription = $subscriptions[0];
}
if ( ! $subscription ) {
return $this->skipped_response( __( 'Subscription does not exists', 'wp-marketing-automations-pro' ) );
}
do_action( 'woocommerce_before_resend_order_emails', $subscription, 'customer_invoice' );
WC()->payment_gateways();
WC()->shipping();
WC()->mailer()->customer_invoice( $subscription );
do_action( 'woocommerce_after_resend_order_email', $subscription, 'customer_invoice' );
return $this->success_message( __( 'Subscription invoice sent to the customer.', 'wp-marketing-automations-pro' ) );
}
public function get_fields_schema() {
return [];
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WCS_Send_Subscription_Invoice';

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.