<?php
 class ent_product { public $data; public $previous; public function __construct($product_id=null) { if (!empty($product_id)) { $this->load($product_id); } else { $this->reset(); } } public function reset() { $this->data = []; $fields_query = database::query( "show fields from ". DB_TABLE_PREFIX ."products;" ); while ($field = database::fetch($fields_query)) { $this->data[$field['Field']] = database::create_variable($field); } $info_fields_query = database::query( "show fields from ". DB_TABLE_PREFIX ."products_info;" ); while ($field = database::fetch($info_fields_query)) { if (in_array($field['Field'], ['id', 'product_id', 'language_code'])) continue; $this->data[$field['Field']] = []; foreach (array_keys(language::$languages) as $language_code) { $this->data[$field['Field']][$language_code] = database::create_variable($field); } } $this->data['status'] = 1; $this->data['tax_class_id'] = settings::get('default_tax_class_id'); $this->data['purchase_price_currency_code'] = settings::get('store_currency_code'); $this->data['quantity_unit_id'] = settings::get('default_quantity_unit_id'); $this->data['delivery_status_id'] = settings::get('default_delivery_status_id'); $this->data['sold_out_status_id'] = settings::get('default_sold_out_status_id'); $this->data['reserved'] = 0; $this->data['categories'] = []; $this->data['attributes'] = []; $this->data['images'] = []; $this->data['prices'] = []; $this->data['campaigns'] = []; $this->data['options'] = []; $this->data['options_stock'] = []; $this->previous = $this->data; } public function load($product_id) { if (empty($product_id)) throw new Exception('Invalid product (ID: n/a)'); $this->reset(); $products_query = database::query( "select * from ". DB_TABLE_PREFIX ."products
        where ". (preg_match('#^[0-9]+$#', $product_id) ? "id = ". (int)$product_id : "sku = '". database::input($product_id) ."'") ."
        limit 1;" ); if ($product = database::fetch($products_query)) { $this->data = array_replace($this->data, array_intersect_key($product, $this->data)); } else { throw new Exception('Could not find product (ID: '. (int)$product_id .') in database.'); } foreach ($product as $key => $value) { $this->data[$key] = $value; } $categories_query = database::query( "select category_id from ". DB_TABLE_PREFIX ."products_to_categories
         where product_id = ". (int)$product_id .";" ); while ($category = database::fetch($categories_query)) { $this->data['categories'][] = $category['category_id']; } $products_info_query = database::query( "select * from ". DB_TABLE_PREFIX ."products_info
         where product_id = ". (int)$product_id .";" ); while ($product_info = database::fetch($products_info_query)) { foreach ($product_info as $key => $value) { if (in_array($key, ['id', 'product_id', 'language_code'])) continue; $this->data[$key][$product_info['language_code']] = $value; } } $product_attributes_query = database::query( "select pa.*, agi.name as group_name, avi.name as value_name from ". DB_TABLE_PREFIX ."products_attributes pa
        left join ". DB_TABLE_PREFIX ."attribute_groups_info agi on (agi.group_id = pa.group_id and agi.language_code = '". database::input(language::$selected['code']) ."')
        left join ". DB_TABLE_PREFIX ."attribute_values_info avi on (avi.value_id = pa.value_id and avi.language_code = '". database::input(language::$selected['code']) ."')
        where product_id = ". (int)$product_id ."
        order by group_name, value_name, custom_value;" ); while ($attribute = database::fetch($product_attributes_query)) { $this->data['attributes'][$attribute['group_id'].'-'.$attribute['value_id'] . ($attribute['custom_value'] ? ':'. $attribute['custom_value'] : '')] = $attribute; } $products_prices_query = database::query( "select * from ". DB_TABLE_PREFIX ."products_prices
        where product_id = ". (int)$this->data['id'] .";" ); while ($product_price = database::fetch($products_prices_query)) { foreach (array_keys(currency::$currencies) as $currency_code) { $this->data['prices'][$currency_code] = $product_price[$currency_code]; } } $product_campaigns_query = database::query( "select * from ". DB_TABLE_PREFIX ."products_campaigns
        where product_id = ". (int)$this->data['id'] ."
        order by start_date;" ); while ($product_campaign = database::fetch($product_campaigns_query)) { $this->data['campaigns'][$product_campaign['id']] = $product_campaign; } $products_options_query = database::query( "select po.*, agi.name from ". DB_TABLE_PREFIX ."products_options po
        left join ". DB_TABLE_PREFIX ."attribute_groups_info agi on (agi.group_id = po.group_id and agi.language_code = '". database::input(language::$selected['code']) ."')
        where product_id = ". (int)$this->data['id'] ."
        order by priority asc;" ); while ($option = database::fetch($products_options_query)) { $option['values'] = []; $products_options_values_query = database::query( "select pov.*, if(pov.value_id = 0, custom_value, avi.name) as name from ". DB_TABLE_PREFIX ."products_options_values pov
          left join ". DB_TABLE_PREFIX ."attribute_values_info avi on (avi.value_id = pov.value_id and avi.language_code = '". database::input(language::$selected['code']) ."')
          where product_id = ". (int)$this->data['id'] ."
          and group_id = ". (int)$option['group_id'] ."
          order by priority asc;" ); while ($value = database::fetch($products_options_values_query)) { $option['values'][$value['id']] = $value; } $this->data['options'][$option['group_id']] = $option; } $products_options_stock_query = database::query( "select pos.*, oi.reserved
        from ". DB_TABLE_PREFIX ."products_options_stock pos
        left join (
          select product_id, sku, sum(quantity) as reserved
          from ". DB_TABLE_PREFIX ."orders_items
          where product_id = ". (int)$this->data['id'] ."
          and order_id in (
            select id from  ". DB_TABLE_PREFIX ."orders
            where order_status_id in (
              select id from ". DB_TABLE_PREFIX ."order_statuses
              where stock_action = 'reserve'
            )
          )
          group by product_id, sku
        ) oi on (oi.sku = pos.sku)
        where pos.product_id = ". (int)$this->data['id'] ."
        order by priority;" ); while ($option_stock = database::fetch($products_options_stock_query)) { $this->data['options_stock'][$option_stock['id']] = $option_stock; $this->data['options_stock'][$option_stock['id']]['name'] = []; foreach (explode(',', $option_stock['combination']) as $combination) { list($group_id, $value_id) = explode('-', $combination); if (preg_match('#^0:"?(.*?)"?$#', $value_id, $matches)) { foreach (array_keys(language::$languages) as $language_code) { if (!isset($this->data['options_stock'][$option_stock['id']]['name'][$language_code])) { $this->data['options_stock'][$option_stock['id']]['name'][$language_code] = ''; } else { $this->data['options_stock'][$option_stock['id']]['name'][$language_code] .= ', '; } $this->data['options_stock'][$option_stock['id']]['name'][$language_code] .= $matches[1]; } } else { $options_values_query = database::query( "select avi.value_id, avi.name, avi.language_code from ". DB_TABLE_PREFIX ."attribute_values_info avi
              where avi.value_id = ". (int)$value_id .";" ); while ($option_value = database::fetch($options_values_query)) { if (!isset($this->data['options_stock'][$option_stock['id']]['name'][$option_value['language_code']])) { $this->data['options_stock'][$option_stock['id']]['name'][$option_value['language_code']] = ''; } else { $this->data['options_stock'][$option_stock['id']]['name'][$option_value['language_code']] .= ', '; } $this->data['options_stock'][$option_stock['id']]['name'][$option_value['language_code']] .= $option_value['name']; } } } } $reserved_query = database::query( "select sum(quantity) as reserved from ". DB_TABLE_PREFIX ."orders_items
        where product_id = ". (int)$this->data['id'] ."
        and order_id in (
          select id from ". DB_TABLE_PREFIX ."orders
          where order_status_id in (
            select id from ". DB_TABLE_PREFIX ."order_statuses
            where stock_action = 'reserve'
          )
        )
        group by product_id;" ); $this->data['reserved'] = database::fetch($reserved_query, 'reserved'); $products_images_query = database::query( "select * from ". DB_TABLE_PREFIX ."products_images
        where product_id = ". (int)$this->data['id'] ."
        order by priority asc, id asc;" ); while ($image = database::fetch($products_images_query)) { $this->data['images'][$image['id']] = $image; } $this->previous = $this->data; } public function save() { if (empty($this->data['id'])) { database::query( "insert into ". DB_TABLE_PREFIX ."products
          (date_created)
          values ('". ($this->data['date_created'] = date('Y-m-d H:i:s')) ."');" ); $this->data['id'] = database::insert_id(); } $this->data['categories'] = array_map('trim', $this->data['categories']); $this->data['categories'] = array_filter($this->data['categories'], function($var) { return ($var != ''); }); $this->data['categories'] = array_unique($this->data['categories']); $this->data['keywords'] = preg_split('#\s*,\s*#', $this->data['keywords'], -1, PREG_SPLIT_NO_EMPTY); $this->data['keywords'] = array_map('trim', $this->data['keywords']); $this->data['keywords'] = array_filter($this->data['keywords']); $this->data['keywords'] = array_unique($this->data['keywords']); $this->data['keywords'] = implode(',', $this->data['keywords']); if (empty($this->data['default_category_id']) || !in_array($this->data['default_category_id'], $this->data['categories'])) { $this->data['default_category_id'] = reset($this->data['categories']); } database::query( "update ". DB_TABLE_PREFIX ."products set
        status = ". (int)$this->data['status'] .",
        manufacturer_id = ". (int)$this->data['manufacturer_id'] .",
        supplier_id = ". (int)$this->data['supplier_id'] .",
        delivery_status_id = ". (int)$this->data['delivery_status_id'] .",
        sold_out_status_id = ". (int)$this->data['sold_out_status_id'] .",
        default_category_id = ". (int)$this->data['default_category_id'] .",
        keywords = '". database::input($this->data['keywords']) ."',
        quantity_min = ". (float)$this->data['quantity_min'] .",
        quantity_max = ". (float)$this->data['quantity_max'] .",
        quantity_step = ". (float)$this->data['quantity_step'] .",
        quantity_unit_id = ". (int)$this->data['quantity_unit_id'] .",
        purchase_price = ". (float)$this->data['purchase_price'] .",
        purchase_price_currency_code = '". database::input($this->data['purchase_price_currency_code']) ."',
        recommended_price = ". (float)$this->data['recommended_price'] .",
        tax_class_id = ". (int)$this->data['tax_class_id'] .",
        code = '". database::input($this->data['code']) ."',
        sku = '". database::input($this->data['sku']) ."',
        mpn = '". database::input($this->data['mpn']) ."',
        gtin = '". database::input($this->data['gtin']) ."',
        taric = '". database::input($this->data['taric']) ."',
        dim_x = ". (float)$this->data['dim_x'] .",
        dim_y = ". (float)$this->data['dim_y'] .",
        dim_z = ". (float)$this->data['dim_z'] .",
        dim_class = '". database::input($this->data['dim_class']) ."',
        weight = ". (float)$this->data['weight'] .",
        weight_class = '". database::input($this->data['weight_class']) ."',
        date_valid_from = ". (empty($this->data['date_valid_from']) ? "null" : "'". date('Y-m-d H:i:s', strtotime($this->data['date_valid_from'])) ."'") .",
        date_valid_to = ". (empty($this->data['date_valid_to']) ? "null" : "'". date('Y-m-d H:i:s', strtotime($this->data['date_valid_to'])) ."'") .",
        date_updated = '". ($this->data['date_updated'] = date('Y-m-d H:i:s')) ."'
        where id = ". (int)$this->data['id'] ."
        limit 1;" ); database::query( "delete from ". DB_TABLE_PREFIX ."products_to_categories
        where product_id = ". (int)$this->data['id'] ."
        and category_id not in ('". implode("', '", database::input($this->data['categories'])) ."');" ); foreach ($this->data['categories'] as $category_id) { if (in_array($category_id, $this->previous['categories'])) continue; database::query( "insert into ". DB_TABLE_PREFIX ."products_to_categories
          (product_id, category_id)
          values (". (int)$this->data['id'] .", ". (int)$category_id .");" ); } foreach (array_keys(language::$languages) as $language_code) { $products_info_query = database::query( "select * from ". DB_TABLE_PREFIX ."products_info
          where product_id = ". (int)$this->data['id'] ."
          and language_code = '". database::input($language_code) ."'
          limit 1;" ); if (!$product_info = database::fetch($products_info_query)) { database::query( "insert into ". DB_TABLE_PREFIX ."products_info
            (product_id, language_code)
            values (". (int)$this->data['id'] .", '". database::input($language_code) ."');" ); } database::query( "update ". DB_TABLE_PREFIX ."products_info set
          name = '". database::input($this->data['name'][$language_code]) ."',
          short_description = '". database::input($this->data['short_description'][$language_code]) ."',
          description = '". database::input($this->data['description'][$language_code], true) ."',
          technical_data = '". database::input($this->data['technical_data'][$language_code], true) ."',
          head_title = '". database::input($this->data['head_title'][$language_code]) ."',
          meta_description = '". database::input($this->data['meta_description'][$language_code]) ."'
          where product_id = ". (int)$this->data['id'] ."
          and language_code = '". database::input($language_code) ."'
          limit 1;" ); } database::query( "delete from ". DB_TABLE_PREFIX ."products_attributes
        where product_id = ". (int)$this->data['id'] ."
        and id not in ('". implode("', '", array_column($this->data['attributes'], 'id')) ."');" ); if (!empty($this->data['attributes'])) { foreach (array_keys($this->data['attributes']) as $key) { if (empty($this->data['attributes'][$key]['id'])) { database::query( "insert into ". DB_TABLE_PREFIX ."products_attributes
              (product_id, group_id, value_id, custom_value)
              values (". (int)$this->data['id'] .", ". (int)$this->data['attributes'][$key]['group_id'] .", ". (int)$this->data['attributes'][$key]['value_id'] .", '". database::input($this->data['attributes'][$key]['custom_value']) ."');" ); $this->data['attributes'][$key]['id'] = database::insert_id(); } database::query( "update ". DB_TABLE_PREFIX ."products_attributes set
              group_id = ". (int)$this->data['attributes'][$key]['group_id'] .",
              value_id = ". (int)$this->data['attributes'][$key]['value_id'] .",
              custom_value = '". database::input($this->data['attributes'][$key]['custom_value']) ."'
            where product_id = ". (int)$this->data['id'] ."
            and id = ". (int)$this->data['attributes'][$key]['id'] ."
            limit 1;" ); } } foreach (array_keys(currency::$currencies) as $currency_code) { $products_prices_query = database::query( "select * from ". DB_TABLE_PREFIX ."products_prices
          where product_id = ". (int)$this->data['id'] ."
          limit 1;" ); if (!$product_price = database::fetch($products_prices_query)) { database::query( "insert into ". DB_TABLE_PREFIX ."products_prices
            (product_id)
            values (". (int)$this->data['id'] .");" ); } $sql_currency_prices = ""; foreach (array_keys(currency::$currencies) as $currency_code) { $sql_currency_prices .= $currency_code ." = '". (!empty($this->data['prices'][$currency_code]) ? (float)$this->data['prices'][$currency_code] : 0) ."', "; } $sql_currency_prices = rtrim($sql_currency_prices, ', '); database::query( "update ". DB_TABLE_PREFIX ."products_prices set
          $sql_currency_prices
          where product_id = ". (int)$this->data['id'] ."
          limit 1;" ); } database::query( "delete from ". DB_TABLE_PREFIX ."products_campaigns
        where product_id = ". (int)$this->data['id'] ."
        and id not in ('". implode("', '", array_column($this->data['campaigns'], 'id')) ."');" ); if (!empty($this->data['campaigns'])) { foreach (array_keys($this->data['campaigns']) as $key) { if (empty($this->data['campaigns'][$key]['id'])) { database::query( "insert into ". DB_TABLE_PREFIX ."products_campaigns
              (product_id)
              values (". (int)$this->data['id'] .");" ); $this->data['campaigns'][$key]['id'] = database::insert_id(); } $sql_currency_campaigns = ""; foreach (array_keys(currency::$currencies) as $currency_code) { $sql_currency_campaigns .= $currency_code ." = '". (float)$this->data['campaigns'][$key][$currency_code] ."', "; } $sql_currency_campaigns = rtrim($sql_currency_campaigns, ', '); database::query( "update ". DB_TABLE_PREFIX ."products_campaigns set
            start_date = ". (empty($this->data['campaigns'][$key]['start_date']) ? "null" : "'". date('Y-m-d H:i:s', strtotime($this->data['campaigns'][$key]['start_date'])) ."'") .",
            end_date = ". (empty($this->data['campaigns'][$key]['end_date']) ? "null" : "'". date('Y-m-d H:i:s', strtotime($this->data['campaigns'][$key]['end_date'])) ."'") .",
            $sql_currency_campaigns
            where product_id = ". (int)$this->data['id'] ."
            and id = ". (int)$this->data['campaigns'][$key]['id'] ."
            limit 1;" ); } } database::query( "delete from ". DB_TABLE_PREFIX ."products_options
        where product_id = ". (int)$this->data['id'] ."
        and id not in ('". implode("', '", array_column($this->data['options'], 'id')) ."');" ); database::query( "delete from ". DB_TABLE_PREFIX ."products_options_values
        where product_id = ". (int)$this->data['id'] ."
        and group_id not in ('". implode("', '", array_column($this->data['options'], 'group_id')) ."');" ); if (!empty($this->data['options'])) { $i = 0; foreach ($this->data['options'] as &$option) { if (empty($option['id'])) { database::query( "insert into ". DB_TABLE_PREFIX ."products_options
              (product_id, group_id)
              values (". (int)$this->data['id'] .", ". (int)$option['group_id'] .");" ); $option['id'] = database::insert_id(); } database::query( "update ". DB_TABLE_PREFIX ."products_options set
              group_id = ". (int)$option['group_id'] .",
              `function` = '". database::input($option['function']) ."',
              required = ". (!empty($option['required']) ? 1 : 0) .",
              sort = '". (!empty($option['sort']) ? database::input($option['sort']) : 'alphabetical') ."',
              priority = ". ++$i ."
            where product_id = ". (int)$this->data['id'] ."
            and id = ". (int)$option['id'] ."
            limit 1;" ); database::query( "delete from ". DB_TABLE_PREFIX ."products_options_values
            where product_id = ". (int)$this->data['id'] ."
            and group_id = ". (int)$option['group_id'] ."
            and id not in ('". implode("', '", !empty($option['values']) ? array_column($option['values'], 'id') : []) ."');" ); if (!empty($option['values'])) { $j = 0; foreach ($option['values'] as &$value) { if (empty($value['id'])) { database::query( "insert into ". DB_TABLE_PREFIX ."products_options_values
                  (product_id, group_id, value_id)
                  values (". (int)$this->data['id'] .", ". (int)$option['group_id'] .", ". (int)$value['value_id'] .");" ); $value['id'] = database::insert_id(); } $sql_currencies = ""; foreach (array_keys(currency::$currencies) as $currency_code) { $sql_currencies .= $currency_code ." = '". (isset($value[$currency_code]) ? (float)$value[$currency_code] : 0) ."', "; } database::query( "update ". DB_TABLE_PREFIX ."products_options_values set
                  group_id = ". (int)$option['group_id'] .",
                  value_id = ". (int)$value['value_id'] .",
                  custom_value = '". database::input($value['custom_value']) ."',
                  price_operator = '". database::input($value['price_operator']) ."',
                  $sql_currencies
                  priority = ". ++$j ."
                where product_id = ". (int)$this->data['id'] ."
                and group_id = ". (int)$option['group_id'] ."
                and id = ". (int)$value['id'] ."
                limit 1;" ); } unset($value); } } unset($option); } database::query( "delete from ". DB_TABLE_PREFIX ."products_options_stock
        where product_id = ". (int)$this->data['id'] ."
        and id not in ('". implode("', '", array_column($this->data['options_stock'], 'id')) ."');" ); if (!empty($this->data['options_stock'])) { $i = 0; foreach ($this->data['options_stock'] as $key => $stock_option) { if (empty($stock_option['id'])) { database::query( "insert into ". DB_TABLE_PREFIX ."products_options_stock
              (product_id, combination, date_created)
              values (". (int)$this->data['id'] .", '". database::input($stock_option['combination']) ."', '". date('Y-m-d H:i:s') ."');" ); $stock_option['id'] = $this->data['options_stock'][$key]['id'] = database::insert_id(); } $combinations = explode(',', $stock_option['combination']); usort($combinations, function($a, $b) { $a = explode('-', $a); $b = explode('-', $b); if ($a[0] == $b[0]) { return ($a[1] < $b[1]) ? -1 : 1; } return ($a[0] < $b[0]) ? -1 : 1; }); $this->data['stock_options'][$key]['combination'] = implode(',', $combinations); database::query( "update ". DB_TABLE_PREFIX ."products_options_stock
            set combination = '". database::input($stock_option['combination']) ."',
            sku = '". database::input($stock_option['sku']) ."',
            weight = '". database::input($stock_option['weight']) ."',
            weight_class = '". database::input($stock_option['weight_class']) ."',
            dim_x = '". database::input($stock_option['dim_x']) ."',
            dim_y = '". database::input($stock_option['dim_y']) ."',
            dim_z = '". database::input($stock_option['dim_z']) ."',
            dim_class = '". database::input($stock_option['dim_class']) ."',
            priority = ". (int)$i++ .",
            date_updated = '". ($this->data['date_updated'] = date('Y-m-d H:i:s')) ."'
            where product_id = ". (int)$this->data['id'] ."
            and id = ". (int)$stock_option['id'] ."
            limit 1;" ); } } $products_images_query = database::query( "select * from ". DB_TABLE_PREFIX ."products_images
        where product_id = ". (int)$this->data['id'] ."
        and id not in ('". implode("', '", array_column($this->data['images'], 'id')) ."');" ); while ($product_image = database::fetch($products_images_query)) { if (is_file(FS_DIR_STORAGE . 'images/' . $product_image['filename'])) { unlink(FS_DIR_STORAGE . 'images/' . $product_image['filename']); } functions::image_delete_cache(FS_DIR_STORAGE . 'images/' . $product_image['filename']); database::query( "delete from ". DB_TABLE_PREFIX ."products_images
          where product_id = ". (int)$this->data['id'] ."
          and id = ". (int)$product_image['id'] ."
          limit 1;" ); } if (!empty($this->data['images'])) { $image_priority = 1; foreach (array_keys($this->data['images']) as $key) { if (empty($this->data['images'][$key]['id'])) continue; if (empty($this->data['images'][$key]['new_filename'])) continue; if ($this->data['images'][$key]['new_filename'] != $this->data['images'][$key]['filename']) { if (is_file(FS_DIR_STORAGE . 'images/' . $this->data['images'][$key]['new_filename'])) { throw new Exception('Cannot rename '. $this->data['images'][$key]['filename'] .' to '. $this->data['images'][$key]['filename'] .' as the new filename already exists'); } rename(FS_DIR_STORAGE . 'images/' . $this->data['images'][$key]['filename'], FS_DIR_STORAGE . 'images/' . $this->data['images'][$key]['new_filename']); $this->data['images'][$key]['filename'] = $this->data['images'][$key]['new_filename']; functions::image_delete_cache(FS_DIR_STORAGE . 'images/' . $this->data['images'][$key]['filename']); functions::image_delete_cache(FS_DIR_STORAGE . 'images/' . $this->data['images'][$key]['new_filename']); } database::query( "update ". DB_TABLE_PREFIX ."products_images
            set filename = '". database::input($this->data['images'][$key]['filename']) ."',
                priority = ". (int)$image_priority++ ."
            where product_id = ". (int)$this->data['id'] ."
            and id = ". (int)$this->data['images'][$key]['id'] ."
            limit 1;" ); } } $this->data['image'] = !empty($this->data['images']) ? array_values($this->data['images'])[0]['filename'] : ''; database::query( "update ". DB_TABLE_PREFIX ."products set
        image = '". database::input($this->data['image']) ."'
        where id = ". (int)$this->data['id'] ."
        limit 1;" ); if (!empty($this->data['options_stock'])) { foreach ($this->data['options_stock'] as $key => $stock_option) { if (!isset($stock_option['quantity_adjustment']) && (empty($this->previous['options_stock'][$key]) || (float)$stock_option['quantity'] != (float)$this->previous['options_stock'][$key]['quantity'])) { if (!empty($this->previous['options_stock'][$key]['quantity'])) { $this->data['options_stock'][$key]['quantity_adjustment'] = (float)$stock_option['quantity'] - (float)$this->previous['options_stock'][$key]['quantity']; } else { $this->data['options_stock'][$key]['quantity_adjustment'] = (float)$stock_option['quantity']; } } } $this->data['quantity'] = array_sum(array_column($this->data['options_stock'], 'quantity_adjust')); } else { if (!isset($this->data['quantity_adjustment']) && (empty($this->previous['quantity']) || (float)$this->data['quantity'] != (float)$this->previous['quantity'])) { $this->data['quantity_adjustment'] = (float)$this->data['quantity'] - (float)$this->previous['quantity']; } } if (!empty($this->data['options_stock'])) { foreach ($this->previous['options_stock'] as $stock_option) { if (!in_array($stock_option['id'], array_column($this->data['options_stock'], 'id'))) { $this->adjust_quantity(-$stock_option['quantity']); } } foreach ($this->data['options_stock'] as $key => $stock_option) { if (!empty($stock_option['quantity_adjustment']) && (float)$stock_option['quantity_adjustment'] != 0) { $this->adjust_quantity($stock_option['quantity_adjustment'], $stock_option['combination']); $this->data['options_stock'][$key]['quantity_adjustment'] = 0; } } } else { if (!empty($this->data['quantity_adjustment']) && (float)$this->data['quantity_adjustment'] != 0) { $this->adjust_quantity($this->data['quantity_adjustment']); $this->data['quantity_adjustment'] = 0; } } $this->previous = $this->data; cache::clear_cache('category'); cache::clear_cache('manufacturer'); cache::clear_cache('products'); } public function adjust_quantity($quantity_adjustment, $combination='') { if ((float)$quantity_adjustment == 0) return; if (empty($this->data['id'])) $this->save(); if (!empty($combination)) { database::query( "update ". DB_TABLE_PREFIX ."products_options_stock
          set quantity = quantity + ". (float)$quantity_adjustment ."
          where product_id = ". (int)$this->data['id'] ."
          and combination = '". database::input($combination) ."'
          limit 1;" ); if (!database::affected_rows()) { trigger_error('Could not adjust stock for product (ID: '. $this->data['id'] .', Combination: '. $combination .')', E_USER_WARNING); } } database::query( "update ". DB_TABLE_PREFIX ."products
        set quantity = quantity + ". (float)$quantity_adjustment ."
        where id = ". (int)$this->data['id'] ."
        limit 1;" ); if (!database::affected_rows()) { trigger_error('Could not adjust stock for product (ID: '. $this->data['id'] .')', E_USER_WARNING); } } public function add_image($file, $filename='') { if (empty($file)) { throw new Exception('Missing image'); }; $checksum = md5_file($file); if (in_array($checksum, array_column($this->data['images'], 'checksum'))) return false; if (!empty($filename)) $filename = 'products/' . $filename; if (empty($this->data['id'])) { $this->save(); } if (!is_dir(FS_DIR_STORAGE . 'images/products/')) mkdir(FS_DIR_STORAGE . 'images/products/', 0777); if (!$image = new ent_image($file)) { throw new Exception('Failed decoding image'); } $i=1; while (empty($filename) || is_file(FS_DIR_STORAGE . 'images/' . $filename)) { $filename = 'products/' . $this->data['id'] .'-'. functions::format_path_friendly($this->data['name'][settings::get('store_language_code')], settings::get('store_language_code')) .'-'. $i++ .'.'. $image->type(); } $priority = count($this->data['images'])+1; if (settings::get('image_downsample_size')) { list($width, $height) = explode(',', settings::get('image_downsample_size')); $image->resample($width, $height, 'FIT_ONLY_BIGGER'); } if (!$image->write(FS_DIR_STORAGE . 'images/' . $filename, 90)) { throw new Exception('Failed writing image to folder'); } functions::image_delete_cache(FS_DIR_STORAGE . 'images/' . $filename); database::query( "insert into ". DB_TABLE_PREFIX ."products_images
        (product_id, filename, checksum, priority)
        values (". (int)$this->data['id'] .", '". database::input($filename) ."', '". database::input($checksum) ."', ". (int)$priority .");" ); $image_id = database::insert_id(); $this->data['images'][$image_id] = [ 'id' => $image_id, 'filename' => $filename, 'checksum' => $checksum, 'priority' => $priority, ]; $this->previous['images'][$image_id] = $this->data['images'][$image_id]; } public function delete() { if (empty($this->data['id'])) return; $this->data['images'] = []; $this->data['campaigns'] = []; $this->data['attributes'] = []; $this->data['options'] = []; $this->data['options_stock'] = []; $this->save(); database::query( "delete from ". DB_TABLE_PREFIX ."products
        where id = ". (int)$this->data['id'] ."
        limit 1;" ); database::query( "delete from ". DB_TABLE_PREFIX ."products_info
        where product_id = ". (int)$this->data['id'] .";" ); database::query( "delete from ". DB_TABLE_PREFIX ."products_to_categories
         where product_id = ". (int)$this->data['id'] .";" ); database::query( "delete from ". DB_TABLE_PREFIX ."products_prices
        where product_id = ". (int)$this->data['id'] .";" ); database::query( "delete from ". DB_TABLE_PREFIX ."products_campaigns
        where product_id = ". (int)$this->data['id'] .";" ); $this->reset(); cache::clear_cache('category'); cache::clear_cache('manufacturer'); cache::clear_cache('products'); } } 