MOON
Server: Apache
System: Linux server.royaltuning.hu 4.18.0-425.13.1.el8_7.x86_64 #1 SMP Tue Feb 21 04:20:52 EST 2023 x86_64
User: royaltuning (1001)
PHP: 8.2.30
Disabled: exec,passthru,shell_exec,system
Upload Files
File: /home/royaltuning/www/public/wp-content/plugins/easysales/includes/EasySales.php
<?php

use EasySales\Request\Request;

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

class EasySales {
    /**
     * @var ApiController
     */
    private $apiController;
    /**
     * @var ProductTransformer
     */
    private $productTransformer;
    /**
     * @var OrderTransformer
     */
    private $orderTransformer;

    /**
     * EasySales constructor.
     * @param ApiController $apiController
     * @param ProductTransformer $productTransformer
     * @param OrderTransformer $orderTransformer
     */
    public function __construct(ApiController $apiController, ProductTransformer $productTransformer, OrderTransformer $orderTransformer) {
        // Hook into the admin menu
        add_action('admin_menu', [$this, 'create_plugin_settings_page']);
        add_action('admin_init', [$this, 'display_options']);
        add_action('rest_api_init', [$this, 'add_api_route']);

        // Product hooks
        add_action('woocommerce_update_product', [$this, 'update_product']);

        // Categories hooks
        add_action('created_product_cat', [$this, 'add_category'], 10, 1);
        add_action('edited_product_cat', [$this, 'update_category'], 10, 1);

        // Attributes hooks
        add_action('woocommerce_attribute_added', [$this, 'add_attribute'], 10, 2);
        add_action('woocommerce_attribute_updated', [$this, 'update_attribute'], 10, 2);

        // Orders hooks
        add_action('woocommerce_checkout_order_processed', [$this, 'new_order'], 1, 1);
        add_action('woocommerce_order_edit_status', [$this, 'update_order'], 1, 2);

        // EAN Variations
        add_action('woocommerce_product_after_variable_attributes', [$this, 'variation_ean_field' ], 10, 3);
        add_action('woocommerce_save_product_variation', [$this, 'save_variations' ], 10, 2);

        // Set easysales api URL
        add_option('easysales-api-url', EASYSALES_API_URL);

        $this->apiController = $apiController;
        $this->apiController->setPluginInstance($this);
        $this->productTransformer = $productTransformer;
        $this->orderTransformer = $orderTransformer;
    }

    /**
     * Adds easySales 2ea Settings Page
     */
    public function create_plugin_settings_page() {
        add_menu_page(
            'easySales Settings',
            'easySales',
            'manage_options',
            'easysales-settings',
            [$this, 'plugin_settings_page_content'],
            'dashicons-chart-area',
            100
        );
    }

    public function plugin_settings_page_content() {
        ?>
            <div class="wrap">
                <h1>easySales Settings</h1>

                <div class="card" style="max-width: initial;">
                    <div class="card-body">
                        <form method="post" action="options.php">
                            <?php
                            do_settings_sections('easysales-options-page');

                            settings_fields('easysales-options');
                            // Add the submit button to serialize the options
                            submit_button();
                            ?>
                        </form>
                    </div>
                </div>
            </div>
        <?php
    }

    public function display_options()
    {
        //section name, display name, callback to print description of section, page to which section is attached.
        add_settings_section('easysales-options', null, null, 'easysales-options-page');

        //setting name, display name, callback to print form element, page in which field is displayed, section to which it belongs.
        //last field section is optional.
        add_settings_field('token', 'Token', [$this, 'display_token_form_element'], 'easysales-options-page', 'easysales-options');

        add_settings_field('brand', 'Brand Attribute', [$this, 'display_brand_select'], 'easysales-options-page', 'easysales-options');

        add_settings_field('ean-source', 'What should be the EAN source?', [$this, 'display_ean_source_select'], 'easysales-options-page', 'easysales-options');

        if ($this->ean_source() == '1') {
            add_settings_field('ean', 'EAN Metadata Key', [$this, 'display_ean_metadata_key'], 'easysales-options-page', 'easysales-options');
        } else if ($this->ean_source() == '2') {
            add_settings_field('ean', 'EAN Attribute', [$this, 'display_ean_select'], 'easysales-options-page', 'easysales-options');
        }

        add_settings_field('default-brand', 'Default Brand', [$this, 'display_default_brand_form_element'], 'easysales-options-page', 'easysales-options');

        add_settings_field('warehouse-location', 'Warehouse Location Attribute', [$this, 'display_warehouse_location_select'], 'easysales-options-page', 'easysales-options');

        add_settings_field('sku', 'Generate SKU', [$this, 'display_sku_select'], 'easysales-options-page', 'easysales-options');

        add_settings_field('invoice-series', 'Invoice Series', [$this, 'display_invoice_series_form_element'], 'easysales-options-page', 'easysales-options');

        add_settings_field('disabled-products', 'Send disabled products', [$this, 'display_disabled_products'], 'easysales-options-page', 'easysales-options');

        add_settings_field('private-products', 'Send private products', [$this, 'display_private_products'], 'easysales-options-page', 'easysales-options');

        add_settings_field('draft-products', 'Send draft products', [$this, 'display_draft_products'], 'easysales-options-page', 'easysales-options');

        add_settings_field('description', 'Description type', [$this, 'display_description_select'], 'easysales-options-page', 'easysales-options');

        add_settings_field('order-status-map', 'Order status map', [$this, 'display_order_status_map_select'], 'easysales-options-page', 'easysales-options');

        add_settings_field('webhook-completed-status', 'What status to use when order is finalized from easySales?', [$this, 'display_webhook_completed_select'], 'easysales-options-page', 'easysales-options');

        add_settings_field('webhook-cancelled-status', 'What status to use when order is cancelled from easySales?', [$this, 'display_webhook_cancelled_select'], 'easysales-options-page', 'easysales-options');

        add_settings_field('load-order-tax-from', 'Get order tax from', [$this, 'display_load_order_tax_from_select'], 'easysales-options-page', 'easysales-options');

        add_settings_field('country-tax', 'From what country we should use the tax rate?', [$this, 'display_country_tax_select'], 'easysales-options-page', 'easysales-options');

        //section name, form element name, callback for sanitization
        register_setting('easysales-options', 'easysales-token', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-brand', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-ean-source', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-ean', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-metadata-key', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-warehouse-location', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-generate-sku', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-invoice-series', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-default-brand', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-draft-products', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-disabled-products', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-private-products', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-description-type', [$this, 'sanitize']);

        /** Create new setting for each status **/
        $orderStatusFields = $this->orderTransformer->getOrderStatusMapFields();
        foreach($orderStatusFields as $orderStatusField){
            register_setting('easysales-options', $orderStatusField, [$this, 'sanitize']);
        }

        register_setting('easysales-options', 'easysales-webhook-completed-status', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-webhook-cancelled-status', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-load-order-tax-from', [$this, 'sanitize']);

        register_setting('easysales-options', 'easysales-country-tax', [$this, 'sanitize']);
    }

    public function sanitize($option)
    {
        //sanitize
        $option = sanitize_text_field($option);

        return $option;
    }

    public function display_token_form_element()
    {
        //id and name of form element should be same as the setting name.
        ?>
        <textarea type="text" name="easysales-token" class="large-text" id="easysales-token"><?php echo get_option('easysales-token');?></textarea>

        <p>Insert token generated in easySales platform</p>
        <?php
    }

    public function display_invoice_series_form_element()
    {
        //id and name of form element should be same as the setting name.
        ?>
        <input type="text" name="easysales-invoice-series" class="large-text" id="easysales-invoice-series" value="<?php echo get_option('easysales-invoice-series');?>" />

        <p>Insert Invoice Series</p>
        <?php
    }

    public function display_default_brand_form_element()
    {
        //id and name of form element should be same as the setting name.
        ?>
        <input type="text" name="easysales-default-brand" class="large-text" id="easysales-default-brand" value="<?php echo get_option('easysales-default-brand');?>" />

        <p>Default Brand</p>
        <?php
    }

    public function display_brand_select()
    {
        ?>
            <select name="easysales-brand" id="easysales-brand">
                <option value="" disabled selected>Select your option</option>
                <option value="-1" <?php selected(get_option('easysales-brand'), -1) ?>>None</option>
                <?php
                $attributes = wc_get_attribute_taxonomies();
                foreach ($attributes as $attribute) {
                    echo '<option value="' . $attribute->attribute_name . '" ' . selected(get_option('easysales-brand'), $attribute->attribute_name) .'>' . $attribute->attribute_label .'</option>';
                }
                ?>
            </select>

            <p>Select which attribute will be used as brand</p>
        <?php
    }

    public function ean_source()
    {
        $ean = get_option('easysales-ean');
        $ean_source = get_option('easysales-ean-source');

        if ($ean == '-1') {
            return -1;
        } else {
            // no saved option yet
            if ($ean_source === false) {
                return 2;
            }
        }

        return $ean_source;
    }

    public function display_ean_source_select()
    {
        $ean_source = $this->ean_source();

        ?>
        <select name="easysales-ean-source" id="easysales-ean-source">
            <option value="-1" <?php selected($ean_source, -1); ?>>None</option>
            <option value="1" <?php selected($ean_source, 1); ?>>Metadata</option>
            <option value="2" <?php selected($ean_source, 2); ?>>Attribute</option>
        </select>
        <?php
    }

    public function display_ean_select()
    {
        ?>
        <select name="easysales-ean" id="easysales-ean">
            <option value="" disabled selected>Select your option</option>

            <?php
            $attributes = wc_get_attribute_taxonomies();
            foreach ($attributes as $attribute) {
                echo '<option value="' . esc_attr($attribute->attribute_name) . '" ' . selected(get_option('easysales-ean'), $attribute->attribute_name, false) . '>' . esc_html($attribute->attribute_label) . '</option>';
            }
            ?>
        </select>

        <p>Select which attribute will be used as EAN</p>
        <?php
    }


    public function display_ean_metadata_key()
    {
        ?>
        <input type="text" name="easysales-metadata-key" class="large-text" id="easysales-metadata-key" value="<?php echo get_option('easysales-metadata-key');?>" />

        <p>Insert EAN Metadata Key</p>
        <?php
    }

    public function display_sku_select()
    {
        ?>
        <select name="easysales-generate-sku" id="easysales-generate-sku">
            <option value="" disabled selected>Select your option</option>

            <option value="1" <?php selected(get_option('easysales-generate-sku'), 1) ?>>Yes</option>
            <option value="0" <?php selected(get_option('easysales-generate-sku'), 0) ?>>No</option>
        </select>

        <p>Use this option to generate unique variation SKU based on main product reference</p>
        <?php
    }


    public function display_disabled_products()
    {
        ?>
        <select name="easysales-disabled-products" id="easysales-disabled-products">
            <option value="" disabled selected>Select your option</option>

            <option value="1" <?php selected(get_option('easysales-disabled-products'), 1) ?>>Yes</option>
            <option value="0" <?php selected(get_option('easysales-disabled-products'), 0) ?>>No</option>
        </select>

        <p>Use this option to send disabled products.</p>
        <?php
    }

    public function display_private_products()
    {
        ?>
        <select name="easysales-private-products" id="easysales-private-products">
            <option value="" disabled selected>Select your option</option>

            <option value="1" <?php selected(get_option('easysales-private-products'), 1) ?>>Yes</option>
            <option value="0" <?php selected(get_option('easysales-private-products'), 0) ?>>No</option>
        </select>

        <p>Use this option to send private products.</p>
        <?php
    }


    public function display_draft_products()
    {
        ?>
        <select name="easysales-draft-products" id="easysales-draft-products">
            <option value="" disabled selected>Select your option</option>

            <option value="1" <?php selected(get_option('easysales-draft-products'), 1) ?>>Yes</option>
            <option value="0" <?php selected(get_option('easysales-draft-products'), 0) ?>>No</option>
        </select>

        <p>Use this option to send draft products.</p>
        <?php
    }

    public function display_warehouse_location_select()
    {
        ?>
        <select name="easysales-warehouse-location" id="easysales-warehouse-location">
            <option value="" disabled selected>Select your option</option>
            <option value="-1" <?php selected(get_option('easysales-warehouse-location'), -1) ?>>None</option>

            <?php
            $attributes = wc_get_attribute_taxonomies();
            foreach ($attributes as $attribute) {
                echo '<option value="' . $attribute->attribute_name . '" ' . selected(get_option('easysales-warehouse-location'), $attribute->attribute_name) .'>' . $attribute->attribute_label .'</option>';
            }
            ?>
        </select>

        <p>Select which attribute will be used as warehouse location</p>
        <?php
    }

    public function display_description_select()
    {
        ?>
        <select name="easysales-description-type" id="easysales-description-type">
            <option value="" disabled selected>Select your option</option>

            <option value="0" <?php selected(get_option('easysales-description-type'), 0) ?>>Description</option>
            <option value="1" <?php selected(get_option('easysales-description-type'), 1) ?>>Short description</option>
        </select>

        <p>Use this option if you want to send short description to easySales</p>
        <?php
    }

    public function display_order_status_map_select()
    {
        $defaultStatusMap = $this->orderTransformer->getDefaultStatusMap();
        $wooUnmappedStatuses = $this->orderTransformer->getWooUnmappedStatuses();
        $easySalesOrderStatuses = $this->orderTransformer->getEasySalesOrderStatuses();

        foreach($wooUnmappedStatuses as $unmappedStatus){
            $defaultStatusMap[$unmappedStatus] = $easySalesOrderStatuses['New'];
        }

        ?>
        <div>
            <div style="display: flex;align-items: center; justify-content: flex-start; margin-bottom: 10px;">
                <span style="display: block; width: 250px; text-decoration: underline;">woocommerce status</span>
                <span style="text-decoration: underline;">easySales status</span>
            </div>
            <?php foreach (array_keys($defaultStatusMap) as $defaultStatusKey) { ?>
                <?php
                $statusName = wc_get_order_status_name($defaultStatusKey);
                $wooOrderStatuses = wc_get_order_statuses();
                if (isset($wooOrderStatuses[$defaultStatusKey]) && $statusName === $defaultStatusKey) {
                    $statusName = $wooOrderStatuses[$defaultStatusKey];
                }
                ?>
                <div style="display: flex;align-items: center; justify-content: flex-start; margin-bottom: 5px;">
                    <span style="display: block; width: 250px;"><strong><?php echo $statusName; ?></strong></span>

                    <?php
                    $mappingKey = $this->orderTransformer->getOrderStatusMapKey($defaultStatusKey);
                    $existingMapping = get_option($mappingKey);

                    if($existingMapping === false){
                        $existingMapping = null;
                        $existingMapping = $defaultStatusMap[$defaultStatusKey];
                    }
                    ?>
                    <select name="<?php echo $mappingKey; ?>" id="<?php echo $mappingKey; ?>">
                        <option value="" disabled selected>Select your option</option>
                        <?php foreach ($easySalesOrderStatuses as $easySalesStatusName => $easySalesStatusValue) { ?>
                            <option
                                    value="<?php echo $easySalesStatusValue; ?>"
                                    <?php selected($existingMapping, $easySalesStatusValue); ?>
                            >
                                <?php echo $easySalesStatusName; ?>
                            </option>
                        <?php } ?>
                    </select>
                </div>
            <?php } ?>
            <p>Use this option to map woocommerce statuses with easySales one</p>
        </div>
        <?php
    }

    public function display_webhook_completed_select()
    {
        ?>
        <select name="easysales-webhook-completed-status" id="easysales-webhook-completed-status">
            <option value="" disabled selected>Select your option</option>

            <?php
            $wooOrderStatuses = wc_get_order_statuses();
            foreach ($wooOrderStatuses as $wooOrderStatusKey => $wooOrderStatusLabel) {
                echo '<option value="' . $wooOrderStatusKey . '" ' . selected(get_option('easysales-webhook-completed-status'), $wooOrderStatusKey) .'>' . $wooOrderStatusLabel .'</option>';
            }
            ?>
        </select>
        <?php
    }

    public function display_webhook_cancelled_select()
    {
        ?>
        <select name="easysales-webhook-cancelled-status" id="easysales-webhook-cancelled-status">
            <option value="" disabled selected>Select your option</option>
            <?php
            $wooOrderStatuses = wc_get_order_statuses();
            foreach ($wooOrderStatuses as $wooOrderStatusKey => $wooOrderStatusLabel) {
                echo '<option value="' . $wooOrderStatusKey . '" ' . selected(get_option('easysales-webhook-cancelled-status'), $wooOrderStatusKey) .'>' . $wooOrderStatusLabel .'</option>';
            }
            ?>
        </select>
        <?php
    }

    public function display_load_order_tax_from_select()
    {
        ?>
        <select name="easysales-load-order-tax-from" id="easysales-load-order-tax-from">
            <option value="0" <?php selected(get_option('easysales-load-order-tax-from'), 0) ?>>Products</option>
            <option value="1" <?php selected(get_option('easysales-load-order-tax-from'), 1) ?>>Shipping</option>
        </select>
        <?php
    }

    public function display_country_tax_select()
    {
        ?>
        <select name="easysales-country-tax" id="easysales-country-tax">
            <option value="" disabled selected>Select your option</option>
            <?php
            $countries = WC()->countries->get_countries();
            foreach ($countries as $countryCode => $countryName) {
                echo '<option value="' . $countryCode . '" ' . selected(get_option('easysales-country-tax'), $countryCode) .'>' . $countryName .'</option>';
            }
            ?>
        </select>
        <?php
    }

    /**
     * Add api route
     */
    public function add_api_route()
    {
        register_rest_route('easysales', '/api', [
                'methods' => 'GET, POST',
                'callback' => [$this, 'api_callback'],
                'permission_callback' => [$this, 'check_token'],
                'args' => [
                        'auth' => [
                                'required' => true,
                                'sanitize_callback' => 'esc_attr'
                        ],
                        'request' => [
                                'required' => true,
                                'sanitize_callback' => 'esc_attr'
                        ]
                ]
        ]);
    }

    /**
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public function api_callback(WP_REST_Request $request)
    {
        $method = $request->get_param('request');

        if (!method_exists($this->apiController, $method)) {
            return new WP_REST_Response([ 'error' => 'true', 'message' => 'Invalid method' ], 401);
        }

        $response = $this->apiController->{$method}($request);

        if ($response instanceof WP_Error) {
            return $this->errorResponse($response);
        }

        return new WP_REST_Response($response, 200);
    }

    /**
     * Verify if given token match easysales-token
     * @param WP_REST_Request $request
     * @return bool
     */
    public function check_token(WP_REST_Request $request)
    {
        return base64_decode($request->get_param('auth')) === get_option('easysales-token');
    }

    /**
     * @param WP_Error $response
     * @param int $code
     * @return WP_REST_Response
     */
    private function errorResponse(WP_Error $response, $code = 400)
    {
        return new WP_REST_Response([
                'message' => $response->get_error_message()
        ], $code);
    }

    /**
     * @param $product_id
     */
    public function update_product($product_id)
    {
        $this->sync_product($product_id, 'update');
    }

    /**
     * @param $product_id
     * @param $method
     */
    public function sync_product($product_id, $method)
    {
        $data = [
                'website_token' => get_option('easysales-token')
        ];

        $product = wc_get_product($product_id);
        $visibility  = $product->get_catalog_visibility();
        $status  = $product->get_status();

        if (get_option('easysales-draft-products') != 1 && $status === 'draft') {
            return;
        }

        if (get_option('easysales-private-products') != 1 && $status === 'private') {
            return;
        }

        if (get_option('easysales-disabled-products') != 1 && $visibility === 'hidden') {
            return;
        }

        $response = $this->apiController->getProductByIdentifier([
                "product_id" => $product_id
        ]);

        if ($response instanceof WP_Error) {
            return $this->errorResponse($response);
        }

        $data['product'] = $response['product'];

        if (isset($response['product'])) {
            Request::post('products/save', $data);
        }
    }

    /**
     * @param $id
     */
    public function add_category($id)
    {
        $this->sync_category($id, 'add');
    }

    /**
     * @param $id
     */
    public function update_category($id)
    {
        $this->sync_category($id, 'update');
    }

    /**
     * @param $id
     * @param $method
     */
    public function sync_category($id, $method)
    {
        $category = get_term($id);

        $data = [
                'website_token' => get_option('easysales-token'),
                'category'  => [
                        'category_website_id' => $category->term_id,
                        'name' => $category->name
                ]
        ];

        Request::post('categories/save', $data);
    }

    /**
     * @param $id
     * @param $attribute
     */
    public function add_attribute($id, $attribute)
    {
        $this->sync_attribute($id, $attribute, 'add');
    }

    /**
     * @param $id
     * @param $attribute
     */
    public function update_attribute($id, $attribute)
    {
        $this->sync_attribute($id, $attribute, 'update');
    }

    /**
     * @param $id
     * @param $attribute
     * @param $method
     */
    public function sync_attribute($id, $attribute, $method)
    {
        $data = [
                'website_token' => get_option('easysales-token'),
                'characteristic'  => [
                        'characteristic_website_id' => $id,
                        'name' => $attribute['attribute_label']
                ]
        ];

        Request::post('characteristics/save', $data);
    }

    /**
     * @param $id
     */
    public function new_order($id)
    {
        $this->sync_order($id, 'add', null);
    }

    /**
     * @param $id
     * @param $status
     */
    public function update_order($id, $status)
    {
        $this->sync_order($id, 'update', $status);
    }

    /**
     * @param $id
     * @param $method
     * @param $status
     */
    public function sync_order($id, $method, $status)
    {
        $order = wc_get_order($id);

        $order = $this->orderTransformer->transform($order);

        if ($status) {
            $order['status'] = $this->orderTransformer->getStatus($status, $order['payment_mode']);
        }

        $data = [
                'website_token' => get_option('easysales-token'),
                'order'  => $order
        ];

        Request::post('orders/save', $data);
    }

    /**
     * Save variation settings
     */
    public function save_variations( $post_id )
    {
        $post = $_POST['easysales_var_ean'][ $post_id ];

        if( isset( $post ) ) {
            update_post_meta( $post_id, 'easysales_var_ean', esc_attr( $post ) );
        }

        /** Remove empty meta **/
        $meta = get_post_meta( $post_id,'easysales_var_ean', true );

        if ( empty( $meta ) ) {
            delete_post_meta( $post_id, 'easysales_var_ean', '' );
        }
    }

    /**
     * Add EAN Field for variations
     */
    public function variation_ean_field( $loop, $variation_data, $variation )
    {
        /** add EAN field for variations **/
        woocommerce_wp_text_input(
                array(
                    'id' => 'easysales_var_ean[' . $variation->ID . ']',
                    'wrapper_class' => 'form-row',
                    'label' => 'EAN',
                    'desc_tip' => 'true',
                    'description' => 'Enter EAN.',
                    'value'       => get_post_meta( $variation->ID, 'easysales_var_ean', true ),
            )
        );
    }
}