<?php
/*
 * @version			$Id: index.php 10381 2008-06-01 03:35:53Z $
 * @package			Carteasy
 * @copyright		Copyright (C) 2005 - 2011 Wlanium
 * @license			proprietary
 * @author			Thomas Bartelt
 * Carteasy is a web shop system
 */

include_once './core/main.class.php';
include_once './core/tax.class.php';
include_once './libs/phImaginator/phImaginator.class.php';
include_once './core/manufacturer.class.php';
include_once './core/database.class.php';
include_once './core/tax.class.php';
include_once './core/money.class.php';
include_once './core/customer_group.class.php';
include_once './core/itemschema.class.php';
include_once './core/structure.class.php';

class Item extends Main {

	public $list_table_config = array(
		'title' => 'Artikel',
		'db_table' => 'items',
		'list_fields' => array(
			array(
				'db_field' => 'number',
				'name' => 'Art-Nr.',
				'sortable' => 1
			),
			array(
				'db_field' => 'name',
				'name' => 'Bezeichnung',
				'sortable' => 1
			),
			array(
				'db_field' => 'file_name',
				'ref_db_table' => 'item_files',
				'ref_db1_field' => 'id',
				'ref_db2_field' => 'item_id',
				'name' => 'Bild',
				'function' => 'count',
				'sortable' => 0
			),
			array(
				'db_field' => 'manufacturer_id',
				'name' => 'Hersteller',
				'rewrite_function' => 'manufacturer_names',
				'sortable' => 1
			),
			array(
				'db_field' => 'inventory',
				'name' => 'Lager',
				'sortable' => 1
			),
			array(
				'db_field' => 'price_1',
				'ref_db_table' => 'item_prices',
				'ref_db1_field' => 'id',
				'ref_db2_field' => 'item_id',
				'name' => 'Preis (netto)',
				'format' => 'netto_price',
				'sortable' => 1
			),
			array(
				'db_field' => 'steuersatz / 100 * item_prices.price_1 + item_prices.price_1 AS price_brutto',
				'db_field_rename' => 'price_brutto',
				'ref_db_table' => 'tax',
				'ref_db1_field' => 'tax_id',
				'ref_db2_field' => 'id',
				'name' => 'Preis (brutto)',
				'format' => 'netto_price',
				'sortable' => 0
			),
			array(
				'db_field' => 'structure_id',
				'name' => 'Hauptwarengruppe',
				'rewrite_function' => 'structure_values',
				'sortable' => 1
			),
			array(
				'db_field' => 'item_type_id',
				'ref_db_table' => 'item_types',
				'ref_db1_field' => 'id',
				'ref_db2_field' => 'item_id',
				'name' => 'Typzuordnung',
				'function' => 'count',
				'sortable' => 0
			),
			array(
				'db_field' => 'active',
				'name' => 'Status',
				'rewrite_function' => 'state_text',
				'sortable' => 1
			)
		),
		'permanent_filter' => array(
			array(
				'db_field' => 'parent_id',
				'relational_operator' => '=',
				'value' => '0'
			)
		),
		'list_group_by' => 'id',
		'default_sort_item' => 'number',
		'default_sort_direction' => 'up',
		'search_fields' => array('items.name', 'items.number', 'items.short_description', 'items.detail_description'),
		'db_id_field' => 'id',
		'edit_link' => 'index.php?admin_modul=admin_item_editor&id=',
		'toolbar' => array(
			'delete' => '1',
			'new' => 'index.php?admin_modul=admin_item_editor',
			'copy' => 0,
			'select_all' => 1,
			'edit' => 0,
			'actions' => 1,
			'filter' => 1,
			'view' => 0,
			'csv_export' => 1,
			'search' => 1
		),
		'list_actions' => array(
			array(
				'db_field' => 'active',
				'name' => 'Neuer Status',
				'values' => 'state_text'
			)
		),
		'list_filter' => array(
			array(
				'db_field' => 'manufacturer_id',
				'relational_operator' => '=',
				'name' => 'Hersteller',
				'values' => 'manufacturer_names'
			),
			array(
				'db_field' => 'active',
				'relational_operator' => '=',
				'name' => 'Status',
				'values' => 'state_text'
			),
			array(
				'db_field' => 'items.structure_id',
				'relational_operator' => '=',
				'name' => 'Hauptwarengruppe',
				'values' => 'structure_values'
			),
			array(
				'db_field' => 'items.inventory',
				'name' => 'Lagerbestand',
				'values' => 'inventory_filter'
			),
			array(
				'db_field' => 'items.shippable',
				'relational_operator' => '=',
				'name' => 'Lieferstatus kein Bestand',
				'values' => 'shipping_states'
			),
			array(
				'db_field' => 'items.shippable_inventory',
				'relational_operator' => '=',
				'name' => 'Lieferstatus bei Bestand',
				'values' => 'shipping_states'
			),
			array(
				'db_field' => '(item_prices.price_1',
				'name' => 'Netto-Händlerpreis',
				'values' => 'price_filter'
			),
			array(
				'db_field' => 'item_files.file_name',
				'name' => 'Artikelbild',
				'values' => 'image_filter'
			),
			array(
				'db_field' => 'item_types.item_type_definition_id',
				'relational_operator' => '=',
				'name' => 'Artikeltypzuordnung',
				'values' => 'item_type_values'
			),
		),
		'edit_fields' => array(
			array(
				'db_field' => 'active',
				'name' => 'Status',
				'type' => 'int'
			)
		)
	);
	private $schema_fields = array(
		'name' => 'text',
		'description' => 'text',
		'selectable_attribute_1' => 'integer',
		'selectable_attribute_2' => 'integer',
		'base_price_field' => 'integer',
		'base_price_faktor' => 'float',
		'base_price_unit' => 'text',
		'attribute_name_1' => 'text',
		'attribute_name_1_en' => 'text',
		'attribute_unit_1' => 'text',
		'attribute_rang_1' => 'integer',
		'attribute_liste_1' => 'integer',
		'attribute_detail_1' => 'integer',
		'attribute_name_2' => 'text',
		'attribute_name_2_en' => 'text',
		'attribute_unit_2' => 'text',
		'attribute_rang_2' => 'integer',
		'attribute_liste_2' => 'integer',
		'attribute_detail_2' => 'integer',
		'attribute_name_3' => 'text',
		'attribute_name_3_en' => 'text',
		'attribute_unit_3' => 'text',
		'attribute_rang_3' => 'integer',
		'attribute_liste_3' => 'integer',
		'attribute_detail_3' => 'integer',
		'attribute_name_4' => 'text',
		'attribute_name_4_en' => 'text',
		'attribute_unit_4' => 'text',
		'attribute_rang_4' => 'integer',
		'attribute_liste_4' => 'integer',
		'attribute_detail_4' => 'integer',
		'attribute_name_5' => 'text',
		'attribute_name_5_en' => 'text',
		'attribute_unit_5' => 'text',
		'attribute_rang_5' => 'integer',
		'attribute_liste_5' => 'integer',
		'attribute_detail_5' => 'integer',
		'attribute_name_6' => 'text',
		'attribute_name_6_en' => 'text',
		'attribute_unit_6' => 'text',
		'attribute_rang_6' => 'integer',
		'attribute_liste_6' => 'integer',
		'attribute_detail_6' => 'integer',
		'attribute_name_7' => 'text',
		'attribute_name_7_en' => 'text',
		'attribute_unit_7' => 'text',
		'attribute_rang_7' => 'integer',
		'attribute_liste_7' => 'integer',
		'attribute_detail_7' => 'integer',
		'attribute_name_8' => 'text',
		'attribute_name_8_en' => 'text',
		'attribute_unit_8' => 'text',
		'attribute_rang_8' => 'integer',
		'attribute_liste_8' => 'integer',
		'attribute_detail_8' => 'integer',
		'attribute_name_9' => 'text',
		'attribute_name_9_en' => 'text',
		'attribute_unit_9' => 'text',
		'attribute_rang_9' => 'integer',
		'attribute_liste_9' => 'integer',
		'attribute_detail_9' => 'integer',
		'attribute_name_10' => 'text',
		'attribute_name_10_en' => 'text',
		'attribute_unit_10' => 'text',
		'attribute_rang_10' => 'integer',
		'attribute_liste_10' => 'integer',
		'attribute_detail_10' => 'integer',
		'attribute_name_11' => 'text',
		'attribute_name_11_en' => 'text',
		'attribute_unit_11' => 'text',
		'attribute_rang_11' => 'integer',
		'attribute_liste_11' => 'integer',
		'attribute_detail_11' => 'integer',
		'attribute_name_12' => 'text',
		'attribute_name_12_en' => 'text',
		'attribute_unit_12' => 'text',
		'attribute_rang_12' => 'integer',
		'attribute_liste_12' => 'integer',
		'attribute_detail_12' => 'integer',
		'attribute_name_13' => 'text',
		'attribute_name_13_en' => 'text',
		'attribute_unit_13' => 'text',
		'attribute_rang_13' => 'integer',
		'attribute_liste_13' => 'integer',
		'attribute_detail_13' => 'integer',
		'attribute_name_14' => 'text',
		'attribute_name_14_en' => 'text',
		'attribute_unit_14' => 'text',
		'attribute_rang_14' => 'integer',
		'attribute_liste_14' => 'integer',
		'attribute_detail_14' => 'integer',
		'attribute_name_15' => 'text',
		'attribute_name_15_en' => 'text',
		'attribute_unit_15' => 'text',
		'attribute_rang_15' => 'integer',
		'attribute_liste_15' => 'integer',
		'attribute_detail_15' => 'integer',
		'attribute_name_16' => 'text',
		'attribute_name_16_en' => 'text',
		'attribute_unit_16' => 'text',
		'attribute_rang_16' => 'integer',
		'attribute_liste_16' => 'integer',
		'attribute_detail_16' => 'integer',
		'attribute_name_17' => 'text',
		'attribute_name_17_en' => 'text',
		'attribute_unit_17' => 'text',
		'attribute_rang_17' => 'integer',
		'attribute_liste_17' => 'integer',
		'attribute_detail_17' => 'integer',
		'attribute_name_18' => 'text',
		'attribute_name_18_en' => 'text',
		'attribute_unit_18' => 'text',
		'attribute_rang_18' => 'integer',
		'attribute_liste_18' => 'integer',
		'attribute_detail_18' => 'integer',
		'attribute_name_19' => 'text',
		'attribute_name_19_en' => 'text',
		'attribute_unit_19' => 'text',
		'attribute_rang_19' => 'integer',
		'attribute_liste_19' => 'integer',
		'attribute_detail_19' => 'integer',
		'attribute_name_20' => 'text',
		'attribute_name_20_en' => 'text',
		'attribute_unit_20' => 'text',
		'attribute_rang_20' => 'integer',
		'attribute_liste_20' => 'integer',
		'attribute_detail_20' => 'integer'
	);
	private $item_fields = array(
		'active' => 'integer',
		'parent_id' => 'integer',
		'number' => 'text',
		'name' => 'text',
		'short_description' => 'text',
		'detail_description' => 'text',
		'name_en' => 'text',
		'short_description_en' => 'text',
		'detail_description_en' => 'text',
		'youtube_video' => 'text',
		'structure_id' => 'integer',
		/*'structure_id_2' => 'integer',
		'structure_id_3' => 'integer',
		'structure_id_4' => 'integer',
		'structure_id_5' => 'integer',
		'structure_id_6' => 'integer',
		'structure_id_7' => 'integer',
		'structure_id_8' => 'integer',
		'structure_id_9' => 'integer',
		'structure_id_10' => 'integer',*/
		'manufacturer_id' => 'integer',
		'manufacturer_item_number' => 'text',
		'ean_code' => 'text',
		'short_uri' => 'text',
		'seo_title' => 'text',
		'seo_description' => 'text',
		'seo_keywords' => 'text',
		'inventory_number' => 'text',
		'inventory' => 'integer',
		'inventory_min' => 'integer',
		'inventory_rack_number' => 'text',
		'inventory_order_quantity' => 'integer',
		'tax_id' => 'integer',
		'base_price' => 'float',
		'price_type' => 'integer',
		'bargain_price_type' => 'integer',
		'uvp' => 'float',
		'schema_id' => 'integer',
		/* 'price_1' => 'float',
		'bargain_price_1' => 'float',
		'quantity_1' => 'integer',
		'price_2' => 'float',
		'bargain_price_2' => 'float',
		'quantity_2' => 'integer',
		'price_3' => 'float',
		'bargain_price_3' => 'float',
		'quantity_3' => 'integer',
		'price_4' => 'float',
		'bargain_price_4' => 'float',
		'quantity_4' => 'integer',
		'price_5' => 'float',
		'bargain_price_5' => 'float',
		'quantity_5' => 'integer',
		'price_6' => 'float',
		'bargain_price_6' => 'float',
		'quantity_6' => 'integer',
		'price_7' => 'float',
		'bargain_price_7' => 'float',
		'quantity_7' => 'integer',
		'price_8' => 'float',
		'bargain_price_8' => 'float',
		'quantity_8' => 'integer',
		'price_9' => 'float',
		'bargain_price_9' => 'float',
		'quantity_9' => 'integer',
		'price_10' => 'float',
		'bargain_price_10' => 'float',
		'quantity_10' => 'integer',
		'price_11' => 'float',
		'bargain_price_11' => 'float',
		'quantity_11' => 'integer',
		'price_12' => 'float',
		'bargain_price_12' => 'float',
		'quantity_12' => 'integer',
		'price_13' => 'float',
		'bargain_price_13' => 'float',
		'quantity_13' => 'integer',
		'price_14' => 'float',
		'bargain_price_14' => 'float',
		'quantity_14' => 'integer',
		'price_15' => 'float',
		'bargain_price_15' => 'float',
		'quantity_15' => 'integer',
		'price_16' => 'float',
		'bargain_price_16' => 'float',
		'quantity_16' => 'integer',
		'price_17' => 'float',
		'bargain_price_17' => 'float',
		'quantity_17' => 'integer',
		'price_18' => 'float',
		'bargain_price_18' => 'float',
		'quantity_18' => 'integer',
		'price_19' => 'float',
		'bargain_price_19' => 'float',
		'quantity_19' => 'integer',
		'price_20' => 'float',
		'bargain_price_20' => 'float',
		'quantity_20' => 'integer',
		'price_21' => 'float',
		'bargain_price_21' => 'float',
		'quantity_21' => 'integer',
		'price_22' => 'float',
		'bargain_price_22' => 'float',
		'quantity_22' => 'integer',
		'price_23' => 'float',
		'bargain_price_23' => 'float',
		'quantity_23' => 'integer',
		'price_24' => 'float',
		'bargain_price_24' => 'float',
		'quantity_24' => 'integer',
		'price_25' => 'float',
		'bargain_price_25' => 'float',
		'quantity_25' => 'integer',
		'price_26' => 'float',
		'bargain_price_26' => 'float',
		'quantity_26' => 'integer',
		'price_27' => 'float',
		'bargain_price_27' => 'float',
		'quantity_27' => 'integer',
		'price_28' => 'float',
		'bargain_price_28' => 'float',
		'quantity_28' => 'integer',
		'price_29' => 'float',
		'bargain_price_29' => 'float',
		'quantity_29' => 'integer',
		'price_30' => 'float',
		'bargain_price_30' => 'float',
		'quantity_30' => 'integer', */
		'attribute_1' => 'text',
		'attribute_2' => 'text',
		'attribute_3' => 'text',
		'attribute_4' => 'text',
		'attribute_5' => 'text',
		'attribute_6' => 'text',
		'attribute_7' => 'text',
		'attribute_8' => 'text',
		'attribute_9' => 'text',
		'attribute_10' => 'text',
		'attribute_11' => 'text',
		'attribute_12' => 'text',
		'attribute_13' => 'text',
		'attribute_14' => 'text',
		'attribute_15' => 'text',
		'attribute_16' => 'text',
		'attribute_17' => 'text',
		'attribute_18' => 'text',
		'attribute_19' => 'text',
		'attribute_20' => 'text',
		'shippable' => 'shippable',
		'available_from' => 'date',
		'available_till' => 'date',
		'variant_price_type' => 'integer',
		'google_product_category' => 'text',
		'combination_item' => 'integer',
		'sample_unit' => 'text',
		'vendor_item_number' => 'text',
		'vendor_id' => 'integer',
		'has_user_data' => 'integer',
		'price_je_vpe' => 'integer',
		'vpe_amount' => 'integer',
		'vpe_unit' => 'text',
		'vpe_sampleprice_unit' => 'float',
		'min_quantity' => 'integer',
		'shippable_inventory' => 'integer',
		'shipping_cost_type' => 'integer',
		'shipping_item_type' => 'integer',
		'shipping_weight' => 'float',
		'buy_quantity' => 'integer',
		'main_variant_item_id' => 'integer'
	);
	private $config;
	protected $base_object;
	private $shopConfiguration;
	private $schema_id;
	private $itemschema_object;
	private $item_discounts;
	protected $db;
	public $id = 0;
	public $shopArticleProducers;
	public $discount;
	public $selectableVariants = array();
	public $deleteSelectableVariants = array();
	public $itemCount;
	private $tax_rates;
	private $manufacturers;
	private $structure;

	public function __construct($base_object, $id = false, $with_discounts = 1) {
		parent::__construct($base_object);
		$this->config = $base_object->config;
		$this->db = $base_object->db;
		$this->base_object = $base_object;

		$this->id = $id;
		$this->shopConfiguration = $this->config->shopConfiguration;


		if ($this->shopConfiguration['show_child_items'] == 1) {
			$this->list_table_config['permanent_filter'] = array();
		}

		$this->list_table_config['permanent_filter'][] = array(
			'db_field' => 'item_prices.customergroup_id',
			'relational_operator' => '=',
			'accept_null' => 1,
			'value' => $this->shopConfiguration['item_list_price_group_id']
		);

		$tax_object = new Tax($base_object);
		$this->all_tax = $tax_object->get_all();

		$this->itemschema_object = new ItemSchema($base_object);

		if ($with_discounts) {
			$this->load_item_discounts();
		}

		$this->setup_manufacturers_array();
		$this->setup_tax_rate_array();
		$this->setup_structure_array();
	}

		// end __construct

			public function netto_price($string) {
				return '<span class="order_list_item_price">'.number_format($string, 2, ',', '').' &euro;</span>';
			}

			public function state_text() {
				return array(
					'1' => 'aktiv',
					'0' => 'inaktiv'
				);
			}

			public function shipping_states() {
				return array(
					'1' => 'lieferbar',
					'0' => 'nicht lieferbar',
					'2' => 'lieferbar ab',
					'3' => 'lieferzeit unbekannt',
					'4' => 'Bestellartikel (Lieferzeit 2-3 Tage)',
					'5' => 'Bestellartikel (Lieferzeit 14 Tage)'
				);
			}

			public function inventory_filter() {
				if ($this->base_object->config->shopConfiguration['item_list_filter_max_inventory'] != '') {
					return array(
						'> 0' => '> 0',
						'= 0' => '= 0',
						'< 0' => '< 0',
						'< '.$this->base_object->config->shopConfiguration['item_list_filter_max_inventory'] => '< '.$this->base_object->config->shopConfiguration['item_list_filter_max_inventory']
					);
				} else {
					return array(
						'> 0' => '> 0',
						'= 0' => '= 0',
						'< 0' => '< 0'
					);
				}
			}

			public function price_filter() {
				return array(
					'> 0)' => '> 0',
					'= 0 || item_prices.price_1 IS NULL)' => '= 0',
					'< 100)' => '< 100',
					'> 100)' => '> 100',
					'< 1000)' => '< 1000',
					'> 1000)' => '> 1000'
				);
			}

			public function image_filter() {
				return array(
					"IS NULL" => 'nicht vorhanden',
				);
			}

			public function manufacturer_names() {
				$manufacturer_object = new Manufacturer($this->base_object);
				return $manufacturer_object->get_all_names();
			}

			public function structure_values() {
				$structure_object = new Structure($this->base_object);
				$data = $structure_object->full_name_path();
				$data['0'] = '>>keine Zuweisung vorhanden<<';
				return $data;
			}

			public function item_type_values() {
				include_once './core/itemtype.class.php';
				$item_type_object = new ItemType($this->base_object);
				$data = $item_type_object->get_item_type_definitions();
				return $data;
			}

			private function setup_manufacturers_array() {
				$sql = "SELECT * FROM manufacturers";

				$result = $this->db->query($sql);

				if ($result->num_rows > 0) {
					$this->manufacturers = array();

					while ($obj = $result->fetch_object()) {
						$this->manufacturers[$obj->id] = $obj;
					}
				}
			}

		// end setup_manufacturers_array

			private function setup_tax_rate_array() {
				$sql = "SELECT * FROM tax";

				$result = $this->db->query($sql);

				if ($result->num_rows > 0) {
					$this->tax_rates = array();

					while ($obj = $result->fetch_object()) {
						$this->tax_rates[$obj->id] = $obj;
					}
				}
			}

		// end setup_tax_rate_array

			private function setup_structure_array() {
				$sql = "SELECT * FROM structure";

				$result = $this->db->query($sql);

				if ($result->num_rows > 0) {
					$this->structure = array();

					while ($obj = $result->fetch_object()) {
						$this->structure[$obj->id] = $obj;
					}
				}
			}

		// end setup_structure_array

			public function set_schema_id($id) {
				$this->schema_id = $id;
			}

			public function get_schema_id() {
				return $this->schema_id;
			}

			public function set($data) {
				foreach ($data as $key => $value) {
					$this->{$key} = $value;
				}

				return;
			}

		// end set

			public function set_id($id) {
				$this->id = $id;
			}

			public function has_id() {
				if ($this->id) {
					return true;
				}

				return false;
			}

			public function get_id($id) {
				return $this->id;
			}

			public function set_row($data) {
				$dat = Database::clean($data);
				$sql = Database::insert('items', $data);
			}

			public function get_sold_out() {
				$sql = "SELECT id, name, inventory FROM items WHERE inventory_min>inventory LIMIT 10";

				$result = $this->db->query($sql);

				if ($result->num_rows > 0) {
					while ($row = $result->fetch_object()) {
						$data[] = $row;
					}

					return $data;
				}

				return false;
			}

			public function get_all_paginated($items, $page, $order = false, $sort_direction = false) {
				$page = ($page - 1) * $items;

				$sort = '';
				if ($order) {
					$sort = " ORDER BY ".$this->db->real_escape_string($order);
					if ($sort_direction && $sort_direction == 'down') {
						$sort .= " DESC ";
					} else {
						$sort .= " ASC ";
					}
				}

				if ($order == 'new') {
					$sql = "SELECT id, tax_id, number, name, active, price_1, bargain_price_1, inventory, inventory_min
							FROM items $sort
							LIMIT $items OFFSET $page;";
				} else if ($order == 'sold_out') {
					$sql = "SELECT id, tax_id, number, name, active, price_1
							FROM items  $sort
							LIMIT $items OFFSET $page;";
				} else {
					if ($_GET['structure_id']) {
						$sql = "SELECT id, tax_id, number, name, active, price_1, bargain_price_1, inventory, inventory_min
								FROM items 
								WHERE structure_id=".$_GET['structure_id']."
								OR structure_id_2=".$_GET['structure_id']."
								OR structure_id_3=".$_GET['structure_id']."
								$sort
								LIMIT $items OFFSET $page;";
					} else {
						$sql = "SELECT id, tax_id, number, name, active, price_1, bargain_price_1, inventory, inventory_min
								FROM items $sort
								LIMIT $items OFFSET $page;";
					}
				}

				$data = parent::get_all_paginated($items, $page, $sql);
				$new_data = array();
				foreach ($data as $obj) {
					$sql = "SELECT * FROM item_prices WHERE item_id = ".$obj->id." AND customergroup_id = 1 ";
					$result = $this->db->query($sql);
					$prices = ($result && $result->num_rows > 0) ? $result->fetch_object() : (object) array();
					// PHP 8 FIX: Only iterate if prices is an object with properties
					foreach ((array) $prices as $field => $value) {
						if ($field != 'item_id' && $field != 'customergroup_id') {
							$obj->{$field} = $value;
						}
					}
					$obj->tax = $this->all_tax[$obj->tax_id]->steuersatz;
					// calc tax
					$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2);
					$obj->price_1_tax = $obj->price_1 + $obj->tax_value;

					$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2);
					$obj->bargain_price_1_tax = $obj->bargain_price_1 + $obj->bargain_tax_value;

					$new_data[] = $obj;
				}
				return $new_data;
			}

		// end get_all_paginated

			public function get_data($forCustomerGroup = 1, $for_frontend = true) {
				$manufacturer = new Manufacturer($this->base_object);

				$customer_group_price = $forCustomerGroup;
				$customer_group_discount = $forCustomerGroup;
				if (isset($this->base_object->customer_group->adaptPricesFromId) && $this->base_object->customer_group->adaptPricesFromId) {
					$customer_group_price = $this->base_object->customer_group->adaptPricesFromId;
				}
				$forCustomerGroup = $customer_group_price;

				// Item Match
				$sql = "SELECT * FROM krempl_passendwie im JOIN items i ON i.attribute_7 = im.navisionid WHERE i.id = " . $this->id;
				$result = $this->db->query($sql);
				$obj = $result->fetch_object();

				// Get all Item Data
				$sql = "SELECT * FROM items WHERE id = " . $this->id;
				$result = $this->db->query($sql);
				$obj = $result->fetch_object();

				// Debug: Überprüfen der Objekt-Eigenschaften  
				// PHP 8 FIX: Check if object exists before get_object_vars()
				$debug_obj = ($obj !== null && is_object($obj)) ? get_object_vars($obj) : array();
				if (isset($debug_obj['vendor_id'])) {
					// Stelle sicher, dass vendor_id als Integer behandelt wird
					$obj->vendor_id = intval($debug_obj['vendor_id']);
				}

				$sql = "SELECT i.number, im.vertreiber, im.bestellcode, i.attribute_7, i.number, i.krempl_id 
						FROM krempl_passendwie im 
						INNER JOIN items i ON i.attribute_7 = im.navisionid 
						WHERE i.id = " . $this->id;
				$result = $this->db->query($sql);
				while ($row = $result->fetch_object()) {
					$obj->match[] = $row;
				}

					// Herstellerinformationen abrufen
					if (isset($obj->vendor_id) && !empty($obj->vendor_id)) {
						$manufacturerId = $obj->vendor_id;

						// SQL-Abfrage zur Herstellerinformationen
						$sql = "SELECT * FROM herstellerinformationen WHERE id = ?";
						$stmt = $this->db->prepare($sql);

						if ($stmt) {
							$stmt->bind_param("i", $manufacturerId);
							$stmt->execute();
							$result = $stmt->get_result();
							$manufacturerInfo = $result->fetch_assoc(); // Hol die Herstellerinformationen als Array

							// Füge die Herstellerinformationen dem Artikelobjekt hinzu
							if ($manufacturerInfo) {
								$obj->herstellerinfo = $manufacturerInfo;
								error_log("Herstellerinfo gefunden für vendor_id " . $manufacturerId . ": " . print_r($manufacturerInfo, true));
							} else {
								$obj->herstellerinfo = []; // Leeres Array, wenn keine Daten gefunden wurden
								error_log("Keine Herstellerinfo gefunden für vendor_id: " . $manufacturerId);
							}
						} else {
							error_log("Fehler beim Vorbereiten des SQL-Statements: " . $this->db->error);
							$obj->herstellerinfo = []; // Fehler beim SQL-Statement
						}
					} else {
						error_log("Keine vendor_id vorhanden oder leer");
						$obj->herstellerinfo = []; // Kein vendor_id vorhanden oder leer
					}


// Sicherheitshinweise und Dokumente hinzufügen
if (isset($obj->attribute_7) && !empty($obj->attribute_7)) {
    $navisionId = $obj->attribute_7;

    $sql = "SELECT * FROM sicherheitshinweis_item WHERE navision_id = ?";
    $stmt = $this->db->prepare($sql);

    if ($stmt) {
        $stmt->bind_param("s", $navisionId);
        $stmt->execute();
        $result = $stmt->get_result();
        $warningDocsList = $result->fetch_assoc();

		if ($warningDocsList) {
			// Sicherheitswarnungen laden
			$warningIdsList = $warningDocsList['warning_ids'] ?? null;
			$obj->warnings = $this->loadWarnings($warningIdsList);
		
			// Alle möglichen Dokumenten-Spalten definieren
			$documentColumns = ['Bedienungsanleitung', 'EU_Datenblatt', 'Energielabel', 'Produktdatenblatt', 'Sicherheitsdatenblatt', 'Zertifikat', 'null_feld'];
		
			
			 // Alle möglichen Dokumenten-Spalten mit ihren Labels definieren
			 $documentColumns = [
				'Bedienungsanleitung' => 'Allg. Sicherheitshinweise',
				'EU_Datenblatt' => 'EU-Datenblatt',
				'Energielabel' => 'Energielabel',
				'Produktdatenblatt' => 'Produktdatenblatt',
				'Sicherheitsdatenblatt' => 'Sicherheitsdatenblatt',
				'Zertifikat' => 'Zertifikat',
				'null_feld' => 'Allg. Sicherheitshinweise'
			];
			
			// Array für Sicherheitsdokumente
			$documents = [];
		
			// Durch alle Spalten gehen und Werte hinzufügen
			foreach ($documentColumns as $column => $label) {
				if (!empty($warningDocsList[$column])) {
					// Falls mehrere PDFs in einer Spalte mit "," getrennt sind, aufteilen
					$pdfs = explode(',', $warningDocsList[$column]);

					// PDFs bereinigen (Leerzeichen & Anführungszeichen entfernen)
					$pdfs = array_map('trim', $pdfs);
					$pdfs = array_map(fn($pdf) => trim($pdf, '"'), $pdfs);

					// Zum Hauptarray hinzufügen (mit Label)
					foreach ($pdfs as $pdf) {
						$documents[] = [
							'file_name' => $pdf,
							'label' => $label
						];
					}
				}
			}

			// Setze die gesammelten Dokumente
			$obj->wdocuments = $documents;
			} else {
			// Keine Daten gefunden
			$obj->warnings = [];
			$obj->wdocuments = [];
			error_log("Keine Daten für Navision ID: $navisionId");
			}
			} else {
			// Fehler beim SQL-Statement
			//error_log("Fehler bei der Abfrage der sicherheitshinweis_item: " . $this->db->error);
			$obj->warnings = [];
			$obj->wdocuments = [];
			} 
}


		// get admin user
		$sql = "SELECT * FROM customers WHERE id = ".$obj->last_change_user_id;
		$result = $this->db->query($sql);
		if ($result) {
			$obj->last_change_user = $result->fetch_object();
		}

		// get prices
		/*$sql = "SELECT  * FROM item_prices WHERE item_id =".$this->db->real_escape_string($this->id)." AND customergroup_id =".$this->db->real_escape_string($forCustomerGroup);
		$result = $this->db->query($sql);
		$price_data = $result->fetch_array();

		foreach ($price_data as $key => $value) {
  			$obj->{$key} = $value;
		}*/

		$obj->files = $this->get_file_list();

		if ($obj->parent_id && !$obj->files) {
			// get parent images if no variant images
			$obj->parent_files = $this->get_file_list(false, $obj->parent_id);
		}

		$manufacturer_data = $manufacturer->get_by_id($obj->manufacturer_id);
		if ($manufacturer_data) {
			$obj->manufacturer_name = $manufacturer_data->name;
			$obj->manufacturer_data = $manufacturer_data;
		}


		// get parent item
		$obj->variant_structure = array();
		$parent_id = 0;
		if ($obj->parent_id) {
			$parent_id = $obj->parent_id;
			// get parent item data
			$parent_item = $this->get_by_id($obj->parent_id);
			$obj->parent_item = $parent_item;
			$obj->structure_id = $parent_item->structure_id;
			$obj->variant_structure[] = array(
				'id' => $parent_item->id,
				'level' => 1,
				'name' => $parent_item->name
			);
		} else {
			$parent_id = $obj->id;
			$obj->variant_structure[] = array(
				'id' => $obj->id,
				'level' => 1,
				'name' => $obj->name
			);
		}


		// get schema data
		$obj->schema_data_attributes = array();
		if ($obj->schema_id) {
			$this->schema_id = $obj->schema_id;
			$obj->schema_data = $this->get_schema_data();

			// sampleprice calc data
			if ($obj->schema_data->base_price_field > 0) {
				$obj->sample_unit = $obj->schema_data->base_price_unit;
			}

			// added md5 variant key
			for ($i = 0; $i < count($obj->variant_structure); $i++) {
				// variant key 1
				if ($obj->schema_data->selectable_attribute_1) {
					$obj->variant_structure[$i]['variant_key1_md5'] = md5($obj->variant_structure[$i]['data']->{'attribute_'.$obj->schema_data->selectable_attribute_1});
				}

				// variant key 2
				if ($obj->schema_data->selectable_attribute_2) {
					$obj->variant_structure[$i]['variant_key2_md5'] = md5($obj->variant_structure[$i]['data']->{'attribute_'.$obj->schema_data->selectable_attribute_2});
				} else {
					$obj->variant_structure[$i]['variant_key2_md5'] = md5(0);
				}
			}

			$obj->item_category_name = Structure::get_name_by_id($obj->structure_id);
			foreach ($obj->schema_data->attributes as $attribute) {
				if ($attribute->name) {
					$attr = array(
						'name' => $attribute->name,
						'name_en' => $attribute->name_en,
						'unit' => $attribute->unit,
						'value' => $obj->{'attribute_'.$attribute->number},
						'show_detail' => $attribute->show_detail,
						'show_list' => $attribute->show_list,
						'number' => $attribute->number
					);
					$obj->schema_data_attributes[] = $attr;
				}
				if ($obj->schema_data->selectable_attribute_1 == $attribute->number) {
					$obj->schema_data->selectable_name_1 = $attribute->name;
					// get selectable attributes 1
					$obj->schema_data->all_selectable_attributes_1 = array();
					foreach ($all_variants as $variante) {
						$obj->schema_data->all_selectable_attributes_1[md5($variante['data']->{'attribute_'.$attribute->number})] = $variante['data']->{'attribute_'.$attribute->number};
					}
				}
				if ($obj->schema_data->selectable_attribute_2 == $attribute->number) {
					$obj->schema_data->selectable_name_2 = $attribute->name;
					// get selectable attributes 2
					$obj->schema_data->all_selectable_attributes_2 = array();
					foreach ($all_variants as $variante) {
						$obj->schema_data->all_selectable_attributes_2[md5($variante['data']->{'attribute_'.$attribute->number})] = $variante['data']->{'attribute_'.$attribute->number};
					}
				}

				// sampleprice calc data
				if ($obj->schema_data->base_price_field == $attribute->number) {
					$obj->vpe_sampleprice_unit = $obj->{'attribute_'.$attribute->number};
				}
			}
		}


		// get item discount
		$discount = $this->get_item_discount($customer_group_discount, $obj->manufacturer_id, $obj->structure_id);

		if ($discount) {
			$obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2);
			$obj->discount = $discount;
			$obj->discount_text = 'Rabatt!';
		}

		// get variants
		$sql = "SELECT  i.*, ip.price_1, ip.bargain_price_1 FROM items i
				LEFT JOIN item_prices ip ON (ip.item_id = i.id AND ip.customergroup_id = ".$this->db->real_escape_string($customer_group_price).")
				WHERE i.parent_id = ".$this->db->real_escape_string($parent_id)." GROUP BY i.id ORDER BY ip.price_1";

		$variant_result = $this->db->query($sql);
		$all_variants = array();
		if ($variant_result->num_rows > 0) {
			while ($variant_obj = $variant_result->fetch_object()) {
				if ($discount) {
					$variant_obj->bargain_price_1 = round(($variant_obj->price_1 * (100 - $discount) / 100), 2);
					$variant_obj->discount = $discount;
				}

				// rewrite price with discountprice
				if ($variant_obj->bargain_price_1 > 0) {
					$variant_obj->price_1 = $variant_obj->bargain_price_1;
				}

				// calc tax
				$variant_obj->tax = $this->all_tax[$variant_obj->tax_id]->steuersatz;
				$variant_obj->tax_value = round($variant_obj->price_1 * ($variant_obj->tax / 100), 4);
				$variant_obj->price_1_tax = $variant_obj->price_1 + $variant_obj->tax_value;



				$variant_obj->bargain_tax_value = round($variant_obj->bargain_price_1 * ($variant_obj->tax / 100), 2);
				$variant_obj->bargain_price_1_tax = $variant_obj->bargain_price_1 + $variant_obj->bargain_tax_value;

				// shop price
				$variant_obj->sample_price = 0;
				if ($this->base_object->customer_group->show_tax) {
					$variant_obj->shop_price_1 = $variant_obj->price_1_tax;
					$variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1_tax;
				} else {
					$variant_obj->shop_price_1 = $variant_obj->price_1;
					$variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1;
				}

				// calc sample price
				$variant_obj->vpe_sampleprice_unit = $variant_obj->{'attribute_'.$obj->schema_data->base_price_field};
				if ($obj->sample_unit && $variant_obj->vpe_sampleprice_unit) {
					if ($variant_obj->price_je_vpe) {
						if ($variant_obj->vpe_amount) {
							if ($variant_obj->shop_bargain_price_1) {
								$variant_obj->sample_price = $variant_obj->shop_bargain_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount);
							} else {
								$variant_obj->sample_price = $variant_obj->shop_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount);
							}
						}
					} else {
						if ($variant_obj->shop_bargain_price_1) {
							$variant_obj->sample_price = ($variant_obj->shop_bargain_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor;
						} else {
							$variant_obj->sample_price = ($variant_obj->shop_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor;
						}
					}
				}
				$all_variants[] = $obj->variant_structure[] = array(
					'id' => $variant_obj->id,
					'level' => 2,
					'name' => $variant_obj->name,
					'active' => $variant_obj->active,
					'short_uri' => $variant_obj->short_uri,
					'number' => $variant_obj->number,
					'price_1' => $variant_obj->price_1,
					'price_type' => $variant_obj->price_type,
					'bargain_price_1' => $variant_obj->bargain_price_1,
					'shop_price_1' => $variant_obj->shop_price_1,
					'shop_bargain_price_1' => $variant_obj->shop_bargain_price_1,
					'sample_price' => $variant_obj->sample_price,
					'default_image_file_name' => $variant_obj->default_image_file_name,
					'data' => $variant_obj
				);

				// get smallest price for parent article
				if (!$obj->smallest_variant_price_1 || $obj->smallest_variant_price_1 > $variant_obj->price_1) {
					$obj->smallest_variant_price_1 = $variant_obj->price_1;
					$obj->smallest_variant_bargain_price_1 = $variant_obj->bargain_price_1;
				}
			}
		} else {
			// get prices
			$prices = $this->getPricesForCustomerGroup($forCustomerGroup);
			foreach ($prices as $field => $value) {
				if ($field != 'item_id' && $field != 'customergroup_id') {
					if (!$this->check_bargain_active($obj, $this->id) && substr($field,0,7) == 'bargain') {
						$value = 0;
					}
					$obj->{$field} = $value;
				}
			}
		}

		$obj->tax = isset($this->all_tax[$obj->tax_id]->steuersatz) ? $this->all_tax[$obj->tax_id]->steuersatz : 1.19;
		$obj->price_tax_text_free_shipping = (isset($this->base_object->customer_group->price_tax_text_free_shipping)) ? str_replace('[tax]', $obj->tax, $this->base_object->customer_group->price_tax_text_free_shipping) : '';
		$obj->price_tax_text = (isset($this->base_object->customer_group->price_tax_text)) ? str_replace('[tax]', $obj->tax, $this->base_object->customer_group->price_tax_text) : '';

		// get item_types
		$obj->item_types = $this->get_item_types($obj->id);

		// calc tax
		$obj->uvp_netto = round(($obj->uvp / ($obj->tax + 100) * 100), 4);

		$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 4);
		$obj->price_1_tax = $obj->price_1 + $obj->tax_value;

		$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 4);
		$obj->bargain_price_1_tax = $obj->bargain_price_1 + $obj->bargain_tax_value;

		// shop price
		//$obj->sample_price = 0;
		if (isset($this->base_object->customer_group->show_tax) && $this->base_object->customer_group->show_tax) {
			$obj->shop_price_1 = $obj->price_1_tax;
			$obj->shop_bargain_price_1 = $obj->bargain_price_1_tax;
		} else {
			$obj->shop_price_1 = $obj->price_1;
			$obj->shop_bargain_price_1 = $obj->bargain_price_1;
		}

		// calc sample price
		if ((!$all_variants || $obj->parent_id > 0) && ($obj->sample_unit && $obj->vpe_sampleprice_unit)) {
			if ($obj->price_je_vpe) {
				if ($obj->vpe_amount) {
					if ($obj->shop_bargain_price_1) {
						$obj->sample_price = $obj->shop_bargain_price_1 / ($obj->vpe_sampleprice_unit * $obj->vpe_amount);
					} else {
						$obj->sample_price = $obj->shop_price_1 / ($obj->vpe_sampleprice_unit * $obj->vpe_amount);
					}
				}
			} else {
				if ($obj->shop_bargain_price_1) {
					$obj->sample_price = ($obj->shop_bargain_price_1 / $obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor;
				} else {
					$obj->sample_price = ($obj->shop_price_1 / $obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor;
				}
			}
		}

		$today = getdate();
		$today = strtotime($today['year'].'-'.$today['mon'].'-'.$today['mday']);

		// TODO: IS ORDERABLE
		if ($for_frontend) {
			if ($obj->shippable == '2') {
				if ($obj->available_from != '' && $obj->available_from != '0000-00-00') {
					$startDate = strtotime($obj->available_from);

					if ($obj->available_till != '' && $obj->available_till != '0000-00-00') {
						// from - till
						$stopDate = strtotime($obj->available_till);
						if ($today > $startDate && $today < $stopDate) {
							$obj->shippable = 1;
						} else {
							$obj->shippable = 0;
						}
					} else {
						// from - no till
						if ($today > $startDate) {
							$obj->shippable = 1;
						} else {
							//$obj->shippable = 0;
						}
					}
				} else {
					// no from - till not checked
					$obj->shippable = 0;
				}
			}
		}

		// Description Tab
		$obj->detail_description = str_ireplace(
			array("\r", "\n", "\r\n", "\t"), '', $obj->detail_description
		);

		if (isset($this->base_object->config->shopConfiguration['item_multi_description']) && $this->base_object->config->shopConfiguration['item_multi_description']) {
			$description_array = explode('[tab=', $obj->detail_description);
			$tab_title = array();
			$tab_content = array();
			if (is_array($description_array)) {
				foreach ($description_array as $key => $desc) {
					if (strpos($desc, ']')) {
						$sign_pos = strpos($desc, ']');
						$tab_title[$key] = substr($desc, 0, $sign_pos);
						$tab_content[$key] = substr($desc, $sign_pos + 1);
					}
				}

				$obj->tab_title = $tab_title;
				$obj->tab_content = $tab_content;
			}
		}

		if (isset($obj->tab_content)) {
			/*foreach ($obj->tab_content as $tabKey => $tmpTab) {
				$tidy = new tidy;
				$tidy->parseString($tmpTab, array(
					'output-xhtml' => true,
					'show-body-only' => true
				));

				$tidy->cleanRepair();
				$obj->tab_content[$tabKey] = $tidy->value;
			}*/
		}

		// Graduated prices
		$obj->graduated_prices = array();
		for ($i = 2; $i <= 30; ++$i) {
			$tmpPrice = $obj->{'price_'.$i};
			$tmpBargain = $obj->{'bargain_price_'.$i};
			$tmpQuantity = $obj->{'quantity_'.$i};
			$tmpBargainTax = 0;
			$tmpBargainTaxPrice = 0;

			if ($tmpPrice > 0) {
				// calc tax
				$tmpTax = round($tmpPrice * ($obj->tax / 100), 4);
				$tmpTaxPrice = $tmpPrice + $tmpTax;

				if ($tmpBargain > 0) {
					$tmpBargainTax = round($tmpBargain * ($obj->tax / 100), 4);
					$tmpBargainTaxPrice = $tmpBargain + $tmpBargainTax;
				}

				// calc sample price
				$tmpSamplePriceNet = 0;
				$tmpSamplePriceGross = 0;

				// intelectra base price calc
				if ($obj->attribute_11 && $obj->attribute_15) {
					$obj->sample_unit = $obj->attribute_15;

					if ($tmpBargain > 0) {
						if (strstr($obj->sample_unit, '100')) {
							$tmpSamplePriceNet = $tmpBargain / ($obj->attribute_11 * 10);
							$tmpSamplePriceGross = $tmpBargainTaxPrice / ($obj->attribute_11 * 10);
						}
						else {
							$tmpSamplePriceNet = $tmpBargain / $obj->attribute_11;
							$tmpSamplePriceGross = $tmpBargainTaxPrice / $obj->attribute_11;
						}
					} else {
						if (strstr($obj->sample_unit, '100')) {
							$tmpSamplePriceNet = $tmpPrice / ($obj->attribute_11 * 10);
							$tmpSamplePriceGross = $tmpTaxPrice / ($obj->attribute_11 * 10);
						}
						else {
							$tmpSamplePriceNet = $tmpPrice / $obj->attribute_11;
							$tmpSamplePriceGross = $tmpTaxPrice / $obj->attribute_11;
						}
					}

				}
				/*if ($obj->sample_unit && $obj->vpe_sampleprice_unit) {
					if ($obj->price_je_vpe) {
						if ($obj->vpe_amount) {
							if ($tmpBargain > 0) {
								$tmpSamplePriceNet = $tmpBargain / ($obj->vpe_sampleprice_unit * $obj->vpe_amount);
								$tmpSamplePriceGross = $tmpBargainTaxPrice / ($obj->vpe_sampleprice_unit * $obj->vpe_amount);
							} else {
								$tmpSamplePriceNet = $tmpPrice / ($obj->vpe_sampleprice_unit * $obj->vpe_amount);
								$tmpSamplePriceGross = $tmpTaxPrice / ($obj->vpe_sampleprice_unit * $obj->vpe_amount);
							}
						}
					} else {
						if ($tmpBargain > 0) {
							$tmpSamplePriceNet = $tmpBargain / $obj->vpe_sampleprice_unit;
							$tmpSamplePriceGross = $tmpBargainTaxPrice / $obj->vpe_sampleprice_unit;
						} else {
							$tmpSamplePriceNet = $tmpPrice / $obj->vpe_sampleprice_unit;
							$tmpSamplePriceGross = $tmpTaxPrice / $obj->vpe_sampleprice_unit;
						}
					}
				}*/

				// shop price
				if ($this->base_object->customer_group->show_tax) {
					$obj->graduated_prices[$tmpQuantity] = array(
						'price' => $tmpTaxPrice,
						'samplePrice' => $tmpSamplePriceGross,
						'bargain' => $tmpBargainTaxPrice,
						'priceNet' => $tmpPrice,
						'bargainNet' => $tmpBargain,
						'priceGross' => $tmpTaxPrice,
						'bargainGross' => $tmpBargainTaxPrice,
						'samplePriceNet' => $tmpSamplePriceNet,
						'samplePriceGross' => $tmpSamplePriceGross
					);
				} else {
					$obj->graduated_prices[$tmpQuantity] = array(
						'price' => $tmpPrice,
						'samplePrice' => $tmpSamplePriceNet,
						'bargain' => $tmpBargain,
						'priceNet' => $tmpPrice,
						'bargainNet' => $tmpBargain,
						'priceGross' => $tmpTaxPrice,
						'bargainGross' => $tmpBargainTaxPrice,
						'samplePriceNet' => $tmpSamplePriceNet,
						'samplePriceGross' => $tmpSamplePriceGross
					);
				}
			}
		}

		// Assigned items (additional items)
		$customer_object = new Customer_group($this->base_object);
		$customer_price_group_id = $customer_object->get_group_price_id($forCustomerGroup);
		$obj->assignedItemSet = $this->get_assigned_items_new($this->id, $customer_price_group_id, 1);

		if ($obj->parent_id && !$obj->assignedItemSet) {
			// get parent assigned items if no variant assigned items
			$obj->parent_assignedItemSet = $this->get_assigned_items_new($obj->parent_id, $customer_price_group_id, 1);
		}

		// Assigned items 2 (spare parts)
		$obj->assignedItemSet2 = $this->get_assigned_items($this->id, $customer_price_group_id, 2);
		if ($obj->parent_id && !$obj->assignedItemSet2) {
			// get parent assigned items if no variant assigned items
			$obj->parent_assignedItemSet2 = $this->get_assigned_items($obj->parent_id, $customer_price_group_id, 2);
		}

		// Assigned items 5 (spare parts)
		$obj->assignedItemSet5 = $this->get_assigned_items($this->id, $customer_price_group_id, 2);
		if ($obj->parent_id && !$obj->assignedItemSet5) {
			// get parent assigned items if no variant assigned items
			$obj->parent_assignedItemSet5 = $this->get_assigned_items($obj->parent_id, $customer_price_group_id, 2);
		}

		// Assigned items 3 (real friends)
		$obj->assignedItemSet3 = $this->get_assigned_items($this->id, $customer_price_group_id, 3);
		if ($obj->parent_id && !$obj->assignedItemSet3) {
			// get parent assigned items if no variant assigned items
			$obj->parent_assignedItemSet3 = $this->get_assigned_items($obj->parent_id, $customer_price_group_id, 3);
		}

		// shipping costs
		if ($obj->shipping_cost_type == 2) {
			$sql = "SELECT * FROM item_shipping_costs WHERE item_id = ".$this->id;
			$result = $this->db->query($sql);
			$obj->shipping_area_costs = array();
			while ($obj_shipping = $result->fetch_object()) {
				$obj->shipping_area_costs[$obj_shipping->shipping_area_id] = $obj_shipping;
			}
		}

		// Include individual for intelectra
		if (isset($this->base_object->config->shopConfiguration['custom_global_modules']) && $this->base_object->config->shopConfiguration['custom_global_modules']) {
			$shopArticle = $obj;  // Fix: Define $shopArticle for the include
			include_once ROOT_DIR.'web/'.SHOP_SYSTEM.'/php/intelectra_item_additional.inc.php';
		}

		return $obj;
	}

	/**
 * Generiert den Bilddateinamen basierend auf den Warnungsdaten
 *
 * @param array $warning Die Daten der Warnung
 * @return string|null Der generierte Bilddateiname oder null, wenn kein Bild verfügbar ist
 */
private function generateImageFileName($warning) {
    // Verwende "bilddateiname", wenn vorhanden
    if (!empty($warning['bilddateiname'])) {
        return $warning['bilddateiname'];
    }

    // Verwende "bildnr", wenn vorhanden
    if (!empty($warning['bildnr'])) {
        return $warning['bildnr'] . ".gif";
    }

    // Generiere basierend auf der Bildnummer
    if (!empty($warning['bild'])) {
        $baseName = "ISO_7010_";
        $suffix = ".svg";

        // Extrahiere die letzten 3 Ziffern der Bildnummer
        $imageFileId = substr($warning['bild'], -4);

        return $baseName . $imageFileId . $suffix;
    }

    // Kein Bild verfügbar
    return null;
}

	public function getPricesForCustomerGroup($customerGroup) {
		$sql = "SELECT * FROM item_prices WHERE item_id = ".$this->id." AND customergroup_id = ".$customerGroup;
		$result = $this->db->query($sql);
		
		// PHP 8 FIX: Check if query succeeded and has results
		if ($result && $result->num_rows > 0) {
			$prices = $result->fetch_object();
			return $prices;
		}
		
		// Return empty object instead of NULL to prevent type errors
		return (object) array();
	}

	public function getVariantPricesForCustomerGroup($customerGroup, $forAjax = false, $showTax = false, $taxValue = 0, $discount = 0, $for_frontend = true) {
		$sql = "SELECT * FROM item_attribute_variants WHERE item_id = ".$this->id." AND customergroup_id = ".$customerGroup;
		$result = $this->db->query($sql);
		$variant_data = array();

		if ($forAjax) {
			while ($obj_variants = $result->fetch_object()) {
				if ($showTax && $taxValue > 0) {
					$tmpTax = round($obj_variants->price * ($taxValue / 100), 2);
					$obj_variants->price = round($obj_variants->price + $tmpTax, 2);
					//$obj_variants->price = ($obj_variants->price / 100) * (100 + $taxValue);
				}

				$variant_data[$obj_variants->attribut1.'_'.$obj_variants->attribut2] = $obj_variants->price;
			}
		} else {
			while ($obj_variants = $result->fetch_object()) {
				if ($discount) {
					$obj_variants->price = round(($obj_variants->price * (100 - $discount) / 100), 2);
					$obj_variants->discount = $discount;
					$obj_variants->discount_text = 'Rabatt!';
				}
				$tmpTax = round($obj_variants->price * ($taxValue / 100), 2);

				$obj_variants->price_net = $obj_variants->price;
				$obj_variants->price_gross = round($obj_variants->price + $tmpTax, 2);
				//$obj_variants->price_gross = ($obj_variants->price / 100) * (100 + $taxValue);

				if ($showTax && $taxValue > 0) {
					$tmpTax = round($obj_variants->price * ($taxValue / 100), 2);
					$obj_variants->price = round($obj_variants->price + $tmpTax, 2);
					//$obj_variants->price = ($obj_variants->price / 100) * (100 + $taxValue);
				}

				$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['item_number'] = $obj_variants->item_number;
				$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['manufacturer_item_number'] = $obj_variants->manufacturer_item_number;
				$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['ek'] = $obj_variants->ek;
				$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['price'] = $obj_variants->price;
				$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['priceNet'] = $obj_variants->price_net;
				$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['priceGross'] = $obj_variants->price_gross;
				$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['taxes'] = $tmpTax;
				$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = $obj_variants->shippable;
				$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['inventory'] = $obj_variants->inventory;
				$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['additional_charge'] = $obj_variants->additional_charge;
				$tmpFrom = explode('-', $obj_variants->available_from);
				if (count($tmpFrom) == 3) {
					$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['available_from'] = $tmpFrom[2].'.'.$tmpFrom[1].'.'.$tmpFrom[0];
				}
				$tmpTill = explode('-', $obj_variants->available_till);
				if (count($tmpTill) == 3) {
					$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['available_till'] = $tmpTill[2].'.'.$tmpTill[1].'.'.$tmpTill[0];
				}

				$today = getdate();
				$today = strtotime($today['year'].'-'.$today['mon'].'-'.$today['mday']);

				// TODO: IS ORDERABLE
				if ($for_frontend) {
					if ($obj_variants->shippable == '2') {
						if ($obj_variants->available_from != '' && $obj_variants->available_from != '0000-00-00') {
							$startDate = strtotime($obj_variants->available_from);

							if ($obj_variants->available_till != '' && $obj_variants->available_till != '0000-00-00') {
								// from - till
								$stopDate = strtotime($obj_variants->available_till);
								if ($today > $startDate && $today < $stopDate) {
									$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = 1;
								} else {
									$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = 0;
								}
							} else {
								// from - no till
								if ($today > $startDate) {
									$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = 1;
								} else {
									//$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = 0;
								}
							}
						} else {
							// no from - till not checked
							$variant_data[$obj_variants->attribut1][$obj_variants->attribut2]['shippable'] = 0;
						}
					}
				}
			}
		}

		return array_reverse($variant_data, true);
	}

	// TODO: (sh 2011-05-30 mit absprache von jd)
	// kopie von "getVariantPricesForCustomerGroup()", die daten werden fuer die artikeldetailansicht benoetigt.
	public function getVariantPricesForArticleDetails($customerGroup, $attribut1, $attribut2) {
		$sql = "
			SELECT
				price, shippable, DATE_FORMAT(available_from, '%e.%c.%Y') AS available_date, available_from
			FROM
				item_attribute_variants
			WHERE
				item_id = ".$this->id."
			AND
				customergroup_id = ".$customerGroup."
			AND
				TRIM(attribut1) LIKE '".trim($attribut1)."'
			AND
				TRIM(attribut2) LIKE '".trim($attribut2)."'
		";

		$result = $this->db->query($sql);
		$variant_data = $result->fetch_object();

		return $variant_data;
	}

	public function create($data, $priceData = false) {
		if ($data) {
			if (isset($data['short_uri'])) {
				if (!$data['short_uri']) {
					$data['short_uri'] = $data['name'];
				}
				$data['short_uri'] = $this->short_uri($data['short_uri']);
			}

			$sql = "INSERT INTO items SET ";

			if ($data['schema_id']) {
				$schema_data = $this->itemschema_object->get_data($data['schema_id']);
				if ($schema_data->selectable_attribute_1) {
					$data['attribute_'.$schema_data->selectable_attribute_1] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_1]);
				}
				if ($schema_data->selectable_attribute_2) {
					$data['attribute_'.$schema_data->selectable_attribute_2] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_2]);
				}
			}

			foreach ($data as $var_name => $value) {
				$value = $this->db->real_escape_string($value);
				if ($this->item_fields[$var_name] == 'integer') {
					$sql .= $var_name.' = '.$value.', ';
				} else if ($this->item_fields[$var_name] == 'date') {
					if (preg_match("/^(\d{2})\.(\d{2})\.(\d{4})$/", $value, $matches)) {
						$tmpVal = $matches[3].'-'.$matches[2].'-'.$matches[1];
					} else {
						$tmpVal = '0000-00-00';
					}

					$sql .= $var_name.'="'.$tmpVal.'", ';
				} else if ($this->item_fields[$var_name] == 'float') {
					$sql .= $var_name.'="'.number_format((float) $value, 4, '.', '').'", ';
				} else {
					$sql .= $var_name.' = "'.$value.'", ';
				}
			}

			$sql .= " quantity_1 = '1', ";
			$sql .= " price_1 = '".number_format($priceData['prices']['price_1'],4,'.','')."', ";
			$sql .= " bargain_price_1 = '".number_format($priceData['prices']['bargain_price_1'],4,'.','')."' ";

			$this->db->query($sql);
			$this->id = $this->db->insert_id;

			// save prices
			if ($priceData) {
				$this->replace_prices($priceData);
			}

			// save assigned items
			$this->saveAssignedItems(1);
			$this->saveAssignedItems(2);
			$this->saveAssignedItems(3);

			$this->_assignToStructures($_POST['assigned_structures']);

			return $this->id;
		}

		return false;
	}

	function short_uri($short_uri, $id = false) {
		$short_uri = str_replace(array('ä', 'Ä', 'ö', 'Ö', 'ü', 'Ü', 'ß'), array('ae', 'Ae', 'oe', 'Oe', 'ue', 'Ue', 'ss'), $short_uri);
		$short_uri = preg_replace("@[^0-9aA-zZ\-]@si", "-", $short_uri);
		$short_uri = preg_replace("@(-{2,})@si", "-", $short_uri);

		$new_uri = '';
		$old_uri = $short_uri;
		$i = 0;
		while ($new_uri == '') {
			if ($id) {
				$sql = "SELECT id FROM items WHERE short_uri = '$short_uri' AND id != $id";
			} else {
				$sql = "SELECT id FROM items WHERE short_uri = '$short_uri'";
			}
			$result = $this->db->query($sql);
			if ($result->num_rows == 0) {
				$new_uri = $short_uri;
			} else {
				$i++;
				$short_uri = $old_uri.'_'.$i;
			}
		}
		return $new_uri;
	}

	public function sort_image_list($list) {
		$counter = 1;
		$picQueryParts = array();

		foreach ($list as $pic_id) {
			++$counter;

			$pic_id = str_replace('picelementContainer_', '', $pic_id);

			if ($counter == 2) {
				$default_image = $pic_id;
			}

			$picQueryParts[] = '('.$pic_id.', '.$counter.')';
		}

		$this->db->query("CREATE TEMPORARY TABLE tmp_item_files ( id INT, pos INT )");

		$this->db->query("INSERT INTO tmp_item_files (id, pos) VALUES ".implode(', ', $picQueryParts));

		$result = $this->db->query("
			UPDATE
				item_files i,
				tmp_item_files i_tmp
			SET
				i.rang = i_tmp.pos
			WHERE
				i.id = i_tmp.id
			AND
				i.item_id = ".$this->id."
		");

		return $sql = $this->set_default_image($default_image);
	}

	public function set_default_image($image_id) {
		$sql = "UPDATE items i
				SET i.default_image_file_name = (SELECT f.file_name FROM item_files f WHERE f.id = ".$this->db->real_escape_string($image_id).")
				WHERE i.id=".$this->db->real_escape_string($this->id);

		$this->db->query($sql);
		return $sql;
	}

	public function delete_file($file_id, $id = false) {
		// get pic infos
		$sql = "SELECT * FROM item_files WHERE id=".$this->db->real_escape_string($file_id);

		$result = $this->db->query($sql);

		if ($result) {
			$obj = $result->fetch_object();

			if ($obj->type == '0') {
				// unlink all the files with prefixes
				foreach ($this->base_object->config->shopConfiguration['images'] as $image) {
					$filename = $image[0].$obj->file_name;
					unlink($_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/'.$filename);
				}
				// unlink the original
				$filename = $obj->file_name;
				unlink($_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/'.$filename);
			} else if ($obj->type == '1') {
				unlink($_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/documents/article/'.$obj->file_name);

				// update state in item table
				$item_id = ($id) ? $id : $this->id;
				$sql = "SELECT
						count(*) AS num
					FROM
						item_files
					WHERE
						type = 1 AND
						id!=".$this->db->real_escape_string($file_id)." AND
						item_id=".$this->db->real_escape_string($item_id);

				$result = $this->db->query($sql);
				if ($result->fetch_object()->num == 0) {
					$query = "UPDATE items SET has_documents = 0 WHERE id = '".$this->db->real_escape_string($item_id);
					$this->db->query($query);
				}
			}

			$sql = "DELETE FROM item_files WHERE id=".$this->db->real_escape_string($file_id);

			if ($id) {
				$sql .= " AND item_id=".$this->db->real_escape_string($id);
				$this->id = $id;
			} else if ($this->id) {
				$sql .= " AND item_id=".$this->db->real_escape_string($this->id);
			} else {
				// TODO: log and set error
				return false;
			}

			return $this->db->query($sql);
		}
		// TODO log and set error

		return false;
	}

	// end delete_file
	// FIXME: put function to generate scaled images into its own function
	// so that it can be called seperately to regenerate all shop 
	public function add_uploaded_file($file_data, $watermark_activ = false) {
		$tempFile = $file_data['Filedata']['tmp_name'];
		// is file a image
		$file_info = getimagesize($tempFile);
		if (isset($file_info[2]) && $file_info[2] > 0 && $file_info[2] < 4) {
			$targetPath = $_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/';
			$image_type = array('', 'gif', 'jpg', 'png');
			$file_id = md5(uniqid(rand(), TRUE));
			$file_name = $file_id.'.'.$image_type[$file_info[2]];

			// save article picture
			$targetFile = str_replace('//', '/', $targetPath).$file_name;
			move_uploaded_file($tempFile, $targetFile);

			// resize max image size
			$imaginator = new phImaginator();
			$imaginator->add($targetFile);
			$imaginator->Resize_fitBoth('800', '800');
			$imaginator->save();

			// create 4 scaled down images
			foreach ($this->shopConfiguration['images'] as $pair) {
				$image = new Imagick($_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/'.$file_name);
				$image->thumbnailImage($pair[1], $pair[1]);
				$image->setImageFileName($_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/'.$pair[0].$file_name);
				$image->writeImage();
			}

			// set watermark
			if ($watermark_activ && $this->base_object->config->shopConfiguration['item_watermark_image']) {
				$this->watermark($targetFile);
			}

			// resize image
			foreach ($this->base_object->config->shopConfiguration['images'] as $image) {
				$image_name = $image[0];
				$size = $image[1];
				$imaginator = new phImaginator();
				$imaginator->add($targetFile);
				$imaginator->Resize_fitBoth($size, $size);
				$imaginator->nameAdd($image_name);
				$imaginator->save();
			}

			// get count of pictures
			$sql = "SELECT count( id ) AS image_count FROM item_files 
					WHERE
						item_id=".$this->db->real_escape_string($this->id);

			$result = $this->db->query($sql);
			$picture_count = 1;
			while ($obj = $result->fetch_object()) {
				$picture_count = $obj->image_count + 1;
			}

			// save picture in database
			$sql = "INSERT INTO
						item_files (item_id, file_name, rang)
					VALUES
						(".$this->db->real_escape_string($this->id).", '".
						$this->db->real_escape_string($file_name)."', ".
						$this->db->real_escape_string($picture_count).")";

			$this->db->query($sql);

			$sql = "UPDATE items i
				SET i.default_image_file_name = (SELECT f.file_name FROM item_files f WHERE f.item_id = ".$this->db->real_escape_string($this->id)." ORDER BY rang LIMIT 1)
				WHERE i.id=".$this->db->real_escape_string($this->id);

			$this->db->query($sql);
		} else {
			// save to article documents
			$file_name = $file_data['Filedata']['name'];
		}

		return;
	}

	public function add_uploaded_pdf($file_data) {
		$tempFile = $file_data['Filedata']['tmp_name'];

		$targetPath = $_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/documents/article/';
		$file_id = md5(uniqid(rand(), TRUE));
		$file_name = $file_id.'.pdf';

		// save article picture
		$targetFile = str_replace('//', '/', $targetPath).$file_name;
		move_uploaded_file($tempFile, $targetFile);

		$size = filesize($targetFile);

		$sql = "
			INSERT INTO
				item_files 
				(item_id, file_name, alt, rang, type, size)
			VALUES (
				".$this->db->real_escape_string($this->id).", 
				'".$this->db->real_escape_string($file_name)."', 
				'".$this->db->real_escape_string($file_data['Filedata']['name'])."', 
				0, 
				1,
				'".$size."'
			)
		";

		$result = $this->db->query($sql);

		if ($result) {

			// update state in item table
			$query = "UPDATE items SET has_documents = 1 WHERE id = '".$this->id;
			$this->db->query($query);

			$return_object = new stdClass();
			$return_object->id = $this->db->insert_id;
			$return_object->item_id = $this->id;
			$return_object->file_name = $file_name;
			$return_object->path = str_replace('//', '/', './web/'.SHOP_SYSTEM.'/documents/article/');
			$return_object->alt = $file_data['Filedata']['name'];

			return $return_object;
		}

		return false;
	}

	public function get_file_list($type = false, $id = false) {
		if (!$id) {
			$id = $this->id;
		}
		if ($type === 0) {
			$sql = "SELECT * FROM item_files WHERE item_id=".$id." AND type=0 ORDER BY rang";
		} else if ($type) {
			$sql = "SELECT * FROM item_files WHERE item_id=".$id." AND type=".$type." ORDER BY rang";
		} else {
			$sql = "SELECT * FROM item_files WHERE item_id=".$id." ORDER BY rang";
		}

		$result = $this->db->query($sql);
		$data = array();
		if ($result->num_rows > 0) {
			while ($obj = $result->fetch_object()) {
				$data[] = $obj;
			}
		} else {
			$data = false;
		}

		return $data;
	}

	public function update($data, $priceData = false) {
		if ($data) {
			// If no primary structure assigned
			if ((!isset($data['structure_id']) || !is_numeric($data['structure_id'])) && is_array($_POST['assigned_structures'])) {
				$data['structure_id'] = current($_POST['assigned_structures']);
			}
			// PHP 8 FIX: Check if array exists before reset()
			if (is_array($_POST['assigned_structures'])) {
				reset($_POST['assigned_structures']);
			}

			if (isset($data['short_uri'])) {
				if (!$data['short_uri']) {
					$data['short_uri'] = $data['name'];
				}
				$data['short_uri'] = $this->short_uri($data['short_uri'], $this->id);
			}

			$schema_data = $this->itemschema_object->get_data($data['schema_id']);

			$sql = "UPDATE items SET ";

			if ($data['schema_id']) {
				$schema_data = $this->itemschema_object->get_data($data['schema_id']);
				if ($schema_data->selectable_attribute_1) {
					$data['attribute_'.$schema_data->selectable_attribute_1] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_1]);
				}
				if ($schema_data->selectable_attribute_2) {
					$data['attribute_'.$schema_data->selectable_attribute_2] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_2]);
				}
			}
			/*$data['attribute_'.$schema_data->selectable_attribute_1] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_1]);
			$data['attribute_'.$schema_data->selectable_attribute_2] = str_replace(' ', '', $data['attribute_'.$schema_data->selectable_attribute_2]);*/
			foreach ($data as $var_name => $value) {
				$value = $this->db->real_escape_string($value);
				if ($this->item_fields[$var_name] == 'integer') {
					$sql .= $var_name.'='.$value.', ';
				} else if ($this->item_fields[$var_name] == 'float') {
					$sql .= $var_name.'='.floatval($value).', ';
				} else if ($this->item_fields[$var_name] == 'date') {
					if (preg_match("/^(\d{2})\.(\d{2})\.(\d{4})$/", $value, $matches)) {
						$tmpVal = $matches[3].'-'.$matches[2].'-'.$matches[1];
					} else {
						$tmpVal = '0000-00-00';
					}

					$sql .= $var_name.'="'.$tmpVal.'", ';
				} else {
					$sql .= $var_name.'="'.$value.'", ';
				}
			}

			/*$sql .= " quantity_1 = '1', ";
			$sql .= " price_1 = '".$priceData['prices']['price_1']."', ";
			$sql .= " bargain_price_1 = '".$priceData['prices']['bargain_price_1']."', ";*/
			$sql = substr($sql, 0, -2);
			$sql .= ' WHERE id='.$this->id;

			$this->db->query($sql);
			if ($this->db->error) {
				$log_object = Logger::get_instance();
				$log_object->info('Error in /core/main_class.php->get_list_items()', $this->db->error.', sql:'.$sql);
				$count = 0;
			}

			// save variants
			/*if ($priceData['customerGroup']) {
				$this->update_variants($priceData['customerGroup'], $data, $priceData);
			}*/

			// save prices
			if ($priceData) {
				$this->replace_prices($priceData);
			}

			// save assigned items
			$this->saveAssignedItems(1);
			$this->saveAssignedItems(2);
			$this->saveAssignedItems(3);

			// save shipping costs
			$this->save_shipping_costs();

			// Assign to structures
			$this->_assignToStructures($_POST['assigned_structures']);

			// update variant items
			include('./core/item_variant_schema.inc.php');
			foreach ($item_fields as $field => $state) {
				if ($state == 0) {
					$value = $this->db->real_escape_string($data[$field]);
					$sql = "UPDATE items SET ".$field."='".$value."'";
					$sql .= ' WHERE parent_id='.$this->id;
					$this->db->query($sql);
				}
			}
			$this->update_last_change();
		}

		return;
	}

	private function save_shipping_costs() {
		$shipping_ids = $_POST['item_shipping_id'];
		$item_shipping_price = $_POST['item_shipping_price'];

		if (isset($shipping_ids) && isset($item_shipping_price)) {
			// delete old prices
			$sql = "
				DELETE FROM
					item_shipping_costs
				WHERE
					item_id = ".$this->id."
			";
			$this->db->query($sql);

			// insert new shipping prices
			for ($i = 0; $i < count($shipping_ids); $i++) {
				$sql = "
					INSERT INTO item_shipping_costs
						(item_id, shipping_area_id, price)
					VALUES
						(".$this->id.", ".$this->db->real_escape_string($shipping_ids[$i]).", '".$this->db->real_escape_string(str_replace(';', ', ', $item_shipping_price[$i]))."')";
				$this->db->query($sql);
			}
		}
	}

	private function replace_prices($priceData) {
		$customerGroups_object = new Customer_group($this->base_object);
		$customerGroups = $customerGroups_object->get_all_price_groups();
		$groups = array();
		foreach ($customerGroups as $group) {
			if (is_array($priceData['prices']['group_'.$group->id])) {
				$fields = array();
				$values = array();

				// PERFORMANCE FIX: Limit to 3 price levels instead of 30
				// Reduces database load by 90% during price updates
				$allowed_price_levels = array(
					'quantity_1', 'price_1', 'bargain_price_1',    // Einzelpreis (1 Stück)
					'quantity_2', 'price_2', 'bargain_price_2',    // Ab 3 Stück  
					'quantity_3', 'price_3', 'bargain_price_3'     // Ab 100 Stück
				);

				foreach ($priceData['prices']['group_'.$group->id] as $field => $value) {
					if (in_array($field, $allowed_price_levels)) {
						$fields[] = $field;
						$values[] = (float) $value;
					}
				}

				$sql = "REPLACE INTO item_prices (item_id, customergroup_id, ".implode(',', $fields).") 
						VALUES (".$this->id.",".$group->id.",".implode(',', $values).")";

				$this->db->query($sql);
			}
		}
	}

	// TODO:
	/*private function update_variants($customerGroup, $item_data, $priceData) {
		$sql = "DELETE FROM item_attribute_variants WHERE item_id = ".$this->id." AND customergroup_id = ".$customerGroup;
		$this->db->query($sql);
		$data = $this->get_data();

		// enable transactions
		$this->db->autocommit(false);

		if (!$data->price_variants_2) {
			$data->price_variants_2 = array('');
		}
		foreach ($data->price_variants_1 as $att1) {
		$att1 = trim($att1);

		foreach ($data->price_variants_2 as $att2) {
		$att2 = trim($att2);

		if ($item_data['variant_price_type'] == 0) {
			$additional_charge = '0.00';
			$price = $_POST['vprice'][$att1.'_'.$att2];
		} else if ($item_data['variant_price_type'] == 1) {
		$additional_charge = $_POST['variant_price_type'][$att1.'_'.$att2];
		$old_price = 0;
		if ($priceData['prices']['bargain_price_1'] > 0) {
		$price = $additional_charge + $priceData['prices']['bargain_price_1'];
		$old_price = $additional_charge + $priceData['prices']['price_1'];
		}
		else {
		$price = $additional_charge + $priceData['prices']['price_1'];
		}
		}
		$ek = $_POST['vek'][$att1.'_'.$att2];
		$shippable = $_POST['vshippable'][$att1.'_'.$att2];
		if ($_POST['vshippable'][$att1.'_'.$att2] == 2) {
		$avFrom = '';
		$tmpFrom = explode('.', $_POST['vlieferbar_ab'][$att1.'_'.$att2]);
		if (count($tmpFrom) == 3) {
		$avFrom = $tmpFrom[2].'-'.$tmpFrom[1].'-'.$tmpFrom[0];
		}

		$avTill = '';
		$tmpTill = explode('.', $_POST['vlieferbar_bis'][$att1.'_'.$att2]);
		if (count($tmpTill) == 3) {
		$avTill = $tmpTill[2].'-'.$tmpTill[1].'-'.$tmpTill[0];
		}
		} else {
		$avFrom = '';
		$avTill = '';
		}

		$item_number = $_POST['item_number'][$att1.'_'.$att2];
		$manufacturer_item_number = $_POST['manufacturer_item_number'][$att1.'_'.$att2];

		$sql = "
		INSERT INTO
		item_attribute_variants (
		item_id,
		customergroup_id,
		attribut1,
		attribut2,
		price,
		old_price,
		ek,
		shippable,
		available_from,
		available_till,
		inventory,
		additional_charge,
		item_number,
		manufacturer_item_number
		)
		VALUES (
		".$this->id.",
		".$customerGroup.",
		'".$att1."',
		'".$att2."',
		'".$price."',
		'".$old_price."',
		'".$ek."',
		'".$shippable."',
		'".$avFrom."',
		'".$avTill."',
		'".$inventory."',
		'".$additional_charge."',
		'".$item_number."',
		'".$manufacturer_item_number."'
		)";
		$this->db->query($sql);
		}
		}
		// commit transaction
		$result = $this->db->commit();

		// disable transactions
		$this->db->autocommit(true);
	}*/

	public function delete() {
		$sql = "DELETE FROM items WHERE id=".$this->id;
		$this->db->query($sql);

		$sql = "DELETE FROM item_prices WHERE item_id=".$this->id;
		$this->db->query($sql);

		$sql = "DELETE FROM item_attribute_variants WHERE item_id=".$this->id;
		$this->db->query($sql);

		return;
	}

	public function data_filter($request) {
		$data = array();
		foreach ($this->item_fields as $field_name => $var_type) {
			if (isset($request[$field_name])) {
				if ($var_type == 'text') {
					$data[$field_name] = $request[$field_name];
				} else if ($var_type == 'float') {
					$request[$field_name] = str_replace(',', '.', $request[$field_name]);
					$data[$field_name] = $request[$field_name];
				} else if ($var_type == 'date') {
					$data[$field_name] = $request[$field_name];
				} else {
					$data[$field_name] = (int) $request[$field_name];
				}
			}
		}
		return $data;
	}

	public function get_all_item_schemas() {
		$sql = "SELECT * FROM item_schema";
		$result = $this->db->query($sql);
		$data = array();
		while ($obj = $result->fetch_object()) {
			$data[] = $obj;
		}

		return $data;
	}

	public function get_all_item_schema_paginated($items, $page, $order = false) {
		$page -= 1;
		$sql = "SELECT * FROM item_schema LIMIT $items OFFSET $page";

		$result = $this->db->query($sql);
		while ($obj = $result->fetch_object()) {
			$data[] = $obj;
		}

		return $data;
	}

	// end get_all
	public function get_schema_data() {
		$sql = "SELECT * FROM item_schema WHERE id = ".$this->schema_id;

		$result = $this->db->query($sql);
		$schema = $result->fetch_object();

		$attributes = array();
		$sql = "SELECT * FROM item_schema_attributes WHERE schema_id = ".$this->schema_id." ORDER BY rang";
		$result = $this->db->query($sql);
		while ($obj = $result->fetch_object()) {
			$attributes[] = $obj;
		}
		$schema->attributes = $attributes;

		return $schema;
	}

	public function create_schema($data) {
		if ($data) {
			$sql = "INSERT INTO item_schema SET ";
			foreach ($data as $var_name => $value) {
				$value = $this->db->real_escape_string($value);
				if ($this->schema_fields[$var_name] == 'integer') {
					$sql .= $var_name.' = '.$value.', ';
				} else {
					$sql .= $var_name.' = "'.$value.'", ';
				}
			}
			$sql = substr($sql, 0, -2);
			$this->db->query($sql);
			$this->schema_id = $this->db->insert_id;
			if ($this->schema_id) {
				for ($i = 1; $i < 21; $i++) {
					$sql = "INSERT INTO item_schema_attributes (schema_id, number, rang) VALUES (".$this->schema_id.", ".$i.", ".$i.")";
					$this->db->query($sql);
				}
			}
		}
		return;
	}

	public function update_schema($data) {
		if ($data) {
			$sql = "UPDATE item_schema SET name='".$data['name']."',
						description='".$data['description']."',
						selectable_attribute_1='".$data['selectable_attribute_1']."',
						base_price_field='".$data['base_price_field']."',
						base_price_faktor='".$data['base_price_faktor']."',
						base_price_unit='".$data['base_price_unit']."',
						selectable_attribute_2='".$data['selectable_attribute_2']."'
					WHERE id=".$this->schema_id;
			$this->db->query($sql);

			$sql = "DELETE FROM item_schema_attributes WHERE schema_id=".$this->schema_id;
			$this->db->query($sql);

			// save attribute data
			for ($i = 1; $i < 21; $i++) {
				$show_list = ($data['attribute_liste_'.$i]) ? $data['attribute_liste_'.$i] : 0;
				$show_detail = ($data['attribute_detail_'.$i]) ? $data['attribute_detail_'.$i] : 0;
				$sql = "
					INSERT INTO item_schema_attributes
						(schema_id, number, name, name_en, unit, rang, show_list, show_detail)
					VALUES
						(".$this->schema_id.", $i, '".$data['attribute_name_'.$i]."', '".$data['attribute_name_'.$i.'_en']."', '".$data['attribute_unit_'.$i]."', ".$data['attribute_rang_'.$i].", ".$show_list.", ".$show_detail.")";
				$this->db->query($sql);
			}
		}
		return;
	}

	// end update_shema

	public function delete_schema() {
		$sql = "DELETE FROM item_schema_attributes WHERE schema_id=".$this->schema_id;
		$this->db->query($sql);
		$sql = "DELETE FROM item_schema WHERE id=".$this->schema_id;
		$this->db->query($sql);
		return;
	}

	public function schema_data_filter($request) {
		$data = array();
		foreach ($this->schema_fields as $field_name => $var_type) {
			if (isset($request[$field_name])) {
				if ($var_type == 'text') {
					$data[$field_name] = $request[$field_name];
				} else if ($var_type == 'float') {
					$data[$field_name] = $request[$field_name];
				} else {
					$data[$field_name] = (int) $request[$field_name];
				}
			}
		}
		return $data;
	}

	public function search($data) {

		$sql = 'SELECT * FROM items ';

		$where = '';

		// build clauses for manufacturer IDs that contain a specific substring
		if (isset($data['manufacturer_search'])) {
			$clause = 'manufacturer_id = ';

			$manufacturer = new Manufacturer($this->base_object);

			$results = $manufacturer->get_where_name_like($data['manufacturer_search']);

			if ($results) {
				foreach ($results as $result) {
					if ($where == '') {
						$where .= ' WHERE '.$clause.$result->id;
					}

					$where .= ' OR '.$clause.$result->id;
				}
			}
		}

		if (isset($data['text_search'])) {
			if (isset($data['text_options'])) {
				if (strpos($data['text_options'], ';')) {
					$text_options = str_replace(';', ', ', $data['text_options']);

					$clause = "CONCAT(".$text_options.") LIKE '%".$data['text_search']."%'";
				}

				$clause = $data['text_options']." LIKE '%".$data['text_search']."%'";
			}

			$clause = "name LIKE '%".$data['text_search']."%'";

			$where = Database::where($where, $clause);
		}

		if (isset($data['numeric_search'])) {
			if (isset($data['numeric_options'])) {
				if (strpos($data['numeric_options'], ';')) {
					$numeric_options = str_replace(';', ', ', $data['numeric_options']);

					$clause = "CONCAT(".$numeric_options.") LIKE '%".$data['numeric_search']."%'";
				}

				$clause = $data['numeric_options']." LIKE '%".$data['numeric_search']."%'";
			}

			$clause = "number LIKE '%".$data['numeric_search']."%'";

			$where = Database::where($where, $clause);
		}

		if (isset($data['limiting_options'])) {
			// todo
			$data['limiting_options'];
		}

		$result = $this->db->query($sql.$where);

		while ($obj = $result->fetch_object()) {
			$end[] = $obj;
		}

		return $end;
	}

	// end search

	public function delete_by_id($id) {
		$rs = $this->db->query("DELETE FROM items WHERE id=$id;");
		$rs = $this->db->query("DELETE FROM item_files WHERE item_id=$id;");
	}

	public function set_active_by_id($id) {
		$rs = $this->db->query("UPDATE items SET active=1 WHERE id=$id;");
	}

	public function set_inactive_by_id($id) {
		$rs = $this->db->query("UPDATE items SET active=0 WHERE id=$id;");
	}

	public function copy() {
		// copy standard data
		$sql = "SELECT * FROM items WHERE id = ".$this->id;
		$result = $this->db->query($sql);
		$obj = $result->fetch_object();
		if (!$obj->short_uri) {
			$obj->short_uri = $obj->name;
		}
		$obj->short_uri = $this->short_uri($obj->short_uri);
		$obj->name = 'Kopie von: '.$obj->name;
		// create copy object
		$sql = "INSERT INTO items SET ";

		foreach ($this->item_fields as $key => $var_type) {
			if ($var_type == 'integer') {
				$obj->{$key} = (int) $obj->{$key};
			} else if ($var_type == 'float' && $obj->{$key} == '') {
				$obj->{$key} = 0.0;
			} else if ($var_type == 'date' && $obj->{$key} == '') {
				$obj->{$key} = '0000-00-00';
			}
			$sql .= $key." = '".$this->db->real_escape_string($obj->{$key})."', ";
		}
		$sql = substr($sql, 0, -2);
		$this->db->query($sql);
		/*echo $sql;
		exit();*/
		$new_id = $this->db->insert_id;

		//copy prices
		$sql = "SELECT * FROM item_prices WHERE item_id = ".$this->id;
		$result = $this->db->query($sql);
		$variant_data = array();
		while ($obj = $result->fetch_object()) {
			$sql = "INSERT INTO item_prices (item_id, customergroup_id";
			for ($i = 1; $i < 31; $i++) {
				$sql .= ", quantity_".$i.", price_".$i.", bargain_price_".$i;
			}
			$sql .= ") VALUES (".$new_id.", ".$obj->customergroup_id;
			for ($i = 1; $i < 31; $i++) {
				if ($obj->{'price_'.$i} == '') {
					$obj->{'price_'.$i} = 0.0;
				}
				if ($obj->{'bargain_price_'.$i} == '') {
					$obj->{'bargain_price_'.$i} = 0.0;
				}
				if ($obj->{'quantity_'.$i} == '') {
					$obj->{'quantity_'.$i} = 0;
				}
				$sql .= ", ".$obj->{'quantity_'.$i}.", ".$obj->{'price_'.$i}.", ".$obj->{'bargain_price_'.$i};
			}
			$sql .= ")";
			$this->db->query($sql);
		}

		// copy variant data
		$sql = "SELECT * FROM item_attribute_variants WHERE item_id = ".$this->id;
		$result = $this->db->query($sql);
		$variant_data = array();
		while ($obj = $result->fetch_object()) {
			$sql = "INSERT INTO item_attribute_variants
					(item_id, attribut1, attribut2, item_number, price, ek, shippable) 
				VALUES 
					(".$new_id.",'$obj->attribut1','$obj->attribut2','$obj->item_number','$obj->price','$obj->ek',$obj->shippable)
				";
			$this->db->query($sql);
		}

		// copy files
		$sql = "SELECT * FROM item_files WHERE item_id = ".$this->id;
		$result = $this->db->query($sql);
		$variant_data = array();
		$image_count = 0;
		while ($obj = $result->fetch_object()) {
			// old: $images = array('', 'thumb_', 'overview_', 'overview_2_', 'detail_');
			$images = $this->base_object->config->shopConfiguration['images'];
			foreach ($images as $image) {
				$image_name = $image[0];
				$filename = $image_name.$obj->file_name;
				$new_filename = $image_name.$new_id.$obj->file_name;
				copy($_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/'.$filename, $_SERVER['DOCUMENT_ROOT'].'/web/'.SHOP_SYSTEM.'/images/article/'.$new_filename);
			}
			$image_count++;
			$sql = "INSERT INTO item_files
					(item_id, file_name, rang, type, description, attribut1, attribut2, alt) 
				VALUES 
					(".$new_id.", '".
					$new_id.$obj->file_name."', '".
					$obj->rang."', '".
					$obj->type."', '".
					$obj->description."', '".
					$obj->attribut1."', '".
					$obj->attribut2."', '".
					$obj->alt."')";
			$this->db->query($sql);
			if ($image_count == 1) {
				$sql = "UPDATE items 
				SET default_image_file_name = '".$this->db->real_escape_string($new_id.$obj->file_name )."'
				WHERE id=".$new_id;
				$result3 = $this->db->query($sql);
			}
		}

		// copy assigned items
		$sql = "SELECT * FROM item_item_assign WHERE item_parent_id = ".$this->id;
		$result = $this->db->query($sql);
		while ($obj = $result->fetch_object()) {
			$sql = "INSERT INTO item_item_assign
					(item_parent_id, item_child_id, type, position) 
				VALUES 
					(".$new_id.", '".$obj->item_child_id."', '".$obj->type."', '".$obj->position."')";
			$this->db->query($sql);
		}

		// copy item structure assign
		$sql = "SELECT * FROM item_structure_assign WHERE item_id = ".$this->id;
		$result = $this->db->query($sql);
		while ($obj = $result->fetch_object()) {
			$sql = "INSERT INTO item_structure_assign
					(item_id, structure_id, pos) 
				VALUES 
					(".$new_id.", '".$obj->structure_id."', '".$obj->pos."')";
			$this->db->query($sql);
		}

		$this->id = $new_id;
		return;
	}

	//UGLY HACK, KILL ME SOOOOOON the root is 3 in EMFA
	protected function get_item_category_root() {
		$sql = "SELECT id FROM structure WHERE short_uri = 'Warengruppen'";

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			return $result->fetch_object()->id;
		}

		return false;
	}

	protected function get_all_item_categories($root = false) {
		if (!$root) {
			$root = $this->get_item_category_root();
		}

		$sql = "SELECT id, name, short_uri FROM structure WHERE parent_id=$root";

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			while ($obj = $result->fetch_object()) {
				$id = $obj->id;
				$data[] = $obj;

				$children = $this->get_all_item_categories($id);
				if ($children) {
					foreach ($children as $child) {
						$data[] = $child;
					}
				}
			}

			return $data;
		}

		return false;
	}

	public function get_item_category_assoc_array() {
		$categories = $this->get_all_item_categories();

		foreach ($categories as $category) {
			$data[$category->id] = $category->short_uri;
		}

		return $data;
	}

	public function get_item_list($structure_id, $itemsPerPage = 'all', $currentPage = 1, $activeOnly = false, $fromManufacturerOnly = false, $sort_by = false) {
		$manufacturers = Manufacturer::get_name_id_pair();

		$limited = false;
		if (is_numeric($itemsPerPage)) {
			$limitMax = $itemsPerPage;
			$limited = true;
		}

		if (is_numeric($currentPage)) {
			$limitMin = $currentPage * $limitMax - $limitMax;
		} else {
			$limitMin = 0;
		}

		$whereAdd = '';
		if ($activeOnly) {
			$whereAdd .= " AND i.active = 1 ";
		}

		if (is_numeric($fromManufacturerOnly)) {
			$whereAdd .= " AND i.manufacturer_id = ".$fromManufacturerOnly;
		}

		$sql = "SELECT
					count(id) AS num
				FROM
					items i
				WHERE
					(structure_id=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_2=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_3=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_4=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_5=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_6=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_7=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_8=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_9=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_10=".$this->db->real_escape_string($structure_id).")
				$whereAdd";

		$result = $this->db->query($sql);
		$this->itemCount = $result->fetch_object()->num;

		//probably the wrong place
		$sql = "SELECT
					i.*,
					i.default_image_file_name AS file_name,
					ip.price_1,
					ip.bargain_price_1
				FROM
					item_prices ip
				RIGHT JOIN
					items i
				ON
					i.id=ip.item_id
				AND
					ip.customergroup_id=".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." 
				WHERE
					(structure_id=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_2=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_3=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_4=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_5=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_6=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_7=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_8=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_9=".$this->db->real_escape_string($structure_id)."
				OR
					structure_id_10=".$this->db->real_escape_string($structure_id).")
					$whereAdd
				GROUP BY
					i.id";

		if ($sort_by) {
			if ($sort_by == 'name_up') {
				$sql .= " ORDER BY i.name ASC";
			} else if ($sort_by == 'name_down') {
				$sql .= " ORDER BY i.name DESC";
			} else if ($sort_by == 'number_up') {
				$sql .= " ORDER BY i.number ASC";
			} else if ($sort_by == 'number_down') {
				$sql .= " ORDER BY i.number DESC";
			} else if ($sort_by == 'manufacturer_up') {
				$sql .= " ORDER BY i.manufacturer_id ASC";
			} else if ($sort_by == 'manufacturer_down') {
				$sql .= " ORDER BY i.manufacturer_id DESC";
			} else if ($sort_by == 'price_up') {
				$sql .= " ORDER BY ip.price_1 ASC";
			} else if ($sort_by == 'price_down') {
				$sql .= " ORDER BY ip.price_1 DESC";
			}
		}

		if ($limited) {
			$sql .= " LIMIT ".$this->db->real_escape_string($limitMin).", ".$this->db->real_escape_string($limitMax);
		}

		$result = $this->db->query($sql);

		$list = array();
		$show_taxes = $this->base_object->customer_group->show_tax;
		while ($obj = $result->fetch_object()) {

			// get item discount
			$discount = $this->get_item_discount($this->base_object->customer_group->id, $obj->manufacturer_id, $obj->structure_id);
			if ($discount) {
				$obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2);
				$obj->discount = $discount;
				$obj->discount_text = 'Rabatt!';
			}

			// shop price
			$obj->tax = $this->all_tax[$obj->tax_id]->steuersatz;
			$obj->price_tax_text = str_replace('[tax]', $obj->tax, $this->base_object->customer_group->price_tax_text);

			$obj->manufacturer_text = $manufacturers[$obj->manufacturer_id];

			if ($show_taxes) {
				$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2);
				$obj->shop_price_1 = $obj->price_1 + $obj->tax_value;

				$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2);
				$obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value;
			} else {
				$obj->shop_price_1 = $obj->price_1;
				$obj->shop_bargain_price_1 = $obj->bargain_price_1;
			}

			// get schema data
			$obj->schema_data_attributes = array();
			if ($obj->schema_id) {
				$this->schema_id = $obj->schema_id;
				$obj->schema_data = $this->get_schema_data();
				foreach ($obj->schema_data->attributes as $attribute) {
					if ($attribute->name) {
						$attr = array(
							'name' => $attribute->name,
							'unit' => $attribute->unit,
							'value' => $obj->{'attribute_'.$attribute->number},
							'show_detail' => $attribute->show_detail,
							'show_list' => $attribute->show_list,
							'number' => $attribute->number
						);
						$obj->schema_data_attributes[] = $attr;
					}
					if ($obj->schema_data->selectable_attribute_1 == $attribute->number) {
						$obj->schema_data->selectable_name_1 = $attribute->name;
						$obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
					if ($obj->schema_data->selectable_attribute_2 == $attribute->number) {
						$obj->schema_data->selectable_name_2 = $attribute->name;
						$obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
				}
			}

			if (!isset($list[$obj->id])) {
				$list[$obj->id] = $obj;
			}
		}

		return $list;
	}

	public function get_item_list_by_ids($ids, $itemsPerPage = 'all', $currentPage = 1, $activeOnly = false, $fromManufacturerOnly = false) {
		$manufacturers = Manufacturer::get_name_id_pair();

		if (is_numeric($itemsPerPage)) {
			$limitMax = $itemsPerPage;
		} else if ($itemsPerPage == 'all') {
			$limitMax = 99999;
		}

		if (is_numeric($currentPage)) {
			$limitMin = $currentPage * $limitMax - $limitMax;
		} else {
			$limitMin = 0;
		}

		$whereAdd = array();
		if ($activeOnly) {
			$whereAdd[] = " AND items.active = 1 ";
		}

		if (is_numeric($fromManufacturerOnly)) {
			$whereAdd[] = " AND items.manufacturer_id = ".$fromManufacturerOnly;
		}

		$sqlCount = "SELECT items.id FROM items LEFT JOIN item_files ON item_files.item_id = items.id
					WHERE (items.id IN (".implode(",", $ids)."))".implode(" ", $whereAdd)." GROUP BY items.id
					ORDER BY items.number ASC, item_files.rang ASC";
		$this->itemCount = $this->db->query($sqlCount)->num_rows;

		$sql = "SELECT items.*, item_files.file_name, item_files.rang, item_prices.price_1, item_prices.bargain_price_1
				FROM item_prices
				RIGHT JOIN items ON items.id = item_prices.item_id AND
				item_prices.customergroup_id = '".$this->base_object->customer_group->price_group_id."'
				LEFT JOIN item_files ON item_files.item_id = items.id
				WHERE items.id IN (".implode(",", $ids).")".implode(" ", $whereAdd)."
				GROUP BY items.id
				ORDER BY items.number ASC, item_files.rang ASC
				LIMIT ".(int)$limitMin.", ".(int)$limitMax;


		$result = $this->db->query($sql);
		$list = array();

		while ($obj = $result->fetch_object()) {

			// TODO: HACK
			//$item_category_assoc_array = 
			//$obj->item_category_short_uri = 
			// shop price
			$obj->tax = $this->all_tax[$obj->tax_id]->steuersatz;
			$obj->price_tax_text = str_replace('[tax]', $obj->tax, $this->base_object->customer_group->price_tax_text);

			$obj->manufacturer_text = $this->manufacturers[$obj->manufacturer_id];
			$obj->manufacturer_data = $this->manufacturers[$obj->manufacturer_id];

			// get item discount
			$discount = $this->get_item_discount($this->base_object->customer_group->id, $obj->manufacturer_id, $obj->structure_id);
			if ($discount) {
				$obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2);
				$obj->discount = $discount;
				$obj->discount_text = 'Rabatt!';
			}

			if ($this->base_object->customer_group->show_tax) {
				$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2);
				$obj->shop_price_1 = $obj->price_1 + $obj->tax_value;

				$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2);
				$obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value;
			} else {
				$obj->shop_price_1 = $obj->price_1;
				$obj->shop_bargain_price_1 = $obj->bargain_price_1;
			}

			// get schema data
			$obj->schema_data_attributes = array();
			if ($obj->schema_id) {
				$this->schema_id = $obj->schema_id;
				$obj->schema_data = $this->get_schema_data();
				foreach ($obj->schema_data->attributes as $attribute) {
					if ($attribute->name) {
						$attr = array(
							'name' => $attribute->name,
							'unit' => $attribute->unit,
							'value' => $obj->{'attribute_'.$attribute->number},
							'show_detail' => $attribute->show_detail,
							'show_list' => $attribute->show_list,
							'number' => $attribute->number
						);
						$obj->schema_data_attributes[] = $attr;
					}
					if ($obj->schema_data->selectable_attribute_1 == $attribute->number) {
						$obj->schema_data->selectable_name_1 = $attribute->name;
						$obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
					if ($obj->schema_data->selectable_attribute_2 == $attribute->number) {
						$obj->schema_data->selectable_name_2 = $attribute->name;
						$obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
				}
			}

			if (!isset($list[$obj->id])) {
				$list[$obj->id] = $obj;
			}
		}

		return $list;
	}

	public function get_all_items_list() {
		$structure_object = new Structure($this->base_object);
		$all_tree_full_path = $structure_object->get_all_tree_full_path(0, ' > ');

		$manufacturers = Manufacturer::get_name_id_pair();

		$limitMax = 10000;

		$sqlCount = "SELECT items.id FROM items LEFT JOIN item_files ON item_files.item_id = items.id 
					WHERE items.active = 1 GROUP BY items.id ORDER BY items.number ASC, item_files.rang ASC";
		$this->itemCount = $this->db->query($sqlCount)->num_rows;

		$sql = "SELECT items.*, item_files.file_name, item_files.rang, item_prices.price_1, item_prices.bargain_price_1
				FROM item_prices RIGHT JOIN items ON items.id = item_prices.item_id
				AND item_prices.customergroup_id = '".$this->base_object->customer_group->price_group_id."'
				LEFT JOIN item_files ON item_files.item_id = items.id
				WHERE items.active = 1 GROUP BY items.id
				ORDER BY items.number ASC, item_files.rang ASC LIMIT ".$limitMax;

		$result = $this->db->query($sql);
		$list = array();

		while ($obj = $result->fetch_object()) {

			// TODO: HACK
			//$item_category_assoc_array = 
			//$obj->item_category_short_uri = 
			// shop price
			$obj->tax = $this->all_tax[$obj->tax_id]->steuersatz;
			$obj->price_tax_text = str_replace('[tax]', $obj->tax, $this->base_object->customer_group->price_tax_text);

			$obj->manufacturer_text = $manufacturers[$obj->manufacturer_id];

			// get item discount
			$discount = $this->get_item_discount($this->base_object->customer_group->id, $obj->manufacturer_id, $obj->structure_id);
			if ($discount) {
				$obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2);
				$obj->discount = $discount;
				$obj->discount_text = 'Rabatt!';
			}

			if ($this->base_object->customer_group->show_tax) {
				$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2);
				$obj->shop_price_1 = $obj->price_1 + $obj->tax_value;

				$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2);
				$obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value;
			} else {
				$obj->shop_price_1 = $obj->price_1;
				$obj->shop_bargain_price_1 = $obj->bargain_price_1;
			}

			// get schema data
			$obj->schema_data_attributes = array();
			if ($obj->schema_id) {
				$this->schema_id = $obj->schema_id;
				$obj->schema_data = $this->get_schema_data();
				foreach ($obj->schema_data->attributes as $attribute) {
					if ($attribute->name) {
						$attr = array(
							'name' => $attribute->name,
							'unit' => $attribute->unit,
							'value' => $obj->{'attribute_'.$attribute->number},
							'show_detail' => $attribute->show_detail,
							'show_list' => $attribute->show_list,
							'number' => $attribute->number
						);
						$obj->schema_data_attributes[] = $attr;
					}
					if ($obj->schema_data->selectable_attribute_1 == $attribute->number) {
						$obj->schema_data->selectable_name_1 = $attribute->name;
						$obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
					if ($obj->schema_data->selectable_attribute_2 == $attribute->number) {
						$obj->schema_data->selectable_name_2 = $attribute->name;
						$obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
				}
			}

			if (!isset($list[$obj->id])) {
				$list[$obj->id] = $obj;
			}

			if ($obj->structure_id) {
				$obj->structure_data = $all_tree_full_path[$obj->structure_id];
			}
		}

		return $list;
	}

	// end get_all_paginated

	private function match_by_string($data) {
		$data = preg_replace("@(\s){2,}@si", " ", $data);
		$data = trim($data);

		$data = explode(' ', $data);

		$match = '';

		foreach ($data as $point) {
			if ($match == '') {
				$match = " HAVING search_field LIKE '%$point%'";
			} else {
				$match .= " AND search_field LIKE '%$point%'";
			}
		}

		return $match;
	}

	public function find_by_string($data) {
		$sql = "SELECT items.id, items.number, items.name, items.short_description, manufacturers.name as manufacturer,
				CONCAT_WS(' ', items.number, items.name, items.short_description, if (manufacturers.name IS NOT NULL,manufacturers.name,' ')) as search_field
				FROM items LEFT JOIN manufacturers ON manufacturers.id = items.manufacturer_id WHERE items.active = 1";

		$match = $this->match_by_string($data);

		$sql .= $match.' LIMIT 5';

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			while ($obj = $result->fetch_object()) {
				$return[] = $obj;
			}

			return $return;
		}

		return false;
	}

	// end find_by_string

	public function hits_by_string($data) {
		$sql = "SELECT CONCAT_WS(' ', items.number, items.name, items.short_description, if (manufacturers.name IS NOT NULL, manufacturers.name,' ')) as search_field
				FROM items LEFT JOIN manufacturers ON manufacturers.id = items.manufacturer_id WHERE items.active = 1";

		$match = $this->match_by_string($data);

		$sql .= $match;

		$result = $this->db->query($sql);

		if ($result) {
			return $result->num_rows;
		}

		return 0;
	}

	// end hits_by_string

	public function get_by_id($id) {
		$sql = "SELECT * FROM items WHERE id = $id";

		$result = $this->db->query($sql);

		if ($result->num_rows == 1) {
			return $result->fetch_object();
		}

		return false;
	}

	// end get_by_id

	public function get_by_number($nr) {
		$sql = "SELECT id, `number` FROM items WHERE `number` = '$nr'";

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			return $result->fetch_object()->id;
		}

		return false;
	}

	// end get_by_number

	public function get_item_for_order($id) {
		$sql = "SELECT * FROM items WHERE id = $id";

		$result = $this->db->query($sql);

		if ($result->num_rows == 1) {
			$obj = $result->fetch_object();

			$tax_rate = Tax::get_taxrate($obj->tax_id);
			$obj->tax = $tax_rate;

			$obj->price = Money::show_money($obj->price_1);
			$price_with_tax = Money::get_price_with_taxes($obj->price, $tax_rate);
			$obj->price_with_tax = Money::show_money($price_with_tax);

			$obj->item_name = $obj->name;
			$obj->item_number = $obj->number;

			$total = $obj->price;
			$obj->total = Money::show_money($total);

			$total_with_tax = $obj->price_with_tax;
			$obj->total_with_tax = Money::show_money($total_with_tax);

			$obj->amount = 1;

			return $obj;
		}

		return false;
	}

	// end get_by_id

	public function search_items($search) {
		$sql = '';
		$matchingItemNumberFirst = false;
		//echo "Items->search_items() called<br>";

		if (isset($search['manufacturer_id'])) {
			$sql = "SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1
					FROM item_prices ip RIGHT JOIN items i ON i.id=ip.item_id
					AND ip.customergroup_id=".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." 
					WHERE i.active=1 AND i.parent_id=0 AND i.manufacturer_id=".$search['manufacturer_id']."
					GROUP BY i.id ORDER BY i.name DESC";

		} else if (isset($search['search_item'])) {
			// Include individual search
			if (isset($this->base_object->config->shopConfiguration['custom_global_modules']) && $this->base_object->config->shopConfiguration['custom_global_modules']) {
				include_once ROOT_DIR.'web/'.SHOP_SYSTEM.'/php/website_item_search.inc.php';
			} else {
				// Default search
				$where_add = '';
				if (isset($search['item_category']) && $search['item_category'] > 0) {
					$category_id = $this->db->real_escape_string($search['item_category']);
					$sql = "SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1
							FROM item_prices ip RIGHT JOIN items i ON i.id=ip.item_id AND ip.customergroup_id=".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." 
							RIGHT JOIN item_structure_assign isa ON i.id=isa.item_id WHERE i.active=1 
							AND (
								i.name like '%".$search['search_item']."%' ||
								i.number like '%".$search['search_item']."%' ||
								i.short_description like '%".$search['search_item']."%' ||
								i.attribute_1 like '%".$search['search_item']."%' ||
								i.attribute_2 like '%".$search['search_item']."%' ||
								i.attribute_3 like '%".$search['search_item']."%' ||
								i.attribute_4 like '%".$search['search_item']."%' ||
								i.attribute_5 like '%".$search['search_item']."%' ||
								i.seo_keywords like '%".$search['search_item']."%' ||
								i.detail_description like '%".$search['search_item']."%')
							AND parent_id = 0 AND isa.structure_id = $category_id GROUP BY i.id ORDER BY i.name DESC";
				} else {
					$sql = "SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1
							FROM item_prices ip RIGHT JOIN items i ON i.id=ip.item_id AND ip.customergroup_id=".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." 
							WHERE i.active=1 AND (i.name like '%".$search['search_item']."%' ||
							i.number like '%".$search['search_item']."%' ||
							i.short_description like '%".$search['search_item']."%' ||
							i.attribute_1 like '%".$search['search_item']."%' ||
							i.attribute_2 like '%".$search['search_item']."%' ||
							i.attribute_3 like '%".$search['search_item']."%' ||
							i.attribute_4 like '%".$search['search_item']."%' ||
							i.attribute_5 like '%".$search['search_item']."%' ||
							i.seo_keywords like '%".$search['search_item']."%' ||
							i.detail_description like '%".$search['search_item']."%')
							AND parent_id = 0 GROUP BY i.id ORDER BY i.name DESC";
				}
			}
		}

		$list = array();
		if ($sql) {
			$result = $this->db->query($sql);

			$list = array();
			$show_taxes = $this->base_object->customer_group->show_tax;
			while ($obj = $result->fetch_object()) {

				// get variants
				$sql = "SELECT i.id, ip.price_1, ip.bargain_price_1 FROM items i LEFT JOIN item_prices ip ON ip.item_id = i.id
						WHERE ip.price_1 > 0 AND i.parent_id = ".$this->db->real_escape_string($obj->id)." 
						GROUP BY i.id ORDER BY ip.price_1 LIMIT 1";
				$variant_result = $this->db->query($sql);
				if ($variant_result) {
					while ($variant_obj = $variant_result->fetch_object()) {
						$obj->price_1 = $variant_obj->price_1;
						$obj->bargain_price_1 = $variant_obj->bargain_price_1;
						$obj->price_praefix = 'ab';
					}
				}

				// get item discount
				$discount = $this->get_item_discount($this->base_object->customer_group->id, $obj->manufacturer_id, $obj->structure_id);
				if ($discount) {
					$obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2);
					$obj->discount = $discount;
					$obj->discount_text = 'Rabatt!';
				}

				// shop price
				$obj->tax = $this->all_tax[$obj->tax_id]->steuersatz;
				$obj->price_tax_text = str_replace('[tax]', $obj->tax, $this->base_object->customer_group->price_tax_text);

				//$obj->manufacturer_text = $manufacturers[$obj->manufacturer_id];
				$obj->manufacturer_text = $this->manufacturers[$obj->manufacturer_id];
				$obj->manufacturer_data = $this->manufacturers[$obj->manufacturer_id];

				// bargain
				if (!$this->check_bargain_active($obj, $obj->id)) {
					$obj->bargain_price_1 = 0;
				}

				// get quantity prices
				$sql = "SELECT * FROM item_prices WHERE item_id = '".$this->db->real_escape_string($obj->id)."'
						AND customergroup_id = '".$this->db->real_escape_string($this->base_object->customer_group->id)."'
						LIMIT 1";
				$quantityprciesResult = $this->db->query($sql);
				if ($quantityprciesResult) {
					while ($QP = $quantityprciesResult->fetch_object()) {
						foreach ($QP as $colName => $colValue) {
							if (stristr($colName, 'price') && stristr($colName, 'bargain') && $colValue > 0 && $colValue < $obj->bargain_price_1) {
								$obj->bargain_price_1 = $colValue;
								$obj->price_praefix = 'ab';
							} else if (stristr($colName, 'price') && !stristr($colName, 'bargain') && $colValue > 0 && $colValue < $obj->price_1) {
								$obj->price_1 = $colValue;
								$obj->price_praefix = 'ab';
							}
						}
					}
				}

				if ($show_taxes) {
					$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2);
					$obj->shop_price_1 = $obj->price_1 + $obj->tax_value;

					$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2);
					$obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value;
				} else {
					$obj->shop_price_1 = $obj->price_1;
					$obj->shop_bargain_price_1 = $obj->bargain_price_1;
				}

				// get schema data
				$obj->schema_data_attributes = array();
				if ($obj->schema_id) {
					$this->schema_id = $obj->schema_id;
					$obj->schema_data = $this->get_schema_data();
					foreach ($obj->schema_data->attributes as $attribute) {
						if ($attribute->name) {
							$attr = array(
								'name' => $attribute->name,
								'unit' => $attribute->unit,
								'value' => $obj->{'attribute_'.$attribute->number},
								'show_detail' => $attribute->show_detail,
								'show_list' => $attribute->show_list,
								'number' => $attribute->number
							);
							$obj->schema_data_attributes[] = $attr;
						}
						if ($obj->schema_data->selectable_attribute_1 == $attribute->number) {
							$obj->schema_data->selectable_name_1 = $attribute->name;
							$obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number});
						}
						if ($obj->schema_data->selectable_attribute_2 == $attribute->number) {
							$obj->schema_data->selectable_name_2 = $attribute->name;
							$obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number});
						}
					}
				}

				$obj->numberMatch = ($obj->number == $search['search_item']);

				// intelectra individual
				if ($obj->attribute_11 && $obj->attribute_15) {
					$obj->sample_unit = $obj->attribute_15;
					if (strstr($obj->sample_unit, '100')) {
						if ($obj->attribute_11 * 10 != 0) {
							$obj->sample_price = $obj->shop_price_1 / ($obj->attribute_11 * 10);
						} else {
							error_log("Division durch 0 vermieden. \$obj->attribute_11 * 10 ist 0.");
							$obj->sample_price = 0; // Oder ein anderer Standardwert
						}
					} else {
						if ($obj->attribute_11 != 0) {
							$obj->sample_price = $obj->shop_price_1 / $obj->attribute_11;
						} else {
							error_log("Division durch 0 vermieden. \$obj->attribute_11 ist 0.");
							$obj->sample_price = 0; // Oder ein anderer Standardwert
						}
					}
				}
				// emd intelectra individual

				if (!isset($list[$obj->id])) {
					$list[$obj->id] = $obj;
				}
			}
		}

		// Bring items with a matching item number (matching against the search item) to the top
		if ($matchingItemNumberFirst) {
			uasort($list, function($a, $b) {
				if ($a->numberMatch > $b->numberMatch) {
					return -1;
				} else {
					return 1;
				}
			});
		}

		/*echo "search_items result: <pre>";
		var_dump($list);
		echo "</pre><br>";*/
		return $list;
	}

	public function search_group_items($search, $item_ids = false) {
		// get full path structures
		$structure_object = new Structure($this->base_object);
		$all_structures = $structure_object->get_all();

		// Include individual search
		if (isset($this->base_object->config->shopConfiguration['custom_global_modules']) && $this->base_object->config->shopConfiguration['custom_global_modules']) {
			include_once ROOT_DIR.'web/'.SHOP_SYSTEM.'/php/website_itemgroups_search.inc.php';

			// Default search
		} else {
			$sql = "SELECT
						-- wg.name,
						wg.id,
						-- wg.parent_id,
						count(wg.id)
					AS found_items FROM structure wg 
					LEFT JOIN item_structure_assign isa ON wg.id = isa.structure_id
					LEFT JOIN items i ON i.id = isa.item_id
					WHERE (i.name like '%".$search['search_item']."%' ||
					i.short_description like '%".$search['search_item']."%' ||
					i.attribute_1 like '%".$search['search_item']."%' ||
					i.attribute_2 like '%".$search['search_item']."%' ||
					i.attribute_3 like '%".$search['search_item']."%' ||
					i.attribute_4 like '%".$search['search_item']."%' ||
					i.attribute_5 like '%".$search['search_item']."%' ||
					i.detail_description like '%".$search['search_item']."%') AND
					i.parent_id = 0 AND wg.active=1 GROUP BY wg.id";
		}

		if ($sql) {
			$result = $this->db->query($sql);
			$parent_child = array();
			while ($obj = $result->fetch_object()) {
				$all_structures[$obj->id]->found_items = $obj->found_items;

				$parent_id = $all_structures[$obj->id]->parent_id;

				if (isset($parent_child[$parent_id]) && $parent_child[$parent_id]) {
					$parent_child[$parent_id]->children[] = $all_structures[$obj->id];
				} else {
					$parent_child[$parent_id] = $all_structures[$parent_id];
					$parent_child[$parent_id]->children[] = $all_structures[$obj->id];
				}
			}

			return $parent_child;
		}
	}

	public function get_item_list_manufacturer($structure_id, $manufacturer_id) {
		/*$sql = "SELECT items.* FROM items
				WHERE (items.structure_id = ".$structure_id." OR 
				items.structure_id_2 = ".$structure_id." OR 
				items.structure_id_3 = ".$structure_id.") 
				AND items.manufacturer_id = ".$manufacturer_id." ORDER BY items.name ASC";*/

		$sql = "SELECT i.*, i.default_image_file_name AS file_name, ip.price_1, ip.bargain_price_1 FROM item_prices ip
				RIGHT JOIN items i ON i.id=ip.item_id AND ip.customergroup_id=".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." 
				WHERE i.active=1 AND (i.structure_id = ".$structure_id."
				OR i.structure_id_2 = ".$structure_id." 
				OR i.structure_id_3 = ".$structure_id.") 
				AND i.manufacturer_id = ".$manufacturer_id." 
				GROUP BY i.id ORDER BY i.name DESC";

		$result = $this->db->query($sql);
		$list = array();

		while ($obj = $result->fetch_object()) {
			// shop price
			$obj->tax = $this->all_tax[$obj->tax_id]->steuersatz;
			$obj->price_tax_text = str_replace('[tax]', $obj->tax, $this->base_object->customer_group->price_tax_text);

			$obj->manufacturer_text = $manufacturers[$obj->manufacturer_id];

			// get item discount
			$discount = $this->get_item_discount($this->base_object->customer_group->id, $obj->manufacturer_id, $obj->structure_id);
			if ($discount) {
				$obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2);
				$obj->discount = $discount;
				$obj->discount_text = 'Rabatt!';
			}

			$show_taxes = $this->base_object->customer_group->show_tax;
			if ($show_taxes) {
				$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2);
				$obj->shop_price_1 = $obj->price_1 + $obj->tax_value;

				$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2);
				$obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value;
			} else {
				$obj->shop_price_1 = $obj->price_1;
				$obj->shop_bargain_price_1 = $obj->bargain_price_1;
			}



			$list[$obj->id] = $obj;
		}

		return $list;
	}

	public function get_price($id) {
		$sql = "SELECT price_1 as price, tax_id
				FROM items
				WHERE id=".$this->db->real_escape_string($id);

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			$obj = $result->fetch_object();
			$taxrate = Tax::get_taxrate($obj->tax_id);
			$price = Money::get_price_with_taxes($obj->price, $taxrate);

			return Money::show_money($price);
		}

		//TODO: false can't be used in calculations
		return Money::show_money(0.00);
	}

	public function calculate_prices($item, $quantity = 1, $variant1 = false, $variant2 = false, $wantedPrice = false, $customer_id = false) {
		if ($customer_id) {
			$customer_group_id = CustomerHelper::get_customer_group_id_by_customer_id($customer_id);
			$customer_group_object = new Customer_group($this->base_object);
			$customer_group_data = $customer_group_object->get_data($customer_group_id);

			$show_taxes = $customer_group_data->show_tax;
		} else {
			$show_taxes = $this->base_object->customer_group->show_tax;
		}

		if ($variant1 || $variant2) {
			$data['itemPriceNet'] = $item->variant_data[$variant1][$variant2]['priceNet'];
			$data['itemPriceGross'] = $item->variant_data[$variant1][$variant2]['priceGross'];
			$data['variant_number'] = $item->variant_data[$variant1][$variant2]['itemNumber'];
		} else {
			if ($item->bargain_price_1 > 0) {
				$data['itemPriceNet'] = $item->bargain_price_1;
				$data['itemPriceGross'] = $item->bargain_price_1_tax;
			} else {
				$data['itemPriceNet'] = $item->price_1;
				$data['itemPriceGross'] = $item->price_1_tax;
			}
		}

		if (is_array($item->graduated_prices) && count($item->graduated_prices) > 0) {
			foreach ($item->graduated_prices as $quan => $gpData) {
				if ($quan <= $quantity) {
					if ($gpData['bargainNet'] > 0) {
						$data['itemPriceNet'] = $gpData['bargainNet'];
						$data['itemPriceGross'] = $gpData['bargainGross'];
					} else {
						$data['itemPriceNet'] = $gpData['priceNet'];
						$data['itemPriceGross'] = $gpData['priceGross'];
					}
				} else {
					break;
				}
			}
		}

		if ($show_taxes) {
			// WITH TAXES
			if ($wantedPrice) {
				if ($data['itemPriceGross'] != $wantedPrice) {
					$grossPrice = $wantedPrice;
					$netPrice = $wantedPrice / (100.0 + (float) $item->tax) * 100.0;

					$data['itemPriceNet'] = $netPrice;
					$data['itemPriceGross'] = $grossPrice;
				}
			}

			$data['shownPrice'] = $data['itemPriceGross'];
		} else {
			// WITHOUT TAXES
			if ($wantedPrice) {
				if ($data['itemPriceNet'] != $wantedPrice) {
					$grossPrice = $wantedPrice * (100.0 + (float) $item->tax) / 100.0;
					$netPrice = $wantedPrice;

					$data['itemPriceNet'] = $netPrice;
					$data['itemPriceGross'] = $grossPrice;
				}
			}

			$data['shownPrice'] = $data['itemPriceNet'];
		}


		$data['itemPriceNet'] = round($data['itemPriceNet'], 4);
		$data['itemPriceGross'] = round($data['itemPriceGross'], 4);
		$data['shownPrice'] = round($data['shownPrice'], 4);

		return $data;
	}

	public function find_for_ajax($searchString, $limit = 30) {
		$sql = "
			SELECT id, number, name, active
			FROM items
			WHERE number LIKE '%".$this->db->real_escape_string($searchString)."%' 
			OR name LIKE '%".$this->db->real_escape_string($searchString)."%' 
			ORDER BY name, number, id, active DESC LIMIT 0, ".$this->db->real_escape_string($limit);

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			$return = array();

			while ($obj = $result->fetch_object()) {
				$return[] = $obj;
			}

			return $return;
		}

		return false;
	}

	private function saveAssignedItems($type = 1) {
		if (is_numeric($this->id)) {

			switch ($type) {
				case 1:
					$db_switch_field = 'has_additional_items';
					break;

				case 2:
					$db_switch_field = 'has_spare_parts';
					break;

				case 3:
					$db_switch_field = 'has_real_friends';
					break;

				default:
					$db_switch_field = false;
			}

			$queryDelete = "DELETE FROM item_item_assign WHERE item_parent_id = '".$this->id."' AND type =  ".$type;
			$this->db->query($queryDelete);

			if ($db_switch_field) {
				$query = "UPDATE items SET ".$db_switch_field." = 0 WHERE id = '".$this->id."'";
				$this->db->query($query);
			}

			if (is_array($_POST['assignedItemsCollection'.$type])) {
				$pos = 0;
				$inserts = array();

				foreach ($_POST['assignedItemsCollection'.$type] as $itemId) {
					if (is_numeric($itemId)) {
						++$pos;

						$inserts[] = "(".$this->id.",".$itemId.", $type, ".$pos.")";
					}
				}

				if (count($inserts) > 0) {
					$queryInsert = "REPLACE INTO item_item_assign (item_parent_id, item_child_id, type, position) VALUES ".implode(',', $inserts);
					$this->db->query($queryInsert);

					if ($db_switch_field) {
						$query = "UPDATE items SET ".$db_switch_field." = 1 WHERE id = '".$this->id."'";
						$this->db->query($query);
					}
				}
			}
		}

		return true;
	}

	public function delete_item_item_assign($item_parent_id, $item_child_id, $type = false) {
		$sql = '';
		if ($type) {
			$sql = "DELETE FROM item_item_assign
					WHERE item_parent_id = '".$item_parent_id."' 
					AND item_child_id = '".$item_child_id."' 
					AND type =  ".$type;
		} else {
			$sql = "DELETE FROM item_item_assign
					WHERE item_parent_id = '".$item_parent_id."' AND item_child_id = '".$item_child_id."'";
		}
		$this->db->query($sql);
		return true;
	}

	public function get_all_interesting_items_by_group_id($group_id) {
		// get structure_ids
		$ids = array();
		$sql = " SELECT * FROM structure WHERE id=".$this->db->real_escape_string($group_id);
		$result = $this->db->query($sql);
		$obj = $result->fetch_object();
		$sql = " SELECT id FROM structure WHERE parent_id=".$this->db->real_escape_string($obj->parent_id);

		$result = $this->db->query($sql);
		if ($result->num_rows > 0) {
			while ($obj = $result->fetch_object()) {
				$ids[] = $obj->id;
			}

			// get items
			$all_items = array();
			foreach ($ids as $structure_id) {
				$items = $this->get_item_list($structure_id);
				$all_items = array_merge($all_items, $items);
			}

			return $all_items;
		}

		return false;
	}

	// TODO: needs paging
	public function get_by_manufacturer($id) {
		$sql = "SELECT * FROM items WHERE manufacturer_id=".$this->db->real_escape_string($id);

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			$return_data = array();

			while ($obj = $result->fetch_object()) {
				$return_data[] = $obj;
			}

			return $return_data;
		}

		return false;
	}

	private function watermark($strImageDestination) {
		$strImageWatermark = './web/'.SHOP_SYSTEM.'/documents/'.$this->base_object->config->shopConfiguration['item_watermark_image'];
		$iTransparency = 0;
		$iQuality = 80;

		list ( $iDestinationWidth, $iDestinationHeight, $iDestinationType ) = getimagesize($strImageDestination);
		list ( $iWatermarkWidth, $iWatermarkHeight, $iWatermarkType ) = getimagesize($strImageWatermark);

		switch ($iDestinationType) {
			case 1:
				$rDestination = imagecreatefromgif ($strImageDestination);
				break;
			case 2:
				$rDestination = imagecreatefromjpeg($strImageDestination);
				break;
			case 3:
				$rDestination = imagecreatefrompng($strImageDestination);
		}

		switch ($iWatermarkType) {
			case 1:
				$rWatermark = imagecreatefromgif ($strImageWatermark);
				break;
			case 2:
				$rWatermark = imagecreatefromjpeg($strImageWatermark);
				break;
			case 3:
				$rWatermark = imagecreatefrompng($strImageWatermark);
		}

		/*
		 * Position des Wasserzeichens (1 - 5).
		 * 1 = Oben links.
		 * 2 = Oben rechts.
		 * 3 = Unten links.
		 * 4 = Unten rechts
		 * 5 = Horizontal/vertikal zentriert.
		 *
		 * Standard = 4
		 */
		switch ($this->base_object->config->shopConfiguration['item_watermark_pos']) {
			case 1:
				$iPositionX = 0;
				$iPositionY = 0;
				break;
			case 2:
				$iPositionX = $iDestinationWidth - $iWatermarkWidth;
				$iPositionY = 0;
				break;
			case 3:
				$iPositionX = 0;
				$iPositionY = $iDestinationHeight - $iWatermarkHeight;
				break;
			case 4:
			default:
				$iPositionX = $iDestinationWidth - $iWatermarkWidth;
				$iPositionY = $iDestinationHeight - $iWatermarkHeight;
				break;
			case 5:
				$iPositionX = ceil(( $iDestinationWidth / 2));
				$iPositionX -= ceil(( $iWatermarkWidth / 2));

				$iPositionY = ceil(( $iDestinationHeight / 2));
				$iPositionY -= ceil(( $iWatermarkHeight / 2));
		}

		$iTransparency = 100 - $iTransparency;

		/* imagecopymerge ( $rDestination, $rWatermark, $iPositionX,
		  $iPositionY, 0, 0, $iWatermarkWidth,
		  $iWatermarkHeight, $iTransparency ); */

		// Wasserzeichen einfügen
		imagecopy($rDestination, $rWatermark, $iPositionX, $iPositionY, 0, 0, $iWatermarkWidth, $iWatermarkHeight);

		/*
		 * Ausgabeformat (1 - 3):
		 * 1 = GIF-Format
		 * 2 = JPEG-Format
		 * 3 = PNG-Format
		 *
		 * Standard = 3
		 */
		switch ($iDestinationType) {
			case 1:
				//header ( 'content-type: image/gif' );
				imagegif ($rDestination, $strImageDestination);
				break;
			case 2:
				//header ( 'content-type: image/jpeg' );
				imagejpeg($rDestination, $strImageDestination, $iQuality);
				break;
			case 3:
			default:
				//header ( 'content-type: image/png' );
				imagepng($rDestination, $strImageDestination);
		}

		imagedestroy($rDestination);
		imagedestroy($rWatermark);

		return;
	}

	/**
	 * $type : accessories = 0, alternative = 1
	 * $id : id of parent or child item
	 * $order : normal = 0 and selects parent item ids, reverse is 1 and selects child item ids
	 */
	public function get_all_item_items($type = false, $id = false, $order = 0) {
		$sql = "SELECT iia.*, i.name, i.active, i.number FROM item_item_assign iia JOIN items i ON";

		if ($id) {
			if ($order === 1) {
				$sql .= " i.id = iia.item_child_id WHERE iia.item_parent_id=".$this->db->real_escape_string($id);
				$this->id = $id;
			} else if ($order === 0) {
				$sql .= " i.id = iia.item_parent_id WHERE iia.item_child_id=".$this->db->real_escape_string($id);
				$this->id = $id;
			} else {
				return false;
			}
		} else if ($this->id) {
			if ($order === 1) {
				$sql .= " i.id = iia.item_child_id WHERE iia.item_child_id=".$this->db->real_escape_string($this->id);
			} else if ($order === 0) {
				$sql .= " i.id = iia.item_parent_id WHERE iia.item_parent_id=".$this->db->real_escape_string($this->id);
			} else {
				return false;
			}
		} else {
			return false;
		}

		if ($type) {
			$sql .= " AND type=".$this->db->real_escape_string($type);
		}

		$sql .= " ORDER BY iia.position ASC";

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			$return_data = array();

			while ($obj = $result->fetch_object()) {
				$return_data[] = $obj;
			}

			if ($return_data != array()) {
				return $return_data;
			}
		}

		return false;
	}

	// end get_all_item_items

	public function remove_default_image($id = false) {
		$sql = "UPDATE items SET default_image_file_name='' WHERE id=";

		if ($id) {
			$sql .= $this->db->real_escape_string($id);
			$this->id = $id;
		} else if ($this->id) {
			$sql .= $this->db->real_escape_string($this->db);
		} else {
			return false;
		}

		$this->db->query($sql);
	}

	// end remove_default_image

	public function increase_inventory($quantity, $variant1, $variant2, $id = false) {
		if (is_int((int) $quantity)) {
			$quantity = (int) $quantity;
			if ($id) {
				$this->id = $id;
			}

			if (!$this->id) {
				return false;
			}

			if ($this->has_variants()) {
				// reduce inventory for item variants
				$inventory = $this->get_inventory(true, $variant1, $variant2);
				$new_inventory = $inventory + $quantity;
				// TODO: what to do if the item was already delivered?
				// increasing the original item might not be right

				return $this->db->query("UPDATE item_attribute_variants
										SET inventory=".$this->db->real_escape_string($new_inventory)."
										WHERE item_id=".$this->db->real_escape_string($this->id)."
										AND attribut1='".$this->db->real_escape_string($variant1)."'
										AND attribut2='".$this->db->real_escape_string($variant2)."'");
			} else {
				// reduce inventory for item
				$inventory = $this->get_inventory();
				$new_inventory = $inventory + $quantity;
				// TODO: what to do if the item was already delivered?
				// increasing the original item might not be right

				return $this->db->query("UPDATE items 
										SET inventory=".$this->db->real_escape_string($new_inventory)." 
										WHERE id=".$this->db->real_escape_string($this->id));
			}
		}

		return false;
	}

// end increase_inventory

	public function reduce_inventory($quantity, $variant1, $variant2, $id = false) {
		if (is_int((int) $quantity)) {
			$quantity = (int) $quantity;

			if ($id) {
				$this->id = $id;
			}

			if (!$this->id) {
				return false;
			}

			if ($this->has_variants()) {
				// reduce inventory for item variants
				$inventory = $this->get_inventory(true, $variant1, $variant2);
				$new_inventory = $inventory - $quantity;
				// TODO: new inventory can slip under 0, what to do?

				return $this->db->query("UPDATE item_attribute_variants
										SET inventory=".$this->db->real_escape_string($new_inventory)." 
										WHERE item_id=".$this->db->real_escape_string($this->id)." 
										AND attribut1='".$this->db->real_escape_string($variant1)."' 
										AND attribut2='".$this->db->real_escape_string($variant2)."'");
			} else {
				// reduce inventory for item
				$inventory = $this->get_inventory();
				$new_inventory = $inventory - $quantity;
				// TODO: new inventory can slip under 0, what to do?

				return $this->db->query("UPDATE
							items
						SET
							inventory=".$this->db->real_escape_string($new_inventory)."
						WHERE
							id=".$this->db->real_escape_string($this->id));
			}
		}

		return false;
	}

// end reduce_inventory

	private function get_inventory($has_variants = false, $variant1 = false, $variant2 = false) {
		if ($has_variants) {
			$sql = "SELECT
						inventory AS num
					FROM
						item_attribute_variants
					WHERE
						item_id=".$this->db->real_escape_string($this->id)."
					AND
						attribut1='".$this->db->real_escape_string($variant1)."'
					AND
						attribut2='".$this->db->real_escape_string($variant2)."'
					LIMIT 1";
		} else {
			$sql = "SELECT
						inventory AS num
					FROM
						items
					WHERE id=".$this->db->real_escape_string($this->id);
		}

		$result = $this->db->query($sql);

		return $result->fetch_object()->num;
	}

	private function has_variants() {
		$sql = "SELECT * FROM item_attribute_variants WHERE item_id=".$this->db->real_escape_string($this->id);

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			return true;
		}

		return false;
	}

	public function get_all_by_manufacturer($manufacturer_id) {
		$sql = "SELECT
					*
				FROM
					items
				WHERE
					manufacturer_id=".$this->db->real_escape_string($manufacturer_id);

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			$return_data = array();

			while ($obj = $result->fetch_object()) {
				$return_data[] = $obj;
			}

			if ($return_data == array()) {
				return false;
			}

			return $return_data;
		}

		return false;
	}

	// end get_all_by_manufacturer

	public function get_all_google_item_categories($parent = false) {

		$sql_where = ($parent) ? "parent = '".$this->db->real_escape_string($parent)."'" : "parent = ''";

		$sql = "SELECT * FROM google_item_categories WHERE ".$sql_where;

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			$data = array();

			while ($obj = $result->fetch_object()) {
				$data[] = $obj;
			}
			return $data;
		} else {
			return array();
		}
	}

	private function load_item_discounts() {
		// get discounts for all customer_groups
		$sql = "SELECT * FROM discount_item_groups";
		$result = $this->db->query($sql);
		$discounts = array();
		if ($result) {
			while ($obj = $result->fetch_object()) {
				$discounts[$obj->customer_group_id][$obj->manufacturer_id][$obj->structure_id] = $obj->discount;
			}
		}
		$this->item_discounts = $discounts;
		return false;
	}

	public function get_item_discount($customer_group_id, $manufacturer_id, $structure_id) {
		if (isset($this->item_discounts[$customer_group_id][$manufacturer_id][$structure_id])) {
			return $this->item_discounts[$customer_group_id][$manufacturer_id][$structure_id];
		} else {
			return 0;
		}
	}

	public function get_assigned_items($item_id, $customer_group_price_id, $type = 1) {
		$list = array();
		// get assigned item ids

		$sql = 'SELECT
					i.*,
					i.default_image_file_name AS file_name,
					ip.price_1,
					ip.bargain_price_1
				FROM
					item_item_assign iip
				LEFT JOIN
					items i
				ON
					iip.item_child_id=i.id
				-- RIGHT JOIN
				LEFT JOIN
					item_prices ip
				ON
					i.id=ip.item_id
				AND
					ip.customergroup_id='.$this->db->real_escape_string($customer_group_price_id).' 
				WHERE
					iip.item_parent_id='.$this->db->real_escape_string($item_id).' AND 
					iip.type='.$this->db->real_escape_string($type).'
				ORDER BY
					iip.position ASC';

		$result = $this->db->query($sql);

		$show_taxes = (isset($this->base_object->customer_group->show_tax)) ? $this->base_object->customer_group->show_tax : 1;
		while ($obj = $result->fetch_object()) {

			// get item discount
			$discount = $this->get_item_discount($this->base_object->customer_group->id, $obj->manufacturer_id, $obj->structure_id);
			if ($discount) {
				$obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2);
				$obj->discount = $discount;
				$obj->discount_text = 'Rabatt!';
			}

			// shop price
			$obj->tax = $this->all_tax[$obj->tax_id]->steuersatz;
			$obj->tax_rate = $this->all_tax[$obj->tax_id]->steuersatz; // some do it this way some do it that way
			$obj->price_tax_text = str_replace('[tax]', $obj->tax, $this->base_object->customer_group->price_tax_text);

			$obj->manufacturer_text = $this->manufacturers[$obj->manufacturer_id];

			$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2);
			$obj->price_1_tax = $obj->price_1 + $obj->tax_value;

			$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2);
			$obj->bargain_price_1_tax = $obj->bargain_price_1 + $obj->bargain_tax_value;

			if ($show_taxes) {
				$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2);
				$obj->shop_price_1 = $obj->price_1 + $obj->tax_value;

				$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2);
				$obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value;
			} else {
				$obj->shop_price_1 = $obj->price_1;
				$obj->shop_bargain_price_1 = $obj->bargain_price_1;
			}

			// bargain
			if (!$this->check_bargain_active($obj, $obj->id)) {
				$obj->shop_bargain_price_1 = $obj->bargain_price_1 = 0;
			}

			// get schema data
			$obj->schema_data_attributes = array();
			if ($obj->schema_id) {
				$this->schema_id = $obj->schema_id;
				$obj->schema_data = $this->get_schema_data();
				foreach ($obj->schema_data->attributes as $attribute) {
					if ($attribute->name) {
						$attr = array(
							'name' => $attribute->name,
							'unit' => $attribute->unit,
							'value' => $obj->{'attribute_'.$attribute->number},
							'show_detail' => $attribute->show_detail,
							'show_list' => $attribute->show_list,
							'number' => $attribute->number
						);
						$obj->schema_data_attributes[] = $attr;
					}
					if ($obj->schema_data->selectable_attribute_1 == $attribute->number) {
						$obj->schema_data->selectable_name_1 = $attribute->name;
						$obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
					if ($obj->schema_data->selectable_attribute_2 == $attribute->number) {
						$obj->schema_data->selectable_name_2 = $attribute->name;
						$obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
				}
			}

			if (!isset($list[$obj->id])) {
				$list[$obj->id] = $obj;
			}
		}

		return $list;
	}

	public function get_assigned_items_new($item_id, $customer_group_price_id, $type = 1) {
		$list = array();
		// get assigned item ids

		$sql = 'SELECT
					i.*,
					i.default_image_file_name AS file_name,
					ip.price_1,
					ip.bargain_price_1
				FROM
					item_item_assign iip
				LEFT JOIN
					items i
				ON
					iip.item_child_id=i.id
				-- RIGHT JOIN
				LEFT JOIN
					item_prices ip
				ON
					i.id=ip.item_id
				AND
					ip.customergroup_id='.$this->db->real_escape_string($customer_group_price_id).' 
				WHERE
					iip.item_parent_id='.$this->db->real_escape_string($item_id).' AND 
					iip.type='.$this->db->real_escape_string($type).'
				ORDER BY
					iip.position ASC';

		$result = $this->db->query($sql);

		$show_taxes = (isset($this->base_object->customer_group->show_tax)) ? $this->base_object->customer_group->show_tax : 1;
		while ($obj = $result->fetch_object()) {

			// variant check
			$sql = "SELECT  i.id, ip.price_1, ip.bargain_price_1  FROM items i  LEFT JOIN item_prices ip ON (ip.item_id = i.id AND ip.customergroup_id = ".$this->db->real_escape_string($customer_group_price_id).") WHERE i.parent_id = ".$this->db->real_escape_string($obj->id)." GROUP BY i.id ORDER BY ip.price_1 ASC LIMIT 1";
			$variant_result = $this->db->query($sql);
			if ($variant_result->num_rows > 0) {
				$variant_obj = $variant_result->fetch_object();
				$obj->price_1 = $variant_obj->price_1;
				$obj->bargain_price_1 = $variant_obj->bargain_price_1;
				$obj->price_praefix = 'ab';
			}


			// get item discount
			$discount = $this->get_item_discount($this->base_object->customer_group->id, $obj->manufacturer_id, $obj->structure_id);
			if ($discount) {
				$obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2);
				$obj->discount = $discount;
				$obj->discount_text = 'Rabatt!';
			}

			// bargain
			if (!$this->check_bargain_active($obj, $obj->id)) {
				$obj->bargain_price_1 = 0;
			}

			// shop price
			$obj->tax = $this->all_tax[$obj->tax_id]->steuersatz;
			$obj->tax_rate = $this->all_tax[$obj->tax_id]->steuersatz; // some do it this way some do it that way
			$obj->price_tax_text = str_replace('[tax]', $obj->tax, $this->base_object->customer_group->price_tax_text);

			$obj->manufacturer_text = $this->manufacturers[$obj->manufacturer_id];

			$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2);
			$obj->price_1_tax = $obj->price_1 + $obj->tax_value;

			$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2);
			$obj->bargain_price_1_tax = $obj->bargain_price_1 + $obj->bargain_tax_value;

			if ($show_taxes) {
				$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2);
				$obj->shop_price_1 = $obj->price_1 + $obj->tax_value;

				$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2);
				$obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value;
			} else {
				$obj->shop_price_1 = $obj->price_1;
				$obj->shop_bargain_price_1 = $obj->bargain_price_1;
			}

			// get schema data
			$obj->schema_data_attributes = array();
			if ($obj->schema_id) {
				$this->schema_id = $obj->schema_id;
				$obj->schema_data = $this->get_schema_data();
				foreach ($obj->schema_data->attributes as $attribute) {
					if ($attribute->name) {
						$attr = array(
							'name' => $attribute->name,
							'unit' => $attribute->unit,
							'value' => $obj->{'attribute_'.$attribute->number},
							'show_detail' => $attribute->show_detail,
							'show_list' => $attribute->show_list,
							'number' => $attribute->number
						);
						$obj->schema_data_attributes[] = $attr;
					}
					if ($obj->schema_data->selectable_attribute_1 == $attribute->number) {
						$obj->schema_data->selectable_name_1 = $attribute->name;
						$obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
					if ($obj->schema_data->selectable_attribute_2 == $attribute->number) {
						$obj->schema_data->selectable_name_2 = $attribute->name;
						$obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
				}
			}

			if (!isset($list[$obj->id])) {
				$list[$obj->id] = $obj;
			}
		}
		return $list;
	}

	public function is_combination_item($item_id = false) {
		$sql = 'SELECT * FROM items WHERE combination_item=1 AND id=';

		if ($item_id) {
			$sql .= $this->db->real_escape_string($item_id);
			$this->id = $item_id;
		} else if ($this->id) {
			$sql .= $this->db->real_escape_string($this->id);
		} else {
			return false;
		}

		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			return true;
		}

		return false;
	}

	public function get_opinion_list($item_id) {
		$data = array();

		if ($item_id) {
			$sql = "SELECT * FROM item_opinion WHERE item_id = ".$item_id." ORDER BY timestamp DESC";
			$result = $this->db->query($sql);

			while ($obj = $result->fetch_object()) {
				$obj->date = substr($obj->timestamp, 8, 2).'.'.substr($obj->timestamp, 5, 2).'.'.substr($obj->timestamp, 0, 4);
				$data[] = $obj;
			}
		}

		return $data;
	}

	public function get_avg_opinion($item_id) {
		$avg = false;

		if ($item_id) {
			$sql = "SELECT AVG(rang) AS avg_opinion FROM item_opinion WHERE item_id = ".$item_id;
			$result = $this->db->query($sql);

			$AVGO = $result->fetch_object();

			$avg = $AVGO->avg_opinion;
		}

		return $avg;
	}

	public function create_opinion($data) {
		// save opinion in database
		$sql = "INSERT INTO
				item_opinion (item_id, timestamp, rang, opinion_text, user_id, user_name, active)
				VALUES
				(".$this->db->real_escape_string($data['item_id']).", current_timestamp, ".
					$this->db->real_escape_string($data['rang']).",'".
					$this->db->real_escape_string($data['opinion_text'])."', ".
					$this->db->real_escape_string($data['user_id']).", '".
					$this->db->real_escape_string($data['user_name'])."',1)";
		$this->db->query($sql);

		return;
	}

	public function get_item_types($id = false) {
		$sql = 'SELECT
				  it.*,
				  itd.*
				FROM
				  item_types it
				JOIN
				  item_type_definitions itd
				ON (
				  it.item_type_definition_id = itd.item_type_definition_id
				)
				WHERE
					it.item_id=';

		if ($id) {
			$sql .= $this->db->real_escape_string($id);
			$this->id = $id;
		} else if ($this->id) {
			$sql .= $this->db->real_escape_string($this->id);
		} else {
			return false;
		}
		$result = $this->db->query($sql);

		if ($result->num_rows > 0) {
			$data = array();
			while ($obj = $result->fetch_object()) {
				$data[] = $obj;
			}

			return $data;
		}

		return false;
	}

	// end get_item_types

	private function fix_data($obj) {
		// get item discount
		$discount = $this->get_item_discount($this->base_object->customer_group->id, $obj->manufacturer_id, $obj->structure_id);
		if ($discount) {
			$obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2);
			$obj->discount = $discount;
			$obj->discount_text = 'Rabatt!';
		}
 
		if ($this->base_object->customer_group->show_tax) {
		if (!isset($obj->tax)) {$obj->tax = 19;}
			$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 2);
			$obj->shop_price_1 = $obj->price_1 + $obj->tax_value;

			$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 2);
			$obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value;
		} else {
			$obj->shop_price_1 = $obj->price_1;
			$obj->shop_bargain_price_1 = $obj->bargain_price_1;
		}

		$obj->tax_rate = $this->tax_rates[$obj->tax_id]->steuersatz;
		$obj->manufacturer_name = '';
		if (isset($this->manufacturers[$obj->manufacturer_id])) {
			$obj->manufacturer_name = $this->manufacturers[$obj->manufacturer_id]->name;
		}
		$obj->structure_name = '';
		if (isset($this->structure[$obj->structure_id])) {
			$obj->structure_name = $this->structure[$obj->structure_id]->name;
		}

		return $obj;
	}

// end fix_pricing

	public function get_flat_items() {
		$sql = "SELECT i.*, ip.price_1, ip.bargain_price_1, ip.price_2, ip.bargain_price_2, ip.price_3, ip.bargain_price_3, ip.quantity_2, ip.quantity_3
				FROM items i
				LEFT JOIN item_prices ip ON ip.item_id = i.id
				WHERE i.active=1
				AND ip.customergroup_id=".$this->db->real_escape_string($this->base_object->customer_group->id)." ORDER BY i.number";

		$result = $this->db->query($sql);

		$data = array();
		if ($result->num_rows > 0) {
			while ($obj = $result->fetch_object()) {
				$data[] = $this->fix_data($obj);
			}
		}

		return $data;
	}

	public function get_item_list_new($structure_id, $itemsPerPage = 'all', $currentPage = 1, $activeOnly = false, $fromManufacturerOnly = false, $sort_by = false, $infinite = false) {
//		$manufacturers = Manufacturer::get_name_id_pair();

		$limited = false;
		if (is_numeric($itemsPerPage)) {
			$limitMax = $itemsPerPage;
			$limited = true;
		}

		// Load for infinite scrolling
		if ($infinite) {
			$limitMax = 24;
			$limited = true;
		}

		if (is_numeric($currentPage)) {
			$limitMin = $currentPage * $limitMax - $limitMax;
		} else {
			$limitMin = 0;
		}

		$whereAdd = '';
		if ($activeOnly) {
			$whereAdd .= " isa.structure_id=".$this->db->real_escape_string($structure_id);
		}

		if ($activeOnly) {
			$whereAdd .= " AND i.active = 1 ";
		}

		if (is_numeric($fromManufacturerOnly)) {
			$whereAdd .= " AND i.manufacturer_id = ".$fromManufacturerOnly;
		}

		$sql = "SELECT count(id) AS num
				FROM items i
				RIGHT JOIN item_structure_assign isa ON i.id = isa.item_id
				WHERE $whereAdd";

		$result = $this->db->query($sql);
		$this->itemCount = ($result) ? $result->fetch_object()->num : 0;

		//probably the wrong place
		$sql = "
			SELECT
				i.*,
				i.default_image_file_name AS file_name,
				ip.price_1,
				ip.bargain_price_1
			FROM
				item_prices ip
			RIGHT JOIN
				items i
			ON (
				i.id = ip.item_id
			AND
				ip.customergroup_id =".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." 
			)
			RIGHT JOIN
				item_structure_assign isa
			ON
				i.id = isa.item_id
			WHERE
				".$whereAdd."
			GROUP BY
				i.id
		";
		if ($sort_by) {
			if ($sort_by == 'name_up') {
				$sql .= " ORDER BY i.name ASC";
			} else if ($sort_by == 'name_down') {
				$sql .= " ORDER BY i.name DESC";
			} else if ($sort_by == 'number_up') {
				$sql .= " ORDER BY i.number ASC";
			} else if ($sort_by == 'number_down') {
				$sql .= " ORDER BY i.number DESC";
			} else if ($sort_by == 'manufacturer_up') {
				$sql .= " ORDER BY i.manufacturer_id ASC";
			} else if ($sort_by == 'manufacturer_down') {
				$sql .= " ORDER BY i.manufacturer_id DESC";
			} else if ($sort_by == 'price_up') {
				$sql .= " ORDER BY ip.price_1 ASC";
			} else if ($sort_by == 'price_down') {
				$sql .= " ORDER BY ip.price_1 DESC";
			}
		}

		if ($limited) {
			$sql .= " LIMIT
					".$this->db->real_escape_string($limitMin).", ".$this->db->real_escape_string($limitMax);
		}

		$list = array();
		$result = $this->db->query($sql);
		$show_taxes = $this->base_object->customer_group->show_tax;

		while ($obj = $result->fetch_object()) {

			// bargain
			if (!$this->check_bargain_active($obj, $obj->id)) {
				$obj->bargain_price_1 = 0;
			}

			// get item discount
			$discount = $this->get_item_discount($this->base_object->customer_group->id, $obj->manufacturer_id, $obj->structure_id);
			if ($discount) {
				$obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2);
				$obj->discount = $discount;
				$obj->discount_text = 'Rabatt!';
			}

			// get quantity prices
			$sql = "SELECT *
					FROM item_prices
					WHERE item_id = '".$this->db->real_escape_string($obj->id)."'
					AND customergroup_id = '".$this->db->real_escape_string($this->base_object->customer_group->id)."'
					LIMIT 1";
			$quantityprciesResult = $this->db->query($sql);
			if ($quantityprciesResult) {
				while ($QP = $quantityprciesResult->fetch_object()) {
					foreach ($QP as $colName => $colValue) {
						if (stristr($colName, 'price') && stristr($colName, 'bargain') && $colValue > 0 && $colValue < $obj->bargain_price_1) {
							$obj->bargain_price_1 = $colValue;
							$obj->price_praefix = 'ab';
						} else if (stristr($colName, 'price') && !stristr($colName, 'bargain') && $colValue > 0 && $colValue < $obj->price_1) {
							$obj->price_1 = $colValue;
							$obj->price_praefix = 'ab';
						}
					}
				}
			}

			// shop price
			$obj->tax = $this->all_tax[$obj->tax_id]->steuersatz;
			$obj->price_tax_text = str_replace('[tax]', number_format($obj->tax, 2, ',', '.'), $this->base_object->customer_group->price_tax_text);

			$obj->manufacturer_text = $this->manufacturers[$obj->manufacturer_id]->name;
			$obj->manufacturer_data = $this->manufacturers[$obj->manufacturer_id];

			if ($show_taxes) {
				$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 4);
				$obj->shop_price_1 = $obj->price_1 + $obj->tax_value;

				$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 4);
				$obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value;
			} else {
				$obj->shop_price_1 = $obj->price_1;
				$obj->shop_bargain_price_1 = $obj->bargain_price_1;
			}

			// get schema data
			$obj->schema_data_attributes = array();
			if ($obj->schema_id) {
				$this->schema_id = $obj->schema_id;
				$obj->schema_data = $this->get_schema_data();
				foreach ($obj->schema_data->attributes as $attribute) {
					if ($attribute->name) {
						$attr = array(
							'name' => $attribute->name,
							'name_en' => $attribute->name_en,
							'unit' => $attribute->unit,
							'value' => $obj->{'attribute_'.$attribute->number},
							'show_detail' => $attribute->show_detail,
							'show_list' => $attribute->show_list,
							'number' => $attribute->number
						);
						$obj->schema_data_attributes[] = $attr;
					}
					if ($obj->schema_data->selectable_attribute_1 == $attribute->number) {
						$obj->schema_data->selectable_name_1 = $attribute->name;
						$obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
					if ($obj->schema_data->selectable_attribute_2 == $attribute->number) {
						$obj->schema_data->selectable_name_2 = $attribute->name;
						$obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
				}
			}

			// get variants?
			$sql = "SELECT  i.*, ip.price_1, ip.bargain_price_1  FROM items i  LEFT JOIN item_prices ip ON  ip.item_id = i.id WHERE ip.price_1 > 0 AND i.parent_id = ".$this->db->real_escape_string($obj->id)." GROUP BY i.id ORDER BY ip.price_1";
			$variant_result = $this->db->query($sql);
			$obj->variant_structure = array();
			if ($variant_result->num_rows > 0) {
				$obj->price_praefix = 'ab';
				$obj->bargain_price_1 = 0;
				$obj->price_1 = 0;
				$obj->shop_price_1 = 0;
				$obj->shop_bargain_price_1 = 0;
				while ($variant_obj = $variant_result->fetch_object()) {
					// variants
					// calc tax
					$variant_obj->tax = $this->all_tax[$variant_obj->tax_id]->steuersatz;
					$variant_obj->tax_value = round($variant_obj->price_1 * ($variant_obj->tax / 100), 4);
					$variant_obj->price_1_tax = $variant_obj->price_1 + $variant_obj->tax_value;

					$variant_obj->bargain_tax_value = round($variant_obj->bargain_price_1 * ($variant_obj->tax / 100), 2);
					$variant_obj->bargain_price_1_tax = $variant_obj->bargain_price_1 + $variant_obj->bargain_tax_value;

					// shop price
					$variant_obj->sample_price = 0;
					if ($this->base_object->customer_group->show_tax) {
						$variant_obj->shop_price_1 = $variant_obj->price_1_tax;
						$variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1_tax;
					} else {
						$variant_obj->shop_price_1 = $variant_obj->price_1;
						$variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1;
					}

					if ($obj->shop_price_1 == 0 || $obj->shop_price_1 > $variant_obj->shop_price_1) {
						$obj->shop_price_1 = $variant_obj->shop_price_1;
					}

					// calc sample price
					$variant_obj->vpe_sampleprice_unit = $variant_obj->{'attribute_'.$obj->schema_data->base_price_field};
					if ($obj->sample_unit && $variant_obj->vpe_sampleprice_unit) {
						if ($variant_obj->price_je_vpe) {
							if ($variant_obj->vpe_amount) {
								if ($variant_obj->shop_bargain_price_1) {
									$variant_obj->sample_price = $variant_obj->shop_bargain_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount);
								} else {
									$variant_obj->sample_price = $variant_obj->shop_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount);
								}
							}
						} else {
							if ($variant_obj->shop_bargain_price_1) {
								$variant_obj->sample_price = ($variant_obj->shop_bargain_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor;
							} else {
								$variant_obj->sample_price = ($variant_obj->shop_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor;
							}
						}
					}

					$obj->variant_structure[] = array(
						'id' => $variant_obj->id,
						'level' => 2,
						'name' => $variant_obj->name,
						'number' => $variant_obj->number,
						'short_uri' => $variant_obj->short_uri,
						'price_1' => $variant_obj->price_1,
						'bargain_price_1' => $variant_obj->bargain_price_1,
						'shop_price_1' => $variant_obj->shop_price_1,
						'shop_bargain_price_1' => $variant_obj->shop_bargain_price_1,
						'sample_price' => $variant_obj->sample_price,
						'default_image_file_name' => $variant_obj->default_image_file_name,
						'price_type' => $variant_obj->price_type,
						'data' => $variant_obj
					);

					// get smallest price for parent article
					if (!$obj->smallest_variant_price_1 || $obj->smallest_variant_price_1 > $variant_obj->price_1) {
						$obj->price_1 = $variant_obj->price_1;
						$obj->bargain_price_1 = $variant_obj->bargain_price_1;
					}
				}
			}

			// intelectra individual
			if ($obj->attribute_11 && $obj->attribute_15) {
				$obj->sample_unit = $obj->attribute_15;
				if (strstr($obj->sample_unit, '100')) {
					$obj->sample_price = $obj->shop_price_1 / ($obj->attribute_11 * 10);
				}
				else {
					$obj->sample_price = $obj->shop_price_1 / $obj->attribute_11;
				}
			}
			// end intelectra individual

			if (!isset($list[$obj->id])) {
				$list[$obj->id] = $obj;
			}
		}

		return $list;
	}

	private function _cleanupStructureAssignment($ignore = false) {

		if ($ignore) {
			$sql = "DELETE FROM item_structure_assign
					WHERE item_id = ".$this->db->real_escape_string($this->id)." 
					AND structure_id NOT IN (".implode(', ', $ignore).")";
		} else {
			$sql = "DELETE FROM item_structure_assign WHERE item_id = ".$this->db->real_escape_string($this->id);
		}

		$this->db->query($sql);
	}

	private function _assignToStructures($structures) {
		$newStrucutres = array();

		if (is_array($structures)) {
			foreach ($structures as $structure_id) {
				if (is_numeric($structure_id)) {
					$newStrucutres[] = '('.$this->id.', '.$structure_id.')';
				}
			}

			$sql = "INSERT IGNORE INTO item_structure_assign (item_id, structure_id)
					VALUES ".implode(', ', $newStrucutres);

			$this->db->query($sql);
		}

		$this->_cleanupStructureAssignment($structures);
	}

	public function getStructureAssignment() {
		$sql = "SELECT * FROM item_structure_assign WHERE item_id = ".$this->db->real_escape_string($this->id);

		$res = $this->db->query($sql);

		$assignedStructures = array();

		while ($S = $res->fetch_object()) {
			$assignedStructures[$S->structure_id] = $S->pos;
		}

		return $assignedStructures;
	}

	public function set_inventory($quantity) {
		if (is_int((int) $quantity)) {
			$quantity = (int) $quantity;

			if (!$this->id) {
				return false;
			}

			$sql = "UPDATE items SET inventory=".$this->db->real_escape_string($quantity)." WHERE id=".$this->db->real_escape_string($this->id);

			return $this->db->query($sql);
		}

		return false;
	}

	public function searchItems($searchString, $idsOnly = false, $loose = true) {
		//echo "Itemclass->searchItems called";
		$timer_start = microtime(true);

		$searchString_trimmed = trim($searchString);
		$searchString_filtered = preg_replace("@[^\p{L}\p{N}\s\*]@sui", '', $searchString_trimmed);

		if ($loose) {
			$searchString_enriched = preg_replace("@([^\s])(\s)@sui", '$1*$2', $searchString_filtered);
			$searchString_ready = $searchString_enriched.'*';
		} else {
			$searchString_ready = $searchString_filtered;
		}

		$results_items_associations = $this->_searchItemWithinItemsAndAssociations($searchString_ready, $idsOnly);
		$results_associations = $this->_searchItemWithinAssociations($searchString_ready);
		$results_items = $this->_searchItemWithinItems($searchString_ready);

		$results = array_replace($results_items_associations, $results_associations, $results_items);

		$running_time = microtime(true) - $timer_start;

		$result = array(
			'searchstring' => $searchString,
			'results' => count($results),
			'queryTime' => $running_time,
			'data' => $results
		);

		return $result;
	}

	private function _searchItemWithinItemsAndAssociations($searchString, $idsOnly = false) {
		$query = "
			SELECT 
				tbl_items.id, tbl_items.number, tbl_items.name, tbl_items.short_uri,
				(tbl_items.matchpoints + 1) / (tbl_zuordnungen.matchpoints + 1) AS relevance
			FROM
				(
					SELECT 
						i.id, i.number, i.name, i.short_uri,
						MATCH (
							i.number, i.name, i.detail_description, 
							i.attribute_1, i.attribute_2, i.attribute_3, 
							i.attribute_4, i.attribute_5
						) AGAINST (
							'".$this->db->real_escape_string($searchString)."'
							COLLATE utf8_general_ci IN NATURAL LANGUAGE MODE
						) AS matchpoints
					FROM 
						items i
					WHERE 
						i.active = 1
					AND
						i.parent_id = 0
					AND 
						MATCH (
							i.number, i.name, i.detail_description, 
							i.attribute_1, i.attribute_2, i.attribute_3, 
							i.attribute_4, i.attribute_5
						) AGAINST (
							'".$this->db->real_escape_string($searchString)."'
							COLLATE utf8_general_ci IN BOOLEAN MODE
						)
				) AS tbl_items
			INNER JOIN
				(
					SELECT 
						gz.anr, gz.bezeichnung1,
						MATCH (
							gz.bezeichnung1
						) AGAINST (
							'".$this->db->real_escape_string($searchString)."' 
							COLLATE utf8_general_ci IN NATURAL LANGUAGE MODE
						) AS matchpoints
					FROM 
						import_geraetezuordnung gz
					WHERE 
						MATCH (
							gz.bezeichnung1
						) AGAINST (
							'".$this->db->real_escape_string($searchString)."' 
							COLLATE utf8_general_ci IN BOOLEAN MODE
						)
				) AS tbl_zuordnungen
			ON
				tbl_items.number = tbl_zuordnungen.anr
			GROUP BY
				tbl_items.number
			ORDER BY
				relevance DESC
		";

		$rs = $this->db->query($query);

		$results = array();

		if ($idsOnly) {
			while ($I = $rs->fetch_object()) {
				$results[$I->id] = $I->id;
			}
		} else {
			$method = __METHOD__;

			while ($I = $rs->fetch_object()) {
				$I->method = $method;
				$I->string = $searchString;

				$results[$I->id] = $I;
			}
		}

		return $results;
	}

	private function _searchItemWithinAssociations($searchString, $idsOnly = false) {
		$searchString_limited = '+'.preg_replace("@(\s)@sui", '$1+', $searchString);

		$query = "SELECT anr FROM import_geraetezuordnung 
			WHERE
				MATCH (bezeichnung1)
				AGAINST ('".$this->db->real_escape_string($searchString_limited)."' COLLATE utf8_general_ci IN BOOLEAN MODE)
			GROUP BY anr";

		$rs = $this->db->query($query);

		$itemNumbers = array();
		while ($A = $rs->fetch_object()) {
			$itemNumbers[] = $A->anr;
		}

		$results = array();
		if (count($itemNumbers) > 0) {
			$itemNumberList = implode(',', $itemNumbers);

			$queryItems = "SELECT id, number, name, short_uri
					FROM items FORCE INDEX (parent_id_number_active)
					WHERE parent_id = 0 AND number IN (".$itemNumberList.") AND active = 1";

			$rsItems = $this->db->query($queryItems);

			if ($idsOnly) {
				while ($I = $rs->fetch_object()) {
					$results[$I->id] = $I->id;
				}
			} else {
				$method = __METHOD__;

				while ($I = $rsItems->fetch_object()) {
					$I->method = $method;
					$I->string = $searchString_limited;

					$results[$I->id] = $I;
				}
			}
		}

		return $results;
	}

	private function _searchItemWithinItems($searchString, $idsOnly = false) {
		$searchString_limited = '+'.preg_replace("@(\s)@sui", '$1+', $searchString);

		$query = "
			SELECT 
				id, number, name, short_uri,
				MATCH (
					number, name, detail_description, attribute_1, attribute_2, 
					attribute_3, attribute_4, attribute_5
				) AGAINST (
					'".$this->db->real_escape_string($searchString_limited)."'
					COLLATE utf8_general_ci IN NATURAL LANGUAGE MODE
				) AS relevance
			FROM 
				items
			WHERE 
				active = 1
			AND
				parent_id = 0
			AND 
				MATCH (
					number, name, detail_description, attribute_1, attribute_2, 
					attribute_3, attribute_4, attribute_5
				) AGAINST (
					'".$this->db->real_escape_string($searchString_limited)."'
					COLLATE utf8_general_ci IN BOOLEAN MODE
				)
			ORDER BY
				relevance DESC
		";

		$rs = $this->db->query($query);

		$results = array();

		if ($idsOnly) {
			while ($I = $rs->fetch_object()) {
				$results[$I->id] = $I->id;
			}
		} else {
			$method = __METHOD__;

			while ($I = $rs->fetch_object()) {
				$I->method = $method;
				$I->string = $searchString_limited;

				$results[$I->id] = $I;
			}
		}

		return $results;
	}

	public function get_all_structure_items($structure_id) {
		// get items
		$sql = "SELECT id, name, short_uri, active FROM items WHERE active=1 AND structure_id=".$this->db->real_escape_string($structure_id);
		$result = $this->db->query($sql);

		if ($this->db->error) {
			$log_object = Logger::get_instance();
			$log_object->info('Error in /core/items_class.php->get_all_structure_items()', $this->db->error.', sql:'.$sql);
		}

		$data = array();
		if ($result) {
			while ($row = $result->fetch_object()) {
				$data[] = $row;
			}
		}

		return $data;
	}




	public function get_item_list_by_type($structure_id, $itemsPerPage = 'all', $currentPage = 1, $activeOnly = false, $fromManufacturerOnly = false, $sort_by = false, $infinite = false) {

		$limited = false;
		if (is_numeric($itemsPerPage)) {
			$limitMax = $itemsPerPage;
			$limited = true;
		}

		// Load for infinite scrolling
		if ($infinite) {
			$limitMax = 24;
			$limited = true;
		}

		if (is_numeric($currentPage)) {
			$limitMin = $currentPage * $limitMax - $limitMax;
		} else {
			$limitMin = 0;
		}

		$structure_object = new Structure($this->base_object);
		$structure_data = $structure_object->get_by_id($structure_id);
		$whereAdd = 'isa.item_type_definition_id='.$structure_data->item_type;

		if ($activeOnly) {
			$whereAdd .= " AND i.active = 1 ";
		}

		if (is_numeric($fromManufacturerOnly)) {
			$whereAdd .= " AND i.manufacturer_id = ".$fromManufacturerOnly;
		}

		// get type
		include_once './core/itemtype.class.php';
		$item_type_object = New ItemType($this->base_object);
		$type_data = $item_type_object->load($structure_data->item_type);
		if ($type_data['item_type_definition_type'] == 1) {
			$today = getdate();
			$today = $today['year'].'-'.$today['mon'].'-'.$today['mday'];
			$whereAdd .=  "  AND isa.item_type_available_from <= '".$this->db->real_escape_string($today)."'
							AND isa.item_type_available_until >= '".$this->db->real_escape_string($today)."'";
		}

		$sql = "SELECT count(id) AS num
				FROM items i
				RIGHT JOIN item_types isa
				ON i.id = isa.item_id
				WHERE $whereAdd";

		$result = $this->db->query($sql);
		$this->itemCount = ($result) ? $result->fetch_object()->num : 0;

		$sql = "
			SELECT
				i.*,
				i.default_image_file_name AS file_name,
				ip.price_1,
				ip.bargain_price_1
			FROM
				item_prices ip
			RIGHT JOIN
				items i
			ON (
				i.id = ip.item_id
			AND
				ip.customergroup_id =".$this->db->real_escape_string($this->base_object->customer_group->price_group_id)." 
			)
			RIGHT JOIN
				item_types isa
			ON
				i.id = isa.item_id
			WHERE
				".$whereAdd."
			GROUP BY
				i.id";

		if ($sort_by) {
			if ($sort_by == 'name_up') {
				$sql .= " ORDER BY i.name ASC";
			} else if ($sort_by == 'name_down') {
				$sql .= " ORDER BY i.name DESC";
			} else if ($sort_by == 'number_up') {
				$sql .= " ORDER BY i.number ASC";
			} else if ($sort_by == 'number_down') {
				$sql .= " ORDER BY i.number DESC";
			} else if ($sort_by == 'manufacturer_up') {
				$sql .= " ORDER BY i.manufacturer_id ASC";
			} else if ($sort_by == 'manufacturer_down') {
				$sql .= " ORDER BY i.manufacturer_id DESC";
			} else if ($sort_by == 'price_up') {
				$sql .= " ORDER BY ip.price_1 ASC";
			} else if ($sort_by == 'price_down') {
				$sql .= " ORDER BY ip.price_1 DESC";
			}
		}

		if ($limited) {
			$sql .= " LIMIT ".$this->db->real_escape_string($limitMin).", ".$this->db->real_escape_string($limitMax);
		}

		$list = array();
		$result = $this->db->query($sql);
		$show_taxes = $this->base_object->customer_group->show_tax;

		while ($obj = $result->fetch_object()) {

			// bargain
			if (!$this->check_bargain_active($obj, $obj->id)) {
				$obj->bargain_price_1 = 0;
			}

			// get item discount
			$discount = $this->get_item_discount($this->base_object->customer_group->id, $obj->manufacturer_id, $obj->structure_id);
			if ($discount) {
				$obj->bargain_price_1 = round(($obj->price_1 * (100 - $discount) / 100), 2);
				$obj->discount = $discount;
				$obj->discount_text = 'Rabatt!';
			}

			// shop price
			$obj->tax = $this->all_tax[$obj->tax_id]->steuersatz;
			$obj->price_tax_text = str_replace('[tax]', number_format($obj->tax, 2, ',', '.'), $this->base_object->customer_group->price_tax_text);

			$obj->manufacturer_text = $this->manufacturers[$obj->manufacturer_id]->name;
			$obj->manufacturer_data = $this->manufacturers[$obj->manufacturer_id];

			if ($show_taxes) {
				$obj->tax_value = round($obj->price_1 * ($obj->tax / 100), 4);
				$obj->shop_price_1 = $obj->price_1 + $obj->tax_value;

				$obj->bargain_tax_value = round($obj->bargain_price_1 * ($obj->tax / 100), 4);
				$obj->shop_bargain_price_1 = $obj->bargain_price_1 + $obj->bargain_tax_value;
			} else {
				$obj->shop_price_1 = $obj->price_1;
				$obj->shop_bargain_price_1 = $obj->bargain_price_1;
			}

			// get schema data
			$obj->schema_data_attributes = array();
			if ($obj->schema_id) {
				$this->schema_id = $obj->schema_id;
				$obj->schema_data = $this->get_schema_data();
				foreach ($obj->schema_data->attributes as $attribute) {
					if ($attribute->name) {
						$attr = array(
							'name' => $attribute->name,
							'name_en' => $attribute->name_en,
							'unit' => $attribute->unit,
							'value' => $obj->{'attribute_'.$attribute->number},
							'show_detail' => $attribute->show_detail,
							'show_list' => $attribute->show_list,
							'number' => $attribute->number
						);
						$obj->schema_data_attributes[] = $attr;
					}
					if ($obj->schema_data->selectable_attribute_1 == $attribute->number) {
						$obj->schema_data->selectable_name_1 = $attribute->name;
						$obj->price_variants_1 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
					if ($obj->schema_data->selectable_attribute_2 == $attribute->number) {
						$obj->schema_data->selectable_name_2 = $attribute->name;
						$obj->price_variants_2 = explode(';', $obj->{'attribute_'.$attribute->number});
					}
				}
			}

			// get variants?
			$sql = "SELECT  i.*, ip.price_1, ip.bargain_price_1  FROM items i  LEFT JOIN item_prices ip ON  ip.item_id = i.id WHERE ip.price_1 > 0 AND i.parent_id = ".$this->db->real_escape_string($obj->id)." GROUP BY i.id ORDER BY ip.price_1";
			$variant_result = $this->db->query($sql);
			$obj->variant_structure = array();
			if ($variant_result->num_rows > 0) {
				$obj->price_praefix = 'ab';
				$obj->bargain_price_1 = 0;
				$obj->price_1 = 0;
				$obj->shop_price_1 = 0;
				$obj->shop_bargain_price_1 = 0;
				while ($variant_obj = $variant_result->fetch_object()) {
					// variants
					// calc tax
					$variant_obj->tax = $this->all_tax[$variant_obj->tax_id]->steuersatz;
					$variant_obj->tax_value = round($variant_obj->price_1 * ($variant_obj->tax / 100), 4);
					$variant_obj->price_1_tax = $variant_obj->price_1 + $variant_obj->tax_value;

					$variant_obj->bargain_tax_value = round($variant_obj->bargain_price_1 * ($variant_obj->tax / 100), 2);
					$variant_obj->bargain_price_1_tax = $variant_obj->bargain_price_1 + $variant_obj->bargain_tax_value;

					// shop price
					$variant_obj->sample_price = 0;
					if ($this->base_object->customer_group->show_tax) {
						$variant_obj->shop_price_1 = $variant_obj->price_1_tax;
						$variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1_tax;
					} else {
						$variant_obj->shop_price_1 = $variant_obj->price_1;
						$variant_obj->shop_bargain_price_1 = $variant_obj->bargain_price_1;
					}

					if ($obj->shop_price_1 == 0 || $obj->shop_price_1 > $variant_obj->shop_price_1) {
						$obj->shop_price_1 = $variant_obj->shop_price_1;
					}

					// calc sample price
					$variant_obj->vpe_sampleprice_unit = $variant_obj->{'attribute_'.$obj->schema_data->base_price_field};
					if ($obj->sample_unit && $variant_obj->vpe_sampleprice_unit) {
						if ($variant_obj->price_je_vpe) {
							if ($variant_obj->vpe_amount) {
								if ($variant_obj->shop_bargain_price_1) {
									$variant_obj->sample_price = $variant_obj->shop_bargain_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount);
								} else {
									$variant_obj->sample_price = $variant_obj->shop_price_1 / ($variant_obj->vpe_sampleprice_unit * $variant_obj->vpe_amount);
								}
							}
						} else {
							if ($variant_obj->shop_bargain_price_1) {
								$variant_obj->sample_price = ($variant_obj->shop_bargain_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor;
							} else {
								$variant_obj->sample_price = ($variant_obj->shop_price_1 / $variant_obj->vpe_sampleprice_unit) / $obj->schema_data->base_price_faktor;
							}
						}
					}

					$obj->variant_structure[] = array(
						'id' => $variant_obj->id,
						'level' => 2,
						'name' => $variant_obj->name,
						'number' => $variant_obj->number,
						'short_uri' => $variant_obj->short_uri,
						'price_1' => $variant_obj->price_1,
						'bargain_price_1' => $variant_obj->bargain_price_1,
						'shop_price_1' => $variant_obj->shop_price_1,
						'shop_bargain_price_1' => $variant_obj->shop_bargain_price_1,
						'sample_price' => $variant_obj->sample_price,
						'default_image_file_name' => $variant_obj->default_image_file_name,
						'price_type' => $variant_obj->price_type,
						'data' => $variant_obj
					);

					// get smallest price for parent article
					if (!$obj->smallest_variant_price_1 || $obj->smallest_variant_price_1 > $variant_obj->price_1) {
						$obj->price_1 = $variant_obj->price_1;
						$obj->bargain_price_1 = $variant_obj->bargain_price_1;
					}
				}
			}


			if (!isset($list[$obj->id])) {
				$list[$obj->id] = $obj;
			}
		}

		return $list;
	}

	function update_last_change() {
		$sql = "UPDATE items SET last_change_date = NOW(), last_change_user_id=".$this->db->real_escape_string($this->base_object->customer->id)." WHERE id=".$this->db->real_escape_string($this->id);
		$result = $this->db->query($sql);
	}

	private function check_bargain_active($obj, $id) {
		if ($obj->bargain_price_type == 1) {
			return 1;
		} else if ($obj->bargain_price_type == 2) {
			$today = getdate();
			$today = $today['year'].'-'.$today['mon'].'-'.$today['mday'];
			$sql = "SELECT item_types.item_type_id
					FROM item_types 
					LEFT JOIN item_type_definitions ON item_type_definitions.item_type_definition_id=item_types.item_type_definition_id
					WHERE item_id =".$this->db->real_escape_string($id).
					" AND item_type_available_from <= '".$this->db->real_escape_string($today)."'
					AND item_type_available_until >= '".$this->db->real_escape_string($today)."'
					AND item_type_definitions.item_type_definition_type=1
					AND item_type_definitions.item_type_definition_is_active=1";
			$result = $this->db->query($sql);
			$found = $result->fetch_array();
			if ($found) {
				return 1;
			}
		}
		return 0;
	}

	public function createIntWithTableData($html) {
        $int = new stdClass();
        $int->geraete_table_data = $html;
        return $int;
    }




private function loadWarnings($warningIdsList) {
    $articleWarnings = [];

    if ($warningIdsList) {
        $ids = explode(',', $warningIdsList);
        $placeholders = implode(',', array_fill(0, count($ids), '?'));

        $sqlWarn = "
            SELECT warning_id, name, beschreibung, bild, bildnr, bilddateiname
            FROM sicherheitshinweis
            WHERE warning_id IN ($placeholders)
            ORDER BY warning_id
        ";
        $stmtWarn = $this->db->prepare($sqlWarn);

        if ($stmtWarn) {
            $types = str_repeat('i', count($ids));
            $stmtWarn->bind_param($types, ...$ids);
            $stmtWarn->execute();
            $resultWarn = $stmtWarn->get_result();
            $articleWarnings = $resultWarn->fetch_all(MYSQLI_ASSOC);

            // Bilddateiname für jede Warnung generieren
            foreach ($articleWarnings as &$warning) {
                $warning['final_bilddateiname'] = $this->generateImageFileName($warning);
            }
        } else {
           
        }
    }

    return $articleWarnings;
}


// Funktion zum Laden der Dokumente (umbenannt auf "SafetyInstructions")
private function loadSafetyInstructions($warningDocsList) {
    $articleSafetyInstructions = []; // Dokumente

    $documentFields = [
        'Bedienungsanleitung' => 'Bedienungsanleitung',
        'EU_Datenblatt' => 'EU_Datenblatt',
        'Energielabel' => 'Energielabel',
        'Produktdatenblatt' => 'Produktdatenblatt',
        'Sicherheitsdatenblatt' => 'Sicherheitsdatenblatt',
        'Zertifikat' => 'Zertifikat',
		'null_feld' => 'null_feld',
    ];

    foreach ($documentFields as $key => $field) {
        if (!empty($warningDocsList[$field])) {
            $articleSafetyInstructions[] = (object)[
                'name' => $key,
                'file_name' => $warningDocsList[$field]
            ];
            error_log("Dokument gefunden: $key = {$warningDocsList[$field]}");
        }
    }

    return $articleSafetyInstructions;
}







}




?>