# Development

## Filters and Actions

These filters are called by Extended Coupon Features for WooCommerce:

    apply_filters( 'wjecf_apply_with_other_coupons', true, $the_coupon, $applied_coupon_codes ) );
    apply_filters( 'wjecf_bogo_product_amount_for_coupon', $qty, $coupon );
    apply_filters( 'wjecf_bogo_products_to_apply_for_coupon', $bogos, $coupon );
    apply_filters( 'wjecf_coupon_can_be_applied', $can_be_applied, $coupon );
    apply_filters( 'wjecf_coupon_has_a_value', $has_a_value, $coupon );
    apply_filters( 'wjecf_coupon_item_quantity', $item_quantity, $coupon, $item, $wc_discounts );
    apply_filters( 'wjecf_coupon_multiplier_value', $coupon_multiplier_values, $coupon, $wc_discounts );
    apply_filters( 'wjecf_first_order_statuses_to_check', $order_statuses );
    apply_filters( 'wjecf_free_cart_item_price', __('Free!', 'woocommerce'), $price_html, $cart_item, $cart_item_key );
    apply_filters( 'wjecf_free_cart_item_subtotal', __('Free!', 'woocommerce'), $price_html, $cart_item, $cart_item_key );
    apply_filters( 'wjecf_free_product_amount_for_coupon', $coupon_qty, $coupon );
    apply_filters( 'wjecf_free_products_to_apply_for_coupon', $free_product_quantities, $coupon )
    apply_filters( 'wjecf_get_limit_to_options', $options );
    apply_filters( 'wjecf_is_first_purchase', $is_first_purchase );
    apply_filters( 'wjecf_set_free_product_amount_in_cart', $quantity, $product );
    apply_filters( 'wjecf_set_free_product_amount_in_cart', $quantity, $product, $variation )

These actions are called by Extended Coupon Features for WooCommerce:

    do_action( 'wjecf_admin_after_settings' );
    do_action( 'wjecf_admin_before_settings' );
    do_action( 'wjecf_after_update_matched_autocoupons' );
    do_action( 'wjecf_assert_coupon_is_valid', $coupon );
    do_action( 'wjecf_before_update_matched_autocoupons' );
    do_action( 'wjecf_coupon_metabox_checkout', $thepostid, $post );
    do_action( 'wjecf_coupon_metabox_customer', $thepostid, $post );
    do_action( 'wjecf_coupon_metabox_free_products', $thepostid, $post );
    do_action( 'wjecf_coupon_metabox_misc', $thepostid, $post );
    do_action( 'wjecf_coupon_metabox_products', $thepostid, $post );
    do_action( 'wjecf_init_plugins');
    do_action( 'wjecf_woocommerce_coupon_options_extended_features', $thepostid, $post );

### Programming additional rules for 'Limit discount to'

apply_filters( 'wjecf_get_limit_to_options', $options )` filter allows developers to append rules for 'Limit to:'.

Rules can be added to the `$options`-array with these properties:

`$key => [ 'function' => $callback_function, 'title' => $title ]`

- `$key` = The key that identifies the 'Limit to'-rule.
- `$title` = The title of the 'Limit to'-rule.
- `$function` = The callback with functionality of the rule. Callback must have this signature: `function callback_function( $coupon, $discountable_items )` `$discountable_items` are stdClass objects as generated by WC_Discounts. The callback must return an array with the maximum amount of items to be discounted. `[ $item_key => $discount_limit, ... ]` Discount-quantity of cart_items that are not in the array will not be limited.

## Create mini-plugins for Extended Coupon Features

You can further extend functionality of Extended Coupon Features for WooCommerce by creating your own mini-plugins.

1. Hook into the `wjecf_init_plugins`-action. (Using this hook guarantees that the WooCommerce and Extended Coupon Features for WooCommerce plugins are loaded)
2. Here, create a class that extends `Abstract_WJECF_Plugin`.
3. Create a constructor `__construct()`, where you setup the plugin data by calling `$this->set_plugin_data`
4. Create a function `init_hook()`, where you setup your plugin and define frontend hooks.
5. Create a function `init_admin_hook()`, where you setup your plugin for admin usage and define admin hooks.

6. (Version 2.5.1+ only) If your plugin need to handle custom meta fields, use the WooCommerce meta box functions (e.g. `woocommerce_wp_select`).

   To handle the sanitization of these fields, create a function `admin_coupon_meta_fields( $coupon )` and have it return an array `[ 'field_name' => 'sanitization', ... ]` .

   Upon saving a coupon, these fields will be automatically read from `$_POST` and sanitized with the given sanitization method, e.g. `'int'`, `'int[]'`, `'yesno'`, `'decimal'`, `'clean'` or even a callback: `[ 'callback' => callback ]` and saved to the current coupon.

   For versions prior to 2.5.1, you need to handle process_shop_coupon_meta yourself.

7. Load the class by calling `WJECF()->add_plugin( 'NameOfYourClass')`

Example:

    <?php
    /**
    Plugin Name: WJECF Example plugin - Allow a coupon on certain weekdays only
    Description: An example on how to extend Extended Coupon Features for WooCommerce
    Author: Soft79
    Version: 1.0
    Author URI: http://www.soft79.nl/
    */

    add_action( 'wjecf_init_plugins', 'setup_my_wjecf_example_plugin' );

    function setup_my_wjecf_example_plugin() {

        class WJECF_Plugin_Example extends Abstract_WJECF_Plugin {

            //This is the meta-key where the weekday will be saved
            //HINT: Prepend it with _wjecf_<your plugin name> to avoid naming conflicts
            const META_KEY_WEEKDAY = '_wjecf_example_plugin_weekday';

            /**
             * In the constructor you can supply general information about your WJECF-plugin.
             */
            public function __construct() {
                $this->set_plugin_data( array(
                    'description' => __( 'WJECF Example plugin - Accept a coupon on certain weekdays only.', 'your-text-domain' ),
                    'dependencies' => array(),
                    'minimal_wjecf_version' => '2.5.1',
                    'can_be_disabled' => true
                ) );
            }

    //FRONTEND

            /**
             * This function is called when WooCommerce and all other plugins are loaded.
             * Here you can setup frontend hooks.
             */

            public function init_hook() {
                add_action( 'woocommerce_coupon_is_valid', array( $this, 'filter_woocommerce_coupon_is_valid' ), 10, 2 );
            }

            /**
             * Invalidates the coupon if the weekday is not ok
             * @param bool $valid
             * @param WC_Coupon $coupon
             * @return bool False if invalid
             */

            public function filter_woocommerce_coupon_is_valid( $valid, $coupon ) {
                if ( is_callable( array( $coupon, 'get_meta' ) ) ) {
                    //WC3.0+
                    $coupon_weekday = $coupon->get_meta( self::META_KEY_WEEKDAY );
                } else {
                    //Older WC versions
                    $coupon_weekday = get_post_meta( $coupon->id, self::META_KEY_WEEKDAY, true );
                }

                //Not valid if the weekday differs
                if ( is_numeric( $coupon_weekday ) && date('w') != $coupon_weekday ) {
                    return false;
                }

                return $valid;
            }

    //ADMIN

            /**
             * This function is called when WooCommerce and all other plugins are loaded and we are on the admin section of WordPress.
             * Here you can setup admin hooks.
             */
            public function init_admin_hook() {
                add_action( 'woocommerce_coupon_options_usage_restriction', array( $this, 'action_woocommerce_coupon_options_usage_restriction' ), 9999 ); //9999 is at the bottom of the tab
            }

            /**
             * Automatically called at the process_shop_coupon_meta action (WJECF 2.5.1+ only).
             *
             * Returns an array [ meta_key => sanitizion_rule, ... ] with the meta fields that must be saved if the user clicks 'Update' on the coupon admin page.         *
             * Valid sanitizion rules are: 'html', 'clean', 'yesno', 'decimal', 'int', 'int[]' (array of ints), 'int,' (comma separated ints)
             *
             * $_POST[meta_key] will be sanitized and automatically saved.
             *
             * @since 2.5.1
             * @param WC_Coupon $coupon The coupon that will be saved
             * @return array An array with [ key => sanitizion_rule, ... ]
             */
            public function admin_coupon_meta_fields( $coupon ) {
                return array( self::META_KEY_WEEKDAY => 'int' );
            }

            /**
             * This is called when the usage restrictions tab is rendered.
             */
            public function action_woocommerce_coupon_options_usage_restriction() {
                woocommerce_wp_select(
                    array(
                        'id' => self::META_KEY_WEEKDAY,
                        'label' => __( 'Weekday', 'woocommerce-jos-autocoupon' ),
                        'options' => array(
                            '' => '(Always valid)',
                            0 => 'Sunday',
                            1 => 'Monday',
                            2 => 'Tuesday',
                            3 => 'Wednesday',
                            4 => 'Thursday',
                            5 => 'Friday',
                            6 => 'Saturday'
                        ),
                        'description' => __( 'Coupon is only valid on this weekday.', 'your-text-domain' ),
                        'desc_tip' => true
                    )
                );
            }
        }

        //Loads the plugin!
        WJECF()->add_plugin( 'WJECF_Plugin_Example' );
    }

« Previous