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,137 @@
<?php
final class BWFAN_WC_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->included_events = array(
'wc_new_order',
'wc_order_note_added',
'wc_order_status_change',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced',
'wc_order_status_pending',
);
$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 = array();
$custom_fields = array();
$custom_fields_value = array();
$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['order_metas'] = $meta_fields;
return $data_to_set;
}
public function process_v2() {
if ( 0 === intval( $this->data['order_id'] ) ) {
return $this->skipped_response( __( 'Order missing.', 'wp-marketing-automations-pro' ) );
}
$order = wc_get_order( intval( $this->data['order_id'] ) );
if ( ! $order instanceof WC_Order ) {
return $this->skipped_response( __( 'Not a WC order', 'wp-marketing-automations-pro' ) );
}
if ( empty( $this->data['order_metas'] ) ) {
return $this->skipped_response( __( 'Custom field(s) are required.', 'wp-marketing-automations-pro' ) );
}
foreach ( $this->data['order_metas'] as $meta_key => $meta_value ) {
$order->update_meta_data( $meta_key, $meta_value );
}
$order->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,
"placeholder" => __( 'Enter Field Key', 'wp-marketing-automations-pro' ),
],
[
"id" => 'field_value',
"label" => "",
"type" => 'text',
"class" => 'bwfan-input-wrapper',
"description" => "",
"required" => false,
"placeholder" => __( 'Enter Field value', 'wp-marketing-automations-pro' ),
]
],
'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_WC_Add_Custom_Field';

View File

@@ -0,0 +1,248 @@
<?php
final class BWFAN_WC_Add_Order_Note extends BWFAN_Action {
private static $ins = null;
protected function __construct() {
$this->action_name = __( 'Add Order Note', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This action adds an order note to the WC order', 'wp-marketing-automations-pro' );
$this->required_fields = array( 'order_id', 'body' );
$this->included_events = array(
'wc_new_order',
'wc_order_note_added',
'wc_order_status_change',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced',
'wc_order_status_pending',
);
$this->action_priority = 25;
$this->support_v2 = true;
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
/**
* 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() ); ?>">
<#
body = (_.has(data.actionSavedData, 'data') && _.has(data.actionSavedData.data, 'body')) ? data.actionSavedData.data.body : '';
note_type = (_.has(data.actionSavedData, 'data') && _.has(data.actionSavedData.data, 'note_type')) ? data.actionSavedData.data.note_type : '';
#>
<div class="bwfan-input-form clearfix">
<label for="" class="bwfan-label-title"><?php echo esc_html__( 'Order Note', 'wp-marketing-automations-pro' ); ?><?php echo $this->inline_merge_tag_invoke(); //phpcs:ignore WordPress.Security.EscapeOutput ?></label>
<div class="bwfan-col-sm-12 bwfan-pl-0 bwfan-pr-0">
<textarea required class="bwfan-input-wrapper" rows="4" placeholder="<?php echo esc_html__( 'Order Note', 'wp-marketing-automations-pro' ); ?>" name="bwfan[{{data.action_id}}][data][body]">{{body}}</textarea>
</div>
</div>
<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 bwfan-single-select" name="bwfan[{{data.action_id}}][data][note_type]">
<option {{ note_type===
'private' ? 'selected' : '' }} value="private"><?php echo esc_html__( 'Private', 'wp-marketing-automations-pro' ); ?></option>
<option {{ note_type===
'public' ? 'selected' : '' }} value="public"><?php echo esc_html__( 'Note to Customer', 'wp-marketing-automations-pro' ); ?></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 ) {
$this->set_data_for_merge_tags( $task_meta );
$body = $task_meta['data']['body'];
$note_type = $task_meta['data']['note_type'];
$body = BWFAN_Common::decode_merge_tags( $body );
$data_to_set = array();
$data_to_set['body'] = $body;
$data_to_set['note_type'] = $note_type;
foreach ( $task_meta['global'] as $key1 => $value1 ) {
$data_to_set[ $key1 ] = $value1;
}
return $data_to_set;
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = array();
$data_to_set['body'] = BWFAN_Common::decode_merge_tags( $step_data['body'] );
$data_to_set['note_type'] = $step_data['note_type'];
$email = ( isset( $automation_data['global']['email'] ) && is_email( $automation_data['global']['email'] ) ) ? $automation_data['global']['email'] : '';
$data_to_set['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : 0;
$user = is_email( $email ) ? get_user_by( 'email', $email ) : '';
$data_to_set['user_id'] = $user instanceof WP_User ? $user->ID : 0;
$data_to_set['email'] = $email;
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 $result;
}
/**
* 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();
}
$order = BWFAN_Merge_Tag_Loader::get_data( 'wc_order' );
if ( ! $order instanceof WC_Order ) {
return array(
'status' => 4,
'message' => __( 'Not a WooCommerce Order Object', 'wp-marketing-automations-pro' ),
);
}
$note = $this->data['body'];
$is_customer_note = 'public' === $this->data['note_type'] ? true : false;
if ( false === $is_customer_note ) {
/** Prefix adding when private note */
add_filter( 'woocommerce_new_order_note_data', array( $this, 'add_autonami_prefix_in_notes' ), 9999, 2 );
}
$order->add_order_note( $note, $is_customer_note );
if ( false === $is_customer_note ) {
remove_filter( 'woocommerce_new_order_note_data', array( $this, 'add_autonami_prefix_in_notes' ), 9999, 2 );
}
return true;
}
public function process_v2() {
$order_id = absint( $this->data['order_id'] );
$order = wc_get_order( $order_id );
if ( ! $order instanceof WC_Order ) {
return $this->skipped_response( __( 'WooCommerce Order not found', 'wp-marketing-automations-pro' ) );
}
$note = $this->data['body'];
$is_customer_note = 'public' === $this->data['note_type'] ? true : false;
if ( false === $is_customer_note ) {
/** Prefix adding when private note */
add_filter( 'woocommerce_new_order_note_data', array( $this, 'add_autonami_prefix_in_notes' ), 9999, 2 );
}
$order->add_order_note( $note, $is_customer_note );
if ( false === $is_customer_note ) {
remove_filter( 'woocommerce_new_order_note_data', array( $this, 'add_autonami_prefix_in_notes' ), 9999, 2 );
}
return $this->success_message( __( 'Order note added.', 'wp-marketing-automations-pro' ) );
}
/**
* Append Autonami prefix in notes so that can be identified the note is added by Autonami
*
* @param $note
* @param $data
*
* @return mixed
*/
public function add_autonami_prefix_in_notes( $note, $data ) {
if ( isset( $this->data['order_id'] ) && intval( $this->data['order_id'] ) === intval( $data['order_id'] ) ) {
$note['comment_content'] = 'FKA: ' . $note['comment_content'];
}
return $note;
}
public function get_fields_schema() {
return [
[
'id' => 'body',
'type' => 'textarea',
'label' => __( 'Order Note', 'wp-marketing-automations-pro' ),
'placeholder' => __( 'Order Note', 'wp-marketing-automations-pro' ),
'tip' => "",
"description" => "",
"required" => true,
],
[
'id' => 'note_type',
'type' => 'wp_select',
'label' => __( 'Note Type', 'wp-marketing-automations-pro' ),
'options' => [
[
'label' => __( 'Private', 'wp-marketing-automations-pro' ),
'value' => 'private'
],
[
'label' => __( 'Note to Customer', 'wp-marketing-automations-pro' ),
'value' => 'public'
],
],
'placeholder' => __( 'Choose Note Type', 'wp-marketing-automations-pro' ),
'tip' => "",
"description" => "",
"required" => true,
]
];
}
/** set default values */
public function get_default_values() {
return [
'note_type' => 'public',
];
}
public function get_desc_text( $data ) {
$data = json_decode( wp_json_encode( $data ), true );
if ( ! isset( $data['body'] ) || empty( $data['body'] ) ) {
return '';
}
return $data['body'];
}
}
return 'BWFAN_WC_Add_Order_Note';

View File

@@ -0,0 +1,215 @@
<?php
final class BWFAN_WC_Change_order_status extends BWFAN_Action {
private static $ins = null;
protected function __construct() {
$this->action_name = __( 'Change Order Status', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This action changes the WooCommerce order status', 'wp-marketing-automations-pro' );
$this->required_fields = array( 'order_id', 'status' );
$this->included_events = array(
'wc_new_order',
'wc_order_note_added',
'wc_order_status_change',
'wc_product_purchased',
'wc_product_refunded',
'wc_product_stock_reduced',
'wc_order_status_pending',
);
$this->action_priority = 15;
$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(), 'status_options', $data );
}
}
public function get_view_data() {
return wc_get_order_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_status = (_.has(data.actionSavedData, 'data') && _.has(data.actionSavedData.data, 'status')) ? data.actionSavedData.data.status : '';
#>
<div data-element-type="bwfan-select" class="bwfan-<?php echo esc_html__( $this->get_slug() ); ?>">
<label for="" class="bwfan-label-title"><?php echo esc_html__( 'Change Order Status To', 'wp-marketing-automations-pro' ); ?></label>
<select data-element-type="bwfan-select" required id="" class="bwfan-input-wrapper" name="bwfan[{{data.action_id}}][data][status]">
<option value=""><?php echo esc_html__( 'Choose Order Status', 'wp-marketing-automations-pro' ); ?></option>
<#
if(_.has(data.actionFieldsOptions, 'status_options') && _.isObject(data.actionFieldsOptions.status_options) ) {
_.each( data.actionFieldsOptions.status_options, function( value, key ){
selected = (key == selected_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 ) {
return array(
'status' => $task_meta['data']['status'],
'order_id' => $task_meta['global']['order_id'],
);
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = array();
$data_to_set['status'] = $step_data['status'];
$email = ( isset( $automation_data['global']['email'] ) && is_email( $automation_data['global']['email'] ) ) ? $automation_data['global']['email'] : '';
$data_to_set['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : 0;
$user = is_email( $email ) ? get_user_by( 'email', $email ) : '';
$data_to_set['user_id'] = $user instanceof WP_User ? $user->ID : 0;
$data_to_set['email'] = $email;
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' => 4,
'message' => __( 'Something went wrong', '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->change_status();
}
/**
* Change order status.
*
* order_id, status are required.
*
* @return array|bool
* @throws Exception
*/
public function change_status() {
$order = new WC_Order( $this->data['order_id'] );
add_filter( 'woocommerce_new_order_note_data', array( $this, 'add_autonami_prefix_in_notes' ), 9999, 2 );
$res = $order->update_status( $this->data['status'] );
remove_filter( 'woocommerce_new_order_note_data', array( $this, 'add_autonami_prefix_in_notes' ), 9999, 2 );
return $res;
}
public function process_v2() {
$order_id = absint( $this->data['order_id'] );
$order = wc_get_order( $order_id );
if ( ! $order instanceof WC_Order ) {
return $this->skipped_response( __( 'Not a WooCommerce Order Object', 'wp-marketing-automations-pro' ) );
}
$order->update_status( $this->data['status'] );
remove_filter( 'woocommerce_new_order_note_data', array( $this, 'add_autonami_prefix_in_notes' ), 9999, 2 );
return $this->success_message( __( 'Order status changed.', 'wp-marketing-automations-pro' ) );
}
public function add_autonami_prefix_in_notes( $note, $data ) {
if ( isset( $this->data['order_id'] ) && intval( $this->data['order_id'] ) === intval( $data['order_id'] ) ) {
$note['comment_content'] = 'FunnelKit Automations: ' . $note['comment_content'];
}
return $note;
}
public function get_fields_schema() {
$status = array_replace( [ '' => 'Select' ], $this->get_view_data() );
$options = BWFAN_PRO_Common::prepared_field_options( $status );
return [
[
'id' => 'status',
'label' => __( "Change Order Status To", 'wp-marketing-automations-pro' ),
'type' => 'wp_select',
'options' => $options,
'placeholder' => __( 'Choose Order Status', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper',
'tip' => "",
"description" => "",
"required" => true,
],
];
}
public function get_desc_text( $data ) {
$data = json_decode( wp_json_encode( $data ), true );
if ( ! isset( $data['status'] ) || empty( $data['status'] ) ) {
return '';
}
$status = $this->get_view_data();
return $status[ $data['status'] ];
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WC_Change_order_status';

View File

@@ -0,0 +1,623 @@
<?php
final class BWFAN_Pro_WC_Create_Coupon extends BWFAN_Action {
private static $ins = null;
protected function __construct() {
$this->action_name = __( 'Create Coupon', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This action creates a new personalized coupon for the customer', 'wp-marketing-automations-pro' );
$this->required_fields = array( 'coupon', 'coupon_name' );
$this->action_priority = 5;
$this->support_v2 = true;
$this->support_v1 = false;
}
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 $automation_data
* @param $step_data
*
* @return array|void
*/
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = array();
$data_to_set['email'] = $automation_data['global']['email'];
if ( ! isset( $step_data['coupon_data'] ) || empty( $step_data['coupon_data'] ) ) {
return;
}
$coupon_details = $step_data['coupon_data'];
$data_to_set['coupon'] = [];
$data_to_set['coupon_type'] = isset( $coupon_details['type'] ) ? $coupon_details['type'] : 'new';
$data_to_set['coupon']['prefix'] = isset( $coupon_details['general'] ) && isset( $coupon_details['general']['coupon_prefix'] ) ? BWFAN_Common::decode_merge_tags( $coupon_details['general']['coupon_prefix'] ) : '';
if ( $data_to_set['coupon_type'] === 'existing' ) {
$data_to_set['coupon_id'] = isset( $coupon_details['coupon_id'] ) && isset( $coupon_details['coupon_id']['key'] ) && ! empty( $coupon_details['coupon_id']['key'] ) ? $coupon_details['coupon_id']['key'] : '';
} else {
$data_to_set['coupon']['discount_type'] = isset( $coupon_details['general'] ) && isset( $coupon_details['general']['discount_type'] ) ? $coupon_details['general']['discount_type'] : 'percent';
$data_to_set['coupon']['coupon_amount'] = isset( $coupon_details['general'] ) && isset( $coupon_details['general']['amount'] ) ? $coupon_details['general']['amount'] : 0;
$data_to_set['coupon']['free_shipping'] = isset( $coupon_details['general'] ) && isset( $coupon_details['general']['allow_shipping'] ) ? $coupon_details['general']['allow_shipping'] : 0;
/** getting the restrictions info of the coupons */
if ( isset( $coupon_details['restrictions'] ) ) {
if ( isset( $coupon_details['restrictions']['min_spend'] ) ) {
$data_to_set['coupon']['minimum_amount'] = $coupon_details['restrictions']['min_spend'];
}
if ( isset( $coupon_details['restrictions']['max_spend'] ) ) {
$data_to_set['coupon']['maximum_amount'] = $coupon_details['restrictions']['max_spend'];
}
if ( isset( $coupon_details['restrictions']['exclude_sale_item'] ) ) {
$data_to_set['coupon']['exclude_sale_items'] = $coupon_details['restrictions']['exclude_sale_item'];
}
/** individual_use in coupon data */
if ( isset( $coupon_details['restrictions']['individual_use'] ) ) {
$data_to_set['coupon']['individual_use'] = $coupon_details['restrictions']['individual_use'];
}
/** restrict_customer_email in coupon data */
if ( isset( $coupon_details['restrictions']['restrict_customer_email'] ) ) {
$data_to_set['coupon']['restrict_customer_email'] = $coupon_details['restrictions']['restrict_customer_email'];
}
/** passing the product ids in coupon data */
if ( isset( $coupon_details['restrictions']['products'] ) && is_array( $coupon_details['restrictions']['products'] ) ) {
$data_to_set['coupon']['product_ids'] = array_map( function ( $product ) {
return isset( $product['id'] ) ? $product['id'] : "";
}, $coupon_details['restrictions']['products'] );
}
/** passing the excluded product ids in coupon data */
if ( isset( $coupon_details['restrictions']['exclude_products'] ) && is_array( $coupon_details['restrictions']['exclude_products'] ) ) {
$data_to_set['coupon']['exclude_product_ids'] = array_map( function ( $product ) {
return isset( $product['id'] ) ? $product['id'] : "";
}, $coupon_details['restrictions']['exclude_products'] );
}
/** passing the category ids in coupon data */
if ( isset( $coupon_details['restrictions']['categories'] ) && is_array( $coupon_details['restrictions']['categories'] ) ) {
$data_to_set['coupon']['product_categories'] = array_map( function ( $category ) {
return isset( $category['id'] ) ? $category['id'] : "";
}, $coupon_details['restrictions']['categories'] );
}
/** passing the excluded category ids in coupon data */
if ( isset( $coupon_details['restrictions']['exclude_categories'] ) && is_array( $coupon_details['restrictions']['exclude_categories'] ) ) {
$data_to_set['coupon']['exclude_product_categories'] = array_map( function ( $category ) {
return isset( $category['id'] ) ? $category['id'] : "";
}, $coupon_details['restrictions']['exclude_categories'] );
}
}
}
/** set the coupon expiry details */
if ( isset( $coupon_details['general'] ) && isset( $coupon_details['general']['expiry'] ) ) {
$data_to_set['coupon']['expiry'] = $coupon_details['general']['expiry'];
}
if ( isset( $coupon_details['general'] ) && isset( $coupon_details['general']['specific_expiry_type'] ) ) {
$data_to_set['coupon']['specific_expiry_type'] = $coupon_details['general']['specific_expiry_type'];
}
/** get details of the limit usage settings of coupon */
if ( isset( $coupon_details['limits'] ) ) {
if ( isset( $coupon_details['limits']['usage_limit_per_coupon'] ) ) {
$data_to_set['coupon']['usage_limit'] = $coupon_details['limits']['usage_limit_per_coupon'];
}
if ( isset( $coupon_details['limits']['usage_limit_per_user'] ) ) {
$data_to_set['coupon']['usage_limit_per_user'] = $coupon_details['limits']['usage_limit_per_user'];
}
if ( isset( $coupon_details['limits']['usage_limit_x_item'] ) ) {
$data_to_set['coupon']['limit_usage_to_x_items'] = $coupon_details['limits']['usage_limit_x_item'];
}
}
/** If opid (Optin form unique id) in automation data */
if ( isset( $automation_data['global']['opid'] ) ) {
$data_to_set['coupon']['opid'] = isset( $automation_data['global']['opid'] ) ? $automation_data['global']['opid'] : '';
}
if ( isset( $automation_data['global']['order_id'] ) ) {
$data_to_set['coupon']['order_id'] = isset( $automation_data['global']['order_id'] ) ? $automation_data['global']['order_id'] : '';
}
return $data_to_set;
}
public function process_v2() {
$data = $this->data;
$save = apply_filters( 'bwfan_save_coupon', false );
if ( $save ) {
/** Check if coupon is already saved in automation meta */
$coupon = $this->maybe_coupon_already_saved();
if ( ! empty( $coupon ) ) {
$data['coupon_name'] = $coupon;
$this->set_data( $data );
/** update new coupon value in automation contact row */
$automation_contact_id = $data['automation_contact_id'];
$this->update_automation_contact_row( $automation_contact_id, $coupon );
return $this->prepare_response( wc_get_coupon_id_by_code( $coupon ) );
}
}
/** Coupon name */
$coupon_prefix = $data['coupon']['prefix'];
$dynamic_string = BWFAN_Common::get_dynamic_string( 6 );
$coupon_name = $coupon_prefix . $dynamic_string;
/** set new coupon meta */
$new_coupon_meta['_is_bwfan_coupon'] = 1;
$new_coupon_meta['_bwfan_automation_id'] = $data['automation_id'];
$new_coupon_meta['_bwfan_step_id'] = $data['step_id'];
$new_coupon_meta['expiry_date'] = '';
$new_coupon_meta['date_expires'] = '';
$new_coupon_meta['customer_email'] = array();
$new_coupon_meta['usage_limit'] = isset( $data['coupon']['usage_limit'] ) ? $data['coupon']['usage_limit'] : '';
$specific_expiry_type = isset( $data['coupon']['specific_expiry_type'] ) ? intval( $data['coupon']['specific_expiry_type'] ) : 0;
/** set coupon expiry dates */
if ( $specific_expiry_type > 0 && $specific_expiry_type !== 3 && isset( $data['coupon']['expiry'] ) && ! empty( $data['coupon']['expiry'] ) && 0 < absint( $data['coupon']['expiry'] ) ) {
$expiry = $this->get_expiry_dates_v2( $data['coupon']['expiry'], $specific_expiry_type );
$new_coupon_meta['expiry_date'] = $expiry['expire_on'];
$new_coupon_meta['date_expires'] = $expiry['expiry_timestamped'];
}
if ( isset( $data['coupon_type'] ) && $data['coupon_type'] === 'existing' ) {
if ( ! isset( $data['coupon_id'] ) || empty( $data['coupon_id'] ) ) {
return $this->error_response( __( 'Coupon ID is required for existing coupon type', 'wp-marketing-automations-pro' ) );
}
$coupon_id = $data['coupon_id'];
$coupon = new WC_Coupon( $coupon_id );
if ( ! $coupon instanceof WC_Coupon ) {
return $this->error_response( __( 'Coupon does not exist', 'wp-marketing-automations-pro' ) );
}
/** creating new coupon */
$new_coupon_id = $this->create_coupon( $coupon_name, $new_coupon_meta );
if ( is_array( $new_coupon_id ) && count( $new_coupon_id ) > 0 ) {
/** Some error occurred while making coupon post */
return $this->prepare_response( $coupon_id );
}
$new_coupon = new WC_Coupon( $new_coupon_id );
// Get existing coupon meta
$existing_coupon_meta = get_post_meta( $coupon_id );
// Copy existing coupon meta to new coupon
foreach ( $existing_coupon_meta as $key => $values ) {
foreach ( $values as $value ) {
// Ensure to exclude core meta keys that should not be duplicated
if ( ! in_array( $key, array(
'_edit_lock',
'_edit_last',
'date_expires',
'usage_limit',
'usage_count',
'expiry_date',
'_is_bwfan_coupon',
'_bwfan_automation_id',
'_bwfan_step_id'
) ) ) {
add_post_meta( $new_coupon_id, $key, maybe_unserialize( $value ) );
}
}
}
if ( isset( $data['coupon']['limit_usage_to_x_items'] ) && ! empty( $data['coupon']['limit_usage_to_x_items'] ) ) {
$new_coupon->set_limit_usage_to_x_items( $data['coupon']['limit_usage_to_x_items'] );
}
if ( isset( $data['coupon']['usage_limit_per_user'] ) && ! empty( $data['coupon']['usage_limit_per_user'] ) ) {
$new_coupon->set_usage_limit_per_user( $data['coupon']['usage_limit_per_user'] );
}
// Save the new coupon
$new_coupon->save();
} else {
if ( ! isset( $data['coupon']['discount_type'] ) || ! array_key_exists( $data['coupon']['discount_type'], wc_get_coupon_types() ) ) {
return $this->error_response( __( 'Invalid discount type: ' . $data['coupon']['discount_type'], 'wp-marketing-automations-pro' ) );
}
/** creating new coupon */
$coupon_id = $this->create_coupon( $coupon_name, $new_coupon_meta );
if ( is_array( $coupon_id ) && count( $coupon_id ) > 0 ) {
/** Some error occurred while making coupon post */
return $this->prepare_response( $coupon_id );
}
/** restricted coupon with customer email */
if ( isset( $data['coupon']['restrict_customer_email'] ) && 1 === absint( $data['coupon']['restrict_customer_email'] ) ) {
$this->handle_coupon_restriction( $coupon_id, $data['email'] );
}
/** passing other coupon details */
$this->handle_other_coupon_restriction( $coupon_id, $data['coupon'] );
}
/** update new coupon value in automation contact row */
$automation_contact_id = $data['automation_contact_id'];
$this->update_automation_contact_row( $automation_contact_id, $coupon_name );
/** using special property to end the current automation process for a contact */
BWFAN_Common::$end_v2_current_contact_automation = true;
do_action( 'bwfan_coupon_created_v2', $coupon_id, $coupon_name, $data );
/** Set coupon name in data */
$data['coupon_name'] = $coupon_name;
$this->set_data( $data );
if ( $save ) {
/** Save coupon in optin form table or order meta */
$this->save_coupon_in_object( $coupon_name );
}
return $this->prepare_response( $coupon_id );
}
/**
* update new coupon value in automation contact row
*
* @param $automation_contact_id
* @param $coupon_name
*
* @return void
*/
public function update_automation_contact_row( $automation_contact_id, $coupon_name ) {
$row_data = $this->get_automation_contact_row( $automation_contact_id );
if ( empty( $row_data ) ) {
return;
}
$data = $this->data;
$coupons_data = isset( $row_data['coupons'] ) && is_array( $row_data['coupons'] ) ? $row_data['coupons'] : [];
$coupons_data[ $data['step_id'] ] = $coupon_name;
$row_data['coupons'] = $coupons_data;
BWFAN_Model_Automation_Contact::update( array(
'data' => json_encode( $row_data )
), array(
'ID' => $automation_contact_id,
) );
}
/**
* Save coupon in automation meta
*
* @param $coupon_name
*
* @return void
*/
public function save_coupon_in_object( $coupon_name ) {
$automation_sid = $this->data['step_id'];
$opid = isset( $this->data['coupon'] ) && isset( $this->data['coupon']['opid'] ) ? $this->data['coupon']['opid'] : '';
if ( ! empty( $opid ) ) {
$data = $this->get_optin_data( $opid );
$data['coupons'][ $automation_sid ] = $coupon_name;
global $wpdb;
$wpdb->update( "{$wpdb->prefix}bwf_optin_entries", [ 'data' => json_encode( $data ) ], [ 'opid' => $opid ] ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
return;
}
$order = wc_get_order( $this->data['coupon']['order_id'] );
if ( ! $order instanceof WC_Order ) {
return;
}
$coupons = $order->get_meta( 'bwfan_coupons' );
$coupons = is_array( $coupons ) ? $coupons : [];
$coupons[ $automation_sid ] = $coupon_name;
$order->update_meta_data( 'bwfan_coupons', $coupons );
$order->save_meta_data();
}
/**
* @param $opid
*
* @return array
*/
public function get_optin_data( $opid ) {
global $wpdb;
$optin_data = $wpdb->get_var( $wpdb->prepare( "SELECT `data` FROM {$wpdb->prefix}bwf_optin_entries WHERE `opid`=%s", $opid ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$optin_data = json_decode( $optin_data, true );
return ! is_array( $optin_data ) ? [] : $optin_data;
}
/**
* Get automation contact row data only
*
* @param $automation_contact_id
*
* @return mixed|void|null
*/
public function get_automation_contact_row( $automation_contact_id ) {
if ( empty( $automation_contact_id ) ) {
return;
}
$automation_contact_data = BWFAN_Model_Automation_Contact::get_data( $automation_contact_id );
if ( empty( $automation_contact_data ) ) {
return;
}
return json_decode( $automation_contact_data['data'], true );
}
public function handle_other_coupon_restriction( $coupon_id, $coupon_data ) {
if ( empty( $coupon_data ) ) {
return;
}
$coupon = new WC_Coupon( $coupon_id );
if ( ! $coupon instanceof WC_Coupon ) {
return;
}
/** set coupon type */
$coupon->set_discount_type( $coupon_data['discount_type'] );
$coupon->set_amount( $coupon_data['coupon_amount'] );
$coupon->set_free_shipping( $coupon_data['free_shipping'] );
if ( isset( $coupon_data['minimum_amount'] ) ) {
$coupon->set_minimum_amount( $coupon_data['minimum_amount'] );
}
if ( isset( $coupon_data['maximum_amount'] ) ) {
$coupon->set_maximum_amount( $coupon_data['maximum_amount'] );
}
if ( isset( $coupon_data['exclude_sale_items'] ) ) {
$coupon->set_exclude_sale_items( $coupon_data['exclude_sale_items'] );
}
if ( isset( $coupon_data['individual_use'] ) ) {
$coupon->set_individual_use( $coupon_data['individual_use'] );
}
if ( isset( $coupon_data['product_ids'] ) ) {
$coupon->set_product_ids( $coupon_data['product_ids'] );
}
if ( isset( $coupon_data['exclude_product_ids'] ) ) {
$coupon->set_excluded_product_ids( $coupon_data['exclude_product_ids'] );
}
if ( isset( $coupon_data['product_categories'] ) ) {
$coupon->set_product_categories( $coupon_data['product_categories'] );
}
if ( isset( $coupon_data['exclude_product_categories'] ) ) {
$coupon->set_excluded_product_categories( $coupon_data['exclude_product_categories'] );
}
if ( isset( $coupon_data['usage_limit'] ) ) {
$coupon->set_usage_limit( $coupon_data['usage_limit'] );
}
if ( isset( $coupon_data['usage_limit_per_user'] ) ) {
$coupon->set_usage_limit_per_user( $coupon_data['usage_limit_per_user'] );
}
if ( isset( $coupon_data['limit_usage_to_x_items'] ) ) {
$coupon->set_limit_usage_to_x_items( $coupon_data['limit_usage_to_x_items'] );
}
$coupon->save();
return $coupon;
}
/** set expiry date for newly created coupon
*
* @param $expiry
* @param $specific_expiry_type
*
* @return array
*/
public function get_expiry_dates_v2( $expiry, $specific_expiry_type ) {
$dbj = new DateTime();
if ( $specific_expiry_type == 2 ) { // in case specific date mention
$exptime = strtotime( strval( $expiry ) );
$dbj->setTimestamp( $exptime );
} else {
$expiry += 1;
$exptime = strtotime( "+{$expiry} days" );
$dbj->setTimestamp( $exptime );
}
$exp_date = $dbj->format( 'Y-m-d' );
$exp_date_email = date( 'Y-m-d', $exptime );
$expiry_timestamp = $exptime;
return array(
'expiry' => $exp_date,
'expire_on' => $exp_date_email,
'expiry_timestamped' => $expiry_timestamp,
);
}
public function create_coupon( $coupon_name, $meta_data ) {
$args = array(
'post_type' => 'shop_coupon',
'post_status' => 'publish',
'post_title' => $coupon_name,
);
$coupon_id = wp_insert_post( $args );
if ( ! is_wp_error( $coupon_id ) ) {
$meta_data['usage_count'] = 0;
if ( is_array( $meta_data ) && count( $meta_data ) > 0 ) {
foreach ( $meta_data as $key => $val ) {
update_post_meta( $coupon_id, $key, $val );
}
}
return $coupon_id;
}
return array(
'err_msg' => $coupon_id->get_error_message(),
);
}
public function prepare_response( $result ) {
if ( is_array( $result ) && count( $result ) > 0 ) { // Error in coupon creation
return $this->error_response( $result['err_msg'] );
}
if ( ! is_integer( $result ) ) {
return $this->error_response( __( 'Coupon does not exist', 'wp-marketing-automations-pro' ) );
}
$get_type = get_post_field( 'post_type', $result );
if ( 'shop_coupon' !== $get_type ) {
return $this->error_response( __( 'Coupon does not exist', 'wp-marketing-automations-pro' ) );
}
return $this->success_message( "Coupon {$this->data['coupon_name']} created." );
}
/**
* @param $coupon_id
* @param $email
*
* @return void|WC_Coupon
*/
public function handle_coupon_restriction( $coupon_id, $email ) {
if ( ! is_email( $email ) ) {
return;
}
$coupon = new WC_Coupon( $coupon_id );
if ( 0 === $coupon->get_id() ) {
return;
}
$coupon->set_email_restrictions( [ $email ] );
$coupon->save();
return $coupon;
}
/**
* 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 ( $this->fields_missing ) {
return array(
'status' => 4,
'message' => $result['body'][0],
);
}
if ( is_array( $result ) && count( $result ) > 0 ) { // Error in coupon creation
return array(
'status' => 4,
'message' => $result['err_msg'],
);
}
if ( ! is_integer( $result ) ) {
return array(
'status' => 4,
'message' => __( 'Coupon does not exist', 'wp-marketing-automations-pro' ),
);
}
$get_type = get_post_field( 'post_type', $result );
if ( 'shop_coupon' !== $get_type ) {
return array(
'status' => 4,
'message' => __( 'Coupon does not exist', 'wp-marketing-automations-pro' ),
);
}
return array(
'status' => 3,
'message' => "Coupon {$this->data['coupon_name']} created."
);
}
public function get_fields_schema() {
return [
[
'id' => 'coupon_data',
'type' => 'create_coupon',
'required' => true,
'coupon_type_options' => BWFAN_Common::prepared_field_options( wc_get_coupon_types() ),
]
];
}
public function get_desc_text( $data ) {
$data = json_decode( wp_json_encode( $data ), true );
if ( ! isset( $data['coupon_data'] ) || empty( $data['coupon_data'] ) || ! isset( $data['coupon_data']['general'] ) ) {
return '';
}
return isset( $data['coupon_data']['general']['title'] ) ? $data['coupon_data']['general']['title'] : '';
}
/**
* Get saved coupon in automation meta
*
* @return false|mixed
*/
public function maybe_coupon_already_saved() {
$sid = $this->data['step_id'];
$opid = $this->data['coupon']['opid'] ?? '';
$order_id = $this->data['coupon']['order_id'] ?? '';
if ( empty( $opid ) && empty( $order_id ) ) {
return false;
}
if ( ! empty( $opid ) ) {
$optin_data = $this->get_optin_data( $opid );
return $optin_data['coupons'][ $sid ] ?? '';
}
$order = wc_get_order( $order_id );
if ( ! $order instanceof WC_Order ) {
return false;
}
$coupons = $order->get_meta( 'bwfan_coupons' );
return $coupons[ $sid ] ?? '';
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_Pro_WC_Create_Coupon';

View File

@@ -0,0 +1,976 @@
<?php
if ( ! class_exists( 'BWFAN_WC_Create_Order' ) ) {
final class BWFAN_WC_Create_Order extends BWFAN_Action {
private static $ins = null;
protected function __construct() {
$this->action_name = __( 'Create Order', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This action creates a new WooCommerce order for a customer', 'wp-marketing-automations-pro' );
$this->action_priority = 7;
$this->support_v2 = true;
$this->support_v1 = false;
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
/**
* Generate the order data for processing
*
* @param array $automation_data
* @param array $step_data
*
* @return array
*/
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = [];
$data_to_set['status'] = $step_data['status'] ?? 'wc-on-hold';
$data_to_set['is_shipping_address'] = $step_data['is_shipping_address'] ?? 'same_as_billing';
/** Validate and set email */
$email = isset( $step_data['billing_email'] ) ? BWFAN_Common::decode_merge_tags( $step_data['billing_email'] ) : '';
$user = is_email( $email ) ? get_user_by( 'email', $email ) : '';
$data_to_set['customer_id'] = $user instanceof WP_User ? $user->ID : 0;
/** Set products */
$data_to_set['products'] = $step_data['products'] ?? [];
/** Set billing and shipping information */
$data_to_set['billing'] = self::get_billing_addresses( $step_data, $email );
$data_to_set['shipping'] = self::get_shipping_addresses( $step_data );
$data_to_set['order_note'] = BWFAN_Common::decode_merge_tags( $step_data['order_note'] ) ?? '';
/** Payment method */
$data_to_set['payment_method'] = BWFAN_Common::decode_merge_tags( $step_data['payment_method'] ) ?? '';
$data_to_set['shipping_methods'] = BWFAN_Common::decode_merge_tags( $step_data['shipping_methods'] ) ?? '';
$data_to_set['shipping_cost'] = isset( $step_data['shipping_cost'] ) ? BWFAN_Common::decode_merge_tags( $step_data['shipping_cost'] ) : '';
$data_to_set['contact_id'] = $automation_data['global']['contact_id'] ?? $automation_data['global']['cid'] ?? 0;
$data_to_set['bwfan_coupons'] = self::check_for_available_coupons( $step_data );
$data_to_set['skip_order_if_products'] = isset( $step_data['skip_order_if_products'] ) && (bool) $step_data['skip_order_if_products'];
$data_to_set['order_custom_fields'] = ! empty( $step_data['order_custom_fields'] ) ? $step_data['order_custom_fields'] : [];
return $data_to_set;
}
/**
* Process the order creation
*
* @return array
*/
public function process_v2() {
if ( ! function_exists( 'wc_create_order' ) ) {
return $this->error_response( __( '`wc_create_order` function is missing.', 'wp-marketing-automations-pro' ) );
}
$order_data = $this->data;
if ( ! isset( $order_data['products'] ) || empty( $order_data['products'] ) ) {
return $this->skipped_response( __( 'No products found. Add at least one product to proceed with the order.', 'wp-marketing-automations-pro' ) );
}
/** Validate email */
if ( empty( $order_data['billing']['email'] ) || ! is_email( $order_data['billing']['email'] ) ) {
return $this->error_response( __( 'Invalid or missing email address.', 'wp-marketing-automations-pro' ) );
}
$product_validation = self::validate_order_products( $order_data['products'] );
if ( empty( $product_validation ) ) {
return $this->error_response( __( 'Order not created. No valid products found.', 'wp-marketing-automations-pro' ) );
}
if ( isset( $order_data['skip_order_if_products'] ) && $order_data['skip_order_if_products'] && count( $product_validation ) !== count( $order_data['products'] ) ) {
return $this->skipped_response( __( 'Order not created. Some products are invalid or missing.', 'wp-marketing-automations-pro' ) );
}
$args = array(
'created_via' => __( 'Order created via FunnelKit Automations.', 'wp-marketing-automations-pro' ),
'customer_id' => $order_data['customer_id'],
);
$order = wc_create_order( $args );
if ( is_wp_error( $order ) ) {
return $this->error_response( __( 'Failed to create order: ', 'wp-marketing-automations-pro' ) . $order->get_error_message() );
}
/** Add validated products */
foreach ( $product_validation as $item ) {
$order->add_product( $item['product'], $item['quantity'], isset( $item['price'] ) ? [ 'totals' => [ 'subtotal' => $item['price'], 'total' => $item['price'] ] ] : [] );
}
/** Set addresses */
$order->set_address( $order_data['billing'] );
if ( 'same_as_billing' === $order_data['is_shipping_address'] ) {
$order->set_address( $order_data['billing'], 'shipping' );
} elseif ( 'different_shipping_address' === $order_data['is_shipping_address'] ) {
$order->set_address( $order_data['shipping'], 'shipping' );
}
/** Set shipping methods */
if ( ! empty( $order_data['shipping_methods'] ) ) {
$shipping_method_id = is_array( $order_data['shipping_methods'] ) ? reset( $order_data['shipping_methods'] ) : $order_data['shipping_methods'];
$shipping_method = $this->set_shipping_method( $shipping_method_id, $order_data['shipping_cost'] );
if ( ! empty( $shipping_method ) ) {
$order->add_item( $shipping_method );
}
}
// Calculate totals after adding products and shipping methods
$order->calculate_totals();
/** Add coupons */
if ( ! empty( $order_data['bwfan_coupons'] ) && is_array( $order_data['bwfan_coupons'] ) ) {
foreach ( $order_data['bwfan_coupons'] as $coupon_code ) {
try {
$result = $order->apply_coupon( $coupon_code );
if ( is_wp_error( $result ) ) {
$error_message = $result->get_error_message();
BWFAN_Common::log_test_data( sprintf( 'Coupon "%s" failed to apply on Order #%d: %s', $coupon_code, $order->get_id(), $error_message ), 'fka_order_created_log', true );
}
} catch ( Error $e ) {
return $this->skipped_response( sprintf( __( 'Order #%d was created but further processing was skipped due to coupon error: %s', 'wp-marketing-automations-pro' ), $order->get_id(), $e->getMessage() ) );
}
}
}
/** Add custom fields */
if ( ! empty( $order_data['order_custom_fields'] ) ) {
foreach ( $order_data['order_custom_fields'] as $field ) {
if ( ! empty( $field['field'] ) && ! empty( $field['field_value'] ) ) {
$order->update_meta_data( $field['field'], BWFAN_Common::decode_merge_tags( $field['field_value'] ) );
}
}
}
/** Set order note */
$order->add_order_note( $args['created_via'] );
/** Set payment method */
$order->set_payment_method( $order_data['payment_method'] );
/** Add order note */
if ( isset( $order_data['order_note'] ) && ! empty( trim( $order_data['order_note'] ) ) ) {
$order->add_order_note( $order_data['order_note'] );
}
/** Set contact ID */
$order->update_meta_data( '_woofunnel_cid', $order_data['contact_id'] ?? 0 );
/** set status */
$order->update_status( $order_data['status'] );
$order->save();
do_action( 'bwfan_order_created', $order, $order->get_id(), $order_data );
return $this->success_message( __( 'Order created successfully.', 'wp-marketing-automations-pro' ) );
}
/**
* Check for available coupons
*
* @param $data
*
* @return array
*/
public static function check_for_available_coupons( $data ) {
if ( ! isset( $data['couponType'] ) ) {
return [];
}
$coupons = [];
switch ( $data['couponType'] ) {
case 'static':
if ( ! empty( $data['bwfan_coupons'] ) || ! is_array( $data['bwfan_coupons'] ) ) {
foreach ( $data['bwfan_coupons'] as $coupon ) {
if ( ! empty( $coupon['name'] ) ) {
$coupons[] = wc_format_coupon_code( BWFAN_Common::decode_merge_tags( $coupon['name'] ) );
}
}
}
break;
case 'dynamic':
if ( ! empty( $data['dynamic_coupon'] ) ) {
$dynamic_coupon = explode( ',', $data['dynamic_coupon'] );
foreach ( $dynamic_coupon as $coupon ) {
$coupons[] = ! empty( $coupon ) ? wc_format_coupon_code( BWFAN_Common::decode_merge_tags( $coupon ) ) : '';
}
}
break;
default:
return [];
}
return array_filter( $coupons );
}
/**
* @param $method_id
* @param $shipping_cost
*
* @return WC_Order_Item_Shipping|null
*/
private function set_shipping_method( $method_id, $shipping_cost ) {
if ( ! class_exists( '\WC_Order_Item_Shipping' ) ) {
return null;
}
$shipping_methods = $this->get_available_shipping_methods();
if ( empty( $shipping_methods[ $method_id ] ) ) {
return null;
}
$item = new \WC_Order_Item_Shipping();
try {
$item->set_method_title( $shipping_methods[ $method_id ] );
$item->set_method_id( $method_id );
$item->set_total( floatval( $shipping_cost ) );
} catch ( \Exception $e ) {
$item = null;
}
return $item;
}
/**
* @param $products_data
*
* @return array
*/
public static function validate_order_products( $products_data ) {
$valid_products = [];
$invalid_products = [];
if ( empty( $products_data ) || ! is_array( $products_data ) ) {
BWFAN_Common::log_test_data( __( 'No products found. Add at least one product to proceed with the order.', 'wp-marketing-automations-pro' ), 'order_creation_errors', true );
return $valid_products;
}
foreach ( $products_data as $product_group ) {
if ( ! isset( $product_group['products'] ) || ! is_array( $product_group['products'] ) ) {
BWFAN_Common::log_test_data( __( 'Invalid product group: products array missing or invalid', 'wp-marketing-automations-pro' ), 'order_creation_errors', true );
continue;
}
foreach ( $product_group['products'] as $product ) {
$product_id = is_string( $product['id'] ) ? BWFAN_Common::decode_merge_tags( $product['id'] ) : $product['id'];
if ( ! is_numeric( $product_id ) ) {
$invalid_products[] = $product['id'];
BWFAN_Common::log_test_data( sprintf( __( 'Non-numeric product ID: "%s" (decoded: "%s")', 'wp-marketing-automations-pro' ), $product['id'], $product_id ), 'order_creation_errors', true );
continue;
}
$product_obj = wc_get_product( $product_id );
if ( ! $product_obj || ! $product_obj->exists() ) {
$invalid_products[] = $product['id'];
BWFAN_Common::log_test_data( sprintf( __( 'Product does not exist: %d', 'wp-marketing-automations-pro' ), $product_id ), 'order_creation_errors', true );
continue;
}
$product_data = [
'product' => $product_obj,
'quantity' => isset( $product_group['quantity'] ) && intval( $product_group['quantity'] ) > 0 ? floatval( $product_group['quantity'] ) : 1,
];
if ( isset( $product_group['price'] ) && '' !== $product_group['price'] ) {
$product_data['price'] = floatval( $product_group['price'] ) * $product_data['quantity'];
}
$valid_products[] = $product_data;
}
}
return $valid_products;
}
/**
* Returns decoded billing data
*
* @param $step_data
* @param $email
*
* @return array
*/
static function get_billing_addresses( $step_data, $email ) {
$country = BWFAN_Common::decode_merge_tags( $step_data['billing_country'][0]['id'] ?? '' );
$code = $step_data['billing_state'][0]['id'] ?? '';
$state_name = $step_data['billing_state'][0]['name'] ?? '';
$state = self::validate_state_for_country( $code, $country, $state_name );
return [
'first_name' => BWFAN_Common::decode_merge_tags( $step_data['billing_first_name'] ?? '' ),
'last_name' => BWFAN_Common::decode_merge_tags( $step_data['billing_last_name'] ?? '' ),
'company' => BWFAN_Common::decode_merge_tags( $step_data['billing_company'] ?? '' ),
'address_1' => BWFAN_Common::decode_merge_tags( $step_data['billing_address_line_1'] ?? '' ),
'address_2' => BWFAN_Common::decode_merge_tags( $step_data['billing_address_line_2'] ?? '' ),
'city' => BWFAN_Common::decode_merge_tags( $step_data['billing_city'] ?? '' ),
'postcode' => BWFAN_Common::decode_merge_tags( $step_data['billing_postcode'] ?? '' ),
'country' => $country,
'state' => $state,
'email' => $email,
'phone' => BWFAN_Common::decode_merge_tags( $step_data['billing_phone_no'] ?? '' ),
];
}
/**
* Returns decoded shipping addresses
*
* @param $step_data
*
* @return array
*/
static function get_shipping_addresses( $step_data ) {
$country = BWFAN_Common::decode_merge_tags( $step_data['shipping_country'][0]['id'] ?? '' );
$code = $step_data['shipping_state'][0]['id'] ?? '';
$state_name = $step_data['shipping_state'][0]['name'] ?? '';
$state = self::validate_state_for_country( $code, $country, $state_name );
return [
'first_name' => BWFAN_Common::decode_merge_tags( $step_data['shipping_first_name'] ?? '' ),
'last_name' => BWFAN_Common::decode_merge_tags( $step_data['shipping_last_name'] ?? '' ),
'company' => BWFAN_Common::decode_merge_tags( $step_data['shipping_company'] ?? '' ),
'address_1' => BWFAN_Common::decode_merge_tags( $step_data['shipping_address_line_1'] ?? '' ),
'address_2' => BWFAN_Common::decode_merge_tags( $step_data['shipping_address_line_2'] ?? '' ),
'city' => BWFAN_Common::decode_merge_tags( $step_data['shipping_city'] ?? '' ),
'postcode' => BWFAN_Common::decode_merge_tags( $step_data['shipping_postcode'] ?? '' ),
'country' => $country,
'state' => BWFAN_Common::decode_merge_tags( $state ),
'phone' => BWFAN_Common::decode_merge_tags( $step_data['shipping_phone_no'] ?? '' ),
];
}
/**
* Validate if state exists for the given country
*
* @param string $state_code
* @param string $country
* @param string $state_name
*
* @return string
*/
static function validate_state_for_country( $state_code, $country, $state_name ) {
if ( empty( $country ) ) {
return '';
}
$states = WC()->countries->get_states( $country );
if ( empty( $states ) ) {
return $state_name;
}
return isset( $states[ $state_code ] ) ? $state_code : '';
}
/**
* Added Field schema
*/
public function get_fields_schema() {
$status = BWFAN_PRO_Common::prepared_field_options( wc_get_order_statuses() );
$set_payment_gateways = array_replace( [ '' => 'N/A' ], self:: payment_gateways() );
$payment_gateways = BWFAN_PRO_Common::prepared_field_options( $set_payment_gateways );
$schema = [
[
'id' => 'products',
'label' => __( 'Products', 'wp-marketing-automations-pro' ),
'type' => 'repeater',
'add_btn_text' => __( 'Add Product', 'wp-marketing-automations-pro' ),
'class' => 'bwf-repeater-alter-w',
'required' => true,
"hint" => __( "Quantity and price are optional. If left blank, a quantity of 1 and the product's default unit price will be applied.", 'wp-marketing-automations-pro' ),
'tip' => __( 'Select products or use merge tag (e.g., {{product_id}}) to dynamically set the product during order creation.', 'wp-marketing-automations-pro' ),
'fields' => [
[
'id' => 'products',
'type' => 'custom_search',
'autocompleterOption' => [
'path' => 'wc_new_order_product',
'slug' => 'wc_new_order_product',
'labelText' => __( 'Product', 'wp-marketing-automations-pro' ),
'freeTextLabel' => __( 'Use merge tag {{query /}} to dynamically insert a product ID', 'wp-marketing-automations-pro' ),
],
'label' => __( 'Product', 'wp-marketing-automations-pro' ),
"allowFreeTextSearch" => true,
"multiple" => false,
],
[
'id' => 'quantity',
'type' => 'number',
'label' => __( 'Quantity', 'wp-marketing-automations-pro' ),
'placeholder' => __( 'Quantity', 'wp-marketing-automations-pro' ),
'min' => 1,
'default' => 1,
],
[
'id' => 'price',
'type' => 'number',
'label' => __( 'Price', 'wp-marketing-automations-pro' ),
'placeholder' => __( 'Price', 'wp-marketing-automations-pro' ),
],
],
],
[
'id' => 'skip_order_if_products',
'type' => 'checkbox',
'checkboxlabel' => __( 'Skip order creation if all product line items fail to add', 'wp-marketing-automations-pro' ),
'description' => '',
],
[
'id' => 'billing_email',
'label' => __( 'Email', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'Email', 'wp-marketing-automations-pro' ),
'class' => 'bwfan-input-wrapper bwfan-field-crm_create_contact bwf-2-col-item',
'description' => '',
'required' => true,
'automation_merge_tags' => true
],
[
'id' => 'billing_phone_no',
'label' => __( 'Billing Phone', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'Phone', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
],
[
'id' => 'billing_first_name',
'label' => __( 'Billing First Name', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'First Name', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-3-col-item',
'description' => '',
'required' => false,
],
[
'id' => 'billing_last_name',
'label' => __( 'Billing Last Name', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'last Name', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-3-col-item',
'description' => '',
'required' => false,
],
[
'id' => 'billing_company',
'label' => __( 'Billing Company', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'Company', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-3-col-item',
'description' => '',
'required' => false,
],
[
'id' => 'billing_address_line_1',
'label' => __( 'Billing Address 1', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'Address 1', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
],
[
'id' => 'billing_address_line_2',
'label' => __( 'Billing Address 2', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'Address 2', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
],
[
'id' => 'billing_city',
'label' => __( 'Billing City', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'City', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
],
[
'id' => 'billing_postcode',
'label' => __( 'Billing Postcode / ZIP', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'Postcode / ZIP', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
],
[
'id' => 'billing_country',
'label' => __( 'Billing Country / Region', 'wp-marketing-automations-pro' ),
"type" => 'custom_search',
'autocompleterOption' => [
'path' => 'wc_countries',
'slug' => 'wc_countries',
'labelText' => __( 'Countries', 'wp-marketing-automations-pro' ),
],
"allowFreeTextSearch" => false,
"multiple" => false,
"class" => 'bwfan-input-wrapper bwf-2-col-item',
],
[
'id' => 'billing_state',
'label' => __( 'Billing State / Province', 'wp-marketing-automations-pro' ),
"type" => 'custom_search',
'autocompleterOption' => [
'path' => 'wc_states',
'slug' => 'wc_states',
'labelText' => __( 'States', 'wp-marketing-automations-pro' ),
'extraData' => [
'country' => 'billing_country'
]
],
"allowFreeTextSearch" => true,
"multiple" => false,
"class" => 'bwfan-input-wrapper bwf-2-col-item',
],
[
'id' => 'payment_method',
'label' => __( 'Payment method', 'wp-marketing-automations-pro' ),
'type' => 'wp_select',
'options' => $payment_gateways,
'placeholder' => __( 'Payment method', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
],
];
/** Shipping field if active */
$shipping_methods = $this->get_available_shipping_methods();
if ( ! empty( $shipping_methods ) ) {
$set_shipping_methods = array_replace( [ '' => 'N/A' ], $shipping_methods );
$shipping_methods = BWFAN_PRO_Common::prepared_field_options( $set_shipping_methods );
$schema[] = [
'id' => 'shipping_methods',
'label' => __( 'Shipping Methods', 'wp-marketing-automations-pro' ),
'type' => 'wp_select',
'options' => $shipping_methods,
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
];
$schema[] = [
'id' => 'shipping_cost',
'label' => __( 'Shipping Cost', 'wp-marketing-automations-pro' ),
'type' => 'number',
'min' => 0,
'placeholder' => __( 'Enter', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
"toggler" => [
'fields' => [
[
'id' => 'shipping_methods',
'value' => '',
]
],
],
];
}
/** Coupon fields if active */
$coupons_enabled = get_option( 'woocommerce_enable_coupons' ) === 'yes';
if ( $coupons_enabled ) {
$coupon_schema = [
[
'id' => 'couponType',
'label' => __( 'Coupon Type', 'wp-marketing-automations-pro' ),
'type' => 'radio',
'options' => [
[
'label' => __( 'Store Coupon', 'wp-marketing-automations-pro' ),
'value' => 'static'
],
[
'label' => __( 'Dynamic Coupon', 'wp-marketing-automations-pro' ),
'value' => 'dynamic'
],
],
],
[
'id' => 'bwfan_coupons',
'label' => __( "Coupon", 'wp-marketing-automations-pro' ),
'type' => 'search',
'autocompleter' => 'coupons',
"multiple" => true,
"required" => false,
"toggler" => [
'fields' => [
[
'id' => 'couponType',
'value' => 'static',
]
]
],
],
[
'id' => 'dynamic_coupon',
'label' => __( 'Dynamic Coupon', 'wp-marketing-automations-pro' ),
'type' => 'text',
"class" => 'bwfan-input-wrapper ',
'hint' => __( 'Use comma seperated values for multiple options.', 'wp-marketing-automations-pro' ),
"description" => "",
"placeholder" => __( 'Dynamic coupon merge tag', 'wp-marketing-automations-pro' ),
"required" => false,
'toggler' => [
'fields' => [
[
'id' => 'couponType',
'value' => 'dynamic',
]
]
],
]
];
$schema = array_merge( $schema, $coupon_schema );
}
$schema = array_merge( $schema, [
[
'id' => 'status',
'label' => __( "Order Status", 'wp-marketing-automations-pro' ),
'type' => 'wp_select',
'options' => $status,
'placeholder' => __( 'Status', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper ',
'tip' => "",
"description" => "",
"required" => true,
],
[
'id' => 'order_note',
'label' => __( 'Order Note', 'wp-marketing-automations-pro' ),
'type' => 'text',
"class" => 'bwfan-input-wrapper ',
'tip' => "",
"description" => "",
"placeholder" => __( 'Note text', 'wp-marketing-automations-pro' ),
"required" => false,
]
] );
if ( $this->is_shipping_active() ) {
$schema = array_merge( $schema, [
[
'id' => 'is_shipping_address',
'label' => __( 'Shipping Address', 'wp-marketing-automations-pro' ),
'type' => 'radio',
'options' => [
[
'label' => __( 'Same as Billing', 'wp-marketing-automations-pro' ),
'value' => 'same_as_billing'
],
[
'label' => __( 'Different Shipping Address', 'wp-marketing-automations-pro' ),
'value' => 'different_shipping_address'
],
],
],
[
'id' => 'shipping_first_name',
'label' => __( 'Shipping First Name', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'First Name', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-3-col-item',
'description' => '',
'required' => false,
'toggler' => [
'fields' => [
[
'id' => 'is_shipping_address',
'value' => 'different_shipping_address',
]
]
],
],
[
'id' => 'shipping_last_name',
'label' => __( 'Shipping Last Name', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'last Name', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-3-col-item',
'description' => '',
'required' => false,
'toggler' => [
'fields' => [
[
'id' => 'is_shipping_address',
'value' => 'different_shipping_address',
]
]
],
],
[
'id' => 'shipping_company',
'label' => __( 'Shipping Company', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'Company', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-3-col-item',
'description' => '',
'required' => false,
'toggler' => [
'fields' => [
[
'id' => 'is_shipping_address',
'value' => 'different_shipping_address',
]
]
],
],
[
'id' => 'shipping_address_line_1',
'label' => __( 'Shipping Address 1', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'Address 1', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
'toggler' => [
'fields' => [
[
'id' => 'is_shipping_address',
'value' => 'different_shipping_address',
]
]
],
],
[
'id' => 'shipping_address_line_2',
'label' => __( 'Shipping Address 2', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'Address 2', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
'toggler' => [
'fields' => [
[
'id' => 'is_shipping_address',
'value' => 'different_shipping_address',
]
]
],
],
[
'id' => 'shipping_city',
'label' => __( 'Shipping City', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'City', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
'toggler' => [
'fields' => [
[
'id' => 'is_shipping_address',
'value' => 'different_shipping_address',
]
]
],
],
[
'id' => 'shipping_postcode',
'label' => __( 'Shipping Postcode / ZIP', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'Postcode / ZIP', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
'toggler' => [
'fields' => [
[
'id' => 'is_shipping_address',
'value' => 'different_shipping_address',
]
]
],
],
[
'id' => 'shipping_country',
'label' => __( 'Shipping Country / Region', 'wp-marketing-automations-pro' ),
"type" => 'custom_search',
'autocompleterOption' => [
'path' => 'wc_countries',
'slug' => 'wc_countries',
'labelText' => __( 'Countries', 'wp-marketing-automations-pro' ),
],
"allowFreeTextSearch" => false,
"multiple" => false,
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'toggler' => [
'fields' => [
[
'id' => 'is_shipping_address',
'value' => 'different_shipping_address',
]
]
],
],
[
'id' => 'shipping_state',
'label' => __( 'Shipping State / Province', 'wp-marketing-automations-pro' ),
"type" => 'custom_search',
'autocompleterOption' => [
'path' => 'wc_states',
'slug' => 'wc_states',
'labelText' => __( 'States', 'wp-marketing-automations-pro' ),
'extraData' => [
'country' => 'shipping_country'
]
],
"allowFreeTextSearch" => true,
"multiple" => false,
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'toggler' => [
'fields' => [
[
'id' => 'is_shipping_address',
'value' => 'different_shipping_address',
]
]
],
],
[
'id' => 'shipping_phone_no',
'label' => __( 'Shipping Phone', 'wp-marketing-automations-pro' ),
'type' => 'text',
'placeholder' => __( 'Phone', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper bwf-2-col-item',
'description' => '',
'required' => false,
'toggler' => [
'fields' => [
[
'id' => 'is_shipping_address',
'value' => 'different_shipping_address',
]
]
],
]
] );
}
return array_merge( $schema, [
[
'id' => 'order_custom_fields',
'type' => 'repeater',
'add_btn_text' => __( 'Add Field', 'wp-marketing-automations-pro' ),
'label' => __( 'Custom Meta Fields', 'wp-marketing-automations-pro' ),
"fields" => [
[
'id' => 'field',
'type' => 'text',
'label' => __( 'Field Key', 'wp-marketing-automations-pro' ),
'tip' => "",
"description" => "",
"required" => false,
"placeholder" => __( 'Field Key (e.g., custom_label)', 'wp-marketing-automations-pro' ),
],
[
"id" => 'field_value',
"label" => __( 'Field Value', 'wp-marketing-automations-pro' ),
"type" => 'text',
"class" => 'bwfan-input-wrapper',
"description" => "",
"required" => false,
"placeholder" => __( 'Field Value (e.g., 1234 or info@example.com)', 'wp-marketing-automations-pro' ),
]
],
'tip' => "",
"description" => "",
'wrap_after' => wc_tax_enabled() ? '<div class="bwf-single-automation-notice is-info bwf-mt-8">' . __( 'Tax will be automatically calculated and applied based on the order details at the time of creation.', 'wp-marketing-automations-pro' ) . '</div>' : '',
],
] );
}
/**
* @return array
* Added Default value
*/
public function get_default_values() {
return [
'billing_email' => '{{contact_email}}',
'billing_first_name' => '{{contact_first_name}}',
'billing_last_name' => '{{contact_last_name}}',
'billing_company' => '{{contact_company}}',
'billing_phone_no' => '{{contact_phone}}',
'shipping_first_name' => '{{contact_first_name}}',
'shipping_last_name' => '{{contact_last_name}}',
'shipping_company' => '{{contact_company}}',
'shipping_phone_no' => '{{contact_phone}}',
'is_shipping_address' => 'same_as_billing',
'couponType' => 'static',
'status' => 'wc-pending',
'order_custom_fields' => [],
];
}
/**
* Helper method to get available shipping methods
*/
private function get_available_shipping_methods() {
if ( ! $this->is_shipping_active() ) {
return [];
}
$methods = [];
$zones = WC_Shipping_Zones::get_zones();
foreach ( $zones as $zone ) {
foreach ( $zone['shipping_methods'] as $method ) {
if ( $method->is_enabled() ) {
$methods[ $method->id ] = $method->get_title();
}
}
}
// Check default zone (zone 0)
$default_zone = WC_Shipping_Zones::get_zone( 0 );
foreach ( $default_zone->get_shipping_methods() as $method ) {
if ( $method->is_enabled() ) {
$methods[ $method->id ] = $method->get_title();
}
}
return $methods;
}
private function is_shipping_active() {
$woocommerce_ship_to_countries = get_option( 'woocommerce_ship_to_countries' );
return 'disabled' !== $woocommerce_ship_to_countries;
}
/**
* @return array
*/
static function payment_gateways() {
$result = array();
foreach ( WC()->payment_gateways()->payment_gateways() as $gateway ) {
if ( 'yes' === $gateway->enabled ) {
$result[ $gateway->id ] = $gateway->get_title();
$result[ $gateway->id ] = $gateway->get_title();
}
}
return $result;
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WC_Create_Order';
}

View File

@@ -0,0 +1,283 @@
<?php
final class BWFAN_WC_Remove_Coupon extends BWFAN_Action {
private static $ins = null;
protected function __construct() {
$this->action_name = __( 'Delete Coupon', 'wp-marketing-automations-pro' );
$this->action_desc = __( 'This action deletes a WooCommerce coupon', 'wp-marketing-automations-pro' );
$this->required_fields = array( 'coupon_name' );
$this->support_v2 = true;
$this->action_priority = 10;
}
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
/**
* 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() ); ?>">
<#
entered_coupon_name = (_.has(data.actionSavedData, 'data') && _.has(data.actionSavedData.data, 'coupon_name')) ? data.actionSavedData.data.coupon_name : '';
#>
<div class="bwfan-input-form clearfix">
<label for="" class="bwfan-label-title">
<?php echo esc_html__( 'Coupon Name', 'wp-marketing-automations-pro' ); ?>
<?php echo $this->inline_merge_tag_invoke(); //phpcs:ignore WordPress.Security.EscapeOutput ?>
</label>
<input required type="text" class="bwfan-input-wrapper" name="bwfan[{{data.action_id}}][data][coupon_name]" value="{{entered_coupon_name}}"/>
</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 ) {
$this->set_data_for_merge_tags( $task_meta );
$data_to_set = array();
$data_to_set['email'] = $task_meta['global']['email'];
$data_to_set['coupon_name'] = BWFAN_Common::decode_merge_tags( $task_meta['data']['coupon_name'] );
return $data_to_set;
}
public function make_v2_data( $automation_data, $step_data ) {
$data_to_set = array();
$type = isset( $step_data['coupon_type'] ) ? $step_data['coupon_type'] : 'static';
$coupon_name = '';
switch ( $type ) {
case 'static':
if ( isset( $step_data['coupon_name'] ) && ! empty( $step_data['coupon_name'] ) ) {
$coupon_name = $step_data['coupon_name'];
}
break;
case 'dynamic':
if ( isset( $step_data['dynamic_coupon_id'] ) && ! empty( $step_data['dynamic_coupon_id'] ) ) {
$coupon_name = '{{wc_dynamic_coupon id="' . $step_data['dynamic_coupon_id'] . '"}}';
}
}
$data_to_set['coupon_name'] = BWFAN_Common::decode_merge_tags( $coupon_name );
$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;
}
/**
* 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 ( $this->fields_missing ) {
return array(
'status' => 4,
'message' => $result['body'][0],
);
}
if ( is_array( $result ) && count( $result ) > 0 ) { // Error in coupon deletion, coupon does not exists.
$status = array(
'status' => 3,
'message' => $result['err_msg'],
);
return $status;
}
return array(
'status' => 3,
'message' => "Coupon {$this->data['coupon_name']} deleted.",
);
}
/**
* 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 ) {
$this->fields_missing = true;
return $this->show_fields_error();
}
$data = $this->data;
$coupon_name = $data['coupon_name'];
$coupon = new WC_Coupon( $coupon_name );
$coupon_id = $coupon->get_id();
if ( 0 === $coupon_id ) { // Coupon does not exists
return [
'err_msg' => __( 'Coupon does not exists', 'wp-marketing-automations-pro' )
];
}
$coupons_email = $coupon->get_email_restrictions();
if ( is_array( $coupons_email ) && count( $coupons_email ) > 0 ) {
$index = array_search( $data['email'], $coupons_email, true );
if ( false !== $index ) {
unset( $coupons_email[ $index ] );
}
}
if ( is_array( $coupons_email ) && count( $coupons_email ) > 0 ) {
$coupon->set_email_restrictions( $coupons_email );
$coupon->save();
} else {
wp_delete_post( $coupon_id, true );
}
return $coupon_id;
}
public function process_v2() {
$data = $this->data;
$coupon_name = $data['coupon_name'];
$coupon = new WC_Coupon( $coupon_name );
$coupon_id = $coupon->get_id();
if ( 0 === $coupon_id ) { // Coupon does not exists
return $this->skipped_response( __( 'Coupon does not exist.', 'wp-marketing-automations-pro' ) );
}
$coupons_email = $coupon->get_email_restrictions();
if ( is_array( $coupons_email ) && count( $coupons_email ) > 0 ) {
$index = array_search( $data['email'], $coupons_email, true );
if ( false !== $index ) {
unset( $coupons_email[ $index ] );
}
}
if ( is_array( $coupons_email ) && count( $coupons_email ) > 0 ) {
$coupon->set_email_restrictions( $coupons_email );
$coupon->save();
} else {
wp_delete_post( $coupon_id, true );
}
return $this->success_message( __( 'Coupon deleted.', 'wp-marketing-automations-pro' ) );
}
public function get_fields_schema() {
return [
[
'id' => 'coupon_type',
'label' => __( 'Coupon Type', 'wp-marketing-automations-pro' ),
'type' => 'radio',
'options' => [
[
'label' => __( "Static Coupon", 'wp-marketing-automations-pro' ),
'value' => 'static',
],
[
'label' => __( "Dynamic Coupon", 'wp-marketing-automations-pro' ),
'value' => 'dynamic',
]
],
'class' => 'inline-radio-field',
'required' => false,
'wrap_before' => '',
],
[
"id" => 'coupon_name',
"label" => __( 'Coupon Name', 'wp-marketing-automations-pro' ),
"type" => 'text',
"class" => 'bwfan-input-wrapper',
"required" => true,
"hint" => __( 'Copy the value of coupon code. You can add dynamic coupon code merge tag or static coupon code. ( Only 1 allowed )', 'wp-marketing-automations-pro' ),
"toggler" => [
'fields' => [
[
'id' => 'coupon_type',
'value' => 'static'
]
],
'relation' => 'AND',
]
],
[
'id' => 'dynamic_coupon_id',
'type' => 'ajax',
'label' => __( 'Step ID', 'wp-marketing-automations-pro' ),
"class" => 'bwfan-input-wrapper',
"required" => true,
'placeholder' => __( 'Select', 'wp-marketing-automations-pro' ),
"description" => "",
"ajax_cb" => 'bwfan_get_automation_wc_dynamic_coupon',
"toggler" => [
'fields' => [
[
'id' => 'coupon_type',
'value' => 'dynamic'
]
],
'relation' => 'AND',
],
],
];
}
public function get_default_values() {
return [
'coupon_type' => 'static',
];
}
public function get_desc_text( $data ) {
$data = json_decode( wp_json_encode( $data ), true );
$type = isset( $data['coupon_type'] ) ? $data['coupon_type'] : 'static';
switch ( $type ) {
case 'static':
if ( ! isset( $data['coupon_name'] ) || empty( $data['coupon_name'] ) ) {
return '';
}
return $data['coupon_name'];
case 'dynamic':
if ( ! isset( $data['dynamic_coupon_id'] ) || empty( $data['dynamic_coupon_id'] ) ) {
return '';
}
return '{{wc_dynamic_coupon id="' . $data['dynamic_coupon_id'] . '"}}';
default:
return '';
}
}
}
/**
* Register this action. Registering the action will make it eligible to see it on single automation screen in select actions dropdown.
*/
return 'BWFAN_WC_Remove_Coupon';

View File

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

View File

@@ -0,0 +1,101 @@
<?php
final class BWFAN_PRO_WC {
private static $instance = null;
private $action_dir = __DIR__;
/**
* Constructor
*
* @access public
*/
private function __construct() {
add_action( 'bwfan_wc_actions_loaded', [ $this, 'load_actions' ] );
add_action( 'bwfan_wc_events_loaded', [ $this, 'load_events' ] );
}
/**
* Ensures only one instance of the class is loaded or can be loaded.
*
* @return BWFAN_PRO_WC
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* @param $integration BWFAN_Integration
*/
public function load_actions( $integration ) {
$resource_dir = $this->action_dir . '/actions';
if ( file_exists( $resource_dir ) ) {
foreach ( glob( $resource_dir . '/class-*.php' ) as $_field_filename ) {
$file_data = pathinfo( $_field_filename );
if ( isset( $file_data['basename'] ) && 'index.php' === $file_data['basename'] ) {
continue;
}
$action_class = require_once( $_field_filename );
if ( ! is_null( $action_class ) && method_exists( $action_class, 'get_instance' ) ) {
/**
* @var $action_obj BWFAN_Action
*/
$action_obj = $action_class::get_instance();
$action_obj->load_hooks();
if ( method_exists( $action_obj, 'admin_enqueue_assets' ) && is_admin() && BWFAN_Common::is_automation_v1_active() && BWFAN_Common::is_autonami_page() ) {
// Add action to avoid enqueueing assets on every admin page load
add_action( 'admin_enqueue_scripts', array( $action_obj, 'admin_enqueue_assets' ), 98 );
}
$action_obj->set_integration_type( $integration->get_slug() );
BWFAN_Load_Integrations::register_actions( $action_obj );
}
}
}
}
public function load_events() {
$event_dir = __DIR__ . '/events';
foreach ( glob( $event_dir . '/class-*.php' ) as $_field_filename ) {
$file_data = pathinfo( $_field_filename );
if ( isset( $file_data['basename'] ) && 'index.php' === $file_data['basename'] ) {
continue;
}
$event_class = require_once( $_field_filename );
if ( ! is_null( $event_class ) && method_exists( $event_class, 'get_instance' ) ) {
/**
* @var $event_obj BWFAN_Event
*/
$event_obj = $event_class::get_instance();
$source_object = BWFAN_WC_Source::get_instance();
BWFAN_Load_Sources::$all_events[ $source_object->get_name() ][ $event_obj->get_slug() ] = $event_obj->get_name();
if ( isset( $global_settings[ 'bwfan_stop_event_' . $event_obj->get_slug() ] ) && ! empty( $global_settings[ 'bwfan_stop_event_' . $event_obj->get_slug() ] ) ) {
continue;
}
$event_obj->load_hooks();
if ( method_exists( $event_obj, 'admin_enqueue_assets' ) && is_admin() && BWFAN_Common::is_automation_v1_active() && BWFAN_Common::is_autonami_page() ) {
// Add action to avoid enqueueing assets on every admin page load
add_action( 'admin_enqueue_scripts', array( $event_obj, 'admin_enqueue_assets' ), 98 );
}
$event_obj->set_source_type( $source_object->get_slug() );
BWFAN_Load_Sources::register_events( $event_obj );
}
}
}
}
/**
* Register this class as an integration.
*/
if ( bwfan_is_woocommerce_active() ) {
BWFAN_Load_Integrations::register( 'BWFAN_PRO_WC' );
}

View File

@@ -0,0 +1,675 @@
<?php
final class BWFAN_WC_Customer_Win_Back extends BWFAN_Event {
private static $instance = null;
public $user_id = 0;
public $email = '';
public $first_name = '';
public $last_name = '';
protected $min = 30;
protected $max_gap = 15;
private $action_hook = 'bwfan_winback_one_minute_action';
private function __construct() {
$this->event_merge_tag_groups = array( 'bwf_contact' );
$this->event_name = esc_html__( 'Customer Win Back', 'wp-marketing-automations-pro' );
$this->event_desc = esc_html__( 'This event runs once per customers for selected period based on Last Ordered Date.', 'wp-marketing-automations-pro' );
$this->event_rule_groups = array(
'wc_customer',
'bwf_contact_segments',
'bwf_contact',
'bwf_contact_fields',
'bwf_contact_user',
'bwf_contact_wc',
'bwf_contact_geo',
'bwf_engagement',
'bwf_broadcast'
);
$this->optgroup_label = esc_html__( 'Customer', 'wp-marketing-automations-pro' );
$this->source_type = 'wc';
$this->priority = 60;
$this->is_time_independent = true;
$this->v2 = true;
$this->optgroup_priority = 20;
$this->disable_default_fields = true;
}
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
public function load_hooks() {
add_action( 'bwfan_sync_call_delete_tasks', array( $this, 'delete_schedule_tasks' ), 11, 2 );
add_action( $this->action_hook, array( $this, 'do_winback_schedule_work' ), 10, 3 );
}
/**
* Delete already schedule tasks by email or phone of current event for v1 automation
*
* @param $email
* @param $phone
*
* @return void
*/
public function delete_schedule_tasks( $email, $phone = '' ) {
if ( empty( $email ) && empty( $phone ) ) {
return;
}
$active_automations = BWFAN_Core()->automations->get_active_automations( 1, $this->get_slug() );
if ( empty( $active_automations ) ) {
return;
}
$win_back_automations = array_keys( $active_automations );
/** get schedule task by email */
$schedule_tasks = [];
if ( ! empty( $email ) ) {
$schedule_tasks_email = BWFAN_Common::get_schedule_task_by_email( $win_back_automations, $email );
$schedule_tasks = array_merge( $schedule_tasks, $schedule_tasks_email );
}
if ( ! empty( $phone ) ) {
$schedule_tasks_phone = BWFAN_Common::get_schedule_task_by_phone( $win_back_automations, $phone );
$schedule_tasks = array_merge( $schedule_tasks, $schedule_tasks_phone );
}
$schedule_tasks = array_filter( $schedule_tasks );
if ( 0 === count( $schedule_tasks ) ) {
return;
}
$schedule_tasks = array_unique( $schedule_tasks );
$delete_tasks = array();
foreach ( $schedule_tasks as $automation_id => $tasks ) {
if ( empty( $tasks ) ) {
continue;
}
foreach ( $tasks as $task ) {
$delete_tasks[] = $task['ID'];
}
BWFAN_Core()->tasks->delete_tasks( $delete_tasks );
}
}
/**
* Localize data for html fields for the current event.
*/
public function admin_enqueue_assets() {
if ( BWFAN_Common::is_load_admin_assets( 'automation' ) ) {
$data = $this->get_view_data();
BWFAN_Core()->admin->set_events_js_data( $this->get_slug(), 'last_run', $data['last_run'] );
}
}
public function get_view_data() {
$last_run = '';
if ( isset( $_GET['edit'] ) ) {
$last_run = BWFAN_Model_Automationmeta::get_meta( sanitize_text_field( $_GET['edit'] ), 'last_run' );
if ( false !== $last_run ) {
$last_run = date( get_option( 'date_format' ), strtotime( $last_run ) );
}
}
return [
'last_run' => $last_run,
];
}
/**
* Show the html fields for the current event.
*/
public function get_view( $db_eventmeta_saved_value ) {
?>
<script type="text/html" id="tmpl-event-<?php echo esc_html__( $this->get_slug() ); ?>">
<#
min_days_entered = (_.has(data, 'eventSavedData') && _.has(data.eventSavedData, 'days_min')) ? data.eventSavedData.days_min : '';
min_days_entered = ('' == min_days_entered) ? '<?php esc_attr_e( $this->min ) ?>' : min_days_entered;
max_days_entered = (_.has(data, 'eventSavedData') && _.has(data.eventSavedData, 'days_max')) ? data.eventSavedData.days_max : '';
max_days_entered = ('' == max_days_entered) ? '<?php esc_attr_e( $this->min + $this->max_gap ) ?>' : max_days_entered;
hours_entered = (_.has(data, 'eventSavedData') && _.has(data.eventSavedData, 'hours')) ? data.eventSavedData.hours : 11;
minutes_entered = (_.has(data, 'eventSavedData') && _.has(data.eventSavedData, 'minutes')) ? data.eventSavedData.minutes :'';
#>
<div class="bwfan_mt15"></div>
<div class="bwfan-col-sm-12 bwfan-p-0">
<label for="bwfan-days_before" class="bwfan-label-title"><?php echo esc_html__( 'Customer Last Ordered Period', 'wp-marketing-automations-pro' ); ?></label>
Over <input required type="number" name="event_meta[days_min]" id="bwfan-days_before" placeholder="30" class="bwfan-input-wrapper bwfan-input-s" value="{{min_days_entered}}"/> days ago
AND Under <input required type="number" name="event_meta[days_max]" id="bwfan-days_before" placeholder="45" class="bwfan-input-wrapper bwfan-input-s" value="{{max_days_entered}}"/>
days ago
</div>
<div class="clearfix bwfan_field_desc"><?php echo esc_html__( 'Runs once per customer for the selected period', 'wp-marketing-automations-pro' ); ?></div>
<div class="bwfan-clear"></div>
<div class="bwfan-input-form bwfan-row-sep bwfan_mt15"></div>
<div class="bwfan-col-sm-12 bwfan-p-0">
<label for="bwfan-hours" class="bwfan-label-title"><?php echo esc_html__( 'Schedule this automation to run everyday at', 'wp-marketing-automations-pro' ); ?></label>
<input max="23" min="0" type="number" name="event_meta[hours]" id="bwfan-hours" class="bwfan-input-wrapper bwfan-input-inline" value="{{hours_entered}}" placeholder="<?php echo esc_html__( 'HH', 'wp-marketing-automations-pro' ); ?>"/>
:
<input max="59" min="0" type="number" name="event_meta[minutes]" id="bwfan-minutes" class="bwfan-input-wrapper bwfan-input-inline" value="{{minutes_entered}}" placeholder="<?php echo esc_html__( 'MM', 'wp-marketing-automations-pro' ); ?>"/>
<# if( _.has(data.eventFieldsOptions, 'last_run') && '' != data.eventFieldsOptions.last_run ) { #>
<div class="clearfix bwfan_field_desc"><?php echo esc_html__( 'This automation last ran on ', 'wp-marketing-automations-pro' ); ?>{{data.eventFieldsOptions.last_run}}</div>
<# } #>
</div>
</script>
<?php
}
/**
* Set up rules data
*
* @param $automation_data
*/
public function pre_executable_actions( $automation_data ) {
BWFAN_Core()->rules->setRulesData( $this->user_id, 'user_id' );
BWFAN_Core()->rules->setRulesData( $this->email, 'email' );
BWFAN_Core()->rules->setRulesData( $this->first_name, 'first_name' );
BWFAN_Core()->rules->setRulesData( $this->last_name, 'last_name' );
BWFAN_Core()->rules->setRulesData( BWFAN_Common::get_bwf_customer( $this->email, $this->user_id ), 'bwf_customer' );
}
/**
* Registers the tasks for current event.
*
* @param $automation_id
* @param $integration_data
* @param $event_data
*/
public function register_tasks( $automation_id, $integration_data, $event_data ) {
if ( ! is_array( $integration_data ) ) {
return;
}
$data_to_send = $this->get_event_data();
$this->create_tasks( $automation_id, $integration_data, $event_data, $data_to_send );
}
public function get_event_data() {
$data_to_send = [ 'global' => [] ];
$data_to_send['global']['user_id'] = $this->user_id;
$data_to_send['global']['email'] = $this->email;
$data_to_send['global']['first_name'] = $this->first_name;
$data_to_send['global']['last_name'] = $this->last_name;
return $data_to_send;
}
/**
* Make the view data for the current event which will be shown in task listing screen.
*
* @param $global_data
*
* @return false|string
*/
public function get_task_view( $global_data ) {
ob_start();
?>
<li>
<strong><?php echo esc_html__( 'Name:', 'wp-marketing-automations-pro' ); ?> </strong>
<?php echo esc_html__( $global_data['first_name'] ) . esc_html__( $global_data['last_name'] ); ?>
</li>
<li>
<strong><?php echo esc_html__( 'User ID:', 'wp-marketing-automations-pro' ); ?> </strong>
<?php echo esc_html__( $global_data['user_id'] ); ?>
</li>
<li>
<strong><?php echo esc_html__( 'email:', 'wp-marketing-automations-pro' ); ?> </strong>
<?php echo esc_html__( $global_data['email'] ); ?>
</li>
<?php
return ob_get_clean();
}
/**
* Set global data for all the merge tags which are supported by this event.
*
* @param $task_meta
*/
public function set_merge_tags_data( $task_meta ) {
$get_data = BWFAN_Merge_Tag_Loader::get_data( 'referral_id' );
if ( ( empty( $get_data ) || intval( $get_data ) !== intval( $task_meta['global']['referral_id'] ) ) ) {
$set_data = array(
'user_id' => $task_meta['global']['user_id'],
'email' => $task_meta['global']['email'],
'first_name' => $task_meta['global']['first_name'],
'last_name' => $task_meta['global']['last_name'],
);
BWFAN_Merge_Tag_Loader::set_data( $set_data );
}
}
/**
* Capture the async data for the current event.
* @return array|bool
*/
public function capture_async_data() {
$this->user_id = BWFAN_Common::$events_async_data['user_id'];
$this->email = BWFAN_Common::$events_async_data['email'];
$this->first_name = BWFAN_Common::$events_async_data['first_name'];
$this->last_name = BWFAN_Common::$events_async_data['last_name'];
return $this->run_automations();
}
/**
* This is a time independent event. A cron is run once a day and it makes all the tasks for the current event.
*
* @param $automation_id
* @param $automation_details
*/
public function make_task_data( $automation_id, $automation_details ) {
global $wpdb;
$date_time = new DateTime();
$date_time->setTime( 00, 00, 00 );
$current_day = $date_time->format( 'Y-m-d' );
$last_run = BWFAN_Model_Automationmeta::get_meta( $automation_id, 'last_run' );
if ( false !== $last_run ) {
$where = [
'bwfan_automation_id' => $automation_id,
'meta_key' => 'last_run',
];
$data = [
'meta_value' => $current_day,
];
BWFAN_Model_Automationmeta::update( $data, $where );
} else {
$meta = [
'bwfan_automation_id' => $automation_id,
'meta_key' => 'last_run',
'meta_value' => $current_day,
];
BWFAN_Model_Automationmeta::insert( $meta );
}
$days_min = isset( $automation_details['meta']['event_meta']['last-ordered']['days_min'] ) ? $automation_details['meta']['event_meta']['last-ordered']['days_min'] : $automation_details['meta']['event_meta']['days_min'];
$days_max = isset( $automation_details['meta']['event_meta']['last-ordered']['days_max'] ) ? $automation_details['meta']['event_meta']['last-ordered']['days_max'] : $automation_details['meta']['event_meta']['days_max'];
$days_min = ( empty( $days_min ) ) ? $this->min : $days_min;
$days_max = ( empty( $days_max ) ) ? ( $this->min + $this->max_gap ) : $days_max;
$min_date = new DateTime();
$min_date->modify( '+' . BWFAN_Common::get_timezone_offset() * HOUR_IN_SECONDS . ' seconds' ); // get site time
$max_date = clone $min_date;
$min_date->modify( "-$days_min days" );
$max_date->modify( "-$days_max days" );
$max_date->setTime( 00, 00, 01 );
$min_date->setTime( 23, 59, 59 );
$max_date->modify( '-' . BWFAN_Common::get_timezone_offset() * HOUR_IN_SECONDS . ' seconds' );
$min_date->modify( '-' . BWFAN_Common::get_timezone_offset() * HOUR_IN_SECONDS . ' seconds' );
$start_date = $max_date->format( 'Y-m-d H:i:s' );
$end_date = $min_date->format( 'Y-m-d H:i:s' );
$start_date_timestamp = $max_date->getTimestamp();
/** query always from older date (start) to new date (end) */
/** Get all the customers of selected range in the automations */
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$customers = $wpdb->get_results( $wpdb->prepare( "
SELECT c.wpid as id, c.email as email, c.f_name as first_name, c.l_name as last_name, c.id as bwf_cid
FROM {$wpdb->prefix}bwf_contact as c
LEFT JOIN {$wpdb->prefix}bwf_wc_customers as wc
ON c.id = wc.cid
WHERE c.email !=''
AND wc.l_order_date > %s
AND wc.l_order_date < %s
", $start_date, $end_date ), ARRAY_A );
if ( empty( $customers ) ) {
return;
}
/** Check if automations v1 or v2 exists */
BWFAN_Core()->public->load_active_automations( $this->get_slug() );
BWFAN_Core()->public->load_active_v2_automations( $this->get_slug() );
if ( ( ! is_array( $this->automations_arr ) || count( $this->automations_arr ) === 0 ) && ( ! is_array( $this->automations_v2_arr ) || count( $this->automations_v2_arr ) === 0 ) ) {
return;
}
if ( count( $this->automations_arr ) > 0 ) {
/** Get all the customers where automations already ran for the given automation range */
$query = $wpdb->prepare( "SELECT DISTINCT `contact_id` FROM `{$wpdb->prefix}bwfan_contact_automations` WHERE `automation_id` = %d AND `time` > %d", $automation_id, $start_date_timestamp );
$ran_customers = $wpdb->get_results( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
} else {
$contacts = BWFAN_Model_Automation_Contact::get_contacts_automation( $automation_id, $start_date );
$complete_contacts = BWFAN_Model_Automation_Complete_Contact::get_contacts_automation( $automation_id, $start_date );
$ran_customers = array_merge( $contacts, $complete_contacts );
}
/** filter customer */
if ( is_array( $ran_customers ) && count( $ran_customers ) > 0 ) {
$ran_customers = array_column( $ran_customers, 'contact_id' );
$filtered_customers = array_column( array_filter( $customers, function ( $customer ) use ( $ran_customers ) {
if ( ! in_array( $customer['bwf_cid'], $ran_customers, true ) ) {
return $customer['bwf_cid'];
}
} ), 'bwf_cid' );
$customers = $filtered_customers;
} else {
$customers = array_column( $customers, 'bwf_cid' );
}
if ( empty( $customers ) ) {
if ( bwf_has_action_scheduled( $this->action_hook ) ) {
bwf_unschedule_actions( $this->action_hook, array(), 'woofunnels' );
}
return;
}
$key = 'bwf_async_event_' . $this->get_slug() . '_' . time();
$args = [ 'key' => $key, 'aid' => $automation_id, 'new' => 1 ];
if ( ! bwf_has_action_scheduled( $this->action_hook ) ) {
bwf_schedule_recurring_action( time(), 60, $this->action_hook, $args, 'woofunnels' );
bwf_options_update( $key, $customers );
}
}
public function do_winback_schedule_work( $option_key, $aid, $new = 0 ) {
$customers = [];
if ( 0 === $new ) {
/** Un-schedule old scheduled hook */
bwf_unschedule_actions( $this->action_hook, [ 'key' => $option_key, 'aid' => $aid ], 'woofunnels' );
$customers = get_option( $option_key, [] );
delete_option( $option_key );
$args = [ 'key' => $option_key, 'aid' => $aid, 'new' => 1 ];
bwf_schedule_recurring_action( time(), 60, $this->action_hook, $args, 'woofunnels' );
}
$customers = empty( $customers ) ? bwf_options_get( $option_key ) : $customers;
if ( empty( $customers ) ) {
bwf_options_delete( $option_key );
bwf_unschedule_actions( $this->action_hook, [ 'key' => $option_key, 'aid' => $aid, 'new' => 1 ], 'woofunnels' );
}
global $wpdb;
$updated_customers = $customers;
$start_time = time();
$batch_size = 10;
while ( ( time() - $start_time ) < 15 ) {
/** Get first 10 ids */
$customers = ( count( $customers ) > $batch_size ) ? array_slice( $customers, 0, $batch_size ) : $customers;
$selected_customers = implode( ', ', $customers );
$query = "SELECT c.wpid as id,c.id as cid, c.email as email, c.f_name as first_name, c.l_name as last_name FROM {$wpdb->prefix}bwf_contact as c where c.id IN ($selected_customers)";
$selected_customers = $wpdb->get_results( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
foreach ( $selected_customers as $customer ) {
$this->process( $customer['id'], $customer['email'], $customer['first_name'], $customer['last_name'] );
}
/** Remove customer ids from data after automation process */
$updated_customers = array_diff( $updated_customers, $customers );
if ( empty( $updated_customers ) ) {
bwf_options_delete( $option_key );
bwf_unschedule_actions( $this->action_hook, [ 'key' => $option_key, 'aid' => $aid, 'new' => 1 ], 'woofunnels' );
return;
}
sort( $updated_customers );
bwf_options_update( $option_key, $updated_customers );
/** Assign updated customers */
$customers = $updated_customers;
}
}
public function update_scheduler_offset( $offset, $aid ) {
BWFAN_Model_Automationmeta::update( [
'meta_value' => $offset,
], [
'bwfan_automation_id' => $aid,
'meta_key' => 'winback_schedule_offset',
] );
}
public function process( $user_id, $email, $first_name, $last_name ) {
$this->user_id = $user_id;
$this->email = $email;
$this->first_name = $first_name;
$this->last_name = $last_name;
/** v2 event execution start */
$contact_data_v2 = array(
'user_id' => $user_id,
'email' => $email,
'first_name' => $first_name,
'last_name' => $last_name,
);
BWFAN_Common::maybe_run_v2_automations( $this->get_slug(), $contact_data_v2 );
/** v2 event execution end */
$this->run_automations();
}
public function get_email_event() {
return $this->email;
}
/**
* @param $task_details
*
* @return array
*/
public function validate_event( $task_details ) {
$result = [];
$automation_id = $task_details['processed_data']['automation_id'];
$current_automation_event_meta = BWFAN_Model_Automationmeta::get_meta( $automation_id, 'event_meta' );
$days_min = $current_automation_event_meta['days_min'];
$days_min = ( empty( $days_min ) ) ? $this->min : $days_min;
$days_max = $current_automation_event_meta['days_max'];
$days_max = ( empty( $days_max ) ) ? ( $this->min + $this->max_gap ) : $days_max;
$winback_timestamp = $this->get_winback_start_end_timestamp( $days_min, $days_max );
$processed_email = $task_details['processed_data']['email'];
$processed_wpid = isset( $task_details['processed_data']['user_id`'] ) ? $task_details['processed_data']['user_id`'] : 0;
$customer = BWFAN_Common::get_bwf_customer( $processed_email, $processed_wpid );
$order_last_date = '';
if ( $customer ) {
$order_last_date = $customer->get_l_order_date();
}
if ( empty( $order_last_date ) ) {
return $this->get_automation_event_success();
}
$order_last_date_timestamp = strtotime( $order_last_date );
if ( ( $order_last_date_timestamp > $winback_timestamp['start_date_timestamp'] ) && ( $order_last_date_timestamp < $winback_timestamp['end_date_timestamp'] ) ) {
return $this->get_automation_event_success();
}
$order_last_order_date = date( 'Y-m-d h:i:s', $order_last_date_timestamp );
$result['status'] = 4;
$result['message'] = esc_html__( "Customer Last Order date ( $order_last_order_date ) doesn't lies in this period: $days_min - $days_max days", 'wp-marketing-automations-pro' );
return $result;
}
/**
* v2 Method: Validate event settings
*
* @param $automation_data
*
* @return bool
*/
public function validate_v2_event_settings( $automation_data ) {
$days_min = $automation_data['event_meta']['last-ordered']['days_min'];
$days_min = ( empty( $days_min ) ) ? $this->min : $days_min;
$days_max = $automation_data['event_meta']['last-ordered']['days_max'];
$days_max = ( empty( $days_max ) ) ? ( $this->min + $this->max_gap ) : $days_max;
$winback_timestamp = $this->get_winback_start_end_timestamp( $days_min, $days_max );
$processed_email = $automation_data['email'];
$processed_wpid = isset( $automation_data['user_id`'] ) ? $automation_data['user_id`'] : 0;
$customer = BWFAN_Common::get_bwf_customer( $processed_email, $processed_wpid );
$order_last_date = '';
if ( $customer ) {
$order_last_date = $customer->get_l_order_date();
}
if ( empty( $order_last_date ) ) {
return true;
}
$order_last_date_timestamp = strtotime( $order_last_date );
if ( ( $order_last_date_timestamp > $winback_timestamp['start_date_timestamp'] ) && ( $order_last_date_timestamp < $winback_timestamp['end_date_timestamp'] ) ) {
return true;
}
return false;
}
/** getting the start , end timestamp of winback event
*
* @param $days_min
* @param $days_max
*
* @return mixed
*/
public function get_winback_start_end_timestamp( $days_min, $days_max ) {
$min_date = new DateTime();
$min_date->modify( '+' . BWFAN_Common::get_timezone_offset() * HOUR_IN_SECONDS . ' seconds' ); // get site time
$max_date = clone $min_date;
$min_date->modify( "-$days_min days" );
$max_date->modify( "-$days_max days" );
$max_date->setTime( 00, 00, 01 );
$min_date->setTime( 23, 59, 59 );
$max_date->modify( '-' . BWFAN_Common::get_timezone_offset() * HOUR_IN_SECONDS . ' seconds' );
$min_date->modify( '-' . BWFAN_Common::get_timezone_offset() * HOUR_IN_SECONDS . ' seconds' );
$timestamp['start_date_timestamp'] = $max_date->getTimestamp();
$timestamp['end_date_timestamp'] = $min_date->getTimestamp();
return $timestamp;
}
public function get_fields_schema() {
return [
[
'id' => 'last-ordered',
'type' => 'expression',
'expression' => __( 'Over', 'wp-marketing-automations-pro' ) . ' {{days_min/}} ' . __( 'days ago AND Under', 'wp-marketing-automations-pro' ) . ' {{days_max /}} ' . __( 'days ago', 'wp-marketing-automations-pro' ),
'label' => __( 'Customer Last Ordered Period', 'wp-marketing-automations-pro' ),
'fields' => array(
array(
"id" => 'days_min',
"label" => '',
"type" => 'number',
"min" => '0',
"placeholder" => "30",
"hint" => "",
"nested" => '',
"required" => false,
),
array(
"id" => 'days_max',
"label" => '',
"type" => 'number',
"min" => '0',
"placeholder" => "45",
"hint" => "",
"nested" => '',
"required" => false,
)
),
"hint" => __( 'Runs once per customer for the selected period.', 'wp-marketing-automations-pro' ),
],
[
'id' => 'scheduled-everyday-at',
'type' => 'expression',
'expression' => " {{hours /}} {{minutes /}}",
'label' => __( 'Schedule this automation to run everyday at (24 Hours)', 'wp-marketing-automations-pro' ),
'fields' => [
[
"id" => 'hours',
"label" => '',
"type" => 'number',
"max" => '23',
"min" => '0',
"class" => 'bwfan-input-wrapper bwfan-input-s',
"placeholder" => "HH",
"description" => "",
"required" => false,
],
[
"id" => 'minutes',
"label" => '',
"type" => 'number',
"max" => '59',
"min" => '0',
"class" => 'bwfan-input-wrapper bwfan-input-s',
"placeholder" => "MM",
"description" => "",
"required" => false,
]
],
"description" => ""
],
];
}
/** v2 Methods: END */
/** set default values */
public function get_default_values() {
return [
'last-ordered' => [
'days_min' => '60',
'days_max' => '90',
],
'scheduled-everyday-at' => [
'hours' => '7',
'minutes' => '00',
],
];
}
}
/**
* Register this event to a source.
* This will show the current event in dropdown in single automation screen.
*/
if ( bwfan_is_woocommerce_active() ) {
return 'BWFAN_WC_Customer_Win_Back';
}

View File

@@ -0,0 +1,350 @@
<?php
final class BWFAN_WC_Order_Status_Pending extends BWFAN_Event {
private static $instance = null;
public $user_id = 0;
public $email = '';
public $order_id = 0;
/** @var $order WC_Order|null */
public $order = null;
private function __construct() {
$this->event_merge_tag_groups = array( 'wc_order', 'bwf_contact' );
$this->event_name = esc_html__( 'Order Status Pending', 'wp-marketing-automations-pro' );
$this->event_desc = esc_html__( 'This event runs after a Pending order is created.', 'wp-marketing-automations-pro' );
$this->event_rule_groups = array(
'wc_order',
'bwf_contact_segments',
'bwf_contact',
'bwf_contact_fields',
'bwf_contact_user',
'bwf_contact_wc',
'bwf_contact_geo',
'bwf_engagement',
'bwf_broadcast'
);
$this->optgroup_label = esc_html__( 'Orders', 'wp-marketing-automations-pro' );
$this->source_type = 'wc';
$this->priority = 15.2;
$this->is_time_independent = true;
$this->v2 = true;
$this->supported_blocks = [ 'order' ];
$this->automation_add = true;
}
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
public function load_hooks() {
/** Hooked over 5 mins action when active automations found */
add_action( 'bwfan_5_min_action', array( $this, 'checking_eligible_orders' ) );
}
public function checking_eligible_orders( $active_automations ) {
/** Filter active automations for this event */
$event_automations = array_filter( $active_automations, function ( $automation ) {
return $this->get_slug() === $automation['event'];
} );
if ( 0 === count( $event_automations ) ) {
return;
}
/** Fetching pending state orders with a gap of 10 mins default to current time and a 3 hr interval */
$mins_gap = apply_filters( 'bwfan_wc_pending_order_mins_gap', 10 );
$mins_gap = absint( $mins_gap ) > 0 ? absint( $mins_gap ) : 10;
$to = time() - ( MINUTE_IN_SECONDS * $mins_gap );
$from = apply_filters( 'bwfan_wc_pending_order_hrs_interval', 3 );
$from = absint( $from ) > 0 ? absint( $from ) : 3;
$from = $to - ( $from * HOUR_IN_SECONDS );
$order_ids = $this->get_unpaid_orders( $from, $to );
if ( ! is_array( $order_ids ) || ! count( $order_ids ) > 0 ) {
return;
}
/** Trigger event on each order & mark the order as processed for this event */
foreach ( $order_ids as $order_id ) {
$this->process( $order_id );
}
}
public function get_unpaid_orders( $from, $to ) {
global $wpdb;
if ( BWF_WC_Compatibility::is_hpos_enabled() ) {
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$order_ids = $wpdb->get_col( $wpdb->prepare( "SELECT distinct(posts.id)
FROM {$wpdb->prefix}wc_orders AS posts
WHERE posts.type = 'shop_order'
AND posts.status = 'wc-pending'
AND posts.date_created_gmt > %s
AND posts.date_created_gmt < %s
AND (SELECT count(*) FROM {$wpdb->prefix}wc_orders_meta WHERE order_id = posts.id and meta_key = '_bwfan_pending_checked') = 0", gmdate( 'Y-m-d H:i:s', intval( $from ) ), gmdate( 'Y-m-d H:i:s', intval( $to ) ) ) );
return $order_ids;
}
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
return $wpdb->get_col( $wpdb->prepare( "SELECT distinct(posts.ID)
FROM {$wpdb->posts} AS posts
WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'wc-pending'
AND posts.post_date_gmt > %s
AND posts.post_date_gmt < %s
AND (SELECT count(*) FROM {$wpdb->postmeta} where post_id = posts.ID and meta_key = '_bwfan_pending_checked') = 0", gmdate( 'Y-m-d H:i:s', absint( $from ) ), gmdate( 'Y-m-d H:i:s', absint( $to ) ) ) );
}
public function process( $order_id ) {
$order = $order_id > 0 ? wc_get_order( $order_id ) : false;
if ( ! $order instanceof WC_Order ) {
return;
}
$this->order_id = $order_id;
$this->order = wc_get_order( $this->order_id );
if ( ! $this->order instanceof WC_Order ) {
return;
}
BWFAN_Core()->public->load_active_automations( $this->get_slug() );
BWFAN_Core()->public->load_active_v2_automations( $this->get_slug() );
if ( ( ! is_array( $this->automations_arr ) || count( $this->automations_arr ) === 0 ) && ( ! is_array( $this->automations_v2_arr ) || count( $this->automations_v2_arr ) === 0 ) ) {
return;
}
$this->order->update_meta_data( '_bwfan_pending_checked', 1 );
$this->order->save();
$this->user_id = $this->order->get_user_id();
$this->email = $this->order->get_billing_email();
$contact_data_v2 = array(
'order_id' => absint( $this->order_id ),
'email' => $this->email,
'user_id' => $this->user_id,
'event' => $this->get_slug(),
'version' => 2
);
BWFAN_Common::maybe_run_v2_automations( $this->get_slug(), $contact_data_v2 );
if ( empty( $this->automations_arr ) ) {
return;
}
$this->run_automations();
}
/**
* Override method to change the state of Cart based on Automations found
* v1 code
*
* @return array|bool|void
*/
public function run_automations() {
foreach ( $this->automations_arr as $automation_id => $automation_data ) {
if ( 0 !== intval( $automation_data['requires_update'] ) ) {
continue;
}
$this->handle_single_automation_run( $automation_data, $automation_id );
}
}
/**
* Set up rules data
*
* @param $automation_data
*/
public function pre_executable_actions( $automation_data ) {
BWFAN_Core()->rules->setRulesData( $this->user_id, 'user_id' );
BWFAN_Core()->rules->setRulesData( $this->email, 'email' );
BWFAN_Core()->rules->setRulesData( $this->order, 'wc_order' );
BWFAN_Core()->rules->setRulesData( $this->order_id, 'wc_order_id' );
BWFAN_Core()->rules->setRulesData( $this->order_id, 'order_id' );
BWFAN_Core()->rules->setRulesData( BWFAN_Common::get_bwf_customer( $this->email, $this->user_id ), 'bwf_customer' );
}
/**
* Registers the tasks for current event.
*
* @param $automation_id
* @param $integration_data
* @param $event_data
*/
public function register_tasks( $automation_id, $integration_data, $event_data ) {
if ( ! is_array( $integration_data ) ) {
return;
}
$data_to_send = $this->get_event_data();
$this->create_tasks( $automation_id, $integration_data, $event_data, $data_to_send );
}
public function get_event_data() {
$data_to_send = [ 'global' => [] ];
$data_to_send['global']['user_id'] = $this->user_id;
$data_to_send['global']['email'] = $this->email;
$data_to_send['global']['wc_order_id'] = $this->order_id;
$data_to_send['global']['order_id'] = $this->order_id;
$data_to_send['global']['wc_order'] = $this->order;
$order_lang = BWFAN_PRO_Common::passing_event_language( [ 'order_id' => $this->order_id ] );
if ( is_array( $order_lang ) && isset( $order_lang['language'] ) && ! empty( $order_lang['language'] ) ) {
$data_to_send['global']['language'] = $order_lang['language'];
}
return $data_to_send;
}
/**
* Make the view data for the current event which will be shown in task listing screen.
*
* @param $global_data
*
* @return false|string
*/
public function get_task_view( $global_data ) {
ob_start();
if ( absint( $global_data['wc_order_id'] ) > 0 ) {
$order = wc_get_order( absint( $global_data['wc_order_id'] ) );
if ( $order instanceof WC_Order ) { ?>
<li>
<strong><?php echo esc_html__( 'Order: ', 'wp-marketing-automations-pro' ); ?></strong>
<a target="_blank" href="<?php echo get_edit_post_link( $global_data['order_id'] ); //phpcs:ignore WordPress.Security.EscapeOutput
?>"><?php echo '#' . esc_attr( $global_data['order_id'] . ' ' . $order->get_billing_first_name() . ' ' . $order->get_billing_last_name() ); ?></a>
</li>
<?php
}
}
?>
<li>
<strong><?php echo esc_html__( 'Email: ', 'wp-marketing-automations-pro' ); ?></strong>
<?php echo esc_html__( $global_data['email'] ); ?>
</li>
<?php
return ob_get_clean();
}
/**
* Set global data for all the merge tags which are supported by this event.
*
* @param $task_meta
*/
public function set_merge_tags_data( $task_meta ) {
$set_data = array(
'user_id' => $task_meta['global']['user_id'],
'email' => $task_meta['global']['email'],
'wc_order_id' => $task_meta['global']['wc_order_id'],
'order_id' => $task_meta['global']['order_id'],
'wc_order' => $task_meta['global']['wc_order']
);
BWFAN_Merge_Tag_Loader::set_data( $set_data );
}
public function get_email_event() {
$email = is_email( $this->email ) ? $this->email : false;
$email = ( false === $email && $this->user_id > 0 ) ? get_user_by( 'id', $this->user_id ) : false;
$email = $email instanceof WP_User ? $email->user_email : false;
$email = is_email( $email ) ? $email : false;
return $email;
}
public function get_user_id_event() {
$user_id = $this->user_id > 0 ? $this->user_id : false;
$user_id = ( false === $user_id && $this->order instanceof WC_Order ) ? $this->order->get_user_id() : false;
$user_id = ( false === $user_id && is_email( $this->email ) ) ? get_user_by( 'email', $this->email ) : false;
$user_id = $user_id instanceof WP_User ? $user_id->ID : false;
return $user_id;
}
public function validate_event_data_before_executing_task( $data ) {
if ( ! isset( $data['order_id'] ) ) {
return false;
}
$order = wc_get_order( absint( $data['order_id'] ) );
if ( $order instanceof WC_Order ) {
return ( 'pending' === $order->get_status() );
}
$order = isset( $data['wc_order_id'] ) ? wc_get_order( absint( $data['wc_order_id'] ) ) : false;
if ( ! $order instanceof WC_Order ) {
return false;
}
return ( 'pending' === $order->get_status() );
}
public function get_fields_schema() {
return [
[
'id' => 'notice',
'type' => 'notice',
'class' => '',
'status' => 'warning',
'message' => __( "This event runs automatically for orders marked as 'Pending', starting 10 minutes after creation. Order status is checked before execution.", 'wp-marketing-automations-pro' ),
'dismiss' => false,
'required' => false,
'isHtml' => true,
'toggler' => [],
],
];
}
/**
* get contact automation data
*
* @param $automation_data
* @param $cid
*
* @return array|null[]
*/
public function get_manually_added_contact_automation_data( $automation_data, $cid ) {
$contact = new WooFunnels_Contact( '', '', '', $cid );
/** Check if contact exists */
if ( ! $contact instanceof WooFunnels_Contact || empty( $contact->get_id() ) ) {
return [ 'status' => 0, 'type' => __( 'contact_not_found', 'wp-marketing-automations-pro' ) ];
}
$unpaid_order_id = $this->get_last_unpaid_order( $cid );
$order = wc_get_order( $unpaid_order_id );
if ( empty( $unpaid_order_id ) || ! $order instanceof WC_Order ) {
return [ 'status' => 0, 'type' => '', 'message' => __( "Contact doesn't have any pending order.", 'wp-marketing-automations-pro' ) ];
}
$this->user_id = $order->get_user_id();
$this->email = $order->get_billing_email();
return array_merge( $automation_data, [ 'order_id' => $unpaid_order_id, 'user_id' => $this->user_id, 'email' => $this->email ] );
}
public function get_last_unpaid_order( $cid ) {
global $wpdb;
if ( BWF_WC_Compatibility::is_hpos_enabled() ) {
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$query = $wpdb->prepare( "SELECT o.id FROM {$wpdb->prefix}wc_orders AS o JOIN {$wpdb->prefix}wc_orders_meta AS om ON o.id=om.order_id WHERE `type` = %s AND `status` = %s AND om.meta_key = %s AND om.meta_value=%d ORDER BY o.id DESC LIMIT 1", 'shop_order', 'wc-pending', '_woofunnel_cid', $cid );
return $wpdb->get_var( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
return $wpdb->get_var( $wpdb->prepare( "SELECT p.ID FROM {$wpdb->posts} AS p JOIN {$wpdb->postmeta} AS pm ON p.ID=pm.post_id WHERE p.post_type = %s AND p.post_status = %s AND pm.meta_key = %s AND pm.meta_value=%d ORDER BY p.ID DESC LIMIT 1 ", 'shop_order', 'wc-pending', '_woofunnel_cid', $cid ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
}
/**
* Register this event to a source.
* This will show the current event in dropdown in single automation screen.
*/
if ( bwfan_is_woocommerce_active() ) {
return 'BWFAN_WC_Order_Status_Pending';
}

View File

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

View File

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

View File

@@ -0,0 +1,43 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
class BWFAN_WC_Countries {
private static $ins = null;
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
public function get_slug() {
return 'wc_countries';
}
public function get_options( $search ) {
$countries = WC()->countries->get_countries();
$country_array = array();
if ( ! empty( $countries ) && is_array( $countries ) ) {
foreach ( $countries as $code => $country ) {
$country_array[ $code ] = $country;
}
}
return BWFAN_PRO_Common::search_srting_from_data( $country_array, $search );
}
}
if ( class_exists( 'BWFAN_Load_Custom_Search' ) ) {
BWFAN_Load_Custom_Search::register( 'BWFAN_WC_Countries' );
}

View File

@@ -0,0 +1,51 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
class BWFAN_WC_New_Order_Product {
private static $ins = null;
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
public function get_slug() {
return 'wc_new_order_product';
}
public function get_options( $search ) {
$ids = BWFAN_Common::search_products( $search, true );
$product_objects = array_filter( array_map( 'wc_get_product', $ids ), 'wc_products_array_filter_editable' );
$products = array();
foreach ( $product_objects as $product_object ) {
if ( ! $product_object instanceof WC_Product ) {
continue;
}
if ( 'pending' === $product_object->get_status() ) {
continue;
}
$products[ $product_object->get_id() ] = strip_tags( rawurldecode( BWFAN_Common::get_formatted_product_name( $product_object ) ) );
}
return $products;
}
}
if ( class_exists( 'BWFAN_Load_Custom_Search' ) ) {
BWFAN_Load_Custom_Search::register( 'BWFAN_WC_New_Order_Product' );
}

View File

@@ -0,0 +1,65 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
class BWFAN_WC_States {
private static $ins = null;
public static function get_instance() {
if ( null === self::$ins ) {
self::$ins = new self();
}
return self::$ins;
}
public function get_slug() {
return 'wc_states';
}
/**
* @param $search
*
* @return array
*/
public function get_options( $search, $extra_data = [] ) {
$country = ! empty( $extra_data['country'] ) ? $extra_data['country'] : '';
$states = WC()->countries->get_states( $country );
if ( empty( $states ) || ! is_array( $states ) ) {
return [];
}
$state_array = [];
if( $country ) {
foreach ( $states as $state_code => $state_name ) {
if ( stripos( $state_name, $search ) !== false || stripos( $country, $search ) !== false ) {
$state_array[ $state_code ] = sprintf( '%s (%s)', $state_name, $country );
}
}
return $state_array;
}
foreach ( $states as $country => $state_list ) {
if ( empty( $state_list ) || ! is_array( $state_list ) ) {
continue;
}
foreach ( $state_list as $state_code => $state_name ) {
if ( stripos( $state_name, $search ) !== false || stripos( $country, $search ) !== false ) {
$state_array[ $state_code ] = sprintf( '%s (%s)', $state_name, $country );
}
}
}
return $state_array;
}
}
if ( class_exists( 'BWFAN_Load_Custom_Search' ) ) {
BWFAN_Load_Custom_Search::register( 'BWFAN_WC_States' );
}

View File

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

View File

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