<?php
 class ent_order { public $data; public $previous; public function __construct($order_id=null) { if (!empty($order_id)) { $this->load($order_id); } else { $this->reset(); } } public function reset() { $this->data = []; $fields_query = database::query( "show fields from ". DB_TABLE_PREFIX ."orders;" ); while ($field = database::fetch($fields_query)) { switch ($field['Field']) { case 'customer_id': case 'customer_email': case 'customer_tax_id': case 'customer_company': case 'customer_firstname': case 'customer_lastname': case 'customer_address1': case 'customer_address2': case 'customer_postcode': case 'customer_city': case 'customer_country_code': case 'customer_zone_code': case 'customer_phone': $this->data['customer'][preg_replace('#^(customer_)#', '', $field['Field'])] = database::create_variable($field); break; case 'shipping_company': case 'shipping_firstname': case 'shipping_lastname': case 'shipping_address1': case 'shipping_address2': case 'shipping_postcode': case 'shipping_city': case 'shipping_country_code': case 'shipping_zone_code': case 'shipping_phone': $this->data['customer']['shipping_address'][preg_replace('#^(shipping_)#', '', $field['Field'])] = database::create_variable($field); break; case 'payment_option_id': case 'payment_option_name': $this->data['payment_option'][preg_replace('#^(payment_option_)#', '', $field['Field'])] = database::create_variable($field); break; case 'shipping_option_id': case 'shipping_option_name': $this->data['shipping_option'][preg_replace('#^(shipping_option_)#', '', $field['Field'])] = database::create_variable($field); break; default: $this->data[$field['Field']] = database::create_variable($field); break; } } $this->data = array_merge($this->data, [ 'uid' => uniqid(), 'weight_class' => settings::get('store_weight_class'), 'currency_code' => currency::$selected['code'], 'currency_value' => currency::$selected['value'], 'language_code' => language::$selected['code'], 'incoterm' => settings::get('default_incoterm'), 'items' => [], 'order_total' => [], 'comments' => [], 'subtotal' => ['amount' => 0, 'tax' => 0], 'display_prices_including_tax' => settings::get('default_display_prices_including_tax'), 'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '', 'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '', 'domain' => isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '', ]); $this->previous = $this->data; } public function load($order_id) { if (!preg_match('#^[0-9]+$#', $order_id)) throw new Exception('Invalid order (ID: '. $order_id .')'); $this->reset(); $order_query = database::query( "select * from ". DB_TABLE_PREFIX ."orders
        where id = ". (int)$order_id ."
        limit 1;" ); if ($order = database::fetch($order_query)) { $this->data = array_replace($this->data, array_intersect_key($order, $this->data)); } else { throw new Exception('Could not find order in database (ID: '. (int)$order_id .')'); } foreach ($order as $field => $value) { switch ($field) { case 'customer_id': case 'customer_email': case 'customer_tax_id': case 'customer_company': case 'customer_firstname': case 'customer_lastname': case 'customer_address1': case 'customer_address2': case 'customer_postcode': case 'customer_city': case 'customer_country_code': case 'customer_zone_code': case 'customer_phone': $this->data['customer'][preg_replace('#^(customer_)#', '', $field)] = $value; break; case 'shipping_company': case 'shipping_firstname': case 'shipping_lastname': case 'shipping_address1': case 'shipping_address2': case 'shipping_postcode': case 'shipping_city': case 'shipping_country_code': case 'shipping_zone_code': case 'shipping_phone': $this->data['customer']['shipping_address'][preg_replace('#^(shipping_)#', '', $field)] = $value; break; case 'payment_option_id': case 'payment_option_name': $this->data['payment_option'][preg_replace('#^(payment_option_)#', '', $field)] = $value; break; case 'shipping_option_id': case 'shipping_option_name': $this->data['shipping_option'][preg_replace('#^(shipping_option_)#', '', $field)] = $value; break; } } $order_items_query = database::query( "select * from ". DB_TABLE_PREFIX ."orders_items
        where order_id = ". (int)$order_id ."
        order by priority;" ); while ($item = database::fetch($order_items_query)) { $item['options'] = unserialize($item['options']); $this->data['items'][$item['id']] = $item; } $order_totals_query = database::query( "select * from ". DB_TABLE_PREFIX ."orders_totals
        where order_id = ". (int)$order_id ."
        order by priority;" ); while ($row = database::fetch($order_totals_query)) { $row['value'] = (float)$row['value']; $row['tax'] = (float)$row['tax']; $this->data['order_total'][$row['id']] = $row; } $order_comments_query = database::query( "select oc.*, u.username as author_username from ". DB_TABLE_PREFIX ."orders_comments oc
        left join ". DB_TABLE_PREFIX ."users u on (u.id = oc.author_id)
        where oc.order_id = ". (int)$order_id ."
        order by oc.id;" ); while ($row = database::fetch($order_comments_query)) { $this->data['comments'][$row['id']] = $row; } $this->previous = $this->data; } public function save() { $this->refresh_total(); if (!empty($this->previous['id']) && ($this->data['order_status_id'] != $this->previous['order_status_id'])) { $this->data['comments'][] = [ 'author' => 'system', 'text' => strtr(language::translate('text_user_changed_order_status_to_new_status', 'Order status changed to %new_status', settings::get('store_language_code')), [ '%username' => !empty(user::$data['username']) ? user::$data['username'] : 'system', '%new_status' => reference::order_status($this->data['order_status_id'], settings::get('store_language_code'))->name, ]), 'hidden' => 1, ]; } if (empty($this->data['customer']['id']) && !empty($this->data['customer']['email'])) { $customers_query = database::query( "select id from ". DB_TABLE_PREFIX ."customers
          where email = '". database::input($this->data['customer']['email']) ."'
          limit 1;" ); if ($customer = database::fetch($customers_query)) { $this->data['customer']['id'] = $customer['id']; } } if (empty($this->data['public_key'])) { $this->data['public_key'] = substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstuvwxyz', mt_rand(5, 10))), 0, 32); } if (empty($this->data['id'])) { database::query( "insert into ". DB_TABLE_PREFIX ."orders
          (uid, client_ip, user_agent, domain, date_created)
          values ('". database::input($this->data['uid']) ."', '". database::input($this->data['client_ip']) ."', '". database::input($this->data['user_agent']) ."', '". database::input($this->data['domain']) ."', '". ($this->data['date_created'] = date('Y-m-d H:i:s')) ."');" ); $this->data['id'] = database::insert_id(); } database::query( "update ". DB_TABLE_PREFIX ."orders set
        starred = ". (int)$this->data['starred'] .",
        unread = ". (int)$this->data['unread'] .",
        order_status_id = ". (int)$this->data['order_status_id'] .",
        customer_id = ". (int)$this->data['customer']['id'] .",
        customer_email = '". database::input($this->data['customer']['email']) ."',
        customer_tax_id = '". database::input($this->data['customer']['tax_id']) ."',
        customer_company = '". database::input($this->data['customer']['company']) ."',
        customer_firstname = '". database::input($this->data['customer']['firstname']) ."',
        customer_lastname = '". database::input($this->data['customer']['lastname']) ."',
        customer_address1 = '". database::input($this->data['customer']['address1']) ."',
        customer_address2 = '". database::input($this->data['customer']['address2']) ."',
        customer_city = '". database::input($this->data['customer']['city']) ."',
        customer_postcode = '". database::input($this->data['customer']['postcode']) ."',
        customer_country_code = '". database::input($this->data['customer']['country_code']) ."',
        customer_zone_code = '". database::input($this->data['customer']['zone_code']) ."',
        customer_phone = '". database::input($this->data['customer']['phone']) ."',
        shipping_company = '". database::input($this->data['customer']['shipping_address']['company']) ."',
        shipping_firstname = '". database::input($this->data['customer']['shipping_address']['firstname']) ."',
        shipping_lastname = '". database::input($this->data['customer']['shipping_address']['lastname']) ."',
        shipping_address1 = '". database::input($this->data['customer']['shipping_address']['address1']) ."',
        shipping_address2 = '". database::input($this->data['customer']['shipping_address']['address2']) ."',
        shipping_city = '". database::input($this->data['customer']['shipping_address']['city']) ."',
        shipping_postcode = '". database::input($this->data['customer']['shipping_address']['postcode']) ."',
        shipping_country_code = '". database::input($this->data['customer']['shipping_address']['country_code']) ."',
        shipping_zone_code = '". database::input($this->data['customer']['shipping_address']['zone_code']) ."',
        shipping_phone = '". database::input($this->data['customer']['shipping_address']['phone']) ."',
        shipping_option_id = '". database::input($this->data['shipping_option']['id']) ."',
        shipping_option_name = '". database::input($this->data['shipping_option']['name']) ."',
        shipping_tracking_id = '". database::input($this->data['shipping_tracking_id']) ."',
        shipping_tracking_url = '". database::input($this->data['shipping_tracking_url']) ."',
        payment_option_id = '". database::input($this->data['payment_option']['id']) ."',
        payment_option_name = '". database::input($this->data['payment_option']['name']) ."',
        payment_transaction_id = '". database::input($this->data['payment_transaction_id']) ."',
        payment_receipt_url = '". database::input($this->data['payment_receipt_url']) ."',
        payment_terms = '". database::input($this->data['payment_terms']) ."',
        incoterm = '". database::input($this->data['incoterm']) ."',
        reference = '". database::input($this->data['reference']) ."',
        language_code = '". database::input($this->data['language_code']) ."',
        currency_code = '". database::input($this->data['currency_code']) ."',
        currency_value = ". (float)$this->data['currency_value'] .",
        weight_total = ". (float)$this->data['weight_total'] .",
        weight_class = '". database::input($this->data['weight_class']) ."',
        display_prices_including_tax = ". (int)$this->data['display_prices_including_tax'] .",
        payment_due = ". (float)$this->data['payment_due'] .",
        tax_total = ". (float)$this->data['tax_total'] .",
        public_key = '". database::input($this->data['public_key']) ."',
        date_paid = ". (!empty($this->data['date_paid']) ? "'". date('Y-m-d H:i:s', strtotime($this->data['date_paid'])) ."'" : "null") .",
        date_dispatched = ". (!empty($this->data['date_dispatched']) ? "'". date('Y-m-d H:i:s', strtotime($this->data['date_dispatched'])) ."'" : "null") .",
        date_updated = '". ($this->data['date_updated'] = date('Y-m-d H:i:s')) ."'
        where id = ". (int)$this->data['id'] ."
        limit 1;" ); if (!empty($this->previous['order_status_id']) && reference::order_status($this->previous['order_status_id'], $this->data['language_code'])->stock_action == 'commit') { foreach ($this->previous['items'] as $previous_order_item) { if (empty($previous_order_item['product_id'])) continue; $this->adjust_stock_quantity($previous_order_item['product_id'], $previous_order_item['option_stock_combination'], (float)$previous_order_item['quantity']); } } database::query( "delete from ". DB_TABLE_PREFIX ."orders_items
        where order_id = ". (int)$this->data['id'] ."
        and id not in ('". implode("', '", array_column($this->data['items'], 'id')) ."');" ); $i = 0; foreach ($this->data['items'] as &$item) { if (empty($item['id'])) { database::query( "insert into ". DB_TABLE_PREFIX ."orders_items
            (order_id)
            values (". (int)$this->data['id'] .");" ); $item['id'] = database::insert_id(); if (!empty($item['product_id'])) { database::query( "update ". DB_TABLE_PREFIX ."products
              set purchases = purchases + ". (float)$item['quantity'] ."
              where id = ". (int)$item['product_id'] ."
              limit 1;" ); } } if (!empty($this->data['order_status_id']) && reference::order_status($this->data['order_status_id'])->stock_action == 'commit') { if (!empty($item['product_id'])) { $this->adjust_stock_quantity($item['product_id'], $item['option_stock_combination'], -(float)$item['quantity']); } } database::query( "update ". DB_TABLE_PREFIX ."orders_items
          set product_id = ". (int)$item['product_id'] .",
          option_stock_combination = '". database::input($item['option_stock_combination']) ."',
          options = '". (!empty($item['options']) ? database::input(serialize($item['options'])) : '') ."',
          name = '". database::input($item['name']) ."',
          sku = '". database::input($item['sku']) ."',
          gtin = '". database::input($item['gtin']) ."',
          taric = '". database::input($item['taric']) ."',
          quantity = ". (float)$item['quantity'] .",
          price = ". (float)$item['price'] .",
          tax = ". (float)$item['tax'] .",
          weight = ". (float)$item['weight'] .",
          weight_class = '". database::input($item['weight_class']) ."',
          dim_x = ". (float)$item['dim_x'] .",
          dim_y = ". (float)$item['dim_y'] .",
          dim_z = ". (float)$item['dim_z'] .",
          dim_class = '". database::input($item['dim_class']) ."',
          priority = ". ++$i ."
          where order_id = ". (int)$this->data['id'] ."
          and id = ". (int)$item['id'] ."
          limit 1;" ); } unset($item); database::query( "delete from ". DB_TABLE_PREFIX ."orders_totals
        where order_id = ". (int)$this->data['id'] ."
        and id not in ('". implode("', '", array_column($this->data['order_total'], 'id')) ."');" ); $i = 0; foreach ($this->data['order_total'] as &$row) { if (empty($row['id'])) { database::query( "insert into ". DB_TABLE_PREFIX ."orders_totals
            (order_id)
            values (". (int)$this->data['id'] .");" ); $row['id'] = database::insert_id(); } database::query( "update ". DB_TABLE_PREFIX ."orders_totals
          set title = '". database::input($row['title']) ."',
          module_id = '". database::input($row['module_id']) ."',
          value = '". (float)$row['value'] ."',
          tax = '". (float)$row['tax'] ."',
          calculate = '". (empty($row['calculate']) ? 0 : 1) ."',
          priority = ". ++$i ."
          where order_id = ". (int)$this->data['id'] ."
          and id = ". (int)$row['id'] ."
          limit 1;" ); } unset($row); database::query( "delete from ". DB_TABLE_PREFIX ."orders_comments
        where order_id = ". (int)$this->data['id'] ."
        and id not in ('". implode("', '", array_column($this->data['comments'], 'id')) ."');" ); if (!empty($this->data['comments'])) { $notify_comments = []; foreach ($this->data['comments'] as &$comment) { if (empty($comment['author'])) $comment['author'] = 'system'; if (empty($comment['author_id'])) $comment['author_id'] = ($comment['author'] == 'customer') ? -1 : 0; if (empty($comment['id'])) { database::query( "insert into ". DB_TABLE_PREFIX ."orders_comments
              (order_id, date_created)
              values (". (int)$this->data['id'] .", '". ($comment['date_created'] = date('Y-m-d H:i:s')) ."');" ); $comment['id'] = database::insert_id(); if ($comment['author'] == 'staff' && !empty($comment['notify']) && empty($comment['hidden'])) { $notify_comments[] = $comment; } } database::query( "update ". DB_TABLE_PREFIX ."orders_comments
            set author = '". (!empty($comment['author']) ? database::input($comment['author']) : 'system') ."',
              author_id = ". (int)$comment['author_id'] .",
              text = '". database::input($comment['text']) ."',
              hidden = '". (!empty($comment['hidden']) ? 1 : 0) ."'
            where order_id = ". (int)$this->data['id'] ."
            and id = ". (int)$comment['id'] ."
            limit 1;" ); } unset($comment); if (!empty($notify_comments)) { $subject = '['. language::translate('title_order', 'Order') .' #'. $this->data['id'] .'] ' . language::translate('title_new_comments_added', 'New Comments Added', $this->data['language_code']); $message = language::translate('text_new_comments_added_to_your_order', 'New comments added to your order', $this->data['language_code']) . ":\r\n\r\n"; foreach ($notify_comments as $comment) { $message .= language::strftime(language::$selected['format_datetime'], strtotime($comment['date_created'])) ." – ". trim($comment['text']) . "\r\n\r\n"; } $email = new ent_email(); $email->add_recipient($this->data['customer']['email'], $this->data['customer']['firstname'] .' '. $this->data['customer']['lastname']) ->set_subject($subject) ->add_body($message) ->send(); } } if (!empty($this->previous) && ($this->data['order_status_id'] != $this->previous['order_status_id'])) { if (!empty(reference::order_status($this->data['order_status_id'])->notify)) { $this->send_email_notification(); } } list($module_id, $option_id) = !empty($this->data['payment_option']['id']) ? preg_split('#:#', $this->data['payment_option']['id'], 2) : ['', '']; $payment_modules = new mod_payment(); $payment_modules->run('after_save', $module_id, $this); $order_modules = new mod_order(); $order_modules->update($this); $this->previous = $this->data; cache::clear_cache('order'); cache::clear_cache('category'); cache::clear_cache('manufacturer'); cache::clear_cache('products'); } public function refresh_total() { $this->data['subtotal'] = ['amount' => 0, 'tax' => 0]; $this->data['payment_due'] = 0; $this->data['tax_total'] = 0; $this->data['weight_total'] = 0; foreach ($this->data['items'] as $item) { $this->data['subtotal']['amount'] += (float)$item['price'] * (float)$item['quantity']; $this->data['subtotal']['tax'] += (float)$item['tax'] * (float)$item['quantity']; $this->data['payment_due'] += ((float)$item['price'] + (float)$item['tax']) * (float)$item['quantity']; $this->data['tax_total'] += (float)$item['tax'] * (float)$item['quantity']; $this->data['weight_total'] += weight::convert((float)$item['weight'], $item['weight_class'], $this->data['weight_class']) * (float)$item['quantity']; } foreach ($this->data['order_total'] as &$row) { if ($row['module_id'] == 'ot_subtotal') { $row['value'] = (float)$this->data['subtotal']['amount']; $row['tax'] = (float)$this->data['subtotal']['tax']; } if (empty($row['calculate'])) continue; $this->data['payment_due'] += (float)$row['value'] + (float)$row['tax']; $this->data['tax_total'] += (float)$row['tax']; } unset($row); } public function add_item($item) { $fields = [ 'product_id', 'options', 'option_stock_combination', 'name', 'sku', 'gtin', 'taric', 'price', 'tax', 'quantity', 'weight', 'weight_class', 'dim_x', 'dim_y', 'dim_z', 'dim_class', 'error', ]; $i = 1; while (isset($this->data['items']['new_'.$i])) $i++; $item_key = 'new_'.$i; $this->data['items']['new_'.$i]['id'] = ''; foreach ($fields as $field) { $this->data['items']['new_'.$i][$field] = isset($item[$field]) ? $item[$field] : ''; } $this->data['subtotal']['amount'] += (float)$item['price'] * (float)$item['quantity']; $this->data['subtotal']['tax'] += (float)$item['tax'] * (float)$item['quantity']; $this->data['payment_due'] += ((float)$item['price'] + (float)$item['tax']) * (float)$item['quantity']; $this->data['tax_total'] += (float)$item['tax'] * (float)$item['quantity']; $this->data['weight_total'] += weight::convert((float)$item['weight'], $item['weight_class'], $this->data['weight_class']) * (float)$item['quantity']; } public function add_ot_row($row) { $row = [ 'id' => 0, 'module_id' => $row['id'], 'title' => $row['title'], 'value' => (float)$row['value'], 'tax' => (float)$row['tax'], 'calculate' => !empty($row['calculate']) ? 1 : 0, ]; $i = 1; while (isset($this->data['order_total']['new_'.$i])) $i++; $this->data['order_total']['new_'.$i] = $row; if (!empty($row['calculate'])) { $this->data['payment_due'] += $row['value'] + $row['tax']; $this->data['tax_total'] += $row['tax']; } } public function validate($shipping = null, $payment = null) { if (empty($this->data['items'])) return language::translate('error_order_missing_items', 'The order does not contain any items'); foreach ($this->data['items'] as $item) { if (!empty($item['error'])) return language::translate('error_cart_contains_errors', 'Your cart contains errors'); } try { if (empty($this->data['customer']['firstname'])) throw new Exception(language::translate('error_missing_firstname', 'You must enter a first name.')); if (empty($this->data['customer']['lastname'])) throw new Exception(language::translate('error_missing_lastname', 'You must enter a last name.')); if (empty($this->data['customer']['address1'])) throw new Exception(language::translate('error_missing_address1', 'You must enter an address.')); if (empty($this->data['customer']['city'])) throw new Exception(language::translate('error_missing_city', 'You must enter a city.')); if (empty($this->data['customer']['country_code'])) throw new Exception(language::translate('error_missing_country', 'You must select a country.')); if (empty($this->data['customer']['email'])) throw new Exception(language::translate('error_missing_email', 'You must enter an email address.')); if (empty($this->data['customer']['phone'])) throw new Exception(language::translate('error_missing_phone', 'You must enter a phone number.')); if (!functions::validate_email($this->data['customer']['email'])) throw new Exception(language::translate('error_invalid_email_address', 'Invalid email address')); if (reference::country($this->data['customer']['country_code'])->tax_id_format) { if (!empty($this->data['customer']['tax_id'])) { if (!preg_match('#'. reference::country($this->data['customer']['country_code'])->tax_id_format .'#i', $this->data['customer']['tax_id'])) { throw new Exception(language::translate('error_invalid_tax_id_format', 'Invalid tax ID format')); } } } if (reference::country($this->data['customer']['country_code'])->postcode_format) { if (!empty($this->data['customer']['postcode'])) { if (!preg_match('#'. reference::country($this->data['customer']['country_code'])->postcode_format .'#i', $this->data['customer']['postcode'])) { throw new Exception(language::translate('error_invalid_postcode_format', 'Invalid postcode format')); } } else { throw new Exception(language::translate('error_missing_postcode', 'You must enter a postcode')); } } if (settings::get('customer_field_zone') && reference::country($this->data['customer']['country_code'])->zones) { if (empty($this->data['customer']['zone_code']) && reference::country($this->data['customer']['country_code'])->zones) throw new Exception(language::translate('error_missing_zone', 'You must select a zone.')); } if (empty($this->data['customer']['id'])) { $customer_query = database::query( "select id from ". DB_TABLE_PREFIX ."customers
            where email = '". database::input($this->data['customer']['email']) ."'
            and status = 0
            limit 1;" ); if (database::num_rows($customer_query)) { throw new Exception(language::translate('error_customer_account_is_disabled', 'The customer account is disabled')); } } } catch (Exception $e) { return language::translate('title_customer_details', 'Customer Details') .': '. $e->getMessage(); } try { if (!empty($this->data['customer']['different_shipping_address'])) { if (empty($this->data['customer']['shipping_address']['firstname'])) throw new Exception(language::translate('error_missing_firstname', 'You must enter a first name.')); if (empty($this->data['customer']['shipping_address']['lastname'])) throw new Exception(language::translate('error_missing_lastname', 'You must enter a last name.')); if (empty($this->data['customer']['shipping_address']['address1'])) throw new Exception(language::translate('error_missing_address1', 'You must enter an address.')); if (empty($this->data['customer']['shipping_address']['city'])) throw new Exception(language::translate('error_missing_city', 'You must enter a city.')); if (empty($this->data['customer']['shipping_address']['country_code'])) throw new Exception(language::translate('error_missing_country', 'You must select a country.')); if (reference::country($this->data['customer']['shipping_address']['country_code'])->postcode_format) { if (!empty($this->data['customer']['shipping_address']['postcode'])) { if (!preg_match('#'. reference::country($this->data['customer']['shipping_address']['country_code'])->postcode_format .'#i', $this->data['customer']['shipping_address']['postcode'])) { throw new Exception(language::translate('error_invalid_postcode_format', 'Invalid postcode format.')); } } else { throw new Exception(language::translate('error_missing_postcode', 'You must enter a postcode.')); } } if (settings::get('customer_field_zone') && reference::country($this->data['customer']['shipping_address']['country_code'])->zones) { if (empty($this->data['customer']['shipping_address']['zone_code']) && reference::country($this->data['customer']['shipping_address']['country_code'])->zones) return language::translate('error_missing_zone', 'You must select a zone.'); } } } catch (Exception $e) { return language::translate('title_shipping_address', 'Shipping Address') .': '. $e->getMessage(); } $mod_customer = new mod_customer(); $result = $mod_customer->validate($this->data['customer']); if (!empty($result['error'])) { return $result['error']; } if (!empty($shipping->modules) && count($shipping->options($this->data['items'], $this->data['currency_code'], $this->data['customer']))) { if (!empty($this->data['shipping_option']['id'])) { list($module_id, $option_id) = $this->data['shipping_option']['id'] ? preg_split('#:#', $this->data['shipping_option']['id'], 2) : ['', '']; if (empty($shipping->data['options'][$module_id]['options'][$option_id])) { return language::translate('error_invalid_shipping_method_selected', 'Invalid shipping method selected'); } if (!empty($shipping->data['options'][$module_id]['options'][$option_id]['error'])) { return language::translate('error_shipping_method_contains_error', 'The selected shipping method contains errors'); } if ($error = $shipping->run('validate', $module_id, $this)) { return $error; } } else { return language::translate('error_no_shipping_method_selected', 'No shipping method selected'); } } if (!empty($payment->modules) && count($payment->options($this->data['items'], $this->data['currency_code'], $this->data['customer']))) { if (!empty($this->data['payment_option']['id'])) { list($module_id, $option_id) = $this->data['payment_option']['id'] ? preg_split('#:#', $this->data['payment_option']['id'], 2) : ['', '']; if (empty($payment->data['options'][$module_id]['options'][$option_id])) { return language::translate('error_invalid_payment_method_selected', 'Invalid payment method selected'); } if (!empty($payment->data['options'][$module_id]['options'][$option_id]['error'])) { return language::translate('error_payment_method_contains_error', 'The selected payment method contains errors'); } if ($error = $payment->run('validate', $module_id, $this)) { return $error; } } else { return language::translate('error_no_payment_method_selected', 'No payment method selected'); } } $mod_order = new mod_order(); $result = $mod_order->validate($this); if (!empty($result['error'])) { return $result['error']; } return false; } public function send_order_copy($recipient, $ccs=[], $bccs=[], $language_code='') { if (empty($recipient)) return; if (empty($language_code)) $language_code = $this->data['language_code']; $order_status = $this->data['order_status_id'] ? reference::order_status($this->data['order_status_id'], $language_code) : ''; $aliases = [ '%order_id' => $this->data['id'], '%firstname' => $this->data['customer']['firstname'], '%lastname' => $this->data['customer']['lastname'], '%billing_address' => functions::format_address($this->data['customer']), '%payment_transaction_id' => !empty($this->data['payment_transaction_id']) ? $this->data['payment_transaction_id'] : '-', '%shipping_address' => functions::format_address($this->data['customer']['shipping_address']), '%shipping_tracking_id' => !empty($this->data['shipping_tracking_id']) ? $this->data['shipping_tracking_id'] : '-', '%shipping_tracking_url' => !empty($this->data['shipping_tracking_url']) ? $this->data['shipping_tracking_url'] : '', '%order_items' => null, '%payment_due' => currency::format($this->data['payment_due'], true, $this->data['currency_code'], $this->data['currency_value']), '%order_copy_url' => document::ilink('order', ['order_id' => $this->data['id'], 'public_key' => $this->data['public_key']], false, [], $language_code), '%order_status' => !empty($order_status) ? $order_status->name : null, '%store_name' => settings::get('store_name'), '%store_url' => document::ilink('', [], false, [], $language_code), ]; foreach ($this->data['items'] as $item) { if (!empty($item['product_id'])) { $product = reference::product($item['product_id'], $language_code); $options = []; if (!empty($item['options'])) { foreach ($item['options'] as $k => $v) { $options[] = $k .': '. $v; } } $aliases['%order_items'] .= (float)$item['quantity'] .' x '. $product->name . (!empty($options) ? ' ('. implode(', ', $options) .')' : '') . "\r\n"; } else { $aliases['%order_items'] .= (float)$item['quantity'] .' x '. $item['name'] . (!empty($options) ? ' ('. implode(', ', $options) .')' : '') . "\r\n"; } } $aliases['%order_items'] = trim($aliases['%order_items']); $subject = '['. language::translate('title_order', 'Order', $language_code) .' #'. $this->data['id'] .'] '. language::translate('title_order_confirmation', 'Order Confirmation', $language_code); $message = "Thank you for your purchase!\r\n\r\n" . "Your order #%order_id has successfully been created with a total of %payment_due for the following ordered items:\r\n\r\n" . "%order_items\r\n\r\n" . "A printable order copy is available here:\r\n" . "%order_copy_url\r\n\r\n" . "Regards,\r\n" . "%store_name\r\n" . "%store_url\r\n"; $message = strtr(language::translate('email_order_confirmation', $message, $language_code), $aliases); if (!empty(language::$languages[$this->data['language_code']]) && language::$languages[$this->data['language_code']]['direction'] == 'rtl') { $message = "\xe2\x80\x8f" . $message; } $email = new ent_email(); if (!empty($ccs)) { foreach ($ccs as $cc) { $email->add_cc($cc); } } if (!empty($bccs)) { foreach ($bccs as $bcc) { $email->add_bcc($bcc); } } $email->add_recipient($recipient) ->set_subject($subject) ->add_body($message) ->send(); } public function send_email_notification() { if (empty($this->data['order_status_id'])) return; $order_status = reference::order_status($this->data['order_status_id'], $this->data['language_code']); $aliases = [ '%order_id' => $this->data['id'], '%new_status' => $order_status->name, '%firstname' => $this->data['customer']['firstname'], '%lastname' => $this->data['customer']['lastname'], '%billing_address' => nl2br(functions::format_address($this->data['customer']), false), '%payment_transaction_id' => !empty($this->data['payment_transaction_id']) ? $this->data['payment_transaction_id'] : '-', '%shipping_address' => nl2br(functions::format_address($this->data['customer']['shipping_address']), false), '%shipping_tracking_id' => !empty($this->data['shipping_tracking_id']) ? $this->data['shipping_tracking_id'] : '-', '%shipping_tracking_url' => !empty($this->data['shipping_tracking_url']) ? $this->data['shipping_tracking_url'] : '', '%order_items' => null, '%payment_due' => currency::format($this->data['payment_due'], true, $this->data['currency_code'], $this->data['currency_value']), '%order_copy_url' => document::ilink('order', ['order_id' => $this->data['id'], 'public_key' => $this->data['public_key']], false, [], $this->data['language_code']), '%order_status' => $order_status->name, '%store_name' => settings::get('store_name'), '%store_url' => document::ilink('', [], false, [], $this->data['language_code']), ]; foreach ($this->data['items'] as $item) { if (!empty($item['product_id'])) { $product = reference::product($item['product_id'], $this->data['language_code']); $options = []; if (!empty($item['options'])) { foreach ($item['options'] as $k => $v) { $options[] = $k .': '. $v; } } $aliases['%order_items'] .= (float)$item['quantity'] .' x '. $product->name . (!empty($options) ? ' ('. implode(', ', $options) .')' : '') . "<br>\r\n"; } else { $aliases['%order_items'] .= (float)$item['quantity'] .' x '. $item['name'] . (!empty($options) ? ' ('. implode(', ', $options) .')' : '') . "<br>\r\n"; } } $subject = strtr($order_status->email_subject, $aliases); $message = strtr($order_status->email_message, $aliases); if (empty($subject)) $subject = '['. language::translate('title_order', 'Order', $this->data['language_code']) .' #'. $this->data['id'] .'] '. $order_status->name; if (empty($message)) $message = strtr(language::translate('text_order_status_changed_to_new_status', 'Order status changed to %new_status', $this->data['language_code']), $aliases); if (!empty(language::$languages[$this->data['language_code']]) && language::$languages[$this->data['language_code']]['direction'] == 'rtl') { $message = '<div dir="rtl">' . PHP_EOL . $message . PHP_EOL . '</div>'; } $email = new ent_email(); $email->add_recipient($this->data['customer']['email'], $this->data['customer']['firstname'] .' '. $this->data['customer']['lastname']) ->set_subject($subject) ->add_body($message, true) ->send(); } public function adjust_stock_quantity($product_id, $combination, $quantity_adjustment) { if ($quantity_adjustment == 0) return; $product = new ent_product($product_id); $product->adjust_quantity((float)$quantity_adjustment, $combination); } public function delete() { if (empty($this->data['id'])) return; $order_modules = new mod_order(); $order_modules->delete($this->previous); $this->data['items'] = []; $this->data['order_total'] = []; $this->data['comments'] = []; $this->refresh_total(); $this->save(); database::query( "delete from ". DB_TABLE_PREFIX ."orders
        where id = ". (int)$this->data['id'] ."
        limit 1;" ); $this->reset(); cache::clear_cache('order'); cache::clear_cache('category'); cache::clear_cache('manufacturer'); cache::clear_cache('products'); } } 